PageRenderTime 49ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 1ms

/veriler/f3/lib/web.php

https://gitlab.com/fbi/razyo-api-server
PHP | 507 lines | 378 code | 12 blank | 117 comment | 77 complexity | b2d3097e8ddeb0eb1fdcafc35cfb7f99 MD5 | raw file
  1. <?php
  2. /**
  3. Web pack for the PHP Fat-Free Framework
  4. The contents of this file are subject to the terms of the GNU General
  5. Public License Version 3.0. You may not use this file except in
  6. compliance with the license. Any of the license terms and conditions
  7. can be waived if you get permission from the copyright holder.
  8. Copyright (c) 2009-2011 F3::Factory
  9. Bong Cosca <bong.cosca@yahoo.com>
  10. @package Expansion
  11. @version 2.0.4
  12. **/
  13. //! Web pack
  14. class Web extends Base {
  15. //@{ Locale-specific error/exception messages
  16. const
  17. TEXT_Minify='Unable to minify %s',
  18. TEXT_Timeout='Connection timed out';
  19. //@}
  20. const
  21. //! Carriage return/line feed sequence
  22. EOL="\r\n";
  23. /**
  24. Return a URL/filesystem-friendly version of string
  25. @return string
  26. @param $text string
  27. @param $maxlen integer
  28. **/
  29. static function slug($text,$maxlen=0) {
  30. $out=preg_replace('/([^\w]|-)+/','-',
  31. trim(strtr(str_replace('\'','',$text),
  32. self::$vars['DIACRITICS'])));
  33. return trim(strtolower($maxlen?substr($out,0,$maxlen):$out),'-');
  34. }
  35. /**
  36. Strip Javascript/CSS files of extraneous whitespaces and comments;
  37. Return combined output as a minified string
  38. @return string
  39. @param $base string
  40. @param $files array
  41. @param $echo bool
  42. @public
  43. **/
  44. static function minify($base,array $files,$echo=TRUE) {
  45. preg_match('/\.(js|css)$/',$files[0],$ext);
  46. if (!$ext[1]) {
  47. // Not a JavaSript/CSS file
  48. error(404);
  49. return $echo?NULL:FALSE;
  50. }
  51. $mime=array(
  52. 'js'=>'application/x-javascript',
  53. 'css'=>'text/css'
  54. );
  55. $path=self::fixslashes($base);
  56. foreach ($files as $file)
  57. if (!is_file($path.$file)) {
  58. trigger_error(sprintf(self::TEXT_Minify,$file));
  59. return $echo?NULL:FALSE;
  60. }
  61. $src='';
  62. foreach ($files as $file) {
  63. $stats=&self::ref('STATS');
  64. $stats['FILES']['minified']
  65. [basename($file)]=filesize($path.$file);
  66. // Rewrite relative URLs in CSS
  67. $src.=preg_replace_callback(
  68. '/\b(?<=url)\(([\"\'])*([^\1]+?)\1\)/',
  69. function($url) use($path,$file) {
  70. // Ignore absolute URLs
  71. if (preg_match('/https?:/',$url[2]))
  72. return $url[0];
  73. $fdir=dirname($file);
  74. $rewrite=explode(
  75. '/',$path.($fdir!='.'?$fdir.'/':'').$url[2]
  76. );
  77. $i=0;
  78. while ($i<count($rewrite))
  79. // Analyze each URL segment
  80. if ($i>0 &&
  81. $rewrite[$i]=='..' &&
  82. $rewrite[$i-1]!='..') {
  83. // Simplify URL
  84. unset($rewrite[$i],$rewrite[$i-1]);
  85. $rewrite=array_values($rewrite);
  86. $i--;
  87. }
  88. else
  89. $i++;
  90. // Reconstruct simplified URL
  91. return
  92. '('.implode('/',array_merge($rewrite,array())).')';
  93. },
  94. // Retrieve CSS/Javascript file
  95. self::getfile($path.$file)
  96. );
  97. }
  98. $ptr=0;
  99. $dst='';
  100. while ($ptr<strlen($src)) {
  101. if ($src[$ptr]=='/') {
  102. // Presume it's a regex pattern
  103. $regex=TRUE;
  104. if ($ptr>0) {
  105. // Backtrack and validate
  106. $ofs=$ptr;
  107. while ($ofs>0) {
  108. $ofs--;
  109. // Pattern should be preceded by parenthesis,
  110. // colon or assignment operator
  111. if ($src[$ofs]=='(' || $src[$ofs]==':' ||
  112. $src[$ofs]=='=') {
  113. while ($ptr<strlen($src)) {
  114. $str=strstr(substr($src,$ptr+1),'/',TRUE);
  115. if (!strlen($str) && $src[$ptr-1]!='/' ||
  116. strpos($str,"\n")!==FALSE) {
  117. // Not a regex pattern
  118. $regex=FALSE;
  119. break;
  120. }
  121. $dst.='/'.$str;
  122. $ptr+=strlen($str)+1;
  123. if ($src[$ptr-1]!='\\' ||
  124. $src[$ptr-2]=='\\') {
  125. $dst.='/';
  126. $ptr++;
  127. break;
  128. }
  129. }
  130. break;
  131. }
  132. elseif ($src[$ofs]!="\t" && $src[$ofs]!=' ') {
  133. // Not a regex pattern
  134. $regex=FALSE;
  135. break;
  136. }
  137. }
  138. if ($regex && $ofs<1)
  139. $regex=FALSE;
  140. }
  141. if (!$regex || $ptr<1) {
  142. if (substr($src,$ptr+1,2)=='*@') {
  143. // Conditional block
  144. $str=strstr(substr($src,$ptr+3),'@*/',TRUE);
  145. $dst.='/*@'.$str.$src[$ptr].'@*/';
  146. $ptr+=strlen($str)+6;
  147. }
  148. elseif ($src[$ptr+1]=='*') {
  149. // Multiline comment
  150. $str=strstr(substr($src,$ptr+2),'*/',TRUE);
  151. $ptr+=strlen($str)+4;
  152. }
  153. elseif ($src[$ptr+1]=='/') {
  154. // Single-line comment
  155. $str=strstr(substr($src,$ptr+2),"\n",TRUE);
  156. $ptr+=strlen($str)+2;
  157. }
  158. else {
  159. // Division operator
  160. $dst.=$src[$ptr];
  161. $ptr++;
  162. }
  163. }
  164. continue;
  165. }
  166. if ($src[$ptr]=='\'' || $src[$ptr]=='"') {
  167. $match=$src[$ptr];
  168. // String literal
  169. while ($ptr<strlen($src)) {
  170. $str=strstr(substr($src,$ptr+1),$src[$ptr],TRUE);
  171. $dst.=$match.$str;
  172. $ptr+=strlen($str)+1;
  173. if ($src[$ptr-1]!='\\' || $src[$ptr-2]=='\\') {
  174. $dst.=$match;
  175. $ptr++;
  176. break;
  177. }
  178. }
  179. continue;
  180. }
  181. if (ctype_space($src[$ptr])) {
  182. $last=substr($dst,-1);
  183. $ofs=$ptr+1;
  184. if ($ofs+1<strlen($src)) {
  185. while (ctype_space($src[$ofs]))
  186. $ofs++;
  187. if (preg_match('/[\w%][\w'.
  188. // IE is sensitive about certain spaces in CSS
  189. ($ext[1]=='css'?'#\-*\.':'').'$]/',$last.$src[$ofs]))
  190. $dst.=$src[$ptr];
  191. }
  192. $ptr=$ofs;
  193. }
  194. else {
  195. $dst.=$src[$ptr];
  196. $ptr++;
  197. }
  198. }
  199. if ($echo) {
  200. if (PHP_SAPI!='cli' && !headers_sent())
  201. header(self::HTTP_Content.': '.$mime[$ext[1]].'; '.
  202. 'charset='.self::$vars['ENCODING']);
  203. echo $dst;
  204. die;
  205. }
  206. return $dst;
  207. }
  208. /**
  209. Convert seconds to frequency (in words)
  210. @return integer
  211. @param $secs string
  212. @public
  213. **/
  214. static function frequency($secs) {
  215. $freq['hourly']=3600;
  216. $freq['daily']=86400;
  217. $freq['weekly']=604800;
  218. $freq['monthly']=2592000;
  219. foreach ($freq as $key=>$val)
  220. if ($secs<=$val)
  221. return $key;
  222. return 'yearly';
  223. }
  224. /**
  225. Send HTTP/S request to another host; Follow 30x redirects (default);
  226. Forward headers received (if specified) and return content
  227. @return mixed
  228. @param $pattern string
  229. @param $query string
  230. @param $reqhdrs array
  231. @param $follow bool
  232. @param $forward bool
  233. @public
  234. **/
  235. static function http(
  236. $pattern,$query='',$reqhdrs=array(),$follow=TRUE,$forward=FALSE) {
  237. // Check if valid route pattern
  238. list($method,$route)=explode(' ',$pattern,2);
  239. // Content divider
  240. $div=chr(0);
  241. $url=parse_url($route);
  242. if (!isset($url['path']))
  243. // Set to Web root
  244. $url['path']='/';
  245. if ($method!='GET') {
  246. if (isset($url['query']) && $url['query']) {
  247. // Non-GET method; Query is distinct from URI
  248. $query=$url['query'];
  249. $url['query']='';
  250. }
  251. }
  252. else {
  253. if ($query) {
  254. // GET method; Query is integral part of URI
  255. $url['query']=$query;
  256. $query='';
  257. }
  258. }
  259. // Set up host name and TCP port for socket connection
  260. if (isset($url['scheme']) && $url['scheme']=='https') {
  261. if (!isset($url['port']))
  262. $url['port']=443;
  263. $target='ssl://'.$url['host'];
  264. }
  265. else {
  266. if (!isset($url['port']))
  267. $url['port']=80;
  268. $target=$url['host'];
  269. }
  270. $socket=@fsockopen($target,$url['port'],$errno,$text);
  271. if (!$socket) {
  272. // Can't establish connection
  273. trigger_error($text);
  274. return FALSE;
  275. }
  276. // Set connection timeout parameters
  277. stream_set_blocking($socket,TRUE);
  278. stream_set_timeout($socket,ini_get('default_socket_timeout'));
  279. // Send HTTP request
  280. fputs($socket,
  281. $method.' '.(isset($url['path'])?$url['path']:'').
  282. (isset($url['query']) && $url['query']?
  283. ('?'.$url['query']):'').' '.
  284. 'HTTP/1.0'.self::EOL.
  285. self::HTTP_Host.': '.$url['host'].self::EOL.
  286. self::HTTP_Agent.': Mozilla/5.0 '.
  287. '(compatible;'.PHP_OS.')'.self::EOL.
  288. ($reqhdrs?
  289. (implode(self::EOL,$reqhdrs).self::EOL):'').
  290. ($method!='GET'?(
  291. 'Content-Type: '.
  292. 'application/x-www-form-urlencoded'.self::EOL.
  293. 'Content-Length: '.strlen($query).self::EOL):'').
  294. self::HTTP_AcceptEnc.': gzip'.self::EOL.
  295. self::HTTP_Connect.': close'.self::EOL.self::EOL.
  296. $query.self::EOL.self::EOL
  297. );
  298. $found=FALSE;
  299. $expires=FALSE;
  300. $gzip=FALSE;
  301. $rcvhdrs='';
  302. $info=stream_get_meta_data($socket);
  303. // Get headers and response
  304. $response='';
  305. while (!feof($socket) && !$info['timed_out']) {
  306. $response.=fgets($socket,4096); // MDFK97
  307. $info=stream_get_meta_data($socket);
  308. if (!$found && is_int(strpos($response,self::EOL.self::EOL))) {
  309. $found=TRUE;
  310. $rcvhdrs=strstr($response,self::EOL.self::EOL,TRUE);
  311. ob_start();
  312. if ($follow &&
  313. preg_match('/HTTP\/1\.\d\s30\d/',$rcvhdrs)) {
  314. // Redirection
  315. preg_match('/'.self::HTTP_Location.
  316. ':\s*(.+)/',$rcvhdrs,$loc);
  317. return self::http($method.' '.trim($loc[1]),
  318. $query,$reqhdrs);
  319. }
  320. foreach (explode(self::EOL,$rcvhdrs) as $hdr) {
  321. self::$vars['HEADERS'][]=$hdr;
  322. if (PHP_SAPI!='cli' && $forward)
  323. // Forward HTTP header
  324. header($hdr);
  325. elseif (preg_match('/^'.
  326. self::HTTP_Encoding.':\s*.*gzip/',$hdr))
  327. // Uncompress content
  328. $gzip=TRUE;
  329. }
  330. ob_end_flush();
  331. // Split content from HTTP response headers
  332. $response=substr(strstr($response,self::EOL.self::EOL),4);
  333. }
  334. }
  335. fclose($socket);
  336. if ($info['timed_out']) {
  337. trigger_error(self::TEXT_Timeout);
  338. return FALSE;
  339. }
  340. if (PHP_SAPI!='cli') {
  341. if ($gzip)
  342. $response=gzinflate(substr($response,10));
  343. }
  344. // Return content
  345. return $response;
  346. }
  347. /**
  348. Parse each URL recursively and generate sitemap
  349. @param $url string
  350. @public
  351. **/
  352. static function sitemap($url=NULL) {
  353. if (is_null($url))
  354. $url=self::$vars['BASE'].'/';
  355. if ($url=='#' || isset(self::$vars['SITEMAP'][$url]) &&
  356. is_bool(self::$vars['SITEMAP'][$url]['status']))
  357. // Skip
  358. return;
  359. $response=self::http('GET '.self::$vars['PROTOCOL'].'://'.
  360. $_SERVER['SERVER_NAME'].$url);
  361. if (!$response) {
  362. // No HTTP response
  363. self::$vars['SITEMAP'][$url]['status']=FALSE;
  364. return;
  365. }
  366. foreach (self::$vars['HEADERS'] as $header)
  367. if (preg_match('/HTTP\/\d\.\d\s(\d+)/',$header,$match) &&
  368. $match[1]!=200) {
  369. self::$vars['SITEMAP'][$url]['status']=FALSE;
  370. return;
  371. }
  372. $doc=new DOMDocument('1.0',self::$vars['ENCODING']);
  373. // Suppress errors caused by invalid HTML structures
  374. libxml_use_internal_errors(TRUE);
  375. if ($doc->loadHTML($response)) {
  376. // Valid HTML; add to sitemap
  377. if (!self::$vars['SITEMAP'][$url]['level'])
  378. // Web root
  379. self::$vars['SITEMAP'][$url]['level']=0;
  380. self::$vars['SITEMAP'][$url]['status']=TRUE;
  381. self::$vars['SITEMAP'][$url]['mod']=time();
  382. self::$vars['SITEMAP'][$url]['freq']=0;
  383. // Cached page
  384. $hash='url.'.self::hash('GET '.$url);
  385. $cached=Cache::cached($hash);
  386. if ($cached) {
  387. self::$vars['SITEMAP'][$url]['mod']=$cached['time'];
  388. self::$vars['SITEMAP'][$url]['freq']=$_SERVER['REQUEST_TTL'];
  389. }
  390. // Parse all links
  391. $links=$doc->getElementsByTagName('a');
  392. foreach ($links as $link) {
  393. $ref=$link->getAttribute('href');
  394. preg_match('/^http[s]*:\/\/([^\/$]+)/',$ref,$host);
  395. if (!empty($host) && $host[1]!=$_SERVER['SERVER_NAME'] ||
  396. !$ref || ($rel=$link->getAttribute('rel')) &&
  397. preg_match('/nofollow/',$rel))
  398. // Don't crawl this link!
  399. continue;
  400. if (!isset(self::$vars['SITEMAP'][$ref]))
  401. self::$vars['SITEMAP'][$ref]=array(
  402. 'level'=>self::$vars['SITEMAP'][$url]['level']+1,
  403. 'status'=>NULL
  404. );
  405. }
  406. // Parse each link
  407. $map=array_keys(self::$vars['SITEMAP']);
  408. array_walk($map,'self::sitemap');
  409. }
  410. unset($doc);
  411. if (!self::$vars['SITEMAP'][$url]['level']) {
  412. // Finalize sitemap
  413. $depth=1;
  414. while ($ref=current(self::$vars['SITEMAP']))
  415. // Find deepest level while iterating
  416. if (!$ref['status'])
  417. // Remove remote URLs and pages with errors
  418. unset(self::$vars['SITEMAP']
  419. [key(self::$vars['SITEMAP'])]);
  420. else {
  421. $depth=max($depth,$ref['level']+1);
  422. next(self::$vars['SITEMAP']);
  423. }
  424. // Create XML document
  425. $xml=simplexml_load_string(
  426. '<?xml version="1.0" encoding="'.
  427. self::$vars['ENCODING'].'"?>'.
  428. '<urlset xmlns='.
  429. '"http://www.sitemaps.org/schemas/sitemap/0.9"'.
  430. '/>'
  431. );
  432. $host=self::$vars['PROTOCOL'].'://'.$_SERVER['SERVER_NAME'];
  433. foreach (self::$vars['SITEMAP'] as $key=>$ref) {
  434. // Add new URL
  435. $item=$xml->addChild('url');
  436. // Add URL elements
  437. $item->addChild('loc',$host.$key);
  438. $item->addChild('lastMod',gmdate('c',$ref['mod']));
  439. $item->addChild('changefreq',
  440. self::frequency($ref['freq']));
  441. $item->addChild('priority',
  442. sprintf('%1.1f',1-$ref['level']/$depth));
  443. }
  444. // Send output
  445. if (PHP_SAPI!='cli' && !headers_sent())
  446. header(self::HTTP_Content.': application/xml; '.
  447. 'charset='.self::$vars['ENCODING']);
  448. $xml=dom_import_simplexml($xml)->ownerDocument;
  449. $xml->formatOutput=TRUE;
  450. echo $xml->saveXML();
  451. die;
  452. }
  453. }
  454. /**
  455. Return TRUE if HTTP request origin is AJAX
  456. @return bool
  457. @public
  458. **/
  459. static function isajax() {
  460. return isset($_SERVER['HTTP_X_REQUESTED_WITH']) &&
  461. $_SERVER['HTTP_X_REQUESTED_WITH']=='XMLHttpRequest';
  462. }
  463. /**
  464. Class initializer
  465. @public
  466. **/
  467. static function onload() {
  468. if (!extension_loaded('sockets'))
  469. // Sockets extension required
  470. trigger_error(sprintf(self::TEXT_PHPExt,'sockets'));
  471. // Default translations
  472. $diacritics=array(
  473. 'À'=>'A','Á'=>'A','Â'=>'A','Ã'=>'A','Å'=>'A','Ä'=>'A','Æ'=>'AE',
  474. 'à'=>'a','á'=>'a','â'=>'a','ã'=>'a','å'=>'a','ä'=>'a','æ'=>'ae',
  475. 'Þ'=>'B','þ'=>'b','Č'=>'C','Ć'=>'C','Ç'=>'C','č'=>'c','ć'=>'c',
  476. 'ç'=>'c','Ď'=>'D','ð'=>'d','ď'=>'d','Đ'=>'Dj','đ'=>'dj','È'=>'E',
  477. 'É'=>'E','Ê'=>'E','Ë'=>'E','è'=>'e','é'=>'e','ê'=>'e','ë'=>'e',
  478. 'Ì'=>'I','Í'=>'I','Î'=>'I','Ï'=>'I','ì'=>'i','í'=>'i','î'=>'i',
  479. 'ï'=>'i','Ľ'=>'L','ľ'=>'l','Ñ'=>'N','Ň'=>'N','ñ'=>'n','ň'=>'n',
  480. 'Ò'=>'O','Ó'=>'O','Ô'=>'O','Õ'=>'O','Ø'=>'O','Ö'=>'O','Œ'=>'OE',
  481. 'ð'=>'o','ò'=>'o','ó'=>'o','ô'=>'o','õ'=>'o','ö'=>'o','œ'=>'oe',
  482. 'ø'=>'o','Ŕ'=>'R','Ř'=>'R','ŕ'=>'r','ř'=>'r','Š'=>'S','š'=>'s',
  483. 'ß'=>'ss','Ť'=>'T','ť'=>'t','Ù'=>'U','Ú'=>'U','Û'=>'U','Ü'=>'U',
  484. 'Ů'=>'U','ù'=>'u','ú'=>'u','û'=>'u','ü'=>'u','ů'=>'u','Ý'=>'Y',
  485. 'Ÿ'=>'Y','ý'=>'y','ý'=>'y','ÿ'=>'y','Ž'=>'Z','ž'=>'z'
  486. );
  487. self::$vars['DIACRITICS']=isset(self::$vars['DIACRITICS'])?
  488. array_merge($diacritics,self::$vars['DIACRITICS']):$diacritics;
  489. // Site structure
  490. self::$vars['SITEMAP']=NULL;
  491. }
  492. }