Inurl message чаемый. Поиск слов при помощи дополнительных операторов

Любой поиск уязвимостей на веб-ресурсах начинается с разведки и сбора информации.
Разведка может быть как активной - брутфорс файлов и директорий сайта, запуск сканеров уязвимостей, ручной просмотр сайта, так и пассивной - поиск информации в разных поисковых системах. Иногда бывает так, что уязвимость становится известна еще до открытия первой страницы сайта.

Как такое возможно?
Поисковые роботы, безостановочно бродящие по просторам интернета, помимо информации, полезной обычному пользователю, часто фиксируют то, что может быть использовано злоумышленниками при атаке на веб-ресурс. Например, ошибки скриптов и файлы с чувствительной информацией (начиная от конфигурационных файлов и логов, заканчивая файлами с аутентификационными данными и бэкапами баз данных).
С точки зрения поискового робота сообщение об ошибке выполнения sql-запроса - это обычный текст, неотделимый, например, от описания товаров на странице. Если вдруг поисковый робот наткнулся на файл с расширением.sql, который почему-то оказался в рабочей папке сайта, то он будет воспринят как часть содержимого сайта и так же будет проиндексирован (включая, возможно, указанные в нём пароли).

Подобную информацию можно найти, зная устойчивые, часто уникальные, ключевые слова, которые помогают отделить «уязвимые страницы» от страниц, не содержащих уязвимости.
Огромная база специальных запросов с использованием ключевых слов (так называемых дорков) существует на exploit-db.com и известна под названием Google Hack Database.

Почему google?
Дорки ориентированы в первую очередь на google по двум причинам:
− наиболее гибкий синтаксис ключевых слов (приведен в Таблице 1) и специальных символов (приведен в Таблице 2);
− индекс google всё же более полный нежели у других поисковых систем;

Таблица 1 – Основные ключевые слова google

Ключевое слово
Смысл
Пример
site
Поиск только на указанном сайте. Учитывает только url
site:somesite.ru - найдет все страницы по данному домену и поддоменам
inurl
Поиск по словам, присутствующим в uri. В отличие от кл. слова “site”, ищет совпадения после имени сайта
inurl:news - найдет все страницы, где в uri встретится данное слово
intext
Поиск в теле страницы
intext:”пробки” - полностью аналогично обычному запросу “пробки”
intitle
Поиск в заголовке страницы. Текст, заключенный между тэгами <br></td> <td width="214">intitle:”index of” - найдет все страницы с листингом директории<br></td> </tr><tr><td width="214">ext<br></td> <td width="214">Поиск страниц с указанным расширением<br></td> <td width="214">ext:pdf - найдет все pdf-файлы<br></td> </tr><tr><td width="214">filetype<br></td> <td width="214">В настоящее время полностью аналогично кл. слову “ext”<br></td> <td width="214">filetype:pdf - аналогично<br></td> </tr><tr><td width="214">related<br></td> <td width="214">Поиск сайтов со схожей тематикой<br></td> <td width="214">related:google.ru - покажет свои аналоги<br></td> </tr><tr><td width="214">link<br></td> <td width="214">Поиск сайтов, ссылающихся на данный<br></td> <td width="214">link:somesite.ru - найдет все сайты, на которых есть ссылка на данный<br></td> </tr><tr><td width="214">define<br></td> <td width="214">Показать определение слова<br></td> <td width="214">define:0day - определение термина<br></td> </tr><tr><td width="214">cache<br></td> <td width="214">Показать содержимое страницы в кэше (если имеется)<br></td> <td width="214">cache:google.com - откроет страницу из кэша<br></td> </tr></tbody></table><p>Таблица 2 – Специальные символы запросов google<br></p><table><tbody><tr><td width="214"><b>Символ </b><br></td> <td width="214"><b>Смысл </b><br></td> <td width="214"><b>Пример </b><br></td> </tr><tr><td width="214">“<br></td> <td width="214">Точная фраза<br></td> <td width="214">intitle:«RouterOS router configuration page» - поиск роутеров<br></td> </tr><tr><td width="214">*<br></td> <td width="214">Любой текст<br></td> <td width="214">inurl:«bitrix*mcart» - поиск сайтов на bitrix с уязвимым модулем mcart<br></td> </tr><tr><td width="214">.<br></td> <td width="214">Любой символ<br></td> <td width="214">Index.of - аналогично запросу index of<br></td> </tr><tr><td width="214">-<br></td> <td width="214">Исключить слово<br></td> <td width="214">error -warning - показать все страницы, где есть error, но нет warning<br></td> </tr><tr><td width="214">..<br></td> <td width="214">Диапазон<br></td> <td width="214">cve 2006..2016 - показать уязвимости по годам начиная с 2006<br></td> </tr><tr><td width="214">|<br></td> <td width="214">Логическое «или»<br></td> <td width="214">linux | windows - показать страницы, где встречается либо первое либо второе слово<br></td> </tr></tbody></table><br> Стоит понимать, что любой запрос к поисковой системе - это поиск только по словам.<br> Бесполезно искать на странице мета-символы (кавычки, скобки, знаки пунктуации и т. п). Даже поиск по точной фразе, указанной в кавычках, - это поиск по словам, с последующим поиском точного совпадения уже в результатах.<p>Все дорки Google Hack Database разделены логически на 14 категорий и представлены в таблице 3.<br> Таблица 3 – Категории Google Hack Database<br></p><table><tbody><tr><td width="168"><b>Категория </b><br></td> <td width="190"><b>Что позволяет найти </b><br></td> <td width="284"><b>Пример </b><br></td> </tr><tr><td width="168">Footholds<br></td> <td width="190">Веб-шеллы, публичные файловые менеджеры<br></td> <td width="284">Найти все взломанные сайты, где залиты перечисленные вебшеллы:<br> (intitle:«phpshell» OR intitle:«c99shell» OR intitle:«r57shell» OR intitle:«PHP Shell » OR intitle:«phpRemoteView») `rwx` «uname»<br></td> </tr><tr><td width="168">Files containing usernames<br></td> <td width="190">Файлы реестра, конфигурационные файлы, логи, файлы, содержащие историю введенных команд<br></td> <td width="284">Найти все файлы реестра, содержащие информацию об аккаунтах:<br><i>filetype:reg reg +intext:«internet account manager» </i><br></td> </tr><tr><td width="168">Sensitive Directories<br></td> <td width="190">Каталоги с различной информацией (личные документы, конфиги vpn, скрытые репозитории и т.д.)<br></td> <td width="284">Найти все листинги директорий содержащих файлы, относящиеся к vpn:<br><i>«Config» intitle:«Index of» intext:vpn </i><br> Сайты, содержащие git-репозитории:<br><i>(intext:«index of /.git») («parent directory») </i><br></td> </tr><tr><td width="168">Web Server Detection<br></td> <td width="190">Версию и иную информацию о веб-сервере<br></td> <td width="284">Найти административные консоли сервера JBoss:<br><i>inurl:"/web-console/" intitle:«Administration Console» </i><br></td> </tr><tr><td width="168">Vulnerable Files<br></td> <td width="190">Скрипты, содержащие известные уязвимости<br></td> <td width="284">Найти сайты, использующие скрипт, позволяющий выгрузить произвольный файл с сервера:<br><i>allinurl:forcedownload.php?file= </i><br></td> </tr><tr><td width="168">Vulnerable Servers<br></td> <td width="190">Инсталляционные скрипты, веб-шеллы, открытые административные консоли и т.д<br></td> <td width="284">Найти открытые PHPMyAdmin консоли, запущенные от root:<br><i>intitle:phpMyAdmin «Welcome to phpMyAdmin ***» «running on * as root@*» </i><br></td> </tr><tr><td width="168">Error Messages<br></td> <td width="190">Различные ошибки и предупреждения часто раскрывающие важную информацию - начиная от версии CMS до паролей<br></td> <td width="284">Сайты, имеющие ошибки в выполнении sql-запросов к базе:<br><i>«Warning: mysql_query()» «invalid query» </i><br></td> </tr><tr><td width="168">Files containing juicy info<br></td> <td width="190">Сертификаты, бэкапы, электронные письмы, логи, sql-скрипты и т.д<br></td> <td width="284">Найти инициализационные sql-скрипты:<br><i>filetype:sql and «insert into» -site:github.com </i><br></td> </tr><tr><td width="168">Files containing passwords<br></td> <td width="190">Всё что может содержать пароли - логи, sql-скрипты и т.д<br></td> <td width="284">Логи, упоминающие пароли:<br><i>filetype: </i><i>log </i><i>intext: </i><i>password | </i><i>pass | </i><i>pw </i><br> sql-скрипты содержащие пароли:<br><i>ext: </i><i>sql </i><i>intext: </i><i>username </i><i>intext: </i><i>password </i><br></td> </tr><tr><td width="168">Sensitive Online Shopping Info<br></td> <td width="190">Информацию связанную с онлайн покупками<br></td> <td width="284">Найти пинкоды:<br><i>dcid= </i><i>bn= </i><i>pin </i><i>code= </i><br></td> </tr><tr><td width="168">Network or vulnerability data<br></td> <td width="190">Информацию, не относящуюся непосредственно к веб-ресурсу, но затрагивающую сеть либо прочие не веб-сервисы<br></td> <td width="284">Найти скрипты автоматической настройки прокси, содержащие информацию о внутренней сети:<br><i>inurl:proxy | inurl:wpad ext:pac | ext:dat findproxyforurl </i><br></td> </tr><tr><td width="168">Pages containing login portals<br></td> <td width="190">Страницы, содержащие формы входа<br></td> <td width="284">Веб-страницы saplogon:<br><i>intext:«2016 SAP AG. All rights reserved.» intitle:«Logon» </i><br></td> </tr><tr><td width="168">Various Online Devices<br></td> <td width="190">Принтеры, роутеры, системы мониторинга и т.д<br></td> <td width="284">Найти конфигурационную панель принтера:<br><i>intitle:" </i><i>hp </i><i>laserjet" </i><i>inurl: </i><i>SSI/ </i><i>Auth/ </i><i>set_ </i><i>config_ </i><i>deviceinfo. </i><i>htm </i><br></td> </tr><tr><td width="168">Advisories and Vulnerabilities<br></td> <td width="190">Сайты на уязвимых версиях CMS<br></td> <td width="284">Найти уязвимые плагины, через которые можно загрузить произвольный файл на сервер:<br><i>inurl:fckeditor -intext:«ConfigIsEnabled = False» intext:ConfigIsEnabled </i><br></td> </tr></tbody></table><br> Дорки чаще ориентированы на поиск по всем сайтам сети интернет. Но ни что не мешает ограничить область поиска на каком-либо сайте или сайтах.<br> Каждый запрос к google можно сосредоточить на определённом сайте, добавив к запросу ключевое слово «site:somesite.com». Данное ключевое слово может быть дописано к любому дорку.<p><b>Автоматизация поиска уязвимостей </b><br> Так родилась идея написать простенькую утилиту, автоматизирующую поиск уязвимостей с помощью поисковой системы (google) и опирающуюся на Google Hack Database.</p><p>Утилита представляет из себя скрипт, написанный на nodejs с использованием phantomjs. Если быть точным, то скрипт интерпретируется самим phantomjs.<br> Phantomjs - это полноценный веб-браузер без графического интерфейса, управляемый с помощью js-кода и обладающий удобным API.<br> Утилита получила вполне понятное название – dorks. Запустив её в командной строке (без опций) получаем короткую справку с несколькими примерами использования:<br><br><img src='https://i1.wp.com/habrastorage.org/getpro/habr/post_images/edd/6fb/ccc/edd6fbccc5ec340abe750f3073c1b427.jpg' width="100%" loading=lazy><br> Рисунок 1 - Список основных опций dorks</p><p>Общий синтаксис утилиты: dork «команда» «список опций».<br> Подробное описание всех опций представлено в таблице 4. </p><p>Таблица 4 – Синтаксис dorks<br></p><table border="1"><tbody><tr><td width="214"><b>Команда </b><br></td> <td width="214"><b>Опция </b><br></td> <td width="214"><b>Описание </b><br></td> </tr><tr><td rowspan="4" width="214">ghdb<br></td> <td width="214">-l<br></td> <td width="214">Вывести нумерованный список категорий дорков Google Hack Database<br></td> </tr><tr><td width="214">-c «номер или название категории»<br></td> <td width="214">Загрузить дорки указанной категории по номеру или названию<br></td> </tr><tr><td width="214">-q «фраза»<br></td> <td width="214">Загрузить дорки, найденные по запросу<br></td> </tr><tr><td width="214">-o «файл»<br></td> <td width="214">Сохранить результат в файл (только вместе с опциями -c|-q)<br></td> </tr><tr><td rowspan="8" width="214">google<br></td> <td width="214">-d «дорк»<br></td> <td width="214">Задать произвольный дорк (опция может использоваться много раз, допускается сочетание с опцией -D)<br></td> </tr><tr><td width="214">-D «файл»<br></td> <td width="214">Использовать дорки из файла<br></td> </tr><tr><td width="214">-s «сайт»<br></td> <td width="214">Задать сайт (опция может использоваться много раз, допускается сочетание с опцией -S)<br></td> </tr><tr><td width="214">-S «файл»<br></td> <td width="214">Использовать сайты из файла (перебор дорков будет выполнен по каждому сайту независимо)<br></td> </tr><tr><td width="214">-f «фильтр»<br></td> <td width="214">Задать дополнительные ключевые слова (будет добавлено к каждому дорку)<br></td> </tr><tr><td width="214">-t «количество мс»<br></td> <td width="214">Интервал между запросами к google<br></td> </tr><tr><td width="214">-T «количество мс»<br></td> <td width="214">Таймаут, если встретилась каптча<br></td> </tr><tr><td width="214">-o «файл»<br></td> <td width="214">Сохранить результат в файл (будут сохранены только те дорки, по которым что-то нашлось)<br></td> </tr></tbody></table><br> С помощью команды ghdb можно получить все дорки с exploit-db по произвольному запросу, либо указать целиком всю категорию. Если указать категорию 0 - то будет выгружена вся база (около 4.5 тысяч дорков).<p>Список категорий доступных на данный момент представлен на рисунке 2.<br><br><img src='https://i1.wp.com/habrastorage.org/getpro/habr/post_images/b8f/b11/ffe/b8fb11ffeaced5066fd2fd9e43be67fb.jpg' width="100%" loading=lazy></p><p>Рисунок 2 - Список доступных категорий дорков GHDB</p><p>Командой google будет произведена подстановка каждого дорка в поисковик google и проанализирован результат на предмет совпадений. Дорки по которым что-то нашлось будут сохранены в файл.<br> Утилита поддерживает разные режимы поиска:<br> 1 дорк и 1 сайт;<br> 1 дорк и много сайтов;<br> 1 сайт и много дорков;<br> много сайтов и много дорков;<br> Список дорков и сайтов можно задать как через аргумент, так и через файл.</p><p><b>Демонстрация работы </b><br> Попробуем поискать какие-либо уязвимости на примере поиска сообщений об ошибках. По команде: dorks ghdb –c 7 –o errors.dorks будут загружены все известные дорки категории “Error Messages” как показано на рисунке 3.<br><br><img src='https://i1.wp.com/habrastorage.org/getpro/habr/post_images/28c/386/641/28c386641d1528652f7f8e8b8089097a.jpg' width="100%" loading=lazy><br> Рисунок 3 – Загрузка всех известных дорков категории “Error Messages”</p><p>Дорки загружены и сохранены в файл. Теперь остается «натравить» их на какой-нибудь сайт (см. рисунок 4).<br><br><img src='https://i2.wp.com/habrastorage.org/getpro/habr/post_images/8e0/a8a/3af/8e0a8a3af4f26544da1faa584813dbff.jpg' width="100%" loading=lazy><br> Рисунок 4 – Поиск уязвимостей интересуемого сайта в кэше google</p><p>Спустя какое-то время на исследуемом сайте обнаруживается несколько страниц, содержащих ошибки (см. рисунок 5).</p><p><img src='https://i0.wp.com/habrastorage.org/getpro/habr/post_images/10b/e83/ba3/10be83ba38f172213ba06b3f9ad05a58.jpg' width="100%" loading=lazy><br> Рисунок 5 – Найденные сообщения об ошибках</p><p>Итог, в файле result.txt получаем полный список дорков, приводящих к появлению ошибки.<br> На рисунке 6 представлен результат поиска ошибок сайта.<br><br> Рисунок 6 – Результат поиска ошибок</p><p>В кэше по данному дорку выводится полный бэктрейс, раскрывающих абсолютные пути скриптов, систему управления содержимым сайта и тип базы данных (см. рисунок 7).<br><br><img src='https://i2.wp.com/habrastorage.org/getpro/habr/post_images/0a9/455/588/0a9455588496d6609f5e13d598cb5a48.jpg' width="100%" loading=lazy><br> Рисунок 7 – раскрытие информации об устройстве сайта </p><p>Однако стоит учитывать, что не все дорки из GHDB дают истинный результат. Так же google может не найти точного совпадения и показать похожий результат.</p><p>В таком случае разумнее использовать свой персональный список дорков. Например, всегда стоит поискать файлы с «необычными» расширениями, примеры которых приведены на рисунке 8.<br><br><img src='https://i0.wp.com/habrastorage.org/getpro/habr/post_images/d7f/865/693/d7f865693f7fcf13137598eeed0ecb58.jpg' width="100%" loading=lazy><br> Рисунок 8 – Список расширений файлов, не характерных для обычного веб-ресурса</p><p>В итоге, по команде dorks google –D extensions.txt –f банк, с самого первого запроса google начинает отдавать сайты с «необычными» расширениями файлов (см. рисунок 9). <br><br><img src='https://i2.wp.com/habrastorage.org/getpro/habr/post_images/107/e1f/a2f/107e1fa2f41c4169bcc254cba2f2f4b6.jpg' width="100%" loading=lazy><br> Рисунок 9 – Поиск «нехороших» типов файлов на сайтах банковской тематики</p><p>Стоит иметь ввиду, что google не воспринимает запросы длиннее 32 слов.</p><p>С помощью команды dorks google –d intext:”error|warning|notice|syntax” –f университет <br> можно поискать ошибки интерпретатора PHP на сайтах учебной тематики (см. рисунок 10). <br><br><img src='https://i0.wp.com/habrastorage.org/getpro/habr/post_images/717/74f/e36/71774fe3656bfc058c42d43262fdec4a.jpg' width="100%" loading=lazy><br> Рисунок 10 – Поиск PHP-ошибок времени исполнения</p><p>Иногда пользоваться какой-то одной или двумя категориями дорков не удобно.<br> Например, если известно, что сайт работает на движке wordpress, то нужны дорки именно по wordpress. В таком случае удобно воспользоваться поиском Google Hack Database. Команда dorks ghdb –q wordpress –o wordpress_dorks.txt загрузит все дорки по Wordpress, как показано на рисунке 11:<br><br><img src='https://i0.wp.com/habrastorage.org/getpro/habr/post_images/dcb/ac9/a4e/dcbac9a4eb12f6ec775d9cccc2fdee87.jpg' width="100%" loading=lazy><br> Рисунок 11 – Поиск дорков, относящихся к Wordpress</p><p>Снова вернемся к банкам и командой dorks google –D wordpress_dords.txt –f банк попробуем найти что-нибудь интересное, связанное с wordpress (см. рисунок 12).<br><br><img src='https://i1.wp.com/habrastorage.org/getpro/habr/post_images/042/0c2/c43/0420c2c435931704288b171f725ccc6a.jpg' width="100%" loading=lazy><br> Рисунок 12 – Поиск уязвимостей Wordpress</p><p>Стоит заметить, что поиск на Google Hack Database не воспринимает слова короче 4 символов. Например, если CMS сайта не известна, но известен язык - PHP. В таком случае можно отфильтровать нужное вручную с помощью пайпа и системной утилиты поиска dorks –c all | findstr /I php > php_dorks.txt (см. рисунок 13):<br><br><img src='https://i2.wp.com/habrastorage.org/getpro/habr/post_images/4c1/2f8/6e1/4c12f86e111074293c14d6a939c6ebab.jpg' width="100%" loading=lazy><br> Рисунок 13 – Поиск по всем доркам, где есть упоминание PHP</p><p>Поиск уязвимостей или какой-то чувствительной информации в поисковой системе следует искать только в случае если по данному сайту есть значительный индекс. Например, если у сайта проиндексировано 10-15 страниц, то глупо что-либо искать подобным образом. Проверить размер индекса просто - достаточно ввести в строку поиска google «site:somesite.com». Пример сайта с недостаточным индексом показан на рисунке 14.<br><br><img src='https://i1.wp.com/habrastorage.org/getpro/habr/post_images/78e/1db/b4f/78e1dbb4fc78cd422cec311fc2ca9d33.jpg' width="100%" loading=lazy><br> Рисунок 14 – Проверка размера индекса сайта</p><p>Теперь о неприятном… Периодически google может запросить каптчу - тут ничего не поделать - её придется ввести. Например, у меня, при переборе категории «Error Messages» (90 дорков) каптча выпала только один раз.</p><p>Стоит добавить, что phantomjs поддерживает работу так же и через прокси, как через http, так и через socks интерфейс. Для включения режима прокси надо раскоментировать соответствующую строку в dorks.bat или dorks.sh.</p><p>Инструмент доступен в виде исходного кода</p> <p>Масштабное обновление программы XRumer, в котором значительно эволюционировала логика регистрации профилей на самых разных платформах, улучшена работа с платформами Bitrix, Joomla, WordPress Forum, MyBB, VBulletin, XenForo, добавлен механизм модификации отправляемого текста в зависимости от тематики сайта-реципиента (новый макрос #theme), обновлены и увеличены прилагаемые базы - общий объём превысил 8 миллионов сайтов, улучшена работа с HTTPS и Google ReCaptcha-2, и многое другое...</p> <i>26 января 2019 </i> <h3>XRumer 16.0.18 + SocPlugin 4.0.63</h3> <p>Прилагаемые базы проверены и обновлены, общий объём увеличен до 8 (!) миллионов поддерживаемых ресурсов — блогов, форумов, гостевых книг, досок, BBS, CMS, и прочих платформ. База известных тексткапч увеличена более чем на 2000 новых ответов на антибот-вопросы и теперь составляет 324000 тексткапч. Существенно повышена стабильность и скорость работы, оптимизирован расход ресурсов: потолок достигает до 500 и более потоков (в зависимости от режима работы). Улучшена работа с HTTPS. И основное, ключевое улучшение: многократно повышена эффективность рассылок личных сообщений — режим MassPM. Плюс, многие другие улучшения и исправления:)</p> <i>14 сентября 2018 </i> <h3>XRumer 16.0.17</h3> <p>Важное обновление XRumer, существенно оптимизирующее расход ресурсов. Повышена стабильность и скорость работы, увеличен потолок потоков. Теперь проход по многомиллионным базам более комфортен! Также улучшена работа с HTTPS, JavaScript, улучшена работа с платформой Joomla K2, и многое другое...</p> <i>05 июля 2018 </i> <p>Необходимо включить JavaScript для того, чтобы сайт работал корректно</p> <h1>Нововведения и улучшения в XRumer и SocPlugin<i>12 сентября 2014 </i></h1> <h3>Нововведения и улучшения в XRumer 12.0.7</h3> <h3>Нововведения и улучшения в SocPlugin 4.0.10</h3> <ul><li>в Автоответчике реализована поддержка Одноклассников</li> <li>обновлена функция комментирования видео на ВКонтакте</li> <li>скорректирована процедура сохранения базы анкет</li> <li>обновлён User-agent</li> <li>добавлена возможность копирования всех выделенных ссылок на анкеты в окне отображения списка анкет (а не только одной)</li> <li>реализована рандомизация каждой задержки в пределах ± 20%</li> <li>в окне списка групп добавлено выпадающее меню для управления списком: удаление, копирование, открытие в браузере</li> <li>улучшена информативность сообщений о проблемах с авторизацией</li> <li>скорректирована загрузка/сохранение списка пользователей из/в XML-файл</li> <li>скорректирована работа некоторых опций автонаполнения аккаунтов</li> <li>обновлено получение параметров анкет на Фэйсбуке</li> </ul> <p>Recently I was working on my Website, and decided I wanted to implement a guestbook. I started to search the Web to find the best guestbook for my Website, but when none turned up, I thought ‘Hey I’m a developer, why not create my own?’ </p> <p>It was very easy to create a guestbook — you can do it too. In this tutorial, I’ll show you how. I’ll assume that you have already knowledge about the basics of ASP.NET programming, that you know the techniques involved in codebehind, and that you have some XML/XSL skills.</p> <h5>Overview</h5> <p>What do we need in order to create a guestbook? We need two Web forms: one in which the user can enter their name, email address, and comment, and another that’s used to display these comments as they’re signed into the guestbook. Of course we can build this functionality into one Web form, but to have a clean code, I’ll use two Web forms with several codebehind files (I’ll discuss these in more detail in a moment).</p> <p>We’ll also need a database to hold the information entered via the form. I used a simple XML file (a database) to store the information entered by the user. For the visualisation of the XML we’ll use XSL.</p> <p>So, in summary, we need the following:</p> <ul><li>Two Web forms</li><li>Codebehind</li><li>Database</li> </ul><p>In a guestbook, it’s usually sufficient to store a user’s name, location, email address, Website address, and comment. Of course, you can store more fields, but for our purposes, these are enough. We’ll store this data in the XML file, which will look something like this:</p><p> <?xml version="1.0" encoding="ISO-8859-1"?> <br> <guestbook> <br> <guest> <br> <name>Sonu Kapoor</name> <br> <location>Germany</location> <br> <email>sonu@codefinger.de</email> <br> <website>www.codefinger.de</website> <br> <comment>This guestbook is written by Sonu Kapoor. <br> I hope you like it. To learn how to create such a guestbook, <br> read the whole story on my website.</comment> <br> </guest> <br> </guestbook> </p><h5>Signing the Guestbook</h5> <p>We’ll allow the user to ‘sign’ our guestbook by entering some information into a simple Web form — in our example this is the guestbook.aspx file. I use the following fields in the Web form:</p> <ul><li>Location</li><li>Email</li><li>Website</li><li>Comment</li> </ul><p>Here’s the code:</p><p> <% @Page Language="C#" Debug="true" Src="Guestbook.cs" <br> Inherits="Guestbook" %> <br> <form runat="server"> <br> ... <br> ... <br> <ASP:Textbox id="name" size="64" runat="server"/> </p><p> <asp:RequiredFieldValidator id="nameRequired" runat="server" <br> ControlToValidate="name" <br> ErrorMessage="You must enter a value into textbox1" <br> Display="dynamic">Enter name <br> </asp:RequiredFieldValidator> </p><p> <ASP:Textbox id="location" size="64" runat="server"/> </p><p> <asp:RequiredFieldValidator id="locationRequired" runat="server" <br> ControlToValidate="location" ErrorMessage="You must enter <br> a value into textbox1" Display="dynamic"> <br> Enter location </asp:RequiredFieldValidator> </p><p> <ASP:Textbox id="website" size="64" runat="server"/> <br> <ASP:Textbox id="email" size="64" runat="server"/> <br> <ASP:Textbox id="comment" TextMode="Multiline" <br> columns="50" rows="10" wrap="true" runat="server"/> </p><p> <asp:RequiredFieldValidator id="commentRequired" runat="server" <br> ControlToValidate="comment" ErrorMessage="You must enter <br> a value into textbox1" Display="dynamic"> <br> Enter comment </asp:RequiredFieldValidator> </p><p> <ASP:Button id="submit" runat="server" Text="Submit" <br> OnClick="Save_Comment"/> <br> <ASP:Button id="reset" runat="server" Text="Reset"/> <br> ... <br> ...doing some visualisation stuff <br> ... <br> </script> <br> </form> </p><p>To avoid confusing you with unnecessary code, I have removed the visualisation tags — including table, table header etc. — from this example (though, of course, these are all included in the downloadable code that’s provided at the end of this tutorial). As we only display a simple form with a few fields and buttons, you can’t see any real programming code in this file. This is because all the functionality is hidden in the codebehind.</p> <p>In the first line of the code above, I set the SRC attribute to let the ASP.NET file know that we are using the codebehind file Guestbook.cs I’ve also set the attribute Inherits with the corresponding classname. This attribute lets the file know which class to inherit.</p> <p>Next, I’ve implemented the required text fields. Remember that if you want to use the same variables in the codebehind, they need to have the same ID in both files, and they must be declared as public.</p> <p>In the next section of the code, I used the ASP.NET validator controls. These controls check whether the user has entered a value into the text field, without doing a round-trip to the server. The code is executed on the client side.</p> <p>Finally, I implemented a submit button with an OnClick event called Save_Comment . This event is used to store the information entered into the XML file by the user. The function of this event is available in Guestbook.cs. I also implemented a reset button — and that’s it! Nothing more has to be done to the Web form. Now, if you run the guestbook.aspx, you should see a Web form that looks like this:</p> <p>Now we know how to display the Web form, but we haven’t seen the code that handles the event in guestbooks.cs. Let’s take a look at that now.</p><p>Using System; <br> using System.Web; <br> using System.Web.UI; <br> using System.Xml; </p><p>Public class Guestbook: Page <br> { <br> // Create the required webcontrols with the same name as <br> in the guestbook.aspx file <br> public TextBox name; <br> public TextBox location; <br> public TextBox email; <br> public TextBox website; <br> public TextBox comment; </p><p>Public void Save_Comment(object sender, EventArgs e) <br> { <br> // Everything is all right, so let us save the data <br> into the XML file <br> SaveXMLData(); </p><p> // Remove the values of the textboxes <br> name.Text=""; <br> location.Text=""; <br> website.Text=""; <br> email.Text=""; <br> comment.Text=""; <br> } <br> } </p><p>Private void SaveXMLData() <br> { <br> // Load the xml file <br> XmlDocument xmldoc = new XmlDocument(); <br> xmldoc.Load(Server.MapPath("guestbook.xml")); </p><p> //Create a new guest element and add it to the root node <br> XmlElement parentNode = xmldoc.CreateElement("guest"); <br> xmldoc.DocumentElement.PrependChild(parentNode); </p><p> // Create the required nodes <br> XmlElement nameNode = xmldoc.CreateElement("name"); <br> XmlElement locationNode = xmldoc.CreateElement("location"); <br> XmlElement emailNode = xmldoc.CreateElement("email"); <br> XmlElement websiteNode = xmldoc.CreateElement("website"); <br> XmlElement commentNode = xmldoc.CreateElement("comment"); </p><p> // retrieve the text <br> XmlText nameText = xmldoc.CreateTextNode(name.Text); <br> XmlText locationText = xmldoc.CreateTextNode(location.Text); <br> XmlText emailText = xmldoc.CreateTextNode(email.Text); <br> XmlText websiteText = xmldoc.CreateTextNode(website.Text); <br> XmlText commentText = xmldoc.CreateTextNode(comment.Text); </p><p> // append the nodes to the parentNode without the value <br> parentNode.AppendChild(nameNode); <br> parentNode.AppendChild(locationNode); <br> parentNode.AppendChild(emailNode); <br> parentNode.AppendChild(websiteNode); <br> parentNode.AppendChild(commentNode); </p><p> // save the value of the fields into the nodes <br> nameNode.AppendChild(nameText); <br> locationNode.AppendChild(locationText); <br> emailNode.AppendChild(emailText); <br> websiteNode.AppendChild(websiteText); <br> commentNode.AppendChild(commentText); </p><p> // Save to the XML file <br> xmldoc.Save(Server.MapPath("guestbook.xml")); </p><p> // Display the user the signed guestbook <br> Response.Redirect("viewguestbook.aspx"); <br> } <br> } </p><p>Wow! That’s our codebehind file… but what really happens here? You won’t believe it, but the answer is: "not much"!</p> <p>First, we implement the minimal required namespaces which we need in order to access several important functions. Then I create a new class called Guestbook:</p> public class Guestbook: Page <p>Note that it’s this class that’s inherited by the guestbook.aspx file. Then we declare 5 public variables of type textbox. Remember that here, the names have to be identical to those we used when we created the text boxes in guestbook.aspx. Then, as you can see, we use the Save_Comment event, which is fired by the submit button we included in the guestbookpx file. This event is used to save the data.</p> <h5>The Saving Process</h5> <p>The function SaveXMLData() saves the information for us. As we’re using an XML database to store the information, we use the XmlDocument , XmlElement and XmlText classes, which provide all the functions we need.</p> <p>Next, we create a new XMLDocument class object and load the guestbook.xml file. The required nodes are created with the function CreateElement , and the information entered by the user is retrieved and stored to an object of XmlText . Next, we store the created nodes without any values, using the function AppendChild in conjunction with the main XmlDocument object.</p> <p>And finally, the values are stored in the nodes we just created, we save all changes to the guestbook.xml file, and we redirect the page to viewguestbook.aspx, where the stored comment is displayed.</p> <h5>Viewing the Guestbook</h5> <p>To view the guestbook, we must created an another Web form:</p><p> <% @Page Language="C#" Debug="true" Src="ViewGuestbook.cs" <br> Inherits="ViewGuestbook" %> </p><p>As you see, this Web form doesn’t really do all that much. It simply calls the codebehind file, ViewGuestbook.cs. Let’s take a look at this file.</p><p>Using System; <br> using System.Web; <br> using System.Web.UI; <br> using System.Web.UI.WebControls; <br> using System.Xml; <br> using System.Xml.Xsl; <br> using System.IO; </p><p>Public class ViewGuestbook: Page <br> { <br> private void Page_Load(object sender, System.EventArgs e) <br> { <br> //Load the XML file <br> XmlDocument doc = new XmlDocument(); <br> doc.Load(Server.MapPath("guestbook.xml")); </p><p> //Load the XSL file <br> XslTransform xslt = new XslTransform(); <br> xslt.Load(Server.MapPath("guestbook.xsl")); </p><p>String xmlQuery="//guestbook"; <br> XmlNodeList nodeList=doc.Document <br> Element.SelectNodes(xmlQuery); </p><p>MemoryStream ms=new MemoryStream(); <br> xslt.Transform(doc, null, ms); <br> ms.Seek(0, SeekOrigin.Begin); </p><p>StreamReader sr = new StreamReader(ms); </p><p> //Print out the result <br> Response.Write(sr.ReadToEnd()); <br> } <br> } </p><p>I’ve created this class to display all comments submitted through the guestbook to our users. Again, the first thing we do is implement the required namespaces, and, as we’re using XSL for the visualisation, we have to be sure to include the namespace System.Xml.Xsl .</p> <p>Then we create a new class called ViewGuestbook , with a private inbuilt function called Page_Load . This function is always called when the page loads, or when the user performs a refresh. Here, the function loads the guestbook.xml file, and then the XslTranform class is used to transform the XML elements into HTML before we load the guestbook.xsl with the help of a XslTransform object.</p> <p>Next, we create a new object of class XmlNodeList , which will allow us to select the required nodes. We then use the class MemoryStream , available via the namespace System.IO , to create a stream that has memory as a backing store, and use the Transform function to assign the xml data to this memory stream. The Seek function sets the current position to zero.</p> <p>We then create an object of the class StreamReader , which reads the stream, and print the result with the help of the function ReadToEnd() . This function reads the stream from the current position to the end. If you run viewguestbook.aspx, you should see a Web form like this:</p> <p><img src='https://i0.wp.com/sitepointstatic.com/graphics/webform2.gif' width="100%" loading=lazy></p> <h5>The XSL</h5> <p>As I’ve already mentioned, we use XSL for the transformation of the data from XML to HTML. I’ve assumed that you’re already experienced with XSLT, so I’ll only touch on the important aspects here. I have used an XSL for-each loop to iterate through all the guests in the book, which looks something like this:</p><p> <xsl:for-each select="//guest"> <br> <xsl:apply-templates select="name"/> <br> </xsl:for-each> </p><p>And in the loop we call the XSL template name, which looks something like this:</p><p> <xsl:template match="name"> <br> <xsl:value-of select="."/> <br> </xsl:template> </p><h5>Conclusion</h5> <p>As you see, it’s not very difficult to create a guestbook. Good luck! And don’t forget to .</p> <p>Here we start out with a simple "settings" file, named settings.asp. This file will be included on each page, and will contain the basic settings for this guestbook.</p> <p>Since the password (logincode) is NOT in the database, you can leave the database in the webroot with a mappath statement to make the install easier. However, the best place for the database is outside of your webroot, in which case you would want to change the database_path string to your full path ("C:\inetpub\database\post.mdb" for example)</p> <p>There is also an important settings to allow html, or not. Many times folks abuse a guestbook by filling it with links, and other junk. It would be a good idea to disallow html, unless you really need it.</p> <p>The language setting is just a set of variables for text used within the system, for each language there is a different text that is used. Very easy to add a "new" language to the system.</p> <h2>Details</h2> <p>The login is a simple login check page, which checks the login code entered on the form <br>with the one stored in the settings.asp file.</p> " title of your guestbook. pagetitle = " Demo" " language " <span>english = en, german = ger, french = fr </span> lang = " en" " admin password logincode = " 1234" " number of entries to show. show_posts = " 25" " <span>minimum length of post to be allowed. </span> minimum_length = 4 " <span>set to "no" for no html, set to "yes" to allow html (not recommended!) </span> allow_html = " no" " <span>leave as is, unless you want to move your database. </span> database_path = Server .MapPath(" post.mdb" ) <%Option Explicit %> <!--<span class=" code-comment" > #INCLUDE FILE=" settings.asp" --></ span > <% if Request .Form(" mynumber" ) = " " then response .redirect(" login.asp?l=password_blank" ) End If " set variables from form FormPwd = Request .Form(" mynumber" ) FormPwd = replace (FormPwd," "" ," """ ) " <span>run login or return to login page </span> if formpwd = logincode then Session(" LoginID" ) = formpwd else response .redirect(" <span>login.asp?l=incorrect_login_or_password" </span>) End if " final redirect response .redirect(" post.asp" ) %> <p>The login uses session variables to store the login information, so to log off we simple abandon the session. The redirect appends the date to avoid seeing a "cached" login page after being logged out. This is not a security issue, but just for convenience.</p><p> <% session.abandon response .redirect(" post.asp?d=" & date ) %> </p><p>Now the main code is the post.asp page, this page is the same whether you are logged in as admin or just a guest visiting the page. If you are logeed in you see the same data as a guest, only you have more options available, you can delete posts, or restore deleted posts, or empty the "recycle bin" (where deleted posts are stored until you clear them out).</p> <p><img src='https://i1.wp.com/codeproject.com/KB/asp/asp-guestbook/guestbook.jpg' width="100%" loading=lazy></p> <p>As you can see from the code below, we check for the loggedin session right from the start,<br>then we can use this throughout the rest of the script to display data based on your status as admin or guest.</p><p> <% option explicit %> <head> <!--<span class=" code-comment" > #INCLUDE FILE=" settings.asp" --></ span > <% LoggedIn = Session(" loginID" ) </p><p>Once you are logged in you see more options available.</p> <p><img src='https://i2.wp.com/codeproject.com/KB/asp/asp-guestbook/admin-deleted.jpg' width="100%" loading=lazy></p> <p>The file is split up into "parts" depending on what querystring is passed.</p> <p>The section below checks to see if you are logged in and then check so see if<br>you have attempted to empty the "deleted" items from the database.</p> " <span>============Empty Deleted Items from the database============ </span> If LoggedIn <> " " Then if request .querystring(" del" ) = 1 then Set dConn = Server .CreateObject (" ADODB.Connection" ) dConn.Open " & _ database_path mySQL = " <span>DELETE FROM tblpost where active = 2;" </span> dConn.execute(mySQL) dconn.close set dconn = nothing response .redirect(" post.asp" ) end if end if <p>As you can see from the rest of the main "post" code, different items are displayed or actions performed based on being logged in or not, and if so what querystring value you have passed to the page.</p> " <span>============set based on delete or undelete============ </span> If LoggedIn <> " " Then showdeleted = request .querystring(" showdeleted" ) if showdeleted = 1 then active = 2 removetype = 1 delete_text = undelete_text delimage = " undelete.gif" else active = 1 removetype = 2 delete_text = delete_text delimage = " delete.gif" end if else active = 1 end if " <span>============Delete/Undelete Items from the guestbook display============ </span> remove = request .querystring(" remove" ) if remove = 1 then Set dConn = Server .CreateObject (" ADODB.Connection" ) dConn.Open " <span>PROVIDER=MICROSOFT.JET.OLEDB.4.0;DATA SOURCE=" </span> & database_path removetype = request .querystring(" removetype" ) mySQL = " UPDATE tblPost SET Active = " & removetype & " WHERE ID = " & _ ID & " ;" response .write " updating" dConn.execute(mySQL) dConn.Close set dConn = Nothing response .redirect(" post.asp" ) end if " <span>============End Delete Section============ </span> Set dataRS = Server .CreateObject (" ADODB.RecordSet" ) dataSQL = " Select TOP " & show_posts & " <span> message, remote_addr, sysdate, " </span> &_ " <span> systime, id FROM tblPost WHERE active = " </span> & active &_ " <span> order by sysdate DESC, systime DESC;" </span> " Response.Write dataSQL " response.end Set dConn = Server .CreateObject (" ADODB.Connection" ) dConn.Open " <span>PROVIDER=MICROSOFT.JET.OLEDB.4.0;DATA SOURCE=" </span> & database_path dataRS.Open dataSQL, dConn, 1 , 3 recordcount = dataRS.recordcount if recordcount > 0 then data = dataRS.GetRows() " <span>Data is retrieved so close all connections </span> dataRS.Close Set dataRS = Nothing dconn.close set dconn = nothing " Setup for array usage iRecFirst = LBound (data, 2 ) iRecLast = UBound (data, 2 ) end if " <span>============IF IS A POST BACK============ </span> message = trim (request .form(" message" )) if request .form(" ispostback" ) = 1 AND (len (message) > minimum_length) then if allow_html = " no" then message = RemoveHTMLtags(message) else message = PreSubmit2(message) end if strSQL = " tblPost" " Open a recordset Set cRS2 = Server .CreateObject (" ADODB.recordset" ) Set dConn = Server .CreateObject (" ADODB.Connection" ) dConn.Open " <span>PROVIDER=MICROSOFT.JET.OLEDB.4.0;DATA SOURCE=" </span> &_ database_path cRS2.Open strSQL, dConn, 1 ,3 cRS2.AddNew cRS2(" message" ) = message cRS2(" sysdate" ) = date () cRS2(" systime" ) = time () cRS2(" remote_addr" ) = request .ServerVariables(" remote_addr" ) cRS2(" Active" ) = 1 cRS2.Update cRS2.Close Set cRS2 = Nothing dConn.Close Set dConn = Nothing response .redirect(" post.asp" ) end if " <span>============End POSTBACK Section============ </span> %> <title><%=pagetitle%> </ title > </ head > <P style=" FONT-WEIGHT: bold" ><%=pagetitle%> <table border=2 bordercolor=" silver" CELLSPACING=0 CELLPADDING=4> <form action=" post.asp" method=" post" name=" form1" id=" form1" > <tr class=" smalltext"> <td><textarea cols=" 50" rows=" 4" name=" message" style=" <span>font-family: Arial, Helvetica, sans-serif;" </span> class=" cssborder" title=" <%=add_text%>" ></ textarea > </ td > <td nowrap><input type=" submit" value=" <%=add_text%>" style=" height: 50px;" class=" cssborder" ></ td > </ tr > <input type=" hidden" name=" ispostback" value=" 1" > </ form > </ table > <% if recordcount > 0 then %> <table border=" 2" cellspacing=" 0" cellpadding=" 4" bordercolor=" silver" width=" 500" > <tr> <th><%= message_text %> </ th > <% If LoggedIn <> " " then %> <th><%= delete_text %> </ th > <% end if %> </ tr > <% " <span> Loop through the records (second dimension of the array) </span> For I = iRecFirst To iRecLast Response .Write " <tr class="smalltext">" & _ " <td colspan="top">" & data(0 , I) & " [" & data(3 ,I) & " | " & data(2 , I) & " | " & data(1 , I) & " ]</td>" if LoggedIn <> " " then response .write " <span><td nowrap valign="top" align="center">" </span> response .write " <A href="post.asp?id=" & data(4 , I) response .write " &remove=1&removetype=" & removetype response .write " "><img src='/wp-content/uploads/2023/" %20&%20delimage%20&%20' loading=lazy></A></td>" end if Next " I %> </ table > <% end if If LoggedIn <> " " Then response .write logoutlink else response .write loginlink end if " close db just in case on error resume next dConn.Close Set dConn = Nothing on error goto 0 %> <p>That is basically it, this is a very simple little guestbook, that should be easy to add to an site that supports ASP and MS Access database connections (No ODBC is necesary).</p> <script>document.write("<img style='display:none;' src='//counter.yadro.ru/hit;artfast_after?t44.1;r"+ escape(document.referrer)+((typeof(screen)=="undefined")?"": ";s"+screen.width+"*"+screen.height+"*"+(screen.colorDepth? screen.colorDepth:screen.pixelDepth))+";u"+escape(document.URL)+";h"+escape(document.title.substring(0,150))+ ";"+Math.random()+ "border='0' width='1' height='1' loading=lazy>");</script> </div> <div class="sidebar col-md-3"> <noindex> <div class="anchor_fix"></div> <div class="fixed_related" id="getFixed"> <div class='yarpp-related'> <div class="subscribe"> <ul class="related"> </ul> </div> </div> </div> <div id="vk_groups"></div> </div> </div> </noindex> </div> </div> </div> </div> </div> </div> <div class="footer"> <div class="container"> <div class="copyright pull-left"> © 2024 vspishkacraft.ru - Windows. Программы. Железо. Интернет. Безопасность. Операционные системы<br> <style type="text/css"> .madeby { margin: 10px 0; font-size: 12px; line-height: 15px; color: white; float: left; display: block; width: 240px; text-align: left; clear: right; padding-left: 40px; background-repeat: no-repeat; background-position: left center; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA+BpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDE0IDc5LjE1MTQ4MSwgMjAxMy8wMy8xMy0xMjowOToxNSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgKFdpbmRvd3MpIiB4bXA6Q3JlYXRlRGF0ZT0iMjAxNy0wMi0yNFQxMzozNjo1MSswMzowMCIgeG1wOk1vZGlmeURhdGU9IjIwMTctMDItMjRUMTM6MzcrMDM6MDAiIHhtcDpNZXRhZGF0YURhdGU9IjIwMTctMDItMjRUMTM6MzcrMDM6MDAiIGRjOmZvcm1hdD0iaW1hZ2UvcG5nIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjJDNDE4M0FFRkE3RDExRTY4RDA5RDBBNDU4QTVENTdDIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjJDNDE4M0FGRkE3RDExRTY4RDA5RDBBNDU4QTVENTdDIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6MkM0MTgzQUNGQTdEMTFFNjhEMDlEMEE0NThBNUQ1N0MiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MkM0MTgzQURGQTdEMTFFNjhEMDlEMEE0NThBNUQ1N0MiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6p6JuUAAAEDElEQVR42qyXz4sURxTHX1X1RMPuQSSJIMIqLBEMISxBgj8QQV13Z/Ym/gVCLvkLPOYPiIGI1z16yc0wTtRl1REU0bCCECQoiHiJASE60zPdPT2T76vqrq7qnh1n3RR8t6p7u9+n3qvXr2rEaDQir23M07bawvPx99e+2kkDeYIGYgn9oYD+r8bzT4V/786hfQCt4D5g6hTGs4AS9IvYtsf8+lAYaCoCjI/C8DLGDehrAxJk+0SDzwbb8pCBQ/EFAHXtVSrOUip3aUDqwLhPLLiD67sfA5aAfQvDK+jZMx5LA8uMpyWYD75NP9yPpgXvhs4AVM9gn2ehLVQOqVlLgBywUYsNTgJ/A9WhJYT1GIyrYi1lBhsH1eMYgHsY7wD4uAPl/zd98Mb8LP6eglY0jGhfKXHMeCA38/I1DP+uDQ/EGl142KHLx9YdIFEsntKP668MeGP+e/TnoRPQJ6XE8cPpr2GK8X30LR2+gXiiARceGkd+Pj5LiTpaQPUEmrmf7PEz6IiFDh3vrGcW+g+ujVeJvIXrt6XEKRaqH5zG9Y4MmEm0CvDC8za85qS5Ds1UkiYVz2D8Vxj+Df0f6IcTEqcAh6rh3U/kvxSpB8WnYcpcGwbrMNS1D8aZIvUpRXIV/SNoCMEbRz1HfM3t4hlBvaAOkVYIva/dpNVriQ/m9t1fbYpVHbCugSrSkEjNQXdgdH8VmBnuB+Y6zMA9tQDt1cAO9K7G4KZfDNx28k/AZR2gLrwkx7s5yMB7QdXL0JmEBgeL1NGwXEOotTmYW6TaMFaHup6HDO8B3mPPcy+zMLqT4fau1nCg8Lr2mNavvpkM7qsqvGeNG3gIeFha3y5D8GGcO7cbsCMl8I1q3R0HNmrD4DLUtSE1EwA8gOfBASdxXMgSeqVDzetr+uZ04CJx7iGkBu57OAfgbRg8kCWOq4aFchTC4A30qIyp1mo27JU51NwE+2uiK9SMvt/Psx0lsq8OZtnPz0r0i/ZTjJXZFP6+MvwwmJMmsSUurzgGHqkWQDMWFMmXzphBh/HeZ/678vq4HagKDhWVKk7+PSPsGTzK4SidsYXyZEvVSqCey7XpwL2AvOrVt4WEAYAj4WKGS4Y3bVgTPeGGLqP5MqXiAQ0uvZ0SrMh64UGze+x5LBl+Cf0LJ6x7oQW7TZqDX3Ozzb4K5oyMxoBjWfSccLE67YRUH+AgoYHF+XEL4Pc11zs3cYqNI99tEukeBpbJP7C+otFPTz8OHJegfuIUIR0KvESLJUs3Jx3iNgm1F9Y8caiUOO4Bfg9UK1lqTj6qVsC24lQ3gL6z3v6vhtfQMn+M+VbDP1q2Bu4GRi7UAlX1Z0rR2g78Lta3s7VQh4FfMvPPYzTV+TuHf/mhB/8TYAD5G5WwXg8pHgAAAABJRU5ErkJggg=='); } </style> </div> <ul id="menu-bottom-menu" class="bottom-menu pull-right"> <li id="menu-item-14" class="menu-item menu-item-type-post_type menu-item-object-page"><a href="/sitemap.xml">Карта сайта</a></li> <li class="menu-item menu-item-type-post_type menu-item-object-page"><a href="">Реклама</a></li> <li class="menu-item menu-item-type-post_type menu-item-object-page"><a href="/feedback.html">Контакты</a></li> </ul> </div> </div> <a id="to-top" href="#" class="scrollToTop"></a> <link rel='stylesheet' id='yarppRelatedCss-css' href='/wp-content/plugins/yet-another-related-posts-plugin/style/related.css?ver=9dc0bdd0f1d2506e0eda58c88609f331' media='all' /> <script type='text/javascript' src='/wp-content/themes/blank/js/lib/conditionizr-4.3.0.min.js?ver=9dc0bdd0f1d2506e0eda58c88609f331'></script> <script type='text/javascript' src='/wp-content/themes/blank/js/lib/modernizr-2.7.1.min.js?ver=9dc0bdd0f1d2506e0eda58c88609f331'></script> <script type='text/javascript' src='/wp-includes/js/jquery/jquery.js?ver=9dc0bdd0f1d2506e0eda58c88609f331'></script> <script type='text/javascript' src='/wp-includes/js/jquery/jquery-migrate.min.js?ver=9dc0bdd0f1d2506e0eda58c88609f331'></script> <script type='text/javascript' src='/wp-content/themes/blank/js/scripts.js?ver=9dc0bdd0f1d2506e0eda58c88609f331'></script> <script type='text/javascript' src='/wp-includes/js/comment-reply.min.js?ver=9dc0bdd0f1d2506e0eda58c88609f331'></script> <script type='text/javascript' src='/wp-includes/js/imagesloaded.min.js?ver=9dc0bdd0f1d2506e0eda58c88609f331'></script> <script type='text/javascript' src='/wp-includes/js/masonry.min.js?ver=9dc0bdd0f1d2506e0eda58c88609f331'></script> <script type='text/javascript' src='/wp-includes/js/jquery/jquery.masonry.min.js?ver=9dc0bdd0f1d2506e0eda58c88609f331b'></script> <script type='text/javascript' src='/wp-content/plugins/advanced-recent-posts/lptw-recent-posts.js?ver=9dc0bdd0f1d2506e0eda58c88609f331'></script> <script type='text/javascript' src='/wp-content/plugins/contact-form-7/includes/js/jquery.form.min.js?ver=9dc0bdd0f1d2506e0eda58c88609f331-2014.06.20'></script> <script type='text/javascript' src='/assets/scripts1.js'></script> <script type='text/javascript' src='//vspishkacraft.ru/wp-content/plugins/woocommerce/assets/js/jquery-blockui/jquery.blockUI.min.js?ver=9dc0bdd0f1d2506e0eda58c88609f331'></script> <script type='text/javascript' src='//vspishkacraft.ru/wp-content/plugins/woocommerce/assets/js/frontend/woocommerce.min.js?ver=9dc0bdd0f1d2506e0eda58c88609f331'></script> <script type='text/javascript' src='//vspishkacraft.ru/wp-content/plugins/woocommerce/assets/js/jquery-cookie/jquery.cookie.min.js?ver=9dc0bdd0f1d2506e0eda58c88609f331'></script> <script type='text/javascript' src='//vspishkacraft.ru/wp-content/plugins/woocommerce/assets/js/frontend/cart-fragments.min.js?ver=9dc0bdd0f1d2506e0eda58c88609f331'></script> <script type='text/javascript' src='/wp-content/plugins/optin-monster/assets/js/api.js?ver=9dc0bdd0f1d2506e0eda58c88609f331'></script> <script type='text/javascript' src='/wp-includes/js/wp-embed.min.js?ver=9dc0bdd0f1d2506e0eda58c88609f331'></script> <script type='text/javascript' src='/wp-content/plugins/disqus-comment-system/media/js/count.js?ver=9dc0bdd0f1d2506e0eda58c88609f331'></script> <script type="text/javascript">(window.Image ? (new Image()) : document.createElement('img')).src = location.protocol + '//vk.com/rtrg?r=YXkLp5Vwqs9VOMWfFWIads6jxBixx6wQyBkSJ0/Hg4WE7l3w2X85qYgv7X5VakufxBiqU5gywDqKku6fxSALURgdcV62OTDaFtTzE45QC4pQEML4f9Q7UhtvgO1g2wr9zg1bO6bL1u*sYLa5sLCeA7pR51y8cE2HUSPPCKbldn8-';</script> <script type="text/javascript" src="/wp-content/themes/blank/javascript.js"></script> <script type="text/javascript" src="//vk.com/js/api/openapi.js?116"></script> <script type="text/javascript" src="/wp-content/themes/blank/js/readmore.min.js"></script> <script type="text/javascript"> jQuery(document).ready(function() { jQuery('.click_menu').click(function() { jQuery('.mobile_menu .list_menu').toggle('normal'); return false; } ); jQuery('.container').click(function() { jQuery('.mobile_menu .list_menu').hide('normal'); } ); // jQuery('.vis .click_menu').click(function() { // jQuery('.vis.mobile_menu').addClass('hide').removeClass('vis'); // } ); } ); </script> <script type="text/javascript"> jQuery(document).ready(function() { jQuery('.fixed_related .entry-image').height((jQuery(window).height()/3)-130); jQuery(function($) { function fixDiv() { if (jQuery( ".anchor_fix" ).length > 0) { var $cache = $('#getFixed'); if ($(window).scrollTop() > jQuery( ".anchor_fix" ).position().top+100) $cache.css({ 'position': 'fixed', 'top': '10px' } ); else $cache.css({ 'position': 'relative', 'top': 'auto' } ); } } $(window).scroll(fixDiv); if (jQuery( ".anchor_fix" ).length > 0) fixDiv(); } ); } ); </script> </body> </html>