Программирование, радиоэлектроника,
саморазвитие и частичка из моей жизни здесь...

Решение проблем совместимости в DLE после обновления до PHP 5.4

html girlНедавно столкнулся с необходимостью переноса нескольких сайтов моего знакомого на выделенный сервер, сайты построены на основе движка DLE(Data Life Engine) версий 8.3 и 9.3. Скопировал все файлы сайтов, выставил нужные права для чтения и записи на необходимые папки и залил дампы баз данных - после этого сайты заработали да вот только не совсем корректно... На сайтах пропали заголовки, в некоторых блоках текст, в админке при просмотре списка публикаций нет заголовков новостей, поиск публикаций по пользователю приводит к пустой белой страничке, проблемы с авторизацией через форму на сайте. Стоял выбор: даунгрейд PHP до версии 5.2 или правка движков под PHP 5.4 - я выбрал последний, казалось-бы сумасшедший вариант...

Содержание:

  1. Предисловие
  2. Ищем суть проблемы
  3. Приступаем к исправлениям
  4. В завершение

Предисловие

Для начала решил поискать что народ думает и как поступает в данной ситуации, кинулся в поиск и наоткрывал разных форумов, сервисов вопросов-ответов. Все советы и комментарии сводились к нескольким решениям: даунгрейд PHP, обновление ДЛЕ до самой новой версии(там все корректно работает с PHP 5.4), сменить хостера )))

В общем я понял что нужно брать и разбираться самому, поскольку ниодного толкового совета я не встретил - я выбрал путь который идет вразрез со всеми советами и подсказками на форумах и конференциях.

(i) Если вам не интересны технические нюансы и нужно только руководство к действию то можете сразу переходить к нижней части  статьи.

Итак, для начала разберемся что же изменилось в PHP 5.4 без обратной совместимости, для этого в несколько кликов через Гугл попадаем вот сюда: Что изменилось в PHP 5.4.x?, а там идем по ссылке несколько несовместимостей.

Ищем суть проблемы

Вот основные необратимые изменения которые нам интересны:

  • Безопасного режима в PHP больше нет (для ДЛЕ это не критично, здесь все ОК)
  • "Волшебные" кавычки (Magic Quotes) теперь не работают (здесь желательно будет проверить)
  • Возможность передачи по ссылке во время вызова функции была убрана (тоже может что-то поломать, проверим)
  • Операторы break и continue теперь не принимают аргументов в виде переменной (редко встречал такое в ДЛЕ, думаю тут все ОК)
  • Если вы используете функцию htmlentities с азиатскими наборами символов, то она работает также, как функция htmlspecialchars. (нужно будет проверить)
  • Удалены некторые функции, нам интересны здесь: session_is_registered(), session_register() и session_unregister().

По умолчанию в DLE включено достаточное отображение ошибок, что нам очень кстати для отслеживания проблемных скриптов:

@error_reporting ( E_ALL ^ E_WARNING ^ E_NOTICE );
@ini_set ( 'display_errors', true );

Смотрим проблемные странички на предмет вывода сообщений об ошибке - сразу же наткнулся на ошибку:

Function set_magic_quotes_runtime() is deprecated

На сайтах стоят модули SAPE и матерится именно на файл-скрипт sape.php. Функции set_magic_quotes_runtime уже нет начиная с PHP 5.3, просто нужно удалить все вызовы этой функции из файла и все будет в порядке. Насчет обновления кода SAPE с сайта партнерки я париться не стал, все ссылки отображаются корректно.

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

После недолгих поисков по коду было найдено что текст заголовка перед выводом экранируется(фильтруется) функцией htmlspecialchars - эта функция нужна для преобразования специальных HTML символов в безопасные для вывода пользователю в браузер.

Убрав фильтрацию этой функцией все названия статей в админке вернулись на свое место. Функция htmlspecialchars используется достаточно часто и отказаться от ее использования очень неразумное решение, нужно разобраться почему она не работает.

Исследовав как в DLE в разных модулях вызывается данная функция я пришел к выводу что вызывают ее очень часто с одним аргументом, а иногда еще в качестве другого аргумента передается флаг ENT_QUOTES.

Обратившись к документации по PHP внимательно рассмотрим какие аргументы принимает функция:

string htmlspecialchars ( string $string [, int $flags = ENT_COMPAT | ENT_HTML401 [, string $encoding = 'UTF-8' [, bool $double_encode = true ]]] )

