Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
Социальная инженерия и социальные хакеры. Авторы: Кузнецов М.В., Симдянов И.В. Объектно-ориентированное программирование на PHP. Авторы: Кузнецов М.В., Симдянов И.В. Программирование. Ступени успешной карьеры. Авторы: Кузнецов М.В., Симдянов И.В. C++. Мастер-класс в задачах и примерах. Авторы: Кузнецов М.В., Симдянов И.В. MySQL на примерах. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум PHP

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: ***** ЗАДАЧА N2 *****
 
 автор: FatBoy   (31.01.2006 в 00:58)   письмо автору
 
 

Задача N2. (Категория 2) Вывод из файла и запись в файл.

Условие:
Написать скрипт index.php, который выводит из файла data.txt
все строки с разделителем '=' в таблицу и имеет в конце форму с 1 полем
ввода text и 1 полем ввода textarea для передачи данных в скрипт-обработчик
script2.php. Обработчик заносит данные в файл data.txt с
разделителем '=' и возвращает пользователя обратно в index.php.
(мини-гостевая книга)

Примечание:
data.txt:
text1=text2
text3=text4
...
---------------------------------


Вопросы в тему не задаем. В условии достаточно информации для решения.
Если по вашему мнению необходимо внести в решение что-то не
описанное в условии - внесите с пояснениями для чего.
НЕ ПИШИТЕ ГРОМОЗДКИЕ конструкции со стилевыми оформлениями, старайтесь
уместить все в тот минимум кода, который будет просто работать правильно.

Все желающие пишут свои варианты решения (2 файла - index.php
и script2.php) и отправляют их на e-mail: fatboy@hotmail.kg
(еще продублируйте на e-mail: fatboy_php@mail.ru)
В заголовке письма пишется "Решение задачи N2".
В теле письма:


<?php 
// скрипт index.php к задаче N2
// Фамилия, Имя, ФОРУМОВСКИЙ Ник
... 
полное решение с комментариями и пояснениями 
... 
// end of index.php
?>



<?php 
// скрипт script2.php к задаче N2
... 
полное решение с комментариями и пояснениями 
... 
// end of script2.php
?> 



Вложения не допускаются. Все решения будут проиндексированы
и выложены через 12-18 часов на форуме (без указания авторства) для
обсуждения. Обсуждение длится сутки, потом выкладываются
Ники авторов.
PS. Не стесняйтесь прислать свой вариант решения.

   
 
 автор: cheops   (31.01.2006 в 02:45)   письмо автору
 
   для: FatBoy   (31.01.2006 в 00:58)
 

Задача добавлена в раздел задач http://www.softtime.ru/info/task.php?id_article=72

   
 
 автор: FatBoy   (01.02.2006 в 14:12)   письмо автору
 
   для: FatBoy   (31.01.2006 в 00:58)
 

Итак, ответы на задачу N2. (не забываем комментировать и оценивать)

   
 
 автор: FatBoy   (01.02.2006 в 14:15)   письмо автору
 
   для: FatBoy   (01.02.2006 в 14:12)
 


<?php
// скрипт index.php к задаче N2
// Решение 002-001
$file 'data.txt';
if(isset(
$_GET['ok'])) { echo "Запись добавлена"; }
if(
file_exists($file) && is_readable($file)) {
    
$records file($file);
    
$total count($records);
    if(
$total 0) {
        echo 
"<table border=1>\r\n";
        foreach (
$records as $value) {
            
$rec explode("="$value);
            
// В следующих строках избавляемся от защиты = и \r\n
            
$item1 stripslashes(str_replace('\\x3d''='$rec[0]));
            
$item2 stripslashes(str_replace('\\x3d''='$rec[1]));
            echo 
"<tr><td>" $item1 "</td><td>" trim($item2) . "</td></tr>\r\n";
        }
        echo 
"</table>\r\n";
    } else {
        echo 
"Записей нет.";
    }
} else {
    echo 
"Ошибка чтения файла '" $file "'.";
}
?>
<br>
<form action="script2.php" method="POST">
<input type="text" name="item1"><br>
<textarea name="item2"></textarea><br>
<input type="submit" value="ok">
</form>
<!-- end -->



