Так уж сложилось у веб-мастеров, что на их сайты заходят как пользователи, так и спамерские роботы. Если первые заходят на сайт для поиска нужной информации, то вторым непременно подавай адреса e-mail'ов. Так называемые флудеры, которым попросту от нечего делать или от небольшого интеллекта так и хочется завалить ваши новости, статьи бестолковой лексикой. Ну а форум сообщениями, явно не относящимися к тематике рассматриваемой темы. Это неизбежно, как и то что за ночью приходит день и наоборот. Но с этим нужно бороться - иначе ваши порядочные пользователи вовсе потеряют интерес к вашему сайту - можете не сомневаться.
Самым простой метод противодействия данным явлениям - это банить таких посетителей по ip. Проще говоря, закрывать им доступ на ваш сайт. Данный метод пусть и не идеальная защита, но порядка 90% защиту он вам обеспечит. а это уже лучше, чем ничего.
Далее рассмотрим, как данная техника защиты работает на практике и как ее можно реализовать на php.
За дело
Для начала нам нужно получить список ip-адресов, которым будет закрыт доступ на наш сайт. Еще потребуется использовать массивы и циклы - вот где нам и пригодится php.
Дальше - больше :)
Для получения ip-адреса посетителя можно использовать суперглобальную переменную $_SERVER['REMOTE_ADDR'].
На php это реализуется следующим образом:
.
.
А теперь разберемся с остальными переменными нашего мини-скрипта. Создаем массив ($ban), куда помещаем все забаненые ip:
.
.
Как видите, ip нужно помещать в одинарные кавычки и отделять их друг от друга запятой (все просто и ясно - за что я и люблю php)
В следующая переменная ($count) будет занесено количество этих самых ip:
.
.
Для чего это все нужно - читайте дальше.
Что мы имеем:
1) IP адрес определенного посетителя - переменная $ip;
2) массив запрещенных IP-адресов - $ban;
3) число элементов этого массива - $count.
Все элементарно просто - берем и сверяем адрес $ip со списком запрещенных - а так как у нас их может быть несколько, то для этого понадобится обход всего массива забаненых адресов.
Эту работу за нас легко проделает цикл for:
.
.
.
Вот и получается, что если проверяемый адрес совпадет с одним из наших "нехороших", то мы и дадим знать его обладателю - I'm sorry, you've been banned. 68.225.34.86.
А вот и весь скрипт целиком - это для тех, кому лень его собирать по частям из статьи:
Добрый день уважаемые господа! В данной статье я хотел бы затронуть очень важную тему, а именно шаблоны в PHP. В этой статье я приведу простой, но работающий пример “шаблонов”, также мы рассмотрим все за и против использования шаблонов.
Использование шаблонов
Прежде чем использовать шаблоны, подумайте, действительно ли они вам так нужны? В данный момент существует огромное количество коммерческих вариантов шаблонов. Все они работают по одному принципу (значение, замена), но имеют огромное количество наворотов, таких как автоматическое изменения регистра переменных, поиск по регулярным выражениям и т.д., все это конечно хорошо и легко реализуемо. Когда я решил посмотреть “коммерческий” шаблон, я ужаснулся, один его класс весил 398 КБ. Это нормально? Также в сети можно найти множество бесплатных вариантов шаблонов (классы шаблонов в PHPBB, IPB…), но все они много весят и работают не слишком быстро. Я предлагаю вам простой каркас “шаблонов” на PHP, с его помощью можно сделать свой классный шаблонизатор, со всеми необходимыми вам функциями.
За и против
Приведу вам жизненный пример, не так давно я занимался разработкой программы для одного человека, заранее было обговорено, что я пишу программу, а дизайн это его дело. Через некоторое время, мой заказчик пишет мне, что дизайн для моей программы сделать невозможно. Конечно, человек ничего не знающий в web-программировании будет испытывать огромные затруднения, при построении дизайна в PHP-программе. Главная задача ‘шаблонов’ – это облегчить жизнь дизайнеру. Безусловно, главным плюсом использования шаблонов можно считать то, что дизайнер без помощи программиста сможет изменять свой web-проект. Также мне нравится само разделение – программа и дизайн.
Я не использую шаблоны в своих личных проектах, т.к. они дают дополнительную “нагрузку”. Шаблоны это хорошо, но использовать их надо только если пишешь какой, то публичный проект или выполняешь работу на заказ.
Реализация шаблонов на PHP
И так приступим. Всего у нас будет 2 ключевых файла.
1) file2compile.tpl – файл который мы будем парсить
2) template.php – главный файл содержащий класс шаблонов
Листинг файла file2compile.tpl:
Листинг файла template.php:
Теперь я подробно опишу содержание этих двух файлов.
Файл: file2compile.tpl
Тут приведен обычный HTML код. В данном файле можно найти переменные вида {TITLE}. Это как раз именно те переменные которые мы будем заменять на нужное нам значение.
Файл: template.php
Мы имеем PHP класс, разделенный на 3 функции. В самом начале файла мы объявляем классовые переменные.
$vars – массив со значениями (переменная, замена).
$template – файл который мы будем парсить.
Теперь перейдем к описанию функций.
Функция: get_tpl
В качестве аргумента функция принимает имя файла. В теле функции мы проверяем задан ли аргумент и существует ли файл. Если аргумент не задан и файл не существует мы возвращаем значение FALSE. В противном случае мы заполняем классовую переменную(template) содержанием файла.
Функция set_tpl
Функция принимает 2 значения, это переменная (напр. {TITLE)} и значение на которое мы будем ее заменять.
Функция tpl_parse
Функция не принимает никаких значений. В теле функции мы считывает массив $vars и производим замену установленных переменных на заданные значения.
Использование класса.
Для вывода на экран используйте следующие команды:
Заключение.
Надеюсь, моя статья поможет вам лучше понять, что такое шаблоны.
На полноту изложения темы я не претендую, это ведь статья, а не справочное пособие, но для начинающих будет вводной информацией в эту технику.
Собственно, о самом термине:
Автоматическое перенаправление пользователя со страницы, на которую он попал на другую страницу или сайт. Технически реализовать редирект можно целым рядом способов.
Данным механизмом следует пользоваться только в исключительных случаях, по той причине, что поисковые системы считают, что редирект может быть использован недобросовестными раскрутчиками, привлекающими таким способом аудиторию на собственый сайт со страниц специально созданных для поисковых машин на страницы действительно содержащие полезный контент, что выглядит как обман поисковиков.
Перед началом повествования сделаю небольшие замечания:
* Вам не обязательно быть PHP-программистом, чтобы разобраться в технике редиректа;
* Подразумевается, что сервер (будь-то локальный - localhost, или же ваш хостинг в интернете) поддерживает выполнение PHP-скриптов.
А вообще, если что будет непонятно, то милости прошу на php.net :)
Суть технологии или техники редиректа - это автоматическое перенаправление кого-то куда-то :) А куда именно - вы сами задаете в скрипте, таким образом, при выполнении скрипта он вас автоматически перенаправит на определенный web-адрес.
Получается, что переход идет не по прямой ссылке с сайта вида <a href="http://www.google.com">google.com</a>, а через скрипт.
1. Открываем любой html-редактор (хотя подойдет и блокнот) и набираем/вставляем в него следующий код:
2. Далее сохраняем наш файл с вышеприведенным кодом, например code.php и загружаем его на веб-сервер. К примеру, если вы загрузили code.php в корневую папку сайта codeguru.com.ua, то вызвать скрипт можно по URL http://www.coders-library.ru/code.php. После исполнения скрипта на сервере вы будете автоматически перенаправлены (средиректены :)) на полезный сайт для программистов realcoding.net - что и было указано в нашем скрипте.
Еще можно просто на сайте в теле страницы (внутри тегов <body>...</body>) поставить ссылку вида:
.
.
Вот такая нехитрая техника редиректа (redirect).
Эта задача возникает для PHP-скриптов вызываемых без параметров или являющимися индексами директорий, однако формирующих данные персонально под пользователя (например на основе cookies или user agent) или работающих на основе быстро изменяющихся данных.
По спецификации HTTP/1.1 мы можем управлять следующими полями:
Expires
Задает дату истечения срока годности документа. Задание ее в прошлом определяет запрет кэш для данной страницы.
Cache-control: no-cache
Управление кэш. Значение no-cache определяет запрет кэш данной страницы. Для версии протокола HTTP/1.0 действует "Pragma: no-cache".
Last-Modified
Дата послднего изменения содержимого. Поле актуально только для статических страниц. Apache заменяет это поле значением поля Date для динамически генерируемых страниц, в том числе для страниц содержащих SSI.
На сайте www.php.net дается следующий код для запрета кеширования.
Однако, я считаю, что данный заголовок избыточен. В большинстве случаев достаточно:
Чтобы пометить документ как "уже устаревший" следует установить Expires равным полю Date.
Ну и не следует забывать, что формы, запрошенные по POST также не подлежат кэшированию.
Для оптимизации работы с сетью используется механизм сохранения однажды полученных по HTTP документов в кеше с целью их повторного использования без обращения к серверу-источнику. Документ, сохраненный в кеше будет доступен при следующем обращении к нему, без выгрузки с сервера-источника, что призвано повысить скорость доступа клиента к нему и уменьшить расход трафика сети.
Сами кэши бываю двух видов - локальные и общие
Локальный это кеш, хранимый непосредственно на диске у клиента, создаваемый и управляемый его браузером. Общий - кэш прокси-сервера организации или провайдера и может состоять из одного или нескольких прокси-серверов. Локальный кеш присутствует, наверное в каждом браузере, общими пользуется значительная часть людей использующих Internet. И если малую часть сайтов сейчас оценивают по расходу трафика, то скорость загрузки - важный критерий, который должен учитываться при разработке Вашего web-проекта.
Для динамических страниц, создаваемых в результате работы PHP-программы, казалось бы, кэширование вредно. Содержание страницы формируются по запросу пользователя на основе какого-либо источника данных. Однако, кэширование может быть полезным. Управляя им Вы можете сделать работу с Вашим сервером комфортнее для пользователя, разрешая загрузку из кэш определенных страниц, предотвращая тем самым их повторную выгрузку с Вашего сервера и экономя пользователю время и трафик.
Кэшировать или нет?
Возможность сохранения в кэш страницы определяется динамичностью информации в источнике данных. Таким образом необходимость использования кэша определяется Вами, исходя из планируемого времени жизни страницы.
Если речь идет о формировании выборки по базе (например, поиск введенного пользователем слова), то такую страница обязательно следует запрашивать с сервера при каждом вызове без использования кэш, так как количество вариантов запрашиваемых слов огромно, а если мы к тому же имеем дело с меняющимся массивом данных, то кэширование бессмысленно. Или речь идет о формировании допустим графика приходящих посетителей (который изменяется с каждым визитом, то есть практически с каждым вызовом), то кеширование уже просто вредно.
Однако, если мы говорим о том же графике но за вчерашний день, то кэширование рекомендуется, так как данные изменяться уже не будут и мы можем экономить себе и пользователю ресурсы и время на загрузку таких страниц помещением их в локальный или общий кэш. Как продолжение этой ситуации формирование графика не в реальном масштабе времени, а ежечасно. Тут Вы можете заранее предсказать дату окончания "срока годности" сформированных данных.
PHP-программа может управлять кэшированием результатов ее работы формируя дополнительные поля в заголовке HTTP ответа вызовом функции Header().
Несколько общих утверждений характерных не только для PHP-программ:
* Страницы передаваемые по POST никогда не сохраняются в кэш.
* Страницы запрашиваемые по GET и содержащие параметры (в URL присутствует '?') не сохраняются в кэш, если не указано обратное
Таким образом в большинстве ситуаций дополнительных инструкций в программу добавлять не надо. Основные моменты на которые следует обратить внимание можно свести к двум:
* запрет кэширования документов, кэшируемых по умолчанию
* кэширование документов, не подлежащих кэшированию по умолчанию.
Рассмотрим пример - прайс лист обновляемый по понедельникам. Вы заранее знаете, что содержание страницы можно хранить в кэш до наступления новой недели, что и следует указать в заголовке ответа обеспечивая нужное поведение страницы в кэш. Основная задача - получить дату следующего понедельника в формате RFC-1123.
.
.
.
.
.
Этим методом можно эффективно управлять поведением страницы в кэш и пременим но для большого числа страниц - так или иначе можно выделить временные интервалы в течении которых содержание страницы остается постоянным. Реальное положение вещей таково, что страницы большинства динамических сайтов имеют определенное время жизни исходя из которго разработчик может сераер более приятным для работы.
Другой подход, применяемый при более оперативном обновлении информации и одновременной высокой посещаемости сервера (иначе кэширование не будет эффективным) состоит в использовании заголовка Cache-control: max-age=секунды, определяющий время по истечении которого документ считается устаревшим и имеющий больший приоритет при вычислении "свежести" документа. Если Вы публикуете новости с интервалом в 30 минут:
Процесс создания cookies на ASP очень прост. После создания этих файлов, они будут храниться на компьютерах у посетителей вашего сайта.
Одним из основных параметров у cookies является дата истечения срока их действия, т.е. expire date. Получается, что у вас, как у программиста, в руках жизнь этих файлов.
Еще отмечу, что если не указать дату expire для cookies, то они существуют до тех пор, пока пользователь не закрыл свой браузер.
Для примера:
Сейчас возьмите и откройте свой любимый бразуер (мой выбор в пользу огненного лиса Firefox :) ) и вызовите страницу с cookie.
Теперь просто удалите в коде строку (1), закройте браузер и еще раз вызовите код. Как вы можете видеть, уже имя сайта не отображается.
Все дело в том, что мы не модифицировали дату истечения срока действия cookie и при закрытии браузера они были потеряны.
Теперь рассмотрим код с добавленной датой expiration date:
Теперь после закрытия браузера и повторного вызова кода можно видеть, что cookie по-прежнему продолжает существовать.
В статье описан процесс регистрации базы данных в BDE из программы.
Для доступа к BDE будем использовать компонент Session (вкладка BDE на панели компонент). Поместим его на форму, пусть это будет Session1. Положим на форму также компонеты Table, DataSource и DBGrid.
1. Простая регистация базы данных (алиаса)
Для добавления стандартного алиаса можно воспользоваться методом AddStandardAlias(Name, Path, DefaultDriver) объекта Session1, где Name - имя алиаса, Path - физический путь к базе данных, DefaultDriver - тип базы данных.
Для стандарного алиаса DefaultDriver может быть трех типов: Paradox, DBASE, ASCIIDRV. Перед запуском метода AddStandardAlias должно быть определено значение SessionName.
Пример:
Регистарция базы данных в BDE производится методом AddAlias(Name, Driver, List) объекта Session1, где Name - имя алиаса, Driver - используемый драйвер БД, List - список параметров.
Вот пример кода, выполняющего действия, аналогичные описанным в пункте 1.
.
.
.
.
.
.
.
.
.
.
.
.
. 3. Удаление базы данных (алиаса) из BDE
Здесь все просто, запускаем метод Alias с указанием имени алиаса.
Проверить, существует ли интересующий нас алиас можно с помощью методa IsAlias.
В случае нажатия пользователем клавиши или изменении текущего элемента компонента ComboBox, вы обратите внимание на досадную задержку, возникающую при генерации события On.
Так как "работа кипит", я хотел бы отреагировать на изменение ItemIndex несколько позднее, например, 100 миллисекунд спустя. Вот что у меня получилось. На простой форме располагаем компоненты ComboBox и Label. Необходимым дополнением является вызов Application.ProcessMessages, позволяющий избежать замедления работы PC, когда очередь сообщений для формы пуста.
Возможно ли создание массива компонентов? Для показа статуса я использую набор LED-компонентов и хотел бы иметь к ним доступ, используя массив.
Прежде всего необходимо объявить массив:
.
.
При необходимости динамического создания LED-компонентов организуйте цикл, пример которого мы приводим ниже:
.
.
.
.
.
.
.
.
Если компоненты уже присутствуют на форме (в режиме проектирования), сделайте их элементами массива, например так:
.
.
.
.
.
.
.
.
.
.
Тем не менее у нас получился массив со случайным расположением LED-компонентов. Я предлагаю назначить свойству Tag каждого LED-компонента порядковый номер его расположения в массиве, а затем заполнить массив, используя это свойство:
.
.
.
.
.
.
.
.
Если вам нужен двухмерный массив, то для формирования индекса понадобится другая хитрость, например, хранение в свойстве Hint информации о времени создания компонентов.
Мне необходимо найти индекс компонента в родительском списке дочерних элементов управления. Я попытался модифицировать prjexp.dll, но без успеха. У кого-нибудь есть идеи?
Есть такая функция. Ищет родителя заданного компонента, перебирает список и возвращает индекс искомого компонента. Функция прошла многочисленные тесты и вполне работоспособна.
Inprise также рассказывала об этом в выпусках TechInfo. Поищите ti2938.asc Creating Dynamic Components at Runtime на публичном WWW или FTP сайте компании Inprise.
Данная проблема решается как минимум двумя путями, о чем и будет рассказано ниже.
Решение 1
Действительно, любой компонент можно создать и без (вне) формы или любого другого дочернего компонента. Для этого я использую параметр nil:
Решение 2
Я привожу некоторый код, касающийся описываемой проблемы: он работал, когда я использовал его в большом приложении. Я не знаю специфического метода создания компонента TTable вне родителей, поэтому я пошел путем создания своего класса от TTable во время инициализации модуля. Удобство такого подхода объясняется наличием под рукой всегда готового к работе экземпляра класса, стоит всего-лишь добавить модуль к вашему приложению.
Конечно, новый класс не должен иметь одиноко выглядящую процедуру со странной технологией фильтрации данных :=))), да и не помешала бы публикация нескольких событий, но этот пример призван все-го лишь продемонстрировать иной подход к решаемой задаче.
Я несколько раз видел в конференциях вопросы типа "как мне добавить элементы управления в TTabbedNotebook или TNotebook во время выполнения программы?". Теперь, когда у меня выдалось несколько свободных минут, я попытаюсь осветить этот вопрос как можно подробнее.
TTabbedNotebook
Добавление элементов управления в TTabbedNotebook во время проектирования - красивая и простая задача. Все, что Вам нужно - это установить свойство PageIndex или ActivePage на необходимую страницу и начать заполнять ее элементами управления.
Добавление элементов управление во время выполнения приложения также очень просто. Тем не менее, в прилагаемой документации по Delphi вы не найдете рецептов типа Что-и-Как. Видимо для того, чтобы окончательно запутать начинающих программистов, фирма-изготовитель даже не удосужилась включить исходный код TTabbedNotebook в VCL-библиотеку. Таким образом, TTabbedNotebook остается для некоторых тайной за семью печатями. К счастью, я имею некоторый опыт, коим и хочу поделиться.
Первым шагом к раскрытию тайны послужит просмотр файла DELPHIDOCTABNOTBK.INT, интерфейсной секции модуля TABNOTBK.PAS, в котором определен класс TTabbedNotebook. Беглый просмотр позволяет обнаружить класс TTabPage, описанный как хранилище элементов управления отдельной страницы TTabbedNotebook.
Вторым шагом в исследовании TTabbedNotebook может стать факт наличия свойством Pages типа TStrings. В связи с этим отметим, что Delphi-классы TStrings и TStringList соорганизуются с двумя свойствами: Strings и Objects. Другими словами, для каждой строки в TStrings есть указатель на соответствующий Objects. Во многих случаях этот дополнительный указатель игнорируется, нам же он очень пригодится.
После небольшого эксперимента выясняем, что свойство Objects указывает на нашу копию TTabPage и ссылается на имя страницы в свойстве Strings. Блестяще! Всегда полезно знать что ищешь. Теперь посмотрим что мы можем сделать:
TNotebook
Операция по заполнению элементами управления компонента TNotebook почти такая же, как и в TTabbedNotebook - разница лишь в типе класса - TPage вместо TTabPage. Тем не менее, если вы заглянете в DELPHIDOCEXTCTRLS.INT, декларацию класса TPage вы там не найдете. По неизвестной причине Borland не включил определение TPage и в DOC-файлы, поставляемые с Delphi. Декларация TPage в EXTCTRLS.PAS (можно найти в библиотеке VCL-исходников), правда, расположена в интерфейсной части модуля. Мы восполним пропущенную информацию о классе TPage:
Теперь, по аналогии с вышеприведенной процедурой, попробуем добавить кнопку на TNotebook. Все, что мы должны сделать - заменить "TTabbedNotebook" на "TNotebook" и "TTabPage" на "TPage". Вот что должно получиться: