• Познакомьтесь с пентестом веб-приложений на практике в нашем новом бесплатном курсе

    «Анализ защищенности веб-приложений»

    🔥 Записаться бесплатно!

  • CTF с учебными материалами Codeby Games

    Обучение кибербезопасности в игровой форме. Более 200 заданий по Active Directory, OSINT, PWN, Веб, Стеганографии, Реверс-инжинирингу, Форензике и Криптографии. Школа CTF с бесплатными курсами по всем категориям.

Помогите составить скрипт

  • Автор темы Vadik(R)
  • Дата начала
V

Vadik(R)

Люди, помогите, пожалуйста, написать скрипт.
В общем хочу сделать поиск, чем-то похожий на поиск на некоторых форумах. Но проблема в том, что у меня просматриваются и html-теги. Объясню на примере.
Пусть искомая строка <font color="#00ff00">fahrengeit</font>.
Если пользователь захочет найти "fahrengeit", то результат будет выглядеть так
<font color="#00ff00"><span color="yellow">fahrengeit</span></font>.
Но если пользователь захочет найти "f", то у меня получится результат:
<font color="#00<span color="yellow">f</span><span color="yellow">f</span>00"><span color="yellow">f</span>ahrengeit</font>.
В том-то вся и проблема, как сделать замену подстрок, исключая абсолютно все теги (также надо исключать и все, что записано между тегами <script></script>).
Жду помощи. Если есть специальная функция для решения моей задачи - буду рад.
 
V

Vadik(R)

Люди, вот сегодня нашел более-менее подходящий код:
Код:
function highlighter ($data) {
$t=explode(' ', $_GET['text']);
// получаем массив слов, которые нужно подсвечивать
// Убираем из текста все теги в массив $tagList
preg_match_all('#<[^>]*>#', $data, $tags); array_unique($tags);
$tagList=array(); $k=0;
foreach($tags[0] as $i) {
$k++;
$tagList[$k]=$i;
$data=str_replace($i, '<' . $k . '>', $data);
}
// Производим обрамление текста <span>-ами
foreach($t as $i)
if (!is_numeric($i))
$data=preg_replace('#' . $i . '#i', '<span class="highlight">$0</span>', $data);
// Возвращаем все теги на место
foreach($tagList as $k=>$i) $data=str_replace('<' . $k . '>', $i, $data);
// Убираем все подсветки внутри тегов <title> ... </title>
$data=preg_replace_callback(		'#<title>(.*?)<\/title>#',
create_function(
'$m',
'return preg_replace("#<span([^>]*)>#", "", str_replace("</span>", "", $m[0]));'
),
$data	);
return $data; // Возвращаем подсвеченный текст
}
Только у меня по нему два вопроса:
1. Как сделать callback для тегов <script></script>, <style></style>. Просто не знаю куда это вписать вообще, так как функции в php еще не проходил, так что лучше доделайте этот код(как я предполагаю получится 8 строчек).
2. Почему если я делаю поиск со скобками, то он не работает, или вообще ничего не делает.
Подробнее. . Пока поиск идет только в имени закачавшем игру. Почему, если я набираю Vadik - цветом выделяет, если Vadik(R - вообще не пишет, а если полностью
Код:
Vadik(R)
- пишет имя, но не выделяет.
Заранее спасибо.
 
V

Vadik(R)

Вот еще нашел баг, если искать угловую скобку, то появляются откуда-то <1>,<2>,<3>,<4>...
И для чего нужна вот эта вещь в алгоритме "if (!is_numeric($i))"?
 
V

Vadik(R)

Ну да, а на чем же тогда форум написан?
 
F

Flying

В том-то вся и проблема, как сделать замену подстрок, исключая абсолютно все теги (также надо исключать и все, что записано между тегами <script></script>).

как-то странно у вас всё происходит, обычно текст храниться отдельно от хтмл-кода страницы и поиск выполняется только по тексту...

предложу варианты:
1) использовать поиск, как на php.su (если ваш сайт хорошо индексируется яндексом)
нагрузку с себя снимете (+)
правда юзверя придется передавать яндексу (-)
2) извращенно, но больше ничего не придумалось: убирать из кода теги, хранить оставшийся текст фрагментами (фрагмент текста - участок между тегами), для каждого фрагмента производить подсветку, а потом в первоначальном коде для каждого первичного фрагмента текста стр_реплейс на фрагмент с подсветкой
 
