Wednesday, January 06, 2010

Special characters - part V

The end of the War of the Worlds?


Well... that remains to be seen. I predict the conclusion will be that there's always a possibility unwanted, or "wrong" characters get displayed. But when you start to understand why, my mission is accomplished. By the way - I found an excellent explanation on HTML right here

Setup


For the setup, I used the "we8" database instance (see this entry) I added the 10.1.3.3 Oracle Http Server(based on Apache 2), of which Linux version used to be downloadable off the database download page. There was a bit of work to be done to get things running. The official documentation states:
For Apache 2.0 startup to succeed, link the current libdb.so version to /usr/lib/libdb-3.3.so.

For example, if the current shared library is in /usr/lib is libdb-4.1.so, then run the following command:

cd /usr/lib
ln -s /usr/lib/libdb-4.1.so libdb-3.3.so

Database Access Descriptor (DAD)


My DAD looks simple enough:

# ============================================================================
# mod_plsql DAD Configuration File
# ============================================================================
# 1. Please refer to dads.README for a description of this file
# ============================================================================
<Location /pls/myapp>
SetHandler pls_handler
Order deny,allow
Allow from all
AllowOverride None
PlsqlDatabaseConnectString cs-frank03:1521:we8
PlsqlAuthenticationMode Basic
PlsqlErrorStyle ModplsqlStyle
PlsqlNLSLanguage American_America.UTF8
PlsqlDefaultPage scott.home
</Location>

I added my own html wrapper, and created the following procedure check if the DAD was configured correctly:

create or replace procedure home as
begin
htp.p(format.pagestart(
p_title=>'DAD Check page',
p_text=>'DAD Checked out successfully!')
);
end;
/

This results in a "DAD Checked out successfully!" message, signifying the http server works, the connection to the database works, and my wrapper works.

Webcode


Knowing all the basics are working, I created the following package to display the contents of the blah table:

create or replace package demochar as
procedure showblah;
prodedure editblah;
end;
/
create or replace package body demochar
as
procedure showblah
is
begin
htp.p(format.pagestart(p_title => 'Demonstration of Special Characters on the Web',
p_text => 'Welcome - contents of table is')
);
htp.p('</div>');
htp.p('<div class="content">');
htp.p('<table summary="blah" border="1" align="center">');
htp.p('<tr><th>Character<th>Hex value');
for i in (select b.a, dump(b.a,16) as d
from blah b)
loop
htp.p('<tr>');
htp.p('<td>' || i.a);
htp.p('<td>' || i.d);
end loop;
htp.p('</table>');
htp.p(format.pageend);
end showblah;
procedure editblah is
begin
null;
end editblah;
begin
DEBUG.setlevel(2);
DEBUG.setdestination(DEBUG.destweb);
DBMS_RANDOM.initialize(TO_NUMBER(TO_CHAR(SYSDATE, 'miss')));
end;
/

Data

The blah table is there again, and it's contents is restored:

SQL> col dump(a,16) format a20
SQL> select a, dump(a,16) from blah;

A DUMP(A,16)
-------------------- --------------------
€ Typ=1 Len=1: 80
Æ Typ=1 Len=1: c6
ß Typ=1 Len=1: df

Results and observations


First of all, the UTF8, used in the DAD is standard APEX, to name one. But is it the correct one to use?
Displayed on the web, the page looks like this (Linux/Firefox):

Om MS Windows (XP) with Firefox, as well as using Konqueror on Linux, the dreaded diamond is displayed:


So - the fact that our character does not display in a web browser is depending on the browser and on what is used in the DAD. As we change the DAD characterset to be used to
PlsqlNLSLanguage American_America.WE8ISO8859P15
the page is displayed correctly in Konquerer, incorrect in Firefox on Linux, but that can be corrected by forcing the page to use the 1252 codepage (!). Firefox under MS Windows reacts the same: auto detection, Universal and ISO-8859-15 all do not work, changing the Character Encoding to West European(Windows 1252) displays the page correctly. Internet Explorer V7.0.5730.13: same story: auto detection does not work.

Now - the question arises: is this due to the coding of the page? Character sets are encoded in the header. The last screenshot is the same on all browsers/systems, and is not due to encoding settings, but purely Oracle - the DAD characterset is now WE8ISO8859P1, which indeed does not know how to map the € sign. That results in an upside-down question mark.


Windows...
After inserting the euro character in the MS Windows encoding (0xa4, or 164), all browsers manage to show correct values (that is the € sign) for that when using UTF8 in the DAD, as well as browser Character Encoding. Using WE9ISO8859P15 in the DAD, the pages will display one € correct, based on Character Encoding in the Browser:
- Western ISO-8859-15 will display € for 0xa4
- Western (Windows-1252) will display € for 0x80

Only Konqueror mangages to display the € symbol for both codes, when the DAD uses WE8ISO8859P15, and the page is explicitly coded in ISO-8859-15 (using the META element Content-type in the header):


Conclusion


There's alwyas at least one way to screw up. If it's not the database, that was fed the wrong code points, it's the browser, that does a lousy job. Konqueror does an admirable job, though. Internet Explorer as well as Firefox have the possibility to switch Character Coding, which may result in correct display of the glyphs.
UTF-8 is not always the best PlsqlNLSLanguage!

Friday, December 18, 2009

APEX Notes

If you want to access a procedure without going through the APEX security, alter wwv_flow_epg_include_mod_local to include your procedure.
I had a simple procedure, that lists all applications, called apex_apps:

CREATE OR REPLACE PROCEDURE apex_030200.apex_apps
AS
BEGIN
FOR i IN (SELECT TRIM(TO_CHAR (display_id)) ID, NAME
FROM apex_030200.wwv_flows
WHERE display_id NOT BETWEEN 4000 AND 5000
ORDER BY NAME)
LOOP
HTP.p ('<li><a href="f?p=' || i.ID || '">' || i.NAME || '</a></li>');
END LOOP;
END;


However, calling this resulted in:
[Fri Dec 18 15:57:12 2009] [error] [client x.x.x.x.] 
mod_plsql: /apex/apex_apps HTTP-403
It is forbidden to call this procedure directly from the browser!

After changing wwv_flow_epg_include_mod_local to

CREATE OR REPLACE function APEX_030200.wwv_flow_epg_include_mod_local(
procedure_name in varchar2)
return boolean
is
begin
-- return false; -- remove this statement when you modify this function
--
-- Administrator note: the procedure_name input parameter may be in the format:
--
-- procedure
-- schema.procedure
-- package.procedure
-- schema.package.procedure
--
-- If the expected input parameter is a procedure name only, the IN list code shown below
-- can be modified to itemize the expected procedure names. Otherwise you must parse the
-- procedure_name parameter and replace the simple code below with code that will evaluate
-- all of the cases listed above.
--
if upper(procedure_name) in (
'APEX_APPS') then
return TRUE;
else
return FALSE;
end if;
end wwv_flow_epg_include_mod_local;

everything works as designed.

Monday, December 14, 2009

My first program

Entry # 100 - celebration? Anyway, ran into probably my first program ever. Machine code, for an MC6800 (6802, actually). Dates back to 1978 or 1979:

inadd: CLRB ; clear count
CLR,X
PUSH B ; count on stack
CLR 1,X
inadd3: BSR INHEX
BMI inadd1
LDB#4
inadd2: ASL 1,X
ROL,X
DEC B
BNE inadd2
PSHS A
ORA 1,X
STA 1,X
PULS A
INC,B ; count
LDB,S
CMPB#S
BNE inadd3
inadd1: LDB,S+ ; b=count0 + #hex counts
RTS

INHEX = INCHNP

It's a counter, that should be able to count over 256, if I recall correctly. Quite complicated when you only have 8 bits. The code may not even be correct, as pencil tends to fade, and recycled paper becomes yellowish brown. Not much contrast there.
Addition: I could try it of course, as I still own a Motorola MEK6800D2 kit...

Friday, November 13, 2009

Friday, the 13th.

Could someone persuade Oracle to reinstate the good old Metalink, please?!
Yesterday, I got just "An error has occurred. Please try again later" the whole day. And I was not the only one.
Today it worked for about an hour for me (between 09:00 and 10:00 GMT+1), then it started with http-501 errors, and now this:


Update: My favourites are gone! Years of careful reading, searching and safekeeping: gone! According to the Well Known Problems I should NOT have logged on before Nov, 9th, because the updates were pending. If you did, you favourites are regarded as up-to-date, and will not be migrated. According to metaklunk2, I should have logged on. Shouldn't. Should. Sigh.

So it's like my own fault?!? Right. Don't think so. Unhappy customer here, Oracle.

Go, google, go!

Go - a new programming language. Let's hope it will not be the same disaster as Java became. Google should be large enough to withstand Microsoft. Are we waiting for Yet Another Programming Language? Only the future will tell. I see annoying things like 'garbage collection', which leads me to believe it will be just a "lazy" a language as Java.
And the supposedly simple printf is beyond comprehension. Print would be simple. Printf has too much letters.

Tuesday, November 10, 2009

Administration in Run-Time Only APEX

Simple, but you have to know...
connect system
alter session set current_schema = FLOWS_030100;

begin
apex_instance_admin.set_parameter('PRINT_BIB_LICENSED','ADVANCED');
apex_instance_admin.set_parameter('PRINT_SVR_HOST','tobi01.home.local');
apex_instance_admin.set_parameter('PRINT_SVR_PORT','8123');
apex_instance_admin.set_parameter('PRINT_SVR_SCRIPT','/xmlpserver/convert');
apex_instance_admin.set_parameter('PRINT_SVR_PROTOCOL','http');
end;
/

The doc states you have to have a session as sysdba, but system works for this version, too.

Friday, October 23, 2009

ORA-24062 ( Subscriber table inconsistent with queue table)

Surprisingly little search results in either google, the oracle fora, or metalink for this error. Ran into this today, and could drop an recreate the queues:
SQL> BEGIN
2 SYS.DBMS_AQADM.STOP_QUEUE(QUEUE_NAME =>'TAB_OWNER.TB_BTR_Q_OPDR');
3 SYS.DBMS_AQADM.DROP_QUEUE(QUEUE_NAME =>'TAB_OWNER.TB_BTR_Q_OPDR');
4 END;
5 /
BEGIN
*
ERROR at line 1:
ORA-24062: Subscriber table TAB_OWNER.AQ$_TB_BTR_Q_TBL_S inconsistent with
queue table TAB_OWNER.TB_BTR_Q_TBL
ORA-06512: at "SYS.DBMS_AQADM_SYS", line 4932
ORA-06512: at "SYS.DBMS_AQADM", line 240
ORA-06512: at line 2

The solution is drastic: for each error, reporting the table, force a drop of that table:
SQL> exec SYS.DBMS_AQADM.DROP_QUEUE_TABLE (
QUEUE_table => 'TAB_OWNER.TB_BTR_Q_TBL',
force=>TRUE);

PL/SQL procedure successfully completed.

After that, recreate the queues and queue tables.