Topic
  • 1 reply
  • Latest Post - ‏2011-09-21T14:36:19Z by HermannSW
HermannSW
HermannSW
4728 Posts

Pinned topic Processing quoted-printable body part of a multipart/signed message

‏2011-09-21T14:15:55Z |
Yesterday I posted "Processing quoted-printable body part of a multipart/signed message in XI50 stylesheet":
https://www.ibm.com/developerworks/mydeveloperworks/blogs/HermannSW/entry/processing_quoted_printable_body_part_of_a_multipart_signed_message_in_xi50_stylesheet29
http://tinyurl.com/6h7xa4f (sory, link too long for this Forum SW)

The provided solution had to use a chained service for decoding.

Below I want to show a decoding solution in a single stylesheet, without the need of service chaining
(or a seperate WTX action with QUOTEDTOTEXT() function in policy).
Find attached this simple multipart/signed message (with CRLFs as spec requires):

From: abc@datapower.com To: def@datapower.com Message-ID: <hello@dp4-l3> Subject: quoted-printable demo MIME-Version: 1.0 Content-Type: multipart/signed; protocol=
"application/pkcs7-signature"; micalg=sha1; boundary=
"----=_Part_2_12345"   ------=_Part_2_12345 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable   <?xml version=3D
"1.0" encoding=3D
"ISO-8859-1"?> <sample>If you believe that truth=3Dbeauty, then surely=20= mathematics is the most beautiful branch of philosophy.=0A= <umlaute>=E4=F6=FC=C4=D6=DC=DF</umlaute>= </sample> ------=_Part_2_12345 Content-Type: application/pkcs7-signature; name=smime.p7s; smime-type=signed-data Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename=
"smime.p7s" Content-Description: S/MIME Cryptographic Signature   This should be base64 sign part data. Missing intentionally 

for qouted-printable demo. ------=_Part_2_12345--   epilogue, gets ignored.

Below is a demonstration making use of coproc2nonxml service, see this posting:
https://www.ibm.com/developerworks/mydeveloperworks/blogs/HermannSW/entry/unzip_swa_and_coproc2nonxml13

The only change I made to that service was to select an XML manager with Minimum Output Escaping Rule selected in its Compile Options Policy in order to show the German Umlaute.

Here you can see stylesheet quoted-printable.xsl in action.
It outputs the input, the decoded input and finally the parsed decoded input.

$ coproc2 quoted-printable.xsl Qp.mime http:
//dp3-l3:2224; echo &​lt;?xml version=3D
"1.0" encoding=3D
"ISO-8859-1"?>&​#13; &​lt;sample>If you believe that truth=3Dbeauty, then surely=20=&​#13; mathematics is the most beautiful branch of philosophy.=0A=&​#13; &​lt;umlaute>=E4=F6=FC=C4=D6=DC=DF</umlaute>=&​#13; &​lt;/sample>&​#13; ---------------------------------------- &​lt;?xml version=
"1.0" encoding=
"ISO-8859-1"?>&​#13; &​lt;sample>If you believe that truth=beauty, then surely mathematics is the most beautiful branch of philosophy. &​lt;umlaute>äöüÄÖÜß</umlaute>&​lt;/sample>&​#13; ---------------------------------------- <sample>If you believe that truth=beauty, then surely mathematics is the most beautiful branch of philosophy. <umlaute>äöüÄÖÜß</umlaute></sample> $


 
Hermann<myXsltBlog/>

Attachments

