Андрей Вакурин

Передача файлов по средствам ASN.1

Поскольку мы знаем, что любой файл состоит из массива байт, то для передачи по средствам ASN.1 нам надо знать: блок, длину блока, имя файла и можно создавать свой peer-to-peer. Мы можем ставить в очередь и передавать неограниченное число блоков данных, которые можно собирать в конкретные файлы. Хоть миллион файлов будет передаваться параллельно по блокам, как это делается в torrent клиентах.

Приводим пример, задаем произвольный файл, первый блок, длину блока данных.

Нам не важен язык написания, хоть Java, хоть C#. Абстрактный пример будет на Java.

Задаем глобальную переменную – размер блока передачи

static int blocksize = 0x3E80;

Задаем первый блок для передачи

int block = 0x01;

Задаем дескриптор файла

String filePath = «C:/Downloads/11.jpg»;

System.out.print(String.format(«block = %d \r\n», block));

System.out.print(String.format(«blocksize = %d bytes \r\n», blocksize));

Переходим к реализации функции получения блока данных

byte[] hex = GetBlock(filePath,block);

private static byte[] GetBlock(String filePath, int block) throws IOException {

//Используем произвольный доступ к файлу в режиме read

RandomAccessFile file = new RandomAccessFile(filePath, «r»);

//Получаем смещение согласно номеру блока

file.seek(GetSeek(block));

byte[] bytes = new byte[blocksize];

//Согласно смещению считываем 16 кб данных

file.read(bytes);

file.close();

return bytes;

}

//Вспомогательная функция смещения

private static long GetSeek(int block)

{

if (block == 1) {return 0;}

else {return ((block-1)*blocksize); }

}

//Самое важное еще предусмотреть, что длина файла может быть меньше 16 кб или последний блок может быть меньше 16 кб

System.out.print(String.format(«hex = %s \r\n»,GetHex(hex)));

Для контроля выводим в Hex режиме

GetHex(hex);

//Создаем stringbuilder и собираем строчку

private static String GetHex(byte[] bytes)

{

StringBuilder sb = new StringBuilder();

for (byte b : bytes) {

sb.append(String.format(«%02x», b));

}

return sb.toString();

}

Собираем произвольную TLV структуру

CreateTLV(block,filePath, hex);

private static void CreateTLV(int block, String fd, byte[] hex) {

StringBuilder TLV = new StringBuilder();

//Fd name

TLV.append(0x03);

//Fd name

TLV.append(0x03);

java.io.File file = new java.io.File(fd);

long f = file.length();

TLV.append(GetLen(f));

TLV.append(f);

//Integer block

TLV.append(0x02);

String str = Integer.toString(block);

TLV.append(GetLen(str.length()));

TLV.append(block);

//Block info

TLV.append(«03»);

TLV.append(GetLen(hex.length));

TLV.append(GetHex(hex));

//System.out.print(String.format(«TLV structure = %s \n», TLV.toString()));

System.out.print(«Bytes [] = » + TLV.toString());

}

Напишем дополнительную функцию по переводу dec в hex по определению TLV структуры

private static String GetLen(int length) {

StringBuilder str = new StringBuilder();

if (length< 0x80) str.append(Integer.toHexString(length));

if ((length> 0x80) && (length< 0x100))

{

str.append(81);

str.append(Integer.toHexString(length));

return str.toString();

}

if (length> 0x100)

{

str.append(82);

str.append(Integer.toHexString(length));

}

System.out.print(String.format(«GetLen= %s \n», str.toString()));

return str.toString();

}

Получаем результат

block = 1

blocksize = 16000 bytes

hex = ffd8ffe00010 ……..16 кб данных

Размер файла

GetLen= 8220964

Блок

GetLen= 1

Размер блока = 3e80 = 16 кб

GetLen= 823e80

3

82 2096

