-
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
<?php defined('BLUDIT') or die('Bludit CMS.');
|
||||
header('Content-Type: application/json');
|
||||
|
||||
/*
|
||||
| Change a page's type. Allowed types: published, sticky, static, draft.
|
||||
| Allowed transitions are restricted to the same set on both ends — anything
|
||||
| else (autosave, scheduled) goes through the normal edit flow.
|
||||
|
|
||||
| @_POST['key'] string Page key
|
||||
| @_POST['type'] string Target type
|
||||
|
|
||||
| @return JSON { status, message, key, type }
|
||||
*/
|
||||
|
||||
checkRole(array('admin', 'editor', 'author'));
|
||||
|
||||
$allowed = array('published', 'sticky', 'static', 'draft');
|
||||
|
||||
$key = isset($_POST['key']) ? Sanitize::html($_POST['key']) : false;
|
||||
$newType = isset($_POST['type']) ? Sanitize::html($_POST['type']) : false;
|
||||
|
||||
if (empty($key) || !$pages->exists($key)) {
|
||||
ajaxResponse(1, $L->g('Page not found.'));
|
||||
}
|
||||
|
||||
if (!in_array($newType, $allowed, true)) {
|
||||
ajaxResponse(1, $L->g('Target type is not allowed.'));
|
||||
}
|
||||
|
||||
$current = $pages->db[$key]['type'];
|
||||
if (!in_array($current, $allowed, true)) {
|
||||
ajaxResponse(1, $L->g('Current page type cannot be changed from this menu.'));
|
||||
}
|
||||
|
||||
if ($current === $newType) {
|
||||
ajaxResponse(0, $L->g('Page type unchanged.'), array(
|
||||
'key' => $key,
|
||||
'type' => $newType
|
||||
));
|
||||
}
|
||||
|
||||
// Authors can only change their own pages
|
||||
if (checkRole(array('author'), false)) {
|
||||
if ($pages->db[$key]['username'] !== $login->username()) {
|
||||
ajaxResponse(1, $L->g('Permission denied.'));
|
||||
}
|
||||
}
|
||||
|
||||
// Don't let a static parent be moved away from "static" while it has children;
|
||||
// otherwise the descendants get orphaned in the static tree (getStaticDB filters by type).
|
||||
if ($current === 'static' && $newType !== 'static') {
|
||||
try {
|
||||
$page = new Page($key);
|
||||
if (count($page->children()) > 0) {
|
||||
ajaxResponse(1, $L->g('Cannot change type while the page has children.'));
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
ajaxResponse(1, $L->g('Page not found.'));
|
||||
}
|
||||
}
|
||||
|
||||
if ($pages->setField($key, 'type', $newType) === false) {
|
||||
ajaxResponse(1, $L->g('Failed to update page type.'));
|
||||
}
|
||||
|
||||
ajaxResponse(0, $L->g('Page type updated.'), array(
|
||||
'key' => $key,
|
||||
'type' => $newType
|
||||
));
|
||||
@@ -0,0 +1,68 @@
|
||||
<?php defined('BLUDIT') or die('Bludit CMS.');
|
||||
header('Content-Type: application/json');
|
||||
|
||||
// $_GET
|
||||
// ----------------------------------------------------------------------------
|
||||
// (string) $_GET['query']
|
||||
$query = isset($_GET['query']) ? Text::lowercase($_GET['query']) : false;
|
||||
// ----------------------------------------------------------------------------
|
||||
if ($query===false) {
|
||||
ajaxResponse(1, 'Invalid query.');
|
||||
}
|
||||
|
||||
$result = array();
|
||||
|
||||
// MENU
|
||||
if (Text::stringContains(Text::lowercase($L->g('New content')), $query)) {
|
||||
$tmp = array('disabled'=>true, 'icon'=>'plus-circle', 'type'=>'menu');
|
||||
$tmp['text'] = $L->g('New content');
|
||||
$tmp['url'] = HTML_PATH_ADMIN_ROOT.'new-content';
|
||||
array_push($result, $tmp);
|
||||
}
|
||||
if (Text::stringContains(Text::lowercase($L->g('New category')), $query)) {
|
||||
$tmp = array('disabled'=>true, 'icon'=>'tag', 'type'=>'menu');
|
||||
$tmp['text'] = $L->g('New category');
|
||||
$tmp['url'] = HTML_PATH_ADMIN_ROOT.'new-category';
|
||||
array_push($result, $tmp);
|
||||
}
|
||||
if (Text::stringContains(Text::lowercase($L->g('New user')), $query)) {
|
||||
$tmp = array('disabled'=>true, 'icon'=>'user', 'type'=>'menu');
|
||||
$tmp['text'] = $L->g('New user');
|
||||
$tmp['url'] = HTML_PATH_ADMIN_ROOT.'new-user';
|
||||
array_push($result, $tmp);
|
||||
}
|
||||
if (Text::stringContains(Text::lowercase($L->g('Categories')), $query)) {
|
||||
$tmp = array('disabled'=>true, 'icon'=>'tags', 'type'=>'menu');
|
||||
$tmp['text'] = $L->g('Categories');
|
||||
$tmp['url'] = HTML_PATH_ADMIN_ROOT.'categories';
|
||||
array_push($result, $tmp);
|
||||
}
|
||||
if (Text::stringContains(Text::lowercase($L->g('Users')), $query)) {
|
||||
$tmp = array('disabled'=>true, 'icon'=>'users', 'type'=>'menu');
|
||||
$tmp['text'] = $L->g('Users');
|
||||
$tmp['url'] = HTML_PATH_ADMIN_ROOT.'users';
|
||||
array_push($result, $tmp);
|
||||
}
|
||||
|
||||
|
||||
// PAGES
|
||||
$pagesKey = $pages->getDB();
|
||||
foreach ($pagesKey as $pageKey) {
|
||||
try {
|
||||
$page = new Page($pageKey);
|
||||
$lowerTitle = Text::lowercase($page->title());
|
||||
if (Text::stringContains($lowerTitle, $query)) {
|
||||
$tmp = array('disabled'=>true);
|
||||
$tmp['id'] = $page->key();
|
||||
$tmp['text'] = $page->title();
|
||||
$tmp['type'] = $page->type();
|
||||
array_push($result, $tmp);
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
// continue
|
||||
}
|
||||
}
|
||||
|
||||
exit (json_encode(array('results'=>$result)));
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php defined('BLUDIT') or die('Bludit CMS.');
|
||||
header('Content-Type: application/json');
|
||||
|
||||
/*
|
||||
| Search for pages that have in the title the string $query and returns the array of pages
|
||||
|
|
||||
| @_GET['published'] boolean True to search in published database
|
||||
| @_GET['static'] boolean True to search in static database
|
||||
| @_GET['sticky'] boolean True to search in sticky database
|
||||
| @_GET['scheduled'] boolean True to search in scheduled database
|
||||
| @_GET['draft'] boolean True to search in draft database
|
||||
| @_GET['query'] string Text to search in the title
|
||||
|
|
||||
| @return array
|
||||
*/
|
||||
|
||||
// $_GET
|
||||
// ----------------------------------------------------------------------------
|
||||
$published = empty($_GET['published']) ? false:true;
|
||||
$static = empty($_GET['static']) ? false:true;
|
||||
$sticky = empty($_GET['sticky']) ? false:true;
|
||||
$scheduled = empty($_GET['scheduled']) ? false:true;
|
||||
$draft = empty($_GET['draft']) ? false:true;
|
||||
$query = isset($_GET['query']) ? Text::lowercase($_GET['query']) : false;
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
if ($query===false) {
|
||||
ajaxResponse(1, 'Invalid query.');
|
||||
}
|
||||
|
||||
$pageNumber = 1;
|
||||
$numberOfItems = -1;
|
||||
$pagesKey = $pages->getList($pageNumber, $numberOfItems, $published, $static, $sticky, $draft, $scheduled);
|
||||
$tmp = array();
|
||||
foreach ($pagesKey as $pageKey) {
|
||||
try {
|
||||
$page = new Page($pageKey);
|
||||
$lowerTitle = Text::lowercase($page->title());
|
||||
if (Text::stringContains($lowerTitle, $query)) {
|
||||
$tmp[$page->key()] = $page->json(true);
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
// continue
|
||||
}
|
||||
}
|
||||
|
||||
exit (json_encode($tmp));
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,65 @@
|
||||
<?php defined('BLUDIT') or die('Bludit CMS.');
|
||||
header('Content-Type: application/json');
|
||||
|
||||
/*
|
||||
| Delete an image from a particular page
|
||||
|
|
||||
| @_POST['filename'] string Name of the file to delete
|
||||
| @_POST['uuid'] string Page UUID
|
||||
|
|
||||
| @return array
|
||||
*/
|
||||
|
||||
// $_POST
|
||||
// ----------------------------------------------------------------------------
|
||||
$filename = isset($_POST['filename']) ? $_POST['filename'] : false;
|
||||
$uuid = empty($_POST['uuid']) ? false : $_POST['uuid'];
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
if ($filename===false) {
|
||||
ajaxResponse(1, 'The filename is empty.');
|
||||
}
|
||||
|
||||
if ($uuid && IMAGE_RESTRICT) {
|
||||
if (Text::stringContains($uuid, DS, false)) {
|
||||
ajaxResponse(1, 'Invalid uuid.');
|
||||
}
|
||||
$imagePath = PATH_UPLOADS_PAGES.$uuid.DS;
|
||||
$thumbnailPath = PATH_UPLOADS_PAGES.$uuid.DS.'thumbnails'.DS;
|
||||
} else {
|
||||
$imagePath = PATH_UPLOADS;
|
||||
$thumbnailPath = PATH_UPLOADS_THUMBNAILS;
|
||||
}
|
||||
|
||||
// Delete the original
|
||||
if (Sanitize::pathFile($imagePath.$filename)) {
|
||||
Filesystem::rmfile($imagePath.$filename);
|
||||
}
|
||||
|
||||
// Delete the thumbnail. Exact-name match is the fast path (new uploads have
|
||||
// matching extensions). If no exact match, fall back to any allowed-extension
|
||||
// match on the basename — this recovers legacy pairs where thumbnails were
|
||||
// forced to .jpg while the original kept its real extension. Before deleting
|
||||
// a mismatched candidate, verify no other original owns that extension, to
|
||||
// avoid taking out an unrelated image's thumbnail.
|
||||
if (Sanitize::pathFile($thumbnailPath.$filename) && is_file($thumbnailPath.$filename)) {
|
||||
Filesystem::rmfile($thumbnailPath.$filename);
|
||||
} else {
|
||||
$base = pathinfo($filename, PATHINFO_FILENAME);
|
||||
foreach ($GLOBALS['ALLOWED_IMG_EXTENSION'] as $ext) {
|
||||
$candidate = $base.'.'.$ext;
|
||||
if ($candidate === $filename) {
|
||||
continue;
|
||||
}
|
||||
if (is_file($imagePath.$candidate)) {
|
||||
continue;
|
||||
}
|
||||
if (Sanitize::pathFile($thumbnailPath.$candidate) && is_file($thumbnailPath.$candidate)) {
|
||||
Filesystem::rmfile($thumbnailPath.$candidate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ajaxResponse(0, 'Image deleted.');
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php defined('BLUDIT') or die('Bludit CMS.');
|
||||
header('Content-Type: application/json');
|
||||
|
||||
/*
|
||||
| Generate a slug text for the URL
|
||||
|
|
||||
| @_POST['text'] string The text from where is generated the slug
|
||||
| @_POST['parentKey'] string The parent key if the page has one
|
||||
| @_POST['currentKey'] string The current page key
|
||||
|
|
||||
| @return array
|
||||
*/
|
||||
|
||||
// $_POST
|
||||
// ----------------------------------------------------------------------------
|
||||
$text = isset($_POST['text']) ? $_POST['text'] : '';
|
||||
$parent = isset($_POST['parentKey']) ? $_POST['parentKey'] : '';
|
||||
$oldKey = isset($_POST['currentKey']) ? $_POST['currentKey'] : '';
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
$slug = $pages->generateKey($text, $parent, $returnSlug=true, $oldKey);
|
||||
|
||||
ajaxResponse(0, 'Slug generated.', array(
|
||||
'slug'=>$slug
|
||||
));
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php defined('BLUDIT') or die('Bludit CMS.');
|
||||
header('Content-Type: application/json');
|
||||
|
||||
/*
|
||||
| Returns a list of pages and the title contains the query string
|
||||
| The returned list have published, sticky and statics pages
|
||||
|
|
||||
| @_POST['query'] string The string to search in the title of the pages
|
||||
|
|
||||
| @return array
|
||||
*/
|
||||
|
||||
// $_GET
|
||||
// ----------------------------------------------------------------------------
|
||||
// (string) $_GET['query']
|
||||
$query = isset($_GET['query']) ? Text::lowercase($_GET['query']) : false;
|
||||
// (boolean) $_GET['checkIsParent']
|
||||
$checkIsParent = empty($_GET['checkIsParent']) ? false : true;
|
||||
// ----------------------------------------------------------------------------
|
||||
if ($query===false) {
|
||||
ajaxResponse(1, 'Invalid query.');
|
||||
}
|
||||
|
||||
$result = array();
|
||||
$pagesKey = $pages->getDB();
|
||||
foreach ($pagesKey as $pageKey) {
|
||||
try {
|
||||
$page = new Page($pageKey);
|
||||
if ($page->isParent() || !$checkIsParent) {
|
||||
// Check page status
|
||||
if ($page->published() || $page->sticky() || $page->isStatic()) {
|
||||
// Check if the query contains in the title
|
||||
$lowerTitle = Text::lowercase($page->title());
|
||||
if (Text::stringContains($lowerTitle, $query)) {
|
||||
$tmp = array('disabled'=>false);
|
||||
$tmp['id'] = $page->key();
|
||||
$tmp['text'] = $page->title();
|
||||
$tmp['type'] = $page->type();
|
||||
array_push($result, $tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
// continue
|
||||
}
|
||||
}
|
||||
|
||||
exit (json_encode(array('results'=>$result)));
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,60 @@
|
||||
<?php defined('BLUDIT') or die('Bludit CMS.');
|
||||
header('Content-Type: application/json');
|
||||
|
||||
/*
|
||||
| Returns a list of images from a particular page
|
||||
|
|
||||
| @_POST['pageNumber'] int Page number for the paginator
|
||||
| @_POST['path'] string Pre-defined name for the directory to read, its pre-defined to avoid security issues
|
||||
| @_POST['uuid'] string Page UUID
|
||||
|
|
||||
| @return array Each file is an object with 'filename' (original) and
|
||||
| 'thumbnail' (resolved preview filename — may differ from
|
||||
| the original for legacy pairs or fall back to it when no
|
||||
| thumbnail exists).
|
||||
*/
|
||||
|
||||
// $_POST
|
||||
// ----------------------------------------------------------------------------
|
||||
// $_POST['pageNumber'] > 0
|
||||
$pageNumber = empty($_POST['pageNumber']) ? 1 : (int)$_POST['pageNumber'];
|
||||
$pageNumber = $pageNumber - 1;
|
||||
|
||||
$path = empty($_POST['path']) ? false : $_POST['path'];
|
||||
$uuid = empty($_POST['uuid']) ? false : $_POST['uuid'];
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// The only accepted value is kept for backward-compat with clients that
|
||||
// preserve the old contract; the server now scans originals regardless.
|
||||
if ($path !== 'thumbnails') {
|
||||
ajaxResponse(1, 'Invalid path.');
|
||||
}
|
||||
|
||||
// Resolve the originals and thumbnails directories
|
||||
if ($uuid && IMAGE_RESTRICT) {
|
||||
if (Text::stringContains($uuid, DS, false)) {
|
||||
ajaxResponse(1, 'Invalid uuid.');
|
||||
}
|
||||
$imagePath = PATH_UPLOADS_PAGES.$uuid.DS;
|
||||
$thumbnailPath = PATH_UPLOADS_PAGES.$uuid.DS.'thumbnails'.DS;
|
||||
} else {
|
||||
$imagePath = PATH_UPLOADS;
|
||||
$thumbnailPath = PATH_UPLOADS_THUMBNAILS;
|
||||
}
|
||||
|
||||
// Scan originals and pair each with its matching thumbnail
|
||||
$listOfFilesByPage = mediaManagerListImages($imagePath, $thumbnailPath, MEDIA_MANAGER_NUMBER_OF_FILES);
|
||||
|
||||
if (isset($listOfFilesByPage[$pageNumber])) {
|
||||
ajaxResponse(0, 'List of files and number of chunks.', array(
|
||||
'numberOfPages'=>count($listOfFilesByPage),
|
||||
'files'=>$listOfFilesByPage[$pageNumber]
|
||||
));
|
||||
}
|
||||
|
||||
ajaxResponse(0, 'List of files and number of chunks.', array(
|
||||
'numberOfPages'=>0,
|
||||
'files'=>array()
|
||||
));
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php defined('BLUDIT') or die('Bludit CMS.');
|
||||
header('Content-Type: application/json');
|
||||
|
||||
/*
|
||||
| Delete the site logo
|
||||
| This script delete the file and set and empty string in the database
|
||||
|
|
||||
| @return array
|
||||
*/
|
||||
|
||||
// Delete the file
|
||||
$logoFilename = $site->logo(false);
|
||||
if ($logoFilename) {
|
||||
Filesystem::rmfile(PATH_UPLOADS.$logoFilename);
|
||||
}
|
||||
|
||||
// Remove the logo from the database
|
||||
$site->set(array('logo'=>''));
|
||||
|
||||
ajaxResponse(0, 'Logo removed.');
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,81 @@
|
||||
<?php defined('BLUDIT') or die('Bludit CMS.');
|
||||
header('Content-Type: application/json');
|
||||
|
||||
/*
|
||||
| Upload site logo
|
||||
| The final filename is the site's name and the extension is the same as the file uploaded
|
||||
|
|
||||
| @_FILES['inputFile'] multipart/form-data File from form
|
||||
|
|
||||
| @return array
|
||||
*/
|
||||
|
||||
if (!isset($_FILES['inputFile'])) {
|
||||
ajaxResponse(1, 'Error trying to upload the site logo.');
|
||||
}
|
||||
|
||||
// Check path traversal on $filename
|
||||
if (Text::stringContains($_FILES['inputFile']['name'], DS, false)) {
|
||||
$message = 'Path traversal detected.';
|
||||
Log::set($message, LOG_TYPE_ERROR);
|
||||
ajaxResponse(1, $message);
|
||||
}
|
||||
|
||||
// Block dotfiles
|
||||
if (strpos($_FILES['inputFile']['name'], '.') === 0) {
|
||||
$message = 'File type not allowed.';
|
||||
Log::set($message, LOG_TYPE_ERROR);
|
||||
ajaxResponse(1, $message);
|
||||
}
|
||||
|
||||
// File extension
|
||||
$fileExtension = Filesystem::extension($_FILES['inputFile']['name']);
|
||||
$fileExtension = Text::lowercase($fileExtension);
|
||||
if (!in_array($fileExtension, $GLOBALS['ALLOWED_IMG_EXTENSION'])) {
|
||||
$message = $L->g('File type is not supported. Allowed types:') . ' ' . implode(', ', $GLOBALS['ALLOWED_IMG_EXTENSION']);
|
||||
Log::set($message, LOG_TYPE_ERROR);
|
||||
ajaxResponse(1, $message);
|
||||
}
|
||||
|
||||
// File MIME Type
|
||||
$fileMimeType = Filesystem::mimeType($_FILES['inputFile']['tmp_name']);
|
||||
if ($fileMimeType !== false) {
|
||||
if (!in_array($fileMimeType, $GLOBALS['ALLOWED_IMG_MIMETYPES'])) {
|
||||
$message = $L->g('File mime type is not supported. Allowed types:') . ' ' . implode(', ', $GLOBALS['ALLOWED_IMG_MIMETYPES']);
|
||||
Log::set($message, LOG_TYPE_ERROR);
|
||||
ajaxResponse(1, $message);
|
||||
}
|
||||
}
|
||||
|
||||
// Final filename
|
||||
$filename = 'logo.' . $fileExtension;
|
||||
if (Text::isNotEmpty($site->title())) {
|
||||
$sanitizedTitle = Text::removeSpecialCharacters($site->title(), '-');
|
||||
$sanitizedTitle = Text::removeQuotes($sanitizedTitle);
|
||||
$sanitizedTitle = Text::removeSpaces($sanitizedTitle, '-');
|
||||
$sanitizedTitle = trim($sanitizedTitle, '-');
|
||||
if (Text::isNotEmpty($sanitizedTitle)) {
|
||||
$filename = $sanitizedTitle . '.' . $fileExtension;
|
||||
}
|
||||
}
|
||||
|
||||
// Delete old image
|
||||
$oldFilename = $site->logo(false);
|
||||
if ($oldFilename) {
|
||||
Filesystem::rmfile(PATH_UPLOADS . $oldFilename);
|
||||
}
|
||||
|
||||
// Move from temporary directory to uploads
|
||||
Filesystem::mv($_FILES['inputFile']['tmp_name'], PATH_UPLOADS . $filename);
|
||||
|
||||
// Permissions
|
||||
chmod(PATH_UPLOADS . $filename, 0644);
|
||||
|
||||
// Store the filename in the database
|
||||
$site->set(array('logo' => $filename));
|
||||
|
||||
ajaxResponse(0, 'Image uploaded.', array(
|
||||
'filename' => $filename,
|
||||
'absoluteURL' => DOMAIN_UPLOADS . $filename,
|
||||
'absolutePath' => PATH_UPLOADS . $filename
|
||||
));
|
||||
@@ -0,0 +1,105 @@
|
||||
<?php defined('BLUDIT') or die('Bludit CMS.');
|
||||
header('Content-Type: application/json');
|
||||
|
||||
// $_POST
|
||||
// ----------------------------------------------------------------------------
|
||||
// (string) $_POST['username']
|
||||
$username = empty($_POST['username']) ? false : $_POST['username'];
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
if ($username===false) {
|
||||
ajaxResponse(1, 'Error in username.');
|
||||
}
|
||||
|
||||
if ( ($login->role()!='admin') && ($login->username()!=$username) ) {
|
||||
ajaxResponse(1, 'Error in username.');
|
||||
}
|
||||
|
||||
if (!isset($_FILES['profilePictureInputFile'])) {
|
||||
ajaxResponse(1, 'Error trying to upload the profile picture.');
|
||||
}
|
||||
|
||||
// Check path traversal
|
||||
if (Text::stringContains($username, DS, false)) {
|
||||
$message = 'Path traversal detected.';
|
||||
Log::set($message, LOG_TYPE_ERROR);
|
||||
ajaxResponse(1, $message);
|
||||
}
|
||||
|
||||
// Block dotfiles
|
||||
if (strpos($_FILES['profilePictureInputFile']['name'], '.') === 0) {
|
||||
$message = 'File type not allowed.';
|
||||
Log::set($message, LOG_TYPE_ERROR);
|
||||
ajaxResponse(1, $message);
|
||||
}
|
||||
|
||||
// Sanitize username for filename to prevent issues with special characters
|
||||
$sanitizedUsername = Text::removeSpecialCharacters($username, '-');
|
||||
$sanitizedUsername = Text::removeQuotes($sanitizedUsername);
|
||||
$sanitizedUsername = Text::removeSpaces($sanitizedUsername, '-');
|
||||
|
||||
// Check file extension
|
||||
$fileExtension = Filesystem::extension($_FILES['profilePictureInputFile']['name']);
|
||||
$fileExtension = Text::lowercase($fileExtension);
|
||||
if (!in_array($fileExtension, $GLOBALS['ALLOWED_IMG_EXTENSION']) ) {
|
||||
$message = $L->g('File type is not supported. Allowed types:').' '.implode(', ',$GLOBALS['ALLOWED_IMG_EXTENSION']);
|
||||
Log::set($message, LOG_TYPE_ERROR);
|
||||
ajaxResponse(1, $message);
|
||||
}
|
||||
|
||||
// Check file MIME Type
|
||||
$fileMimeType = Filesystem::mimeType($_FILES['profilePictureInputFile']['tmp_name']);
|
||||
if ($fileMimeType!==false) {
|
||||
if (!in_array($fileMimeType, $GLOBALS['ALLOWED_IMG_MIMETYPES'])) {
|
||||
$message = $L->g('File mime type is not supported. Allowed types:').' '.implode(', ',$GLOBALS['ALLOWED_IMG_MIMETYPES']);
|
||||
Log::set($message, LOG_TYPE_ERROR);
|
||||
ajaxResponse(1, $message);
|
||||
}
|
||||
}
|
||||
|
||||
// Tmp filename
|
||||
$tmpFilename = $sanitizedUsername.'.'.$fileExtension;
|
||||
|
||||
// Final filename
|
||||
$filename = $sanitizedUsername.'.png';
|
||||
|
||||
// Ensure Bludit tmp directory exists
|
||||
if (!Filesystem::directoryExists(PATH_TMP)) {
|
||||
if (!Filesystem::mkdir(PATH_TMP, true)) {
|
||||
$message = 'Temporary directory does not exist and cannot be created.';
|
||||
Log::set($message, LOG_TYPE_ERROR);
|
||||
ajaxResponse(1, $message);
|
||||
}
|
||||
}
|
||||
|
||||
// Move from temporary directory to uploads folder
|
||||
$moved = rename($_FILES['profilePictureInputFile']['tmp_name'], PATH_TMP.$tmpFilename);
|
||||
if (!$moved) {
|
||||
$message = 'Error moving uploaded file to temporary directory.';
|
||||
Log::set($message, LOG_TYPE_ERROR);
|
||||
ajaxResponse(1, $message);
|
||||
}
|
||||
|
||||
// Resize and convert to png
|
||||
$image = new Image();
|
||||
if ($image->setImage(PATH_TMP.$tmpFilename, PROFILE_IMG_WIDTH, PROFILE_IMG_HEIGHT, 'crop') === false) {
|
||||
Filesystem::rmfile(PATH_TMP.$tmpFilename);
|
||||
$message = 'Profile picture upload failed: GD cannot decode the image (unsupported format or corrupted file).';
|
||||
Log::set($message, LOG_TYPE_ERROR);
|
||||
ajaxResponse(1, $message);
|
||||
}
|
||||
$image->saveImage(PATH_UPLOADS_PROFILES.$filename, PROFILE_IMG_QUALITY, false, true);
|
||||
|
||||
// Delete temporary file
|
||||
Filesystem::rmfile(PATH_TMP.$tmpFilename);
|
||||
|
||||
// Permissions
|
||||
chmod(PATH_UPLOADS_PROFILES.$filename, 0644);
|
||||
|
||||
ajaxResponse(0, 'Image uploaded.', array(
|
||||
'filename'=>$filename,
|
||||
'absoluteURL'=>DOMAIN_UPLOADS_PROFILES.$filename,
|
||||
'absolutePath'=>PATH_UPLOADS_PROFILES.$filename
|
||||
));
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php defined('BLUDIT') or die('Bludit CMS.');
|
||||
header('Content-Type: application/json');
|
||||
|
||||
/*
|
||||
| Create/edit a page and save as draft
|
||||
| If the UUID already exists the page is updated
|
||||
|
|
||||
| @_POST['title'] string Page title
|
||||
| @_POST['content'] string Page content
|
||||
| @_POST['uuid'] string Page uuid
|
||||
| @_POST['uuid'] string Page type, by default is draft
|
||||
|
|
||||
| @return array
|
||||
*/
|
||||
|
||||
// $_POST
|
||||
// ----------------------------------------------------------------------------
|
||||
$title = isset($_POST['title']) ? $_POST['title'] : false;
|
||||
$content = isset($_POST['content']) ? $_POST['content'] : false;
|
||||
$uuid = isset($_POST['uuid']) ? $_POST['uuid'] : false;
|
||||
$type = isset($_POST['type']) ? $_POST['type'] : 'draft';
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// Check UUID
|
||||
if (empty($uuid)) {
|
||||
ajaxResponse(1, 'Save as draft fail. UUID not defined.');
|
||||
}
|
||||
|
||||
$page = array(
|
||||
'uuid'=>$uuid,
|
||||
'key'=>$uuid,
|
||||
'slug'=>$uuid,
|
||||
'title'=>$title,
|
||||
'content'=>$content,
|
||||
'type'=>$type
|
||||
);
|
||||
|
||||
// Get the page key by the UUID
|
||||
$pageKey = $pages->getByUUID($uuid);
|
||||
|
||||
// if pageKey is empty means the page doesn't exist
|
||||
if (empty($pageKey)) {
|
||||
createPage($page);
|
||||
} else {
|
||||
editPage($page);
|
||||
}
|
||||
|
||||
ajaxResponse(0, 'Save as draft successfully.', array(
|
||||
'uuid'=>$uuid
|
||||
));
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,127 @@
|
||||
<?php defined('BLUDIT') or die('Bludit CMS.');
|
||||
header('Content-Type: application/json');
|
||||
|
||||
/*
|
||||
| Upload an image to a particular page
|
||||
|
|
||||
| @_POST['uuid'] string Page uuid
|
||||
|
|
||||
| @return array
|
||||
*/
|
||||
|
||||
// $_POST
|
||||
// ----------------------------------------------------------------------------
|
||||
$uuid = empty($_POST['uuid']) ? false : $_POST['uuid'];
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// Check path traversal on $uuid
|
||||
if ($uuid) {
|
||||
if (Text::stringContains($uuid, DS, false)) {
|
||||
$message = 'Path traversal detected.';
|
||||
Log::set($message, LOG_TYPE_ERROR);
|
||||
ajaxResponse(1, $message);
|
||||
}
|
||||
}
|
||||
|
||||
// Set upload directory
|
||||
if ($uuid && IMAGE_RESTRICT) {
|
||||
$imageDirectory = PATH_UPLOADS_PAGES . $uuid . DS;
|
||||
$thumbnailDirectory = $imageDirectory . 'thumbnails' . DS;
|
||||
if (!Filesystem::directoryExists($thumbnailDirectory)) {
|
||||
Filesystem::mkdir($thumbnailDirectory, true);
|
||||
}
|
||||
} else {
|
||||
$imageDirectory = PATH_UPLOADS;
|
||||
$thumbnailDirectory = PATH_UPLOADS_THUMBNAILS;
|
||||
}
|
||||
|
||||
$images = array();
|
||||
foreach ($_FILES['images']['name'] as $uuid => $filename) {
|
||||
// Check for errors
|
||||
if ($_FILES['images']['error'][$uuid] != 0) {
|
||||
$message = $L->g('Maximum load file size allowed:') . ' ' . ini_get('upload_max_filesize');
|
||||
Log::set($message, LOG_TYPE_ERROR);
|
||||
ajaxResponse(1, $message);
|
||||
}
|
||||
|
||||
// Convert URL characters such as spaces or quotes to characters
|
||||
$filename = urldecode($filename);
|
||||
|
||||
// Sanitize filename to prevent issues with special characters
|
||||
$filenameWithoutExt = Filesystem::filename($filename);
|
||||
$filenameWithoutExt = Text::removeSpecialCharacters($filenameWithoutExt, '-');
|
||||
$filenameWithoutExt = Text::removeQuotes($filenameWithoutExt);
|
||||
$filenameWithoutExt = Text::removeSpaces($filenameWithoutExt, '-');
|
||||
$fileExtension = Filesystem::extension($filename);
|
||||
$filename = $filenameWithoutExt . '.' . $fileExtension;
|
||||
|
||||
// Block dotfiles
|
||||
if (strpos($filename, '.') === 0) {
|
||||
$message = 'File type not allowed.';
|
||||
Log::set($message, LOG_TYPE_ERROR);
|
||||
ajaxResponse(1, $message);
|
||||
}
|
||||
|
||||
// Check path traversal on $filename
|
||||
if (Text::stringContains($filename, DS, false)) {
|
||||
$message = 'Path traversal detected.';
|
||||
Log::set($message, LOG_TYPE_ERROR);
|
||||
ajaxResponse(1, $message);
|
||||
}
|
||||
|
||||
// Check file extension
|
||||
$fileExtension = Filesystem::extension($filename);
|
||||
$fileExtension = Text::lowercase($fileExtension);
|
||||
if (!in_array($fileExtension, $GLOBALS['ALLOWED_IMG_EXTENSION'])) {
|
||||
$message = $L->g('File type is not supported. Allowed types:') . ' ' . implode(', ', $GLOBALS['ALLOWED_IMG_EXTENSION']);
|
||||
Log::set($message, LOG_TYPE_ERROR);
|
||||
ajaxResponse(1, $message);
|
||||
}
|
||||
|
||||
// Check file MIME Type
|
||||
$fileMimeType = Filesystem::mimeType($_FILES['images']['tmp_name'][$uuid]);
|
||||
if ($fileMimeType === false) {
|
||||
$message = $L->g('File mime type is not supported. Allowed types:') . ' ' . implode(', ', $GLOBALS['ALLOWED_IMG_MIMETYPES']);
|
||||
Log::set($message, LOG_TYPE_ERROR);
|
||||
ajaxResponse(1, $message);
|
||||
}
|
||||
if (!in_array($fileMimeType, $GLOBALS['ALLOWED_IMG_MIMETYPES'])) {
|
||||
$message = $L->g('File mime type is not supported. Allowed types:') . ' ' . implode(', ', $GLOBALS['ALLOWED_IMG_MIMETYPES']);
|
||||
Log::set($message, LOG_TYPE_ERROR);
|
||||
ajaxResponse(1, $message);
|
||||
}
|
||||
|
||||
// Ensure Bludit tmp directory exists
|
||||
if (!Filesystem::directoryExists(PATH_TMP)) {
|
||||
if (!Filesystem::mkdir(PATH_TMP, true)) {
|
||||
$message = 'Temporary directory does not exist and cannot be created.';
|
||||
Log::set($message, LOG_TYPE_ERROR);
|
||||
ajaxResponse(1, $message);
|
||||
}
|
||||
}
|
||||
|
||||
// Move from PHP tmp file to Bludit tmp directory
|
||||
$moved = Filesystem::mv($_FILES['images']['tmp_name'][$uuid], PATH_TMP . $filename);
|
||||
if (!$moved) {
|
||||
$message = 'Error moving uploaded file to temporary directory.';
|
||||
Log::set($message, LOG_TYPE_ERROR);
|
||||
ajaxResponse(1, $message);
|
||||
}
|
||||
|
||||
// Transform the image and generate the thumbnail
|
||||
$image = transformImage(PATH_TMP . $filename, $imageDirectory, $thumbnailDirectory);
|
||||
|
||||
if ($image) {
|
||||
chmod($image, 0644);
|
||||
$filename = Filesystem::filename($image);
|
||||
array_push($images, $filename);
|
||||
} else {
|
||||
$message = 'Error after transformImage() function.';
|
||||
Log::set($message, LOG_TYPE_ERROR);
|
||||
ajaxResponse(1, $message);
|
||||
}
|
||||
}
|
||||
|
||||
ajaxResponse(0, 'Images uploaded.', array(
|
||||
'images' => $images
|
||||
));
|
||||
Reference in New Issue
Block a user