V

Vadik(R)

Да, ладно, я уже эту тему забросил, решил, что овчинка выделки не стоит или я слишком маловат для этого.
 
A

ARseny

для очистки тегов функция есть такая, strip_tags();
 
V

Vadik(R)

Мда... Если б в этом проблема заключалась, я б не спрашивал на форуме. Как их потом обратно вставить? + Читай link removed.
Flying Если честно то для того сайта, где я хотел такое сделать - это не подойдет. А так на будущее второй вариант хоть и через ж..., зато смогу сам написать.
 
G

GOsha

Да ну вас нафиг. Выгрузить код в strip_tags:

strip_tags
(PHP 3>= 3.0.8, PHP 4>)
strip_tags - вырезает тэги HTML и PHP из строки.

Описание
string strip_tags (string str [, string allowable_tags])

Эта функция пытается вернуть строку str с вырезанными тэгами HTML и PHP. Выдаёт ошибку с предупреждением в случае наличия неполных или ложных тэгов. Использует ту же машину вырезания тэгов, что и fgetss().

Вы можете использовать необязательный второй параметр для специфицирования тэгов, которые не должны вырезаться.
Примечание: allowable_tags был введён в PHP 3.0.13 и в PHP 4.0b3.

Код:
Пример 1. strip_tags()
$string = "<font .... ><b>Text</b></font>";
$string = strip_tags($string, '<a><b><i><u>');
//Вернет "<b>Text</b>"
Ну и т.д. Т.е. Берешь страницы - гасишь теги. Находишь слова... Все просто.
 
V

Vadik(R)

Так я же хочу хайлайт сделать. Я вырежу теги, найду слова, подсвечу его, а потом назад надо прежние теги вернуть. Только, честно говоря, я эту тему подзабросил, потому как для выполнения моей задачи мне кажется надо как-то по-другому сохранять данные на сервере. Либо вырезать теги самому, тогда, у меня есть идея, она немного через ж, зато будет работать :)
 
G

GOsha

1. ВО! Ты сохрани куда-нить исходную строку.
2. Найди в очищенной от тегов строке слова. И спиши их в массив.
3. В исходной строке уже хайлайть найденные слова... ))))
ПОнял?
 
V

Vadik(R)

3. В исходной строке уже хайлайть найденные слова... ))))
Здесь нельзя немного поподробнее?
Пусть исходная строка $str="<font color='red'>red</font><font color='green'>green</font><font color='blue'>blue</font>";
$s=$str; // Сохраняем исходную строку
strip_tags($str); // Вырезали теги
$findstr="green";
Дальше немного поподробнее хотел бы, но в результате должно получится:
$str="<font color='red'>red</font><font color='green'><span class='hl'>green</span></font><font color='blue'>blue</font>";
Если знаешь, то пожалуйста напечатай! Потому как я не знаю, как далее реализовать твой алгоритм.
 
G

GOsha

С помощюь preg_match_all собираем все в массив, который содержит ваш текст разбитый на теги:
Подсказка:
Код:
preg_match_all("/тут регулярное выражение/",$str,$matcharr,PREG_SET_ORDER);
Получим массив:
Код:
$matcharr[0] = "<font color='red'>";
$matcharr[1] = "red";
$matcharr[2] = "</font>";
...
Далее проходим по массиву array_walk(). выбираем и заменяем текст в строках, который не начинается с "<";

*Возможно это не самый короткий, но все же путь.

Не забудьте собрать массив обратно в строку. implode()
 
V

Vadik(R)

