30 diciembre 2015

Uso del cliente JavaScript (jsClient) con PHP

Toda la documentación, ficheros referenciados y la librería de ejemplo indicados en éste artículo, podrá descargarse desde la web de Aula Omnis, archivo denominado “DynamicWebPages.zip”. Una página HTML de jsClient típica, contiene algo como lo siguiente:

≤html≥
≤head≥
≤title≥Studio 5.2 Test≤/title≥
≤meta http-equiv="Content-Type" content="text/html; charset=utf-8"≥

≤!-- This makes mobile device support work --≥
≤meta name="viewport" content="width=device-width"≥

 ≤!-- The style sheets must be present in the directory /css/ --≥
≤link type="text/css" href="/css/omn_dlg.css" rel="stylesheet" media="print,screen" /≥
≤link type="text/css" href="/css/omn_menu.css" rel="stylesheet" media="print, screen" /≥
≤link type="text/css" href="/css/smoothness/jquery-ui-1.8.15.custom.css" rel="stylesheet" /≥
≤link type="text/css" href="/css/slick.grid.css" rel="stylesheet" /≥
≤link type="text/css" href="/css/slick.columnpicker.css" rel="stylesheet"/≥
≤link type="text/css" href="/css/slick.pager.css" rel="stylesheet" /≥

≤!-- Must occur after other stylesheets e.g. jquery-ui 1.8.15.custom.css, as it overrides values --≥
≤link type="text/css" href="/css/omnis.css" rel="stylesheet"/≥

≤!-- Omnis Studio JavaScript client scripts, must be present in the directory /scripts/ --≥
≤script type="text/javascript" src="/scripts/omjsclnt.js"≥≤/script≥
≤script type="text/javascript" src="/scripts/omjqclnt.js"≥≤/script≥
≤/head≥

≤body onload="jOmnis.onLoad()" onunload="jOmnis.onUnload()" style="margin:0;"≥
≤h1≥Test JavaScript Client Studio 5.2≤/h1≥
≤div id="omnisobject1" WebServerUrl="http://192.168.0.4/omnis_apache" OmnisServerAndPort="192.168.0.8:5914" OmnisLibrary="ScriptClient52_Test" OmnisClass="rfTest" param1="A1" param2="B1" param3="C1" param4="D1"≥≤/div≥
≤/body≥
≤/html≥


Si queremos hacer lo mismo desde PHP, modificaríamos la página para obtener algo como lo indicado a continuación. Para el ejemplo localizado en Aula Omnis, se hace uso de un fichero de configuración denominado “webclient.ini”, para componer la pagina “webclient.php”

≤html≥
≤head≥
≤title≥Studio 5.2 Test≤/title≥
≤meta http-equiv="Content-Type" content="text/html; charset=utf-8"≥

≤?php
$phplib = dirname(__FILE     ) . '/../phpsub'
set_include_path(get_include_path() . PATH_SEPARATOR . $phplib); require_once('OmnisWebClass.php');
$x = new OmnisWebClass('ScriptClient52_Test.ini', 'rfTest');
$params = array ("A1", "B1", "C1", "D1");
$x->set_additional_params($params);
$x->display_header_body_omnis_js('/css','/scripts','margin:0;');
?≥

≤h1≥Test JavaScript Client Studio 5.2≤/h1≥

≤?php
$x->display_client_omnis_js();
?≥

≤/body≥
≤/html≥


Por supuesto existen muchas otras opciones y parámetros que pueden usarse a la hora de crear el modelo PHP, el ejemplo que hallará en Aula Omnis “OmnisWebClass.php” constituye una buena muestra de ello.

Una reconfiguración mas cómoda


Cómo ya hemos mencionado, para nuestro ejemplo hacemos uso del fichero de configuración denominado “webclient.ini”, así, si (por ejemplo) queremos modificar el ancho “width” del “remote form”, sólo tendremos que cambiar el parámetro adecuado en éste archivo. Permitiendo además su correcta construcción dependiendo del navegador en uso: Internet Explorer, Netscape, Firefox, etc.

Del mismo modo, cuando sea el caso que estemos realizando pruebas con la versión Omnis para desarrollo, en las que se suele usar nuestro mismo PC. Podemos comentar la línea “OmnisServer = XXX”, ya que si no se encuentra en el archivo “.ini”, una dirección IP, PHP usará la dirección del cliente

Los parámetros “OmnisXXX “del archivo “.ini”, tales como el nombre de la librería o el de la clase remota, son ajustados después de los parámetros “cgi”. Por lo tanto, si se introduce la URL:

http://192.168.0.2/test/webclient.php?lib=TEST&class=rfTest_2&width=200

