22 septembre 2011

Convertir la description encodée de certains objets HR Access

Depuis HRv3e, un certain nombre d'objets ont une description en base "illisible" car encodée au format MIME base64.

Ci dessous par exemple la description d'une page Web :

select ZONXML from WF25 where GPECRA||CDECRA='FPW0F703' order by NOLIG4;
 
00040018Coder-Version: 1.00037Content-Type: text/xml; charset=UTF-80033Content-Transfer-Encoding: base640034Content-Description:HRWFormEntity00005B44PD94bWwgdmVyc2lvbj0iMS4wIj8+DQo8SFJXSU5ET1cgV2lkdGg9IjEwMjQiIEhlaWdodD0iMTEwMCIgU3R5bGU9IiIgVmVyc2lvbj0iNS4wLjAiIHV1aWQ9IjlBNzMyM0Y4LTQ3MEYtNDJBMy05NzUxLTU0Q0JFRjQxNTkzRCIgQm9yZGVyPSJOb25lIiBGb290ZXJBY3Rpb25zPSJDQU5DRUwiPg0KCTxIUlBBTkVMIE1vZGU9InRhYiIgdXVpZD0iNDlFMzQ3MkItRDk2OC00NDg5LThBRTctMkNFOEQ2NTdFM0UyIiBMZWZ0PSIwIiB
...

Ci dessous un exemple de décodage de la description d'une page Web HRv5.
Il a fallu ordonner et joindre les multiples lignes de description :

echo "set lines 3900
select ZONXML||'\' from WF25 where GPECRA||CDECRA='FPW0F703'
order by NOLIG4;" |
i_sql |
sed '$s/\\$//' | sed -e :a -e '/\\$/N; s/\\\n//; ta' | sed -e 's/^.*Content-Description: HRWFormEntity........//' -e 's/^.*Encoding: base64........//' |
perl -MMIME::Base64 -ne 'print decode_base64($_)' | 
sed -e 's/é/é/g' -e 's/ê/ê/g' -e 's/à /à/g'  -e 's/è/è/g' -e 's/#@/@/g' -e 's/ô/ô/g' -e 's/î/î/g' -e 's/â/â/g' -e 's/û/û/g' -e 's/ç/ç/g' -e 's/ù/ù/g' |  tr '@' '\n'

Dans cet exemple de commande on a :
  •  i_sql qui est un utilitaire exécutant un SQLPLUS,
  •  un premier sed qui fusionne les lignes et supprime l'entête HR Access "Content-Description...base64" qui précède la description de l'objet,
  •  un perl qui décode la description,
  •  un second sed qui rétabli les caractères accentués.

ce qui donne :

<?xml version="1.0"?>
<HRWINDOW Width="1024" Height="1100" Style="" Version="5.0.0" uuid="9A7323F8-470F-42A3-9751-54CBEF41593D" Border="None" FooterActions="CANCEL">
<HRPANEL Mode="tab" uuid="49E3472B-D968-4489-8AE7-2CE8D657E3E2" Left="0" Top="0" Width="1024" Height="477" LabelContext="page" Style="PAN05" EnableContext="default">
<HRDS uuid="C2451795-82F1-4C7F-BEDB-712F11229D24" Left="0" Top="0" Width="774" Height="234" Typerep="Z" Maxrowrep="1" Maxcolrep="1" Titlerep="1" Type="normal" HideEmptyrep="0">
<HRPARAMS Left="18" Top="63" Width="738" Height="72" uuid="D21F177F-0433-4011-972E-A52577058799">
<HRPANEL Left="18" Top="63" Width="738" Height="72" Mode="simple" LabelContext="page" Style="PAN02" uuid="83BDF6FD-591F-47E5-A0D1-9ECEEFF251FB" EnableContext="default">
...

4 commentaires:

  1. hello mister D,

    Sais tu si, avec le même principe, on peut récupérer les scripts inclus dans les pages web afin de rechercher plus facilement des exemples d'utilisation de certaines fonctions ?

    D'avance merci.

    RépondreSupprimer
  2. j'ai testé sur la rubrique ZOPROC de la table SP10 mais le résultat n'est pas lisible, c'est bizarre parce que ça a l'air d'être encodé de la même façon.

    RépondreSupprimer
  3. Bonjour,

    Voici une requête sql qui permet de permet de faire ceci ;-)

    -- Lecture des scripts des pages web :
    with sp10_max as (
    select tyenti, cdentc, nuvvar, max(nolign) as nolign_max
    from sp10
    group by tyenti, cdentc, nuvvar
    ) , dephasage as (
    select distinct case when nuvvar = '4.200' then instr(zoproc,'Content-Transfer-Encoding: base64') + length('Content-Transfer-Encoding: base64') +8
    else instr(zoproc,'Content-Description: HRWScript') + length('Content-Description: HRWScript') +8
    end as dephasage, nuvvar
    from sp10 where nolign in ( '01', '001', '0001', '00001' )
    ) , sp10_ok as (
    select a.tyenti, a.cdentc, a.nuvvar, a.nolign, b.nolign_max,
    case when nolign in ( '01', '001', '0001', '00001' ) and nolign_max = nolign then substr(a.zoproc,c.dephasage)
    when nolign in ( '01', '001', '0001', '00001' ) and nolign_max != nolign then substr(a.zoproc,c.dephasage) || substr(lead(a.zoproc,1,0) over (order by a.tyenti, a.cdentc, a.nuvvar, a.nolign) ,1,mod(c.dephasage -1 ,4)) -- pour avoir un modulo 4 dans le decode
    else substr(a.zoproc, mod(c.dephasage,4)) -- pour avoir un modulo 4 dans le decode
    end as zonxml_ok
    from sp10 a inner join sp10_max b on (a.tyenti = b.tyenti and a.cdentc = b.cdentc and a.nuvvar = b.nuvvar)
    inner join dephasage c on (b.nuvvar = c.nuvvar)
    order by 1,2,3
    ), sp10_converti as (
    select tyenti , cdentc, nuvvar, nolign, -- nolig4_max, length(zonxml_ok) as l,
    convert( --'banniÚre' get rid of mojiabke
    UTL_RAW.CAST_TO_VARCHAR2(UTL_ENCODE.BASE64_DECODE(UTL_RAW.CAST_TO_RAW(coalesce(substr(zonxml_ok,1,2000), ' ')))) || -- pas plus de 2000 caractères possibles pour UTL_ENCODE /// et coalesce car le null fait une erreur
    UTL_RAW.CAST_TO_VARCHAR2(UTL_ENCODE.BASE64_DECODE(UTL_RAW.CAST_TO_RAW(coalesce(substr(zonxml_ok,2001 ), ' '))))
    ,'WE8ISO8859P15','AL32UTF8' ) as xml_converti
    from sp10_ok
    )
    select * --cdentc, substr( xml_converti, instr( xml_converti, 'hrSetValue') )
    from sp10_converti
    where xml_converti like '%function %' -- renseigner ici ce qu'on cherche
    escape '\' -- pour avoir un caractère d'échappement dans le like au-dessus
    ;

    RépondreSupprimer
  4. Ouah ... Ça pique les yeux ...
    Bravo et merci !

    RépondreSupprimer