diff --git a/inc/context.php b/inc/context.php index bb261047..f65c3b0d 100644 --- a/inc/context.php +++ b/inc/context.php @@ -1,66 +1,58 @@ config = $config; - } - - public function buildLogDriver(): Log { - $name = $this->config['log_system']['name']; - $level = $this->config['debug'] ? Log::DEBUG : Log::NOTICE; - $backend = $this->config['log_system']['type']; - - // Check 'syslog' for backwards compatibility. - if ((isset($this->config['syslog']) && $this->config['syslog']) || $backend === 'syslog') { - return LogDrivers::syslog($name, $level, $this->config['log_system']['syslog_stderr']); - } elseif ($backend === 'file') { - return LogDrivers::file($name, $level, $this->config['log_system']['file_path']); - } elseif ($backend === 'stderr') { - return LogDrivers::stderr($name, $level); - } elseif ($backend === 'none') { - return LogDrivers::none(); - } else { - return LogDrivers::error_log($name, $level); - } - } - - public function buildHttpDriver(): HttpDriver { - return HttpDrivers::getHttpDriver( - $this->config['upload_by_url_timeout'], - $this->config['max_filesize'] - ); - } -} - class Context { - private DependencyFactory $factory; - private ?Log $log; - private ?HttpDriver $http; + private array $definitions; - - public function __construct(DependencyFactory $factory) { - $this->factory = $factory; + public function __construct(array $definitions) { + $this->definitions = $definitions; } - public function getLog(): Log { - return $this->log ??= $this->factory->buildLogDriver(); - } + public function get(string $name): mixed { + if (!isset($this->definitions[$name])) { + throw new RuntimeException("Could not find a dependency named $name"); + } - public function getHttpDriver(): HttpDriver { - return $this->http ??= $this->factory->buildHttpDriver(); + $ret = $this->definitions[$name]; + if (is_callable($ret) && !is_string($ret) && !is_array($ret)) { + $ret = $ret($this); + $this->definitions[$name] = $ret; + } + return $ret; } } + +function build_context(array $config): Context { + return new Context([ + 'config' => $config, + Log::class => function($c) { + $config = $c->get('config'); + + $name = $config['log_system']['name']; + $level = $config['debug'] ? Log::DEBUG : Log::NOTICE; + $backend = $config['log_system']['type']; + + // Check 'syslog' for backwards compatibility. + if ((isset($config['syslog']) && $config['syslog']) || $backend === 'syslog') { + return LogDrivers::syslog($name, $level, $this->config['log_system']['syslog_stderr']); + } elseif ($backend === 'file') { + return LogDrivers::file($name, $level, $this->config['log_system']['file_path']); + } elseif ($backend === 'stderr') { + return LogDrivers::stderr($name, $level); + } elseif ($backend === 'none') { + return LogDrivers::none(); + } else { + return LogDrivers::error_log($name, $level); + } + }, + HttpDriver::class => function($c) { + $config = $c->get('config'); + return HttpDrivers::getHttpDriver($config['upload_by_url_timeout'], $config['max_filesize']); + } + ]); +} diff --git a/post.php b/post.php index 8eab4da2..644ff111 100644 --- a/post.php +++ b/post.php @@ -207,7 +207,7 @@ function delete_cyclical_posts(string $boardUri, int $threadId, int $cycleLimit) */ $dropped_post = false; -$context = new Context(new WebDependencyFactory($config)); +$context = Vichan\build_context($config); // Is it a post coming from NNTP? Let's extract it and pretend it's a normal post. if (isset($_GET['Newsgroups']) && $config['nntpchan']['enabled']) { @@ -286,7 +286,7 @@ if (isset($_GET['Newsgroups']) && $config['nntpchan']['enabled']) { $content = file_get_contents("php://input"); } elseif ($ct == 'multipart/mixed' || $ct == 'multipart/form-data') { - $context->getLog()->log(Log::DEBUG, 'MM: Files: ' . print_r($GLOBALS, true)); + $context->get(Log::class)->log(Log::DEBUG, 'MM: Files: ' . print_r($GLOBALS, true)); $content = ''; @@ -454,7 +454,7 @@ if (isset($_POST['delete'])) { modLog("User at $ip deleted their own post #$id"); } - $context->getLog()->log( + $context->get(Log::class)->log( Log::INFO, 'Deleted post: /' . $board['dir'] . $config['dir']['res'] . link_for($post) . ($post['thread'] ? '#' . $id : '') ); @@ -517,7 +517,7 @@ if (isset($_POST['delete'])) { try { $query = new NativeCaptchaQuery( - $context->getHttpDriver(), + $context->get(HttpDriver::class), $config['domain'], $config['captcha']['provider_check'] ); @@ -531,7 +531,7 @@ if (isset($_POST['delete'])) { error($config['error']['captcha']); } } catch (RuntimeException $e) { - $context->getLog()->log(Log::ERROR, "Native captcha IO exception: {$e->getMessage()}"); + $context->get(Log::class)->log(Log::ERROR, "Native captcha IO exception: {$e->getMessage()}"); error($config['error']['local_io_error']); } } @@ -550,7 +550,7 @@ if (isset($_POST['delete'])) { $post = $query->fetch(PDO::FETCH_ASSOC); if ($post === false) { - $context->getLog()->log(Log::INFO, "Failed to report non-existing post #{$id} in {$board['dir']}"); + $context->get(Log::class)->log(Log::INFO, "Failed to report non-existing post #{$id} in {$board['dir']}"); error($config['error']['nopost']); } @@ -559,7 +559,7 @@ if (isset($_POST['delete'])) { error($error); } - $context->getLog()->log( + $context->get(Log::class)->log( Log::INFO, 'Reported post: /' . $board['dir'] . $config['dir']['res'] . link_for($post) . ($post['thread'] ? '#' . $id : '') @@ -631,7 +631,7 @@ if (isset($_POST['delete'])) { try { // With our custom captcha provider if ($config['captcha']['enabled'] || ($post['op'] && $config['new_thread_capt'])) { - $query = new NativeCaptchaQuery($context->getHttpDriver(), $config['domain'], $config['captcha']['provider_check']); + $query = new NativeCaptchaQuery($context->get(HttpDriver::class), $config['domain'], $config['captcha']['provider_check']); $success = $query->verify($config['captcha']['extra'], $_POST['captcha_text'], $_POST['captcha_cookie']); if (!$success) { @@ -655,7 +655,7 @@ if (isset($_POST['delete'])) { error($config['error']['bot']); } $response = $_POST['g-recaptcha-response']; - $query = RemoteCaptchaQuery::withRecaptcha($context->getHttpDriver(), $config['recaptcha_private']); + $query = RemoteCaptchaQuery::withRecaptcha($context->get(HttpDriver::class), $config['recaptcha_private']); } // hCaptcha elseif ($config['hcaptcha']) { @@ -663,7 +663,7 @@ if (isset($_POST['delete'])) { error($config['error']['bot']); } $response = $_POST['h-captcha-response']; - $query = RemoteCaptchaQuery::withHCaptcha($context->getHttpDriver(), $config['hcaptcha_private']); + $query = RemoteCaptchaQuery::withHCaptcha($context->get(HttpDriver::class), $config['hcaptcha_private']); } if (isset($query, $response)) { @@ -785,7 +785,7 @@ if (isset($_POST['delete'])) { try { $ret = download_file_from_url( - $context->getHttpDriver(), + $context->get(HttpDriver::class), $_POST['file_url'], $config['upload_by_url_timeout'], $allowed_extensions, @@ -1163,7 +1163,7 @@ if (isset($_POST['delete'])) { try { $file['size'] = strip_image_metadata($file['tmp_name']); } catch (RuntimeException $e) { - $context->getLog()->log(Log::ERROR, "Could not strip image metadata: {$e->getMessage()}"); + $context->get(Log::class)->log(Log::ERROR, "Could not strip image metadata: {$e->getMessage()}"); // Since EXIF metadata can countain sensible info, fail the request. error(_('Could not strip EXIF metadata!'), null, $error); } @@ -1201,7 +1201,7 @@ if (isset($_POST['delete'])) { $post['body_nomarkup'] .= "" . htmlspecialchars($value) . ""; } } catch (RuntimeException $e) { - $context->getLog()->log(Log::ERROR, "Could not OCR image: {$e->getMessage()}"); + $context->get(Log::class)->log(Log::ERROR, "Could not OCR image: {$e->getMessage()}"); } } } @@ -1395,7 +1395,7 @@ if (isset($_POST['delete'])) { buildThread($post['op'] ? $id : $post['thread']); - $context->getLog()->log( + $context->get(Log::class)->log( Log::INFO, 'New post: /' . $board['dir'] . $config['dir']['res'] . link_for($post) . (!$post['op'] ? '#' . $id : '') );