Итак 1й аргумент - строка для обработки, 2й - специальный флаг для указания необходимой обработки, 3й - кодировка, 4й - переключатель что указывает нужно ли преобразовывать существующие html-сущности.

Итак, флаги по умолчанию используются ENT_COMPAT | ENT_HTML401, кодировка по умолчанию UTF-8, следующий аргумент...стоп, стоп...кодировка по умолчанию UTF-8? - так у меня же сайты в CP1251, я решил попробовать принудительно указать функции htmlspecialchars кодировку cp1251 и что вы думаете, названия новостей стали отображаться правильно.

Решил я поГуглить насчет данной темы и выяснилось что функция htmlspecialchars в PHP 5.4 корректно работает с кодировками UTF-8 CP1251 если в качестве кодировки принудительно передать пустую строку, вот как:

$title = htmlspecialchars($str, ENT_COMPAT, '');
$title = htmlspecialchars($str, ENT_QUOTES, '')

Поправив все функции в движке с текстами все стало ОК.

Даже после исправления всех функций htmlspecialchars все же в некоторых модулях тексты могут отображаться в неверной кодировке. Причиной этому может быть функция htmlentities которая переводит символы HTMl в сущности. Вызов ее в скриптах осуществляется таким же образом как и htmlspecialchars, поэтому следует так же пройтись по всем скриптам где есть эта функция и исправить ее вызов.

Осталось разобраться с пустой страницей при выводе списка новостей по имени пользователя.

Отыскав модуль что отвечает за отображение этой странички я начал смотреть на чем затыкается выполнение скрипта. Ставим по порядку в разных местах скрипта вывод отладочного текста и смотрим на каком участке скрипта прекращается вывод отладки. Вот отладочный код для вставок - простой echo, здесь нечего выдумывать:

echo 'Testing 1';

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

Таким способом было выяснено что к затыку приводит функция session_register() в одном из модулей что отвечает за авторизацию. После вызова данной функции инициализируются переменные в глобальном массиве $_SESSION. Имея опыт работы с сессиями я без опасения закомментировал функции session_register() и проблема с пустой страничкой исчезла - все отображается как нужно, с авторизацией нет проблем.

Можно конечно сразу же произвести поиск по всем скриптам на наличие в них функции session_register и поудалять ее там где она есть, но мне хотелось рассказатьь тебе, мой читатель, как еще можно выловить подобный баг.

Были также проверены и другие несовместимости PHP 5.4 на предмет наличия в скриптах сайтов на DLE - больше ничего править не понадобилось.

Подведем итог, подгонка старого движка DLE для работы с PHP 5.4 заключается вот в чем:

  • исправление вызова функций htmlspecialchars().
  • исправление вызова функций htmlentities().
  • удаление/комментирование вызовов функции session_register().

Приступаем к исправлениям

Расскажу подробно как достаточно быстро и удобно поправить скрипты движка любой версии.

Чистка функции session_register().

  1. Для работы нам будет нужен Total Commander и Notepad++.
  2. Загружаем с сайта себе на локальный компьютер папку engine (если на сайте есть другие папки со скриптами, например forum, то нужно их также скопировать для будущей правки); Делаем копию архива с загруженными файлами в надежное место на всякий случай, если нужно будет что-то вернуть назад. Распаковываем еще одну копию файлов(они у нас будут рабочими) в любую удобную папку, например d:Work.
  3. Открываем папку с загруженными скриптами в Total Commander'е и жмем ALT+F7 (поиск), там где "искать файлы" ставим *, а там где "С текстом" ставим галочку и вводим  "session_register(" и нажимаем Поиск;
  4. По завершению поиска снизу в панели будут отображены найденные файлы, нажимаем кнопочку "Файлы на панель" - в панели Total Commander отобразится список с найденными файлами, выделяем их правой кнопкой миши и перетаскиваем в Notepad++.
  5. Каждый файл отображен в своей вкладке, в каждом файле ищем вызов функции session_register с любыми аргументами и полностью ее удаляем. Для удобного поиска жмем CTRL+F и панель поиска переместим вправо к краю не закрывая ее, вводим туда session_register и чистим все найденные файлы от этой функции.

Для большей ясности изложенного приведу несколько скриншотов процесса:

Total Commander

Рис. 1. Поиск текста в в папке при помощи Total Commander.

Редактирование файлов

Рис. 2. Помечаем файлы для редактирования в Total Commander.

