чтобы не лезть в дебри, делай поиск от "function main" до следующей "function *", и от последней function отступи назад до закрывающей фиг. скобки функции main "}" В частном случае это прокатит но если в промежутке будет код, либо внутри main будут анонимные функции, то придётся извращаться. В полноценном коде нужно многое учитывать: и комментарии, и скобки, и кавычки (причём строка может начинаться не только с кавычек) и их приоритеты.
roxblnfk: да, в том то и дело, что перед функциями может быть что угодно. mironich: этот слишком громозкий, из за одной функции тонну кода использовать, но если по другому невозможно, то видимо придется его прикручивать, но спс за ссыль.
Как обфускицировать пхп код без функции eval? По аналогии, как это сделано в этом упаковщике, упаковка версии 2.5 (используют preg_replace)
на битрикс cms вставлена строка с блоком, текст на русском языке закодирован в base64. но в результате раскодирования этой строки, все русские слова и буквы превращяются в набор символов непонятных в таком стиле: Челны как заставить нормально отображаться раскодированую информацию ?
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 раскомментирован
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][пробел][путь до файла от корневой директории]
Возвращаюсь обратно к вопросу: http://php.net/manual/ru/function.token-get-all.php функция не помогла, выводит непонятные цифры. Есть ли ещё какие варианты решения вопроса?
Есть. Вариант 1 (очень плохой): Привязаться к тому стилю оформления кода, который вы привели. И исходить из того, что закрывающая фигурная скобка будет стоять ТОЛЬКО после перевода строки: PHP: <?php $content = file_get_contents( './dummy.php' ); $p = "~function main\(\) \{.*\n\}~Us"; $out = preg_match( $p, $content, $m ); echo '<pre>'; echo $m[ 0 ]; 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 должен быть синтаксически верен, скрипт не должен завершится на инклюде этого файла.
Гляньте еще вот это: https://github.com/nikic/PHP-Parser Вроде как это вполне можно использовать под ваши цели.
Есть мануал 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 . Второй день не могу понять как все это работает в запросе . Может у кого есть ссыка на что почитать .
Вот тут очень подробно описано почему это вообще работает: 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" - алиас этого подзапроса, для того чтобы можно было бы к нему обращаться в самом запросе (в данном случае этот алиас не используется).
Полезная ссылка , процентов на 30 я все осознал . Даже стало что-то кроме USER() и VERSION() получаться . Респект . Правильно ли я понимаю , что Duplicate entry возвращается не каждый раз даже при корректном запросе ?
Ох, 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 несколько раз. Может это баг, может это особенность внутреннего построенния индекса, я не знаю.
Здравствуйте, помогите написать скрипт который кликает по кнопке. как-то должно быть так 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>
Да , наверное , лучше куда-нибудь вынести . Иначе потеряется полезный пост . Похоже на баг . На первый взгляд ничего не мешает вычислять 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 чтобы научиться самому делать такую магию ?