----------------------------------------------------------------------
create or replace function urlencode
----------------------------------------------------------------------
(p_str in varchar2) return varchar2 is
/* Declare */
l_tmp varchar2(6000);
l_hex varchar2(16) default ‘0123456789ABCDEF’;
l_num number;
l_bad varchar2(100) default ‘ >%}\~];?@&<#{|^[`/:=$+''"';
l_char char(1);
begin
if p_str is null
then
return null;
end if;
for i in 1 .. length(p_str) loop
l_char := substr(p_str, i, 1);
if instr(l_bad, l_char) > 0
then
l_num := ascii(l_char);
l_tmp := l_tmp || ‘%’ ||
substr(l_hex, mod(trunc (l_num / 16), 16) + 1, 1) ||
substr(l_hex, mod(l_num, 16) + 1, 1);
else
l_tmp := l_tmp || l_char;
end if;
end loop;
return l_tmp;
end urlencode;
/
----------------------------------------------------------------------
create or replace function urldecode
----------------------------------------------------------------------
(p_str in varchar2) return varchar2 is
/* Declare */
l_hex varchar2(16) := ‘0123456789ABCDEF’;
l_idx number := 0;
l_ret long := p_str;
begin
if p_str is null then
return p_str;
end if;
loop
l_idx := instr(l_ret, ‘%’, l_idx + 1);
exit when l_idx = 0;
l_ret := substr(l_ret, 1, l_idx - 1) ||
chr((instr(l_hex, substr(l_ret, l_idx + 1, 1)) - 1) * 16 +
instr(l_hex, substr(l_ret, l_idx + 2, 1)) - 1) ||
substr(l_ret, l_idx + 3);
end loop;
return l_ret;
end urldecode;
/
Test:
SQL> select urlencode(’&+=’) from dual;
URLENCODE(’&+=’)
——————————————————————————–
%26%2B%3D
SQL> select urldecode(’%26%2B%3D’) from dual;
URLDECODE(’%26%2B%3D’)
——————————————————————————–
Subscribe to:
Post Comments (Atom)

2 comments:
same code with caching (didn't test how big an input must be to have any effect)...
FUNCTION urlencode(p_str IN VARCHAR2) RETURN VARCHAR2 IS
l_tmp VARCHAR2(6000);
l_hex CONSTANT VARCHAR2(16) := '0123456789ABCDEF';
l_num number;
l_bad CONSTANT VARCHAR2(100) := ' >%}\~];?@&<#{|^[`/:=$+''"';
l_char CHAR(1);
TYPE cache_tab_typ IS TABLE OF VARCHAR2(3) INDEX BY PLS_INTEGER;
v_cache cache_tab_typ;
v_target BOOLEAN;
BEGIN
IF p_str IS NULL THEN
RETURN NULL;
END IF;
v_cache.DELETE;
FOR i IN 1 .. LENGTH(p_str) LOOP
l_char := SUBSTR(p_str, i, 1);
l_num := ASCII(l_char);
v_target := v_cache.EXISTS(l_num) OR INSTR(l_bad, l_char) > 0;
IF v_target THEN
IF NOT v_cache.EXISTS(l_num) THEN
v_cache(l_num) := '%'||SUBSTR(l_hex, MOD(TRUNC(l_num/16), 16) + 1, 1)
||SUBSTR(l_hex, MOD(l_num, 16) + 1, 1);
END IF;
l_tmp := l_tmp||v_cache(l_num);
ELSE
l_tmp := l_tmp || l_char;
END IF;
END LOOP;
RETURN l_tmp;
END urlencode;
FUNCTION urldecode(p_str IN VARCHAR2) RETURN VARCHAR2 IS
l_hex CONSTANT VARCHAR2(16) := '0123456789ABCDEF';
l_idx PLS_INTEGER := 0;
l_ret LONG := p_str;
TYPE cache_tab_typ IS TABLE OF VARCHAR2(1) INDEX BY VARCHAR2(2);
v_cache cache_tab_typ;
v_key VARCHAR2(2);
BEGIN
IF p_str IS NULL THEN
RETURN p_str;
END IF;
v_cache.DELETE;
LOOP
l_idx := INSTR(l_ret, '%', l_idx + 1);
EXIT WHEN l_idx = 0;
v_key := substr(l_ret, l_idx + 1, 2);
--DBMS_OUTPUT.PUT_LINE( l_idx||': '||v_key );
IF NOT v_cache.EXISTS(v_key) THEN
v_cache(v_key) := CHR((INSTR(l_hex, SUBSTR(v_key, 1, 1)) - 1) * 16
+ INSTR(l_hex, SUBSTR(v_key, 2, 1)) - 1);
END IF;
--DBMS_OUTPUT.PUT_LINE( ' '||v_cache(v_key) );
l_ret := SUBSTR(l_ret, 1, l_idx - 1) || v_cache(v_key)
|| SUBSTR(l_ret, l_idx + 3);
END LOOP;
RETURN l_ret;
END urldecode;
Nice work and useful,
Thank you very much
Post a Comment