<?php
// скрипт script2.php к задаче N2
$file 'data.txt';
if(
file_exists($file) && is_writable($file)) {
    if(isset(
$_POST['item1']) && isset($_POST['item2'])) {
      
$fp fopen($file"a");
      if (!
get_magic_quotes_gpc()) {
          
$_POST['item1'] = addslashes($_POST['item1']);
          
$_POST['item2'] = addslashes($_POST['item2']);
      }
      
// Защищаем = и \r\n
      
$item1 str_replace('=''\\x3d'$_POST['item1']);
      
$item2 str_replace('=''\\x3d'$_POST['item2']);

      
fwrite($fp$item1 "=" $item2 "\r\n");
      
fclose($fp);
      if(
headers_sent()) {
          
// Если заголовки были отправлены значит уже что-то не то..
          
echo "Ошибка.";
      } else {
          
header("Location: index.php?ok=1");
      }
    } else {
        echo 
"Заполнены не все поля.";
    }
} else {
    echo 
"Ошибка записи в файл '" $file "'.";

?> 

   
 
 автор: cheops   (01.02.2006 в 17:54)   письмо автору
 
   для: FatBoy   (01.02.2006 в 14:15)
 

Код компактный, хорошо читаемый, но не видно нигде htmlspecialchars(), а в файл могут запихать редирект или похищалку cookie. Мне не нравится использование шестнадцетиричного значения равно \x3d и отсутствия подробных коментариев на его счёт - это вынуждает лезть в справочник и смотреть, что же это за символ (а лазание в справочник - это лишнее время).

   
 
 автор: FatBoy   (01.02.2006 в 14:19)   письмо автору
 
   для: FatBoy   (01.02.2006 в 14:12)
 


<?php
// скрипт index.php к задаче N2
// Решение 002-002
# имя файла с данными
$filename "data.txt";
# проверка существования файла
if (file_exists($filename)) {
  
# если файл существует...
  # получим его содержимое в массив
  
$file file($filename);
  
# проверим количество строк
  
if (count($file) !== 0) {
    
# выведем таблицу в цикле
    
echo("<table border=\"1\">");
    foreach (
$file as $line) {
      
# разбиваем строку
      
$line explode("="$line);
      echo(
"<tr><td>".$line[0]."</td>");
      echo(
"<td>".$line[1]."</td></tr>");
    }
    echo(
"</table>");
  } 
# если строк нет, то ничего не выведется
# если файла нет, ничего не выведется
?>
<!-- форма -->
<form action="script2.php" method="post">
<input type="text" name="field1" size="40"/><br />
<textarea name="field2" cols="30", rows="6"></textarea><br />
<input type="submit" />
</form>
<!-- end -->



<?php
// скрипт script2.php к задаче N2
# массив символов, подлежащих замене
$bad = array("\n""\r""=");
# проверка "магических" кавычек
if (get_magic_quotes_gpc()) {
  
# если включены, удаляем экранирование
  # и заменяем "плохие" символы на пробел
  
$field1 str_replace($bad" "stripslashes($_POST['field1']));
  
$field2 str_replace($bad" "stripslashes($_POST['field2']));
} else {
  
# если выключены заменяем "плохие" символы на пробел
  
$field1 str_replace($bad" "$_POST['field1']);
  
$field2 str_replace($bad" "$_POST['field2']);
}
# строка для записи в файл
$data $field1."=".$field2."\n";
# открытие файла
$file fopen("data.txt""at");
# запись в файл строки
fwrite($file$data);
# закрытие файла
fclose($file);
# возвращаем пользователя назад
header("Location: index.php");
?>

   
 
 автор: cheops   (01.02.2006 в 17:58)   письмо автору
 
   для: FatBoy   (01.02.2006 в 14:19)
 

Прекрасная читабельность, однако также не используется htmlspecialchars(), и конструкцию
<?php
if (get_magic_quotes_gpc()) { 
  
# если включены, удаляем экранирование 
  # и заменяем "плохие" символы на пробел 
  
$field1 str_replace($bad" "stripslashes($_POST['field1'])); 
  
$field2 str_replace($bad" "stripslashes($_POST['field2'])); 
} else { 
  
# если выключены заменяем "плохие" символы на пробел 
  
$field1 str_replace($bad" "$_POST['field1']); 
  
$field2 str_replace($bad" "$_POST['field2']); 
}
?>

можно было бы исправить на
<?php
if (get_magic_quotes_gpc()) { 
  
# если включены, удаляем экранирование 
  # и заменяем "плохие" символы на пробел 
  
$_POST['field1'] = stripslashes($_POST['field1']); 
  
$_POST['field1'] = stripslashes($_POST['field2']); 
}
# если выключены заменяем "плохие" символы на пробел 
$field1 str_replace($bad" "$_POST['field1']); 
$field2 str_replace($bad" "$_POST['field2']); 
?>

   
 
 автор: FatBoy   (01.02.2006 в 14:25)   письмо автору
 
   для: FatBoy   (01.02.2006 в 14:12)
 


<!-- Задача N2 -->
<!-- Решение 002-003 -->
<!-- index.php -->
<html>
<head>
<title>index.php</title>
<meta content="text/html; charset=windows-1251" http-equiv=Content-Type>
</head>
<body>
<!-- Это шрифт. Так, для красоты. -->
<font face='Courier'>
<?php
$filename
="./data.txt";
//Если файл существует
if ( file_exists($filename) )
{
     
//Чтение построчно в массив
     
$data=file($filename);
     echo 
"<table width=500 align=center cellspacing=0 cellpadding=2 border=1>";
     
//Перебор массива $data
     
foreach($data as $content)
     {
         
//Это - здоровая паранойя
         //проверка на пустоту текущей строки
         
if($content==="")
         {
             continue;
         }
         
//Разбиваем строку из файла на составляющие, а если в строке
         //вообще символа "=" нет, переходим сразу к следующей (строке)
         
if(!$values=explode("="$content))
         {
             continue;
         }
         echo 
"<tr>";
         
//Перебираем - это для универсальности кода
         
foreach($values as $text)
         {
             echo
" <td valign=top>";
             
//Заменяем "безопасные строки" обратно
             
$text=str_replace("*#!equals!#*""="$text);
             echo 
$text;
             echo
" </td>";
         }
         echo 
" </tr>";
     }
     echo 
"</table> ";
}
else
{
     echo 
"Нет данных для отображения<br><br>";
}
?>
     <br>
     <b>Добавить:</b>
     <form name='form' action='./script2.php' method='POST'>
         TEXT:<br>
         <input type=text name='text' size=20 value=''><br><br>
         TEXTAREA:<br>
         <textarea name='textarea' rows=5 cols=20></textarea><br><br>
         <input type=submit name='action' value='GO'>
     </form>

</font>
</body>
</html>
<!-- end of index.php-->



<!-- script2.php -->
<?php

//Это заголовок для кодировки
$header="
<html>
<head>
<title>script2.php</title>
<meta content=\"text/html; charset=windows-1251\" 
http-equiv=Content-Type>
</head>
<body>
"
;

//Это массив с нежелательными и "безопасными" символами
$escape=array
(
     
"\n" => "",
     
"\r" => "",
     
"="    => "*#!equals!#*"
);
//Проверка на пустоту
if( empty($_POST['text']) || empty($_POST['textarea']) )
{
     echo 
$header;
     echo 
"Одно или оба поля пусты.<br>";
     echo 
"<input type=button value='Назад' OnClick='javascript:history.back()'>";
     exit;
}
//Попытка открыть файл
if(!$handle=fopen('./data.txt''at'))
{
     echo 
$header;
     echo 
"Не могу открыть файл.<br>";
     echo 
"<input type=button value='Назад' OnClick='javascript:history.back()'>";
     exit;
}

//Записываем две переменные в строку - чтобы не делать всё по два раза
$content=$_POST['text']."*#!divider!#*".$_POST['textarea'];

//Заменяем переводы строк на <br />
//и применяем как фильтр массив $escape
$content=nl2br($content);
$content=strtr($content$escape);

//Разбиваем строку по константе *#!divider!#*, затем
//сворачиваем ее через "=" и добавляем в конец "\n"
$content=implode("="explode("*#!divider!#*",
$content))."\n";

//Убираем теги и специальные символы HTML  - защищаемся от XSS
$content=strip_tags($content);
$content=htmlspecialchars($contentENT_QUOTES);

//Блокируем файл
flock($handleLOCK_EX);

//Пишем в файл
if(fwrite($handle$content) === FALSE)
{
     echo 
$header;
     echo 
"Не могу произвести запись в файл";
     exit;
}

//Разблокируем и закрываем файл
flock($handleLOCK_UN);
fclose($handle);

header("Location: ./index.php");
?>
<!-- end of script2.php-->

   
 
 автор: cheops   (01.02.2006 в 18:10)   письмо автору
 
   для: FatBoy   (01.02.2006 в 14:25)
 

Нет проверки на существование записей в файле data.txt, но и без неё всё прекрасно работает. Не смотря на некоторую громоздскость - код прекрасно читается. К достоинствам следует приписать то, что используется htmlspecialchars(), однако не очень удобно то, что применяется функция пред записью, в файл, а не при выводе в окно браузера - это может быть не очень удобно, особенно если текст будет редактироваться.

   
 
 автор: FatBoy   (01.02.2006 в 14:34)   письмо автору
 
   для: FatBoy   (01.02.2006 в 14:12)
 


<!--// Begin of index.php к задаче N2  -->
<!--// Решение 002-004 -->
<table border="1">
<?
$fn
=array("<br>","","=");  //вернем нужные символы
$rp=array('\n','\r',"&#61;");  //наши альтернативные символы
$filename="data.txt";       //чтобы не писать 2 раза
$file=fopen($filename,"r");  //открываем
$text=fread($file,filesize($filename));  //читаем
$text=explode("\r\n",$text);  //разрезаем
for ($i=0;$i<sizeof($text)-1;$i++) {  //зацикливаемся
   
$text[$i]=explode("=",$text[$i]);  //двумерный массив удобен для дальнейшей обработки
   
echo"<tr><td>".str_replace($rp,$fn,$text[$i][0])."</td><td>".str_replace($rp,$fn,$text[$i][1])."</td></tr>";  //заменяем и печатаем
}
    
//форма:
?>
</table>
<form action=script2.php method=post>
  <input type=text name=text1><br>
  <textarea name=text2></textarea><br>
  <input type=submit value="Записать">
</form>
<!--// end of index.php -->



<?
// Begin of script2.php к задаче N2

$fn=array("\n","\r","=");     //проблемные символы
$rp=array('\n','\r',"&#61;"); //альтернативные сочетания символов
$text1 str_replace($fn,$rp,$_POST['text1']); //заменяем
$text2 str_replace($fn,$rp,$_POST['text2']);
  
$fp fopen("data.txt""a");   //открываем
  
fwrite($fp"$text1=$text2\r\n");   //пишем
  
fclose($fp); //закрываем
header("Location: index.php");  //переезжаем

// end of script2.php
?>

   
 
 автор: cheops   (01.02.2006 в 18:16)   письмо автору
 
   для: FatBoy   (01.02.2006 в 14:34)
 

Хм... достаточно изящное решение, почему-то действительно никому в голову не пришло в прошлый раз использовать HTML-эквиваленты, хотя это практически промышленный стандарт. Хотя перед выводом в окно браузера не используется htmlspecialchars(), поэтому можно изменять проивольно дизайн, даже вводить дополнительные строки в таблице, похищать куки и т.п.

   
 
 автор: FatBoy   (01.02.2006 в 14:37)   письмо автору
 
   для: FatBoy   (01.02.2006 в 14:12)
 


<html>
<head>
<title>New document</title>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
</head>
<body>

<?
//скрипт index.php к задаче N2
// Решение 002-005

echo "<table>";
//открываем файл 
$file file("data.txt");

//делаем массив
  
foreach($file as $qk)
 { 
// разделяем =
  
list($text1,$text2) = explode("="$qk); 

// выводим данные
echo "<tr><td>".$text1."</td><td>".$text2."</td></tr>";
}      

echo 
"</table>";
//выводим форму для добавления
?>

<br>
<form action=script2.php method=post> 
  <input type=text name=text1><br> 
  <textarea name=text2></textarea><br> 
  <input type=submit value="Записать"> 
</form>
</body>
</html>



<?php 
//скрипт script2.php к задаче N2
// считываем переданные данные 
$text1 $_POST['text1']; 
$text2 $_POST['text2']; 

// открываем файл для записи если его нет то создаем
$file fopen("data.txt""a");  

// записываем данные в конец файла делаем переход строки 
fwrite($file"$text1=$text2\r\n"); 

// переходим на index.php 
header("location: index.php"); 
?>

   
 
 автор: P@Sol   (01.02.2006 в 16:35)   письмо автору
 
   для: FatBoy   (01.02.2006 в 14:37)
 

а моего скрипта пока нет:( я его послал на меил.ру, т.к. на другой почтовый адрес у меня письмо не уходило

   
 
 автор: cheops   (01.02.2006 в 18:20)   письмо автору
 
   для: FatBoy   (01.02.2006 в 14:37)
 

Минималистский стиль - очень наглядно и компактно, особенно следует отметить использование конструкции list() - число столцбов известно заранее и её использование оправдано, код с использованием list() становится легче читать.

   
 
 автор: udaf   (02.02.2006 в 00:47)   письмо автору
 
   для: cheops   (01.02.2006 в 18:20)
 

где-же мой скрипт?

   
 
 автор: СерегаВЕБ   (02.02.2006 в 14:00)   письмо автору
 
   для: FatBoy   (01.02.2006 в 14:12)
 

Я решил вместо оценок кода просто протестировать скрипты:

001
Не удаляет символы возврата коретки.
Не убивает HTML-теги.
data.txt

001=аыфа\x3dываыв
001=вава
вава
001=<hr>

002
Заменяет все символы на " ".
Не убивает HTML-теги.

002=ке  ке
002=ке ке
002=<hr>

003
Не восстонавливае символы возврата коретки.
Искоренняет HTML-теги.

003=вапфывываав
003=ывфав*#!equals!#*выфавыфа
003=

004
Не убивает HTML-теги.

004=тест\r\nтест
004=тест&#61;тест
004=<hr>

005
Скрипт вообще никак не реагирует на сибволы = и \n
Не убивает HTML-теги.

005=тест
тест
005=тест=тест
005=<hr>

   
 
 автор: cheops   (03.02.2006 в 16:36)   письмо автору
 
   для: FatBoy   (31.01.2006 в 00:58)
 

Мои оценки данных скриптов следующие
N  чит тонкс оригн
1   4    3     3
2   5    3     4
3   2    5     4
4   3    3     4
5   5    0     5

Читабельность выставлялась по пятибальной системе, тонкости столько сколько насчитал - оригинальность - это то насколько скрипт понравился.
Тонкости 001
Учитывается существование файлов
Учитывается =
Учитываются переводы строк

Тонкости 002
Учитывается существование файлов
Учитывается =
Учитываются переводы строк

Тонкости 003
Учитывается существование файлов
Учитывается =
Учитываются переводы строк
Используется htmlspecialchars() при выводе
Используется блокировка файлов

Тонкости 004
Учитывается =
Учитываются переводы строк

Тонкости 005
Учёт тонкостей не производится

   
 
 автор: P@Sol   (03.02.2006 в 17:13)   письмо автору
 
   для: cheops   (03.02.2006 в 16:36)
 

где мой код??????????

   
 
 автор: cheops   (03.02.2006 в 17:31)   письмо автору
 
   для: P@Sol   (03.02.2006 в 17:13)
 

Давайте тему в разном заведём.

   
 
 автор: Саня   (04.02.2006 в 00:02)   письмо автору
 
   для: FatBoy   (31.01.2006 в 00:58)
 

Cheops читает мои мысли, даже когда они ещё не пришли ко мне (оценки те же :)!

Пишу только недостатки. Всё, что не написано - нареканий не вызывает.

№1:
Мало комментариев. Строки покороче нужно сделать - длинные хуже воспринимаются. Шестнадцатиричные значения немного смущают.

№2:
Блок "if (magic_quotes)" нужно оптимизировать. Плохая фильтрация входящих данных.

№3:
Громоздко. Если бы не было оформления - было бы лучше. Идея с безопасными строками спорная. С одной стороны - хорошо, с другой - было бы лучше, если использовались мнемонические заменители.

№4:
Мало проверок.

№5:
Мало проверок.

   
 
 автор: cheops   (04.02.2006 в 01:24)   письмо автору
 
   для: Саня   (04.02.2006 в 00:02)
 

>Cheops читает мои мысли, даже когда они ещё не пришли ко мне
>(оценки те же :)!
Когда занимался наукой у нас ходила поговорка: всё о чём ты подумал уже придумали японцы :)))

   
 
 автор: P@Sol   (06.02.2006 в 13:28)   письмо автору
 
   для: cheops   (04.02.2006 в 01:24)
 

хм....потеряли мой скрипт :/

   
 
 автор: cheops   (06.02.2006 в 13:49)   письмо автору
 
   для: P@Sol   (06.02.2006 в 13:28)
 

Начиная с задачи N3 действует автоматическая система регистрации ответов - теперь ничего не будет терятся - система либо обязательно зарегистрирует ответ, либо откажется его принимать, если время отведённое на решение закончилось. Приём заданий по задаче 3 закончилось - ответы по задаче 4 принимаются в форме http://www.softtime.ru/task/addthemeform.php?id_task=4 до четверга (в четверг подведение итогов и выкладывается новая задача).

   
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования