diff --git a/addons/photoswipe/rx_photoswipe.js b/addons/photoswipe/rx_photoswipe.js
index dc06dc4be..d21fbabce 100644
--- a/addons/photoswipe/rx_photoswipe.js
+++ b/addons/photoswipe/rx_photoswipe.js
@@ -25,7 +25,7 @@ var initPhotoSwipeFromDOM = function(gallerySelector) {
// CSS selector for photoswipe items.
var ps_find_selector = 'img:not(' + ps_skip_elements + ps_skip_class + '), img' + ps_enroll_class;
- // parse slide data (url, title, size ...) from DOM elements
+ // parse slide data (url, title, size ...) from DOM elements
// (children of gallerySelector)
var parseThumbnailElements = function(el) {
var imgElements = $(el).find(ps_find_selector),
@@ -39,7 +39,7 @@ var initPhotoSwipeFromDOM = function(gallerySelector) {
imgEl = imgElements.get(i); // element
- // include only element nodes
+ // include only element nodes
if (imgEl.nodeType !== 1 || !imgEl.src || !$(imgEl).attr('data-pswp-pid')) {
continue;
}
@@ -56,11 +56,11 @@ var initPhotoSwipeFromDOM = function(gallerySelector) {
var ps_skip_alt_class = '.photoswipe-no-caption';
if(imgEl.alt && !$(imgEl).is(ps_skip_alt_class)) {
- item.title = imgEl.alt;
+ item.title = imgEl.alt;
}
if(imgEl.title && !$(imgEl).is(ps_skip_alt_class)) {
- item.title = imgEl.title;
+ item.title = imgEl.title;
}
item.el = imgEl; // save link to element for getThumbBoundsFn
@@ -87,7 +87,7 @@ var initPhotoSwipeFromDOM = function(gallerySelector) {
if(!clickedListItem) {
return;
}
-
+
e = e || window.event;
e.preventDefault ? e.preventDefault() : e.returnValue = false;
@@ -108,8 +108,8 @@ var initPhotoSwipeFromDOM = function(gallerySelector) {
}*/
for (var i = 0; i < numChildNodes; i++) {
- if(childNodes[i].nodeType !== 1 || !$(childNodes[i]).attr('data-pswp-pid')) {
- continue;
+ if(childNodes[i].nodeType !== 1 || !$(childNodes[i]).attr('data-pswp-pid')) {
+ continue;
}
if(childNodes[i] === clickedListItem) {
@@ -140,7 +140,7 @@ var initPhotoSwipeFromDOM = function(gallerySelector) {
if(!vars[i]) {
continue;
}
- var pair = vars[i].split('=');
+ var pair = vars[i].split('=');
if(pair.length < 2) {
continue;
}
@@ -172,7 +172,7 @@ var initPhotoSwipeFromDOM = function(gallerySelector) {
// See Options -> getThumbBoundsFn section of documentation for more info
var thumbnail = items[index].el,
pageYScroll = window.pageYOffset || document.documentElement.scrollTop,
- rect = thumbnail.getBoundingClientRect();
+ rect = thumbnail.getBoundingClientRect();
return {x:rect.left, y:rect.top + pageYScroll, w:rect.width};
},
@@ -191,7 +191,7 @@ var initPhotoSwipeFromDOM = function(gallerySelector) {
// PhotoSwipe opened from URL
if(fromURL) {
if(options.galleryPIDs) {
- // parse real index when custom PIDs are used
+ // parse real index when custom PIDs are used
// http://photoswipe.com/documentation/faq.html#custom-pid-in-url
for(var j = 0; j < items.length; j++) {
if(items[j].pid == index) {
@@ -232,6 +232,7 @@ var initPhotoSwipeFromDOM = function(gallerySelector) {
var regx_skip = /(?:(modules|addons|classes|common|layouts|libs|widgets|widgetstyles)\/)/i;
var regx_allow_i6pngfix = /(?:common\/tpl\/images\/blank\.gif$)/i;
+ var isMobile = String(navigator.userAgent).match(/mobile/i);
var galleryImgEls = $(galleryElements[i]).find(ps_find_selector);
for(var j = 0, jl = galleryImgEls.length; j < jl; j++) {
// skip components
@@ -240,6 +241,11 @@ var initPhotoSwipeFromDOM = function(gallerySelector) {
//$(galleryImgEls[j]).attr('data-pswp-uid', i+1);
$(galleryImgEls[j]).attr('data-pswp-pid', j+1);
+ // Fix stretching of image on mobile
+ if (isMobile) {
+ galleryImgEls[j].style.height = 'auto';
+ galleryImgEls[j].height = null;
+ }
}
}
diff --git a/classes/context/Context.class.php b/classes/context/Context.class.php
index 0a2eb1f35..0c9f71190 100644
--- a/classes/context/Context.class.php
+++ b/classes/context/Context.class.php
@@ -338,7 +338,11 @@ class Context
}
// start session
- if (\PHP_SAPI !== 'cli')
+ if (\PHP_SAPI === 'cli')
+ {
+ $_SESSION = [];
+ }
+ else
{
if (self::$_current_request->getRouteOption('enable_session'))
{
@@ -1214,7 +1218,7 @@ class Context
else
{
// Set HTTP_RAW_POST_DATA for third-party apps that look for it.
- if (!$_POST && !isset($GLOBALS['HTTP_RAW_POST_DATA']))
+ if (empty($_POST) && empty($_FILES) && !isset($GLOBALS['HTTP_RAW_POST_DATA']))
{
$GLOBALS['HTTP_RAW_POST_DATA'] = file_get_contents('php://input');
}
@@ -1230,7 +1234,7 @@ class Context
}
// Decide whether it's JSON or XMLRPC by looking at the first character of the POST data.
- if (!$_POST && !empty($GLOBALS['HTTP_RAW_POST_DATA']))
+ if (empty($_POST) && !empty($GLOBALS['HTTP_RAW_POST_DATA']))
{
self::$_instance->request_method = substr($GLOBALS['HTTP_RAW_POST_DATA'], 0, 1) === '<' ? 'XMLRPC' : 'JSON';
return;
@@ -1258,7 +1262,7 @@ class Context
}
// Set JSON and XMLRPC arguments.
- if(isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'POST' && !$_POST && !empty($GLOBALS['HTTP_RAW_POST_DATA']))
+ if(isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'POST' && empty($_POST) && !empty($GLOBALS['HTTP_RAW_POST_DATA']))
{
$params = array();
$request_method = self::getRequestMethod();
diff --git a/classes/display/HTMLDisplayHandler.php b/classes/display/HTMLDisplayHandler.php
index 4f9a09bce..609fe787a 100644
--- a/classes/display/HTMLDisplayHandler.php
+++ b/classes/display/HTMLDisplayHandler.php
@@ -151,13 +151,20 @@ class HTMLDisplayHandler
Context::loadFile(array($edited_layout_css, 'all', '', 100));
}
}
- if(!$layout_path)
+ if (!$layout_path)
{
$layout_path = './common/tpl';
}
- if(!$layout_file)
+ if (!$layout_file)
{
- $layout_file = 'default_layout';
+ if ($layout_path === './common/tpl')
+ {
+ $layout_file = 'default_layout';
+ }
+ else
+ {
+ $layout_file = 'layout';
+ }
}
$oTemplate = new Rhymix\Framework\Template;
diff --git a/classes/module/ModuleHandler.class.php b/classes/module/ModuleHandler.class.php
index 5b910d223..e0faee25e 100644
--- a/classes/module/ModuleHandler.class.php
+++ b/classes/module/ModuleHandler.class.php
@@ -151,7 +151,16 @@ class ModuleHandler extends Handler
$site_module_info->domain = Rhymix\Framework\URL::getCurrentDomain();
$site_module_info->is_default_domain = 'N';
$site_module_info->is_default_replaced = true;
+
+ // Reset context variables if the domain was replaced.
Context::set('site_module_info', $site_module_info);
+ Context::set('_default_url', null);
+ Context::set('request_uri', $current_url = Context::getRequestUri());
+ if ($query_string = http_build_query(Context::getCurrentRequest()->args))
+ {
+ $current_url .= '?' . $query_string;
+ }
+ Context::set('current_url', $current_url);
}
}
}
diff --git a/classes/page/PageHandler.class.php b/classes/page/PageHandler.class.php
index 82d45e97f..0a74fcd0f 100644
--- a/classes/page/PageHandler.class.php
+++ b/classes/page/PageHandler.class.php
@@ -44,24 +44,23 @@ class PageHandler extends Handler implements Iterator
$this->page_count = $page_count;
$this->point = 0;
- $first_page = $cur_page - (int) ($page_count / 2);
- if($first_page < 1)
+ if ($this->cur_page > $total_page)
{
- $first_page = 1;
+ $this->cur_page = $total_page;
+ }
+ if ($this->page_count > $total_page)
+ {
+ $this->page_count = $total_page;
}
- if($total_page > $page_count && $first_page + $page_count - 1 > $total_page)
+ $first_page = max(1, $this->cur_page - floor($this->page_count / 2));
+ if (($first_page + $this->page_count - 1) > $total_page)
{
- $first_page -= $first_page + $page_count - 1 - $total_page;
+ $first_page = max(1, $total_page - $this->page_count + 1);
}
$this->first_page = $first_page;
$this->last_page = $total_page;
-
- if($total_page < $this->page_count)
- {
- $this->page_count = $total_page;
- }
}
/**
diff --git a/common/framework/DB.php b/common/framework/DB.php
index b436ce9e8..0f30246e8 100644
--- a/common/framework/DB.php
+++ b/common/framework/DB.php
@@ -1126,17 +1126,17 @@ class DB
}
else
{
- $exceptions = [];
+ $exceptions = ['TABLE'];
}
// Add prefixes to all other table names in the query string.
- return preg_replace_callback('/\b((?:DELETE\s+)?FROM|JOIN|INTO|(?column as $column_info)
{
+ // Is this column generated?
+ $is_generated = strval($column_info['generated'] ?? '') !== '';
+ if ($is_generated)
+ {
+ $column = new DBTable\GeneratedColumn;
+ $column->generated = strtolower($column_info['generated']);
+ $column->is_stored = strtolower($column_info['stored'] ?? '');
+ $column->is_stored = $column->is_stored !== 'virtual' && toBool($column->is_stored);
+ }
+ else
+ {
+ $column = new DBTable\Column;
+ }
+
// Get the column name and type.
- $column = new DBTable\Column;
$column->name = strval($column_info['name']);
list($column->type, $column->xetype, $column->size) = self::getTypeAndSize(strval($column_info['type']), strval($column_info['size']));
diff --git a/common/framework/parsers/dbquery/VariableBase.php b/common/framework/parsers/dbquery/VariableBase.php
index 0c5f984dd..f4e29a0c5 100644
--- a/common/framework/parsers/dbquery/VariableBase.php
+++ b/common/framework/parsers/dbquery/VariableBase.php
@@ -398,7 +398,11 @@ class VariableBase
// Don't apply a filter if there is no variable.
$column = $this instanceof ColumnWrite ? $this->name : $this->column;
$filter = isset($this->filter) ? $this->filter : '';
- if (!is_array($value) && strval($value) === '')
+ if (is_object($value) && !method_exists($value, '__toString'))
+ {
+ throw new \Rhymix\Framework\Exceptions\QueryError('Variable ' . $this->var . ' for column ' . $column . ' is not stringable');
+ }
+ if (is_scalar($value) && strval($value) === '')
{
$filter = '';
}
diff --git a/common/framework/parsers/dbtable/GeneratedColumn.php b/common/framework/parsers/dbtable/GeneratedColumn.php
new file mode 100644
index 000000000..60a9726fb
--- /dev/null
+++ b/common/framework/parsers/dbtable/GeneratedColumn.php
@@ -0,0 +1,12 @@
+charset . ' COLLATE ' . $column->charset . '_general_ci';
}
}
+ if ($column instanceof GeneratedColumn)
+ {
+ $columndef .= ' GENERATED ' . strtoupper($column->generated ?: 'always');
+ $columndef .= ' AS (' . $column->default_value . ')';
+ if ($column->is_stored)
+ {
+ $columndef .= ' STORED';
+ }
+ }
+ else
+ {
+ if ($column->default_value !== null)
+ {
+ if (preg_match('/(?:int|float|double|decimal|number)/i', $column->type) && is_numeric($column->default_value))
+ {
+ $columndef .= ' DEFAULT ' . $column->default_value;
+ }
+ elseif (preg_match('/^\w+\(\)$/', $column->default_value))
+ {
+ $columndef .= ' DEFAULT ' . $column->default_value;
+ }
+ else
+ {
+ $columndef .= ' DEFAULT \'' . $column->default_value . '\'';
+ }
+ }
+ }
if ($column->not_null)
{
$columndef .= ' NOT NULL';
}
- if ($column->default_value !== null)
- {
- if (preg_match('/(?:int|float|double|decimal|number)/i', $column->type) && is_numeric($column->default_value))
- {
- $columndef .= ' DEFAULT ' . $column->default_value;
- }
- elseif (preg_match('/^\w+\(\)$/', $column->default_value))
- {
- $columndef .= ' DEFAULT ' . $column->default_value;
- }
- else
- {
- $columndef .= ' DEFAULT \'' . $column->default_value . '\'';
- }
- }
if ($column->auto_increment)
{
$columndef .= ' AUTO_INCREMENT';
}
+
$columns[] = $columndef;
}
diff --git a/common/functions.php b/common/functions.php
index 84b923681..2e2080687 100644
--- a/common/functions.php
+++ b/common/functions.php
@@ -671,7 +671,7 @@ function utf8_mbencode($str): string
$bytes = array(ord($m[0][0]), ord($m[0][1]), ord($m[0][2]), ord($m[0][3]));
$codepoint = ((0x07 & $bytes[0]) << 18) + ((0x3F & $bytes[1]) << 12) + ((0x3F & $bytes[2]) << 6) + (0x3F & $bytes[3]);
return '' . dechex($codepoint) . ';';
- }, (string)$str);
+ }, (string)$str) ?? '';
}
/**
@@ -686,11 +686,11 @@ function utf8_normalize_spaces($str, bool $multiline = false): string
{
if ($multiline)
{
- return preg_replace(['/((?!\x0A)[\pZ\pC])+/u', '/\x20*\x0A\x20*/'], [' ', "\n"], (string)$str);
+ return preg_replace(['/((?!\x0A)[\pZ\pC])+/u', '/\x20*\x0A\x20*/'], [' ', "\n"], (string)$str) ?? '';
}
else
{
- return preg_replace('/[\pZ\pC]+/u', ' ', (string)$str);
+ return preg_replace('/[\pZ\pC]+/u', ' ', (string)$str) ?? '';
}
}
diff --git a/common/js/plugins/jquery.fileupload/js/main.js b/common/js/plugins/jquery.fileupload/js/main.js
index 6d7be5095..40a94dba2 100644
--- a/common/js/plugins/jquery.fileupload/js/main.js
+++ b/common/js/plugins/jquery.fileupload/js/main.js
@@ -145,7 +145,7 @@
chunkfail: function(e, res) {
lastUploadTime = Date.now();
if (chunkStatus) {
- alert(window.xe.lang.msg_file_upload_error + " (Type 3)" + "
\n" + res.errorThrown + "
\n" + res.textStatus);
+ alert(window.xe.lang.msg_file_upload_error + " (Type 3)" + "\n" + res.errorThrown + "\n" + res.textStatus);
return chunkStatus = false;
}
},
@@ -169,7 +169,7 @@
result = jQuery.parseJSON(result);
}
if (!result) {
- alert(window.xe.lang.msg_file_upload_error + " (Type 5)" + "
\n" + res.response().result);
+ alert(window.xe.lang.msg_file_upload_error + " (Type 5)" + "\n" + res.response().result);
return false;
}
@@ -215,7 +215,7 @@
return false;
} else {
$container.data('editorStatus', null);
- alert(window.xe.lang.msg_file_upload_error + " (Type 6)" + "
\n" + res.response().result);
+ alert(window.xe.lang.msg_file_upload_error + " (Type 6)" + "\n" + res.response().result);
return false;
}
},
@@ -229,7 +229,7 @@
}
}, 1000);
if (chunkStatus) {
- alert(window.xe.lang.msg_file_upload_error + " (Type 7)" + "
\n" + res.errorThrown + "
\n" + res.textStatus);
+ alert(window.xe.lang.msg_file_upload_error + " (Type 7)" + "\n" + res.errorThrown + "\n" + res.textStatus);
return false;
}
},
diff --git a/common/scripts/cron.php b/common/scripts/cron.php
index 5d3ff146d..954d6a062 100644
--- a/common/scripts/cron.php
+++ b/common/scripts/cron.php
@@ -4,14 +4,18 @@
* This script runs the task queue.
*
* Unlike other scripts provided with Rhymix, it can be called
- * both on the command line and over the network.
+ * both on the CLI (through index.php) and over the network (directly).
*/
define('RXQUEUE_CRON', true);
// If called on the CLI, run additional checks.
if (PHP_SAPI === 'cli')
{
- require_once __DIR__ . '/common.php';
+ if (!defined('RX_VERSION'))
+ {
+ echo "Error: This script must not be called directly.\n";
+ exit(1);
+ }
}
else
{
diff --git a/modules/admin/admin.admin.model.php b/modules/admin/admin.admin.model.php
index cdaaed1dc..b45f9f457 100644
--- a/modules/admin/admin.admin.model.php
+++ b/modules/admin/admin.admin.model.php
@@ -56,11 +56,7 @@ class AdminAdminModel extends Admin
*/
public function getSiteAllList()
{
- if(Context::get('domain'))
- {
- $domain = Context::get('domain');
- }
- $siteList = $this->getAllSitesThatHaveModules($domain);
+ $siteList = $this->getAllSitesThatHaveModules(Context::get('domain'));
$this->add('site_list', $siteList);
}
diff --git a/modules/comment/comment.item.php b/modules/comment/comment.item.php
index a372bc029..30508fc69 100644
--- a/modules/comment/comment.item.php
+++ b/modules/comment/comment.item.php
@@ -466,10 +466,12 @@ class CommentItem extends BaseObject
$content = trim(utf8_normalize_spaces(html_entity_decode(strip_tags($content))));
if($strlen)
{
- $content = cut_str($content, $strlen, '...');
+ $content = escape(cut_str($content, $strlen, '...'), false);
+ }
+ else
+ {
+ $content = escape($content);
}
-
- $content = escape($content);
if ($content === '')
{
@@ -511,9 +513,12 @@ class CommentItem extends BaseObject
$content = trim(utf8_normalize_spaces(html_entity_decode(strip_tags($content))));
if($strlen)
{
- $content = cut_str($content, $strlen, '...');
+ return escape(cut_str($content, $strlen, '...'), false);
+ }
+ else
+ {
+ return escape($content);
}
- return escape($content);
}
/**
diff --git a/modules/document/document.item.php b/modules/document/document.item.php
index dcf90e8d7..1fdf94d8f 100644
--- a/modules/document/document.item.php
+++ b/modules/document/document.item.php
@@ -634,10 +634,12 @@ class DocumentItem extends BaseObject
$content = trim(utf8_normalize_spaces(html_entity_decode(strip_tags($content))));
if($strlen)
{
- $content = cut_str($content, $strlen, '...');
+ return escape(cut_str($content, $strlen, '...'), false);
+ }
+ else
+ {
+ return escape($content);
}
-
- return escape($content);
}
function getContentText($strlen = 0)
@@ -653,17 +655,22 @@ class DocumentItem extends BaseObject
}
$content = preg_replace('!(