Notepad++

Рис. 3. Поиск кода и его редактирование в Notepad++ (кликните для увеличения).

Исправления функции htmlspecialchars.

Здесь работки будет побольше. Так само по аналогии ищем все файлы скриптов, в которых встречается ф-я htmlspecialchars, таких файлов может найтись порядка 40-70 штук(в зависимости от количества установленных плагинов и модулей к движку), перетаскиваем их в наш любимый Notepad++ и производим правки в зависимости от того как вызывается ф-я, это очень важно!

а) Если функция вызывается с одним аргументом, например:

$title=htmlspecialchars($title)
$name = $db->safesql( $parse->process( htmlspecialchars( trim( $_POST['name'] ) ) ) );

то добавляем еще два аргумента, правим ее к слудующему виду :

$title=htmlspecialchars($title, ENT_COMPAT, '')
$name = $db->safesql( $parse->process( htmlspecialchars( trim( $_POST['name'] ), ENT_COMPAT, '' ) ) );

б) Если функция вызывается с двумя аргументами, например в fullsearch.php:

$tpl->set( '{result-author}', "<a href="mailto:".htmlspecialchars($row['gast_email'], ENT_QUOTES)."">"

то добавляем третий - пустая строка, кавычки:

$tpl->set( '{result-author}', "<a href="mailto:".htmlspecialchars($row['gast_email'], ENT_QUOTES, '')."">"

в) Есть моменты(таких немного, 1-2 шт примерно) где не нужно ничего трогать, например это файлы editnews.php, registration.php:

$name = $db->safesql(trim(htmlspecialchars($parse->process(convert_unicode($_POST['name'], $config['charset'])))));

Здесь переменная $_POST['name'] приводится к нужной кодировке с помощью функции convert_unicode в которую указана кодировка для предварительной конвертации из системной переменной $config.

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

$db->safesql(htmlspecialchars(trim($_POST['name'])));

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

Аналогичным способом ищем и исправляем все вызовы функции htmlentities, их будет намного меньце - как правило несколько штук.

После всех правок закрываем редактор, упаковываем папки со скриптами в архив и закачиваем его на хостинг, там распаковываем архив с заменой файлов и радуемся результату. Желательно все же перед  распаковкой архива удалить старые папки со скриптами, так будет более надежно и мы будем уверены что скрипты у нас теперь те что нужно.

Если какую-то правку сделаете неверно то  очень скоро она себя проявит и вы достаточно быстро сможете ее исправить.

Также советую пройтись по всех ключевых моментах работы движка и проверить работоспособность - зарегистрировать пользователя, пройти авторизацию, создать новость, загрузить картинки, сохранить настройки в админке.

Итак включив свою логику и использовав простые подручные программные средства мы добились нужного результата. После вот таких сравнительно несложных но множественных операций работоспособность движка DLE, перенесенного на PHP 5.4, будет восстановлена. По крайней мере других глюков пока замечено не было )

В завершение

В этой статье я постарался с одной стороны коснуться сложных технических моментов, а с другой доступно разъяснить новичку как все исправить. Хотя работы получается немало но это все же дешевле и более практично нежели делать даунгрейд PHP или сезжать к другому хостеру в которого стоит старый PHP 5.2.

К тому же в PHP 5.4 есть ряд новшеств, которые будут использоваться в новых движках, которые вы возможно будете использовать, да и скорость работы нового PHP явно выше чем у версии 5.2.

Буду рад выслушать ваши мнения и комментарии!

4 1783 PHP
Комментарии к публикации (18):
Евгений #1Евгений
22 Май 2013 23:41

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

0
Владислав #2Владислав
11 Декабрь 2013 11:33

хостер обновил vps и поставил php 5.4
На одном сайте дле во вкладке редактировать новости не отображались названия статей. Нашел вашу статью, сделал все по инструкции, все заработало smile

Единственной что, у меня не было функции session_register() ни в одном файле.

И еще, тотал коммандер не обязательно иметь, можно просто сделать поиск через notepad++ по папке во всех файлах и прям в нодпаде все откроется

+1
ph0en1x #3ph0en1x
11 Декабрь 2013 14:54

Да, функции session_register() может и не быть в исходных кодах, она как правило встречается во всяких плагинах и сторонних модах, поэтому я решил упомянуть о ней на всякий случай.

можно просто сделать поиск через notepad++

Хорошее замечание, можно и так.