El servidor PHP compondrá una página web con éstos parámetros Omnis, de modo que el “remote form” “rfTest2” sea mostrado con una anchura de 200 píxeles. Todos los parámetros no presentes en la URL serán tomados del archivo “.ini”. Todo esto podrá encontrarlo perfectamente documentado dentro del propio archivo “OmnisWebClass.php”.

Parámetros HTTP


Al analizarse la petición HTTP, PHP puede recuperar otros parámetros de la cabecera HTTP, como (por ejemplo) el navegador que está usando el cliente. Esto también podría pasarse como parámetro adicional al “remote form” Omnis. Para ello sería necesario añadir a la página HTML el siguiente código:

; para Internet-Explorer
≤paramname = "Param1" value="myParameter = myValue"≥

; para Netscape y otros
Param1 = "myParameter=myValue"


Para incluir el uso de parámetros en el caso de la clase “OmnisWebClass.php”. Después de crearse la instancias del objeto PHP, e inmediatamente antes de la línea “$x-≥display_plugin()”; será necesario crear una matriz y llenarla con la información que se pasará a la instancia:

$params = array ();
$params['myParam'] = 'myValue';
$params['Browser']=
$_SERVER['HTTP_USER_AGENT'];
// insert here further parameters, see below
$X-≥set_additional_params($params);


Si el acceso a la página web está protegido con “htaccess”, podremos incluso obtener el nombre de usuario y su contraseña, para pasársela como parámetros a Omnis. El código PHP necesario es el siguiente:

if (isset($_SERVER['REMOTE_USER']))
$params['User1'] = $_SERVER['REMOTE_USER'];
if (isset($_SERVER['PHP_AUTH_USER']))
$params['User2'] = $_SERVER['PHP_AUTH_USER'];
if (isset($_SERVER['PHP_AUTH_PW']))
$params['Password'] = $_SERVER['PHP_AUTH_PW'];


Pero debemos tener en cuenta que, (para que esto funcione) el servidor PHP, deberá permitir ciertas restricciones de seguridad, consulte las “safe mode restrictions”.

Reconocimiento del servicio “Off-Line”


Un “Omnis App Server” suele ser muy estable, pero aún así es necesario hacer algo de mantenimiento de vez en cuando. De modo que puede ser inevitable que debido a que el servidor esté en modo “off-line” y le llegue una solicitud de “remote form” desde un navegador, el navegador se congela durante varios minutos, terminando por ofrecer como respuesta "'Error reading the response from the WEB server”.

Pero ésto se puede ser evitado fácilmente, mediante el uso de la clase “OmnisWebClass.php” y añadiendo algunas enmiendas a la librería Omnis. En este caso, el “Omnis App Server” deberá poseer permisos de escritura sobre el sistema de archivos del servidor web. Además, deberán rebajarse algunas de las normas de seguridad impuestas en PHP. De éste modo, el “Omnis App Server” podría, (inmediatamente después de abrir la librería) crear un archivo, (por ejemplo, con el nombre “Semaphore_WEBCLIENT.txt”) bajo el mismo directorio donde se encuentra “webclient.php”, el cual sería eliminado tras cerrarse la librería.

La idea es, que la instancia de “OmnisWebClass.php” pueda comprobar la existencia o no, de este archivo. Si no existe, en lugar de mostrarse el código de error, mostrar algo como “≤h3≥Omnis App. Server, cumple tareas de mantenimiento≤/h3≥”. El texto exacto es configurable. Para implementar este comportamiento, tan sólo sería necesario ñadir una línea más al archivo “webclient.php” informando a la instancia sobre el nombre del archivo a crear, del modo siguiente:

$x-≥set_semaphore('Semaphore_WEBCLIENT.txt');

23 diciembre 2015

Programación asíncrona con Omnis

Existen dos enfoques básicos a la hora de programar determinadas funciones o métodos, nos referimos a la programación “sincrónica” y “asincrónica”. Con programación “sincrónica”, la ejecución de cada función o método deberá completarse antes de iniciarse el siguiente. Este es el comportamiento predeterminado en Omnis. La desventaja de este modelo es que el proceso puede quedar congelado por largo tiempo debido a la esperar por una acción del usuario o de la ocurrencia de un evento a fin de poder ejecutar otras tareas. Una solución a esto la encontramos bajo el modelo de programación “asíncrona”. En este caso, una función o método es ejecutado en un hilo separado, siendo posible el procesado en paralelo de otras funciones, cada una en su propio hilo. Sin duda (dependiendo del tipo de tareas a realizar) éste método es más rápido y eficiente, ya que la ejecución de un método nunca se queda parado a la espera de un suceso.

Imagine una situación en la que una aplicación necesita realizar una importación de datos, pero sin que eso le impida al mismo tiempo llevar a cabo alguna otra función. Bajo el modelo “sincrónico”, tendría que completarse primero la importación de datos, lo cual dejaría al programa bloqueado, mientras que en modo “asíncrono” la importación de datos podría ejecutarse en segundo plano, si impedir la ejecución de cualquier otro código.

