Joomla 3-4-5-x getLimitBox() - Длина списка элементов

archive view archive save

joomla-code.jpg getLimitBox() - Creates a dropdown box for selecting how many records to show per page. Создает список для выбора, сколько записей для показывать на странице.

Но есть у этого списка древнейший сука недостаток, - в нём присутствует неудаляемый вариант отображения всех записей (All)!

Теперь прикинем, что у нас есть сайт с числом записей в 50 000 и более, скажем 500 000+, отображая которые может не только сервер усратца, но также браузер и сам юзер ожидающий вывода всех элементов.

  1. Override getLimitBox()
  2. Длина списка элементов
  3. Костыли
    1. Костыль №1 Модификация _REQUEST
    2. Костыль №2 Скрыть в настройках
    3. Костыль №3 preg_replace
    4. Другие варианты костылей
  4. Холивар
  5. Финита

Override getLimitBox()

Печаль заключается в том, что эта «фича» по-факту дырка для ДДОС-атаки не поддаётся удалению путём переопределения исходного файла и жестко закодирована в:

  • /libraries/src/Pagination/Pagination.php
  • /libraries/src/Form/Field/LimitboxField.php

На всяк случай создана «ХолиВар» на github

Где не долго думая камарад с ником «brianteeman» поспешил уведомить нас, что мы дебилы и не в тот код смотрим, ок дружище.., - но всё же ты не предложил ничего дельного и вопрос «how to override him and remove JALL» остался открытым:

brianteeman commented

You are looking at the wrong code.

You should be looking at the code for the limitboxfield in libraries\src\Form\Field

very nice, but how to override him and remove JALL?

Дебилы ли мы и не в тот ли код смотрим (оч. даже может быть), но заглянув в /components/com_tags/tmpl/tags/default_items.php, который поддаётся переопределению в текущем шаблоне, мы видим:

<?php if ($this->params->get('show_pagination_limit')) : ?>
    <div class="btn-group float-end">
        <label for="limit" class="visually-hidden">
            <?php echo Text::_('JGLOBAL_DISPLAY_NUM'); ?>
        </label>
        <?php echo $this->pagination->getLimitBox(); ?>
    </div>
<?php endif; ?>

Что, коробку со списком лимитов делает основная функция getLimitBox(), в файле /libraries/src/Pagination/Pagination.php:

public function getLimitBox()
{
    $limits = [];
 
    // Make the option list.
    for ($i = 5; $i <= 30; $i += 5) {
        $limits[] = HTMLHelper::_('select.option', "$i");
    }
 
    $limits[] = HTMLHelper::_('select.option', '50', Text::_('J50'));
    $limits[] = HTMLHelper::_('select.option', '100', Text::_('J100'));
    //$limits[] = HTMLHelper::_('select.option', '0', Text::_('JALL'));
    ...
}

Закомментировав строку с текстовой константой JALL, вариант отображения всех записей (All) исчезает из списка.

Длина списка элементов

Система - Общие настройки - Сайт предлагает Длина списка элементов начиная от 5 до 500 ( [5, 10, 15, 20, 25, 30, 50, 100, 200, 500] ), по-умолчанию начальный лимит списка 20 и прописан в /configuration.php в переменной public $list_limit = 20;

Вариант же отображения всех записей (All) к списку добавляется как-то без ведома пользователя и не поддаётся никакой настройке в шаблонах модулей, плагинов и/или компонентов.

При наличии неконтролируемой возможности вывода всех записей пропадает всякий смысл в любых лимитах (от 5 до 500 в административной части, от 5 до 100 на фронтенде).

Хотя, там гамно вопрос, и незначительно изменив логику кода движка можно же в настройки Система - Общие настройки - Сайт сразу же под параметром Длина списка элементов добавить дополнительную кнопку/переключатель Разрешить показывать все и варианты Да/Нет.

В идеале же сделать настройку диапазона min -> max (минимальный/максимальный) или start -> max (начальный/максимальный) - с той разницей, что второй вариант устанавливал бы начальный лимит (например 20) разрешая все меньшие значения (5, 10, 15), а не жесткий минимальный, как в первом случае.

