Browse Source

[WIP] Rewrite to Proxy class: (#5507)

* Rewrite to Proxy class:
- introduced new Friendica\Network\Proxy class for in exchange of proxy_*()
  functions
- moved also all PROXY_* constants there as Proxy::*
- removed now no longer needed mod/proxy.php loading as composer's auto-load
  will do this for us
- renamed those proxy_*() functions to better names:
  + proxy_init()           -> Proxy::init()         (public)
  + proxy_url()            -> Proxy::proxifyUrl()   (public)
  + proxy_parse_html()     -> Proxy::proxifyHtml()  (public)
  + proxy_is_local_image() -> Proxy::isLocalImage() (private)
  + proxy_parse_query()    -> Proxy::parseQuery()   (private)
  + proxy_img_cb()         -> Proxy::replaceUrl()   (private)

* Ops, need to set $a here ...

* CR request:
- moved Proxy class to Friendica\Module
- extended BaseModule

* Ops, no need for own instance of $a when self::getApp() is around.

* Proxy-rewrite:
- proxy_url() and proxy_parse_html() are both non-module functions (now
  methods)
- so they must be splitted into a seperate class
- also the SIZE_* and DEFAULT_TIME constants are both not relevant to module

* No instances from utility classes

* Fixed error:
- proxify*() is now located in `Friendica\Util\ProxyUtils`

* Moved back to original place, ops? How did they move here? Well, it was not
intended by me.

* Removed duplicate (left-over from split) constants and static array. Thank to
MrPetovan finding it.

* Renamed ProxyUtils -> Proxy and aliased it back to ProxyUtils.
pull/5534/head
Roland Häder 3 years ago
committed by Hypolite Petovan
parent
commit
4d39164c1e
30 changed files with 578 additions and 448 deletions
  1. +3
    -3
      include/api.php
  2. +9
    -4
      include/conversation.php
  3. +1
    -0
      include/dba.php
  4. +2
    -2
      include/text.php
  5. +4
    -4
      mod/acl.php
  6. +2
    -1
      mod/allfriends.php
  7. +2
    -1
      mod/common.php
  8. +2
    -3
      mod/contacts.php
  9. +2
    -3
      mod/directory.php
  10. +2
    -1
      mod/dirfind.php
  11. +2
    -1
      mod/follow.php
  12. +2
    -1
      mod/hovercard.php
  13. +2
    -2
      mod/match.php
  14. +3
    -2
      mod/message.php
  15. +2
    -1
      mod/network.php
  16. +3
    -3
      mod/ping.php
  17. +0
    -375
      mod/proxy.php
  18. +5
    -5
      mod/suggest.php
  19. +2
    -3
      mod/viewcontacts.php
  20. +2
    -1
      src/Content/ForumManager.php
  21. +6
    -3
      src/Content/OEmbed.php
  22. +3
    -4
      src/Content/Text/BBCode.php
  23. +12
    -11
      src/Core/NotificationsManager.php
  24. +2
    -2
      src/Model/Profile.php
  25. +268
    -0
      src/Module/Proxy.php
  26. +4
    -4
      src/Object/Post.php
  27. +2
    -2
      src/Protocol/OStatus.php
  28. +221
    -0
      src/Util/Proxy.php
  29. +5
    -2
      src/Worker/CronJobs.php
  30. +3
    -4
      view/theme/vier/theme.php

+ 3
- 3
include/api.php View File

@ -40,6 +40,7 @@ use Friendica\Object\Image;
use Friendica\Protocol\Diaspora;
use Friendica\Util\DateTimeFormat;
use Friendica\Util\Network;
use Friendica\Util\Proxy as ProxyUtils;
use Friendica\Util\XML;
require_once 'include/conversation.php';
@ -47,7 +48,6 @@ require_once 'mod/share.php';
require_once 'mod/item.php';
require_once 'include/security.php';
require_once 'mod/wall_upload.php';
require_once 'mod/proxy.php';
define('API_METHOD_ANY', '*');
define('API_METHOD_GET', 'GET');
@ -2518,7 +2518,7 @@ function api_get_entitities(&$text, $bbcode)
preg_match_all("/\[img](.*?)\[\/img\]/ism", $bbcode, $images);
foreach ($images[1] as $image) {
$replace = proxy_url($image);
$replace = ProxyUtils::proxifyUrl($image);
$text = str_replace($image, $replace, $text);
}
return [];
@ -2627,7 +2627,7 @@ function api_get_entitities(&$text, $bbcode)
// If image cache is activated, then use the following sizes:
// thumb (150), small (340), medium (600) and large (1024)
if (!Config::get("system", "proxy_disabled")) {
$media_url = proxy_url($url);
$media_url = ProxyUtils::proxifyUrl($url);
$sizes = [];
$scale = Image::getScalingDimensions($image[0], $image[1], 150);


+ 9
- 4
include/conversation.php View File

@ -20,6 +20,7 @@ use Friendica\Model\Term;
use Friendica\Object\Post;
use Friendica\Object\Thread;
use Friendica\Util\DateTimeFormat;
use Friendica\Util\Proxy as ProxyUtils;
use Friendica\Util\Temporal;
use Friendica\Util\XML;
@ -407,7 +408,6 @@ function visible_activity($item) {
*
*/
function conversation(App $a, array $items, $mode, $update, $preview = false, $order = 'commented', $uid = 0) {
require_once 'mod/proxy.php';
$ssl_state = ((local_user()) ? true : false);
@ -418,8 +418,10 @@ function conversation(App $a, array $items, $mode, $update, $preview = false, $o
if (local_user()) {
$str_blocked = PConfig::get(local_user(), 'system', 'blocked');
if ($str_blocked) {
$arr_blocked = explode(',', $str_blocked);
for ($x = 0; $x < count($arr_blocked); $x ++) {
$arr_blocked[$x] = trim($arr_blocked[$x]);
}
@ -477,6 +479,7 @@ function conversation(App $a, array $items, $mode, $update, $preview = false, $o
}
} elseif ($mode === 'notes') {
$profile_owner = local_user();
if (!$update) {
$live_update_div = '<div id="live-notes"></div>' . "\r\n"
. "<script> var profile_uid = " . local_user()
@ -484,6 +487,7 @@ function conversation(App $a, array $items, $mode, $update, $preview = false, $o
}
} elseif ($mode === 'display') {
$profile_owner = $a->profile['uid'];
if (!$update) {
$live_update_div = '<div id="live-display"></div>' . "\r\n"
. "<script> var profile_uid = " . defaults($_SESSION, 'uid', 0) . ";"
@ -492,6 +496,7 @@ function conversation(App $a, array $items, $mode, $update, $preview = false, $o
} elseif ($mode === 'community') {
$items = conversation_add_children($items, true, $order, $uid);
$profile_owner = 0;
if (!$update) {
$live_update_div = '<div id="live-community"></div>' . "\r\n"
. "<script> var profile_uid = -1; var netargs = '" . substr($a->cmd, 10)
@ -523,7 +528,7 @@ function conversation(App $a, array $items, $mode, $update, $preview = false, $o
$page_template = get_markup_template("conversation.tpl");
if ($items && count($items)) {
if (!empty($items)) {
if ($mode === 'community') {
$writable = true;
} else {
@ -645,7 +650,7 @@ function conversation(App $a, array $items, $mode, $update, $preview = false, $o
'name' => $profile_name_e,
'sparkle' => $sparkle,
'lock' => $lock,
'thumb' => System::removedBaseUrl(proxy_url($item['author-avatar'], false, PROXY_SIZE_THUMB)),
'thumb' => System::removedBaseUrl(ProxyUtils::proxifyUrl($item['author-avatar'], false, ProxyUtils::SIZE_THUMB)),
'title' => $title_e,
'body' => $body_e,
'tags' => $tags_e,
@ -664,7 +669,7 @@ function conversation(App $a, array $items, $mode, $update, $preview = false, $o
'indent' => '',
'owner_name' => $owner_name_e,
'owner_url' => $owner_url,
'owner_photo' => System::removedBaseUrl(proxy_url($item['owner-avatar'], false, PROXY_SIZE_THUMB)),
'owner_photo' => System::removedBaseUrl(ProxyUtils::proxifyUrl($item['owner-avatar'], false, ProxyUtils::SIZE_THUMB)),
'plink' => get_plink($item),
'edpost' => false,
'isstarred' => $isstarred,


+ 1
- 0
include/dba.php View File

@ -11,6 +11,7 @@ use Friendica\Database\DBA;
*
* @param $args Query parameters (1 to N parameters of different types)
* @return array|bool Query array
* @deprecated
*/
function q($sql) {
$args = func_get_args();


+ 2
- 2
include/text.php View File

@ -20,8 +20,8 @@ use Friendica\Model\Item;
use Friendica\Render\FriendicaSmarty;
use Friendica\Util\DateTimeFormat;
use Friendica\Util\Map;
use Friendica\Util\Proxy as ProxyUtils;
require_once "mod/proxy.php";
require_once "include/conversation.php";
/**
@ -858,7 +858,7 @@ function micropro($contact, $redirect = false, $class = '', $textmode = false) {
'$click' => defaults($contact, 'click', ''),
'$class' => $class,
'$url' => $url,
'$photo' => proxy_url($contact['thumb'], false, PROXY_SIZE_THUMB),
'$photo' => ProxyUtils::proxifyUrl($contact['thumb'], false, ProxyUtils::SIZE_THUMB),
'$name' => $contact['name'],
'title' => $contact['name'] . ' [' . $contact['addr'] . ']',
'$parkle' => $sparkle,


+ 4
- 4
mod/acl.php View File

@ -9,9 +9,9 @@ use Friendica\Core\Addon;
use Friendica\Database\DBA;
use Friendica\Model\Contact;
use Friendica\Model\Item;
use Friendica\Util\Proxy as ProxyUtils;
require_once 'include/dba.php';
require_once 'mod/proxy.php';
function acl_content(App $a)
{
@ -192,7 +192,7 @@ function acl_content(App $a)
$contacts = [];
foreach ($r as $g) {
$contacts[] = [
'photo' => proxy_url($g['photo'], false, PROXY_SIZE_MICRO),
'photo' => ProxyUtils::proxifyUrl($g['photo'], false, ProxyUtils::SIZE_MICRO),
'name' => $g['name'],
'nick' => defaults($g, 'addr', $g['url']),
'network' => $g['network'],
@ -214,7 +214,7 @@ function acl_content(App $a)
foreach ($r as $g) {
$entry = [
'type' => 'c',
'photo' => proxy_url($g['micro'], false, PROXY_SIZE_MICRO),
'photo' => ProxyUtils::proxifyUrl($g['micro'], false, ProxyUtils::SIZE_MICRO),
'name' => htmlentities($g['name']),
'id' => intval($g['id']),
'network' => $g['network'],
@ -275,7 +275,7 @@ function acl_content(App $a)
if (count($contact) > 0) {
$unknown_contacts[] = [
'type' => 'c',
'photo' => proxy_url($contact['micro'], false, PROXY_SIZE_MICRO),
'photo' => ProxyUtils::proxifyUrl($contact['micro'], false, ProxyUtils::SIZE_MICRO),
'name' => htmlentities($contact['name']),
'id' => intval($contact['cid']),
'network' => $contact['network'],


+ 2
- 1
mod/allfriends.php View File

@ -11,6 +11,7 @@ use Friendica\Database\DBA;
use Friendica\Model\Contact;
use Friendica\Model\GContact;
use Friendica\Model\Profile;
use Friendica\Util\Proxy as ProxyUtils;
require_once 'include/dba.php';
require_once 'mod/contacts.php';
@ -80,7 +81,7 @@ function allfriends_content(App $a)
'url' => $rr['url'],
'itemurl' => defaults($contact_details, 'addr', $rr['url']),
'name' => htmlentities($contact_details['name']),
'thumb' => proxy_url($contact_details['thumb'], false, PROXY_SIZE_THUMB),
'thumb' => ProxyUtils::proxifyUrl($contact_details['thumb'], false, ProxyUtils::SIZE_THUMB),
'img_hover' => htmlentities($contact_details['name']),
'details' => $contact_details['location'],
'tags' => $contact_details['keywords'],


+ 2
- 1
mod/common.php View File

@ -10,6 +10,7 @@ use Friendica\Database\DBA;
use Friendica\Model\Contact;
use Friendica\Model\GContact;
use Friendica\Model\Profile;
use Friendica\Util\Proxy as ProxyUtils;
require_once 'include/dba.php';
require_once 'mod/contacts.php';
@ -120,7 +121,7 @@ function common_content(App $a)
'url' => $rr['url'],
'itemurl' => defaults($contact_details, 'addr', $rr['url']),
'name' => $contact_details['name'],
'thumb' => proxy_url($contact_details['thumb'], false, PROXY_SIZE_THUMB),
'thumb' => ProxyUtils::proxifyUrl($contact_details['thumb'], false, ProxyUtils::SIZE_THUMB),
'img_hover' => htmlentities($contact_details['name']),
'details' => $contact_details['location'],
'tags' => $contact_details['keywords'],


+ 2
- 3
mod/contacts.php View File

@ -19,8 +19,7 @@ use Friendica\Model\Group;
use Friendica\Model\Profile;
use Friendica\Network\Probe;
use Friendica\Util\DateTimeFormat;
require_once 'mod/proxy.php';
use Friendica\Util\Proxy as ProxyUtils;
function contacts_init(App $a)
{
@ -970,7 +969,7 @@ function _contact_detail_for_template(array $rr)
'id' => $rr['id'],
'alt_text' => $alt_text,
'dir_icon' => $dir_icon,
'thumb' => proxy_url($rr['thumb'], false, PROXY_SIZE_THUMB),
'thumb' => ProxyUtils::proxifyUrl($rr['thumb'], false, ProxyUtils::SIZE_THUMB),
'name' => htmlentities($rr['name']),
'username' => htmlentities($rr['name']),
'account_type' => Contact::getAccountType($rr),


+ 2
- 3
mod/directory.php View File

@ -12,6 +12,7 @@ use Friendica\Core\L10n;
use Friendica\Database\DBA;
use Friendica\Model\Contact;
use Friendica\Model\Profile;
use Friendica\Util\Proxy as ProxyUtils;
function directory_init(App $a)
{
@ -35,8 +36,6 @@ function directory_post(App $a)
function directory_content(App $a)
{
require_once("mod/proxy.php");
if ((Config::get('system', 'block_public') && !local_user() && !remote_user())
|| (Config::get('system', 'block_local_dir') && !local_user() && !remote_user())
) {
@ -165,7 +164,7 @@ function directory_content(App $a)
'id' => $rr['id'],
'url' => $profile_link,
'itemurl' => $itemurl,
'thumb' => proxy_url($rr[$photo], false, PROXY_SIZE_THUMB),
'thumb' => ProxyUtils::proxifyUrl($rr[$photo], false, ProxyUtils::SIZE_THUMB),
'img_hover' => $rr['name'],
'name' => $rr['name'],
'details' => $details,


+ 2
- 1
mod/dirfind.php View File

@ -16,6 +16,7 @@ use Friendica\Model\GContact;
use Friendica\Network\Probe;
use Friendica\Protocol\PortableContact;
use Friendica\Util\Network;
use Friendica\Util\Proxy as ProxyUtils;
require_once 'mod/contacts.php';
@ -226,7 +227,7 @@ function dirfind_content(App $a, $prefix = "") {
'url' => Contact::magicLink($jj->url),
'itemurl' => $itemurl,
'name' => htmlentities($jj->name),
'thumb' => proxy_url($jj->photo, false, PROXY_SIZE_THUMB),
'thumb' => ProxyUtils::proxifyUrl($jj->photo, false, ProxyUtils::SIZE_THUMB),
'img_hover' => $jj->tags,
'conntxt' => $conntxt,
'connlnk' => $connlnk,


+ 2
- 1
mod/follow.php View File

@ -10,6 +10,7 @@ use Friendica\Model\Contact;
use Friendica\Model\Profile;
use Friendica\Network\Probe;
use Friendica\Database\DBA;
use Friendica\Util\Proxy as ProxyUtils;
function follow_post(App $a)
{
@ -144,7 +145,7 @@ function follow_content(App $a)
$o = replace_macros($tpl, [
'$header' => htmlentities($header),
//'$photo' => proxy_url($ret['photo'], false, PROXY_SIZE_SMALL),
//'$photo' => ProxyUtils::proxifyUrl($ret['photo'], false, ProxyUtils::SIZE_SMALL),
'$desc' => '',
'$pls_answer' => L10n::t('Please answer the following:'),
'$does_know_you' => ['knowyou', L10n::t('Does %s know you?', $ret['name']), false, '', [L10n::t('No'), L10n::t('Yes')]],


+ 2
- 1
mod/hovercard.php View File

@ -14,6 +14,7 @@ use Friendica\Core\System;
use Friendica\Database\DBA;
use Friendica\Model\Contact;
use Friendica\Model\GContact;
use Friendica\Util\Proxy as ProxyUtils;
function hovercard_init(App $a)
{
@ -96,7 +97,7 @@ function hovercard_content()
'name' => $contact['name'],
'nick' => $contact['nick'],
'addr' => defaults($contact, 'addr', $contact['url']),
'thumb' => proxy_url($contact['thumb'], false, PROXY_SIZE_THUMB),
'thumb' => ProxyUtils::proxifyUrl($contact['thumb'], false, ProxyUtils::SIZE_THUMB),
'url' => Contact::magicLink($contact['url']),
'nurl' => $contact['nurl'], // We additionally store the nurl as identifier
'location' => $contact['location'],


+ 2
- 2
mod/match.php View File

@ -11,9 +11,9 @@ use Friendica\Core\System;
use Friendica\Database\DBA;
use Friendica\Model\Contact;
use Friendica\Util\Network;
use Friendica\Util\Proxy as ProxyUtils;
require_once 'include/text.php';
require_once 'mod/proxy.php';
/**
* @brief Controller for /match.
@ -100,7 +100,7 @@ function match_content(App $a)
'tags' => $contact_details['keywords'],
'about' => $contact_details['about'],
'account_type' => Contact::getAccountType($contact_details),
'thumb' => proxy_url($jj->photo, false, PROXY_SIZE_THUMB),
'thumb' => ProxyUtils::proxifyUrl($jj->photo, false, ProxyUtils::SIZE_THUMB),
'inttxt' => ' ' . L10n::t('is interested in:'),
'conntxt' => L10n::t('Connect'),
'connlnk' => $connlnk,


+ 3
- 2
mod/message.php View File

@ -14,6 +14,7 @@ use Friendica\Database\DBA;
use Friendica\Model\Contact;
use Friendica\Model\Mail;
use Friendica\Util\DateTimeFormat;
use Friendica\Util\Proxy as ProxyUtils;
use Friendica\Util\Temporal;
require_once 'include/conversation.php';
@ -388,7 +389,7 @@ function message_content(App $a)
'from_url' => $from_url,
'from_addr' => $contact['addr'],
'sparkle' => $sparkle,
'from_photo' => proxy_url($from_photo, false, PROXY_SIZE_THUMB),
'from_photo' => ProxyUtils::proxifyUrl($from_photo, false, ProxyUtils::SIZE_THUMB),
'subject' => $subject_e,
'body' => $body_e,
'delete' => L10n::t('Delete message'),
@ -489,7 +490,7 @@ function render_messages(array $msg, $t)
'$from_url' => Contact::magicLink($rr['url']),
'$from_addr' => $contact['addr'],
'$sparkle' => ' sparkle',
'$from_photo' => proxy_url($from_photo, false, PROXY_SIZE_THUMB),
'$from_photo' => ProxyUtils::proxifyUrl($from_photo, false, ProxyUtils::SIZE_THUMB),
'$subject' => $subject_e,
'$delete' => L10n::t('Delete conversation'),
'$body' => $body_e,


+ 2
- 1
mod/network.php View File

@ -22,6 +22,7 @@ use Friendica\Model\Item;
use Friendica\Model\Profile;
use Friendica\Module\Login;
use Friendica\Util\DateTimeFormat;
use Friendica\Util\Proxy as ProxyUtils;
require_once 'include/conversation.php';
require_once 'include/items.php';
@ -652,7 +653,7 @@ function networkThreadedView(App $a, $update, $parent)
'id' => 'network',
'name' => htmlentities($contact['name']),
'itemurl' => defaults($contact, 'addr', $contact['nurl']),
'thumb' => proxy_url($contact['thumb'], false, PROXY_SIZE_THUMB),
'thumb' => ProxyUtils::proxifyUrl($contact['thumb'], false, ProxyUtils::SIZE_THUMB),
'details' => $contact['location'],
];


+ 3
- 3
mod/ping.php View File

@ -19,9 +19,9 @@ use Friendica\Model\Group;
use Friendica\Model\Item;
use Friendica\Util\DateTimeFormat;
use Friendica\Util\Temporal;
use Friendica\Util\Proxy as ProxyUtils;
use Friendica\Util\XML;
require_once 'mod/proxy.php';
require_once 'include/enotify.php';
/**
@ -356,9 +356,9 @@ function ping_init(App $a)
$contact = Contact::getDetailsByURL($notif['url']);
if (isset($contact['micro'])) {
$notif['photo'] = proxy_url($contact['micro'], false, PROXY_SIZE_MICRO);
$notif['photo'] = ProxyUtils::proxifyUrl($contact['micro'], false, ProxyUtils::SIZE_MICRO);
} else {
$notif['photo'] = proxy_url($notif['photo'], false, PROXY_SIZE_MICRO);
$notif['photo'] = ProxyUtils::proxifyUrl($notif['photo'], false, ProxyUtils::SIZE_MICRO);
}
$local_time = DateTimeFormat::local($notif['date']);


+ 0
- 375
mod/proxy.php View File

@ -1,375 +0,0 @@
<?php
/**
* @file mod/proxy.php
* @brief Based upon "Privacy Image Cache" by Tobias Hößl <https://github.com/CatoTH/>
*/
use Friendica\App;
use Friendica\Core\Config;
use Friendica\Core\System;
use Friendica\Database\DBA;
use Friendica\Model\Photo;
use Friendica\Object\Image;
use Friendica\Util\DateTimeFormat;
use Friendica\Util\Network;
define('PROXY_DEFAULT_TIME', 86400); // 1 Day
define('PROXY_SIZE_MICRO', 'micro');
define('PROXY_SIZE_THUMB', 'thumb');
define('PROXY_SIZE_SMALL', 'small');
define('PROXY_SIZE_MEDIUM', 'medium');
define('PROXY_SIZE_LARGE', 'large');
require_once 'include/security.php';
function proxy_init(App $a) {
// Pictures are stored in one of the following ways:
// 1. If a folder "proxy" exists and is writeable, then use this for caching
// 2. If a cache path is defined, use this
// 3. If everything else failed, cache into the database
//
// Question: Do we really need these three methods?
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
header('HTTP/1.1 304 Not Modified');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s', time()) . ' GMT');
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');
}
exit;
}
if (function_exists('header_remove')) {
header_remove('Pragma');
header_remove('pragma');
}
$thumb = false;
$size = 1024;
$sizetype = '';
$basepath = $a->get_basepath();
// If the cache path isn't there, try to create it
if (!is_dir($basepath . '/proxy') && is_writable($basepath)) {
mkdir($basepath . '/proxy');
}
// Checking if caching into a folder in the webroot is activated and working
$direct_cache = (is_dir($basepath . '/proxy') && is_writable($basepath . '/proxy'));
// Look for filename in the arguments
if ((isset($a->argv[1]) || isset($a->argv[2]) || isset($a->argv[3])) && !isset($_REQUEST['url'])) {
if (isset($a->argv[3])) {
$url = $a->argv[3];
} elseif (isset($a->argv[2])) {
$url = $a->argv[2];
} else {
$url = $a->argv[1];
}
if (isset($a->argv[3]) && ($a->argv[3] == 'thumb')) {
$size = 200;
}
// thumb, small, medium and large.
if (substr($url, -6) == ':micro') {
$size = 48;
$sizetype = ':micro';
$url = substr($url, 0, -6);
} elseif (substr($url, -6) == ':thumb') {
$size = 80;
$sizetype = ':thumb';
$url = substr($url, 0, -6);
} elseif (substr($url, -6) == ':small') {
$size = 175;
$url = substr($url, 0, -6);
$sizetype = ':small';
} elseif (substr($url, -7) == ':medium') {
$size = 600;
$url = substr($url, 0, -7);
$sizetype = ':medium';
} elseif (substr($url, -6) == ':large') {
$size = 1024;
$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);
if ($url) {
$_REQUEST['url'] = $url;
}
} else {
$direct_cache = false;
}
if (!$direct_cache) {
$urlhash = 'pic:' . sha1($_REQUEST['url']);
$cachefile = get_cachefile(hash('md5', $_REQUEST['url']));
if ($cachefile != '' && file_exists($cachefile)) {
$img_str = file_get_contents($cachefile);
$mime = image_type_to_mime_type(exif_imagetype($cachefile));
header('Content-type: ' . $mime);
header('Last-Modified: ' . gmdate('D, d M Y H:i:s', time()) . ' GMT');
header('Etag: "' . md5($img_str) . '"');
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + (31536000)) . ' GMT');
header('Cache-Control: max-age=31536000');
// reduce quality - if it isn't a GIF
if ($mime != 'image/gif') {
$Image = new Image($img_str, $mime);
if ($Image->isValid()) {
$img_str = $Image->asString();
}
}
echo $img_str;
killme();
}
} else {
$cachefile = '';
}
$valid = true;
$photo = null;
if (!$direct_cache && ($cachefile == '')) {
$photo = DBA::selectFirst('photo', ['data', 'desc'], ['resource-id' => $urlhash]);
if (DBA::isResult($photo)) {
$img_str = $photo['data'];
$mime = $photo['desc'];
if ($mime == '') {
$mime = 'image/jpeg';
}
}
}
if (!DBA::isResult($photo)) {
// It shouldn't happen but it does - spaces in URL
$_REQUEST['url'] = str_replace(' ', '+', $_REQUEST['url']);
$redirects = 0;
$img_str = Network::fetchUrl($_REQUEST['url'], true, $redirects, 10);
$tempfile = tempnam(get_temppath(), 'cache');
file_put_contents($tempfile, $img_str);
$mime = image_type_to_mime_type(exif_imagetype($tempfile));
unlink($tempfile);
// If there is an error then return a blank image
if ((substr($a->get_curl_code(), 0, 1) == '4') || (!$img_str)) {
$img_str = file_get_contents('images/blank.png');
$mime = 'image/png';
$cachefile = ''; // Clear the cachefile so that the dummy isn't stored
$valid = false;
$Image = new Image($img_str, 'image/png');
if ($Image->isValid()) {
$Image->scaleDown(10);
$img_str = $Image->asString();
}
} elseif ($mime != 'image/jpeg' && !$direct_cache && $cachefile == '') {
$image = @imagecreatefromstring($img_str);
if ($image === FALSE) {
die();
}
$fields = ['uid' => 0, 'contact-id' => 0, 'guid' => System::createGUID(), 'resource-id' => $urlhash, 'created' => DateTimeFormat::utcNow(), 'edited' => DateTimeFormat::utcNow(),
'filename' => basename($_REQUEST['url']), 'type' => '', 'album' => '', 'height' => imagesy($image), 'width' => imagesx($image),
'datasize' => 0, 'data' => $img_str, 'scale' => 100, 'profile' => 0,
'allow_cid' => '', 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => '', 'desc' => $mime];
DBA::insert('photo', $fields);
} else {
$Image = new Image($img_str, $mime);
if ($Image->isValid() && !$direct_cache && ($cachefile == '')) {
Photo::store($Image, 0, 0, $urlhash, $_REQUEST['url'], '', 100);
}
}
}
$img_str_orig = $img_str;
// reduce quality - if it isn't a GIF
if ($mime != 'image/gif') {
$Image = new Image($img_str, $mime);
if ($Image->isValid()) {
$Image->scaleDown($size);
$img_str = $Image->asString();
}
}
// If there is a real existing directory then put the cache file there
// advantage: real file access is really fast
// Otherwise write in cachefile
if ($valid && $direct_cache) {
file_put_contents($basepath . '/proxy/' . proxy_url($_REQUEST['url'], true), $img_str_orig);
if ($sizetype != '') {
file_put_contents($basepath . '/proxy/' . proxy_url($_REQUEST['url'], true) . $sizetype, $img_str);
}
} elseif ($cachefile != '') {
file_put_contents($cachefile, $img_str_orig);
}
header('Content-type: ' . $mime);
// Only output the cache headers when the file is valid
if ($valid) {
header('Last-Modified: ' . gmdate('D, d M Y H:i:s', time()) . ' GMT');
header('Etag: "' . md5($img_str) . '"');
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + (31536000)) . ' GMT');
header('Cache-Control: max-age=31536000');
}
echo $img_str;
killme();
}
/**
* @brief 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, "the isn't deactivated" (sic) and if the config
* system.proxy_disabled is set to false.
*
* @param string $url The URL to proxyfy
* @param bool $writemode Returns a local path the remote URL should be saved to
* @param string $size One of the PROXY_SIZE_* constants
*
* @return string The proxyfied URL or relative path
*/
function proxy_url($url, $writemode = false, $size = '') {
$a = get_app();
if (substr($url, 0, strlen('http')) !== 'http') {
return $url;
}
// Only continue if it isn't a local image and the isn't deactivated
if (proxy_is_local_image($url)) {
$url = str_replace(normalise_link(System::baseUrl()) . '/', System::baseUrl() . '/', $url);
return $url;
}
if (Config::get('system', 'proxy_disabled')) {
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');
// Creating a sub directory to reduce the amount of files in the cache directory
$basepath = $a->get_basepath() . '/proxy';
$shortpath = hash('md5', $url);
$longpath = substr($shortpath, 0, 2);
if (is_dir($basepath) && $writemode && !is_dir($basepath . '/' . $longpath)) {
mkdir($basepath . '/' . $longpath);
chmod($basepath . '/' . $longpath, 0777);
}
$longpath .= '/' . strtr(base64_encode($url), '+/', '-_');
// Extract the URL extension
$extension = pathinfo(parse_url($url, PHP_URL_PATH), PATHINFO_EXTENSION);
$extensions = ['jpg', 'jpeg', 'gif', 'png'];
if (in_array($extension, $extensions)) {
$shortpath .= '.' . $extension;
$longpath .= '.' . $extension;
}
$proxypath = System::baseUrl() . '/proxy/' . $longpath;
if ($size != '') {
$size = ':' . $size;
}
// Too long files aren't supported by Apache
// Writemode in combination with long files shouldn't be possible
if ((strlen($proxypath) > 250) && $writemode) {
return $shortpath;
} elseif (strlen($proxypath) > 250) {
return System::baseUrl() . '/proxy/' . $shortpath . '?url=' . urlencode($url);
} elseif ($writemode) {
return $longpath;
} else {
return $proxypath . $size;
}
}
/**
* @param $url string
* @return boolean
*/
function proxy_is_local_image($url) {
if ($url[0] == '/') {
return true;
}
if (strtolower(substr($url, 0, 5)) == 'data:') {
return true;
}
// links normalised - bug #431
$baseurl = normalise_link(System::baseUrl());
$url = normalise_link($url);
return (substr($url, 0, strlen($baseurl)) == $baseurl);
}
/**
* @brief Return the array of query string parameters from a URL
*
* @param string $url
* @return array Associative array of query string parameters
*/
function proxy_parse_query($url) {
$query = parse_url($url, PHP_URL_QUERY);
$query = html_entity_decode($query);
$query_list = explode('&', $query);
$arr = [];
foreach ($query_list as $key_value) {
$key_value_list = explode('=', $key_value);
$arr[$key_value_list[0]] = $key_value_list[1];
}
unset($url, $query_list, $url);
return $arr;
}
function proxy_img_cb($matches) {
// if the picture seems to be from another picture cache then take the original source
$queryvar = proxy_parse_query($matches[2]);
if (($queryvar['url'] != '') && (substr($queryvar['url'], 0, 4) == 'http')) {
$matches[2] = urldecode($queryvar['url']);
}
// following line changed per bug #431
if (proxy_is_local_image($matches[2])) {
return $matches[1] . $matches[2] . $matches[3];
}
return $matches[1] . proxy_url(htmlspecialchars_decode($matches[2])) . $matches[3];
}
function proxy_parse_html($html) {
$html = str_replace(normalise_link(System::baseUrl()) . '/', System::baseUrl() . '/', $html);
return preg_replace_callback('/(<img [^>]*src *= *["\'])([^"\']+)(["\'][^>]*>)/siU', 'proxy_img_cb', $html);
}

+ 5
- 5
mod/suggest.php View File

@ -11,6 +11,7 @@ use Friendica\Core\System;
use Friendica\Database\DBA;
use Friendica\Model\Contact;
use Friendica\Model\GContact;
use Friendica\Util\Proxy as ProxyUtils;
function suggest_init(App $a) {
if (! local_user()) {
@ -51,11 +52,10 @@ function suggest_init(App $a) {
}
function suggest_content(App $a) {
require_once("mod/proxy.php");
function suggest_content(App $a)
{
$o = '';
if (! local_user()) {
notice(L10n::t('Permission denied.') . EOL);
return;
@ -91,7 +91,7 @@ function suggest_content(App $a) {
'itemurl' => (($contact_details['addr'] != "") ? $contact_details['addr'] : $rr['url']),
'img_hover' => $rr['url'],
'name' => $contact_details['name'],
'thumb' => proxy_url($contact_details['thumb'], false, PROXY_SIZE_THUMB),
'thumb' => ProxyUtils::proxifyUrl($contact_details['thumb'], false, ProxyUtils::SIZE_THUMB),
'details' => $contact_details['location'],
'tags' => $contact_details['keywords'],
'about' => $contact_details['about'],


+ 2
- 3
mod/viewcontacts.php View File

@ -10,6 +10,7 @@ use Friendica\Core\L10n;
use Friendica\Database\DBA;
use Friendica\Model\Contact;
use Friendica\Model\Profile;
use Friendica\Util\Proxy as ProxyUtils;
function viewcontacts_init(App $a)
{
@ -39,8 +40,6 @@ function viewcontacts_init(App $a)
function viewcontacts_content(App $a)
{
require_once("mod/proxy.php");
if ((Config::get('system', 'block_public')) && (! local_user()) && (! remote_user())) {
notice(L10n::t('Public access denied.') . EOL);
return;
@ -102,7 +101,7 @@ function viewcontacts_content(App $a)
'id' => $rr['id'],
'img_hover' => L10n::t('Visit %s\'s profile [%s]', $contact_details['name'], $rr['url']),
'photo_menu' => Contact::photoMenu($rr),
'thumb' => proxy_url($contact_details['thumb'], false, PROXY_SIZE_THUMB),
'thumb' => ProxyUtils::proxifyUrl($contact_details['thumb'], false, ProxyUtils::SIZE_THUMB),
'name' => htmlentities(substr($contact_details['name'], 0, 20)),
'username' => htmlentities($contact_details['name']),
'details' => $contact_details['location'],


+ 2
- 1
src/Content/ForumManager.php View File

@ -10,6 +10,7 @@ use Friendica\Core\L10n;
use Friendica\Core\System;
use Friendica\Database\DBA;
use Friendica\Model\Contact;
use Friendica\Util\Proxy as ProxyUtils;
require_once 'include/dba.php';
@ -110,7 +111,7 @@ class ForumManager
'name' => $contact['name'],
'cid' => $contact['id'],
'selected' => $selected,
'micro' => System::removedBaseUrl(proxy_url($contact['micro'], false, PROXY_SIZE_MICRO)),
'micro' => System::removedBaseUrl(ProxyUtils::proxifyUrl($contact['micro'], false, ProxyUtils::SIZE_MICRO)),
'id' => ++$id,
];
$entries[] = $entry;


+ 6
- 3
src/Content/OEmbed.php View File

@ -19,9 +19,9 @@ use Friendica\Database\DBA;
use Friendica\Util\DateTimeFormat;
use Friendica\Util\Network;
use Friendica\Util\ParseUrl;
use Friendica\Util\Proxy as ProxyUtils;
require_once 'include/dba.php';
require_once 'mod/proxy.php';
/**
* Handles all OEmbed content fetching and replacement
@ -191,13 +191,16 @@ class OEmbed
$ret = $oembed->html;
}
break;
case "photo":
$ret .= '<img width="' . $oembed->width . '" src="' . proxy_url($oembed->url) . '">';
$ret .= '<img width="' . $oembed->width . '" src="' . ProxyUtils::proxifyUrl($oembed->url) . '">';
break;
case "link":
break;
case "rich":
$ret .= proxy_parse_html($oembed->html);
$ret .= ProxyUtils::proxifyHtml($oembed->html);
break;
}


+ 3
- 4
src/Content/Text/BBCode.php View File

@ -24,10 +24,9 @@ use Friendica\Object\Image;
use Friendica\Util\Map;
use Friendica\Util\Network;
use Friendica\Util\ParseUrl;
use Friendica\Util\Proxy as ProxyUtils;
use League\HTMLToMarkdown\HtmlConverter;
require_once "mod/proxy.php";
class BBCode extends BaseObject
{
/**
@ -361,7 +360,7 @@ class BBCode extends BaseObject
{
// Only send proxied pictures to API and for internal display
if (in_array($simplehtml, [false, 2])) {
return proxy_url($image);
return ProxyUtils::proxifyUrl($image);
} else {
return $image;
}
@ -1033,7 +1032,7 @@ class BBCode extends BaseObject
} else {
$text = trim($share[1]) . "\n";
$avatar = proxy_url($avatar, false, PROXY_SIZE_THUMB);
$avatar = ProxyUtils::proxifyUrl($avatar, false, ProxyUtils::SIZE_THUMB);
$tpl = get_markup_template('shared_content.tpl');
$text .= replace_macros($tpl, [


+ 12
- 11
src/Core/NotificationsManager.php View File

@ -13,6 +13,7 @@ use Friendica\Database\DBA;
use Friendica\Model\Contact;
use Friendica\Model\Item;
use Friendica\Util\DateTimeFormat;
use Friendica\Util\Proxy as ProxyUtils;
use Friendica\Util\Temporal;
use Friendica\Util\XML;
@ -243,7 +244,7 @@ class NotificationsManager extends BaseObject
case 'system':
$default_item_label = 'notify';
$default_item_link = System::baseUrl(true) . '/notify/view/' . $it['id'];
$default_item_image = proxy_url($it['photo'], false, PROXY_SIZE_MICRO);
$default_item_image = ProxyUtils::proxifyUrl($it['photo'], false, ProxyUtils::SIZE_MICRO);
$default_item_url = $it['url'];
$default_item_text = strip_tags(BBCode::convert($it['msg']));
$default_item_when = DateTimeFormat::local($it['date'], 'r');
@ -253,7 +254,7 @@ class NotificationsManager extends BaseObject
case 'home':
$default_item_label = 'comment';
$default_item_link = System::baseUrl(true) . '/display/' . $it['parent-guid'];
$default_item_image = proxy_url($it['author-avatar'], false, PROXY_SIZE_MICRO);
$default_item_image = ProxyUtils::proxifyUrl($it['author-avatar'], false, ProxyUtils::SIZE_MICRO);
$default_item_url = $it['author-link'];
$default_item_text = L10n::t("%s commented on %s's post", $it['author-name'], $it['parent-author-name']);
$default_item_when = DateTimeFormat::local($it['created'], 'r');
@ -263,7 +264,7 @@ class NotificationsManager extends BaseObject
default:
$default_item_label = (($it['id'] == $it['parent']) ? 'post' : 'comment');
$default_item_link = System::baseUrl(true) . '/display/' . $it['parent-guid'];
$default_item_image = proxy_url($it['author-avatar'], false, PROXY_SIZE_MICRO);
$default_item_image = ProxyUtils::proxifyUrl($it['author-avatar'], false, ProxyUtils::SIZE_MICRO);
$default_item_url = $it['author-link'];
$default_item_text = (($it['id'] == $it['parent'])
? L10n::t("%s created a new post", $it['author-name'])
@ -278,7 +279,7 @@ class NotificationsManager extends BaseObject
$notif = [
'label' => 'like',
'link' => System::baseUrl(true) . '/display/' . $it['parent-guid'],
'image' => proxy_url($it['author-avatar'], false, PROXY_SIZE_MICRO),
'image' => ProxyUtils::proxifyUrl($it['author-avatar'], false, ProxyUtils::SIZE_MICRO),
'url' => $it['author-link'],
'text' => L10n::t("%s liked %s's post", $it['author-name'], $it['parent-author-name']),
'when' => $default_item_when,
@ -291,7 +292,7 @@ class NotificationsManager extends BaseObject
$notif = [
'label' => 'dislike',
'link' => System::baseUrl(true) . '/display/' . $it['parent-guid'],
'image' => proxy_url($it['author-avatar'], false, PROXY_SIZE_MICRO),
'image' => ProxyUtils::proxifyUrl($it['author-avatar'], false, ProxyUtils::SIZE_MICRO),
'url' => $it['author-link'],
'text' => L10n::t("%s disliked %s's post", $it['author-name'], $it['parent-author-name']),
'when' => $default_item_when,
@ -304,7 +305,7 @@ class NotificationsManager extends BaseObject
$notif = [
'label' => 'attend',
'link' => System::baseUrl(true) . '/display/' . $it['parent-guid'],
'image' => proxy_url($it['author-avatar'], false, PROXY_SIZE_MICRO),
'image' => ProxyUtils::proxifyUrl($it['author-avatar'], false, ProxyUtils::SIZE_MICRO),
'url' => $it['author-link'],
'text' => L10n::t("%s is attending %s's event", $it['author-name'], $it['parent-author-name']),
'when' => $default_item_when,
@ -317,7 +318,7 @@ class NotificationsManager extends BaseObject
$notif = [
'label' => 'attendno',
'link' => System::baseUrl(true) . '/display/' . $it['parent-guid'],
'image' => proxy_url($it['author-avatar'], false, PROXY_SIZE_MICRO),
'image' => ProxyUtils::proxifyUrl($it['author-avatar'], false, ProxyUtils::SIZE_MICRO),
'url' => $it['author-link'],
'text' => L10n::t("%s is not attending %s's event", $it['author-name'], $it['parent-author-name']),
'when' => $default_item_when,
@ -330,7 +331,7 @@ class NotificationsManager extends BaseObject
$notif = [
'label' => 'attendmaybe',
'link' => System::baseUrl(true) . '/display/' . $it['parent-guid'],
'image' => proxy_url($it['author-avatar'], false, PROXY_SIZE_MICRO),
'image' => ProxyUtils::proxifyUrl($it['author-avatar'], false, ProxyUtils::SIZE_MICRO),
'url' => $it['author-link'],
'text' => L10n::t("%s may attend %s's event", $it['author-name'], $it['parent-author-name']),
'when' => $default_item_when,
@ -347,7 +348,7 @@ class NotificationsManager extends BaseObject
$notif = [
'label' => 'friend',
'link' => System::baseUrl(true) . '/display/' . $it['parent-guid'],
'image' => proxy_url($it['author-avatar'], false, PROXY_SIZE_MICRO),
'image' => ProxyUtils::proxifyUrl($it['author-avatar'], false, ProxyUtils::SIZE_MICRO),
'url' => $it['author-link'],
'text' => L10n::t("%s is now friends with %s", $it['author-name'], $it['fname']),
'when' => $default_item_when,
@ -622,7 +623,7 @@ class NotificationsManager extends BaseObject
'madeby_zrl' => Contact::magicLink($it['url']),
'madeby_addr' => $it['addr'],
'contact_id' => $it['contact-id'],
'photo' => ((x($it, 'fphoto')) ? proxy_url($it['fphoto'], false, PROXY_SIZE_SMALL) : "images/person-175.jpg"),
'photo' => ((x($it, 'fphoto')) ? ProxyUtils::proxifyUrl($it['fphoto'], false, ProxyUtils::SIZE_SMALL) : "images/person-175.jpg"),
'name' => $it['fname'],
'url' => $it['furl'],
'zrl' => Contact::magicLink($it['furl']),
@ -650,7 +651,7 @@ class NotificationsManager extends BaseObject
'uid' => $_SESSION['uid'],
'intro_id' => $it['intro_id'],
'contact_id' => $it['contact-id'],
'photo' => ((x($it, 'photo')) ? proxy_url($it['photo'], false, PROXY_SIZE_SMALL) : "images/person-175.jpg"),
'photo' => ((x($it, 'photo')) ? ProxyUtils::proxifyUrl($it['photo'], false, ProxyUtils::SIZE_SMALL) : "images/person-175.jpg"),
'name' => $it['name'],
'location' => BBCode::convert($it['glocation'], false),
'about' => BBCode::convert($it['gabout'], false),


+ 2
- 2
src/Model/Profile.php View File

@ -20,10 +20,10 @@ use Friendica\Model\Contact;
use Friendica\Protocol\Diaspora;
use Friendica\Util\DateTimeFormat;
use Friendica\Util\Network;
use Friendica\Util\Proxy as ProxyUtils;
use Friendica\Util\Temporal;
require_once 'include/dba.php';
require_once 'mod/proxy.php';
class Profile
{
@ -495,7 +495,7 @@ class Profile
}
if (isset($p['photo'])) {
$p['photo'] = proxy_url($p['photo'], false, PROXY_SIZE_SMALL);
$p['photo'] = ProxyUtils::proxifyUrl($p['photo'], false, ProxyUtils::SIZE_SMALL);
}
$p['url'] = Contact::magicLink(defaults($p, 'url', $profile_url));


+ 268
- 0
src/Module/Proxy.php View File

@ -0,0 +1,268 @@
<?php
/**
* @file src/Module/Proxy.php
* @brief Based upon "Privacy Image Cache" by Tobias Hößl <https://github.com/CatoTH/>
*/
namespace Friendica\Module;
use Friendica\App;
use Friendica\BaseModule;
use Friendica\Core\Config;
use Friendica\Core\System;
use Friendica\Database\DBA;
use Friendica\Model\Photo;
use Friendica\Object\Image;
use Friendica\Util\DateTimeFormat;
use Friendica\Util\Network;
use Friendica\Util\Proxy as ProxyUtils;
require_once 'include/security.php';
/**
* @brief Module Proxy
*/
class Proxy extends BaseModule
{
/**
* @brief Initializer method for this class.
*
* Sets application instance and checks if /proxy/ path is writable.
*
* @param \Friendica\App $app Application instance
*/
public static function init()
{
// Set application instance here
$a = self::getApp();
/*
* Pictures are stored in one of the following ways:
*
* 1. If a folder "proxy" exists and is writeable, then use this for caching
* 2. If a cache path is defined, use this
* 3. If everything else failed, cache into the database
*
* Question: Do we really need these three methods?
*/
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
header('HTTP/1.1 304 Not Modified');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s', time()) . ' GMT');
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');
}
/// @TODO Stop here?
exit();
}
if (function_exists('header_remove')) {
header_remove('Pragma');
header_remove('pragma');
}
$thumb = false;
$size = 1024;
$sizetype = '';
$basepath = $a->get_basepath();
// If the cache path isn't there, try to create it
if (!is_dir($basepath . '/proxy') && is_writable($basepath)) {
mkdir($basepath . '/proxy');
}
// Checking if caching into a folder in the webroot is activated and working
$direct_cache = (is_dir($basepath . '/proxy') && is_writable($basepath . '/proxy'));
// Look for filename in the arguments
if ((isset($a->argv[1]) || isset($a->argv[2]) || isset($a->argv[3])) && !isset($_REQUEST['url'])) {
if (isset($a->argv[3])) {
$url = $a->argv[3];
} elseif (isset($a->argv[2])) {
$url = $a->argv[2];
} else {
$url = $a->argv[1];
}
if (isset($a->argv[3]) && ($a->argv[3] == 'thumb')) {
$size = 200;
}
// thumb, small, medium and large.
if (substr($url, -6) == ':micro') {
$size = 48;
$sizetype = ':micro';
$url = substr($url, 0, -6);
} elseif (substr($url, -6) == ':thumb') {
$size = 80;
$sizetype = ':thumb';
$url = substr($url, 0, -6);
} elseif (substr($url, -6) == ':small') {
$size = 175;
$url = substr($url, 0, -6);
$sizetype = ':small';
} elseif (substr($url, -7) == ':medium') {
$size = 600;
$url = substr($url, 0, -7);
$sizetype = ':medium';
} elseif (substr($url, -6) == ':large') {
$size = 1024;
$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);
if ($url) {
$_REQUEST['url'] = $url;
}
} else {
$direct_cache = false;
}
if (!$direct_cache) {
$urlhash = 'pic:' . sha1($_REQUEST['url']);
$cachefile = get_cachefile(hash('md5', $_REQUEST['url']));
if ($cachefile != '' && file_exists($cachefile)) {
$img_str = file_get_contents($cachefile);
$mime = image_type_to_mime_type(exif_imagetype($cachefile));
header('Content-type: ' . $mime);
header('Last-Modified: ' . gmdate('D, d M Y H:i:s', time()) . ' GMT');
header('Etag: "' . md5($img_str) . '"');
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + (31536000)) . ' GMT');
header('Cache-Control: max-age=31536000');
// reduce quality - if it isn't a GIF
if ($mime != 'image/gif') {
$image = new Image($img_str, $mime);
if ($image->isValid()) {
$img_str = $image->asString();
}
}
echo $img_str;
exit();
}
} else {
$cachefile = '';
}
$valid = true;
$photo = null;
if (!$direct_cache && ($cachefile == '')) {
$photo = DBA::selectFirst('photo', ['data', 'desc'], ['resource-id' => $urlhash]);
if (DBA::isResult($photo)) {
$img_str = $photo['data'];
$mime = $photo['desc'];
if ($mime == '') {
$mime = 'image/jpeg';
}
}
}
if (!DBA::isResult($photo)) {
// It shouldn't happen but it does - spaces in URL
$_REQUEST['url'] = str_replace(' ', '+', $_REQUEST['url']);
$redirects = 0;
$img_str = Network::fetchUrl($_REQUEST['url'], true, $redirects, 10);
$tempfile = tempnam(get_temppath(), 'cache');
file_put_contents($tempfile, $img_str);
$mime = image_type_to_mime_type(exif_imagetype($tempfile));
unlink($tempfile);
// If there is an error then return a blank image
if ((substr($a->get_curl_code(), 0, 1) == '4') || (!$img_str)) {
$img_str = file_get_contents('images/blank.png');
$mime = 'image/png';
$cachefile = ''; // Clear the cachefile so that the dummy isn't stored
$valid = false;
$image = new Image($img_str, 'image/png');
if ($image->isValid()) {
$image->scaleDown(10);
$img_str = $image->asString();
}
} elseif ($mime != 'image/jpeg' && !$direct_cache && $cachefile == '') {
$image = @imagecreatefromstring($img_str);
if ($image === FALSE) {
die();
}
$fields = ['uid' => 0, 'contact-id' => 0, 'guid' => System::createGUID(), 'resource-id' => $urlhash, 'created' => DateTimeFormat::utcNow(), 'edited' => DateTimeFormat::utcNow(),
'filename' => basename($_REQUEST['url']), 'type' => '', 'album' => '', 'height' => imagesy($image), 'width' => imagesx($image),
'datasize' => 0, 'data' => $img_str, 'scale' => 100, 'profile' => 0,
'allow_cid' => '', 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => '', 'desc' => $mime];
DBA::insert('photo', $fields);
} else {
$image = new Image($img_str, $mime);
if ($image->isValid() && !$direct_cache && ($cachefile == '')) {
Photo::store($image, 0, 0, $urlhash, $_REQUEST['url'], '', 100);
}
}
}
$img_str_orig = $img_str;
// reduce quality - if it isn't a GIF
if ($mime != 'image/gif') {
$image = new Image($img_str, $mime);
if ($image->isValid()) {
$image->scaleDown($size);
$img_str = $image->asString();
}
}
/*
* If there is a real existing directory then put the cache file there
* advantage: real file access is really fast
* Otherwise write in cachefile
*/
if ($valid && $direct_cache) {
file_put_contents($basepath . '/proxy/' . ProxyUtils::proxifyUrl($_REQUEST['url'], true), $img_str_orig);
if ($sizetype != '') {
file_put_contents($basepath . '/proxy/' . ProxyUtils::proxifyUrl($_REQUEST['url'], true) . $sizetype, $img_str);
}
} elseif ($cachefile != '') {
file_put_contents($cachefile, $img_str_orig);
}
header('Content-type: ' . $mime);
// Only output the cache headers when the file is valid
if ($valid) {
header('Last-Modified: ' . gmdate('D, d M Y H:i:s', time()) . ' GMT');
header('Etag: "' . md5($img_str) . '"');
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + (31536000)) . ' GMT');
header('Cache-Control: max-age=31536000');
}
echo $img_str;
exit();
}
}

+ 4
- 4
src/Object/Post.php View File

@ -16,6 +16,7 @@ use Friendica\Model\Contact;
use Friendica\Model\Item;
use Friendica\Model\Term;
use Friendica\Util\DateTimeFormat;
use Friendica\Util\Proxy as ProxyUtils;
use Friendica\Util\Temporal;