Поиск глюков в php скриптах на примере LiveStreet CMS

В один день на сайте под управлением LiveStreet отказались загружаться фотографии. Появлялось красное окно с ошибкой «Невозможно обработать файл, проверьте тип и размер файла».
Поиск по сайту проекта вывел на пост, где не вопрос пользователя не только не ответили, но и накидали минусов, когда он написал «жаль что всем пох».
Вообще в livestreet очень слабая документация и поддержка пользователей. Никогда не нравился их сайт и вообще этот движок.
Просто так сложилось исторически, что qwe.az работает на livestreet.
Короче говоря, есть ошибка и нужно найти её решение самому без помощи сообщества.
Мы имеем ошибку «Невозможно обработать файл, проверьте тип и размер файла» выдаваемую во время попытки загрузить изображение через редактор.
Зная, что все строки находятся в языковых файлах, открываем /templates/language/russian.php и ищем в нем стоку «Невозможно обработать файл, проверьте тип и размер файла»

Находим вот такую строку:
'uploadimg_file_error' => 'Невозможно обработать файл, проверьте тип и размер файла',


Теперь нам нужно найти, в каком скрипте выводится такая строка.
Для этого в linux достаточно перейти в корень сайта и выполнить команду:
grep -rl 'uploadimg_file_error' ./


В результате получаем список файлов:
./templates/language/russian.php
./templates/language/english.php
./include/ajax/uploadImg.php


Понятно, что первые два — это языковые файлы и само собой в них встречается строка 'uploadimg_file_error', а вот третий это как раз то, что нам нужно.

Открываем файл через vim:
vim ./include/ajax/uploadImg.php


Ищем нужную нам строку:
/uploadimg_file_error


Находим такой кусок кода в начале файла:
if(!$sFile=$oEngine->Topic_UploadTopicImageFile($_FILES['img_file'],$oUserCurrent)) {
        $sMsgTitle=$oEngine->Lang_Get('error');
        $sMsg=$oEngine->Lang_Get('uploadimg_file_error');
}

Значит ошибка выводится из-за того, что функция Topic_UploadTopicImageFile() возвращает false
Будем искать, почему она это делает.
Выходим из vim, набрав команду
:q


ищем в каком файле располагается функция Topic_UploadTopicImageFile
grep -rl 'function Topic_UploadTopicImageFile' ./


В ответ нам ничего не выыедится. Значит, нету такой функции?
Особенность livestreet в том, что авторы перемудрили до такой степени, что разобраться в движке порой бывает сложновато.
Включив интуицию можно догадаться, что Topic_UploadTopicImageFile это сорее всего сгенерированная функция. Называется она UploadTopicImageFile и распологается в классе Topic.
Чтобы проверить это вводим
grep -rl 'function UploadTopicImageFile' ./

и получаем
./classes/modules/topic/Topic.class.php

Как и ожидалось.
vim ./classes/modules/topic/Topic.class.php


и ищем нужную нам строку
/function UploadTopicImageFile


Находим вот такую функцию:
public function UploadTopicImageFile($aFile,$oUser) {

                if(!is_array($aFile) || !isset($aFile['tmp_name'])) {
                        return false;
                }

                $sFileTmp=Config::Get('sys.cache.dir').func_generator();

                if (!move_uploaded_file($aFile['tmp_name'],$sFileTmp)) {
                        return false;
                }

                $sDirUpload=$this->Image_GetIdDir($oUser->getId());
                $aParams=$this->Image_BuildParams('topic');

                $sFileImage=$this->Image_Resize($sFileTmp,$sDirUpload,func_generator(6),Config::Get('view.img_max_width'),Config::Get('view.img_max_height'),Config::Get('view.img_resize_width'),null,true,$aParams);

                if ($sFileImage) {
                        @unlink($sFileTmp);
                        return $this->Image_GetWebPath($sFileImage);
                }
                @unlink($sFileTmp);
                return false;
        }


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

Меняем кое что в скрипте, чтобы в итоге получилась вот такая функция:

