За последние 24 часа нас посетили 18378 программистов и 1635 роботов. Сейчас ищут 1711 программистов ...

Движок гостевой книги

Тема в разделе "Решения, алгоритмы", создана пользователем [vs], 23 апр 2009.

  1. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    Гостевая книга UnoScriptBook.
    Весь движок в одном файле. Имеет функции администрирования, антифлуд и пагинатор. Хранит сообщение в файле.
    engine.php:
    Код (PHP):
    1. <?php
    2. /** 
    3.  * UnoScriptBook (USBook)
    4.  * 
    5.  * @Author Vasilii B. Shpilchin (ICQ: 379512)
    6.  * @copyright [vs]
    7.  * @version 1.0
    8.  * 
    9.  * Гостевая книга, USBook хранит данные в текстовом файле.
    10.  * Распространяется по лицензии BSD.
    11.  * 
    12.  * Формат БД:
    13.  * {serialize_array}[0]time[0]nick[0]text[0]time[0]nick[0]text[0]...
    14.  */
    15.  
    16. #Секция конфигурации.
    17. //Заголовок <title>
    18. $CONFIG['title'] = 'USBook :: [vs] code';
    19. //Имя файла Базы Данных
    20. $CONFIG['dbase'] = 'usbook.db';
    21. //Постов на страницу
    22. $CONFIG['msgOnPage'] = 10;
    23. //Задержка антифлуда в секундах
    24. $CONFIG['antiFlood'] = 5;
    25. //Вырезать теги?
    26. $CONFIG['stripTags'] = 'Off';
    27. //Заменять спецсимволы html-кодами?
    28. $CONFIG['htmlspecialchars'] = 'On';
    29. //Максимальная длина имени
    30. $CONFIG['maxName'] = 32;
    31. //Максимальная длина сообщения
    32. $CONFIG['maxPost'] = 512;
    33. //Имя админа 
    34. $CONFIG['adminName'] = 'admin';
    35. //Пароль админа
    36. $CONFIG['adminPass'] = 'admpass';
    37.  
    38. #База данных
    39. $DB = null;
    40.  
    41. #Проверка на наличие ошибок.
    42. if (!is_writeable($CONFIG['dbase'])) {
    43.     die('Файл '.$CONFIG['dbase'].' недоступен.');
    44. }
    45.  
    46. #Обработчик Базы Данных
    47. function handler ()
    48. {
    49.     global $CONFIG;
    50.     global $DB;
    51.     $DB = file_get_contents($CONFIG['dbase']);
    52.     
    53.     //Пустой файл бывает при первом запуске и после очистки.
    54.     if (empty($DB)) {
    55.         //Система антифлуда основана на запоминани времени отправки сообщения с конкретного IP.
    56.         $DB = serialize(array());
    57.         file_put_contents($CONFIG['dbase'], $DB.chr(0));
    58.         return handler();
    59.     }
    60.     $DB = explode(chr(0), $DB);
    61.     
    62.     //Собственно, антифлуд
    63.     $DB[0] = unserialize($DB[0]);
    64.     if (key_exists(ip2long($_SERVER['REMOTE_ADDR']), $DB[0]) && time() - $DB[0][ip2long($_SERVER['REMOTE_ADDR'])] < $CONFIG['antiFlood']) { 
    65.         define('CAN_POST', false);    
    66.     } else {
    67.         define('CAN_POST', true);
    68.         unset($DB[0][ip2long($_SERVER['REMOTE_ADDR'])]);
    69.     }
    70.     $DB[0] = serialize($DB[0]);
    71. }
    72.  
    73. #Оптимизатор Базы Данных
    74. function optimizer ()
    75. {
    76.     global $CONFIG;
    77.     global $DB;
    78.     
    79.     //Суть оптимизации сводится к очистке списка AntiFlood
    80.     $DB[0] = serialize(array());
    81.     
    82.     $DB = implode(chr(0), $DB);
    83.     file_put_contents($CONFIG['dbase'], $DB);
    84. }
    85.  
    86. #Очистка Базы Данных
    87. function clear ()
    88. {
    89.     global $CONFIG;
    90.     
    91.     file_put_contents($CONFIG['dbase'], null);
    92. }
    93.  
    94. #Получение сообщений
    95. function getMsgs ()
    96. {
    97.     global $CONFIG;
    98.     global $DB;
    99.     $msgsArr = array();
    100.     $limit = (isset($_GET['page']) && $_GET['page'] > 0) ? $_GET['page'] * $CONFIG['msgOnPage'] : $CONFIG['msgOnPage'];
    101.     
    102.     for ($i = ($limit - $CONFIG['msgOnPage'])*3 + 1; $i < $limit*3; $i+=3) {
    103.         if (key_exists($i+2, $DB)) {
    104.             $msgsArr[$DB[$i]] = array($DB[$i+1], $DB[$i+2]);
    105.         } else {
    106.             break;
    107.         }
    108.     }
    109.     
    110.     return $msgsArr;
    111. }
    112.  
    113. #Добавление сообщения
    114. function addMsg ($name, $text)
    115. {
    116.     global $CONFIG;
    117.     global $DB;
    118.     
    119.     if (substr_count($name, chr(0))) {
    120.         $name = str_replace(chr(0), null);
    121.     }
    122.     if (substr_count($text, chr(0))) {
    123.         $text = str_replace(chr(0), null);
    124.     }
    125.     
    126.     if (!strpos($DB[0], ip2long($_SERVER['REMOTE_ADDR']))) {
    127.         $DB[0] = unserialize($DB[0]);
    128.         $DB[0][ip2long($_SERVER['REMOTE_ADDR'])] = time();
    129.         $DB[0] = serialize($DB[0]);
    130.     }
    131.     $padding = strlen($DB[0]);
    132.     $DB = implode(chr(0), $DB);
    133.     
    134.     //Новое сообщение добавляется вначале
    135.     $DB = substr_replace($DB, chr(0).implode(chr(0), array(time(), $name, $text)).chr(0), $padding, 1);
    136.     
    137.     file_put_contents($CONFIG['dbase'], $DB);
    138. }
    139.  
    140. #Удаление сообщения
    141. function delMsg ($n)
    142. {
    143.     global $CONFIG;
    144.     global $DB;
    145.     
    146.     if (!key_exists($n, $DB)) {
    147.         return true;
    148.     }
    149.     
    150.     //Чтобы не удалить антиспам-массив
    151.     if ($n == 0) {
    152.         return true;
    153.     }
    154.     
    155.     //Допустим только номер элемента-даты
    156.     if (!is_numeric($DB[$n])) {
    157.         return true;
    158.     }
    159.     
    160.     unset($DB[$n]);
    161.     unset($DB[++$n]);
    162.     unset($DB[++$n]);
    163.     
    164.     $DB = implode(chr(0), $DB);
    165.     file_put_contents($CONFIG['dbase'], $DB);
    166. }
    167.  
    168. #Список страниц
    169. function paginator ()
    170. {
    171.     global $CONFIG;
    172.     global $DB;
    173.     $current = isset($_GET['page']) ? $_GET['page'] : 1;
    174.     
    175.     $pages = ceil(((count($DB) - 1) / 3) / $CONFIG['msgOnPage']);
    176.     $buffer = null;
    177.     for ($i=1; $i <= $pages; $i++) {
    178.         if ($i == $current) {
    179.             $buffer .= '<b>'.$current.'</b> ';
    180.         } else {
    181.             $buffer .= '[url="'.$_SERVER['PHP_SELF'].'?page='.$i.'"]'.$i.'[/url] ';
    182.         }
    183.     }
    184.     return $buffer;
    185. }
    186.  
    187. #Авторизация админа
    188. function auth ()
    189. {
    190.     global $CONFIG;
    191.     
    192.     if (!isset($_SERVER['PHP_AUTH_USER']) || $_SERVER['PHP_AUTH_USER'] != $CONFIG['adminName'] || $_SERVER['PHP_AUTH_PW'] != $CONFIG['adminPass'])  {
    193.         header("WWW-authenticate: basic realm='Welcome to USBook!'");
    194.         header("HTTP/1.0 401 Auth Required");
    195.         die('Login invalid!');
    196.     } else {
    197.         define('ADMIN', true);
    198.     }
    199. }
    200.  
    201. #Обновление страницы
    202. function refresh () {
    203.     global $addit;
    204.     die(header('Location: '.$_SERVER['PHP_SELF'].'?'.$addit));
    205. }
    206.  
    207. #Алгоритм работы
    208. handler(); //Amen!
    209.  
    210. //Авторизация
    211. if (isset($_GET['admin'])) {
    212.     auth();
    213.     $addit = 'admin';
    214. } else {
    215.     $addit = null;
    216. }
    217.  
    218. //Добавление сообщения
    219. if (isset($_POST['add'])) {
    220.     if (CAN_POST && isset($_POST['name']) && isset($_POST['post']) && !empty($_POST['name']) && !empty($_POST['post'])) {
    221.     
    222.         //Обработка данных
    223.         if (get_magic_quotes_gpc()) {
    224.             $_POST['name'] = stripslashes($_POST['name']);
    225.             $_POST['post'] = stripslashes($_POST['post']);
    226.         }
    227.         if (strlen($_POST['name']) > $CONFIG['maxName']) {
    228.             $_POST['name'] = substr($_POST['Name'], 0, $CONFIG['maxName']);
    229.         }
    230.         if (strlen($_POST['post']) > $CONFIG['maxPost']) {
    231.             $_POST['post'] = substr($_POST['Post'], 0, $CONFIG['maxPost']);
    232.         }
    233.         if (strtolower($CONFIG['stripTags']) == 'on') {
    234.             $_POST['name'] = strip_tags($_POST['name']);
    235.             $_POST['post'] = strip_tags($_POST['post']);
    236.         }
    237.         if (strtolower($CONFIG['htmlspecialchars']) == 'on') {
    238.             $_POST['name'] = htmlspecialchars($_POST['name']);
    239.             $_POST['post'] = htmlspecialchars($_POST['post']);
    240.         }
    241.         
    242.         //Запись
    243.         addMsg($_POST['name'], $_POST['post']);
    244.         refresh();
    245.     }
    246. }
    247.  
    248. //Действия администратора
    249. if (defined('ADMIN')) {
    250.     //Удаление сообщения
    251.     if (isset($_GET['del'])) {
    252.         delMsg($_GET['del']);
    253.         refresh();
    254.     }
    255.     //Оптимизация БД
    256.     elseif (isset($_GET['optimize'])) {
    257.         optimizer();
    258.         refresh();
    259.     }
    260.     //Очистка БД
    261.     elseif (isset($_GET['clear'])) {
    262.         clear();
    263.         refresh();
    264.     }
    265.     //Выход
    266.     if (isset($_GET['logout'])) {
    267.         $addit = null;
    268.         unset($_SERVER['PHP_AUTH_USER']);
    269.         unset($_SERVER['PHP_AUTH_PW']);
    270.         refresh();
    271.     }
    272. }
    273. ?>
    Пример использования движка:
    sample.php:
    Код (Text):
    1.  
    2. <?php
    3. require('engine.php');
    4. ?>
    5. <html>
    6. <head>
    7. <title><?=$CONFIG['title']?></title>
    8. </head>
    9. <body>
    10. <h1>USBook 1.0</h1>
    11. <hr noshade size="1">
    12. <?php
    13. if (defined('ADMIN')) {
    14. ?>
    15.     Размер БД: <?=round(filesize($CONFIG['dbase'])/1024,3)?>кб&nbsp;-&nbsp;
    16.     <a href="<?=$_SERVER['PHP_SELF']?>?optimize&admin">Оптимизировать БД</a>&nbsp;-&nbsp;
    17.     <a href="<?=$_SERVER['PHP_SELF']?>?clear&admin">Очистить БД</a>&nbsp;-&nbsp;
    18.     <a href="<?=$_SERVER['PHP_SELF']?>?logout&admin">Выйти</a>
    19. <?php
    20. } else {
    21. ?>
    22.     <a href="<?=$_SERVER['PHP_SELF']?>?admin">Войти</a>
    23. <?php
    24. }
    25. ?>
    26. <hr noshade size="1">
    27. <table bgcolor="#EFEFEF" width="300">
    28. <?php
    29. $messages = getMsgs();
    30. $color = '#FFEEEE';
    31. $i = 1;
    32. foreach ($messages as $time => $msg) {
    33.     echo '<tr>';
    34.     echo '<td><b>'.$msg[0].'</b></td><td align="right"><b>'.date('d-m-Y', $time).'</b>';
    35.    
    36.     if (defined('ADMIN')) {
    37.         echo '<a href="'.$_SERVER['PHP_SELF'].'?del='.$i.'&admin">[x]</a>';
    38.     }
    39.    
    40.     echo '</tr><tr bgcolor="'.$color.'">';
    41.     echo '<td colspan="2" height="50" valign="top">'.$msg[1].'</td>';
    42.     echo '</tr>';
    43.    
    44.     if ($color == '#FFEEEE') {
    45.         $color = '#EEEEFF';
    46.     } else {
    47.         $color = '#FFEEEE';
    48.     }
    49.     $i+=3;
    50. }
    51. ?>
    52. </table>
    53. <form action="<?=$_SERVER['PHP_SELF'].'?'.$addit?>" method="POST">
    54. <li>Все поля обязательны для заполнения!</li>
    55. <li>Максимальная длина имени - <?=$CONFIG['maxName'];?> символов!</li>
    56. <li>Максимальная длина сообщения - <?=$CONFIG['maxPost']?> символов!</li>
    57. <p><b>Имя:</b><br>
    58. <input name="name">
    59. <br><b>Сообщение:</b><br>
    60. <textarea name="post"></textarea>
    61. <br>
    62. <input type="submit" name="add" value="Послать">
    63. </form>
    64. <hr noshade size="1">
    65. <b>Страницы:</b><br>
    66. <?=paginator();?>
    67. </body>
    68. </html>
    Демо:
    http://tanktiks.com/vs/usbook.php
     
  2. admyx

    admyx Активный пользователь

    С нами с:
    14 мар 2008
    Сообщения:
    2.159
    Симпатии:
    1
    А капча?
     
  3. kas1e

    kas1e Активный пользователь

    С нами с:
    6 апр 2009
    Сообщения:
    280
    Симпатии:
    0
    убого =(
     
  4. много из вас показало что нибудь лучше?
     
  5. kas1e

    kas1e Активный пользователь

    С нами с:
    6 апр 2009
    Сообщения:
    280
    Симпатии:
    0
    показать - нет. написать - да.

    если необходимо лучше - могу потом из дома принести и поставить где-нибудь. хоть минифорум самописный, для онлайн игры когда-то писал.
     
  6. написать все могут. теоретичеки. )

    Мне то не нужно. Просто я считаю, что критиковать можно только несделанное, или сделанное неверно. Нельзя критиковать то, к чему человек приложил старание и здравый смысл.
     
  7. Mr.M.I.T.

    Mr.M.I.T. Старожил

    С нами с:
    28 янв 2008
    Сообщения:
    4.586
    Симпатии:
    1
    Адрес:
    у тебя канфетка?
    может лучше
    Код (Text):
    1. array(
    2.    array(
    3.        "time"=>"",
    4.        "nick"=>"",
    5.        .....
    6.    ),
    7.    ...
    8. )
    ?
     
  8. Mr.M.I.T.

    Mr.M.I.T. Старожил

    С нами с:
    28 янв 2008
    Сообщения:
    4.586
    Симпатии:
    1
    Адрес:
    у тебя канфетка?
    флоппик
    Поэтому ты всегда даёшь советы а не критикуешь? =)
     
  9. Mr.M.I.T.

    Mr.M.I.T. Старожил

    С нами с:
    28 янв 2008
    Сообщения:
    4.586
    Симпатии:
    1
    Адрес:
    у тебя канфетка?
    PHP:
    1.  if ($CONFIG['stripTags'] == 'On') {
    логичее было бы true\false
     
  10. Mr.M.I.T.

    Mr.M.I.T. Старожил

    С нами с:
    28 янв 2008
    Сообщения:
    4.586
    Симпатии:
    1
    Адрес:
    у тебя канфетка?
    [vs]
    Вообще, раз уж так, я бы сделал всё в один класс
     
  11. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    При сериализации много всякой информации добавляется о элементах массива, простая строка компактнее.
    А мне кажется, что так красивее)
     
  12. lexa

    lexa Активный пользователь

    С нами с:
    22 июл 2007
    Сообщения:
    1.746
    Симпатии:
    0
    Адрес:
    Санкт-Петербург
    on и off это и есть булевые только за пределами языка программирования: вкл. и выкл., свободно и занято и т.д.

    Что будет, когда пользователь напишет:
    Код (Text):
    1. $CONFIG['stripTags'] = 'on';
    ? Ничего потому что кому-то взбрендило считать, что "On" текст да и с учётом регистра это красивее.

    Красиво когда: 1) красиво (сюрприз); 2) удобно. В твоём случае это ни то, ни другое.

    Введи булевые, запихни в класс, введи метод-"поглощатель" конфига. Для собственного интереса.
     
  13. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    Действительно, надо strtolower делать ;-)
     
  14. Mr.M.I.T.

    Mr.M.I.T. Старожил

    С нами с:
    28 янв 2008
    Сообщения:
    4.586
    Симпатии:
    1
    Адрес:
    у тебя канфетка?
    я имел ввиду var_export($arr,1)
     
  15. Elkaz

    Elkaz Старожил
    Команда форума Модератор

    С нами с:
    26 июн 2006
    Сообщения:
    3.373
    Симпатии:
    0
    Адрес:
    Баку, Азербайджан
    [vs], просто зачёт :)
     
  16. Vitas

    Vitas Активный пользователь

    С нами с:
    7 фев 2006
    Сообщения:
    595
    Симпатии:
    0
    Адрес:
    Новосибирск, Академгородок
    Elkaz, а ты, товарищ, кретин.
     
  17. Vitas

    Vitas Активный пользователь

    С нами с:
    7 фев 2006
    Сообщения:
    595
    Симпатии:
    0
    Адрес:
    Новосибирск, Академгородок
    Если уж пошло на то, то почему бы не использовать pack() для упаковки int'ов?
     
  18. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    Потому что это уже маразм.
     
  19. SoM

    SoM Активный пользователь

    С нами с:
    18 май 2009
    Сообщения:
    3
    Симпатии:
    0
    [vs]
    А можно для чайников пошагово: куда код вставлять? Нужно ли отдельный файл создавать PHP, если да - как его обзывать?

    З.Ы. очень хочется разобраться =/
     
  20. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    SoM
    Движок и пример использования можно соеденить в один файл, или можно разнеси их по разным файлам, и подключать один к другому с помощью include. Имя файла значения не имеет.
     
  21. SoM

    SoM Активный пользователь

    С нами с:
    18 май 2009
    Сообщения:
    3
    Симпатии:
    0
    [vs]
    Немного (ну или много) не ясно:
    Положим я разнесла все по разным файлам. В итоге у меня получается файл, например, file.php с самим движком и файл с html кодом.

    Собственно вопросы:
    1. PHP я включаю как <?php include 'file.php';?> ?
    2. Куда именно в html файле его вставлять?
    3. Должно ли расширение html файла меняться на php?
     
  22. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    SoM
    Чуть-чуть подредактировал первое сообщение.
     
  23. SoM

    SoM Активный пользователь

    С нами с:
    18 май 2009
    Сообщения:
    3
    Симпатии:
    0
    [vs]
    Спасибо большое))
     
  24. Vladson

    Vladson Старожил

    С нами с:
    4 фев 2006
    Сообщения:
    4.040
    Симпатии:
    26
    Адрес:
    Estonia, Tallinn
    А мне понравилось... Можно подробнее, что там убого ?
     
  25. Padaboo

    Padaboo Старожил
    Команда форума Модератор

    С нами с:
    26 окт 2009
    Сообщения:
    5.242
    Симпатии:
    1
    Vladson
    :)