domingo, 26 de febrero de 2012

Actualizaciones automáticas, instalación de complementos, y Windows haciendo cosas raras

En el sitio de ZinjaI agregé hace un tiempo una sección de complementos y versiones de prueba entre las descargas. Lo que uno encuentra allí son ejecutables de versiones no estables (¿alguna lo es realmente?... no, pero estos no están ni testeados a veces) y archivos para facilitar el trabajo con bibliotecas (templates de proyectos, archivos para el autocompletado, binarios, documentación, etc.). Estos archivos se presentan como comprimidos (zip o tgz) y la "instalación" consiste en que el usuario lo descargue y lo descomprima encima de la instalación original de ZinjaI.

Por el momento sólo hay un complemento (para trabajar con la biblioteca SFML) y encima no muy actualizado, pero me gustaría mejorar esa situación actualizándolo y agregando algunos otros. Dándole vueltas al asunto empecé a analizar la idea de incorporar una opción de menú para instalar los complementos directamente desde ZinjaI. Es decir, que ZinjaI los descomprima donde el sabe de modo que no haya forma de equivocarse, y podría ser que en el futuro, además de descomprimir, también ejecute algunas acciones como alterar configuraciones para colocar botones accesos a las referencias en la barra de herramientas.

De la instalación de complementos desde el mismo programa surgen dos tópicos interesantes para comentar: 1) ¿que tal si hago que ZinjaI acceda al sitio y descargue él los complementos para que el proceso sea todavía más fácil y rápido?, y 2) algunas cuestiones de implementación relacionadas a los privilegios y permisos de usuario que requiere esta instalación.

Respecto al primer ítem, lo que quiero es simplemente dar mi versión de por qué ZinjaI no descarga sus complementos, o lo que sería aún mejor, porque tampoco descarga automáticamente sus actualizaciones. La respuesta es muy simple: no tengo un servidor propio. Todos mis proyectos están alojados en sourceforge, sitio que me provee de forma totalmente gratuita lugar para los archivos instaladores, el sitio web, el repositorio git y si quisiera muchísimas otras herramientas que aún no he explorado como foros, o facilidades para bug-tracking por citar algunas interesantes. Si yo hiciera que ZinjaI descargue automáticamente las actualizaciones, evitaría que el usuario entre al sitio, conozca sourceforge, vea la publicidad, etc. Y eso no me parece muy piola considerando lo que dije antes. Por esto, en lugar de descargar todo, lo que hago en mis programas es abrir el navegador en el sitio en la sección de descargas, para que el usuario pase por sourceforge y vea la publicidad (que no tiene nada que ver conmigo, ni me interesa demasiado, pero es una buena parte lo que mantiene al sitio funcionando y hace que yo lo disfrute, entre otras cosas sin poner un peso). Entonces, mis programas van a seguir enviando al usuario a sourceforge para que él haga la descarga desde su navegador. Más aún, en principio pensé que ni siquiera sería compatible con las condiciones del sitio hacerlo de otra forma, pero algunos proyectos lo hacen, como por ejemplo mingw32, el compilador que uso en ZinjaI. Ya que hay que descargar como 15 paquetes y de versiones particulares para tenerlo andando, ellos ofrecen una herramienta (que no probé, solo leí) que hace las descargas adecuadas y resuelve las dependencias automáticamente. Pero por el momento, como una forma más de agradecer a la gente sourceforge, los seguiré obligando a ver sus publicidades, que después de todo ni siquiera son molestas o demoran el proceso como sí pasa en otros sitios.

El segundo ítem plantea aristas un poco más técnicas. El primer problema que aparece a la hora de querer instalar desde ZinjaI una actualización o complemento es el de los permisos. ZinjaI suele instalarse en "Archivos de Programa" o "Program Files" en Windows, y el usuario "común" en principio no tiene permisos para escribir allí. Por eso al instalar una aplicación cualquiera en Windows Vista o 7 el sistema avisa y pide confirmación antes. En el caso de GNU/Linux, es similar, el usuario podría instalar ZinjaI en /usr/local/share o en /opt, o en algún otro lugar donde no tiene permisos normalmente. Por eso debió instalarlo utilizando sudo. Pues bien, si ZinjaI se ejecuta como hasta ahora, sin pedir permisos de administrador, en estos casos no podrá instalar extensiones. Pero si siempre se ejecuta como administrador/root, se tornará muy molesto, ya que pedirá confirmación/contraseña en cada ejecución, aún cuando querramos hacer cosas que no necesitan tantos privilegios, y esto es lo más usual. La primer solución que se me viene a la cabeza es que ZinjaI se ejecute sin tantos privilegios, y a la hora de instalar actualizaciones invoque a otro ejecutable que sí pida los privilegios, y sólo en caso de ser necesario, ya que si ZinjaI está instalado en el home del usuario no es realmente necesario.
Entonces, ¿cómo hacemos para que el segundo ejecutable pida permisos o no?. En GNU/Linux parece fácil: invocándolo a través del comando sudo, o no. Pero hay un problema, para que el usuario pueda ingresar la contraseña hay que abrir una terminal, y en general cada distribución o instalación tiene su terminal, no hay una universal. Esto en ZinjaI está solucionado ya que ZinjaI usa una terminal para ejecutar sus programas, así que ya tiene esta configuración a mano. Hay que notar que las alternativas gráficas al universal y omnipresente sudo que muestran una ventanita más simpática que la terminal (como la que utiliza Ubuntu), también dependen de cada distribución, y aunque hay algunas más o menos comunes (como gksudo), mi Slackware, por citar un ejemplo, no incluye ninguna de ellas. Por eso, de momento voy a lo seguro, abrir el la terminal gráfica que ya tengo configurada, y usar el sudo de toda la vida. En el caso de Windows, parece que la forma de hacerlo es con el famoso manifest.xml. Este es un archivo xml que se puede colocar separado del ejecutable, pero con el mismo nombre y agregando ".manifest" al final, o dentro de los recursos compilados. Permite indicar, entre otras cosas el nivel de privilegios que el programa necesita para ser ejecutado correctamente. Windows se encargará de pedir confirmación/contraseña si el nivel es más alto que el que el usuario tiene al momento de invocarlo.

