Javascript: cerrar una ventana automáticamente cuando se cierre el diálogo de impresión.

Veamos el caso práctico que me encontré: una aplicación web que para imprimir un documento abre un popup con la previsualización del mismo, cuando pulsas el botón de imprimir debería abrirse el diálogo de impresión y después de aceptar el popup debería cerrarse… pero resulta que si bien en el Safari y el Internet Explorer lo hace correctamente, en el Chrome o en el Firefox se cierra la ventana antes de que se abra el diálogo de impresión. ¿Cómo hacemos para que se cierre en todos los navegadores automáticamente esa ventana tras confirmar el diálogo de impresión?

Pues como el objeto window en Javascript es capaz de reconocer el evento de que se ha cerrado la ventana de impresión (evento onafterprint), bastará con que programemos que se ejecute window.close() cuando se de dicho evento. El código sería:

window.onafterprint = function () {
    window.close();
}

Protección de datos: Derecho de supresión ¿En qué consiste?

El derecho de supresion viene recogido en el artículo 17 del RGPD y básicamente nos garantiza que podremos solicitar al responsable del tratamiento de nuestros datos personales que los elimine y este tendrá que hacerlo, siempre que se cumplan ciertas circunstancias:

  • Si tus datos personales ya no son necesarios en relación con los fines para los que fueron recopilados, o si el fin del tratamiento ha cambiado.
  • Si el tratamiento se basaba solo en tu consentimiento y lo has retirado.
  • Si previamente has ejercido tu derecho de oposición para solicitar que no se ejecute el tratamiento.
  • Si tus datos se consiguieron de forma ilegal o se trataron de forma ilícita.
  • Si la información se procesa a través de la oferta servicios de la sociedad de la información a un menor de edad.
  • Si deben eliminarse para cumplir con una obligación legal establecida por el derecho de la UE o de algún estado miembro.

Este derecho fue uno de los más comentados cuando se lanzó el reglamento pues se permite aplicarlo de manera específica a los buscadores de internet, una práctica que se conoció como “derecho al olvido“, que permite eliminar nuestros datos de los resultados de las búsquedas de, por ejemplo, Google o DuckDuckGo y que levantó cierta polémica en su momento, pues se considera que este derecho puede entrar en colisión con los derechos a la libertad de información y libertad de expresión.

También hay que puntualizar que este derecho no es ilimitado, la supresión de los datos no será posible cuando estos sean necesarios para el cumplimiento de una obligación legal, para el cumplimiento de una misión realizada en interés público o en el ejercicio de poderes públicos conferidos a la persona responsable, por razones de interés público, en el ámbito de la salud pública, con fines de archivo de interés público, fines de investigación científica o histórica o fines estadísticos, o para la formulación, el ejercicio o la defensa de reclamaciones, además de los derechos a la libertad de información y de expresión mencionados ya en el párrafo sobre buscadores.

Para ejercitar este decho la AEPD nos facilita desde su web un formulario que podemos cubrir para ejercer este derecho.

Sobreescribir la función javascript window.alert() nativa del navegador por una personalizada

Resulta me veía con una cuestión trabajosa: en una aplicación web tenía que hacer una ventana de alerta personalizada que sustituyera al window.alert() nativo del navegador. La parte de diseñar la nueva ventana no era tan laboriosa, la labor pesada y repetitiva venía del tener que localizar todas las ocurrencias de window.alert() diseminadas por el código y cambiarlas por la nueva función. Y ahí pensé “¿y si pudiera cambiar el window.alert() por la nueva función?“. Hay un fichero de javascript que está presente en todas las pantallas, así que solo tendría que introducirlo allí.

¿Y cómo reescribimos la función window.alert()? Pues simplemente así:

window.alert = function(){}

Asignando una nueva función a window.alert() sobreescribe su comportamiento nativo por el indicado. Veámoslo de nuevo con más o menos todo el código que lleva:

//alert personalizado, recibe el mensaje a mostrar y el elemento sobre el que poner el foco si es un mensaje de error
window.alert = function(msg,el,isError){
	var left = parseInt((screen.width - 750) / 2);
	var top = parseInt((screen.height-300)/2);
	var ventana = window.open("AvisoNuevo.asp?e="+isError+"&m="+msg,"modal","width=750,height=300,top="+top+",left="+left+",scrollbars=auto,resizable=no,menubar=no,toolbar=no");	
	if(isError && el!=null && el!="" && el!=false){			
		try {
		  document.getElementById(el).focus();
	    }
	     catch (e) { return; }
	}
}

Electron.js: Error “require is not defined” y conflictos entre require y jQuery.

Aquí sigo trabajando en mi primera aplicación corriendo sobre Electron.js y me están saliendo canas por diversos errores que me aparecen a la hora de integrar. Uno de ellos ha sido recibir constantemente el error “require is not defined“. Una de las causas de este error suele ser que la integración con NodeJS está deshabilitada, por seguridad este parámetro viene deshabilitado por defecto para evitar ataques que puedan, por ejemplo, borrar ficheros de nuestro equipo remotamente si cargamos una página no segura. En caso de que estemos cargando una aplicación local podemos ir al main.js y activarlo desde allí configurando las preferencias de nuestro ventana web:

 webPreferences: {
            contextIsolation: false,
            nodeIntegration: true,
            nodeIntegrationInWorker: true,                                                  
            enableRemoteModule: true                                                                     
 }

Es posible que esta configuración nos genere un nuevo conflicto entre jQuery y NodeJS ya que ambos intentan sobreescribir la función require(). Esto puede solucionarse añadiendo esta línea antes de la carga de jQuery:

<script>
		window.nodeRequire = require;
		delete window.require;
		delete window.exports;
		delete window.module;
</script>

Trasponer una matriz en Python

La definción técnica del término matriz traspuesta es “el resultado de reordenar la matriz original mediante el cambio de filas por columnas y las columnas por filas en una nueva matriz”. Imaginemos que tenemos un array en Python tal que así:

x = [[1,2,3],
  [2,3,1],
  [3,1,2]]

Ahora queremos meter esa matriz en otra variable, pero tras trasponerla. Si bien en la mayoría de los lenguajes es posible trasponer la matriz utilizando una serie de bucles anidados, en Python podremos hacerlo de forma muy sencilla sirviéndonos de la función zip() y el operador *. Para almacenar la matriz traspuesta en otra variable bastaría con hacer:

y=zip(*x)

Y solo con esa línea ya habría traspuesto nuestra matriz original.

Televisión en tu PC o tablet: plataformas de streaming gratuitas.

Hace años que no tengo tele, en concreto desde el 2016. No es ningún tipo de alegato pseudointelectual como el que hacía un profesor de filosofía que tuve en el instituto, que decía no tenerla para mantener su cabeza limpia y pura y seguía con una larga reivindicación de la radio (como si las tertulias radiofónicas no fuesen también pozos de desinformación y embrutecimiento, vamos).

En todo caso, aquí ya todos sabéis que como mucha gente veo películas, series, documentales y retransmisiones deportivas, así que no hay nada de reivindicación en decir que no tengo aparato de televisión, simplemente utilizo un ordenador viejo para ello porque me resulta más práctico y porque así tengo en el mismo electrodoméstico televisión, radio, reproductor de música y consola de videojuegos. Si como yo eres de los que no van a invertir en una tele porque le resulta más barato o más cómodo usar un ordenador, pero no quieres dejarte una parte de tu salario en pagar servicios de streaming, aquí van unas cuantas opciones gratis para usar tu ordenador o tablet como tele.

Photo by Tim Mossholder on Pexels.com

Tivify: Tivify es una plataforma de streaming que tiene tres planes de precios, uno de los cuales es gratis (que es lo que nos interesa en este artículo). Básicamente lo que incluye esta plataforma son canales de TDT que emiten en España, tanto los de nivel estatal como los autonómicos y a mayores incluye algún canal internacional de noticias. Si bien muchas de estas cadenas son también accesibles a través de sus webs oficiales en esta plataforma consigues la comodidad de poder tenerlas todas juntas. Tiene además dos planes de pago que aumentan la capacidad para guardar grabaciones, dan acceso a canales temáticos y permiten vincular más dispositivos a la cuenta.

