Двоичные данные и кодировка Base64 в 1С 8.Х




Принцип обмена данными из 1С с сайтом (на MySQL) и выдачи (публикации) этих данных по запросу.
PHP-Скрипт автоматической загрузки данных из файла данных в формате CSV в базу данных сайта работающего на WordPress.

В продолжение моей темы: 1С:Альфа-Авто Автосалон Автосервис: обмен с сайтом.
С помощью данного скрипта можно загружать в автоматическом режиме, по расписанию, данные сервисных книжек (ремонтов авто) из 1С:Альфа-Авто Автосалон Автосервис.
Также можно загружать данные в ручном режиме: для этого делается скрытая страница, где размещается специальная кнопка.
Комментарии размещенные внутри скрипта разъяснят логику и порядок действия.
Комментарии с "/////    echo" использовались для отладки.
Дополнительно создана таблица для журналирования результатов загрузки данных.
Скрипт включает в себя защиту от SQL инъекций (думаю безопасность соблюдена в полной мере).
В кратце:
1. Пишется скрипт, который запускает этот.
2. Создается регламентное задание в WordPress, по которому запускается скрипт из п.1. 
3. Этот скрипт осуществляет проверку на существование файла обмена в папке.
4. Если данные не новые, загрузка не производится.
5. Если данные новые, очищается таблица сервисных книжек.
6. Загружаются новые данные.

Собственно сам скрипт:

<?php // Полная загрузка сервисных книжек, создан 2024-01-05 12:44:55

global $wpdb2;
global $failure;
global $file_hist;

/////  echo '<H2><b>Старт загрузки</b></H2><br>';

$failure=FALSE;
//подключаемся к базе
$wpdb2 = include_once 'connection.php'; ; // подключаемся к MySQL
// если не удалось подключиться, и нужно оборвать PHP с сообщением об этой ошибке
if (!empty($wpdb2->error))
{
/////   echo '<H2><b>Ошибка подключения к БД, завершение.</b></H2><br>';
$failure=TRUE;
wp_die( $wpdb2->error );
}

$m_size_file=0;
$m_mtime_file=0;
$m_comment='';
/////проверка существования файлов выгрузки из 1С
////файл выгрузки сервисных книжек
$file_hist = ABSPATH.'/_1c_alfa_exchange/AA_hist.csv';
if (!file_exists($file_hist))
{
/////   echo '<H2><b>Файл обмена с сервисными книжками не существует.</b></H2><br>';
$m_comment='Файл обмена с сервисными книжками не существует';
$failure=TRUE;
}

/////инициируем таблицу лога
/////если не существует файла то возврат и ничего не делаем
if ($failure){
///включает защиту от SQL инъекций и данные можно передавать как есть, например: $_GET['foo']
/////   echo '<H2><b>Попытка вставить запись в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>$m_comment));
wp_die();
/////    echo '<H2><b>Возврат в начало.</b></H2><br>';
return $failure;
}
/////проверка лога загрузки, что бы не загружать тоже самое
$masiv_data_file=stat($file_hist);   ////передаем в массив свойство файла
$m_size_file=$masiv_data_file[7];    ////получаем размер файла
$m_mtime_file=$masiv_data_file[9];   ////получаем дату модификации файла
////создаем запрос на получение последней удачной загрузки
////выбираем по штампу времени создания (редактирования) файла загрузки AA_hist.csv, $m_mtime_file

/////   echo '<H2><b>Размер файла: '.$m_size_file.'</b></H2><br>';
/////   echo '<H2><b>Штамп времени файла: '.$m_mtime_file.'</b></H2><br>';
/////   echo '<H2><b>Формирование запроса на выборку из лога</b></H2><br>';
////препарируем запрос
$text_zaprosa=$wpdb2->prepare("SELECT * FROM `vin_logs` WHERE `last_mtime_upload` = %s", $m_mtime_file);
$results=$wpdb2->get_results($text_zaprosa);

if ($results)
{   foreach ( $results as $r)
{
////если штамп времени и размер файла совпадают, возврат
if (($r->last_mtime_upload==$m_mtime_file) && ($r->last_size_upload==$m_size_file))
{////echo '<H2><b>Возврат в начало, т.к. найдена запись в логе.</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>'Загрузка отменена, новых данных нет, т.к. найдена запись в логе.'));
wp_die();
return $failure;
}
}
}
////если данные новые, пишем в лог запись о начале загрузки
/////echo '<H2><b>Попытка вставить запись о начале загрузки в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>0, 'last_size_upload'=>$m_size_file, 'comment'=>'Начало загрузки'));

////очищаем таблицу
$clear_tbl_zap=$wpdb2->prepare("TRUNCATE TABLE %s", 'vin_history');
$clear_tbl_zap_repl=str_replace("'","`",$clear_tbl_zap);
$results=$wpdb2->query($clear_tbl_zap_repl);
/////   echo '<H2><b>Очистка таблицы сервисных книжек</b></H2><br>';
if (empty($results))
{
/////   echo '<H2><b>Ошибка очистки таблицы книжек, завершение.</b></H2><br>';
//// если очистка не удалась, возврат
$failure=TRUE;
wp_die();
return $failure;
}

