mirror of
https://github.com/typemill/typemill.git
synced 2025-08-06 14:16:46 +02:00
Version 1.5.1: File restrictions, download controller, noindex, fix youtube, cyanine third teaser
This commit is contained in:
@@ -180,7 +180,7 @@ class ControllerAuthorArticleApi extends ControllerAuthor
|
||||
|
||||
# check if it is a folder and if the folder has published pages.
|
||||
$message = false;
|
||||
if($this->item->elementType == 'folder')
|
||||
if($this->item->elementType == 'folder' && isset($this->item->folderContent))
|
||||
{
|
||||
foreach($this->item->folderContent as $folderContent)
|
||||
{
|
||||
|
@@ -6,6 +6,7 @@ use Slim\Http\Request;
|
||||
use Slim\Http\Response;
|
||||
use Typemill\Models\ProcessImage;
|
||||
use Typemill\Models\ProcessFile;
|
||||
use Typemill\Models\WriteYaml;
|
||||
use Typemill\Controllers\ControllerAuthorBlockApi;
|
||||
|
||||
class ControllerAuthorMediaApi extends ControllerAuthor
|
||||
@@ -92,6 +93,69 @@ class ControllerAuthorMediaApi extends ControllerAuthor
|
||||
return $response->withJson(['errors' => 'file not found or file name invalid'],404);
|
||||
}
|
||||
|
||||
public function getFileRestrictions(Request $request, Response $response, $args)
|
||||
{
|
||||
# get params from call
|
||||
$this->params = $request->getParams();
|
||||
$this->uri = $request->getUri()->withUserInfo('');
|
||||
$restriction = 'all';
|
||||
|
||||
$userroles = $this->c->acl->getRoles();
|
||||
|
||||
if(isset($this->params['filename']) && $this->params['filename'] != '')
|
||||
{
|
||||
$writeYaml = new WriteYaml();
|
||||
$restrictions = $writeYaml->getYaml('media' . DIRECTORY_SEPARATOR . 'files', 'filerestrictions.yaml');
|
||||
if(isset($restrictions[$this->params['filename']]))
|
||||
{
|
||||
$restriction = $restrictions[$this->params['filename']];
|
||||
}
|
||||
}
|
||||
|
||||
return $response->withJson(['userroles' => $userroles, 'restriction' => $restriction]);
|
||||
}
|
||||
|
||||
public function updateFileRestrictions(Request $request, Response $response, $args)
|
||||
{
|
||||
# get params from call
|
||||
$this->params = $request->getParams();
|
||||
$this->uri = $request->getUri()->withUserInfo('');
|
||||
$filename = isset($this->params['filename']) ? $this->params['filename'] : false;
|
||||
$role = isset($this->params['role']) ? $this->params['role'] : false;
|
||||
|
||||
if(!$filename OR !$role)
|
||||
{
|
||||
return $response->withJson(['errors' => ['message' => 'Filename or userrole is missing.']], 422);
|
||||
}
|
||||
|
||||
$userroles = $this->c->acl->getRoles();
|
||||
|
||||
if($role != 'all' AND !in_array($role, $userroles))
|
||||
{
|
||||
return $response->withJson(['errors' => ['message' => 'Userrole is unknown.']], 422);
|
||||
}
|
||||
|
||||
$writeYaml = new WriteYaml();
|
||||
$restrictions = $writeYaml->getYaml('media' . DIRECTORY_SEPARATOR . 'files', 'filerestrictions.yaml');
|
||||
if(!$restrictions)
|
||||
{
|
||||
$restrictions = [];
|
||||
}
|
||||
|
||||
if($role == 'all')
|
||||
{
|
||||
unset($restrictions[$filename]);
|
||||
}
|
||||
else
|
||||
{
|
||||
$restrictions[$filename] = $role;
|
||||
}
|
||||
|
||||
$writeYaml->updateYaml('media' . DIRECTORY_SEPARATOR . 'files', 'filerestrictions.yaml', $restrictions);
|
||||
|
||||
return $response->withJson(['restrictions' => $restrictions]);
|
||||
}
|
||||
|
||||
public function createImage(Request $request, Response $response, $args)
|
||||
{
|
||||
# get params from call
|
||||
@@ -382,14 +446,14 @@ class ControllerAuthorMediaApi extends ControllerAuthor
|
||||
return $response->withJson(['errors' => ['message' => 'Please check if your media-folder exists and all folders inside are writable.']], 500);
|
||||
}
|
||||
|
||||
$tmpImage = $imageProcessor->createImage($imageData64, $desiredSizes);
|
||||
$tmpImage = $imageProcessor->createImage($imageData64, $videoID, $desiredSizes);
|
||||
|
||||
if(!$tmpImage)
|
||||
{
|
||||
return $response->withJson(array('errors' => 'could not create temporary image'));
|
||||
}
|
||||
|
||||
$imageUrl = $imageProcessor->publishImage($desiredSizes, $videoID);
|
||||
$imageUrl = $imageProcessor->publishImage();
|
||||
if($imageUrl)
|
||||
{
|
||||
$this->params['markdown'] = '{#' . $videoID. ' .' . $class . '}';
|
||||
|
@@ -313,6 +313,7 @@ class ControllerAuthorMetaApi extends ControllerAuthor
|
||||
# normalize the meta-input
|
||||
$metaInput['navtitle'] = (isset($metaInput['navtitle']) && $metaInput['navtitle'] !== null )? $metaInput['navtitle'] : '';
|
||||
$metaInput['hide'] = (isset($metaInput['hide']) && $metaInput['hide'] !== null) ? $metaInput['hide'] : false;
|
||||
$metaInput['noindex'] = (isset($metaInput['noindex']) && $metaInput['noindex'] !== null) ? $metaInput['noindex'] : false;
|
||||
|
||||
# input values are empty but entry in structure exists
|
||||
if(!$metaInput['hide'] && $metaInput['navtitle'] == "" && isset($extended[$this->item->urlRelWoF]))
|
||||
@@ -327,10 +328,12 @@ class ControllerAuthorMetaApi extends ControllerAuthor
|
||||
($this->hasChanged($metaInput, $metaPage['meta'], 'navtitle'))
|
||||
OR
|
||||
($this->hasChanged($metaInput, $metaPage['meta'], 'hide'))
|
||||
OR
|
||||
($this->hasChanged($metaInput, $metaPage['meta'], 'noindex'))
|
||||
)
|
||||
{
|
||||
# add new file data. Also makes sure that the value is set.
|
||||
$extended[$this->item->urlRelWoF] = ['hide' => $metaInput['hide'], 'navtitle' => $metaInput['navtitle']];
|
||||
$extended[$this->item->urlRelWoF] = ['hide' => $metaInput['hide'], 'navtitle' => $metaInput['navtitle'], 'noindex' => $metaInput['noindex']];
|
||||
|
||||
$structure = true;
|
||||
}
|
||||
|
144
system/Controllers/ControllerDownload.php
Normal file
144
system/Controllers/ControllerDownload.php
Normal file
@@ -0,0 +1,144 @@
|
||||
<?php
|
||||
|
||||
namespace Typemill\Controllers;
|
||||
|
||||
use Typemill\Models\WriteYaml;
|
||||
|
||||
class ControllerDownload extends ControllerShared
|
||||
{
|
||||
public function download($request, $response, $args)
|
||||
{
|
||||
|
||||
$filename = isset($args['params']) ? $args['params'] : false;
|
||||
$root = $this->c->get('settings')['rootPath'];
|
||||
$mediapath = 'media/files/';
|
||||
$filepath = $root . $mediapath;
|
||||
|
||||
if(!$filename)
|
||||
{
|
||||
die('the requested file does not exist.');
|
||||
}
|
||||
|
||||
# validate
|
||||
$allowedFiletypes = [];
|
||||
if(!$this->validate($filepath, $filename, $allowedFiletypes))
|
||||
{
|
||||
die('the requested file is not allowed.');
|
||||
}
|
||||
|
||||
$writeYaml = new WriteYaml();
|
||||
$restrictions = $writeYaml->getYaml('media' . DIRECTORY_SEPARATOR . 'files', 'filerestrictions.yaml');
|
||||
|
||||
if($restrictions && isset($restrictions[$mediapath . $filename]))
|
||||
{
|
||||
$allowedrole = $restrictions[$mediapath . $filename];
|
||||
|
||||
if(!isset($_SESSION['role']))
|
||||
{
|
||||
die("You have to be an authenticated $allowedrole to download this file.");
|
||||
}
|
||||
elseif(
|
||||
$_SESSION['role'] != 'administrator'
|
||||
AND $_SESSION['role'] != $allowedrole
|
||||
AND !$this->c->acl->inheritsRole($_SESSION['role'], $allowedrole)
|
||||
)
|
||||
{
|
||||
die("You have to be a $allowedrole to download this file.");
|
||||
}
|
||||
}
|
||||
|
||||
$file = $filepath . $filename;
|
||||
|
||||
# for now we only allow one download
|
||||
$this->sendDownload($file);
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate if the file exists and if
|
||||
* there is a permission (download dir) to download this file
|
||||
*
|
||||
* You should ALWAYS call this method if you don't want
|
||||
* somebody to download files not intended to be for the public.
|
||||
*
|
||||
* @param string $file GET parameter
|
||||
* @param array $allowedFiletypes (defined in the head of this file)
|
||||
* @return bool true if validation was successfull
|
||||
*/
|
||||
private function validate($path, $file, $allowedFiletypes)
|
||||
{
|
||||
$filepath = $path . $file;
|
||||
|
||||
# check if file exists
|
||||
if (!isset($filepath) || empty($filepath) || !file_exists($filepath))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
# check allowed filetypes
|
||||
if(!empty($allowedFiletypes))
|
||||
{
|
||||
$fileAllowed = false;
|
||||
foreach ($allowedFiletypes as $filetype)
|
||||
{
|
||||
if (strpos($file, $filetype) === (strlen($file) - strlen($filetype)))
|
||||
{
|
||||
$fileAllowed = true; //ends with $filetype
|
||||
}
|
||||
}
|
||||
|
||||
if (!$fileAllowed) return false;
|
||||
}
|
||||
|
||||
# check download directory
|
||||
if (strpos($file, '..') !== false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Download function.
|
||||
* Sets the HTTP header and supplies the given file
|
||||
* as a download to the browser.
|
||||
*
|
||||
* @param string $file path to file
|
||||
*/
|
||||
private function sendDownload($file)
|
||||
{
|
||||
# Parse information
|
||||
$pathinfo = pathinfo($file);
|
||||
$extension = strtolower($pathinfo['extension']);
|
||||
$mimetype = null;
|
||||
|
||||
# Get mimetype for extension
|
||||
# This list can be extended as you need it.
|
||||
# A good start to find mimetypes is the apache mime.types list
|
||||
# http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types
|
||||
switch ($extension) {
|
||||
case 'zip': $mimetype = "application/zip"; break;
|
||||
default: $mimetype = "application/force-download";
|
||||
}
|
||||
|
||||
# Required for some browsers like Safari and IE
|
||||
if (ini_get('zlib.output_compression'))
|
||||
{
|
||||
ini_set('zlib.output_compression', 'Off');
|
||||
}
|
||||
|
||||
header('Pragma: public');
|
||||
header('Content-Encoding: none');
|
||||
header('Expires: 0');
|
||||
header('Accept-Ranges: bytes'); # Allow support for download resume
|
||||
header('Last-Modified: ' . gmdate('D, d M Y H:i:s', filemtime($file)) . ' GMT');
|
||||
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
|
||||
header('Cache-Control: private', false); # required for some browsers
|
||||
header('Content-Type: application/zip');
|
||||
header('Content-Disposition: attachment; filename="'.basename($file).'";'); # Make the browser display the Save As dialog
|
||||
header('Content-Transfer-Encoding: binary');
|
||||
header('Content-Length: '.filesize($file));
|
||||
ob_end_flush();
|
||||
readfile($file); # This is necessary in order to get it to actually download the file, otherwise it will be 0Kb
|
||||
}
|
||||
}
|
@@ -177,7 +177,7 @@ abstract class ControllerShared
|
||||
$pagetreeLive = Folder::scanFolder($this->settings['rootPath'] . $this->settings['contentFolder'], $draft = false );
|
||||
|
||||
# if there is content, then get the content details
|
||||
if(count($pagetreeLive) > 0)
|
||||
if($pagetreeLive && count($pagetreeLive) > 0)
|
||||
{
|
||||
# get the extended structure files with changes like navigation title or hidden pages
|
||||
$yaml = new writeYaml();
|
||||
@@ -295,28 +295,37 @@ abstract class ControllerShared
|
||||
$opts = array(
|
||||
'http'=>array(
|
||||
'method'=>"GET",
|
||||
'ignore_errors' => true,
|
||||
'timeout' => 5
|
||||
)
|
||||
);
|
||||
|
||||
$context = stream_context_create($opts);
|
||||
$context = stream_context_create($opts);
|
||||
|
||||
$resultBing = file_get_contents($pingBingUrl, false, $context);
|
||||
$resultGoogle = file_get_contents($pingGoogleUrl, false, $context);
|
||||
$responseBing = file_get_contents($pingBingUrl, false, $context);
|
||||
$responseGoogle = file_get_contents($pingGoogleUrl, false, $context);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function generateUrlSets($structureLive)
|
||||
{
|
||||
{
|
||||
$urlset = '';
|
||||
|
||||
|
||||
foreach($structureLive as $item)
|
||||
{
|
||||
if($item->elementType == 'folder')
|
||||
if($item->elementType == 'folder' && isset($item->noindex) && $item->noindex === true)
|
||||
{
|
||||
$urlset .= $this->generateUrlSets($item->folderContent, $urlset);
|
||||
}
|
||||
elseif($item->elementType == 'folder')
|
||||
{
|
||||
$urlset = $this->addUrlSet($urlset, $item->urlAbs);
|
||||
$urlset .= $this->generateUrlSets($item->folderContent, $urlset);
|
||||
$urlset .= $this->generateUrlSets($item->folderContent, $urlset);
|
||||
}
|
||||
elseif(isset($item->noindex) && $item->noindex === true )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
Reference in New Issue
Block a user