public function UploadTopicImageFile($aFile,$oUser) {

                if(!is_array($aFile) || !isset($aFile['tmp_name'])) {
                        return -1;
                }

                file_put_contents('/home/baxi/www/qwe.az/upload_log.txt', '1 - OK');

                $sFileTmp=Config::Get('sys.cache.dir').func_generator();

                if (!move_uploaded_file($aFile['tmp_name'],$sFileTmp)) {
                        return -2;
                }

                file_put_contents('/home/baxi/www/qwe.az/upload_log.txt', '2 - OK');

                $sDirUpload=$this->Image_GetIdDir($oUser->getId());
                $aParams=$this->Image_BuildParams('topic');

                $sFileImage=$this->Image_Resize($sFileTmp,$sDirUpload,func_generator(6),Config::Get('view.img_max_width'),Config::Get('view.img_max_height'),Config::Get('view.img_resize_width'),null,true,$aParams);

                if ($sFileImage) {
                        @unlink($sFileTmp);
                        return $this->Image_GetWebPath($sFileImage);
                }
                @unlink($sFileTmp);
                return -3;
        }


Сохраняем файл и выходим из редактора
:wq


Снова откроем uploadImg.php
vim ./include/ajax/uploadImg.php


Снова находим кусок кода, ответственный за вывод ошибки:
if(!$sFile=$oEngine->Topic_UploadTopicImageFile($_FILES['img_file'],$oUserCurrent)) {
                        $sMsgTitle=$oEngine->Lang_Get('error');
                        $sMsg=$oEngine->Lang_Get('uploadimg_file_error');
                }


и меняем его на
if(!$sFile=$oEngine->Topic_UploadTopicImageFile($_FILES['img_file'],$oUserCurrent)) {
                        $sMsgTitle=$oEngine->Lang_Get('error');
                        $sMsg=$oEngine->Lang_Get('uploadimg_file_error');
                        $sMsg=$sFile;
                }


Пробуем загрузить картинку еще раз.
Если в тексте появилось такая строка:
<img src="-3" alt="" />


значит функция UploadTopicImageFile вернула -3, а это означает, что она отработала до самого конца и проблема где-то в функции Image_Resize:
$sFileImage=$this->Image_Resize($sFileTmp,$sDirUpload,func_generator(6),Config::Get('view.img_max_width'),Config::Get('view.img_max_height'),Config::Get('view.img_resize_width'),null,true,$aParams);


Попробуем найти, в каком файле находится эта функция:
grep -rl 'function Image_Resize' ./

ничего не выдает. Значит как и в предыдущем случае, скорее всего функция называется Resize и находится в модуле Image.
Пробуем поиск заново:
grep -rl 'function Resize' ./

получаем:
./engine/modules/image/Image.class.php


открываем файл и ищем функцию Resize, как уже делали выше.
После строки, объявления переменной
public function Resize($sFileSrc,$sDirDest,$sFileDest,$iWidthMax,$iHeightMax,$iWidthDest=null,$iHeightDest=null,$bForcedMinSize=true,$aParams=null,$oImage=null) {

добавим
$args = func_get_args();
file_put_contents('/tmp/upload_log.txt', var_export( $args, true) );

Это запишет значение всех аргументов, переданных функции в файл /tmp/upload_log.txt

После очередной попытки загрузить файл посмотрим в лог файл:
vim /tmp/upload_log.txt

Покажет что-то вроде:
array (
  0 => '/home/baxi/www/qwe.az/tmp/e0b0eb5b41',
  1 => '/uploads/images/00/00/18/2011/01/26',
  2 => 'a30c40',
  3 => '',
  4 => '',
  5 => 500,
  6 => NULL,
  7 => true,
...


Видим, что четвертый и пятый аргументы пусты.
$iWidthMax
$iHeightMax

а дальше в коде функции есть такой кусок:
if (($oImage->get_image_params('width')>$iWidthMax)
                        or ($oImage->get_image_params('height')>$iHeightMax)) {
                                return false;
                }


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

Одно из решений этого бага — это проверять переменные $iWidthMax и $iHeightMax
if (  ($iWidthMax > 0 AND ($oImage->get_image_params('width')>$iWidthMax) )
                        or ( $iHeightMax > 0 AND ($oImage->get_image_params('height')>$iHeightMax))) {
                                return false;
                }


А вообще главный урок, который лично я извлек из этого глюка: Нужно внимательнее изучать админку AceAdmin, ибо в ней и оказались две эти переменные, но без значений, что и вызвало глюк.
  • +2
  • 27 января 2011, 09:38
  • baxi

Комментарии (2)

RSS свернуть / развернуть
комментарий был удален

+
+1
Отличная работа)
avatar

Mecid

  • 31 января 2011, 18:00

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.