////загружаем данные
$table='vin_history';         // Имя таблицы для импорта
//$file_hist Имя CSV файла, откуда берется информация     // (путь от корня web-сервера)
$delim=';';          // Разделитель полей в CSV файле
$enclosed='"';      // Кавычки для содержимого полей
$escaped='\

33 Comments

  1. Гость

    Автор, на ошибки проверяли?

    Reply
  2. andrewks

    для кого/чего эта статья? или чисто учебные цели — демонстрация реализации алгоритма кодирования base64 на языке 1с?

    Reply
  3. lefthander

    А на рубрику обратили внимание? Правильно, практика программирования — вполне уместно.

    Спасибо автору.

    Reply
  4. Гобсек

    (1) Гость,

    Процедура рабочая

    Reply
  5. Гобсек

    (2) andrewks,

    Мне понадобилась такая процедура для перекодировки. К своему удивлению, готовой на языке 1С в Интернете я не нашел. Написал свою. Сегодня на одном из форумов увидел, что один из участников спрашивал про такую процедуру. Я выложил сюда. Кому надо, пусть пользуются.

    Reply
  6. tusv

    Отрывок кода

    Если Индекс Массив64[Индекс] = Ост;

    КонецЕсли;

    Что это?

    Reply
  7. Гость

    извините, вот это мне не понятно.

    Если Индекс Массив64[Индекс] = Ост;

    КонецЕсли;

    Reply
  8. Гобсек

    (6) tusv,

    (7)Гость

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

    Reply
  9. Гобсек
    Reply
  10. Гобсек

    Выкладываю обработку. Там только листинг процедуры.

    Reply
  11. andrewks

    (5)

    Мне понадобилась такая процедура для перекодировки.

    для перекодировки чего? мне непонятна практическая цель.

    если цель — демонстрация реалтизации алгоритма, тогда без вопросов

    Reply
  12. Гобсек

    Статью переделал. Теперь вроде все нормально.

    Reply
  13. Гобсек

    (11)Практическая задача: банк присылает файлы *.DBF Их содержимое нужно загружать в 1С. Для того, чтобы стандартно обработать файл при помощи объекта XBASE, нужно сначала снять электронную подпись. Программное обеспечение для электронных подписей на данном компьютере ставить не планируется. Делаем так. Из заголовка файла узнаем какая у него должна быть длина. Если фактическая длина больше на заданное число байт, то конец файла обрезаем. Для реализации схемы нужно работать с двоичными данными. Все достаточно просто. Вопрос возник только с перекодировкой Base64 туда и обратно.

    Reply
  14. andrewks

    (13) т.е. Вам нужно ДД (двоичные данные) обрезать, и сохранить в файл, я правильно понял? а для чего, собственно, Массив?

    Reply
  15. miap

    Внешнюю обработку, конечно, надо. а то код разбросан уже по коментам, неудобно. Если б я не прочел коменты, не догадался бы.

    Reply
  16. Гобсек

    (14)Чтобы проанализировать заголовок DBF файла.

    Reply
  17. Гобсек

    (15)Я статью уже исправил. Теперь вроде все нормально. Код процедуры можно взять из статьи.

    Reply
  18. andrewks

    (16) ага, ясно.

    т.е. берёте размер из заголовка и просто отсекаете подпись, которая идёт в самом конце файла.

    задача, конечно, извращённая 🙂

    а точно длина подписи не постоянна?

    Reply
  19. Гобсек

    (18)Зато никаких внешних компонент и тому подобное. Не нужно держать в голове, что на данном компьютере должно быть установлено для нормальной работы.

    Длина подписи постоянна. Но нужно проверить, она есть или ее нету.

    Reply
  20. yku

    (11), (13) Приведу еще один пример.

    Дано: базы ЗУП и БП на скуле.

    Справочник физ. лица синхронизирован по ссылке.

    В ЗУПе есть внешний источник данных — справочник физ. лиц из БП.

    Нужно, находясь в ЗУПе получить данные по конкретному физ лицу из БП.

    Но ссылки во внешнем источнике данных имеют тип Binary(16).

    Т.е. нам нужно преобразовать уникальный идентификатор в двоичные данные.

    Алгоритм такой

    УникальныйИдентификатор -> «51012ccc-397d-11de-b595-00055d80a2b9» -> «b59500055d80a2b911de397d51012ccc» -> Числовой массив из шестнадцати байтов -> СтрокаBase64 -> ДвоичныеДанные -> Запрос «Где Внеш_ФизЛица.Ссылка = &ДвоичныеДанные»

    PS:

    -> ???? -> PROFIT!!!

    Reply
  21. sokir

    (20) yku, не понял как из «51012ccc-397d-11de-b595-00055d80a2b9» получено «b59500055d80a2b911de397d51012ccc». Можно поподробнее?

    Reply
  22. AllexSoft

    (20) yku, весе просто, переверните «51012ccc-397d-11de-b595-00055d80a2b9» и удалите «-» и все поймете

    Reply
  23. uri1978
    Строка64 — обычная строка

    Работает только с английским алфавитом и цифрами…

    Reply
  24. Sevg

    Пример моего кода

    новКартБМП=Новый Картинка(QRkod);

    HEXСтрокаКартинка=СтрЗаменить(«»+новКартБМП.ПолучитьДвоичныеДанные(),» «,»»);

    и анализировать вроде быстрее HEXстроку

    Reply
  25. AlexeyDmuhin

    Спасибо за функцию Преобразовать64!

    я с ее помощью получаю хэш-строку в base64 🙂

    Функция ВычислитьНаСервереХешСтрокиПоАлгоритму_HMAC_SHA256(Строка, Ключ, ВернутьBase64 = Истина) Экспорт
    
    Текст = Новый COMОбъект(«System.Text.UTF8Encoding»);
    КриптоSHA256 = Новый COMОбъект(«System.Security.Cryptography.HMACSHA256»);
    КриптоSHA256.key = Текст.GetBytes_4(Ключ);
    Если ВернутьBase64 Тогда
    
    Хэш256 = КриптоSHA256.ComputeHash_2(Текст.GetBytes_4(Строка)).Выгрузить();
    СтрокаХэша = Преобразовать64(, Хэш256);
    
    Иначе
    
    Хэш256 = КриптоSHA256.ComputeHash_2(Текст.GetBytes_4(Строка));
    оStr = Новый COMОбъект(«System.Text.StringBuilder»);
    Для Каждого стр Из Хэш256 Цикл
    оStr.AppendFormat(«{0:x02}», стр);
    КонецЦикла;
    
    СтрокаХэша = оStr.ToString; //последовательность байтов
    
    КонецЕсли;
    
    Возврат СтрокаХэша;
    
    КонецФункции

    Показать

    до этого считал на Jawa-скрипте через MSScriptControl, но траблы и их решение при переводе на 64-bit сервер не устроили

    Reply
  26. mrbus
    ЗакодированноеЗначение = «OgEDmDjPAgyGeEono3y20tK7+to=»;
    РаскодированноеЗначение = Строка(Base64Значение(ЗакодированноеЗначение)); // «3A 01 03 98 38 CF 02 0C 86 78 4A 27 A3 7C B6 D2 D2 BB FA DA»
    Сообщить(«ПРОФИТ!»);
    
    Reply
  27. alex_pshkv

    (25)

    Возникали у вас какие-нибудь проблемы при использовании библиотек кодирования NET на 64-битном сервере? Что-нибудь настраивали?

    Reply
  28. AlexeyDmuhin

    (27) Сейчас уже не помню. Пересели на 8.3.10 — а под нее уже есть реализация вычисления хэша встроенными средствами платформы.

    Reply
  29. alex_pshkv

    (28)

    Жаль, что не помните, но все равно спасибо за ответ.

    Reply
  30. unoDosTres

    (28)

    Шифрования HMAС встроенного все равно нет 🙁

    может поделитесь кодом, если есть откуда взять как реализовывали, ну чтобы без comОБъектов

    Reply
  31. SlavaKron
    Перем Ч64;
    
    Функция МассивВСтроку64(МассивБайтов)
    
    
    Массив = Новый Массив;
    s = «»;
    Остаток = МассивБайтов.Количество() % 3;
    Если Остаток > 0 Тогда
    Для Сч = 1 По 3 — Остаток Цикл
    МассивБайтов.Добавить(0);
    КонецЦикла;
    КонецЕсли;
    Количество = Цел(МассивБайтов.Количество() / 3) — 1;
    Для i = 0 По Количество Цикл
    Число24Бит = МассивБайтов[i * 3] * 65536 + МассивБайтов[i * 3 + 1] * 256 + МассивБайтов[i * 3 + 2];
    s = s + Ч64[Цел(Число24Бит / 4096)] + Ч64[Число24Бит % 4096];
    Если СтрДлина(s) = 64 Тогда
    Массив.Добавить(s);
    s = «»;
    КонецЕсли;
    КонецЦикла;
    Если s <> «» Тогда
    Массив.Добавить(s);
    КонецЕсли;
    Возврат Сред(СтрЗаменить(ЗначениеВСтрокуВнутр(Массив), «»»},» + Символы.ПС + «{«»S»»,»»», «»), 53 + СтрДлина(Формат(Массив.Количество(), «ЧГ=»)));
    КонецФункции
    
    Ч64 = Новый Массив(4096);
    Символы64 = «ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456­789+/»;
    Для Сч = 0 По 4095 Цикл
    Ч64[Сч] = Сред(Символы64, Цел(Сч / 64) + 1, 1) + Сред(Символы64, Сч % 64 + 1, 1)
    КонецЦикла;

    Показать

    Reply
  32. AlexeyDmuhin

    (30)

    Взял по адресу https://infostart.ru/public/611505/

    и доработал под себя, функции в прикрепленном файле

    Reply
  33. user611515_akorneev

    (11) Имя отправителя e-mail в кириллице перекодировать, чтобы почтовые клиенты корректно отображали

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *