Итак, вы решили поднять свою браузерку.

Вы понимаете все сопутствующие нюансы и принципы поведения Администратора браузерки: habrahabr.ru/post/249625
Вы чётко осознаёте, что единственный разумный вариант, зачем в это стоит впрягаться — это саморазвитие, причем это не самый лучший путь: habrahabr.ru/post/249705

Мыши кололись и плакали, но продолжали жрать кактус…

Окей. В ваши цепкие лапки попал какой-нибудь скачанный из инета движок браузерки. В лучшем случае — это будет опенсорс с хорошим количеством форков (т.е. свободный от «детских проблем»). Возможно это будет т.н. «дамп» — т.е. слитый с живого коммерческого сервера движок с дампом БД. Но вероятнее всего — это будет очередная «поделка на тему». Вот на последнем случае мы и остановимся — потому что минимально необходимые действия общие для всех трёх случаев.

Здесь я неявно предполагаю, что ваш движок базируется на PHP+MySQL. Именно для этой связки я и буду вести дальнейший рассказ. Если у вас ВДРУГ Python+PostgressSQL — ничего страшного. Фундаментальные принципы работы с такими движками идентичны — различается лишь реализация.

Что же вам нужно сделать в первую очередь с движком? Ответить на этот вопрос не так-то просто, не ознакомившись с основными принципами работы с данными внутри браузерного движка (да и вообще — любого сайта или даже любой программы). Принципов этих немного и они весьма просты.

Данные, пришедшие от пользователя — токсичны


НЕ ДОВЕРЯЙТЕ ПОЛЬЗОВАТЕЛЬСКОМУ ВВОДУ!
Все данные, исходящие от пользователя по определению считаются «токсичными» — т.е. неправильными, невалидными или даже злонамеренными до тех пор, пока не будет доказано обратное. Это значит, что все данные от пользователя нужно проверять на стороне сервера.

Вы думаете, что у вас есть чудесный валидатор на JavaScript, который не пропустит некорректные данные к бэкенду? ОШИБКА! Любой запрос от фронтенда (та часть, что непосредственно видна пользователю и отвечает за взаимодействие с ним) вашего движка можно фальсифицировать — поэтому бэкэнд (та часть, которая производит фактическую обработку данных на стороне сервера и записывает изменения в БД) ОБЯЗАН всегда повторять расчёты фронтенда, что бы быть уверенным, что вам не скормили туфту.

Нормализация данных


Все операции внутри фронтенда и бэкэнда должны производиться над исходными данными с минимальным преобразованием. Чуточку непонятно?

Ну, например, у вас есть последовательность символов, которая по факту является многострочным текстом. Вроде бы ничего сложного и всё очевидно, так? ОШИБКА! Строка может быть получена из внешнего файла.

Тут сразу начинаются пляски с бубном по поводу символа перевода строки. Ведь в разных системах конец строки кодируется по-разному. Файлы Юникс-подобных систем отбивают новую строку символом LF (Line Feed, ASCII 0x0A). Старые системы (МакОСь до 9-й версии, Коммодор и ещё некоторые) обожали заканчивать строку символом CR (Carriage Return, ASCII 0x0D). Самая десктопная ОСь Винда (как наследник MS-DOS) обожают комбинацию CR+LF — и именно в таком порядке!

И тут появляется великий HTML, для которого всё, что за рамками тэга «pre» (и других подобных тегов) — суть одна строка. А разбивка на строки производится тегом <br>. Который, конечно, правильно записывать как <br />. Допускается так же и <br/>, <br > итд

Проблема с нормализацией строк не зря упомянута первой. Обычно неправильная нормализация строк не даёт критичных ошибок — зато чаще всего видна игрокам. Кому приятно вместо отформатированного по параграфам текста увидеть что-то вроде
Строка 1\r\nСтрока 2\r\nСтрока 3? Или даже Строка 1<br />Строка 2<br />Строка 3, что случается при одновременной ошибке в нормализации данных и форматировании вывода.

Числа не лишены аналогичных проблем. Казалось бы — что может быть проще числа? intval() и floatval() (и их аналоги в JavaScript — впрочем, это отдельный разговор. JS позволяет выстрелить себе в ногу множеством изощрённых путей...) должны решить все проблемы, правда же? ОШИБКА!