У меня прогресс очень хороший. Правда решил доделать код в 2 посте. Вот, что получил:
Код:
<?php
setlocale(LC_ALL, array ('ru_RU.CP1251', 'rus_RUS.1251'));
/*
Ограничения поиска:
Для работы с тегами <title>, <style>, <script> и т. п. где между ними размещен "особый" код, надо создавать
свой список таких тегов.
Callback не будет работать правильно, если теги будут повторятся. То есть для следующей строки поиск не сработает:
"<script></script>какой-то текст<script></script>". 
Алгоритм никогда не сможет найти слово Вадим в строке "<font size='7'>В</font>адим".
Такой поиск сделать можно, но его надо очччень хорошо продумать и алгоритм там будет другой. Придется писать
свою функцию replace_str, так, что бы она при проходе от первого сивола к последнему считала строки
"<$i>" как за пустые ("").
*/
function highlighter ($data, $mystr) {
// Массив тегов (определены, как регулярные выражения)
$specialTags=array("<title>", "<\/title>", "<style>", "<\/style>", "<script([^>]*)>", "<\/script>");
// Открывающая строка для подсветки
$firststr='<span style="color:#ff0000;">';
// Закрывающая строка для подсветки
$secondstr='</span>';
// Получаем массив слов которые надо подсвечивать и заодно заменяем спец. символы html-сущностями.
$t=explode(' ', html_entity_decode($mystr, ENT_QUOTES, "Windows-1251"));
// Удаляем повторяющиеся слова. Ведь бывают же извращенцы;)
$t=array_unique($t);
// Выполняем процедуру подсветки для каждого слова
foreach($t as $hren) {
// Получаем список тегов
preg_match_all('#<[^>]*>#', $data, $tags);
// Удаляем повторяющиеся теги
$tags=array_unique($tags);
// Без комментариев;)
$tagList=array(); $k=0;
// $tags=Array of Array; Там находятся все теги, поэтому делаем двойной цикл.
foreach($tags as $hren1) {
foreach($hren1 as $i) {
// Увеличиваем размер массив
$k++;
// Заносим в массив новый уникальный тег
$tagList[$k]=$i;
// А в строке заменяем этот тег на "<номер элемента массива, в котором мы сохранили тег>"
$data=str_replace($i, '<'.$k.'>', $data);
}
}
// Производим обрамление текста <span>-ами 
$data=str_replace($hren, $firststr.$hren.$secondstr, $data);
// Если пользователь ищет цифры, то они могут встретится в тегах. Поэтому возвращаем замененные теги назад
$data=str_replace('<'.$firststr.$hren.$secondstr.'>', '<'.$hren.'>', $data);
// Убираем все подсветки внутри "особых" тегов
/*for($i=0; $i<=(length($specialTags)+1)/2; $i++) {
for ($j=1; $j<=$k; $j++) {
if ($s)
$data=preg_replace_callback(		'#'.tag1.'(.*?)'.tag2.'#',
create_function(
'$m',
'return str_replace("<".$firststr.$hren.$secondstr.">", "<".$hren.">", $data);'
),
$data	);
}
}*/
// Возвращаем все теги на место
foreach($tagList as $k=>$i) $data=str_replace('<'.$k.'>', $i, $data);
}
return $data; // Возвращаем подсвеченный текст
}
echo highlighter("Vadik(R)", "(R)");
?>
Единственное, осталось проверить правильно ли я сделал регулярные выражения и дописать функцию preg_replace_callback. Сам не ожидал от себя такого результата :)
 
G

GOsha

Окак... )) Вперед... Как говорил мой дедушка-ветеран "Сиськи на амбразуры!" )))
А проверить вы и сами сможете...

Маньяк)
 
V

Vadik(R)

Почти доделал. Только callback не работает. А как сделаю, так опубликую, может кому пригодится :)
Сам долго искал в нете, нашел и то пришлось дорабатывать.

