Пакетный файл с отложенным расширением переменных — кодировка URL — знак равенства — конвертер токенов RSA

Я автоматизирую преобразование программных токенов RSA и передаю строку преобразования в Outlook. Я понимаю, что не могу преобразовать строку в URL-адрес, используя командную строку пакетного просмотра, однако это не моя проблема. Моя проблема заключается в преобразовании надоедливого знака равенства в его эквивалент в кодировке URL «% 3D».

@echo off
setlocal enableDelayedExpansion

set /p fname=Enter the Filename:
set /p pss=Enter the encryption pass:

IF NOT EXIST "%fname%".sdtid (
echo File Not Found!  Closing...
PING 1.1.1.1 -n 4 >NUL
exit
)

echo File Found! starting process...

REM tokenconverter %fname%.sdtid -iphone >> temp_batch.txt
tokenconverter %fname%.sdtid -p %pss% -iphone >> temp_batch.txt

set /p result= < temp_batch.txt
DEL temp_batch.txt
REM %result% | clip

set "stringclean1=!result:?=%%3F!"
set "stringclean2=!stringclean1::=%%3A!"
set "stringclean3=!stringclean2:/=%%2F!"

В следующей строке не удается закодировать знак равенства:

 set "stringclean4=!stringclean3:==%%3D!"

Я пробовал:

 set "stringclean4=!stringclean3:=^=%%3D!"
 set "stringclean4=!stringclean3:=%=%%3D!"

Однако знак равенства остается незакодированным.

echo Piping over to outlook..
REM passing stringclean3 since stringclean4 no worky.
pushd "C:\Program Files\Microsoft Office\Office12"
outlook.exe /c ipm.note /m "&subject=TEsT&body=%stringclean3%"

Каков правильный способ URL-кодирования знака равенства с использованием отложенного расширения переменной?

Любая помощь приветствуется. Заранее спасибо.


person Justin    schedule 07.03.2013    source источник


Ответы (3)


Извините, простого решения для замены = в пакетном режиме просто не существует :-(

Лучшее, что вы можете сделать, используя чистый пакет, - это перебрать строку, символ за символом, и заменить ее по мере необходимости.

Вот решение грубой силы, в котором есть место для большей оптимизации. Но это достаточно хорошо. Сначала он проверяет, существует ли =, прежде чем кодировать =.

:: test if string contains =
:: only take the time to encode = if it exists
set "test=a!stringClean3!"
for /f "delims=" %%S in ("!test!") do if /i "!test:%%S=%%S!" neq "!test!" (

  :: compute length of string - 1
  set end=0
  for /l %%A in (12,-1,0) do (
    set /a "end|=1<<%%A"
    for %%B in (!end!) do if "!stringClean3:~%%B,1!"=="" set /a "end&=~1<<%%A"
  )

  :: replace = with %3D
  for /l %%N in (0 1 !end!) do (
    if "!stringClean3:~%%N,1!" equ "=" (
      set "stringClean4=!stringClean4!%%3D"
    ) else (
      set "stringClean4=!stringClean4!!stringClean3:~%%N,1!"
    )
  )

) else set stringClean4=!stringClean3!


ИЗМЕНИТЬ

Вот еще один совершенно другой подход, использующий CERTUTIL для кодирования и декодирования строки в шестнадцатеричном формате. Закодировать шестнадцатеричную строку очень просто. Я не думаю, что CERTUTIL поставляется с XP. Я не помню, но синтаксис CERTUTIL может немного меняться в зависимости от версии Windows. Я разработал и протестировал это на Vista.

set "tempFile=%temp%\replaceEqual%random%"

(>"%tempFile%.before" echo(!stringClean3!)
certutil -encodehex "%tempFile%.before" "%tempFile%.hex" >nul
>"%tempFile%.hex2" (
  for /f "usebackq tokens=1*" %%A in ("%tempFile%.hex") do (
    set ln=%%B
    set "ln=!ln:~0,48!"
    (echo !ln:3d=25 33 44!)
  )
)
certutil -decodehex "%tempFile%.hex2" "%tempFile%.after" >nul
<"%tempFile%.after" set /p "stringClean4="
del "%tempFile%.*"

Использование SET /P для чтения результата приводит к следующим ограничениям:

  • длина строки должна быть меньше или равна 1021 символу.
  • строка не должна заканчиваться управляющим символом (конечные управляющие символы удаляются)
  • строка не должна содержать перевод строки

Результат может быть прочитан с помощью FOR /F, но тогда отложенное расширение испортит все ! при раскрытии переменной FOR.

person dbenham    schedule 07.03.2013
comment
+1 эффективно, но я уверен, что это было бы хорошей причиной для гибридного решения пакет + JScript/VBScript. Замена регулярного выражения может быть более эффективной, чем посимвольная проверка и замена. Ты знаешь чего хочешь. :) - person rojo; 07.03.2013
comment
@rojo - да, я почти добавил это решение. Но еще лучше было бы решение JScript (возможно, гибрид JScript/Batch), которое использует encodeURIComponent() для обработки всех аспектов кодирования. - person dbenham; 07.03.2013

У dbenham была хорошая идея использовать метод JScript encodeURIComponent. Вот он, вставленный в пример сценария OP:

@echo off
setlocal

set /p fname=Enter the Filename:
set /p pss=Enter the encryption pass:

IF NOT EXIST "%fname%".sdtid (
    echo File Not Found!  Closing...
    PING 1.1.1.1 -n 4 >NUL
    exit
)

echo File Found! starting process...

echo WScript.Stdout.WriteLine(encodeURIComponent(WScript.StdIn.ReadLine()));>uri.js
for /f "delims=" %%I in (
    'tokenconverter %fname%.sdtid -p %pss% -iphone ^| cscript /nologo uri.js'
) do set "result=%%I"
del uri.js
person rojo    schedule 07.03.2013
comment
Хорошо, но вы должны отключить отложенное расширение, по крайней мере, до set "result=%%I", иначе вы потеряете восклицательные знаки и символы вставки. - person jeb; 07.03.2013
comment
Хорошая идея. В любом случае в сценарии нет ничего, требующего enabledelayedexpansion, так что теперь его нет. - person rojo; 07.03.2013

person    schedule
comment
Этот алгоритм терпит неудачу, если есть последовательные =, и проблема не может быть устранена. Это также не работает, если stringclean0X существует, но эту проблему можно решить. - person dbenham; 07.03.2013