El siguiente ejemplo hace uso del componente “Web Services”. Tomemos un ejemplo sencillo: en un bucle vamos incrementado el valor de una variable, mientras que, al mismo tiempo, se le presenta un “OK message” al usuario indicándole que existe un proceso ejecutándose en segundo plano.

En primer lugar, añadiremos a nuestra librería una “remote task” de nombre “RTest”, sobre la que crearemos el método denominado “$backgroundMethod()”. Pulsamos botón-derecho sobre el método y lo marcamos como “Web Service Method static”, tal y como mostramos en la siguiente imagen.


A continuación, añadiremos al método el siguiente código:

For contador from 1 to 1000000 step 1
  Calculate contador2 as contador+1
End For
OK message {¡Proceso en segundo plano finalizado!}

Ahora crearemos una ventana con un botón, al cual añadir en su método “$event()” el siguiente código:

Start server
Do async method rTest/$backgroundMethod
OK message {¡Método contador ejecutándose en segundo plano!}

Para probarlo, abra la ventana y haga clic sobre el botón. Primero aparecerá el “OK message” indicando que se está ejecutando el método. Aunque pulse “Aceptar”, el proceso seguirá su curso, pero a su conclusión se le mostrará otro “OK message” indicando su finalización.

Cuando esté ejecutando métodos en modo “asíncrono”, deberá asegurarse de que se está programando en un entorno "seguro para subprocesos", es decir, asegurarse de no utilizar variables globales o comandos que puedan modificar indicadores globales. Los resultados podrían resultar los no esperados, si utilizamos comandos que (por ejemplo) cambien el valor de #F. Para volver al modo de ejecución “sincrónica” (el modo por defecto), deberemos usar el comando “Stop server”.

19 diciembre 2015

Cómo verificar y/o reparar los permisos del disco en OS X Capitán

Abra la aplicación Terminal (se encuentra en /Aplicaciones/Utilidades/) y use el comando siguiente:

sudo /usr/libexec/repair_packages --verify --standard-pkgs /

Si desea comprobar los permisos de una unidad diferente, especifique el volumen correspondiente en lugar de "/".  El comando se ejecutará, mostrando las diferencias que se encuentre, del siguiente modo:

Permissions differ on "usr/libexec/cups/cgi-bin", should be drwxr-xr-x , they are dr-xr-xr-x .
Permissions differ on "usr/libexec/cups/daemon", should be drwxr-xr-x , they are dr-xr-xr-x .
Permissions differ on "usr/libexec/cups/driver", should be drwxr-xr-x , they are dr-xr-xr-x .
Permissions differ on "usr/libexec/cups/monitor", should be drwxr-xr-x , they are dr-xr-xr-x .


Si se han encontrado permisos que difieren y le gustaría para repararlos, simplemente deberemos sustituir la bandera -verify por -repair, del modo siguiente:

sudo /usr/libexec/repair_packages --repair --standard-pkgs --volume /





16 diciembre 2015

Acceso directo HTTP con Omnis

La técnica Omnis denominada “Cliente-Ligero” o “Ultra-thin” nos permite invocar una tarea remota o “remote task” desde un formulario HTML, sin necesidad de utilizar el cliente JavaScript o el también llamado “jsClient”. En éstos casos Omnis crea una instancia para la tarea remota particular, he invoca a su método “$construct()”. El valor de retorno, será texto HTML standard.

La invocación directa http, deberá seguir la siguiente estructura:

http://≤Servidor≥:≤Puerto≥/Cliente-ligero

≤Servidor≥ es el nombre de dominio o dirección IP del equipo en el que se esté ejecutando Omnis Studio. La dirección 127.0.0.1, será apropiada si se trata de nuestra propia máquina.

≤Puerto≥ es el número de puerto previamente fijado sobre la propiedad “$ServerPort” de Omnis Studio; de forma predeterminada es el 5912, pero puede cambiarse por cualquier otro entre 1 y 32767. La propiedad “$ServerPort” forma parte del grupo “$root.$prefs”.

Para probar esto, puede optar por descargarse la librería denominada “DirectHTTP”, la cual está disponible para su descarga gratuita desde la web de Aula Omnis, o bien créela una con ese mismo nombre y después añádale una “remote task” con el nombre “rtDirectHTTP” e inserte en su método “$construct()” el código siguiente:

; Sobre el $construct()
; Cree también la siguientes variables
; Cómo parámetro: pParams (Row)
; Como locales: fullhtml (Char 100000000) y html (Char 100000000)

