<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-5416816</id><updated>2011-04-21T22:18:18.611+02:00</updated><title type='text'>El arte de programar</title><subtitle type='html'>Un weblog donde expongo todos aquellos retos (insignificantes o apasionantes) de la programación entre otras cosas.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://sistemasorp.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://sistemasorp.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>sistemasorp</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>36</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-5416816.post-412860643196359894</id><published>2008-01-26T20:43:00.000+01:00</published><updated>2008-01-26T20:45:41.002+01:00</updated><title type='text'>Me cambio de vecindario</title><content type='html'>Dejo blogger para publicar un blog en mi propio dominio. A partir de ahora escribiré en este y todos los artículos que hay en el actual los iré copiando al nuevo. Si quereis cambiar vuestros enlaces al nuevo, la url es:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.sistemasorp.es"&gt;http://www.sistemasorp.es&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5416816-412860643196359894?l=sistemasorp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sistemasorp.blogspot.com/feeds/412860643196359894/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5416816&amp;postID=412860643196359894' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/412860643196359894'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/412860643196359894'/><link rel='alternate' type='text/html' href='http://sistemasorp.blogspot.com/2008/01/me-cambio-de-vecindario.html' title='Me cambio de vecindario'/><author><name>sistemasorp</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5416816.post-217776520556892702</id><published>2007-02-01T10:37:00.000+01:00</published><updated>2007-02-04T16:09:39.759+01:00</updated><title type='text'>Wardriving con la fonera</title><content type='html'>La fonera es para mi un ordenador con muchas posibilidades. La verdad es que tenerlo solo para compartir la conexión de internet me parece subestimar todo su potencial. Entre las muchas cosas que pueden hacerse con ella (la imaginación es el único limite), una de ellas es hacer &lt;a href="http://es.wikipedia.org/wiki/Wardriving"&gt;wardriving&lt;/a&gt;. Hasta ahora el wardriving se hacía con un portatil o una pda que tuviese wifi y gps (ambos en módulos separados o integrados en el hardware) pero eso ha cambiado...&lt;br /&gt;&lt;br /&gt;Antes de empezar quiero comentar que todo esto es experimental, y que no me hago responsable de los daños que pudierais ocasionaros a vosotros mismos o a cualquier cosa implicada en el proceso.&lt;br /&gt;&lt;br /&gt;Pues bien, la principal ventaja del sistema de wardriving que he estado desarrollando es que es mucho más barato que las soluciones anteriormente citadas, por lo que paso a detallar lo necesario para fabricarse un sistema de wardriving con la fonera (los enlaces son méramente orientativos, no me llevo ninguna comisión por ellos):&lt;br /&gt;&lt;br /&gt;Como es lógico, es necesario una fonera, que cuesta unos 30 €  en &lt;a href="http://www.fon.es/"&gt;fon&lt;/a&gt; (o menos si lo compras en &lt;a href="http://www.ebay.es/"&gt;ebay&lt;/a&gt; o incluso si te la regalan).&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.sistemasorp.net/blog/fonera2.jpg" /&gt;&lt;br /&gt;&lt;br /&gt;Un &lt;a href="http://www.deluoelectronics.com/customer/product.php?productid=89&amp;cat=19&amp;amp;page=1"&gt;módulo gps&lt;/a&gt; que funcione a 3,3 voltios, que cuesta alrededor de 40 €. Aunque si se tiene ya un gps de mano con conexión serie se puede hacer un circuito con un chip max3232 (que no 232).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.sistemasorp.net/blog/gps.jpg" /&gt;&lt;br /&gt;&lt;br /&gt;Una &lt;a href="http://www.ciudadwireless.com/product_info.php?products_id=539"&gt;antena wifi omnidireccional&lt;/a&gt; con imán y conector rp-sma ideal para ponerla en el techo del coche, por unos 17 €. Aunque se puede usar la antena que viene en la fonera (con lo que habrá menos cobertura).&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.sistemasorp.net/blog/antena.jpg" /&gt;&lt;br /&gt;&lt;br /&gt;Finalmente un &lt;a href="http://www.activagps.com/detalles.asp?codigo=490&amp;codigobarras=1"&gt;adaptador de mechero para el coche&lt;/a&gt; de 5 voltios y 2 amperios por unos 12 €. En mi caso me compré un adaptador de mechero para la &lt;a href="http://es.wikipedia.org/wiki/PlayStation_Portable"&gt;PSP&lt;/a&gt; que también reúne las características necesarias y que modifiqué ligeramente para poder enchufarlo a la fonera.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.sistemasorp.net/blog/adaptador.jpg" /&gt;&lt;br /&gt;&lt;br /&gt;Para unir el GPS al puerto serie de la fonera me fabriqué un pequeño cable que va unido a un circuito, y este a su vez a la fonera través de un cable IDE.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.sistemasorp.net/blog/cable.jpg" /&gt;&lt;br /&gt;&lt;br /&gt;Al final uniendo todos los componentes quedaría así:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.sistemasorp.net/blog/union.jpg" /&gt;&lt;br /&gt;&lt;br /&gt;Para hacer funcionar el invento necesitáis instalar en la fonera el firmware OpenWRT Kamikaze, en &lt;a href="http://www.fonera.info/index.php/topic,32.msg209.html#msg209"&gt;La Fonera Developers Forum&lt;/a&gt; podeis encontrar un artículo estupendo de como hacerlo. Si no lo hago con el firmware que trae por defecto FON es simplemente porque la fonera no arranca si no encuentra una conexión de red válida (y en el coche no tendremos red alguna) además de que usa el led de WLAN que nosotros aprovecharemos para otro tema.&lt;br /&gt;&lt;br /&gt;Ahora por la parte software programé un demonio el cual se encarga de escanear las redes wifi al mismo tiempo que va tomando la posición GPS. El demonio se llama fonerawd y guarda los resultados del escaneo en el directorio /www/wifispots, creando un fichero con la mac de cada red detectada y guardando dentro de este el SSID de la red, el tipo de conexión, si está encriptada o no y su latitud y longitud (si no existe GPS pondrá error, si no tiene señal será 0); todos estos campos están separados por el carácter barra "|".&lt;br /&gt;&lt;br /&gt;El puerto serie de la fonera lo programé gracias a este &lt;a href="http://es.tldp.org/COMO-INSFLUG/COMOs/Programacion-Serie-Como/Programacion-Serie-Como-3.html#ss3.1"&gt;artículo&lt;/a&gt; que explica como hacerlo en modo canónico, que es ideal para recibir las lineas de datos del protocolo NMEA del GPS. El escaneo de redes lo hice basándome en este &lt;a href="http://svn.pardus.org.tr/projeler/tasmanet/device.cpp"&gt;artículo&lt;/a&gt; que aunque no explica como hacerlo, el código fuente es suficientemente descriptivo.&lt;br /&gt;&lt;br /&gt;Este software esta bajo licencia GPL y lo podéis descargar aquí:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.sistemasorp.net/blog/fonerawd.tar.gz"&gt;http://www.sistemasorp.net/blog/fonerawd.tar.gz&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Aunque ya viene el ejecutable probablemente queráis compilarlo por vosotros mismos, por lo que además de &lt;a href="http://sistemasorp.blogspot.com/2006/11/compilando-programas-para-la-fonera.html"&gt;seguir las instrucciones que publiqué en un reciente artículo&lt;/a&gt;, debéis compilarlo incluyendo una librería y un directorio de includes de la siguiente forma:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;mips-linux-uclibc-gcc -I../fonera/staging_dir_mips/usr/include  -L../fonera/staging_dir_mips/usr/lib -liw -o fonerawd fonerawd.c&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Donde la ruta &lt;span style="font-style: italic;"&gt;../fonera&lt;/span&gt; la debéis cambiar a la ruta donde tengáis el toolchain.&lt;br /&gt;&lt;br /&gt;Una vez compilado el ejecutable debéis descargarlo a la fonera en el directorio /usr/bin&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;wget http://xxx.xxx.xxx.xxx/fonerawd&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;mv fonerawd /usr/bin&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;donde xxx.xxx.xxx.xxx es la ip de un servidor web. Después hay que darle permisos de ejecución&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;chmod +x /usr/bin/fonerawd&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Ahora debemos hacer unas modificaciones en el kamikaze:&lt;br /&gt;&lt;br /&gt;1) Editar con el vi el fichero /etc/inittab y desactivar el entrada por consola comentado la linea tts/0::askfirst:/bin/ash --login con una almohadilla "#". Esto hará que los comandos NMEA del GPS enviados al puerto serie no provoquen el crear una sesión shell por el puerto serie ya que contienen un retorno de carro y el linux lo confundiría con la pulsación de la tecla ENTER.&lt;br /&gt;&lt;br /&gt;2) Poner una ip fija en la fonera para luego poder entrar en ella sin tener que adivinar que IP tiene. Para ello editamos con el vi el fichero /etc/config/network y ponemos esto en la interfaz lan (la ip puede ser cualquier otra de vuestro segmento de red):&lt;br /&gt;&lt;blockquote&gt;config interface lan&lt;br /&gt;    option ifname   eth0&lt;br /&gt;    option proto    static&lt;br /&gt;    option ipaddr   192.168.0.12&lt;br /&gt;    option netmask  255.255.255.0&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;3) Instalar el modulo proc_gpio citado en este &lt;a href="http://forum.openwrt.org/viewtopic.php?pid=40728"&gt;artículo&lt;/a&gt;. Para ello debéis copiar el fichero proc_gpio.ko en el directorio /lib/modules/2.6.19.1 . Esto nos permitirá tener control sobre la luz WLAN de la fonera.&lt;br /&gt;&lt;br /&gt;4) En el directorio /etc/init.d crear un fichero con el vi llamando red y le añadís las siguientes líneas:&lt;br /&gt;&lt;blockquote&gt;#!/bin/sh /etc/rc.common&lt;br /&gt;&lt;br /&gt;start () {&lt;br /&gt;    wlanconfig ath0 destroy&lt;br /&gt;    wlanconfig ath0 create wlandev wifi0 wlanmode sta&lt;br /&gt;    ifconfig ath0 up&lt;br /&gt;    insmod proc_gpio.ko&lt;br /&gt;    echo 1 &amp;gt; /proc/gpio/2_dir&lt;br /&gt;    echo 1 &amp;gt; /proc/gpio/2_out&lt;br /&gt;    /usr/bin/fonerawd&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;stop () {&lt;br /&gt;    echo "hola"&lt;br /&gt;}&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;Y le damos permisos de ejecución&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;. Finalmente debéis crear un enlace a este fichero desde el directorio /etc/rc.d de la siguiente forma:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;ln -s /etc/init.d/red S76red&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Esto hará que cuando se arranque la fonera y busque en el directorio rc.d que scripts deben ejecutarse, se ejecute el script llamado red. Este script crea una interfaz wireless llamada ath0 en modo cliente para poder escanear las redes wifi, luego el módulo proc_gpio hará que se encienda la luz de WLAN, señal que indica que el demonio fonerawd esta cargado y podemos conectar el gps al puerto serie de la fonera (y no antes).&lt;br /&gt;&lt;br /&gt;El proceso a seguir sería el siguiente:&lt;br /&gt;&lt;br /&gt;1) Ponéis la fonera en el salpicadero del vehículo.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.sistemasorp.net/blog/coche1.jpg" /&gt;&lt;br /&gt;&lt;br /&gt;2) Ponéis la antena en el techo del vehículo y pasais el cable al interior a través de la ventanilla conectándola a la fonera.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.sistemasorp.net/blog/coche2.jpg" /&gt;&lt;br /&gt;&lt;br /&gt;3) Enchufáis el adaptador al mechero del coche y el otro extremo de este a la fonera.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.sistemasorp.net/blog/coche3.jpg" /&gt;&lt;br /&gt;&lt;br /&gt;4) Cuando la luz de WLAN este encendida conectar el módulo GPS.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.sistemasorp.net/blog/coche4.jpg" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Un resultado de una de mis salidas haciendo wardriving se puede ver en &lt;a href="http://www.sistemasorp.net/fonerawd"&gt;http://www.sistemasorp.net/fonerawd&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Hacer wardriving no conlleva que te conectes a las redes wifi necesariamente, simplemente se trata de listarlas, por eso este proyecto solo lista las redes y no hace nada más con ellas, siendo 100% legal.&lt;br /&gt;&lt;br /&gt;El próximo proyecto que tengo en mente es hacer que la fonera con el firmware de FON pueda actuar como interfaz entre internet y un PIC 16F628 para hacer &lt;a href="http://es.wikipedia.org/wiki/Dom%C3%B3tica"&gt;domótica&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Actualización 04/02/2007:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Añado un video sobre una sesión de wardriving con la fonera:&lt;br /&gt;&lt;br /&gt;&lt;object width="425" height="350"&gt;&lt;param name="movie" value="http://www.youtube.com/v/6julv86RhF4"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/6julv86RhF4" type="application/x-shockwave-flash" width="600" height="350"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;A pesar de que en el vídeo somos dos personas, en las sesiones de wardriving con la fonera solo es necesario el conductor, ya que la fonera se encarga de hacerlo todo ella sola (eso si, poned el gps cuando la luz de WLAN esté en verde y antes de movilizar el vehículo).&lt;br /&gt;&lt;br /&gt;Creo que también es necesario un pequeño esquema de como se deben conectar los pines del gps que he utilizado para las sesiones con los pines de la fonera:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.sistemasorp.net/blog/conexiongpsfonera.jpg" /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5416816-217776520556892702?l=sistemasorp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sistemasorp.blogspot.com/feeds/217776520556892702/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5416816&amp;postID=217776520556892702' title='20 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/217776520556892702'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/217776520556892702'/><link rel='alternate' type='text/html' href='http://sistemasorp.blogspot.com/2007/02/wardriving-con-la-fonera.html' title='Wardriving con la fonera'/><author><name>sistemasorp</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>20</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5416816.post-116734354064965162</id><published>2006-12-28T22:53:00.000+01:00</published><updated>2006-12-28T23:05:40.663+01:00</updated><title type='text'>Sun Solaris 10 en mi casa</title><content type='html'>Después de tres semanas de haber rellenado el &lt;a href="http://www2.sun.de/dc/forms/reg_us_2211_391.jsp" target="_blank"&gt;formulario&lt;/a&gt; para que me enviasen los dvd del sistema operativo Solaris 10 (uno para SPARC y otro para 32 y 64 bits) y las herramientas de desarrollo Sun Studio 11, finalmente ha llegado:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.quejateportodo.com/blog/sunsolaris.jpg"&gt;&lt;br /&gt;&lt;img src="http://www.quejateportodo.com/blog/sunsolaris2.jpg"&gt;&lt;br /&gt;&lt;br /&gt;Me gusta mucho linux, pero tener un unix en mis manos (y próximamente en mi ordenador) es un placer de informático :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5416816-116734354064965162?l=sistemasorp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sistemasorp.blogspot.com/feeds/116734354064965162/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5416816&amp;postID=116734354064965162' title='9 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/116734354064965162'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/116734354064965162'/><link rel='alternate' type='text/html' href='http://sistemasorp.blogspot.com/2006/12/sun-solaris-10-en-mi-casa.html' title='Sun Solaris 10 en mi casa'/><author><name>sistemasorp</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5416816.post-116687150917893944</id><published>2006-12-23T11:36:00.000+01:00</published><updated>2006-12-23T11:58:29.793+01:00</updated><title type='text'>Fuentes del proyecto de domótica</title><content type='html'>Como muchos me habéis pedido aquí dejo las fuentes del proyecto de domótica:&lt;br /&gt;&lt;br /&gt;&lt;!--Creative Commons License--&gt;&lt;a rel="license" href="http://creativecommons.org/licenses/by-nc/2.5/es/"&gt;&lt;img alt="Creative Commons License" style="border-width: 0" src="http://i.creativecommons.org/l/by-nc/2.5/es/88x31.png"/&gt;&lt;/a&gt;&lt;br/&gt;Esta obra está bajo una &lt;a rel="license" href="http://creativecommons.org/licenses/by-nc/2.5/es/"&gt;licencia de Creative Commons&lt;/a&gt;.&lt;!--/Creative Commons License--&gt;&lt;!-- &lt;rdf:RDF xmlns="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"&gt;&lt;br /&gt; &lt;Work rdf:about=""&gt;&lt;br /&gt;  &lt;license rdf:resource="http://creativecommons.org/licenses/by-nc/2.5/es/" /&gt;&lt;br /&gt; &lt;/Work&gt;&lt;br /&gt; &lt;License rdf:about="http://creativecommons.org/licenses/by-nc/2.5/es/"&gt;&lt;permits rdf:resource="http://web.resource.org/cc/Reproduction"/&gt;&lt;permits rdf:resource="http://web.resource.org/cc/Distribution"/&gt;&lt;requires rdf:resource="http://web.resource.org/cc/Notice"/&gt;&lt;requires rdf:resource="http://web.resource.org/cc/Attribution"/&gt;&lt;prohibits rdf:resource="http://web.resource.org/cc/CommercialUse"/&gt;&lt;permits rdf:resource="http://web.resource.org/cc/DerivativeWorks"/&gt;&lt;/License&gt;&lt;/rdf:RDF&gt; --&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.quejateportodo.com/blog/Luces.zip"&gt;Luces&lt;/a&gt;: (Visual C++ 6.0) El corazón del sistema software. Este es el encargado de abrir el puerto tcp 1976 para recibir conexiones, validar usuarios, enviar por el puerto paralelo las ordenes que estos dicten entre otras cosas. Podeis descargar el programa compilado, con su base de datos y su fichero .ini &lt;a href="http://www.quejateportodo.com/blog/servidor.zip"&gt;aquí&lt;/a&gt; (Recordad que para ejecutarlo en windows NT, 2000, XP o 2003 debeis usar el &lt;span style="font-style:italic;"&gt;allowio&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.quejateportodo.com/blog/web.zip"&gt;Web&lt;/a&gt;: (DHTML y ASP) Interfaz web para poder usar el sistema mediante un navegador o un móvil con WEP.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.quejateportodo.com/blog/applet.zip"&gt;Applet&lt;/a&gt;: (Visual J++) Applet de java para la interfaz web, la cual muestra en tiempo real los cambios de los aparatos eléctricos.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.quejateportodo.com/blog/Remoto.zip"&gt;Remoto&lt;/a&gt;: (Visual C++ 6.0) Aplicación para gestionar los comandos de un mando a distancia por infrarrojos.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.quejateportodo.com/blog/SMS.zip"&gt;SMS&lt;/a&gt;: (Visual C++ 6.0) Aplicación para gestionar los comandos de mensajes cortos por móvil.&lt;br /&gt;&lt;br /&gt;Me hubiera gustado modificar los fuentes para dejarlos más claros, elegantes e incluso más eficientes, pero no he tenido tiempo hasta ahora y no lo tendré en un tiempo futuro, por lo que los pongo tal como los dejé.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5416816-116687150917893944?l=sistemasorp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sistemasorp.blogspot.com/feeds/116687150917893944/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5416816&amp;postID=116687150917893944' title='10 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/116687150917893944'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/116687150917893944'/><link rel='alternate' type='text/html' href='http://sistemasorp.blogspot.com/2006/12/fuentes-del-proyecto-de-domtica.html' title='Fuentes del proyecto de domótica'/><author><name>sistemasorp</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5416816.post-116323903560558204</id><published>2006-11-11T09:57:00.000+01:00</published><updated>2007-02-08T22:33:28.700+01:00</updated><title type='text'>Compilando programas para la fonera</title><content type='html'>Hace poco leí un &lt;a href="http://barrapunto.com/article.pl?sid=06/11/06/1610230" target="_blank"&gt;artículo en barrapunto&lt;/a&gt; donde descubrí (un poco tarde, ya lo sé) que la fonera tenía ssh (y por ende linux embebido).&lt;br /&gt;&lt;br /&gt;El caso es que viendo páginas como la de &lt;a href="http://fonera.q3.nu/" traget="_blank"&gt;radikalq3&lt;/a&gt; me animé a solicitar a FON su preciado router wireless (cuando aún estaba de oferta a 5 ?) para hacer "pruebas y experimentos" y de paso unirme a la comunidad FON.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.quejateportodo.com/blog/fonera.jpg" /&gt;&lt;br /&gt;&lt;br /&gt;La recibí ayer, y por supuesto habilité el ssh mediante hardware (cables, condensadores, MAX232 y el puerto serie). Por cierto, una vez listado todo el proceso de arranque el usuario debe pulsar INTRO para activar la consola. Una vez abierto el puerto 22 monté de nuevo la fonera y me conecté por ssh. La primera vez que entras debes entrar como root y con password admin. Posteriormente cambié la clave de root desde la &lt;a href="http://www.fon.com/" target="_blank"&gt;web de FON&lt;/a&gt; en &lt;span style="font-style: italic;"&gt;Configura tu Router Social FON/Contraseña del Router&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;A continuación me bajé los fuentes de la fonera &lt;a href="http://download.fon.com/firmware/fonera/latest/fonera.tar.bz2"&gt;http://download.fon.com/firmware/fonera/latest/fonera.tar.bz2&lt;/a&gt; (unos noventa megas), los guardé en mi carpeta personal de mi servidor con mandriva 2006, los descomprimí con &lt;span style="font-style: italic;"&gt;tar xvjf fonera.tar.bz2&lt;/span&gt;, ejecuté &lt;span style="font-style: italic;"&gt;make menuconfig&lt;/span&gt; sin modificar nada, grabé y posteriormente tecleé &lt;span style="font-style: italic;"&gt;make&lt;/span&gt;. La primera vez no me compiló, por lo que tuve que instalar varios paquetes: &lt;span style="font-style: italic;"&gt;urpmi flex&lt;/span&gt;, &lt;span style="font-style: italic;"&gt;urpmi bison&lt;/span&gt; y &lt;span style="font-style: italic;"&gt;urpmi byacc&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Una vez compilados los fuentes ya solo me quedaba saber como poder compilar un programa y subirlo a la fonera. La compilación se explica en la web de OpenWRT:&lt;br /&gt;&lt;a href="http://downloads.openwrt.org/docs/buildroot-documentation.html#using_toolchain" target="_blank"&gt;http://downloads.openwrt.org/docs/buildroot-documentation.html#using_toolchain&lt;/a&gt;. Así que me puse manos a la obra e hice este programa llamado &lt;span style="font-weight: bold;"&gt;prueba.c&lt;/span&gt; el cual simplemente abre le fichero &lt;span style="font-style: italic;"&gt;/etc/passwd&lt;/span&gt; y muestra su contenido (en vez de hacer el típico hola mundo):&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;&lt;br /&gt;int main(void)&lt;br /&gt;{&lt;br /&gt;      FILE *fichero;&lt;br /&gt;      char cadena[100];&lt;br /&gt;      if((fichero=fopen("/etc/passwd","r"))!=NULL)&lt;br /&gt;      {&lt;br /&gt;              fgets(cadena,100,fichero);&lt;br /&gt;              while(!feof(fichero))&lt;br /&gt;              {&lt;br /&gt;                      printf(cadena);&lt;br /&gt;                      fgets(cadena,100,fichero);&lt;br /&gt;              }&lt;br /&gt;              fclose(fichero);&lt;br /&gt;      }&lt;br /&gt;      return 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.quejateportodo.com/blog/servidorssh.jpg" /&gt;&lt;br /&gt;&lt;br /&gt;Lo compilé con &lt;span style="font-style: italic;"&gt;mips-linux-uclibc-gcc -o prueba prueba.c&lt;/span&gt; y se creó un ejecutable sin problemas. A continuación lo moví a /var/www/html para que estuviese disponible a través del servidor web apache y desde la fonera lo recuperé con &lt;span style="font-style: italic;"&gt;wget http://192.168.0.11/prueba&lt;/span&gt; (notese que la ip del servidor será distinta en vuestro caso), le cambié los permisos para que se pudiera ejecutar &lt;span style="font-style: italic;"&gt;chmod 755 prueba&lt;/span&gt; y finalmente lo probé funcionado perfectamente.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.quejateportodo.com/blog/fonerassh.jpg" /&gt;&lt;br /&gt;&lt;br /&gt;Espero que esto os anime a crear vuestros propios programas. Este ejecutable me ocupó  unos 7 KBytes y aún tengo 7 megas de espacio libre en la fonera para añadirle nuevas cosas :)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Actualización 08/02/2007:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Dani, un lector del blog me comentó que la fonera solo tiene 4 megas libres de espacio de almacenamiento permanente (y no 7 megas como había escrito en el artículo). Después de hacer dos experimentos que podéis leer en los comentarios de este blog la capacidad real de la fonera con el firmware de FON es de &lt;span style="font-weight: bold;"&gt;5 MB&lt;/span&gt;. Gracias Dani por forzarme a experimentar ;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5416816-116323903560558204?l=sistemasorp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sistemasorp.blogspot.com/feeds/116323903560558204/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5416816&amp;postID=116323903560558204' title='10 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/116323903560558204'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/116323903560558204'/><link rel='alternate' type='text/html' href='http://sistemasorp.blogspot.com/2006/11/compilando-programas-para-la-fonera.html' title='Compilando programas para la fonera'/><author><name>sistemasorp</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5416816.post-116276891300928190</id><published>2006-11-05T21:26:00.000+01:00</published><updated>2006-11-06T00:28:01.496+01:00</updated><title type='text'>Manejar aparatos eléctricos desde el PC: domótica (5/5)</title><content type='html'>Hola a todos de nuevo. La espera se ha hecho larga (¡¡¡ casi 7 meses !!!), pero es porque me enfrasqué en otros proyectos y he sacrificado el tiempo del blog para poder desarrollarlos, aunque siempre he estado pendiente de los comentarios. Uno de ellos (que no el único) ha sido el de crear &lt;a href="http://www.horaylugar.com" target="_blank"&gt;Hora y Lugar&lt;/a&gt;: una web para crear recordatorios de citas y que ha quedado cuarta en el concurso de &lt;a href="http://concursos.ojobuscador.com/googlemaps/" target="_blank"&gt;Google Maps España&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Como broche final a esta serie de artículos, expongo la interfaz por antonomasia que hace que la domótica cobre un nuevo sentido. Y esa es manejar el sistema mediante el móvil. Ya no se trata de estar en casa o de tener una conexión a internet, sino de prácticamente poder usar nuestros aparatos desde cualquier lugar (donde haya cobertura claro).  En esta ocasión es a base de SMS, que todo el mundo sabe escribir y son relativamente baratos, aunque en un futuro añadiré la funcionalidad de centralita, donde una voz te pregunta e informa y tu envías comandos mendiante tonos DTMF (pulsando las teclas del teléfono) o bién mediante voz; todo ello usando &lt;a href="http://en.wikipedia.org/wiki/TAPI" target="_blank"&gt;TAPI&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Usando el móvil &lt;a href="http://sistemasorp.blogspot.com/2006/01/pc-mvil-pc.html" target="_blank"&gt;que ya todos conoceis&lt;/a&gt; desarrollé la interfaz para poder tratar los mensajes recibidos y traducirlos en comandos para el sistema. Para iniciarlo se carga el programa &lt;span style="font-style:italic;"&gt;SMS&lt;/span&gt; indicandole en que puerto esta eschuchando el móvil y cual es la dirección del servidor.&lt;br /&gt;&lt;br /&gt;Cuando queramos hacer algo, escribimos un mensaje sms con el formato &lt;span style="font-style:italic;"&gt;usuario&lt;/span&gt; &lt;span style="font-style:italic;"&gt;contraseña&lt;/span&gt; &lt;span style="font-style:italic;"&gt;comando&lt;/span&gt;. &lt;br /&gt;&lt;br /&gt;Cuando el móvil recibe el mensaje, el programa SMS que esta comprobando si ha recibido un mensaje cada cierto tiempo lo procesa, muestra el teléfono de origen, la fecha y la cadena enviada. &lt;br /&gt;&lt;br /&gt;A continuación envía el comando al servidor y nos responde con otro mensaje sms indicando en que estado se encuentra el sistema después de haber procesado el comando. &lt;br /&gt;&lt;br /&gt;De la aplicación se puede salir simplemente pulsando INTRO.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.quejateportodo.com/blog/enviacomandomovil.jpg"&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.quejateportodo.com/blog/movildomo1.jpg"&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.quejateportodo.com/blog/lucesdomo4.jpg"&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.quejateportodo.com/blog/reciberespuestamovil.jpg"&gt;&lt;br /&gt;&lt;br /&gt;Aquí teneis un video donde podeis ver como funciona todo lo que he ido explicando en todos los artículos:&lt;br /&gt;&lt;br /&gt;&lt;object width="425" height="350"&gt;&lt;param name="movie" value="http://www.youtube.com/v/-Y5wO0ydRxo"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/-Y5wO0ydRxo" type="application/x-shockwave-flash" width="600" height="350"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;Si no podeis visualizarlo bién, el enlace es &lt;a href="http://www.youtube.com/watch?v=-Y5wO0ydRxo" target="_blank"&gt;http://www.youtube.com/watch?v=-Y5wO0ydRxo&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Y así acaba esta serie de artículos, esperando que os haya servido de utilidad y que os haya dado ideas de como implantarlo vosotros mismos (como ya muchos me habeis comentado). Mi idea es seguir desarrollandolo añadiendo nuevas funcionalidades como reconocimiento de voz, centralita (como ya he comentado más arriba) y más control en los aparatos (de ser un mero encender y apagar a poder manejar todas las funcionalidades).&lt;br /&gt;&lt;br /&gt;&lt;a href="http://sistemasorp.blogspot.com/2006/04/manejar-aparatos-elctricos-desde-el-pc.html"&gt;Manejar aparatos eléctricos desde el PC: domótica (4/5)&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5416816-116276891300928190?l=sistemasorp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sistemasorp.blogspot.com/feeds/116276891300928190/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5416816&amp;postID=116276891300928190' title='23 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/116276891300928190'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/116276891300928190'/><link rel='alternate' type='text/html' href='http://sistemasorp.blogspot.com/2006/11/manejar-aparatos-elctricos-desde-el-pc.html' title='Manejar aparatos eléctricos desde el PC: domótica (5/5)'/><author><name>sistemasorp</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>23</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5416816.post-114548348468799154</id><published>2006-04-19T21:22:00.000+02:00</published><updated>2006-11-06T00:22:54.590+01:00</updated><title type='text'>Manejar aparatos eléctricos desde el PC: domótica (4/5)</title><content type='html'>Después de un largo periodo de descanso empiezo a escribir el siguiente artículo sobre domótica.&lt;br /&gt;&lt;br /&gt;Ya hemos tratado varias formas de acceder remotamente o localmente al sistema de domótica a través de TCP/IP. La cuestión es que hasta ahora las interfaces que necesitábamos para poder interactuar con el sistema necesitaban de un ordenador que se  conectara al sistema central (que podía ser el mismo que contiene el sistema) para enviarle ordenes y recibir el estado. En este artículo trataremos una forma más "casera" de interactuar con el sistema.&lt;br /&gt;&lt;br /&gt;Todo el mundo tiene un mando a distancia en su casa y/o sabe como usarlo, asi que con esta &lt;a href="http://sistemasorp.blogspot.com/2006/01/manejar-un-ordenador-con-un-mando.html" target="_blank"&gt;sencilla interfaz&lt;/a&gt; podemos interactuar con todos los aparatos del sistema de domótica simplemente interpretando las pulsaciones que recibe del mando a distancia (en mi caso mediante un puerto serie) y convirtiendolo en comandos del protocolo del sistema de domótica. Para ello cargamos el programa &lt;span style="font-style:italic;"&gt;Remoto&lt;/span&gt;, que es una aplicación de consola, pasándole como parámetros el puerto serie, el servidor, el usuario y la contraseña. Este lo que hará es acceder mediante TCP/IP al servidor &lt;span style="font-style:italic;"&gt;Luces&lt;/span&gt; con el usuario y contraseña dados y a continuación abrirá el puerto serie para empezar a recibir las señales infrarojas.&lt;br /&gt;&lt;br /&gt;Cuando se pulsa el botón 1, 2, 3 o 4 del mando a distancia cambia el estado del aparato a encendido o apagado si se encuentra apagado o encendido respectivamente. Por supuesto tiene que haber visión directa entre el mando a distancia y el receptor (que puede no estar en la misma habitación que el ordenador al que esta enchufado).&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.quejateportodo.com/blog/remotodomo1.jpg"&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.quejateportodo.com/blog/lucesdomo3.jpg"&gt;&lt;br /&gt;&lt;br /&gt;De la aplicación podemos salir pulsando &lt;span style="font-style:italic;"&gt;intro&lt;/span&gt;. El mando a distancia que tengo y el cable receptor lo obtuve de una capturadora de televisión, sin embargo si no teneis uno similar podeis comprar ya uno hecho de cualquier capturadora MIRO o AVERMEDIA o haceros vosotros mismos uno: &lt;a href="http://www.tldp.org/linuxfocus/Castellano/March2000/article137.html" target="_blank"&gt;http://www.tldp.org/linuxfocus/Castellano/March2000/article137.html&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.quejateportodo.com/blog/pruebamando.gif"&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://sistemasorp.blogspot.com/2006/03/manejar-aparatos-elctricos-desde-el-pc.html"&gt;Manejar aparatos eléctricos desde el PC: domótica (3/5)&lt;/a&gt; &lt;a href="http://sistemasorp.blogspot.com/2006/11/manejar-aparatos-elctricos-desde-el-pc.html"&gt;Manejar aparatos eléctricos desde el PC: domótica (5/5)&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5416816-114548348468799154?l=sistemasorp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sistemasorp.blogspot.com/feeds/114548348468799154/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5416816&amp;postID=114548348468799154' title='26 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/114548348468799154'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/114548348468799154'/><link rel='alternate' type='text/html' href='http://sistemasorp.blogspot.com/2006/04/manejar-aparatos-elctricos-desde-el-pc.html' title='Manejar aparatos eléctricos desde el PC: domótica (4/5)'/><author><name>sistemasorp</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>26</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5416816.post-114289735688628775</id><published>2006-03-20T23:43:00.000+01:00</published><updated>2006-04-19T23:55:20.730+02:00</updated><title type='text'>Manejar aparatos eléctricos desde el PC: domótica (3/5)</title><content type='html'>Al estar el sistema de domótica centralizado en un solo programa que escucha por un puerto TCP, se puede ampliar todo lo que sea necesario para cubrir todo tipo de necesidades de comunicación.&lt;br /&gt;&lt;br /&gt;Una de las posibilidades que ofrece la domótica es poder acceder a los aparatos aún cuando no se está presente en el hogar. Es por ello que necesitaba un medio por el cual poder acceder al sistema desde fuera de mi casa. Pues bién, aprovechando la infraestructura de Internet, y que el protocolo HTTP es el que esta más extendido, instalé un servidor web en casa e hice un portal al cual pudiera acceder desde cualquier sitio que tuviese acceso a Internet mediante un navegador.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.quejateportodo.com/blog/webprincipal.jpg"&gt;&lt;br /&gt;&lt;br /&gt;En la imágen se puede observar el punto de entrada a la web. En su momento instalé un IIS e hice toda la programación con DHTML + ASP. Al ser una web se puede acceder a ella mediante proxy (seleccionando la opción de HTML) y sin proxy (seleccionando la opción de Java). El usuario y contraseña usa la misma base de datos de la que tira el programa Luces.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.quejateportodo.com/blog/webhtml.jpg"&gt;&lt;br /&gt;&lt;br /&gt;La sección de HTML es especial para proxys puesto que en muchos sitios se usan (sobre todo empresas) para compartir una conexión de Internet, mantener un registro de accesos, etc. El problema es que si hay proxy es muy posible que no haya otro medio de conectarse a Internet sin pasar por el y por tanto no pueda hacerse una conexión permanente al servidor. Por ello la interfaz esta diseñada para recibir información cuando se hace la petición http al servidor y no se refresca hasta que no se vuelva a seleccionar otro estado (eligiendo el aparato y pulsando &lt;span style="font-style:italic;"&gt;Enviar&lt;/span&gt;) o ver el estado actual (pulsando el botón &lt;span style="font-style:italic;"&gt;Ver Estado&lt;/span&gt;). Si el usuario es administrador, además de poder visualizar los aparatos e interactuar con ellos como otro usuario con permisos, también es capaz de manejar los comandos privilegiados además de poder hacer consultas sql a la base de datos. El fichero ASP es el encargado de hacer la conexión TCP/IP al programa Luces (tanto Luces como el IIS residen en la misma máquina), para ello usé un componente ActiveX llamado vbwinsock y que lo podeis descargar &lt;a href="http://www.15seconds.com/issue/990408.htm" target="_blank"&gt;aquí&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.quejateportodo.com/blog/webjava.jpg"&gt;&lt;br /&gt;&lt;br /&gt;La sección java es similar a la de HTML pero orientada a usuarios que tienen acceso directo a Internet. Se llama así porque la parte donde estan representados los aparátos es un applet de java con conexión directa al servidor de Luces (la seguridad de java solo deja conectarse al mismo dominio desde que se pidió la página). Por ello si pulsamos en cualquiera de los botones se actualiza rápidamente el estado, incluso si otro usuario cambia el estado de alguno de los aparatos también se vería reflejado. Sería como conectarse por telnet pero de una forma mucho más sencilla y amigable.&lt;br /&gt;&lt;br /&gt;Ha habido gente que me ha preguntado por qué tardo tanto en escribir entre artículo y artículo, la razón es que tengo poco tiempo y otras veces no tengo ganas de salir del trabajo para ponerme otra vez en frente del ordenador, por eso os pido un poco de paciencia.&lt;br /&gt;&lt;br /&gt;Otras personas me han preguntado si voy a dejar accesible el código fuente de las aplicaciones que aquí menciono, y si, efectivamente lo liberaré para que otros puedan hacer soluciones similares o basarse en esta para hacer algo nuevo. Además tengo pensado grabar un video del funcionamiento de todo el sistema de domótica.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://sistemasorp.blogspot.com/2006/02/manejar-aparatos-elctricos-desde-el-pc_21.html"&gt;Manejar aparatos eléctricos desde el PC: domótica (2/5)&lt;/a&gt;&amp;nbsp;&lt;a href="http://sistemasorp.blogspot.com/2006/04/manejar-aparatos-elctricos-desde-el-pc.html"&gt;Manejar aparatos eléctricos desde el PC: domótica (4/5)&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5416816-114289735688628775?l=sistemasorp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sistemasorp.blogspot.com/feeds/114289735688628775/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5416816&amp;postID=114289735688628775' title='8 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/114289735688628775'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/114289735688628775'/><link rel='alternate' type='text/html' href='http://sistemasorp.blogspot.com/2006/03/manejar-aparatos-elctricos-desde-el-pc.html' title='Manejar aparatos eléctricos desde el PC: domótica (3/5)'/><author><name>sistemasorp</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5416816.post-114052143082738216</id><published>2006-02-21T12:22:00.000+01:00</published><updated>2006-03-22T00:02:40.870+01:00</updated><title type='text'>Manejar aparatos eléctricos desde el PC: domótica (2/5)</title><content type='html'>Para poder controlar el módulo por software se me planteaba una duda, ¿cómo hacer para que varios programas accediesen a este?. Todos tenían que ser ejecutables y ser lanzados con el Port Talk, sin embargo no era lo más optimo porque no había manera de saber que aparatos estaban encendidos y cuales no, además de que mi interés era controlar los aparatos no solo desde el propio ordenador donde estaba conectado el módulo, sino también a través de otros dispositivos.&lt;br /&gt;&lt;br /&gt;La solución se mostraba por sí sola: solo un programa accedería al módulo y los demás deberían comunicarse con este para lanzarle las peticiones y recibir el estado actual en que se encontraban los aparatos. De ahí salió el programa &lt;span style="font-style: italic;"&gt;Luces&lt;/span&gt;, el cual era un simple servidor tcp que escuchaba por el puerto 1976 (mi año de nacimiento) y se comunicaba con sus clientes mediante un sencillo protocolo basado en números (al estilo del protocolo simple de transferencia de correo - SMTP). Los códigos que devuelve el servidor son los siguientes:&lt;br /&gt;&lt;br /&gt;&lt;table bgcolor="#8ccb12"&gt;&lt;tr&gt;&lt;td&gt;&lt;span style="font-weight: bold;"&gt;100&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Saludo al nuevo cliente conectado&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;span style="font-weight: bold;"&gt;101&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Estado en que se encuentran los aparatos (máscara)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;span style="font-weight: bold;"&gt;200&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Usuario introducido&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;span style="font-weight: bold;"&gt;201&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Contraseña introducida&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;span style="font-weight: bold;"&gt;202&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Permitir o denegar peticiones, cerrar programa o apagar equipo&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;span style="font-weight: bold;"&gt;300&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Estado no identificado&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;span style="font-weight: bold;"&gt;301&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Comando no reconocido&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;span style="font-weight: bold;"&gt;302&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Fallo en la autentificación&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;Por su parte el cliente envia los siguientes comandos (en mayúsculas o en minúsculas):&lt;br /&gt;&lt;br /&gt;&lt;table bgcolor="#ffb400"&gt;&lt;tr&gt;&lt;td&gt;&lt;span style="font-weight: bold;"&gt;USER:&lt;/span&gt;&amp;lt;usuario&amp;gt;&lt;/td&gt;&lt;td&gt;Usuario a validar&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;span style="font-weight: bold;"&gt;PASS:&lt;/span&gt;&amp;lt;contraseña&amp;gt;&lt;/td&gt;&lt;td&gt;Contraseña a validar&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;span style="font-weight: bold;"&gt;&amp;lt;Número&amp;gt;&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Estado que se quiere aplicar a los aparatos (máscara)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;span style="font-weight: bold;"&gt;OPEN&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Permite a los usuarios no administradores manejar los aparatos&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;span style="font-weight: bold;"&gt;CLOSE&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Deniega a los usuarios no administradores manejar los aparatos&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;span style="font-weight: bold;"&gt;QUIT&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Cierra la aplicación&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;span style="font-weight: bold;"&gt;BYE&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Apaga el equipo&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;En primer lugar el orden que se debe seguir es:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;Servidor&lt;/span&gt;: Mensaje de Saludo.&lt;br /&gt;&lt;span style="font-style:italic;"&gt;Cliente&lt;/span&gt;: Enviar USER: y el nombre de usuario.&lt;br /&gt;&lt;span style="font-style:italic;"&gt;Servidor&lt;/span&gt;: Mensaje de Usuario Introducido.&lt;br /&gt;&lt;span style="font-style:italic;"&gt;Cliente&lt;/span&gt;: Enviar PASS: y la contraseña del usuario.&lt;br /&gt;&lt;span style="font-style:italic;"&gt;Servidor&lt;/span&gt;: Mensaje de Contraseña Introducida.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Si el usuario introduce una contraseña incorrecta el servidor le mostrará un fallo en la autentificación (302) y cerrará la conexión.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Si el usuario introduce un comando no reconocido cuando se está validando el servidor le mostrará un comando no reconocido (301) y le cerrará la conexión, en cambio cuando este validado solo le mostrará el estado de los aparatos (101).&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Si el usuario introduce antes el comando PASS que el USER el servidor le mostrará estado no identificado (300) y le cerrará la conexión.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;En segundo lugar cuando el usuario ya esta validado puede introducir o bién los comandos &lt;span style="font-style:italic;"&gt;OPEN&lt;/span&gt;, &lt;span style="font-style:italic;"&gt;CLOSE&lt;/span&gt;, &lt;span style="font-style:italic;"&gt;QUIT&lt;/span&gt; y &lt;span style="font-style:italic;"&gt;BYE&lt;/span&gt;; o bién un número de 0 a 15 que actuaría como máscara para encender o apagar los aparatos (si el número es mayor que 15 se usa el módulo de 16).&lt;br /&gt;&lt;br /&gt;Haciendo un telnet, lo anterior comentado se vería de la siguiente forma:&lt;br /&gt;&lt;img src="http://www.quejateportodo.com/blog/telnetdomo1.jpg"&gt;&lt;br /&gt;&lt;br /&gt;Y en la aplicación Luces se vería así:&lt;br /&gt;&lt;img src="http://www.quejateportodo.com/blog/lucesdomo1.jpg"&gt;&lt;br /&gt;&lt;br /&gt;Si ahora cometemos un error (por ejemplo metemos mal el usuario) el resultado quedaría así:&lt;br /&gt;&lt;img src="http://www.quejateportodo.com/blog/telnetdomo2.jpg"&gt;&lt;br /&gt;&lt;img src="http://www.quejateportodo.com/blog/lucesdomo2.jpg"&gt;&lt;br /&gt;&lt;br /&gt;Como se puede observar, la segunda conexión la he hecho a través de otro ordenador. Gracias a que se usa el protocolo el tcp/ip se puede conectar desde cualquier programa (independientemente del sistema operativo, arquitectura de ordenador, etc).&lt;br /&gt;&lt;br /&gt;Por otro lado el sistema se basa en una base de datos para gestionar los usuarios, los eventos y los aparatos:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.quejateportodo.com/blog/derdomo.jpg"&gt;&lt;br /&gt;&lt;br /&gt;En mi caso usé una base de datos access, pero como es lógico pensar, se puede usar cualquier tipo de base de datos relacional. Las tablas son sólo 4 y se detallan a continuación:&lt;br /&gt;&lt;br /&gt;&lt;table bgcolor="#cb93f6"&gt;&lt;tr bgcolor="#fffebc"&gt;&lt;td&gt;&lt;span style="font-weight:bold;"&gt;tblUsuarios&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Donde se almacenan los usuarios del sistema y sus permisos&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;span style="font-weight:bold;"&gt;intID&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Autonúmerico (o secuencia) que identifica al usuario inequivocamente&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;span style="font-weight:bold;"&gt;strNombre&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Nombre del usuario&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;span style="font-weight:bold;"&gt;strApellidos&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Apellido o apellidos del usuario&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;span style="font-weight:bold;"&gt;strLogin&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Identificador del usuario para validarse en el sistema&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;span style="font-weight:bold;"&gt;strPassword&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Contraseña del usuario para validarse en el sistema&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;span style="font-weight:bold;"&gt;blnActivo&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Bandera que indica si un usuario puede validarse en el sistema o no&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;span style="font-weight:bold;"&gt;bytNivel&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Nivel del usuario (100 administrador, 50 usuario normal, 0 visitante)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;span style="font-weight:bold;"&gt;bytMascara&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Máscara de permiso para aparatos: Si el usuario tiene por ejemplo 10 (1010 en binario) sólo puede utilizar los aparatos 2 y 4, en cambio los aparatos 1 y 3 únicamente puede ver su estado&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;&lt;table bgcolor="#cb93f6"&gt;&lt;tr bgcolor="#fffebc"&gt;&lt;td&gt;&lt;span style="font-weight:bold;"&gt;tblAcciones&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Donde se almacenan las distintas acciones del usuario&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;span style="font-weight:bold;"&gt;bytID&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Autonúmerico (o secuencia) que identifica la acción inequivocamente&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;span style="font-weight:bold;"&gt;strAccion&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Nombre de la acción (Usuario Validado, Usuario Desconectado, Orden y Comando)&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;&lt;table bgcolor="#cb93f6"&gt;&lt;tr bgcolor="#fffebc"&gt;&lt;td&gt;&lt;span style="font-weight:bold;"&gt;tblLog&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Donde se almacena la actividad que lleva a cabo el usuario&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;span style="font-weight:bold;"&gt;intID&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Autonúmerico (o secuencia) que identifica la acción del usuario&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;span style="font-weight:bold;"&gt;intUsuario&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Campo relacionado con el intID de la tabla tblUsuarios&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;span style="font-weight:bold;"&gt;bytAccion&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Campo relacionado con el bytID de la tabla tblAcciones&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;span style="font-weight:bold;"&gt;datFecha&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Fecha y hora de la acción&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;span style="font-weight:bold;"&gt;strIP&lt;/span&gt;&lt;/td&gt;&lt;td&gt;IP de la máquina donde se ordenó la acción&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;span style="font-weight:bold;"&gt;strDescripcion&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Descripción de la acción&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;&lt;table bgcolor="#cb93f6"&gt;&lt;tr bgcolor="#fffebc"&gt;&lt;td&gt;&lt;span style="font-weight:bold;"&gt;tblAparatos&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Donde se almacenan los nombres de los aparatos a manejar&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;span style="font-weight:bold;"&gt;intID&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Autonúmerico (o secuencia) que identifica el aparato inequivocamente&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;span style="font-weight:bold;"&gt;strNombre&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Nombre del aparato&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://sistemasorp.blogspot.com/2006/02/manejar-aparatos-elctricos-desde-el-pc.html"&gt;Manejar aparatos eléctricos desde el PC: domótica (1/5)&lt;/a&gt; &lt;a href="http://sistemasorp.blogspot.com/2006/03/manejar-aparatos-elctricos-desde-el-pc.html"&gt;Manejar aparatos eléctricos desde el PC: domótica (3/5)&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5416816-114052143082738216?l=sistemasorp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sistemasorp.blogspot.com/feeds/114052143082738216/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5416816&amp;postID=114052143082738216' title='6 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/114052143082738216'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/114052143082738216'/><link rel='alternate' type='text/html' href='http://sistemasorp.blogspot.com/2006/02/manejar-aparatos-elctricos-desde-el-pc_21.html' title='Manejar aparatos eléctricos desde el PC: domótica (2/5)'/><author><name>sistemasorp</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5416816.post-113977258395968120</id><published>2006-02-12T19:14:00.000+01:00</published><updated>2007-02-17T00:49:01.342+01:00</updated><title type='text'>Manejar aparatos eléctricos desde el PC: domótica (1/5)</title><content type='html'>Continuando la &lt;a target="_blank" href="http://sistemasorp.blogspot.com/2006/01/manejar-un-ordenador-con-un-mando.html"&gt;serie &lt;/a&gt; de &lt;a href="http://sistemasorp.blogspot.com/2006/01/pc-mvil-pc.html"&gt;artículos&lt;/a&gt; sobre aparatos que tengo, introduzco el último y más importante del sistema casero de domótica que he creado.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.quejateportodo.com/blog/modulo.jpg" /&gt;&lt;br /&gt;&lt;br /&gt;El kit o módulo que aparece en la fotografía pertenece a la familia de módulos a relé de la empresa &lt;a target="_blank" href="http://www.cebek.com/"&gt;CEBEK&lt;/a&gt;, cuyo código es &lt;a target="_blank" href="http://www.cebek.com/Producte.aspx?referencia=408"&gt;T-1&lt;/a&gt;. Es un módulo que puede manejar hasta 4 &lt;a target="_blank" href="http://es.wikipedia.org/wiki/Rel%C3%A9"&gt;relés&lt;/a&gt; a través de unos bornes de entrada. Tiene muchas ventajas, como que aisla la señal de entrada del resto del circuito con &lt;a target="_blank" href="http://es.wikipedia.org/wiki/Optoacoplador"&gt;optoacopladores&lt;/a&gt; o como que usa un &lt;a target="_blank" href="http://es.wikipedia.org/wiki/Rectificador_de_onda_completa#Puente_de_Graetz."&gt;puente rectificador&lt;/a&gt; para la alimentación del circuito. El módulo se alimenta con una tensión de 12 voltios e intensidad de 200 mA (muchos transformadores pequeños de móvil u otros aparatos los proporcionan de sobra).&lt;br /&gt;&lt;br /&gt;La idea es que con este circuito se puedan manejar aparatos eléctricos (incluidos electrodomesticos) desde el ordenador. Para ello, por una parte se usan los relés a modo de interruptor de un cable normal (en mi caso uso alargadores para no tener que pelar los de los aparatos eléctricos), por lo que en el circuito que uso podría manejar hasta cuatro aparatos distintos; por otra parte los cuatro bornes de entrada van conectados a cuatro de los ocho cables de datos de un &lt;a target="_blank" href="http://es.wikipedia.org/wiki/Cable_Paralelo"&gt;cable paralelo&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Aprovechando que es muy sencillo acceder al puerto paralelo del ordenador y que las señales son de 5 voltios (más que suficiente para activar los optoacopladores) es posible mandar un byte al puerto de datos del paralelo (0x378) para que llegue a los bornes del circuito y posteriormente active los relés. ¿Como funciona la lógica de encender y apagar relés? pues cuando se manda un byte a través del puerto paralelo, los bits que esten a 1 hacen que los correspondientes pines del puerto paralelo se activen a 5 voltios, lo que en el circuito provoca finalmente que se activen los relés asociados. Asi por ejemplo si enviamos un 3, en binario es 0011, activándose los dos primeros relés. Con este sistema se pueden encender lámparas, calefacciones, microondas, lavadoras, persianas eléctricas, sistemas de riego, etc.&lt;br /&gt;&lt;br /&gt;En windows 95, 98 y Millenium se puede acceder directamente al puerto paralelo, sin embargo en windows nt, 2000 y xp se necesita crear un driver que se ejecute en el nivel (ring) privilegiado 0, porque en el nivel 3 no se permite hacer directamente. Como tampoco quise perder tiempo en crear mi propio driver, usé un programa que ya hace todo eso de una forma muy sencilla: &lt;a href="http://www.beyondlogic.org/porttalk/porttalk.htm" target="_blank"&gt;Port Talk&lt;/a&gt;, el cual, una vez instalado, da permiso a una aplicación (proceso) para que acceda a un puerto determinado (o a todos) desde la linea de comandos. Finalmente solo basta usar el método _outp en C para enviar datos al puerto paralelo:&lt;br /&gt;&lt;blockquote&gt;_outp(0x378,3);&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://sistemasorp.blogspot.com/2006/02/manejar-aparatos-elctricos-desde-el-pc_21.html"&gt;Manejar aparatos eléctricos desde el PC: domótica (2/5)&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5416816-113977258395968120?l=sistemasorp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sistemasorp.blogspot.com/feeds/113977258395968120/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5416816&amp;postID=113977258395968120' title='33 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/113977258395968120'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/113977258395968120'/><link rel='alternate' type='text/html' href='http://sistemasorp.blogspot.com/2006/02/manejar-aparatos-elctricos-desde-el-pc.html' title='Manejar aparatos eléctricos desde el PC: domótica (1/5)'/><author><name>sistemasorp</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>33</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5416816.post-113831730119802205</id><published>2006-01-26T23:07:00.000+01:00</published><updated>2006-01-27T00:15:01.236+01:00</updated><title type='text'>PC a móvil a PC</title><content type='html'>Hace un tiempo desarrollé un &lt;a target="_blank" href="http://sistemasorp.blogspot.com/2005/04/gateway-smsemailsms.html"&gt;gateway sms/mail/sms&lt;/a&gt; donde además del software, la pieza clave era esta:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.quejateportodo.com/blog/movilgsm.jpg"&gt;&lt;br /&gt;&lt;br /&gt;El gateway esta dado de baja (tuvo demasiado éxito), sin embargo el móvil que aparece en la imágen lo sigo usando en algunos de mis proyectos (pronto sabreis por qué estoy escribiendo artículos sobre aparatos). Se trata de un siemens m35i que en su día me cargué la pantalla y lo destiné como modem gsm para poder enviar y recibir sms. Este se comunica con un cable de datos por el puerto serie con el ordenador. Como el cable tiene que usar el mismo compartimento que la fuente de alimentación del móvil y necesitaba tener los dos al mismo tiempo, conecté los pines donde se conecta la batería del móvil a un pequeño circuito con un L7805C y dos condensadores, funcionando todo ello con una fuente de alimentación de 12 voltios.&lt;br /&gt;&lt;br /&gt;En este caso el móvil al ser un modem gsm (como la inmensa mayoría) se puede manejar con &lt;a target="_blank" href="http://en.wikipedia.org/wiki/Hayes_AT_command_set"&gt;comandos AT&lt;/a&gt;, aunque algunos son característicos de los móviles (como el de mandar sms).&lt;br /&gt;&lt;br /&gt;Para trabajar con el, en mi caso, tengo que abrir el puerto serie a 19200 baudios, 8 bits, ninguna paridad y un bit de stop.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.quejateportodo.com/blog/hyperterminal.jpg"&gt;&lt;br /&gt;&lt;br /&gt;En mi caso, siempre me interesa usarlo como transmisor/receptor de sms, por lo que leyendo un poco la &lt;a target="_blank" href="http://www.dhservis.cz/docs_soubory/at_pro_c35i-gsm_07.07_a_07.05.pdf"&gt;documentación del móvil&lt;/a&gt; veo que para enviar sms se usa el comando &lt;span style="font-weight:bold;"&gt;AT+CMGS&lt;/span&gt;. Sin embargo mi móvil no permite mensajes de texto de forma directa, sino que necesita enviarlos en &lt;a target="_blank" href="http://www.dreamfabric.com/sms/"&gt;formato estandar PDU&lt;/a&gt; (también cuando muestra los recibidos). Buscando por ahí no he encontrado mucho código fuente (en java &lt;a target="_blank" href="http://www.wrankl.de/SMST/SMST.html"&gt;smstools&lt;/a&gt;) por lo que me hice una rutina en C para pasar de texto a PDU y viceversa:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;/* Transforma un texto normal (pchOriginal) en PDU (pchTransformado) devolviendo pchTransformado*/&lt;br /&gt;char *formatoMensaje(char *pchOriginal, char *pchTransformado)&lt;br /&gt;{&lt;br /&gt; char pchTablaHex[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};&lt;br /&gt; unsigned char chrCaracter;&lt;br /&gt; int intContador;&lt;br /&gt; int intIndice;&lt;br /&gt; int intTamano;&lt;br /&gt; int intMascara;&lt;br /&gt; int intDesplaza;&lt;br /&gt;&lt;br /&gt; intTamano = strlen(pchOriginal);&lt;br /&gt; intMascara = 1;&lt;br /&gt; intContador = 0;&lt;br /&gt; intIndice = 2;&lt;br /&gt; strcpy(pchTransformado,"00");&lt;br /&gt; intDesplaza = 7;&lt;br /&gt;&lt;br /&gt; while(intContador &amp;lt; intTamano)&lt;br /&gt; {&lt;br /&gt;  chrCaracter = ((*(pchOriginal + intContador + 1) &amp; intMascara) &amp;lt;&amp;lt; intDesplaza) + (*(pchOriginal + intContador) &amp;gt;&amp;gt; (7 - intDesplaza));&lt;br /&gt;  pchTransformado[intIndice] = pchTablaHex[(chrCaracter &amp; 0xF0) &amp;gt;&amp;gt; 4];&lt;br /&gt;  intIndice++;&lt;br /&gt;  pchTransformado[intIndice] = pchTablaHex[chrCaracter &amp; 0x0F];&lt;br /&gt;  intIndice++;&lt;br /&gt;  intContador++;&lt;br /&gt;  intMascara &amp;lt;&amp;lt;= 1;&lt;br /&gt;  intMascara++ ;&lt;br /&gt;  intDesplaza--;&lt;br /&gt;  if(intDesplaza == -1)&lt;br /&gt;  {&lt;br /&gt;   intMascara = 1;&lt;br /&gt;   intDesplaza = 7;&lt;br /&gt;   intIndice -= 2;&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; pchTransformado[intIndice] = '\0';&lt;br /&gt;&lt;br /&gt; chrCaracter=(char)intTamano;&lt;br /&gt; pchTransformado[0] = pchTablaHex[(chrCaracter &amp; 0xF0) &amp;gt;&amp;gt; 4];&lt;br /&gt; pchTransformado[1] = pchTablaHex[chrCaracter &amp; 0x0F];&lt;br /&gt;&lt;br /&gt; return pchTransformado;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/* Transforma un texto PDU (pchOriginal) en texto normal (pchTransformado) devolviendo pchTransformado*/&lt;br /&gt;char *decodificaMensaje(char *pchOriginal, char *pchTransformado)&lt;br /&gt;{&lt;br /&gt; char pchLetras[5];&lt;br /&gt; unsigned char chrCaracter;&lt;br /&gt; int intTamano;&lt;br /&gt; int intContador;&lt;br /&gt; int intArrastre;&lt;br /&gt; int intDesplaza;&lt;br /&gt; int intIndice;&lt;br /&gt; int intMascara;&lt;br /&gt;&lt;br /&gt; intMascara = 128;&lt;br /&gt; intIndice = intContador = intArrastre = intDesplaza = 0;&lt;br /&gt;&lt;br /&gt; strcpy(pchLetras, "0x");&lt;br /&gt; strncat(pchLetras, pchOriginal + intIndice, 2);&lt;br /&gt; sscanf(pchLetras, "%x", &amp;intTamano);&lt;br /&gt;&lt;br /&gt; intIndice += 2;&lt;br /&gt;&lt;br /&gt; while(intContador &amp;lt; intTamano)&lt;br /&gt; {&lt;br /&gt;  strcpy(pchLetras, "0x");&lt;br /&gt;  strncat(pchLetras, pchOriginal + intIndice, 2);&lt;br /&gt;  sscanf(pchLetras, "%x", &amp;chrCaracter);&lt;br /&gt;  pchTransformado[intContador] = ((chrCaracter &amp; ~intMascara) &amp;lt;&amp;lt; intDesplaza) + intArrastre;&lt;br /&gt;  intArrastre=(chrCaracter &amp; intMascara) &amp;gt;&amp;gt; (7 - intDesplaza);&lt;br /&gt;  intIndice += 2;&lt;br /&gt;  intMascara &amp;gt;&amp;gt;= 1;&lt;br /&gt;  intMascara += 128;&lt;br /&gt;  intDesplaza++;&lt;br /&gt;  if(intMascara == 255)&lt;br /&gt;  {&lt;br /&gt;   intContador++;&lt;br /&gt;   pchTransformado[intContador] = chrCaracter &amp;gt;&amp;gt; 1;&lt;br /&gt;   intMascara = 128;&lt;br /&gt;   intDesplaza = intArrastre = 0;&lt;br /&gt;  }&lt;br /&gt;  ++intContador;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; pchTransformado[intContador] = '\0';&lt;br /&gt;&lt;br /&gt; return pchTransformado;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5416816-113831730119802205?l=sistemasorp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sistemasorp.blogspot.com/feeds/113831730119802205/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5416816&amp;postID=113831730119802205' title='18 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/113831730119802205'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/113831730119802205'/><link rel='alternate' type='text/html' href='http://sistemasorp.blogspot.com/2006/01/pc-mvil-pc.html' title='PC a móvil a PC'/><author><name>sistemasorp</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>18</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5416816.post-113675920629215321</id><published>2006-01-08T22:33:00.000+01:00</published><updated>2006-01-08T23:26:46.346+01:00</updated><title type='text'>Manejar un ordenador con un mando a distancia</title><content type='html'>En el mercado de hoy en día se venden tarjetas sintonizadoras de televisión para el PC. Muchas de ellas tienen mando a distancia. Y en algunas de ellas el receptor de infrarojos que trae es para conectarlo a un puerto serie del PC.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.quejateportodo.com/blog/mandoadistancia.jpg"&gt;&lt;br /&gt;&lt;br /&gt;Al ser el receptor de infrarojos un conector para el puerto serie, es muy sencillo comprobar que información le envía el mando a distancia y tomar esos datos para aprovecharlos en futuras aplicaciones, como por ejemplo:&lt;br /&gt;&lt;br /&gt;-Apagar el equipo.&lt;br /&gt;-Cargar una aplicación&lt;br /&gt;-Simular pulsaciones del teclado predefinidas o mover el puntero ratón y simular pulsaciones de los botones.&lt;br /&gt;-Escuchar música y subir el volúmen de los altavoces&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;La forma sencilla de saber que datos manda y en que formato sin tener que investigar mucho es usar un sniffer del puerto serie. En mi caso he usado el &lt;a target="_blank" href="http://www.sysinternals.com/Utilities/Portmon.html"&gt;portmon&lt;/a&gt;, que es una excelente utilidad para rastrear la información que va y viene desde los puertos serie y paralelo.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.quejateportodo.com/blog/portmon.jpg"&gt;&lt;br /&gt;&lt;br /&gt;Si os fijais en la imagen, se muestra como inicializa el puerto a 1200 baudios, 8 bits de datos, ninguna paridad y 1 bit de stop. A continuación vienen los datos propiamente dichos. Para la prueba he pulsado el botón 1 del mando a distancia y el resultado es &lt;span style="font-weight:bold;"&gt;FE 9F 31&lt;/span&gt;, si hubiese pulsado el 2 el resultado sería &lt;span style="font-weight:bold;"&gt;FE 3D 32&lt;/span&gt;. Si lo observamos veremos que el 1 y el 2 (y el resto de números) coinciden con su representación ASCII en hexadecimal (31 y 32). En otros casos como la pulsación de las teclas de subir (&lt;span style="font-weight:bold;"&gt;FE F1 3B&lt;/span&gt;) y bajar (&lt;span style="font-weight:bold;"&gt;FE 64 3D&lt;/span&gt;) volumen o subir (&lt;span style="font-weight:bold;"&gt;FE 17 3F&lt;/span&gt;)y bajar (&lt;span style="font-weight:bold;"&gt;FE C6 3E&lt;/span&gt;) de canal muestran otros caracteres. En el caso de que dejáramos una tecla pulsada los códigos varían ligeramente, como en la imágen, que aparece el triplete &lt;span style="font-weight:bold;"&gt;FE 77 71&lt;/span&gt; cuando se deja pulsado el botón 1 del mando a distancia.&lt;br /&gt;&lt;br /&gt;En definitiva, da igual que sea en linux o en windows, podemos capturar estos tripletes y actuar en consecuencia con cada pulsación recibida (si se pulsa el botón de off apagamos el equipo, si pulsamos los botones de subir y bajar el volumen y los canales podemos manejar el puntero del ratón, con el mute podemos apagar el altavoz del equipo, con el botón de play podemos enviar un tabulador, con los números podemos escribir letras estilo sms, etc). Por supuesto, que esa información venga así en mi receptor de infrarojos no significa que sea igual en otros, de ahi que haya que mirar como funciona con utilidades como el portmon.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5416816-113675920629215321?l=sistemasorp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sistemasorp.blogspot.com/feeds/113675920629215321/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5416816&amp;postID=113675920629215321' title='11 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/113675920629215321'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/113675920629215321'/><link rel='alternate' type='text/html' href='http://sistemasorp.blogspot.com/2006/01/manejar-un-ordenador-con-un-mando.html' title='Manejar un ordenador con un mando a distancia'/><author><name>sistemasorp</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5416816.post-113131617983036366</id><published>2005-11-06T23:03:00.000+01:00</published><updated>2005-11-09T17:02:17.940+01:00</updated><title type='text'>Recuperar los títulos de las canciones de un CD con FREEDB</title><content type='html'>Desde hace mucho tiempo estan disponibles dos servicios en Internet cuyo cometido es almacenar una gigantesca base de datos con los títulos de las canciones de cualquier CD de música que se haya editado. La primera es &lt;a href="http://www.gracenote.com/" target="_blank"&gt;Gracenote&lt;/a&gt; (también conocida antes del 2000 por cddb), de la cual no hablaremos en este artículo por requerir licencia. La segunda es &lt;a href="http://www.freedb.org/" target="_blank"&gt;freedb&lt;/a&gt; la cual sigue siendo gratuita y con una simple página web podemos consultar la información que nos interesa. En la sección &lt;em&gt;developers&lt;/em&gt; podreis encontrar la información necesaria para trabajar con esta tecnología.&lt;br /&gt;&lt;br /&gt;Básicamente consiste en obtener una identificación única a partir de la información de la tabla de contenidos de un CD (&lt;em&gt;TOC&lt;/em&gt;). Una vez obtenida la identificación, solo hay que hacer una petición web al servidor de freedb con la misma para que nos devuelva el título del CD y la lista de títulos de canciones y sus respectivos autores de las distintas pistas que conforman el CD.&lt;br /&gt;&lt;br /&gt;El algoritmo para hallar el identificador único consiste en:&lt;br /&gt;-Sumar los números en segundos de lo que dura cada pista. Es decir, si una cancion dura 4:17, entónces son 257 segundos, luego la suma es 2+5+7=14.&lt;br /&gt;-Una vez obtenido el sumatorio de todas las pistas con el anterior algoritmo, se le saca el módulo de 255 y a continuación se le multiplica por 16777216 (2^24); a este resultado se le suma el tiempo total del CD multiplicado por 256 (2^8) y finalmente a este resultado se le suma el número total de pistas que contiene el CD.&lt;br /&gt;&lt;br /&gt;Una vez hallado el identificador único, se transforma a un número hexadecimal y se hace una peticion a &lt;em&gt;freedb&lt;/em&gt; de la siguiente manera:&lt;br /&gt;&lt;br /&gt;http://freedb.freedb.org/~cddb/cddb.cgi?cmd=cddb+read+misc+&amp;lt;ID UNICO&amp;gt;&amp;hello=name+host.com+appname+1.0&amp;proto=1&lt;br /&gt;&lt;br /&gt;&lt;em&gt;cddb read misc &amp;lt;ID UNICO&amp;gt;&lt;/em&gt; del parámetro &lt;strong&gt;cmd&lt;/strong&gt; es el comando que indica que estamos haciendo una petición a la base de datos con el &lt;em&gt;ID UNICO&lt;/em&gt;. Por ejemplo &lt;em&gt;cddb read misc c510910d&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;name host.com appname 1.0&lt;/em&gt; del parámetro &lt;strong&gt;hello&lt;/strong&gt; indica que persona, dominio, aplicación y versión de la misma esta solicitando la información. Por ejemplo: &lt;em&gt;sistemasorp sistemasorp.blogspot.com testeoCDDB 1.0&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;Y finalmente el &lt;em&gt;1&lt;/em&gt; del parámetro &lt;strong&gt;proto&lt;/strong&gt; indica que versión del protocolo queremos usar para hacer la petición a la base de datos, devolviendonos acorde a la versión una información formateada.&lt;br /&gt;&lt;br /&gt;Así por ejemplo si lanzamos esta petición:&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" href="http://freedb.freedb.org/~cddb/cddb.cgi?cmd=cddb+read+misc+c510910d&amp;hello=sistemasorp+sistemasorp.blogspot.com+testeoCDDB+1.0&amp;proto=1"&gt;http://freedb.freedb.org/~cddb/cddb.cgi?cmd=cddb+read+misc+c510910d&amp;hello=sistemasorp+sistemasorp.blogspot.com+testeoCDDB+1.0&amp;proto=1&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Nos devuelve lo siguiente (terminado en una linea con un punto, al estilo del &lt;a href="http://es.wikipedia.org/wiki/SMTP" target="_blank"&gt;SMTP&lt;/a&gt;):&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;210 misc c510910d CD database entry follows (until terminating `.')&lt;br /&gt;# xmcd CD database file&lt;br /&gt;#&lt;br /&gt;# Track frame offsets:&lt;br /&gt;# 150&lt;br /&gt;# 24460&lt;br /&gt;# 45650&lt;br /&gt;# 71127&lt;br /&gt;# 98425&lt;br /&gt;# 118997&lt;br /&gt;# 146585&lt;br /&gt;# 164707&lt;br /&gt;# 188897&lt;br /&gt;# 216340&lt;br /&gt;# 240932&lt;br /&gt;# 271642&lt;br /&gt;# 297722&lt;br /&gt;#&lt;br /&gt;# Disc length: 4243 seconds&lt;br /&gt;#&lt;br /&gt;# Revision: 2&lt;br /&gt;# Processed by: cddbd v1.5PL3 Copyright (c) Steve Scherf et al.&lt;br /&gt;# Submitted via: CDex 1.40Beta9&lt;br /&gt;#&lt;br /&gt;DISCID=c510910d&lt;br /&gt;DTITLE=Various / Rave Massacre [Disk 1]&lt;br /&gt;TTITLE0=Raving Bastards - Love Time&lt;br /&gt;TTITLE1=Chill'n Force - Move Raver (Kemo Mix)&lt;br /&gt;TTITLE2=M.A.F. X-Perience - Dreamland&lt;br /&gt;TTITLE3=Society for Psychical Research - Silversky&lt;br /&gt;TTITLE4=Obsessiv - Tune In, Tune On, Drop Out&lt;br /&gt;TTITLE5=Nettuno - I Cry&lt;br /&gt;TTITLE6=Razor - Is It Love&lt;br /&gt;TTITLE7=Sunbeam - Outside World&lt;br /&gt;TTITLE8=Raver's Nature - Tricky Symphony&lt;br /&gt;TTITLE9=NIP Collective - I'm About&lt;br /&gt;TTITLE10=RBM - Banyo Love&lt;br /&gt;TTITLE11=Paranoia X - Party Program&lt;br /&gt;TTITLE12=NR-Gizer - Raving Generation&lt;br /&gt;EXTD= YEAR: 1994 ID3G: 31&lt;br /&gt;EXTT0=&lt;br /&gt;EXTT1=&lt;br /&gt;EXTT2=&lt;br /&gt;EXTT3=&lt;br /&gt;EXTT4=&lt;br /&gt;EXTT5=&lt;br /&gt;EXTT6=&lt;br /&gt;EXTT7=&lt;br /&gt;EXTT8=&lt;br /&gt;EXTT9=&lt;br /&gt;EXTT10=&lt;br /&gt;EXTT11=&lt;br /&gt;EXTT12=&lt;br /&gt;PLAYORDER=&lt;br /&gt;.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Donde entre comentarios (con la almohadilla delante) da información sobre el disco, copyright y demás; continuando con una lista de parejas nombre/valor que contienen la información que queremos:&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;DISCID&lt;/strong&gt;: El mismo identificador de disco que le hemos pasado&lt;br /&gt;&lt;strong&gt;DTITLE&lt;/strong&gt;: El autor y título del CD&lt;br /&gt;&lt;strong&gt;TTITLEX&lt;/strong&gt;: El título de canción que está en la pista X&lt;br /&gt;&lt;strong&gt;EXTD&lt;/strong&gt;: Información extendida sobre el disco&lt;br /&gt;&lt;strong&gt;EXTTX&lt;/strong&gt;: Información extendida sobre la canción que está en la pista X&lt;br /&gt;&lt;strong&gt;PLAYORDER&lt;/strong&gt;: El orden en el que se deberían reproducir las pistas&lt;br /&gt;&lt;strong&gt;YEAR&lt;/strong&gt;: El año de edición del disco&lt;br /&gt;&lt;strong&gt;ID3G&lt;/strong&gt;: La categoría o clase de música que contiene el CD&lt;br /&gt;&lt;br /&gt;A continuación expongo dos codigos fuentes (el primero para windows y el segundo para linux) que muestran como recoger el identificador único de un cd y a continuación solicitar la información de ese cd a freedb. Ambos se ejecutan en la consola de texto pasandoles como parámetro la unidad o dispositivo de cd.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;WINDOWS&lt;/strong&gt;(&lt;a href="http://www.quejateportodo.com/blog/toc.zip"&gt;ejecutable y fuentes&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#include "stdafx.h"&lt;br /&gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;#include &amp;lt;string.h&amp;gt;&lt;br /&gt;#include &amp;lt;winsock.h&amp;gt;&lt;br /&gt;#include &amp;lt;windows.h&amp;gt;&lt;br /&gt;&lt;br /&gt;#define IOCTL_CDROM_READ_TOC 0x00024000&lt;br /&gt;&lt;br /&gt;typedef struct {&lt;br /&gt;  UCHAR  Reserved;&lt;br /&gt;  UCHAR  Control : 4;&lt;br /&gt;  UCHAR  Adr : 4;&lt;br /&gt;  UCHAR  TrackNumber;&lt;br /&gt;  UCHAR  Reserved1;&lt;br /&gt;  UCHAR  Address[4];&lt;br /&gt;} TRACK_DATA;&lt;br /&gt;&lt;br /&gt;typedef struct {&lt;br /&gt;  UCHAR  Length[2];&lt;br /&gt;  UCHAR  FirstTrack;&lt;br /&gt;  UCHAR  LastTrack;&lt;br /&gt;  TRACK_DATA  TrackData[100];&lt;br /&gt;} CDROM_TOC;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;Funcion:&lt;br /&gt; lee_CDTOC&lt;br /&gt;Parámetros:&lt;br /&gt; sDispositivo: ruta del dispositivo de CD.&lt;br /&gt; toc: estructura donde se almancena la tabla de contenidos del CD.&lt;br /&gt;Descripción:&lt;br /&gt; Esta función se encarga de guardar en la variable toc la información de la tabla de contenidos del CD ubicado en el dispostivo lector de cdrom.&lt;br /&gt;*/&lt;br /&gt;void lee_CDTOC(char *sLetra,CDROM_TOC *toc)&lt;br /&gt;{&lt;br /&gt; HANDLE manejador;&lt;br /&gt; DWORD nTamBuffer;&lt;br /&gt; char sUnidad[7];&lt;br /&gt;&lt;br /&gt; sprintf(sUnidad,"\\\\.\\%s",sLetra);&lt;br /&gt;&lt;br /&gt; manejador = CreateFile(sUnidad, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);&lt;br /&gt; &lt;br /&gt; if(manejador == INVALID_HANDLE_VALUE)&lt;br /&gt; {&lt;br /&gt;  fprintf(stderr,"No se pudo acceder al disco de la unidad de CD\n");&lt;br /&gt;  return;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; if (DeviceIoControl(manejador, IOCTL_CDROM_READ_TOC, NULL, 0, toc, sizeof(CDROM_TOC), &amp;nTamBuffer, NULL) == FALSE)&lt;br /&gt;  fprintf(stderr,"No se pudo leer el contenido del CD\n");&lt;br /&gt;&lt;br /&gt; CloseHandle(manejador);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;Funcion:&lt;br /&gt; lee_InfoCDDB: Devuelve una cadena con los resultados de la petición.&lt;br /&gt;Parámetros:&lt;br /&gt; sIDDisco: identificador único del cd.&lt;br /&gt; sBuffer: buffer donde almacenar los resultados de la petición.&lt;br /&gt;Descripción:&lt;br /&gt; Esta función se encarga de pedir a freedb la información relacionada con un identificador de cd determinado y devolver todo el contenido de la petición.&lt;br /&gt;*/&lt;br /&gt;char *lee_InfoCDDB(char *sIDDisco,char *sBuffer)&lt;br /&gt;{&lt;br /&gt; WSAData data;&lt;br /&gt; SOCKET sock;&lt;br /&gt; struct hostent *servidor;&lt;br /&gt; struct sockaddr_in destino;&lt;br /&gt; char sPeticion[256];&lt;br /&gt; int nEnviados,nRecibidos;&lt;br /&gt;&lt;br /&gt; if(WSAStartup(MAKEWORD( 2, 2 ),&amp;data) == 0)&lt;br /&gt; {&lt;br /&gt;  if((sock=socket(PF_INET,SOCK_STREAM,0)) == INVALID_SOCKET)&lt;br /&gt;   fprintf(stderr,"No se pudo crear la conexion");&lt;br /&gt;  else&lt;br /&gt;  {&lt;br /&gt;   if((servidor=gethostbyname("freedb.freedb.org")) == NULL)&lt;br /&gt;    fprintf(stderr,"No se pudo obtener la IP del servidor");&lt;br /&gt;   else&lt;br /&gt;   {&lt;br /&gt;    destino.sin_family = AF_INET;&lt;br /&gt;    destino.sin_port = htons(80);&lt;br /&gt;    destino.sin_addr = *((struct in_addr *)servidor-&amp;gt;h_addr_list[0]);&lt;br /&gt;    memset(&amp;(destino.sin_zero), '\0', 8);&lt;br /&gt;    if(connect(sock, (struct sockaddr *)&amp;destino, sizeof(struct sockaddr)) == SOCKET_ERROR)&lt;br /&gt;     fprintf(stderr,"No se pudo conectar al servidor");&lt;br /&gt;    else&lt;br /&gt;    {&lt;br /&gt;     sprintf(sPeticion,"GET /~cddb/cddb.cgi?cmd=cddb+read+misc+%s&amp;hello=sistemasorp+sistemasorp.blogspot.com+testeoCDDB+1.0&amp;proto=1 HTTP/1.0\r\n",sIDDisco);&lt;br /&gt;     strcat(sPeticion,"Host: freedb.freedb.org\r\n\r\n");&lt;br /&gt;     nEnviados=send(sock,sPeticion,strlen(sPeticion),0);&lt;br /&gt;     if(nEnviados == SOCKET_ERROR)&lt;br /&gt;      fprintf(stderr,"No se pudo enviar la peticion al servidor");&lt;br /&gt;     nRecibidos=0;&lt;br /&gt;     while(strstr(sBuffer,"\r\n.\r\n") == NULL)&lt;br /&gt;     {&lt;br /&gt;      nRecibidos+=recv(sock,sBuffer+nRecibidos,1024,0);&lt;br /&gt;      sBuffer[nRecibidos]='\0';&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;    }&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;  WSACleanup();&lt;br /&gt; }&lt;br /&gt; else&lt;br /&gt;  fprintf(stderr,"No se puedo inicializar la conexion");&lt;br /&gt; return sBuffer;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;Funcion:&lt;br /&gt; cddb_Suma: Devuelve un número sacado a través de una suma de cifras.&lt;br /&gt;Parámetros:&lt;br /&gt; nDuracion: Duración en segundos de una pista.&lt;br /&gt;Descripción:&lt;br /&gt; Esta función se encarga de sumar todas las cifras de distinto peso entre si para posteriormente devolver el resultado.&lt;br /&gt;*/&lt;br /&gt;int cddb_Suma(int nDuracion)&lt;br /&gt;{&lt;br /&gt; int nSuma = 0;&lt;br /&gt;&lt;br /&gt; while (nDuracion &amp;gt; 0) {&lt;br /&gt;  nSuma = nSuma + (nDuracion % 10);&lt;br /&gt;  nDuracion = nDuracion / 10;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; return nSuma;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;Funcion:&lt;br /&gt; cddb_IDDisco: Devuelve en número que identifica al CD inequivocamente.&lt;br /&gt;Parámetros:&lt;br /&gt; toc: Información de la tabla de contenidos del CD&lt;br /&gt;Descripción:&lt;br /&gt; Esta función se encarga de calcular el identificador único de un CD a través de su tabla de contenidos&lt;br /&gt;*/&lt;br /&gt;unsigned long cddb_IDDisco(CDROM_TOC *toc)&lt;br /&gt;{&lt;br /&gt; int nIndice=0,&lt;br /&gt;  nTotalTiempo = 0,&lt;br /&gt;  nSumatorio = 0;&lt;br /&gt; int nTotalPistas;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt; nTotalPistas=toc-&amp;gt;LastTrack-toc-&amp;gt;FirstTrack+1;&lt;br /&gt; &lt;br /&gt; while (nIndice &amp;lt; nTotalPistas) {&lt;br /&gt;  nSumatorio = nSumatorio + cddb_Suma((toc-&amp;gt;TrackData[nIndice].Address[1] * 60) + toc-&amp;gt;TrackData[nIndice].Address[2]);&lt;br /&gt;  nIndice++;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; nTotalTiempo = ((toc-&amp;gt;TrackData[toc-&amp;gt;LastTrack].Address[1] * 60) + toc-&amp;gt;TrackData[toc-&amp;gt;LastTrack].Address[2]) -&lt;br /&gt;     ((toc-&amp;gt;TrackData[0].Address[1] * 60) + toc-&amp;gt;TrackData[0].Address[2]);&lt;br /&gt;&lt;br /&gt; return ((nSumatorio % 0xff) &amp;lt;&amp;lt; 24 | nTotalTiempo &amp;lt;&amp;lt; 8 | nTotalPistas);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;int main(int argc, char *argv[ ])&lt;br /&gt;{&lt;br /&gt; CDROM_TOC toc;&lt;br /&gt; char sIDDisco[9];&lt;br /&gt; char *sBuffer;&lt;br /&gt;&lt;br /&gt; if(argc==2)&lt;br /&gt; {&lt;br /&gt;  memset(&amp;toc,0,sizeof(CDROM_TOC));&lt;br /&gt;&lt;br /&gt;  lee_CDTOC(argv[1],&amp;toc);&lt;br /&gt;  if(toc.LastTrack&amp;gt;0)&lt;br /&gt;  {&lt;br /&gt;   sprintf(sIDDisco,"%08x",cddb_IDDisco(&amp;toc));&lt;br /&gt;   printf("El ID del disco es %s\n",sIDDisco);&lt;br /&gt;&lt;br /&gt;   sBuffer=(char *)malloc(4096);&lt;br /&gt;   if(sBuffer == NULL)&lt;br /&gt;   {&lt;br /&gt;    fprintf(stderr,"No se pudo alojar memoria");&lt;br /&gt;    return 1;&lt;br /&gt;   }   &lt;br /&gt;   *sBuffer='\0';&lt;br /&gt;   lee_InfoCDDB(sIDDisco,sBuffer);&lt;br /&gt;   if(*sBuffer=='\0')&lt;br /&gt;    return 1;&lt;br /&gt;   printf("La información del disco es:\n%s",sBuffer);&lt;br /&gt;   free(sBuffer);&lt;br /&gt;  }&lt;br /&gt;  else&lt;br /&gt;   return 1;&lt;br /&gt; }&lt;br /&gt; else&lt;br /&gt; {&lt;br /&gt;  fprintf(stderr,"La sintaxis es: %s &amp;lt;unidad de cd&amp;gt;\nEjemplo: %s d:\n",argv[0],argv[0]);&lt;br /&gt;  return 1;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; return 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;LINUX&lt;/strong&gt;(&lt;a href="http://www.quejateportodo.com/blog/toc.tar.gz"&gt;ejecutable y fuentes&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;#include &amp;lt;stdarg.h&amp;gt;&lt;br /&gt;#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;#include &amp;lt;netdb.h&amp;gt;&lt;br /&gt;#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;#include &amp;lt;string.h&amp;gt;&lt;br /&gt;#include &amp;lt;sys/ioctl.h&amp;gt;&lt;br /&gt;#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;#include &amp;lt;sys/socket.h&amp;gt;&lt;br /&gt;&lt;br /&gt;#if defined linux&lt;br /&gt;#include &amp;lt;linux/cdrom.h&amp;gt;&lt;br /&gt;#elif defined sun&lt;br /&gt;#include &amp;lt;sys/cdio.h&amp;gt;&lt;br /&gt;#endif&lt;br /&gt;&lt;br /&gt;typedef struct {&lt;br /&gt; int minutos, segundos;&lt;br /&gt;} TRACK_DATA;&lt;br /&gt;&lt;br /&gt;typedef struct {&lt;br /&gt;  unsigned char  FirstTrack;&lt;br /&gt;  unsigned char LastTrack; &lt;br /&gt;  TRACK_DATA  TrackData[100];&lt;br /&gt;} CDROM_TOC;&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;Funcion:&lt;br /&gt; lee_CDTOC&lt;br /&gt;Parámetros:&lt;br /&gt; sDispositivo: ruta del dispositivo de CD.&lt;br /&gt; toc: estructura donde se almancena la tabla de contenidos del CD.&lt;br /&gt;Descripción:&lt;br /&gt; Esta función se encarga de guardar en la variable toc la información de la tabla de contenidos del CD ubicado en el dispostivo lector de cdrom.&lt;br /&gt;*/&lt;br /&gt;void lee_CDTOC(char *sDispositivo,CDROM_TOC *toc)&lt;br /&gt;{&lt;br /&gt; struct cdrom_tochdr tochdr;&lt;br /&gt; struct cdrom_tocentry tocentry;&lt;br /&gt; int nIndice, manejador;&lt;br /&gt;&lt;br /&gt; manejador= open(sDispositivo, O_RDONLY | O_NONBLOCK);&lt;br /&gt; if(manejador == -1)&lt;br /&gt; {&lt;br /&gt;  fprintf(stderr,"No se pudo acceder al disco de la unidad de CD\n");&lt;br /&gt;  return;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; if (ioctl(manejador, CDROMREADTOCHDR, &amp;tochdr) == -1)&lt;br /&gt;  fprintf(stderr,"No se pudo leer el contenido del CD\n");&lt;br /&gt; else&lt;br /&gt; {&lt;br /&gt;  toc-&amp;gt;FirstTrack=tochdr.cdth_trk0;&lt;br /&gt;  toc-&amp;gt;LastTrack=tochdr.cdth_trk1;&lt;br /&gt;  for (nIndice = toc-&amp;gt;FirstTrack; nIndice &amp;lt;= toc-&amp;gt;LastTrack; nIndice++) &lt;br /&gt;  {&lt;br /&gt;   tocentry.cdte_track = nIndice;&lt;br /&gt;   tocentry.cdte_format = CDROM_MSF;&lt;br /&gt;   ioctl(manejador, CDROMREADTOCENTRY, &amp;tocentry);&lt;br /&gt;   toc-&amp;gt;TrackData[nIndice-1].minutos = tocentry.cdte_addr.msf.minute;&lt;br /&gt;   toc-&amp;gt;TrackData[nIndice-1].segundos = tocentry.cdte_addr.msf.second;&lt;br /&gt;  }&lt;br /&gt;  tocentry.cdte_track = 0xAA;&lt;br /&gt;  tocentry.cdte_format = CDROM_MSF;&lt;br /&gt;  ioctl(manejador, CDROMREADTOCENTRY, &amp;tocentry);&lt;br /&gt;  toc-&amp;gt;TrackData[toc-&amp;gt;LastTrack].minutos = tocentry.cdte_addr.msf.minute;&lt;br /&gt;  toc-&amp;gt;TrackData[toc-&amp;gt;LastTrack].segundos = tocentry.cdte_addr.msf.second;&lt;br /&gt; }&lt;br /&gt; close(manejador);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;Funcion:&lt;br /&gt; lee_InfoCDDB: Devuelve una cadena con los resultados de la petición.&lt;br /&gt;Parámetros:&lt;br /&gt; sIDDisco: identificador único del cd.&lt;br /&gt; sBuffer: buffer donde almacenar los resultados de la petición.&lt;br /&gt;Descripción:&lt;br /&gt; Esta función se encarga de pedir a freedb la información relacionada con un identificador de cd determinado y devolver todo el contenido de la petición.&lt;br /&gt;*/&lt;br /&gt;char *lee_InfoCDDB(char *sIDDisco,char *sBuffer)&lt;br /&gt;{&lt;br /&gt; int sock;&lt;br /&gt; struct hostent *servidor;&lt;br /&gt; struct sockaddr_in destino;&lt;br /&gt; char sPeticion[256];&lt;br /&gt; int nEnviados,nRecibidos;&lt;br /&gt;&lt;br /&gt; if((sock=socket(PF_INET,SOCK_STREAM,0)) == -1)&lt;br /&gt;  fprintf(stderr,"No se pudo crear la conexion");&lt;br /&gt; else&lt;br /&gt; {&lt;br /&gt;  if((servidor=gethostbyname("freedb.freedb.org"))==NULL)&lt;br /&gt;   fprintf(stderr,"No se pudo obtener la IP del servidor");&lt;br /&gt;  else&lt;br /&gt;  {&lt;br /&gt;   destino.sin_family = AF_INET;&lt;br /&gt;   destino.sin_port = htons(80);&lt;br /&gt;   destino.sin_addr = *((struct in_addr *)servidor-&amp;gt;h_addr_list[0]);&lt;br /&gt;   memset(&amp;(destino.sin_zero), '\0', 8);&lt;br /&gt;   if(connect(sock, (struct sockaddr *)&amp;destino, sizeof(struct sockaddr)) == -1)&lt;br /&gt;    fprintf(stderr,"No se pudo conectar al servidor");&lt;br /&gt;   else&lt;br /&gt;   {&lt;br /&gt;    sprintf(sPeticion,"GET /~cddb/cddb.cgi?cmd=cddb+read+misc+%s&amp;hello=sistemasorp+sistemasorp.blogspot.com+testeoCDDB+1.0&amp;proto=1 HTTP/1.0\r\n",sIDDisco);&lt;br /&gt;    strcat(sPeticion,"Host: freedb.freedb.org\r\n\r\n");&lt;br /&gt;    nEnviados=send(sock,sPeticion,strlen(sPeticion),0);&lt;br /&gt;    if(nEnviados == -1)&lt;br /&gt;     fprintf(stderr,"No se pudo enviar la peticion al servidor");&lt;br /&gt;    nRecibidos=0;&lt;br /&gt;    while(strstr(sBuffer,"\r\n.\r\n") == NULL)&lt;br /&gt;    {&lt;br /&gt;     nRecibidos+=recv(sock,sBuffer+nRecibidos,1024,0);&lt;br /&gt;     sBuffer[nRecibidos]='\0';&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt; return sBuffer;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;Funcion:&lt;br /&gt; cddb_Suma: Devuelve un número sacado a través de una suma de cifras.&lt;br /&gt;Parámetros:&lt;br /&gt; nDuracion: Duración en segundos de una pista.&lt;br /&gt;Descripción:&lt;br /&gt; Esta función se encarga de sumar todas las cifras de distinto peso entre si para posteriormente devolver el resultado.&lt;br /&gt;*/&lt;br /&gt;int cddb_Suma(int nDuracion)&lt;br /&gt;{&lt;br /&gt; int nSuma = 0;&lt;br /&gt;&lt;br /&gt; while (nDuracion &amp;gt; 0) {&lt;br /&gt;  nSuma = nSuma + (nDuracion % 10);&lt;br /&gt;  nDuracion = nDuracion / 10;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; return nSuma;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;Funcion:&lt;br /&gt; cddb_IDDisco: Devuelve en número que identifica al CD inequivocamente.&lt;br /&gt;Parámetros:&lt;br /&gt; toc: Información de la tabla de contenidos del CD&lt;br /&gt;Descripción:&lt;br /&gt; Esta función se encarga de calcular el identificador único de un CD a través de su tabla de contenidos&lt;br /&gt;*/&lt;br /&gt;unsigned long cddb_IDDisco(CDROM_TOC *toc)&lt;br /&gt;{&lt;br /&gt; int nIndice=0,&lt;br /&gt;  nTotalTiempo = 0,&lt;br /&gt;  nSumatorio = 0;&lt;br /&gt; int nTotalPistas;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt; nTotalPistas=toc-&amp;gt;LastTrack-toc-&amp;gt;FirstTrack+1;&lt;br /&gt; &lt;br /&gt; while (nIndice &amp;lt; nTotalPistas) {&lt;br /&gt;  nSumatorio = nSumatorio + cddb_Suma((toc-&amp;gt;TrackData[nIndice].minutos * 60) + toc-&amp;gt;TrackData[nIndice].segundos);&lt;br /&gt;  nIndice++;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; nTotalTiempo = ((toc-&amp;gt;TrackData[toc-&amp;gt;LastTrack].minutos* 60) + toc-&amp;gt;TrackData[toc-&amp;gt;LastTrack].segundos) -&lt;br /&gt;     ((toc-&amp;gt;TrackData[0].minutos * 60) + toc-&amp;gt;TrackData[0].segundos);&lt;br /&gt;&lt;br /&gt; return ((nSumatorio % 0xff) &amp;lt;&amp;lt; 24 | nTotalTiempo &amp;lt;&amp;lt; 8 | nTotalPistas);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;int main(int argc, char *argv[ ])&lt;br /&gt;{&lt;br /&gt; CDROM_TOC toc;&lt;br /&gt; char sIDDisco[9];&lt;br /&gt; char *sBuffer;&lt;br /&gt;&lt;br /&gt; if(argc==2)&lt;br /&gt; {&lt;br /&gt;  memset(&amp;toc,0,sizeof(CDROM_TOC));&lt;br /&gt;&lt;br /&gt;  lee_CDTOC(argv[1],&amp;toc);&lt;br /&gt;  if(toc.LastTrack&amp;gt;0)&lt;br /&gt;  {&lt;br /&gt;   sprintf(sIDDisco,"%08x",cddb_IDDisco(&amp;toc));&lt;br /&gt;   printf("El ID del disco es %s\n",sIDDisco);&lt;br /&gt;&lt;br /&gt;   sBuffer=(char *)malloc(4096);&lt;br /&gt;   if(sBuffer == NULL)&lt;br /&gt;   {&lt;br /&gt;    fprintf(stderr,"No se pudo alojar memoria");&lt;br /&gt;    return 1;&lt;br /&gt;   }&lt;br /&gt;   *sBuffer='\0';&lt;br /&gt;   lee_InfoCDDB(sIDDisco,sBuffer);&lt;br /&gt;   if(*sBuffer=='\0')&lt;br /&gt;    return 1;&lt;br /&gt;   printf("La información del disco es:\n%s",sBuffer);&lt;br /&gt;   free(sBuffer);&lt;br /&gt;  }&lt;br /&gt;  else&lt;br /&gt;   return 1;&lt;br /&gt; }&lt;br /&gt; else&lt;br /&gt; {&lt;br /&gt;  fprintf(stderr,"La sintaxis es: %s &amp;lt;dispositivo de cd&amp;gt;\nEjemplo: %s /dev/cdrom\n",argv[0],argv[0]);&lt;br /&gt;  return 1;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; return 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5416816-113131617983036366?l=sistemasorp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sistemasorp.blogspot.com/feeds/113131617983036366/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5416816&amp;postID=113131617983036366' title='1 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/113131617983036366'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/113131617983036366'/><link rel='alternate' type='text/html' href='http://sistemasorp.blogspot.com/2005/11/recuperar-los-ttulos-de-las-canciones.html' title='Recuperar los títulos de las canciones de un CD con FREEDB'/><author><name>sistemasorp</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5416816.post-113085854429137739</id><published>2005-11-01T15:23:00.000+01:00</published><updated>2005-11-01T16:28:34.080+01:00</updated><title type='text'>webchat en tiempo real con php y mysql</title><content type='html'>Después de un pequeño descanso volvemos a las andadas. Esta vez voy a mostrar como crear un webchat en tiempo real.&lt;br /&gt;&lt;br /&gt;El problema de los webchat es que la inmensa mayoría de los que existen se dedican a refrescar la página de la charla cada X tiempo o cuando el usuario ha escrito un mensaje. Esto es debido a que el protocolo HTTP esta diseñado para que una vez recibido los datos cierre la conexión, y si queremos recuperar datos nuevos tenemos que hacer una nueva petición.&lt;br /&gt;&lt;br /&gt;Para lograr una interactividad y un realismo temporal cercanos al irc, messenger, etc. y seguir usando la web tenemos que usar un truco, y es crear una página que nunca termine de ejecutarse. Quizá os pregunteis que si nunca termina de ejecutarse, entónces no saldrá ningún resultado, pues bién, podemos desactivar el buffer del php desde el principio o hacer un volcado continuo para que cada dato nuevo se vaya enviando al navegador del cliente. Los navegadores muestran el contenido según les va llegando, por lo que una sentencia como esta (en pseudocodigo):&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;mientras verdadero&lt;br /&gt; recupera mensajes nuevos&lt;br /&gt; muestra mensajes nuevos&lt;br /&gt;fin del mientras&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;haría que cada vez que un mensaje nuevo apareciese se enviase al navegador y este lo mostrara instantaneamente, con lo que habríamos conseguido que fuese el tiempo real.&lt;br /&gt;&lt;br /&gt;Parar lograr este planteamiento en php tenemos que seguir los siguientes pasos (he reducido su código para simplificarlo):&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;ob_start();&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Que activa el tratamiento del buffer en php&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;set_time_limit(0);&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Indica al motor de php que el script nunca debe caducar a pesar de lo que dure.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;br /&gt;for(;;)&lt;br /&gt;{&lt;br /&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Este es el bucle que constantemente se va repitiendo.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;br /&gt;$rs=mysql_query("SELECT * FROM chat_mensajes WHERE IDMensaje&amp;gt;'" . $id . "' AND WEEK(DatFecha,1)=WEEK(NOW(),1) AND YEAR(DatFecha)=YEAR(NOW()) ORDER BY IDMensaje")&lt;br /&gt;or die ("No se puede realizar la consulta");&lt;br /&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;En mi caso guardo los mensajes en una base de datos mysql, por lo que con la consulta SQL compruebo aquellos mensajes cuyo ID sea mayor que el último ID de mensaje que se ha mostrado (solo aquellos dentro de la semana actual del año en curso).&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;br /&gt;if(mysql_num_rows($rs)&amp;gt;0)&lt;br /&gt;{&lt;br /&gt; while($fila=mysql_fetch_array($rs,MYSQL_ASSOC)) {&lt;br /&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Compruebo si hay nuevos mensajes y los recorro.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;br /&gt;$id=$fila["IDMensaje"];&lt;br /&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Voy actualizando la variable &lt;em&gt;id&lt;/em&gt; para que contenga al final el último ID y así en la siguiente pasada del bucle solo recoger los últimos mensajes escritos a partir del indicado.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;br /&gt;echo "&amp;lt;div&amp;gt;\n";&lt;br /&gt;echo "&amp;lt;span&amp;gt;" . $fila["DatFecha"] . " " . "&amp;lt;/span&amp;gt;";&lt;br /&gt;echo "&amp;lt;span&amp;gt;" . $fila["StrUsuario"] . "&amp;amp;gt;&amp;lt;/span&amp;gt;";&lt;br /&gt;echo "&amp;lt;span&amp;gt;" . $fila["StrMensaje"] . "&amp;lt;/span&amp;gt;";&lt;br /&gt;echo "&amp;lt;/div&amp;gt;\n";&lt;br /&gt;}&lt;br /&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Se va mostrando el contenido de los mensajes (fecha, remitente y mensaje).&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;br /&gt;echo "&amp;lt;script&amp;gt;scrollTo(0,999999999);&amp;lt;/script&amp;gt;\n";&lt;br /&gt;ob_flush();&lt;br /&gt;flush();   &lt;br /&gt;}&lt;br /&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Con un pequeño truco en javascript logramos desplazar la ventana del navegador siempre hasta el final del contenido. A continuacuón vaciamos el buffer hacia el navegador del cliente.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;br /&gt;sleep(1);&lt;br /&gt;}&lt;br /&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Para no recargar mucho el servidor mysql haciendo constantemente consultas, pausamos durante un segundo la ejecución para después continuar con la siguiente iteración del bucle.&lt;br /&gt;&lt;br /&gt;Quizá penseis que esta solución recarga mucho el servidor (tanto el web como el de mysql), pero el impacto es mínimo y si teneis un hosting esto os ahorrará ancho de banda puesto que gasta más por usuario el estar haciendo peticiones al servidor web cada X tiempo que una sola petición que dure eternamente (solo gasta lo que envia, como una petición normal); en cuanto al servidor mysql si este esta en localhost (como el 99% de los hosting) el impacto es mínimo porque no consume ningún recurso de red, además de que el propio mysql es rapídisimo y eficiente haciendo las consultas y no mermará el rendimiento por estar haciendo una cada segundo por cada usuario. Sin embargo si no quereis usar mysql, podeis usar ficheros (&lt;strong&gt;fopen&lt;/strong&gt;) o bién memoria compartida (&lt;strong&gt;Shmop&lt;/strong&gt;). Por supuesto esto no es la panacea, pero para cosas pequeñas (20 personas a la vez) si puede ir bién tenerlo así montado.&lt;br /&gt;&lt;br /&gt;En la web en la que colaboro &lt;a href="http://www.starwarsspanishstuff.info/webchat" target="_blank"&gt;tengo implementado&lt;/a&gt; este sistema, que aunque lo tengo bastante desarollado, todavía tengo que mejorar ciertos aspectos de funcionalidad.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5416816-113085854429137739?l=sistemasorp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sistemasorp.blogspot.com/feeds/113085854429137739/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5416816&amp;postID=113085854429137739' title='16 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/113085854429137739'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/113085854429137739'/><link rel='alternate' type='text/html' href='http://sistemasorp.blogspot.com/2005/11/webchat-en-tiempo-real-con-php-y-mysql.html' title='webchat en tiempo real con php y mysql'/><author><name>sistemasorp</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>16</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5416816.post-112601624931970193</id><published>2005-09-06T14:33:00.000+02:00</published><updated>2005-09-06T16:17:29.350+02:00</updated><title type='text'>Generar imágenes aleatorias con php y google</title><content type='html'>Hace poco me planteé meter una sección de imágenes aleatorias en la &lt;a target="_blank" href="http://www.starwarsspanishstuff.info"&gt;web&lt;/a&gt; que estoy administrando junto con un amigo sobre coleccionismo español de la guerra de las galaxias.&lt;br /&gt;&lt;br /&gt;El caso es que el hecho de tener un montón de imágenes almacenadas no es la mejor solución para un hosting si no tienes mucho espacio, por lo que se me ocurrió recurrir a la sección de imágenes de google. En esta sección se muestran en formato thumbnail (imágen pequeña de referencia) todas las imágenes de las páginas web que en su día indexó google, por lo que además de tener un vasto repertorio de imágenes, todas ellas estan asociadas al texto de la web a la que pertenecen. Así, si buscamos por palabras, podemos encontrar imágenes que concuerden con la búsqueda.&lt;br /&gt;&lt;br /&gt;A mi me viene de lujo para mis intenciones, puesto que poniendo &lt;em&gt;star wars&lt;/em&gt; en el cuadro de texto de la sección de imágenes de google aparecen algo menos de un millón de resultados. Añadiendo que la sección que quería poner en la web era más bién pequeña, las imágenes thumbnail de google son perfectas en cuanto a dimensiones para que quepa en la sección de la web.&lt;br /&gt;&lt;br /&gt;Ahora bién, ¿como hacer para que los thumnails que google ha generado salgan en la web como propios?...Pues gracias a php puedo leer el contenido de las urls y mostrarlo con una cabecera apropiada como si fuera una imagen normal y corriente.&lt;br /&gt;&lt;br /&gt;1-Una imagen en HTML se hace con la etiqueta &lt;em&gt;IMG&lt;/em&gt; y el atributo &lt;em&gt;src&lt;/em&gt;. En mi caso la imágen aletoria de la web debería apuntar siempre a un mismo sitio ya que es el propio php quien mostraría una imagen distinta cada vez. Por lo que en la web si os habeis fijado aparece:&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&amp;lt;img src="aleatorio.php" alt="Imagen aleatoria (Gracias a Google Images)"&amp;gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Que indica al navegador que debe mostrar la imagen que genera la página &lt;em&gt;aleatoria.php&lt;/em&gt; (con esto os podeis imaginar que los nombres de los ficheros le importan un pimiento al navegador, solo le interesa las cabeceras que devuelva el servidor)&lt;br /&gt;&lt;br /&gt;2-Ahora tenemos que programar el código que recupere y muestre los bytes de la imagen que se quiere escoger al azar. Para ello debemos coger las imagenes de google, pero ¿como?. Pues antes de mostrar nada de código, voy a explicar muy por encima como funciona la sección de imágenes de google:&lt;br /&gt;&lt;br /&gt;Voy a &lt;a target="_blank" href="http://images.google.es/"&gt;http://images.google.es/&lt;/a&gt; y pongo como busqueda &lt;em&gt;star wars&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Me salen 20 imágenes, y unos enlaces para ir avanzando en el catálogo de imágenes. Sin embargo los thumbnails que aparecen son todavía un poco grandes para la sección de la web, por lo que elijo la opción &lt;em&gt;Medianas&lt;/em&gt;, ahora pulsaremos por ejemplo sobre la página 3 del catálogo. Si os fijais a medida que he ido pulsando enlaces la url aparece con más datos:&lt;br /&gt;&lt;br /&gt;&lt;em&gt;http://images.google.es/images?q=star+wars&amp;imgsz=small%7Cmedium%7Clarge%7Cxlarge&amp;svnum=10&amp;hl=es&amp;lr=&amp;start=40&amp;sa=N&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Esto es lo que nos servirá como primer punto para la busqueda de imágenes relacionadas con un tema determinado. Si os fiajis en los parámetros de la url está la letra &lt;strong&gt;q&lt;/strong&gt;, donde se almacena el criterio de la búsqueda (en mi caso &lt;em&gt;star+wars&lt;/em&gt;); &lt;strong&gt;imgsz&lt;/strong&gt;, que indica el tamaño de las imágenes a buscar (puede ser también &lt;em&gt;xxlarge &lt;/em&gt;e &lt;em&gt;icon&lt;/em&gt;, aunque en mi caso es small%7Cmedium%7Clarge%7Cxlarge); &lt;strong&gt;svnum&lt;/strong&gt; que no se para que sirve, ya que si lo quito funciona igual; &lt;strong&gt;hl&lt;/strong&gt; para el idioma de los resultados; &lt;strong&gt;lr&lt;/strong&gt; que tampoco sé para que sirve, &lt;strong&gt;start&lt;/strong&gt; que indica desde que indice empezar, este es muy importante ya que aqui usaremos el primer número aleatorio; &lt;strong&gt;sa&lt;/strong&gt;=N que no se para que sirve.&lt;br /&gt;&lt;br /&gt;Como os comentaba, con &lt;strong&gt;start&lt;/strong&gt; se puede indicar desde que índice de las imágenes empezar a mostrar: 0 sería desde la primera página, 20 desde la segunda página, 40 desde la tercera, etc. También podemos poner valores intermedios, pero yo sigo el camino de google con sus enlaces.&lt;br /&gt;&lt;br /&gt;Una vez que ya podemos elegir que página de imágenes queremos cargar, ya solo queda elegir que imagen de las 20 que aparece en esa página mostrar, momento por el cual debemos usar el segundo número aleatorio. Pero claro, lo que nos interesa son las imágenes de google, no las originales a las que apunta el enlace de cada una de ellas. Por eso debemos recorrer el codigo fuente HTML de la página que hemos recuperado para ir etiqueta por etiqueta &lt;em&gt;IMG&lt;/em&gt; hasta alcanzar el número aleatorio que habiamos solicitado. Sin embargo no podemos empezar desde el principio puesto que google tiene en su página un logo, unas imagenes de 1 pixel de grosor, etc. Es por ello que debemos comenzar a partir de un punto donde sepamos que a continuación todas las etiquetas IMG son las de los thumbnails. En mi caso uso la cadena "&lt;em&gt;Solamente se muestran las&lt;/em&gt;". &lt;br /&gt;&lt;br /&gt;A partir de entónces, cuando ya obtengamos el atributo &lt;em&gt;src&lt;/em&gt; de la etiqueta &lt;em&gt;IMG&lt;/em&gt; requerida, ya podremos recuperar los bytes de la imagen thumbnail de google a través de su url. Posteriormente solo queda mostrarla a través del PHP.&lt;br /&gt;&lt;br /&gt;El siguiente código fuente muestra como lo hacer lo que he comentado anteriormente desde una página php:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&amp;lt;?&lt;br /&gt;// Hacemos que nunca se cachee ninguna imagen&lt;br /&gt;header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");&lt;br /&gt;header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");&lt;br /&gt;header("Cache-Control: no-store, no-cache, must-revalidate");&lt;br /&gt;header("Cache-Control: post-check=0, pre-check=0", false);&lt;br /&gt;header("Pragma: no-cache");&lt;br /&gt;&lt;br /&gt;//elegimos una sección al azar de las imagenes de google&lt;br /&gt;$texto="";&lt;br /&gt;mt_srand((double)microtime()*1000000);&lt;br /&gt;$inicio = mt_rand(0,20)*20;&lt;br /&gt;$url="http://images.google.es/images?q=star+wars&amp;imgsz=small%7Cmedium%7Clarge%7Cxlarge&amp;hl=es&amp;lr=&amp;start=$inicio&amp;sa=N";&lt;br /&gt;&lt;br /&gt;// abrimos la url generada dinamicamente&lt;br /&gt;$fichero=fopen($url,"r");&lt;br /&gt;while(!feof($fichero))&lt;br /&gt; $texto.=fread($fichero,1024);&lt;br /&gt;fclose($fichero);&lt;br /&gt;&lt;br /&gt;// dentro de la página devuelta, elegimos una imagen al azar&lt;br /&gt;$indice = mt_rand(1,20);&lt;br /&gt;// para ello debemos recorrer todas las etiquetas IMG desde una posición determinada&lt;br /&gt;$posicion=strpos($texto,"Solamente se muestran las");&lt;br /&gt;for($contador=0;$contador&lt;$indice;$contador++)&lt;br /&gt; $posicion=strpos($texto,"&amp;lt;img",$posicion)+4;&lt;br /&gt;$posicion=strpos($texto,"src=",$posicion);&lt;br /&gt;&lt;br /&gt;// cogemos la url de esa imagen de thumbnail de google&lt;br /&gt;$url="http://images.google.es" . substr($texto,$posicion+4,strpos($texto," ",$posicion)-$posicion-4);&lt;br /&gt;$texto="";&lt;br /&gt;&lt;br /&gt;// la abrimos para recuperar su contenido&lt;br /&gt;$fichero=fopen($url,"r");&lt;br /&gt;while(!feof($fichero))&lt;br /&gt; $texto.=fread($fichero,1024);&lt;br /&gt;fclose($fichero);&lt;br /&gt;&lt;br /&gt;// mostramos la cabecera acorde con el tipo de fichero&lt;br /&gt;switch(substr($url,strrpos($url,".")))&lt;br /&gt;{&lt;br /&gt; case ".gif":&lt;br /&gt;  header("Content-type: image/gif");&lt;br /&gt; break;&lt;br /&gt; case ".png":&lt;br /&gt;  header("Content-type: image/png");&lt;br /&gt; break;&lt;br /&gt; default:&lt;br /&gt;   header("Content-type: image/jpeg");&lt;br /&gt; break;&lt;br /&gt;}&lt;br /&gt;// y finalmente mostramos el contenido de la imágen recuperada&lt;br /&gt;echo $texto;&lt;br /&gt;?&amp;gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Podeis ver un ejemplo de su funcionamiento en la web que os indicaba arriba o directamente en este enlace &lt;a target="_blank" href="http://www.starwarsspanishstuff.info/aleatorio.php"&gt;http://www.starwarsspanishstuff.info/aleatorio.php&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Recomiendo poner en el texto alternativo un reconocimiento a google.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5416816-112601624931970193?l=sistemasorp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sistemasorp.blogspot.com/feeds/112601624931970193/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5416816&amp;postID=112601624931970193' title='5 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/112601624931970193'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/112601624931970193'/><link rel='alternate' type='text/html' href='http://sistemasorp.blogspot.com/2005/09/generar-imgenes-aleatorias-con-php-y.html' title='Generar imágenes aleatorias con php y google'/><author><name>sistemasorp</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5416816.post-112257020966764225</id><published>2005-07-28T18:04:00.000+02:00</published><updated>2005-07-29T08:08:16.680+02:00</updated><title type='text'>Ejecutar una variable</title><content type='html'>Tal como se lee puede parecer algo un tanto extraño. Todo el mundo que programa usa las variables para leer o introducir datos en ellas (aunque a veces lo que se esta haciendo por debajo es realmente llamar a una función). El caso es que el C, y por extensión el C++ (ignoro si el C# tiene esta caracteristica) puede crear punteros a funciones. Estos punteros, como el resto, son una variable que contiene una dirección de memoria; sin embargo, su uso normal es asignarle el nombre de una función en vez de una variable, tal que así:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;typedef unsigned int (*funcion)(const char *);&lt;br /&gt;funcion pepe;&lt;br /&gt;pepe=strlen;&lt;br /&gt;printf("Longitud de hola:%d\n",pepe("hola"));&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Pero que pasaría si en vez de asignarle una función le asignamos una variable? Pues&lt;br /&gt;que el contenido de esa variable lo ejecutaría. Por supuesto, la variable no puede tener cualquier contenido; los bytes que contendría deberían ser codigo maquina. Por ejemplo el siguiente código en ensamblador:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;MOV EAX,9&lt;br /&gt;RET&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;traducido a codigo máquina del intel x86 sería:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;B8 09 00 00 00&lt;br /&gt;C3&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Por lo que si ejecutamos las siguientes lineas:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;typedef unsigned int (*funcion)(void);&lt;br /&gt;funcion pepe;&lt;br /&gt;unsigned char juan[]={0xb8,9,0,0,0,0xc3};&lt;br /&gt;pepe=(unsigned int (*)(void))(void*)juan;&lt;br /&gt;printf("Es un 9?:%d\n",pepe());&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Lo que hemos hecho es llamar a una dirección de memoria que contenia una ristra de bytes, los cuales son significativos para el microprocesador. En el ejemplo hemos asignado al registro EAX (registro que almacena siempre lo que devuelve una función) el número 9 y a continuación ejecutamos un RET para retornar de la llamada de la función. Así hemos simulado una llamada a una función tal y como lo habría hecho el compilador, pudiendo incluso modificar el código (el contenido de la variable) en tiempo de ejecución sin problemas de violaciones de memoria o similares. Este código funciona tanto en Linux como en Windows siempre que sea un micro intel x86, aunque se puede usar en un motorola, power pc, o lo que querais siempre que conozcais el&lt;br /&gt;lenguaje maquina del micro.&lt;br /&gt;&lt;br /&gt;Este artículo dará pie a otro mucho más avanzado sobre como lograr que un programa original pueda acceder a un web service sin que otros se aprovechen de esa información (si usar contraseñas ni nada parecido).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5416816-112257020966764225?l=sistemasorp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sistemasorp.blogspot.com/feeds/112257020966764225/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5416816&amp;postID=112257020966764225' title='4 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/112257020966764225'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/112257020966764225'/><link rel='alternate' type='text/html' href='http://sistemasorp.blogspot.com/2005/07/ejecutar-una-variable.html' title='Ejecutar una variable'/><author><name>sistemasorp</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5416816.post-112067840814357862</id><published>2005-07-06T21:25:00.000+02:00</published><updated>2005-07-06T21:35:08.890+02:00</updated><title type='text'>Por fin nos libramos de las patentes de software</title><content type='html'>Después de haber luchado incansablemente por que las patentes de software no salgan adelante, después de &lt;a target="_blank" href="http://sistemasorp.blogspot.com/2004/05/las-patentes.html"&gt;haber explicado sus contras&lt;/a&gt;, después de habernos llevado grandes disgustos y pequeñas alegrías, por fín puedo decir que la propuesta de patentes de software en Europa ha sido &lt;a target="_blank" href="http://www.elmundo.es/navegante/2005/07/06/softlibre/1120638414.html"&gt;definitivamente derogada&lt;/a&gt; contundentemente por 648 votos a favor, 14 en contra y 18 abstenciones.&lt;br /&gt;&lt;br /&gt;¡¡¡ Estamos de Enhorabuena !!!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5416816-112067840814357862?l=sistemasorp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sistemasorp.blogspot.com/feeds/112067840814357862/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5416816&amp;postID=112067840814357862' title='1 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/112067840814357862'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/112067840814357862'/><link rel='alternate' type='text/html' href='http://sistemasorp.blogspot.com/2005/07/por-fin-nos-libramos-de-las-patentes.html' title='Por fin nos libramos de las patentes de software'/><author><name>sistemasorp</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5416816.post-111869086402873452</id><published>2005-06-13T20:07:00.000+02:00</published><updated>2006-12-05T13:21:28.590+01:00</updated><title type='text'>Wake On LAN y Magic Packet</title><content type='html'>Todos sabemos que podemos apagar el ordenador con un comando o bién con una combinación de pulsaciones de teclado o ratón, también hay programas que dado cierto evento hacen que se apague el sistema. &lt;br /&gt;&lt;br /&gt;Esto no tiene ningún misterio, pero... ¿y si se trata de encenderlo?. Puede que con el solo hecho de pulsar el botón de encendido de la cpu nos sea suficiente (a veces con pulsar un botón del teclado o mover el ratón), sin embargo cuando no estamos físicamente presentes la cosa cambia: un cibercafe donde es más cómodo encender todos los ordenadores a la vez, o encender un ordenador remoto que por las noches se apaga para ahorrar electricidad, etc. Antiguamente los ordenadores se apagaban y punto, pero desde que irrumpió en el mercado el formato &lt;a target="_blank" href="http://en.wikipedia.org/wiki/ATX"&gt;ATX&lt;/a&gt; de cajas y placas madre y con el estandar &lt;a target="_blank" href="http://en.wikipedia.org/wiki/Advanced_Configuration_and_Power_Interface"&gt;ACPI&lt;/a&gt; la cosa no ha hecho más que facilitarnos las cosas: ahora gracias a esos dos estandares somos capaces de apagar el ordenador por software, apagar el equipo ordenadamente por hardware, suspender, volver a reactivar, volver a encender, etc. En la parte que nos toca hay unos eventos que son capaces de encender un ordenador cuando este está apagado, y para la gestión remota de ese encendido se puede usar unos metodos denominados &lt;em&gt;wake on ring, wake on modem (por modem)&lt;/em&gt; o &lt;em&gt;wake on lan (por red)&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;Este artículo se centra en el método &lt;a target="_blank" href="http://en.wikipedia.org/wiki/Wake-on-LAN"&gt;Wake On Lan&lt;/a&gt; (+ o - despertar por red). Este sistema se basa en que un ordenador cuando se apaga, no lo hace totalmente, sino que la fuente de alimentación sigue alimentando a la placa madre, y esta puede gestionar con muy bajo consumo los eventos que se den, como por ejemplo, encender el ordenador cuando recibe un paquete especial por la tarjeta de red. Este paquete, conocido como &lt;em&gt;Magic Packet &lt;/em&gt;es muy simple y su formato consiste en 6 bytes con valor hexadecimal FF y otros 16 grupos de 6 bytes con la dirección &lt;a target="_blank" href="http://en.wikipedia.org/wiki/MAC_address"&gt;MAC&lt;/a&gt; de la tarjeta de red. Da igual en que protocolo se envié ese paquete (IPX, TCP/IP, etc), con tal de que se envíe por toda la red. Así si se quiere encender un ordenador con una MAC 01:02:03.04:05:06 se enviaría un paquete con estos bytes en hexadecimal:&lt;br /&gt;&lt;em&gt;&lt;br /&gt;FFFFFFFFFFFF&lt;br /&gt;010203040506010203040506010203040506010203040506&lt;br /&gt;010203040506010203040506010203040506010203040506&lt;br /&gt;010203040506010203040506010203040506010203040506&lt;br /&gt;010203040506010203040506010203040506010203040506&lt;br /&gt;&lt;/em&gt;&lt;br /&gt;El paquete debe enviarse a toda la red, por lo que hay que intentar que sea con el protocolo que se haga, este debe permitir enviar paquetes &lt;a target="_blank" href="http://en.wikipedia.org/wiki/Broadcast_address"&gt;broadcast&lt;/a&gt;. Esto normalmente se puede conseguir con el protocolo IP, ya que poniendo como destinatario la dirección IP 255.255.255.255 debería llegar a todos los nodos de todas las redes que lo permitan. El TCP o UDP que venga por encima no es importante, aunque personalmente prefiero el UDP por no ser orientado a conexión. Por encima del UDP vendrá el magic packet. A continuación pongo un ejemplo de codigo fuente en varios lenguajes de programación para que podais probarlo (son tan cortos que no hacen falta comentarlos, tampoco tienen gestión de errores para su simplicidad), en vuestro caso solo tendrías que modificar el puerto (1976) y la dirección MAC (01:02:03:04:05:06):&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;C para Linux/Unix y Windows&lt;/strong&gt;&lt;br /&gt;&lt;pre&gt;#ifdef WIN32&lt;br /&gt; #include &amp;lt;stdio.h&amp;gt;&lt;br /&gt; #include &amp;lt;winsock2.h&amp;gt;&lt;br /&gt;#else&lt;br /&gt;        #include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;        #include &amp;lt;sys/socket.h&amp;gt;&lt;br /&gt;        #include &amp;lt;netinet/in.h&amp;gt;&lt;br /&gt;#endif&lt;br /&gt;void main(void)&lt;br /&gt;{&lt;br /&gt; int conexion;&lt;br /&gt; struct sockaddr_in direccion;&lt;br /&gt; unsigned char buffer[102];&lt;br /&gt; unsigned char mac[]={0x01,0x02,0x03,0x04,0x5,0x06};&lt;br /&gt; int valor=1,contador;&lt;br /&gt;#ifdef WIN32&lt;br /&gt;    WSADATA wsaData;&lt;br /&gt;    WSAStartup( MAKEWORD( 2, 2 ), &amp;wsaData );&lt;br /&gt;#endif&lt;br /&gt; for(contador=0;contador&lt;6;contador++)&lt;br /&gt;  buffer[contador]=0xff;&lt;br /&gt; for(contador=6;contador&lt;102;contador+=6)&lt;br /&gt;  memmove(&amp;buffer[contador],mac,6);&lt;br /&gt; memset(direccion.sin_zero,0,8);&lt;br /&gt; direccion.sin_family=AF_INET;&lt;br /&gt; direccion.sin_addr.s_addr=htonl(INADDR_BROADCAST);&lt;br /&gt; direccion.sin_port=htons(1976);&lt;br /&gt; conexion=socket(AF_INET,SOCK_DGRAM,0);&lt;br /&gt; valor=setsockopt(conexion, SOL_SOCKET, SO_BROADCAST, (char *)&amp;valor, sizeof(int));&lt;br /&gt; sendto(conexion,(char *)buffer,102,0,(struct sockaddr *)&amp;direccion,sizeof(struct sockaddr_in));&lt;br /&gt;#ifdef WIN32&lt;br /&gt; WSACleanup();&lt;br /&gt;#endif&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;strong&gt;Perl&lt;/strong&gt;&lt;br /&gt;&lt;pre&gt;use strict;&lt;br /&gt;use IO::Socket::INET;&lt;br /&gt;&lt;br /&gt;my $socket;&lt;br /&gt;my $msg;&lt;br /&gt;my $contador;&lt;br /&gt;&lt;br /&gt;$socket=new IO::Socket::INET-&gt;new(PeerPort=&gt;1976,&lt;br /&gt;        Proto=&gt;'udp',&lt;br /&gt;        PeerAddr=&gt;'255.255.255.255',&lt;br /&gt;        Broadcast=&gt;1&lt;br /&gt;);&lt;br /&gt;$msg="";&lt;br /&gt;for($contador=0;$contador&lt;6;$contador++)&lt;br /&gt;{&lt;br /&gt;        $msg.="\xff";&lt;br /&gt;}&lt;br /&gt;for($contador=0;$contador&lt;16;$contador++)&lt;br /&gt;{&lt;br /&gt;        $msg.="\x01\x02\x03\x04\x05\x06";&lt;br /&gt;}&lt;br /&gt;$socket-&gt;send($msg);&lt;/pre&gt;&lt;br /&gt;&lt;strong&gt;Java&lt;/strong&gt;&lt;br /&gt;&lt;pre&gt;import java.net.*;&lt;br /&gt;import java.io.IOException;&lt;br /&gt;&lt;br /&gt;public class Wol&lt;br /&gt;{&lt;br /&gt; public static void main(String args[])&lt;br /&gt; {&lt;br /&gt;                byte mac[]={0x01,0x02,0x03,0x04,0x05,0x06};&lt;br /&gt;  byte buffer[]=new byte[102];&lt;br /&gt;  byte contador;&lt;br /&gt;  &lt;br /&gt;  for(contador=0;contador&lt;6;contador++)&lt;br /&gt;   buffer[contador]=(byte)0xff;&lt;br /&gt;  for(contador=6;contador&lt;102;contador+=6)&lt;br /&gt;   System.arraycopy(mac,0,buffer,contador,6);&lt;br /&gt;  try&lt;br /&gt;  {&lt;br /&gt;   DatagramSocket udp=new DatagramSocket();&lt;br /&gt;   udp.setBroadcast(true);&lt;br /&gt;   udp.send(new DatagramPacket(buffer,102,InetAddress.getByName("255.255.255.255"),1976));&lt;br /&gt;  }&lt;br /&gt;  catch(java.net.SocketException se)&lt;br /&gt;  {&lt;br /&gt;   System.err.println(se);&lt;br /&gt;  }&lt;br /&gt;  catch(java.net.UnknownHostException ue)&lt;br /&gt;  {&lt;br /&gt;   System.err.println(ue);&lt;br /&gt;  }&lt;br /&gt;  catch(java.io.IOException ie)&lt;br /&gt;  {&lt;br /&gt;   System.err.println(ie);&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;strong&gt;Visual Basic&lt;/strong&gt; (Para que funcione debeis insertar un control Winsock)&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Dim buffer() As Byte&lt;br /&gt;Dim contador As Byte&lt;br /&gt;&lt;br /&gt;ReDim buffer(101) As Byte&lt;br /&gt;For contador = 0 To 5&lt;br /&gt; buffer(contador) = &amp;HFF&lt;br /&gt;Next&lt;br /&gt;For contador = 6 To 101 Step 6&lt;br /&gt; buffer(contador) = &amp;H1&lt;br /&gt; buffer(contador + 1) = &amp;H2&lt;br /&gt; buffer(contador + 2) = &amp;H3&lt;br /&gt; buffer(contador + 3) = &amp;H4&lt;br /&gt; buffer(contador + 4) = &amp;H5&lt;br /&gt; buffer(contador + 5) = &amp;H6&lt;br /&gt;Next&lt;br /&gt;Winsock1.Protocol = sckUDPProtocol&lt;br /&gt;Winsock1.RemoteHost = "255.255.255.255"&lt;br /&gt;Winsock1.RemotePort = 1976&lt;br /&gt;Winsock1.SendData buffer&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;Por supuesto no hay método que sirva para marcar todas las tarjetas a la vez, así que habrá que ir una por una mandando el magic packet para que se vaya encendiendo cada ordenador. La tarjeta de red de cada ordenador apagado compara todos los paquetes que le llegan del tráfico de red para ver si contiene 16 veces su dirección MAC y así mandar a la placa madre que encienda el ordenador.&lt;br /&gt;&lt;br /&gt;Las tarjetas de red que vengan incorporadas ya de fábrica en la placa madre ya tienen esta función activada. Sin embargo las que estan sueltas en ranuras PCI o ISA, deben:&lt;br /&gt;1) Permitir el wake on lan (no todas tienen un firware con esa posibilidad)&lt;br /&gt;2) La placa madre debe tener un conector de 3 pines que permita este evento.&lt;br /&gt;3) Un cable que vaya desde la tarjeta hasta la placa madre.&lt;br /&gt;En ambos casos se debe activar en la BIOS el mantenimiento de energía y posteriormente el evento WAKE ON LAN.&lt;br /&gt;&lt;br /&gt;En mi portatil no puedo probar esta característica (cuando se apaga este, la tarjeta ethernet incorporada también se apaga). En el ordenador de sobremesa no me ha funcionado (tampoco funcionan eventos como el de encender el ordenador con una pulsación del teclado) y con el servidor me ha funcionado perfectamente.&lt;br /&gt;&lt;br /&gt;El Magic Packet también se puede hacer desde Internet:&lt;br /&gt;Si teneis conexión directa solo debeis modificar vuestro programa para que apunte a vuestra IP pública de Internet (si no es fija podeis usar cosas como &lt;a target="_blank" href="http://www.dyndns.org/"&gt;dyndns&lt;/a&gt;).&lt;br /&gt;Si no teneis conexión directa o no quereis usar un programa, podeis hacerlo desde &lt;a target="_blank" href="http://www.majoroak.f2s.com/tim/wol/html.php"&gt;aquí&lt;/a&gt;.&lt;br /&gt;Sin embargo, a no ser que tengais un router que este conectado a Internet y donde podais poner rutas estáticas con IP, puertos y direcciones MAC no podreis hacerlo funcionar, ya que el router (como el mio) borra de la tabla &lt;a target="_blank" href="http://en.wikipedia.org/wiki/Address_Resolution_Protocol"&gt;arp&lt;/a&gt; las relaciones MAC/IP cuando detecta que no hay tráfico en una tarjeta determinada, por lo que aunque reciba un paquete que luego deba reenviar a una ip interna, lo ignora al no encontrarlo en la tabla; tampoco tiene opción para redireccionarlo como broadcast dentro de la red si no sabe que hacer con el.&lt;strong&gt;&lt;/strong&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5416816-111869086402873452?l=sistemasorp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sistemasorp.blogspot.com/feeds/111869086402873452/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5416816&amp;postID=111869086402873452' title='14 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/111869086402873452'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/111869086402873452'/><link rel='alternate' type='text/html' href='http://sistemasorp.blogspot.com/2005/06/wake-on-lan-y-magic-packet.html' title='Wake On LAN y Magic Packet'/><author><name>sistemasorp</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>14</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5416816.post-111515789496532654</id><published>2005-05-03T23:04:00.000+02:00</published><updated>2005-05-11T18:44:41.456+02:00</updated><title type='text'>Ejecutar un programa sin sistema operativo</title><content type='html'>Todo pc ejecuta código máquina: Ya sea en el arranque (La &lt;a target="_blank" href="http://es.wikipedia.org/wiki/BIOS"&gt;bios&lt;/a&gt; no es más que código máquina), en la carga del sistema operativo (el &lt;a target="_blank" href="http://es.wikipedia.org/wiki/Kernel"&gt;kernel&lt;/a&gt; esta programado en su mayor parte en código maquina) y en la ejecución de programas (el código fuente compilado o interpretado se transforma de una u otra manera en código máquina). Esta forma de trabajar hace que realmente no sea necesario un sistema operativo para ejecutar aplicaciones (y si me lo poneis dificil, hasta tampoco haría falta la bios). Es por ello que hay aplicaciones como los gestores de arraque (lilo, grub, nt loader), virus, etc que no necesitan de un sistema operativo para funcionar.&lt;br /&gt;&lt;br /&gt;Siguiendo este camino, cualquiera podría crear una aplicación que, manteniendola y añadiendola nuevas funcionalidades, podría convertirse en el kernel que Linus Torvalds desarrolló de minix y que posteriormente se transformaría en linux.&lt;br /&gt;&lt;br /&gt;Mi intención esta lejos de desarrollar un sistema operativo propio... aún :-), sin embargo a continuación pongo una aplicación, que ejecutada desde un disquete nada más arrancar el pc, muestra un menú y realiza operaciones básicas (chorras). Necesitareis un disquete ya formateado, el programa debug del msdos (por defecto en todos los windows) y que como primera unidad de arranque del pc sea la disquetera (próximamente hablaremos de como pasarlo a un cd mediante el estandar "el torito"). Para los linuxeros de pc, próximamente pondré algo parecido al rawrite. Las instrucciones para hacerlo funcionar son las siguientes:&lt;br /&gt;&lt;br /&gt;1-cargad una consola msdos (en windows 9x: &lt;em&gt;inicio/ejecutar/command&lt;/em&gt;, en windows nt,2000 o xp: &lt;em&gt;inicio/ejecutar/cmd&lt;/em&gt;)&lt;br /&gt;&lt;br /&gt;2-Insertad un disquete ya formateado en la disquetera y que no tenga nada importante (ya que perdereis toda la información que contuviera)&lt;br /&gt;&lt;br /&gt;3-copiad el siguiente texto a un fichero de texto en vuestro disco duro (dejad al final un retorno de carro), por ejemplo &lt;em&gt;codigo.txt&lt;/em&gt;:&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;a&lt;br /&gt;jmp 1f7&lt;br /&gt;db 'Seleccione una opcion del menu'&lt;br /&gt;db '1- Mostrar hora'&lt;br /&gt;db '2- Coche Fantastico'&lt;br /&gt;db '3- Salir'&lt;br /&gt;db 'Desarrollado por Oscar Rodriguez Parra http://sistemasorp.blogspot.com'&lt;br /&gt;db '00:00:00'&lt;br /&gt;db 'Fijese en las luces del teclado'&lt;br /&gt;db 'Retire el disco o cd de la unidad de arranque y pulse una tecla'&lt;br /&gt;cli&lt;br /&gt;xor ax,ax&lt;br /&gt;mov ss,ax&lt;br /&gt;mov sp,7c00&lt;br /&gt;mov es,ax&lt;br /&gt;mov ds,ax&lt;br /&gt;sti&lt;br /&gt;mov ah,0&lt;br /&gt;mov dl,0&lt;br /&gt;int 13h&lt;br /&gt;mov ax,201&lt;br /&gt;mov bx,7e00&lt;br /&gt;mov cx,2&lt;br /&gt;xor dx,dx&lt;br /&gt;int 13h&lt;br /&gt;mov ax,3&lt;br /&gt;int 10h&lt;br /&gt;mov ax,1001&lt;br /&gt;mov bh,1&lt;br /&gt;int 10h&lt;br /&gt;mov ax,1300&lt;br /&gt;mov bx,2&lt;br /&gt;mov cx,1e&lt;br /&gt;mov dx,0119&lt;br /&gt;mov bp,7c03&lt;br /&gt;int 10h&lt;br /&gt;mov ax,1300&lt;br /&gt;mov bx,2&lt;br /&gt;mov cx,0f&lt;br /&gt;mov dx,0519&lt;br /&gt;mov bp,7c21&lt;br /&gt;int 10h&lt;br /&gt;mov ax,1300&lt;br /&gt;mov bx,2&lt;br /&gt;mov cx,13&lt;br /&gt;mov dx,0619&lt;br /&gt;mov bp,7c30&lt;br /&gt;int 10h&lt;br /&gt;mov ax,1300&lt;br /&gt;mov bx,2&lt;br /&gt;mov cx,8&lt;br /&gt;mov dx,0719&lt;br /&gt;mov bp,7c43&lt;br /&gt;int 10h&lt;br /&gt;mov ax,1300&lt;br /&gt;mov bx,4&lt;br /&gt;mov cx,46&lt;br /&gt;mov dx,1705&lt;br /&gt;mov bp,7c4b&lt;br /&gt;int 10h&lt;br /&gt;mov ah,0&lt;br /&gt;int 16h&lt;br /&gt;push ax&lt;br /&gt;mov ax,700&lt;br /&gt;mov bh,0&lt;br /&gt;mov cx,0900&lt;br /&gt;mov dx,094f&lt;br /&gt;int 10h&lt;br /&gt;pop ax&lt;br /&gt;cmp ah,2&lt;br /&gt;je 29f&lt;br /&gt;cmp ah,3&lt;br /&gt;je 2fd&lt;br /&gt;cmp ah,4&lt;br /&gt;jne 29d&lt;br /&gt;jmp 32f&lt;br /&gt;jmp 278&lt;br /&gt;mov ah,2&lt;br /&gt;int 1ah&lt;br /&gt;push cx&lt;br /&gt;mov bx,7c91&lt;br /&gt;mov al,ch&lt;br /&gt;mov cl,4&lt;br /&gt;shr al,cl&lt;br /&gt;add al,30&lt;br /&gt;mov [bx],al&lt;br /&gt;inc bx&lt;br /&gt;mov al,ch&lt;br /&gt;and al,0f&lt;br /&gt;add al,30&lt;br /&gt;mov [bx],al&lt;br /&gt;add bx,2&lt;br /&gt;pop cx&lt;br /&gt;mov ch,cl&lt;br /&gt;mov al,ch&lt;br /&gt;mov cl,4&lt;br /&gt;shr al,cl&lt;br /&gt;add al,30&lt;br /&gt;mov [bx],al&lt;br /&gt;inc bx&lt;br /&gt;mov al,ch&lt;br /&gt;and al,0f&lt;br /&gt;add al,30&lt;br /&gt;mov [bx],al&lt;br /&gt;add bx,2&lt;br /&gt;mov al,dh&lt;br /&gt;mov cl,4&lt;br /&gt;shr al,cl&lt;br /&gt;add al,30&lt;br /&gt;mov [bx],al&lt;br /&gt;inc bx&lt;br /&gt;mov al,dh&lt;br /&gt;and al,0f&lt;br /&gt;add al,30&lt;br /&gt;mov [bx],al&lt;br /&gt;mov ax,1300&lt;br /&gt;mov bx,7&lt;br /&gt;mov cx,8&lt;br /&gt;mov dx,0919&lt;br /&gt;mov bp,7c91&lt;br /&gt;int 10h&lt;br /&gt;jmp 278&lt;br /&gt;mov ax,1300&lt;br /&gt;mov bx,7&lt;br /&gt;mov cx,1f&lt;br /&gt;mov dx,0919&lt;br /&gt;mov bp,7c99&lt;br /&gt;int 10h&lt;br /&gt;mov cx,3&lt;br /&gt;mov ah,2&lt;br /&gt;call 346&lt;br /&gt;mov ah,4&lt;br /&gt;call 346&lt;br /&gt;mov ah,1&lt;br /&gt;call 346&lt;br /&gt;mov ah,4&lt;br /&gt;call 346&lt;br /&gt;loop 311&lt;br /&gt;mov ah,0&lt;br /&gt;call 346&lt;br /&gt;jmp 278&lt;br /&gt;mov ax,1300&lt;br /&gt;mov bx,7&lt;br /&gt;mov cx,3f&lt;br /&gt;mov dx,0908&lt;br /&gt;mov bp,7cb8&lt;br /&gt;int 10h&lt;br /&gt;mov ah,0&lt;br /&gt;int 16h&lt;br /&gt;int 19h&lt;br /&gt;push cx&lt;br /&gt;cli&lt;br /&gt;mov al,ed&lt;br /&gt;out 60,al&lt;br /&gt;in al,64&lt;br /&gt;test al,2&lt;br /&gt;loopnz 34c&lt;br /&gt;mov al,ah&lt;br /&gt;out 60,al&lt;br /&gt;sti&lt;br /&gt;mov ah,0&lt;br /&gt;int 1ah&lt;br /&gt;mov bx,dx&lt;br /&gt;add bx,9&lt;br /&gt;mov ah,0&lt;br /&gt;int 1ah&lt;br /&gt;cmp bx,dx&lt;br /&gt;jnz 360&lt;br /&gt;pop cx&lt;br /&gt;ret&lt;br /&gt;&lt;br /&gt;w 100 0 0 2&lt;br /&gt;q&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;4-Ejecutad el siguiente comando: &lt;em&gt;debug &amp;lt; codigo.txt&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;5-Reiniciad el ordenador con el disquete dentro&lt;br /&gt;&lt;br /&gt;Este proceso lo que hace es ejecutar tanto comandos del debug del msdos, como intrucciones en &lt;a target="_blank" href="http://es.wikipedia.org/wiki/Lenguaje_ensamblador"&gt;ensamblador&lt;/a&gt;. Con esto guardamos en el sector de arranque del disquete (no del disco duro) un programa que se ejecutará nada más reiniciar el ordenador, antes de que se cargue el sistema operativo. Este programa tiene un menú con 3 opciones:&lt;br /&gt;&lt;strong&gt;1- Mostrar hora:&lt;/strong&gt; Muestra la hora actual del sistema.&lt;br /&gt;&lt;strong&gt;2- Coche Fantastico:&lt;/strong&gt; Simula las luces del coche fantástico en los led del teclado&lt;br /&gt;&lt;strong&gt;3- Salir:&lt;/strong&gt; Sale del programa, cuando se retira el disquete carga el sector de arranque del disco duro.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.quejateportodo.com/blog/programa.jpg"&gt;&lt;br /&gt;&lt;br /&gt;Con este programa se muestra todo lo que que se puede necesitar de un pc: &lt;br /&gt;-interfaz con el usuario de entrada (teclado)&lt;br /&gt;-interfaz con el usuario de salida (monitor)&lt;br /&gt;-lectura de disco (lectura del resto del programa en otro sector)&lt;br /&gt;-gestión de memoria (las cadenas de texto y la pila)&lt;br /&gt;-gestión de dispositivos (luces de teclado)&lt;br /&gt;&lt;br /&gt;Las instrucciones del debug son:&lt;br /&gt;&lt;strong&gt;a:&lt;/strong&gt; introducir código en ensamblador.&lt;br /&gt;&lt;strong&gt;w 100 0 0 2:&lt;/strong&gt; escribir el programa en los primeros sectores de arranque del disquete desde la posicion de memoria 100.&lt;br /&gt;&lt;strong&gt;q:&lt;/strong&gt; salir del debug.&lt;br /&gt;&lt;br /&gt;No voy a explicar que hace cada cosa en el programa, sin embargo si alguien tiene dudas puede preguntarme que significa cualquier parte del código en ensamblador. A grosso modo usa las funciones de la bios para poder funcionar: la interrupción 10h la uso para mostrar cadenas, la interrupción 13h para leer un segundo sector del disquete, la interrupción 16h para leer caracteres pulsados del teclado, la interrupción 19h para reiniciar el sistema sin tener que testearlo todo de nuevo, la interrupción 1ah para hacer retardos y averiguar la hora del sistema. Escribo en el puerto 60 para modificar el estado de los leds del teclado. Su arquitectura se basa en la peculiaridad de la bios de guardar nada más arrancar el primer sector del disquete en la zona de memoria 0000:7C00 y luego enviar la ejecución a ese punto.&lt;br /&gt;&lt;br /&gt;El hecho de haber usado la herramienta debug es porque lo tiene todo el mundo en su windows. Sin embargo no esta orientada a usarse para programar sectores de arranque, más bién para editarlos, editar ficheros o crear ficheros ejecutables con extensión .COM; por este último motivo he tenido que ir jugando con los saltos relativos a pelo, es decir, como los programas en debug empiezan en el desplazamiento 100h de la memoria (típico de los ficheros .COM) he estado poniendo los destinos de los saltos en base a esa posición 100h, por lo que cuando he necesitado modificar una instrucción, he tenido que cambiarlos también. Por suerte al ser saltos relativos (e internamente el debug los convierte así) no influye en el resultado final.&lt;br /&gt;&lt;br /&gt;Por último si teneis curiosidad por el mundo del pc y sus interioridades, saber como es el proceso de arranque del pc, cambiar las luces del teclado y muchísimo más, teneis el maravilloso y gratuito libro &lt;a target="_blank" href="http://www.gui.uva.es/udigital/"&gt;EL UNIVERSO DIGITAL  DEL IBM PC, AT Y PS/2&lt;/a&gt; de Ciriaco García de Celis, el cual explica con mucho detalle las tripas de los pcs.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5416816-111515789496532654?l=sistemasorp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sistemasorp.blogspot.com/feeds/111515789496532654/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5416816&amp;postID=111515789496532654' title='68 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/111515789496532654'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/111515789496532654'/><link rel='alternate' type='text/html' href='http://sistemasorp.blogspot.com/2005/05/ejecutar-un-programa-sin-sistema.html' title='Ejecutar un programa sin sistema operativo'/><author><name>sistemasorp</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>68</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5416816.post-111347254481860483</id><published>2005-04-14T10:45:00.000+02:00</published><updated>2005-04-14T12:01:06.633+02:00</updated><title type='text'>Gateway SMS/EMAIL/SMS</title><content type='html'>Bueno, pues hoy voy a enseñar un pequeño proyecto el cual ya hace tiempo que había terminado, pero que hoy doy a la luz pública (en fase beta) para que lo probeis a ver que os parece.&lt;br /&gt;&lt;br /&gt;La idea de hacer un gateway sms2email y email2sms &lt;a href="http://sistemasorp.blogspot.com/2004/07/futuro-proyecto.html" target="_blank"&gt;hacía tiempo que me rondaba la cabeza&lt;/a&gt;. Mi idéa era hacerlo bajo linux, ya que es el mejor sistema operativo que puede hacer de servidor y para este caso en concreto necesitaba un servidor POP3 y SMTP. Segundo necesitaba un aparato que enviase y recibiese sms, por lo que aproveché mi antiguo Siemens M35 y un cable de datos que ya tenía anteriormente para que hiciese las veces de servidor sms. Tercero necesitaba el software que gestionase los sms y los correos, por lo que para el primer caso usé la estupenda herramienta &lt;a href="http://smstools.meinemullemaus.de/" target="_blank"&gt;SMS server tools&lt;/a&gt; cuyo funcionamiento se reduce a guardar en un directorio un archivo con formato por cada sms nuevo del móvil, y enviar un sms por cada archivo con formato que encuentre en otro directorio; para el segundo caso he usado el perl con las librerias Net::POP3, Net::SMTP, MIME::Parser, MIME::Entity y MIME::Body.&lt;br /&gt;&lt;br /&gt;El resultado final es el siguiente que os explico:&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Para enviar un correo y que se transforme en sms:&lt;/strong&gt;&lt;br /&gt;-En el destinatario del correo poneis &lt;a href="mailto:sms@sistemasorp.com"&gt;sms@sistemasorp.com&lt;/a&gt;&lt;br /&gt;-En el asunto del correo poneis &lt;strong&gt;SOLO&lt;/strong&gt; el número de teléfono con prefijo 34 o sin el (no acepta mensajes a móviles que no sean de España).&lt;br /&gt;-En la primera línea del mensaje poneis el texto que querais siendo menor de 140 carácteres.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Para enviar un sms y que se transforme en mail:&lt;/strong&gt;&lt;br /&gt;-Poner la dirección de correo electrónico seguido de un espacio y el texto del mensaje.&lt;br /&gt;-Enviadlo al número de móvil 699744630. Esto os costará lo que vuestro proveedor de telefonía móvil os cobre por un sms normal y corriente (normalmente 15 céntimos de euro).&lt;br /&gt;&lt;br /&gt;En el caso de que sea mi sistema el que envíe el sms después de recibir un correo, me costará 15 céntimos de euro, aunque como estoy probando el sistema y el sim que tengo es de los que tienen dinero aún acumulado por la promoción de compra de un nuevo móvil, no me importa que se gaste. Más adelante lo pondré con contraseña para que solo yo o la gente que decida puedan usarlo.&lt;br /&gt;&lt;br /&gt;El código fuente en perl no esta aún comentado, aunque si quereis una copia, podeis pedirmela sin problemas.&lt;br /&gt;&lt;br /&gt;Los mensajes sms pueden recibirse o enviarse inmediatamente, tardiamente o nunca, eso ya depende de los proveedores de telecomunicaciones, de vuestro servidor de smtp tenga la última ip de mi dominioa través del DNS que use, etc.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5416816-111347254481860483?l=sistemasorp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sistemasorp.blogspot.com/feeds/111347254481860483/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5416816&amp;postID=111347254481860483' title='21 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/111347254481860483'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/111347254481860483'/><link rel='alternate' type='text/html' href='http://sistemasorp.blogspot.com/2005/04/gateway-smsemailsms.html' title='Gateway SMS/EMAIL/SMS'/><author><name>sistemasorp</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>21</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5416816.post-111306737825548170</id><published>2005-04-09T18:30:00.000+02:00</published><updated>2005-04-09T19:22:58.260+02:00</updated><title type='text'>Comprimir la salida de un php</title><content type='html'>Cuando hacemos una página en php, normalmente la solemos hacer para que muestre contenido de texto ya formateado (en html si es para un navegador, en xml si es para un servicio web, etc). Cuando digo formateado me refiero a que no solo contiene contenido textual, sino que también contiene etiquetas de formato, etiquetas pertenecientes al tipo de documento, comentarios, códigos, etc. Esto al final provoca que haya mucha saturación en cuanto a contenido, o dicho de otra forma, se envían muchos bytes.&lt;br /&gt;&lt;br /&gt;El problema radica en que por un lado se esta gastando un ancho de banda que pudiera servir para otras cosas (como es el caso de los hosting, donde tiene un limite de transferencia mensual) y al mismo tiempo provoca que se tarde más tiempo en descargar esa información (especialmente si estamos hablando de modems).&lt;br /&gt;&lt;br /&gt;La solución pasa por comprimir la salida del php y que el navegador del cliente se encargue de descomprimirla. Para ello hace ya tiempo que se &lt;a target="_blank" href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html"&gt;añadió al estardar HTTP 1.1&lt;/a&gt; la cabecera Accept-Enconding. Esta cabecera es enviada por el navegador al servidor web y contiene una lista de métodos de codificación de contenido que el navegador puede tratar. En el caso del Firefox o del Internet Explorer esta lista es gzip y deflate. El gzip es el método que nos interesa, ya que con el, se comprime la salida. Así que si el navegador pide al servidor un página php (y esta permite comprimirla como veremos a continuación), el documento que el servidor entrega al navegador estará comprimido (con una cabecera a su vez denominada Content-Encoding), con el consecuente ahorro de tiempo de transferencia y cantidad de datos a transmitir. Teniendo en cuenta que casi siempre suele ser texto lo que se envía, la compresión se hace mucho mejor, ya que se repite mayor cantidad de carácteres.&lt;br /&gt;&lt;br /&gt;Ejemplo de petición del navegador Firefox:&lt;br /&gt;&lt;em&gt;GET /divisas/divisas.php HTTP/1.1&lt;br /&gt;Host: www.quejateportodo.com&lt;br /&gt;User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; es-AR; rv:1.7.5) Gecko/20041108 Firefox/1.0&lt;br /&gt;Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5&lt;br /&gt;Accept-Language: es-ar,es;q=0.8,en-us;q=0.5,en;q=0.3&lt;br /&gt;Accept-Encoding: gzip,deflate&lt;br /&gt;Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7&lt;br /&gt;Keep-Alive: 300&lt;br /&gt;Connection: keep-alive&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Ejemplo de petición del navegador Internet Explorer:&lt;br /&gt;&lt;em&gt;GET /divisas/divisas.php?idioma=es&amp;fecha=09/04/2005&amp;version=201&amp;codigo=21988 HTTP/1.1&lt;br /&gt;Accept: */*&lt;br /&gt;Accept-Encoding: gzip, deflate&lt;br /&gt;User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)&lt;br /&gt;Host: www.quejateportodo.com&lt;br /&gt;Connection: Keep-Alive&lt;br /&gt;Cookie: PHPSESSID=09b4f65e7adf47e857a309d5a9ef83e3&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;A lo que en mi caso el servidor devuelve esta respuesta similar en ambos casos:&lt;br /&gt;&lt;br /&gt;&lt;em&gt;HTTP/1.1 200 OK&lt;br /&gt;Date: Sat, 09 Apr 2005 16:49:14 GMT&lt;br /&gt;Server: Apache/1.3.33 (Unix) mod_gzip/1.3.26.1a mod_auth_passthrough/1.8 mod_log_bytes/1.2 mod_bwlimited/1.4 PHP/4.3.10 FrontPage/5.0.2.2635 mod_ssl/2.8.22 OpenSSL/0.9.7a&lt;br /&gt;X-Powered-By: PHP/4.3.10&lt;br /&gt;Expires: Mon, 26 Jul 1997 05:00:00 GMT&lt;br /&gt;Cache-Control: no-store, no-cache, must-revalidate&lt;br /&gt;Pragma: no-cache&lt;br /&gt;Last-Modified: Sat, 09 Apr 2005 16:49:14 GMT&lt;br /&gt;Cache-Control: post-check=0, pre-check=0&lt;br /&gt;Content-Encoding: gzip&lt;br /&gt;Vary: Accept-Encoding&lt;br /&gt;Content-Type: text/xml&lt;br /&gt;Age: 496&lt;br /&gt;Connection: close&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Y después de tanta teoría, la práctica:&lt;br /&gt;&lt;br /&gt;&lt;em&gt;&amp;lt;?&lt;br /&gt;ob_start("ob_gzhandler"); &lt;br /&gt;&lt;br /&gt;... Aquí se mete toda la lógica del php ...&lt;br /&gt;&lt;br /&gt;ob_end_flush(); &lt;br /&gt;?&amp;gt;&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;¿A que resulta muy curioso que sea tán extremadamente sencillo el hacerlo?. Primero ponemos al principio del todo de la página php la instrucción &lt;a target="_blank" href="http://es.php.net/manual/es/function.ob-start.php"&gt;ob_start&lt;/a&gt; del php, que sirve para activar el modo "buffering", que no es otra cosa que primero genera la página y luego la envia en vez de irla enviando a medida que se va generando. Hay que pasarle el parámetro  de texto ob_gzhandler para que al final comprima todo lo que tiene en el buffer antes de enviarlo. Finalmente ponemos &lt;a target="_blank" href="http://es.php.net/manual/es/function.ob-end-flush.php"&gt;ob_end_flush&lt;/a&gt; al final del todo de la página php, que sirve para cerrar el buffer y enviarlo todo.&lt;br /&gt;&lt;br /&gt;Y para terminar, solo deciros que lo useis, ya que os supondrá un ahorro bastante efectivo. Si quereis comprobar si lo teneis instalado en vuestro servidor, buscad las librerias zlib, zend y la variable output_buffering a 1 en un &lt;a target="_blank" href="http://es.php.net/manual/es/function.phpinfo.php"&gt;phpinfo&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5416816-111306737825548170?l=sistemasorp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sistemasorp.blogspot.com/feeds/111306737825548170/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5416816&amp;postID=111306737825548170' title='4 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/111306737825548170'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/111306737825548170'/><link rel='alternate' type='text/html' href='http://sistemasorp.blogspot.com/2005/04/comprimir-la-salida-de-un-php.html' title='Comprimir la salida de un php'/><author><name>sistemasorp</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5416816.post-111216751704737441</id><published>2005-03-30T09:19:00.000+02:00</published><updated>2005-03-30T09:40:12.086+02:00</updated><title type='text'>Detección de movimiento con una webcam</title><content type='html'>En este proyecto mi intención no es otra que hacer un sistema de detección de movimiento (que no de reconocimiento de objetos). &lt;br /&gt;&lt;br /&gt;Detectar movimiento no es una cosa sencilla como pueda parecer a priori, ya que la imágen que pueda dar una camara (en este caso un webcam) no es de una calidad suficiente como para que dos imágenes tomadas en distintos momentos puedan considerarse iguales. Esto es debido a que las cámaras suelen introducir ruido en las imágenes que captan, o dicho de otra forma, un pixel de una posición determinada de la imágen nº1 no suele coincidir casi nunca (por no decir nunca) con un pixel de la misma posición de la imágen nº2 (aún siendo estas tomadas con una diferencia de milisegundos). Es por ello que hay que pensar que nivel de tolerancia hay que permitir para que aunque las imágenes no sean iguales exactamente, la información que contienen si sea similar en gran medida; sin detrimentro por supuesto de que si hay algún movimiento de un objeto o de un ser vivo sea tomado como informaciones distintas y provoque un evento o acción.&lt;br /&gt;&lt;br /&gt;Existen varias formas de trabajar con esta tolerancia: algoritmos de detección de bordes (gradientes, derivadas gausianas, transformada de Hough, etc), filtrados descriptores de Fourier, clasificador Bayesiano, etc), etc. Todos ellos sirven, pero no son iguales de rápidos. Es por ello que me decanté por el metodo estadístico de hacer medias de pixeles con los de su alrededor, un metodo sencillo para fijar una tolerancia en escaso tiempo (aunque quizá con un poco de penalización en cuanto a acierto en detección).&lt;br /&gt;&lt;br /&gt;El método consiste en tomar cada pixel de la imágen nº1 y sumar su valor con los 8 pixeles que le rodean (una matriz de 3x3) y luego dividir el resultado por 9, por lo que nos da un valor medio. El mismo proceso lo hacemos con los mismo pixeles pero de la segunda imágen, y así obtenemos otro valor medio. Al compararlos podemos detectar cuanto % de diferencia hay entre uno y otro, momento por el cual, gracias a que hemos configurado que nivel de sensibilidad en la diferencia,  o se admite como que no es un valor a tomar en cuenta, o sin embargo el valor es distinto y por lo tanto se toma en cuenta. Si se sobrepasa una cantidad determinada de pixeles que se toman en cuenta (sensibilidad por puntos), entónces es que las imágenes no son completamente iguales en cuanto a información y se supone que se ha producido un movimiento (cambio de posicion de entidades en la imágen o aparación de otras nuevas). La idea es que se tome una imágen de referencia (una del entorno estático), y se comparen las restantes con ella, para poder así saber con respecto al origen si ha habido algún cambio. Más tarde se toma otra imagen de referencia eliminando así los problemas que pudieran causar otros agentes (como un cambio atenuado de luz por el sol).&lt;br /&gt;&lt;br /&gt;&lt;img alt="Media de pixeles" src="http://www.quejateportodo.com/blog/ilustracionpixeles.jpg"&gt;&lt;br /&gt;&lt;br /&gt;Siguiendo esta idea, he desarrollado una aplicación en visual c++ 6.0 llamada DETECTOR donde he aplicado los conceptos anteriormente citados. Podeis descargar el ejecutable y/o su código fuente en esta dirección (esta bajo licencia creative commons): &lt;a target="_blank" href="http://www.quejateportodo.com/detemovi"&gt;http://www.quejateportodo.com/detemovi&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5416816-111216751704737441?l=sistemasorp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sistemasorp.blogspot.com/feeds/111216751704737441/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5416816&amp;postID=111216751704737441' title='18 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/111216751704737441'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/111216751704737441'/><link rel='alternate' type='text/html' href='http://sistemasorp.blogspot.com/2005/03/deteccin-de-movimiento-con-una-webcam.html' title='Detección de movimiento con una webcam'/><author><name>sistemasorp</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>18</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5416816.post-111158304711520681</id><published>2005-03-23T13:33:00.000+01:00</published><updated>2005-03-25T09:36:04.466+01:00</updated><title type='text'>Otro sistema más para combatir el antispam</title><content type='html'>Hace ya tiempo que le estuve dando vueltas a como combatir el spam de una vez por todas...&lt;br /&gt;&lt;br /&gt;Es de sobra conocido que los filtros anti-spam tienen dos defectos, por un lado filtran muchas veces correos spam como legítimos, y viceversa, correos que estamos esperando no los recibimos porque el filtro los considera spam.&lt;br /&gt;&lt;br /&gt;La solución de tener listas negras de ips (los dominios no sirven porque los spammers &lt;A target="_blank" href="http://sistemasorp.blogspot.com/2004/06/envio-de-mails-con-cualquier-remitente.html"&gt;pueden poner el que quieran como remitente&lt;/A&gt;) no es en absoluto fiable, ya que por ejemplo un usuario puede enviar spam desde una linea adsl (ya sea conscientemente o sin saber que esta infectado por un troyando o virus) y al ser ip dinámica, otro usuario que la tome posteriormente no podrá enviar emails; o aún peor, meter a todo un rango de ips en una lista negra (&lt;A target="_blank" href="http://barrapunto.com/article.pl?sid=04/04/26/0734200"&gt;como pasó con telefonica&lt;/A&gt;) y fastidiando a todos los usuarios de ese ISP que quieran enviar emails.&lt;br /&gt;&lt;br /&gt;El sistema que hace google (y desarrollado por yahoo) de firmar los emails esta bién, pero aún no esta implantado masivamente y tardará aún mucho que todos los programas servidores y clientes de SMTP lo implanten (y peor aún cuando Microsoft no lo tome como estandar y se invente el suyo propio).&lt;br /&gt;&lt;br /&gt;Mi solución, a falta de cubrir ciertos aspectos técnicos se presenta en el siguiente diagrama:&lt;br /&gt;&lt;IMG src="http://www.quejateportodo.com/blog/antispam.JPG"&gt;&lt;br /&gt;&lt;br /&gt;Básicamente consiste en pedir confirmación de los emails a su remitente antes de tomarlos como buenos en futuras ocasiones. Faltarían detalles como listas de correos o publicidad requerida, pero este sistema funcionaría con la tecnología actual y funcionaría como puente entre el servidor POP3 y el cliente de correo.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5416816-111158304711520681?l=sistemasorp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sistemasorp.blogspot.com/feeds/111158304711520681/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5416816&amp;postID=111158304711520681' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/111158304711520681'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/111158304711520681'/><link rel='alternate' type='text/html' href='http://sistemasorp.blogspot.com/2005/03/otro-sistema-ms-para-combatir-el.html' title='Otro sistema más para combatir el antispam'/><author><name>sistemasorp</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5416816.post-110590578862418905</id><published>2005-01-16T20:57:00.000+01:00</published><updated>2005-01-16T21:04:51.890+01:00</updated><title type='text'>¿Buscas un código fuente?</title><content type='html'>Pues en &lt;a target="_blank" href="http://www.koders.com"&gt;www.koders.com&lt;/a&gt; seguramente encuentres algo parecido a lo que estés buscando. Se trata de un buscador de código fuente donde como criterios de busqueda puedes filtrar por lenguaje de programación o licencia de uso del mismo. La única pega es que para encontrar lo que andabas buscando tengas que leer un chorro de codigo de otra persona que tenga una forma curiosa (horrible) de hacer las cosas, cosa por la cual ya he tenido que pasar en algún que otro trabajo donde he estado :).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5416816-110590578862418905?l=sistemasorp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sistemasorp.blogspot.com/feeds/110590578862418905/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5416816&amp;postID=110590578862418905' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/110590578862418905'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/110590578862418905'/><link rel='alternate' type='text/html' href='http://sistemasorp.blogspot.com/2005/01/buscas-un-cdigo-fuente.html' title='¿Buscas un código fuente?'/><author><name>sistemasorp</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5416816.post-110356054853488066</id><published>2004-12-20T16:45:00.000+01:00</published><updated>2004-12-20T21:18:12.380+01:00</updated><title type='text'>Configurar Linux como Router</title><content type='html'>Recientemente he adquirido un &lt;a target="_blank" href="http://www.compaq.es/accesorios/serie.asp?product_line_id=727"&gt;ordenador&lt;/a&gt; de 2º mano en mi empresa. La utilidad que le voy a dar es la de tener un ordenador en la casa donde voy de veraneo en Cercedilla. Pero claro, durante estos días lo he estado configurando y metiendole todos los programas necesarios y los que preveía que tarde o temprano usaré. Con este ya suman 4 los ordenadores que tengo, a saber:&lt;br /&gt;&lt;br /&gt;Servidor: VIA EPIA 800, 128 MB RAM, linux&lt;br /&gt;Uso diario: AMD XP, 2.4 Ghz., 512 MB RAM, 280 GB HD, linux, windows xp&lt;br /&gt;Portatil: AMD XP Mobile, 2.4 Ghz, 512 MB RAM, 40 GB HD, windows xp&lt;br /&gt;Nueva adquisición: Pentium IV 2.4 Ghz, 768 MB RAM, 20 GB HD, windows xp&lt;br /&gt;&lt;br /&gt;Pues con estos equipos el otro día se me ocurrió hacer dos redes, una del tipo 192.168.0.0/24 y otra del tipo 10.0.0.0/8 que estuviesen unidas al nuevo equipo, actuando este como router. En la red 192* tenía el ordenador de uso diario y el router ADSL, y en la red 10* tenía al portatil. Mi intención era que todos los ordenadores se vieran entre si y también tuviesen acceso a Internet. El ordenador nuevo tenía dos tarjetas y corría el linux knoppix. Una tarjeta tenía la ip 10.0.0.254 y la otra tenía la ip 192.168.0.4. En linux ambas se configuran así a través de la shell o linea de comandos:&lt;br /&gt;&lt;br /&gt;ifconfig eth0 192.168.0.4 netmask 255.255.255.0 up&lt;br /&gt;ifconfig eth1 10.0.0.254 netmask 255.0.0.0 up&lt;br /&gt;&lt;br /&gt;En este ordenador, la puerta de enlace o gateway estaba configurado para 192.168.0.254, o lo que es lo mismo, la ip que tiene mi router ADSL:&lt;br /&gt;&lt;br /&gt;route add default gw 192.168.0.254&lt;br /&gt;&lt;br /&gt;El portatil y el ordenador de uso diario ejecutaban windows xp y tenian como ip 10.0.0.1 y 192.168.0.1 respectivamente. El portatil estaba conectado a un switch (con puerta de enlace 10.0.0.254) al igual que una de las tarjetas del ordenador nuevo; el ordenador de uso diario estaba conectado al router ADSL (como es un hub al fin y al cabo; con puerta de enlace 192.168.0.254) al igual que la otra tarjeta del ordenador nuevo.&lt;br /&gt;&lt;br /&gt;Una vez ya todo conectado puse en el linux del ordenador nuevo esta sentencia desde la shell:&lt;br /&gt;&lt;br /&gt;echo "1" &gt; /proc/sys/net/ipv4/ip_forwarding &lt;br /&gt;&lt;br /&gt;que permitia reenviar los paquetes tcp/ip por las redes que tenia acceso este ordenador (se puede ver poniendo un simple &lt;em&gt;route&lt;/em&gt; en linux)&lt;br /&gt;&lt;br /&gt;Pero hay triste de mi que los ordenadores host no se veian entre ellos, ya que haciendo ping de uno a otro no se veian, sin embargo si veian al ordenador nuevo, aunque curiosamente si veían al router y también podían navegar por Internet (en ambos estaban puestas ya las DNS correctas), por lo que pensé que algo había hecho mal. Asi que pensando, pensando, cambié la puerta de enlace del ordenador de uso diario que estaba como he comentado antes a 192.168.0.254 a 192.168.0.4 y ¡¡¡ voila !!! ya se veían entre ellos. Había creado dos redes con casi nada de esfuerzo. Luego ya me entretuve con el iptables para configurar accesos desde el shell como:&lt;br /&gt;&lt;br /&gt;iptables -A FORWARDING -p tcp --destination-port 80 -j DROP&lt;br /&gt;&lt;br /&gt;que no permite el paso de paquetes por el puerto http o &lt;br /&gt;&lt;br /&gt;iptables -A FORWARDING -s 192.168.0.0/24 -d 10.0.0.0/8 -j DROP&lt;br /&gt;&lt;br /&gt;que no permite el flujo de daots entre una red y otra.&lt;br /&gt;&lt;br /&gt;El dibujo de la red sería tal que así:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.quejateportodo.com/blog/red.gif"&gt;&lt;br /&gt;&lt;br /&gt;y muestra como aunque el ordenador de uso diario y el router ADSL estan en la misma red, los paquetes entre uno y otro deben pasar por el ordenador nuevo.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5416816-110356054853488066?l=sistemasorp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sistemasorp.blogspot.com/feeds/110356054853488066/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5416816&amp;postID=110356054853488066' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/110356054853488066'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/110356054853488066'/><link rel='alternate' type='text/html' href='http://sistemasorp.blogspot.com/2004/12/configurar-linux-como-router.html' title='Configurar Linux como Router'/><author><name>sistemasorp</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5416816.post-110173105828210657</id><published>2004-11-29T13:15:00.000+01:00</published><updated>2005-02-07T21:52:34.826+01:00</updated><title type='text'>Transparencias con Windows y GDI en Visual Basic</title><content type='html'>En el trabajo me surgió la problematica de hacer que una imágen tenga un grado de transparencia sobre otra. Esto, aunque parezca una trivialidad, no lo es puesto que aunque la solución original es generar una mascara para hacer la transparencia, el permitir que existan varios grados lo complica un poco. Sin embargo al final he conseguido compactarlo todo en un procedimiento para que pasandole como parametros el dispositivo de contexto de origen, el dispositivo de contexto de destino (y donde se almacenará el resultado de la transparencia), las dimensiones de la imagen (en mi caso suelo poner las dimensiones en pixeles del picturebox) y el grado porcentual de transparencia, se genera de un modo casi inmediato el efecto deseado. Aqui os dejo el código:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;' AUTOR: Oscar Rodríguez&lt;br /&gt;' NOMBRE: Transparenta&lt;br /&gt;' FUNCIONAMINETO: Esta función permite fusionar una imágen de frente con otra de fondo&lt;br /&gt;' dado un grado de transparencia&lt;br /&gt;' PARÁMETROS:&lt;br /&gt;' -OrigenDC: Dispositivo de Contexto de la imágen de frente&lt;br /&gt;' -DestinoDC: Dispositivo de Contexto de la imágen de fondo y resultado de la operación&lt;br /&gt;' -Anchura: Anchura de las imágenes&lt;br /&gt;' -Altura: Altura de las imágenes&lt;br /&gt;' -Transparencia: Grado de transparencia medida en %&lt;br /&gt;Public Sub Transparenta(ByVal OrigenDC As Long, ByVal DestinoDC As Long, ByVal Anchura As Long, ByVal Altura As Long, ByVal Transparencia As Byte)&lt;br /&gt;    Dim bitmap_info As BITMAPINFO&lt;br /&gt;    Dim indice As Long, tamano As Long&lt;br /&gt;    Dim pixels() As Byte&lt;br /&gt;    Dim TemporalDC As Long, TemporalDC2 As Long, MascaraDC As Long&lt;br /&gt;    Dim BitMap As Long, AntiguoBitMap As Long, BitMap2 As Long&lt;br /&gt;    Dim AntiguoBitMap2 As Long, MascaraBitMap As Long, AntiguoMascaraBitMap As Long&lt;br /&gt;    Dim recta As RECT&lt;br /&gt;    Dim brocha As Long&lt;br /&gt;    &lt;br /&gt;    ' Creamos el DC y bitmap de la mascara&lt;br /&gt;    MascaraDC = CreateCompatibleDC(OrigenDC)&lt;br /&gt;    MascaraBitMap = CreateCompatibleBitmap(OrigenDC, Anchura, Altura)&lt;br /&gt;    AntiguoMascaraBitMap = SelectObject(MascaraDC, MascaraBitMap)&lt;br /&gt;    ' Copiamos la imágen de frente a la mascara&lt;br /&gt;    BitBlt MascaraDC, 0, 0, Anchura, Altura, OrigenDC, 0, 0, SRCCOPY&lt;br /&gt;    &lt;br /&gt;    ' Establecemos las propiedades de la cabecera bitmap&lt;br /&gt;    With bitmap_info.bmiHeader&lt;br /&gt;        .biSize = 40&lt;br /&gt;        .biWidth = Anchura&lt;br /&gt;        .biHeight = Altura&lt;br /&gt;        .biPlanes = 1&lt;br /&gt;        .biBitCount = 32&lt;br /&gt;        .biCompression = BI_RGB&lt;br /&gt;    End With&lt;br /&gt;    ' Creamos el buffer donde almacenaremos los bytes de la imágen de la mascara&lt;br /&gt;    tamano = 4 * Anchura * Altura&lt;br /&gt;    ReDim pixels(tamano) As Byte&lt;br /&gt;    ' Guardamos en el buffer los bytes de la imágen de la mascara&lt;br /&gt;    GetDIBits MascaraDC, MascaraBitMap, _&lt;br /&gt;        0, Altura, pixels(0), _&lt;br /&gt;        bitmap_info, DIB_RGB_COLORS&lt;br /&gt;&lt;br /&gt;    ' Calculamos la transparencia según el % que nos han pasado&lt;br /&gt;    Transparencia = Transparencia * 255 / 100&lt;br /&gt;    ' Recorremos todo el buffer para sustituir los colores distintos de blanco por&lt;br /&gt;    ' el de la transparencia&lt;br /&gt;    For indice = 0 To tamano - 1 Step 4&lt;br /&gt;        If pixels(indice) &lt;&gt; 255 Or pixels(indice + 1) &lt;&gt; 255 Or pixels(indice + 2) &lt;&gt; 255 Then&lt;br /&gt;            pixels(indice) = Transparencia&lt;br /&gt;            pixels(indice + 1) = Transparencia&lt;br /&gt;            pixels(indice + 2) = Transparencia&lt;br /&gt;        End If&lt;br /&gt;    Next&lt;br /&gt;    &lt;br /&gt;    ' Copiamos los bytes modifcados del buffer de nuevo a la imágen de la mascara&lt;br /&gt;    SetDIBits MascaraDC, MascaraBitMap, _&lt;br /&gt;        0, Altura, pixels(0), _&lt;br /&gt;        bitmap_info, DIB_RGB_COLORS&lt;br /&gt;    &lt;br /&gt;    ' Establecemos los valores del rectangulo para que coincida con las dimensiones&lt;br /&gt;    ' de las imágenes&lt;br /&gt;    recta.Top = 0&lt;br /&gt;    recta.Left = 0&lt;br /&gt;    recta.Right = Anchura&lt;br /&gt;    recta.Bottom = Altura&lt;br /&gt;    &lt;br /&gt;    ' Creamos una brocha blanca para pintar los DC temporales con ese color&lt;br /&gt;    brocha = CreateSolidBrush(&amp;HFFFFFF)&lt;br /&gt;    &lt;br /&gt;    ' Creamos el DC y bitmap de la imágen temporal nº1&lt;br /&gt;    TemporalDC = CreateCompatibleDC(OrigenDC)&lt;br /&gt;    BitMap = CreateCompatibleBitmap(OrigenDC, Anchura, Altura)&lt;br /&gt;    AntiguoBitMap = SelectObject(TemporalDC, BitMap)&lt;br /&gt;    ' Pintamos de blanco la imágen temporal nº1&lt;br /&gt;    FillRect TemporalDC, recta, brocha&lt;br /&gt;    ' Copiamos la imágen de la mascara invertida en colores a la imágen temporal nº1&lt;br /&gt;    BitBlt TemporalDC, 0, 0, Anchura, Altura, MascaraDC, 0, 0, SRCINVERT&lt;br /&gt;    ' Mezclamos la imágen de frente con la imágen temporal nº1&lt;br /&gt;    BitBlt TemporalDC, 0, 0, Anchura, Altura, OrigenDC, 0, 0, SRCAND&lt;br /&gt;&lt;br /&gt;    &lt;br /&gt;    ' Creamos el DC y bitmap de la imágen temporal nº2 y lo pintamos de blanco&lt;br /&gt;    TemporalDC2 = CreateCompatibleDC(DestinoDC)&lt;br /&gt;    BitMap2 = CreateCompatibleBitmap(DestinoDC, Anchura, Altura)&lt;br /&gt;    AntiguoBitMap2 = SelectObject(TemporalDC2, BitMap2)&lt;br /&gt;    ' Pintamos de blanco la imágen temporal nº2&lt;br /&gt;    FillRect TemporalDC2, recta, brocha&lt;br /&gt;    ' Copiamos la imágen de la mascara a la imágen temporal nº2&lt;br /&gt;    BitBlt TemporalDC2, 0, 0, Anchura, Altura, MascaraDC, 0, 0, SRCCOPY&lt;br /&gt;    ' Mezclamos la imágen de fondo con la imágen temporal nº2&lt;br /&gt;    BitBlt TemporalDC2, 0, 0, Anchura, Altura, DestinoDC, 0, 0, SRCAND&lt;br /&gt;    &lt;br /&gt;    ' Copiamos la imágen temporal nº2 a la imágen de fondo&lt;br /&gt;    BitBlt DestinoDC, 0, 0, Anchura, Altura, TemporalDC2, 0, 0, SRCCOPY&lt;br /&gt;    ' Sumamos la imágen temporal nº1 a la imágen de fondo&lt;br /&gt;    BitBlt DestinoDC, 0, 0, Anchura, Altura, TemporalDC, 0, 0, SRCPAINT&lt;br /&gt;    &lt;br /&gt;    'Limpiamos el sistema&lt;br /&gt;    SelectObject TemporalDC, AntiguoBitMap&lt;br /&gt;    SelectObject TemporalDC2, AntiguoBitMap2&lt;br /&gt;    SelectObject MascaraDC, AntiguoMascaraBitMap&lt;br /&gt;    DeleteObject BitMap&lt;br /&gt;    DeleteObject BitMap2&lt;br /&gt;    DeleteObject MascaraBitMap&lt;br /&gt;    DeleteDC TemporalDC&lt;br /&gt;    DeleteDC TemporalDC2&lt;br /&gt;    DeleteDC MascaraDC&lt;br /&gt;End Sub&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Actualización 07/07/2005:&lt;/strong&gt;&lt;br /&gt;El código de aquí arríba es más limitado de lo que yo pensaba y hace cosas que no debiera, por lo que hoy que hemos estado probandolo lo hemos descartado y en su lugar he encontrado algo mucho más sencillo... La función AlphaBlend de la API de windows 98, Me, 2000 y XP:&lt;br /&gt;&lt;br /&gt;Private Declare Function AlphaBlend _&lt;br /&gt;  Lib "msimg32" ( _&lt;br /&gt;  ByVal hDestDC As Long, _&lt;br /&gt;  ByVal x As Long, ByVal y As Long, _&lt;br /&gt;  ByVal nWidth As Long, _&lt;br /&gt;  ByVal nHeight As Long, _&lt;br /&gt;  ByVal hSrcDC As Long, _&lt;br /&gt;  ByVal xSrc As Long, _&lt;br /&gt;  ByVal ySrc As Long, _&lt;br /&gt;  ByVal widthSrc As Long, _&lt;br /&gt;  ByVal heightSrc As Long, _&lt;br /&gt;  ByVal dreamAKA As Long) _&lt;br /&gt;  As Long&lt;br /&gt;&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;dim numero as Long&lt;br /&gt;numero=127&lt;br /&gt;numero=vbBlue - CLng(numero) * (vbYellow + 1)&lt;br /&gt;AlphaBlend picture2.hDC, 0, 0, picture2.ScaleWidth, picture2.ScaleHeight, picture1.hDC, 0, 0, picture2.ScaleWidth, picture2.ScaleHeight, numero&lt;br /&gt;&lt;br /&gt;Primero colocais en la variable número un valor entre 0 (transparente) y 255 (opaco) para definir el nivel de transparencia de la imagen origen con respecto a la de destino, posteriormente con una sencilla formula (no os calenteis mucho la cabeza, ya que es una regla nemotécnica para darle un valor) se saca el valor a pasar al último parámetro de la función. Luego ya en la función le pasais el hdc de destino, el punto x e y del empiece a trabajar del destino y el ancho y alto del destino, posteriormente los mismos parámetros pero esta vez los del origen. &lt;br /&gt;&lt;br /&gt;Funciona bastante bién y estará en todos los windows modernos.&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5416816-110173105828210657?l=sistemasorp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sistemasorp.blogspot.com/feeds/110173105828210657/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5416816&amp;postID=110173105828210657' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/110173105828210657'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/110173105828210657'/><link rel='alternate' type='text/html' href='http://sistemasorp.blogspot.com/2004/11/transparencias-con-windows-y-gdi-en.html' title='Transparencias con Windows y GDI en Visual Basic'/><author><name>sistemasorp</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5416816.post-109690776729341182</id><published>2004-10-04T17:53:00.000+02:00</published><updated>2004-10-04T18:36:07.293+02:00</updated><title type='text'>A tortas con el MFC y los cursores e iconos</title><content type='html'>Bueno, hoy he estado haciendo pruebas sobre como crear un control estático donde maneje a mi antojo lo que dibuje en el con &lt;a  target="_blank" href="http://en.wikipedia.org/wiki/Microsoft_Foundation_Classes"&gt;MFC&lt;/a&gt; para windows, y entre otras cosas se me ha ocurrido meterle un icono como dibujo y que cuando el ratón pase por una zona del control se cambie el cursor (el puntero).&lt;br /&gt;&lt;br /&gt;Para el primero he tenido varios problemas puesto que no esta muy depurada la API de windows para manejar cursores y dejarlos en 16x16 pixeles, haciendo cosas raras, menos mal que dentro del oceano de Internet uno puede ir recopilando informaciones cuando no se encuentra todo en un documento para saber como hacerlo. Tan sencillo como esto:&lt;br /&gt;&lt;br /&gt;&lt;em&gt;HICON icono=(HICON)LoadImage(AfxGetInstanceHandle(),&lt;br /&gt;MAKEINTRESOURCE(IDI_SEMAFOROVERDE),&lt;br /&gt;IMAGE_ICON,&lt;br /&gt;16,16,&lt;br /&gt;LR_DEFAULTCOLOR);&lt;br /&gt;DrawIconEx(fondo.GetSafeHdc(),10,10,icono,16,16,0,NULL,DI_NORMAL);&lt;br /&gt;DestroyIcon(icono);&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;-Primero cargo el icono con la función LoadImage, donde le paso como parámetros la instancia de la aplicación donde se encuentra el icono (la misma aplicación donde se ejecuta), el identificador del recurso del icono pasado a cadena con la macro MAKEINTRESOURCE, el tipo de imagen que es (un icono), la anchura y la altura del mismo y finalmente que lo coja con los colores por defecto.&lt;br /&gt;&lt;br /&gt;-Segundo dibujo el icono en el dispositivo de contexto que nos ofrece windows para dibujar en el control CStatic, no uso la función DrawIcon del objeto de dispositivo contexto por que no consigue adaptar bién el icono a 16x16 pixeles, por lo que uso la función win32 DrawIconEx que si me lo permite, pasandole como parámetros el manejeador del dispositivo de contexto, la posición x e y donde quiero dibujar el icono, el icono, su achura y altura, ningúna brocha (no es necesario) y le digo que es una imagen con transparencias (DI_NORMAL indica todo eso).&lt;br /&gt;&lt;br /&gt;-Tercero lo destruyo porque en esto de la programación en C es bueno la "limpieza".&lt;br /&gt;&lt;br /&gt;Para el segundo caso, siendo aún más sencillo me he partido más los cuernos, simplemente porque el evento que se debe usar para cambiar el cursor no tiene mucha lógica con lo que uno quiere hacer. Mi idea es que cuando moviese el ratón por una zona del CStatic, se cambiase el cursor, sin embargo usando el evento OnMouseMove no funciona para nada la función SetCursor. He de decir que cuando digo CStatic, en realidad es una clase que he derivado de esa para poder interceptar los eventos. Por lo visto para que funcione lo que queremos hacer debemos usar el vento OnSetCursor, que funciona a semejanza del OnMouseMove, pero que no te da las coordenadas dentro del control donde se encuentre el puntero del ratón, sino que se activa cuando se pasa el ratón por el control. Esto no funcionaría si no tuviesemos activado la opción "notify" de los estilos del control. Aquí dejo mi solución de como lo he conseguido al final:&lt;br /&gt;&lt;br /&gt;&lt;em&gt;POINT point;&lt;br /&gt;GetCursorPos(&amp;point);&lt;br /&gt;ScreenToClient(&amp;point);&lt;br /&gt;&lt;br /&gt;if(point.y&gt;=10 &amp;&amp; point.y&lt;66)&lt;br /&gt;{&lt;br /&gt;::SetCursor(LoadCursor(AfxGetInstanceHandle(),&lt;br /&gt;MAKEINTRESOURCE(IDC_CURSOR)));&lt;br /&gt;&lt;br /&gt;return TRUE;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;return CStatic::OnSetCursor(pWnd, nHitTest, message);&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;-Primero declaro una variable POINT, luego pregunto con GetCursorPos que me diga la posición relativa a pantalla donde se encuentra el ratón, y a continuación lo transformo a coordenadas del control gracias a la función ScreenToClient. Con todo esto logramos saber en que posición de nuestro control esta el cursor ya que el OnSetCursor no nos la da como parámetro como lo hicera el OnMouseMove.&lt;br /&gt;&lt;br /&gt;-Segundo comparo si el cursor esta dentro de un rango en el eje de la altura y si es así ya uso la función SetCursor (de la api de win32 no del objeto), pasandole como parámetro el cursor que me devuelve la función LoadCursor, a la cual se le pasan como parámetros la instancia donde se encuentra el cursor (la nuestra en este caso) y el identificador del cursor pasado a cadena con la macro explicada antes. Después salimos de la función delvolviendo un valor TRUE indicando que no hay que hacer nada más.&lt;br /&gt;&lt;br /&gt;-Tercero, si llega hasta aquí significa que no ha pasado por el if y que llama al manejador por defecto devolviendo el valor que a su vez este devuelve, esta linea la incorpora automáticamente el Editor de Visual C++ cuando añadimos el evento OnSetFocus.&lt;br /&gt;&lt;br /&gt;Como veis la programación de Windows es apasionante, pero muchas veces me encuentro con cosas que no funcionan como deben o se manejan de forma ilógica, pero bueno, menos mal que ya hay mucho escrito sobre eso. Por cierto, sigo pendiente de aprender programar linux, estoy por el capítulo de programación avanzada de ficheros y en siguiente ya son los demonios, y aún así me queda mucho libro por leer :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5416816-109690776729341182?l=sistemasorp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sistemasorp.blogspot.com/feeds/109690776729341182/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5416816&amp;postID=109690776729341182' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/109690776729341182'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/109690776729341182'/><link rel='alternate' type='text/html' href='http://sistemasorp.blogspot.com/2004/10/tortas-con-el-mfc-y-los-cursores-e.html' title='A tortas con el MFC y los cursores e iconos'/><author><name>sistemasorp</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5416816.post-109571159877727185</id><published>2004-09-20T21:33:00.000+02:00</published><updated>2004-09-20T22:25:04.733+02:00</updated><title type='text'>Navegación anónima</title><content type='html'>Después de las vacaciones de verano ya va siendo hora que postee de nuevo en el blog, aunque me da a mi que nadie o casi nadie lo lee, pero bueno, aquí estamos.&lt;br /&gt;&lt;br /&gt;Muchas veces hemos navegado por Internet con nuestro navegador favorito y sabemos que vamos dejando nuestro rastro allá por donde vamos, o bién queremos opinar en algún foro como una persona distinta, o bién queremos votar más de una vez en alguna votación, mandar un correo electrónico y que no se sepa el origen, etc etc etc.&lt;br /&gt;&lt;br /&gt;Pues bién, la solución a todos estos problemas son los proxys abiertos, los cuales son &lt;a target="_blank" href="http://es.wikipedia.org/wiki/Proxy"&gt;proxys&lt;/a&gt; mal configurados por administradores o usuarios particulares que los tienen para compartir una conexión a Internet y por tanto cualquiera puede usar ese mismo proxy desde fuera de la red donde se encuentra.&lt;br /&gt;&lt;br /&gt;Configurando la conexión en nuestro navegador web para que pase a través de un proxy abierto, se elimina la ip que poseemos y se sustituye por la ip del proxy (en algunos casos se pasa como cabecera de la petición a la página con lo que no se elimina del todo), pudiendo asi interactuar con la web que hayamos visitado sin que sepa realmente quienes somos (normalmente no se sabe quienes somos, y menos si tenemos ip dinámica, pero con esto se dobla el anonimato en la navegación).&lt;br /&gt;&lt;br /&gt;Se puede acceder a ftp, http, https desde un proxy (siempre que este configurado para permitirlo) y conectarnos a otros puertos si usamos la tecnología SOCKS v4 o v5 (igualmente debe estar configurado para permitirlo), con lo que prácticamente se&lt;br /&gt;puede hacer de todo en internet a través de un proxy. Es más, si estas en tu empresa y te capan todos los puertos menos el puerto 80 para salir a Internet, con un proxy podrás acceder al resto de puertos sin mayor peoblema.&lt;br /&gt;&lt;br /&gt;Hay muchas listas de proxys abiertos por Internet, yo suelo usar &lt;a  target="_blank" href="http://www.openproxies.com/"&gt;Open Proxies&lt;/a&gt;, pero hay muchas listas más o menos públicas para llevar a cabo tu intimidad y anonimato.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5416816-109571159877727185?l=sistemasorp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sistemasorp.blogspot.com/feeds/109571159877727185/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5416816&amp;postID=109571159877727185' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/109571159877727185'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/109571159877727185'/><link rel='alternate' type='text/html' href='http://sistemasorp.blogspot.com/2004/09/navegacin-annima.html' title='Navegación anónima'/><author><name>sistemasorp</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5416816.post-109125934824389129</id><published>2004-07-31T09:21:00.000+02:00</published><updated>2004-08-03T11:51:04.323+02:00</updated><title type='text'>Programación TCP/IP</title><content type='html'>Creo que a estas alturas todo el mundo sabe que es internet, y lo que aporta a la comunidad, lo que no creo que sepa tanta gente es que como la información se transmite y como hace para llegar a su destino sin errores, diferenciando tantos servicios como existen en internet y demás. Dentro de este último grupo seguro que también hay gente que además de saber lo que son los protocolos &lt;a href="http://es.wikipedia.org/wiki/TCP/IP" target="_blank"&gt;TCP e IP&lt;/a&gt;, les gustaría saber qué pasos seguir para programar un cliente o un servidor de red para Internet o para intranets basadas en TCP/IP. Pues bién, hay una guia estupenda llamada &lt;a href="http://www.ecst.csuchico.edu/~beej/guide/net/" target="_blank"&gt;Beej's Guide to Network Programming&lt;/a&gt; que te explica todo lo que tienes que saber para empezar a programar sockets, que no son otra cosa que los descriptores de "fichero" para la red. Tiene traducción al castellano y además, aunque esta orientado a sistemas linux/unix, también te explica como hacerlo en windows. Yo ya hice mis pinitos hace tiempo con esta guia, y entre otras cosas hice este juego para windows del &lt;a href="http://www.quejateportodo.com/blog/cenraya.zip" target="_blank"&gt;conecta 4&lt;/a&gt; para dos jugadores (tiene sus bugs escondidos, asi que no le trateis mal :-) &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5416816-109125934824389129?l=sistemasorp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sistemasorp.blogspot.com/feeds/109125934824389129/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5416816&amp;postID=109125934824389129' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/109125934824389129'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/109125934824389129'/><link rel='alternate' type='text/html' href='http://sistemasorp.blogspot.com/2004/07/programacin-tcpip.html' title='Programación TCP/IP'/><author><name>sistemasorp</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5416816.post-108919118466898320</id><published>2004-07-07T10:48:00.000+02:00</published><updated>2004-07-31T09:55:53.060+02:00</updated><title type='text'>Futuro proyecto</title><content type='html'>No se si os habeis dado cuenta ya que me gusta experiementar con tecnologías sms y email. Pues bién, mi futuro proyecto es crear un gateway email/sms/email, el cual alguien puede enviar un mensaje desde cualquier móvil al celular del gateway con el formato &amp;lt;dirección de email&amp;gt; &amp;lt;mensaje&amp;gt;, por lo que enviará ese mensaje a la dirección de correo que se solicita. Para el proceso contrario, se debe meter el número de teléfono en el asunto y el texto en el cuerpo del mensaje, con lo que se enviará ese texto al número de teléfono que se indica.&lt;br /&gt;&lt;br /&gt;De momento lo estoy desarollando, sin embargo tengo una utilidad instalada en mi servidor linux particular (&lt;a href="http://www.sistemasorp.com" target="_blank"&gt;http://www.sistemasorp.com&lt;/a&gt;) llamada &lt;a href="http://www.isis.de/members/~s.frings/smstools/" target="_blank"&gt;smstools&lt;/a&gt; que es capaz guardar los mensajes entrantes de un movil conectado por el puerto serie en una carpeta denominada incoming, como de enviar los mensajes que se encuentren en una carpeta denomiada outgoing al mismo.&lt;br /&gt;&lt;br /&gt;La idea es que tenga un demonio corriendo bajo linux que sea quien lea la cuenta de correo habilitada a tal efecto (&lt;a href="mailto:sms@sistemasorp.com"&gt;sms@sistemasorp.com&lt;/a&gt;) enviando el sms si el email es correcto, y que a su vez comprueba la carpeta incoming para enviar el email si el sms es correcto.&lt;br /&gt;&lt;br /&gt;De momento tengo que aprender un poco más de programación en linux para hacer demonios y demás cosillas, espero que pronto este finalizado este proyecto para que podais disfrutarlo.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Edición 31/7/2004:&lt;/strong&gt;&lt;br /&gt;Buscando cosas por internet me he encontrado los &lt;a href="http://www.gnu.org/software/mailutils/mailutils.html" target="_blank"&gt;mailtuils&lt;/a&gt;, que es básicamente una serie de utilidades y librerias para lidiar con el correo. A mi me viene de perlas, porque así puedo recoger los mensajes, interpretar las cabeceras &lt;a href="http://en.wikipedia.org/wiki/MIME" target="_blank"&gt;MIME&lt;/a&gt; del mensaje, enviar emails, etc. desde el código de la aplicación, y sin tener que hacer llamadas al sistema a "mail" y similares como tenía pensado. Ahora solo me queda ponerme con la programación de &lt;a href="http://en.wikipedia.org/wiki/Daemon_(computer_software)" target="_blank"&gt;demonios&lt;/a&gt; en linux para tener a punto el gateway.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5416816-108919118466898320?l=sistemasorp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sistemasorp.blogspot.com/feeds/108919118466898320/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5416816&amp;postID=108919118466898320' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/108919118466898320'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/108919118466898320'/><link rel='alternate' type='text/html' href='http://sistemasorp.blogspot.com/2004/07/futuro-proyecto.html' title='Futuro proyecto'/><author><name>sistemasorp</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5416816.post-108789815023964859</id><published>2004-06-22T11:32:00.000+02:00</published><updated>2004-08-06T16:27:54.213+02:00</updated><title type='text'>Envio de sms con cualquier remitente</title><content type='html'>Y ya puestos después de publicar el anterior artículo, os comentaré como enviar mensajes SMS con un remitente cualquiera. Esta posibilidad es aún más creible que los correos electrónicos, puesto que cuando un usuario de móvil recibe un mensaje de texto en su móvil, creerá que el remitente del mismo es quien le ha enviado tal mensaje, ya que la&lt;br /&gt;gran mayoría no sabrá que los sms se pueden falsificar.&lt;br /&gt;&lt;br /&gt;Esto no es como lo del e-mail, es costoso: Si os haceis una cuenta en www.truesenses.com y comprais una cantidad de mensajes, su interfaz te permite poner además del destinatario y el mensaje, el remitente del mismo. Por lo que puedes poner como origen cadenas de texto o ún número de móvil (cuando el destinatario reciba el mensaje si tiene ese número en la agenda le aparecerá con el nombre con el que lo hubiera guardado).&lt;br /&gt;&lt;br /&gt;Así de sencillo, 300 mensajes cuestan unos 30 euros, sin embargo al ser un operador suizo y al hacer roaming, cuando se envía un mensaje a España se cuenta como si hubieras enviado 2.&lt;br /&gt;&lt;br /&gt;Sin embargo, y por tiempo limitado, aquí os dejo un formulario donde podreis probar este tipo de característica. Que os divirtais.&lt;br /&gt;&lt;br /&gt;&lt;FORM name="formulario"&gt;&lt;TABLE width="100%"&gt;&lt;TR&gt;&lt;TD&gt;&lt;strong&gt;Remitente&lt;/strong&gt; (una cadena o número internacional de móvil de 12 caracteres como máximo)&lt;/TD&gt;&lt;TD&gt;&lt;INPUT type="text" name="remitente" size="12" maxlength="12"&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;&lt;strong&gt;Destinatario&lt;/strong&gt; (un número internacional de móvil de 12 caracteres como máximo)&lt;/TD&gt;&lt;TD&gt;&lt;INPUT type="text" name="destinatario" size="12" maxlength="12"&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;&lt;strong&gt;Mensaje&lt;/strong&gt; (130 caractéres máximo)&lt;/TD&gt;&lt;TD&gt;&lt;TEXTAREA name="mensaje" cols="50" rows="10" maxlength="130"&gt;&lt;/TEXTAREA&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TABLE&gt;&lt;INPUT type="button" value="Enviar" onclick="javascript:function URLencode(sStr) {return escape(sStr).replace(/\+/g, '%2B')};window.open('http://www.quejateportodo.com/mensajes/mensaje.php?remitente='+URLencode(document.formulario.remitente.value)+'&amp;destinatario='+URLencode(document.formulario.destinatario.value)+'&amp;mensaje='+URLencode(document.formulario.mensaje.value))"&gt;&lt;/FORM&gt;&lt;br /&gt;&lt;strong&gt;Edición 06/08/2004:&lt;/strong&gt;&lt;br /&gt;Después de haber tenido el servicio levantado durante 1 mes y 15 días aprox. lo cierro con la satisfacción de que ha sido una gran experiencia para todos los que lo han usado con cerca de 160 mensajes enviados desde este formulario. Quién sabe, a lo mejor me animo y lo vuelvo a activar desde &lt;a target="_blank" href="http://www.sistemasorp.com"&gt;www.sistemasorp.com&lt;/a&gt; (no lo probeis ya que tiene el movil sin batería)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5416816-108789815023964859?l=sistemasorp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sistemasorp.blogspot.com/feeds/108789815023964859/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5416816&amp;postID=108789815023964859' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/108789815023964859'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/108789815023964859'/><link rel='alternate' type='text/html' href='http://sistemasorp.blogspot.com/2004/06/envio-de-sms-con-cualquier-remitente.html' title='Envio de sms con cualquier remitente'/><author><name>sistemasorp</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5416816.post-108783947176665169</id><published>2004-06-21T18:18:00.000+02:00</published><updated>2004-06-22T00:10:43.770+02:00</updated><title type='text'>Envio de mails con cualquier remitente</title><content type='html'>No se si lo sabíais, pero es relativamente fácil falsificar un remitente de una dirección de correo electrónico. Para ello solo teneis que saber lo básico del protocolo SMTP de internet, o lo que es lo mismo, el protocolo que recibe los emails para luego enviarlos, ya sea a destinatarios del mismo dominio (correo local), o bién a destinatarios de otros dominios (distribución, aunque en este último caso si no eres del mismo dominio que el servidor SMTP es bastante improbable que puedas poner un remitente y un destinatario diferentes que el dominio del propio servidor).&lt;br /&gt;&lt;br /&gt;El caso es que queremos enviar un mensaje a un conocido con un remitente distinto al nuestro. Aunque configurasemos nuestro cliente de correo con una cuenta ficticia, probablemente nuestro servidor de correo SMTP no nos dejase enviarlo por lo que he explicado en el anterior párrafo. Sin embargo con unos pocos conocimientos podemos ser nosotros mismos quienes depositemos en mensaje trucado en el buzón del destinatario.&lt;br /&gt;&lt;br /&gt;El proceso a seguir es el siguiente:&lt;br /&gt;&lt;br /&gt;1 - Averiguar el servidor de correo del destinatario, para ello en la linea de comandos  ponemos: &lt;br /&gt;(en windows nt, 2000, xp o Linux) nslookup -q=MX dominio&lt;br /&gt;&lt;br /&gt;Donde "dominio" es el del propio del destinatario, por ejemplo pepito@yahoo.es el dominio es "yahoo.es", con lo que al final queda &lt;em&gt;nslookup -q=MX yahoo.es&lt;/em&gt;. Entónces cogemos la direccion que aparece a la derecha de &lt;em&gt;mail exchanger&lt;/em&gt;; en el caso de yahoo me han salido varios, yo cojo el primero, es decir, mx2.mail.yahoo.com &lt;br /&gt;&lt;br /&gt;2 - Poner luego en la misma linea de comandos lo siguiente:&lt;br /&gt;(en windows o Linux) telnet servidor 25&lt;br /&gt;&lt;br /&gt;Donde "servidor" es la dirección a la que haciamos referencia en el punto 1, con lo que al final queda &lt;em&gt;telnet mx2.mail.yahoo.com 25&lt;/em&gt;. Si ponemos 25 es porque ese es el puerto por donde habitualmente escucha el servidor SMTP de correo del dominio al que queremos conectarnos.&lt;br /&gt;&lt;br /&gt;3 - Una vez conectados veremos un mensaje de bienvenida con un código numérico y un texto, nosotros solo nos centraremos en los códigos numéricos. Si todo funciona correctamente debemos haber recibido un &lt;strong&gt;220&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;Lo primero que haremos es poner HELO dominio y pulsaremos enter, donde "dominio" se supone que es el dominio del remitente del mensaje, si nosotros queremos enviar el mensaje como billgates@microsoft.com sería &lt;em&gt;HELO microsoft.com&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Si todo va bien, recibiremos un código &lt;strong&gt;250&lt;/strong&gt;. Ahora pondremos la dirección de correo del remitente de la siguiente forma MAIL FROM: &amp;lt;remitente&amp;gt; y pulsaremos enter, donde "remitente" en nuestro ejemplo sería billgates@microsoft.com y quedaría así &lt;em&gt;MAIL FROM: &amp;lt;billgates@microsoft.com&amp;gt;&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Si todo fué bién, volveremos a recibir un código &lt;strong&gt;250&lt;/strong&gt;. Ahora pondremos la dirección de correo del destinatario de la siguiente forma RCPT TO: &amp;lt;destinatario&amp;gt; y pulsaremos enter, donde "destinatario" en nuestro ejemplo sería pepito@yahoo.es y quedaría así &lt;em&gt;RCPT TO: &amp;lt;pepito@yahoo.es&amp;gt;&lt;/em&gt;. En el caso de que haya varios destinatarios en el mismo dominio repetir el mismo proceso con todos ellos.&lt;br /&gt;&lt;br /&gt;Si hemos recibido otro código &lt;strong&gt;250&lt;/strong&gt; es que esto va como la seda. Ahora ponemos &lt;em&gt;DATA&lt;/em&gt; y pulsamos enter, si recibimos un código &lt;strong&gt;354&lt;/strong&gt; es que ya podemos poner el correo en sí.&lt;br /&gt;Primero vienen las cabeceras, luego una linea en blanco, luego el texto y luego una linea con un punto, asi que si queremos poner el nombre del remitente, el del destinatario, el título como "Hola colega" y el mensaje "¿Que tál estas?", debemos escribir las siguientes lineas a continuación:&lt;br /&gt;&lt;br /&gt;&lt;em&gt;From:"Bill Gates" &amp;lt;billgates@microsoft.com&amp;gt;&lt;br /&gt;To:"Pepito Perez" &amp;lt;pepito@yahoo.es&amp;gt;&lt;br /&gt;Subject:Hola colega&lt;br /&gt;Content-type:text/plain;charset="iso-8859-1"&lt;br /&gt;&lt;br /&gt;¿Que tal estás?&lt;br /&gt;.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;La linea &lt;em&gt;Content-type:text/plain;charset="iso-8859-1"&lt;/em&gt; de la cabecera sirve para indicar que el texto contiene caracteres occidentales como acentos y demás. Si recibimos un código &lt;strong&gt;250&lt;/strong&gt; significa que el mensaje ha sido enviado satisfactoriamente y que el usuario lo recibirá en cuanto recoja el correo. Ahora si tecleais &lt;em&gt;QUIT&lt;/em&gt; saldreis de la sesión.&lt;br /&gt;&lt;br /&gt;Os animo a que lo probeis con vuestras cuentas de correo para que comprobeis que funciona y coger experiencia para luego probarlo con otras cuentas ;). Una cosa&lt;br /&gt;importante es que vuestra dirección IP se queda reflejada en la cabecera del mensaje,&lt;br /&gt;asi que o bién os buscais un proxy con socks o un wingate para ocultarla, o bien dejais que vuestra ip permanezca en la cabecera si veis que el destinatario no sabrá encontrarla u os da igual que este en la cabecera.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5416816-108783947176665169?l=sistemasorp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sistemasorp.blogspot.com/feeds/108783947176665169/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5416816&amp;postID=108783947176665169' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/108783947176665169'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/108783947176665169'/><link rel='alternate' type='text/html' href='http://sistemasorp.blogspot.com/2004/06/envio-de-mails-con-cualquier-remitente.html' title='Envio de mails con cualquier remitente'/><author><name>sistemasorp</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5416816.post-108628233329705290</id><published>2004-06-03T19:04:00.000+02:00</published><updated>2004-06-03T19:06:54.543+02:00</updated><title type='text'>¿Formato de un fichero?</title><content type='html'>Supongo que todos los que nos dedicamos a programar siempre nos hemos preguntado cual sería el formato de un fichero, como poder leerlo, interpretar sus cabeceras, escribir uno por nuestra cuenta y que pueda ser leido por otras herramientas ajenas a la nuestra, etc. El problema es que siempre que queramos conseguir la descripción de cualquier formato de fichero que tengamos que usar nos tocará buscarlo por Internet , y muchas veces uno se desespera porque hay muchas refrencias a un tipo de fichero pero ninguna que nos interese. Sin embargo, esto se soluciona en gran medida gracias a &lt;A target="_blank" href="http://www.wotsit.org"&gt;wotsit's format&lt;/A&gt;: una web donde podrás buscar casi cualquier tipo de fichero y leer sus especificaciones. Esta organizado por función, tiene busquedas y en general es bastante sencillo de usar, ¿que quieres saber cual es el formato del fichero .DOC, .XLS. PDF, .JPG, .CAD, etc? pues aqui lo encontrarás, por lo que es el sitio ideal siempre que quieras buscar un formato de fichero.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5416816-108628233329705290?l=sistemasorp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sistemasorp.blogspot.com/feeds/108628233329705290/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5416816&amp;postID=108628233329705290' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/108628233329705290'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/108628233329705290'/><link rel='alternate' type='text/html' href='http://sistemasorp.blogspot.com/2004/06/formato-de-un-fichero.html' title='¿Formato de un fichero?'/><author><name>sistemasorp</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5416816.post-108504395310941343</id><published>2004-05-20T10:50:00.000+02:00</published><updated>2004-05-20T11:05:53.110+02:00</updated><title type='text'>Las patentes</title><content type='html'>Recientemente se ha aprobado en la Unión Europea las &lt;a target="_blank" href="http://www.elmundo.es/navegante/2004/05/18/esociedad/1084895955.html"&gt;patentes de software&lt;/a&gt; al más puro estilo Yankee. Esto, lejos de ser beneficioso, provoca que las grandes corporaciones se hagan aún más fuertes en el mercado del software. Hay gente que dice que si tu has desarrollado un algoritmo de software, debes patentarlo para respetar tu autoría y poder explotarlo económicamente. Sin embargo esto no es tan bonito como parece, puesto que el principal perjudicado sería el software libre que ahora estaba empezando a pegar fuerte tanto en empresas como en los hogares. Hace muy poco tiempo Microsoft patentó en los E.E.U.U un sistema de ejecución de programas basado en tiempos a través de un hardware específico, encubriendo así el famoso click y doble click del ratón. Esto podría repercutir en cualquier sistema Mac, Linux/Unix, OS/400, VMS, etc. porque Microsoft podría cobrarles sumas millonarias a aquellos que lo implementen, pudiendo provocar la ruina a muchos de ellos de tal forma que al final M$ consiguiese quedarse como único proveedor de software y posteriormente subiendo los precios como se le antojase sin tener competencia ninguna. Alguno puede que diga que ya se inventará otro sistema para hacer lo mismo, pero el problema es que no es lo único que se puede patentar y un sistema lo conforman muchas cosas.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5416816-108504395310941343?l=sistemasorp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sistemasorp.blogspot.com/feeds/108504395310941343/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5416816&amp;postID=108504395310941343' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/108504395310941343'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/108504395310941343'/><link rel='alternate' type='text/html' href='http://sistemasorp.blogspot.com/2004/05/las-patentes.html' title='Las patentes'/><author><name>sistemasorp</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5416816.post-10843645705490863</id><published>2004-05-12T13:21:00.000+02:00</published><updated>2004-05-12T18:44:54.990+02:00</updated><title type='text'>El mundo de XSL</title><content type='html'>Como primer artículo comentaré que labor estoy desarrollando ahora mismo en mi trabajo. Para poneros en antecedentes os diré que estoy desarrollando (e investigando) en un proyecto para la Comunidad de Madrid. No os comentaré mucho de que trata porque no creo que sin haber salido a la luz les guste a los responsables del mismo que se le de publicidad. Sin embargo si os puedo comentar algo de lo que estoy haciendo:&lt;br /&gt;&lt;br /&gt;Dentro del proyecto hay un apartado donde se generan unas cedulas informativas. El objetivo es poder generar cedulas en formato PDF, sin embargo no es moco de pavo, porque dependiendo del municipio habrá distintos tipos de información y se tendrá que representar de forma igualmente distinta. El caso es que como es un proceso que posiblemente tenga que atender cientos de peticiones no es un simple "imprime en la impresora pdf" como podría ser en word o similares.&lt;br /&gt;&lt;br /&gt;Hay una cosa clara, y es que la información que se baraja tiende a ser la misma, pero no así la presentación (¿os suena esto a la programación a &lt;a target="_blank" href="http://www.extropia.com/tutorials/dna/three_layers.html"&gt;tres capas&lt;/a&gt;?). El caso es que existe una herramienta denominada &lt;a target="_blank" href="http://xml.apache.org/fop/index.html"&gt;FOP&lt;/a&gt; la cual te permite pasarle un fichero XML, un fichero XSL (XSL + FO) y te genera un pdf en un santiamen. El proceso es el siguiente, el XML solo tiene los datos estructuradamente, el XSL contiene el pseudocodigo que manejará los datos XML. Luego cuando se ejecuta el fop, se interpreta el XSL que le dice donde poner los datos del fichero XML y a continuación genera un PDF interpretando las directrices del FO. El resultado es bastante bueno, aunque la generación del XSL la hago de momento a mano y suele ser un poco laborioso, sin embargo es gratificante ver sus resultados.&lt;br /&gt;&lt;br /&gt;Un ejemplo muy cortito sería este:&lt;br /&gt;&lt;br /&gt;--------------------------------------------------------------------------------&lt;br /&gt;Fichero XML&lt;br /&gt;--------------------------------------------------------------------------------&lt;br /&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="ISO-8859-1"?&amp;gt;&lt;br /&gt;&amp;lt;RAIZ&amp;gt;&lt;br /&gt; &amp;lt;NOMBRE&amp;gt;Oscar Rodríguez&amp;lt;/NOMBRE&amp;gt;&lt;br /&gt;&amp;lt;/RAIZ&amp;gt;&lt;br /&gt;&lt;br /&gt;--------------------------------------------------------------------------------&lt;br /&gt;Fichero XSL&lt;br /&gt;--------------------------------------------------------------------------------&lt;br /&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="iso-8859-1"?&amp;gt;&lt;br /&gt;&amp;lt;xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:fo="http://www.w3.org/1999/XSL/Format"&amp;gt;&lt;br /&gt;&amp;lt;xsl:template match="/"&amp;gt;&lt;br /&gt;   &amp;lt;fo:root&amp;gt;&lt;br /&gt;      &amp;lt;fo:layout-master-set&amp;gt;&lt;br /&gt;         &amp;lt;fo:simple-page-master master-name="pagina" page-width="210mm" page-height="297mm"&amp;gt;&lt;br /&gt;            &amp;lt;fo:region-body margin="1cm"/&amp;gt;&lt;br /&gt;         &amp;lt;/fo:simple-page-master&amp;gt;&lt;br /&gt;      &amp;lt;/fo:layout-master-set&amp;gt;&lt;br /&gt;      &amp;lt;fo:page-sequence master-reference="pagina"&amp;gt;&lt;br /&gt;         &amp;lt;fo:flow flow-name="xsl-region-body"&amp;gt;&lt;br /&gt;            &amp;lt;xsl:apply-templates select="//NOMBRE"/&amp;gt;&lt;br /&gt;         &amp;lt;/fo:flow&amp;gt;&lt;br /&gt;      &amp;lt;/fo:page-sequence&amp;gt;&lt;br /&gt;   &amp;lt;/fo:root&amp;gt;&lt;br /&gt;&amp;lt;/xsl:template&amp;gt;&lt;br /&gt;&amp;lt;xsl:template match="NOMBRE"&amp;gt;&lt;br /&gt;   &amp;lt;fo:block font-family="Times" font-size="8pt" color="blue"&amp;gt;Hola, soy &amp;lt;xsl:value-of select="."/&amp;gt;&amp;lt;/fo:block&amp;gt;&lt;br /&gt;&amp;lt;/xsl:template&amp;gt;&lt;br /&gt;&amp;lt;/xsl:stylesheet&amp;gt;&lt;br /&gt;&lt;br /&gt;--------------------------------------------------------------------------------&lt;br /&gt;&lt;br /&gt;Si os fijais, como comentaba antes el XML es una chorrada, sin embargo el XSL es más laborioso porque al fin y al cabo hay que tratar tanto la información del XML (aquellas etiquetas que empiecen por xsl) como indicar como se va a presentar (las etiquetas que empiecen por fo). En este ejemplo se esta diciendo que se genere una página DIN A4 con margen por todos los lados de 1 centimetro; que procese la etiqueta NOMBRE (o lo que sería como llamar a la función NOMBRE) para que saque al final la frase "Hola, soy Oscar Rodríguez" con un tipo de letra Times New Romans de 8 puntos y de color azul.&lt;br /&gt;&lt;br /&gt;EL FOP al ejecutarlo de la siguiente forma:&lt;br /&gt;fop -xsl oscar.xsl -xml oscar.xml -pdf oscar.pdf&lt;br /&gt;&lt;br /&gt;muestra lo siguiente:&lt;br /&gt;[INFO] Using org.apache.xerces.parsers.SAXParser as SAX2 Parser&lt;br /&gt;[INFO] FOP 0.20.5&lt;br /&gt;[INFO] Using org.apache.xerces.parsers.SAXParser as SAX2 Parser&lt;br /&gt;[INFO] building formatting object tree&lt;br /&gt;[INFO] setting up fonts&lt;br /&gt;[INFO] [1]&lt;br /&gt;[INFO] Parsing of document complete, stopping renderer&lt;br /&gt;&lt;br /&gt;Y el resultado final queda &lt;a target="_blank" href="http://www.quejateportodo.com/blog/oscar.pdf"&gt;así&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Luego se puede complicar más poniendo cabeceras, números de página, imágenes, etc. Yo aún sigo investigando para ver todas las posibilidades del &lt;a target="_blank" href="http://www.w3.org/TR/xsl/"&gt;XSL&lt;/a&gt; (y su hermano menor el FO).&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5416816-10843645705490863?l=sistemasorp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sistemasorp.blogspot.com/feeds/10843645705490863/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5416816&amp;postID=10843645705490863' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/10843645705490863'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/10843645705490863'/><link rel='alternate' type='text/html' href='http://sistemasorp.blogspot.com/2004/05/el-mundo-de-xsl.html' title='El mundo de XSL'/><author><name>sistemasorp</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5416816.post-108436011372930084</id><published>2004-05-12T12:56:00.000+02:00</published><updated>2004-05-12T13:16:36.716+02:00</updated><title type='text'>Hay que darle vidilla a esto</title><content type='html'>Mi iniciativa de crear un blog se quedó poco menos que en el aire después de que haya pasado casi un año desde la primera (y única) publicación en blogger, pero hasta aquí hemos llegado. Mi idea era la de desarrollar yo mismo un sistema de weblogging, pero visto los cambios que ha hecho blogger me quedaré con el sistema actual (la excusa extra-oficial es la pereza que me da hacerlo de nuevo).&lt;br /&gt;&lt;br /&gt;Este fenómeno de los weblogs es creciente, tanto que para un tio como yo que le apasiona tanto la informática no puede pasarme desapercibido. Es cierto que esto exige una constancia en cuanto a la publicación, tanta que muchos han desistido o los dejan medio abandonados. Este abandono para mi es quedar mal con los leyentes, por lo que sin pillarme las manos, seré un escritor + o - asiduo si a alguien le interesa mi bitácora.&lt;br /&gt;&lt;br /&gt;¿De que va a tratar? De programación, de informática y demás. Estos tres puntos intentaré diferenciarlos bién, porque yo soy desarrollador, pero también me gustaría escribir sobre cosas relacionadas con el mundo de la informática, y por supuesto, como no es un sistema cerrado también escribiré sobre otros temas que no tengan que ver con los anteriores.&lt;br /&gt;&lt;br /&gt;Mi objetivo es compartir mis experiencias, mis opiniones, mis logros, mis decepciones, etc. por lo que todos los artículos tendrán tinte personal (para eso es un weblog ¿no?), y quien sabe si algún día compartiré con más gente.&lt;br /&gt;&lt;br /&gt;Si has llegado hasta aquí y no te has aburrido, te doy las gracias y te animo a que leas el resto de publicaciones en este blog.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5416816-108436011372930084?l=sistemasorp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sistemasorp.blogspot.com/feeds/108436011372930084/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5416816&amp;postID=108436011372930084' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/108436011372930084'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5416816/posts/default/108436011372930084'/><link rel='alternate' type='text/html' href='http://sistemasorp.blogspot.com/2004/05/hay-que-darle-vidilla-esto.html' title='Hay que darle vidilla a esto'/><author><name>sistemasorp</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry></feed>
