jueves, 21 de mayo de 2015

Extraer contenido de contenedores OLE

Una funcionalidad muy útil en versiones de Forms 6i o anteriores, era la de almacenar archivos en contenedores OLE, para ello bastaba con tener un campo en el bloque asociado a un campo BLOB de la base de datos y ya era posible guardar en él archivos mediante la aplicaciones con soporte OLE2, por ejemplo WORD, EXCEL, PDF, ...

El problema es que desde Forms 9i esta funcionalidad ya no existe, por lo que hay que buscar alternativas, lo normal es a través de implementar la carga / descarga de archivos usando la librería WEBUTIL.

Aparte de tener que cambiar la implementación, el principal problema con el que me he encontrado ha sido la necesidad de migrar de un sistema a otro debido a que los archivos almacenados en un contenedor OLE tienen un envoltorio que hace imposible que se abran directamente, es necesario abrirlos a través de ese contenedor, por lo que había que hacerlo de forma manual uno a uno desde el programa.

La solución que he encontrado a este problema es mediante la aplicación 7zip para Windows que es capaz de separar el envoltorio del contenido (con la de Linux no funciona).


El PDF se encuentra en el archivo CONTENTS dentro de la carpeta "Tenant Object", como se puede observar, en este caso el envoltorio ocupa mucho más que el propio PDF. En algunos casos, puede llamarse "[1]Ole10Native", en ese caso hay que modificar el script que descomprime con 7zip.

IMPORTANTE: El código que voy a poner a continuación, debes usarlo bajo tú responsabilidad y después de haber hecho una copia de seguridad de los datos que vas a procesar, no me hago responsable de ninguna pérdida de datos por la utilización de este código.

Vamos a ver como extraer los archivos de un campo BLOB a un directorio de Oracle. Vamos a crear un directorio llamado BLOB_TEMP (en el propio servidor de base de datos) y lo mapeamos a una ruta:

CREATE DIRECTORY BLOB_TEMP as 'c:\temp\pdfs';
GRANT READ, WRITE ON DIRECTORY BLOB_TEMP TO USUARIO;

Exportamos a ese directorio el contenido del campo BLOB de la tabla

DECLARE
  CURSOR cur_pdfs IS
     SELECT i. archivo campo_blob, i.rowid || '.pdf.7z' nombre_archivo
       FROM tabla i
      WHERE DBMS_LOB.GETLENGTH(i.archivo) > 0
        AND DBMS_LOB.INSTR(i.archivo, HEXTORAW('25504446')) > 0;

  blob_length     INTEGER;
  out_file        UTL_FILE.file_type;
  v_buffer        RAW(32767);
  chunk_size      PLS_INTEGER;
  blob_position   PLS_INTEGER;
BEGIN
  FOR reg IN cur_pdfs LOOP
    blob_position := 1;
    chunk_size := 32767;
    blob_length := DBMS_LOB.getlength(reg.campo_blob);
    out_file := UTL_FILE.fopen('BLOB_TEMP', reg.nombre_archivo, 'wb', chunk_size);

    WHILE blob_position <= blob_length LOOP
      IF blob_position + chunk_size - 1 > blob_length THEN
        chunk_size := blob_length - blob_position + 1;
      END IF;

      DBMS_LOB.READ(reg.campo_blob, chunk_size, blob_position, v_buffer);
      UTL_FILE.put_raw(out_file, v_buffer, TRUE);
      blob_position := blob_position + chunk_size;
    END LOOP;

    UTL_FILE.fclose(out_file);
  END LOOP;
END;
/

Una vez tenemos los archivos, extraemos el contenido con un script, por ejemplo, le llamamos extraepdf.cmd con el siguiente contenido.

for %%f in (*.7z) do (
"C:\Program Files\7-Zip\7z.exe" e "%%f" "Tenant Object\CONTENTS"
rename CONTENTS %%f.pdf
del %%f
)?

Luego, los volvemos a cargar, sobreescribiendo el archivo en el mismo campo de la tabla.

DECLARE
  CURSOR cur_pdfs IS
     SELECT i.rowid, i.rowid || '.pdf.7z.pdf' nombre_archivo, i.archivo
       FROM tabla i
      WHERE DBMS_LOB.GETLENGTH(i.archivo) > 0
        AND DBMS_LOB.INSTR(i.archivo, HEXTORAW('25504446')) > 0;

  l_bfile       BFILE;
  v_resultado   VARCHAR2(30) := 'OK';
  v_archivo     BLOB;
BEGIN
  FOR reg IN cur_pdfs LOOP
    l_bfile := BFILENAME('BLOB_TEMP', reg.nombre_archivo);

    IF DBMS_LOB.fileexists(l_bfile) = 1 AND NVL(DBMS_LOB.getlength(l_bfile), 0) != 0 THEN
      DBMS_LOB.createtemporary(v_archivo, TRUE);
      DBMS_LOB.fileopen(l_bfile, DBMS_LOB.file_readonly);
      DBMS_LOB.loadfromfile(v_archivo, l_bfile, DBMS_LOB.getlength(l_bfile));
      DBMS_LOB.fileclose(l_bfile);
      
      UPDATE tabla i
         SET archivo = v_archivo
       WHERE rowid = reg.rowid;
       
      COMMIT;
      UTL_FILE.fremove('BLOB_TEMP', reg.nombre_archivo);
    END IF;
  END LOOP;