Какое число получится в переменной, если в PHP-бэкэнде написать intval(0123)? Думаете — 123? Ну, тогда вперед, читать мануал: php.net/manual/ru/language.types.integer.php

Отдельная песня — числа с плавающей точкой в PHP и их сравнение. Здесь не урок по PHP — поэтому опять же отошлю к документации: php.net/manual/ru/language.types.float.php Особенное внимание предлагаю уделить внимание вставке «Точность чисел с плавающей точкой» и подразделу «Сравнение чисел с плавающей точкой».

Вряд ли это будет актуально на первом этапе развития, но для понимания важности нормализации данных не могу не упомянуть об отдельном интересном вопросе идентификаторов в БД. Ну, это те самые веселые числа, объявленные как BIGINT(20) в БД и определяющие уникальность каждой записи.
Чтобы полностью понять суть проблемы — опять сошлюсь на документацию PHP php.net/manual/ru/reserved.constants.php Искать в тексте ключевое слово PHP_INT_MAX. Посчитать количество символов. Сравнить с описанием структуры БД выше. Подсказка — в MySQL данное объявление означает число с 20 значащими символами до запятой. При неаккуратной работе с таким идентификатором в PHP- или JS-коде он легко может обратиться во float с потерей точности.

Какой вывод можно сделать из всего вышенаписанного? Данные должны быть НОРМАЛИЗИРОВАНЫ — т.е. приведены к некоей стандартизированной форме, которая будет восприниматься вашим движком отныне и везде. Обычно автор(ы) движка неявно выбирают какую-то одну форму нормализации. К сожалению — те же автор(ы) соблюдают её далеко не всегда и не везде.

Экранирование выводимых данных


Вы удивитесь, насколько часто игре надо будет выводить данные для игроков! Здесь нас так же поджидает куча интересных откровений.

Вывод в HTML


Самое главное правило таково — ЛЮБОЙ вывод в HTML неконтролируемых данных должен производиться исключительно через функцию htmlentities() php.net/manual/ru/function.htmlentities.php! Еще раз подчеркну — ЛЮБОЙ! БЕЗ ИСКЛЮЧЕНИЙ!

Здесь нужно заметить, что данные в движке делятся на «контролируемые» и «неконтролируемые». К первым относятся такие сущности как простые строки локализации, гарантированно нормализованные целые числа, гарантированно нормализованные однострочные строки и… пожалуй — всё. Все остальные данные являются «неконтролируемыми» и должны проходить через мелкое сито htmlentities(). Да, это кажется излишним усложнением — но в будущем это как минимум убережет от порчи вида игры, а как максимум — в определенной мере гарантирует невозможность заражения компьютера игрока враждебными скриптами (100% гарантию даёт только «Госстрах»).

Здесь стоит сделать отступление и подробно поговорить о каждом типе контролируемых данных.

Контролируемые данные в HTML


Начнём с самого простого — с гарантированно нормализованных целых чисел. К ним относятся переменные $variable, которые на проверку is_int($variable) отвечают 'true'. Тупо. Прямо. В лоб. 100% гарантия, что данные переменные при выводе будут состоять только из десятичных цифр, не содержат ничего постороннего и одинаково красиво выглядят в HTML и JS.

Простые строки локализации — это строки из текущей локали, которые состоят из одной строки, не содержат HTML-тэгов, не содержат спецсимволов HTML типа < > " ', переводов строки, не являются регекспами и не являются шаблонами. Здесь тоже вроде всё понятно с первого взгляда. Вроде бы строки локализации полностью контролирует разработчик движка. Вроде бы никаких подводных камней быть не должно — и все эти уточнения излишни… WRONG!

Типичнейшая ошибка — использование шаблонов строк типа «Начало строки %s остальная строка» с последующим использованием функции sprintf(). Мы помним, что данные у нас — должны быть нормализированы, т.е. приведены к стандартному формату. Однако нигде не сказано, что нормальный формат хоть для чего-то является безопасным! Нормализация формата переменных всего лишь гарантирует единообразие вида данных, обрабатываемых в разных кусках кода — и не более того. Являются ли данные безопасными для вывода в HTML или (тем более!) для записи в БД — это нам неизвестно (вообще-то известно — по определению не являются). Поэтому прямой вывод данных в шаблон без указания дополнительных модификаторов — недопустим. Более того — не всякий модификатор гарантирует безопасный вывод данных.

