• Безопасно ли хранить .htaccess в корне сайта?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    Это очень смешной вопрос.

    Если читать только заголовок, то вопрос звучит очень смешно. Типа "опасно ли дышать?". файлик .htaccess как раз и предназначен для размещения в папках сайта, корневой или не корневой - без разницы.

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

    Во-первых, формулировка. Если вспомнить, что корнем сайта как раз и является публичная директория, то вопрос получится изначально бессмысленный, "почему файл лежит в публичной директории, а не в публичной директории?"
    То есть надо сначала понять, что речь в замечании на картинке идет про корень приложения, а не сайта. В котором корень сайта - это всего лишь одна из папок. Та самая, "публичная".

    И только после этого можно приступать к ответу на вопрос:
    В корне приложения - то есть папке, которая, по идее, вообще никакого отношения к веб-серверу не имеет, класть htaccess скорее бессмысленно. И в теории может так оказаться, что веб-сервер-апач его вообще не прочтёт. И, как следствие - некие секретные настройки могут не примениться.

    Но тут надо вспомнить, что завязывать какую бы то ни было безопасность на файлик .htaccess - это уже так себе идея. Поскольку доля веб-сервера-апач неуклонно снижается, и весьма велика вероятность того, что на реальном сервере файлик .htaccess будет просто болтаться мертвым грузом, и никто не обратит на него ни малейшего внимания.
    Ответ написан
    3 комментария
  • Как сделать кэширование запросов в Mysql 8?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    Альтернатива только в использовании MariaDB.
    Ответ написан
    2 комментария
  • Какая функция вызвала эту функцию в PHP?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    $executer = debug_backtrace()[1]['function']  ?? 'direct call';


    или чуть более расширенный вариант

    $class = debug_backtrace()[1]['class'] ?? '';
    $executer = ($class ? "$class::" : "") . (debug_backtrace()[1]['function']  ?? 'direct call');
    Ответ написан
    Комментировать
  • Как удалить параметры при редиректе?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    Ответ написан
    Комментировать
  • Как очищать текст в php?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Никак не очищать.

    На самом деле этот вопрос встречается довольно часто. Вот например популярный ответ на Stack Overflow, который подробно разбирает этот распространённое заблуждение: https://stackoverflow.com/a/3126175. И основная мысль там:

    Понятие такой генерализованной "очистки данных" изначально бессмысленное и вредное.

    Особенно такой вот индусской функцией, которая сама по себе - пример редкого идиотизма: сначала заменяем символы < и > на HTML сущности... а потом бодро пытаемся вырезать HTML теги. Которых к этому моменту в тексте не останется ни одного!
    Или функция stripcslashes, которая здесь вообще ни к селу, ни к городу. Если я хочу написать сочетание \n, то с какой стати эта функция будет заменять его на перевод строки?
    Всё что можно оставить из этого безумного набора - это trim(). Да и то не всегда. Как правильно заметил Rsa97, могут быть случаи, когда лидирующие пробелы имеют значение, например, при выводе форматированного кода. Кстати, этим как раз грешит Хабр. Если запостить код с отступами, то первый будет "съеден"!


    Очистка

    Любая "очистка" (хотя правильнее говорить про форматирование), имеет смысл только в определённом контексте.
    И поэтому "очищать" надо только адресно, строго перед использованием в том или ином конкретном случае.

    Например, базе данных ни жарко, ни холодно от наличия HTML тегов.
    А проблемы могут начаться только при выводе данных в HTML. Но если мы будем предотвращать эти проблемы заранее, то просто попортим кучу данных. Поэтому форматировать данные для использования в контексте отрисовки HTML следет строго перед этой отрисовкой. То есть при выводе.
    Что и делают все популярные РНР шаблонизаторы автоматически.
    То есть вручную колупаться с "очисткой" вообще не нужно.

    Больше того, "очистка" HTML поможет данным, выводимым в яваскрипт, как мёртвому припарки. То есть опять же - всегда надо понимать, в какой именно контекст мы выводим данные, и форматировать соответствующим образом. В частности любые данные передавать в яваскрипт только через json_encode()

    И таких контекстов неисчислимое множество. Например, если мы используем переменную для передачи параметров в консольный скрипт, то надо обязательно обрабатывать её через escapeshellarg(). Если в регулярку - то preg_quote(). Имя файла для инклюда из переменной (хотя так делать вообще не стоит) надо хотя бы обрабатывать через basename(). И так далее.

    Валидация

    Если же наличие HTML тегов в поступающих данных противоречит техническому заданию, то надо заниматься не "очисткой", а валидацией: проверить регулярным выражением, есть ли в строке HTML теги. И если есть, то вернуть пользователю с сообщением об ошибке.

    Защита БД

    И кстати, по поводу "использую pdo".
    На всякий случай уточню, что само по себе использование PDO не защищает ни от каких проблем
    Важно помнить, что защита - это когда в базу данных отправляется строго константная строка запроса, полностью на 100% составленная из значений, прописанных в коде РНР, и в ней не используется ни одно значение, пришедшее в код извне. Причем PDO помогает здесь только наполовину, позволяя использовать в запросе подстановки вместо самих данных.
    Но при этом для всех остальных частей запроса - например имен полей - у ПДО нет никакой защиты и её надо организовывать самостоятельно. Либо проверяя по белому списку, лабо, по крайней мере, прогоняя через регулярку.
    Ответ написан
    13 комментариев
  • Где в Laravel лучше делать валидацию входящих данных - в контроллере или сделать кастомный Request для контроллера, или Middleware?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    Вообще-то в Ларе УЖЕ есть этот самый отдельный сервис - Illuminate\Http\Request, который и предназначен для валидации входящих данных.
    Ответ написан
    2 комментария
  • Как выполнить sql скрипт, который хранится в файле.sql, в файле питона используя библиотеку pymysql.connect?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    4. После размещения вопроса пользователю запрещается осуществлять:
    4.1. Дублирование вопроса, который уже размещался на страницах Сервиса. В том числе и в случае, если вопрос был удалён модератором, или на вопрос не был дан ответ (т.е. категорически запрещается дублирование вопроса с целью повторного привлечения к нему внимания).
    Ответ написан
    Комментировать
  • Почему mysqli_query всегда возвращает false?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Я уже отвечал на этот вопрос

    Но самое конечно ужасное - это что этим людям доверяют работу с картами.
    При том что все данные карт утекут в тот же момент когда этот "сервис" выйдет в онлайн
    Ответ написан
  • Как автоматизировать запуск sql скриптов?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    Проще всего будет действительно через шелл скрипт ("файл с расширением sh"), причем даже записывать эту команду в файл не обязательно, а можно просто выполнить в консоли:
    for file in `ls /path/to/files/*.sql`; do mysql -uUSER -pPASSWORD DATABASE < $file ; done

    здесь mysql - это консольный клиент mysql
    Ответ написан
  • Вывожу картинки через php функцию, как вывести 2 фотки сразу?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Надо добавить метод getImages($num=2) чтобы она принимала аргументом количество картинок и возвращала массив.
    И в шаблоне можно будет сделать foreach(). Только дергать базу два раза некрасиво, лучше сначала получить в переменную, а потом ее использовать

    <?php if ($images = $product_1->getImages()) : ?>
    <?php foreach ($images as $img): ?>
        <img src="/media/uploads/small/small-<?= $img ?>" alt="<?= $product_1->prname ?>" title="Перейти в товар - <?= $product_1->prname ?>" />
    <?php endforeach ?>
    <?php else : ?>
      <img src="/media/uploads/nofoto.jpg" alt="Нет фото на товаре" title="Нет фото" />
    <?php endif; ?>
    Ответ написан
  • Проблема с переменной php на онлайн серверы, Можно как нибудь исправить?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Насколько я помню по прошлому вопросу, для $allonline надо просто перед циклом написать
    $allonline = 0;

    А для $serversonline надо самому смотреть - что это за переменная, откуда она берется и почему у неё нет значения. Ну в смысле код надо не только бодро строчить, но иногда и читать. На предмет имеет ли вообще смысл то, что мы написали. В частности, есть ли у нас переменная, к которой мы пытаемся обратиться.
    Ответ написан
    1 комментарий
  • Почему fetch() возвращает bool?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Во-первых, вместо fetch надо использовать get_result|fetch_assoc.

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

    // перед коннектом говорим mysqli чтобы сообщала об ошибках сама, 
    // чтобы не проверять каждую команду вручную
    mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
    
    // и дальше просто
    $stmt = $connection->prepare("SELECT * FROM users WHERE email = ?");
    $stmt->bind_param("s", $email);
    $stmt->execute();
    $result = $stmt->get_result();
    $row = $result->fetch_assoc();
    $hashed_password = $row["password"];
    if (password_verify($password, $hashed_password)) 
    {            
          echo "Вы успешно залогинились";
    }
    Ответ написан
    Комментировать
  • Как посчитать символы после точки и до единицы?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Самый тупой вариант: strpos($num, '1')-2;
    Ответ написан
    1 комментарий
  • Скачка файлов на сервер с удаленного хоста. Как передать параметр из php-скрипта в wget?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Буквальный ответ на этот вопрос, который будет полезен тем, кого привлечёт заголовок вопроса - escapeshellarg()
    Все параметры, которые передаются в команды шелл, должны в обязательном порядке обрабатываться этой функцией.

    Решение смешной проблемы в текущем коде - надо всего лишь использовать двойные кавычки вместо одинарных.
    $fileD = escapeshellarg("https://domain.zone/files/file".date("Ymd").".zip");
    exec ("wget -O todayfile.zip $fileD");

    Для решения же исходной задачи, разумеется, не нужен никакой РНР. Использовать для этих целей РНР - это все равно что сначала завернуть котлету в целлофановый пакет, а потом её есть. Ну ведь wget - это уже шелловая команда, и запускать её надо напрямую.

    /usr/bin/wget -O /path/todayfile.zip "https://domain.zone/files/file$(date '+%Y%m%d').zip"
    Ответ написан
    3 комментария
  • Почему при экспорте средствами crm в файле базы mysql теряются кавычки?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Если отбросить все фантастические версии, типа различий между операционными системами Centos и Ubuntu, то ошибка Duplicate entry '1' for key 'cb_tmp_acc_buttons.PRIMARY' при явном указании значения автоинкрементного поля в запросе может быть вызвана двумя причинами:
    1. в дампе дублируются значения id
    2. после установки БД уже заполнена какими-то значениями.

    Оба варианта легко проверить и исправить. В первом случае обращаться к авторам программы или поправить руками, во втором - сначала очистить базу.

    С кавычками же - это однозначно к авторам этой кривой программы.

    Ну и самое главное - нет ни одной настройки, которая одни строки обрамляет в кавычки, а другиие - нет.
    Ответ написан
  • Как округлить round в меньшую сторону c одним знаком после запятой?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Вопрос оказался не так прост, как кажется. Действительно, в РНР нет функции, которая округляет дробные числа в меньшую сторону.
    Так что остаётся только решение, предложенное Ankhena в комментариях:

    floor(758.66318000*10)/10;

    Так же, универсальное решение приведено в пользовательских комментариях к функции round() (я, правда, позволил себе его немного подредактировать):

    function round_down($number, int $precision = 2)
    {
        if  ($precision === 0) {
            return floor($number);
        }
        $fig = pow(10, $precision);
        return round(floor($number * $fig) / $fig, $precision);
    }

    (round() в конце на всякий случай, если вдруг деление вернет не 8, а 7.9999999, как это бывает с дробными числами)
    Ответ написан
    Комментировать
  • Как объединить два файла на php?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Правило номер 1: если у вас есть какая-то завиральная идея, типа "а решите мне вот такую-то примитивную стандартную задачу, но только вот с такими, такими и такими ограничениями", необходимо аргументировать свою задачу. То есть объяснять причины, которые привели вас к такой постановке вопроса.
    Ответ написан
  • Почему не работает команда в exec(), но работает, если просто ввести ее в консоли вручную?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Если при выполнении exec() возникает ошибка, то она выводится в stderr.
    Надо просто прочитать её, там будет написано, почему не работает.
    В частности, чтобы получать весь вывод кроновских команд на почту, в том числе и ошибки, надо написать в начале крон файла MAILTO=свойемейл

    Если есть проблемы с чтением stderr, то можно добавить перенаправление в stdout, записать его в переменную и дальше уже направлять по своему усмотрению
    $out = exec('cd /path && mysql -u root < "/path/my-sql.sql" 2>&1');
    log_error($out);
    Ответ написан
    Комментировать
  • Почему биндить в PDO надо обязательно переменную?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Ну вообще-то в сообщении об ошибке всё сказано. C bindParam можно использовать только переменные. Потому что биндинг идёт по ссылке (by reference). А на строку, вписанную прямо в коде, ссылку не поставишь. В этом случае надо использовать другой метод
    $b=$pdo->prepare(" INSERT INTO `main` SET tel=:tel");
    $b->bindValue(":tel", '79998887766');

    или вообще передавать данные сразу в execute():
    $pdo->prepare(" INSERT INTO `main` SET tel=:tel")->execute(["tel" => '79998887766']);

    и всё будет работать
    Ответ написан
    3 комментария