Спрятать число в тексте

Ну Ваша методика поимки школьников сработает только на школьниках. Серьезные сайты используют разные орфографические api. Я к примеру speller от Яшки или банально ворд. Бегло пробегая по строкам вникаю в смысл, если устраивает прогоняю через апи или ворд, чтоб более граммотные тексты были, так сказать ручной труд заменяю машинным.
В вашем случае есть немного вариантов.
При копипасте защиты особо нет, ведь копируется только текст, без стилей скриптов и кода.
Первый вариант на яваскрипте запретить вызов файрбага или поверх текста слой со 100%прозрачностью. Это замедлит действие и отпугнёт совсем школьников.
2-й способ это текст картинка. При пост запросе генерировать из текста изображение и вставлять его. Это отпугнет вторую группу школьников, которые на уроках-то мало пишут, а здесь переписывать ваши тексты и подавно не будут. Минус способа, адаптивность текста в картинке под дисплей. Единственное если в онлайн режиме под размер дисплея произволить генерацию изображения с текстом по средствам яваскрипт.
В общем-то и всё.
 
Последнее редактирование:
Да, задача стоит незаметно прятать id, по всему тексту. Само собой, это не универсальная защита, но во-первых, она незаметная если про неё не знать, а во-вторых, если не иметь специального скрипта, то убрать из текста спрятанный id возможно даже затратнее по времени чем распознавать картинки файнридером.

Да, копируется только текст, без каких-то кодов/оформления.

Я думаю в функцию добавить исключения на url (чтобы ссылки и картинки продолжали работать).
 
убрать из текста спрятанный id возможно даже затратнее по времени
почему же затратнее?
просто меняй все нерусские буквы на русские по той же схеме и все.
за исключением ссылок и картинок.
получится даже быстрее, чем прятать id, т.к. замена будет сплошная, не нужно высчитывать количество замен и пропуски
 
Есть пользователь с id "123". Берём текст и массив букв для замены. Заменяем в тексте первую букву из массива один раз (1), потом замену пропускаем, затем делаем две замены (2), одну пропускаем, три замены (3), пропускаем 2 (в примере 3), потом повторяем сначала.
А если рассматривать id в двоичном виде "01111011" используя это как маску для замен.
"0" оставляем русскую букву.
"1" заменяем на английскую.
Для трёхзначных чисел достаточно 10 бит, а 20 бит хватит для шестизначных.
PHP:
<?php

$text = '
В лесу родилась елочка,
В лесу она росла,
Зимой и летом стройная,
зеленая была.
';

define('BITS_PER_ID', 10);


function encode($text, $id)
{
    $mask = sprintf('%0'.BITS_PER_ID.'b', $id);

    $replace = array('а'=>'a', 'о'=>'o', 'е'=>'e', 'с'=>'c', 'р'=>'p', 'х'=>'x', 'у'=>'y');
    $rus = implode(array_keys($replace));
    $eng = implode(array_values($replace));
    $regex = "~[$rus](?:(?=[а-яё])|(?<=[а-яё].)(?<=[^$rus].))~u";

    return preg_replace_callback(
        $regex, function ($m) use ($replace, $mask) {
            static $i = 0;
            strlen($mask) > $i || $i = 0;
            return $mask[$i++] ? $replace[$m[0]] : $m[0];
        }, $text
    );
}



function decode($text)
{
    $replace = array('а'=>'a', 'о'=>'o', 'е'=>'e', 'с'=>'c', 'р'=>'p', 'х'=>'x', 'у'=>'y');
    $rus = implode(array_keys($replace));
    $eng = implode(array_values($replace));
    $regex = "~[$rus](?:(?=[$eng]*[а-яё])|(?<=[а-яё].)(?<=[^$rus].))";
    $regex .= "|[$eng](?:(?=[$eng]*[а-яё])|(?<=[а-яё].))~u";
    preg_match_all($regex, $text, $matches);
    $raw = '';
    foreach ($matches[0] as $m) {
        $raw .= isset($replace[$m]) ? '0' : '1';
    }
    $r['raw_data'] = $raw;
    $r['binary'] = str_split($raw, BITS_PER_ID);
    $r['decimal'] = array_map('bindec', str_split($raw, BITS_PER_ID));
    return $r;
}