VIX: Se trata de una plataforma de streaming financiada por publicidad, incluye series, cine, concursos, gastronomía o programas de true crime. Hay sobre todo muchas series y telenovelas producidas en América Latina, programas para televisiones locales y su sección de cine se compone principalmente de telefilmes o producciones “directas a vídeo“. Ojo, que si te gusta el cine de bichoños cutres apocalípticos te puedes encontrar una buena cantidad de joyitas para tardes de domingo lluviosas.

iQiyi: ¿Eres fan del K-Pop o de la cultura surcoreana? En los últimos años los productos de entretenimiento provenientes de Corea del Sur han ganado mucha popularidad en occidente. La plataforma iQiyi ofrece series y programas de espectáculos surcoreanos. Además también tiene una enorme oferta de cine de serie B producido en China, películas de acción de Hong Kong, algo de anime, concursos musicales de otros países asiáticos… Ofrecen un plan de pago VIP con acceso a algunos contenidos exclusivos, vídeo en alta definción, descargas para ver sin conexión, etc.

PlutoTV: De PlutoTV ya hablamos aquí en el pasado, cuando todavía no estaba oficialmente en España pero podía ser accedido. Es una plataforma con un montón de canales que emiten programas de televisión de forma lineal, la mayoría de ellos temáticos y dedicados a emitir un solo programa o serie las 24 horas del día. Estos canalaes van cambiando con el paso del tiempo y también se van añadiendo nuevas opciones. Al momento de escribir esto hay más de 70 canales y la promesa de la plataforma es llegar a 100 antes de acabar el año.

RakutenTV Free: RakutenTV es una plataforma principalmente de pago, pero tiene una pequeña sección de su catálogo que puede ser accedida de forma gratuita. Esta oferta gratis incluye principalmente programas de reportajes deportivos o sensacionalistas, programas y series infantiles y una selección de películas que se renueva mes a mes. No esperes estrenos o grandes clásicos, pero siempre hay alguna película decente.

La Liga Sports TV: Si lo tuyo son las retransmisiones deportivas este canal financiado por la La Liga (la empresa que organiza la liga de fútbol profesional en España) ofrece deportes varios como fútbol sala, gimnasia, atletismo, balonmano, baloncesto, fútbol. Al día en que escribí esto ofertaban la Liga Nacional de Fútbol Sala española, la liga ASOBAL de balonmano, las ligas LEB oro y LEB plata de baloncesto (segunda y tercera categorías del baloncesto español), la Premier League Rusa de fútbol, la Champions League Asiática de fútbol y varios campeonatos nacionales españoles de distintos deportes, incluso alguna cosa de e-sports.

UEFA TV: Edito para añadir esta plataforma para los futboleros. No tiene gran cosa: resúmenes semanales de las competiciones europeas dependientes de la UEFA (fútbol masculino, femenino y fútbol sala) y algunos reportajes y entrevistas. Lo interesante es que de vez en cuando ponen partidos enteros en directo: no te esperes la Champions o la Europa League porque los derechos se venden caros, pero sí partidos de torneos de categorías inferiores, partidos de selecciones absolutas de la League of Nations o de las fases de clasificación para Eurocopas o Mundiales.

SQL-Server 2008 R2: “El valor de la línea de comandos INSTALLSHAREDWOWDIR no es válido. Compruebe que la ruta de acceso especificada es válida y diferente de la ruta de acceso de INSTALLSHAREDDIR”

Pues llevo unas horas pegándome con este problema. Ayer un compañero se puso a instalar un SQL-Server 2008 y se le ocurrió poner la misma ruta para los recursos compartidos de la versión de x86 y para la de 64 bits. Cuando llegué hoy a restaurar la base de datos que tenía que ir en ese equipo me encontré con que no podía restaurarla.

