- Add videodb PHP/MySQL media collection manager (Blu-ray, DVD, CD) - Dockerfile: PHP 8.1 + Apache with GD/mysqli/exif extensions - docker-compose.yml: app on port 6761 + MySQL 8.0 with health checks - docker-entrypoint.sh: auto-generates config.inc.php from env vars, waits for MySQL, initializes DB schema idempotently - init-db.php: CLI schema installer using app's own prefix_query() logic - Persistent volumes for DB, cache, and cover images Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
246 lines
7.1 KiB
PHP
246 lines
7.1 KiB
PHP
<?php
|
|
/**
|
|
* HTTP client functions
|
|
*
|
|
* @todo Encapsulate httpClient and Cache as separate classes
|
|
*
|
|
* @package Core
|
|
* @author Andreas Goetz <cpuidle@gmx.de>
|
|
* @author Andreas Gohr <a.gohr@web.de>
|
|
* @author Chinamann <chinamann@users.sourceforge.net>
|
|
* @version $Id: httpclient.php,v 1.21 2013/04/26 15:09:35 andig2 Exp $
|
|
*/
|
|
|
|
require_once 'core/cache.php';
|
|
require_once 'vendor/autoload.php';
|
|
|
|
use GuzzleHttp\Psr7 as Psr7;
|
|
|
|
/**
|
|
* Reads a saved HTTP response from a cachefile.
|
|
* If caching is globally disabled ($config['IMDBage'] <= 0), file is not loaded.
|
|
*
|
|
* @param string $url URL of the cached response
|
|
* @return mixed HTTP Response, false on errors
|
|
*/
|
|
function getHTTPcache($url)
|
|
{
|
|
global $config;
|
|
|
|
if (@$config['cache_pruning'])
|
|
{
|
|
$cache_file = cache_get_filename($url, CACHE_HTML);
|
|
cache_prune_folder(dirname($cache_file).'/', $config['IMDBage']);
|
|
}
|
|
|
|
return cache_get($url, CACHE_HTML, $config['IMDBage'], true);
|
|
}
|
|
|
|
/**
|
|
* Saves a HTTP resonse to a cachefile
|
|
* If caching is globally disabled ($config['IMDBage'] <= 0), file is not saved.
|
|
*
|
|
* @param string $url URL of the response
|
|
* @param mixed $resp HTTP Response
|
|
*/
|
|
function putHTTPcache($url, $data)
|
|
{
|
|
global $config;
|
|
|
|
// for debugging purposes track there the request originated
|
|
$data['source'] = $url;
|
|
|
|
cache_put($url, $data, CACHE_HTML, $config['IMDBage'], true);
|
|
}
|
|
|
|
/**
|
|
* Extract source encoding from HTML code or HTTP header otherwise
|
|
*/
|
|
function get_response_encoding($response)
|
|
{
|
|
$header = $encoding = null;
|
|
|
|
// response array from cache
|
|
if (is_array($response)) {
|
|
if (isset($response['header']['Content-Type'])) {
|
|
$header = $response['header']['Content-Type'];
|
|
}
|
|
}
|
|
else {
|
|
// Psr response
|
|
$header = $response->getHeader('Content-Type');
|
|
}
|
|
|
|
if ($header) {
|
|
$parsed = Psr7\parse_header($header);
|
|
if (array_key_exists('charset', $parsed[0]))
|
|
{
|
|
$encoding = strtolower($parsed[0]['charset']);
|
|
}
|
|
}
|
|
|
|
if (!$encoding)
|
|
{
|
|
$encoding = 'iso-8859-1';
|
|
}
|
|
|
|
return $encoding;
|
|
}
|
|
|
|
/**
|
|
* HTTP Client
|
|
*
|
|
* Returns the raw data from the given URL, uses proxy when configured
|
|
* and follows redirects
|
|
*
|
|
* @author Andreas Goetz <cpuidle@gmx.de>
|
|
* @param string $url URL to fetch
|
|
* @param bool $cache use caching? defaults to false
|
|
* @param string $post POST data, if nonempty POST is used instead of GET
|
|
* @param integer $timeout Timeout in seconds defaults to 15
|
|
* @return mixed HTTP response
|
|
*/
|
|
function httpClient($url, $cache = false, $para = null, $reload = false)
|
|
{
|
|
static $referer = 'https://www.imdb.com/search/';
|
|
global $config;
|
|
$client = new GuzzleHttp\Client();
|
|
|
|
$requestConfig = [];
|
|
$headers = ''; // additional HTTP headers, used for post data
|
|
|
|
if (!empty($para) && array_key_exists('cookies', $para) && $para['cookies'])
|
|
{
|
|
$jar = new GuzzleHttp\Cookie\CookieJar();
|
|
$requestConfig += ['cookies' => $jar];
|
|
}
|
|
|
|
$method = 'GET';
|
|
|
|
$post = isset($para['post']) ? $para['post'] : '';
|
|
if ($post)
|
|
{
|
|
$method = 'POST';
|
|
$requestConfig += ['headers' => ['Content-Type' => 'application/x-www-form-urlencoded']];
|
|
$requestConfig += ['body' => $post];
|
|
}
|
|
|
|
// get data from cache?
|
|
if ($cache &! $reload)
|
|
{
|
|
$resp = getHTTPcache($url.$post);
|
|
if ($resp !== false)
|
|
{
|
|
$resp['cached'] = true;
|
|
return $resp;
|
|
}
|
|
}
|
|
|
|
// proxy setup
|
|
if (!empty($config['proxy_host']) && !$para['no_proxy'])
|
|
{
|
|
$server = $config['proxy_host'];
|
|
if (!($port = @$config['proxy_port']))
|
|
{
|
|
$port = 8080;
|
|
}
|
|
$requestConfig += ['proxy' => sprintf('tcp://%s:%d', $server, $port)];
|
|
}
|
|
|
|
// additional request headers
|
|
if (!empty($para) && array_key_exists('header', $para) && $para['header'])
|
|
{
|
|
$requestConfig += ['headers' => $para['header']];
|
|
}
|
|
|
|
if (empty($requestConfig['headers']['Accept'])) $requestConfig['headers']['Accept'] = 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8';
|
|
if (empty($requestConfig['headers']['Accept-Language'])) $requestConfig['headers']['Accept-Language'] = ((isset($config['acclangbrowser']) && $config['acclangbrowser']) ? filter_input(INPUT_SERVER, 'HTTP_ACCEPT_LANGUAGE') : 'en-US;q=0.7,en;q=0.3');
|
|
if (empty($requestConfig['headers']['DNT'])) $requestConfig['headers']['DNT'] = '1';
|
|
if (empty($requestConfig['headers']['User-Agent'])) $requestConfig['headers']['User-Agent'] = filter_input(INPUT_SERVER, 'HTTP_USER_AGENT');
|
|
if (empty($requestConfig['headers']['Referer'])) $requestConfig['headers']['Referer'] = $referer;
|
|
|
|
$resp = $client->request($method, $url, $requestConfig);
|
|
|
|
$response['error'] = '';
|
|
$response['url'] = $url;
|
|
$response['success'] = false;
|
|
$response['encoding'] = get_response_encoding($resp);
|
|
$response['header'] = $resp->getHeaders();
|
|
$response['data'] = (string) $resp->getBody();
|
|
|
|
if ($config['debug']) echoHeaders($response['header'])."<p>";
|
|
if ($config['debug']) echo "data:<br>".htmlspecialchars($response['data'])."<p>";
|
|
|
|
|
|
// log response
|
|
if ($config['httpclientlog'])
|
|
{
|
|
$log = fopen('httpClient.log', 'a');
|
|
fwrite($log, headers_to_string($response['header']));
|
|
fclose($log);
|
|
}
|
|
|
|
// verify status code
|
|
if ($resp->getStatusCode() != 200)
|
|
{
|
|
$response['error'] = 'Server returned wrong status: ' . $resp->getStatusCode();
|
|
$response['error'] .= " Reason: " . $resp->getReasonPhrase();
|
|
return $response;
|
|
}
|
|
|
|
$response['success'] = true;
|
|
// @todo i'm not sure on the side-effects of setting the previous requested URL as referer
|
|
// for the next, so disabled for now. might be something to investigate...
|
|
//$referer = $url;
|
|
|
|
// commit successful request to cache
|
|
if ($cache)
|
|
{
|
|
putHTTPcache($url.$post, $response);
|
|
}
|
|
|
|
return $response;
|
|
}
|
|
|
|
|
|
/**
|
|
* Print all header info using echo
|
|
* @param response Object homepage Psr7\Response
|
|
*/
|
|
function echoHeaders($headers)
|
|
{
|
|
foreach ($headers as $name => $values) {
|
|
echo $name . ': ' . implode(', ', $values) . "<br>";
|
|
}
|
|
}
|
|
|
|
function headers_to_string($headers)
|
|
{
|
|
$result = '';
|
|
foreach ($headers as $name => $values) {
|
|
$result .= $name . ': ' . implode(', ', $values) . "\n";
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Downloads an URL to the given local file
|
|
*
|
|
* @param string $url URL to download
|
|
* @param string $local Full path to save to
|
|
* @return bool true on succes else false
|
|
*/
|
|
function download($url, $local)
|
|
{
|
|
$resp = httpClient($url);
|
|
|
|
if (!$resp['success'])
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return(@file_put_contents($local, $resp['data']) !== false);
|
|
}
|
|
|
|
?>
|