Рад что моя статья принесла вам пользу. smile

+2
Эдуард #4Эдуард
15 Январь 2014 21:02

Помогло, автору респект! Только не с первого раза, пропустил несколько строк, да нужно быть внимательным.

0
Cyberik #5Cyberik
11 Июнь 2014 00:35

Очень помогла твоя статья, а то думал уже менять PHP или хостинг. Респект! Пиши еще)

+1
shmel #6shmel
07 Октябрь 2014 14:46

Здравствуйте, все сделал как написано, вроде как всё работает, только одна проблема с (Вопросы и ответы для защиты от спама) версия dle 9.6 не работает пишет ответ неверный, отключать не хочется боты спамят ,что я только не делал, помогите пожалуйста

0
ph0en1x #7ph0en1x
08 Октябрь 2014 02:52

Попробуйте пересмотреть все сделанные правки в файлах что касаются модуля "Вопросы и ответы", возможно что-то упустили или же лишнее добавили. Хорошо если есть резервная копия сайта(я думаю перед тем как делать правки вы ее сделали), по ней можно сделать сравнение и проанализировать те изменения что вносили в файлы.

0
Вася #8Вася
25 Сентябрь 2015 01:50

С RSS-лентой что делать? отображается нормально, а в исходном коде страницы квадратики и экспортируются на другие сервисы каракули.

0
ph0en1x #9ph0en1x
25 Сентябрь 2015 11:03

Здесь может быть много вариантов. К примеру если вы переехали на новый сервер где стоит PHP 5.6 а сайт у вас на DLE в кодировке CP1251 то нужно установить в PHP кодировку для скриптов сайта по умолчанию СP1251. Сделать это можно добавив в корневой файл .htaccess в вашей папке с DLE вот такую директиву:
PHP_VALUE default_charset windows-1251

Также в данном случае, после добавления директивы с указанием кодировки, возможно придется во всех скриптах исправить функцию htmlspecialchars и привести ее к прежнему виду, а не так как мы правили в статье под PHP 5.4.

Дело в том что в PHP 5.6 и выше кодировка по умолчанию - UTF8, поэтому функции наподобие htmlspecialchars будут использовать именно эту кодировку по умолчанию. Если ваш сайт в кодировке CP1251 то все скрипты будут работать с данными функциями некорректно. Чтобы исправить кодировку по умолчанию в PHP без правки значения глобально в php.ini мы просто добавляем директиву в .htaccess который лежит в корне определенного сайта и который распространит свои опции только на скрипты данного сайта. С указанной выше директивой все скрипты на сайте будут по умолчанию использовать кодировку CP1251 и функции htmlspecialchars и другие начнут работать как нужно.

Посмотрите исходный код странички с RSS лентой и обратите внимание на верхнюю строчку, там будет указана кодировка для генерируемого XML-файла, сверьте ее с кодировкой сайта. Файл что отвечает за вывод RSS - /engine/rss.php, покопайтесь в нем и посмотрите все ли там на месте, сравните его с таким же файлом из чистой сборки DLE.

Также может быть что при переезде залили базу данных в неверной кодировке, но в этом случае проблема дала бы о себе знать не только в RSS но и в остальных модулях сайта.

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

0
Вася #10Вася
25 Сентябрь 2015 11:12

php5.4, все что вы описали я проверял, установил даже для функции htmlspecialchars кодировку в явном виде во всех файлах движка - все пофиг. проблема только с исходным кодом и экспортом в некоторые сервисы. Хотелось бы разобраться, т.к. нормальных сайтов на ДЛЕ у меня много.

0
ph0en1x #11ph0en1x
25 Сентябрь 2015 13:24

Посмотрел вашу ленту RSS - там все в порядке с кодировкой. А вот теги в полном тексте можно вырезать иначе попадут в экспорт всякие куски ява-скриптов и разные безопасные символы закодированные как & quot; --> & gt; & lt; и т.п. Отредактируйте rss.php, найдите в нем где выводится переменная для вывода полного текста и пропустите ее через функцию strip_tags, которая очистит текст от тегов и ява-скриптов.

0
Вася #12Вася
25 Сентябрь 2015 14:29

Вы исходный код смотрели то? И через что смотрели?lol Ни чего там не в порядке. И такой непорядок абсолютно на всех сайтах не зависимо от версии движка (старых версий естественно).

0
ph0en1x #13ph0en1x
25 Сентябрь 2015 15:36