END;
/

domingo, 8 de febrero de 2015

Reports Builder 11g en Windows 64 bits

Por lo general, al intentar arranca Reports Builder en un Windows de 64 bits nos dará el siguiente error: "REP-50125: rwbuilder.conf:java.lang.NullPointerException"



Vamos a ver como solucionarlo suponiendo que el directorio base de Oracle es C:\Oracle (si fuese otro las rutas cambian).

Editar el archivo: C:\Oracle\Middleware\asinst_1\config\reports\bin\reports.bat

Borrar la línea: set TNS_ADMIN=%ORACLE_INSTANCE%\config

Editar el archivo: C:\Oracle\Middleware\Oracle_FRHome1\bin\rwbuilder.bat

Cambiar: $$Instance.directory$$ por: C:\Oracle\Middleware\asinst_1
Cambiar: $$Instance.oracle_home$$ por: C:\Oracle\Middleware\Oracle_FRHome1

Para arrancar el Report Builder ejecutaremos un archivo de comandos con código similar al siguiente: ReportsBuilderF11g.cmd. (Las rutas pueden variar según donde estén las plls o instalado Oracle):

SET CLASSPATH=C:\Oracle\Middleware\Oracle_FRHome1\forms\j2ee\frmsrv.jar;C:\Oracle\Middleware\Oracle_FRHome1\jlib\ldapjclnt11.jar;C:\Oracle\Middleware\Oracle_FRHome1\jlib\debugger.jar;C:\Oracle\Middleware\Oracle_FRHome1\jlib\ewt3.jar;C:\Oracle\Middleware\Oracle_FRHome1\jlib\share.jar;C:\Oracle\Middleware\Oracle_FRHome1\jlib\utj.jar;C:\Oracle\Middleware\Oracle_FRHome1\jlib\zrclient.jar;C:\Oracle\Middleware\Oracle_FRHome1\reports\jlib\rwrun.jar;C:\Oracle\Middleware\Oracle_FRHome1\forms\java\frmwebutil.jar;C:\Oracle\Middleware\Oracle_FRHome1/jlib/start_dejvm.jar;C:\Oracle\Middleware\Oracle_FRHome1\opmn\lib\optic.jar
SET PATH=C:\Oracle\Middleware\Oracle_FRHome1\bin;C:\Oracle\Middleware\Oracle_FRHome1\jdk\jre\bin\client;C:\Oracle\Middleware\Oracle_FRHome1\jdk\bin
SET REPORTS_PATH=Z:\plls
SET NLS_DATE_FORMAT=DD/MM/YYYY
SET NLS_NUMERIC_CHARACTERS=,.
SET UI_ICON=Z:\iconos
SET NLS_SORT=BINARY
SET TNS_ADMIN=C:\Oracle
SET NLS_LANG=SPANISH_SPAIN.UTF8
start rwbuilder.bat USERID=USUARIO/PASSWORD@CADENA_CONEXION

martes, 25 de marzo de 2014

Generación incorrecta de PDF en Reports 6 en Windows 7 y 8

Al generar archivos desde Reports 6 en PDF en sistemas operativos Windows 7 y Windows 8 está metiendo mal la etiqueta "CreatorDate", abre el paréntesis y sin meter la fecha no lo llega a cerrar. Esto produce que alguna versión de Adobe Reader y de otros visores de PDF no sean capaces de leer el archivo.


Ese mismo PDF generado con el mismo parche de Forms & Reports en un Windows 2003 lo genera correctamente:


Para solucionarlo podemos hacer que no intente meter la línea /CreatorDate modificando la librería RWLIB60.DLL. Para ello necesitaremos un editor Hexadecimal para poder editarla, yo utilizo "HxD - Editor Hexadecimal", que se puede descargar de su página web: http://www.mh-nexus.de.

Abrimos la librería y buscamos (Ctrol + F) el texto CreatorDate


Seleccionamos desde /CreatorDate hasta el punto que está antes de /Author, tal y como se muestra en la siguiente imagen:


Luego hay que ir a Edición -> Rellenar Selección



En la ventana que abre, dejamos 00 en Valores hexadecimales y pulsamos "Aceptar".


Grabamos la librería, y ahora el resultado de la generación con este cambio será el siguiente:




viernes, 17 de enero de 2014

Conexión a webs con Applets de Java sin MANIFEST.MF correcto

Ya ha llegado la actualización 1.7.0_45 de Java. Esta actualización bloquea por defecto todas las aplicaciones que se despliegan desde un navegador que no tengan las últimas directivas de seguridad definidas en el archivo MANIFEST.MF