Главное, мы хоть с кем-то пришли к взаимному пониманию, что такой переключатель нужная и полезная фича:

chmst added the Feature label

Thanks for providing this suggestion. I never thought about that but if your admins use the "All" option on a really huge Data base, it can indeed be an issue. We keep this as a feature request.

Костыли

Вопрос в другом, Как же быть? Пока фича Разрешить показывать все в разработке...

Ответ очевиден: Консолидироваться можно вдвоём, по-вечерам, и на костылях. © Х/Ф Замысел 2019 (Донфильм)

На выбор есть пара-тройка вариантов костылей...

Костыль №1 Модификация _REQUEST

Наверное самый простой и эффективный из костылей - это фильтрация и модификация запроса перед началом его обработки движком.

В административной части лимит на число страниц отправляется в массив $_POST['list']['limit'].

На фронтенде значение помещается в массив $_POST['limit'].

Все значения лимитов отправляются методом POST, присутствуют в $_POST и $_REQUEST, но на всякий пожарный проверим и метод GET.

Копируем:

  • cp /includes/defines.php -> /defines.php
  • cp /administrator/includes/defines.php -> /administrator/defines.php

В начале файла /defines.php и /administrator/defines.php вставляем:

// /administrator/defines.php
// FEATURE-CRUTCH #1 for drop JALL getLimitBox()
// https://github.com/joomla/joomla-cms/issues/41380
// https://itmag.pro/programming/cms/joomla-getlimitbox
if ( isset($_REQUEST['list']['limit']) && intval($_REQUEST['list']['limit']) == 0
      || @$_REQUEST['list']['limit'] > 100 ) {
  $_REQUEST['list']['limit'] = 20;
  if ( isset($_POST['list']['limit']) ) {
    $_POST['list']['limit'] = 20;
  }
}
 
// /defines.php
// FEATURE-CRUTCH #1 for drop JALL getLimitBox()
// https://github.com/joomla/joomla-cms/issues/41380
// https://itmag.pro/programming/cms/joomla-getlimitbox
if ( isset($_REQUEST['limit']) && intval($_REQUEST['limit']) == 0
      || @$_REQUEST['limit'] > 100 ) {
  $_REQUEST['limit'] = 20;
  if ( isset($_POST['limit']) ) {
    $_POST['limit'] = 20;
  }
  if ( isset($_GET['limit']) ) {
    $_GET['limit'] = 20;
  }
}

Там мы предотвращаем / запрещаем не только отображение всех записей All (limit=0), но и контролируем предельно максимальное число отображаемых страниц (['limit'] > 100) - ведь сам движок не делает этого и теоретически атакующий может сформировать прямой POST запрос со значением limit не только равное 0, но и явно превышающие 100 или 500!

Таким образом данная дырка с лимитом элегантно затыкается, а внесённые в /defines.php изменения не будут утеряны после очередного обновления.

Только в /defines.php нужно добавить _JDEFINES и JPATH_BASE, иначе костыль поломается!

// FEATURE for drop JALL getLimitBox()
//...
 
# Define '_JDEFINES' and 'JPATH_BASE' for prevent load '/includes/defines.php'
define('_JDEFINES', 1);
define('JPATH_BASE', __DIR__);
 
// Global definitions
$parts = explode(DIRECTORY_SEPARATOR, JPATH_BASE);

Костыль №2 Скрыть в настройках

Поле выбора количества элементов на странице выбираем Скрыть в настройках отдельного компонента, например Компоненты - Теги - Настройки вкладка Макет.

Система - Общие настройки - Сайт параметр Длина списка элементов устанавливаем в максимально приемлемые для возможностей нашего сервера/хостинга.

Костыль №3 preg_replace

Перехватывать в переменную результат вывода pagination->getLimitBox(); ?> и потом программно выпиливать оттудова <option value="0">All</option>, например:

<?php if ($this->params->get('show_pagination_limit')) : ?>
    <div class="btn-group float-end">
        <label for="limit" class="visually-hidden">
            <?php echo Text::_('JGLOBAL_DISPLAY_NUM'); ?>
        </label>
        <?php         //echo $this->pagination->getLimitBox();
        echo preg_replace('/<option value="0">(\w*)<\/option>/smui', '', $this->pagination->getLimitBox());
        ?>
    </div>