Sin embargo, hay un último detalle que me llamó poderosamente la atención (debido a mi ignorancia previa al respecto), y que creo es de lo más interesante de este post: el sistema de Virtual Data Storage (VDS) que los Widonws utilizan desde Vista en adelante aparentemente. El problema surgió porque hice una pequeña función para verificar si se tenía permisos de escritura en una carpeta, para saber si era necesario o no pedir más. La función simplemente intenta crear un archivo y ve si realmente puede. Armé un pequeño main y corrí el programa en una carpeta en la que se suponía que no podía escribir, y el programa me dijo que sí pudo, y de hecho pudo leer los datos escritos y comprobar que coincidían con los que nunca debería haber podido guardar. Lo mejor de todo es que cuando fui con el explorador a buscar el archivo, ¡este no estaba!. Y ahí es donde me pongo verde, maldigo a Bill Gates y me pregunto: ¿pero qué rayos fue lo que pasó?. Después un rato en Google llegué a entender lo siguiente: el VDS le hace creer a los programas que pueden escribir ahí, pero en realidad guarda los datos en otro lado, dentro del home del usuario, donde sí tiene permisos. ¿Qué es esto? Un sistema que pensó la gente de Microsoft para garantizar compatibilidad hacia atrás. Muchísimos programas escritos antes de que Microsoft comenzara a tomar más o menos en serio la seguridad guardaban cosas en sus carpetas (porque sabemos que todo el mundo era administrador en Windows 98 y XP), y entonces iban a tener problemas en Vista o 7. Para eso inventaron el VDS, un engañador de programas que falsifica la estructura del sistema de archivos sin que nadie se entere. Debo decir que lo odié con toda mi alma por ir contra toda intuición y pronóstico y por obligarme a googlear durante un buen rato, pero pensándolo ahora en frío creo que es una solución bastante interesante. De todos modos, lo importante es que esto se aplica solo a los programas que no tienen un manifest, o que no indican en este el nivel de seguridad que requieren. Por eso, para desactivarlo, y hacer que efectivamente falle al querer escribir donde no se puede (que no mienta), solo hay que agregar un manifest y aclarar en él que no queremos privilegios adicionales (lo que en msdn figura como AsInvoker). Todos los días se aprende algo nuevo, ¿no?.

En conclusión, en la próxima versión podrán desde ZinjaI seleccionar el archivo del complemento o versión de prueba que descargaron y ZinjaI se encargará de descomprimirlo donde y como corresponde, pero por el momento no habrá descargas automáticas de ningún tipo, ya que estoy muy conforme con los servicios de sourceforge y espero que mis proyectos sigan ahí un largo rato.

P.D.: por si alguien intenta hacer algo parecido: en Windows, cuando se quiere llamar a un segundo ejecutable con mayores privilegios que el primero, la única forma de lograrlo es usando ShellExecuteEx y colocando "runas" en el campo lpVerb del struct SHELLEXECUTEINFO. Me llevó un buen rato encontrar porqué daba error en lugar de pedir confirmación para ejecutar como administrador una llamada con wxExecute desde ZinjaI al instalador de complementos.

1 comentario:

  1. Me encanta ZinjaI. De a poco estoy migrando a C++ y desde hace un tiempo usando como IDE a ZinjaI y anda de maravillas. Vaya una respetuosa reverencia (y no hago público mi gusto por el motoGP para que no digan que no trabajo por tu culpa).

    Me encantó la justificación para seguir usando sourceforge. La verdad que nunca se me ocurrió y bajar los archivos tampoco es tan terrible como para necesitar si una actualización automática (es más, generalmente el procedimiento es "avisar de la nueva versión y cuando tenga tiempo instalarla", así que no varía mucho el procedimiento entre hacerlo todo desde el programa y tener que ir hasta sourceforge). Si te digo que estoy muuuy agradecido del aviso de versión nueva disponible que está desde hace un tiempo.

    Y para finalizar y siguiendo en plan felicitador...bravo por el nuevo blog, desde ya te aviso que tenés un nuevo lector.

    Saludos
    Magoo

    ResponderEliminar