Etiqueta

Mostrando entradas con la etiqueta #OMNIS. Mostrar todas las entradas
Mostrando entradas con la etiqueta #OMNIS. Mostrar todas las entradas

06 junio 2023

Omnis Studio 11, soporte para TOTP

La última actualización de Omnis Studio da soporte a TOTP, es el acrónimo de "Time-based One Time Passwords", o contraseñas temporales de un solo uso. Es decir, estas contraseñas tienen una vida útil bien de un uso, o de un periodo de tiempo concreto a partir del cual se auto-destruyen. Dos nuevas funciones nos permiten incorporar éste protocolo en nuestros desarrollos: OW3.$totpgenerate() y OW3.$totpvalidate()

Tech Insight: Autenticación - TOTP | Citrix Tech Zone

La primera contiene 4 parámetros necesarios, más 2 opcionales y su sintaxis es la siguiente:

OW3.$totpgenerate(xSharedSecretKey,iTimeStep,iDigits,&iTOTP[,&cErrorText,iHashType=kOW3hashSHA1])

Esta función genera una contraseña de un solo uso con base en el tiempo, quedará contenida en iTOTP y se utilizará para ello el algoritmo TOTP. Retornado "true" si la función es ejecutada con éxito.

Parámetros obligatorios:

xSharedSecretKey (Binary) es la clave secreta compartida, su longitud debe estar entre 16 y 256 bytes.

iTimeStep (Integer 32 bit) es el salto de tiempo en segundos el cual deberá estar entre 1 y 3600.

iDigits (Integer 32 bit) es el número de dígitos del TOTP resultante, un valor entre 6 y 8.

iTOTP (Integer 32 bit) recibe el TOTP generado.

Parámetros opcionales:

cErrorText (Character 100000000) Si se proporciona, recibirá la descripción del posible error provocado por $totpgenerate o $totpvalidate (si resultó "false").

iHashType (Integer 32 bit), su valor por defecto es proporcionado por la constante kOW3hashSHA1) es el tipo de "hash" a utilizar, use una de las constantes del grupo kOW3hash...

La segunda contiene 4 parámetros necesarios, más 4 opcionales y su sintaxis es la siguiente:

OW3.$totpvalidate(xSharedSecretKey,iTimeStep,iDigits,iTOTP[,&cErrorText,iHashType=kOW3hashSHA1,iStepsBefore=2,iStepsAfter=1])

Esta función valida la contraseña de un solo uso con base en el tiempo, contenida en iTOTP utilizando para ello el algoritmo TOTP. Retornado "true" si iTOTP resulta en un TOTP válido.

Parámetros obligatorios:

xSharedSecretKey (Binary) es la clave secreta compartida, su longitud debe estar entre 16 y 256 bytes.

TimeStep (Integer 32 bit) es el salto de tiempo en segundos el cual deberá estar entre 1 y 3600.

iDigits (Integer 32 bit) es el número de dígitos del TOTP resultante, un valor entre 6 y 8.

iTOTP (Integer 32 bit) es el TOTP que va a ser validado.

Parámetros opcionales:

cErrorText (Character 100000000) Si se proporciona, recibirá la descripción del posible error provocado por $totpgenerate o $totpvalidate (si resultó "false").

iHashType (Integer 32 bit), su valor por defecto es proporcionado por la constante kOW3hashSHA1) es el tipo de "hash" a utilizar, use una de las constantes del grupo kOW3hash...

iStepsBefore (Integer 32 bit), el valor por defecto es 2 y es el número de saltos de tiempo anteriores al momento actual, para llevar a cabo la verificación del TOTP proporcionado, deberá ser un valor entre 1 y 20.

iStepsAfter (Integer 32 bit), su valor por defecto es 1 y es el número de saltos de tiempo después del momento actual, para llevar a cabo la verificación del TOTP proporcionado, deberá ser un valor entre 1 y 20.



26 noviembre 2020

03 julio 2020

Nuevo asistente para la construcción de aplicaciones finales (Deployment Tool)

La última actualización de Omnis 10.1 incluye una nueva herramienta denominada "Deployment Tool", la cual permite crear y personalizar nuestra aplicación final, es decir, la aplicación resultante de la integración de nuestras librerías y ficheros adicionales con el código Omnis (runtime), disponible tanto para Mac OS como para Windows. En el caso de macOS, la herramienta permite crear un paquete (bundle), mientras que en caso de Windows se permite la creación de un constructor completo o parcial. Además, (sólo para Windows) se incluye un nuevo componente externo, denominado "RCEdit", mediante el cual es posible modificar recursos del propio programa Omnis (runtime), permitiendo su completa personalización o "configuración de identidad" del producto final.

Opciones macOS


En caso de macOS y desde la primera pantalla de opciones que mostrará el asistente, podremos cambiar el nombre de la aplicación, la versión, el identificador, el fabricante, el aviso de copyright y su icono:



Desde la segunda pantalla podremos indicar la localización de nuestras carpetas "startup", grupos de iconos (los "iconsets" que requieran nuestras librerías), la "xcomp" e "icons", así como una opción para pre-serializar el paquete o agregar un carpeta de lectura/escritura personalizada.


Finalmente y desde la pantalla de opciones "Build", crearemos el "Omnis Bundle" (Omnis Runtime + nuestros ficheros), indicando una carpeta, es decir, la ruta a la carpeta donde quedará construida la aplicación final, junto con la versión de nuestro "Bundle". También podremos (si así lo deseamos) seleccionar la opción que nos permitirá borrar la carpeta resultante o "Bundle" en caso de producirse algún error durante el proceso.

Opciones Windows

En caso de Windows, podremos indicar el nombre de la aplicación, fabricante, versión, aviso de derechos de autor, nombre del ejecutable y la ruta hacia el archivo ".ico", que será usado en sustitución del icono propio de Omnis.


Desde la segunda pantalla (como en el caso de macOS) podremos especificar su "startup", "iconsets", "xcomp" e "icons", así como la opción para pre-serializar el paquete o agregar un directorio de lectura/escritura personalizado.


En la pantalla de opciones "Build", podremos especificar la ubicación de los archivos de solo lectura propios de Omnis (es decir nuestro Omnis Studio Runtime xx.x), así como la ubicación de los archivos de lectura/escritura (es decir los que se ubicarán en "AppData"), finalmente especificaremos la ruta hacia la carpeta de salida (donde quedará construida la aplicación final) y la opción para 32 o 64 bits. También en éste caso, podremos optar por indicar si queremos que se borre la carpeta "Bundle", si se produce algún error durante el proceso.


En caso de Windows, también podremos optar por crear un directorio simple "Flat tree", una división en árbol "Split tree" o una división en árbol con inclusión del instalador inicial "Split tree with firstruninstall".

  • La opción "Flat tree" generará una carpeta simple con todos los archivos, los de lectura y los de lectura/escritura.
  • La opción "Split tree" generará una carpeta con los archivos de solo lectura, es decir aquellos cuyo destino será "Program Files" y otra de lectura/escritura con los destinados a "AppData".
  • La opción "Split Tree with firstruninstall" generará una carpeta con los archivos de solo lectura y dentro de esta,  otra adicional denominada "firstruninstall", con los archivos de lectura/escritura que Omnis copiará automáticamente sobre la carpeta "AppData" del usuario, la primera vez que ejecute la aplicación.

Es interesante hacer notar que la opción "firstruninstall" nos permitirá instalar y configurar nuestra aplicación sin la necesidad de construir un instalador, lo cual puede resultar ser más rápido, sencillo y/o más conveniente para nuestro producto final. Podríamos incluso usar la función "7Zip's SFX" para que simplemente se auto-descomprima, simplificando así enormemente la instalación de nuestra aplicación, ya que no precisaría del uso de complejos instaladores.

Uso del editor de recursos "RCEdit"


El nuevo componente externo denominado "RCEdit" nos permite editar varios recursos de Windows, tales como la versión del producto, el texto de la versión y el icono representativo del ejecutable Omnis. El componente externo implementa varios métodos nuevos, que podrán ser invocados desde nuestro código Omnis.

  • $setapplicationmanifest(cFile, cManifest), cambia el manifiesto incluido cManifest según la ruta indicada por cFile), ejemplo: Do rcedit.$setapplicationmanifest(“C:\omnis.exe”, “C:\folder\newManifest.xml”) Returns #F

  • $setresourcestring(cFile, cResource, cValue), cambia el recurso "cResource" por el valor de "cValue" para según la ruta indicada en "cFile", ejemplo: Do rcedit.$setresourcestring(“C:\omnis.exe”, “1”, “Nuevo valor”) Returns #F

  • $setproductversion(cFile, cProductVersion), cambia el recurso del ejecutable Windows "Product Version" según lo indicado en cProductVersion para la ruta del archivo cFile, ejemplo: Do rcedit.$setproductversion(“C:\omnis.exe”, “10.1”)

  • $seticon(cFile, cIcon), cambia el icono del ejecutable Windows indicado la ruta del archivo cFile, por el archivo ".ico", indicado en la ruta cIcon, ejemplo: Do rcedit.$seticon(“C:\omnis.exe”, “C:\newIcon.ico”) Returns #F

  • $setversionstring(cFile, cVersion, cValue), cambia el texto de versión en "cVersion" por el especificado en "cValue" según la ruta indicada en cFile, ejemplo: Do rcedit.$setversionstring(“C:\omnis.exe”, “Comments”, “Comment version string”) Returns #F

  • $setfileversion(cFile, cFileVersion), cambia el recurso del ejecutable Windows "File Version" por el contenido en cFileVersion, ejemplo: Do rcedit.$setfileversion(“C:\omnis.exe”, “10.1.0.0”) Returns #F

13 febrero 2020

Cómo mostrar un PDF desde un campo BLOB de Oracle sobre el navegador, sin descargarlo

En este artículo quiero mostrarles un "truco" ideado por Francesco Del Dotto de soporte Omnis en Italia, de modo que lo primero es agradecer su tiempo y darle mi enhorabuena ante la pericia demostrada.


En principio podría pensarse que se trata de algo sencillo de hacer desde Omnis Studio, ya conocemos el método Do $cinst.$clientcommand("assignpdf",row) donde el parámetro row se define como row(html-object-name,pdf-parameters,pdf-id,timeout,pdf-filename), pero el reto está precisamente en el parámetro pdf-filename, es decir que el uso de éste método requiere de la presencia física del fichero con el documento pdf, pero el reto que se plantea en el enunciado de este artículo, es enviar al navegador del cliente, un documento pdf que se encuentra en una variable binary y no en un fichero físico.

La parte digamos "sencilla" fue construir el método (denominado muestraPdf) javascript que se encargaría de mostrar el documento, pasándole el contenido del campo BLOB de oracle y que mostramos a continuación:

# El dato BLOB de Oracle es iDocumentos.DOCUMENTO
# pdfBuffer es una variable var de JavaScript
# el método ha sido marcado como "Execute On Client" 

Calculate pdfBuffer as iDocumentos.DOCUMENTO
JavaScript: var arrayBuffer = base64ToArrayBuffer(pdfBuffer);
JavaScript: function base64ToArrayBuffer(base64) {
JavaScript: var binaryString = window.atob(base64);
JavaScript: var binaryLen = binaryString.length;
JavaScript: var bytes = new Uint8Array(binaryLen);
JavaScript: for (var i = 0; i < binaryLen; i++) {
JavaScript: var ascii = binaryString.charCodeAt(i);
JavaScript: bytes[i] = ascii;
JavaScript: }
JavaScript: return bytes;
JavaScript: }
JavaScript: var blob = new Blob([arrayBuffer], {type: "application/pdf"});
JavaScript: var link = window.URL.createObjectURL(blob);
JavaScript: window.open(link);

El problema estriba en como invocar a éste método desde el lado del servidor, ya que sólo existe en el navegador del cliente y por tanto sólo puede ser invocado desde un método que (al igual que este) haya sido marcado como "Execute On Client", el problema es que la recuperación del campo BLOB con el contenido del PDF, debe hacerse desde un método creado y ejecutado en el entorno del servidor, es decir que no puede llevar la marca "Execute On Client", y es aquí donde llega el "truco de Francesco".

Para que la magia tenga su efecto, lo primero que hacemos es colocar un "Timer Control" sobre el formulario remoto...


...al que incluiremos en su método "$event" el código siguiente y que estratégicamente habremos marcado como "Execute On Client":

On evTimer
Do $cinst.$objs.timerObj.$running.$assign(kFalse)
Do $cinst.$muestraPdf()

El truco consiste en activar el timer alojado en el navegador del cliente desde el servidor, el cual se encargará a su vez de invocar al método "$muestraPdf()" ademas de auto-desactivarse.

A continuación mostramos la secuencia que obtiene el campo BLOB de oracle y activa el timer:

Calculate lCompara as con("where ROWID = '";iListaDctos.ROWID;"'")
Do iDocumentos.$select(lComparaReturns #F
If flag true
Do iDocumentos.$fetch()
If not(isclear(iDocumentos.DOCUMENTO))
Do $cinst.$objs.timerObj.$running.$assign(kTrue)
End If
End If

El código encargado de recuperar el documento desde la base de datos, es también el encargado de activar el timer, que fue previamente alojado en el navegador del cliente.

Gracias de nuevo a Francesco de soporte Omnis, por este maravilloso truco.
 

22 enero 2020

La librería de conversión de DML a SQLite

Recientemente Omnis Studio proporciona la utilidad denominada "Convert Datafile to RDBMS", la cual está soportada por la librería "omsqlconv.lbs" bajo el directorio "startup", pero no debemos pasar por alto, que ésta, no sólo se encarga del proceso de conversión, sino que también funciona en segundo plano, realizando el trabajo de emular los antiguos comandos DML, traduciéndolos y ejecutándolos contra SQLite, así como del comportamiento de semáforos (semaphores) y bloques reversibles (reversible blocks) cuando son usados.


La librería "omsqlconv.lbs", se apoya también en tablas creadas sobre la base de datos resultante de la conversión, las cuales no deberán ser modificadas o eliminadas, a continuación mostramos una lista de los comandos DML que son emulados:

Close datafile, Close lookup file, Create datafile, Floating default datafile, Open datafile, Open lookup file, Prompt for datafile, Set current datafile, Set default datafile, lookup(), Build indexes, Delete data, Drop indexes, Open runtime datafile browser, Rename data, Cancel prepare for update, Delete, Delete with confirmation, Do not flush data, Do not wait for semaphores, Flush data, Flush data now, Prepare for edit, Prepare for insert, Prepare for insert with current values, Test for only one user, Update files, Update files if flag set, Wait for semaphores, Clear all files, Clear main & connected, Clear main file, Clear range of fields, Clear selected files, Set main file, Clear find table, Disable relational finds, Enable relational finds, Find, Find first, Find last, Load connected records, Next, Previous, Prompted find, Single file find, Test for a current record, Test for a unique index value, Clear search class, Reinitialize search class, Set search as calculation, Set search name, Test data with search class, Clear sort fields, Set sort field, Build list from file, Begin reversible block, End reversible block, Quit all methods, $root.$getodbfilelist(), y alguna funciones de sys(), como: sys(11), sys(139), sys(3000) & sys(3001)

Para habilitar la emulación de comandos DML, es necesario establecer la preferencia de librería "$mapdmltodam" para SQLite. No obstante aún habrá que hacer un pequeño cambio en el código de nuestra librería, que tiene que ver con el modo en que se abrimos o accedemos a la base de datos, antes un fichero con extensión .df1 y ahora con extensión .db. El comando para SQLite sería:

Open datafile sdb://192.168.0.10:5743/SQLiteTest

Pero si queremos también podemos optar por cambiar éste comando y hacer uso de la sintaxis de notación del modo siguiente:

Do omsqlSess.$logon(‘sdb://192.168.0.10:5743/SQLiteTest’,’’,’’) Returns #F

15 octubre 2019

¿Cómo evitar el diálogo "Install the legacy Java SE 6 runtime" en Omnis Studio 10.1 y Catalina?

Es muy probable que tras instalar de nuevo el soporte Java para SOAP en Omnis Studio 10.1, nos encontremos con que Omnis nos muestre un cuadro de diálogo Java que tenga el siguiente texto;
Este cuadro de diálogo puede aparecer aún al intentar iniciar una JVM de Oracle en una versión de Studio de 64 bits, es decir, Studio 8.0 y posterior. Las instrucciones predeterminadas establecidas en una versión de Java de 64 bits no permiten que sean iniciadas desde una aplicación incluida en JNI (como es el caso de Omnis). Lo cual causará un fallo el intentar iniciar la JVM mostrándose el mensaje anterior.

Para corregirlo, simplemente debemos editar el fichero "Info.plist" de nuestro Oracle JDK en uso, para permitir que JVM sea iniciado desde aplicaciones incluidas en JNI.

Podrá localizar el fichero a editar en, "/Library/Java/JavaVirtualMachines/jdkX.X.X_XXX.jdk/Contents/Info.plist" (donde X.X.X_XXX es la versión, por ejemplo, 1.8.0_101).

Ahora simplemente cambie la entrada:

≤key≥JVMCapabilities≤/key≥
≤array≥
   ≤string≥CommandLine≤/string≥
≤/array≥
por:

   ≤key≥JVMCapabilities≤/key≥
   ≤array≥
      ≤string≥CommandLine≤/string≥
      ≤string≥JNI≤/string≥
      ≤string≥BundledApp≤/string≥
   ≤/array> 

..y eso habrá sido todo.

16 septiembre 2019

Conexión nativa a Microsoft SQL Server con Omnis Studio 10

Recientemente el DAM para Sybase de Omnis Studio 10, ha sido modificado para su uso mediante la versión "open-source" de LIBCT desarrollada por FreeTDS. FreeTDS facilita principalmente conexión libre de uso, para servidores Sybase ASE y Sybase ASA. Pero resulta que la librería LIBCT de FreeTDS, también soporta conexiones nativas a Microsoft SQLServer, anteriormente, esto sólo era posible mediante los DAM ODBC o JDBC.




La nota técnica: https://omnis.net/developers/resources/technotes/tnsq0036.jsp le dará más detalles sobre como configurar el DAM para su uso con Microsoft SQLServer.

30 agosto 2019

Acceso a datos con aplicaciones Web

Una buena práctica cuando estamos creando aplicaciones para la Web con Omnis Studio, consiste en la creación de un grupo de sesiones (session pool) para controlar el acceso a datos por parte de los usuarios de la aplicación Web. La idea es otorgar a cada usuario activo de la aplicación una sesión individual de acceso a datos, mejorando así los tiempos de acceso, ya que la base de datos podrá atender simultáneamente las peticiones de cada uno de los clientes.


El método Omnis que nos permite hacer esto se denomina $makepool, puesto que Omnis creará el grupo de sesiones de modo global (bajo $root), parece lógico invocarlo desde un método (por ejemplo $acceso) situado en la clase "Startup_Task" y que será ejecutado desde su $construct. Eso garantizará que cada vez que se haga disponible nuestra aplicación Web (se abra la librería) el grupo sea automáticamente creado. El código será algo como esto:

Do $extobjects.PGSQLDAM.$objects.PGSQLSESS.$makepool('myPool',1,'192.168.10.10','myUser','myPassword') Returns iMyPoolRef

El segundo parámetro (1 en el ejemplo) es el número de sesiones de que constará el grupo inicialmente, lo cual no plantea ningún problema, ya que todo "session pool", dispone de propiedades que nos permiten (entre otras cosas) aumentar ésta cifra según surja la necesidad debido al incremento en el número de usuarios que esten haciendo uso de la aplicación Web, o simplemente conocer su cifra actual.

El primer parámetro del método $makepool es el nombre que identifica al grupo de sesiones de modo único. Dado que su existencia es global (nivel $root), deberá eliminarse cuando se destruya su "Startup_Task"". Esto significa que no podrá existir otro grupo de sesiones con el mismo nombre. La variable "iMyPoolRef" nos permite referenciar al grupo creado, pero tambien disponemos de un modo para conocer todos los posibles y diferentes grupos de sesiones que puedan llegar a existir bajo un mismo servidor de aplicaciones Omnis, en $sessionpools.

Para cerrar el grupo de sesiones, usaremos el siguiente código situado en el método $destruct de nuestra clase "Startup_Task":

Do $sessionpools.$remove(iMyPoolRef)

Note que "iMyPoolRef" es una variable de instancia y tipo "Item Reference" cuyo valor ha sido asignado por el método $makepool.

Ahora explicaremos cómo solicitar una nueva sesión al grupo, con el fin de otorgársela al usuario durante el tiempo que esté usando nuestra aplicación Web, para ello usaremos el metodo $new. Con éste fin crearemos un nuevo método en nuestra clase "Startup_Task" al que denominaremos $getSessionFromPool, con el siguiente código:


If iSessionPoolRef.$poolsize=iSessionPoolRef.$inuse
Do iSessionPoolRef.$poolsize.$assign(iSessionPoolRef.$inuse+1)
End If
Quit method iSessionPoolRef.$new()
El tamaño del grupo de sesiones ($poolsize) puede ser aumentado en cualquier momento, nosotros lo haremos comprobando si se ha alcanzado su límite actual ($poolsize=$inuse) y cada vez que requiramos de una nueva sesión. El método $new retornará un nuevo objeto de sesión para acceso a datos.

Ahora nos queda una cuestión importante por resolver, ¿Cómo ejecutar el método $getSessionFromPool ubicado en la calse "Startup_Task" desde una clase "Remote_task"?

Naturalmente necesitamos hacerlo así, ya que queremos asignar la nueva sesión a cada nueva conexión remota. Empezaremos por crear una variable de tipo task, en la clase "Remote_task", donde alojar el nuevo objeto de acceso a datos, la llamaremos "tSessionObj", también resultará lógico que el código para invocar al método $getSessionFromPool lo situemos en el método $construct de la "Remote_task", la respuesta a la pregunta del párrafo anterior sería:

Do $itasks.myLib.$getSessionFromPool() Returns tSessionObj

El literal "myLib" deberá corresponder al nombre de nuestra librería o bien usar la notación [$clib().$name] (importante usar los corchetes) para obtener el nombre de la misma, si optamos por esto último estaríamos garantizando su funcionamiento aunque se llegue a cambiar el nombre asignado inicialmente a la librería.

Esto es todo o casi todo, ahora sólo nos quedaría asignar la sesión (normalmente) a la o las clases "table" que use nuestra aplicación Web, para esto lo más habitual es disponer de una super-clase "table" que será heredada por el resto de clases "table", de ese modo escribiremos nuestro código de asignación de sesión una única vez.

Suponiendo que el nombre de nuestra super-clase es "taSuper", escribiríamos en su método $construct lo siguiente:

Do $cinst.$sessionobject.$assign(tSessionObj)

Naturalmente el resto de clases "table", heredaran este método constructor, aunque también pueden tener el suyo propio, pero si lo usamos, tendremos que utilizar el comando "Do inherited" para ordenar la ejecución del método $construct en la superclase.

24 mayo 2019

Creación de paquetes firmados para la instalación de aplicaciones Omnis en MacOS

Este documento explica cómo hacer lo siguiente:
  1. Preparar tu "First Run Install" con los archivos propios de la aplicación.
  2. Instalar los ficheros .df1 en modo de sólo-lectura.
  3. Crear tu propio "package" (.pkg) de instalación.
  4. Colocar "script's" dentro del "package".
  5. Construir el "package", desde una opción de menú o mediante Cmd+B.
  6. Firmar el "package" resultante, para su distribución.
  7. Probar su carga/descarga, instalación y ejecución.

Antes debo explicarte que realmente existen dos tipos de firmas, una es la "Firma de la aplicación" (Application Signing) y la otra la "Firma del producto" (Product Signing). Ambos tipos pueden ser obtenidos tras registrarte como desarrollador en Apple. ($99 dólares anuales)

De modo que lo primero es convertirse en un desarrollador registrado, para después obtener su certificado. Hacerlo desde Xcode es más fácil que hacerlo manualmente desde la web, pero de todos modos se trata de un proceso realmente sencillo.

Ahora te contaré cómo se hace, si el caso es que no vas a usar Xcode. Lo primero es, que tendremos que hacer uso de tu cuenta en Apple, esa misma que usas para comprar cosas en iTunes o en la App Store. Si no tienes una, tendrás que registrarse para obtenerla.

Lo primero será iniciar sesión con tu cuenta de Apple. Una vez allí, localiza el enlace al "Programa de Desarrolladores" (Developer Program) o al de "Desarrollador Registrado" (Registered Developer). Una vez allí podrás realizar el registro como nuevo desarrollador Apple. Una vez completado el proceso, (es posible que la nueva cuenta tarde un poco en activarse) podremos solicitar certificados.

Localiza el enlace a Certificados (Certificates). Desde aquí podrás solicitar certificados, indicándote también cómo proceder. Observarás que se hace uso del "Keychain Access" (Acceso a llaveros) durante la creación de certificados. Observa también que la página web muestra un menú en la esquina superior izquierda, donde figuran en primer lugar dispositivos iOS, deberemos cambiarlo a MacOS para obtener así el certificado correcto.

Una vez seleccionado MacOS podrás ver sus opciones. Deberemos escoger aplicaciones o instaladores que no estarán en la tienda de aplicaciones (App Store). A partir de ahí, verás que debes elegir entre un certificado para aplicaciones que están en desarrollo o para las ya en producción, elige producción (Production). Luego verás que tienes que elegir entre aplicaciones (Applications) o instaladores (Installers). Elige instalador, porque es el que necesitamos para firmar nuestro .pkg.

Descubre que en la parte inferior de la página, hay un lugar donde hacer clic para obtener un "Certificado Intermedio" (Intermediate Certificate). Este también es necesario, ya que causa que los demás se ejecuten correctamente. Así que obtén el denominado "WW Developers", sin marcar la opción "CA Authority".

Ahora descubrirás que necesitas generar un "Cert. request" desde el "Keychain Access" de tu Mac, después tendrás que subirlo a la web de Apple, para finalmente poder descargar nuestro certificado. Lo que se descarga es un certificado digital que deberás instalar también en el "Keychain Access" de tu Mac, para esto, bastará con hacer doble clic sobre el certificado que acabas de descargar.

Haz que tus certificados se carguen al inicio de sesión (Login Keychain), es una de las tres opciones que se muestran en la ventana tras el dobre-click. También el propio "Keychain Access" muestra un pequeño menú en la esquina superior izquierda, desde el que poder elegir "Login keychain" para el nuevo certificado.

Los certificados se guardan en el "Keychain Access" y son necesarios para verificar tu identidad. Al fin y al cabo, se trata de poner tu firma en tus productos de modo que otros puedan verificar su procedencia.

Una vez que tengas los dos certificados instalados, estarás listo para firmar los instaladores (Productos). Realmente lo único que los desarrolladores de Omnis necesitamos en este momento es la firma de instalador (Installer). Pero también podemos volver a firmar la aplicación Omnis.

Por aplicación, debemos entender una copia completa del paquete Omnis instalado, que lleva la extensión ".app". Mientras que por instalador debemos entender que se trata de un "Package" con extensión ".pkg" y no de orto tipo de instaladores más sofisticados de los que guían al usuario durante la instalación, mientras le muestran algunas imágenes.

Realmente a un desarrollador Omnis (de momento) le vastará con preocuparse por firmar su instalador, y añadir alguna que otra secuencia de comandos que permita ajustar después de la instalación algunas propiedades y cambiar algunos permisos.

En este momento, Apple no obliga a que la aplicación tenga el código firmado para poder ejecutarse, si el caso es que se instala desde un paquete firmado, ten en cuanta que si firmas la aplicación, no podrás cambiar nada dentro de ella sin volver a firmarla. Si alguna vez Apple requiere que la aplicación esté firmada, los desarrolladores de Omnis tendremos que enviar instaladores completos.

La firma deberá llevarse a cabo desde la línea de comandos del terminal y deberá realizarse una vez construido el instalador, este será modificado mediante el comando correspondiente, para incluir tu seña de identidad.

Omnis requiere de la ejecución de un "script" que corrija permisos y, en ocasiones, propiedades de todos los archivos contenidos en el paquete. Este script es muy simple, solo unas pocas líneas de código. La razón por la que debe ejecutarse tras la instalación es debido a que los permisos y las propiedades deben cambiarse, de otro modo el programa fallará y no podrá ejecutarse con normalidad. Crearemos un script para Omnis 4.3 y otro para Omnis Studio 8. Lo más probable es que el script para 8 también funcione para 10 y que el de 4 funcione para 5 y 6.

Para la creación del instalador o .pkg, usaremos "Packages" disponible en:

  
El botón de descarga se encuentra en la esquina superior derecha.

Primero, si tienes archivos ".df1", asegúrate de "Obtener información" (Comando-I) de cada uno de ellos, para marcarlos "Todos" con acceso de "Lectura/Escritura" y situarlos bajo "First Run Install" si se usa.

Después crearemos nuestro "package", simplemente mediante colocar los elementos a instalar sobre el área "Payload" (Carga útil) de "Packages". Ten en cuenta que si quieres que algo quede situado sobre el nivel raíz del disco duro, deberás arrastrarlo a la parte superior, hasta que veas que la línea se desplaza totalmente hacia la izquierda, luego la sueltas, junto a otras posibles cosas que también se deban encontrar en ese mismo nivel.

Ten en cuenta que pueden existir carpetas ocultas. Para verlas, busca en uno de los menús la opción "Show hidden folders". Esto mostrará, (entre otras cosas) una carpeta "fonts" que podrás usar para instalar fuentes... simplemente colócalas con sangría debajo del nombre de esa carpeta, debajo de "fonts" y se instalarán correctamente.

Entra en "Packages Destination" y selecciona la carpeta "First Run Install" de Omnis y su destino, puedes colocar los archivos donde quiera que vayan. Algunos estarán a su vez, en otras carpetas dentro de "First Run Install", la cual es a su vez es una carpeta dentro de Omnis (para localizarla, haz clic con el botón derecho sobre Omnis y "Mostrar contenido del paquete" - luego "Contents", después "MacOS", y encontrarás la carpeta "First Run Install"). Dentro de ésta es donde deberás poner todas tus cosas. Cuando el usuario ejecute Omnis por primera vez, todos su contenido será copiado en los destinos mencionados.

Cuando ya tengas colocados todos los ficheros y carpetas en el lugar que le corresponden dentro de Omnis, deberemos colocar el propio Omnis y cualquier otra cosa que necesitemos en el área "Payload" (Carga útil) de "Packages", de éste modo estaremos listos para construir nuestro paquete. Observa que dispones de muchas opciones, pero ninguna de ellas necesaria durante la construcción de un paquete básico como el nuestro. Claro que no es imprescindible hacer todo esto para instalar una aplicación, pero el uso de "Packages" proporcionará al usuario una experiencia de instalación más profesional.

Una vez que creado, podremos ver un pequeño ícono de caja y será ahora cuando deberemos proceder con el proceso de firma del Producto (Product Sign) mediante comandos de Terminal, después lo probaremos, comprobaremos que podemos cargarlo/descargarlo, que el proceso de verificación "Apple Gatekeeper", funciona correctamente y que la aplicación Omnis puede ser ejecutada sin problemas.

Un truco para ahorrarnos trabajo en el terminal, consiste en arrastar cualquier archivo sobre la ventana de éste, para así obtener la ruta hacia el mismo ya escrita sobre la línea de comandos.

Otra forma de hacerlo es escribiendo la ruta entre comillas dobles, para no necesitar escapar de los espacios u otros caracteres especiales. Por ejemplo escribiendo:

"/Users/Das's/Desktop/JyotishStudio4.pkg"

Algunos comandos de Terminal solicitarán tu contraseña, si te aparece un pequeño candado como cursor en el Terminal, significará que debes escribir tu contraseña de administrador para completar el comando. En algunos casos, puede que se te muestre un cuadro de diálogo solicitando esta misma contraseña.

Aquí está el comando que debes usar para firmar el "Package":

productsign --sign "Developer ID Installer: Das Goravani" /Users/Das\'s/Desktop/build/JyotishStudio4.pkg /Users/Das\'s/Desktop/JyotishStudio4signed.pkg

Realmente el comando consiste en la primera parte solamente, hasta el nombre del desarrollador. El resto son DOS rutas. LA PRIMERA es la ruta hacia el paquete que queremos firmar, sólo UN ESPACIO la separa del nombre del desarrollador y de la segunda ruta indicada. La segunda ruta corresponde a un nuevo archivo que se creará. Será un duplicado de nuestro paquete pero con la firma incluida. El original permanecerá coo estaba.

Si has escrito todo correctamente, al presionar retorno, se firmará tu aplicación y se creará el nuevo archivo cono nuestro instalador ya firmado. Ahora todo lo que queda resta, es probarlo, cosa que puedes hacer de inmediato, cono sólo hacer doble clic sobre él o bien empezar por subirlo a algún sitio para después descargarlo y luego instalarlo.

Su ejecución no será exitosa, a menos que pongamos antes nuestro "Post Process Script". El script deberemos ubicarlo (como ya hemos indicado) desde el programa "Packages" en el apartado "Post Install" pestaña "Scripts". Podemos simplemente arrastrarlo, para soltarlo sobre "Post Install" para ver su icono allí.

El "script" necesario para Omnis 4, 5 o 6, sería el siguiente:
#!/usr/bin/env bash
# Este script se ejecuta una vez instalada la aplicación.
# Indica la ruta hacia tu aplicación
APPLICATION_ROOT="/Jyotish Studio 4.0/JS4.app"
# Estabece permisos
sudo chown -R root:admin "${APPLICATION_ROOT}"
sudo chmod -R 775 "${APPLICATION_ROOT}"
Crea un documento de TEXTO PLANO, con estas líneas y guárdalo, para después añadirlo a tu instalador como ya se ha descrito. Se ejecutará después de la instalación, establecerá todos los permisos y propiedades haciendo que el programa se ejecute correctamente.

Para Omnis 8:
#!/usr/bin/env bash
# Este script se ejecuta una vez instalada la aplicación.
# Indica la ruta hacia tu aplicación
APPLICATION_ROOT="/Applications/Omnis Studio Runtime 8.0.2 x64.app"
# Estabece permisos
sudo chmod -R a+rw "${APPLICATION_ROOT}/Contents/MacOS/startup"
sudo chmod -R a+rw "${APPLICATION_ROOT}/Contents/MacOS/icons"
sudo chmod -R a+rw "${APPLICATION_ROOT}/Contents/MacOS/iconsets"
sudo chmod -R a+rw "${APPLICATION_ROOT}/Contents/MacOS/local"
sudo chmod -R a+rw "${APPLICATION_ROOT}/Contents/MacOS/omnispdf"
sudo chmod -R a+rw "${APPLICATION_ROOT}/Contents/MacOS/studio"
# Para Brainy Data's PDFDevice (omitir si no se usa)
sudo chmod a+rw ../MacOS
Quiero dar las gracias en especial a Das Goravan, Paul Mulrooney y Alex Clay por el trabajo realizado y su aportación a éste documento.

28 marzo 2019

Clases grabadas del curso Introducción a Omnis Studio

Grabación en vídeo de las clases del curso “introducción a Omnis Studio Web y Móvil” de Julio de 2017

(¡ATENCIÓN! Estas grabaciones ya no están disponibles)


08 marzo 2019

Firmado y localización de aplicaciones (Parte 1 de 3)


El núcleo de nuestra aplicación final Omnis Studio resultante para MacOS, es código firmado, lo cual proporciona mayor seguridad y confianza a los destinatarios finales de nuestras aplicaciones. La firma proporciona una garantía de que nosotros (como desarrolladores) somos los creadores del software que el usuario se está instalando en sus equipos, sin que éste haya sufrido alteración alguna desde su compra, por lo tanto, garantiza la autenticidad de una aplicación. Otra ventaja (no menos importante) de las aplicaciones firmadas dentro macOS, es que se les puede conceder permisos de forma automática para realizar acciones, tales como el acceso a servicios red, la ejecución de software auto-contenido o generado por la propia aplicación, como comandos AppleScript, Node.js, etc.

Una aplicación sólo puede ser firmada si su núcleo de código se mantiene sin cambios. En el caso que nos ocupa, (nuestras aplicaciones Omnis Studio) dicho núcleo se encuentra en el "Omnis package", por ejemplo:

Omnis Studio  10.0.app/Contents/MacOS/

Las carpetas "Firstruninstall" y "Application Support"


El resto de archivos susceptibles de ser modificados desde dicho núcleo de código Omnis, y que  también forman parte de nuestra aplicación terminada, (como por ejemplo nuestras librerías) deberán  ser reubicados como datos de la aplicación para el/los usuario/s en sus directorios de trabajo particulares, es decir, en sus carpetas "Application Support":

~/Library/Application Support/Omnis/

Para ello y cuando el usuario ejecuta por primera vez, nuestra aplicación Omnis, se comprobará la existencia de una carpeta denominada "firstruninstall" dentro del "Omnis package". Cualesquiera archivos contenidos en esta carpeta serán copiados en otra dentro del "Application Support" con el nombre asignado al "Omnis package", por ejemplo:

~/Library/Application Support/Omnis/MiAplicacionOmnis
o
~/Library/Application Support/Omnis/Omnis Studio 10.0

La copia no se realizará, si la carpeta de destino ya existe, evitándose así la perdida accidental de cualquier cambio realizado posteriormente. Si la carpeta es eliminada, cambiada de nombre o lugar, será copiada nuevamente tras la ejecución de nuestra aplicación, pero con su contenido inicial.

La idea más interesante de éste modo de funcionamiento, es la de permitirnos (a los desarrolladores) colocar todos los archivos y carpetas requeridos por nuestro "runtime-omnis" y que conforman nuestra aplicación terminada, (como por ejemplo, las carpetas: "icons", "studio", "startup" e incluso una posible carpeta "xcomp" y/o "jscomp", con extensiones no incluidas en el núcleo Omnis) en la carpeta 'firstruninstall', creándose así un procedimiento de instalación de nuestra a aplicación al usuario final.

Una vez realizada la copia en el "Application Support" Omnis sólo actualizará los archivos contenidos en ese lugar dejando la carpeta original "macOS" sin cambios y por tanto con su firma válida.

¿Qué ocurre si necesito actualizar o añadir algún componente ubicado en "xcomp" o "jscomp"?


Puesto que la aplicación está firmada, cualquier componente externo deberá ser añadido o actualizado en la carpeta de datos del usuario. Esto permite que la parte de código firmada permanezca inalterable. De modo que, cualquier componente externo podrá colocarse en:

~/Library/Application Support/Omnis/Omnis Studio 10.0/xcomp
o
~/Library/Application Support/Omnis/Omnis Studio 10.0/jscomp

Si no existe la carpeta requerida podrá ser creada por el usuario. Omnis, siempre cargará primero los archivos contenidos de la carpeta del usuario y después los de su propio núcleo Omnis, si el componente a cargar ya existe, (es decir fue cargado desde la carpeta del usuario) será ignorado, la carpeta del usuario siempre tiene prioridad.

¿Qué debo hacer para personalizar la instalación de mi aplicación y cambiar la firma?


En el momento de distribuir nuestra propia aplicación, deberemos primero actualizar los archivos incluidos en el "Omnis package" a fin de que contenga nuestras librerías, nuestros componentes y nuestro propio nombre de aplicación (no desearemos que se llame Omnis). Estos archivos deberán ser colocados en la carpeta "firstruninstall", los cuales serán tratados como datos del usuario y por tanto serán copiados a la carpeta "Application Support". NOTA: Para el sistema "Windows" existe un procedimiento similar a éste, pero no es objeto de éste artículo.

Por defecto, los datos de usuario para cada instalación de una aplicación Omnis, estarán ubicados en una sub-carpeta de "Application Support" denominada “Omnis” y el nombre del "Omnis package" será el utilizado para denominar a la carpeta de nuestra instalación en particular.

Por ejemplo, para un "Omnis package" con el nombre... /Applications/Omnis Studio 10.0.app
...sería: ~/Library/Application Support/Omnis/Omnis Studio 10.0

..y para un "Omnis package" con el nombre... /Applications/MiAplicacionOmnis.app
...sería: ~/Library/Application Support/MiAplicacionOmnis

Para personalizar la sub-carpeta, podremos editar recurso 25599, y para personalizar la carpeta de instalación, el 25600. Ambos recursos se encuentran en el archivo "localizable.strings" para el idioma en uso, por ejemplo:

/Omnis Studio 10.0.app/Contents/Resources/English.lproj/Localizable.strings
o
/Omnis Studio 10.0.app/Contents/Resources/Spanish.lproj/Localizable.strings

Ambas entradas están vacías, permitiéndose así, su comportamiento por defecto.

"CORE_RES_25599" = "";
"CORE_RES_25600" = "";

Una vez actualizados y ubicados éstos archivos, el paquete Omnis, tendrá que ser vuelto a firmar, con nuestra propia identidad firma. No es posible volver a firmar un archivo que ya está firmado, por lo que la firma anterior deberá ser eliminada antes de volver a firmar. Esto lo haremos de forma recursiva,  a fin de que afecte a todo el "Omnis package" mediante el siguiente comando:

xattr -r -d com.apple.FinderInfo

Por ejemplo:

xattr -r -d com.apple.FinderInfo /Applications/MiAplicacionOmnis.app

Naturalmente la firma pertenece al propietario de la aplicación y por tanto se requiere de una "identidad para la firma de código", desde donde generar y añadir el correspondiente certificado en su modalidad "development" o "production", sino dispone de una podrá obtenerla desde el "Apple developer member center" en su sección "Certificate". Para realizar la firma, el equipo desde el que esté haciéndolo, deberá tener instalados tanto el certificado, como su clave privada. Para comprobar si dispone de una firma de código válida en su equipo, utilice el siguiente comando desde el terminal:

security find-identity -p codesigning -v

Por ejemplo, producirá la siguiente salida donde se muestra su "key" e "identity":

1) 44FFBA8B7DFFB1AFFF36FD0613D6E5FC61FF8DFF "Certificate" (CSSMERR_TP_NOT_TRUSTED)
2) B3EF62FF18E0FFB83D3A8FF3672CF80EFF367FFF "Mac Developer: John Doe (24FFEXFF39)"
2 valid identities found

Para finalmente firmar el "Omnis package" use:

codesign -f --deep --verbose -s

Por ejemplo:

codesign -f --deep --verbose -s "Mac Developer: John Doe (24FFEXFF39)" /Applications/MiAplicacionOmnis.app

Si todo ha ido bien, podrá ver sobre el terminal una línea similar a la siguiente:

:signed app bundle with Mach-O thin (x86_64) [com.myCompany.MyApplication]

De éste modo su aplicación estará firmada y lista para su despliegue, sólo debe ser consciente de que no alterar posteriormente el contenido del "Omnis package" ya que esto anularía la firma. Si desea verificar la firma use el siguiente comando:

codesign --display --verbose=4

La salida de éste comando incluirá información como la autoridad de firma, caducidad, etc.

¿Qué ocurre si necesito actualizar el núcleo de Omnis de mi aplicación final?


Si desea distribuir una actualización del núcleo Omnis (el archivo de programa), sustituyendo el actualmente firmado, deberá hacer lo siguiente:

  • Reemplazar el binario Omnis original firmado por la nueva versión.
  • Volver a firmar Omnis con la misma identidad de firma que utilizó para el original.
  • Usar el binario parcheado de su directorio para su distribución.

Tenga en cuenta que los componentes y otros archivos del usuario pueden ser actualizados sin necesidad de volver a firmar el paquete, ya que las carpetas "xcomp" y "jscomp" residen en la ubicación de datos de usuario, por ejemplo:

~/Library/Application Support/MiAplicacionOmnis

Asegúrese siempre de que el núcleo Omnis que está ejecutando, posea una firma válida mediante el comando:

codesign --display --verbose=4 

07 marzo 2019

Firmado y localización de aplicaciones (Parte 2 de 3)

Personalización de las opciones en el menú del sistema macOS



Tras haber cambiado el nombre "Omnis" por el de nuestra propia aplicación, observaremos que el nombre del menú del sistema MacOS ahora presentará cómo título el nombre de nuestra aplicación, pero siguen apareciendo en él opciones cómo: "Hide Omnis", "Quit Omnis", "Preferences" o "Services" y que (con toda seguridad) desearemos personalizar para nuestra aplicación y según el idioma del usuario. No es el propósito de esta serie de artículos tratar el tema de la localización a otros idiomas de nuestras aplicaciones (tema ya tratado en éste blog) sino más bien, repasar los elementos que permiten la adecuada adaptación de nuestros "runtime-omnis", en cuanto a la creación del paquete final de instalación, de modo que trataremos las llamadas "Studio String Table" (studio.stb) con éste único propósito.

Puesto que llegados a éste punto ya habremos cambiado el nombre del "Omnis app package" por el de nuestra propia aplicación, deberemos cambiar ahora la opciones de su menú principal a fin de que se adecuen a nuestro producto, mediante los pasos siguientes:

  • Abra el "Omnis Catalog" (pulse F9) de Omnis Studio para MacOS
  • Seleccione la pestaña "String Tables" y haga clic derecho sobre "Built-in strings"
  • Introduzca los textos originales sobre la columna de la STRINGID y el texto a cambiar sobre la/s columnas correspondientes al idioma 'en', 'es_es', etc.

Podremos localizar textos específicos a traducir originales de Omnis Studio mediante la opción, "Find strings…" (botón derecho sobre "Built-in strings"), arrastrando y soltando el texto localizado, desde la ventana "Find" sobre la columna "STRINGID", para después añadir su texto traducido.

Cómo ya hemos mencionado, no es el propósito de éste artículo, mostrar como adaptar nuestras aplicaciones a diferentes idiomas, por lo que cuestiones, sobre cómo localizar los días de la semana, meses del año, separadores de caracteres, ordenamiento nacional, etc, tienen en Omnis sus utilidades específicas para éstos asuntos, pero no es nuestro objetivo ahora.

Sólo haremos un apunte en cuanto al comportamiento de Omnis, cuando cambiamos el atributo de idioma en sus preferencias ($language).

Cuando cambiamos la propiedad "$language" Omnis la aplica de inmediato, por lo que no necesita  reiniciar la aplicación ni ninguna otra acción, pero en caso de que la base de datos de localización (la llamada omnisloc.df1) esté siendo compartida entre varios usuarios, el cambio de lenguaje, solo será efectivo tras el reiniciado de la aplicación.

Un pequeño apunte final a modo de recordatorio


La notación: $root.$prefs.$language, retorna el nombre del lenguaje actualmente en uso, el cual podemos (del mismo modo) cambiar con efecto inmediato.

La propiedad: $hascurrlangnationalsortorder, es una propiedad boleana exclusiva de los "df1" y accesible mediante (por ejemplo) "$root.$datas.mificherodf1.$hascurrlangnationalsortorder", si es "true" causará que el orden de clasificación se corresponda con el idioma actual.

06 marzo 2019

Firmado y localización de aplicaciones (Parte 3 de 3)

En esta última parte de la serie, tan sólo incluir una punte sobre nuestras aplicaciones "serverless" para dispositivos móviles.


Como ya sabemos, cuando creamos aplicaciones que van a trabajar sin necesidad de conexión con un servidor y que serán instaladas en dispositivos tales cómo teléfonos o tabletas, hacemos uso de la propiedad "$serverlessclientstringtable" para especificar qué "string table" a utilizar junto con nuestro "SCAF", en ella indicamos el nombre del fichero ".tsv", que deberá usarse.

Un par de apuntes


Recordamos que podemos hacer referencia desde el modo "execut on client" al "string table" actual, mediante la función "stgettext()", y asignar textos mediante el prefijo "$st". Además, los métodos de ejecución en el servidor también pueden hacer uso de "stgettext()" para localizar textos en el entorno local del cliente, ya sea mediante la configuración regional recibida desde el dispositivo del cliente, o mediante lo indicado en la propiedad "$stringtablelocale". Teniendo esto en cuenta, indicar que, en caso de que no sea posible localizar la columna para el lenguaje indicado, en el "string table", "stgettext ()" va a retornar los valores que encuentre en la segunda columna de la tabla, sin importar en que idioma se encuentren.

Otro apunte (ya explicado en otro artículo de éste blog) tiene que ver en cómo traducir a diferentes idiomas, los mensajes estándar, que Omnis envía al cliente, mencionar que todos ellos están por defecto en idioma inglés, pero que desde la versión 6 de Omnis Studio, se nos proporciona un mecanismo mediante el cual localizar a cualquier idioma dichos mensajes.

En la dirección https://developer.omnis.net/documentation/webdev/index.jsp podemos encontrar un listado de estos mensajes, aunque debemos tener en cuanta que muchos de ellos nunca llegarán a ser mostrados, ya que corresponden más a errores de programación que a fallos del sistema o la comunicación, por lo que no todos, deberán ser traducidos.

Para anular modificar cualquiera de los textos de error predeterminados, si se trata de una aplicación Web, bastara con incluir nuestra propia traducción en la página HTML que contiene el código JavaScript de cliente, pero para el caso que nos ocupa, deberemos colocar los textos en un archivo independiente.

05 marzo 2019

Uso de iconos en Omnis Studio (Parte 1 de 2)

Desde la versión 8.0.1 de Omnis Studio, disponemos de un nuevo procedimiento para la incorporación de iconos a nuestras librerías, denominado "Iconset Studio" y ubicados bajo la carpeta "inconsets", dentro de la cual podremos indicar las sub-carpetas donde localizar los iconos con los que trabajaremos en nuestra librería. Ahora cuando hagamos referencia a un icono para su uso con cualquier componente (por ejemplo, mediante asignar la propiedad "$iconid" de un componente "button"). Nuestra librería lo buscará automáticamente en todo el conjunto "Iconset Studio", según la ruta especificada por nosotros mediante la propiedad "$iconset", o en cualquier otra ubicación para iconos. El orden de búsqueda ahora queda establecido del modo siguiente:


  1. En el "Iconset Studio" personalizado para nuestra librería, una sub-carpeta de "inconsets", ruta indicada en su propiedad "$iconid".
  2. En la tabla #ICONS de nuestra librería. (si existe)
  3. En los archivos de datos para iconos, los llamados ".df1", excepto "omnispic" y "userpic", (si existen)
  4. En la sub-carpeta denominada "studio" situada dentro de "inconsets"
  5. En los archivos "Omnispic.df1" y "Userpic.df1".

El cuadro de diálogo "Select Icon", (que se muestra tras hacer clic en "$iconid" desde el "Property Manager") permite seleccionar un icono para nuestro componente, ahora mostrará los ubicados en "studio" y en la carpeta indicada mediante la propiedad "$iconset" de nuestra librería, (si se especifica).

Un apunte que añadir a éste nuevo concepto, es que la carpeta "html/icons" tambien es compatible con el "Iconset Studio", pero se espera que poco a poco, todos los conjuntos de iconos sean ubicados bajo el directorio "/iconsets" localizable bajo el directorio principal de instalación Omnis.

Ahora podremos crear íconos HD desde cualquier software para la edición de imágenes y colocarlas directamente en el directorio Omnis, en la carpeta "inconsets". El icono o los archivos de imagen deben guardarse utilizando el tipo de archivo PNG y colocarse en una subcarpeta de "inconsets". Cada subcarpeta representa lo que se llama un "Iconset Studio", que es una colección de iconos con nombre. El nombre de la sub-carpeta se convierte en el nombre del "Iconset Studio" que luego aparecerá en el cuadro de diálogo de selección de iconos y cuya ruta es especificada bajo la propiedad "$iconset", de nuestra librería. 

Deberemos tener en cuenta que un "Iconset Studio" no puede denominarse igual que uno de nuestros "datafile" de iconos, o mediante alguno de los nombres reservados: "lib", "studio" o "studioide".

Mas adelante publicaré un artículo en este blog, explicando como crear y usar imágenes, teniendo en cuanta los diferentes tamaños (16x16, 32x32, 48x48) y resoluciones para soportar los monitores "retina" (_2x, _15x, etc)

Es posible que queramos utilizar algunos de los iconos actualmente ubicados en los archivos de datos o bien agregar o reemplazar algunos de ellos con versiones de mayor resolución. Para permitirnos exportar los existentes, se dispone de una herramienta en el menú "Tools>>Add Ons", denominada "JS Icon Export", disponible desde el cuadro de diálogo "Web Client Tools" (desplácese hasta el final de la lista "Web Client tools").

La herramienta ‘JS Icon Export’ exportará todos los iconos contenidos del archivo seleccionado y los colocará en una sub-carpeta de "iconsets", aplicando los nombres de archivo correctos. Tenga en cuenta que (tras esto), la propiedad "$iconid" de un control, ahora hará referencia al archivo externo y no a la imagen en el archivo de datos y que Omnis ahora buscará los iconos, según el orden que ya hemos mencionado.

Si el mismo conjunto de iconos es incluido en otra carpeta, (después de que se haya encontrado) se ignoraran las carpetas subsiguientes y se escribirá un error en "iconsetlog.txt", ubicado en la carpeta "Studio".

Si se está usando un servidor omnis web, todos los conjuntos de iconos deberán estar en la carpeta "html/icons" del servidor web.

04 marzo 2019

Uso de iconos en Omnis Studio (Parte 2 de 2)

Importante indicar en primer lugar, que los procedimientos que permite guardar iconos en #ICONS o en archivos (como “Omnispic”) asignándoles un ID ($iconid), por compatibilidad hacia atrás, continúan funcionando, pero ahora sólo resultarán útiles con iconos en 16x16 pixeles. Debemos tener en cuenta, que si nuestras aplicaciones son ejecutadas en una pantalla HD y nuestras librerías aún usan éste tipo de iconos, Omnis intentará localizar un ícono correspondiente en 32x32, de no existir se usará la imagen 16x16 pero su apariencia visual resultará muy pobre. Para conseguir que sus antiguos iconos 16x16 se vean bien en alta definición, deberá crear una nueva versión de cada imagen a 32x32 píxeles e importar cada una de ellas al archivo de datos o #ICONS, bajo la sección 32x32 que encontrará en la misma página de iconos, usando los mismos identificadores o ID, que los usados con la versión 16x16.


Si ha estado ya utilizando iconos en 32x32 o 48x48 píxeles en sus librerías y lo que quiere es que se vean correctamente en pantallas HD, deberá adaptar sus actuales librerías para su uso con el nuevo “Iconsets Studio”, lo cual implica disponer de archivos de imagen separados y ubicados en carpetas, las cuales permiten la inclusión de imágenes para iconos de hasta 96x96 píxeles (es decir, 2 veces el tamaño del icono más grande el de 48x48. Los “iconsets” son compatibles tanto con las clases “remote-form”, como con las habituales clases “window”, pero no podrán usarse con los antiguos plug-in ”’Web Client”, e 'iOS Client’.

Denominación de archivos imagen


Cada archivo de imagen dentro de un conjunto de iconos, deberá seguir la siguiente convención: 

texto_id_tamañoyestado_resolución.png

  • "texto" Es el nombre de la imagen. Aparecerá en el cuadro de diálogo del selector de iconos, mientras asigna el “$iconid” de un objeto.
  • "id" es el ID (valor entero positivo) utilizado como ID del icono. Deberá estar en el rango de 1 a 10.000.000 
  • "tamaño" es el tamaño expresado en píxel CSS de la imagen independiente de su resolución, lo que significa que éste valor no cambiará, para con todas sus diferentes resoluciones. Su valor debe ser expresado en la forma “x”, los valores 16x16, 32x32 y 48x48 deberán existir siempre, ya que corresponden a los tamaños estándar admitidos por Omnis.
  • "resolución" es el factor que identifica su densidad de píxeles, la cual deberá expresarse del modo siguiente:  
    • "_ 2x" para dispositivos HD o pantalla Retina.
    • "_15x" para ciertos dispositivos, como por ejemplo teléfonos con una densidad de píxeles de 1.5x. no será necesario especificar valor alguno para dispositivos con una resolución estándar, o equivalente a _1x

Los archivos (o nombres de carpetas) que no cumplan con las convenciones especificadas serán ignorados.

Ejemplos válidos de nombres de archivo son: 

pencil_1657_16x16.png 
Icono con "estado" normal, de tamaño 16x16, con ID 1657, para dispositivos con resolución estándar
pencil_1657_16x16_2x.png 
Icono con "estado" normal, de tamaño 16x16, con ID 1657, para dispositivos con resolución HD
check_1658_32x32c_2x.png 
Icono con estado “c”, de tamaño 32x32, con ID 1658, para dispositivos con resolución HD (ver más abajo lo que significa su "estado"

Se deberá tener en cuenta que los nombres de los archivos de imagen no distinguen entre mayúsculas y minúsculas y deben ser únicos para con todas la plataformas y sistema de archivos (los nombres repetidos serán ignorados).

Iconos para casillas de verificación


Como caso especial, es posible implementar iconos que permiten diferentes estados, tales como casillas de verificación y botones-radio.

  • "estado" es el estado en que se encuentra el icono (“marcado”, “resaltado” o “normal”) y puede ser uno de los siguientes: (dejarlo en blanco indica su estado “normal”).
    • “c” corresponde a la situación de “marcado” del icono
    • “h” corresponde a la situación de “resaltado” del icono
    • “x” corresponde a la situación de “marcado” y “resaltado” del icono
Si no está seguro de que iconos necesitará crear y cual será su denominación, puede optar por examinar los contenidos en la carpeta “iconsets/studioide”, aquí podrá encontrar archivos de imágenes de diferentes tamaños, tal y como son requeridos para su uso con Omnis Studio. Pero tenga en cuenta que no puede usar los iconos de esta carpeta, sin adquirir antes la licencia adecuada. Use un esquema de nombres similar a éste para con sus propias creaciones.

Imágenes escaladas


No es estrictamente necesario crear una imagen del icono para cada una de las posibles resoluciones, aunque sería recomendable hacerlo si se desea obtener una mejor apariencia. No obstante Omnis puede hacer uso de la imagen que mas se acerque a la resolución deseada, escalando la misma, en éstos casos es mejor forzar a que sea el propio Omnis quien efectúese el escalado en lugar de hacerlo nosotros mismos. En estos casos, lo mejor será proporcionar a Omnis la imagen con la mayor resolución posible, para dejar que Omnis reduzca las imágenes de resolución más baja, pero tenga en cuenta que el escalado puede producir resultados no esperados.

Cuando se produce una conexión (aplicaciones Web), el cliente envía su resolución al servidor de aplicaciones Omnis. Lo cual permite a Omnis hacer uso  del ícono apropiado.

Preguntas frecuentes


¿Cómo hacer uso de Imágenes con tamaños “no estándar”?

Naturalmente podemos disponer de imágenes de tamaño diferente al estándar (16x16, 32x32, 48x48) siempre y cuando incluyamos en su nombre de archivo las especificaciones de tamaño. Por ejemplo, podemos crear una imagen de 100x200 píxeles, nombrándola como "midibujo_1688_100x200.png", su versión en alta resolución (a 200x400 píxeles), tendría como nombre ”midibujo_1688_ 100x200_2x.png”, (esto sería equivalente a una “Icon Page” de Omnis )

¿Cómo agregar “Iconsets” al servidor de aplicaciones web?

Cuando se trate de una aplicación que queremos hacer disponible en la Web, necesitaremos copiar todos los “inconsets”utilizados en nuestros formularios desde el directorio “/iconsets” en de nuestra versión “developer” a la carpeta “/icons” situada al mismo nivel que nuestros archivos “.htm” de nuestra aplicación, es decir, en el lugar donde estén ubicados nuestros ficheros “.htm” en el servidor web: cada “iconsets” deberá aparecer como una sub-carpeta de la carpeta “/icons” y deberá contener todos los archivos PNG que precise nuestra aplicación.

¿Cómo configuro mi librería para el uso de “inconsets”?

Las librerías poseen una preferencia denominada “$iconset” ($libs.LIBRERIA.$Prefs) y es aquí donde deberá figurar el nombre del “iconset” que usaremos con nuestra librería, de éste modo Omnis sabrá dónde buscar los identificadores de nuestros iconos. En cada ocasión que trabajemos con esta librería, Omnis buscará los iconos dentro del “iconset” especificado para ella, antes de hacerlo en el resto de posible ubicaciones.

¿Cómo gestiona Omnis los posibles errores al asignar un ID?

Cualquier error causado al configurar el ID de un icono para los objetos, será enviado a un archivo de errores denominado “iconsetlog.txt” ubicado en la carpeta “html”.

¿Puedo hacer uso de imágenes mediante la indicación de una URL?

Al asignar el “$iconid” para un objeto bajo “jsClient”, podemos optar por indicar una URL. Si el valor asignado consiste en una cadena de caracteres que contiene al menos un carácter ”/“, Omnis lo tratará como una URL generada por la función “iconurl”, esto significa que podremos referenciar archivos de iconos alternativos, según las diferentes resoluciones de pantalla de los clientes, Omnis elegirá el icono correcto. En caso de hacerse la asignación mediante programación y siempre que el valor asignado no sea un ID de icono (un entero o un entero + una constante de tamaño), Omnis entenderá que se trata de una URL generada por la función “iconurl” eligiéndose el correspondiente a la resolución del cliente. Las URL’s que necesite podrán ser generadas mediante el uso de la función “iconurl()” en el método “$construct()” del “remote-form” y ser guardadas en una variable de tipo “list” en el ámbito de la instancia, con el fin de usarlas en el código que realice la asignación de imagen a los diferentes objetos.

¿Cómo gestionar dinámicamente la asignación de imágenes, para (por ejemplo) un componente “tree lists”?

Los “Tree control” de jsClient, han sido modificados, de modo que su columna “iconid” ahora es “iconurl”, y su propiedad “$iconurlprefix” ahora resulta redundante, aunque se sigue manteniendo por compatibilidad hacia atras. La columna “iconurl” deberá ser definida como de tipo carácter y rellenarse utilizando una función “iconurl(iconid)”, que devuelve una cadena URL con el nombre del archivo de imagen o bien una lista separada por punto y coma, con los nombres de los archivos en caso de iconos con varias resoluciones. Esto es lo que permite a Omnis elegir el icono correcto según la resolución de pantalla del cliente conectado.