$id = 123;

echo "<hr>\n", $enc = encode($text, $id), "\n<hr>\n";
echo "<pre>", print_r(decode($enc), 1), "</pre>";
 
почему же затратнее?
просто меняй все нерусские буквы на русские по той же схеме и все.
за исключением ссылок и картинок.
получится даже быстрее, чем прятать id, т.к. замена будет сплошная, не нужно высчитывать количество замен и пропуски
Я в том смысле, что если кто-то хочет скопировать себе и выложить мой текст, то он потратит гораздо меньше усилий и времени в варианте с картинкой - всего несколько кнопок в finereader нажать, или даже парой кликов, если плагин какой-нибудь есть. В случае с заменой букв, это в самом простом способе 8 раз сделать глобальную замену английских на русские по документу в текстовом редакторе (причём ссылки испортятся), с учётом того, что он не знает алгоритма.

lag, хорошая идея, спасибо за код! Прям то что нужно! У меня пока 4, в самой далёкой перспективе 5-значные id, думаю в большинстве случаем такая запись будет компактнее, хоть и надо резервировать место. Кстати, тогда отпадает необходимость в разделителе.

Можно чуть чуть доработать код? Чтобы было удобнее и универсальнее:

1) вместо битов просто переменная - число знаков в id (для резервирования места для двоичного вывода, число битов автоматически зависит от этой переменной)

2) массив букв для замены в принципе можно так оставить (это если мы вдруг используем особый шрифт, в котором сильна видна разница, по-умолчанию остаётся $replace = array('а'=>'a', 'о'=>'o', 'е'=>'e', 'с'=>'c', 'р'=>'p', 'х'=>'x', 'у'=>'y');

3) не меняем буквы в url (адреса и картинки), т.е. изначально в общем случае у нас будет bb код (в котором нужно сохранить ссылки и картинки в исходном виде), а в функции декодирования простой текст (в котором мы игнорируем только ссылки). Это коды url img, а лучше всё что начинается с http и т.п.

4) В идеале также сделать массив стоп слов (через запятую, например), чтобы каждый настроил для себя сам, у всех разные бб коды могут быть и т.п. Например, у меня есть bb код [clan][/clan]

P.S. Хотя разделитель тоже под вопросом - с учётом двоичной системы он уже не будет работать. Может возникнуть ситуация (да и скорее всего так и будет), что скопируют не весь текст, а его часть, как в этом случае определить начало и конец id? перебором искать повторяющиеся комбинации заданной длины не получится - вместо 123 будет 231 (в двоичном коде другое). Пока приходит на ум только начинать шифрование с каждого абзаца заново.
 
Последнее редактирование:
А если рассматривать id в двоичном виде "01111011" используя это как маску для замен.
"0" оставляем русскую букву.
"1" заменяем на английскую.
все выглядит хорошо, до тех пор, пока справа не возникнет НОЛЬ или несколько нолей. "01111000"
как тогда определить какой же длины число зашифровано в тексте?
 
все выглядит хорошо, до тех пор, пока справа не возникнет НОЛЬ или несколько нолей. "01111000"
как тогда определить какой же длины число зашифровано в тексте?
Так вот же на мой взгляд простое решение - начинать шифровать каждый абзац снова (если текст копируют не сначала), и закладывать определённое число символов (байт, в зависимости от числа символов в id), тогда разделитель не нужен. Нулевого id или id начинающегося с нуля не должно быть - это integer, да и вряд ли есть способ которым можно было бы такие числа прятать.
 
Предлагаю резервировать 16 бит для id тогда диапазон получится 0-65535 и добавлять какой-нибудь разделитель, например "1010101010101011".
Кодер и декодер, которые я приводил выше вполне нормально работают с текстом, где есть целые английские слова или отдельно стоящие буквы.
Кодировщик делает замену так, что всегда оставляет в слове какую-нибудь русскую букву.
Т.е. в слове "хор" заменит только первые две буквы, в "ох" только первую букву, в "на" заменит последнюю. Одиночные буквы пропускаются.
Декодер действует аналогичным образом и обращает внимание только на английские буквы, которые стоят рядом с русскими.
Так что в тексте спокойно могут стоять различные Для просмотра ссылки Войди или Зарегистрируйся главное чтобы без кирилицы.
Перед кодированием bb коды и прочее можно заменять на специальные метки, а после кодирования заменять обратно.
 
Предлагаю резервировать 16 бит для id тогда диапазон получится 0-65535
подойдёт, но почему не сделать указание кол-ва битов отдельно? будет универсальней.

и добавлять какой-нибудь разделитель, например "1010101010101011".
а зачем вообще нужен разделитель, если у нас будет подряд идти фиксированное кол-во знаков всё время? Чтобы определять код, если скопирован только кусок абзаца? В принципе согласен, правда кол-во спрятанных id будет в 2 раза меньше. И, мне кажется, лучше 16 нулей подряд? Чтобы в тексте было больше русских символов. Или нет?

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

PHP:
<?php

$text = '
В лесу родилась елочка,
В лесу она росла,
Зимой и летом стройная,
зеленая была.
';   //исходный текст

define('BITS_PER_ID', 10); //длина последовательности (id) - 10 символов


function encode($text, $id)   //функция кодирования
{
    $mask = sprintf('%0'.BITS_PER_ID.'b', $id); // ? маска проверяет первый символ кириллицы?

    $replace = array('а'=>'a', 'о'=>'o', 'е'=>'e', 'с'=>'c', 'р'=>'p', 'х'=>'x', 'у'=>'y'); //массив для замены
    $rus = implode(array_keys($replace)); //меняем русские буквы на английские
    $eng = implode(array_values($replace)); //меняем английские буквы на русские
    $regex = "~[$rus](?:(?=[а-яё])|(?<=[а-яё].)(?<=[^$rus].))~u"; // ? регулярка, которая распознаёт, содержит ли слово русские буквы?

    return preg_replace_callback(   // ? что-то возвращаем
        $regex, function ($m) use ($replace, $mask) {  //параметры - регулярка, функция замены по маске
            static $i = 0;   // создаём статическую (не удалится после выполнения функции, не совсем понятно зачем) переменную
            strlen($mask) > $i || $i = 0;  // ? если длина маски больше переменной, то обнуляем
            return $mask[$i++] ? $replace[$m[0]] : $m[0]; // ? как я понимаю, в этой строчке вся магия замены
        }, $text  //всё это работает с текстом
    );
}



function decode($text)  //функция декодирования
{
    $replace = array('а'=>'a', 'о'=>'o', 'е'=>'e', 'с'=>'c', 'р'=>'p', 'х'=>'x', 'у'=>'y'); //массив замены английских букв на русские
    $rus = implode(array_keys($replace)); //аналогично
    $eng = implode(array_values($replace)); //аналогично
    $regex = "~[$rus](?:(?=[$eng]*[а-яё])|(?<=[а-яё].)(?<=[^$rus].))"; // ? регулярка, определяет есть ли английская буква в русском слове?
    $regex .= "|[$eng](?:(?=[$eng]*[а-яё])|(?<=[а-яё].))~u"; // ? приклеиваем к регулярке, есть ли русская буква в английском слове?
    preg_match_all($regex, $text, $matches); // ? запустили регулярки
    $raw = ''; // ? какая-то переменная
    foreach ($matches[0] as $m) { //на каждое срабатывание проверки регуляркой запускаем в цикле
        $raw .= isset($replace[$m]) ? '0' : '1'; // ? заменяем 0 на 1
    }
    $r['raw_data'] = $raw; // ? результат добавили в массив r
    $r['binary'] = str_split($raw, BITS_PER_ID); // ? преобразуем строку в массив,
    $r['decimal'] = array_map('bindec', str_split($raw, BITS_PER_ID)); // ? переводим в другую систему счисления?
    return $r; // возвращаем r
}

$id = 123; //наш id

echo "<hr>\n", $enc = encode($text, $id), "\n<hr>\n"; //пример закодированного текста
echo "<pre>", print_r(decode($enc), 1), "</pre>"; //пример раскодированного текста

Спасибо!
 
и ещё вопрос, как модифицировать код, чтобы не обрабатывал, например, конкретный текст "[noencode]текст текст текст[/noencode]".
 
Назад
Сверху