Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Epic PHP #6

Roma
March 17, 2014

Epic PHP #6

Слайды к шестому занятию курса Epic PHP (http://epixx.ru/epic-php/).
Темы: работа с файлами, даты и время, безопасность

Roma

March 17, 2014
Tweet

More Decks by Roma

Other Decks in Programming

Transcript

  1. Epic PHP #6
    Рома Лапин, Evercode Lab

    View Slide

  2. Работа с файлами

    View Slide

  3. View Slide

  4. Как правило
    • Открытие файла

    • Манипуляции с данными

    • Закрытие файла

    • Но можно и проще

    View Slide

  5. file_get_contents()
    Считывает все содержимое файла в виде строки.

    !

    $dataString = file_get_contents(‘uploaded_file.csv’);

    var_dump($dataString);

    !
    $habr = file_get_contents('http://habrahabr.ru/');

    echo $habr;

    View Slide

  6. file_put_contents()
    Пишет строку в файл.

    !

    $file = 'secretes.txt';

    $current = file_get_contents($file);

    $current .= "Santa Claus does not exist!\n";

    file_put_contents($file, $current);

    View Slide

  7. Как правило
    • $fp = fopen(‘somedata.txt’, ‘w’);

    • fread($fp , 1024 );

    • fwrite($fp , ‘hello’);

    • fclose($fp);

    View Slide

  8. Режимы
    • r — только чтение

    • r+ — одновременно чтение и запись

    • w — создание нового пустого файла

    • w+ — r+ и w вместе

    • a — запись в конец файла

    • a+ — еще и создаст, если что

    View Slide

  9. Пишем в файл

    $fp = fopen("shfile.txt", "a");

    $mytext = "Строку эту допишем мы в файл.\r\n";

    $test = fwrite($fp, $mytext);

    if ($test) {

    echo 'Данные добавлены! Уиии!';

    } else {

    echo 'Что-то не круто.';

    }

    fclose($fp);

    View Slide

  10. Читаем из файла

    $handle = fopen("/data/superHeros.txt", "r");

    if ($handle) {

    while (($buffer = fgets($handle, 4096)) !== false) {

    echo $buffer;

    }

    if (!feof($handle)) {

    echo "Error: unexpected fgets() fail\n";

    }

    fclose($handle);

    }

    View Slide

  11. Полезные константы
    • __LINE__

    • __FILE__

    • __DIR__

    View Slide

  12. file()
    Считываем весь файл в массив.

    !

    $lines = file('orders.csv');

    !
    foreach ($lines as $line_num => $line) {

    echo "Line #{$line_num} : " . $line . "
    \n";

    }

    !
    $html = implode('', file('https://news.ycombinator.com/'));

    View Slide

  13. Функции
    • is_dir($path);

    • is_file($path);

    • is_link($path);

    • is_readable($path);

    • is_writable($path);

    • file_exists($filename);

    View Slide

  14. Функции. CSV
    $row = 1;

    if (($handle = fopen("test.csv", "r")) !== false) {

    while (($data = fgetcsv($handle, 1000, ",")) !== false) {

    $num = count($data);

    echo " $num fields in line $row:
    \n";

    $row++;

    for ($c=0; $c < $num; $c++) {

    echo $data[$c] . "
    \n";

    }

    }

    fclose($handle);

    }

    View Slide

  15. Функции. CSV
    $list = array (

    array('aaa', 'bbb', 'ccc', 'dddd'),

    array('123', '456', '789'),

    );

    !
    $fp = fopen('file.csv', 'w');

    !
    foreach ($list as $fields) {

    fputcsv($fp, $fields);

    }

    !
    fclose($fp);

    View Slide

  16. Важно
    • Проверки файлов на существование

    • Проверки на отработку функций чтения
    и записи

    • Проверки проверок на проверки
    проверок

    • Ошибок при работе файлов обычно
    много

    View Slide

  17. Задание
    На сайте http://chuckipsum.com/ берем текст и
    сохраняем в файл chuck.txt в дереве нашего
    проекта. Далее все результаты пишем в новый файл
    result.txt.

    !
    1. Переставить абзацы в тексте в обратном порядке

    2. Заменить каждое вхождение “Chuck Norris” на
    “Чебурашка”. А если скучно, то только каждое
    второе.

    3. Удалить каждую третюю строку.

    View Slide

  18. Задание
    Делаем простой импорт данных в БД.

    index.php: форма с файловым полем

    import.php: сохраняем файл в каталог data, каждую
    строчку файла сохраняем в табличку messages(id,
    row) в базе epicphp, делаем редирект обратно на
    index.php.

    Если при обработке была ошибка, сохраняем ее в
    сессию и выводим на index.php после редиректа.

    View Slide

  19. Работа с датами
    и временем

    View Slide

  20. View Slide

  21. Даты и время
    • Нужны очень часто

    • И очень важны

    • В контексте бизнес-логики приложений
    (время транзакций, подсчеты, ...)

    • В контексте сопутствующей информации
    (логи, метки данных, ...)

    View Slide

  22. time()
    Возвращает текущее абсолютное время. Это число
    равно количеству секунд, которое прошло с
    полуночи 1 января 1970 года (с начала эпохи
    UNIX).

    !
    Значение не зависит от часового пояса (UTC).

    View Slide

  23. time()

    $tomorrow = time() + (24 * 60 * 60);

    !
    echo 'Tomorrow: '. date('Y-m-d', $tomorrow) ."\n";

    View Slide

  24. time()

    View Slide

  25. date()
    Самая популярная и олдскульная функция для
    форматирования даты и времени.

    View Slide

  26. date()
    // Monday

    echo date("l");

    !
    // Monday 8th of August 2005 03:12:46 PM

    echo date('l jS \of F Y h:i:s A');

    !
    // July 1, 2000 is on a Saturday

    echo "July 1, 2000 is on a " . date("l", mktime(0, 0, 0, 7, 1, 2000));

    View Slide

  27. date()
    • второй параметр — абсолютное время
    (timestamp)

    • если timestamp не указан, по умолчанию
    time()

    • Лучше в строке формата не вставляйте
    дополнительных слов и символов — без
    правильной обработки вывод может
    быть неожиданным

    View Slide

  28. date()

    // Wednesday the 15th

    echo date('l \t\h\e jS');

    View Slide

  29. mktime()
    Генерит timestamp для конкретной даты.

    !

    echo date("M-d-Y", mktime(0, 0, 0, 12, 32, 1997));

    echo date("M-d-Y", mktime(0, 0, 0, 13, 1, 1997));

    echo date("M-d-Y", mktime(0, 0, 0, 1, 1, 1998));

    echo date("M-d-Y", mktime(0, 0, 0, 1, 1, 98));

    View Slide

  30. strtotime()
    Конвертит английское строковое представление времени в timestamp.
    Отличается умом и сообразительностью.

    !

    echo strtotime("now"), "\n";

    echo strtotime("10 September 2000"), "\n";

    echo strtotime("+1 day"), "\n";

    echo strtotime("+1 week"), "\n";

    echo strtotime("+1 week 2 days 4 hours 2 seconds"), "\n";

    echo strtotime("next Thursday"), "\n";

    echo strtotime("last Monday"), "\n";

    View Slide

  31. Проблемы работы с
    датами и временем

    View Slide

  32. Проблемы работы с
    датами и временем
    • Часовые пояса

    • Переходы на летнее/зимнее время

    • Локализация

    • Разница форматов

    View Slide

  33. Часовые пояса

    View Slide

  34. Часовые пояса
    Попробуйте

    !

    echo date('H:i:s');

    !
    date_default_timezone_set('America/New_York');

    echo date('H:i:s');

    !
    // в php.ini есть настройка date.timezone

    View Slide

  35. Локализация

    View Slide

  36. Локализация
    // выводит названия дней на разных языках

    // локали должны быть установлены в системе

    !
    setlocale(LC_TIME, "fi_FI");

    echo strftime(" in Finnish is %A,");

    setlocale(LC_TIME, "fr_FR");

    echo strftime(" in French %A and");

    setlocale(LC_TIME, "de_DE");

    echo strftime(" in German %A.\n");

    View Slide

  37. setlocale
    • LC_ALL

    • LC_COLLATE

    • LC_NUMERIC

    • LC_TIME

    View Slide

  38. strftime
    • Форматирует время и даты с учетом
    локали

    • http://strftime.net/

    View Slide

  39. DateTime
    Самый модный, современный и удобный способ
    работы с датами в PHP.

    View Slide

  40. DateTime

    $raw = '22. 11. 1968';

    $start = \DateTime::createFromFormat('d. m. Y', $raw);

    !
    echo 'Start date: ' . $start->format('m/d/Y') . "\n";

    !
    $now = new \DateTime();

    echo 'Time to change your life is: ' . $now->format('H:i:s d.m.Y') . "\n";

    View Slide

  41. DateTime
    • Форматирование

    • Сравнение

    • Операции с датами

    View Slide

  42. DateTime. Сравнение

    if ($start < $end) {

    echo "Start is before end!\n";

    }

    View Slide

  43. DateInterval

    // создаем копию $start и прибавляем 1 месяц и 6 дней

    $end = clone $start;

    $end->add(new \DateInterval('P1M6D'));

    !
    $diff = $end->diff($start);

    echo 'Difference: ' . $diff->format('%m month, %d days (total: %a days)') . "\n";

    // Difference: 1 month, 6 days (total: 37 days)

    View Slide

  44. DateInterval
    • Не пишите код, которые полагается на
    фиксированне число секунд в каждом
    дне. Часовые пояса и перевод времени
    все вам сломают.

    • Используйте промежутки времени

    View Slide

  45. DatePeriod

    // Выводим все четверги между $start и $end

    $periodInterval = \DateInterval::createFromDateString('first thursday');

    $periodIterator = new \DatePeriod(

    $start, $periodInterval, $end, \DatePeriod::EXCLUDE_START_DATE

    );

    foreach ($periodIterator as $date) {

    // выводим все даты за период

    echo $date->format('m/d/Y') . ' ';

    }

    View Slide

  46. Даты и БД
    • НЕ ИСПОЛЬЗУЙТЕ VARCHAR!

    • TIMESTAMP

    • проблема Y2K38 (32-bit integer)

    • DATETIME

    • DATE, TIME, YEAR

    View Slide

  47. Задание
    Определите сколько дней осталось до 14 июля, 31
    декабря, до вашего дня рождения.

    !
    Сколько часов осталось до конца дня?

    !
    Вывести дату 15 дней назад.

    Вывести дату на 5 месяцев вперед.

    !
    По возможности сделайте это и с помощью
    функций, и с помощью DateTime.

    View Slide

  48. Безопасность
    приложений

    View Slide

  49. Безопасность

    View Slide

  50. Уровни
    • Сам сервер

    • База данных

    • PHP скрипты

    View Slide

  51. Концепции
    • Plan for failure

    • Fail early

    • Принцип минимальных привилегий

    • Фильтрация

    • Экранирование

    View Slide

  52. Fail early

    View Slide

  53. Fail early
    // Development

    !
    display_errors = On

    display_startup_errors = On

    error_reporting = -1

    log_errors = On

    View Slide

  54. Fail early
    // Production

    !
    display_errors = Off

    display_startup_errors = Off

    error_reporting = E_ALL

    log_errors = On

    View Slide

  55. Register Globals
    Если PHP < 5.4.0, убедитесь, что в php.ini

    register_globals = off

    View Slide

  56. Конфиги
    Храните конфиги там, где их нельзя посмотреть
    напрямую. И основной код желательно тоже.

    !
    ├── src

    │ ├── App

    │ ├── config.php

    │ └── views

    ├── web

    │ └── index.php

    View Slide

  57. Валидация
    • Данным от пользователей доверять
    нельзя ($_GET, $_POST, файлы, куки...)

    • Валидируйте данные сразу, не оставляйте
    на потом

    • Сообщайте пользователям, что пошло не
    так, сразу

    • Whitelist vs Blacklist

    View Slide

  58. Ситуации
    • Пользователь ввел данные, которые
    требовалось и в нужном формате

    • Пользователь ввел что-то не так, не
    разобравшись в ваших требованиях

    • Пользователь проверяет вашу систему на
    прочность неправильными данными

    View Slide

  59. strip_tags

    $text = 'Test paragraph.

    Other text';

    echo strip_tags($text);

    echo "\n";

    !
    // Allow and

    echo strip_tags($text, '');

    View Slide

  60. htmlspecialchars &
    htmlentities

    $new = htmlspecialchars("Test", ENT_QUOTES);

    echo $new; // <a href='test'>Test</a>

    !
    $str = "A 'quote' is bold";

    !
    // A 'quote' is <b>bold</b>

    echo htmlentities($str);

    !
    // A 'quote' is <b>bold</b>

    echo htmlentities($str, ENT_QUOTES);

    View Slide

  61. Валидация

    $email_a = '[email protected]';

    $email_b = 'someshittydata';

    !
    if (filter_var($email_a, FILTER_VALIDATE_EMAIL)) {

    echo "This (email_a) email address is considered valid.";

    }

    if (filter_var($email_b, FILTER_VALIDATE_EMAIL)) {

    echo "This (email_b) email address is considered valid.";

    }

    View Slide

  62. Очистка
    $email = '([email protected])';

    !
    $sanitized_email = filter_var($email, FILTER_SANITIZE_EMAIL);

    if (filter_var($sanitized_email, FILTER_VALIDATE_EMAIL)) {

    echo "This (c) sanitized email address is considered valid.\n";

    echo "Before: $email\n";

    echo "After: $sanitized_email\n";

    }

    View Slide

  63. filter_input

    $search_html = filter_input(

    INPUT_GET, 'search', FILTER_SANITIZE_SPECIAL_CHARS

    );

    $search_url = filter_input(

    INPUT_GET, 'search', FILTER_SANITIZE_ENCODED

    );

    View Slide

  64. XSS
    index.php?name=guestalert('attacked')

    !

    $name = $_GET['name'];

    echo "Welcome $name
    ";

    View Slide

  65. Загрузка файлов
    • Проверять тип файла PHP функциями

    • Выключить вывод списков файлов для
    директорий загрузки и возможность
    выполнять файлы в них

    • Можно располагать директории загрузок
    вне Document root

    View Slide

  66. Другие угрозы
    • Session Fixation

    • Session Hijacking

    • Command Injection

    • CSRF

    View Slide