Blog. Just Blog

Функции urldecode и urlencode на Ассемблере

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Образ мышления: Assembler | Автор: ManHunter
Функции urldecode и urlencode на Ассемблере
Функции urldecode и urlencode на Ассемблере

Моя реализация функций PHP urldecode и urlencode, а также двух их разновидностей rawurldecode и rawurlencode на Ассемблере. Алгоритм их работы описан в документации. Единственное отличие от оригинальной функции rawurlencode в том, что кодируется вся строка целиком, а не только буквенно-цифровые символы. На мой взгляд, это более логичное поведение функции с приставкой "raw". В остальном никаких отличий нет.

Начну с функции декодирования, как с более востребованной. У нее четыре параметра: указатель на исходную строку, длина закодированной строки, указатель на буфер для раскодированной строки и флаг - использовать или нет RAW-декодирование. Разница RAW-декодирования от обычного заключается только в том, что при обычном декодировании символ "+" заменяется на пробел, а при RAW-декодировании обрабатываются только скаляры.
  1. ;-----------------------------------------------------------------------
  2. ; Функция URL-декодирования
  3. ; by ManHunter / PCL
  4. ; http://www.manhunter.ru
  5. ;-----------------------------------------------------------------------
  6. ; Параметры:
  7. ;       lpData - указатель на строку
  8. ;       dSize  - длина строки
  9. ;       lpBuff - указатель на буфер-приемник
  10. ;       dRaw   - использовать RAW-декодирование (TRUE/FALSE)
  11. ;-----------------------------------------------------------------------
  12. proc    url_decode lpData:DWORD, dSize:DWORD, lpBuff:DWORD, dRaw:DWORD
  13.         push    eax ebx ecx edx edi esi
  14.  
  15.         mov     ecx,[dSize]
  16.         mov     esi,[lpData]
  17.         mov     edi,[lpBuff]
  18.  
  19.         or      ecx,ecx
  20.         jz      .loc_done
  21. .loc_decode:
  22.         xor     eax,eax
  23.         lodsb
  24.  
  25.         ; Принудительно конвертировать все подряд
  26.         cmp     [dRaw],TRUE
  27.         je      .raw_decode
  28.  
  29.         ; '+' заменяется на пробел
  30.         cmp     al,'+'
  31.         jne     .raw_decode
  32.         mov     al,' '
  33.         jmp     .loc_store
  34. .raw_decode:
  35.         ; Возможно, это закодированный символ
  36.         cmp     al,'%'
  37.         jne     .loc_store
  38.  
  39.         ; Строка заканчивается?
  40.         cmp     ecx,3
  41.         jb      .loc_store
  42.  
  43.         cmp     byte [esi],'u'
  44.         jne     .decode_ascii
  45.         ; Строка заканчивается?
  46.         cmp     ecx,5
  47.         jb      .loc_store
  48.  
  49.         ; Двухбайтные юникод-скаляры %uNNNN (UTF-16)
  50. .decode_unicode:
  51.         push    eax
  52.         xor     ebx,ebx
  53.         xor     edx,edx
  54.         inc     edx
  55.         mov     ah,5
  56.         jmp     .decode_digit
  57.  
  58.         ; Однобайтовые скаляры %NN
  59. .decode_ascii:
  60.         push    eax
  61.         xor     ebx,ebx
  62.         xor     edx,edx
  63.         mov     ah,2
  64.  
  65.         ; Декодировать нужное количество цифр
  66. .decode_digit:
  67.         shl     ebx,4
  68.         mov     al,byte [esi+edx]
  69.         cmp     al,'0'
  70.         jb      .loc_skip
  71.         cmp     al,'9'
  72.         ja      @f
  73.         sub     al,'0'
  74.         jmp     .decode_digit_next
  75. @@:
  76.         ; Символ в нижний регистр
  77.         or      al,20h
  78.         cmp     al,'a'
  79.         jb      .loc_skip
  80.         cmp     al,'f'
  81.         ja      .loc_skip
  82.         sub     al,'a'-10
  83. .decode_digit_next:
  84.         add     bl,al
  85.         inc     edx
  86.         cmp     dl,ah
  87.         jb      .decode_digit
  88.  
  89.         xchg    eax,ebx
  90.         shr     ebx,8
  91.  
  92.         ; Пропустить следующие символы
  93.         sub     ecx,ebx
  94.         add     esi,ebx
  95.  
  96.         pop     ebx
  97.         jmp     .loc_store
  98. .loc_skip:
  99.         pop     eax
  100.  
  101. .loc_store:
  102.         cmp     eax,0FFh
  103.         jbe     .loc_store_byte
  104. .loc_store_word:
  105.         ; Записать раскодированный юникодный символ в строку
  106.         stosw
  107.         jmp     @f
  108. .loc_store_byte:
  109.         ; Записать раскодированный символ в строку
  110.         stosb
  111. @@:
  112.         loop    .loc_decode
  113. .loc_done:
  114.         ; Символ конца строки
  115.         mov     al,0
  116.         stosb
  117.  
  118.         pop     esi edi edx ecx ebx eax
  119.         ret
  120. endp
Функция универсальная, обрабатывает как однобайтовые скаляры вида %NN, так и двухбайтные юникод-скаляры вида %uNNNN, которые используются при URL-кодировании строк в формате UTF-16. Исходная строка может содержать обычные символы и оба вида скаляров в любом сочетании, все будет корректно раскодировано. Размер буфера-приемника не проверяется, поэтому он должен быть не менее длины исходной строки с учетом завершающего нулевого символа (признак окончания строки).

Функция кодирования также принимает четыре параметра: указатель на исходную строку, длина строки, указатель на буфер для закодированной строки и флаг - использовать или нет RAW-кодирование. В обычном режиме режим замены символов в функции аналогичен PHP-функции, в режиме RAW-кодирования обрабатываются все символы строки без исключения.
  1. ;-----------------------------------------------------------------------
  2. ; Функция URL-кодирования
  3. ; by ManHunter / PCL
  4. ; http://www.manhunter.ru
  5. ;-----------------------------------------------------------------------
  6. ; Параметры:
  7. ;       lpData - указатель на строку
  8. ;       dSize  - длина строки
  9. ;       lpBuff - указатель на буфер-приемник
  10. ;       dRaw   - использовать RAW-кодирование (TRUE/FALSE)
  11. ;-----------------------------------------------------------------------
  12. proc    url_encode lpData:DWORD, dSize:DWORD, lpBuff:DWORD, dRaw:DWORD
  13.         push    eax ecx edi esi
  14.  
  15.         mov     ecx,[dSize]
  16.         mov     esi,[lpData]
  17.         mov     edi,[lpBuff]
  18.  
  19.         or      ecx,ecx
  20.         jz      .loc_done
  21. .loc_encode:
  22.         lodsb
  23.  
  24.         ; Принудительно конвертировать все подряд
  25.         cmp     [dRaw],TRUE
  26.         je      .raw_encode
  27.  
  28.         ; Пробел заменяется на '+'
  29.         cmp     al,' '
  30.         jne     @f
  31.         mov     al,'+'
  32.         jmp     .loc_store
  33. @@:
  34.         ; Следующие символы без изменения
  35.         cmp     al,'_'
  36.         jz     .loc_store
  37.         cmp     al,'.'
  38.         jz     .loc_store
  39.         cmp     al,'-'
  40.         jz     .loc_store
  41.  
  42.         ; Буквенно-цифровые символы без изменения
  43.         cmp     al,'0'
  44.         jb      .raw_encode
  45.         cmp     al,'9'
  46.         jbe     .loc_store
  47.  
  48.         cmp     al,'A'
  49.         jb      .raw_encode
  50.         cmp     al,'Z'
  51.         jbe     .loc_store
  52.  
  53.         cmp     al,'a'
  54.         jb      .raw_encode
  55.         cmp     al,'z'
  56.         jbe     .loc_store
  57.  
  58.         ; Все остальное кодируется
  59. .raw_encode:
  60.         push    eax
  61.         mov     al,'%'
  62.         stosb
  63.         pop     eax
  64.  
  65.         ; Перевести байт в HEX-строку
  66.         movzx   eax,al
  67.         ror     eax,4
  68.         and     al,0Fh
  69.         daa
  70.         add     al,0F0h
  71.         adc     al,40h
  72.         stosb
  73.  
  74.         shr     eax,28
  75.         and     al,0Fh
  76.         daa
  77.         add     al,0F0h
  78.         adc     al,40h
  79. .loc_store:
  80.         ; Записать закодированный символ в строку
  81.         stosb
  82.         loop    .loc_encode
  83. .loc_done:
  84.         ; Символ конца строки
  85.         mov     al,0
  86.         stosb
  87.  
  88.         pop     esi edi ecx eax
  89.         ret
  90. endp
При кодировании не делается различий между UTF-16 и ASCII, все символы кодируются как однобайтовые скаляры. Размер буфера для приема кодированной строки не проверяется и должен заранее определяться с тем расчетом, что каждый символ исходной строки будет преобразован в три закодированных символа плюс нулевой символ окончания строки.

В приложении примеры двух программ с исходными текстами, демонстрирующие функции URL-кодирования и декодирования текстовых строк.

Примеры программ с исходными текстами (FASM)Примеры программ с исходными текстами (FASM)

Urlencode.Urldecode.Demo.zip (6,136 bytes)


Поделиться ссылкой ВКонтакте Поделиться ссылкой на Facebook Поделиться ссылкой на LiveJournal Поделиться ссылкой в Мой Круг Добавить в Мой мир Добавить на ЛиРу (Liveinternet) Добавить в закладки Memori Добавить в закладки Google
Просмотров: 3531 | Комментариев: 0

Внимание! Статья опубликована больше года назад, информация могла устареть!

Комментарии

Отзывы посетителей сайта о статье
Комментариeв нет

Добавить комментарий

Заполните форму для добавления комментария
Имя*:
Текст комментария (не более 2000 символов)*:

*Все поля обязательны для заполнения.
Комментарии, содержащие рекламу, ненормативную лексику, оскорбления и т.п., а также флуд и сообщения не по теме, будут удаляться. Нарушителям может быть заблокирован доступ к сайту.
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2017
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.07 сек. / MySQL: 2 (0.0062 сек.) / Память: 4.5 Mb
Наверх