Замечу — тут мы говорим именно о безопасности вывода, а не о корректности. Например, вывод переменной в шаблон "%d" является безопасным, но не является корректным — если, например, на вход будет подана строка, не сводимая к целому. Тут опять же не могу не отослать к документации: php.net/manual/ru/function.sprintf.php

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

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

Почему гарантированно нормированные строки должны содержать только одну строку/параграф — должно быть уже понятно из прочитанного выше. Но на всякий случай повторюсь — многострочные строки (даже нормированные) требуют разного отношение при выводе в HTML, JS или при сохранении в БД.

Неконтролируемые данные в HTML


Выше мы рассмотрели три вида контролируемых данных, которые (с оговоркам) могут выводится напрямую в HTML минуя функцию htmlentities(). Все остальные данные В ОБЯЗАТЕЛЬНОМ ПОРЯДКЕ должны проходить через вышеупомянутую функцию! Однако здесь есть НЮАНСЫ.

Фактически, «неконтролируемыми данными» являются пользовательские данные, либо строки, не подходящие под вышеописанные критерии. Как работать с пользовательскими данными — будет подробно описано в следующей статье. А работа со строками движка (в частности — локализация) — достаточно деликатная тема.
В зависимости от качества исходного продукта, принципы работы со строками, источниками которых является сам движок, могут сильно отличаться. Я могу дать лишь рекомендации — которые ни в коем случае не должны являться догмой. Очень многое зависит от того, как движок описывает многострочные данные вообще и строки локализации — в частности.

1. Если движок использует для разделения строк в тексте символы CR, LF или комбинацию CR+LF — используйте сначала htmlentities(), а затем — PHP-функцию nl2br() php.net/manual/ru/function.nl2br.php
2. Если движок использует для разделения строк тэг <br /> — выводите данные напрямую, если вы полностью проверили код и уверены в его безопасности
3. Весь вывод шаблонов с использованием форматирования "%s" и аналогичного — всегда ДОЛЖЕН проходить через htmlentities()!

В любом случае ВСЕГДА нужно помнить основополагающий принцип — лучше вывести игроку «некрасивую», но гарантированно безопасную строку, чем в 99,99% выводить «красоту», а в 0,01% — заражать компьютер игрока вредоносным скриптом.

В следующей статье:
— Вывод данных в JavaScript — особенности и приколы;
— Запись данных в БД — как не «попасть» на SQL-injection;
— Как убедится, что данные от пользователя не являются «токсичными»;
— … и многое другое

