Методика полного копирования сайта.
Стаття з журналу Хакер за 5-тий місяць 2009р.
Вступление
Сейчас стало модным делать сайт и называть его словом "стартап". Этим занимаются все кому не лень. Ну и мы жить не сможем без своего стартапа. Но ведь самим писать же лень, да и писать - не наш метод. Лучше возьмем сайт соседа и полностью со всей функциональностью скопируем. А потом лишь внизу подпишем своим именем ;)
Процес копирования сайта from presidentua on Vimeo.
Когда-то вечером, перебирая клейкие листочки на сайте zapisochki.ru, поймал себя на мысли, о том, что владелец сервисе может в теории читать все о чем я написал, и главный вопрос даже не во владельце, ведь мои любимые спецслужбы также могут это делать. Отказываться же от сервиса я не мог в связи с его качеством и полезностью, поэтому решил взломать сервер, скопировать все исходники и установить их себе. Сразу в бой за доступ вступили разные приемы проверки на иньекции, инклуды, простые пароли и прочее. Но эта идея с грохотом провалилась, правда взамен родилась новая-старая идея, которая просто не могла не реализоваться. Но прервемся немного и посмотрим, что собой представляет сайт zapisochki.ru.
Записочки
Сервис он-лайн записочек очень простой, и эта простота притягивает. После захода на сайт весь экран браузера пустой. Если нажать где-то на пустом месте, то появится клейкий листочек - квадратик в котором можно писать текст, и потом его редактировать. Также есть в углу маленький квадратик, нажимая на который можно изменять цвет листочка. И есть крестик, которым удаляется записочка. Весь интерфейс выполнен с полнейшим использованием AJAX, и страница при роботе не перегружается. Вся рабочая поверхность, на которой находятся записочки, называется доска (board) и она имеет уникальный идентификатор, что отображается в URL. Эту информацию я тебе рассказал, потому что без нее сложно будет понимать статью. Хотя, наверно, лучше будет, если перед прочтением зайдешь на сайт и сам попробуешь функционал.
Возрождения старой методики
Вернемся к рассмотрению мегастарой методике, которая сейчас снова возрождается. Итак, раньше все сайты были статические - состояли с HTML файлов и картинок. Все это добро отдается браузеру полностью для отображения. Раньше, для того чтобы скопировать полностью сайт, нужно было всего лишь запустить программу, которая будет открывать все ссылки на сайте и сохранять все что отдает сервер. Дальше пришла динамика в мир Веба, и копирование сайта стало чрезвычайно трудной задачей. К примеру, есть форум с сообщениями, даже если пройдется бот по нему и сохранит все страницы, то это ничего не даст. Ведь практически весь функционал заброшен в скрипты, которые остаются для нас закрытыми... Тенденции к упрощению функционала не наблюдается и, казалось бы, скопировать сайт стало невозможно... Но тут пришла эра Веб2.0 и одним с ее аспектов есть перенос большой части функционала с серверного уровня на браузерный, на JavaScript... а ведь он отдается нам в открытом виде! Чем больше будет система работать на стороне браузера, тем меньше есть кода на сервере - скрытого от нас кода. И этот маленький участок кода можно уже и самому дописать, ведь это же мелочь по сравнению с той частью, что мы без проблем скопируем. Ну, теория может быть немного непонятно, но после практики, думаю, все станет на свои места. В качестве примера был выбран сайт zapisochki.ru. В нем много функциональности находится на стороне JavaScript, а на стороне сервера лишь выполняются несколько запросов по сохранению, обновлению и удалению клейких листочков. Тоесть, если с эмулировать эти несколько запросов, то можно будет полностью скачать с сайта все остальное. Правда все не совсем просто, и сперва нужно понять полностью как работает приложение, какими командами обменивается серверная и клиентская часть, как генерируется первая страница и другое. Давайте пошагово пройдемся по всему процессу полного клонирования.
Инструменты
Для того что бы разобраться с работой сайта лучший инструмент для меня это FireFox с установленными 3 плагинами:
- Temper Data (https://addons.mozilla.org/en-US/firefox/addon/966) для просмотра, перехвата и изменения запросов;
- Web Developer (https://addons.mozilla.org/en-US/firefox/addon/60) для отключения кеша браузера, для просмотра и удаления кукисов;
- FireBug (https://addons.mozilla.org/en-US/firefox/addon/1843) для отладки JavaScript и анализа запросов.
Также необходим Offline Browser для скачивания всего сайта (триальная версия есть на http://www.metaproducts.com/mp/Portable_Offline_Browser.htm, или у нас на диске).
Этапы копирования
Копирования сайта записочки состоит со следующих этапов:
- анализ и эмуляция идентификации;
- копирование страници с записочками;
- анализ протокола обмена клиентской части с серверной;
- анализ генерации главной страницы;
- программинг серверной части.
В результате мы получим полностью рабочий сайт zapisochki.ru у себя на локальном сервере. Давайте подробно разберемся с каждым этапом.
Анализ идентификации
Перед копированием давайте разберемся с идентификацией юзера, ведь у каждого своя страница с клейкими листочками. И нужно знать какому юзеру какие записочки отображать. Перед началом анализа я с помощью плагина Web Developer удалил все кукисы для чистоты эксперимента. Включив Temper Data загрузил zapisochki.ru, на что сервер вернул 302 код переадресации на zapisochki.ru/много_цифр/, да и еще бросил кукисы с каким-то логином и паролем. Теперь попробовал удалить пришедшие кукисы и загрузил zapisochki.ru/много_цифр/. Оказалось, что даже без логина и пароля что были в кукисах, страничка нормально отобразилась. С этого можно сделать вывод, что идентификация происходит именно по этих циферках в URL, а логин и пароль нужны лишь для внутренних нужд сайта.
Теперь можно начинать копировать сайт и реализовать эту идентификацию. Для этого у себя быстро создал на Денвере хост с многозначительным названием «z». Для эмуляции главной странички, набросал скрипт, который при заходе на сайт «z» будет проверять кукисы. Если они есть, то исходя из них юзер будет переброшен на ту доску, которая прописана у него в кукисах.
Тоесть, если в оригинале в кукисах хранятся логин и пароль по которым уже показываются записочки, то мы немного упростим и будем хранить идентификатор доски. Записочки будут привязаны к этому идентификатору. Да, это немного неправильно со стороны безопасности, но нам главное получить рабочий сайт, а доводкой безопасности уже можно потом заниматься. Итак, мы теперь можем написать маленький скрипт, который будет эмулировать идентификацию как указано више, но не будем заострять внимания этой мелочи, ведь его сможете и сами написать, или подсмотреть на диске. Этим скриптом мы с эмулировали функциональность связанную с идентификацией. Теперь можно приступить к следующему этапу.
Offline Explorer в работе
Рассмотрим копирования функциональности самих листочков. Перейдем на сайт zapisochki.ru/много_цифр/ и посоздаем несколько разных записок. А теперь попробуем скопировать HTML-страницу со всей обвязкой. Можно, конечно, все это и вручную проделывать - смотреть какие файлы загружаются вместе со страничкой и потом их копировать по одному. Но лучше воспользуемся инструментом для создания фейков, а именно Offline Browser. Запустим его и в качестве исходного URL зададим zapisochki.ru/много_цифр/, пару кликов на Next и в результате сайт полностью сохранен. После этого воспользуемся функцией экспорта и сохраним результат. В итоге в каталоге экспорта появилась папка с названием zapisochki.ru, а в ней в папке themes все нужные картинки, скрипты и прочее. Также там папка «много_цифр», а в ней один файлик с названием default.htm. Дальше я скопировал в Денвер папки themes и «много_цифр», а default.htm переименовал на index.php. Ведь когда не указать имя файла то по настройках по умолчанию Денвера при открытии папки он будет искать index.php. Теперь если зайти в браузере на http://z/много_буковок/, то отобразится страничка с нашими закладками, правда не все сейчас работает. А именно не двигаются почему-то закладки. Попробуем разобраться...
FireBug vs. Offline Explorer
Откроем наш FireBug и активируем весь функционал, например, нажав на вкладке «Net», где поставим везде галочки и нажмем «применить». Теперь, когда перейдем на вкладку "Console", то там пишется что-то типа такого "ошибка с dragdrop". Тут по-умному нужно отлаживать JavaScript, смотреть в чем проблема, но я воспользовался другой методикой и она сработала... Открыл скачанный default.htm и в поиске ввел "dragdrop" - курсор переместился на строчку:
<script
src="../scriptaculous.js@load=effects,dragdrop"
type="text/javascript"></script>Сразу же в глаза бросается то, что после scriptaculous.js идет "@", хотя в теории должен быть "?", ведь это же Get-запрос. Тут понятно, что все это сделал Offline Browser, чтобы превратить динамически сайт в статически, но нам это не нужно и попробуем вернуть все назад и заменим "@" на "?", а файл scriptaculous.js@load=effects,dragdrop переименуем в изначальный - scriptaculous.js. После этого видим во вкладе Net в FireBug появились 2 ошибки номер 404, тоесть два файла не было обнаружено, а именно файлы:
effects.js
dragdrop.jsДостать их не проблема, смотрим в FireBug пути и без всяких проблем загружаем с сервера записочек. Сохраним их к остальным скриптам. Обновим и увидим, что все отобразилось, ошибок нет, да и к тому же все функции с записочками стали нормально работать. Один из этапов выполнен ;)
Удаление лишнего
Сейчас немного портит красоту разьехавший дизайн – будем исправлять. Если нажать на «инспектора» в FireBug и навести на наше меню, то увидим что это все одна таблица. Нам ее не жалко, заходим в исходник страницы и удаляем все между тегами <table>, да и сами теги также. После обновления наблюдаем идеальный минималистический дизайн.
Но в «Console» FireBug опять появились ошибки. На этот раз в файле sticker.js, также там возле ошибки указывается номер проблемной строчки. Если перейти на нее, а потом удалить строчку, то после обновления ошибки больше нет, а все дальше продолжает отлично работать. Вот так, иногда удаление бывает эффективнее создания.
Протокол обмена
Записочки двигаются, текст и цвет меняется... Но все это не сохраняется. Давайте разберемся в протоколе обмена, чтобы в будущем его с эмулировать. Откроем наши записочки и в FireBug с вкладкой Console. Будем пробовать записочки в действии. Нажмем на пустом месте, появляется пустая записка, теперь введем любой текст, и выставим цвет. Видим, что браузер послал запрос:
Post
board: 70012862175107245171625585615874
color: 1
id:
text: sometext
x: 123.1
y: 543.2Причем переменная board берется с начала нашего файла default.htm, где есть строчка:
var board = '70012862175107245171625585615874';Это важно, ведь потом данную строчку будем генерировать мы скриптом. Также видим, что id пустой передается. В результате сервер возвращает число. Если изменить какой-то параметр записочки (цвет, расположения или текст), то посылается такой-же запрос, лишь id теперь не пустое. С этого сделать можно вывод, что если id пустое, то сервер создает в базе новую запись о записочке и возвращает клиенту ее идентификатор. Если id не пустое, то изменяются в базе параметры той записочки, идентификатор которой передается. Посмотрев на default.htm видим строку:
var saveURL = '../noteboard/save/';var saveURL = '../save.php';POST /NoteBoard/delete/37094Видим, что при удалении в запросе указывается id записочки. URL по которому будет отослан запрос также как и для сохранения хранится в default.htm:
var deleteURL = '../noteboard/delete/';Хотя так несколько неудобно, ведь нужно настраивать .htaccess для таких запросов, поэтому упростим, изменив URL на следующий:
var deleteURL = '../delete.php?';Тогда запросы всегда будут идти на файл delete.php, а id листочка будет приходить как GET-параметр.
Теперь мы знаем протокол обмена между сервером и клиентом и можем уже написать эти два файла save.php и delete.php, но оставим программерскую часть на потом. Ведь у нас осталась еще генерация первой страницы. Тоесть когда уже страница загрузилась, то дальше всю роботу по прорисовке берет на себя JavaScrip, но ведь вначале первый раз страницу нужно нам генерировать. А именно вверху в переменную board писать тот идентификатор, по которым юзер пришел, ведь мы помним, что идентификация происходит по цифрах в URL адресе.
Также нужно вписать в страницу записочки, что в базе ассоциируются с идентификатором доски.
Формирования записочек
Если посмотреть в конце исходника default.htm, то там будет что-то похожее на такое:
<form id="stickers">
<textarea id="s36734"
style="left:61px;top:32px;z-index:1">
текст записочки 1</textarea>
<textarea id="s36735"
style="left:90px;top:33px;z-index:0">
текст записочки 2</textarea>
</form>
Нам нужно будет брать с базы записочки и потом их выводить как textarea, где в стиле прописывать позицию в параметры left и top, в z-index писать цвет, а в id будет идентификатор записочки. Также между этими тегами <textarea> нужно вписать текст.
Программирование
Теперь уже мы знаем как генерировать первую страницу, как обрабатывать AJAX запросы от JavaScript и можем начать последний этап - программинг. В качестве языка был выбран PHP. Только сразу предупреждаю, что не стоит обращать внимания на качество кода и на его безопасность, все писалось в течении минут 10-ти, а переписывать и наводить красоту мне лень )
Итак, нам нужно сделать 4 файла: .htaccess, index.php, save.php, delete.php. В .htaccess пропишем чтобы все запросы к несуществующим файлам и каталогам направлять на index.php, это нужно чтобы перехватить запросы на адреса со многими циферками. Тоесть сервер когда увидит URL /z/много_цифр/, то конечно же такую папку не найдет и вызовет файл index.php. Файл .htaccess такой:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?$1 [L,QSA]Теперь подумаем над хранением информации о записочках. Создадим в MySQL базу данных с одной простой таблицей со следующими полями выбранными исходя из параметров записочки:
id - integer, для хранения идентификатора записочки
board - bigint, для хранения доски, в которой находится записочка
color - tinyint, для хранения цвета
x - float, для хранения x-координаты
y - float, для хранения y-координаты
text - varchar(255), для хранения текстаФайл save.php очень простой, он лишь должен уметь принять Post-данные и сделать или запрос на создание новой записочки:
INSERT INTO z SET `board`='$board', `text`='$text', `x`='$x', `y`='$y', `color`='$color'UPDATE z SET `board`='$board', `text`='$text', `x`='$x', `y`='$y', `color`='$color' WHERE `id`='$id'DELETE FROM z WHERE id='$id' AND board='$board'
Файл index.php, как уже обсуждали, будет уметь переадресовывать юзера по его кукисах на нужную ему страничку, и потом прорисовывать ее. Тоесть брать идентификатор доски id который хранится в кукисах и выбирать с базы все соответствующие записочки, а дальше выводить тот файл, что мы получили от Offline Browser и в нем лишь между тегами <form> помещать записочки в формате что мы определили выше.
Но программинг это мелочь и не существенный предмет в контексте статьи. Он важен лишь для того, чтобы показать простоту реализации серверной части. На диске вы найдете все исходники с подробными комментариями, да еще и видео будет, где показан полностью процесс полного копирования сервиса. Видео рекомендую посмотреть, чтобы увидеть как легко и быстро мною было проделано все то что я описал в статье. Также, немного собрав написанные исходники, ты сможеш получить сервис записочек у себя на компе.
Все у наших ног
На создания сайта у автора ушло месяц времени как минимум, а мы его скопировали за часик. И таких сайтов сейчас очень много, так что простор для творчества огромен.
Позволю напомнить, что вся информация лишь для ознакомления.


