Etiqueta

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.