[php] Новичкам: задаем вопросы

Discussion in 'PHP' started by _Great_, 26 May 2007.

Thread Status:
Not open for further replies.
  1. roxblnfk

    roxblnfk Elder - Старейшина

    Joined:
    6 Feb 2010
    Messages:
    189
    Likes Received:
    42
    Reputations:
    19
    чтобы не лезть в дебри, делай поиск от "function main" до следующей "function *", и от последней function отступи назад до закрывающей фиг. скобки функции main "}"
    В частном случае это прокатит :) но если в промежутке будет код, либо внутри main будут анонимные функции, то придётся извращаться. В полноценном коде нужно многое учитывать: и комментарии, и скобки, и кавычки (причём строка может начинаться не только с кавычек) и их приоритеты.
     
  2. mironich

    mironich Elder - Старейшина

    Joined:
    27 Feb 2011
    Messages:
    733
    Likes Received:
    73
    Reputations:
    19
    Грабитель
    https://github.com/nikic/PHP-Parser
    Вот оно, зачем костыли свои городить когда все готово.
     
  3. Грабитель

    Joined:
    5 Mar 2013
    Messages:
    196
    Likes Received:
    12
    Reputations:
    -7
    roxblnfk: да, в том то и дело, что перед функциями может быть что угодно.
    mironich: этот слишком громозкий, из за одной функции тонну кода использовать, но если по другому невозможно, то видимо придется его прикручивать, но спс за ссыль.
     
  4. Strilo4ka

    Strilo4ka

    Joined:
    5 Apr 2009
    Messages:
    709
    Likes Received:
    729
    Reputations:
    948
    http://php.net/manual/ru/function.token-get-all.php
     
  5. Adidev

    Adidev New Member

    Joined:
    21 May 2013
    Messages:
    3
    Likes Received:
    0
    Reputations:
    0
    спецы по Magento?

    Need to get list of products from current category in /shopgo/gtm/default.phtml.
     
  6. foma9999

    foma9999 New Member

    Joined:
    5 Jan 2010
    Messages:
    83
    Likes Received:
    2
    Reputations:
    -5
    Как обфускицировать пхп код без функции eval?
    По аналогии, как это сделано в этом упаковщике, упаковка версии 2.5 (используют preg_replace)
     
  7. GAiN

    GAiN Elder - Старейшина

    Joined:
    2 Apr 2011
    Messages:
    2,550
    Likes Received:
    172
    Reputations:
    99
    на битрикс cms вставлена строка с блоком, текст на русском языке закодирован в base64.
    но в результате раскодирования этой строки, все русские слова и буквы превращяются в набор символов непонятных в таком стиле: Челны
    как заставить нормально отображаться раскодированую информацию ?
     
  8. Compton

    Compton Member

    Joined:
    31 Jan 2010
    Messages:
    290
    Likes Received:
    25
    Reputations:
    0
    iconv()
     
    1 person likes this.
  9. GAiN

    GAiN Elder - Старейшина

    Joined:
    2 Apr 2011
    Messages:
    2,550
    Likes Received:
    172
    Reputations:
    99
    PHP:
    <?php
    header
    ("Content-Type:text/plain");
      function 
    showTree($folder$space) {
        
    /* Получаем полный список файлов и каталогов внутри $folder */
        
    $files scandir($folder);
        foreach(
    $files as $file) {
          
    /* Отбрасываем текущий и родительский каталог */
          
    if (($file == '.') || ($file == '..')) continue;
          
    $f0 $folder.'/'.$file//Получаем полный путь к файлу
          /* Если это директория */
          
    if (is_dir($f0)) {
            
    /* Выводим, делая заданный отступ, название директории */
            
    //        echo ':'.$space.$file.":\r\n";
            /* С помощью рекурсии выводим содержимое полученной директории */
            
    showTree($f0$space);
          }
          
    /* Если это файл, то просто выводим название файла */
    //      else echo $space.$file.";".md5_file($f0)."\r\n";
        
    }
      }
      
    /* Запускаем функцию для текущего каталога */
      
    showTree("./""");
    ?>
    нашёл функцию, для отображения всех файлов и директорий, как все данные этой функции записать в файл ?

    функция выдаёт ошибку при записи: Notice: Undefined variable

    данные на экран выводятся нормально, если echo раскомментирован
     
  10. roxblnfk

    roxblnfk Elder - Старейшина

    Joined:
    6 Feb 2010
    Messages:
    189
    Likes Received:
    42
    Reputations:
    19

    PHP:
    <?php
    header
    ("Content-Type:text/plain");
      function 
    showTree($folder$space, &$text) {
        
    /* Получаем полный список файлов и каталогов внутри $folder */
        
    $files scandir($folder);
        foreach(
    $files as $file) {
          
    /* Отбрасываем текущий и родительский каталог */
          
    if (($file == '.') || ($file == '..')) continue;
          
    $f0 $folder.'/'.$file//Получаем полный путь к файлу
          /* Если это директория */
          
    if (is_dir($f0)) {
            
    /* Выводим, делая заданный отступ, название директории */
            
    //        echo ':'.$space.$file.":\r\n";
            
    $text .= ':'.$space.$file.":\r\n";
            
    /* С помощью рекурсии выводим содержимое полученной директории */
            
    showTree($f0$space$text);
            continue;
          }
          
    /* Если это файл, то просто выводим название файла */
    //      else echo $space.$file.";".md5_file($f0)."\r\n";
            
    $text .= $space.$file.";".md5_file($f0)."\r\n";
        }
      }
      
    /* Запускаем функцию для текущего каталога */
      
    showTree("./"""$txt='');
      
    file_put_contents('file.txt'$txt);
    ?>
    однако, если тебе нужен md5-список файлов, то лучше использовать такой формат строк:
    [хэш md5][пробел][путь до файла от корневой директории]
     
    #22390 roxblnfk, 1 Mar 2015
    Last edited: 1 Mar 2015
  11. Грабитель

    Joined:
    5 Mar 2013
    Messages:
    196
    Likes Received:
    12
    Reputations:
    -7
    Возвращаюсь обратно к вопросу:
    http://php.net/manual/ru/function.token-get-all.php
    функция не помогла, выводит непонятные цифры.
    Есть ли ещё какие варианты решения вопроса?
     
  12. fl47590

    fl47590 Member

    Joined:
    15 Nov 2013
    Messages:
    54
    Likes Received:
    8
    Reputations:
    0
    Есть.
    Вариант 1 (очень плохой):
    Привязаться к тому стилю оформления кода, который вы привели. И исходить из того, что закрывающая фигурная скобка будет стоять ТОЛЬКО после перевода строки:
    PHP:
    <?php
        $content 
    file_get_contents'./dummy.php' );
        
        
    $p "~function main\(\) \{.*\n\}~Us";
        
        
    $out preg_match$p$content$m );
        
        echo 
    '<pre>';
        echo 
    $m];
        echo 
    '</pre>';
    Соответственно, код в файле dummy.php . Минусы способа - если код будет отформатирован иначе, то все тлен. Метод приведен скорее из соображений вида "как не надо делать".
    Вариант 2 (правильный, но есть и проще):
    Немного теории: в синтаксически верно написанной функции, если рассматривать ее от сигнатуры "function main() {" и заканчивая закрывающей фигурной скобкой "}" количество открывающих и закрывающих фигурных скобок должно быть равным. Поэтому набросок алгоритма будет следующий:
    1. Найти сигнатуру "function main() {".
    2. Объявить счетчик, например $c = 1; (почему 1? Потому что у нас уже есть одна открывающая скобка).
    3. Построчно анализировать исходник, встречая открывающую скобку увеличивать счетчик $c++; Встречая закрывающую скобку уменьшать счетчик $c--;
    4. После каждой скобки сравнивать счетчик с нулем. Если нуль получен, то мы прошли всю функцию и последняя скобка ее закрывала.

    Кстати, чтобы не парится со строчным разбором самому можно как раз воспользоваться http://php.net/manual/ru/function.token-get-all.php . Разобравшись, что за цифры, разумеется ;).
    Вариант 3 (правильный, простой, не всегда применимый):
    Воспользоваться рефлексией PHP. Для начала нужно подключить файл, в котором есть искомая функция. Потом использовать ReflectionFunction:
    PHP:
    <?php
        
    include './dummy.php';
        
        
    $func = new ReflectionFunction'main' );
            echo 
    $func->getStartLine() . ' - ' $func->getEndLine();
    На выходе будем иметь диапазон строк, где находится функция main. Минусы метода: файл dummy.php должен быть синтаксически верен, скрипт не должен завершится на инклюде этого файла.
     
    #22392 fl47590, 9 Mar 2015
    Last edited: 9 Mar 2015
  13. InSys

    InSys Member

    Joined:
    2 Feb 2012
    Messages:
    24
    Likes Received:
    20
    Reputations:
    31
    Гляньте еще вот это:

    https://github.com/nikic/PHP-Parser

    Вроде как это вполне можно использовать под ваши цели.
     
  14. Lazy

    Lazy New Member

    Joined:
    19 Jul 2011
    Messages:
    94
    Likes Received:
    2
    Reputations:
    3
    Есть мануал dr.Zero про sql
    http://forum.antichat.ru/thread43966.html
    Есть сайт с blind-sql который экплотится методом 3.1 Вывод в отчете об ошибках . Но при этом пока кроме DATABASE() и USER() получить ничего не удалось .

    Помогите понять данное выражение из мана
    SELECT COUNT(*) FROM (SELECT 1 UNION SELECT 2 UNION SELECT 3)x GROUP BY CONCAT(MID([YOUR QUERY], 1, 63), FLOOR(RAND(0)*2))

    Что делает (SELECT 1 UNION SELECT 2 UNION SELECT 3)x . Второй день не могу понять как все это работает в запросе . Может у кого есть ссыка на что почитать .
     
  15. InSys

    InSys Member

    Joined:
    2 Feb 2012
    Messages:
    24
    Likes Received:
    20
    Reputations:
    31
    Вот тут очень подробно описано почему это вообще работает:

    http://forum.antichat.ru/showpost.php?p=2954871&postcount=14
    (спойлер: связано с поведением GROUP BY и выражения RAND в нем)

    А вот это:
    Code:
    (SELECT 1 UNION SELECT 2 UNION SELECT 3)x
    - в SQL можно выполнять запрос к подзапросу. В данном случае это
    Code:
    SELECT 1 UNION SELECT 2 UNION SELECT 3
    - подзапрос, а "x" - алиас этого подзапроса, для того чтобы можно было бы к нему обращаться в самом запросе (в данном случае этот алиас не используется).
     
    1 person likes this.
  16. Lazy

    Lazy New Member

    Joined:
    19 Jul 2011
    Messages:
    94
    Likes Received:
    2
    Reputations:
    3
    Полезная ссылка , процентов на 30 я все осознал . Даже стало что-то кроме USER() и VERSION() получаться . Респект .

    Правильно ли я понимаю , что Duplicate entry возвращается не каждый раз даже при корректном запросе ?
     
  17. InSys

    InSys Member

    Joined:
    2 Feb 2012
    Messages:
    24
    Likes Received:
    20
    Reputations:
    31
    Ох, Lazy, есть некоторые вещи которым стоит просто верить, и не вдаваться в подробности как они работают. И это как раз тот самый случай.

    В общем давай, я попробую объяснить. Упростим запрос:
    Code:
    SELECT COUNT(*) FROM (SELECT 1 UNION SELECT 2 UNION SELECT 3)x GROUP BY FLOOR(RAND()*2)
    
    Рассмотрим запрос внимательно. В нем 3 строки группируются по полю RAND (при этом FLOOR(RAND()*2) может вернуть либо 1 либо 0). Для этого MySQL создает промежуточную, временную таблицу (temporary table), и проходя каждую строку записывает в нее результат. После чего на основе этой таблицы строится результат самого запроса. В идеале эта таблица должна выглядеть как то так:
    Code:
    group_key|count
    ---------+--------
     1       | 2
     0       | 1
    
    
    group_key - как уже понятно - является результатом вычисления FLOOR(RAND()*2) для каждой строки. При этом group_key является уникальным индексом в этой таблице, т.е. два значения group_key равным например "1" - недопустимая ситуация.

    То как организуется заполнение этой временной таблицы, выглядит приблизительно так (на самом деле далеко не так*, надо лезть в исходники, мне лень):
    Code:
    если (ключ [FLOOR(RAND()*2)] существует в temporary_table ) {
      //увеличить счетчик для данного group_key
      выполнить("UPDATE `temporary_table` SET `count` = `count` + 1 WHERE `group_key` = FLOOR(RAND()*2)")
    } иначе {
      //добавить новую строку
      выполнить("INSERT INTO `temporary_table` (`group_key`, `count`) VALUES (FLOOR(RAND()*2)), 1")
    }
    
    Как видно на один запрос вызывается два раза RAND.

    Теперь представим на секунду что FLOOR(RAND()*2)) выдаст следующий порядок значений на каждый вызов:
    Code:
    1
    1
    1
    1
    0
    1
    
    То в итоге временная таблица будет заполнятся следующим образом:
    Code:
    // 1 еще не существует в `temporary_table`
    INSERT INTO `temporary_table` (`group_key`, `count`) VALUES (1, 1);
    
    // 1 уже существует в `temporary_table`, увеличиваем счетчик
    UPDATE `temporary_table` SET `count` = `count` + 1 WHERE `group_key` = 1;
    
    // 0 еще не существует в `temporary_table`
    INSERT INTO `temporary_table` (`group_key`, `count`) VALUES (1, 1);
    
    В итоге на последнем запросе мы видим ошибку "Duplicate entry", так как он пытается вставить во временную таблицу второе уже существующее значение уникального индекса. Т.е. MySQL проверил что "group_key = 0" еще нет в таблице, и решил добавить его, но при этом при добавлении вызывал еще раз RAND, которое вернуло другое значение "1", которое уже существует в таблице.

    Вернемся к оригинальному запросу (допустим мы хотим получить VERSION()):
    Code:
    SELECT COUNT(*) FROM (SELECT 1 UNION SELECT 2 UNION SELECT 3)x GROUP BY CONCAT(MID((VERSION()), 1, 63), FLOOR(RAND(0)*2))
    Для RAND здесь указан конкретный seed равный 0:
    Code:
    RAND(0) <----- где "0" это seed
    seed - это начальное значение с помощью которого генерируются остальные случайные числа. Т.е. для всех одинаковых реализаций генератора случайных чисел с одинаковым заданным seed должен выдаваться одинаковый набор чисел. В случае MySQL гарантируется что для одинаковых версий будет сгенерирован одинаковый набор чисел.

    При выполнении этого запроса group_key будет выглядеть как то так 5.5.251 и заполнятся временная таблица будет следующим образом:
    Code:
    // '5.5.251' еще не существует в `temporary_table`
    INSERT INTO `temporary_table` (`group_key`, `count`) VALUES ('5.5.251', 1);
    
    // '5.5.251' уже существует в `temporary_table`, увеличиваем счетчик
    UPDATE `temporary_table` SET `count` = `count` + 1 WHERE `group_key` = '5.5.251';
    
    // '5.5.250' еще не существует в `temporary_table`
    INSERT INTO `temporary_table` (`group_key`, `count`) VALUES ('5.5.251', 1);
    
    На последнем запросе мы получим желанную ошибку:
    Code:
    #1062 - Duplicate entry '5.5.251' for key 'group_key'
    Можно кстати попробовать подобрать другой seed, и сократить немного запрос:
    Code:
    SELECT COUNT(*) FROM (SELECT 1 UNION SELECT 2)x GROUP BY CONCAT(MID([YOUR QUERY], 1, 63), FLOOR(RAND(14)*2))
    На таком наборе данных мы избегаем второго шага, и тем самым нам достаточно всего двух строк в подзапросе.

    Надо было это наверное в статью вынести... :)

    * Внутренний алгоритм отличается от вышеописанного, так как немного не укладывается в некоторые значения RAND, но идея показана верно, на одну строку - вызывается RAND несколько раз. Может это баг, может это особенность внутреннего построенния индекса, я не знаю.
     
  18. polipi

    polipi New Member

    Joined:
    1 Mar 2011
    Messages:
    0
    Likes Received:
    0
    Reputations:
    0
    Здравствуйте, помогите написать скрипт который кликает по кнопке.
    как-то должно быть так
    if (s.indexOf(SITE + '/111/111.php') > 0) клик по кнопке


    Сама кнопка
    <form action="111.php" method="post" enctype="multipart/form-data">
    <input type="hidden" name="ssid" value="">
    <input type="hidden" name="art" value="K4C">
    <input type="hidden" name="jc" value="6c8e82e148b1cc7adc16b269ee83e01a">
    <input type="submit" value="ОХХ">
    </form>
     
  19. Lazy

    Lazy New Member

    Joined:
    19 Jul 2011
    Messages:
    94
    Likes Received:
    2
    Reputations:
    3
    Да , наверное , лучше куда-нибудь вынести . Иначе потеряется полезный пост .

    Похоже на баг . На первый взгляд ничего не мешает вычислять group_key один раз и потом использовать везде где надо . Хрен знает как оно там в оригинальном коде конечно . :\

    По идее rand(0) и (select 1 union select 2 union select 3)(почему их несколько , кстати) всегда возвращает одинаковый результат . Если так duplicate error должен срабатывать(или не срабатывать) в 100% . На практике один и тот же запрос у меня иногда возвращает duplicate_error а иногда
    You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '1'' т е сам подзапрос не проходит и в group_key остается только значение RAND(). Хотя я каждый раз просто копирую его из текстовика .

    Вообще сколько времени нужно разбирать исходники mysql чтобы научиться самому делать такую магию ?
     
    #22399 Lazy, 12 Mar 2015
    Last edited: 12 Mar 2015
  20. polipi

    polipi New Member

    Joined:
    1 Mar 2011
    Messages:
    0
    Likes Received:
    0
    Reputations:
    0
    никто не может? хорошо, а за денюшку?
     
Thread Status:
Not open for further replies.