edit full article archive to publication standard
Build and deploy / deploy (push) Successful in 18s

This commit is contained in:
2026-07-31 23:08:19 +03:00
parent 440c8721dc
commit 7c5b19c960
28 changed files with 583 additions and 39 deletions
+1 -1
View File
@@ -85,7 +85,7 @@ const practiceArticle = {
readingMinutes: 9,
contentHtml: [
paragraph('Загрузка аватара обычно начинается с одного поля формы и вызова <code>move_uploaded_file</code>. Ошибка становится заметна позже: каталог <code>uploads</code> оказывается доступен из веб-корня, имя файла совпадает с уже существующим, а проверка сводится к <code>.jpg</code>. В итоге сервер принимает решение по данным, которые прислал браузер. Давайте соберём минимальный маршрут, где каждое такое решение видно в коде.'),
paragraph('Вопрос этой заметки один: <strong>как принять только JPEG и PNG для аватара, не превращая имя и MIME-тип из формы в правило безопасности?</strong> Пример рассчитан на PHP 7.2. Он не заменяет антивирус и не умеет обрабатывать документы; его задача уже — дать узкий и проверяемый вход для изображения.'),
paragraph('Вопрос этой заметки один: <strong>как принять только JPEG и PNG для аватара, не превращая имя и MIME-тип из формы в правило безопасности?</strong> Пример рассчитан на PHP 7.2. Он не заменяет антивирус и не умеет обрабатывать документы; его задача уже — дать узкий и проверяемый вход для изображения. Цена ошибки — файл в веб-корне, который можно открыть или выполнить не по назначению.'),
heading('Сначала договоримся о результате'),
paragraph('Форма передаёт один файл <code>avatar</code>. Мы принимаем не более 2 МБ, только <code>image/jpeg</code> и <code>image/png</code>, а затем ограничиваем ширину и высоту. В базе или профиле хранится ключ, который придумало приложение, например <code>7f4a...c2.png</code>. Исходное имя можно показать пользователю после отдельной обработки, но оно не участвует в пути на диске.'),
figure(