Есть ли способ декодировать кодировку Quoted-Printable с помощью ApplescriptObj c? - PullRequest
0 голосов
/ 15 января 2020

Я ищу способ декодирования HTML Исходного кода из почтового сообщения, закодированного в кодировке Quoted-Printable, и задаюсь вопросом, можно ли это сделать в AppleScriptObj C?

Я знаю, что в Python 3 есть встроенный модуль с именем quopri, который сделает эту работу. Так что у меня есть запасной вариант. Просто надеясь, что я могу сделать это без необходимости устанавливать Python 3 на компьютере пользователя. Поскольку скрипт уже встроен в AppleScript, я подумал, что AppleScriptObj C будет лучшим местом для go поиска ответа.

Ответы [ 2 ]

1 голос
/ 22 января 2020

Указанный для печати стандарт кодирования определен как часть RFC 2045.

Для краткого изложения и в общем смысле: непечатные символы ASCII кодируются как три -последовательность символов, начинающаяся с "=", за которой сразу следует шестнадцатеричное число, состоящее из двух цифр git, что соответствует коду ASCII-символа; "=" само кодируется таким же образом; строки могут быть длиной до 76 символов, но не более 76 символов, для которых "=" действует как символ продолжения (или мягкого переноса), если он появляется в конце строки.

Я взял расширенный набор этих правил, обеспечивающий выполнение достаточных условий, вокруг которых был написан следующий сценарий, и представлен «как есть» без каких-либо особых попыток оптимизации (для которых еще остается область действия):

#!/usr/bin/env osascript
--------------------------------------------------------------------------------
use framework "Foundation"
use scripting additions
--------------------------------------------------------------------------------
prop NSString: ref current application's NSString

prop rgex: 1024
prop utf8: 4
--------------------------------------------------------------------------------
on qp_decode(input)
        local input

        try # test for existence as a file path
                input as «class fsrf»
                NSString's stringWithContentsOfURL:result ¬
                        encoding:utf8 |error|:(missing value)
        on error
                input
        end try

        set qp to __s(result)

        replace(qp, "(?m)\\h*$", "")      # Removing trailing whitespace
        replace(qp, "(?sm)=(\\R|$)", "")  # Join lines split with a soft-break
        map(qp, "(?i)=[A-F0-9]{2}", char) # Decode escape sequences, i.e. "=HH"
end qp_decode
--------------------------------------------------------------------------------
# "PRIVATE" HANDLERS:
on __s(init)
        ref item 1 of {init}
end __s

to _nsstring_ from _ref given mutability:m as boolean : false
        local _ref, m, t

        set t to NSString's stringWithString:_ref
        if m then set t to t's mutableCopy()
        try
                set _ref's contents to t
        end try
        t
end _nsstring_

to replace(_ref, a, b)
        local _ref, a, f, t

        set t to _nsstring_ from _ref with mutability

        t's replaceOccurrencesOfString:a withString:b ¬
                options:rgex |range|:{0, t's |length|()}
        try
                set _ref's contents to t as text
        end try
        t as text
end replace

to map(_ref, a, func as handler)
        local _ref, a, t, f

        script
                prop fn: func
                prop t : _nsstring_ from _ref
                prop s : t's mutableCopy()
                prop index: 0

                on next()
                        t's rangeOfString:a options:rgex
                        set [j, n] to the result's [location, |length|]
                        if n = 0 then return the yield()
                        set u to (t's substringWithRange:[j, n]) as text
                        set c to fn(text 2 thru -1 of u)
                        tell s to replaceOccurrencesOfString:u ¬
                                withString:c options:0 |range|:[my index, ¬
                                |length|() - my index]
                        set index to index + j
                        set t to the substringFromIndex_(index) of s

                        next()
                end next

                on yield()
                        try
                                set _ref's contents to s as text
                        end try
                        s as text
                end yield
        end script

        result's next()
end map

to base_10 from base_16
        # There's probably a more ASObjC-y way to do this
        local base_16

        set p to 1
        set |ξ| to 0

        script hexadecimal
                prop digits: "123456789ABCDEF"
                prop coefficients: reverse of base_16's characters
        end script

        repeat with x in hexadecimal's coefficients
                set |ξ| to |ξ| + (offset of x in (hexadecimal's digits)) * p
                set p to p * 16
        end repeat

        |ξ|
end denary

to char(k)
        if k's class = text then set k to (base_10 from k)
        character id k
end char
---------------------------------------------------------------------------❮END❯

Основной обработчик, который вы будете вызывать, это qp_decode(), который принимает единственный аргумент, который может быть литеральной строкой или путем к файлу, при котором содержимое файла читается и обрабатывается в виде строки в кодировке UTF-8, а затем обрабатывается как строковый аргумент.

Я отмечаю в ветке комментариев, что вы используете Script Debugger . Если сценарий не удается скомпилировать или выполнить, я бы порекомендовал запустить сценарий в Редактор сценариев (однако здесь вам нужно будет снова скопировать / вставить из исходного источника, как Отладчик сценариев манипулирует содержимым буфера обмена перед вставкой). Я на самом деле использовал vim и osascript при разработке и отладке этого скрипта, так что это девственный текст.

0 голосов
/ 15 января 2020

Очистка от сети, это должно сделать трюк:

use framework "Foundation"

property NSString : class "NSString"

set coded_s to "" -- some quoted-printable string
--convert from applescript text to NSString
set coded_s to NSString's stringWithString:coded_s
-- delete line wraps
set decoded_s to coded_s's stringByReplacingOccurrencesOfString:("=" & return & linefeed) withString:""
-- replace = with percent
set decoded_s to decoded_s's stringByReplacingOccurrencesOfString:"=" withString:"%"
-- decode as percent-escaped string
set decoded_s to decoded_s's stringByReplacingPercentEscapesUsingEncoding:(current application's NSUTF8StringEncoding)
-- convert from NSString to applescript text
decoded_s as text
...