/** * Check if this URL is a redirect and return redir info. * * Most code should call File_redirection::where instead, to check if we * already know that redirection and avoid extra hits to the web. * * The URL is hit and any redirects are followed, up to 10 levels or until * a protected URL is reached. * * @param string $in_url * @return mixed one of: * string - target URL, if this is a direct link or can't be followed * array - redirect info if this is an *unknown* redirect: * associative array with the following elements: * code: HTTP status code * redirects: count of redirects followed * url: URL string of final target * type (optional): MIME type from Content-Type header * size (optional): byte size from Content-Length header * time (optional): timestamp from Last-Modified header */ public function lookupWhere($short_url, $redirs = 10, $protected = false) { if ($redirs < 0) { return false; } if (strpos($short_url, '://') === false) { return $short_url; } try { $request = self::_commonHttp($short_url, $redirs); // Don't include body in output $request->setMethod(HTTP_Request2::METHOD_HEAD); $response = $request->send(); if (405 == $response->getStatus() || 204 == $response->getStatus()) { // HTTP 405 Unsupported Method // Server doesn't support HEAD method? Can this really happen? // We'll try again as a GET and ignore the response data. // // HTTP 204 No Content // YFrog sends 204 responses back for our HEAD checks, which // seems like it may be a logic error in their servers. If // we get a 204 back, re-run it as a GET... if there's really // no content it'll be cheap. :) $request = self::_commonHttp($short_url, $redirs); $response = $request->send(); } } catch (Exception $e) { // Invalid URL or failure to reach server common_log(LOG_ERR, "Error while following redirects for {$short_url}: " . $e->getMessage()); return $short_url; } if ($response->getRedirectCount() && File::isProtected($response->getUrl())) { // Bump back up the redirect chain until we find a non-protected URL return self::lookupWhere($short_url, $response->getRedirectCount() - 1, true); } $ret = array('code' => $response->getStatus(), 'redirects' => $response->getRedirectCount(), 'url' => $response->getUrl()); $type = $response->getHeader('Content-Type'); if ($type) { $ret['type'] = $type; } if ($protected) { $ret['protected'] = true; } $size = $response->getHeader('Content-Length'); // @fixme bytes? if ($size) { $ret['size'] = $size; } $time = $response->getHeader('Last-Modified'); if ($time) { $ret['time'] = strtotime($time); } return $ret; }
function _redirectWhere_imp($short_url, $redirs = 10, $protected = false) { if ($redirs < 0) { return false; } // let's see if we know this... $a = File::staticGet('url', $short_url); if (!empty($a)) { // this is a direct link to $a->url return $a->url; } else { $b = File_redirection::staticGet('url', $short_url); if (!empty($b)) { // this is a redirect to $b->file_id $a = File::staticGet('id', $b->file_id); return $a->url; } } $curlh = File_redirection::_commonCurl($short_url, $redirs); // Don't include body in output curl_setopt($curlh, CURLOPT_NOBODY, true); curl_exec($curlh); $info = curl_getinfo($curlh); curl_close($curlh); if (405 == $info['http_code']) { $curlh = File_redirection::_commonCurl($short_url, $redirs); curl_exec($curlh); $info = curl_getinfo($curlh); curl_close($curlh); } if (!empty($info['redirect_count']) && File::isProtected($info['url'])) { return File_redirection::_redirectWhere_imp($short_url, $info['redirect_count'] - 1, true); } $ret = array('code' => $info['http_code'], 'redirects' => $info['redirect_count'], 'url' => $info['url']); if (!empty($info['content_type'])) { $ret['type'] = $info['content_type']; } if ($protected) { $ret['protected'] = true; } if (!empty($info['download_content_length'])) { $ret['size'] = $info['download_content_length']; } if (isset($info['filetime']) && $info['filetime'] > 0) { $ret['time'] = $info['filetime']; } return $ret; }