noviembre 2017

Cadena aleatoria en PHP

Introducción

A veces nos veremos en la necesidad de generar carácteres aleatorios o una cadena o string aleatoria. También puede que necesitemos generar algún NIP o dígitos al azar.

Es por eso que aquí traigo estas funciones que pueden servirnos en un apuro.

Generar cadena alfanumérica

Esta función toma un banco de carácteres (modificable) y elige uno de ellos al azar en un ciclo que va desde 0 hasta la longitud deseada.

function cadenaAleatoria($longitud = 10)
{
	$caracteres = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
	$cadenaAleatoria = '';
		for ($i = 0; $i < $longitud; $i++) {
			$cadenaAleatoria .= $caracteres[rand(0, strlen($caracteres) - 1)];
		}
	return $cadenaAleatoria;
}

La longitud es un parámetro opcional cuyo valor por defecto es 10. De esta manera nos devolverá dicho string con una longitud de 10 (si no llamamos a la función con argumentos).

Generando NIP de 4 dígitos

Si quisiéramos sólo números aleatorios (por ejemplo, para un código de verificación), sería así:

function digitosAleatorios($longitud = 4)
{
	$caracteres = '0123456789';
	$cadenaAleatoria = '';
		for ($i = 0; $i < $longitud; $i++) {
			$cadenaAleatoria .= $caracteres[rand(0, strlen($caracteres) - 1)];
		}
	return $cadenaAleatoria;
}

En este caso, si llamamos a la función sin argumentos nos devolverá 4 números aleatorios en cada llamada.

Generando cadena con la mayoría de carácteres

Tal vez en algún momento necesitemos que nuestro string al azar lleve guiones bajos, guiones, etcétera. Podemos lograrlo de la siguiente manera:

function cadenaAleatoriaLarga($longitud = 10)
{
	$caracteres = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_!"#$%&/()?¡+{}-,;.:[]';
	$cadenaAleatoria = '';
		for ($i = 0; $i < $longitud; $i++) {
			$cadenaAleatoria .= $caracteres[rand(0, strlen($caracteres) - 1)];
		}
	return $cadenaAleatoria;
}

Aquí traerá incluidos signos como !,#,”, etcétera.

Probando funciones

Para probar las funciones podemos hacer un ciclo e ir imprimiendo los resultados, así:

for($x = 0; $x < 5; $x++){
	echo "cadenaAleatoria --> " . cadenaAleatoria() . "<br>";
	echo "cadenaAleatoria con longitud de 20 --> " . cadenaAleatoria(20) . "<br>";
	echo "digitosAleatorios --> " . digitosAleatorios() . "<br>";
	echo "digitosAleatorios con longitud de 20 --> " . digitosAleatorios(20) . "<br>";
	echo "cadenaAleatoriaLarga --> " . cadenaAleatoriaLarga() . "<br>";
	echo "cadenaAleatoriaLarga con longitud de 20 --> " . cadenaAleatoriaLarga(20) . "<br>";
}

Al ejecutarlo, los resultados son lo siguientes:

cadenaAleatoria --> cFY0verQBA
cadenaAleatoria con longitud de 20 --> z9zXaT14Bx27I3dQRVEs
digitosAleatorios --> 8096
digitosAleatorios con longitud de 20 --> 00173793063697953580
cadenaAleatoriaLarga --> q{Z1]vNQo{
cadenaAleatoriaLarga con longitud de 20 --> 2MK.f8QIQ,/3An1Gj)Kv
cadenaAleatoria --> 5RgBB4uGSE
cadenaAleatoria con longitud de 20 --> 5zvkoKAlfaGp0iVJv7T3
digitosAleatorios --> 0065
digitosAleatorios con longitud de 20 --> 51893855213964342617
cadenaAleatoriaLarga --> NA&7vQ,a]X
cadenaAleatoriaLarga con longitud de 20 --> SapTG$R;Rs/LOFi;HEU7
cadenaAleatoria --> X0wr2iBYl4
cadenaAleatoria con longitud de 20 --> haYynZvsfT3ZJRcSbm2l
digitosAleatorios --> 4311
digitosAleatorios con longitud de 20 --> 83632219956881992785
cadenaAleatoriaLarga --> 33fcJT,8NH
cadenaAleatoriaLarga con longitud de 20 --> _8I6UuhsqP:!$4UoUzRy
cadenaAleatoria --> 3VI6xhfOdI
cadenaAleatoria con longitud de 20 --> 6wGXAI1czkQbnQf7SfNI
digitosAleatorios --> 3962
digitosAleatorios con longitud de 20 --> 70233882940602793176
cadenaAleatoriaLarga --> e(74C6q+HA
cadenaAleatoriaLarga con longitud de 20 --> Jug(vg(#+OmgXp)O{Hz,
cadenaAleatoria --> 3XkFiRpMcV
cadenaAleatoria con longitud de 20 --> 1KQoZvQXFyiQUQMM2RoY
digitosAleatorios --> 9571
digitosAleatorios con longitud de 20 --> 84857348895210758209
cadenaAleatoriaLarga --> -vjcP[mr#3
cadenaAleatoriaLarga con longitud de 20 --> #k#0?9C(7Tc0N6YF,9F"

De esta forma podemos generar múltiples carácteres aleatorios. Si quieres generar fechas aleatorias, puedes leer este post.

Quitar o modificar título de archivo MKV

Introducción

Hay ocasiones en las que por una u otra razón (incluso porque a veces es molesto, o porque se nos da la gana) necesitaremos quitar el título que sale al prinicipio de un vídeo en formato MKV. O modificar otras propiedades.

Por suerte, hay gente por ahí que ha inventado una maravillosa herramienta llamada mkvtoolnix que, como su nombre lo dice, te permite editar propiedades y manipular un archivo mkv.

La herramienta es gratis y aquí mostraré cómo descargarla, configurarla y usarla.

Descargando

Para descargarla, nos tenemos que dirigir a este sitio. Una vez ahí, veremos lo siguiente:

Elegiremos la versión que se adapte a nuestro sistema. Recomiendo evitar las que dicen portable. En mi caso, como mi sistema es Windows de 64 bits voy a escoger la primera opción. Si el tuyo es de 32 bits, elige la tercera.

Una vez que se haya descargado, procederemos a instalarlo.

Instalando

Vamos a abrir el archivo ejecutable que se descargó. Si pide permisos de administrador los concedemos.

Primero que nada va a pedirnos el idioma de la instalación. Aquí tenemos que elegir español.

Nos dará la bienvenida. Presionamos Siguiente.

 

Aquí elegimos la ruta de instalación. Podemos cambiarla si lo deseamos, pero no lo recomiendo. Una vez configurado, hacemos click en Siguiente.

Finalmente tenemos que elegir la carpeta del menú inicio. De nuevo recomiendo dejar todo como está y hacer click en Instalar.

Sólo resta esperar para que la instalación termine.

Una vez terminada hacemos click en Siguiente y Terminar. Es momento de configurarla y agregarla a la variable PATH.

Configurando

Debido a que esta herramienta se ejecuta en la línea de comandos, necesitaremos agregarla a la variable path de nuestro sistema para que pueda ser llamada desde cualquier lugar.

Para ello, abrimos una consola o símbolo del sistema y escribimos lo siguiente:

set PATH=%PATH%;C:\Program Files\MKVToolNix

Lo que hace ese comando es agregar la ruta de instalación de MKVToolNix al path del sistema. Así, todos los archivos .exe que están dentro de la carpeta podrán ser invocados desde cualquier lugar sin tener que escribir dicha ruta completa.

Ahora sí podemos probar.

Cambiando título

Para cambiar propiedades de un archivo o fichero MKV usamos mkvpropedit. En este caso, vamos a cambiar el título, por lo que su sintaxis es:

mkvpropedit "NombreArchivoMKV" -e info -s title="Nuevo título"

Voy a poner de ejemplo un episodio de la serie Rick y Morty. Lo abriré con VLC, el cual muestra el título en la parte superior, y también lo muestra al iniciar el vídeo.

Se ve así:

Por favor noten lo que está encerrado con un rectángulo rojo. Es el título. Por lo regular, la mayoría de personas agregan ahí sus sitio web, nombre, etcétera.

Para quitar esto, vamos a abrir de nuevo el símbolo del sistema y navegaremos hasta donde está el episodio. Es decir, iremos de carpeta en carpeta (desde el cmd) hasta estar en el mismo lugar que el vídeo. En mi caso está en C:\Users\Luis Cabrera Benito\Documents.

Para ir a la carpeta, los comandos son:

Ahora ejecutaré el comando para editar las propiedades. Así que escribiré lo siguiente:

mkvpropedit "Rick.and.Morty.mkv" -e info -s title="Hola - parzibyte.me/blog"

 

Al presionar enter, el programa nos confirma:

Y si vuelvo a abrir el vídeo, veremos que ahora muestra algo distinto:

Es exactamente lo que escribí entre comillas al ejecutar el comando. De esta forma podemos cambiar la propiedad. Si queremos simplemente quitar el título, usamos:

mkvpropedit "Rick.and.Morty.mkv" -e info -d title

Conclusión

Con este proceso podemos editar propiedades. Pero no sólo se puede cambiar el título, hay millones de cosas que podemos hacer.

Aquí podemos ver la documentación oficial del programa, en donde nos dice los argumentos y la respectiva descripción de cada uno de ellos.

Este tutorial lo pude hacer al investigar cómo remover el título, lo que me llevó a la siguiente página en donde aprendí la sintaxis.

También funciona para MacOS e incluso hay una versión que no necesita escribir comandos; pero eso es arena de otro costal. Además, preferiré mil veces el símbolo del sistema y las terminales.

Gráficas de barras con Chart.js y AngularJS para mostrar estadísticas y reportes

Introducción

En este post daré una pequeña introducción a la creación de gráficas de barras usando el poderoso y superheroico framework AngularJS. Usaremos también la librería llamada ChartJS y otra llamada angular-chart. Lo que hace ésta última es “pegar” o juntar a las dos primeras.

ChartJS puede ser usado sin ningún framework; es decir, podemos hacerlo con simple javascript, pero no queremos eso ahora. AngularJS, como todos lo sabemos, refresca la vista cuando detecta que algo en el controlador cambió, pero como ChartJS no tiene que ver nada con él, las gráficas no se dibujarán de nuevo cuando algún dato cambie. Aquí es en donde viene angular-chart que, como lo dije, funciona como un pegamento y hace que trabajemos con gráficas in the angular way.

Incluyendo archivos

Lo primero que tenemos que hacer es incluir las librerías antes mencionadas. Aquí podemos obtener la última versión estable de AngularJS, aquí la de Chart.js y finalmente aquí la de angular-chart.

Una vez incluidas, nuestro archivo html debería verse así:

<!DOCTYPE html>
<html>

<head>
  <link rel="stylesheet" href="style.css">
  <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.6/angular.min.js"></script>
  <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.0/Chart.min.js"></script>
  <script type="text/javascript" src="https://cdn.rawgit.com/jtblin/angular-chart.js/master/dist/angular-chart.min.js"></script>
  <script src="script.js"></script>
</head>

<body>

</body>

</html>

Declarando app y controlador

Una vez que hemos incluido los scripts vamos a comenzar a declarar nuestra app y nuestro controlador principal. Así que en nuestro archivo de javascript pondremos lo siguiente:

angular
  .module("app", ['chart.js']) // Le decimos que usaremos a chart.js
  .controller("ControladorPrincipal", ["$scope", function($scope) {

  }]);

Ya declaramos todo en nuestro script. Ahora vamos a declararlo en nuestra vista agregando ng-app y ng-controller:

<!DOCTYPE html>
<html>

<head>
  <link rel="stylesheet" href="style.css">
  <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.6/angular.min.js"></script>
  <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.0/Chart.min.js"></script>
  <script type="text/javascript" src="https://cdn.rawgit.com/jtblin/angular-chart.js/master/dist/angular-chart.min.js"></script>
  <script src="script.js"></script>
</head>

<body ng-app="app">
  <div ng-controller="ControladorPrincipal">
  </div>
</body>

</html>

Ahora sí nos vamos a centrar en las gráficas

Creando gráficas

Gráfica de barras

Para pintar nuestra gráfica, usaremos canvas. No tenemos que interactuar directamente con él; simplemente tenemos que definirlo con algunos atributos. Al agregar el canvas nuestra vista debe verse así:

<!DOCTYPE html>
<html>

<head>
  <link rel="stylesheet" href="style.css">
  <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.6/angular.min.js"></script>
  <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.0/Chart.min.js"></script>
  <script type="text/javascript" src="https://cdn.rawgit.com/jtblin/angular-chart.js/master/dist/angular-chart.min.js"></script>
  <script src="script.js"></script>
</head>

<body ng-app="app">
  <div ng-controller="ControladorPrincipal">
    <canvas 
    class="chart chart-bar" 
    chart-data="datos" 
    chart-labels="etiquetas" 
    chart-series="series"></canvas>
  </div>
</body>

</html>

Si nos fijamos bien, el elemento canvas tiene muchos atributos desconocidos o raros. Aquí los explico:

  • id: El id que todos los elementos pueden tener. Es opcional
  • class: Dos clases, la clase chart y chart-bar. Chart-bar puede cambiar dependiendo del tipo de gráfica. Atributo requerido
  • chart-data: El nombre de la variable que se encuentra en el controlador. Estos datos son los que se van a dibujar en la gráfica. Éste debe ser un arreglo, más adelante lo explicaré
  • chart-labels: Las etiquetas o leyendas que serán dibujadas en el plano X
  • chart-series: Si vamos a hacer una comparación, aquí debemos poner cuántos campos queremos que salgan por cada etiqueta

Ahora vamos al controlador para que esto quede más claro. Así se debe ver:

angular
  .module("app", ['chart.js']) // Le decimos que usaremos a chart.js
  .controller("ControladorPrincipal", ["$scope", function($scope) {
    $scope.etiquetas = ['2006', '2007', '2008', '2009'];
    $scope.series = ['Ventas', 'Gastos'];

    $scope.datos = [
      [65, 59, 80, 81],
      [28, 48, 40, 19]
    ];
  }]);

Ahora sí podemos ver cómo se está dibujando la gráfica. En este caso vamos a comparar los gastos y las ventas por año. Comenzando con las etiquetas, podemos ver que son los años.

Son 4 años los que estamos comparando, por lo que los datos deben ser un arreglo de arreglos. Y dentro de cada arreglo están los datos que van a ir por año. Por ejemplo, en el 2006 se verá que para ventas hubo 65 y para gastos 28.

El resultado hasta el momento será el siguiente:

 

Gráfica de pastel

Ahora veremos cómo crear una gráfica pero de pastel. El código es casi el mismo que el anterior; sólo cambia el tipo de gráfica a chart-pie. Queda definida así:

 <canvas 
    class="chart chart-pie" 
    chart-data="datos" 
    chart-labels="etiquetas"></canvas>

Y en el controlador, los datos ahora estarán en un arreglo. No hacen falta definir series, pues no estamos comparando nada.

Como dije hace un momento, los datos estarán en un arreglo de una sola dimensión; contrario a cuando definimos una de barras. El código del controlador se ve así:

angular
  .module("app", ['chart.js']) // Le decimos que usaremos a chart.js
  .controller("ControladorPrincipal", ["$scope", function($scope) {
    $scope.etiquetas = ['Gastos', 'Ventas', 'Compras'];

    $scope.datos = [1244, 1500, 2053];
  }]);

El resultado es el siguiente:

Cambiando datos y refrescando gráficas

Si cambiamos algún dato dentro del modelo, se supone que debería refrescarse en la gráfica. Para ello usaremos el ejemplo de la gráfica de pastel.  Agregaremos dos campos de texto para que se puedan agregar etiquetas y valores. Al presionar el botón, se podrá apreciar cómo se refresca la gráfica automáticamente.

Los campos de texto quedan definidos así:

    <canvas class="chart chart-pie" chart-data="datos" chart-labels="etiquetas"></canvas>
    <br>
    <input placeholder="Etiqueta" type="text" ng-model="etiqueta" />
    <br>
    <br>
    <input placeholder="Valor" type="number" ng-model="valor" />
    <br>
    <br>
    <button ng-click="agregarDato(etiqueta, valor)">Agregar</button>

Al hacer click en el botón, se llamará al método agregarDato que reside en el controlador. Se le pasarán como argumentos la etiqueta y el valor.

angular
  .module("app", ['chart.js']) // Le decimos que usaremos a chart.js
  .controller("ControladorPrincipal", ["$scope", function($scope) {
    $scope.etiquetas = ['Gastos', 'Ventas', 'Compras'];

    $scope.datos = [1244, 1500, 2053];
    $scope.agregarDato = function(etiqueta, valor) {
      if (etiqueta && valor) { //Comprobar si no son nulos o indefinidos
        $scope.datos.push(valor);
        $scope.etiquetas.push(etiqueta);
      }
    };
  }]);

Lo único que hacemos es agregar un valor al arreglo de etiquetas y datos. Obviamente los validamos antes de meterlos. Aquí los resultados:

Conclusión

Como podemos ver,  se pueden crear gráficas de barras con AngularJS de una forma muy fácil. Definimos el elemento canvas en la vista y los datos en el contrador. Sólo eso, de lo demás se encarga el framework.

Tomar foto con Javascript y cámara para guardarla en servidor PHP

Introducción

Nota: ya hay una versión 3 de este código. En ese nuevo post explico cómo dar la posibilidad de que el usuario cambie la cámara, además de que introduzco otras mejoras y actualizaciones. Míralo aquí.

Nunca imaginé que algún día se podría tomar una foto y guardarla en un servidor usando código nativo de Javascript y la cámara del dispositivo. Eso abre un mundo de posibilidades que permite a nuestras aplicaciones tener más características.

Hoy mostraré aquí un pequeño tutorial que nos permitirá tomar una simple foto y subirla a un servidor que tendrá PHP. No se usará ningún framework, ni de Javascript ni de PHP.

Nota: debido a que vamos a tomar una foto con la cámara, debemos servir nuestra app en localhost (para hacer pruebas locales) o en un servidor con https. Es decir, nuestro código debe estar en un servidor con un certificado SSL, o corriendo en nuestra máquina.

Si te gusta programar en Python, te invito a leer cómo tomar una foto de la cámara web, utilizando Python.

Continue reading…

Python 3 y SQLite 3 – Introducción y ejemplos

Introducción

En esta entrada veremos cómo crear, leer, actualizar y eliminar registros en SQLite3 usando Python 3. Es decir, haremos un CRUD con SQLite. Para ello lo único que necesitamos es instalar Python. La librería que permite gestionar la base de datos ya viene incluida.

Te invito a leer el tutorial de PHP con PDO y SQLite3 para crear CRUD

Nota: si quieres ver el código completo ve a GitHub. También he creado otros tutoriales para conectar Python con SQL Server, PostgreSQL y MySQL.

Continue reading…

Promedio de valores de un arreglo usando reduce en Javascript

Si tenemos un arreglo con números dentro de él y queremos calcular el promedio de dichos valores podemos usar algo así:

var suma = 0;

for(var x = 0; x < arreglo.length; x++){
  suma += arreglo[x];
}
var promedio = suma / arreglo.length;

Lo que hoy explicaré es una función de los arreglos en dicho lenguaje llamada reduce, dicho procedimiento no necesita ningún ciclo for y es un poco más elegante.

Sumatoria con números

Con esto, podemos sacar la sumatoria de la siguiente manera:

var arreglo = [4,2,5,6,77,844,432]; //Con este arreglo trabajaremos
var sumatoria = arreglo.reduce(function(acumulador, siguienteValor){
  return acumulador + siguienteValor;
}, 0);

Simplemente invocamos a la función reduce y le pasamos dos argumentos:

  • El primero, una función anónima que recibirá a su vez acumulador y siguienteValor. acumulador es el acumulador, que la primera vez tendrá el valor del primer elemento, o el valor que establezcamos por defecto (ver segundo argumento). Tomando como ejemplo el array de arriba, primero se llamará con acumulador=4 y siguienteValor=2, después con acumulador=6 (4 + 2) y siguienteValor=5, y así sucesivamente.
  • El segundo, un valor por defecto. Debido a que en algún momento el arreglo puede estar vacío, se necesita un valor por default. Ya que se llamará a la función anónima con acumulador y siguienteValor, pero, como no hay elementos, ambos serán indefinidos y no se podrán sumar. Por esto es que indicamos el valor por defecto.

Una vez que tengamos la sumatoria, podemos calcular el promedio dividiéndola entre el número de elementos:

var arreglo = [4,2,5,6,77,844,432]; //Con este arreglo trabajaremos
var sumatoria = arreglo.reduce(function(a, b){
  return a + b; //Regresa el acumulador más el siguiente
}, 0); //Pero si no encuentras nada o no hay siguiente, regresa 0
var promedio = sumatoria / arreglo.length;

Sumatoria con objetos

Igualmente podemos calcular la sumatoria si nuestro array contiene objetos. Veamos un ejemplo en donde sumaremos la edad de algunas personas. Como podemos ver, este arreglo ahora tiene personas (objetos) en vez de simples números.

var arreglo = [
  {
    nombre: "John Doe",
    edad: 50
  },
  {
    nombre: "Pedro",
    edad: 20
  },
  {
    nombre: "Juanita",
    edad: 22
  }
];

Definido el arreglo de arriba, para sacar la sumatoria sería:

var sumatoriaObjeto = arreglo.reduce(function(acumulador, siguienteValor){
  return {
    edad: acumulador.edad + siguienteValor.edad
  };
}, {edad: 0}); //Si no hay nada, regresamos un objeto con edad = 0. No hay necesidad de devolver el nombre, pues no es necesario

Noten por favor que ahora devolvemos un objeto que lleva la clave edad, cuyo valor es la suma de los otros dos objetos.

Eso devolverá, al terminar la función, algo como {edad: 92}. Para tener ahora sí el verdadero número debemos acceder a sumatoriaObjeto.edad y ese valor dividirlo entre el número de personas, así:

var sumatoriaObjeto = arreglo.reduce(function(acumulador, siguienteValor){
  return {
    edad: acumulador.edad + siguienteValor.edad
  };
}, {edad: 0}); //Si no hay nada, regresamos un objeto con edad = 0. No hay necesidad de devolver el nombre, pues no es necesario

var promedioEdad = sumatoriaObjeto.edad / arreglo.length;

Y así es como podemos sacar promedios y sumatorias en Javascript usando reduce, de una forma elegante.

Deshabilitar administrador de tareas en Windows 10

Introducción

En algún momento de la vida puede que deseemos desactivar el task manager en Windows 10. Hay una manera muy fácil de hacerlo.

Para hacerlo necesitamos ser administradores del sistema.

Desactivar administrador de tareas

Presionar Windows + R

En la ventana que salga, escribir gpedit.msc y hacemos click en Aceptar:

Ahora vamos a Configuración de usuario > Plantillas administrativas > Sistema > Opciones de Ctrl + Alt + Supr y a la derecha aparecerá Quitar Administrador de tareas.

Hacemos doble click en Quitar Administrador de tareas y aparecerá otra ventana:

En la ventana seleccionaremos la opción Habilitada y luego haremos click en Aceptar. Se debe ver así:

Una vez que hagamos click en Aceptar, podemos cerrar todo. Ahora, si presionamos Ctrl + Shift + Esc (que debería abrir el administrador de tareas) no pasará nada. Tampoco si hacemos click derecho en la barra de tareas:

Y si intentamos abrirlo yendo a C:\Windows\System32 o presionamos Win + R y escribimos taskmgr, saldrá el siguiente aviso:

Obviamente cualquier persona con permisos de administrador podrá hacer el proceso inverso, pero por eso se supone que debemos cuidar a quién damos dicho privilegio.

Cifrando y comprobando contraseñas en PHP

Introducción

Es una buena práctica (y algo que debemos hacer todos) cifrar las contraseñas si las vamos a guardar en una base de datos. También es importante hacerlo con un algoritmo de un solo camino; es decir, que se pueda cifrar pero que nunca se pueda hacer el proceso inverso.

¿Por qué cifrarlas, si mi base de datos está protegida?

Recordemos que la seguridad absoluta no existe y que siempre estamos propensos a un ataque de cualquier tipo, así que hay que proteger cada cosa individualmente.

Supongamos que nuestro servidor FTP sí está bien protegido, y que ningún usuario malicioso puede acceder a él. Ahora imaginemos que alguien logra hacer un ataque a la base de datos, y consigue todos los nombres de usuario y contraseñas. Lo que conseguirá serán contraseñas cifradas que no le servirán para nada. Pero si no las ciframos, podrán hacer lo que se les antoje.

Cifrando contraseñas

Debilidad de SHA1 y MD5

PHP ya viene con una opción para cifrar las contraseñas. No debemos usar nunca SHA1 ni MD5, porque aunque no son reversibles sí son predecibles con ataques de diccionario.

Aquí pongo un ejemplo:

Si yo uso SHA1 para cifrar “123” obtendré “40bd001563085fc35165329ea1ff5c5ecbdbbeef“. Esto nunca cambiará; siempre que yo cifre “123” obtendré el mismo resultado. Si alguien obtiene la contraseña cifrada que será “40bd001563085fc35165329ea1ff5c5ecbdbbeef”, no sabrá cuál contraseña plana es.

Pero comenzará a probar diferentes contraseñas y las irá cifrando, una por una. Puede comenzar con las más comunes, como 12345, 0000, etcétera. Por lo que conseguirá los siguientes resultados:

  • 12345 se convierte en 8cb2237d0679ca88db6464eac60da96345513964. No es esta contraseña porque no coincide con 40bd001563085fc35165329ea1ff5c5ecbdbbeef
  • 0000 se convierte en 39dfa55283318d31afe5a3ff4a0e3253e2045e43. Tampoco es esta porque no coincide con 40bd001563085fc35165329ea1ff5c5ecbdbbeef

E irá probando hasta que llegue a 123. Se verá así:

  • 123 se convierte en 40bd001563085fc35165329ea1ff5c5ecbdbbeef. Sí es, porque coincide con 40bd001563085fc35165329ea1ff5c5ecbdbbeef.

Lo peor de esto es que ya hay diccionarios online que tienen la mayoría de contraseñas más comunes y no tan comunes. Por eso nunca se debe usar esta función.

Con MD5 es lo mismo, así que no lo explicaré

Usando sal

Cuando usamos la función que PHP recomienda, se le añade sal a la contraseña cifrada. Es una cadena aleatoria que siempre producirá resultados diferentes.

La primera vez que cifre 123 puede que el resultado sea $2y$10$I4tJZFA.mxRSaxiy/uLUWOAB8CCoBI5UJUJZ/pkJ278oYJm6nstJ. La segunda $2y$10$uxHsXhUq90CzCbPNeoCL/enuYtJVmChl2Bc9biUJnq/LYtDDusk5K, la tercera $2y$10$8lVMtOjKf6nsorwQp4cWW.hzfuVqk.MyuKzesEPZu2r7fKt0X2V4K y así sucesivamente. Por lo que siempre dará un resultado distinto, y nunca se le podrá hacer un ataque como el que menciono arriba.

Algoritmos

Así que para guardar estas contraseñas el algoritmo es:

  1. Tener la contraseña plana del usuario
  2. Cifrarla con password_hash()
  3. Guardar el resultado del paso anterior (la contraseña ya cifrada) en la base de datos

Y para comprobar si esta contraseña es correcta cuando el usuario intente acceder es:

  1. Obtener contraseña cifrada de la base de datos
  2. Utilizar password_verify()
  3. Si el resultado del paso anterior es true, entonces la contraseña es correcta. De otro modo, no.

Ejemplo

Estructura de la tabla

El manual oficial recomienda que si vamos a usar password_hash declaremos nuestro campo en la base de datos con una longitud de 255.

Registrar usuario

Voy a abstraer y omitir  la conexión a la base de datos porque explicarlo no es el propósito de este post. Así que supondré que el usuario sabe manejar bases de datos y sus conexiones.

if(isset($_POST["nombre_usuario"]) && isset($_POST["password"])){
  $usuario = $_POST["nombre_usuario"];
  $pass = $_POST["password"];
  $passCifrada = password_hash($pass, PASSWORD_DEFAULT);
  $baseDeDatos->prepare("INSERT INTO usuarios (nombre, pass) VALUES (?,?);");
  $baseDeDatos->execute([$usuario, $passCifrada]);
}

En el código de arriba tomamos el usuario y la contraseña del usuario, que pudieron ser enviadas por un formulario. Preparamos la consulta SQL para evitar inyecciones y guardamos.

Es importante notar que usamos password_hash() y le pasamos como primer argumento la contraseña plana, y como segundo una constante que es el algoritmo a ser utilizado. Recomiendo usar siempre esta constante.

Ese fue el proceso para guardar el usuario y la contraseña.

Comprobando credenciales

 

Ahora imaginemos que el usuario intenta acceder, y que igualmente manda el nombre de usuario y la contraseña por un formulario. El código quedaría así:

if(isset($_POST["nombre_usuario"]) && isset($_POST["password"])){
  $nombreUsuario = $_POST["nombre_usuario"];
  $pass = $_POST["password"];
  $baseDeDatos->prepare("SELECT pass FROM usuarios WHERE nombre = ? LIMIT 1;");
  $baseDeDatos->execute([$nombreUsuario]);
  $passObtenida = $baseDeDatos->fetch()->pass;
  //Aquí comprobamos:
  if(password_verify($pass, $passObtenida) === TRUE){
    //Datos correctos
  }else{
    //Datos incorrectos
  }
}

Conclusión

Así es como, a grosso modo, podemos comprobar si las credenciales de determinado usuario son válidas, al mismo tiempo que protegemos su contraseña.

Es muy importante mencionar que no debemos intentar crear nuestros propios algoritmos, por más que pensemos que somos listos nunca debemos de intentar hacerlo por nuestra cuenta.

Char a Int en Arduino

Si queremos convertir un char a entero en Arduino, podemos usar:

char c = '5';
int convertido = int(c);

El resultado sería el número 53, porque el número 5 es el carácter ASCII número 53. Nosotros no queremos eso, nosotros esperábamos un que ‘5’ se convirtiera en 5. Para obtener lo que realmente necesitamos, podemos usar lo siguiente:

char c = '5';
int convertido = String(c).toInt();

Ahora sí, el resultado sería 5 como entero. De esta forma podemos convertir carácter a entero, e incluso String a entero.

Invertir cadena en Arduino

Introducción

Recientemente tuve la necesidad de girar o invertir una cadena en Arduino. Así que hice una pequeña función que toma como parámetro un String y devuelve una variable del mismo tipo cuyo valor es el de la otra cadena, pero invertida.

Definición de la función.

String invertirCadena(String s) {
  String temporal = "";
  for (int m = s.length() - 1; m >= 0; m--)
    temporal += s[m];
  return temporal;
}

El algoritmo es sencillo y tal vez un poco lento, pero funciona. Básicamente se crea una cadena vacía que será llamada temporal. Luego, recorremos la original de derecha a izquierda y vamos concatenando el carácter con la temporal. Finalmente, la devolvemos.

Invocación

Para invocar o llamar a la función, podemos hacerlo así:

String cadenaInvertida = invertirCadena("aloH");

El resultado de arriba sería la palabra Hola.

Espero que esto haya servido.

Configurar HC-05 bluetooth sin TTL con Arduino y modo AT

Introducción

Cuando conseguimos un módulo bluetooth HC-05 siempre será necesario cambiar el nombre y la contraseña. En casos más avanzados, vamos a necesitar incluso cambiar el modo (esclavo o maestro). Me he topado con muchos tutoriales por ahí, todos varían y algunos piden un módulo USB a TTL.

Al final de todo logré entrar en modo AT para configurar mi módulo. Y no necesité otra cosa más que un Arduino, el propio módulo y el cable con el que se suben los programas al Arduino.

Dicho esto, comencemos.

Continue reading…

Linux: mover archivos que comienzan con

Esto será un poco breve pero algo que nos será de mucha ayuda. A veces necesitaremos mover todos los archivos que comiencen, tengan o terminen con determinada cadena. Por ejemplo, supongamos que tenemos los siguientes archivos:

foto_2015-11-20_11-55-20.png
foto_2015-11-20_13-55-30.png
foto_2015-11-10_11-55-12.png

(son 3, pero para ejemplificar basta)

Ahora supongamos que queremos moverlos a una carpeta llamada 2015-11 (dicha carpeta debe existir).

El comando sería:

mv -v foto_2015-11-* ./2015-11/

Otros Ejemplos

Si quisiéramos mover los que contengan algo en el centro, sería:

mv -v *cadena-central* ./nombre-carpeta/

Y si fueran archivos que terminan con algo, sería:

mv -v *terminacion ./nombre-carpeta/

 

Proteger, controlar y restringir acceso a imágenes usando PHP y Apache

Introducción

En este artículo mostraré cómo podemos proteger nuestras imágenes o fotos usando PHP para que sólo en casos específicos se puedan ver. Usaremos la configuración de Apache para restringir el acceso (para que no puedan acceder a ejemplo.com/imagenes/imagen_secreta.png). PHP será utilizado para leer ese archivo y mostrarlo sólo si se debería.

Preparando archivos para trabajar

En nuestro entorno de trabajo de PHP (en htdocs si estás usando xampp) crearemos una carpeta llamada “probar_fotos“. Dentro de ella crearemos un archivo index.php y otra carpeta llamada img.  Dentro de esta última carpeta pondremos algunas imágenes de nuestra elección (no importa el formato ni calidad) y un archivo llamado .htaccess.

En mi caso, el directorio se ve así:

Configurando htaccess

En primera instancia vamos a denegar cualquier acceso a la carpeta en donde tenemos nuestras imágenes. Para ello nos servirá el archivo que pusimos ahí dentro. Simplemente le diremos al servidor que deniegue cualquier acceso.

Antes de modificar el archivo, si navegamos a localhost/probar_fotos/img podemos ver todas las imágenes:

De esta manera todos podrían verlas. Y eso no es lo que queremos. Por ello, en el archivo .htaccess escribiremos:

Deny from all

Guardamos cambios y volvemos a la ruta. Ahora nos encontraremos con esto:

Listo, ya tenemos nuestra carpeta protegida. Nota: incluso si el usuario supiera el nombre de la imagen y quisiera acceder a ella a través de localhost/probar_fotos/img/st.jpg no podría; saldría esto:

Con esto hemos terminado de configurar a Apache. Ahora es el turno de PHP.

Leyendo archivos con PHP

Como PHP leerá los archivos sin pasar a través del servidor, no importa que éstos estén protegidos por Apache.

El algoritmo es simple: debemos saber cómo se llama la imagen que queremos leer, comprobar si existe, mandar los encabezados (para que el navegador interprete los datos como imagen) y finalmente mandar la imagen. Por ejemplo, yo tengo una imagen llamada st.jpg, y para mostrarla hago lo siguiente en index.php:

<?php
$rutaImagen = __DIR__ . "/img/st.jpg";
$informacionImagen = getimagesize($rutaImagen);
header("Content-type: {$informacionImagen['mime']}");
readfile($rutaImagen);
?>

En la primera línea declaro la ruta de la imagen. Luego, obtengo su información (para saber si es png, jpg, etcétera) y mando los encabezados. Finalmente hago uso de readfile para leer la imagen y mandarla a través del búfer de salida. Podríamos usar file_get_contents pero ésta función también carga la imagen a memoria, cosa que no queremos, ya que sólo queremos mandarla directamente, sin hacerle modificación alguna.

Si ahora voy a localhost/probar_fotos/index.php veré lo siguiente:

Podemos ver que la imagen ha sido mostrada.

Leyendo archivos sólo si se tiene permiso

Arriba mostramos la imagen a cualquier usuario, cosa que es insegura como si no protegiéramos nada. Pero para restringir el acceso a determinados usuarios dependerá de cómo sea nuestra aplicación. Por ejemplo, si sólo los usuarios logueados pueden verlas, sería más o menos así:

<?php
session_start();
if($_SESSION["logueado"] === true){

  $rutaImagen = __DIR__ . "/img/st.jpg";
  $informacionImagen = getimagesize($rutaImagen);
  header("Content-type: {$informacionImagen['mime']}");
  readfile($rutaImagen);
}
?>

Si en cambio dependiera de un nivel de acceso almacenado en sesión, sería algo así:

<?php
session_start();
if($_SESSION["permiso_usuario"] >= 5){ #Suponiendo que el nivel de permisos para ver imágenes es 5

  $rutaImagen = __DIR__ . "/img/st.jpg";
  $informacionImagen = getimagesize($rutaImagen);
  header("Content-type: {$informacionImagen['mime']}");
  readfile($rutaImagen);
}
?>

Todo esto cambia dependiendo de cómo sea nuestro software. Más abajo omitiré esta comprobación del usuario, y me centraré en cómo mostrar archivos de diversas maneras. Queda en manos del desarrollador proteger el acceso a determinados clientes.

Mostrando imágenes según nombre

Ahora vamos a hacer que se muestre cualquier imagen si es que sabemos su nombre, pero sólo si existe y si su extensión es .jpg. Para ello leeremos el nombre almacenado en la variable $_GET. Modificaré el código así:

<?php
if(isset($_GET["nombre"])){ #Comprobar si está definida la variable
	$nombreImagen = $_GET["nombre"];
	$rutaImagen = __DIR__ . "/img/$nombreImagen.jpg"; #Concatenar nombre con .jpg
	if(file_exists($rutaImagen)){ #Comprobar si el archivo existe
		$informacionImagen = getimagesize($rutaImagen);
		header("Content-type: {$informacionImagen['mime']}");
		readfile($rutaImagen);
	}
}
?>

Ahora iré a localhost/probar_fotos/index.php?nombre=the-good-dinosaur y veré lo siguiente:

Y si accedo a localhost/probar_fotos/index.php?nombre=st veré lo siguiente:

De esta manera podríamos leer cualquier imagen, aunque nunca debemos de hacerlo de esta manera, porque cualquier usuario malicioso podría ir probando nombres de imágenes y viendo si existen o no. Además, podría navegar a otros directorios.

Esto nos lleva a otro método que detallo más abajo.

Mostrando imágenes por nombre y expresión regular

Este método se parece mucho al de arriba, sólo que ahora comprobaremos el nombre con una expresión regular. Básicamente sólo permitiremos imágenes cuyo nombre esté compuesto por letras y números o guiones, por un punto y por una extensión que puede ser png, jpg o jpeg. Si no se da ningún nombre, la expresión no coincide o no existe el archivo, simplemente indicamos que no se encontró la imagen.

<?php
if(isset($_GET["nombre"])){ #Comprobar si está definida la variable
	$nombreImagen = $_GET["nombre"];
	$expresionRegular = '/^[a-z0-9A-Z-]*\.(?:png|jpg|jpeg)$/';
	if(preg_match($expresionRegular, $nombreImagen) === 1){
		$rutaImagen = __DIR__ . "/img/$nombreImagen"; #Concatenar nombre con __DIR__
		if(file_exists($rutaImagen)){ #Comprobar si el archivo existe
			$informacionImagen = getimagesize($rutaImagen);
			header("Content-type: {$informacionImagen['mime']}");
			readfile($rutaImagen);
		}else exit("Imagen no encontrada");
	}else exit("Imagen no encontrada");
}else exit("Imagen no encontrada");
?>

Ahora puedo navegar a localhost/probar_fotos/index.php?nombre=the-good-dinosaur.jpg y ver la imagen. Si pongo un nombre raro como ../../ veré el error:

Por otro lado, si el nombre de la imagen coincide con la expresión regular pero no existe, veremos lo mismo:

Conclusión

Puede que parezca que en realidad no estamos haciendo nada, pero sí que lo estamos haciendo. De esta manera podemos proteger el acceso a imágenes para algunos usuarios; podemos hacer todo tipo de cosas, todo depende de los requerimientos de nuestra aplicación, pero la base es la misma.

Referencias

Stack Overflow – Show image using file_get_contents

Stack Overflow – Deny direct access to all .php files except index.php