Begin text block
  Text: ≤html≥ (Carriage return,Linefeed)
  Text: ≤body bgcolor="FFFFFF"≥ (Carriage return,Linefeed)
  Text: ≤title≥Hello [pParams.User] ≤/title≥ (Carriage return,Linefeed)
  Text: ≤H1≥Hello [pParams.User] ≤/H1≥ (Carriage return,Linefeed)
  Text: ≤a href="javascript:history.go(-1);"≥Go back≤/a≥ (Carriage return,Linefeed)
  Text: ≤/BODY≥ (Carriage return,Linefeed)
  Text: ≤/html≥ (Carriage return,Linefeed)
End text block
Get text block html

Calculate fullhtml as con('content-type: text/html',chr(13,10),'content-length:',len(html),chr(13,10,13,10),html)
Quit method fullhtml


La “remote task” es invocada desde dentro del formulario HTML del modo siguiente:

≤html≥
  ≤form action="http://127.0.0.1:5912/ultra" method="Get"≥
    ¿Cuál es su nombre? ≤input br="" maxlength="50" name="User" size="30" type="Text" /≥    ≤input type="Submit" name="Send" value="Send"≥
    ≤input type="hidden" name="OmnisLibrary" value="DirectHTTP"≥
    ≤input type="hidden" name="OmnisClass" value="rtDirectHTTP"≥
  ≤/form≥
≤/html≥


Deberá cambiar la dirección IP y el puerto 5912 para que se conforme a su configuración, la dirección IP y el número de puerto indicados anteriormente son los usados por Omnis como valores por defecto.

A continuación, abra el formulario HTML en un navegador, introduzca un nombre y haga clic en “Send”. Esto provocará la invocación del método “$construct” de la tarea remota “rtDirectHTTP”, pasándole el parámetro denominado “User”, que contendrá el texto introducido en el formulario. La llamada http completa es la siguiente:

http://127.0.0.1:5912/ultra?User=Santa&Send=Send&OmnisLibrary=DirectHTTP&OmnisClass=rtDirectHTTP

La “remote task” procesa los valores del formulario y devuelve al navegador texto HTML estándar, como se muestra a continuación:




09 diciembre 2015

Uso de “sockets” seguros con Omnis.

Existen dos formas de hacer que nuestro servidor “Omnis App Server” soporte conexión segura para los clientes, el primero (más extendido) es mediante el uso de un prefijo en el “WebServerURL” que para páginas HTML es el “https://”. Éste modo asegura que el servidor web y sus clientes transfieran la información en modo seguro, durante todo el tiempo que permanezcan conectados. En éste caso no es necesario hacer uso de la propiedad de las “remote task” “$issecure”.

En el segundo método que proponemos, usaremos la propiedad de que disponen las “remote task” denominada “$issecure”. En primer lugar hacer notar, que dicha propiedad pude ser cambia dinámicamente, lo que posibilita su uso sólo cuando realmente sea necesario, como por ejemplo, en el momento de tener que enviar el número de una tarjeta de crédito, para después retornar a su estado anterior o “no seguro”, lo cual permite reducir al mínimo la sobrecarga adicional en la que incurre el uso de los “secure sockets”.

Al contrario de lo que ocurría con el primer método, no existe indicación alguna de que el cliente se este ejecutando en modo seguro, además las diferencias en cuanto los tiempos de conexión segura y “no segura” (al usarse de modo dinámico) son apenas apreciables. De modo que el navegador Web puede mostrar un estado de “no seguro”, pero internamente el cliente estar ejecutándose en modo seguro.

La propiedad indicada puede ser cambiada mediante el comando siguiente:

Do $ctask.$issecure.$assign(kTrue)

Como se trata de una propiedad de la “remote task”, el uso del método “$changeform()” no afectará a su estado.

02 diciembre 2015

jsClient: uso de “assignpdf” y “showpdf”

Desde la publicación de la versión 6 de Omnis Studio, ha sido posible imprimir y visualizar archivos PDF mediante el componente PDFDevice y sus métodos javascript “addignpdf” y “showpdf”. Pero debido a un ajuste de seguridad (publicado en la nota ST/WT/1860) el uso de éstos métodos puede generar un error de tipo “You are not allowed to get the file D:/temp/test.pdf using the getpdf command”. ¿Cómo podemos resolver este problema?

La solución, pasa por realizar un pequeño cambio en su archivo “Config.json” a fin de especificar en él, qué carpetas o directorios deben ser accesibles a la función “GetPDF()”. Éste archivo lo podremos encontrar bajo la carpeta “Studio” dentro del directorio raíz de instalación de Omnis.

Concretamente, deberemos incluir, bajo su sección “Server” algo como lo siguiente:

"getpdfFolders": ["c:\\Temp", "c:\\MyPDFFile"]

Deberemos asegurarnos de que no quede ningún separador de los usados en los nombres de directorios sin ser “escapado” y de que estén encerrados entre comillas dobles. Esto permitirá el uso de los documentos PDF ubicados en las carpetas referenciadas.