Skip to content
Commits on Source (10)
......@@ -7,13 +7,13 @@
*/
namespace Minds\Controllers\api\v1\media;
use Minds\Api\Factory;
use Minds\Common;
use Minds\Core;
use Minds\Core\Di\Di;
use Minds\Helpers;
use Minds\Core\Features\Manager as FeaturesManager;
use Minds\Entities;
use Minds\Interfaces;
use Minds\Api\Factory;
use Minds\Core\Features\Manager as FeaturesManager;
class thumbnails implements Interfaces\Api, Interfaces\ApiIgnorePam
{
......@@ -29,24 +29,33 @@ class thumbnails implements Interfaces\Api, Interfaces\ApiIgnorePam
exit;
}
$featuresManager = new FeaturesManager();
$guid = $pages[0];
if ($featuresManager->has('cdn-jwt')) {
error_log("{$_SERVER['REQUEST_URI']} was hit, and should not have been");
Core\Security\ACL::$ignore = true;
$size = isset($pages[1]) ? $pages[1] : null;
$last_cache = isset($pages[2]) ? $pages[2] : time();
$entity = Entities\Factory::build($guid);
if (!$entity) {
return Factory::response([
'status' => 'error',
'message' => 'This endpoint has been deprecated. Please use fs/v1/thumbnail',
'message' => 'Entity not found'
]);
}
$guid = $pages[0];
Core\Security\ACL::$ignore = true;
$featuresManager = new FeaturesManager();
$size = isset($pages[1]) ? $pages[1] : null;
if ($entity->access_id !== Common\Access::PUBLIC && $featuresManager->has('cdn-jwt')) {
error_log("{$_SERVER['REQUEST_URI']} was hit, and should not have been");
$last_cache = isset($pages[2]) ? $pages[2] : time();
return Factory::response([
'status' => 'error',
'message' => 'This endpoint has been deprecated. Please use fs/v1/thumbnail',
]);
}
$etag = $last_cache . $guid;
if (isset($_SERVER['HTTP_IF_NONE_MATCH']) && trim($_SERVER['HTTP_IF_NONE_MATCH']) == $etag) {
......@@ -54,7 +63,7 @@ class thumbnails implements Interfaces\Api, Interfaces\ApiIgnorePam
exit;
}
$thumbnail = Di::_()->get('Media\Thumbnails')->get($guid, $size);
$thumbnail = Di::_()->get('Media\Thumbnails')->get($entity, $size);
if ($thumbnail instanceof \ElggFile) {
$thumbnail->open('read');
......
......@@ -7,9 +7,7 @@
namespace Minds\Controllers\api\v1\minds;
use Minds;
use Minds\Core;
use Minds\Core\Rewards\Contributions\ContributionValues;
use Minds\Interfaces;
use Minds\Api\Factory;
......@@ -22,33 +20,10 @@ class config implements Interfaces\Api, Interfaces\ApiIgnorePam
*/
public function get($pages)
{
$minds = [
"cdn_url" => Minds\Core\Config::_()->get('cdn_url') ?: Minds\Core\Config::_()->cdn_url,
"cinemr_url" => Minds\Core\Config::_()->get('cinemr_url') ?: Minds\Core\Config::_()->cinemr_url,
"site_url" => Minds\Core\Config::_()->get('site_url') ?: Minds\Core\Config::_()->site_url,
"socket_server" => Minds\Core\Config::_()->get('sockets-server-uri') ?: 'ha-socket-io-us-east-1.minds.com:3030',
"thirdpartynetworks" => Minds\Core\Di\Di::_()->get('ThirdPartyNetworks\Manager')->availableNetworks(),
"categories" => Minds\Core\Config::_()->get('categories') ?: [],
"stripe_key" => Minds\Core\Config::_()->get('payments')['stripe']['public_key'],
"recaptchaKey" => Minds\Core\Config::_()->get('google')['recaptcha']['site_key'],
"max_video_length" => (Core\Session::getLoggedInUser() && Core\Session::getLoggedInUser()->isPlus())
? Minds\Core\Config::_()->get('max_video_length_plus')
: Minds\Core\Config::_()->get('max_video_length'),
"max_video_file_size" => Minds\Core\Config::_()->get('max_video_file_size') ?: 0,
"features" => (object) (Minds\Core\Config::_()->get('features') ?: []),
"blockchain" => (object) Minds\Core\Di\Di::_()->get('Blockchain\Manager')->getPublicSettings(),
"plus" => Minds\Core\Config::_()->get('plus'),
"report_reasons" => Minds\Core\Config::_()->get('report_reasons'),
"last_tos_update" => (Minds\Core\Config::_()->get('last_tos_update') ?: time()),
'handlers' => [
'plus' => Minds\Core\Di\Di::_()->get('Config')->get('plus')['handler'] ?? null,
'pro' => Minds\Core\Di\Di::_()->get('Config')->get('pro')['handler'] ?? null,
],
'upgrades' => Minds\Core\Di\Di::_()->get('Config')->get('upgrades'),
'contribution_values' => ContributionValues::export(),
];
return Factory::response($minds);
return Factory::response(
Core\Di\Di::_()->get('Config\Exported')
->export()
);
}
/**
......
......@@ -39,9 +39,14 @@ class keys implements Interfaces\Api
// $priv = helpers\openssl::temporaryPrivateKey($priv, $unlock_password, $unlock_password);
// \elgg_set_plugin_user_setting('privatekey', $priv, elgg_get_logged_in_user_guid(), 'gatherings');
//}
$keystore->unlockPrivateKey($unlock_password, null);
$tmp = $keystore->getUnlockedPrivateKey();
try {
$keystore->unlockPrivateKey($unlock_password, null);
$tmp = $keystore->getUnlockedPrivateKey();
} catch (\Exception $e) {
$response['status'] = 'error';
$response['message'] = $e->getMessage();
return Factory::response($response);
}
if (!$tmp || !$unlock_password) {
$response['status'] = 'error';
......
......@@ -10,7 +10,7 @@ namespace Minds\Controllers\fs\v1;
use Minds\Core;
use Minds\Entities;
use Minds\Interfaces;
use Minds\Api\Factory;
use Minds\Helpers\File;
class avatars implements Interfaces\FS
{
......@@ -59,10 +59,8 @@ class avatars implements Interfaces\FS
$contents = file_get_contents($filepath);
}
if ($filepath) {
$finfo = finfo_open(FILEINFO_MIME);
$mimetype = finfo_file($finfo, $filepath);
finfo_close($finfo);
if (!empty($contents)) {
$mimetype = File::getMime($contents);
} else {
$mimetype = 'image/jpeg';
}
......
......@@ -10,7 +10,7 @@ namespace Minds\Controllers\fs\v1;
use Minds\Core;
use Minds\Entities;
use Minds\Interfaces;
use Minds\Api\Factory;
use Minds\Helpers\File;
class banners implements Interfaces\FS
{
......@@ -102,9 +102,7 @@ class banners implements Interfaces\FS
}
}
$finfo = finfo_open(FILEINFO_MIME);
$mimetype = finfo_buffer($finfo, $content);
finfo_close($finfo);
$mimetype = File::getMime($content);
header('Content-Type: '.$mimetype);
header('Expires: ' . date('r', time() + 864000));
......
......@@ -10,7 +10,7 @@ namespace Minds\Controllers\fs\v1;
use Minds\Core;
use Minds\Entities;
use Minds\Interfaces;
use Minds\Api\Factory;
use Minds\Helpers\File;
class paywall implements Interfaces\FS
{
......@@ -31,9 +31,7 @@ class paywall implements Interfaces\FS
$contents = file_get_contents(Core\Di\Di::_()->get('Config')->get('path') . 'engine/Assets/photos/andromeda-galaxy.jpg');
}
$finfo = finfo_open(FILEINFO_MIME);
$mimetype = finfo_file($finfo, $filepath);
finfo_close($finfo);
$mimetype = File::getMime($contents);
header('Content-Type: '.$mimetype);
header('Expires: ' . date('r', time() + 864000));
header("Pragma: public");
......
......@@ -4,11 +4,14 @@
*/
namespace Minds\Controllers\fs\v1;
use Minds\Api\Factory;
use Minds\Common;
use Minds\Core;
use Minds\Core\Di\Di;
use Minds\Core\Features\Manager as FeaturesManager;
use Minds\Entities;
use Minds\Interfaces;
use Minds\Core\Features\Manager as FeaturesManager;
use Minds\Helpers\File;
class thumbnail extends Core\page implements Interfaces\page
{
......@@ -18,9 +21,30 @@ class thumbnail extends Core\page implements Interfaces\page
exit;
}
Core\Security\ACL::$ignore = true;
$guid = $pages[0] ?? null;
if (!$guid) {
return Factory::response([
'status' => 'error',
'message' => 'guid must be provided'
]);
}
$size = isset($pages[1]) ? $pages[1] : null;
$entity = Entities\Factory::build($guid);
if (!$entity) {
return Factory::response([
'status' => 'error',
'message' => 'Entity not found'
]);
}
$featuresManager = new FeaturesManager;
if ($featuresManager->has('cdn-jwt')) {
if ($entity->access_id !== Common\Access::PUBLIC && $featuresManager->has('cdn-jwt')) {
$signedUri = new Core\Security\SignedUri();
$uri = (string) \Zend\Diactoros\ServerRequestFactory::fromGlobals()->getUri();
if (!$signedUri->confirm($uri)) {
......@@ -31,9 +55,8 @@ class thumbnail extends Core\page implements Interfaces\page
/** @var Core\Media\Thumbnails $mediaThumbnails */
$mediaThumbnails = Di::_()->get('Media\Thumbnails');
Core\Security\ACL::$ignore = true;
$size = isset($pages[1]) ? $pages[1] : null;
$thumbnail = $mediaThumbnails->get($pages[0], $size);
$thumbnail = $mediaThumbnails->get($entity, $size);
if ($thumbnail instanceof \ElggFile) {
$thumbnail->open('read');
......@@ -47,8 +70,7 @@ class thumbnail extends Core\page implements Interfaces\page
}
try {
$finfo = new \finfo(FILEINFO_MIME);
$contentType = $finfo->buffer($contents) ?: 'image/jpeg';
$contentType = File::getMime($contents);
} catch (\Exception $e) {
error_log($e);
$contentType = 'image/jpeg';
......
......@@ -14,7 +14,7 @@ class ReferralsEarningsMetric extends AbstractEarningsMetric
protected $id = 'earnings_referrals';
/** @var string */
protected $label = 'Referrals USD';
protected $label = 'Referrals';
/** @var string */
protected $description = "Total earnings for your active referrals. You earn $0.10 for every active referral. A referral must log in at least 3 of 7 days after registration to be credited.";
......
......@@ -14,7 +14,7 @@ class SalesEarningsMetric extends AbstractEarningsMetric
protected $id = 'earnings_sales';
/** @var string */
protected $label = 'Sales USD';
protected $label = 'Sales';
/** @var string */
protected $description = "Total earnings for the sales you have referred. You earn a 25% commission when your referrals purchase Plus, Pro or Minds Tokens.";
......
......@@ -14,7 +14,7 @@ class ViewsEarningsMetric extends AbstractEarningsMetric
protected $id = 'earnings_views';
/** @var string */
protected $label = 'Pageviews USD';
protected $label = 'Pageviews';
/** @var string */
protected $description = "Total earnings for the pageviews on your channel's assets. You earn $1 for every 1,000 pageviews.";
......
......@@ -14,7 +14,7 @@ class SubscribersMetric extends AbstractEngagementMetric
protected $id = 'subscribers';
/** @var string */
protected $label = 'Subscribes';
protected $label = 'Subscribers';
/** @var string */
protected $description = "Number of subscribers your channel has gained";
......
......@@ -17,5 +17,9 @@ class ConfigProvider extends Provider
$this->di->bind('Config', function ($di) {
return new Config();
}, ['useFactory'=>true]);
$this->di->bind('Config\Exported', function ($di) {
return new Exported();
}, ['useFactory' => true]);
}
}
<?php
/**
* Exported
* @author edgebal
*/
namespace Minds\Core\Config;
use Minds\Core\Blockchain\Manager as BlockchainManager;
use Minds\Core\Di\Di;
use Minds\Core\I18n\I18n;
use Minds\Core\Navigation\Manager as NavigationManager;
use Minds\Core\Rewards\Contributions\ContributionValues;
use Minds\Core\Session;
use Minds\Core\ThirdPartyNetworks\Manager as ThirdPartyNetworksManager;
use Minds\Entities\User;
use Minds\Helpers\Counters;
class Exported
{
/** @var Config */
protected $config;
/** @var ThirdPartyNetworksManager */
protected $thirdPartyNetworks;
/** @var I18n */
protected $i18n;
/**
* Exported constructor.
* @param Config $config
* @param ThirdPartyNetworksManager $thirdPartyNetworks
* @param I18n $i18n
* @param BlockchainManager $blockchain
*/
public function __construct(
$config = null,
$thirdPartyNetworks = null,
$i18n = null,
$blockchain = null
) {
$this->config = $config ?: Di::_()->get('Config');
$this->thirdPartyNetworks = $thirdPartyNetworks ?: Di::_()->get('ThirdPartyNetworks\Manager');
$this->i18n = $i18n ?: Di::_()->get('I18n');
$this->blockchain = $blockchain ?: Di::_()->get('Blockchain\Manager');
}
/**
* @return array
*/
public function export(): array
{
$context = defined('__MINDS_CONTEXT__') ? __MINDS_CONTEXT__ : 'app';
$exported = [
'MindsContext' => $context,
'LoggedIn' => Session::isLoggedIn() ? true : false,
'Admin' => Session::isAdmin() ? true : false,
'cdn_url' => $this->config->get('cdn_url'),
'cdn_assets_url' => $this->config->get('cdn_assets_url'),
'site_url' => $this->config->get('site_url'),
'cinemr_url' => $this->config->get('cinemr_url'),
'socket_server' => $this->config->get('sockets-server-uri') ?: 'ha-socket-io-us-east-1.minds.com:3030',
'navigation' => NavigationManager::export(),
'thirdpartynetworks' => $this->thirdPartyNetworks->availableNetworks(),
'language' => $this->i18n->getLanguage(),
'languages' => $this->i18n->getLanguages(),
'categories' => $this->config->get('categories') ?: [],
'stripe_key' => $this->config->get('payments')['stripe']['public_key'],
'recaptchaKey' => $this->config->get('google')['recaptcha']['site_key'],
'max_video_length' => $this->config->get('max_video_length'),
'max_video_file_size' => $this->config->get('max_video_file_size'),
'features' => (object) ($this->config->get('features') ?: []),
'blockchain' => (object) $this->blockchain->getPublicSettings(),
'sale' => $this->config->get('blockchain')['sale'],
'last_tos_update' => $this->config->get('last_tos_update') ?: time(),
'tags' => $this->config->get('tags') ?: [],
'plus' => $this->config->get('plus'),
'report_reasons' => $this->config->get('report_reasons'),
'handlers' => [
'plus' => $this->config->get('plus')['handler'] ?? null,
'pro' => $this->config->get('pro')['handler'] ?? null,
],
'upgrades' => $this->config->get('upgrades'),
'contribution_values' => ContributionValues::export(),
'environment' => getenv('MINDS_ENV') ?: 'development',
];
if (Session::isLoggedIn()) {
/** @var User $user */
$user = Session::getLoggedinUser();
$exported['user'] = $user->export();
$exported['user']['rewards'] = (bool) $user->getPhoneNumberHash();
$exported['wallet'] = [
'balance' => Counters::get($user->guid, 'points', false),
];
if ($user->isPlus()) {
$exported['max_video_length'] = $this->config->get('max_video_length_plus');
}
}
if ($context === 'embed') {
$exported['MindsEmbed'] = $embedded_entity ?? null;
}
return $exported;
}
}
<?php
/**
* Index
* @author edgebal
*/
namespace Minds\Core\Front;
use Minds\Core\Config\Exported;
use Minds\Core\Di\Di;
use Minds\Core\Pro\Domain as ProDomain;
use Minds\Core\Pro\Settings;
use Minds\Core\SEO\Manager;
class Index
{
/** @var Exported */
protected $configExported;
/** @var ProDomain */
protected $proDomain;
/** @var string[] */
protected $meta = [];
/** @var string[] */
protected $head = [];
/** @var string[] */
protected $tail = [];
/** @var string */
protected $context = 'app';
/** @var string */
protected $title = '';
/**
* Index constructor.
* @param Exported $configExported
* @param ProDomain $proDomain
*/
public function __construct(
$configExported = null,
$proDomain = null
) {
$this->configExported = $configExported ?: Di::_()->get('Config\Exported');
$this->proDomain = $proDomain ?: Di::_()->get('Pro\Domain');
$this->build();
}
public function build(): void
{
$this->meta = [];
$this->head = [];
$this->tail = [];
//
/** @var Settings|null $pro */
$pro = $this->proDomain->lookup($_SERVER['HTTP_HOST'] ?? null);
// Config variable
$minds = $this->configExported->export();
if ($pro) {
$minds['pro'] = $pro;
}
// Title
$this->title = 'Minds';
if ($pro) {
$this->title = $pro->getTitle() ?: $pro->getDomain();
}
// Favicons
$icons = [
[
'type' => 'image/svg',
'href' => "{$minds['cdn_assets_url']}assets/logos/bulb.svg",
],
[
'rel' => 'apple-touch-icon',
'type' => 'image/png',
'href' => "{$minds['cdn_assets_url']}assets/logos/bulb-apple-touch-icon.png",
'sizes' => '180x180',
],
[
'type' => 'image/png',
'href' => "{$minds['cdn_assets_url']}assets/logos/bulb-32x32.png",
'sizes' => '32x32',
],
[
'type' => 'image/png',
'href' => "{$minds['cdn_assets_url']}assets/logos/bulb-16x16.png",
'sizes' => '16x16',
],
];
if ($pro) {
$icons = [
[
'type' => 'image/jpeg',
'href' => $this->proDomain->getIcon($pro),
],
];
}
foreach ($icons as $icon) {
$attrs = [];
foreach (array_merge(['rel' => 'icon'], $icon) as $key => $value) {
$attrs[] = sprintf("%s=%s", $key, htmlspecialchars($value));
}
$this->meta[] = sprintf("<link %s />", implode(' ', $attrs));
}
// SEO Meta + Title Override
$meta = Manager::get();
foreach ($meta as $name => $content) {
$name = htmlspecialchars($name);
$content = htmlspecialchars($content);
if ($name === 'title') {
$this->title = $content;
continue;
}
$nameAttr = 'name';
if (
strpos($name, ":") !== false &&
strpos($name, "smartbanner") === false
) {
// Attributes with a colon that are not smartbanner
// should use property="<name>"
$nameAttr = 'property';
}
$this->meta[] = sprintf(
"<meta %s=\"%s\" content=\"%s\" />",
$nameAttr,
$name,
$content
);
}
// Head
if ($pro) {
$this->head[] = sprintf(
"<!-- Minds Pro: %s -->\n%s\n<!-- End -->",
$pro->getUserGuid(),
$pro->getCustomHead() ?: '<!-- (no custom head) -->'
);
}
// Tail
$this->tail[] = sprintf("<script>window.Minds = %s;</script>", json_encode($minds));
}
/**
* @return string
*/
public function getMetaHtml(): string
{
return PHP_EOL . implode(PHP_EOL, $this->meta) . PHP_EOL;
}
/**
* @return string
*/
public function getHeadHtml(): string
{
return PHP_EOL . implode(PHP_EOL, $this->head) . PHP_EOL;
}
/**
* @return string
*/
public function getTailHtml(): string
{
return PHP_EOL . implode(PHP_EOL, $this->tail) . PHP_EOL;
}
/**
* @return string
*/
public function getContext(): string
{
return $this->context;
}
/**
* @return string
*/
public function getTitle(): string
{
return $this->title;
}
}
<?php
/**
* Module
* @author edgebal
*/
namespace Minds\Core\Front;
use Minds\Interfaces\ModuleInterface;
class Module implements ModuleInterface
{
/**
* Executed onInit
* @return void
*/
public function onInit(): void
{
(new Provider())->register();
}
}
<?php
/**
* Provider
* @author edgebal
*/
namespace Minds\Core\Front;
use Minds\Core\Di\Provider as DiProvider;
class Provider extends DiProvider
{
public function register()
{
$this->di->bind('Front\Index', function () {
return new Index();
}, [ 'useFactory' => true ]);
}
}
......@@ -20,7 +20,7 @@ class Image implements AssetsInterface
public function upload(array $media, array $data)
{
$filename = "/image/{$this->entity->batch_guid}/{$this->entity->guid}/master.jpg";
$filename = "image/{$this->entity->batch_guid}/{$this->entity->guid}/master.jpg";
// @note: legacy file handling
$file = new \ElggFile();
......
......@@ -64,7 +64,10 @@ class Manager
}
$uri = $this->config->get('cdn_url') . 'fs/v1/thumbnail/' . $asset_guid . '/' . $size;
$uri = $this->signUri($uri);
if ($entity->access_id !== ACCESS_PUBLIC) {
$uri = $this->signUri($uri);
}
return $uri;
}
......
......@@ -9,6 +9,7 @@
namespace Minds\Core\Media\Proxy;
use Minds\Core\Di\Di;
use Minds\Helpers\File;
use Minds\Core\Http\Curl\Client;
use Minds\Traits\MagicAttributes;
......@@ -99,8 +100,7 @@ class Download
throw new \Exception('Invalid image');
}
$finfo = new \finfo(FILEINFO_MIME);
$mime = $finfo->buffer($content);
$mime = File::getMime($content);
if (!$mime) {
throw new \Exception('Cannot read image MIME');
......
......@@ -8,16 +8,27 @@ use Minds\Entities;
class Thumbnails
{
/** @var Core\Config */
protected $config;
/** @var Core\EntitiesBuilder */
protected $entitiesBuilder;
public function __construct($config = null)
public function __construct($config = null, $entitiesBuilder = null)
{
$this->config = $config ?: Di::_()->get('Config');
$this->entitiesBuilder = $entitiesBuilder ?: Di::_()->get('EntitiesBuilder');
}
public function get($guid, $size)
/**
* @param $entity Entities\Entity|string
* @param $size
* @return bool|\ElggFile|mixed|string
*/
public function get($entity, $size)
{
$entity = Entities\Factory::build($guid);
if (is_string($entity)) {
$entity = $this->entitiesBuilder->build($entity);
}
if (!$entity || !Core\Security\ACL::_()->read($entity)) {
return false;
}
......