The legacy proxy functionality is removed

pull/14096/head
Michael 2024-04-15 18:58:02 +00:00
parent c30e4c02de
commit 0e79b5373b
9 changed files with 324 additions and 618 deletions

View File

@ -317,7 +317,7 @@ class BBCode
} elseif ($uriid > 0) {
return Post\Link::getByLink($uriid, $image, $size);
} else {
return Proxy::proxifyUrl($image, $size);
return $image;
}
}

View File

@ -97,7 +97,6 @@ class Site extends BaseAdmin
$adjust_poll_frequency = !empty($_POST['adjust_poll_frequency']);
$min_poll_interval = (!empty($_POST['min_poll_interval']) ? intval(trim($_POST['min_poll_interval'])) : 0);
$explicit_content = !empty($_POST['explicit_content']);
$proxify_content = !empty($_POST['proxify_content']);
$local_search = !empty($_POST['local_search']);
$blocked_tags = (!empty($_POST['blocked_tags']) ? trim($_POST['blocked_tags']) : '');
$cache_contact_avatar = !empty($_POST['cache_contact_avatar']);
@ -271,7 +270,6 @@ class Site extends BaseAdmin
$transactionConfig->set('system', 'adjust_poll_frequency' , $adjust_poll_frequency);
$transactionConfig->set('system', 'min_poll_interval' , $min_poll_interval);
$transactionConfig->set('system', 'explicit_content' , $explicit_content);
$transactionConfig->set('system', 'proxify_content' , $proxify_content);
$transactionConfig->set('system', 'local_search' , $local_search);
$transactionConfig->set('system', 'blocked_tags' , Strings::cleanTags($blocked_tags));
$transactionConfig->set('system', 'cache_contact_avatar' , $cache_contact_avatar);
@ -518,7 +516,6 @@ class Site extends BaseAdmin
'$private_addons' => ['private_addons', DI::l10n()->t('Disallow public access to addons listed in the apps menu.'), DI::config()->get('config', 'private_addons'), DI::l10n()->t('Checking this box will restrict addons listed in the apps menu to members only.')],
'$disable_embedded' => ['disable_embedded', DI::l10n()->t('Don\'t embed private images in posts'), DI::config()->get('system', 'disable_embedded'), DI::l10n()->t('Don\'t replace locally-hosted private photos in posts with an embedded copy of the image. This means that contacts who receive posts containing private photos will have to authenticate and load each image, which may take a while.')],
'$explicit_content' => ['explicit_content', DI::l10n()->t('Explicit Content'), DI::config()->get('system', 'explicit_content'), DI::l10n()->t('Set this to announce that your node is used mostly for explicit content that might not be suited for minors. This information will be published in the node information and might be used, e.g. by the global directory, to filter your node from listings of nodes to join. Additionally a note about this will be shown at the user registration page.')],
'$proxify_content' => ['proxify_content', DI::l10n()->t('Proxify external content'), DI::config()->get('system', 'proxify_content'), DI::l10n()->t('Route external content via the proxy functionality. This is used for example for some OEmbed accesses and in some other rare cases.')],
'$local_search' => ['local_search', DI::l10n()->t('Only local search'), DI::config()->get('system', 'local_search'), DI::l10n()->t('Blocks search for users who are not logged in to prevent crawlers from blocking your system.')],
'$blocked_tags' => ['blocked_tags', DI::l10n()->t('Blocked tags for trending tags'), DI::config()->get('system', 'blocked_tags'), DI::l10n()->t("Comma separated list of hashtags that shouldn't be displayed in the trending tags.")],
'$cache_contact_avatar' => ['cache_contact_avatar', DI::l10n()->t('Cache contact avatars'), DI::config()->get('system', 'cache_contact_avatar'), DI::l10n()->t('Locally store the avatar pictures of the contacts. This uses a lot of storage space but it increases the performance.')],

View File