Смотрел через CTRL+U в Firefox, правда по умолчанию стоит автодетект кодировки - не обратил внимания. Потом посмотрел через Firebug, видно что в исходнике кодировка неверная.
На всякий случай проверьте кодировки таблиц и соединения в базе данных, а потом уже пройдитесь еще раз по функциям htmlspecialchars, возможно где-то в движке одну не исправили или же исправили но не верно.
Кодировка в RSS у вас - CP1252(Western), пробуйте вычислить откуда она берется.
Еще одна мысль: у вас в выводе RSS спецсимволы HTML преобразовываются в сущности на подобии & quot; & gt; - за это отвечает функция htmlentities (преобразует все возможные символы в соответствующие HTML-сущности).

Исправьте все вызовы данной функции в движке так же как и для htmlspecialchars и посмотрите что получится.

+1
Maks #14Maks
26 Июль 2017 18:26

Блин, у меня тоже хостер перешел с php 5.3. Можно теперь выбрать 5.4, 5.5, 5.6 Сначала выбрал 5.6 Пришлось в httaccess добавлять 1251. ну это ладно. Появились такие проблемы. В админке не отображаются теперь похожие новости, что-то там ищет и пустота, видимо с mysql глюк. И еще заметил глюк, теперь рейтинг новости на сайте не пашет, при нажатии на нужную звездочку(оценку) вся полоска пропадает и при обновлении страницы все так, как будто ничего и не оценивал Sad Это и на 5.6 и на 5.4, на 5.4 еще и проблема с заголовками новостей, о которых вы писали. 5.5 выдает ошибку 503 на всем сайте, а 7.0 даже боюсь выбиратьLol Вот теперь не знаю как решить проблему с рейтингом и похожими новостями в админке. На самом сайте похожие новости выводятся.

0
ph0en1x #15ph0en1x
26 Июль 2017 19:59

Maks, сделайте полную копию сайта на том же хостинге или же на локальный сервер (например OpenServer), выбрав в настройках нужную версию PHP - работать с файлами локально намного быстрее и удобнее.
Теперь на копии сайта можно выполнять различные эксперименты, не опасаясь что можно испортить еще что-то на работающем проекте.
Первым делом разобраться с проблемой в админке - найти в дереве скриптов сайта файл который выводит нужный контент не так как нужно, поиграться с кодом и функциями скрипта, попробовать выловить где теряется контент.
Дальше таким же образом найти скрипт модуля для вывода звездного рейтинга, скорее всего это какой-то мод, поэтому универсального решения здесь нет, нужно разбираться самостоятельно.
Вы пишете что при нажатии вся полоска рейтинга пропадает - скорее всего при нажатии выполняется асинхронный запрос через JavaScript (AJAX), а его ответ пустой или содержит некорректные данные.
Отследить все параметры AJAX запросов можно используя дополнение FireBug или встроенные инструменты (Developer tools) в браузере Firefox.
Не спешите, воспринимайте процесс как увлекательный квест Wink

0
Макс #16Макс
26 Июль 2017 20:33

Да, буду пробовать, может что-то и получится...а то жалко, поиск похожих новостей в админке мне иногда помогал. Ну и рейтинг придется убрать. Или поищу в интернете другой рейтинг для dle. Да, там ajax, и в рейтинге и в поиске похожих новостей. Буду копать в папке ajax файлы rating.php и find_relates.php Видимо что-то не так с запросами mysql

+1
Макс #17Макс
28 Июль 2017 23:55

В общем получилось)) Получилось бы гораздо быстрее, если бы я вашу статью сразу до конца прочиталLol А так пришлось самому выяснять. Поставил firebug, но там что-то оч. сложно, не знаю, как там ошибки ajax отслеживать. Короче поступил проще, стал выводить echo с нейтральным текстом в в ajax/find_relates.php и нашел "злодея" - sitelogin.php, закомментировал строчки с session_register(), которая с php 5.4 не поддерживается и все сразу заработало, заодно и в init.php несколько строк таких закомментировал. Теперь все пашет, и поиск и рейтинг) Потом уже вашу статью до конца прочитал и увидел, что вы в принципе так и делали)

+1
ph0en1x #18ph0en1x
29 Июль 2017 00:27

В первый раз когда столкнулся с этой проблемой в DLE то также применил такое мощное средство отладки как "echo с нейтральным текстом".
Рад что у вас все получилось. Smile

0