4433a2f446f776e6c6f6164732f31312e6a706721103823e80ffd8ffe000104a46494600010101004800480000ffe20240

2 1

1

3 82 3E80

16 кб первого блока

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

Криптография. Создание сигнатуры

Одной из массовых систем для шифрования, для цифровой подписи является система RSA. Как уже было рассмотрено, в данной системе есть этап генерации ключей, передачи, шифрование и расшифровка. Если мы говорим про передачу отдельных параметров по средствам сети, то важно эти данные защищать, накладывать подписи, в противном случае есть риск компрометации данных/компрометации параметров ключей.
На практике часто используется SHA256RSA, SHA1RSA, ГОСТ серии 34.10 (где-то в государственных предприятиях)
SHA256 with RSA — это эффективный асимметричный метод шифрования. Этот алгоритм сначала вычисляет уникальный хэш исходных данных с помощью алгоритма SHA256. Хэш затем шифруется с помощью частного ключа с использованием алгоритма RSA
SHA1 with RSA — это эффективный асимметричный метод шифрования. Этот алгоритм сначала вычисляет уникальный хэш исходных данных с помощью алгоритма SHA1. Хэш затем шифруется с помощью частного ключа с использованием алгоритма RSA
Погружаем дальше
Алгоритм SHA-1 (англ. Secure Hash Algorithm 1-bit) – это безопасный алгоритм хеширования, применяющийся для шифрования, размер выходных данных при этом составляет 160 бит. С помощью алгоритмов хеширования создаются уникальные хеши с необратимым кодированием.
Алгоритм SHA-256 (англ. Secure Hash Algorithm 256-bit) – это безопасный алгоритм хеширования, применяющийся для шифрования, размер выходных данных при этом составляет 256 бит. С помощью алгоритмов хеширования создаются уникальные хеши с необратимым кодированием.
На языке C# используем пространство System.Security.Cryptography класс RSACryptoServiceProvider.
Для упрощения работы используем библиотечные функции импортирования ключей и вычисления сигнатуры, проверки сигнатуры.
Для подписания данных:
Первое, задаем входные данные, для которых определяем хеш значение, второе, определяем halg = Хэш-алгоритм, который следует использовать для создания хэш-значения, опционально смещение и количество байт.
Для подписания хэш алгоритма:
Первое, хеш значение подписываемых данных, второе, идентификатор хэш-алгоритма (OID), используемый для создания хэш-значения данных.
В результате получаем подпись System.Security.Cryptography.RSA для указанных данных. Размер подписи будет равен 256 байт.
Производим обратную процедуру – верификация подписи.
1. Получаем хэш значение входных данных (или хэш значение файла)
2. Указываем идентификатор хэш-алгоритма (OID), используемый для создания хэш-значения данных.
3. Данные подписи, которые требуется поверить.
На выходе получаем положительный или отрицательный результат

Рассмотрим сертификаты электронной подписи через призму стандарта ASN.1