Ну вот, вроде и все. Вот окончательный код:
Код:
<?php
setlocale(LC_ALL, array ('ru_RU.CP1251', 'rus_RUS.1251'));
/*
Ограничения поиска:
Работает только с учетом регистра.
Для работы с тегами <title>, <style>, <script> и т. п. где между ними размещен "особый" код, надо создавать
свой список таких тегов.
Callback не будет работать правильно, если одинаковые специальные теги будут вложены. То есть для следующей 
строки подсветка сработает неправильно: "<script><script></script></script>".
Алгоритм никогда не сможет найти слово Вадим в строке "<font size='7'>В</font>адим".
Такой поиск сделать можно, но его надо очччень хорошо продумать и алгоритм там будет другой. Придется писать
свою функцию replace_str, так, что бы она при проходе от первого сивола к последнему считала строки
"<$i>" как за пустые ("").
*/
function myfunc($x) {
$firststr='<span style="color:#ff0000;">';
$secondstr='</span>';
return str_replace($firststr, "", str_replace($secondstr, "", $x));
}
function highlighter ($data, $mystr) {
// Массив тегов (определены, как регулярные выражения)
$specialTags=array("<title>", "<\/title>", "<style>", "<\/style>", "<script[^>]*?>", "<\/script>");
// Открывающая строка для подсветки
$firststr='<span style="color:#ff0000;">';
// Закрывающая строка для подсветки
$secondstr='</span>';
// Получаем массив слов которые надо подсвечивать и заодно заменяем спец. символы html-сущностями.
$t=explode(' ', htmlspecialchars($mystr, ENT_QUOTES, "Windows-1251"));
// Удаляем повторяющиеся слова. Ведь бывают же извращенцы;)
$t=array_unique($t);
// Выполняем процедуру подсветки для каждого слова
foreach($t as $hren) {
// Получаем список тегов
preg_match_all('#<[^>]*?>#', $data, $tags);
// Без комментариев;)
$tagList=array(); $k=0;
// В $tags[0] полное совпадение по шаблону, там находятся все теги
foreach($tags[0] as $i) {
// Увеличиваем размер массив
$k++;
// Заносим в массив новый уникальный тег
$tagList[$k]=$i;
// А в строке заменяем этот тег на "<номер элемента массива, в котором мы сохранили тег>"
$data=substr_replace($data, '<<'.$k.'>>', strpos($data, $i), strlen($i));
}
// Производим обрамление текста <span>-ами 
$data=str_replace($hren, $firststr.$hren.$secondstr, $data);
// Если пользователь ищет цифры, то они могут встретится в тегах. Поэтому возвращаем замененные теги назад
$data=preg_replace_callback(		'#<(([0-9])*?(<[^>]*?>)*?)*?>#',
create_function(
'$m',
'return myfunc($m[0]);'
),
$data	);
// Убираем все подсветки внутри "особых" тегов
$ffirst=0;
$ssecond=0;
for($i=0; $i<=(count($specialTags)-1)/2; $i++) {
for ($j=1; $j<=$k; $j++) {
if (preg_match ("/".$specialTags[$i*2]."/i", $tagList[$j])) $ffirst="<<".$j.">>";
if (preg_match ("/".$specialTags[$i*2+1]."/i", $tagList[$j])) $ssecond="<<".$j.">>";
if ($ffirst && $ssecond) {
$data=preg_replace_callback(		'#'.$ffirst.'(.*?)'.$ssecond.'#',
create_function(
'$m',
'return myfunc($m[0]);'
),
$data	);
$ffirst=0;
$ssecond=0;
}
}
}
// Возвращаем все теги на место
foreach($tagList as $k=>$i) $data=str_replace('<<'.$k.'>>', $i, $data);
}
// Возвращаем подсвеченный текст
return $data;
}
?>
Хотелось бы, что бы вы его потестили, а то может чего я из виду и упустил. Но проверял несколько раз. Все равно не верится, что у меня получилось. Думал лет в 20 такое напишу, когда будет работа и т. д. и т. п.
А так всем спасибо за участие и поддержку. Сейчас все будут награждены плюсиками :)
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!