1. PHP / Говнокод #13438

    +149

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    if (!class_exists($module, false))
    {
    // Get content from php file
    $filepath = _PS_MODULE_DIR_.$module.'/'.$module.'.php';
    $file = trim(file_get_contents(_PS_MODULE_DIR_.$module.'/'.$module.'.php'));
    if (substr($file, 0, 5) == '<?php')
    	$file = substr($file, 5);
    if (substr($file, -2) == '?>')
    	$file = substr($file, 0, -2);
    
    // If (false) is a trick to not load the class with "eval".
    // This way require_once will works correctly
    if (eval('if (false){	'.$file.' }') !== false)
    	require_once( _PS_MODULE_DIR_.$module.'/'.$module.'.php' );
    else
    	$errors[] = sprintf(Tools::displayError('%1$s (parse error in %2$s)'), $module, substr($filepath, strlen(_PS_ROOT_DIR_)));
    }

    Это оригинал кода из знаменитого Prestashop ...
    Попросили написать модуль. Долго мучался, почему валидный код не работает. Потом нашел.
    Смысл логики в строках 13-17 : мы не хотим принимать файлы модулей с eval функцией.
    Поэтому мы сначала проверяем, есть ли eval в файле.
    Как проверяем?
    А давайте его просто выполним!
    Если выполнится - тогда - require_once
    В общем я О....ЕЛ! Других слов просто нет.
    Мало того, так еще нужно следить, чтобы ваш файл модуля был валидным для eval функции.
    Иначе - Parse error: syntax error ...

    Запостил: corner578, 17 Июля 2013

    Комментарии (6) RSS

    • Лет ми спик фром май харт, бат ин май хамбл апиньен зе транслейшн оф камментс из щитти. И с выводами публикатор торопится, не изучив логику работы: http://ideone.com/WHHiiR

      if (false)” используется, чтобы конструкция скомпилировалась, но не выполнилась: «... is a trick to not load...» А переводить а английского нужно с конца: «the class with "eval"» — исходная информация, а «to not load» — новая.

      Да, мы пытаемся скомпилировать файл модуля, не выполняя его, а после попытки eval вернёт false, если не компилируется. Проверка выполняется оператором !==, чтобы отличить его от NULL, который eval вернёт в случае успешной компиляции.

      В итоге require_once выполнится, только если включаемый файл валидный с точки зрения eval (для того и сравнение !== false). Наличие же eval во включаемом модуле не проверяется, поэтому смело можете закладывать в модуль бомбу.
      Ответить
      • И зачем все это? Ради двойной загрузки? Про наличие eval (проверка на наличие) - я тестировал, это действительно так. Объясните, в чем смысл проверки? Дважды файл грузить? Или обеспечить электростанции работой?
        Ответить
        • Последний шанс реабилитации автора: проверка сделана для того, чтобы код не валился в случайном месте. В случае синтаксической ошибки во внешнем модуле он не будет подключен и код попытается отработать без него, выведя нормальную страницу, пусть и с отсутствующими элементами.

          Однако, я бы понял автора, если бы результат проверки кэшировался (записывался бы в конфиг), но грузить каждый раз модуль дважды — лишняя работа. Поэтому нет автору прощения, придётся признать Вашу правоту.
          Ответить

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