IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

PL/SQL Oracle Discussion :

Noyau 8.1.7 et UTL_ENCODE


Sujet :

PL/SQL Oracle

  1. #1
    Expert confirmé
    Avatar de SheikYerbouti
    Profil pro
    Inscrit en
    Mai 2003
    Messages
    6 760
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2003
    Messages : 6 760
    Par défaut Noyau 8.1.7 et UTL_ENCODE
    Bonjour,
    Le package système UTL_ENCODE n'existe pas encore en 8.1.7. J'ai trouvé un lien vers ce qui semble être une solution, cependant ce lien est mort:
    http://www.oracle.com/us/technology/...4demo8_sql.txt
    Quelqu'un a t-il conservé ce script ? ou sinon, connait une solution pour décoder du base64 avec un noyau 8.1.7 ?
    D'avance merci

  2. #2
    McM
    McM est déconnecté
    Expert confirmé

    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Juillet 2003
    Messages
    4 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Juillet 2003
    Messages : 4 580
    Billets dans le blog
    4
    Par défaut
    Tu peux pas le coder en pl ?

  3. #3
    Expert confirmé
    Avatar de SheikYerbouti
    Profil pro
    Inscrit en
    Mai 2003
    Messages
    6 760
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2003
    Messages : 6 760
    Par défaut
    Citation Envoyé par McM Voir le message
    Tu peux pas le coder en pl ?
    Et bien, si je pouvais le faire, je ne posterais pas cette question ici

  4. #4
    McM
    McM est déconnecté
    Expert confirmé

    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Juillet 2003
    Messages
    4 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Juillet 2003
    Messages : 4 580
    Billets dans le blog
    4
    Par défaut
    J'essaye de te coder ça

  5. #5
    Expert confirmé
    Avatar de SheikYerbouti
    Profil pro
    Inscrit en
    Mai 2003
    Messages
    6 760
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2003
    Messages : 6 760
    Par défaut
    Le but est de remplacer ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    UTL_RAW.CAST_TO_VARCHAR2(UTL_ENCODE.BASE64_ENCODE(LR$Raw))
    et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    rawData := utl_encode.BASE64_DECODE(utl_raw.CAST_TO_RAW(PC$Chunk));

  6. #6
    McM
    McM est déconnecté
    Expert confirmé

    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Juillet 2003
    Messages
    4 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Juillet 2003
    Messages : 4 580
    Billets dans le blog
    4
    Par défaut
    Bon, je t'ai fait le ENCODE, c'est du brut (variables non normées, dbms, etc...)
    J'améliorerai après avoir fait le decode.
    ma référence : http://en.wikipedia.org/wiki/Base64

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    DECLARE
    	v_retour VARCHAR2(4000);
      v_chaine VARCHAR2(2000) := 'any carnal pleasure'; --' is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure.';
      v_b64 VARCHAR2(24); -- binaire de 3 char => 4 car 64
    	len NUMBER;
      j NUMBER;
      v_bin VARCHAR2(6);
    	-- fonction decimal en binaire
    	FUNCTION dec2bin (N IN number) RETURN varchar2 IS
        binval varchar2(64);
        N2 number := N;
      BEGIN
        WHILE N2 > 0
        LOOP
          binval := MOD(N2, 2) || binval;
          N2 := TRUNC( N2 / 2 );
        END LOOP;
        RETURN binval;
      END dec2bin;
      FUNCTION bin2dec (binval IN char) RETURN number IS
      result            number := 0;
      current_digit     char(1);
      current_digit_dec number;
      BEGIN
        FOR i IN 1..LENGTH(binval) LOOP
           current_digit := SUBSTR(binval, i, 1);
           current_digit_dec := TO_NUMBER(current_digit);
           result := (result * 2) + current_digit_dec;
        END LOOP;
        RETURN result;
      END bin2dec;
      FUNCTION car64(p_num IN number) RETURN varchar2
      IS
      BEGIN
      	-- Renvoit A-Z
      	IF p_num BETWEEN 0 AND 25 THEN RETURN CHR(65 + p_num); END IF;
    		-- a-z
      	IF p_num <= 51 THEN RETURN CHR(71 + p_num); END IF;
     		-- 0-9
      	IF p_num <= 61 THEN RETURN CHR(-4 + p_num); END IF;
        IF p_num = 62 THEN RETURN '+'; END IF;
        IF p_num = 63 THEN RETURN '/'; END IF;
    		RAISE_APPLICATION_ERROR(-20001, 'Pb num appel car64 :'|| p_num);
      END;
    --
    BEGIN
    --
    	len := LENGTH(v_chaine);
    	-- On boucle par 3 car qui seront transformés en 4
    	FOR i IN 1 .. CEIL(len/3)
      LOOP
        v_b64 := LPAD(dec2bin(ASCII(SUBSTR(v_chaine, 3*(i-1)+1, 1))),8,'0');
    		-- si le car suivant existe
        IF 3*(i-1)+2 <= len
        THEN
    	    v_b64 := v_b64 || LPAD(dec2bin(ASCII(SUBSTR(v_chaine, 3*(i-1)+2, 1))),8,'0');
          -- si le car suivant existe
          IF 3*(i-1)+3 <= len
          THEN
            v_b64 := v_b64 || LPAD(dec2bin(ASCII(SUBSTR(v_chaine, 3*(i-1)+3, 1))),8,'0');
      		ELSE
          	-- On rajoute des '0' pour arriver à 18 bits (3 car 64)
    	      v_b64 := RPAD(v_b64, 18, '0');
          END IF;
         ELSE
         	-- On rajoute des '0' pour arriver à 12 bits (2 car 64)
    	      v_b64 := RPAD(v_b64, 12, '0');
         END IF;
       --  DBMS_OUTPUT.put_line(v_b64);
    		-- On crée les caractères en B64 (codés sur 6 bits)
        -- On lit par 6 bits x 4
        FOR i IN 0..3
        LOOP
        	v_bin := SUBSTR(v_b64, 6*i+1, 6);
         -- DBMS_OUTPUT.put_line(i||':'||v_bin ||':'|| bin2dec(v_bin));
          IF v_bin IS NOT NULL
          THEN
          	v_retour := v_retour || car64(bin2dec(v_bin));
          ELSE
          	v_retour := v_retour || LPAD('=', 4-i, '=');
            EXIT;
          END IF;
        END LOOP;
      END LOOP;
      DBMS_OUTPUT.put_line(v_retour);
    END;

  7. #7
    Expert confirmé
    Avatar de SheikYerbouti
    Profil pro
    Inscrit en
    Mai 2003
    Messages
    6 760
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2003
    Messages : 6 760
    Par défaut
    Super
    Monsieur est un prince

  8. #8
    Expert confirmé
    Avatar de SheikYerbouti
    Profil pro
    Inscrit en
    Mai 2003
    Messages
    6 760
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2003
    Messages : 6 760
    Par défaut
    Ce n'est pas aussi simple que cela.
    Voici le code utilisé pour récupérer des tranches d'image (JPEG) stockée dans un BLOB:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
      -------------------------------------------------------------
      -- Return a Base 64 16384 bytes chunk of the selected BLOB --
      -------------------------------------------------------------
      FUNCTION Get_B64_Chunk RETURN VARCHAR2
      IS
        LN$amt  NUMBER := GN$Chunk ;
        LR$raw  RAW(16384);
      BEGIN
        LN$amt := GN$Chunk ;
        -- Read the BLOB
        dbms_lob.READ(GL$Blob, LN$amt, GN$Pos, LR$raw);
        GN$Pos := GN$Pos + LN$amt;
        LN$amt := GN$Chunk;
        RETURN UTL_RAW.CAST_TO_VARCHAR2(UTL_ENCODE.BASE64_ENCODE(LR$Raw));
      EXCEPTION
        WHEN OTHERS THEN
            RETURN NULL ;
      END Get_B64_Chunk ;
    On récupère la tranche d'image dans un RAW, et pas un VARCHAR2...

  9. #9
    Expert confirmé
    Avatar de SheikYerbouti
    Profil pro
    Inscrit en
    Mai 2003
    Messages
    6 760
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2003
    Messages : 6 760
    Par défaut
    Encoder B64 java:

    /9j/4AAQSkZJRgABAgAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8

    Encoder PL/SQL:

    /9j/4BA=SkZJRgB=AC==AQB=/D==20D=CAG=BgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aH

    Apparament, ton encodeur ne fournit pas la même chaine que Java

  10. #10
    McM
    McM est déconnecté
    Expert confirmé

    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Juillet 2003
    Messages
    4 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Juillet 2003
    Messages : 4 580
    Billets dans le blog
    4
    Par défaut
    Attention : L'encodage d'une longue chaine en b64 nécessite obligatoirement de découper en petites chaine de longueur multiple de 3
    Le = (ou ==) dans la chaine encodée indique une fin de chaine (lorsque celle ci n'est pas multiple de 3)

    Bon, pour le RAW, je ne sais pas j'ai rarement codé avec, je vais voir comment ça marche.
    Sinon voici le package en version varchar(2000)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    CREATE OR REPLACE PACKAGE PKG_B64 AS
     
    	FUNCTION F_ENCODE (p_chaine IN VARCHAR2) RETURN VARCHAR2;
    	FUNCTION F_DECODE(p_chaine IN VARCHAR2) RETURN VARCHAR2;
    END;
    /
     
    CREATE OR REPLACE PACKAGE BODY PKG_B64 
    IS
      v_b64 VARCHAR2(24); -- binaire de 3 car Ascii => 4 car b64
     -- fonction decimal en binaire
     
    	FUNCTION dec2bin (p_dec IN number) RETURN varchar2 IS
        binval varchar2(64);
        v number := p_dec;
      BEGIN
        WHILE v > 0
        LOOP
          binval := MOD(v, 2) || binval;
          v := TRUNC( v / 2 );
        END LOOP;
        RETURN binval;
      END dec2bin;
     
     -----+ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     
     
      FUNCTION bin2dec (binval IN varchar2) RETURN number IS
    	  result  number := 0;
      BEGIN
        FOR i IN 1..LENGTH(binval) 
        LOOP
           result := (result * 2) + TO_NUMBER(SUBSTR(binval, i, 1));
        END LOOP;
        RETURN result;
      END bin2dec;
     
    -----+ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     
      FUNCTION car64_encode(p_num IN number) RETURN varchar2
      IS
      BEGIN
      	-- Renvoit A-Z (0-25)
      	IF p_num BETWEEN 0 AND 25 THEN RETURN CHR(65 + p_num); END IF;
    		-- a-z (26-51)
      	IF p_num <= 51 THEN RETURN CHR(71 + p_num); END IF;
     		-- 0-9 (52-61)
      	IF p_num <= 61 THEN RETURN CHR(-4 + p_num); END IF;
        IF p_num = 62 THEN RETURN '+'; END IF;
        IF p_num = 63 THEN RETURN '/'; END IF;
    		RAISE_APPLICATION_ERROR(-20001, 'Pb num appel car64 :'|| p_num);
      END;
     
      FUNCTION car64_decode(p_car IN VARCHAR2) RETURN NUMBER
      IS
      BEGIN
      	--  A-Z :0-25
      	IF p_car BETWEEN 'A' AND 'Z' THEN RETURN ASCII(p_car) - 65; END IF;
    		-- a-z : 26-51
      	IF p_car BETWEEN 'a' AND 'z' THEN RETURN ASCII(p_car) - 71; END IF;
     		-- 0-9 : 52-61
      	IF p_car BETWEEN '0' AND '9' THEN RETURN ASCII(p_car) + 4; END IF;
        IF p_car = '+' THEN RETURN 62; END IF;
        IF p_car = '/' THEN RETURN 63; END IF;
    		RAISE_APPLICATION_ERROR(-20001, 'Pb num appel car64_decode :'|| p_car);
      END;
     
    -----+ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     
    	FUNCTION F_ENCODE (p_chaine IN VARCHAR2) RETURN VARCHAR2
      IS
        len NUMBER;
        j NUMBER;
        v_bin VARCHAR2(6);
        v_retour VARCHAR2(2668); -- taille max : 4 * ceil(2000/3)
      BEGIN
        len := LENGTH(p_chaine);
        -- On boucle par 3 car qui seront transformés en 4
        FOR i IN 1 .. CEIL(len/3)
        LOOP
          v_b64 := LPAD(dec2bin(ASCII(SUBSTR(p_chaine, 3*(i-1)+1, 1))),8,'0');
          -- si le car suivant existe
          IF 3*(i-1)+2 <= len
          THEN
            v_b64 := v_b64 || LPAD(dec2bin(ASCII(SUBSTR(p_chaine, 3*(i-1)+2, 1))),8,'0');
            -- si le car suivant existe
            IF 3*(i-1)+3 <= len
            THEN
              v_b64 := v_b64 || LPAD(dec2bin(ASCII(SUBSTR(p_chaine, 3*(i-1)+3, 1))),8,'0');
            ELSE
              -- On rajoute des '0' pour arriver à 18 bits (3 car 64)
              v_b64 := RPAD(v_b64, 18, '0');
            END IF;
           ELSE
            -- On rajoute des '0' pour arriver à 12 bits (2 car 64)
              v_b64 := RPAD(v_b64, 12, '0');
           END IF;
         --  DBMS_OUTPUT.put_line(v_b64);
          -- On crée les caractères en B64 (codés sur 6 bits)
          -- On lit par 6 bits x 4
          FOR i IN 0..3
          LOOP
            v_bin := SUBSTR(v_b64, 6*i+1, 6);
           -- DBMS_OUTPUT.put_line(i||':'||v_bin ||':'|| bin2dec(v_bin));
            IF v_bin IS NOT NULL
            THEN
              v_retour := v_retour || car64_encode(bin2dec(v_bin));
            ELSE
              -- On complete par des = pour avoir des groupes de 4 car
              v_retour := v_retour || LPAD('=', 4-i, '=');
              EXIT;
            END IF;
          END LOOP;
        END LOOP;
        RETURN v_retour;
      END F_ENCODE;
     
    -----+ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     
      FUNCTION F_DECODE(p_chaine IN VARCHAR2) RETURN VARCHAR2 IS
        v_car VARCHAR2(1); len NUMBER;
        v_retour VARCHAR2(2000); 
      BEGIN
        len := NVL(LENGTH(p_chaine),-1);
        IF MOD(len, 4) <> 0
        THEN
          RAISE_APPLICATION_ERROR(-20001, 'Taille non multiple de 4 ('|| LENGTH(p_chaine) ||')');
        END IF;
        IF LTRIM(LOWER(p_chaine)||'=', 'abcdefghijklmnopqrstuvwxyz0123456789+/') NOT IN ('=', '==', '===')
        THEN
          RAISE_APPLICATION_ERROR(-20001, 'Chaine contient des caractères autre que base64');
        END IF;
        -- On va lire par bloc de 4 caractères B64 pour les coder en 3 caractères Ascii
        FOR i IN 1 .. (len/4)
        LOOP
          v_b64 := LPAD(dec2bin(car64_decode(SUBSTR(p_chaine, 4*(i-1)+1, 1))),6,'0')
                  ||LPAD(dec2bin(car64_decode(SUBSTR(p_chaine, 4*(i-1)+2, 1))),6,'0');
          IF SUBSTR(p_chaine, 4*(i-1)+3, 1) <> '='
          THEN
              v_b64 := v_b64 || LPAD(dec2bin(car64_decode(SUBSTR(p_chaine, 4*(i-1)+3, 1))),6,'0');
          END IF;        
          IF SUBSTR(p_chaine, 4*(i-1)+4, 1) <> '='
          THEN
              v_b64 := v_b64 || LPAD(dec2bin(car64_decode(SUBSTR(p_chaine, 4*(i-1)+4, 1))),6,'0');
          END IF;        
      --            
         -- DBMS_OUTPUT.put_line(v_b64);    							
          -- On lit les binaires Ascii (8 bits)
            v_retour := v_retour || CHR(bin2dec(SUBSTR(v_b64, 1, 8)));
          IF LENGTH(v_b64) > 12 -- au moins 2 car (le reste sont des = enlevés) 
          THEN
              v_retour := v_retour || CHR(bin2dec(SUBSTR(v_b64, 9, 8)));
          END IF;
          IF LENGTH(v_b64) = 24 -- tous les car
          THEN
              v_retour := v_retour || CHR(bin2dec(SUBSTR(v_b64, 17, 8)));
          END IF;
        END LOOP;
        RETURN v_retour;
      END;
    END;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    DECLARE
     v_chaine VARCHAR2(300);
     v_encode varchar2(400);
     v_decode varchar2(300);
    BEGIN 
    	v_chaine := 'any carnal pleasure.';
      DBMS_OUTPUT.put_line(v_chaine);
      v_encode := PKG_B64.f_encode(v_chaine);
    	DBMS_OUTPUT.put_line(v_encode);
      v_decode := PKG_B64.f_decode(v_encode);
    	DBMS_OUTPUT.put_line(v_decode);
    END;
     
    any carnal pleasure.
    YW55IGNhcm5hbCBwbGVhc3VyZS4=
    any carnal pleasure.

  11. #11
    Expert confirmé
    Avatar de SheikYerbouti
    Profil pro
    Inscrit en
    Mai 2003
    Messages
    6 760
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2003
    Messages : 6 760
    Par défaut
    Merci beaucoup pour le boulot.
    Toutefois, cela semble ne pas fonctionner avec les contenus binaires stockés dans les BLOB

  12. #12
    McM
    McM est déconnecté
    Expert confirmé

    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Juillet 2003
    Messages
    4 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Juillet 2003
    Messages : 4 580
    Billets dans le blog
    4
    Par défaut
    Tss.. attends.. laisse moi le temps de coder

    Voici avec une fonction encode pour du RAW (qui est simplement le codage hexa, équivalent au résultat de dbms_log.substr)

    Petite précision, l'encodage RAW (=hexa)=> B64 nécessite donc des tailles de chunk multiples de 6.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    CREATE OR REPLACE PACKAGE PKG_B64 AS
     
    	FUNCTION F_ENCODE (p_chaine IN VARCHAR2) RETURN VARCHAR2;
    	FUNCTION F_DECODE(p_chaine IN VARCHAR2) RETURN VARCHAR2;
    	FUNCTION F_ENCODE_RAW (p_chaine IN RAW) RETURN VARCHAR2;
    END;
    /
     
    CREATE OR REPLACE PACKAGE BODY PKG_B64 
    IS
      v_b64 VARCHAR2(24); -- binaire de 3 car Ascii => 4 car b64
     -- fonction decimal en binaire
     
    	FUNCTION dec2bin (p_dec IN number) RETURN varchar2 IS
        binval varchar2(64);
        v number := p_dec;
      BEGIN
        WHILE v > 0
        LOOP
          binval := MOD(v, 2) || binval;
          v := TRUNC( v / 2 );
        END LOOP;
        RETURN binval;
      END dec2bin;
     
     -----+ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     
     
      FUNCTION bin2dec (binval IN varchar2) RETURN number IS
    	  result  number := 0;
      BEGIN
        FOR i IN 1..LENGTH(binval) 
        LOOP
           result := (result * 2) + TO_NUMBER(SUBSTR(binval, i, 1));
        END LOOP;
        RETURN result;
      END bin2dec;
     
    -----+ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     
      FUNCTION car64_encode(p_num IN number) RETURN varchar2
      IS
      BEGIN
      	-- Renvoit A-Z (0-25)
      	IF p_num BETWEEN 0 AND 25 THEN RETURN CHR(65 + p_num); END IF;
    		-- a-z (26-51)
      	IF p_num <= 51 THEN RETURN CHR(71 + p_num); END IF;
     		-- 0-9 (52-61)
      	IF p_num <= 61 THEN RETURN CHR(-4 + p_num); END IF;
        IF p_num = 62 THEN RETURN '+'; END IF;
        IF p_num = 63 THEN RETURN '/'; END IF;
    		RAISE_APPLICATION_ERROR(-20001, 'Pb num appel car64 :'|| p_num);
      END;
     
      FUNCTION car64_decode(p_car IN VARCHAR2) RETURN NUMBER
      IS
      BEGIN
      	--  A-Z :0-25
      	IF p_car BETWEEN 'A' AND 'Z' THEN RETURN ASCII(p_car) - 65; END IF;
    		-- a-z : 26-51
      	IF p_car BETWEEN 'a' AND 'z' THEN RETURN ASCII(p_car) - 71; END IF;
     		-- 0-9 : 52-61
      	IF p_car BETWEEN '0' AND '9' THEN RETURN ASCII(p_car) + 4; END IF;
        IF p_car = '+' THEN RETURN 62; END IF;
        IF p_car = '/' THEN RETURN 63; END IF;
    		RAISE_APPLICATION_ERROR(-20001, 'Pb num appel car64_decode :'|| p_car);
      END;
     
    -----+ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     
    	FUNCTION F_ENCODE (p_chaine IN VARCHAR2) RETURN VARCHAR2
      IS
        len NUMBER;
        j NUMBER;
        v_bin VARCHAR2(6);
        v_retour VARCHAR2(2668); -- taille max : 4 * ceil(2000/3)
      BEGIN
        len := LENGTH(p_chaine);
        -- On boucle par 3 car qui seront transformés en 4
        FOR i IN 1 .. CEIL(len/3)
        LOOP
          v_b64 := LPAD(dec2bin(ASCII(SUBSTR(p_chaine, 3*(i-1)+1, 1))),8,'0');
          -- si le car suivant existe
          IF 3*(i-1)+2 <= len
          THEN
            v_b64 := v_b64 || LPAD(dec2bin(ASCII(SUBSTR(p_chaine, 3*(i-1)+2, 1))),8,'0');
            -- si le car suivant existe
            IF 3*(i-1)+3 <= len
            THEN
              v_b64 := v_b64 || LPAD(dec2bin(ASCII(SUBSTR(p_chaine, 3*(i-1)+3, 1))),8,'0');
            ELSE
              -- On rajoute des '0' pour arriver à 18 bits (3 car 64)
              v_b64 := RPAD(v_b64, 18, '0');
            END IF;
           ELSE
            -- On rajoute des '0' pour arriver à 12 bits (2 car 64)
              v_b64 := RPAD(v_b64, 12, '0');
           END IF;
         --  DBMS_OUTPUT.put_line(v_b64);
          -- On crée les caractères en B64 (codés sur 6 bits)
          -- On lit par 6 bits x 4
          FOR i IN 0..3
          LOOP
            v_bin := SUBSTR(v_b64, 6*i+1, 6);
           -- DBMS_OUTPUT.put_line(i||':'||v_bin ||':'|| bin2dec(v_bin));
            IF v_bin IS NOT NULL
            THEN
              v_retour := v_retour || car64_encode(bin2dec(v_bin));
            ELSE
              -- On complete par des = pour avoir des groupes de 4 car
              v_retour := v_retour || LPAD('=', 4-i, '=');
              EXIT;
            END IF;
          END LOOP;
        END LOOP;
        RETURN v_retour;
      END F_ENCODE;
     
    -----+ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     
      FUNCTION F_DECODE(p_chaine IN VARCHAR2) RETURN VARCHAR2 IS
        v_car VARCHAR2(1); len NUMBER;
        v_retour VARCHAR2(2000); 
      BEGIN
        len := NVL(LENGTH(p_chaine),-1);
        IF MOD(len, 4) <> 0
        THEN
          RAISE_APPLICATION_ERROR(-20001, 'Taille non multiple de 4 ('|| LENGTH(p_chaine) ||')');
        END IF;
        IF LTRIM(LOWER(p_chaine)||'=', 'abcdefghijklmnopqrstuvwxyz0123456789+/') NOT IN ('=', '==', '===')
        THEN
          RAISE_APPLICATION_ERROR(-20001, 'Chaine contient des caractères autre que base64');
        END IF;
        -- On va lire par bloc de 4 caractères B64 pour les coder en 3 caractères Ascii
        FOR i IN 1 .. (len/4)
        LOOP
          v_b64 := LPAD(dec2bin(car64_decode(SUBSTR(p_chaine, 4*(i-1)+1, 1))),6,'0')
                  ||LPAD(dec2bin(car64_decode(SUBSTR(p_chaine, 4*(i-1)+2, 1))),6,'0');
          IF SUBSTR(p_chaine, 4*(i-1)+3, 1) <> '='
          THEN
              v_b64 := v_b64 || LPAD(dec2bin(car64_decode(SUBSTR(p_chaine, 4*(i-1)+3, 1))),6,'0');
          END IF;        
          IF SUBSTR(p_chaine, 4*(i-1)+4, 1) <> '='
          THEN
              v_b64 := v_b64 || LPAD(dec2bin(car64_decode(SUBSTR(p_chaine, 4*(i-1)+4, 1))),6,'0');
          END IF;        
      --            
         -- DBMS_OUTPUT.put_line(v_b64);    							
          -- On lit les binaires Ascii (8 bits)
            v_retour := v_retour || CHR(bin2dec(SUBSTR(v_b64, 1, 8)));
          IF LENGTH(v_b64) > 12 -- au moins 2 car (le reste sont des = enlevés) 
          THEN
              v_retour := v_retour || CHR(bin2dec(SUBSTR(v_b64, 9, 8)));
          END IF;
          IF LENGTH(v_b64) = 24 -- tous les car
          THEN
              v_retour := v_retour || CHR(bin2dec(SUBSTR(v_b64, 17, 8)));
          END IF;
        END LOOP;
        RETURN v_retour;
      END;
     
      FUNCTION F_HEX2BIN (p_car IN VARCHAR2) RETURN VARCHAR2
      IS
      BEGIN
      	IF 		p_car = '0' THEN RETURN '0000';
        ELSIF p_car = '1' THEN RETURN '0001';
        ELSIF p_car = '2' THEN RETURN '0010';
        ELSIF p_car = '3' THEN RETURN '0011';
        ELSIF p_car = '4' THEN RETURN '0100';
        ELSIF p_car = '5' THEN RETURN '0101';
        ELSIF p_car = '6' THEN RETURN '0110';
        ELSIF p_car = '7' THEN RETURN '0111';
        ELSIF p_car = '8' THEN RETURN '1000';
        ELSIF p_car = '9' THEN RETURN '1001';
        ELSIF p_car = 'A' THEN RETURN '1010';
        ELSIF p_car = 'B' THEN RETURN '1011';
        ELSIF p_car = 'C' THEN RETURN '1100';
        ELSIF p_car = 'D' THEN RETURN '1101';
        ELSIF p_car = 'E' THEN RETURN '1110';
        ELSIF p_car = 'F' THEN RETURN '1111';
        ELSE 
        		RAISE_APPLICATION_ERROR(-20001, 'carac hexa invalide '|| p_car);
        END IF;
      END;
     
      FUNCTION F_ENCODE_RAW (p_chaine IN RAW) RETURN VARCHAR2
      IS
        len NUMBER; len_ret NUMBER := 0;
        j NUMBER;
        v_bin VARCHAR2(6);
        v_retour VARCHAR2(3000); -- taille max : 4 * ceil(2000/3)
      BEGIN
      	-- Le raw doit avoir une taille multiple de 6 si on veut découper (2 car pour chaque code ascii, 3 car ascii pour 4 car B64).
        -- Et obligatoirement multiple de 2
        len := LENGTH(p_chaine);
        IF MOD(len,2) <> 0 THEN 
    			RAISE_APPLICATION_ERROR(-20001, 'Taille du RAW non paire');
        END IF;
     
        -- On boucle par 6 car hexa qui seront transformés en 4 car B64
        FOR i IN 1 .. CEIL(len/6)
        LOOP
          v_b64 := F_HEX2BIN(SUBSTR(p_chaine, 6*(i-1)+1, 1)) || F_HEX2BIN(SUBSTR(p_chaine, 6*(i-1)+2, 1));
          -- si le car suivant existe
          IF 6*(i-1)+3 <= len
          THEN
            v_b64 := v_b64 || F_HEX2BIN(SUBSTR(p_chaine, 6*(i-1)+3, 1)) || F_HEX2BIN(SUBSTR(p_chaine, 6*(i-1)+4, 1));
            -- si le car suivant existe
            IF 6*(i-1)+5 <= len
            THEN
              v_b64 := v_b64 || F_HEX2BIN(SUBSTR(p_chaine, 6*(i-1)+5, 1)) || F_HEX2BIN(SUBSTR(p_chaine, 6*(i-1)+6, 1));
            ELSE
              -- On rajoute des '0' pour arriver à 18 bits (3 car 64)
              v_b64 := RPAD(v_b64, 18, '0');
            END IF;
           ELSE
            -- On rajoute des '0' pour arriver à 12 bits (2 car 64)
              v_b64 := RPAD(v_b64, 12, '0');
           END IF;
         --  DBMS_OUTPUT.put_line(v_b64);
          -- On crée les caractères en B64 (codés sur 6 bits)
          -- On lit par 6 bits x 4
          FOR i IN 0..3
          LOOP
            v_bin := SUBSTR(v_b64, 6*i+1, 6);
    					-- La chaine de retour est découpée en 64 caractères avec RC+LF
        			IF len_ret = 64 
              THEN 
              	v_retour := v_retour || CHR(13)|| CHR(10);
                len_ret := 1;
              ELSE
              	len_ret := len_ret + 1;
              END IF;
          -- DBMS_OUTPUT.put_line(i||':'||v_bin ||':'|| bin2dec(v_bin));
            IF v_bin IS NOT NULL
            THEN
            	v_retour := v_retour || car64_encode(bin2dec(v_bin));
            ELSE
              -- On complete par des = pour avoir des groupes de 4 car
              -- Je ne fais pas de retour à la ligne pour les = si le second dépasse les 64 car.. 
              v_retour := v_retour || LPAD('=', 4-i, '=');
              EXIT;
            END IF;
          END LOOP;
        END LOOP;
     
        RETURN v_retour;
     
      END F_ENCODE_RAW;
    END;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    DECLARE
      LN$amt  NUMBER := 2001; --GN$Chunk ;
      LR$raw  RAW(16384);
      v_lob BLOB;
    BEGIN
    	SELECT logo INTO v_lob --DBMS_LOB.getlength(logo)
      FROM table_logo
      WHERE ste = 1;
      -- Read the BLOB
      dbms_lob.READ(v_lob, LN$amt, 1, LR$raw);
      dbms_output.put_line('UTL_RAW.CAST_TO_VARCHAR2(UTL_ENCODE.BASE64_ENCODE');
      dbms_output.put_line(SUBSTR(UTL_RAW.CAST_TO_VARCHAR2(UTL_ENCODE.BASE64_ENCODE(LR$Raw)),1,250));
    	dbms_output.put_line('pkg_b64.F_ENCODE_RAW(LR$Raw);');
      dbms_output.put_line(SUBSTR(pkg_b64.F_ENCODE_RAW(LR$Raw),1,250));
    END;
     
    UTL_RAW.CAST_TO_VARCHAR2(UTL_ENCODE.BASE64_ENCODE
    R0lGODlhNAOVAfcAAAAAAAEBAQICAgMDAwQEBAUFBQYGBgcHBwgICAkJCQoKCgsL
    CwwMDA0NDQ4ODg8PDxAQEBERERISEhMTExQUFBUVFRYWFhcXFxgYGBkZGRoaGhsb
    GxwcHB0dHR4eHh8fHyAgICEhISIiIiMjIyQkJCUlJSYmJicnJygoKCkpKSoqKisr
    KywsLC0tLS4uLi8vLzAwMDExMTIyMjMzMzQ0NDU1NTY2Njc3Nzg4
    pkg_b64.F_ENCODE_RAW(LR$Raw);
    R0lGODlhNAOVAfcAAAAAAAEBAQICAgMDAwQEBAUFBQYGBgcHBwgICAkJCQoKCgsL
    CwwMDA0NDQ4ODg8PDxAQEBERERISEhMTExQUFBUVFRYWFhcXFxgYGBkZGRoaGhsb
    GxwcHB0dHR4eHh8fHyAgICEhISIiIiMjIyQkJCUlJSYmJicnJygoKCkpKSoqKisr
    KywsLC0tLS4uLi8vLzAwMDExMTIyMjMzMzQ0NDU1NTY2Njc3Nzg4
    J'ai bon ?

  13. #13
    Expert confirmé
    Avatar de SheikYerbouti
    Profil pro
    Inscrit en
    Mai 2003
    Messages
    6 760
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2003
    Messages : 6 760
    Par défaut
    oui, t'as bon
    Cependant (je fais mon gros lourd) c'est très lent. Est-il possible de passer les chunks de 2000 à un multiple plus elevé, 8192 ou 16384 ?

    en fait, passer à 16384 n'accélère rien. c'est l'algo qui est lent. Je vais voir comment optimiser.

  14. #14
    Expert confirmé
    Avatar de SheikYerbouti
    Profil pro
    Inscrit en
    Mai 2003
    Messages
    6 760
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2003
    Messages : 6 760
    Par défaut
    pour info, il faut 9 secondes pour une image de 24Ko

  15. #15
    McM
    McM est déconnecté
    Expert confirmé

    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Juillet 2003
    Messages
    4 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Juillet 2003
    Messages : 4 580
    Billets dans le blog
    4
    Par défaut
    C'est sur l'algo est un peu lent .. mais pas au point où tu le dis, j'en suis à 2.3s pour 47 Ko
    Enfin ça reste très loin des perfs de utl_encode (test sur une base 9)
    BLOB Taille :47735
    UTL_ENCODE :1 /100s
    PLSQL :227 /100s
    J'ai lancé un test sur un pdf de 10Mo.. estimation prévue 10 min.. pas top..
    Ca y est, résultat :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    BLOB Taille :10976898
    UTL_ENCODE :64 /100s
    PLSQL :53284 /100s
    Bon, je vais voir où ça rame.

  16. #16
    Expert confirmé
    Avatar de laurentschneider
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Décembre 2005
    Messages
    2 944
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Finance

    Informations forums :
    Inscription : Décembre 2005
    Messages : 2 944
    Par défaut
    en b64 on groupe par 6bit, en raw on groupe par 8bit.

    donc 3 octets = 4 caractères b64

    avec une petite table de conversion pour 3 octets, on obtient

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    create or replace package p is
      type tt is table of varchar2(4000);
      t tt;
      function f(r raw) return varchar2;
    end p;
    /
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    create or replace package body p is
      function f(r raw) return varchar2 is
        c varchar2(4000) := null;
        i integer := 0;
      begin
        while i < trunc(utl_raw.length(r)/3) loop
          c := c || t(utl_raw.cast_to_binary_integer(utl_raw.substr(r,i*3+1,3))+1);
          i:=i+1;
        end loop;
        c := c || 
          case mod(utl_raw.length(r),3) 
            when 1 then substr(t(utl_raw.cast_to_binary_integer(utl_raw.substr(r,i*3+1,1))*65536+1),1,2)||'=='
            when 2 then substr(t(utl_raw.cast_to_binary_integer(utl_raw.substr(r,i*3+1,2))*256+1),2,3)||'='
          end;
        return c;
      end;
     
    begin
      t := new tt();
      t.extend(16777216);
      for i in 0..63 loop
        for j in 0..63 loop
          for k in 0..63 loop
            for l in 0..63 loop
              t(i*262144+j*4096+k*64+l+1) := 
                case
                  when (i<26) then chr(65+i)
                  when (i<52) then chr(71+i)
                  when (i<62) then chr(i-4)
                  when (i=62) then chr(43)
                  when (i=63) then chr(47)
                end
                ||
                case
                  when (j<26) then chr(65+j)
                  when (j<52) then chr(71+j)
                  when (j<62) then chr(j-4)
                  when (j=62) then chr(43)
                  when (j=63) then chr(47)
                end
                ||
                case
                  when (k<26) then chr(65+k)
                  when (k<52) then chr(71+k)
                  when (k<62) then chr(k-4)
                  when (k=62) then chr(43)
                  when (k=63) then chr(47)
                end
                ||
                case
                  when (l<26) then chr(65+l)
                  when (l<52) then chr(71+l)
                  when (l<62) then chr(l-4)
                  when (l=62) then chr(43)
                  when (l=63) then chr(47)
                end;
            end loop;
          end loop;
        end loop;
      end loop;
    end;
    /
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    SQL> select p.f('001122') from dual;
    P.F('001122')                                                                   
    ------------------------------------------------------
    ABEi                                                                            
    Elapsed: 00:00:37.68
    SQL> select p.f('001122334455') from dual;
    P.F('001122334455')                                                             
    ------------------------------------------------------
    ABEiM0RW                                                                        
    Elapsed: 00:00:00.03
    SQL> select p.f('00112233445566778899AABBCCDDEEFF') from dual;
    P.F('00112233445566778899AABBCCDDEEFF')                                         
    ------------------------------------------------------
    ABEiM0RWZneJmaq7zN3u/w==                                                        
    1 row selected.
    Elapsed: 00:00:00.03
    on pourrait booster la première exécution en faisant un bulk collect depuis une table

    PS: j'ai corrigé un petit bug ...

  17. #17
    Expert confirmé
    Avatar de SheikYerbouti
    Profil pro
    Inscrit en
    Mai 2003
    Messages
    6 760
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2003
    Messages : 6 760
    Par défaut
    Merci Laurent
    ça c'est la fonction d'encodage, mais il parait plus rarissime, voir impossible de trouver le code de décodage
    tu aurais cela en stock ?

  18. #18
    Expert confirmé
    Avatar de laurentschneider
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Décembre 2005
    Messages
    2 944
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Finance

    Informations forums :
    Inscription : Décembre 2005
    Messages : 2 944
    Par défaut
    tu peux t'aider d'une table, style

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    create table t(n number primary key, b64 varchar2(4), r raw(3));
    insert into t with b as (select rownum-1 n,  
        case when (rownum<27) then chr(64+rownum)
          when (rownum<53) then chr(70+rownum)
          when (rownum<63) then chr(rownum-5)
          when (rownum=63) then chr(43)
          when (rownum=64) then chr(47) end c
      from dual connect by level<=64) 
    select b1.n*64*64*64+b2.n*64*64+b3.n*64+b4.n n,
       b1.c||b2.c||b3.c||b4.c b64,
       utl_raw.cast_from_binary_integer(b1.n*64*64*64+b2.n*64*64+b3.n*64+b4.n) r
    from b b1, b b2, b b3, b b4;
    le reste se tape tout seul... bonne chance

  19. #19
    Expert confirmé
    Avatar de SheikYerbouti
    Profil pro
    Inscrit en
    Mai 2003
    Messages
    6 760
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2003
    Messages : 6 760
    Par défaut
    ORA-12899: valeur trop grande pour la colonne "EQUD"."T"."R" (reelle : 4, maximum : 3)
    sir je passe la colonne r à 4 le code semble entrer dans une boucle infinie

  20. #20
    McM
    McM est déconnecté
    Expert confirmé

    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Juillet 2003
    Messages
    4 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Juillet 2003
    Messages : 4 580
    Billets dans le blog
    4
    Par défaut
    Suite à la procédure de codage que tu m'as envoyé, j'ai fait le decodage.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    CREATE OR REPLACE PACKAGE BODY SERCA.demo_base64 IS
     
    TYPE Map_table IS TABLE OF VARCHAR2(1) INDEX BY BINARY_INTEGER;
    map Map_table;
    TYPE Unmap_table IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;
    unmap Unmap_table;
     
    -- Initialize the Base64 mapping
    PROCEDURE init_map IS
    BEGIN
      map(0) :='A'; map(1) :='B'; map(2) :='C'; map(3) :='D'; map(4) :='E';
      map(5) :='F'; map(6) :='G'; map(7) :='H'; map(8) :='I'; map(9):='J';
      map(10):='K'; map(11):='L'; map(12):='M'; map(13):='N'; map(14):='O';
      map(15):='P'; map(16):='Q'; map(17):='R'; map(18):='S'; map(19):='T';
      map(20):='U'; map(21):='V'; map(22):='W'; map(23):='X'; map(24):='Y';
      map(25):='Z'; map(26):='a'; map(27):='b'; map(28):='c'; map(29):='d';
      map(30):='e'; map(31):='f'; map(32):='g'; map(33):='h'; map(34):='i';
      map(35):='j'; map(36):='k'; map(37):='l'; map(38):='m'; map(39):='n';
      map(40):='o'; map(41):='p'; map(42):='q'; map(43):='r'; map(44):='s';
      map(45):='t'; map(46):='u'; map(47):='v'; map(48):='w'; map(49):='x';
      map(50):='y'; map(51):='z'; map(52):='0'; map(53):='1'; map(54):='2';
      map(55):='3'; map(56):='4'; map(57):='5'; map(58):='6'; map(59):='7';
      map(60):='8'; map(61):='9'; map(62):='+'; map(63):='/';
     
    	unmap(65)  := 0;	unmap(66)  := 1;	unmap(67)  := 2;	unmap(68)  := 3;	unmap(69)  := 4;
      unmap(70)  := 5;	unmap(71)  := 6;	unmap(72)  := 7;	unmap(73)  := 8;	unmap(74)  := 9;	
      unmap(75)  := 10;	unmap(76)  := 11;	unmap(77)  := 12;	unmap(78)  := 13;	unmap(79)  := 14;	
      unmap(80)  := 15;	unmap(81)  := 16;	unmap(82)  := 17;	unmap(83)  := 18;	unmap(84)  := 19;	
      unmap(85)  := 20;	unmap(86)  := 21;	unmap(87)  := 22;	unmap(88)  := 23;	unmap(89)  := 24;	
      unmap(90)  := 25;	unmap(97)  := 26;	unmap(98)  := 27;	unmap(99)  := 28;	unmap(100)  := 29;	
      unmap(101)  := 30;	unmap(102)  := 31;	unmap(103)  := 32;	unmap(104)  := 33;	unmap(105)  := 34;	
      unmap(106)  := 35;	unmap(107)  := 36;	unmap(108)  := 37;	unmap(109)  := 38;	unmap(110)  := 39;	
      unmap(111)  := 40;	unmap(112)  := 41;	unmap(113)  := 42;	unmap(114)  := 43;	unmap(115)  := 44;	
      unmap(116)  := 45;	unmap(117)  := 46;	unmap(118)  := 47;	unmap(119)  := 48;	unmap(120)  := 49;	
      unmap(121)  := 50;	unmap(122)  := 51;	unmap(48)  := 52;	unmap(49)  := 53;	unmap(50)  := 54;	
      unmap(51)  := 55;	unmap(52)  := 56;	unmap(53)  := 57;	unmap(54)  := 58;	unmap(55)  := 59;	
      unmap(56)  := 60;	unmap(57)  := 61;	unmap(43)  := 62;	unmap(47)  := 63;	
      unmap(61)  := 61; -- = 	
     
    END;
     
    FUNCTION encode(r IN RAW) RETURN VARCHAR2 IS
      i PLS_INTEGER;
      x PLS_INTEGER;
      y PLS_INTEGER;
      v VARCHAR2(32767);
    BEGIN
     
     
    -- For every 3 bytes, split them into 4 6-bit units and map them to
    -- the Base64 characters
      i := 1;
      WHILE ( i + 2 <= UTL_RAW.LENGTH(r) )
      LOOP
        x := TO_NUMBER(UTL_RAW.SUBSTR(r, i, 1), '0X') * 65536 +
        TO_NUMBER(UTL_RAW.SUBSTR(r, i + 1, 1), '0X') * 256 +
        TO_NUMBER(UTL_RAW.SUBSTR(r, i + 2, 1), '0X');
        y := FLOOR(x / 262144); v := v || map(y); x := x - y * 262144;
        y := FLOOR(x / 4096); v := v || map(y); x := x - y * 4096;
        y := FLOOR(x / 64); v := v || map(y); x := x - y * 64;
        v := v || map(x);
        i := i + 3;	
    	END LOOP;
     
      -- Process the remaining bytes that has fewer than 3 bytes.
      IF UTL_RAW.LENGTH(r) - i = 0
      THEN
        x := TO_NUMBER(UTL_RAW.SUBSTR(r, i, 1), '0X');
        y := FLOOR(x / 4); v := v || map(y); x := x - y * 4;
        x := x * 16; v := v || map(x);
        v := v || '==';
      ELSIF UTL_RAW.LENGTH(r) - i = 1
      THEN
        x := TO_NUMBER(UTL_RAW.SUBSTR(r, i, 1), '0X') * 256 + TO_NUMBER(UTL_RAW.SUBSTR(r, i + 1, 1), '0X');
        y := FLOOR(x / 1024); v := v || map(y); x := x - y * 1024;
        y := FLOOR(x / 16); 	v := v || map(y); x := x - y * 16;
        x := x * 4; v := v || map(x);
        v := v || '=';
      END IF;
     
      RETURN v;
     
    END;
     
    FUNCTION DECODE_64(r IN RAW) RETURN VARCHAR2 IS
      i PLS_INTEGER;
      x PLS_INTEGER;
      y PLS_INTEGER;
      v VARCHAR2(32767);
    BEGIN
     
    -- For every 4 bytes, split them into 3 8-bit units and map them to
    -- the Ascii characters
      i := 1;
      WHILE ( i <= UTL_RAW.LENGTH(r) )
      LOOP
        x := unmap(TO_NUMBER(UTL_RAW.SUBSTR(r, i, 1), '0X')) * 262144
        			+ unmap(TO_NUMBER(UTL_RAW.SUBSTR(r, i + 1, 1), '0X')) * 4096
        			+ unmap(TO_NUMBER(UTL_RAW.SUBSTR(r, i + 2, 1), '0X')) * 64
              + unmap(TO_NUMBER(UTL_RAW.SUBSTR(r, i + 3, 1), '0X'));
        y := FLOOR(x / 65536); v := v || CHR(y); x := x - y * 65536;
        IF UTL_RAW.SUBSTR(r, i+2, 1) <> '3D'
        THEN
    	    y := FLOOR(x / 256); v := v || CHR(y); x := x - y * 256;
      	END IF;
        IF UTL_RAW.SUBSTR(r, i+3, 1) <> '3D'
        THEN
    	    v := v || CHR(x);
      	END IF;
        i := i + 4;	
    	END LOOP;
     
       RETURN v;
     
    END;
     
     
    BEGIN
    init_map;
    END;
    /
    Edit : Je pense qu'il faudrait changer le type d'entrée et de sortie de la fonction decode_64 que j'ai faite, mettre du varchar2 en entrée et du raw en sortie.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Erreur de compilation du noyau
    Par pierreg dans le forum Administration système
    Réponses: 12
    Dernier message: 31/01/2007, 18h53
  2. Problème de modules (noyau 2.6.6)
    Par Francois Trazzi dans le forum Administration système
    Réponses: 14
    Dernier message: 04/06/2004, 00h13
  3. Noyau
    Par wincroc dans le forum Administration système
    Réponses: 2
    Dernier message: 03/07/2003, 08h33
  4. Recompilation du noyau
    Par keikoz dans le forum Administration système
    Réponses: 7
    Dernier message: 17/02/2003, 23h54
  5. Primitive du noyau
    Par freud dans le forum Programmation d'OS
    Réponses: 5
    Dernier message: 25/11/2002, 03h17

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo