/** Retrieve from cache; or save SQL query results to cache if not previously executed @param $_cmd string @param $_bind mixed @param $_id string @param $_ttl integer @private **/ private static function sqlCache($_cmd, $_bind = NULL, $_id = 'DB', $_ttl = 0) { $_hash = 'sql.' . F3::hashCode($_cmd); $_db =& F3::$global[$_id]; $_cached = Cache::cached($_hash); if ($_cached && time() - $_cached['time'] < $_ttl) { // Gather cached SQL queries for profiler F3::$global['PROFILE'][$_id]['cache'][$_cmd]++; // Retrieve from cache, unserialize, and restore DB variable $_db = unserialize(gzinflate(Cache::fetch($_hash))); } else { self::sqlExec($_cmd, NULL, $_id); if (!F3::$global['ERROR']) { // Serialize, compress and cache unset($_db['pdo'], $_db['query']); Cache::store($_hash, gzdeflate(serialize($_db))); } } }
/** Retrieve from cache; or save SQL query results to cache if not previously executed @param $_cmd string @param $_bind mixed @param $_id string @param $_ttl integer @private **/ private static function sqlCache($_cmd, $_bind = NULL, $_id = 'DB', $_ttl = 0) { $_hash = 'sql.' . F3::hashCode($_cmd); $_db =& F3::$global[$_id]; $_cached = Cache::cached($_hash); if ($_cached && time() - $_cached['time'] < $_ttl) { // Gather cached SQL queries for profiler F3::$global['PROFILE'][$_id]['cache'][$_cmd]++; // Retrieve from cache $_db = Cache::fetch($_hash); } else { self::sqlExec($_cmd, NULL, $_id); if (!F3::$global['ERROR']) { // Save to cache unset($_db['pdo'], $_db['query']); Cache::store($_hash, $_db); } } }
/** Parse each URL recursively and generate sitemap @param $_url string @public **/ public static function sitemap($_url = '/') { $_map =& F3::$global['SITEMAP']; if (array_key_exists($_url, $_map) && $_map[$_url]['status'] !== NULL) { // Already crawled return; } preg_match('/^http[s]*:\\/\\/([^\\/$]+)/', $_url, $_host); if (!empty($_host) && $_host[1] != $_SERVER['SERVER_NAME']) { // Remote URL $_map[$_url]['status'] = FALSE; return; } F3::$global['QUIET'] = TRUE; F3::mock('GET ' . $_url); F3::run(); // Check if an error occurred or no HTTP response if (F3::$global['ERROR'] || !F3::$global['RESPONSE']) { $_map[$_url]['status'] = FALSE; // Reset error flag for next page unset(F3::$global['ERROR']); return; } $_doc = new XMLTree('1.0', F3::$global['ENCODING']); if ($_doc->loadHTML(F3::$global['RESPONSE'])) { // Valid HTML; add to sitemap if (!$_map[$_url]['level']) { // Web root $_map[$_url]['level'] = 0; } $_map[$_url]['status'] = TRUE; $_map[$_url]['mod'] = time(); $_map[$_url]['freq'] = 0; // Cached page $_hash = 'url.' . F3::hashCode('GET ' . $_url); $_cached = Cache::cached($_hash); if ($_cached) { $_map[$_url]['mod'] = $_cached['time']; $_map[$_url]['freq'] = $_SERVER['REQUEST_TTL']; } // Parse all links $_links = $_doc->getElementsByTagName('a'); foreach ($_links as $_link) { $_ref = $_link->getAttribute('href'); $_rel = $_link->getAttribute('rel'); if (!$_ref || $_rel && preg_match('/nofollow/', $_rel)) { // Don't crawl this link! continue; } if (!array_key_exists($_ref, $_map)) { $_map[$_ref] = array('level' => $_map[$_url]['level'] + 1, 'status' => NULL); } } // Parse each link array_walk(array_keys($_map), 'self::sitemap'); } unset($_doc); if (!$_map[$_url]['level']) { // Finalize sitemap $_depth = 1; while ($_ref = current($_map)) { // Find depest level while iterating if (!$_ref['status']) { // Remove remote URLs and pages with errors unset($_map[key($_map)]); } else { $_depth = max($_depth, $_ref['level'] + 1); next($_map); } } // Create XML document $_xml = simplexml_load_string('<?xml version="1.0" encoding="' . F3::$global['ENCODING'] . '"?>' . '<urlset xmlns="' . 'http://www.sitemaps.org/schemas/sitemap/0.9' . '"/>'); $_host = 'http://' . $_SERVER['SERVER_NAME']; foreach ($_map as $_key => $_ref) { // Add new URL $_item = $_xml->addChild('url'); // Add URL elements $_item->addChild('loc', $_host . $_key); $_item->addChild('lastMod', date('c', $_ref['mod'])); $_item->addChild('changefreq', self::frequency($_ref['freq'])); $_item->addChild('priority', sprintf('%1.1f', 1 - $_ref['level'] / $_depth)); } // Send output F3::$global['QUIET'] = FALSE; if (PHP_SAPI != 'cli' && !headers_sent()) { header(F3::HTTP_Content . ': application/xhtml+xml; ' . 'charset=' . F3::$global['ENCODING']); } $_xml = dom_import_simplexml($_xml)->ownerDocument; $_xml->formatOutput = TRUE; echo $_xml->saveXML(); } }
/** Send HTTP/S request to another host; Forward headers received (if QUIET variable is FALSE) and return content; Respect HTTP 30x redirects if last argument is TRUE @return mixed @param $_pattern string @param $_query string @param $_reqhdrs array @param $_follow boolean @public **/ public static function http($_pattern, $_query = '', $_reqhdrs = array(), $_follow = TRUE) { // Check if valid route pattern list($_method, $_route) = F3::checkRoute($_pattern); // Content divider $_div = chr(0); // Determine if page is in cache $_hash = 'url.' . F3::hashCode($_pattern); $_cached = Cache::cached($_hash); if ($_cached) { // Retrieve from cache $_buffer = Cache::fetch($_hash); $_rcvhdrs = strstr($_buffer, $_div, TRUE); $_response = substr(strstr($_buffer, $_div), 1); // Find out if cache is stale $_expires = NULL; foreach (explode(self::EOL, $_rcvhdrs) as $_hdr) { if (preg_match('/^' . F3::HTTP_Expires . ':(.+)/', $_hdr, $_match)) { $_expires = strtotime($_match[1]); break; } } if (!is_null($_expires) && time() < $_expires) { // Cached page is still fresh foreach (explode(self::EOL, $_rcvhdrs) as $_hdr) { F3::$global['HEADERS'][] = $_hdr; if (preg_match('/' . F3::HTTP_Content . '/', $_hdr)) { // Forward HTTP header header($_hdr); } } return $_response; } } $_url = parse_url($_route); if (!$_url['path']) { // Set to Web root $_url['path'] = '/'; } if ($_method != 'GET') { if ($_url['query']) { // Non-GET method; Query is distinct from URI $_query = $_url['query']; $_url['query'] = ''; } } else { if ($_query) { // GET method; Query is integral part of URI $_url['query'] = $_query; $_query = ''; } } // Set up host name and TCP port for socket connection if (preg_match('/https/', $_url['scheme'])) { if (!$_url['port']) { $_url['port'] = 443; } $_target = 'ssl://' . $_url['host'] . ':' . $_url['port']; } else { if (!$_url['port']) { $_url['port'] = 80; } $_target = $_url['host'] . ':' . $_url['port']; } $_socket = @fsockopen($_target, $_url['port'], $_errno, $_text); if (!$_socket) { // Can't establish connection trigger_error($_text); return FALSE; } // Send HTTP request fputs($_socket, $_method . ' ' . $_url['path'] . ($_url['query'] ? '?' . $_url['query'] : '') . ' ' . 'HTTP/1.0' . self::EOL . F3::HTTP_Host . ': ' . $_url['host'] . self::EOL . F3::HTTP_Agent . ': Mozilla/5.0 (' . 'compatible;' . F3::TEXT_AppName . ' ' . F3::TEXT_Version . ')' . self::EOL . ($_reqhdrs ? implode(self::EOL, $_reqhdrs) . self::EOL : '') . ($_method != 'GET' ? 'Content-Type: ' . 'application/x-www-form-urlencoded' . self::EOL . 'Content-Length: ' . strlen($_query) . self::EOL : '') . F3::HTTP_AcceptEnc . ': gzip' . self::EOL . ($_cached ? F3::HTTP_Cache . ': max-age=86400' . self::EOL : '') . F3::HTTP_Connect . ': close' . self::EOL . self::EOL . $_query . self::EOL . self::EOL); $_found = FALSE; $_expires = FALSE; $_gzip = FALSE; // Set connection timeout parameters stream_set_blocking($_socket, TRUE); stream_set_timeout($_socket, ini_get('default_socket_timeout')); $_info = stream_get_meta_data($_socket); // Get headers and response while (!feof($_socket) && !$_info['timed_out']) { $_response .= fgets($_socket, 4096); // MDFK97 $_info = stream_get_meta_data($_socket); if (!$_found) { $_rcvhdrs = strstr($_response, self::EOL . self::EOL, TRUE); if ($_rcvhdrs) { $_found = TRUE; if (PHP_SAPI != 'cli' && !headers_sent()) { ob_start(); if ($_follow && preg_match('/HTTP\\/1\\.\\d\\s30\\d/', $_rcvhdrs)) { // Redirection preg_match('/' . F3::HTTP_Location . ':\\s*(.+?)/', $_rcvhdrs, $_loc); return self::http($_method . ' ' . $_loc[1], $_query, $_reqhdrs); } foreach (explode(self::EOL, $_rcvhdrs) as $_hdr) { F3::$global['HEADERS'][] = $_hdr; if (!F3::$global['QUIET'] && preg_match('/' . F3::HTTP_Content . '/', $_hdr)) { // Forward HTTP header header($_hdr); } elseif (preg_match('/^' . F3::HTTP_Encoding . ':\\s*.*gzip/', $_hdr)) { // Uncompress content $_gzip = TRUE; } elseif (preg_match('/^' . F3::HTTP_Expires . ':\\s*.+/', $_hdr)) { // Cache this page $_expires = TRUE; } } ob_end_flush(); if ($_flag) { Cache::store($_hash, $_rcvhdrs . $_div . $_response); } } // Split content from HTTP response headers $_response = substr(strstr($_response, self::EOL . self::EOL), 4); } } } fclose($_socket); if ($_info['timed_out']) { trigger_error(self::TEXT_Timeout); return FALSE; } if (PHP_SAPI != 'cli' && !headers_sent()) { if ($_gzip) { $_response = gzinflate(substr($_response, 10)); } if ($_expires) { Cache::store($_hash, $_rcvhdrs . $_div . $_response); } } // Return content return $_response; }