<?php endif; ?>

Другие варианты костылей

Да справедливости ради, и для полноты картины мира...

How to override getLimitBox() function in joomla 4.3? · Issue #41380 · joomla/joomla-cms

Gratia-Mira

I agree! Certain Joomla extensions have recognised this problem and let the request "ALL" run into the void. Not such a great way either.

But there is a very simple way to hide this with jQuery. Simply insert this code at the end of the body as a workaround. "id" and "option" must of course be adapted.

<script>
$('select[id="limit"] option[value="0"]').remove();
</script>

ReLater

One can also override JLayout layouts\joomla\form\field\list.php by adding a condition like (at least in Joomla 5)

if ($name === 'list[limit]')
{
 foreach($options as $key => $option)
 {
  if ($option->value == 0)
  {
    unset($options[$key]);
  }
 }
}

Другие варианты по-смыслу ничем не отличаются от костылей №2-3 - просто скрывают опцию, но не защищают от прямых запросов.

Холивар

Попёрло быдло кверху.

В теме на гитхабе начали всплывать кучи спамеров пытающихся опорочить (обосрать) предложенное нами решение с фильтрацией параметров в _REQUEST:

@rdeutz commented Apr 27, 2024 •
https://github.com/joomla/joomla-cms/issues/41380#issuecomment-2080698282

We found crutch-feature for fix this hole for all whole site, and also tested - rewrite _REQUEST in defines.php, enjoy guys :)

Great idea to use user provided content without filtering, don't do that!

If you really can wait make a system plugin and try to change it onAfterRoute something.

И мол нужно create a plugin with the following function, где некий крендель @HLeithner предлагает налепить кучу говнокода чтобы убрать из списка элемент ALL.

На что был дан вполне приличный ответ:

itmagpro commented Apr 28, 2024
https://github.com/joomla/joomla-cms/issues/41380#issuecomment-2081521866

> rdeutz

Great idea to use user provided content without filtering, don't do that!

@rdeutz you understand what you talk? Explain to me, please, how we can "to use user provided content without filtering" when we only filtering and set need value in $_REQUEST['list']['limit'] parameter? Explain to me, please, - or dont spam here about nothing!

> HLeithner

DisableShowAll plugin...

very Nice! But, this just fake masquerade and not protect from direct requests! @HLeithner - you not enoug understand this issue.

_Originally posted by @itmagpro in https://github.com/joomla/joomla-cms/issues/41380#issuecomment-1971938836_

No need any plugins, [rewrite _REQUEST in defines.php] enoug elegance solution for fix this joomla bug! enjoy guys :)

_Originally posted by @itmagpro in https://github.com/joomla/joomla-cms/issues/41380#issuecomment-1974793812_

Где мы попросили чувака @rdeutz (какая свинячая отвратительная рожа) пояснить нам (аргументировать) почему нельзя так делать или прекратить спамить в теме, а кренделю @HLeithner сделано замечание о том, что простое скрытие элемента ALL не защищает от прямых запросов и он не внимательно ознакомлен с темой, что - согласитесь, не выходит за рамки приличия тех же опонентов!

Но, в ответ лишь пена со рта и никакой аргументации по-сути - мол: Твой голос на мамин совсем не похож! Ты голосом толстым фальшиво поёшь!... и мы вас будем заебанивать и всё такое прочее...:

@brianteeman commented 7 minutes ago
wow - some automated translators are either really bad or realy rude

---

@HLeithner commented 4 minutes ago
@itmagpro your tone is very rude, if you don't stop this insulting and start to communicate in a nice way with people trying to help you, will end in an temporary ban from this repo.

Разумеется, терпеливо проглатывать такое дерьмо мы не стали - патамушта... Ни одно тело в открытой теме нам так и не помогло в корне решить проблему, а единственно рабочий костыль был предложен нами!

Кроме того, тут над головами пули свистят и ракеты летают, а потому пугать нас какими-то там сраными банами на каком-то говнохабе!? Сами понимаете.., безперспективняк полнейший.