Decidí que lo mejor sería desinstalar el motor de base de datos y volver a instalarlo, pero me saltó el error del título: “El valor de la línea de comandos INSTALLSHAREDWOWDIR no es válido. Compruebe que la ruta de acceso especificada es válida y diferente de la ruta de acceso de INSTALLSHAREDDIR. Como el tiempo apretaba y no acababa de encontrar en google ninguna solución para cambiar esas rutas pensé que la solución rápida sería instalar otra instancia con otro nombre y usar esa, dejando la primera mal instalada apagada, pero me encontré con que el instalador tampoco me permitía cambiar la ruta duplicada al iniciar una nueva instalación.

Busqué en Google pero no había casi pistas, de hecho el ejemplo que encontraba no solía ser para esto problema sino para otro en el que uno de los directorios está definido y el otro no, que no era el caso. La cosa era que si el programa de instalación estaba abriendo ya con una ruta cargada esa ruta tenía que estar definida en algún sitio. Fiándome de un foro busqué un fichero que se llamase config.ini o ConfigurationFile.ini sin suerte. Al final encontré esta entrada en otro blog donde alguien había tenido ese problema cuando intentó actualizar de un 2008 a un 2014.

La cosa es que la ruta está guardada en el registro del sistema, en concreto en la clave HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-518\Components\0D1F366D0FE0E404F8C15EE4F1C15094 para INSTALLSHAREDDIR y en la clave HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\ Components\C90BFAC020D87EA46811C836AD3C507F para INSTALLSHAREDWOWDIR. Decidí modificar todos los valores y cambiarlos por la ruta por defecto que suele usar SQL-Server para no tener ya más quebraderos de cabeza. Tras el cambio no tuve ni que reiniciar, volví a abrir el programa de instalación y me permitió desinstalar y volver a instalar correctamente.

Electron.js: obtener el nombre, la versión o la arquitectura de nuestro sistema operativo

Bueno, pues hace unas semanas que en el trabajo estoy currando con el framework Electron.js, que básicamente nos permite transformar aplicaciones web en aplicaciones nativas de escritorio. En mi caso es para actualizar un software de intranet que dependía de ActiveX y de Internet Explorer en exceso. En todo caso vamos a ver algunas cosillas sobre Electron, una de ellas es ¿cómo puedo obtener los datos sobre mi sistema operativo? Pues Electron incluye un módulo para eso:

Lo primero será importar el módulo “os“, para que la aplicación pueda trabajar con el sistema operativo anfitrión. Para el ejemplo crearemos una variable llamada también os (por recordarlo bien) para almacenar dicho objeto:

var os = require("os");

Ahora veamos ¿cómo haríamos para ver la arquitectura de nuestro sistema operativo? Pues llamando al método arch().

var arquitectura = os.arch();

¿Y para ver el nombre del sistema operativo? Pues tenemos dos opciones: el método type() nos devolverá el tipo genérico (Linux, Darwin o Windows) y el método platform() nos devolverá un resultado más concreto (darwin,freebsd,sunos,win32…). Finalmente el método version() nos devolverá la versión del sistema operativo:

var tipo = os.type();
var plataforma = os.platform();
var version = os.version();

OpenSSL: verificando claves, mensajes, autoridades…

OpenSSL es uno de los proyectos de software libre más exitosos entre profesionales TIC pues nos ofrece un conjunto importante y completo de herramientas criptográficas. Aunque el nombre haga referencia directamente a SSL, se creó en 1998 como implementación open-source de este protocolo, también implementa desde hace años soporte para el protocolo TLS.

Veamos ahora algunos comandos de verificación con OpenSSL:

Para verificar una clave privada:

openssl rsa -in clavedeprueba.key –check

Para verificar un archivo certificado:

openssl x509 -in archivodeprueba.pem -text –noout

Para verificar la autoridad firmante:

openssl x509 -in archivodeprueba.pem -noout -issuer -issuer_hash

Para verificar un hash:

openssl x509 -noout -hash -in archivodeprueba.pem

Para verificar la fecha de vencimiento de un certificado:

openssl x509 -noout -in archivodeprueba.pem -dates