<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"
	xmlns:media="http://search.yahoo.com/mrss/"
>

<channel>
	<title>Con G de GNU &#187; Guias y manuales</title>
	<atom:link href="http://www.congdegnu.es/category/guias-manuales/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.congdegnu.es</link>
	<description>aptitude install freedom</description>
	<lastBuildDate>Sat, 28 Jan 2012 19:22:41 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.3</generator>
	<copyright>2006-2007 </copyright>
	<managingEditor>congdegnu@gmail.com (Con G de GNU)</managingEditor>
	<webMaster>congdegnu@gmail.com (Con G de GNU)</webMaster>
	<image>
		<url>http://www.congdegnu.es/wp-content/plugins/podpress/images/powered_by_podpress.jpg</url>
		<title>Con G de GNU</title>
		<link>http://www.congdegnu.es</link>
		<width>144</width>
		<height>144</height>
	</image>
	<itunes:subtitle></itunes:subtitle>
	<itunes:summary>aptitude install freedom</itunes:summary>
	<itunes:keywords></itunes:keywords>
	<itunes:category text="Society &#38; Culture" />
	<itunes:author>Con G de GNU</itunes:author>
	<itunes:owner>
		<itunes:name>Con G de GNU</itunes:name>
		<itunes:email>congdegnu@gmail.com</itunes:email>
	</itunes:owner>
	<itunes:block>no</itunes:block>
	<itunes:explicit>no</itunes:explicit>
	<itunes:image href="http://www.congdegnu.es/wp-content/plugins/podpress/images/powered_by_podpress_large.jpg" />
		<item>
		<title>BeagleBone: Primeros pasos</title>
		<link>http://www.congdegnu.es/2012/01/28/beaglebone-primeros-pasos/</link>
		<comments>http://www.congdegnu.es/2012/01/28/beaglebone-primeros-pasos/#comments</comments>
		<pubDate>Sat, 28 Jan 2012 16:35:31 +0000</pubDate>
		<dc:creator>Maxpowel</dc:creator>
				<category><![CDATA[GNU/Linux]]></category>
		<category><![CDATA[Guias y manuales]]></category>
		<category><![CDATA[Hardware]]></category>
		<category><![CDATA[arduino]]></category>
		<category><![CDATA[beagle]]></category>
		<category><![CDATA[beaglebone]]></category>
		<category><![CDATA[cloud9]]></category>

		<guid isPermaLink="false">http://www.congdegnu.es/?p=1362</guid>
		<description><![CDATA[Hola! Os voy a presentar el beagle bone. Seguro que muchos ya lo conocéis así que tras una breve introducción mostraré cómo dar los primeros pasos, que aunque sencillos, a veces te pueden hacer perder mucho tiempo. En resumidas cuentas Beagle Bone es un ordenador en pequeño pero con el que también puedes controlar hardware [...]]]></description>
			<content:encoded><![CDATA[<p>Hola! Os voy a presentar el beagle bone. Seguro que muchos ya lo conocéis así que tras una breve introducción mostraré cómo dar los primeros pasos, que aunque sencillos, a veces te pueden hacer perder mucho tiempo. En resumidas cuentas Beagle Bone es un ordenador en pequeño pero con el que también puedes controlar hardware externo a través de sus pines (como con arduino). Para que te hagas una idea, su procesador es un ARM A8 cortex que funciona a unos 700mhz (este dato  es sólo algo orientativo, otro día veremos cómo &#8220;comparar&#8221; procesadores) y cuenta con 256MB de RAM. Exacto, con todo eso puedes ejecutar un sistema operativo como el que tienes en tu ordenador (siempre y cuando exista para ARM que en el caso de Linux así es <img src='http://www.congdegnu.es/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> .</p>
<p><div class="wp-caption alignright" style="width: 410px"><img src="http://www.adafruit.com/images/medium/beaglesticker_MED.jpg" alt="" width="400" height="308" /><p class="wp-caption-text">El logo es un adorable perrito</p></div></p>
<p>Es realmente pequeño, unos 9cm de largo y 5,5 de ancho (un poco más grande que arduino) y cuenta con un lector de trajetas microsd (donde metes el SO y lo que tu quieras), un host USB (para enchufarle camáras, teclados, ratones&#8230;), un conector RJ45 y un micro USB para conetarlo al PC.</p>
<p>Bien, no me enrrollo más. Todo esto que cuento ya lo han contado cientos de veces en otras páginas así que vamos al tema. Qué hacer cuando sacas el beaglebone de su caja.</p>
<p>&nbsp;</p>
<p>Lo primero que se me ocurre es conectarlo al PC por el microUSB y ver que pasa. Tras unos segundos (recuerda que tiene que iniciar el sistema operativo y eso lleva tiempo) el ordenador detectará un dispositivo de almacenamiento masivo mediante el cual podrás acceder a las particiones que tengas excepto la usada por beaglebone. Recuerda que en esa tarjeta de memoria también están los archivos del sistema operativo. Por defecto la tarjeta trae dos particiones, la que he comentado (que es un Angstrom Linux) y una FAT donde trae unos archivos de manual y drivers para windows y mac. En linux no te hará falta instalar nada.</p>
<p>Bien, ya sabemos que el cacharrito funciona, ahora vamos a hacer algo más divertido. Vamos a conectarnos por consola a nuestro beaglebone y a hozar un poco. Por supuesto también podrías enchufarle un monitor y un teclado pero para conectarle un monitor necesitas una shield (que es carilla) o fabricarla tu mismo.</p>
<p><span id="more-1362"></span>Para nuestra siguiente labor, en Linux tenemos que cargar un módulo a mano ya que no reconoce las uuid (he leído que en futuras versiones esto lo cambiarán). No es grave, lo hacemos con este comando</p>
<pre>sudo modprobe ftdi_sio vendor=0x0403 product=0xa6d0</pre>
<p>Sería un rollo poner esto siempre así que creamos un fichero llamado /etc/udev/rules.d/73-beaglebone.rules con el siguiente contenido</p>
<pre>ACTION=="add", SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_interface", 
        ATTRS{idVendor}=="0403", ATTRS{idProduct}=="a6d0", 
        DRIVER=="", RUN+="/sbin/modprobe -b ftdi_sio"

ACTION=="add", SUBSYSTEM=="drivers", 
        ENV{DEVPATH}=="/bus/usb-serial/drivers/ftdi_sio", 
        ATTR{new_id}="0403 a6d0"

ACTION=="add", KERNEL=="ttyUSB*", 
	ATTRS{interface}=="BeagleBone", 
        ATTRS{bInterfaceNumber}=="00", 
	SYMLINK+="beaglebone-jtag"

ACTION=="add", KERNEL=="ttyUSB*", 
	ATTRS{interface}=="BeagleBone", 
        ATTRS{bInterfaceNumber}=="01", 
	SYMLINK+="beaglebone-serial"</pre>
<p>Ahora cada vez que enchufemos el beaglebone se detectara sin problema. Esto nos creara una interfaz en /dev/ttyUSBX donde X es un numero que depende de los cacharros que tengas conectados. Ahora ya sólo tenemos que conectarnos, para ello uso el comando screen de esta manera:</p>
<p>screen /dev/ttyUSB1 115200</p>
<p>El número 115200 es la velocidad de transmisión (simula un puerto serie). Si todo va bien, veremos algo como la siguiente imagen.</p>
<p><a href="http://www.congdegnu.es/wp-content/uploads/2012/01/consola1.png"><img class="aligncenter size-full wp-image-1365" src="http://www.congdegnu.es/wp-content/uploads/2012/01/consola1.png" alt="" width="565" height="186" /></a></p>
<p>El login por defecto es root y no tiene contraseña. Una vez dentro puedes manejarlo como un Linux cualquiera!</p>
<p>Ya tenemos control absoluto sobre nuestro aparatito. Sí, podríamos escribir programas en C, compilarlos y ejecutarlos (o pyhton o lo que te de la gana, incluso puedes tener tu servidor apache con php y conectarlo a tu LAN por el RJ45) pero vamos a utilizar una herramienta muy interesante que trae que se llama cloud9. Colud9 es un IDE que se ejecuta en un navegador. Está en el beagle bone y desde nuestro navegador accedemos, compilamos y ejecutamos programas. Todo ello sin instalar ningun software en nuestro ordenador y disponible en cualquier momento. Por defecto programaremos con este IDE como si lo haríamos con javascript (la sintaxis) que para quienes los conozcan se llama Node.js.</p>
<p>Como hemos conectado el beagle bone mediante USB, muchos servicios están desativados e incluso el procesador va a menos ciclos (a 500 en vez de 700). El motivo es que el USB no proporciona la energía necesaría. Para tener funcionando a pleno rendimiento tendríamos que usar la entrada de 5V. Pero queremos algo sencillo y que funcione ya así que crearemos una interfaz ethernet a través de USB. Calma, esto ya viene preparado de serie y es muy sencillo de hacer. Tan sólo tienes que desmontar la unidad de almacenamiento (que se llama BONE nosequé) y automáticamente se iniciará eso del ethernet por usb. Ojo, si te pasa como a mi y no se inicia nada después de desmontar la unidad de almacenamiento ejecuta el comando &#8220;eject&#8221; para forzarlo. En mi caso es &#8220;eject /dev/sdh&#8221;. En algunas distribuciones no hace falta, yo uso debian y me llevó un motón de tiempo averiguar por qué narices no funcionaba. Recuerda, si no va usas el comando eject y listo.</p>
<p>Ahora hacemos ifconfig y veremos una interfaz de red nueva. En mi caso se llama eth1 y tiene la IP 192.168.7.1. Esa es la IP que el beagle bone ve. Es una maravilla porque ello sólo se encarga de configurar todo. Si queremos conectarnos al beagle usaremos la dirección ip 192.168.7.2 desde nuestro PC. Si por lo que sea (nunca se sabe) ha cogido otra IP lo que tenemos que hacer es conectarnos por serie al beaglebone (como expliqué antes) y con ifconfig ver qué IP ha cogido. Con esta IP podemos hacer SSH al beagle o lo que queramos, la verdad es que es muy divertido. Ya sea por ssh o por serie nos conectamos al beaglebone y ejecutamos el comando &#8220;cloud9&#8243;. Tras unos segundos veremos el iconito de la nube con un 9 dentro y debajo pone:</p>
<p>&#8220;Project root is: /var/lib/cloud9<br />
Point your browser to http://localhost:3000&#8243;</p>
<p>Ya está listo. Vamos a nuestro navegador y accedemos a http://192.168.7.2:3000/ Cargará el IDE que además viene con unos ejemplos y en concreto uno llamado blink.js. Con este ejemplo haremos parpadear a un LED. Beagle bone cuenta con un chorro de pines de entrada/salida (Ojo que funcionan a 3.3V no a 5V así que ni se te ocurra conectarlo directamente a un arduino o aparatos que usen 5V. Si estás interesado busca sobre level shifter o pregúntame a mi <img src='http://www.congdegnu.es/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  )</p>
<p>Los bancos de pines se llaman P8 y P9 (está escrito en un lado). Ese ejemplo usa el pin 3 que está en el banco P8 (bone.P8_3). Si te fijas, en las cuatro esquinas de cada banco aparecen unos numeritos (en caso de P8 pone 2,1   46,45). Eso indica el número del pin. Hay un montón de pines diferentes y para usos diferentes y todo eso viene en la documentación oficial. Para encender un LED conectaremos el polo positivo (patita larga) al pin 3 y el negativo al pin 1 o 2 (son de masa, tierra o ground como quieras llamarlo). Ya sólo nos queda darle a &#8220;Run&#8221; y veremos como se enciende y apaga el LED. Si! Es la cosa más sencilla del mundo pero esto es sólo el principio! A partir de ahora puedes aplicar todos tus conocimientos para crear todo tipo de robots y autómatas!</p>
<p><a href="http://www.congdegnu.es/wp-content/uploads/2012/01/IMG_20120128_1713242.jpg"><img class="aligncenter size-full wp-image-1369" src="http://www.congdegnu.es/wp-content/uploads/2012/01/IMG_20120128_1713242.jpg" alt="" /></a></p>
<p>Por cierto, te recomendaría que apagues el beaglebone antes de desenchufarlo. Si estás habituado al arduino igual tienes la costumbre de desconectar directamente pero recuerda que esto es como tu ordenador., hay que es apagarlo correctamente (con el comando halt por ejemplo) antes de desenchufar. De la misma manera que con tu ordenador normal, si lo desconectas directamente podrías crear incogruencias en el sistema de ficheros o cortar un proceso importante del sistema operativo (de acuerdo, nunca pasa nada pero cuando pasa, pasa)</p>
<p>Por último, una foto con el arduino (si es necesario es hace una comparativa o algo entre ambas máquinas) o si necesitas más detalles o ayuda con el beagle bone tal vez pueda ayudarte.</p>
<p><a href="http://www.congdegnu.es/wp-content/uploads/2012/01/IMG_20120128_1715161.jpg"><img class="aligncenter size-full wp-image-1371" src="http://www.congdegnu.es/wp-content/uploads/2012/01/IMG_20120128_1715161.jpg" alt="" /></a></p>
<p>En mi caso ejecutaré OpenCV en mi robocoche y algun algoritmo más pesado de toma de decisiones (o una red neuronal). Ya os iré contando novedades <img src='http://www.congdegnu.es/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>Nos vemos!</p>
<p>Edito par añadir un par de enlaces (en inglés).<br />
Documentación oficial: <cite>beagleboard.org/static/BONESRM_latest.pdf</cite></p>
<p>Guía oficial: http://www.beagleboard.org/static/beaglebone/a3/README.htm</p>
<div class="shr-publisher-1362"></div>

<p>Entradas relacionadas.</p>]]></content:encoded>
			<wfw:commentRss>http://www.congdegnu.es/2012/01/28/beaglebone-primeros-pasos/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Juega a tu Nintendo 64 con tu mando de la Wii y arduino</title>
		<link>http://www.congdegnu.es/2011/08/29/juega-a-tu-nintendo-64-wiimote-arduino/</link>
		<comments>http://www.congdegnu.es/2011/08/29/juega-a-tu-nintendo-64-wiimote-arduino/#comments</comments>
		<pubDate>Mon, 29 Aug 2011 15:49:27 +0000</pubDate>
		<dc:creator>Maxpowel</dc:creator>
				<category><![CDATA[Guias y manuales]]></category>
		<category><![CDATA[Hardware]]></category>
		<category><![CDATA[Programación]]></category>
		<category><![CDATA[arduino]]></category>
		<category><![CDATA[n64]]></category>
		<category><![CDATA[nintendo]]></category>
		<category><![CDATA[ocarina of time]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[wii]]></category>
		<category><![CDATA[zelda]]></category>

		<guid isPermaLink="false">http://www.congdegnu.es/?p=1312</guid>
		<description><![CDATA[¿Alguna vez has pensado cómo sería jugar a tu juego favorito de tu nintendo 64 con un wiimote? Yo sí, quería dar espadazos con Link en Ocarina of Time y con la ayuda de mi querido arduino he podido cumplirlo!. Se que podría haber usado un emulador pero&#8230; donde queda el romanticismo? Antes de nada, [...]]]></description>
			<content:encoded><![CDATA[<p>¿Alguna vez has pensado cómo sería jugar a tu juego favorito de tu nintendo 64 con un wiimote? Yo sí, quería dar espadazos con Link en Ocarina of Time y con la ayuda de mi querido arduino he podido cumplirlo!. Se que podría haber usado un emulador pero&#8230; donde queda el romanticismo? <img src='http://www.congdegnu.es/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> </p>
<p>Antes de nada, os pongo un vídeo del resultado.</p>
<p><p><a href="http://www.youtube.com/watch?v=HBf7m3zylcA"><img src="http://img.youtube.com/vi/HBf7m3zylcA/2.jpg"></a></p>
<p><a href="http://www.youtube.com/watch?v=HBf7m3zylcA">Click here</a> to view the video on YouTube.</p>
</p>
<p>&nbsp;</p>
<p>Sí, ese es el menda jugando. ¿Te interesa saber cómo puedes hacerlo? Si es así sigue leyendo, de lo contrario sólo perderás tu tiempo.<span id="more-1312"></span></p>
<p>Lo primero y antes de nada tengo que decir que mi código del arduino es una vil copia del proyecto <a title="Gamecube to N64" href="https://github.com/brownan/Gamecube-N64-Controller">Gamecube-N64-Controller</a>. Ese proyecto permite jugar a la nintendo 64 con un mando de la gamecube. De ahí básicamente saqué el protocolo de comunicación y las funciones para &#8220;dialogar&#8221; con la n64 (que ya es bastante!!).</p>
<p>También tengo que aclarar que jugar con el wiimote es bastante más complicado. El stick del nunchuk es bastante mediocre comparado con el joystick de la nintendo 64 (para mi uno de los mejores que han existido), de ahí mi manqueo a la hora de apuntar a ganondorf con el arco. El segundo motivo es que el juego está preparado para responder a una única pulsación, entonces responderá sólo cuando hayamos terminado el movimiento lo cual implica movimientos &#8220;retardados&#8221;. Es mucho más rápido pulsar un botón que hacer el gesto del movimiento de la espada.</p>
<p>Ahora voy a explicar más o menos como funciona la cosa. Tenemos un mando de la wii con nunchuk y queremos jugar a la nintendo 64. El primer problema que se nos plantea es que el mando de la n64 va por cable mientras que el wiimote es inalámbrico. Mi solución ha sido usar el ordenador como pasarela: el wiimote se conecta al ordenador por bluetooth y luego el ordenador mediante usb al arduino, quien simula ser un mando de n64. Si quieres hacer algo más profesional siempre puedes usar el módulo bluetooth para arduino y desarrollar una biblioteca de comunicación. Llegados a este punto vemos que necesitamos dos programas, uno para el arduino y otro para el ordenador. Vamos a ello.</p>
<h2>Software para arduino</h2>
<p>Nuestro arduino va a ser simplemente un enlace sin ningún tipo de lógica. Nosotros le enviamos los datos y directamente se lo sirve a la consola sin nada de procesamiento (en el proyecto de gamecube que mencioné antes, el arduino realiza las operaciones necesarias para convertir los comandos). El motivo es para que sea más práctico, así sólo es necesario modificar le programa de ordenador si queremos hacer cualquier cambio. La función loop del programa arduino se ha reducido bastante, ya que al recibir los datos preparaditos para enviar no tiene que hacer más que eso (recibir datos del ordenador por el puerto serie y tal cual mandarlos a la consola).</p>
<p>&nbsp;</p>
<h2>Software para ordenador</h2>
<p>Utilizo la biblioteca cwiid desde python y en principio es multiplataforma (aunque sólo lo he probado en Linux). Doy por supuesto que tienes un dispositivo bluetooth funcionando y el software de arduino instalado. Este programa python también es sencillo. Lo que hace es conectarse al mando de la wii (usando cwiid), obtener las pulsaciones de botones y mandarlas al arduino. La verdad es que, sabiendo el protocolo del mando es muy sencillo pero llegar a manejar bien un protocolo cerrado de esos es un infierno. Voy a tratar de explicar (sin detalles técnicos) un poco como funciona.</p>
<h3>Funcionamiento del mando de nintendo 64</h3>
<p>La consola puede mandar 4 tipos de comandos diferentes al mando. Estos son de identificación, de estado, de lectura y de escritura. Los dos últimos, hasta lo que yo se (recordemos que es un protocolo cerrado y vete tu a saber que más cosas hace) es para gestionar el rumble pack (un aparato que hace al mando vibrar). Cuando encendemos la consola, ésta manda el comando de identificación al que los mandos conectados (en nuestro caso el arduino) y éstos deben responder. Si no, la consola nos mostrará un bonito &#8220;NO CONTROLLER&#8221;. Por último, la consola nos manda el comando de estado cuando necesita saber que botones estamos pulsando. Cuando la consola nos pregunte por el estado nosotros respondemos. Al contrario de lo que mucha gente pueda pensar, no es el mando quien manda información todo el rato a la consola, sino que es la consola quién pregunta al mando todo el rato que botones hay pulsados. Nuestra labor va a ser que cuando la consola pregunte por esa información el arduino se la entregue.</p>
<p>Ahora veamos qué información es la que mandamos. El paquete con toda la información sobre el estado del mando (los botones pulsados) son 4 Bytes. De estos 4 Bytes, los dos primeros expresan el estado de los botones y los dos últimos la posición del joystick. Para el caso de los botones es bien sencillo, bit a 1 boton pulstado y bit a 0 boton no pulsado. De esta manera con 2 Bytes podemos representar 16 botones y como la consola tiene 14 pues incluso son sobran 2 bits. El contenido exacto de los bytes es este:</p>
<p>Byte 1: A, B, Z, Start, PadArriba, PadAbajo, PadIzquierda, PadDerecha</p>
<p>Entonces si tenemos pulsado el botón A, el primer byte será: 1 0 0 0 0 0 0 0, si pulsamos A y Z será: 1 0 1 0 0 0 0 0. Sencillo de entender, verdad?<br />
El segundo byte contiene: 0, 0, BotonL, BotonR, C-Arriba, C-Debajo, C-Izquierda, C-derecha<br />
Como dije antes nos sobran dos bits, que son esos dos primero bits que siempre valen 0.</p>
<p>Por último nos quedan los bytes para el joystick, el byte 3 contiene la posición X y el byte 4 la posición Y. Para representarlo se utiliza un byte con signo más o menos desde -80 a 80. Esto es muy importante ya que cuando mandemos la información en binario hay que tener muy claro lo que mandamos para que todo funcione bien y de manera sencilla (por eso en el programa python, al empaquetar los bytes los primero con con <strong>B</strong>, unsigned char, y los dos último son <strong>b</strong>, signed char). Nosotros generaremos ese paquete de 4Bytes y por el puerto serie se lo mandaremos al arduino.</p>
<p>Ya conocemos la teoría así que a programar. Yo he elegido python pero puedes usar el que te de la gana siempre y cuando generes bien esos 4 Bytes. El programa de arduino te servirá igual.</p>
<h2>Obtener el código fuente</h2>
<p>El código fuente lo he subido a github y por supuesto con licencia GPL. Puedes clonarlo usando esta dirección <a title="Video" href="https://github.com/maxpowel/Wii-N64-Controller" target="_blank">https://github.com/maxpowel/Wii-N64-Controller</a><br />
Si ves algun fallo o quieres compartir una configuración de botones (sobretodo es interesante el tema del acelerómetro del wiiomte) te agradecería que me hicieras un pull request <img src='http://www.congdegnu.es/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>&nbsp;</p>
<h2>Montaje</h2>
<p>Material:</p>
<ul>
<li>Arduino (y su cable USB)</li>
<li>2 Cablecitos</li>
<li>Nintendo 64</li>
<li>Ordenador</li>
<li>Bluetooth</li>
</ul>
<p>Supongo que no tendrás problemas para conectar tu arduino y bluetooth a tu PC. El siguiente paso es conectar el cable de tierra de la conexión del mando a un pin de tierra del arduino usando uno de los cablecitos. El otro cable es para unir el pin 8 (puedes usar el pin que quieras, pero en el código uso el 8 ) con el de datos de la consola. El esquema de pines del mando es el siguiente:</p>
<ol>
<li>+3.3V &#8211; Alimentación. No lo usamos ya que el arduino tiene su propia alimentación.</li>
<li>Datos &#8211; Conectado con el pin digital 8</li>
<li>GND &#8211; Conectado a un pin de tierra de arduino</li>
</ol>
<p><strong>Nota:</strong> Recuerda que este es el esquema del <strong>mando</strong> y el de la consola quedará espejado (mirando de frente a la consola se usan los dos pines de la derecha). Espero no haberte líado con esto</p>
<p><img class="alignnone" src="https://github.com/maxpowel/Wii-N64-Controller/raw/master/connections.png" alt="" width="136" height="151" /></p>
<p>Como nota, decir que siempre hay que encender primero el arduino antes que la consola ya que de otra manera no detectará ningún mando. Recuerda lo que dije antes de que la consola cuando se enciende &#8220;pregunta&#8221; a los mandos para ver qué hay conectado.</p>
<p>Para terminar un pequeño vídeo de como tengo montado el tinglao.</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><p><a href="http://www.youtube.com/watch?v=1a5wc_V0vO0"><img src="http://img.youtube.com/vi/1a5wc_V0vO0/2.jpg"></a></p>
<p><a href="http://www.youtube.com/watch?v=1a5wc_V0vO0">Click here</a> to view the video on YouTube.</p>
</p>
<div class="shr-publisher-1312"></div>

<p>Entradas relacionadas.</p>]]></content:encoded>
			<wfw:commentRss>http://www.congdegnu.es/2011/08/29/juega-a-tu-nintendo-64-wiimote-arduino/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Vistas en Doctrine ORM</title>
		<link>http://www.congdegnu.es/2010/12/21/vistas-en-doctrine-orm/</link>
		<comments>http://www.congdegnu.es/2010/12/21/vistas-en-doctrine-orm/#comments</comments>
		<pubDate>Tue, 21 Dec 2010 20:10:49 +0000</pubDate>
		<dc:creator>Maxpowel</dc:creator>
				<category><![CDATA[Guias y manuales]]></category>
		<category><![CDATA[Programación]]></category>
		<category><![CDATA[doctrine]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[symfony]]></category>
		<category><![CDATA[vista]]></category>

		<guid isPermaLink="false">http://www.congdegnu.es/?p=1235</guid>
		<description><![CDATA[Saludos! que tal? Espero que bien. Esta vez te voy a hablar acerca de las vistas sql en el orm doctrine. Quien conozca estas herramientas no hace falta que se las presente, pero para los demás ahí va una breve explicación. En bases de datos relacionales (MySQL por ejemplo) una vista  es como un &#8220;resumen&#8221; [...]]]></description>
			<content:encoded><![CDATA[<p>Saludos! que tal? Espero que bien. Esta vez te voy a hablar acerca de las vistas sql en el orm doctrine. Quien conozca estas herramientas no hace falta que se las presente, pero para los demás ahí va una breve explicación.</p>
<p>En bases de datos relacionales (MySQL por ejemplo) una vista  es como un &#8220;resumen&#8221; de un conjunto de consultas. Un orm es una herramienta de programador que te ayuda a trabajar con bases de datos desde tu aplicación.</p>
<p>Doctrine es el ORM (junto a propel) que trae por defecto el framework php symfony (mi favorito) y como no hay mucha documentación sobre las vistas, y menos en castellano, pues aquí va este pequeño manual.</p>
<p><span id="more-1235"></span>Mi manera de trabajar es trabajar lo menos posible (vagooo!!). Calma! Lo que quiero decir es que cuanto más trabaje el ordenador por mí, más rápido y mejor se desarrolla una aplicación. Por este motivo yo no me molesto en escribir ni una sóla consulta SQL salvo que sea estrictamente necesario (como veremos que será cuando hagamos las vistas).</p>
<p>Por supuesto no quiere decir que saber SQL sea inútil ni mucho menos. Es más, para trabajar bien (de manera eficiente) con un ORM necesitas saber SQL como el comer.  Este el motivo por el que yo &#8220;sólo&#8221; hago el diseño de la base de datos y el ordenador genera todo lo demás por mí. Esto tiene muchas ventajas como por ejemplo la independencia del sistema (da igual que uses mysql, postgres&#8230;) y reducción de errores (que si se me olvida una foreign key por ahí, que si por qué falla esta consulta si está &#8220;perfecta&#8221; y después de media hora ves que era una coma, etc).</p>
<p>Además, el ordenador también crea las clases para manipular los datos (geters y seters entre otras muchas cosas).</p>
<p>En concreto con Doctrine (y symfony en general) eso se lo indicamos mediante archivos <a title="YML" href="http://es.wikipedia.org/wiki/YAML" target="_blank">YML</a></p>
<p>Hasta aquí todo bien pero&#8230; no hay soporte para vistas!! Entonces toca hacerlo a mano&#8230; Esto es un problema, porque empiezas a depender de tu <a title="Sistema Gesto de Bases de Datos" href="http://es.wikipedia.org/wiki/SGBD" target="_blank">SGBD</a> pero por otra parte, es vital si quieres obtener un buen rendimiento para determinadas consultas.</p>
<p>Bien,<strong> después de toda esta insustancial parrafada vayamos al turrón</strong></p>
<p>Usaré un ejemplo real, sacado de Wixet.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">create or replace view search_profile
<span style="color: #b1b100;">as</span>
SELECT user_id<span style="color: #339933;">,</span>gender<span style="color: #339933;">,</span>uid<span style="color: #339933;">,</span>birthday<span style="color: #339933;">,</span>city_id<span style="color: #339933;">,</span>country_id<span style="color: #339933;">,</span>town_id FROM profile</pre></div></div>

<p>Es simple, verdad? Así nos centraremos en lo importante, la clase Doctrine.</p>
<p>Diferenciamos 2 tipos de clases, las nuestras y las de doctrine. Las &#8220;nuestras&#8221; están vacías de serie mientras que en las de doctrine es donde está todo el meollo. El motivo es que si añadimos métodos propios, doctrine los machacará. Por eso están diferenciadas. Luego una hereda de otra así que el resultado final es algo totalmente homogéneo.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">abstract <span style="color: #000000; font-weight: bold;">class</span> BasesearchProfile <span style="color: #000000; font-weight: bold;">extends</span> sfDoctrineRecord
<span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">//Because profile is acl protected, we use this view to</span>
        <span style="color: #666666; font-style: italic;">//get some data when doing an user search</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> setTableDefinition<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-</span>\<span style="color: #339933;">&amp;</span>gt<span style="color: #339933;">;</span>setTableName<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'search_profile'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>hasColumn<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'user_id'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'integer'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">4</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
             <span style="color: #0000ff;">'type'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'integer'</span><span style="color: #339933;">,</span>
             <span style="color: #0000ff;">'primary'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">,</span>
             <span style="color: #0000ff;">'length'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #cc66cc;">4</span><span style="color: #339933;">,</span>
             <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>hasColumn<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'gender'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'integer'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
             <span style="color: #0000ff;">'type'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'integer'</span><span style="color: #339933;">,</span>
             <span style="color: #0000ff;">'length'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">,</span>
             <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>hasColumn<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'uid'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'string'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">25</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
             <span style="color: #0000ff;">'type'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'string'</span><span style="color: #339933;">,</span>
             <span style="color: #0000ff;">'unique'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">,</span>
             <span style="color: #0000ff;">'length'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #cc66cc;">25</span><span style="color: #339933;">,</span>
             <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>hasColumn<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'birthday'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'date'</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
             <span style="color: #0000ff;">'type'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'date'</span><span style="color: #339933;">,</span>
             <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>hasColumn<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'city_id'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'integer'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">4</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
             <span style="color: #0000ff;">'type'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'integer'</span><span style="color: #339933;">,</span>
             <span style="color: #0000ff;">'length'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #cc66cc;">4</span><span style="color: #339933;">,</span>
             <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>hasColumn<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'country_id'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'integer'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">4</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
             <span style="color: #0000ff;">'type'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'integer'</span><span style="color: #339933;">,</span>
             <span style="color: #0000ff;">'length'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #cc66cc;">4</span><span style="color: #339933;">,</span>
             <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>hasColumn<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'town_id'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'integer'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">4</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
             <span style="color: #0000ff;">'type'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'integer'</span><span style="color: #339933;">,</span>
             <span style="color: #0000ff;">'length'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #cc66cc;">4</span><span style="color: #339933;">,</span>
             <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> setUp<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        parent<span style="color: #339933;">::</span><span style="color: #004000;">setUp</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>hasOne<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'sfGuardUser as user'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
             <span style="color: #0000ff;">'local'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'user_id'</span><span style="color: #339933;">,</span>
             <span style="color: #0000ff;">'foreign'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'id'</span><span style="color: #339933;">,</span>
             <span style="color: #0000ff;">'onDelete'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'CASCADE'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>hasMany<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'interest as interests'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
             <span style="color: #0000ff;">'local'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'user_id'</span><span style="color: #339933;">,</span>
             <span style="color: #0000ff;">'foreign'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'profile_id'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>hasOne<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'city'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
             <span style="color: #0000ff;">'local'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'city_id'</span><span style="color: #339933;">,</span>
             <span style="color: #0000ff;">'foreign'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'city_id'</span><span style="color: #339933;">,</span>
             <span style="color: #0000ff;">'onDelete'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'SET NULL'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>hasOne<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'country'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
             <span style="color: #0000ff;">'local'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'country_id'</span><span style="color: #339933;">,</span>
             <span style="color: #0000ff;">'foreign'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'country_id'</span><span style="color: #339933;">,</span>
             <span style="color: #0000ff;">'onDelete'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'SET NULL'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
       <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>hasOne<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'city as town'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
             <span style="color: #0000ff;">'local'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'town_id'</span><span style="color: #339933;">,</span>
             <span style="color: #0000ff;">'foreign'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'city_id'</span><span style="color: #339933;">,</span>
             <span style="color: #0000ff;">'onDelete'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'SET NULL'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
       <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>hasMany<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'place as places'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
             <span style="color: #0000ff;">'refClass'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'placeUser'</span><span style="color: #339933;">,</span>
             <span style="color: #0000ff;">'local'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'user_id'</span><span style="color: #339933;">,</span>
             <span style="color: #0000ff;">'foreign'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'user_id'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>hasMany<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'workplace as workplaces'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
             <span style="color: #0000ff;">'refClass'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'workplaceUser'</span><span style="color: #339933;">,</span>
             <span style="color: #0000ff;">'local'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'user_id'</span><span style="color: #339933;">,</span>
             <span style="color: #0000ff;">'foreign'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'user_id'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>hasMany<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'school as schools'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
             <span style="color: #0000ff;">'refClass'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'schoolUser'</span><span style="color: #339933;">,</span>
             <span style="color: #0000ff;">'local'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'user_id'</span><span style="color: #339933;">,</span>
             <span style="color: #0000ff;">'foreign'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'user_id'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>hasMany<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'city as cityplace'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
             <span style="color: #0000ff;">'refClass'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'cityUser'</span><span style="color: #339933;">,</span>
             <span style="color: #0000ff;">'local'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'user_id'</span><span style="color: #339933;">,</span>
             <span style="color: #0000ff;">'foreign'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'user_id'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">//No full relation to make searches faster</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>hasMany<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'placeUser'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
             <span style="color: #0000ff;">'local'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'user_id'</span><span style="color: #339933;">,</span>
             <span style="color: #0000ff;">'foreign'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'user_id'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>hasMany<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'workplaceUser'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
             <span style="color: #0000ff;">'local'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'user_id'</span><span style="color: #339933;">,</span>
             <span style="color: #0000ff;">'foreign'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'user_id'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>hasMany<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'cityUser'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
             <span style="color: #0000ff;">'local'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'user_id'</span><span style="color: #339933;">,</span>
             <span style="color: #0000ff;">'foreign'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'user_id'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>hasMany<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'schoolUser'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
             <span style="color: #0000ff;">'local'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'user_id'</span><span style="color: #339933;">,</span>
             <span style="color: #0000ff;">'foreign'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'user_id'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Perdón por los  &#8220;&amp;gt; &#8221; pero es que el wordpress insiste en convertir los &#8220;&gt;&#8221;</p>
<p>El archivo puede ser algo confuso, pero su estructura es sencilla.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">//Primero definimos los datos de la tabla</span>
<span style="color: #666666; font-style: italic;">//En el método &quot;setTableDefinition&quot;</span>
<span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>setTableName<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'search_profile'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//Nombre</span>
<span style="color: #666666; font-style: italic;">//Y lo siguiente para cada tipo de dato</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>hasColumn<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'user_id'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'integer'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">4</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
             <span style="color: #0000ff;">'type'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'integer'</span><span style="color: #339933;">,</span>
             <span style="color: #0000ff;">'primary'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">,</span>
             <span style="color: #0000ff;">'length'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #cc66cc;">4</span><span style="color: #339933;">,</span>
             <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">//En el metodo setup</span>
&nbsp;
<span style="color: #339933;">&lt;</span>pre lang<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;php&quot;</span><span style="color: #339933;">&gt;</span>        parent<span style="color: #339933;">::</span><span style="color: #004000;">setUp</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><span style="color: #666666; font-style: italic;">//Ejecutamos el setup de la clase padre, que es la otra que hemos creado</span>
<span style="color: #666666; font-style: italic;">//Las relaciones. La estructura es sencilla si conoces algo de doctrine</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>hasOne<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'sfGuardUser as user'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
             <span style="color: #0000ff;">'local'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'user_id'</span><span style="color: #339933;">,</span>
             <span style="color: #0000ff;">'foreign'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'id'</span><span style="color: #339933;">,</span>
             <span style="color: #0000ff;">'onDelete'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'CASCADE'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

</pre>
<p>Ahora metemos esos archivos en sus respectivos directorios (/lib/model/doctrine en el caso de symfony) y ya lo tenemos!</p>
<p>Ahora ya puedes usar la clase pero ojo, es una vista, no intentes cambiar sus datos. Doctrine lanzará una excepción mysql si lo intentas. Para todo lo demás, funciona como una tabla normal.</p>
<p><strong>Nota</strong>: si esto te parece muy complicado, otra opcion es crear un archivo yml una tabla equivalente a la vista (en cuanto a datos y relaciones) y posteriormente eliminar la tabla de mysql e insertar tus vista. En este caso, ojo con usar atributos tipo timestamptable o poner ondelete cascade/update en las relaciones porque recuerda que una vista es sólo de lecutra.</p>
<p><strong>Nota2: </strong>Cuidado cuando hagas doctrine:clean, como no encontrará un yml correspondiente a esa tabla te dirá que si quieres borrar la clase. Tendrás que responder que no, lógicamente.</p>
<div class="shr-publisher-1235"></div>

<p>Entradas relacionadas:<ol><li><a href='http://www.congdegnu.es/2009/05/04/conoce-sql-views-vistas/' rel='bookmark' title='Permanent Link: Conoce SQL &#8211; VIEWS (vistas)'>Conoce SQL &#8211; VIEWS (vistas)</a> <small>Ahora ya sabemos como hacer consultas bastante completas, pero ademas...</small></li>
<li><a href='http://www.congdegnu.es/2010/09/27/autenticacion-ldap-en-symfony/' rel='bookmark' title='Permanent Link: Autenticación LDAP en Symfony'>Autenticación LDAP en Symfony</a> <small>Buenas, hoy voy a hablaros de autenticación de usuarios usando...</small></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.congdegnu.es/2010/12/21/vistas-en-doctrine-orm/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Autenticación LDAP en Symfony</title>
		<link>http://www.congdegnu.es/2010/09/27/autenticacion-ldap-en-symfony/</link>
		<comments>http://www.congdegnu.es/2010/09/27/autenticacion-ldap-en-symfony/#comments</comments>
		<pubDate>Mon, 27 Sep 2010 21:34:47 +0000</pubDate>
		<dc:creator>Maxpowel</dc:creator>
				<category><![CDATA[Guias y manuales]]></category>
		<category><![CDATA[Programación]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[doctrine]]></category>
		<category><![CDATA[ldap]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://www.congdegnu.es/?p=1196</guid>
		<description><![CDATA[Buenas, hoy voy a hablaros de autenticación de usuarios usando LDAP en Symfony. Symfony es un framework PHP, el cual ofrece la posibilidad de usar LDAP para autenticar usuarios. Pero sólo eso, la &#8220;posibilidad&#8221; nada más (que no es poco). Nosotros tenemos que crear la clase que conecte symfony con el servidor ldap y que [...]]]></description>
			<content:encoded><![CDATA[<p>Buenas, hoy voy a hablaros de autenticación de usuarios usando LDAP en Symfony.</p>
<p>Symfony es un framework PHP, el cual ofrece la posibilidad de usar LDAP para autenticar usuarios. Pero sólo eso, la &#8220;posibilidad&#8221; nada más (que no es poco). Nosotros tenemos que crear la clase que conecte symfony con el servidor ldap y que modifique, cree y haga todo lo necesario en el mismo. Exactamente eso es lo que tendremos al terminar de leer esta entrada.</p>
<h2>¿Por qué usar LDAP?</h2>
<p>De esta manera usamos un servicio de autenticación genérico. Imagina que nosotros tenemos nuestra página web con sus usuarios y de repente se nos antoja instalar un foro o un blog o un servidor xmpp&#8230; software de terceros que manejan los usuarios como quieren. Con LDAP nos olvidamos de todos los rollos, configuramos todo ese software para que use LDAP y listo.</p>
<h2>¿Cómo trabaja Symfony con LDAP?<a href="http://www.congdegnu.es/wp-content/uploads/2010/09/symfony-logo.png"><img class="size-full wp-image-1208 alignright" src="http://www.congdegnu.es/wp-content/uploads/2010/09/symfony-logo.png" alt="" width="271" height="115" /></a></h2>
<p>Es simple. Symfony sigue manteniendo su base de datos pero ademas comprueba que el usuario es válido en el servidor LDAP. Esto es que cuando te autenticas en Symfony, primero mira si el usuario es válido en la base de datos de Symfony y si es válido lo mira en LDAP. Si uno de los dos falla, la autenticación falla. Entendemos entonces que la &#8220;dificultad&#8221; está en mantener las bases de datos sincronizadas.</p>
<h2>¿Qué haremos nosotros?</h2>
<p>Lo que haremos será que cada vez que symfony produce un evento (nuevo usuario, usuario eliminado o cambio de contraseña) symfony se lo notificará al servidor LDAP.</p>
<h2><span id="more-1196"></span>Comencemos&#8230;</h2>
<p>Antes de nada decir que uso sfDoctrineGuardPlugin para la gestión de usuarios y supongo que tienes una instalación de Symfony funcionando. Según el README del plugin tenemos que poner algo así en app.yml</p>
<pre>all:
  sf_guard_plugin:
    check_password_callable: [ldapLogin, checkPassword]</pre>
<p>Y por requerimientos del plugin ldapLogin (que así he llamado yo a mi clase) tiene que ser una clase estática y tener un método llamado checkPassword que devolverá verdadero o falso. Además los argumentos son usuario y contraseña (en ese orden).<br />
Una vez hemos metido ese parámetro en app.yml creamos en /lib (si, el lib del proyecto así te sirve para todas la aplicaciones) &#8220;ldapLogin.class.php&#8221;.</p>
<p>Yo he aprovechado y en esa misma clase he metido los métodos de creación de usuario, modificación y borrado. El esqueleto de la clase sería algo así</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> LdapLogin <span style="color: #009900;">&#123;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> static <span style="color: #000000; font-weight: bold;">function</span> checkPassword<span style="color: #009900;">&#40;</span><span style="color: #000088;">$user</span><span style="color: #339933;">,</span><span style="color: #000088;">$pass</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		<span style="color: #666666; font-style: italic;">//Devolver verdadero o falso</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> static <span style="color: #000000; font-weight: bold;">function</span> createUser<span style="color: #009900;">&#40;</span><span style="color: #000088;">$user</span><span style="color: #339933;">,</span><span style="color: #000088;">$pass</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> static <span style="color: #000000; font-weight: bold;">function</span> removeUser<span style="color: #009900;">&#40;</span><span style="color: #000088;">$user</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> static <span style="color: #000000; font-weight: bold;">function</span> updatePassword<span style="color: #009900;">&#40;</span><span style="color: #000088;">$user</span><span style="color: #339933;">,</span><span style="color: #000088;">$pass</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
&nbsp;
	<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Ya tenemos un poco en mente lo que queremos. Antes de continuar, vamos hacer nuestro sistema un poco más versátil. Como la localización, datos de administrador y todo lo relativo a LDAP puede variar vamos a hacer que esos datos sean leídos de un archivo de configuración.</p>
<p>Yo he utilizado el archivo config/settings.yml del proyecto y la estructura que he elegido es esta:</p>

<div class="wp_syntax"><div class="code"><pre class="yml" style="font-family:monospace;">all:
  ldap:
     admin: uid=admin,ou=system
     password: 123456
     hostname: 127.0.0.1
     suffix: ou=users,ou=system</pre></div></div>

<p>En admin pones el dn del admin ldap. Suffix es donde se guardan los usuarios. Esta configuración es la que se usaría si tu servidor LDAP es Apache Directory Server.</p>
<p>Para acceder a esa configuración podemos hace<a href="http://www.congdegnu.es/wp-content/uploads/2010/09/logo_apacheDS.png"><img class="size-full wp-image-1209 alignright" src="http://www.congdegnu.es/wp-content/uploads/2010/09/logo_apacheDS.png" alt="Servidor LDAP Apache Directory Server" width="128" height="128" /></a>rlo de dos maneras, una es directamente a cada valor</p>
<p>sfConfig::get(&#8216;sf_ldap_suffix&#8217;)</p>
<p>O cargando el archivo yml en una variable</p>
<p>$settings = sfYaml::load(sfConfig::get(&#8216;sf_root_dir&#8217;).&#8221;/config/settings.yml&#8221;);<br />
$suffix = $settings['all']['ldap']['suffix'];</p>
<p>Estos dos códigos hacen lo mismo. Si sólo vas a coger un dato la primera opción es mejor mientras que para varios yo prefiero la segunda pero para gustos los colores.</p>
<p>Ya sabemos como lo queremos hacer. Ahora queda hacerlo. Lo primero es saber cómo conectarnos a un servidor LDAP mediante php. Este código te ayudará</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$ds</span> <span style="color: #339933;">=</span> <span style="color: #990000;">ldap_connect</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$host</span><span style="color: #339933;">,</span><span style="color: #000088;">$port</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><span style="color: #666666; font-style: italic;">//Nos conectamos</span>
<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$ds</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> Exception<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Cant connect to LDAP host &quot;'</span><span style="color: #339933;">.</span><span style="color: #000088;">$host</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'&quot;'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">//Si no se pudo conectar, lazamos una excepción</span>
<span style="color: #990000;">ldap_set_option</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$ds</span><span style="color: #339933;">,</span> LDAP_OPT_PROTOCOL_VERSION<span style="color: #339933;">,</span> <span style="color: #cc66cc;">3</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><span style="color: #666666; font-style: italic;">//Usamos la versión 3, si no lo pones php or defecto usa una version mas vieja</span>
&nbsp;
<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">ldap_bind</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$ds</span><span style="color: #339933;">,</span> <span style="color: #000088;">$admin</span><span style="color: #339933;">,</span>  <span style="color: #000088;">$adminPass</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> Exception<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Cant bind to LDAP host &quot;'</span><span style="color: #339933;">.</span><span style="color: #000088;">$host</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'&quot;'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">//Nos autenticamos como administrador. Si todo va bien la conexión esta hecha</span></pre></div></div>

<p>Ahora necesitamos saber cómo insertar, modificar y elminar registros en el servidor LDAP.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">//Insertar usuario en LDAP</span>
<span style="color: #666666; font-style: italic;">//$user es la variable donde tenemos el nombre de usuario. Tiene que se el mismo que el nombre de usuario de symfony</span>
&nbsp;
                <span style="color: #000088;">$info</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;sn&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">=</span> <span style="color: #000088;">$user</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$info</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;uid&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">=</span> <span style="color: #000088;">$user</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$info</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;cn&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">=</span> <span style="color: #000088;">$user</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$info</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;userPassword&quot;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;{SHA}&quot;</span><span style="color: #339933;">.</span> <span style="color: #990000;">base64_encode</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">sha1</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$pass</span><span style="color: #339933;">,</span><span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    	<span style="color: #000088;">$info</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;objectclass&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;person&quot;</span><span style="color: #339933;">;</span>
    	<span style="color: #000088;">$info</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;objectclass&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;inetOrgPerson&quot;</span><span style="color: #339933;">;</span>
    	<span style="color: #000088;">$info</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;objectclass&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;top&quot;</span><span style="color: #339933;">;</span>
    	<span style="color: #000088;">$info</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;objectclass&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;organizationalPerson&quot;</span><span style="color: #339933;">;</span>
		<span style="color: #b1b100;">return</span> <span style="color: #990000;">ldap_add</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$ds</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;uid=&quot;</span><span style="color: #339933;">.</span><span style="color: #000088;">$user</span><span style="color: #339933;">.</span><span style="color: #0000ff;">&quot;, &quot;</span><span style="color: #339933;">.</span>sfConfig<span style="color: #339933;">::</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'sf_ldap_suffix'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$info</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Vemos que para user password usamos ciertas funciones extra. Eso es porque a mi me gusta cifrar los datos sensibles. Si usas directamente la variable $pass, ésta se guardará en texto plano.</p>
<p>Eliminar el usuario es más sencillo</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">    <span style="color: #990000;">ldap_delete</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$ds</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;uid=&quot;</span><span style="color: #339933;">.</span><span style="color: #000088;">$user</span><span style="color: #339933;">.</span><span style="color: #0000ff;">&quot;, &quot;</span><span style="color: #339933;">.</span>sfConfig<span style="color: #339933;">::</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'sf_ldap_suffix'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Y cambiar la contraseña también es muy fácil</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$pass</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;userPassword&quot;</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">&quot;{SHA}&quot;</span><span style="color: #339933;">.</span> <span style="color: #990000;">base64_encode</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">sha1</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$pass</span><span style="color: #339933;">,</span><span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #b1b100;">return</span> <span style="color: #990000;">ldap_modify</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$ds</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;uid=&quot;</span><span style="color: #339933;">.</span><span style="color: #000088;">$user</span><span style="color: #339933;">.</span><span style="color: #0000ff;">&quot;, &quot;</span><span style="color: #339933;">.</span>sfConfig<span style="color: #339933;">::</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'sf_ldap_suffix'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$pass</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Si juntamos todo, obtenemos la clase completa</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> LdapLogin <span style="color: #009900;">&#123;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> static <span style="color: #000000; font-weight: bold;">function</span> checkPassword<span style="color: #009900;">&#40;</span><span style="color: #000088;">$user</span><span style="color: #339933;">,</span><span style="color: #000088;">$pass</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$ldapUser</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;uid=&quot;</span><span style="color: #339933;">.</span><span style="color: #000088;">$user</span><span style="color: #339933;">.</span><span style="color: #0000ff;">&quot;,&quot;</span><span style="color: #339933;">.</span>sfConfig<span style="color: #339933;">::</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'sf_ldap_suffix'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>		
&nbsp;
		<span style="color: #000088;">$ds</span> <span style="color: #339933;">=</span> <span style="color: #990000;">ldap_connect</span><span style="color: #009900;">&#40;</span>sfConfig<span style="color: #339933;">::</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'sf_ldap_hostname'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><span style="color: #cc66cc;">10389</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #990000;">ldap_set_option</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$ds</span><span style="color: #339933;">,</span> LDAP_OPT_PROTOCOL_VERSION<span style="color: #339933;">,</span> <span style="color: #cc66cc;">3</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #b1b100;">return</span> <span style="color: #339933;">@</span><span style="color: #990000;">ldap_bind</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$ds</span><span style="color: #339933;">,</span> <span style="color: #000088;">$ldapUser</span><span style="color: #339933;">,</span> <span style="color: #000088;">$pass</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//BIND</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> static <span style="color: #000000; font-weight: bold;">function</span> createUser<span style="color: #009900;">&#40;</span><span style="color: #000088;">$user</span><span style="color: #339933;">,</span><span style="color: #000088;">$pass</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>sfConfig<span style="color: #339933;">::</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'sf_ldap_admin'</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #0000ff;">&quot;&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
			<span style="color: #000088;">$settings</span> <span style="color: #339933;">=</span> sfYaml<span style="color: #339933;">::</span><span style="color: #004000;">load</span><span style="color: #009900;">&#40;</span>sfConfig<span style="color: #339933;">::</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'sf_root_dir'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">&quot;/config/settings.yml&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #000088;">$admin</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$settings</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'all'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'ldap'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'admin'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
			<span style="color: #000088;">$adminPass</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$settings</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'all'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'ldap'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'password'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
			<span style="color: #000088;">$host</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$settings</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'all'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'ldap'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'hostname'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span><span style="color: #b1b100;">else</span><span style="color: #009900;">&#123;</span>
			<span style="color: #000088;">$admin</span> <span style="color: #339933;">=</span> sfConfig<span style="color: #339933;">::</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'sf_ldap_admin'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #000088;">$adminPass</span> <span style="color: #339933;">=</span> sfConfig<span style="color: #339933;">::</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'sf_ldap_password'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #000088;">$host</span> <span style="color: #339933;">=</span> sfConfig<span style="color: #339933;">::</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'sf_ldap_hostname'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
&nbsp;
		<span style="color: #000088;">$ds</span> <span style="color: #339933;">=</span> <span style="color: #990000;">ldap_connect</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$host</span><span style="color: #339933;">,</span><span style="color: #cc66cc;">10389</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$ds</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> Exception<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Cant connect to LDAP host &quot;'</span><span style="color: #339933;">.</span><span style="color: #000088;">$host</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'&quot;'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #990000;">ldap_set_option</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$ds</span><span style="color: #339933;">,</span> LDAP_OPT_PROTOCOL_VERSION<span style="color: #339933;">,</span> <span style="color: #cc66cc;">3</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">ldap_bind</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$ds</span><span style="color: #339933;">,</span> <span style="color: #000088;">$admin</span><span style="color: #339933;">,</span>  <span style="color: #000088;">$adminPass</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> Exception<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Cant bind to LDAP host &quot;'</span><span style="color: #339933;">.</span><span style="color: #000088;">$host</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'&quot;'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$info</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;sn&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">=</span> <span style="color: #000088;">$user</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$info</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;uid&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">=</span> <span style="color: #000088;">$user</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$info</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;cn&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">=</span> <span style="color: #000088;">$user</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$info</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;userPassword&quot;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;{SHA}&quot;</span><span style="color: #339933;">.</span> <span style="color: #990000;">base64_encode</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">sha1</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$pass</span><span style="color: #339933;">,</span><span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    	<span style="color: #000088;">$info</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;objectclass&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;person&quot;</span><span style="color: #339933;">;</span>
    	<span style="color: #000088;">$info</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;objectclass&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;inetOrgPerson&quot;</span><span style="color: #339933;">;</span>
    	<span style="color: #000088;">$info</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;objectclass&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;top&quot;</span><span style="color: #339933;">;</span>
    	<span style="color: #000088;">$info</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;objectclass&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;organizationalPerson&quot;</span><span style="color: #339933;">;</span>
		<span style="color: #b1b100;">return</span> <span style="color: #990000;">ldap_add</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$ds</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;uid=&quot;</span><span style="color: #339933;">.</span><span style="color: #000088;">$user</span><span style="color: #339933;">.</span><span style="color: #0000ff;">&quot;, &quot;</span><span style="color: #339933;">.</span>sfConfig<span style="color: #339933;">::</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'sf_ldap_suffix'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$info</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> static <span style="color: #000000; font-weight: bold;">function</span> removeUser<span style="color: #009900;">&#40;</span><span style="color: #000088;">$user</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>sfConfig<span style="color: #339933;">::</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'sf_ldap_admin'</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #0000ff;">&quot;&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
			<span style="color: #000088;">$settings</span> <span style="color: #339933;">=</span> sfYaml<span style="color: #339933;">::</span><span style="color: #004000;">load</span><span style="color: #009900;">&#40;</span>sfConfig<span style="color: #339933;">::</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'sf_root_dir'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">&quot;/config/settings.yml&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #000088;">$admin</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$settings</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'all'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'ldap'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'admin'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
			<span style="color: #000088;">$adminPass</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$settings</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'all'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'ldap'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'password'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
			<span style="color: #000088;">$host</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$settings</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'all'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'ldap'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'hostname'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span><span style="color: #b1b100;">else</span><span style="color: #009900;">&#123;</span>
			<span style="color: #000088;">$admin</span> <span style="color: #339933;">=</span> sfConfig<span style="color: #339933;">::</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'sf_ldap_admin'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #000088;">$adminPass</span> <span style="color: #339933;">=</span> sfConfig<span style="color: #339933;">::</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'sf_ldap_password'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #000088;">$host</span> <span style="color: #339933;">=</span> sfConfig<span style="color: #339933;">::</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'sf_ldap_hostname'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
&nbsp;
		<span style="color: #000088;">$ds</span> <span style="color: #339933;">=</span> <span style="color: #990000;">ldap_connect</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$host</span><span style="color: #339933;">,</span><span style="color: #cc66cc;">10389</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$ds</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> Exception<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Cant connect to LDAP host &quot;'</span><span style="color: #339933;">.</span><span style="color: #000088;">$host</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'&quot;'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #990000;">ldap_set_option</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$ds</span><span style="color: #339933;">,</span> LDAP_OPT_PROTOCOL_VERSION<span style="color: #339933;">,</span> <span style="color: #cc66cc;">3</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">ldap_bind</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$ds</span><span style="color: #339933;">,</span> <span style="color: #000088;">$admin</span><span style="color: #339933;">,</span>  <span style="color: #000088;">$adminPass</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> Exception<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Cant bind to LDAP host &quot;'</span><span style="color: #339933;">.</span><span style="color: #000088;">$host</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'&quot;'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #b1b100;">return</span> <span style="color: #990000;">ldap_delete</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$ds</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;uid=&quot;</span><span style="color: #339933;">.</span><span style="color: #000088;">$user</span><span style="color: #339933;">.</span><span style="color: #0000ff;">&quot;, &quot;</span><span style="color: #339933;">.</span>sfConfig<span style="color: #339933;">::</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'sf_ldap_suffix'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> static <span style="color: #000000; font-weight: bold;">function</span> updatePassword<span style="color: #009900;">&#40;</span><span style="color: #000088;">$user</span><span style="color: #339933;">,</span><span style="color: #000088;">$pass</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>sfConfig<span style="color: #339933;">::</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'sf_ldap_admin'</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #0000ff;">&quot;&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
			<span style="color: #000088;">$settings</span> <span style="color: #339933;">=</span> sfYaml<span style="color: #339933;">::</span><span style="color: #004000;">load</span><span style="color: #009900;">&#40;</span>sfConfig<span style="color: #339933;">::</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'sf_root_dir'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">&quot;/config/settings.yml&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #000088;">$admin</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$settings</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'all'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'ldap'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'admin'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
			<span style="color: #000088;">$adminPass</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$settings</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'all'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'ldap'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'password'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
			<span style="color: #000088;">$host</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$settings</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'all'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'ldap'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'hostname'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span><span style="color: #b1b100;">else</span><span style="color: #009900;">&#123;</span>
			<span style="color: #000088;">$admin</span> <span style="color: #339933;">=</span> sfConfig<span style="color: #339933;">::</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'sf_ldap_admin'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #000088;">$adminPass</span> <span style="color: #339933;">=</span> sfConfig<span style="color: #339933;">::</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'sf_ldap_password'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #000088;">$host</span> <span style="color: #339933;">=</span> sfConfig<span style="color: #339933;">::</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'sf_ldap_hostname'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
&nbsp;
		<span style="color: #000088;">$ds</span> <span style="color: #339933;">=</span> <span style="color: #990000;">ldap_connect</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$host</span><span style="color: #339933;">,</span><span style="color: #cc66cc;">10389</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$ds</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> Exception<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Cant connect to LDAP host &quot;'</span><span style="color: #339933;">.</span><span style="color: #000088;">$host</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'&quot;'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #990000;">ldap_set_option</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$ds</span><span style="color: #339933;">,</span> LDAP_OPT_PROTOCOL_VERSION<span style="color: #339933;">,</span> <span style="color: #cc66cc;">3</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">ldap_bind</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$ds</span><span style="color: #339933;">,</span> <span style="color: #000088;">$admin</span><span style="color: #339933;">,</span>  <span style="color: #000088;">$adminPass</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> Exception<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Cant bind to LDAP host &quot;'</span><span style="color: #339933;">.</span><span style="color: #000088;">$host</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'&quot;'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #000088;">$pass</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;userPassword&quot;</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">&quot;{SHA}&quot;</span><span style="color: #339933;">.</span> <span style="color: #990000;">base64_encode</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">sha1</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$pass</span><span style="color: #339933;">,</span><span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #b1b100;">return</span> <span style="color: #990000;">ldap_modify</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$ds</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;uid=&quot;</span><span style="color: #339933;">.</span><span style="color: #000088;">$user</span><span style="color: #339933;">.</span><span style="color: #0000ff;">&quot;, &quot;</span><span style="color: #339933;">.</span>sfConfig<span style="color: #339933;">::</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'sf_ldap_suffix'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$pass</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Desde cualquier parte de symfony podremos usar esta clase.</p>
<p>Para terminar vamos a poner la guinda al pastel. Cuando se cree el usuario en symfony, también haremos que se cree en el sevidor LDAP.</p>
<p>En mi aplicación la creación de un usuario es algo bastante complejo y por ese motivo uso el task create-user de sfGuard. Por supuesto que puedes modificar la clase sfGuardUser para que cuango haga insert o update ejecute el código para insertar el usuario pero yo voy a exponer mi método.</p>
<p>Abrimos el archivo plugins/sfDoctrineGuardPlugin/lib/task/sfGuardCreateUserTask.class.php<br />
En el método execute insertamos justo al principio este código</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>LdapLogin<span style="color: #339933;">::</span><span style="color: #004000;">createUser</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$arguments</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'username'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span><span style="color: #000088;">$arguments</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'password'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
        <span style="color: #b1b100;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> Exception<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'User already exists in LDAP database'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Creo que estas líneas se explican por sí solas. Intenta crear el usuario en el servidor LDAP. Si ya existe lanza una excepción tirando abajo el proceso de creación d<a href="http://www.congdegnu.es/wp-content/uploads/2010/09/logo_doctrine.png"><img class="alignright size-full wp-image-1211" src="http://www.congdegnu.es/wp-content/uploads/2010/09/logo_doctrine.png" alt="" /></a>el usuario.</p>
<p>Lo ideal es que crees otros task para actualizar y borrar el usuario ya que si te limitas a hacer un delete al user sólo borrarás al usuario de la base de datos de symfony pero no del servidor LDAP. Aunque como dije antes, puedes hacer que las acciones de update y delete de un objeto Doctrine (ORM usado por Symfony) hagan más cosas. Probablemente otro día te diga como hacerlo.</p>
<p>Nos vemos!</p>
<div class="shr-publisher-1196"></div>

<p>Entradas relacionadas:<ol><li><a href='http://www.congdegnu.es/2010/12/21/vistas-en-doctrine-orm/' rel='bookmark' title='Permanent Link: Vistas en Doctrine ORM'>Vistas en Doctrine ORM</a> <small>Saludos! que tal? Espero que bien. Esta vez te voy...</small></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.congdegnu.es/2010/09/27/autenticacion-ldap-en-symfony/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Crear plugins para Openfire</title>
		<link>http://www.congdegnu.es/2010/09/18/crear-plugins-para-openfire/</link>
		<comments>http://www.congdegnu.es/2010/09/18/crear-plugins-para-openfire/#comments</comments>
		<pubDate>Sat, 18 Sep 2010 16:08:40 +0000</pubDate>
		<dc:creator>Maxpowel</dc:creator>
				<category><![CDATA[Guias y manuales]]></category>
		<category><![CDATA[Programación]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[jsp]]></category>
		<category><![CDATA[openfire]]></category>
		<category><![CDATA[plugin]]></category>
		<category><![CDATA[servlet]]></category>
		<category><![CDATA[xmpp]]></category>

		<guid isPermaLink="false">http://www.congdegnu.es/?p=1191</guid>
		<description><![CDATA[Buenas, probablemente si has llegado hasta aquí es porque sabes qué es Openfire y te interesa saber hacer un plugin. Si no, explico brevemente qué es. Openfire es un servidor XMPP. El protocolo XMPP es por ejemplo el que usa google para Gtalk. Seguro que con esta información supones para lo que sirve. Sí, Openfire [...]]]></description>
			<content:encoded><![CDATA[<p>Buenas, probablemente si has llegado hasta aquí es porque sabes qué es Openfire y te interesa saber hacer un plugin. Si no, explico brevemente qué es.</p>
<p>Openfire es un servidor XMPP. El protocolo XMPP es por ejemplo el que usa google para Gtalk. Seguro que con esta información supones para lo que sirve. Sí, Openfire es un servidor de mensajería instántanea libre y que usa un protocolo libre.</p>
<p>De serie openfire trae una herramienta muy potente, que es la consola de administración. Desde ella puedes gestionar absolutamente todo y además de manera visual (se llama consola pero es una interfaz web). Bien, para hacer cosas a mano esta interfaz web está muy bien pero cuando queremos hac<a href="http://www.congdegnu.es/wp-content/uploads/2010/09/openfire.png"><img class="size-full wp-image-1192 alignright" src="http://www.congdegnu.es/wp-content/uploads/2010/09/openfire.png" alt="" width="385" height="112" /></a>er cosas desde una aplicación externa lo más correcto es mediante plugins. También se podría con curl ir navegando por la página pero, creéme, sería una chapuza que no da más que problemas y te lo digo por experiencia <img src='http://www.congdegnu.es/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> <span id="more-1191"></span>Si nuestra aplicación es java, podemos usar directamente el API pero resulta que yo programo las páginas web en PHP. Openfire está hecho en java así que la solución es enviar peticiones al servidor a traves de una conexion http. Un plugin de Openfire recibirá esas peticiones y hará cosas al respecto.</p>
<p>Para comprender fácilmente cómo funcionan estos plugins os pongo mi ejemplo.<br />
En mi página los usuarios pueden hablar entre ellos mediante un chat y un usuario sólo puede hablar con sus amigos. Cuando en la página web dos usuarios se hacen amigos se envía una petición al servidor XMPP para que añada como contactos a los usuarios en sendas cuentas. En mi caso, cuando se hacen amigos se envía una petición del tipo &#8220;http://servidor.com:9090/plugins/rosterManager/rostermanager?type=create&amp;username=usuario&amp;jid=amigo@servidor.com&amp;secret=tSLl7i5t&#8221;</p>
<p>La petición va al puerto 9090 (es por el que escucha openfire) y el plugin es &#8220;rosterManager&#8221;. Los parámetros son type, username&#8230; esos los he puesto yo porque me ha dado la gana, pueden ser los que tu quieras o necesites. Además el servidor nos responde con los resultados que en mi caso son éxito o no éxito (e indicando el problema) siendo así muy fácil saber si todo ha ido bien.</p>
<p>Después de todo este rollo vamos al tema.</p>
<h2>SOFTWARE NECESARIO</h2>
<ul>
<li>Necesitamos el código fuente de openfire. No es que vayamos a compilar todo openfire, el motivo es que ahí tienen todo preparadito para compilar y empaquetar los plugins. Lo podemos encontrar aquí http://www.igniterealtime.org/downloads/source.jsp</li>
<li>Ant. Está en los repositorios así que con aptitude lo instalas</li>
<li>JDK para compilar Java</li>
<li>Un plugin de ejemplo (para seguir los pasos y tenerlo como base más que nada) http://wixet.googlecode.com/files/rostermanager.tar.gz</li>
</ul>
<p>Una vez tengas todo esto desempaqueta el código fuente de openfire, entra en el directorio y ejecuta &#8220;ant plugins&#8221;. Si todo va bien terminará sin errores. Yo tuve un problema y es que el script comprueba tu versión de ant y yo tenía instalada una más nueva. Hay dos opciones, o modificar el script y añadir nuestra version o instalar una versión más vieja. Yo edité el archivo build.xml y por la línea 226 vemos que comprueba las versiones. Añade una línea exactamente igual pero con tu versión. En mi caso metí esta línea</p>
<p>&lt;contains string=&#8221;${ant.version}&#8221; substring=&#8221;1.8&#8243;/&gt;</p>
<p>Los plugins compilados y empaquetados se crearán en target/openfire/plugins. El archivo que se genere en este directorio es el que seleccionaremos desde la consola de administración para instalar el plugin. Por último, nuestro código fuente (el que se compilará) lo tenemos en src/plugins.</p>
<p>Si todo ha ido bien ya tenemos todo lo necesario para ponernos picar código.</p>
<h2>CREAR EL PLUGIN</h2>
<p>Un plugin de openfire está dividido en dos partes:</p>
<ul>
<li>Servlet: Es la parte web. Nos sirve para comunicarnos con el plugin tanto directamente (como lo hará nuestra aplicación externa) como dentro de la consola de administración. Sí, crearemos un apartado dentro de la consola para configurar el plugin. Si te fijas en la url que dije antes (http://servidor.com:9090/plugins/rosterManager/rostermanager?type=create&amp;username=usuario&amp;jid=amigo@servidor.com&amp;secret=tSLl7i5t) está el parámetro secret. Esa variable la uso para que sólo quien conozca esa clave pueda mandar órdenes al plugin. Esta clave (así como otras cosas como activar el plugin, direcciones ip admitidas&#8230;) se configura desde la sección que crearemos para la consola.</li>
<li>La otra parte es el programa en sí. El código java que hará las tareas de verdad. Es sin duda la parte más divertida. Ahora que no me oye, diré que el servlet es un coñazo pero es necesario.</li>
</ul>
<p>La estructura de directorios del plugin es algo así:</p>
<p><a href="http://www.congdegnu.es/wp-content/uploads/2010/09/arbol.png"><img class="aligncenter size-full wp-image-1193" src="http://www.congdegnu.es/wp-content/uploads/2010/09/arbol.png" alt="" /></a></p>
<p>En este caso el plugin se llama rostermanager (roster es como se le llama a la lista de contactos). En el raíz (rostermanager) sólo hay archivos de información, el icono del plugin y esas cosas. Luego pongo para descargar un ejemplo de plugin para que lo veas, que tardarás menos en verlo y comprenderlo que en leer (y quizá entender) mi explicación.</p>
<p>En el directorio &#8220;web&#8221; tenemos todo lo relacionado con lo que se mostrará en la sección de la consola. Es simplemente un jsp (como un php pero de java). Aquí pones las tablas y todas las cosas que quieras que se muestren. No olvides configurar el archivo &#8220;WEB-INF/web-custom.xml&#8221;. La configuración de ese archivo sirve para indicar a qué plugin manda la información el jsp y cosas así. Si es un plugin sencillo (como el mío) la configuración consiste en cambiar &#8220;rostermanager&#8221; por el nombre de tu plugin todas las veces que aparezca.</p>
<p>Ahora nos vamos a la carpeta &#8220;plugin&#8221;. Dentro encontramos el archivo &#8220;RosterManagerPlugin.java&#8221;. Que bien por fin un archivo java, ya podemos programar!. Si, en este archivo es donde está todo el meollo. Consiste en una clase a la que le añades todos los métodos que quieras. En mi caso se llama &#8220;RosterManagerPlugin&#8221; y si estás usando mi archivo de configuración de antes, tu clase se llamaría TuClasePlugin. Esta clase implementa las clases Plugin y PropertyEventListener y por este motivo tienes que definir ciertas funciones que son para inicializar el plugin y esas cosas. Sólo me queda por decir que aquí puedes usar el API de openfire (http://www.igniterealtime.org/builds/openfire/docs/latest/documentation/javadoc/index.html). Este api tiene toda tipo de clases para hacer todo lo que quieras con el servidor xmpp.</p>
<p>Por último vamos al directorio rosterManager (que en tu caso será el nombre de tu plugin) dentro del directorio plugin. En él vemos RosterManagerServlet.java que va a ser quien instancie nuestra clase y nos comunique con el exterior. Este archivo recibirá los parametros de las peticiones y las gestionará. En el ejemplo mencionado anteriormente, (http://servidor.com:9090/plugins/rosterManager/rostermanager?type=create&amp;username=usuario&amp;jid=amigo@servidor.com&amp;secret=tSLl7i5t&#8221;) a este archivo le llegarán los parámetros type, usuario, jid&#8230; y hará lo que tenga que hacer con ellos. Vemos que esta clase tiene un método de inicialización donde obtenemos un objeto que no es más que un objeto de la clase que hemos creado antes.</p>
<p>En mi caso, si el &#8220;type&#8221; es &#8220;create&#8221; ejecuto &#8220;plugin.createRoster(username,jid);&#8221;. El método createRoster(username,jid) está definido en el archivo de antes. Tenemos que pensar que esta clase se ejecutará como una página web. Se hace la petición, se procesan los datos, se muestran y termina. Por este motivo es bueno mostrar datos de lo que ha pasado. En mi caso muestro mensajes en formato json informando de si todo ha ido bien o si ha ocurrido algún problema. Por así decirlo, el metodo doGet sería como el main de una aplicación java normal y el archivo donde creamos la otra clase es una biblioteca.</p>
<p>Y esto es todo. Puede parecer complicado y lioso pero es sencillo. Este tipo de plugin es el básico, una vez cojas práctica puedes liar la madeja todo lo que quieras aunque normalmente los plugin hacen &#8220;una cosa y punto&#8221;. Recueda que no es bueno hacer &#8220;algo&#8221; que lo haga todo, sino muchas cosas pequeñas que hagan poco pero que lo hagan bien.</p>
<p>Una plantilla de plugin (que puedes usar y modificar) sería esta http://wixet.googlecode.com/files/rostermanager.tar.gz (la misma que he puesto arriba). Ahora te toca investigar por el API de Openfire para saber cómo usar las clases y todas esas cosas.</p>
<p>Se que este manual no es más que unas pequeñas directrices pero espero que te ayude a asentar una base.</p>
<p>Nos vemos!</p>
<div class="shr-publisher-1191"></div>

<p>Entradas relacionadas:<ol><li><a href='http://www.congdegnu.es/2008/11/24/crear-usbs-con-gnulinux/' rel='bookmark' title='Permanent Link: crear USBs con GNU/Linux'>crear USBs con GNU/Linux</a> <small>Los que somos adictos a instalar y probar mil distribuciones...</small></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.congdegnu.es/2010/09/18/crear-plugins-para-openfire/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>