joomla-getlimitbox-holy-war.jpg

My tone is very nice and without empty words!

NO ONE BODY NOT HELPED ME HERE!!!

I HELPED BY ME SELF!

SO... - fuc.you all, spammers! Bye.

В итоге, критики-говнокодеры никакой аргументации так и не предоставили, все наши комментарии в теме были тупо This comment was marked as abuse. и стали доступны только для зарегистрированных на гитхабе, а нас типа заебанили (паработало падло) - Ай-я-яй.., КакоОое безобразие!

From: GitHub <[email protected]>
To: "itmag.pro" <[email protected]>
Subject: [GitHub] You have been blocked from joomla
Date: Sun, 28 Apr 2024 09:13:27 -0700
Reply-To: GitHub <[email protected]>

Hi itmag.pro,

A maintainer of the @joomla organization has blocked you because of a recent post.

For more information please see or https://docs.github.com/articles/github-community-guidelines.

Thanks,
The GitHub Team

Красавы, помогли пидарасы добрые люди. Ура товарищи! Пэрэмога!

Финита

Если кто получает от хостинг-провайдер регулярные извещения о превышениях лимитов на SQL-запросы или нагрузку CPU, то вполне возможно, что доступность отобразить все элементы/страницы сайта (его отдельных разделов) является одной из причин.

Упомянутые выше костыли №2 и №3 лишь маскируют, но не решаю проблему, и являются косметической «защитой от дурака».

Опытный же «долбо-стено-сверло-перфораторщик», знающий движок и как и куда сверлить-долбить, может:

  • попробовать в запросе к компоненту движка передать value="0";
  • по результатам зондирования написать bash-скрипт;
  • при наличии огромного числа выводимых элементов «задолбить» сайт/сервер/хостинг под плинтус.

Для сайтов с большим числом элементов/материалов просто необходима фича для запрета/разрешения value="0" на уровне ядра, чтобы getLimitBox() не принимала и не обрабатывала value="0" (Все/All), и - Костыль №1 Модификация _REQUEST пока единственно правильный, быстрый и РЕАЛЬНО РАБОЧИЙ вариант решения.

Данная ситуация из категории Пока никто не жаловался - мы стали первыми.

Это ж 18 лет движку, и до сих пор никто не жаловался - это десятками лет, никто не видит, не слышит и всем похеру, тупо жрут всё подряд, что дадут.

Есть ещё куча «дырок», особенно в головах людей, которых столетиями, а то и тысячелетиями никто не замечает, но.., - это уже совсем другая история.

Практика же в который раз доказала, что всё нужно делать самому ибо среди разрабов часто-густо много спамеров (хуэло-ворлдщиков) и просто тупых да рогатых...водителей камаза...они все давно переквалифицировались в артистов дизайнеров и программистов, побрили подмышки и аста-ла-виста!

Мышки плакали, кололись, но продолжали грызть кактус.


Об авторе
АдМинь БагоИскатель
АдМинь БагоИскатель ярый борец за безглючную работу любых механизмов и организмов во всей вселенной и потому пребывает в вечном поиске всяческих багов, а тот кто ищет как известно всегда находит. Когда что-то или кого-то вылечить не в состоянии, то со словами "Я в аду, а вы все черти" уходит в запой выйдя из которого снова берётся лечить неизлечимое.
Ещё статьи автора

Нет комментариев

Вы можете стать первым, кто добавит комментарий к этой записи.

Добавить комментарий

АХТУНГ! Все комменты гостей модерасятся модерастом.
  1. Мессаги исключительно рекламного содержания, либо содержащие только одни оценочные суждения типа "круто" ("отлично", "спасибо", "автор дебил" и т.п.) не публикуются;
  2. Злостным спамерам, пранкерам и прочей сетевой нечисти рекомендуем напрасно не тратить своего времени и удовлетворять свои больные фантазии на специализированных Интернет ресурсах!;
  3. Разумная обоснованная критика, замечания, дополнения приветствуются. Поля помеченные символом * обязательны к заполнению.


Защитный код
Обновить

Комментарии в блоге
Новое на форуме