Комментарии (15)


  1. gene4000
    24.01.2016 08:13
    +1

    А есть ли смысл делать не вывод с htmlentities(), а ввод? Ведь тогда получается, что обработка будет сделана только один раз. Или же в БД данные могут попасть не только от вредительствующих игроков?


    1. aml
      24.01.2016 11:55
      +1

      Затем, что презентация данных не всегда делается через HTML. Может быть, вам надо будет текстовое письмо отправить, может в JSON завернуть, чтобы в API выдать, может в мобильное приложение передать и т.д. Данные должны храниться всегда в сыром виде.


      1. SuperNovaWS
        24.01.2016 20:38
        +1

        Подпишусь

        IMHO — данные внутри движка должны циркулировать в виде «что бы не стыдно было в базу положить». Т.е. со стандартизированной отбивкой строк (CR+LF или LF — кому что ближе. Главное — единообразно по всему движку и независимо от системы), без какого-либо HTML-форматирования (хочется форматирования? Используйте BBCode или аналоги!), естественно — без какого-либо PHP-кода под eval().

        Еще очень полезно явно типизировать переменные. Если это целое — значит это именно integer 48, а не string '48'. Если логическая переменная — значит типа boolean true/false, а не integer 1/0 итд


  1. michael_vostrikov
    24.01.2016 08:26
    +15

    Зачем учить новичков плохому…

    поэтому бэкэнд (та часть, которая производит фактическую обработку данных на стороне сервера и записывает изменения в БД) ОБЯЗАН всегда повторять расчёты фронтенда
    Наоборот, фронтенд обязан повторять расчеты бэкенда. Вернее даже не так. Фронтенд может повторять проверки бэкенда — для ускорения работы и улучшения UI, а может и не повторять. На бэкенде все проверки всегда должны быть в полном объеме.

    Тут сразу начинаются пляски с бубном по поводу символа перевода строки.
    Насколько я знаю, браузеры вполне неплохо сами разбираются с разными переводами строк. В любом случае, это исправляется простой заменой разных переводов строк на нужные в функции получения данных из файла.

    И тут появляется великий HTML
    Не надо путать текст и HTML. Если в файле есть <br>, значит это разметка, и не надо работать с ней как с текстом. Если разметка расположена вперемешку с текстовыми файлами, значит это проблема в архитектуре конкретного проекта. Исправить можно аналогично, через замену по регулярному выражению. Переводы строк тут ни при чем.

    Кому приятно вместо отформатированного по параграфам текста увидеть что-то вроде
    Это ошибка только в форматировании вывода. Любая замена переводов строк эту проблему не решит.

    Какое число получится в переменной, если в PHP-бэкэнде написать intval('0123')
    Выведет 123. Кстати, вам надо было поставить там ссылку на документацию по intval() (заодно и сами бы почитали).
    Если записать без кавычек, то будет 83, но это уже изначально int, записанный в 8-ричной системе. Это аналогично записи 0x123 без кавычек для 16-ричной. Лидирующие нули в строках на результат не влияют. А для преобразования string в int лучше использовать приведение типов "(int)$var".

    Отдельная песня — числа с плавающей точкой в PHP и их сравнение
    PHP здесь ни при чем, так происходит во всех языках, это особенность представления таких чисел в процессоре.

    Ну, это те самые веселые числа, объявленные как BIGINT(20,0) в БД
    Откуда у INT дробная часть?
    ALTER TABLE `test_table` ADD COLUMN `test_column` BIGINT(20,0) NOT NULL;
    /* SQL Error (1064): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '0) NOT NULL' at line 1 */
    

    «Что бы полностью понять суть проблемы», надо знать, что такое разрядность. Да и вообще, для большинства таблиц простого INT хватает. Не собираетесь же вы в каждой таблице по 3 миллиарда записей хранить?

    htmlentities()
    Рекомендуют использовать htmlspecialchars().

    многострочные строки (даже нормированные) требуют разного отношения при выводе в HTML, JS или при сохранении в БД
    Не знаю, что за задачи этого требуют, лично я ни разу не сталкивался. Обычно что сохраняем, то и выводим, плюс экранирование. Для javascript можно выводить через json_encode().


    1. SuperNovaWS
      24.01.2016 17:01
      +1

      > Зачем учить новичков плохому…

      Вполне нормальный ВВОДНЫЙ текст для новичка. В школе тоже не сразу теорвер дают, а в первых классах изучают арифметику.
      Такое ощущение, что текст вы не читали или не вдумывались в него и спорите чисто что бы поспорить.

      > Наоборот, фронтенд обязан повторять расчеты бэкенда. Вернее даже не так. Фронтенд может повторять проверки бэкенда — для ускорения работы и улучшения UI, а может и не повторять. На бэкенде все проверки всегда должны быть в полном объеме.

      Фронтенд первым производит валидизацию данных чисто по-определению фронтенда и бэкэнда. Поэтому именно бэкэнд должен повторять ВСЕ проверки фронтенда как минимум и, возможно, производить свои.

      > Насколько я знаю, браузеры вполне неплохо сами разбираются с разными переводами строк. В любом случае, это исправляется простой заменой разных переводов строк на нужные в функции получения данных из файла.

      … именно это и является «нормализацией данных» как я писал в статье.

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

      Что значит «путать»? HTML является разновидностью текста. Ну и расскажите, что «не надо работать с разметкой, как с текстом» не мне, а десяткам авторов различных движков сайтов.

      > Это ошибка только в форматировании вывода. Любая замена переводов строк эту проблему не решит.

      Вы действительно не читали текст. Я же написал: «что случается при одновременной ошибке в нормализации данных и форматировании вывода.» Нормирование текста и замена символов новой строки на единообразные нужны, потому что часто в движка встречается не использование nl2br(), а конструкции вида str_replace("\r\n", '<br>', $string)

      > Выведет 123. Кстати, вам надо было поставить там ссылку на документацию по intval() (заодно и сами бы почитали).

      Тут кавычки не нужны, согласен. Поправил.

      > PHP здесь ни при чем, так происходит во всех языках, это особенность представления таких чисел в процессоре.

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

      > Ну, это те самые веселые числа, объявленные как BIGINT(20,0) в БД

      Много работал с DECIMAL — поэтому автоматически поставил и здесь десятичную точность. Поправил.

      > Не собираетесь же вы в каждой таблице по 3 миллиарда записей хранить?

      А почему бы и нет?

      > Рекомендуют использовать htmlspecialchars().

      Абсолютно вредные рекомендации для новичка. htmlentities() дополнительно перекодируют одинарную кавычку — что бывает важным при выводе в JavaScript, а так же спецзнаки типа ©, ®, ™ и некоторых других. Таким образом — htmlentities() безопаснее в применении.

      >> многострочные строки (даже нормированные) требуют разного отношения при выводе в HTML, JS или при сохранении в БД

      > Не знаю, что за задачи этого требуют, лично я ни разу не сталкивался. Обычно что сохраняем, то и выводим, плюс экранирование. Для javascript можно выводить через json_encode().

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


      1. DSL88
        24.01.2016 19:17
        +1

        Вы меня простите, но на сервере можно хранить текст таким, какой он есть, аля производя минимальные операции по изменению… На фронте же вы можете добавить обработку вызова и это, сюрприз-сюрприз, снимет с вас часть проблем.

        > дополнительно перекодируют одинарную кавычку — что бывает важным при выводе в JavaScript
        JSON должен быть в двойных кавычках. Если вы не используете json_encode, то проблемы на вашей стороне.
        Все равно строка будет с кавычкой.
        Скажите вариант, когда это не поможет?!


        1. SuperNovaWS
          24.01.2016 19:57

          ю Вы меня простите, но на сервере можно хранить текст таким, какой он есть, аля производя минимальные операции по изменению… На фронте же вы можете добавить обработку вызова и это, сюрприз-сюрприз, снимет с вас часть проблем.

          Именно об этом я и говорю другими словами. Хранить данные в «сыром» виде, всю обработку в общепринятый в движке (т.е. «нормализованный вид») проводить при вводе данных, преобразовывать формат для представления — при выводе.

          >> дополнительно перекодируют одинарную кавычку — что бывает важным при выводе в JavaScript
          > JSON должен быть в двойных кавычках. Если вы не используете json_encode, то проблемы на вашей стороне.
          > Все равно строка будет с кавычкой.
          > Скажите вариант, когда это не поможет?!

          Когда движок — чужой и вообще по-первах непонятно, как там и что устроено.
          Когда программист — новичок и вообще не представляет, что вообще можно сделать.

          Еще раз — это БАЗОВАЯ и ПРОСТАЯ теория для НОВИЧКОВ, которые сами решили взяться за доработку чужого движка.

          Статья написана на основании собственного опыта ковыряния чужих движков — как новичком, так и в более опытном состоянии. Я искренне уверен, что мне бы вот такая статья очень сильно бы помогла в начале пути. Дала бы базовую теорию, указала на основные принципиальные подходы итд итп

          Да, здесь нет глубокомысленных рассуждений о необходимости, скажем, Dependency Injection или автолоадеров по формату PSR-4… Так и в самописных движках, что доступны широкой публике обычно речь идёт не о том, что не используется DI или юнит-тесты, а о том. как бы рагрести HTML-CSS-PHP-SQL спагетти-код и хоть как-то закрыть игру от явных SQLi.


          1. DSL88
            24.01.2016 21:06
            +1

            Ну, в плане новичков — согласен. За свои N лет разработки я уже переобучился писать так, чтобы никому не было больно…


      1. michael_vostrikov
        24.01.2016 20:44
        +2

        В школе тоже не сразу теорвер дают

        Я не сказал, что текст сложный, я сказал, что он дает неправильную информацию при объяснении особенностей. Конкретно:
        — Про бэкенд. Из текста и из вашего комментария складывается впечатление, что бэкенд вторичен. На самом деле он «главнее», потому что в нем находится логика. Если на фронтенде нет проверок, а на бэкенде есть, проблем с данными не будет. А если на бэкенде нет проверок, а на фронтенде есть, то можно отправить неправильные данные вручную, без фронтенда. У вас в статье примерно то же самое, но акцент сделан не на том.
        — Про intval. Тут вы поправили, но intval тут роли не играет. «echo 0123» тоже выведет 83. Это документированное обозначение 8-ричных чисел, так же как 0x123 обозначение для 16-ричных. Такое же обозначение используется, например, и в C++, и в Java, и в JavaScript. Из текста же складывается впечатление, что это какая-то фишка PHP, сходная с багом.
        — Числа с плавающей точкой — проблема PHP. «Я говорил конкретно про PHP — в нём эта проблема есть». Это что-то вроде «у меня ваша программа не работает — так электричества же нет, поэтому компьютер не включается — ну и что, я же в вашей программе работаю».
        — В проблеме с разрядностью про разрядность ничего не сказано. Не сказано, что в большинстве случаев такая разрядность не нужна, особенно в проектах начинающих. Если бы я не знал причину, у меня бы сложилось впечатление, что это опять какой-то косяк PHP.

        HTML является разновидностью текста

        А текст является разновидностью байтов. Это не значит, что надо с любыми данными работать как с байтовым массивом. У вас как-то все сумбурно — как будто разметка это разновидность перевода строк.

        Ну, естественно! Если вы не сталкивались — значит проблема не существует

        Там написано, что я с этой проблемой не сталкивался, я не сказал, что ее не существует. Вообще это был своего рода намек «Уважаемый автор, не расскажете ли вы, с какими именно задачами вы столкнулись, что там переводы строк это серьезная проблема. Я вот не сталкивался, вдруг понадобится, хоть буду знать». У вас половина статьи о том, что это важно, но нет никаких примеров, которые бы эту проблему иллюстрировали. Пара неправильно отформатированных строк это не примеры, потому что непонятно, как они появились.


        1. SuperNovaWS
          24.01.2016 22:33
          -2

          > — Про бэкенд. Из текста и из вашего комментария складывается впечатление, что бэкенд вторичен. На самом деле он «главнее», потому что в нем находится логика. Если на фронтенде нет проверок, а на бэкенде есть, проблем с данными не будет. А если на бэкенде нет проверок, а на фронтенде есть, то можно отправить неправильные данные вручную, без фронтенда. У вас в статье примерно то же самое, но акцент сделан не на том.

          У вас какое-то неправильно понимание. С точностью до «наоборот»: бэкенд должен КАК МИНИМУМ повторять все проверки фронтенда. Часто авторы движков полагаются на фронтенд, ослабляя проверки на бэкенде. Именно об этом данный параграф.

          > Про intval. Тут вы поправили, но intval тут роли не играет. «echo 0123» тоже выведет 83. Это документированное обозначение 8-ричных чисел, так же как 0x123 обозначение для 16-ричных. Такое же обозначение используется, например, и в C++, и в Java, и в JavaScript. Из текста же складывается впечатление, что это какая-то фишка PHP, сходная с багом.

          Опять — у вас какое-то странное понимание. Я написал про ОСОБЕННОСТЬ работы с числами — что 0123 не равно 123. И всё. Остальное вы сами додумали.

          > Числа с плавающей точкой — проблема PHP. «Я говорил конкретно про PHP — в нём эта проблема есть». Это что-то вроде «у меня ваша программа не работает — так электричества же нет, поэтому компьютер не включается — ну и что, я же в вашей программе работаю».

          Отсутствие врождённой способности оперировать с числами фиксированной точности и необходимость использовать для этого сторонние библиотеки и/или подключаемые плагины — это конкретно проблема PHP и достаточно серьезная, если игра оперирует числами типа float — в частности, если сравнивает такие числа. Особенно остро эта проблема стоит, когда в MySQL поле объявлено как DECIMAL — т.е. с фиксированной точностью.

          > В проблеме с разрядностью про разрядность ничего не сказано. Не сказано, что в большинстве случаев такая разрядность не нужна, особенно в проектах начинающих. Если бы я не знал причину, у меня бы сложилось впечатление, что это опять какой-то косяк PHP.

          Я уже не понимаю — какую статью вы читали? Указано на разницу в количестве разрядов в primary-ключе MySQL и максимальным количеством разрядов в целом числе PHP.
          Нужна такая разрядность или нет — очевидно, решать не вам. И не мне. И даже не новичку, который разбирается в чужом движке. Это решил за него автор — и вопрос, на который должен ответить новичок — соблюдает ли автор движка свои же соглашения и везде ли корректно оперирует с полной разрядностью идентификаторов.
          Я обозначил проблему. А то, что работать с целыми числами за пределами PHP_INT_MAX можно только с использованием специальных библиотек (а не просто используя стандартные операторы) — это действительно косяк PHP.

          > Там написано, что я с этой проблемой не сталкивался, я не сказал, что ее не существует. Вообще это был своего рода намек «Уважаемый автор, не расскажете ли вы, с какими именно задачами вы столкнулись, что там переводы строк это серьезная проблема. Я вот не сталкивался, вдруг понадобится, хоть буду знать».

          Очевидно — я видел это в одном из движков, которые ковырял. И проблема была именно в ненормированности данных — часть многострочных строк выводилась в JS нормально, часть — нет. В результате в лучшем случае не работал JavaScript на странице, а в худшем — появлялся мусор или вообще открывалась уязвимость для внедрения своего скрипта, потому что разработчик «запамятовал», что вводимые данные от игрока могут быть и некорректными.

          > У вас половина статьи о том, что это важно, но нет никаких примеров, которые бы эту проблему иллюстрировали. Пара неправильно отформатированных строк это не примеры, потому что непонятно, как они появились.

          Вы читал начало статьи? А её окончание? По-моему — нет. Иначе было бы очевидно, что эта — одна из статей цикла. Дальше будет (наверное — через неделю. Не снялся recovery mode) еще теория, а потом пойдут сплошные примеры.


  1. aml
    24.01.2016 11:58
    -5

    Интересно, почему статью минусуют. Она, конечно, никакого отношения к играм не имеет, но как ликбез по хранению и вводу/выводу данных веб-приложения — вполне правильная.


    1. terryP
      24.01.2016 17:02
      +2

      Выше уже разобрали ошибки статьи, да и суть статьи умещается в одну банальную строчку «не доверяйте пользовательским данным из веба», которая встречается в почти каждом руководстве «php для чайников». Для ликбеза как минимум не сказано о том что картинки и любые пользовательские файлы, сохраняемые на сервере, ттоже должны досконально проверяться. Стороние ссылки тоже проверяться и зарещаться, все sql запросы подвержены sql инъекциям и т.д., вообще правил создания безпопасного приложения намного больше чем описано в статье.


      1. Tairesh
        24.01.2016 17:22
        +1

        Ошибки либо мелкие, либо холиварные, часть уже поправлена. К чему минусовать полезную для кого-то статью в которой есть не всё, вместо того чтобы дополнить её/привести ссылку на более полную статью?


      1. aml
        24.01.2016 17:30
        +1

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


      1. SuperNovaWS
        24.01.2016 18:47
        +1

        Вообще-то это очередная статья цикла. И в конце анонсированы темы для дальнейшего рассмотрения — в том числе и SQL-injections. Все-все-все рекомендации можно, конечно, уместить в одну статью — но она тогда будет на сотни символов и её мало кто прочитает. Плюс — будет слишком много информации и поэтому она будет тяжело усваиваться.

        В «разборе» ошибок два указания на действительные неточности (опечатки по факту), несколько придирок и один вреднейший совет для НАЧИНАЮЩЕГО программиста, который имеет дело с ЧУЖИМ как правило НИЗКОКАЧЕСТВЕННЫМ движком, в котором обычно сделаны все возможные базовые ошибки новичка.