forked from GNUsocial/gnu-social
[Embed][StoreRemoteMedia][Media] Copy and cleanup plugins from v2
This commit is contained in:
parent
66ed6fb658
commit
efd2719481
5
config/preload.php
Normal file
5
config/preload.php
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
if (file_exists(dirname(__DIR__) . '/var/cache/prod/App_KernelProdContainer.preload.php')) {
|
||||||
|
require dirname(__DIR__) . '/var/cache/prod/App_KernelProdContainer.preload.php';
|
||||||
|
}
|
@ -18,6 +18,7 @@
|
|||||||
* OEmbed and OpenGraph implementation for GNU social
|
* OEmbed and OpenGraph implementation for GNU social
|
||||||
*
|
*
|
||||||
* @package GNUsocial
|
* @package GNUsocial
|
||||||
|
*
|
||||||
* @author Mikael Nordfeldth
|
* @author Mikael Nordfeldth
|
||||||
* @author Stephen Paul Weber
|
* @author Stephen Paul Weber
|
||||||
* @author hannes
|
* @author hannes
|
||||||
@ -29,9 +30,9 @@
|
|||||||
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
|
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
defined('GNUSOCIAL') || die();
|
namespace Plugin\Embed;
|
||||||
|
|
||||||
use Embed\Embed;
|
use App\Core\Module;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for the Embed plugin that does most of the heavy lifting to get
|
* Base class for the Embed plugin that does most of the heavy lifting to get
|
||||||
@ -40,7 +41,7 @@ use Embed\Embed;
|
|||||||
* @copyright 2014-2021 Free Software Foundation, Inc http://www.fsf.org
|
* @copyright 2014-2021 Free Software Foundation, Inc http://www.fsf.org
|
||||||
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
|
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
|
||||||
*/
|
*/
|
||||||
class EmbedPlugin extends Plugin
|
class Embed extends Module
|
||||||
{
|
{
|
||||||
const PLUGIN_VERSION = '2.1.0';
|
const PLUGIN_VERSION = '2.1.0';
|
||||||
|
|
||||||
@ -58,7 +59,7 @@ class EmbedPlugin extends Plugin
|
|||||||
public $thumbnail_width = 128;
|
public $thumbnail_width = 128;
|
||||||
public $thumbnail_height = 128;
|
public $thumbnail_height = 128;
|
||||||
public $crop = true;
|
public $crop = true;
|
||||||
public $max_size = null;
|
public $max_size;
|
||||||
|
|
||||||
protected $imgData = [];
|
protected $imgData = [];
|
||||||
|
|
||||||
@ -106,8 +107,10 @@ class EmbedPlugin extends Plugin
|
|||||||
* on this event to add our action handler for Embed.
|
* on this event to add our action handler for Embed.
|
||||||
*
|
*
|
||||||
* @param $m URLMapper the router that was initialized.
|
* @param $m URLMapper the router that was initialized.
|
||||||
* @return void true if successful, the exception object if it isn't.
|
*
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
|
*
|
||||||
|
* @return void true if successful, the exception object if it isn't.
|
||||||
*/
|
*/
|
||||||
public function onRouterInitialized(URLMapper $m)
|
public function onRouterInitialized(URLMapper $m)
|
||||||
{
|
{
|
||||||
@ -122,13 +125,14 @@ class EmbedPlugin extends Plugin
|
|||||||
* @param $url string the remote URL we're looking at
|
* @param $url string the remote URL we're looking at
|
||||||
* @param $dom DOMDocument the document we're getting metadata from
|
* @param $dom DOMDocument the document we're getting metadata from
|
||||||
* @param $metadata stdClass class representing the metadata
|
* @param $metadata stdClass class representing the metadata
|
||||||
|
*
|
||||||
* @return bool true if successful, the exception object if it isn't.
|
* @return bool true if successful, the exception object if it isn't.
|
||||||
*/
|
*/
|
||||||
public function onGetRemoteUrlMetadataFromDom(string $url, DOMDocument $dom, stdClass &$metadata)
|
public function onGetRemoteUrlMetadataFromDom(string $url, DOMDocument $dom, stdClass &$metadata)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
common_log(LOG_INFO, "Trying to find Embed data for $url with 'oscarotero/Embed'");
|
common_log(LOG_INFO, "Trying to find Embed data for {$url} with 'oscarotero/Embed'");
|
||||||
$info = Embed::create($url);
|
$info = self::create($url);
|
||||||
|
|
||||||
$metadata->version = '1.0'; // Yes.
|
$metadata->version = '1.0'; // Yes.
|
||||||
$metadata->provider_name = $info->authorName;
|
$metadata->provider_name = $info->authorName;
|
||||||
@ -142,15 +146,15 @@ class EmbedPlugin extends Plugin
|
|||||||
if (substr($info->image, 0, 4) === 'data') {
|
if (substr($info->image, 0, 4) === 'data') {
|
||||||
// Inline image
|
// Inline image
|
||||||
$imgData = base64_decode(substr($info->image, stripos($info->image, 'base64,') + 7));
|
$imgData = base64_decode(substr($info->image, stripos($info->image, 'base64,') + 7));
|
||||||
list($filename, , ) = $this->validateAndWriteImage($imgData);
|
list($filename) = $this->validateAndWriteImage($imgData);
|
||||||
// Use a file URI for images, as file_embed can't store a filename
|
// Use a file URI for images, as file_embed can't store a filename
|
||||||
$metadata->thumbnail_url = 'file://' . File_thumbnail::path($filename);
|
$metadata->thumbnail_url = 'file://' . File_thumbnail::path($filename);
|
||||||
} else {
|
} else {
|
||||||
$metadata->thumbnail_url = $info->image;
|
$metadata->thumbnail_url = $info->image;
|
||||||
}
|
}
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
common_log(LOG_INFO, "Failed to find Embed data for $url with 'oscarotero/Embed'" .
|
common_log(LOG_INFO, "Failed to find Embed data for {$url} with 'oscarotero/Embed'" .
|
||||||
", got exception: " . get_class($e));
|
', got exception: ' . get_class($e));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($metadata->thumbnail_url)) {
|
if (isset($metadata->thumbnail_url)) {
|
||||||
@ -166,7 +170,7 @@ class EmbedPlugin extends Plugin
|
|||||||
// some wordpress opengraph implementations sometimes return a white blank image
|
// some wordpress opengraph implementations sometimes return a white blank image
|
||||||
// no need for us to save that!
|
// no need for us to save that!
|
||||||
if ($metadata->thumbnail_url == 'https://s0.wp.com/i/blank.jpg') {
|
if ($metadata->thumbnail_url == 'https://s0.wp.com/i/blank.jpg') {
|
||||||
unset($metadata->thumbnail_url);
|
$metadata->thumbnail_url = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: this is also true of locally-installed wordpress so we should watch out for that.
|
// FIXME: this is also true of locally-installed wordpress so we should watch out for that.
|
||||||
@ -174,6 +178,7 @@ class EmbedPlugin extends Plugin
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Placeholder */
|
||||||
public function onEndShowHeadElements(Action $action)
|
public function onEndShowHeadElements(Action $action)
|
||||||
{
|
{
|
||||||
switch ($action->getActionName()) {
|
switch ($action->getActionName()) {
|
||||||
@ -200,9 +205,9 @@ class EmbedPlugin extends Plugin
|
|||||||
'link',
|
'link',
|
||||||
[
|
[
|
||||||
'rel' => 'alternate',
|
'rel' => 'alternate',
|
||||||
'type' => "application/$format+oembed",
|
'type' => "application/{$format}+oembed",
|
||||||
'href' => common_local_url('oembed', [], ['format' => $format, 'url' => $url]),
|
'href' => common_local_url('oembed', [], ['format' => $format, 'url' => $url]),
|
||||||
'title' => 'oEmbed'
|
'title' => 'oEmbed',
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -210,6 +215,7 @@ class EmbedPlugin extends Plugin
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Placeholder */
|
||||||
public function onEndShowStylesheets(Action $action)
|
public function onEndShowStylesheets(Action $action)
|
||||||
{
|
{
|
||||||
$action->cssLink($this->path('css/embed.css'));
|
$action->cssLink($this->path('css/embed.css'));
|
||||||
@ -223,7 +229,7 @@ class EmbedPlugin extends Plugin
|
|||||||
*
|
*
|
||||||
* @param File $file The newly inserted File object.
|
* @param File $file The newly inserted File object.
|
||||||
*
|
*
|
||||||
* @return boolean success
|
* @return bool success
|
||||||
*/
|
*/
|
||||||
public function onEndFileSaveNew(File $file)
|
public function onEndFileSaveNew(File $file)
|
||||||
{
|
{
|
||||||
@ -234,12 +240,11 @@ class EmbedPlugin extends Plugin
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isset($file->mimetype)
|
if (isset($file->mimetype)
|
||||||
&& (('text/html' === substr($file->mimetype, 0, 9) ||
|
&& (('text/html' === substr($file->mimetype, 0, 9) || 'application/xhtml+xml' === substr($file->mimetype, 0, 21)))) {
|
||||||
'application/xhtml+xml' === substr($file->mimetype, 0, 21)))) {
|
|
||||||
try {
|
try {
|
||||||
$embed_data = File_embed::getEmbed($file->url);
|
$embed_data = File_embed::getEmbed($file->url);
|
||||||
if ($embed_data === false) {
|
if ($embed_data === false) {
|
||||||
throw new Exception("Did not get Embed data from URL $file->url");
|
throw new Exception("Did not get Embed data from URL {$file->url}");
|
||||||
}
|
}
|
||||||
$file->setTitle($embed_data->title);
|
$file->setTitle($embed_data->title);
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
@ -256,6 +261,7 @@ class EmbedPlugin extends Plugin
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Placeholder */
|
||||||
public function onEndShowAttachmentLink(HTMLOutputter $out, File $file)
|
public function onEndShowAttachmentLink(HTMLOutputter $out, File $file)
|
||||||
{
|
{
|
||||||
$embed = File_embed::getKV('file_id', $file->getID());
|
$embed = File_embed::getKV('file_id', $file->getID());
|
||||||
@ -264,17 +270,17 @@ class EmbedPlugin extends Plugin
|
|||||||
}
|
}
|
||||||
$out->elementStart('div', ['id' => 'oembed_info', 'class' => 'e-content']);
|
$out->elementStart('div', ['id' => 'oembed_info', 'class' => 'e-content']);
|
||||||
foreach (['author_name' => ['class' => ' author', 'url' => 'author_url'],
|
foreach (['author_name' => ['class' => ' author', 'url' => 'author_url'],
|
||||||
'provider' => ['class' => '', 'url' => 'provider_url']]
|
'provider' => ['class' => '', 'url' => 'provider_url'], ]
|
||||||
as $field => $options) {
|
as $field => $options) {
|
||||||
if (!empty($embed->{$field})) {
|
if (!empty($embed->{$field})) {
|
||||||
$out->elementStart('div', "fn vcard" . $options['class']);
|
$out->elementStart('div', 'fn vcard' . $options['class']);
|
||||||
if (empty($embed->{$options['url']})) {
|
if (empty($embed->{$options['url']})) {
|
||||||
$out->text($embed->{$field});
|
$out->text($embed->{$field});
|
||||||
} else {
|
} else {
|
||||||
$out->element(
|
$out->element(
|
||||||
'a',
|
'a',
|
||||||
['href' => $embed->{$options['url']},
|
['href' => $embed->{$options['url']},
|
||||||
'class' => 'url'],
|
'class' => 'url', ],
|
||||||
$embed->{$field}
|
$embed->{$field}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -284,6 +290,7 @@ class EmbedPlugin extends Plugin
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Placeholder */
|
||||||
public function onFileEnclosureMetadata(File $file, &$enclosure)
|
public function onFileEnclosureMetadata(File $file, &$enclosure)
|
||||||
{
|
{
|
||||||
// Never treat generic HTML links as an enclosure type!
|
// Never treat generic HTML links as an enclosure type!
|
||||||
@ -301,6 +308,7 @@ class EmbedPlugin extends Plugin
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Placeholder */
|
||||||
public function onStartShowAttachmentRepresentation(HTMLOutputter $out, File $file)
|
public function onStartShowAttachmentRepresentation(HTMLOutputter $out, File $file)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
@ -367,6 +375,7 @@ class EmbedPlugin extends Plugin
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Placeholder */
|
||||||
public function onShowUnsupportedAttachmentRepresentation(HTMLOutputter $out, File $file)
|
public function onShowUnsupportedAttachmentRepresentation(HTMLOutputter $out, File $file)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
@ -400,12 +409,14 @@ class EmbedPlugin extends Plugin
|
|||||||
* @param $file File the file of the created thumbnail
|
* @param $file File the file of the created thumbnail
|
||||||
* @param &$imgPath null|string = the path to the created thumbnail (output)
|
* @param &$imgPath null|string = the path to the created thumbnail (output)
|
||||||
* @param $media string = media type
|
* @param $media string = media type
|
||||||
* @return bool true if it succeeds (including non-action
|
*
|
||||||
* states where it isn't oEmbed data, so it doesn't mess up the event handle
|
|
||||||
* for other things hooked into it), or the exception if it fails.
|
|
||||||
* @throws FileNotFoundException
|
* @throws FileNotFoundException
|
||||||
* @throws NoResultException
|
* @throws NoResultException
|
||||||
* @throws ServerException
|
* @throws ServerException
|
||||||
|
*
|
||||||
|
* @return bool true if it succeeds (including non-action
|
||||||
|
* states where it isn't oEmbed data, so it doesn't mess up the event handle
|
||||||
|
* for other things hooked into it), or the exception if it fails.
|
||||||
*/
|
*/
|
||||||
public function onCreateFileImageThumbnailSource(File $file, ?string &$imgPath, string $media): bool
|
public function onCreateFileImageThumbnailSource(File $file, ?string &$imgPath, string $media): bool
|
||||||
{
|
{
|
||||||
@ -459,8 +470,11 @@ class EmbedPlugin extends Plugin
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return bool false on no check made, provider name on success
|
* @param mixed $url
|
||||||
|
*
|
||||||
* @throws ServerException if check is made but fails
|
* @throws ServerException if check is made but fails
|
||||||
|
*
|
||||||
|
* @return bool false on no check made, provider name on success
|
||||||
*/
|
*/
|
||||||
protected function checkWhitelist($url)
|
protected function checkWhitelist($url)
|
||||||
{
|
{
|
||||||
@ -470,7 +484,7 @@ class EmbedPlugin extends Plugin
|
|||||||
|
|
||||||
$host = parse_url($url, PHP_URL_HOST);
|
$host = parse_url($url, PHP_URL_HOST);
|
||||||
foreach ($this->domain_whitelist as $regex => $provider) {
|
foreach ($this->domain_whitelist as $regex => $provider) {
|
||||||
if (preg_match("/$regex/", $host)) {
|
if (preg_match("/{$regex}/", $host)) {
|
||||||
return $provider; // we trust this source, return provider name
|
return $provider; // we trust this source, return provider name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -483,14 +497,17 @@ class EmbedPlugin extends Plugin
|
|||||||
* the content-length variable returned. This isn't 100% foolproof but is
|
* the content-length variable returned. This isn't 100% foolproof but is
|
||||||
* reliable enough for our purposes.
|
* reliable enough for our purposes.
|
||||||
*
|
*
|
||||||
* @return string|bool the file size if it succeeds, false otherwise.
|
* @param mixed $url
|
||||||
|
* @param null|mixed $headers
|
||||||
|
*
|
||||||
|
* @return bool|string the file size if it succeeds, false otherwise.
|
||||||
*/
|
*/
|
||||||
private function getRemoteFileSize($url, $headers = null)
|
private function getRemoteFileSize($url, $headers = null)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
if ($headers === null) {
|
if ($headers === null) {
|
||||||
if (!common_valid_http_url($url)) {
|
if (!common_valid_http_url($url)) {
|
||||||
common_log(LOG_ERR, "Invalid URL in Embed::getRemoteFileSize()");
|
common_log(LOG_ERR, 'Invalid URL in Embed::getRemoteFileSize()');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$head = (new HTTPClient())->head($url);
|
$head = (new HTTPClient())->head($url);
|
||||||
@ -509,13 +526,16 @@ class EmbedPlugin extends Plugin
|
|||||||
* A private helper function that uses a CURL lookup to check the mime type
|
* A private helper function that uses a CURL lookup to check the mime type
|
||||||
* of a remote URL to see it it's an image.
|
* of a remote URL to see it it's an image.
|
||||||
*
|
*
|
||||||
|
* @param mixed $url
|
||||||
|
* @param null|mixed $headers
|
||||||
|
*
|
||||||
* @return bool true if the remote URL is an image, or false otherwise.
|
* @return bool true if the remote URL is an image, or false otherwise.
|
||||||
*/
|
*/
|
||||||
private function isRemoteImage($url, $headers = null)
|
private function isRemoteImage($url, $headers = null)
|
||||||
{
|
{
|
||||||
if (empty($headers)) {
|
if (empty($headers)) {
|
||||||
if (!common_valid_http_url($url)) {
|
if (!common_valid_http_url($url)) {
|
||||||
common_log(LOG_ERR, "Invalid URL in Embed::isRemoteImage()");
|
common_log(LOG_ERR, 'Invalid URL in Embed::isRemoteImage()');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$head = (new HTTPClient())->head($url);
|
$head = (new HTTPClient())->head($url);
|
||||||
@ -531,9 +551,9 @@ class EmbedPlugin extends Plugin
|
|||||||
* by $this->thumbnail_height
|
* by $this->thumbnail_height
|
||||||
*
|
*
|
||||||
* @param $imgData - The image data to validate. Taken by reference to avoid copying
|
* @param $imgData - The image data to validate. Taken by reference to avoid copying
|
||||||
* @param string|null $url - The url where the image came from, to fetch metadata
|
* @param null|string $url - The url where the image came from, to fetch metadata
|
||||||
* @param array|null $headers - The headers possible previous request to $url
|
* @param null|array $headers - The headers possible previous request to $url
|
||||||
* @param int|null $file_id - The id of the file this image belongs to, used for logging
|
* @param null|int $file_id - The id of the file this image belongs to, used for logging
|
||||||
*/
|
*/
|
||||||
protected function validateAndWriteImage(&$imgData, ?string $url = null, ?array $headers = null, ?int $file_id = null): array
|
protected function validateAndWriteImage(&$imgData, ?string $url = null, ?array $headers = null, ?int $file_id = null): array
|
||||||
{
|
{
|
||||||
@ -556,8 +576,8 @@ class EmbedPlugin extends Plugin
|
|||||||
}
|
}
|
||||||
$filename = MediaFile::encodeFilename($original_name ?? _m('Untitled attachment'), $filehash);
|
$filename = MediaFile::encodeFilename($original_name ?? _m('Untitled attachment'), $filehash);
|
||||||
} catch (Exception $err) {
|
} catch (Exception $err) {
|
||||||
common_log(LOG_ERR, "Went to write a thumbnail to disk in StoreRemoteMediaPlugin::storeRemoteThumbnail " .
|
common_log(LOG_ERR, 'Went to write a thumbnail to disk in StoreRemoteMediaPlugin::storeRemoteThumbnail ' .
|
||||||
"but encountered error: $err");
|
"but encountered error: {$err}");
|
||||||
throw $err;
|
throw $err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -595,7 +615,7 @@ class EmbedPlugin extends Plugin
|
|||||||
$height = $box['height'];
|
$height = $box['height'];
|
||||||
$img->resizeTo($fullpath, $box);
|
$img->resizeTo($fullpath, $box);
|
||||||
} catch (\Intervention\Image\Exception\NotReadableException $e) {
|
} catch (\Intervention\Image\Exception\NotReadableException $e) {
|
||||||
common_log(LOG_ERR, "StoreRemoteMediaPlugin::storeRemoteThumbnail was unable to decode image with Intervention: $e");
|
common_log(LOG_ERR, "StoreRemoteMediaPlugin::storeRemoteThumbnail was unable to decode image with Intervention: {$e}");
|
||||||
// No need to interrupt processing
|
// No need to interrupt processing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -606,8 +626,8 @@ class EmbedPlugin extends Plugin
|
|||||||
} catch (AlreadyFulfilledException $e) {
|
} catch (AlreadyFulfilledException $e) {
|
||||||
// Carry on
|
// Carry on
|
||||||
} catch (Exception $err) {
|
} catch (Exception $err) {
|
||||||
common_log(LOG_ERR, "Went to write a thumbnail to disk in EmbedPlugin::storeRemoteThumbnail " .
|
common_log(LOG_ERR, 'Went to write a thumbnail to disk in EmbedPlugin::storeRemoteThumbnail ' .
|
||||||
"but encountered error: $err");
|
"but encountered error: {$err}");
|
||||||
throw $err;
|
throw $err;
|
||||||
} finally {
|
} finally {
|
||||||
unset($imgData);
|
unset($imgData);
|
||||||
@ -620,6 +640,7 @@ class EmbedPlugin extends Plugin
|
|||||||
* Function to create and store a thumbnail representation of a remote image
|
* Function to create and store a thumbnail representation of a remote image
|
||||||
*
|
*
|
||||||
* @param $thumbnail File_thumbnail object containing the file thumbnail
|
* @param $thumbnail File_thumbnail object containing the file thumbnail
|
||||||
|
*
|
||||||
* @return bool true if it succeeded, the exception if it fails, or false if it
|
* @return bool true if it succeeded, the exception if it fails, or false if it
|
||||||
* is limited by system limits (ie the file is too large.)
|
* is limited by system limits (ie the file is too large.)
|
||||||
*/
|
*/
|
||||||
@ -650,15 +671,15 @@ class EmbedPlugin extends Plugin
|
|||||||
if ($is_image == true) {
|
if ($is_image == true) {
|
||||||
$file_size = $this->getRemoteFileSize($url, $headers);
|
$file_size = $this->getRemoteFileSize($url, $headers);
|
||||||
if (($file_size != false) && ($file_size > $this->max_size)) {
|
if (($file_size != false) && ($file_size > $this->max_size)) {
|
||||||
common_debug("Went to store remote thumbnail of size " . $file_size .
|
common_debug('Went to store remote thumbnail of size ' . $file_size .
|
||||||
" but the upload limit is " . $this->max_size . " so we aborted.");
|
' but the upload limit is ' . $this->max_size . ' so we aborted.');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} catch (Exception $err) {
|
} catch (Exception $err) {
|
||||||
common_debug("Could not determine size of remote image, aborted local storage.");
|
common_debug('Could not determine size of remote image, aborted local storage.');
|
||||||
throw $err;
|
throw $err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -683,22 +704,22 @@ class EmbedPlugin extends Plugin
|
|||||||
}
|
}
|
||||||
} catch (UnsupportedMediaException $e) {
|
} catch (UnsupportedMediaException $e) {
|
||||||
// Couldn't find anything that looks like an image, nothing to do
|
// Couldn't find anything that looks like an image, nothing to do
|
||||||
common_debug("Embed was not able to find an image for URL `$url`: " . $e->getMessage());
|
common_debug("Embed was not able to find an image for URL `{$url}`: " . $e->getMessage());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Update our database for the thumbnail record
|
// Update our database for the thumbnail record
|
||||||
$orig = clone($thumbnail);
|
$orig = clone $thumbnail;
|
||||||
$thumbnail->filename = $filename;
|
$thumbnail->filename = $filename;
|
||||||
$thumbnail->width = $width;
|
$thumbnail->width = $width;
|
||||||
$thumbnail->height = $height;
|
$thumbnail->height = $height;
|
||||||
// Throws exception on failure.
|
// Throws exception on failure.
|
||||||
$thumbnail->updateWithKeys($orig);
|
$thumbnail->updateWithKeys($orig);
|
||||||
} catch (Exception $err) {
|
} catch (Exception $err) {
|
||||||
common_log(LOG_ERR, "Went to write a thumbnail entry to the database in " .
|
common_log(LOG_ERR, 'Went to write a thumbnail entry to the database in ' .
|
||||||
"EmbedPlugin::storeRemoteThumbnail but encountered error: ".$err);
|
'EmbedPlugin::storeRemoteThumbnail but encountered error: ' . $err);
|
||||||
throw $err;
|
throw $err;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -709,6 +730,7 @@ class EmbedPlugin extends Plugin
|
|||||||
* Adds this plugin's version information to $versions array
|
* Adds this plugin's version information to $versions array
|
||||||
*
|
*
|
||||||
* @param &$versions array inherited from parent
|
* @param &$versions array inherited from parent
|
||||||
|
*
|
||||||
* @return bool true hook value
|
* @return bool true hook value
|
||||||
*/
|
*/
|
||||||
public function onPluginVersion(array &$versions): bool
|
public function onPluginVersion(array &$versions): bool
|
||||||
@ -717,9 +739,8 @@ class EmbedPlugin extends Plugin
|
|||||||
'version' => self::PLUGIN_VERSION,
|
'version' => self::PLUGIN_VERSION,
|
||||||
'author' => 'Mikael Nordfeldth',
|
'author' => 'Mikael Nordfeldth',
|
||||||
'homepage' => GNUSOCIAL_ENGINE_URL,
|
'homepage' => GNUSOCIAL_ENGINE_URL,
|
||||||
'description' =>
|
'description' => // TRANS: Plugin description.
|
||||||
// TRANS: Plugin description.
|
_m('Plugin for using and representing oEmbed, OpenGraph and other data.'), ];
|
||||||
_m('Plugin for using and representing oEmbed, OpenGraph and other data.')];
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -18,6 +18,7 @@
|
|||||||
* OembedPlugin implementation for GNU social
|
* OembedPlugin implementation for GNU social
|
||||||
*
|
*
|
||||||
* @package GNUsocial
|
* @package GNUsocial
|
||||||
|
*
|
||||||
* @author Craig Andrews <candrews@integralblue.com>
|
* @author Craig Andrews <candrews@integralblue.com>
|
||||||
* @author Mikael Nordfeldth <mmn@hethane.se>
|
* @author Mikael Nordfeldth <mmn@hethane.se>
|
||||||
* @author hannes
|
* @author hannes
|
||||||
@ -26,7 +27,7 @@
|
|||||||
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
|
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
defined('GNUSOCIAL') || die();
|
namespace Plguin\Embed\actions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Oembed provider implementation
|
* Oembed provider implementation
|
||||||
@ -38,6 +39,7 @@ defined('GNUSOCIAL') || die();
|
|||||||
*/
|
*/
|
||||||
class OEmbedAction extends Action
|
class OEmbedAction extends Action
|
||||||
{
|
{
|
||||||
|
/** Placeholder */
|
||||||
protected function handle()
|
protected function handle()
|
||||||
{
|
{
|
||||||
parent::handle();
|
parent::handle();
|
||||||
@ -58,7 +60,7 @@ class OEmbedAction extends Action
|
|||||||
// $r->map will throw ClientException 404 if it fails to find a mapping
|
// $r->map will throw ClientException 404 if it fails to find a mapping
|
||||||
$proxy_args = $r->map($path);
|
$proxy_args = $r->map($path);
|
||||||
|
|
||||||
$oembed=array();
|
$oembed = [];
|
||||||
$oembed['version'] = '1.0';
|
$oembed['version'] = '1.0';
|
||||||
$oembed['provider_name'] = common_config('site', 'name');
|
$oembed['provider_name'] = common_config('site', 'name');
|
||||||
$oembed['provider_url'] = common_root_url();
|
$oembed['provider_url'] = common_root_url();
|
||||||
@ -100,9 +102,7 @@ class OEmbedAction extends Action
|
|||||||
$oembed['thumbnail_url'] = $attachment->getUrl();
|
$oembed['thumbnail_url'] = $attachment->getUrl();
|
||||||
break; // we're happy with that
|
break; // we're happy with that
|
||||||
} catch (ServerException $e) {
|
} catch (ServerException $e) {
|
||||||
//
|
|
||||||
} catch (ClientException $e) {
|
} catch (ClientException $e) {
|
||||||
//
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -159,7 +159,7 @@ class OEmbedAction extends Action
|
|||||||
$oembed['type'] = 'link';
|
$oembed['type'] = 'link';
|
||||||
$oembed['url'] = common_local_url(
|
$oembed['url'] = common_local_url(
|
||||||
'attachment',
|
'attachment',
|
||||||
array('attachment' => $attachment->id)
|
['attachment' => $attachment->id]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if ($attachment->title) {
|
if ($attachment->title) {
|
||||||
@ -176,13 +176,13 @@ class OEmbedAction extends Action
|
|||||||
case 'xml':
|
case 'xml':
|
||||||
$this->init_document('xml');
|
$this->init_document('xml');
|
||||||
$this->elementStart('oembed');
|
$this->elementStart('oembed');
|
||||||
foreach (array(
|
foreach ([
|
||||||
'version', 'type', 'provider_name',
|
'version', 'type', 'provider_name',
|
||||||
'provider_url', 'title', 'author_name',
|
'provider_url', 'title', 'author_name',
|
||||||
'author_url', 'url', 'html', 'width',
|
'author_url', 'url', 'html', 'width',
|
||||||
'height', 'cache_age', 'thumbnail_url',
|
'height', 'cache_age', 'thumbnail_url',
|
||||||
'thumbnail_width', 'thumbnail_height',
|
'thumbnail_width', 'thumbnail_height',
|
||||||
) as $key) {
|
] as $key) {
|
||||||
if (isset($oembed[$key]) && $oembed[$key] != '') {
|
if (isset($oembed[$key]) && $oembed[$key] != '') {
|
||||||
$this->element($key, null, $oembed[$key]);
|
$this->element($key, null, $oembed[$key]);
|
||||||
}
|
}
|
||||||
@ -203,6 +203,7 @@ class OEmbedAction extends Action
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Placeholder */
|
||||||
public function init_document($type)
|
public function init_document($type)
|
||||||
{
|
{
|
||||||
switch ($type) {
|
switch ($type) {
|
||||||
@ -216,7 +217,7 @@ class OEmbedAction extends Action
|
|||||||
// Check for JSONP callback
|
// Check for JSONP callback
|
||||||
$callback = $this->arg('callback');
|
$callback = $this->arg('callback');
|
||||||
if ($callback) {
|
if ($callback) {
|
||||||
print $callback . '(';
|
echo $callback . '(';
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -226,6 +227,7 @@ class OEmbedAction extends Action
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Placeholder */
|
||||||
public function end_document($type)
|
public function end_document($type)
|
||||||
{
|
{
|
||||||
switch ($type) {
|
switch ($type) {
|
||||||
@ -236,7 +238,7 @@ class OEmbedAction extends Action
|
|||||||
// Check for JSONP callback
|
// Check for JSONP callback
|
||||||
$callback = $this->arg('callback');
|
$callback = $this->arg('callback');
|
||||||
if ($callback) {
|
if ($callback) {
|
||||||
print ')';
|
echo ')';
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -244,7 +246,6 @@ class OEmbedAction extends Action
|
|||||||
$this->serverError(_('Not a supported data format.'), 501);
|
$this->serverError(_('Not a supported data format.'), 501);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -252,7 +253,7 @@ class OEmbedAction extends Action
|
|||||||
*
|
*
|
||||||
* @param array $args other arguments
|
* @param array $args other arguments
|
||||||
*
|
*
|
||||||
* @return boolean is read only action?
|
* @return bool is read only action?
|
||||||
*/
|
*/
|
||||||
public function isReadOnly($args)
|
public function isReadOnly($args)
|
||||||
{
|
{
|
@ -21,11 +21,12 @@ namespace Plugin\Media\Controller;
|
|||||||
*
|
*
|
||||||
* @category Personal
|
* @category Personal
|
||||||
* @package GNUsocial
|
* @package GNUsocial
|
||||||
|
*
|
||||||
* @author Evan Prodromou <evan@status.net>
|
* @author Evan Prodromou <evan@status.net>
|
||||||
* @copyright 2008-2009 StatusNet, Inc.
|
* @copyright 2008-2009 StatusNet, Inc.
|
||||||
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
|
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
|
||||||
*/
|
*/
|
||||||
class Attachment_thumbnailAction extends Attachment_viewAction
|
class AttachmentThumbnail extends AttachmentView
|
||||||
{
|
{
|
||||||
protected $thumb_w; // max width
|
protected $thumb_w; // max width
|
||||||
protected $thumb_h; // max height
|
protected $thumb_h; // max height
|
||||||
|
@ -26,6 +26,7 @@ namespace Plugin\Media\Controller;
|
|||||||
*/
|
*/
|
||||||
class AttachmentView extends Attachment
|
class AttachmentView extends Attachment
|
||||||
{
|
{
|
||||||
|
/** Placeholder */
|
||||||
public function showPage(): void
|
public function showPage(): void
|
||||||
{
|
{
|
||||||
// Disable errors, to not mess with the file contents (suppress errors in case access to this
|
// Disable errors, to not mess with the file contents (suppress errors in case access to this
|
||||||
|
@ -147,7 +147,7 @@ class ImageFile extends MediaFile
|
|||||||
* Shortcut method to get an ImageFile from a File
|
* Shortcut method to get an ImageFile from a File
|
||||||
*
|
*
|
||||||
* @param File $file
|
* @param File $file
|
||||||
* @return ImageFile
|
*
|
||||||
* @throws ClientException
|
* @throws ClientException
|
||||||
* @throws FileNotFoundException
|
* @throws FileNotFoundException
|
||||||
* @throws NoResultException
|
* @throws NoResultException
|
||||||
@ -156,6 +156,7 @@ class ImageFile extends MediaFile
|
|||||||
* @throws UseFileAsThumbnailException
|
* @throws UseFileAsThumbnailException
|
||||||
*
|
*
|
||||||
* @return ImageFile
|
* @return ImageFile
|
||||||
|
* @return ImageFile
|
||||||
*/
|
*/
|
||||||
public static function fromFileObject(File $file)
|
public static function fromFileObject(File $file)
|
||||||
{
|
{
|
||||||
@ -181,6 +182,7 @@ class ImageFile extends MediaFile
|
|||||||
|
|
||||||
return new self($file->getID(), $filepath, $file->filehash);
|
return new self($file->getID(), $filepath, $file->filehash);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function getPath()
|
public function getPath()
|
||||||
{
|
{
|
||||||
@ -233,10 +235,10 @@ class ImageFile extends MediaFile
|
|||||||
* and ensures the uploaded file is in fact an image.
|
* and ensures the uploaded file is in fact an image.
|
||||||
*
|
*
|
||||||
* @param string $url Remote image URL
|
* @param string $url Remote image URL
|
||||||
* @param Profile|null $scoped
|
* @param null|Profile $scoped
|
||||||
* @param string|null $name
|
* @param null|string $name
|
||||||
* @param int|null $file_id same as in this class constructor
|
* @param null|int $file_id same as in this class constructor
|
||||||
* @return ImageFile
|
*
|
||||||
* @throws ClientException
|
* @throws ClientException
|
||||||
* @throws HTTP_Request2_Exception
|
* @throws HTTP_Request2_Exception
|
||||||
* @throws InvalidFilenameException
|
* @throws InvalidFilenameException
|
||||||
@ -246,6 +248,7 @@ class ImageFile extends MediaFile
|
|||||||
* @throws UseFileAsThumbnailException
|
* @throws UseFileAsThumbnailException
|
||||||
*
|
*
|
||||||
* @return ImageFile
|
* @return ImageFile
|
||||||
|
* @return ImageFile
|
||||||
*/
|
*/
|
||||||
public static function fromUrl(string $url, ?Profile $scoped = null, ?string $name = null, ?int $file_id = null): self
|
public static function fromUrl(string $url, ?Profile $scoped = null, ?string $name = null, ?int $file_id = null): self
|
||||||
{
|
{
|
||||||
@ -527,7 +530,7 @@ class ImageFile extends MediaFile
|
|||||||
return [(int) $rw, (int) $rh,
|
return [(int) $rw, (int) $rh,
|
||||||
(int) $cx, (int) $cy,
|
(int) $cx, (int) $cy,
|
||||||
is_null($cw) ? $width : (int) $cw,
|
is_null($cw) ? $width : (int) $cw,
|
||||||
is_null($ch) ? $height : (int)$ch];
|
is_null($ch) ? $height : (int) $ch, ];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -570,7 +573,7 @@ class ImageFile extends MediaFile
|
|||||||
* @param $height
|
* @param $height
|
||||||
* @param $crop
|
* @param $crop
|
||||||
* @param false $upscale
|
* @param false $upscale
|
||||||
* @return File_thumbnail
|
*
|
||||||
* @throws ClientException
|
* @throws ClientException
|
||||||
* @throws FileNotFoundException
|
* @throws FileNotFoundException
|
||||||
* @throws FileNotStoredLocallyException
|
* @throws FileNotStoredLocallyException
|
||||||
@ -578,6 +581,8 @@ class ImageFile extends MediaFile
|
|||||||
* @throws ServerException
|
* @throws ServerException
|
||||||
* @throws UnsupportedMediaException
|
* @throws UnsupportedMediaException
|
||||||
* @throws UseFileAsThumbnailException
|
* @throws UseFileAsThumbnailException
|
||||||
|
*
|
||||||
|
* @return File_thumbnail
|
||||||
*/
|
*/
|
||||||
public function getFileThumbnail($width = null, $height = null, $crop = null, $upscale = false)
|
public function getFileThumbnail($width = null, $height = null, $crop = null, $upscale = false)
|
||||||
{
|
{
|
||||||
|
@ -95,18 +95,21 @@ class MediaFile
|
|||||||
* Shortcut method to get a MediaFile from a File
|
* Shortcut method to get a MediaFile from a File
|
||||||
*
|
*
|
||||||
* @param File $file
|
* @param File $file
|
||||||
* @return MediaFile|ImageFile
|
*
|
||||||
* @throws ClientException
|
* @throws ClientException
|
||||||
* @throws FileNotFoundException
|
* @throws FileNotFoundException
|
||||||
* @throws NoResultException
|
* @throws NoResultException
|
||||||
* @throws ServerException
|
* @throws ServerException
|
||||||
|
*
|
||||||
|
* @return ImageFile|MediaFile
|
||||||
*/
|
*/
|
||||||
public static function fromFileObject(File $file)
|
public static function fromFileObject(File $file)
|
||||||
{
|
{
|
||||||
$filepath = null;
|
$filepath = null;
|
||||||
try {
|
try {
|
||||||
$filepath = $file->getPath();
|
$filepath = $file->getPath();
|
||||||
} catch (Exception $e) {}
|
} catch (Exception $e) {
|
||||||
|
}
|
||||||
return new self($filepath, common_get_mime_media($file->mimetype), $file->filehash, $file->getID());
|
return new self($filepath, common_get_mime_media($file->mimetype), $file->filehash, $file->getID());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,7 +124,8 @@ class MediaFile
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param bool|null $use_local true means require local, null means prefer original, false means use whatever is stored
|
* @param null|bool $use_local true means require local, null means prefer original, false means use whatever is stored
|
||||||
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getUrl(?bool $use_local = null): ?string
|
public function getUrl(?bool $use_local = null): ?string
|
||||||
@ -155,6 +159,9 @@ class MediaFile
|
|||||||
@unlink($this->filepath);
|
@unlink($this->filepath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the file from filesystem
|
||||||
|
*/
|
||||||
public function unlink()
|
public function unlink()
|
||||||
{
|
{
|
||||||
$this->filename = null;
|
$this->filename = null;
|
||||||
@ -249,7 +256,7 @@ class MediaFile
|
|||||||
// Set file geometrical properties if available
|
// Set file geometrical properties if available
|
||||||
try {
|
try {
|
||||||
$image = ImageFile::fromFileObject($file);
|
$image = ImageFile::fromFileObject($file);
|
||||||
$orig = clone($file);
|
$orig = clone $file;
|
||||||
$file->width = $image->width;
|
$file->width = $image->width;
|
||||||
$file->height = $image->height;
|
$file->height = $image->height;
|
||||||
$file->update($orig);
|
$file->update($orig);
|
||||||
@ -457,7 +464,7 @@ class MediaFile
|
|||||||
try {
|
try {
|
||||||
return ImageFile::fromFileObject($file);
|
return ImageFile::fromFileObject($file);
|
||||||
} catch (UnsupportedMediaException $e) {
|
} catch (UnsupportedMediaException $e) {
|
||||||
return MediaFile::fromFileObject($file);
|
return self::fromFileObject($file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Assert: If we got to this line, then we only traversed URLs on the while loop above.
|
// Assert: If we got to this line, then we only traversed URLs on the while loop above.
|
||||||
@ -528,10 +535,10 @@ class MediaFile
|
|||||||
* The filename has the following format: bin2hex("{$original_name}.{$ext}")."-{$filehash}"
|
* The filename has the following format: bin2hex("{$original_name}.{$ext}")."-{$filehash}"
|
||||||
*
|
*
|
||||||
* @param string $url Remote media URL
|
* @param string $url Remote media URL
|
||||||
* @param Profile|null $scoped
|
* @param null|Profile $scoped
|
||||||
* @param string|null $name
|
* @param null|string $name
|
||||||
* @param int|null $file_id same as in this class constructor
|
* @param null|int $file_id same as in this class constructor
|
||||||
* @return ImageFile|MediaFile
|
*
|
||||||
* @throws ClientException
|
* @throws ClientException
|
||||||
* @throws HTTP_Request2_Exception
|
* @throws HTTP_Request2_Exception
|
||||||
* @throws InvalidFilenameException
|
* @throws InvalidFilenameException
|
||||||
@ -541,6 +548,7 @@ class MediaFile
|
|||||||
* @throws UseFileAsThumbnailException
|
* @throws UseFileAsThumbnailException
|
||||||
*
|
*
|
||||||
* @return ImageFile|MediaFile
|
* @return ImageFile|MediaFile
|
||||||
|
* @return ImageFile|MediaFile
|
||||||
*/
|
*/
|
||||||
public static function fromUrl(string $url, ?Profile $scoped = null, ?string $name = null, ?int $file_id = null)
|
public static function fromUrl(string $url, ?Profile $scoped = null, ?string $name = null, ?int $file_id = null)
|
||||||
{
|
{
|
||||||
@ -588,8 +596,7 @@ class MediaFile
|
|||||||
} else {
|
} else {
|
||||||
throw new ServerException(sprintf('Invalid remote media URL headers %s.', $url));
|
throw new ServerException(sprintf('Invalid remote media URL headers %s.', $url));
|
||||||
}
|
}
|
||||||
unset($head);
|
unset($head, $headers);
|
||||||
unset($headers);
|
|
||||||
|
|
||||||
$tempfile = new TemporaryFile('gs-mediafile');
|
$tempfile = new TemporaryFile('gs-mediafile');
|
||||||
fwrite($tempfile->getResource(), HTTPClient::quickGet($url));
|
fwrite($tempfile->getResource(), HTTPClient::quickGet($url));
|
||||||
|
@ -14,10 +14,15 @@
|
|||||||
// You should have received a copy of the GNU Affero General Public License
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
|
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
namespace Plugin\StoreRemoteMedia;
|
||||||
|
|
||||||
|
use App\Core\Module;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The StoreRemoteMedia plugin downloads remotely attached files to local server.
|
* The StoreRemoteMedia plugin downloads remotely attached files to local server.
|
||||||
*
|
*
|
||||||
* @package GNUsocial
|
* @package GNUsocial
|
||||||
|
*
|
||||||
* @author Mikael Nordfeldth
|
* @author Mikael Nordfeldth
|
||||||
* @author Stephen Paul Weber
|
* @author Stephen Paul Weber
|
||||||
* @author Mikael Nordfeldth
|
* @author Mikael Nordfeldth
|
||||||
@ -26,7 +31,7 @@
|
|||||||
* @copyright 2015-2016, 2019-2021 Free Software Foundation, Inc http://www.fsf.org
|
* @copyright 2015-2016, 2019-2021 Free Software Foundation, Inc http://www.fsf.org
|
||||||
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
|
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
|
||||||
*/
|
*/
|
||||||
class StoreRemoteMediaPlugin extends Plugin
|
class StoreRemoteMedia extends Module
|
||||||
{
|
{
|
||||||
const PLUGIN_VERSION = '3.0.0';
|
const PLUGIN_VERSION = '3.0.0';
|
||||||
|
|
||||||
@ -42,10 +47,10 @@ class StoreRemoteMediaPlugin extends Plugin
|
|||||||
public $check_whitelist = false; // security/abuse precaution
|
public $check_whitelist = false; // security/abuse precaution
|
||||||
|
|
||||||
public $store_original = false; // Whether to maintain a copy of the original media or only a thumbnail of it
|
public $store_original = false; // Whether to maintain a copy of the original media or only a thumbnail of it
|
||||||
public $thumbnail_width = null;
|
public $thumbnail_width;
|
||||||
public $thumbnail_height = null;
|
public $thumbnail_height;
|
||||||
public $crop = null;
|
public $crop;
|
||||||
public $max_size = null;
|
public $max_size;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the StoreRemoteMedia plugin and set up the environment it needs for it.
|
* Initialize the StoreRemoteMedia plugin and set up the environment it needs for it.
|
||||||
@ -72,12 +77,14 @@ class StoreRemoteMediaPlugin extends Plugin
|
|||||||
* @param $file File the file of the created thumbnail
|
* @param $file File the file of the created thumbnail
|
||||||
* @param &$imgPath null|string = out the path to the created thumbnail (output parameter)
|
* @param &$imgPath null|string = out the path to the created thumbnail (output parameter)
|
||||||
* @param $media string = media type (unused)
|
* @param $media string = media type (unused)
|
||||||
* @return bool
|
*
|
||||||
* @throws AlreadyFulfilledException
|
* @throws AlreadyFulfilledException
|
||||||
* @throws FileNotFoundException
|
* @throws FileNotFoundException
|
||||||
* @throws FileNotStoredLocallyException
|
* @throws FileNotStoredLocallyException
|
||||||
* @throws HTTP_Request2_Exception
|
* @throws HTTP_Request2_Exception
|
||||||
* @throws ServerException
|
* @throws ServerException
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function onCreateFileImageThumbnailSource(File $file, ?string &$imgPath = null, ?string $media = null): bool
|
public function onCreateFileImageThumbnailSource(File $file, ?string &$imgPath = null, ?string $media = null): bool
|
||||||
{
|
{
|
||||||
@ -121,15 +128,15 @@ class StoreRemoteMediaPlugin extends Plugin
|
|||||||
if ($is_image == true) {
|
if ($is_image == true) {
|
||||||
$file_size = $this->getRemoteFileSize($url, $headers);
|
$file_size = $this->getRemoteFileSize($url, $headers);
|
||||||
if (($file_size != false) && ($file_size > $this->max_size)) {
|
if (($file_size != false) && ($file_size > $this->max_size)) {
|
||||||
common_debug("Went to store remote thumbnail of size " . $file_size .
|
common_debug('Went to store remote thumbnail of size ' . $file_size .
|
||||||
" but the upload limit is " . $this->max_size . " so we aborted.");
|
' but the upload limit is ' . $this->max_size . ' so we aborted.');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} catch (Exception $err) {
|
} catch (Exception $err) {
|
||||||
common_debug("Could not determine size of remote image, aborted local storage.");
|
common_debug('Could not determine size of remote image, aborted local storage.');
|
||||||
throw $err;
|
throw $err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,7 +161,7 @@ class StoreRemoteMediaPlugin extends Plugin
|
|||||||
}
|
}
|
||||||
} catch (UnsupportedMediaException $e) {
|
} catch (UnsupportedMediaException $e) {
|
||||||
// Couldn't find anything that looks like an image, nothing to do
|
// Couldn't find anything that looks like an image, nothing to do
|
||||||
common_debug("StoreRemoteMedia was not able to find an image for URL `$url`: " . $e->getMessage());
|
common_debug("StoreRemoteMedia was not able to find an image for URL `{$url}`: " . $e->getMessage());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -163,7 +170,7 @@ class StoreRemoteMediaPlugin extends Plugin
|
|||||||
if ($this->store_original) {
|
if ($this->store_original) {
|
||||||
try {
|
try {
|
||||||
// Update our database for the file record
|
// Update our database for the file record
|
||||||
$orig = clone($file);
|
$orig = clone $file;
|
||||||
$file->filename = $filename;
|
$file->filename = $filename;
|
||||||
$file->filehash = $filehash;
|
$file->filehash = $filehash;
|
||||||
$file->width = $width;
|
$file->width = $width;
|
||||||
@ -171,8 +178,8 @@ class StoreRemoteMediaPlugin extends Plugin
|
|||||||
// Throws exception on failure.
|
// Throws exception on failure.
|
||||||
$file->updateWithKeys($orig);
|
$file->updateWithKeys($orig);
|
||||||
} catch (Exception $err) {
|
} catch (Exception $err) {
|
||||||
common_log(LOG_ERR, "Went to update a file entry on the database in " .
|
common_log(LOG_ERR, 'Went to update a file entry on the database in ' .
|
||||||
"StoreRemoteMediaPlugin::storeRemoteThumbnail but encountered error: " . $err);
|
'StoreRemoteMediaPlugin::storeRemoteThumbnail but encountered error: ' . $err);
|
||||||
throw $err;
|
throw $err;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -184,12 +191,12 @@ class StoreRemoteMediaPlugin extends Plugin
|
|||||||
$data->thumbnail_height = $height;
|
$data->thumbnail_height = $height;
|
||||||
File_thumbnail::saveNew($data, $file->getID());
|
File_thumbnail::saveNew($data, $file->getID());
|
||||||
$ft = File_thumbnail::byFile($file);
|
$ft = File_thumbnail::byFile($file);
|
||||||
$orig = clone($ft);
|
$orig = clone $ft;
|
||||||
$ft->filename = $filename;
|
$ft->filename = $filename;
|
||||||
$ft->updateWithKeys($orig);
|
$ft->updateWithKeys($orig);
|
||||||
} catch (Exception $err) {
|
} catch (Exception $err) {
|
||||||
common_log(LOG_ERR, "Went to write a thumbnail entry to the database in " .
|
common_log(LOG_ERR, 'Went to write a thumbnail entry to the database in ' .
|
||||||
"StoreRemoteMediaPlugin::storeRemoteThumbnail but encountered error: " . $err);
|
'StoreRemoteMediaPlugin::storeRemoteThumbnail but encountered error: ' . $err);
|
||||||
throw $err;
|
throw $err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -208,14 +215,17 @@ class StoreRemoteMediaPlugin extends Plugin
|
|||||||
* the content-length variable returned. This isn't 100% foolproof but is
|
* the content-length variable returned. This isn't 100% foolproof but is
|
||||||
* reliable enough for our purposes.
|
* reliable enough for our purposes.
|
||||||
*
|
*
|
||||||
* @return string|bool the file size if it succeeds, false otherwise.
|
* @param mixed $url
|
||||||
|
* @param null|mixed $headers
|
||||||
|
*
|
||||||
|
* @return bool|string the file size if it succeeds, false otherwise.
|
||||||
*/
|
*/
|
||||||
private function getRemoteFileSize($url, $headers = null)
|
private function getRemoteFileSize($url, $headers = null)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
if ($headers === null) {
|
if ($headers === null) {
|
||||||
if (!common_valid_http_url($url)) {
|
if (!common_valid_http_url($url)) {
|
||||||
common_log(LOG_ERR, "Invalid URL in StoreRemoteMedia::getRemoteFileSize()");
|
common_log(LOG_ERR, 'Invalid URL in StoreRemoteMedia::getRemoteFileSize()');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$head = (new HTTPClient())->head($url);
|
$head = (new HTTPClient())->head($url);
|
||||||
@ -234,13 +244,16 @@ class StoreRemoteMediaPlugin extends Plugin
|
|||||||
* A private helper function that uses a CURL lookup to check the mime type
|
* A private helper function that uses a CURL lookup to check the mime type
|
||||||
* of a remote URL to see it it's an image.
|
* of a remote URL to see it it's an image.
|
||||||
*
|
*
|
||||||
|
* @param mixed $url
|
||||||
|
* @param null|mixed $headers
|
||||||
|
*
|
||||||
* @return bool true if the remote URL is an image, or false otherwise.
|
* @return bool true if the remote URL is an image, or false otherwise.
|
||||||
*/
|
*/
|
||||||
private function isRemoteImage($url, $headers = null): bool
|
private function isRemoteImage($url, $headers = null): bool
|
||||||
{
|
{
|
||||||
if (empty($headers)) {
|
if (empty($headers)) {
|
||||||
if (!common_valid_http_url($url)) {
|
if (!common_valid_http_url($url)) {
|
||||||
common_log(LOG_ERR, "Invalid URL in StoreRemoteMedia::isRemoteImage()");
|
common_log(LOG_ERR, 'Invalid URL in StoreRemoteMedia::isRemoteImage()');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$head = (new HTTPClient())->head($url);
|
$head = (new HTTPClient())->head($url);
|
||||||
@ -256,9 +269,9 @@ class StoreRemoteMediaPlugin extends Plugin
|
|||||||
* by $this->thumbnail_height
|
* by $this->thumbnail_height
|
||||||
*
|
*
|
||||||
* @param $imgData - The image data to validate. Taken by reference to avoid copying
|
* @param $imgData - The image data to validate. Taken by reference to avoid copying
|
||||||
* @param string|null $url - The url where the image came from, to fetch metadata
|
* @param null|string $url - The url where the image came from, to fetch metadata
|
||||||
* @param array|null $headers - The headers possible previous request to $url
|
* @param null|array $headers - The headers possible previous request to $url
|
||||||
* @param int|null $file_id - The id of the file this image belongs to, used for logging
|
* @param null|int $file_id - The id of the file this image belongs to, used for logging
|
||||||
*/
|
*/
|
||||||
protected function validateAndWriteImage(&$imgData, ?string $url = null, ?array $headers = null, ?int $file_id = null): array
|
protected function validateAndWriteImage(&$imgData, ?string $url = null, ?array $headers = null, ?int $file_id = null): array
|
||||||
{
|
{
|
||||||
@ -281,8 +294,8 @@ class StoreRemoteMediaPlugin extends Plugin
|
|||||||
}
|
}
|
||||||
$filename = MediaFile::encodeFilename($original_name ?? _m('Untitled attachment'), $filehash);
|
$filename = MediaFile::encodeFilename($original_name ?? _m('Untitled attachment'), $filehash);
|
||||||
} catch (Exception $err) {
|
} catch (Exception $err) {
|
||||||
common_log(LOG_ERR, "Went to write a thumbnail to disk in StoreRemoteMediaPlugin::storeRemoteThumbnail " .
|
common_log(LOG_ERR, 'Went to write a thumbnail to disk in StoreRemoteMediaPlugin::storeRemoteThumbnail ' .
|
||||||
"but encountered error: $err");
|
"but encountered error: {$err}");
|
||||||
throw $err;
|
throw $err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -320,7 +333,7 @@ class StoreRemoteMediaPlugin extends Plugin
|
|||||||
$height = $box['height'];
|
$height = $box['height'];
|
||||||
$img->resizeTo($fullpath, $box);
|
$img->resizeTo($fullpath, $box);
|
||||||
} catch (\Intervention\Image\Exception\NotReadableException $e) {
|
} catch (\Intervention\Image\Exception\NotReadableException $e) {
|
||||||
common_log(LOG_ERR, "StoreRemoteMediaPlugin::storeRemoteThumbnail was unable to decode image with Intervention: $e");
|
common_log(LOG_ERR, "StoreRemoteMediaPlugin::storeRemoteThumbnail was unable to decode image with Intervention: {$e}");
|
||||||
// No need to interrupt processing
|
// No need to interrupt processing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -331,8 +344,8 @@ class StoreRemoteMediaPlugin extends Plugin
|
|||||||
} catch (AlreadyFulfilledException $e) {
|
} catch (AlreadyFulfilledException $e) {
|
||||||
// Carry on
|
// Carry on
|
||||||
} catch (Exception $err) {
|
} catch (Exception $err) {
|
||||||
common_log(LOG_ERR, "Went to write a thumbnail to disk in StoreRemoteMediaPlugin::storeRemoteThumbnail " .
|
common_log(LOG_ERR, 'Went to write a thumbnail to disk in StoreRemoteMediaPlugin::storeRemoteThumbnail ' .
|
||||||
"but encountered error: $err");
|
"but encountered error: {$err}");
|
||||||
throw $err;
|
throw $err;
|
||||||
} finally {
|
} finally {
|
||||||
unset($imgData);
|
unset($imgData);
|
||||||
@ -342,8 +355,11 @@ class StoreRemoteMediaPlugin extends Plugin
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return bool false on no check made, provider name on success
|
* @param mixed $url
|
||||||
|
*
|
||||||
* @throws ServerException if check is made but fails
|
* @throws ServerException if check is made but fails
|
||||||
|
*
|
||||||
|
* @return bool false on no check made, provider name on success
|
||||||
*/
|
*/
|
||||||
protected function checkWhitelist($url)
|
protected function checkWhitelist($url)
|
||||||
{
|
{
|
||||||
@ -353,7 +369,7 @@ class StoreRemoteMediaPlugin extends Plugin
|
|||||||
|
|
||||||
$host = parse_url($url, PHP_URL_HOST);
|
$host = parse_url($url, PHP_URL_HOST);
|
||||||
foreach ($this->domain_whitelist as $regex => $provider) {
|
foreach ($this->domain_whitelist as $regex => $provider) {
|
||||||
if (preg_match("/$regex/", $host)) {
|
if (preg_match("/{$regex}/", $host)) {
|
||||||
return $provider; // we trust this source, return provider name
|
return $provider; // we trust this source, return provider name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -366,6 +382,7 @@ class StoreRemoteMediaPlugin extends Plugin
|
|||||||
* Adds this plugin's version information to $versions array
|
* Adds this plugin's version information to $versions array
|
||||||
*
|
*
|
||||||
* @param &$versions array inherited from parent
|
* @param &$versions array inherited from parent
|
||||||
|
*
|
||||||
* @return bool true hook value
|
* @return bool true hook value
|
||||||
*/
|
*/
|
||||||
public function onPluginVersion(array &$versions): bool
|
public function onPluginVersion(array &$versions): bool
|
||||||
@ -374,9 +391,8 @@ class StoreRemoteMediaPlugin extends Plugin
|
|||||||
'version' => self::PLUGIN_VERSION,
|
'version' => self::PLUGIN_VERSION,
|
||||||
'author' => 'Mikael Nordfeldth, Diogo Peralta Cordeiro',
|
'author' => 'Mikael Nordfeldth, Diogo Peralta Cordeiro',
|
||||||
'homepage' => GNUSOCIAL_ENGINE_URL,
|
'homepage' => GNUSOCIAL_ENGINE_URL,
|
||||||
'description' =>
|
'description' => // TRANS: Plugin description.
|
||||||
// TRANS: Plugin description.
|
_m('Plugin for downloading remotely attached files to local server.'), ];
|
||||||
_m('Plugin for downloading remotely attached files to local server.')];
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
627
symfony.lock
627
symfony.lock
@ -1,19 +1,189 @@
|
|||||||
{
|
{
|
||||||
|
"alchemy/resource-component": {
|
||||||
|
"version": "0.1.1"
|
||||||
|
},
|
||||||
|
"alchemy/zippy": {
|
||||||
|
"version": "v0.5.x-dev"
|
||||||
|
},
|
||||||
|
"beberlei/assert": {
|
||||||
|
"version": "v2.9.9"
|
||||||
|
},
|
||||||
|
"composer/semver": {
|
||||||
|
"version": "3.2.4"
|
||||||
|
},
|
||||||
|
"composer/xdebug-handler": {
|
||||||
|
"version": "1.4.6"
|
||||||
|
},
|
||||||
|
"doctrine/annotations": {
|
||||||
|
"version": "1.0",
|
||||||
|
"recipe": {
|
||||||
|
"repo": "github.com/symfony/recipes",
|
||||||
|
"branch": "master",
|
||||||
|
"version": "1.0",
|
||||||
|
"ref": "a2759dd6123694c8d901d0ec80006e044c2e6457"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"config/routes/annotations.yaml"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"doctrine/cache": {
|
||||||
|
"version": "1.10.2"
|
||||||
|
},
|
||||||
|
"doctrine/collections": {
|
||||||
|
"version": "1.6.7"
|
||||||
|
},
|
||||||
|
"doctrine/common": {
|
||||||
|
"version": "3.1.2"
|
||||||
|
},
|
||||||
|
"doctrine/dbal": {
|
||||||
|
"version": "2.13.0"
|
||||||
|
},
|
||||||
"doctrine/deprecations": {
|
"doctrine/deprecations": {
|
||||||
"version": "v0.5.3"
|
"version": "v0.5.3"
|
||||||
},
|
},
|
||||||
|
"doctrine/doctrine-bundle": {
|
||||||
|
"version": "2.3",
|
||||||
|
"recipe": {
|
||||||
|
"repo": "github.com/symfony/recipes",
|
||||||
|
"branch": "master",
|
||||||
|
"version": "2.3",
|
||||||
|
"ref": "6e0f582596a8f1c865aaa0d3cceb9bf0daf609b4"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"config/packages/doctrine.yaml",
|
||||||
|
"config/packages/prod/doctrine.yaml",
|
||||||
|
"config/packages/test/doctrine.yaml",
|
||||||
|
"src/Entity/.gitignore",
|
||||||
|
"src/Repository/.gitignore"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"doctrine/doctrine-migrations-bundle": {
|
||||||
|
"version": "3.1",
|
||||||
|
"recipe": {
|
||||||
|
"repo": "github.com/symfony/recipes",
|
||||||
|
"branch": "master",
|
||||||
|
"version": "3.1",
|
||||||
|
"ref": "ee609429c9ee23e22d6fa5728211768f51ed2818"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"config/packages/doctrine_migrations.yaml",
|
||||||
|
"migrations/.gitignore"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"doctrine/event-manager": {
|
||||||
|
"version": "1.1.1"
|
||||||
|
},
|
||||||
|
"doctrine/inflector": {
|
||||||
|
"version": "2.0.3"
|
||||||
|
},
|
||||||
|
"doctrine/instantiator": {
|
||||||
|
"version": "1.4.0"
|
||||||
|
},
|
||||||
|
"doctrine/lexer": {
|
||||||
|
"version": "1.2.1"
|
||||||
|
},
|
||||||
|
"doctrine/migrations": {
|
||||||
|
"version": "3.1.1"
|
||||||
|
},
|
||||||
|
"doctrine/orm": {
|
||||||
|
"version": "2.8.4"
|
||||||
|
},
|
||||||
|
"doctrine/persistence": {
|
||||||
|
"version": "2.1.0"
|
||||||
|
},
|
||||||
|
"doctrine/sql-formatter": {
|
||||||
|
"version": "1.1.1"
|
||||||
|
},
|
||||||
|
"egulias/email-validator": {
|
||||||
|
"version": "3.1.1"
|
||||||
|
},
|
||||||
|
"erusev/parsedown": {
|
||||||
|
"version": "1.7.4"
|
||||||
|
},
|
||||||
|
"friendsofphp/php-cs-fixer": {
|
||||||
|
"version": "2.17",
|
||||||
|
"recipe": {
|
||||||
|
"repo": "github.com/symfony/recipes",
|
||||||
|
"branch": "master",
|
||||||
|
"version": "2.17",
|
||||||
|
"ref": "f0d4b4ddb4e2bb73b227e3987b6ecc53cd8be431"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
".php_cs.dist"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"friendsofphp/proxy-manager-lts": {
|
||||||
|
"version": "v1.0.3"
|
||||||
|
},
|
||||||
|
"giggsey/libphonenumber-for-php": {
|
||||||
|
"version": "8.12.21"
|
||||||
|
},
|
||||||
|
"giggsey/locale": {
|
||||||
|
"version": "1.9"
|
||||||
|
},
|
||||||
"jchook/phpunit-assert-throws": {
|
"jchook/phpunit-assert-throws": {
|
||||||
"version": "v1.0.3"
|
"version": "v1.0.3"
|
||||||
},
|
},
|
||||||
|
"laminas/laminas-code": {
|
||||||
|
"version": "4.1.0"
|
||||||
|
},
|
||||||
|
"laminas/laminas-eventmanager": {
|
||||||
|
"version": "3.3.1"
|
||||||
|
},
|
||||||
|
"laminas/laminas-zendframework-bridge": {
|
||||||
|
"version": "1.2.0"
|
||||||
|
},
|
||||||
|
"league/uri-parser": {
|
||||||
|
"version": "1.4.1"
|
||||||
|
},
|
||||||
|
"lstrojny/functional-php": {
|
||||||
|
"version": "1.17.0"
|
||||||
|
},
|
||||||
|
"masterminds/html5": {
|
||||||
|
"version": "2.7.4"
|
||||||
|
},
|
||||||
|
"monolog/monolog": {
|
||||||
|
"version": "2.2.0"
|
||||||
|
},
|
||||||
"myclabs/deep-copy": {
|
"myclabs/deep-copy": {
|
||||||
"version": "1.10.2"
|
"version": "1.10.2"
|
||||||
},
|
},
|
||||||
|
"niels-de-blaauw/php-doc-check": {
|
||||||
|
"version": "v0.2.2"
|
||||||
|
},
|
||||||
|
"nikic/php-parser": {
|
||||||
|
"version": "v4.10.4"
|
||||||
|
},
|
||||||
|
"odolbeau/phone-number-bundle": {
|
||||||
|
"version": "3.0",
|
||||||
|
"recipe": {
|
||||||
|
"repo": "github.com/symfony/recipes-contrib",
|
||||||
|
"branch": "master",
|
||||||
|
"version": "3.0",
|
||||||
|
"ref": "4388686329b81291918a948cd42891829fb1de71"
|
||||||
|
}
|
||||||
|
},
|
||||||
"phar-io/manifest": {
|
"phar-io/manifest": {
|
||||||
"version": "2.0.1"
|
"version": "2.0.1"
|
||||||
},
|
},
|
||||||
"phar-io/version": {
|
"phar-io/version": {
|
||||||
"version": "3.1.0"
|
"version": "3.1.0"
|
||||||
},
|
},
|
||||||
|
"php-cs-fixer/diff": {
|
||||||
|
"version": "v1.3.1"
|
||||||
|
},
|
||||||
|
"php-ds/php-ds": {
|
||||||
|
"version": "v1.3.0"
|
||||||
|
},
|
||||||
|
"phpdocumentor/reflection-common": {
|
||||||
|
"version": "2.2.0"
|
||||||
|
},
|
||||||
|
"phpdocumentor/reflection-docblock": {
|
||||||
|
"version": "5.2.2"
|
||||||
|
},
|
||||||
|
"phpdocumentor/type-resolver": {
|
||||||
|
"version": "1.4.0"
|
||||||
|
},
|
||||||
"phpspec/prophecy": {
|
"phpspec/prophecy": {
|
||||||
"version": "1.13.0"
|
"version": "1.13.0"
|
||||||
},
|
},
|
||||||
@ -46,6 +216,21 @@
|
|||||||
"tests/bootstrap.php"
|
"tests/bootstrap.php"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"psr/cache": {
|
||||||
|
"version": "1.0.1"
|
||||||
|
},
|
||||||
|
"psr/container": {
|
||||||
|
"version": "1.1.1"
|
||||||
|
},
|
||||||
|
"psr/event-dispatcher": {
|
||||||
|
"version": "1.0.0"
|
||||||
|
},
|
||||||
|
"psr/link": {
|
||||||
|
"version": "1.1.1"
|
||||||
|
},
|
||||||
|
"psr/log": {
|
||||||
|
"version": "1.1.3"
|
||||||
|
},
|
||||||
"sebastian/cli-parser": {
|
"sebastian/cli-parser": {
|
||||||
"version": "1.0.1"
|
"version": "1.0.1"
|
||||||
},
|
},
|
||||||
@ -94,7 +279,449 @@
|
|||||||
"sebastian/version": {
|
"sebastian/version": {
|
||||||
"version": "3.0.2"
|
"version": "3.0.2"
|
||||||
},
|
},
|
||||||
|
"sensio/framework-extra-bundle": {
|
||||||
|
"version": "5.2",
|
||||||
|
"recipe": {
|
||||||
|
"repo": "github.com/symfony/recipes",
|
||||||
|
"branch": "master",
|
||||||
|
"version": "5.2",
|
||||||
|
"ref": "fb7e19da7f013d0d422fa9bce16f5c510e27609b"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"config/packages/sensio_framework_extra.yaml"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"someonewithpc/memcached-polyfill": {
|
||||||
|
"version": "1.0.1"
|
||||||
|
},
|
||||||
|
"someonewithpc/redis-polyfill": {
|
||||||
|
"version": "dev-master"
|
||||||
|
},
|
||||||
|
"symfony/amqp-messenger": {
|
||||||
|
"version": "v5.2.4"
|
||||||
|
},
|
||||||
|
"symfony/asset": {
|
||||||
|
"version": "v5.2.4"
|
||||||
|
},
|
||||||
|
"symfony/browser-kit": {
|
||||||
|
"version": "v5.2.4"
|
||||||
|
},
|
||||||
|
"symfony/cache": {
|
||||||
|
"version": "v5.2.6"
|
||||||
|
},
|
||||||
|
"symfony/cache-contracts": {
|
||||||
|
"version": "v2.2.0"
|
||||||
|
},
|
||||||
|
"symfony/config": {
|
||||||
|
"version": "v5.2.4"
|
||||||
|
},
|
||||||
|
"symfony/console": {
|
||||||
|
"version": "5.1",
|
||||||
|
"recipe": {
|
||||||
|
"repo": "github.com/symfony/recipes",
|
||||||
|
"branch": "master",
|
||||||
|
"version": "5.1",
|
||||||
|
"ref": "c6d02bdfba9da13c22157520e32a602dbee8a75c"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"bin/console"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"symfony/css-selector": {
|
||||||
|
"version": "v5.2.4"
|
||||||
|
},
|
||||||
|
"symfony/debug-bundle": {
|
||||||
|
"version": "4.1",
|
||||||
|
"recipe": {
|
||||||
|
"repo": "github.com/symfony/recipes",
|
||||||
|
"branch": "master",
|
||||||
|
"version": "4.1",
|
||||||
|
"ref": "f8863cbad2f2e58c4b65fa1eac892ab189971bea"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"config/packages/dev/debug.yaml"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"symfony/debug-pack": {
|
||||||
|
"version": "v1.0.9"
|
||||||
|
},
|
||||||
|
"symfony/dependency-injection": {
|
||||||
|
"version": "v5.2.6"
|
||||||
|
},
|
||||||
|
"symfony/deprecation-contracts": {
|
||||||
|
"version": "v2.2.0"
|
||||||
|
},
|
||||||
|
"symfony/doctrine-bridge": {
|
||||||
|
"version": "v5.2.6"
|
||||||
|
},
|
||||||
|
"symfony/doctrine-messenger": {
|
||||||
|
"version": "v5.2.5"
|
||||||
|
},
|
||||||
|
"symfony/dom-crawler": {
|
||||||
|
"version": "v5.2.4"
|
||||||
|
},
|
||||||
|
"symfony/dotenv": {
|
||||||
|
"version": "v5.2.4"
|
||||||
|
},
|
||||||
|
"symfony/error-handler": {
|
||||||
|
"version": "v5.2.6"
|
||||||
|
},
|
||||||
|
"symfony/event-dispatcher": {
|
||||||
|
"version": "v5.2.4"
|
||||||
|
},
|
||||||
|
"symfony/event-dispatcher-contracts": {
|
||||||
|
"version": "v2.2.0"
|
||||||
|
},
|
||||||
|
"symfony/expression-language": {
|
||||||
|
"version": "v5.2.4"
|
||||||
|
},
|
||||||
|
"symfony/filesystem": {
|
||||||
|
"version": "v5.2.6"
|
||||||
|
},
|
||||||
|
"symfony/finder": {
|
||||||
|
"version": "v5.2.4"
|
||||||
|
},
|
||||||
|
"symfony/flex": {
|
||||||
|
"version": "1.0",
|
||||||
|
"recipe": {
|
||||||
|
"repo": "github.com/symfony/recipes",
|
||||||
|
"branch": "master",
|
||||||
|
"version": "1.0",
|
||||||
|
"ref": "c0eeb50665f0f77226616b6038a9b06c03752d8e"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
".env"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"symfony/form": {
|
||||||
|
"version": "v5.2.6"
|
||||||
|
},
|
||||||
|
"symfony/framework-bundle": {
|
||||||
|
"version": "5.2",
|
||||||
|
"recipe": {
|
||||||
|
"repo": "github.com/symfony/recipes",
|
||||||
|
"branch": "master",
|
||||||
|
"version": "5.2",
|
||||||
|
"ref": "6ec87563dcc85cd0c48856dcfbfc29610506d250"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"config/packages/cache.yaml",
|
||||||
|
"config/packages/framework.yaml",
|
||||||
|
"config/packages/test/framework.yaml",
|
||||||
|
"config/preload.php",
|
||||||
|
"config/routes/dev/framework.yaml",
|
||||||
|
"config/services.yaml",
|
||||||
|
"public/index.php",
|
||||||
|
"src/Controller/.gitignore",
|
||||||
|
"src/Kernel.php"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"symfony/http-client": {
|
||||||
|
"version": "v5.2.6"
|
||||||
|
},
|
||||||
|
"symfony/http-client-contracts": {
|
||||||
|
"version": "v2.3.1"
|
||||||
|
},
|
||||||
|
"symfony/http-foundation": {
|
||||||
|
"version": "v5.2.4"
|
||||||
|
},
|
||||||
|
"symfony/http-kernel": {
|
||||||
|
"version": "v5.2.6"
|
||||||
|
},
|
||||||
|
"symfony/intl": {
|
||||||
|
"version": "v5.2.4"
|
||||||
|
},
|
||||||
|
"symfony/mailer": {
|
||||||
|
"version": "4.3",
|
||||||
|
"recipe": {
|
||||||
|
"repo": "github.com/symfony/recipes",
|
||||||
|
"branch": "master",
|
||||||
|
"version": "4.3",
|
||||||
|
"ref": "15658c2a0176cda2e7dba66276a2030b52bd81b2"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"config/packages/mailer.yaml"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"symfony/maker-bundle": {
|
||||||
|
"version": "1.0",
|
||||||
|
"recipe": {
|
||||||
|
"repo": "github.com/symfony/recipes",
|
||||||
|
"branch": "master",
|
||||||
|
"version": "1.0",
|
||||||
|
"ref": "fadbfe33303a76e25cb63401050439aa9b1a9c7f"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"symfony/messenger": {
|
||||||
|
"version": "4.3",
|
||||||
|
"recipe": {
|
||||||
|
"repo": "github.com/symfony/recipes",
|
||||||
|
"branch": "master",
|
||||||
|
"version": "4.3",
|
||||||
|
"ref": "e9a414b113ceadbf4e52abe37bf8f1b443f06ccb"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"config/packages/messenger.yaml"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"symfony/mime": {
|
||||||
|
"version": "v5.2.6"
|
||||||
|
},
|
||||||
|
"symfony/monolog-bridge": {
|
||||||
|
"version": "v5.2.5"
|
||||||
|
},
|
||||||
|
"symfony/monolog-bundle": {
|
||||||
|
"version": "3.7",
|
||||||
|
"recipe": {
|
||||||
|
"repo": "github.com/symfony/recipes",
|
||||||
|
"branch": "master",
|
||||||
|
"version": "3.7",
|
||||||
|
"ref": "f4adb4379ee437f91ecb1bd5a41c1de6286b9a04"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"config/packages/dev/monolog.yaml",
|
||||||
|
"config/packages/prod/deprecations.yaml",
|
||||||
|
"config/packages/prod/monolog.yaml",
|
||||||
|
"config/packages/test/monolog.yaml"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"symfony/notifier": {
|
||||||
|
"version": "5.0",
|
||||||
|
"recipe": {
|
||||||
|
"repo": "github.com/symfony/recipes",
|
||||||
|
"branch": "master",
|
||||||
|
"version": "5.0",
|
||||||
|
"ref": "c31585e252b32fe0e1f30b1f256af553f4a06eb9"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"config/packages/notifier.yaml"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"symfony/options-resolver": {
|
||||||
|
"version": "v5.2.4"
|
||||||
|
},
|
||||||
|
"symfony/orm-pack": {
|
||||||
|
"version": "v2.1.0"
|
||||||
|
},
|
||||||
|
"symfony/phpunit-bridge": {
|
||||||
|
"version": "5.1",
|
||||||
|
"recipe": {
|
||||||
|
"repo": "github.com/symfony/recipes",
|
||||||
|
"branch": "master",
|
||||||
|
"version": "5.1",
|
||||||
|
"ref": "bf16921ef8309a81d9f046e9b6369c46bcbd031f"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
".env.test",
|
||||||
|
"bin/phpunit",
|
||||||
|
"phpunit.xml.dist",
|
||||||
|
"tests/bootstrap.php"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"symfony/polyfill-intl-grapheme": {
|
||||||
|
"version": "v1.22.1"
|
||||||
|
},
|
||||||
|
"symfony/polyfill-intl-icu": {
|
||||||
|
"version": "v1.22.1"
|
||||||
|
},
|
||||||
|
"symfony/polyfill-intl-idn": {
|
||||||
|
"version": "v1.22.1"
|
||||||
|
},
|
||||||
|
"symfony/polyfill-intl-normalizer": {
|
||||||
|
"version": "v1.22.1"
|
||||||
|
},
|
||||||
|
"symfony/polyfill-mbstring": {
|
||||||
|
"version": "v1.22.1"
|
||||||
|
},
|
||||||
|
"symfony/polyfill-php73": {
|
||||||
|
"version": "v1.22.1"
|
||||||
|
},
|
||||||
|
"symfony/polyfill-php80": {
|
||||||
|
"version": "v1.22.1"
|
||||||
|
},
|
||||||
|
"symfony/process": {
|
||||||
|
"version": "v5.2.4"
|
||||||
|
},
|
||||||
|
"symfony/profiler-pack": {
|
||||||
|
"version": "v1.0.5"
|
||||||
|
},
|
||||||
|
"symfony/property-access": {
|
||||||
|
"version": "v5.2.4"
|
||||||
|
},
|
||||||
|
"symfony/property-info": {
|
||||||
|
"version": "v5.2.4"
|
||||||
|
},
|
||||||
|
"symfony/proxy-manager-bridge": {
|
||||||
|
"version": "v5.2.4"
|
||||||
|
},
|
||||||
|
"symfony/redis-messenger": {
|
||||||
|
"version": "v5.2.4"
|
||||||
|
},
|
||||||
|
"symfony/routing": {
|
||||||
|
"version": "5.1",
|
||||||
|
"recipe": {
|
||||||
|
"repo": "github.com/symfony/recipes",
|
||||||
|
"branch": "master",
|
||||||
|
"version": "5.1",
|
||||||
|
"ref": "b4f3e7c95e38b606eef467e8a42a8408fc460c43"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"config/packages/prod/routing.yaml",
|
||||||
|
"config/packages/routing.yaml",
|
||||||
|
"config/routes.yaml"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"symfony/security-bundle": {
|
||||||
|
"version": "5.1",
|
||||||
|
"recipe": {
|
||||||
|
"repo": "github.com/symfony/recipes",
|
||||||
|
"branch": "master",
|
||||||
|
"version": "5.1",
|
||||||
|
"ref": "0a4bae19389d3b9cba1ca0102e3b2bccea724603"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"config/packages/security.yaml"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"symfony/security-core": {
|
||||||
|
"version": "v5.2.6"
|
||||||
|
},
|
||||||
|
"symfony/security-csrf": {
|
||||||
|
"version": "v5.2.4"
|
||||||
|
},
|
||||||
|
"symfony/security-guard": {
|
||||||
|
"version": "v5.2.4"
|
||||||
|
},
|
||||||
|
"symfony/security-http": {
|
||||||
|
"version": "v5.2.6"
|
||||||
|
},
|
||||||
|
"symfony/serializer": {
|
||||||
|
"version": "v5.2.4"
|
||||||
|
},
|
||||||
|
"symfony/serializer-pack": {
|
||||||
|
"version": "v1.0.4"
|
||||||
|
},
|
||||||
|
"symfony/service-contracts": {
|
||||||
|
"version": "v2.2.0"
|
||||||
|
},
|
||||||
|
"symfony/stopwatch": {
|
||||||
|
"version": "v5.2.4"
|
||||||
|
},
|
||||||
|
"symfony/string": {
|
||||||
|
"version": "v5.2.6"
|
||||||
|
},
|
||||||
|
"symfony/test-pack": {
|
||||||
|
"version": "v1.0.7"
|
||||||
|
},
|
||||||
|
"symfony/translation": {
|
||||||
|
"version": "3.3",
|
||||||
|
"recipe": {
|
||||||
|
"repo": "github.com/symfony/recipes",
|
||||||
|
"branch": "master",
|
||||||
|
"version": "3.3",
|
||||||
|
"ref": "2ad9d2545bce8ca1a863e50e92141f0b9d87ffcd"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"config/packages/translation.yaml",
|
||||||
|
"translations/.gitignore"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"symfony/translation-contracts": {
|
||||||
|
"version": "v2.3.0"
|
||||||
|
},
|
||||||
|
"symfony/twig-bridge": {
|
||||||
|
"version": "v5.2.6"
|
||||||
|
},
|
||||||
|
"symfony/twig-bundle": {
|
||||||
|
"version": "5.0",
|
||||||
|
"recipe": {
|
||||||
|
"repo": "github.com/symfony/recipes",
|
||||||
|
"branch": "master",
|
||||||
|
"version": "5.0",
|
||||||
|
"ref": "fab9149bbaa4d5eca054ed93f9e1b66cc500895d"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"config/packages/test/twig.yaml",
|
||||||
|
"config/packages/twig.yaml",
|
||||||
|
"templates/base.html.twig"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"symfony/twig-pack": {
|
||||||
|
"version": "v1.0.1"
|
||||||
|
},
|
||||||
|
"symfony/validator": {
|
||||||
|
"version": "4.3",
|
||||||
|
"recipe": {
|
||||||
|
"repo": "github.com/symfony/recipes",
|
||||||
|
"branch": "master",
|
||||||
|
"version": "4.3",
|
||||||
|
"ref": "d902da3e4952f18d3bf05aab29512eb61cabd869"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"config/packages/test/validator.yaml",
|
||||||
|
"config/packages/validator.yaml"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"symfony/var-dumper": {
|
||||||
|
"version": "v5.2.6"
|
||||||
|
},
|
||||||
|
"symfony/var-exporter": {
|
||||||
|
"version": "v5.2.4"
|
||||||
|
},
|
||||||
|
"symfony/web-link": {
|
||||||
|
"version": "v5.2.5"
|
||||||
|
},
|
||||||
|
"symfony/web-profiler-bundle": {
|
||||||
|
"version": "3.3",
|
||||||
|
"recipe": {
|
||||||
|
"repo": "github.com/symfony/recipes",
|
||||||
|
"branch": "master",
|
||||||
|
"version": "3.3",
|
||||||
|
"ref": "6bdfa1a95f6b2e677ab985cd1af2eae35d62e0f6"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"config/packages/dev/web_profiler.yaml",
|
||||||
|
"config/packages/test/web_profiler.yaml",
|
||||||
|
"config/routes/dev/web_profiler.yaml"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"symfony/yaml": {
|
||||||
|
"version": "v5.2.5"
|
||||||
|
},
|
||||||
|
"symfonycasts/verify-email-bundle": {
|
||||||
|
"version": "v1.3.0"
|
||||||
|
},
|
||||||
|
"tgalopin/html-sanitizer": {
|
||||||
|
"version": "1.4.0"
|
||||||
|
},
|
||||||
|
"tgalopin/html-sanitizer-bundle": {
|
||||||
|
"version": "1.0",
|
||||||
|
"recipe": {
|
||||||
|
"repo": "github.com/symfony/recipes-contrib",
|
||||||
|
"branch": "master",
|
||||||
|
"version": "1.0",
|
||||||
|
"ref": "95b935177db9abb65356fe19e57fe5abd908b5b8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"theseer/tokenizer": {
|
"theseer/tokenizer": {
|
||||||
"version": "1.2.0"
|
"version": "1.2.0"
|
||||||
|
},
|
||||||
|
"twig/extra-bundle": {
|
||||||
|
"version": "v3.3.0"
|
||||||
|
},
|
||||||
|
"twig/markdown-extra": {
|
||||||
|
"version": "v3.3.0"
|
||||||
|
},
|
||||||
|
"twig/twig": {
|
||||||
|
"version": "v3.3.0"
|
||||||
|
},
|
||||||
|
"ulrichsg/getopt-php": {
|
||||||
|
"version": "v3.4.0"
|
||||||
|
},
|
||||||
|
"webmozart/assert": {
|
||||||
|
"version": "1.10.0"
|
||||||
|
},
|
||||||
|
"wp-cli/php-cli-tools": {
|
||||||
|
"version": "v0.11.12"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user