Para salir del paso, es posible, en el equipo donde corre el navegador añadir excepciones a esa validación. Para ello (en Windows) vamos a Panel de Control -> Programas (Si tenemos activado "Ver por: Categoría) -> Java

En la pestaña "Seguridad" en la sección "Lista de excepciones de sitios" pulsamos sobre el botón "Editar lista de sitios" y añadimos el sitio en que confiamos de que no nos vaya a ejecutar nada peligroso en nuestro equipo.


He puesto como ejemplo "https://www.bbva.es", ya que a día de hoy para validarse con el DNI electrónico usa un applet Java que no tiene el MANIFEST.MF correcto, y lo peor de todo, cuando vas a validar una operación da un error de error de firma del archivo.

viernes, 15 de noviembre de 2013

Almacenar la contraseña de Weblogic de forma persistente

Por defecto, cada vez que se arranca Weblogic y los servidores manejados WLS_FORMS y WLS_REPORTS nos solicita la contraseña de weblogic:


La forma de guardar la contraseña en un archivo y evitar que la pida en cada arranque es muy simple: hay que crear un archivo con el nombre "boot.properties" en las siguientes carpetas:


  • $DOMAIN_HOME/servers/AdminServer/security
  • $DOMAIN_HOME/servers/WLS_FORMS/security
  • $DOMAIN_HOME/servers/WLS_REPORTS/security


El archivo tiene que contener únicamente dos líneas:

username=weblogic
password=

En el archivo metemos la contraseña en texto plano, pero en el primer arranque la encripta.

viernes, 18 de octubre de 2013

Problemas para Forms 11g en próximas actualizaciones de Java

Al actualizar a la última actualización de Java 7, el parche 45 (1.7.0_45), al mostrar la advertencia de seguridad sobre los JAR firmados acompaña el siguiente texto: "Esta aplicación estará bloqueada en una futura actualización de seguridad de Java porque el archivo MANIFEST de JAR no contiene el atributo de permisos. Póngase en contacto con el publicador para obtener más información".


¿Qué significa esto?, pues que a partir de ahora y cuando Oracle quiera, sacará una actualización de Java (no necesariamente en el próximo parche) que dejará a nuestros Forms KO.

Ya hace unos cuantos parches que en la consola de Java ya lo estaba advirtiendo al cargar los archivos, pero la mayoría hizo caso omiso a ello.

Los archivos JAR dentro de la carpeta META-INF tienen que tener el archivo MANIFEST.MF con las siguientes líneas (puede haber más):

Codebase: *
Permissions: all-permissions

¿Cómo solucionarlo?, en mi caso tengo 3 tipo de JARS, los propios de Oracle, JARS propios y JARS de terceros.

  • Los propios de Oracle (frmall.jar, frmgeneric_laf.jar, frmmain.jar, frmoracle_laf.jar, frmresources.jar, frmwebutil.jar): Para estos Oracle ha publicado un parche que incluye el MANIFEST correcto, el parche es el 16837591 que se puede bajar del Metalink. Si no tienes acceso al Metalink puedes hacer lo mismo que explico con JARS de terceros.
  • JARS Propios. Estos los voy a dividir en 2 grupos (los de iconos y los generados con JDeveloper).
    • Iconos: Creamos un archivo MANIFEST.TXT en cualquier ubicación de nuestro disco, por ejemplo, C:\Temp\MANIFEST.TXT con el siguiente contenido:
Manifest-Version: 1.0
Codebase: * 
Created-By: 1.6.0_35 (Sun Microsystems Inc.)
Permissions: all-permissions
      • Generar el archivo JAR con el siguiente comando (suponemos que los iconos están en C:\Temp\iconos): jar cvfm c:\temp\archivoiconos.jar c:\MANIFEST.TXT C:\temp\iconos\*.gif

    • Jars desplegados con JDeveloper. Creamos un archivo dentro del proyecto de JDeveloper de texto plano con el siguiente contenido (NOTA: Hay que dejar un retorno de carro al final para que al hacer el despliegue meta las 2 líneas):
Codebase: *
Permissions: all-permissions
        • Al configurar el despliegue del archivo JAR, marcamos la check "Include Manifest File (META-INF/MANIFEST.MF) he indicamos en "Additional Manifest Files to Merge into MANIFEST.MF" la ruta al archivo que hemos creado anteriormente.

  • JARS de Terceros: Lo que hice en este caso, es descomprimirlos, modificar el MANIFEST.MF, borrar la firma que estaba en la carpeta META-INF, volver a comprimirlos en formato ZIP y luego cambiar la extensión a ".jar". Luego los volví a firmar con mi certificado de firma de código.

Una vez tenemos los JAR con el MANIFEST correcto y perfectamente firmados, los volvemos a colocar en $ORACLE_HOME/forms/java y reiniciamos el servicio de WLS_FORMS:

$DOMAIN_HOME/bin/stopManagedWebLogic.sh WLS_FORMS
$DOMAIN_HOME/bin/startManagedWebLogic.sh WLS_FORMS&