Любой сертификат цифровой подписи или любой документ представляет собой данные в виде байт, массива байт. Нам необходимо знать хэш алгоритм, необходимо знать издателя сертификата, публичный /закрытый ключ, цепочку сертификатов, срок действия и тд. Сертификаты определяются по стандарту X.509, в системе хранятся в виде массива байт по стандарту ASN.1, что соответствует TLV структуре.
У каждого сертификата есть один из важных параметров : OID, Object identifier. Например, OID хеш алгоритма Sha256 в человеческом виде будет (1.2.840.113549.2.9), в Hex формате 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x09.
Возьмем публичный ключ, декодируем его из base 64 в byte массив, размер массива будет равен 162 байта. Пример:
30 81 9F 30 0D 06 09 2A 86 48 86 F7 0D 01 01 01 05 00 03 81 8D 00 30 81 89 02 81 81 00 C2 AC 3D E3 D3 43 2C 88 4D 0C 7C 4C 3D AC 14 95 20 A6 45 11 B6 D3 BC 90….
Как мы уже знаем, 30 — секвенция, значит это не примитивный тип, после размера будет хранится ссылка на следующий блок информации. 81 размер, но ссылка, что следующий блок больше 0x80, но меньше 0х100. в 10 виде это 159 меньше чем 256. Проваливаемся дальше. Нам важно найти 0х06 идентификатор с OID. Кажется мы его нашли 06 09 2A 86 48 86 F7 0D 01 01 01. Это алгоритм 1 2 840 113549 1 1 11 т е sha256WithRSAEncryption. Дальше ищем RSA параметры с тегом 0х02 или 0x03 (бит стринг или целочисленное значение). d — частная экспонтента, dp, dq, exponent, modulus, inverseq, p, q. Экспортируем это все в структуру параметров. В публичном ключе нам важны два параметра modulus и exponent. В закрытом ключе нужны все параметры (поскольку это контейнер с ссылкой на все выпущенные публичные сертификаты). А дальше работаем на уровне Cryptoapi или на уровне CLI С#, JRM.

TLV и протокол ASN.1

TLV — схема кодирования для использования информационных элементов, сокращённо Tag-length-value.
ASN.1 — абстрактная синтаксическая нотация, в том числе международный телекоммуникационный стандарт.

1) Tag Первые два бита кодируют класс текущего блока, это может быть sequence, например, и другие типы, следующий бит равен 0x00, если у нас простые данные, но 0x01, если внутри значения блока содержится дополнительные блоки ASN.1. Остальные биты содержат тип данных, например integer, bit_string, bool, Null и другие.
Если идентификатор типа содержит значение выше 31, то в последних битах будут все 0х01 (по определению их 5 битов).
2. Length. Если длина информационного сообщения меньше 0x80, то размер кодируется одним байтом, если сообщение x>0x80 и >0x100, то к размеру добавляется идентификатор 81. Если сообщение больше 0x100, то длина будет 82. Если длина блока равна 201, то значение в 16 ричное системе будет
81C9, что соответствует 1000 0001, 1100 1001. Важно что общая длина сообщения не может выйти за объем =65535 в 10 степени. Вообще рекомендуется передавать небольшие блоки данных, блок данных 16 /32 Кб отправится быстрее, чем блок 64 КБ. Важно помнить, что на уровне сети и сетевого соединения находится много сетевых устройств, возможно задержка. Tcp протокол запрашивает подтверждение. да и блок 32 КБ делится предположим по 4 Кб, получается 8 блоков
3)Value. Тут тоже все не так просто. Текст переводится в массив byte. Числа в зависимости от набора процессорных инструкций декодируются как big endian и little endian. Т е имеет значение порядок байтов в памяти компьютера. 4-байтное целое число 0x01020304 будет сохранено в памяти системы big endian следующим образом: 0x01 0x02 0x03 0x04, в системе little endian обратный порядок 0x04 0x03 0x02 0x01. Важна не запись, а учёт формата хранения данных в памяти для обмена с другими системами.

Сайт для Таро услуг

За январские праздники начал разработку/прототипирование сайта для консультаций и обучения по Таро картам .

Карты Таро – уникальный эзотерический инструмент, с помощью которого таролог погружается в информационный поток и формулирует предсказание на основе посыла карт.

Колода Райдера Уэйта состоит из 78 карт: 22 аркана – старшие и 56 – младшие. Каждая карта обладает своим уникальным названием. В том или ином сочетании посыл каждой может быть усилен или нивелирован. В отличие от высших арканов, младшие делятся на 4 масти, на каждой из которых есть либо числовое обозначение, либо портретное. В зависимости от того, какое количество карт той или иной масти или старшинства выпало в раскладе, предсказание может меняться.