@ -1,211 +0,0 @@
<?php
/**
* @copyright Copyright (C) 2010-2024, the Friendica project
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
namespace Friendica\Module;
use Friendica\BaseModule;
use Friendica\Core\Logger;
use Friendica\Core\System;
use Friendica\DI;
use Friendica\Network\HTTPClient\Client\HttpClientAccept;
use Friendica\Network\HTTPClient\Client\HttpClientOptions;
use Friendica\Network\HTTPException\NotModifiedException;
use Friendica\Object\Image;
use Friendica\Util\HTTPSignature;
use Friendica\Util\Images;
use Friendica\Util\Proxy as ProxyUtils;
/**
* Module Proxy
*
* urls:
* /proxy/[sub1/[sub2/]]<base64url image url>[.ext][:size]
* /proxy?url=<image url>
*/
class Proxy extends BaseModule
{
/**
* Fetch remote image content
*/
protected function rawContent(array $request = [])
{
$request = $this->getRequestInfo();
if (!DI::config()->get('system', 'proxify_content')) {
Logger::notice('Proxy access is forbidden', ['request' => $request, 'agent' => $_SERVER['HTTP_USER_AGENT'] ?? '', 'accept' => $_SERVER['HTTP_ACCEPT'] ?? '']);
throw new \Friendica\Network\HTTPException\NotFoundException();
}
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
header('Last-Modified: ' . gmdate('D, d M Y H:i:s', time()) . ' GMT');
if (!empty($_SERVER['HTTP_IF_NONE_MATCH'])) {
header('Etag: ' . $_SERVER['HTTP_IF_NONE_MATCH']);
}
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + (31536000)) . ' GMT');
header('Cache-Control: max-age=31536000');
if (function_exists('header_remove')) {
header_remove('Last-Modified');
header_remove('Expires');
header_remove('Cache-Control');
}
throw new NotModifiedException();
}
if (empty($request['url'])) {
throw new \Friendica\Network\HTTPException\BadRequestException();
}
if (!DI::userSession()->getLocalUserId()) {
Logger::debug('Redirecting not logged in user to original address', ['url' => $request['url']]);
System::externalRedirect($request['url']);
}
// It shouldn't happen but it does - spaces in URL
$request['url'] = str_replace(' ', '+', $request['url']);
// Fetch the content with the local user
try {
$fetchResult = HTTPSignature::fetchRaw($request['url'], DI::userSession()->getLocalUserId(), [HttpClientOptions::ACCEPT_CONTENT => [HttpClientAccept::IMAGE], 'timeout' => 10]);
$img_str = $fetchResult->getBodyString();
if (!$fetchResult->isSuccess() || empty($img_str)) {
Logger::notice('Error fetching image', ['image' => $request['url'], 'return' => $fetchResult->getReturnCode(), 'empty' => empty($img_str)]);
self::responseError();
// stop.
}
} catch (\Exception $exception) {
Logger::notice('Error fetching image', ['image' => $request['url'], 'exception' => $exception]);
self::responseError();
}
Logger::debug('Got picture', ['Content-Type' => $fetchResult->getHeader('Content-Type'), 'uid' => DI::userSession()->getLocalUserId(), 'image' => $request['url']]);
$image = new Image($img_str, $fetchResult->getContentType(), $request['url']);
if (!$image->isValid()) {
Logger::notice('The image is invalid', ['image' => $request['url'], 'mime' => $fetchResult->getContentType()]);
self::responseError();
// stop.
}
// reduce quality - if it is supported for this image type
if (Images::canResize($image->getType())) {
$image->scaleDown($request['size']);
}
self::responseImageHttpCache($image);
// stop.
}
/**
* Build info about requested image to be proxied
*
* @return array
* [
* 'url' => requested url,
* 'size' => requested image size (int)
* 'sizetype' => requested image size (string): ':micro', ':thumb', ':small', ':medium', ':large'
* ]
* @throws \Exception
*/
private function getRequestInfo(): array
{
$size = ProxyUtils::PIXEL_LARGE;
$sizetype = '';
if (!empty($this->parameters['url']) && empty($_REQUEST['url'])) {
$url = $this->parameters['url'];
// thumb, small, medium and large.
if (substr($url, -6) == ':micro') {
$size = ProxyUtils::PIXEL_MICRO;
$sizetype = ':micro';
$url = substr($url, 0, -6);
} elseif (substr($url, -6) == ':thumb') {
$size = ProxyUtils::PIXEL_THUMB;
$sizetype = ':thumb';
$url = substr($url, 0, -6);
} elseif (substr($url, -6) == ':small') {
$size = ProxyUtils::PIXEL_SMALL;
$url = substr($url, 0, -6);
$sizetype = ':small';
} elseif (substr($url, -7) == ':medium') {
$size = ProxyUtils::PIXEL_MEDIUM;
$url = substr($url, 0, -7);
$sizetype = ':medium';
} elseif (substr($url, -6) == ':large') {
$size = ProxyUtils::PIXEL_LARGE;
$url = substr($url, 0, -6);
$sizetype = ':large';
}
$pos = strrpos($url, '=.');
if ($pos) {
$url = substr($url, 0, $pos + 1);
}
$url = str_replace(['.jpg', '.jpeg', '.gif', '.png'], ['','','',''], $url);
$url = base64_decode(strtr($url, '-_', '+/'), true);
} else {
$url = $_REQUEST['url'] ?? '';
}
return [
'url' => $url,
'size' => $size,
'sizetype' => $sizetype,
];
}
/**
* In case of an error just stop. We don't return content to avoid caching problems
*
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
private static function responseError()
{
throw new \Friendica\Network\HTTPException\InternalServerErrorException();
}
/**
* Output the image with cache headers
*
* @param Image $img
* @return void
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
private static function responseImageHttpCache(Image $img)
{
if (is_null($img) || !$img->isValid()) {
Logger::notice('The cached image is invalid');
self::responseError();
// stop.
}
header('Content-type: ' . $img->getType());
header('Last-Modified: ' . gmdate('D, d M Y H:i:s', time()) . ' GMT');
header('Etag: "' . md5($img->asString()) . '"');
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + (31536000)) . ' GMT');
header('Cache-Control: max-age=31536000');
echo $img->asString();
System::exit();
}
}

View File

@ -69,63 +69,6 @@ class Proxy
// No instances from utilities classes
}
/**
* Transform a remote URL into a local one.
*
* This function only performs the URL replacement on http URL and if the
* provided URL isn't local
*
* @param string $url The URL to proxify
* @param string $size One of the Proxy::SIZE_* constants
* @return string The proxified URL or relative path
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public static function proxifyUrl(string $url, string $size = ''): string
{
if (!DI::config()->get('system', 'proxify_content')) {
return $url;
}
// Trim URL first
$url = trim($url);
// Quit if not an HTTP/HTTPS link or if local
if (!in_array(parse_url($url, PHP_URL_SCHEME), ['http', 'https']) || self::isLocalImage($url)) {
return $url;
}
// Image URL may have encoded ampersands for display which aren't desirable for proxy
$url = html_entity_decode($url, ENT_NOQUOTES, 'utf-8');
$shortpath = hash('md5', $url);
$longpath = substr($shortpath, 0, 2);
$longpath .= '/' . strtr(base64_encode($url), '+/', '-_');
// Extract the URL extension
$extension = pathinfo(parse_url($url, PHP_URL_PATH), PATHINFO_EXTENSION);
if (in_array($extension, self::$extensions)) {
$shortpath .= '.' . $extension;
$longpath .= '.' . $extension;
}
$proxypath = DI::baseUrl() . '/proxy/' . $longpath;
if ($size != '') {
$size = ':' . $size;
}
Logger::info('Created proxy link', ['url' => $url]);
// Too long files aren't supported by Apache
if (strlen($proxypath) > 250) {
return DI::baseUrl() . '/proxy/' . $shortpath . '?url=' . urlencode($url);
} else {
return $proxypath . $size;
}
}
/**
* "Proxifies" HTML code's image tags
*

View File

@ -595,13 +595,6 @@ return [
'/u/{nickname}' => $profileRoutes,
'/~{nickname}' => $profileRoutes,
'/proxy' => [
'[/]' => [Module\Proxy::class, [R::GET]],
'/{url}' => [Module\Proxy::class, [R::GET]],
'/{sub1}/{url}' => [Module\Proxy::class, [R::GET]],
'/{sub1}/{sub2}/{url}' => [Module\Proxy::class, [R::GET]],
],
// OStatus stack modules
'/ostatus/repair' => [Module\OStatus\Repair::class, [R::GET ]],
'/ostatus/subscribe' => [Module\OStatus\Subscribe::class, [R::GET ]],

View File

@ -241,10 +241,6 @@ return [
// Maximum amount of tags in a post before it is rejected as spam.
'relay_max_tags' => 20,
// proxify_content (Boolean)
// Use the proxy functionality for fetching external content
'proxify_content' => true,
// relay_directly (Boolean)
// Directly transmit content to relay subscribers without using a relay server
'relay_directly' => false,

File diff suppressed because it is too large Load Diff

View File

@ -88,7 +88,6 @@
{{include file="field_checkbox.tpl" field=$allow_relay_channels}}
{{include file="field_checkbox.tpl" field=$adjust_poll_frequency}}
{{include file="field_checkbox.tpl" field=$explicit_content}}
{{include file="field_checkbox.tpl" field=$proxify_content}}
{{include file="field_checkbox.tpl" field=$local_search}}
{{include file="field_input.tpl" field=$blocked_tags}}
<div class="submit"><input type="submit" name="page_site" value="{{$submit}}"/></div>

View File

@ -168,7 +168,6 @@
{{include file="field_checkbox.tpl" field=$allow_relay_channels}}
{{include file="field_checkbox.tpl" field=$adjust_poll_frequency}}
{{include file="field_checkbox.tpl" field=$explicit_content}}
{{include file="field_checkbox.tpl" field=$proxify_content}}
{{include file="field_checkbox.tpl" field=$local_search}}
{{include file="field_input.tpl" field=$blocked_tags}}
</div>