Создание контроллеров в ExtJS. Создание контроллеров в ExtJS Получение версии WEB сервера

USSCLTD 10 мая 2016 в 12:38

Ищем уязвимости с помощью google

  • Информационная безопасность

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

Как такое возможно?
Поисковые роботы, безостановочно бродящие по просторам интернета, помимо информации, полезной обычному пользователю, часто фиксируют то, что может быть использовано злоумышленниками при атаке на веб-ресурс. Например, ошибки скриптов и файлы с чувствительной информацией (начиная от конфигурационных файлов и логов, заканчивая файлами с аутентификационными данными и бэкапами баз данных).
С точки зрения поискового робота сообщение об ошибке выполнения 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 – <a href="/chto-takoe-sochetanie-klavish-goryachie-klavishi-na-standartnoi-klaviature-vvod/">Специальные символы</a> запросов 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://i2.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://i2.wp.com/habrastorage.org/getpro/habr/post_images/b8f/b11/ffe/b8fb11ffeaced5066fd2fd9e43be67fb.jpg' width="100%" loading=lazy></p><p>Рисунок 2 - Список доступных категорий дорков GHDB</p><p>Командой google будет произведена подстановка каждого дорка в <a href="/chto-delat-esli-poiskovik-google-postoyanno-trebuet-vvesti-kapchu-recaptcha/">поисковик google</a> и проанализирован результат на предмет совпадений. Дорки по которым что-то нашлось будут сохранены в файл.<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://i2.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://i2.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://i1.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://i1.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 страниц, то глупо что-либо искать подобным образом. Проверить размер индекса просто - достаточно ввести в строку <a href="/google-scholar-akademiya-google-biblioteka-nauchnyh-statei-poisk-katalogi-ogranicheniya/">поиска google</a> «site:somesite.com». Пример сайта с недостаточным индексом показан на рисунке 14.<br><br><img src='https://i0.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>Последнее обновление: 1.11.2015</p> <p>Контроллер является ключевым звеном, который связывает все части приложения воедино и заставляет их работать. Добавим в каталог <i>BookApp/app/controller </i> файл <i>Books.js </i> со следующим содержанием:</p><p>Ext.define("BookApp.controller.Books", { extend: "Ext.app.Controller", views: ["BookList", "Book"], stores: ["BookStore"], models: ["Book"], init: function() { this.control({ "viewport > booklist": { itemdblclick: this.editBook }, "bookwindow button": { click: this.createBook }, "bookwindow button": { click: this.updateBook }, "bookwindow button": { click: this.deleteBook }, "bookwindow button": { click: this.clearForm } }); }, // обновление updateBook: function(button) { var win = button.up("window"), form = win.down("form"), values = form.getValues(), id = form.getRecord().get("id"); values.id=id; Ext.Ajax.request({ url: "app/data/update.php", params: values, success: function(response){ var data=Ext.decode(response.responseText); if(data.success){ var store = Ext.widget("booklist").getStore(); store.load(); Ext.Msg.alert("Обновление",data.message); } else{ Ext.Msg.alert("Обновление","Не удалось обновить книгу в библиотеке"); } } }); }, // создание createBook: function(button) { var win = button.up("window"), form = win.down("form"), values = form.getValues(); Ext.Ajax.request({ url: "app/data/create.php", params: values, success: function(response, options){ var data=Ext.decode(response.responseText); if(data.success){ Ext.Msg.alert("Создание",data.message); var store = Ext.widget("booklist").getStore(); store.load(); } else{ Ext.Msg.alert("Создание","Не удалось добавить книгу в библиотеку"); } } }); }, // удаление deleteBook: function(button) { var win = button.up("window"), form = win.down("form"), id = form.getRecord().get("id"); Ext.Ajax.request({ url: "app/data/delete.php", params: {id:id}, success: function(response){ var data=Ext.decode(response.responseText); if(data.success){ Ext.Msg.alert("Удаление",data.message); var store = Ext.widget("booklist").getStore(); var record = store.getById(id); store.remove(record); form.getForm.reset(); } else{ Ext.Msg.alert("Удаление","Не удалось удалить книгу из библиотеки"); } } }); }, clearForm: function(grid, record) { var view = Ext.widget("bookwindow"); view.down("form").getForm().reset(); }, editBook: function(grid, record) { var view = Ext.widget("bookwindow"); view.down("form").loadRecord(record); } }); </p><p>Теперь разберем код контроллера. Во-первых, мы наследуем его от класса Ext.app.Controller и устанавливаем для контроллера ранее созданные представления, модели и хранилища:</p><p>Views: ["BookList", "Book"], stores: ["BookStore"], models: ["Book"], </p><p>Далее в параметре init с помощью функции мы инициализируем обработчики кнопок, которые у нас находятся в представлении. Связать обработчики с компонентами помогает функция control . Эта функция использует класс Ext.ComponentQuery , который позволяет с помощью селектор в стиле CSS найти элементы. Например, выражение "viewport > booklist" ищет элементы с псевдонимом booklist, которые определены в компоненте viewport. Данный селектор будет в итоге получать представление BookList.</p> <p>А выражение "bookwindow button" получит кнопку button, у которой свойство action имеет значение new и которая находится в элементе bookwindow, то есть в представлении Book, которое имеет псевдоним bookwindow. Таким образом, если вы знакомы с селекторами CSS, то вам не составит труда в понимании работы селекторов и в ExtJS.</p> <p> "viewport > booklist": { itemdblclick: this.editBook } </p><p>Все функции обработчиков определены после функции init . Обработчик this.editBook загружает выбранную модель в окно:</p><p>EditBook: function(grid, record) { var view = Ext.widget("bookwindow"); view.down("form").loadRecord(record); } </p><p>С помощью метода Ext.widget мы находим нужный компонент по селектору Ext.ComponentQuery (этот выражение было бы аналогично выражению Ext.create("widget.bookwindow")) и затем получаем его дочерний элемент с помощью метода down , также по селектору. И далее загружаем в форму выбранную модель.</p> <p>После загрузки модели мы можем воспользоваться тремя возможностями: добавить новую книгу, изменить выбранную или удалить выбранную. И тут в дело вступают обработчики этих кнопок. Поскольку обработчики однотипны, разберем один из них.</p> <p>Обработчик updateBook получает данные измененной книги и отправляет ajax-запрос на сервер:</p><p>UpdateBook: function(button) { var win = button.up("window"), form = win.down("form"), values = form.getValues(), id = form.getRecord().get("id"); values.id=id; Ext.Ajax.request({ url: "app/data/update.php", params: values, success: function(response){ var data=Ext.decode(response.responseText); if(data.success){ var store = Ext.widget("booklist").getStore(); store.load(); Ext.Msg.alert("Обновление",data.message); } else{ Ext.Msg.alert("Обновление","Не удалось обновить книгу в библиотеке"); } } }); }, </p><p>Обработчик в качестве параметра получает нажатую кнопку и затем, используя метод up мы можем получить родительские элементы по отношению к этой кнопке: function(button) {var win= button.up("window")...</p> <p>Выражением values = form.getValues() мы получаем все значения полей формы, но поскольку при изменении при взаимодействии с бд, например, требуется id, то затем добавляем к переменной values еще и id обновляемой модели.</p> <p>Далее отправляем ajax-запрос с новыми данными книги на сервер, передавая запросу в качестве параметра переменную values. Принимающий файл <i>update.php </i> (который, как предполагается, находится в папке <i>BookApp/app/data </i>) мог бы так получать переданные параметры:</p><p> <?php $id = $_POST["id"]; $name = $_POST["name"]; $author = $_POST["author"]; $year = $_POST["year"]; // далее проводим обработку полученных данных echo "{ "success": true, "message":"Книга: " . $id . ". " . $name . " (" . $author . ") обновлена"}"; ?> </p><p>И в конце в функции success мы смотрим на результат, который посылает в ответ сервер, и если все прошло успешно, то загружаем обновленные данные с сервера.</p> <p>По похожему принципу действуют остальные два обработчика.</p> <p>И в самом конце изменим файл приложения <i>app.js </i>, чтобы он принимал созданный выше контроллер следующим образом:</p><p>Ext.application({ requires: ["Ext.container.Viewport"], name: "BookApp", appFolder: "app", controllers: ["Books"], launch: function() { Ext.create("Ext.container.Viewport", { layout: "fit", items: { xtype: "booklist" } }); } }); </p><p>В свойстве controllers: ["Books"] указываем созданный выше контроллер.</p> <p>Теперь приложение готово и его можно запускать:</p> <p>Таким образом, мы можем применять паттерн MVC к построению приложений на Ext JS.</p> <p>Returns: jqXHR </p> <p>Выполняет асинхронный HTTP (Ajax) запрос</p> <ul><li><h4>version added: <a>1.5</a> jQuery.ajax(url [, settings])</h4> <p><b>url </b><br><b>Тип </b>: Строка<br> URL адрес, на который будет отправлен Ajax запрос</p> <p><b>settings </b><br><b>Тип </b>: Объект<br> Набор параметров вида ключ / значение, которые настраивают запрос Ajax. Все настройки опциональны. По умолчанию настройки берутся из . Ниже приведен полный список всех настроек.</p></li> <li><h4>version added: <a>1.0</a> jQuery.ajax(settings)</h4> <p><b>settings </b><br><b>Тип </b>: Объект<br> Набор параметров вида ключ / значение, которые настраивают запрос Ajax. Все настройки опциональны. По умолчанию настройки берутся из .</p></li> </ul><h2>settings:</h2> <table style="width: 100%;" border="0"><tr><td>Настройка </td> <td style="width: 50px;">Тип данных </td> </tr><tbody><tr><td> <h5>accepts</h5> <p>По умолчанию: <b>зависит от типа данных </b></p> <p>При выполнении ajax-запроса, в заголовках (header) указываются допустимые типы содержимого, ожидаемого от сервера. Значения этих типов будут взяты из параметра accepts . Если требуется его изменить, лучше сделать это с помощью метода <a href="jquery.php?id=12">$.ajaxSetup()</a> .</p> </td> <td class="center">объект </td> </tr><tr><td> <h5>async</h5> <p>По умолчанию: <b>true </b></p> <p>По умолчанию, все запросы отсылаются асинхронно (значение данного параметра true). Если же вам нужны синхронные запросы, то параметру async выставите значение false. Кроссдоменные запросы и dataType: "jsonp" не выполняются в синхронном режиме. Учтите, синхронные запросы могут на время выполнения запроса заблокировать браузер.</p> </td> <td class="center">логический </td> </tr><tr><td> <h5>beforeSend(jqXHR jqXHR, объект settings) </h5> <p>Функция, которая будет вызвана непосредственно перед отправкой ajax-запроса на сервер. Она может быть использована для модификации jqXHR-объекта (в <a href="/kak-polnostyu-udalit-sledy-kontinent-ap-udalenie-abonentskogo/">ранних версиях</a>, до jQuery 1.4.x использовался XMLHttpRequest). Так же может использоваться для изменения заголовков (headers) и т.д. Объект типа jqXHR и объект настроек, передаются в качестве аргументов. Возврат значения false в функции beforeSend вызовет отмену ajax-запроса. <b>Начиная с jQuery 1.5 </b>, beforeSend сработает вне зависимости от типа запроса.</p> </td> <td class="center">функция </td> </tr><tr><td> <h5>cache</h5> <p>По умолчанию: <b>true </b>, <b>false </b>для типов данных "script" and "jsonp"</p> <p>Если false, запрашиваемая страница не будет кэшироваться браузером.</p> </td> <td class="center">логический </td> </tr><tr><td> <h5>complete(jqXHR jqXHR, строка textStatus)</h5> <p>Функция, которая будет вызвана после завершения ajax запроса (срабатывает после функций-обработчиков success и error). Функция принимает два аргумента: объект типа jqXHR (в ранних версиях, до jQuery 1.4.x использовался XMLHttpRequest) и строку, характеризующую статус запроса ("success", "notmodified", "error", "timeout", "abort", или "parsererror"). <b>Начиная с jQuery 1.5 </b>, complete может принимать массив функций.</p> </td> <td class="center">функция или массив </td> </tr><tr><td> <h5>contents</h5> <p>Параметр задается в формате {строка:регулярное выражение} и определяет, как jQuery будет разбирать ответ от сервера, в зависимости от его типа. <span><b>(добалено в версии 1.5) </b> </p> </td> <td class="center">объект </td> </tr><tr><td> <h5>contentType</h5> <p>По умолчанию: <b>"application/x-www-form-urlencoded; charset=UTF-8" </b></p> <p>При отправке Ajax запроса, данные передаются в том виде, в котором указаны в данном параметре. По умолчанию используется "application/x-www-form-urlencoded; charset=UTF-8". Если задать значение самим, то оно будет отправлено на сервер. Если кодировка не указана, то по умолчанию будет использоваться кодировка выставленная на сервере.</p> </td> <td class="center">строка </td> </tr><tr><td> <h5>context</h5> <p>Объект, который станет контекстом после выполнения запроса (передаваемое значение в переменную this). Например, если указать в качестве контекста DOM-элемент, то все обработчики ajax-запроса тоже будут выполняться в контексте данного DOM-элемента. В данном примере ключевое слово this будет содержать document.body:</p><p> $.ajax({ url: "test.html", context: document.body, success: function(){ $(this).addClass("done"); } }); </p></td> <td class="center">объект </td> </tr><tr><td> <h5>converters</h5> <p>По умолчанию: {"* text": window.String, "text html": true, "text json": jQuery.parseJSON, "text xml": jQuery.parseXML}</p> <p>Определяет, с помощью каких функций будет производиться конвертация значений из одного типа, в другой. <span>(добалено в версии 1.5) </p> </td> <td class="center">объект </td> </tr><tr><td> <h5>crossDomain</h5> <p>По умолчанию: false для одного и того же домена, true для кроссбоменных запросов.</p> <p>Если вы хотите, чтобы выполнить кросс-доменный запрос (например, JSONP) на том же домене, выставите true в настройке crossDomain. Это позволяет, например, сделать серверные перенаправление на другой домен. <span>(добалено в версии 1.5) </p> </td> <td class="center">логический </td> </tr><tr><td> <h5>data</h5> <p>Данные, которые будут переданы на сервер. Если данные не являются строкой, то они конвертируются в строку запроса. Для запросов типа GET данные прикрепляются к URL. Объект должен состоять из пар <b>ключ/значение </b>. Если в значении массив, то jQuery упорядочивает значения в зависимости от настройки traditional. По умолчанию, например, {foo:["bar1", "bar2"]} превращается в <b>&foo=bar1&foo=bar2 </b>.</p> </td> <td class="center">объект или строка </td> </tr><tr><td> <h5>dataFilter(строка data, строка type)</h5> <p>Функция, с помощью которой будут обрабатываться сырые данные типа XMLHttpRequest, полученные от сервера. Ваша функция должна играть роль фильтра и возвращать очищенную строку. В функцию передаются два параметра: полученные данные и значение параметра dataType.</p> </td> <td class="center">функция </td> </tr><tr><td> <h5>dataType</h5> <p>По умолчанию: автоматически определяемая строка (xml, json, script, или html)</p> <p>Тип данных, ожидаемых от сервера. Если опция не определена, то jQuery попытается определить тип, основываясь на MIME-типе ответа.</p> </td> <td class="center">строка </td> </tr><tr><td> <h5>error(jqXHR jqXHR, строка textStatus, строка errorThrown)</h5> <p>Функция, исполняемая в случае неудачного запроса. Принимает 3 аргумента: объект jqXHR (в прошлом XMLHttpRequest), строку с описанием ошибки, а так же строку исключения, если оно было выбрашено. Второй аргумент может содержать следующие значения: null, "timeout", "error", "abort", и "parsererror". В случае если происходит HTTP ошибка, то в третий аргумент будет записан её текстовой статус. К примеру, "Not Found" или "Internal Server Error.". Начиная с jQuery 1.5, вместо одной функции, этот параметр может принимать массив функций. <i>Событие error не происходит при dataType равному script или JSONP. </i></p> </td> <td class="center">функция или массив </td> </tr><tr><td> <h5>global</h5> <p>По умолчанию: <b>true </b>.</p> <p>Вызывать или нет глобальные обработчики событий Ajax для этого запроса (например ajaxStart или ajaxStop).</p> </td> <td class="center">логический </td> </tr><tr><td> <h5>headers</h5> <p>По умолчанию<b>: </b>{}</p> <p>Здесь можно указать дополнительные заголовки запроса (header). Значения этой настройки будут введены до вызова функции beforeSend, в которой могут быть внесены окончательные изменения в заголовки. <span>(добалено в версии 1.5) </p> </td> <td class="center">объект </td> </tr><tr><td> <h5>ifModified</h5> <p>По умолчанию: <b>false </b></p> <p>Запрос будет считаться успешным только в случае, если данные ответа изменились со времени последнего запроса. Проверка осуществляется по заголовку Last-Modified. По умолчани, данная опция отключена. В jQuery 1.4 так же проверяется значение "etag", для отслеживания факта изменения данных.</p> </td> <td class="center">логический </td> </tr><tr><td> <h5>isLocal</h5> <p>По умолчанию: <b>в зависимости от текущей локации </b></p> <p>Параметр определяет, запущена ли веб-страница локально (например по протоколу file, *-extension, и widget) или нет (например по протоколу http). Данную настройку лучше менять с помощью метода <a href="jquery.php?id=12">$.ajaxSetup()</a> . <span>(добалено в версии 1.5) </p> </td> <td class="center">логический </td> </tr><tr><td> <h5>jsonp</h5> <p>Определяет имя параметра, который добавляется в url JSONP-запроса(по умолчанию, используется "callback"). К примеру настройка {jsonp:"onJSONPLoad"} преобразуется в часть url строки "onJSONPLoad=?". <b>Начиная с версии 1.5 </b>, указание в этом параметре false предотвращает добавление в url дополнительного параметра. В этом случае, необходимо установить значение настройки jsonpCallback. Например так: {jsonp:false, jsonpCallback:"callbackName"}.</p> </td> <td class="center">строка </td> </tr><tr><td> <h5>jsonpCallback</h5> <p>Функция, которая будет вызвана при ответе сервера на запрос типа JSONP. По умолчанию, jQuery генерирует произвольное уникальное имя этой функции, что более предпочтительно. Если вы хотите использовать кэширование GET запросов, то вписывайте название функции сами. <b>Начиная с версии 1.5 </b> можно указать функцию, для того, чтобы обработать ответ сервера самостоятельно.</p> </td> <td class="center">строка или функция </td> </tr><tr><td> <h5>mimeType</h5> <p>Здесь можно указать тип данных, в котором ожидается ответ от сервера вместо XHR. <span>(добалено в версии 1.5.1) </p> </td> <td class="center">строка </td> </tr><tr><td> <h5>password</h5> <p>Пароль, который будет использоваться в ответ на запрос проверки подлинности доступа HTTP (если это требуется)</p> </td> <td class="center">строка </td> </tr><tr><td> <h5>username</h5> <p>Имя пользователя, которое будет использоваться в ответ на запрос проверки подлинности доступа HTTP (если это требуется)</p> </td> <td class="center">строка </td> </tr><tr><td> <h5>processData</h5> <p>По умолчанию: <b>true </b>;</p> <p>По умолчанию передаваемые на сервер данные преобразуются из объекта в строку запроса и отправляются как "application/x-www-form-urlencoded". Если вам необходимо отправить DOM-документ или иные данные, которые нельзя подвергать конвертированию установите опцию processData в false.</p> </td> <td class="center">логический </td> </tr><tr><td> <h5>scriptCharset</h5> <p>Применяется только для Ajax GET-запросов типов "JSONP" и "script ". Если сервер на стороннем домене использует кодировку, отличную от вашей, необходимо указать кодировку стороннего сервера.</p> </td> <td class="center">строка </td> </tr><tr><td> <h5>statusCode</h5> <p>По умолчанию: {}</p> <p>Набор пар, в котором кодам выполнения запроса сопоставляются функции, которые при этом будет вызваны. Например, для кода 404 (страницы не существуют) можно сделать вывод сообщения на экран:</p><p> $.ajax({ statusCode:{ 404:function(){ alert("Страница не найдена"); } } }); </p><p>Если запрос прошёл успешно, то в качестве параметра, анонимная функция будет принимать те же параметры, что и при success. При ошибке, будет принимать то же самое что и при функции-обработчике error. <b>(добалено в версии 1.5) </b></p> </td> <td class="center">объект </td> </tr><tr><td> <h5>success(объект data, строка textStatus, объект jqXHR)</h5> <p>Функция, которая будет вызвана в случае успешного завершения запроса. Принимает 3 аргумента - данные (<b>data </b>), присланные сервером и прошедшие предварительную обработку; строка со статусом выполнения (textStatus); объект jqXHR (в версиях до 1.5 вместо jqXHR используетсяXMLHttpRequest). <i>С версии jQuery 1.5, вместо одной функции, этот параметр может принимать массив функций. </i></p> </td> <td class="center">функция или массив </td> </tr><tr><td> <h5>timeout</h5> <p>Время ожидания ответа от сервера в миллисекундах. Переписывает глобальную настройку этого же параметра в $.ajaxSetup(). Если это время будет превышено, запрос будет завершен с ошибкой и произойдет <a href="/raskryvaya-tainy-windows-kak-rabotaet-sluzhba-registracii-oshibok/">событие error</a>, которое будет иметь статус "timeout".</p> </td> <td class="center">число </td> </tr><tr><td> <h5>traditional</h5> <p>По умолчанию: <b>false </b></p> <p>Установите значение этого параметра в true, для того, чтобы использовать традиционный стиль сериализации.</p> </td> <td class="center">логический </td> </tr><tr><td> <h5>type</h5> <p>По умолчанию: <b>GET </b></p> <p>Определяет тип запроса GET или POST. Можно также использовать другие HTTP-запросы (такие как PUT или DELETE), но следует помнить, что они поддерживаются не всеми бразерами.</p> </td> <td class="center">строка </td> </tr><tr><td> <h5>url</h5> <p>По умолчанию: <b>текущая страница. </b></p> <p>Страница, накоторую будет отправлен запрос.</p> </td> <td class="center">строка </td> </tr><tr><td> <h5>xhr</h5> <p>По умолчанию <b>ActiveXObject в IE, XMLHttpRequest в других браузерах. </b></p> <p>Callback-функция, для создания объекта XMLHttpRequest. Создав свою функцию, вы берёте на себя всю ответственность за формирование объекта.</p> </td> <td class="center">function </td> </tr><tr><td> <h5>xhrFields</h5> <p>Объект вида {имя:значене} для изменения значений соответствующих полей объекта XMLHttpRequest .</p><p> $.ajax({ url: a_cross_domain_url, xhrFields: { withCredentials: true } }); </p><p>(добалено в версии 1.5.1) </p> </td> <td class="center">map </td> </tr></tbody></table><p> $.ajax({ type: "POST", url: "some.php", data: { name: "John", location: "Boston" } }).done(function(msg) { alert("Data Saved: " + msg); }); </p><p>Получить <a href="/obnovlenie-brauzera-google-chrome-zachem-kak-i-chto-delat-pri-oshibkah-bystroe/">последнюю версию</a> HTML страницы</p><p> $.ajax({ url: "test.html", cache: false }).done(function(html) { $("#results").append(html); }); </p><p>Передаём в качестве данных <a href="/podpis-dokumentov-failov-xml-ecp-elektronno-cifrovoi-podpisyu/">XML документ</a>. Отключаем автоматическую конвертацию данных в обычную строку, задав настройке processData значение false:</p><p>Var xmlDocument = ; var xmlRequest = $.ajax({ url: "page.php", processData: false, data: xmlDocument }); xmlRequest.done(handleResponse); </p><p>Var menuId = $("ul.nav").first().attr("id"); var request = $.ajax({ url: "script.php", type: "POST", data: {id: menuId}, dataType: "html" }); request.done(function(msg) { $("#log").html(msg); }); request.fail(function(jqXHR, textStatus) { alert("Request failed: " + textStatus); }); </p><p>Загрузить и выполнить файл JavaScript:</p><p> $.ajax({ type: "GET", url: "test.js", dataType: "script" }); </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> </article> </div> <div class="cont_banner"> <div> </div> <div> </div> </div> <div class="cont_figSmall"> <p>Последние материалы раздела:</p> <section> <figure style='vertical-align:top;'> <a href="/kakoi-router-ne-snizhaet-skorost-interneta-pochemu-rezhetsya/"><img src="https://i0.wp.com/bazava.ru/wp-content/uploads/2018/e9e97-kak-uvelichit-skorost-vay-fay-routera4-min.jpg" style="width:80px" alt="Почему режется скорость Интернета по WiFi: Бесплатные советы как ускорить передачу данных" loading=lazy></a> <figcaption> <a class="anonstitle" href="/kakoi-router-ne-snizhaet-skorost-interneta-pochemu-rezhetsya/">Почему режется скорость Интернета по WiFi: Бесплатные советы как ускорить передачу данных</a> <p class='fig_article'>Плохая скорость интернета через роутер - одна из наиболее «популярных» проблем всех любителей беспроводного соединения . В предыдущих статьях мы...</p> </figcaption> </figure> <figure style='vertical-align:top;'> <a href="/vse-o-kontekstnom-menyu-kompyutera-kontekstnoe-menyu-v-windows-osnovnye/"><img src="https://i1.wp.com/steptosleep.ru/wp-content/uploads/2018/06/90464.png" style="width:80px" alt="Контекстное меню в Windows" loading=lazy></a> <figcaption> <a class="anonstitle" href="/vse-o-kontekstnom-menyu-kompyutera-kontekstnoe-menyu-v-windows-osnovnye/">Контекстное меню в Windows</a> <p class='fig_article'>Из этой информационной статьи вы узнаете о том, как вызвать контекстное меню для любого файла, папки, ярлыка и т.п используя для этого несколько...</p> </figcaption> </figure> <figure style='vertical-align:top;'> <a href="/prodvizhenie-v-instagramme-samostoyatelno-prodvizhenie-v-instagram/"><img src="https://i2.wp.com/businessman.ru/static/img/a/23597/240148/29262.jpg" style="width:80px" alt="Продвижение в Instagram: самая подробная инструкция" loading=lazy></a> <figcaption> <a class="anonstitle" href="/prodvizhenie-v-instagramme-samostoyatelno-prodvizhenie-v-instagram/">Продвижение в Instagram: самая подробная инструкция</a> <p class='fig_article'>XXI век - стремительно меняющийся и ломающий прежние представления об успехе. Социальные сети стали феноменом, люди часами проводят время в режиме...</p> </figcaption> </figure> </section> </div> <dblock></dblock> <dblock></dblock> </div> <aside> <div> <div class="accordion"> <ul> <li><a href="/">Рубрики</a> <ul class='menu2' style="display:block;padding-top:15px;"> <li><a href="/category/windows/">Windows</a></li> <li><a href="/category/accessories/">Аксессуары</a></li> <li><a href="/category/internet/">Интернет</a></li> <li><a href="/category/computer-hardware/">Компьютерное железо</a></li> <li><a href="/category/mobile/">Мобильные </a></li> <li><a href="/category/soft/">Софт</a></li> <li><a href="/category/social-networks/">Социальные сети</a></li> </ul> </li> </ul> </div> <dblock></dblock> <div class="box" style="margin-left:5px"> <br> <div align='center'> </div> <span id="place"></span> </div> </div> </aside> </main> <footer> <div class="foot_logo"> <a href="/"><img src="/img/logo.svg" alt="logo" loading=lazy></a> </div> <div class="foot_info"> <p>© Эра технологий <span>BIMTEX.RU</span>, 2024</p> <p>Все статьи, расположенные на сайте, несут лишь ознакомительный характер. </p> <dblock></dblock> </div> <div class="foot_ico"> </div> <SCRIPT language="Javascript"> var delta = 0; $(document).ready(function() { $(window).scroll(function() { var ScrollTo = $('#place').offset().top; if ($(window).scrollTop() > ScrollTo) { $('#float-box').animate({ 'top': delta + 'px' }, 500); } else $('#float-box').stop(true).animate({ 'top': '5600px' }, 100); }); $('#float-box .close').bind('click', function() { $(this).parent().remove(); }); }); </script> </footer> </div> <div class="overlay"></div> </body> </html>