Функционал сайта для консультаций и обучения по Таро картам следующий:

  • можно добавлять свои курсы
  • регистрироваться и в перспективе оплачивать услуги
  • раскладывать онлайн расклады
  • записываться на курсы
  • читать материалы по Арканам (Старшим и младшим)
  • редактировать информацию по Арканам
  • у каждого зарегистрированного пользователя доступен личный кабинет с доступом к определенному курсу и тд
  • редактировать мета теги страниц/ настройки сайта/пользователей и тд

Язык разработки Python, Mysql — база данных

Сайт/платформу можно купить, базовая стоимость 30.000 рублей

andrey@businessarchitecture.ru, телефон 89309468161

    

Получение курсов криптовалют

Используем сайт https://coinmarketcap.com/all/views/all/

Код на python

import requests
from bs4 import BeautifulSoup

def main():
link = «https://coinmarketcap.com/all/views/all/»
links = get_urls(get_html(link))
for lin in links:
data = get_price(lin)
print (data[‘name’], data[‘cast’])

def get_price(lin):
data = requests.get(lin)
soup = BeautifulSoup(data.text,’lxml’)
name = soup.find(‘h2’).text.strip()
cast = soup.find(‘div’, class_=»priceValue»).text.strip()

data = {«name»: name, «cast»: cast}
return data

def get_html(url):
r = requests.get(url)
return r.text

def get_urls(html):
links = []
soup = BeautifulSoup(html,’lxml’)
tds = soup.find(‘tbody’).find_all(‘div’,class_=’cmc-table__column-name—narrow-layout’)
for td in tds:
a = td.find(‘a’).get(‘href’)
links.append(‘https://coinmarketcap.com’+a)
return links

if __name__==’__main__’:
main()

Результат

Автоматизированная система для создания акта выполненных работ

акт выполненных работ

Создание новой заявки-нового объекта и создание для данного объекта акта выполненных строительных работ, печать акта выполненных строительных работ и предоставление его клиенту. Список работ грузится на сайт в Excel формате, дополнительные работы инженер может указать или переименовать уже существующие работы, новая заявка сохраняется в базу данных и инженер/клиент может иметь к ней постоянный доступ.

Проект готов на 90 процентов

Есть возможность предоставить (продать) полностью исходный код или выделить ежемесячный доступ на компанию/работника

Бек: Python, Flask, Mysql база данных, SQLAchemy
Фронт: Html, Javascript

Наши контакты
Моб: 89309468161 (Андрей)
https://businessarchitecture.ru/

Форма авторизации

Создание новой заявки — новый клиент

Список пользователей

Мониторинг активности пользователей портала

Список заявок с актами

Формирование нового акта

Дашборд

Скрипт архивирования на bat

Batch является языком программирования, используется для создания файлов сценарий которые можно выполнять на операционной системе Windows, обычно эти файлы имею окончание *.bat или *.cmd. При выполнении они открывают окно «Command Prompt», обычно это окно имеет черный фон, белый шрифт.
Файлы batch (*.bat, *.cmd) называются файлами сценарий (script file), они могут содержать команды вмешивающиеся в операционную систему.

@echo off
SetLocal EnableDelayedExpansion
set now=%DATE: =0% %TIME: =0%

set d=%date:~0,2%
set m=%date:~3,2%
set y=%date:~6,4%

rem ~0,2% для времени меньше 10 часов вместо ведущего нуля выводит пробел

if %d:~0,1%==0 set d=%d:~1%
if %m:~0,1%==0 set m=%m:~1%

set /a feb=y%%4
if %feb%==0 (set feb=29) else (set feb=28)

rem самописная функция для нахождения предыдущего дня
set /a tok=m-1
if %tok%==0 set tok=12
for /f «tokens=%tok%» %%i in («31 %feb% 31 30 31 30 31 31 30 31 30 31») do (
set /a d-=1
if !d!==0 (
set d=%%i
set m=%tok%
if !m!==12 set /a y-=1
)
)

set d=0%d%
set m=0%m%
set yesterday=%y%_%m:~-2%_%d:~-2%
set yesterdaylog=%d:~-2%_%m:~-2%_%y%

echo «delete and arhiving for yesterday = » %yesterday%
echo «delete and arhiving path log for yesterday = » %yesterdaylog%

rem считаем и удаляем каталог с бакапом созданный неделю назад
set T_Date=%date%
IF %T_DATE:~0,1%==0 (
set /A T_DAY=%T_DATE:~1,1%) else (
set /A T_DAY=%T_DATE:~0,2%)

IF %T_DATE:~3,1%==0 (
set /A T_MONTH=%T_DATE:~4,1%) else (
set /A T_MONTH=%T_DATE:~3,2%)
set /A T_YEAR=%T_DATE:~6,4%

rem за сколько дней удалять бакап (до 28 дней, т.к. скрипт, при «отрицательном» дне всегда делает — 1 месяц)
rem ************************
set back_day=28
rem ************************
set /A T_DAY=%T_DAY%-%back_day%

IF %T_DAY% LEQ 0 SET /A T_MONTH=%T_MONTH%-1
IF %T_MONTH%== 0 SET /A T_YEAR=%T_YEAR%-1
IF %T_MONTH%== 0 SET /A T_MONTH=12
IF %T_MONTH%==1 Set /A DIM=31
IF %T_MONTH%==2 Set /A DIM=28
IF %T_MONTH%==3 Set /A DIM=31
IF %T_MONTH%==4 Set /A DIM=30
IF %T_MONTH%==5 Set /A DIM=31
IF %T_MONTH%==6 Set /A DIM=30
IF %T_MONTH%==7 Set /A DIM=31
IF %T_MONTH%==8 Set /A DIM=31
IF %T_MONTH%==9 Set /A DIM=30
IF %T_MONTH%==10 Set /A DIM=31
IF %T_MONTH%==11 Set /A DIM=30
IF %T_MONTH%==12 Set /A DIM=31
IF %T_DAY% LEQ 0 SET /A T_DAY=%T_DAY%+%DIM%
IF %T_DAY% LSS 10 SET T_DAY=0%T_DAY%
IF %T_MONTH% LSS 10 SET T_MONTH=0%T_MONTH%

set DateArchive=%T_YEAR%_%T_MONTH%_%T_DAY%

rem Устанавливаем пути рабочей директории и директории для хранения архивов ConnectUPSH
set WorkDirConnectUPSH=»C:\SBBOL_20180216\ConnectUPSH»
set LogDirConnectUPSH=»C:\SBBOL_20180216\ARCHIVE\log_ConnectUPSH»

rem Устанавливаем пути рабочей директории и директории для хранения архивов DataToReturn
set WorkDirDataToReturn=»C:\SBBOL_20180216\dataToReturn»
set LogDirDataToReturn=»C:\SBBOL_20180216\ARCHIVE\log_DataToReturn»

rem Устанавливаем пути рабочей директории и директории для хранения архивов Exceptions
set WorkDirExceptions=»C:\SBBOL_20180216\Exceptions»
set LogDirExceptions=»C:\SBBOL_20180216\ARCHIVE\log_Exceptions»

rem Устанавливаем пути рабочей директории и директории для хранения архивов IncomingData
set WorkDirIncomingData=»C:\SBBOL_20180216\incomingData»
set LogDirIncomingData=»C\ARCHIVE\log_IncomingData»

rem Устанавливаем пути рабочей директории и директории для хранения архивов SendedToSbbol
set WorkDirSendedToSbbol=»C:\SBBOL_20180216\SendedToSbbol»
set LogDirSendedToSbbol=»C:\SBBOL_20180216\ARCHIVE\log_SendedToSbbol»

rem Устанавливаем пути рабочей директории и директории для хранения архивов log
set WorkDirlog=»C:\SBBOL_20180216\log»
set LogDirlog=»C:\SBBOL_20180216\ARCHIVE\Log»

if exist «%WorkDirConnectUPSH%\connectUPSH_%yesterday%.txt» «C:\Program Files\7-Zip\7z.exe» a -ssw -mx9 -r0 %LogDirConnectUPSH%\connectUPSH_%yesterday% %WorkDirConnectUPSH%\connectUPSH_%yesterday%.txt
if exist «%WorkDirConnectUPSH%\connectUPSH_%yesterday%.txt» del %WorkDirConnectUPSH%\connectUPSH_%yesterday%.txt

if exist «%WorkDirDataToReturn%\dataToReturn_%yesterday%.txt» «C:\Program Files\7-Zip\7z.exe» a -ssw -mx9 -r0 %LogDirDataToReturn%\dataToReturn_%yesterday% %WorkDirDataToReturn%\dataToReturn_%yesterday%.txt)
if exist «%WorkDirDataToReturn%\dataToReturn_%yesterday%.txt» del %WorkDirDataToReturn%\dataToReturn_%yesterday%.txt

if exist «%WorkDirExceptions%\error_%yesterday%.txt» «C:\Program Files\7-Zip\7z.exe» a -ssw -mx9 -r0 %LogDirExceptions%\error_%yesterday% %WorkDirExceptions%\error_%yesterday%.txt
if exist «%WorkDirExceptions%\error_%yesterday%.txt» %WorkDirExceptions%\error_%yesterday%.txt

if exist «%WorkDirIncomingData%\incommingData_%yesterday%.txt» «C:\Program Files\7-Zip\7z.exe» a -ssw -mx9 -r0 %LogDirIncomingData%\incommingData_%yesterday% %WorkDirIncomingData%\incommingData_%yesterday%.txt
if exist «%WorkDirIncomingData%\incommingData_%yesterday%.txt» del %WorkDirIncomingData%\incommingData_%yesterday%.txt

if exist «%WorkDirSendedToSbbol%\SendedToSbbol_%yesterday%.txt» «C:\Program Files\7-Zip\7z.exe» a -ssw -mx9 -r0 %LogDirSendedToSbbol%\SendedToSbbol_%yesterday% %WorkDirSendedToSbbol%\SendedToSbbol_%yesterday%.txt
if exist «%WorkDirSendedToSbbol%\SendedToSbbol_%yesterday%.txt» %WorkDirSendedToSbbol%\SendedToSbbol_%yesterday%.txt

echo %yesterdaylog%
if exist «%WorkDirlog%\%yesterdaylog%.txt» «C:\Program Files\7-Zip\7z.exe» a -ssw -mx9 -r0 %LogDirlog%\Log_%yesterdaylog% %WorkDirlog%\%yesterdaylog%.txt
if exist «%WorkDirlog%\%yesterdaylog%.txt» del %WorkDirlog%\%yesterdaylog%.txt

rem удаление файлов за back_day
if exist «%LogDirConnectUPSH%\connectUPSH_%DateArchive%.7z» del %LogDirConnectUPSH%\connectUPSH_%DateArchive%.7z
if exist «%LogDirDataToReturn%\dataToReturn_%DateArchive%.7z» del %LogDirDataToReturn%\dataToReturn_%DateArchive%.7z
if exist «%LogDirExceptions%\error_%DateArchive%.7z» del %LogDirExceptions%\error_%DateArchive%.7z
if exist «%LogDirIncomingData%\incommingData_%DateArchive%.7z» del %LogDirIncomingData%\incommingData_%DateArchive%.7z
if exist «%LogDirSendedToSbbol%\SendedToSbbol_%DateArchive%.7z» del %LogDirSendedToSbbol%\SendedToSbbol_%DateArchive%.7z
if exist «%LogDirlog%\%DateArchive%.7z» del %LogDirlog%\%DateArchive%.7z

