Précédent   Forum des professionnels en informatique > Bases de données > Oracle > PL/SQL
PL/SQL Forum d'entraide sur le PL/SQL
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 17/01/2012, 06h46   #1
Rédacteur

 
Avatar de SheikYerbouti
 
Inscription : mai 2003
Messages : 6 530
Détails du profil
Informations forums :
Inscription : mai 2003
Messages : 6 530
Points : 6 460
Points : 6 460
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
__________________
Rédacteur Oracle (Oracle ACE)
Guide Oracle ,Guide PL/SQL, Guide Forms 9i/10g, Index de recherche
Je ne réponds pas aux questions techniques par MP
Blogs: Forms-PL/SQL-J2EE - Forms Java Beans
SheikYerbouti est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/01/2012, 11h23   #2
McM
Expert Confirmé Sénior
 
Inscription : juillet 2003
Messages : 3 440
Détails du profil
Informations forums :
Inscription : juillet 2003
Messages : 3 440
Points : 4 183
Points : 4 183
Tu peux pas le coder en pl ?
__________________
More Code : More Bugs. Less Code : Less Bugs
McM est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/01/2012, 11h46   #3
Rédacteur

 
Avatar de SheikYerbouti
 
Inscription : mai 2003
Messages : 6 530
Détails du profil
Informations forums :
Inscription : mai 2003
Messages : 6 530
Points : 6 460
Points : 6 460
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
__________________
Rédacteur Oracle (Oracle ACE)
Guide Oracle ,Guide PL/SQL, Guide Forms 9i/10g, Index de recherche
Je ne réponds pas aux questions techniques par MP
Blogs: Forms-PL/SQL-J2EE - Forms Java Beans
SheikYerbouti est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/01/2012, 11h48   #4
McM
Expert Confirmé Sénior
 
Inscription : juillet 2003
Messages : 3 440
Détails du profil
Informations forums :
Inscription : juillet 2003
Messages : 3 440
Points : 4 183
Points : 4 183
J'essaye de te coder ça
__________________
More Code : More Bugs. Less Code : Less Bugs
McM est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/01/2012, 12h03   #5
Rédacteur

 
Avatar de SheikYerbouti
 
Inscription : mai 2003
Messages : 6 530
Détails du profil
Informations forums :
Inscription : mai 2003
Messages : 6 530
Points : 6 460
Points : 6 460
Le but est de remplacer ceci:
Code :
UTL_RAW.CAST_TO_VARCHAR2(UTL_ENCODE.BASE64_ENCODE(LR$Raw))
et
Code :
rawData := utl_encode.BASE64_DECODE(utl_raw.CAST_TO_RAW(PC$Chunk));
__________________
Rédacteur Oracle (Oracle ACE)
Guide Oracle ,Guide PL/SQL, Guide Forms 9i/10g, Index de recherche
Je ne réponds pas aux questions techniques par MP
Blogs: Forms-PL/SQL-J2EE - Forms Java Beans
SheikYerbouti est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/01/2012, 12h29   #6
McM
Expert Confirmé Sénior
 
Inscription : juillet 2003
Messages : 3 440
Détails du profil
Informations forums :
Inscription : juillet 2003
Messages : 3 440
Points : 4 183
Points : 4 183
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 :
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;
__________________
More Code : More Bugs. Less Code : Less Bugs
McM est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/01/2012, 13h34   #7
Rédacteur

 
Avatar de SheikYerbouti
 
Inscription : mai 2003
Messages : 6 530
Détails du profil
Informations forums :
Inscription : mai 2003
Messages : 6 530
Points : 6 460
Points : 6 460
Super
Monsieur est un prince
__________________
Rédacteur Oracle (Oracle ACE)
Guide Oracle ,Guide PL/SQL, Guide Forms 9i/10g, Index de recherche
Je ne réponds pas aux questions techniques par MP
Blogs: Forms-PL/SQL-J2EE - Forms Java Beans
SheikYerbouti est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/01/2012, 14h26   #8
Rédacteur

 
Avatar de SheikYerbouti
 
Inscription : mai 2003
Messages : 6 530
Détails du profil
Informations forums :
Inscription : mai 2003
Messages : 6 530
Points : 6 460
Points : 6 460
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 :
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...
__________________
Rédacteur Oracle (Oracle ACE)
Guide Oracle ,Guide PL/SQL, Guide Forms 9i/10g, Index de recherche
Je ne réponds pas aux questions techniques par MP
Blogs: Forms-PL/SQL-J2EE - Forms Java Beans
SheikYerbouti est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/01/2012, 14h35   #9
Rédacteur

 
Avatar de SheikYerbouti
 
Inscription : mai 2003
Messages : 6 530
Détails du profil
Informations forums :
Inscription : mai 2003
Messages : 6 530
Points : 6 460
Points : 6 460
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
__________________
Rédacteur Oracle (Oracle ACE)
Guide Oracle ,Guide PL/SQL, Guide Forms 9i/10g, Index de recherche
Je ne réponds pas aux questions techniques par MP
Blogs: Forms-PL/SQL-J2EE - Forms Java Beans
SheikYerbouti est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/01/2012, 15h14   #10
McM
Expert Confirmé Sénior
 
Inscription : juillet 2003
Messages : 3 440
Détails du profil
Informations forums :
Inscription : juillet 2003
Messages : 3 440
Points : 4 183
Points : 4 183
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 :
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 :
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.
__________________
More Code : More Bugs. Less Code : Less Bugs
McM est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/01/2012, 15h45   #11
Rédacteur

 
Avatar de SheikYerbouti
 