Updated on 2011-09-21T14:36:19Z at 2011-09-21T14:36:19Z by HermannSW
  • HermannSW
    HermannSW
    4728 Posts

    Re: Processing quoted-printable body part of a multipart/signed message

    ‏2011-09-21T14:36:19Z  
    Find attached stylesheet quoted-printable.xsl which is shown below, too.

    
    <xsl:template match=
    "/">
    

    • first the Non-XML input is extracted into $input
    • then the boundary is determined in MIME header
    • then the 1st quoted-printable encoded MIME section is determined ($input3)
    • output: $input3, decoded $input3 and the parsed decoded $input3

    
    <func:function name=
    "func:qp">
    

    • decode quoted-printable string
    • first remove all soft line breaks
    • then eliminate all '=' by splitting at '=3D'
    • call recursive func:qp-rec for each splitted string
    • concatenate all results together

    
    <!-- Recursive quoted-printable decoding. Precondition: - no soft line breaks (
    '=' at end of line) - no 
    '=3D' contained -->   <func:function name=
    "func:qp-rec">
    

    • determine first hex code following a '='
    • determine parsed entity for that hex code
    • regexp:replace all of these
    • recursive call for next '=XY' still there

    
    <!-- Map 
    
    for 8bit characters; Non-UTF8 characters are mapped to 
    '_'. This mapping is 
    
    for ISO-8859-1, please adapt 
    
    if necessary. --> <xsl:variable name=
    "apos" select=
    '"&apos;"'/>   <xsl:variable name=
    "map" select=
    "concat('&#x5F;&#x5F;&#x5F;&#x5F;&#x5F;&#x5F;&#x5F;&#x5F;', 
    '&#x5F;&#x09;&#x0A;&#x5F;&#x5F;&#x0D;&#x5F;&#x5F;', 
    '&#x5F;&#x5F;&#x5F;&#x5F;&#x5F;&#x5F;&#x5F;&#x5F;', 
    '&#x5F;&#x5F;&#x5F;&#x5F;&#x5F;&#x5F;&#x5F;&#x5F;', 
    '&#x20;&#x21;&#x22;&#x23;&#x24;&#x25;&#x26;',$apos, ... ... 
    '&#xF0;&#xF1;&#xF2;&#xF3;&#xF4;&#xF5;&#xF6;&#xF7;', 
    '&#xF8;&#xF9;&#xFA;&#xFB;&#xFC;&#xFD;&#xFE;&#xFF;' )
    "/>
    


    quoted-printable.xsl:

    
    <xsl:stylesheet version=
    "1.0" xmlns:xsl=
    "http://www.w3.org/1999/XSL/Transform" xmlns:dp=
    "http://www.datapower.com/extensions" xmlns:regexp=
    "http://exslt.org/regular-expressions" xmlns:str=
    "http://exslt.org/strings" xmlns:func=
    "http://exslt.org/functions" extension-element-prefixes=
    "dp" > <dp:input-mapping href=
    "store:///pkcs7-convert-input.ffd" type=
    "ffd"/>   <xsl:output omit-xml-declaration=
    "yes" />     <xsl:template match=
    "/"> <!-- base64 encode Non-XML input data --> <xsl:variable name=
    "input64" select=
    "dp:binary-encode(/object/message/node())"/>   <!-- base64 decode; results in input in 
    
    case of valid UTF-8 --> <xsl:variable name=
    "input" select=
    "dp:decode($input64, 'base-64')"/>   <!-- determine bounday from mime headers --> <xsl:variable name=
    "boundary" select=
    "substring-before( substring-after($input,
    'boundary=&quot;'), 
    '&quot;' )
    "/>   <!-- determine first quoted-prinatble part --> <xsl:variable name=
    "input1" select=
    "substring-after( $input, 
    'Content-Transfer-Encoding: quoted-printable' )
    "/>   <!-- skip over header values separated by empy line --> <xsl:variable name=
    "input2" select=
    "substring-after($input1,'&#13;&#10;&#13;&#10;')"/>   <!-- take anything until next boundary --> <xsl:variable name=
    "input3" select=
    "substring-before($input2,concat('--',$boundary))"/>   <!-- output data as is and quoted-printable decoded --> <xsl:value-of select=
    "$input3"/> <xsl:text>----------------------------------------
    </xsl:text> <xsl:copy-of select=
    "func:qp($input3)"/>   <!-- Parsing has to skip xml-declaration because of DataPower internal UTF-8 encoding, 
    
    for details see these postings: https:
    //www.ibm.com/developerworks/mydeveloperworks/blogs/HermannSW/tags/encoding --> <xsl:text>----------------------------------------
    </xsl:text> <xsl:copy-of select=
    "dp:parse(substring-after(func:qp($input3),'?>'))"/>   </xsl:template>   <!-- decode quoted-prinatble string --> <func:function name=
    "func:qp"> <xsl:param name=
    "str"/>   <!-- eliminate soft line breaks --> <xsl:variable name=
    "wosoft" select=
    "regexp:replace($str,'=\r{0,1}\n','','')"/>   <!-- eliminate 
    '=' characters (encoded as =3D) by splitting --> <xsl:variable name=
    "tokens" select=
    "str:split($wosoft,'=3D')"/>   <func:result> <!-- decode first token --> <xsl:value-of select=
    "func:qp-rec($tokens[1])"/>   <!-- 
    
    for all other tokes --> <xsl:for-each select=
    "$tokens[position() > 1]"> <!-- output 
    '=' (
    
    for =3D) --> <xsl:text>=</xsl:text>   <!-- decode token --> <xsl:value-of select=
    "func:qp-rec(.)"/> </xsl:for-each> </func:result> </func:function>     <!-- Recursive quoted-printable decoding. Precondition: - no soft line breaks (
    '=' at end of line) - no 
    '=3D' contained --> <func:function name=
    "func:qp-rec"> <xsl:param name=
    "str"/>   <xsl:choose> <!-- 
    
    if $str does not contaion a 
    '=' we are done --> <xsl:when test=
    "not(contains($str,'='))"> <func:result select=
    "$str"/> </xsl:when>   <xsl:otherwise> <!-- determine index of first quoted-printable character --> <xsl:variable name=
    "idx" select=
    "substring(substring-after($str,'='), 1, 2)"/>   <!-- map to corresponding parsed character value --> <xsl:variable name=
    "m" select=
    "substring($map, 1+dp:radix-convert($idx,16,10), 1)"/>   <!-- replace all occurences --> <func:result select=
    "func:qp-rec(regexp:replace($str,concat('=',$idx),'g',$m))"/> </xsl:otherwise> </xsl:choose> </func:function>     <!-- Map 
    
    for 8bit characters; Non-UTF8 characters are mapped to 
    '_'. This mapping is 
    
    for ISO-8859-1, please adapt 
    
    if necessary. --> <xsl:variable name=
    "apos" select=
    '"&apos;"'/>   <xsl:variable name=
    "map" select=
    "concat('&#x5F;&#x5F;&#x5F;&#x5F;&#x5F;&#x5F;&#x5F;&#x5F;', 
    '&#x5F;&#x09;&#x0A;&#x5F;&#x5F;&#x0D;&#x5F;&#x5F;', 
    '&#x5F;&#x5F;&#x5F;&#x5F;&#x5F;&#x5F;&#x5F;&#x5F;', 
    '&#x5F;&#x5F;&#x5F;&#x5F;&#x5F;&#x5F;&#x5F;&#x5F;', 
    '&#x20;&#x21;&#x22;&#x23;&#x24;&#x25;&#x26;',$apos, 
    '&#x28;&#x29;&#x2A;&#x2B;&#x2C;&#x2D;&#x2E;&#x2F;', 
    '&#x30;&#x31;&#x32;&#x33;&#x34;&#x35;&#x36;&#x37;', 
    '&#x38;&#x39;&#x3A;&#x3B;&#x3C;&#x3D;&#x3E;&#x3F;', 
    '&#x40;&#x41;&#x42;&#x43;&#x44;&#x45;&#x46;&#x47;', 
    '&#x48;&#x49;&#x4A;&#x4B;&#x4C;&#x4D;&#x4E;&#x4F;', 
    '&#x50;&#x51;&#x52;&#x53;&#x54;&#x55;&#x56;&#x57;', 
    '&#x58;&#x59;&#x5A;&#x5B;&#x5C;&#x5D;&#x5E;&#x5F;', 
    '&#x60;&#x61;&#x62;&#x63;&#x64;&#x65;&#x66;&#x67;', 
    '&#x68;&#x69;&#x6A;&#x6B;&#x6C;&#x6D;&#x6E;&#x6F;', 
    '&#x70;&#x71;&#x72;&#x73;&#x74;&#x75;&#x76;&#x77;', 
    '&#x78;&#x79;&#x7A;&#x7B;&#x7C;&#x7D;&#x7E;&#x7F;', 
    '&#x80;&#x81;&#x82;&#x83;&#x84;&#x85;&#x86;&#x87;', 
    '&#x88;&#x89;&#x8A;&#x8B;&#x8C;&#x8D;&#x8E;&#x8F;', 
    '&#x90;&#x91;&#x92;&#x93;&#x94;&#x95;&#x96;&#x97;', 
    '&#x98;&#x99;&#x9A;&#x9B;&#x9C;&#x9D;&#x9E;&#x9F;', 
    '&#xA0;&#xA1;&#xA2;&#xA3;&#xA4;&#xA5;&#xA6;&#xA7;', 
    '&#xA8;&#xA9;&#xAA;&#xAB;&#xAC;&#xAD;&#xAE;&#xAF;', 
    '&#xB0;&#xB1;&#xB2;&#xB3;&#xB4;&#xB5;&#xB6;&#xB7;', 
    '&#xB8;&#xB9;&#xBA;&#xBB;&#xBC;&#xBD;&#xBE;&#xBF;', 
    '&#xC0;&#xC1;&#xC2;&#xC3;&#xC4;&#xC5;&#xC6;&#xC7;', 
    '&#xC8;&#xC9;&#xCA;&#xCB;&#xCC;&#xCD;&#xCE;&#xCF;', 
    '&#xD0;&#xD1;&#xD2;&#xD3;&#xD4;&#xD5;&#xD6;&#xD7;', 
    '&#xD8;&#xD9;&#xDA;&#xDB;&#xDC;&#xDD;&#xDE;&#xDF;', 
    '&#xE0;&#xE1;&#xE2;&#xE3;&#xE4;&#xE5;&#xE6;&#xE7;', 
    '&#xE8;&#xE9;&#xEA;&#xEB;&#xEC;&#xED;&#xEE;&#xEF;', 
    '&#xF0;&#xF1;&#xF2;&#xF3;&#xF4;&#xF5;&#xF6;&#xF7;', 
    '&#xF8;&#xF9;&#xFA;&#xFB;&#xFC;&#xFD;&#xFE;&#xFF;' )
    "/> </xsl:stylesheet>
    


     
    Hermann<myXsltBlog/>