удаление файлов c начала года
set /a ArchiveMonth=%T_MONTH% + 1
echo «Delete old file»
for /L %%B in (1,1,%ArchiveMonth%) do (
for /L %%C in (1,1,31) do (
IF %%B LSS %T_MONTH% if exist «%LogDirConnectUPSH%\connectUPSH_%T_YEAR%_%%B_%%C.7z» start ( del %LogDirConnectUPSH%\connectUPSH_%T_YEAR%_%%B_%%C.7z)
IF %%B LSS %T_MONTH% if exist «%LogDirDataToReturn%\dataToReturn_%T_YEAR%_%%B_%%C.7z» start (del %LogDirDataToReturn%\dataToReturn_%T_YEAR%_%%B_%%C.7z)
IF %%B LSS %T_MONTH% if exist «%LogDirExceptions%\error_%T_YEAR%_%%B_%%C.7z» start (del %LogDirExceptions%\error_%T_YEAR%_%%B_%%C.7z)
IF %%B LSS %T_MONTH% if exist «%LogDirIncomingData%\incommingData_%T_YEAR%_%%B_%%C.7z» start (del %LogDirIncomingData%\incommingData_%T_YEAR%_%%B_%%C.7z)
IF %%B LSS %T_MONTH% if exist «%LogDirSendedToSbbol%\SendedToSbbol_%T_YEAR%_%%B_%%C.7z» start (del %LogDirSendedToSbbol%\SendedToSbbol_%T_YEAR%_%%B_%%C.7z)
IF %%B EQU %T_MONTH% IF %%C LEQ %T_DAY% if exist «%LogDirConnectUPSH%\connectUPSH_%T_YEAR%_%%B_%%C.7z» start (del %LogDirConnectUPSH%\connectUPSH_%T_YEAR%_%%B_%%C.7z)
IF %%B EQU %T_MONTH% IF %%C LEQ %T_DAY% if exist «%LogDirDataToReturn%\dataToReturn_%DateArchive%.7z» start (del %LogDirDataToReturn%\dataToReturn_%T_YEAR%_%%B_%%C.7z)
IF %%B EQU %T_MONTH% IF %%C LEQ %T_DAY% if exist «%LogDirDataToReturn%\dataToReturn_%T_YEAR%_%%B_%%C.7z» start del (%LogDirExceptions%\error_%T_YEAR%_%%B_%%C.7z)
IF %%B EQU %T_MONTH% IF %%C LEQ %T_DAY% if exist «%LogDirIncomingData%\incommingData_%T_YEAR%_%%B_%%C.7z» start (del %LogDirIncomingData%\incommingData_%T_YEAR%_%%B_%%C.7z)
IF %%B EQU %T_MONTH% IF %%C LEQ %T_DAY% if exist «%LogDirSendedToSbbol%\SendedToSbbol_%T_YEAR%_%%B_%%C.7z» start (del %LogDirSendedToSbbol%\SendedToSbbol_%T_YEAR%_%%B_%%C.7z)
)
)

Альфа-Банк расширяет команду IT-специалистов

💪🏻 Альфа-Банк расширяет команду IT-специалистов и приглашает системных аналитиков на One Day Offer. Это online-мероприятие, которое избавляет вас от стандартного двухнедельного процесса трудоустройства.

🔥 Получите оффер всего за один день и присоединяйтесь к банку, который нарушает правила:
— «Правило посещения офиса» — работайте удалённо, хоть с Марса
— «Правило с девяти до шести» — меняйте график под себя, а не себя под график
— «Правило сложной релокации» — меняйте город быстро и просто
— «Правило дресс-кода» — надевайте пижаму с жирафами, если захочется

🙃 Если вы готовы нарушать с Альфа-Банком, то подавайте заявку на нашем сайте до 2 декабря!

 

https://onedayofferalfa.ru/?utm_source=telegram-channel&utm_medium=1tworks&utm_campaign=sa