Некоторые Интернет службы поддерживают только 7 - битовую ASCII - кодировку (SMTP, NNTP, POP3 и др.). Кодировка Base 64 используется при передачи вложений к электронному сообщению и в заголовках самого сообщения. При создании почтового клиента эта кодировка обязательно потребуется, а как её осуществить рассказано в этой статье.
Алгоритм кодирования Base 64
Процедура предназначена для преобразования данных перед передачей их через службы, поддерживающие только 7 - битовую ASCII - кодировку (SMTP, NNTP, POP3 и др.). Сущность преобразования сводится к замене серий двоичных знаков на серии ASCII - символов. Каждая последовательность из трех байт (24 бит) сообщения преобразуется в четыре шестибитовых значения. Затем каждому шестибитовому значению ставится в соответствие символ ASCII согласно числу, представленному шестью битами. Количество символов ASCII ограничено 64. Пример соответствия кодов Base64 и ASCII приведен ниже. Если количество символов (байтов) не кратно трем, то используется дополнительный символ "=".
Для создания алгоритма кодирования нам потребуются функции перевода чисел из десятичной системы счисления в двоичную и обратно. Но так как встроенных функций у Visual Basic нет, то я создал свои функции и назвал из GetDec и GetBin, в которые немного изменил для правильного возвращения значенй:
Function GetDec(Bin As String) As Long If InStr(1, Bin, "=") Then GetDec = 64: Exit Function If InStr(1, Bin, " ") Then GetDec = 256: Exit Function Dim Cnt As Integer Cnt = Len(Bin) - 1 For t = 1 To Len(Bin) If Mid(Bin, t, 1) = 1 Then GetDec = GetDec + (2 ^ Cnt) End If Cnt = Cnt - 1 Next End Function
Функция GetDec переводит число из двоичной системы в десятичную. Параметр Bin принимает двоичное число и определён как строковая переменная для того, чтобы ему можно было передать строку с дополнительными символами.
Function GetBin(Dec As Single, cFormat As Integer) As String Dim sFormat As String sFormat = String(cFormat, "0") If Dec = 64 Then GetBin = "00000 ": Exit Function If Dec = 0 Then GetBin = sFormat: Exit Function Do While Dec >= 1 Dec = Int(Dec) / 2 If Dec = Int(Dec) Then GetBin = 0 & GetBin Else GetBin = 1 & GetBin End If Loop GetBin = Format$(GetBin, sFormat) End Function
Функция GetBin переводит число из десятичной в двоичную систему и возвращает результат как строку, чтобы можно было представить двоичное число в виде "0011010". Параметр cFormat определяет сколько должно быть бит в двоичном числе (cFormat=8, GetBin="00001101").
Перейдём к самому алгоритму кодирования, который я назвал AsciiToBase64:
Function AsciiToBase64 (sSource As String) As String Dim Bin As String, Pos As Integer For t = 1 To Len(sSource) Step 3 Bin = "" For l = t To t + 2 If l > Len(sSource) Then Bin = Bin & "0000000=" Else Bin = Bin & GetBin(Asc(Mid$(sSource, l, 1)), 8) End If Next l For m = 1 To Len(Bin) Step 6 Pos = GetDec(Mid$(Bin, m, 6)) AsciiToBase64 = AsciiToBase64 & Mid$(Table, Pos + 1, 1) Next m Next t End Function
Эта функция возвращает закодированную строку, параметр sSource получает строку, которую надо закодировать. После объявления переменных Bin и Pos идёт первый цикл, который проходит по всей кодируемой строке через три символа. Следующий цикл идёт по трём символам кодируемой строки, согласно алгоритму, и состовляет из них ряд из двоичных чисел, получаемый при переводе порядкового номера символа в двоичный формат. В случае, если последняя пара символов не кратна 3, то в ряд Bin вставляется 7-и битовое число, состоящее из нулей, и знак "=". Последний третий цикл проходит по двоичному ряду с шагом 6, из которого 6-и битовые двоичные числа будут переводится в десятичные, и согласно которым из таблицы символов Base 64 будет состовляться закодированная строка. Совсем забыл сказать, что такое таблица символов Base 64, объявите её как константу в начале вашего модуля или формы:
Const Table As String = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
По правилам, оригинальная таблица состоит из 64 символов. Откуда 65-й? Всё очень просто. Вспомните строки:
Bin = Bin & "0000000=" ------------ и ------------- If InStr(1, Bin, "=") Then GetDec = 64: Exit Function
Так вот, если функция GetDec встречает в строке Bin символ "=", то она возвращает число 64 (64 + 1 = 65), а согласно алгоритму, в случае, если у нас некратная пара символов, то мы ставим знак "=". Как видите, этот способ намного облегчает создание алгоритма кодирования.
Алгоритм декодирования Base 64
Последовательность символов, закодированных методом Base 64, разделяется на группы по 4 символа. Затем каждому символу в соответствии с таблицей кодировки Base 64 ставится в соответствие десятичное значение порядкового номера. Каждое десятичное значение представляется в шестибитовом виде, и далее формируется последовательность длиной 24 бита (6*4). Полученная последовательность разбивается на три группы по 8 бит, при приведении которых к символьному виду получаются 3 символа ASCII.
Function Base64ToAscii (sSource As String) As String Dim Bin As String, Pos As Integer For t = 1 To Len(sSource) Step 4 Bin = "" For l = t To t + 3 Pos = InStr(1, Table, Mid$(sSource, l, 1)) Bin = Bin & GetBin(CStr(Pos - 1), 6) Next l For m = 1 To Len(Bin) Step 8 If GetDec(Mid$(Bin, m, 8)) <> 256 Then Base64ToAscii = Base64ToAscii & Chr$(GetDec(Mid$(Bin, m, 8))) End If Next m Next t End Function
Думаю, что подробно разбирать алгоритм не стоит, т.к. его сущность вы уже прочитали чуть выше. Замечу только то, что я отсеивал все нечитаемые символы (использовал алгоритм при работе со строками, а не с двоичными данными).