Inscription : mai 2003
Messages : 6 530
Détails du profil
Informations forums :
Inscription : mai 2003
Messages : 6 530
Points : 6 460
Points : 6 460
Merci beaucoup pour le boulot.
Toutefois, cela semble ne pas fonctionner avec les contenus binaires stockés dans les BLOB
__________________
Rédacteur Oracle (Oracle ACE)
Guide Oracle ,Guide PL/SQL, Guide Forms 9i/10g, Index de recherche
Je ne réponds pas aux questions techniques par MP
Blogs: Forms-PL/SQL-J2EE - Forms Java Beans
SheikYerbouti est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/01/2012, 16h01   #12
McM
Expert Confirmé Sénior
 
Inscription : juillet 2003
Messages : 3 440
Détails du profil
Informations forums :
Inscription : juillet 2003
Messages : 3 440
Points : 4 183
Points : 4 183
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 :
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 :
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 ?
__________________
More Code : More Bugs. Less Code : Less Bugs
McM est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 17/01/2012, 16h14   #13
Rédacteur

 
Avatar de SheikYerbouti
 
Inscription : mai 2003
Messages : 6 530
Détails du profil
Informations forums :
Inscription : mai 2003
Messages : 6 530
Points : 6 460
Points : 6 460
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.
__________________
Rédacteur Oracle (Oracle ACE)
Guide Oracle ,Guide PL/SQL, Guide Forms 9i/10g, Index de recherche
Je ne réponds pas aux questions techniques par MP
Blogs: Forms-PL/SQL-J2EE - Forms Java Beans
SheikYerbouti est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/01/2012, 16h27   #14
Rédacteur

 
Avatar de SheikYerbouti
 
Inscription : mai 2003
Messages : 6 530
Détails du profil
Informations forums :
Inscription : mai 2003
Messages : 6 530
Points : 6 460
Points : 6 460
pour info, il faut 9 secondes pour une image de 24Ko
__________________
Rédacteur Oracle (Oracle ACE)
Guide Oracle ,Guide PL/SQL, Guide Forms 9i/10g, Index de recherche
Je ne réponds pas aux questions techniques par MP
Blogs: Forms-PL/SQL-J2EE - Forms Java Beans
SheikYerbouti est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/01/2012, 17h15   #15
McM
Expert Confirmé Sénior
 
Inscription : juillet 2003
Messages : 3 440
Détails du profil
Informations forums :
Inscription : juillet 2003
Messages : 3 440
Points : 4 183
Points : 4 183
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)
Citation:
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 :
1
2
3
BLOB Taille :10976898
UTL_ENCODE :64 /100s
PLSQL :53284 /100s
Bon, je vais voir où ça rame.
__________________
More Code : More Bugs. Less Code : Less Bugs
McM est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/01/2012, 13h27   #16
Expert Confirmé Sénior


 
Avatar de laurentschneider
 
Homme Laurent Schneider
Administrateur de base de données
Inscription : décembre 2005
Messages : 2 927
Détails du profil
Informations personnelles :
Nom : Homme Laurent Schneider
Localisation : Suisse

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

Informations forums :
Inscription : décembre 2005
Messages : 2 927
Points : 4 549
Points : 4 549
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 :
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 :
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 :
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 ...
__________________
Mon blog : laurentschneider.com
Mon livre : Advanced Oracle SQL Programming
laurentschneider est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 18/01/2012, 13h41   #17
Rédacteur

 
Avatar de SheikYerbouti
 
Inscription : mai 2003
Messages : 6 530
Détails du profil
Informations forums :
Inscription : mai 2003
Messages : 6 530
Points : 6 460
Points : 6 460
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 ?
__________________
Rédacteur Oracle (Oracle ACE)
Guide Oracle ,Guide PL/SQL, Guide Forms 9i/10g, Index de recherche
Je ne réponds pas aux questions techniques par MP
Blogs: Forms-PL/SQL-J2EE - Forms Java Beans
SheikYerbouti est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/01/2012, 14h13   #18
Expert Confirmé Sénior


 
Avatar de laurentschneider
 
Homme Laurent Schneider
Administrateur de base de données
Inscription : décembre 2005
Messages : 2 927
Détails du profil
Informations personnelles :
Nom : Homme Laurent Schneider
Localisation : Suisse

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

Informations forums :
Inscription : décembre 2005
Messages : 2 927
Points : 4 549
Points : 4 549
tu peux t'aider d'une table, style

Code :
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
__________________
Mon blog : laurentschneider.com
Mon livre : Advanced Oracle SQL Programming
laurentschneider est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/01/2012, 15h07   #19
Rédacteur

 
Avatar de SheikYerbouti
 
Inscription : mai 2003
Messages : 6 530
Détails du profil
Informations forums :
Inscription : mai 2003
Messages : 6 530
Points : 6 460
Points : 6 460
Citation:
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
__________________
Rédacteur Oracle (Oracle ACE)
Guide Oracle ,Guide PL/SQL, Guide Forms 9i/10g, Index de recherche
Je ne réponds pas aux questions techniques par MP
Blogs: Forms-PL/SQL-J2EE - Forms Java Beans
SheikYerbouti est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/01/2012, 11h38   #20
McM
Expert Confirmé Sénior
 
Inscription : juillet 2003
Messages : 3 440
Détails du profil
Informations forums :
Inscription : juillet 2003
Messages : 3 440
Points : 4 183
Points : 4 183
Suite à la procédure de codage que tu m'as envoyé, j'ai fait le decodage.

Code :
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.
__________________
More Code : More Bugs. Less Code : Less Bugs
McM est déconnecté   Envoyer un message privé Réponse avec citation 10
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 21h27.


 
 
 
 
Partenaires

Hébergement Web