<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>

<channel>
	<title>/home/blaster [ Blaster's blog ]</title>
	<atom:link href="http://blaster.comunidad-itsjr.com.mx/feed" rel="self" type="application/rss+xml" />
	<link>http://blaster.comunidad-itsjr.com.mx</link>
	<description>java,programacion,codigos,programas,como programar,netbeans,manual netbeans,bajar netbeans,java,jdk,jdbc</description>
	<pubDate>Sun, 15 Jun 2008 20:11:23 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6</generator>
	<language>en</language>
			<item>
		<title>cual es la diferencia de un hub,un switch y un router ?</title>
		<link>http://blaster.comunidad-itsjr.com.mx/archives/272</link>
		<comments>http://blaster.comunidad-itsjr.com.mx/archives/272#comments</comments>
		<pubDate>Sun, 15 Jun 2008 20:11:23 +0000</pubDate>
		<dc:creator>blaster</dc:creator>
		
		<category><![CDATA[redes]]></category>

		<guid isPermaLink="false">http://blaster.comunidad-itsjr.com.mx/?p=272</guid>
		<description><![CDATA[Hub
Un HUB tal como dice su nombre es un concentrador. Simplemente une conexiones y no altera las tramas que le llegan. Para entender como funciona veamos paso a paso lo que sucede (aproximadamente) cuando llega una trama.
Visto lo anterior podemos sacar las siguientes conclusiones:
1 - El HUB envía información a ordenadores que no están interesados. [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Hub</strong></p>
<p>Un HUB tal como dice su nombre es un concentrador. Simplemente une conexiones y no altera las tramas que le llegan. Para entender como funciona veamos paso a paso lo que sucede (aproximadamente) cuando llega una trama.</p>
<p>Visto lo anterior podemos sacar las siguientes conclusiones:</p>
<p>1 - El HUB envía información a ordenadores que no están interesados. A este nivel sólo hay un destinatario de la información, pero para asegurarse de que la recibe el HUB envía la información a todos los ordenadores que están conectados a él, así seguro que acierta.</p>
<p>2 - Este tráfico añadido genera más probabilidades de colisión. Una colisión se produce cuando un ordenador quiere enviar información y emite de forma simultánea que otro ordenador que hace lo mismo. Al chocar los dos mensajes se pierden y es necesario retransmitir. Además, a medida que añadimos ordenadores a la red también aumentan las probabilidades de colisión.</p>
<p>3 - Un HUB funciona a la velocidad del dispositivo más lento de la red. Si observamos cómo funciona vemos que el HUB no tiene capacidad de almacenar nada. Por lo tanto si un ordenador que emite a 100 megabit le trasmitiera a otro de 10 megabit algo se perdería el mensaje. En el caso del ADSL los routers suelen funcionar a 10 megabit, si lo conectamos a nuestra red casera, toda la red funcionará a 10, aunque nuestras tarjetas sean 10/100.</p>
<p>4 - Un HUB es un dispositivo simple, esto influye en dos características. El precio es baratito. El retardo, un HUB casi no añade ningún retardo a los mensajes.</p>
<p><strong>Switch</strong></p>
<p>Cuando hablamos de un switch lo haremos refiriéndonos a uno de nivel 2, es decir, perteneciente a la capa “Enlace de datos”. Normalmente un switch de este tipo no tiene ningún tipo de gestión, es decir, no se puede acceder a él. Sólo algunos switch tienen algún tipo de gestión pero suele ser algo muy simple. Veamos cómo funciona un “switch”.</p>
<p>Puntos que observamos del funcionamiento de los “switch”:</p>
<p>1 - El “switch” conoce los ordenadores que tiene conectados a cada uno de sus puertos (enchufes). Cuando en la especificación del un “switch” leemos algo como “8k MAC address table” se refiere a la memoria que el “switch” destina a almacenar las direcciones. Un “switch” cuando se enchufa no conoce las direcciones de los ordenadores de sus puertos, las aprende a medida que circula información a través de él. Con 8k hay más que suficiente. Por cierto, cuando un “switch” no conoce la dirección MAC de destino envía la trama por todos sus puertos, al igual que un HUB (“Flooding”, inundación). Cuando hay más de un ordenador conectado a un puerto de un “switch” este aprende sus direcciones MAC y cuando se envían información entre ellos no la propaga al resto de la red, a esto se llama filtrado.</p>
<p>El tráfico entre A y B no llega a C. Como decía, esto es el filtrado. Las colisiones que se producen entre A y B tampoco afectan a C. A cada parte de una red separada por un “switch” se le llama segmento.</p>
<p>2 - El “switch” almacena la trama antes de reenviarla. A este método se llama “store &amp; forward”, es decir “almacenar y enviar”. Hay otros métodos como por ejemplo “Cut-through” que consiste en recibir los 6 primeros bytes de una trama que contienen la dirección MAC y a partir de aquí ya empezar a enviar al destinatario. “Cut-through” no permite descartar paquetes defectuosos. Un “switch” de tipo “store &amp; forward” controla el CRC de las tramas para comprobar que no tengan error, en caso de ser una trama defectuosa la descarta y ahorra tráfico innecesario. El “store &amp; forward” también permite adaptar velocidades de distintos dispositivos de una forma más cómoda, ya que la memoria interna del “switch” sirve de “buffer”. Obviamente si se envía mucha información de un dispositivo rápido a otro lento otra capa superior se encargará de reducir la velocidad.</p>
<p>Finalmente comentar que hay otro método llamado “Fragment-free” que consiste en recibir los primeros 64 bytes de una trama porque es en estos donde se producen la mayoría de colisiones y errores. Así pues cuando vemos que un “switch” tiene 512KB de RAM es para realizar el “store &amp; forward”. Esta RAM suele estar compartida entre todos los puertos, aunque hay modelos que dedican un trozo a cada puerto.</p>
<p>3 - Un “switch” moderno también suele tener lo que se llama “Auto-Negotation”, es decir, negocia con los dispositivos que se conectan a él la velocidad de funcionamiento, 10 megabit ó 100, así como si se funcionara en modo “full-duplex” o “half-duplex”. “Full-duplex” se refiere a que el dispositivo es capaz de enviar y recibir información de forma simultánea, “half-duplex” por otro lado sólo permite enviar o recibir información, pero no a la vez.</p>
<p>4 - Velocidad de proceso: todo lo anterior explicado requiere que el “switch” tenga un procesador y claro, debe ser lo más rápido posible. También hay un parámetro conocido como “back-plane” o plano trasero que define el ancho de banda máximo que soporta un “switch”. El “back plane” dependerá del procesador, del número de tramas que sea capaz de procesar. Si hacemos números vemos lo siguiente: 100megabits x 2 (cada puerto puede enviar 100 megabit y enviar 100 más en modo “full-duplex”) x 8 puertos = 1,6 gigabit. Así pues, un “switch” de 8 puertos debe tener un “back-plane” de 1,6 gigabit para ir bien. Lo que sucede es que para abaratar costes esto se reduce ya que es muy improbable que se produzca la situación de tener los 8 puertos enviando a tope&#8230; Pero la probabilidad a veces no es cierta wink.gif</p>
<p>5 - Si un nodo puede tener varias rutas alternativas para llegar a otro un “switch” tiene problemas para aprender su dirección ya que aparecerá en dos de sus entradas. A esto se le llama “loop” y suele haber una lucecita destinada a eso delante de los “switch”. El protocolo de Spanning Tree Protocol IEEE 802.1d se encarga de solucionar este problema, aunque los “switch” domésticos no suelen tenerlo&#8230; No hagáis redondas&#8230;</p>
<p><strong>Router</strong><br />
Un router (en español enrutador o encaminador) es un dispositivo hardware o software de interconexión de redes de computadoras que opera en la capa tres (nivel de red) del modelo OSI. Este dispositivo interconecta segmentos de red o redes enteras. Hace pasar paquetes de datos entre redes tomando como base la información de la capa de red.</p>
<p>El router toma decisiones lógicas con respecto a la mejor ruta para el envío de datos a través de una red interconectada y luego dirige los paquetes hacia el segmento y el puerto de salida adecuados. Sus decisiones se basan en diversos parámetros. Una de las más importantes es decidir la dirección de la red hacia la que va destinado el paquete (En el caso del protocolo IP esta sería la dirección IP). Otras decisiones son la carga de tráfico de red en las distintas interfaces de red del router y establecer la velocidad de cada uno de ellos, dependiendo del protocolo que se utilice.</p>
<p>En el ejemplo del diagrama, se muestran 3 redes IP interconectadas por 2 routers. La computadora con el IP 222.22.22.1 envía 2 paquetes, uno para la computadora 123.45.67.9 y otro para 111.11.11.1 A través de sus tablas de enrutamiento configurados previamente, los routers pasan los paquetes para la red o router con el rango de direcciones que corresponde al destino del paquete. Nota: el contenido de las tablas de rutas está simplificado por motivos didácticos. En realidad se utilizan máscaras de red para definir las subredes interconectadas.</p>
<p>Los broadcast, o difusiones, se producen cuando una fuente envía datos a todos los dipositivos de una red. En el caso del protocolo IP, una dirección de broadcast es una dirección compuesta exclusivamente por números unos (1) en el campo del host (para la dirección ip en formato binario de modo que para una máscara de red 255.255.255.0 la dirección de broadcast para la dirección 192.168.0.1 seria la 192.168.0.255 o sea xxxxxxxx.xxxxxxxx.xxxxxxxx.11111111). Los protocolos de enrutamiento son aquellos protocolos que utilizan los routers o encaminadores para comunicarse entre sí y compartir información que les permita tomar la decisión de cual es la ruta más adecuada en cada momento para enviar un paquete. Los protocolos más usados son RIP (v1 y v2), OSPF (v1, v2 y v3), y BGP (v4), que se encargan de gestionar las rutas de una forma dinámica. aunque no es estrictamente necesario que un router haga uso de estos protocolos, pudiéndosele indicar de forma estática las rutas (caminos a seguir) para las distintas subredes que estén conectadas al dispositivo. Comúnmente los routers se implementan también como puertas de acceso a Internet (por ejemplo un router ADSL), usándose normalmente en casas y oficinas pequeñas. Es correcto utilizar el término router en este caso, ya que estos dispositivos unen dos redes (una red de área local con Internet). Existe la posibilidad de no utilizar equipos dedicados, opción que puede ser la más adecuada para redes locales o redes con un tráfico limitado, y usar software que implemente los protocolos de red antes mencionados. Para dar funcionalidad de router a un PC con los sistemas operativos GNU/Linux o BSD es suficiente con añadirle al menos dos interfaces de red y activar el soporte de enrutamiento en el kernel.</p>
<p><strong>Donde usar Switch?</strong></p>
<p>Uno de los principales factores que determinan el exito del diseño de una red, es la<br />
habilidad de la red para proporcionar una satisfactoria interacción entre cliente/servidor, pues los usuarios juzgan la red por la rápidez de obtener un prompt y la confiabilidad del servicio.<br />
Hay diversos factores que involucran el incremento de ancho de banda en una LAN:<br />
•El elevado incremento de nodos en la red.<br />
•El continuo desarrollo de procesadores mas rápidos y poderosos en estaciones de<br />
trabajo y servidores.<br />
•La necesidad inmediata de un nuevo tipo de ancho de banda para aplicaciones<br />
intensivas cliente/servidor.<br />
•Cultivar la tendencia hacia el desarrollo de granjas centralizadas de servidores para<br />
facilitar la administración y reducir el número total de servidores.<br />
La regla tradicional 80/20 del diseño de redes, donde el 80% del tráfico en una LAN<br />
permanece local, se invierte con el uso del switch.<br />
Los switches resuelven los problemas de anchos de banda al segmentar un dominio de colisiones de una LAN, en pequeños dominios de colisiones.<br />
En la figura la segmentación casí elimina el concurso por el medio y da a cada estación final más ancho de banda en la LAN.</p>
<p><strong>Donde usar un ruteador?</strong></p>
<p>Las funciones primarias de un ruteador son:<br />
•Segmentar la red dentro de dominios individuales de brodcast.<br />
•Suministrar un envio inteligente de paquetes. Y<br />
•Soportar rutas redundantes en la red.<br />
Aislar el tráfico de la red ayuda a diagnosticar problemas, puesto que cada puerto del ruteador es una subred separada, el tráfico de los brodcast no pasaran a través del ruteador.<br />
Otros importantes beneficios del ruteador son:<br />
•Proporcionar seguridad a través de sotisficados filtros de paquetes, en ambiente<br />
LAN y WAN.<br />
•Consolidar el legado de las redes de mainframe IBM, con redes basadas en PCs a<br />
través del uso de Data Link Switching (DLSw).<br />
•Permitir diseñar redes jerarquicas, que delegen autoridad y puedan forzar el manejo<br />
local de regiones separadas de redes internas.<br />
•Integrar diferentes tecnologías de enlace de datos, tales como Ethernet, Fast<br />
Ethernet, Token Ring, FDDI y ATM.</p>
]]></content:encoded>
			<wfw:commentRss>http://blaster.comunidad-itsjr.com.mx/archives/272/feed</wfw:commentRss>
		</item>
		<item>
		<title>Un poco sobre permisos en sistemas Unix/Linux</title>
		<link>http://blaster.comunidad-itsjr.com.mx/archives/271</link>
		<comments>http://blaster.comunidad-itsjr.com.mx/archives/271#comments</comments>
		<pubDate>Tue, 10 Jun 2008 01:50:08 +0000</pubDate>
		<dc:creator>blaster</dc:creator>
		
		<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://blaster.comunidad-itsjr.com.mx/?p=271</guid>
		<description><![CDATA[En los sistemas basados en Unix los archivos poseen importantes atributos que rigen su comportamiento con respecto a los usuarios, los permisos. Estos se dividen en 3 niveles, permisos de propietario, permisos de grupo y permisos para el resto del mundo. Dentro de cada nivel hay 3 tipos de permisos: lectura, escritura y ejecución.
Los permisos [...]]]></description>
			<content:encoded><![CDATA[<p>En los sistemas basados en Unix los archivos poseen importantes atributos que rigen su comportamiento con respecto a los usuarios, los permisos. Estos se dividen en 3 niveles, permisos de propietario, permisos de grupo y permisos para el resto del mundo. Dentro de cada nivel hay 3 tipos de permisos: lectura, escritura y ejecución.</p>
<p>Los permisos de lectura controlan si un usuario puede visualizar un archivo, los permisos de escritura determinan si un usuario puede realizar cambios en un archivo y los permisos de ejecución controlan si un usuario puede iniciar o ejecutar un archivo. Cuando se aplican a un directorio, si el permiso de ejecución está desactivado significa que no se puede ejecutar el comando cd sobre el mismo, no se puede visualizar el contenido y no se pueden realizar cambios, si el permiso de lectura está desactivado, se puede crear y leer archivos pero no se puede obtener un listado del contenido del mismo y si el permiso de escritura está desactivado se puede visualizar un listado del contenido y leer archivos, pero no se pueden crear nuevos archivos.</p>
<p>Para ver los permisos de los arhivos podemos usar el comando <span style="font-style: italic;">ls -l </span>esto nos proporcionará un listado en el que se asocian permisos con archivos. En cada archivo encontraremos una cadena del estilo siguiente:</p>
<blockquote style="font-style: italic;"><p>-rw-rwx-r&#8211;<br />
drwxrwxr&#8211;</p></blockquote>
<p>El primer caracter determina si es un archivo &#8216;-&#8217; o un directorio &#8216;d&#8217;, los primeros 3 son los permisos del propietario, los 3 siguientes del grupo y los 3 últimos del resto del mundo.</p>
<p>Para modificar los permisos de un archivo tenemos el comando <span style="font-style: italic;">chmod. </span>Este comando tiene dos modos de uso a los que llamaremos implícito y explícito:</p>
<p><span style="font-size: 180%;"><span style="font-weight: bold;"><br />
Modo Explícito</span></span></p>
<p>Este modo lo he denominado así debido a que su sintaxis expresa de manera clara los cambios que se realizan en los archivos. Tiene el siguiente formato:</p>
<p><span style="font-style: italic;"></p>
<blockquote><p>chmod &#8220;nivel&#8221; &#8220;acción&#8221; &#8220;permiso&#8221; &#8220;nombre de archivo&#8221; &#8220;nombre de archivo&#8221;</p></blockquote>
<p></span></p>
<p><span style="font-size: 130%;"><span style="font-weight: bold;">Niveles</span></span></p>
<p>Propietario -     &#8216;u&#8217;<br />
Grupo -     &#8216;g&#8217;<br />
Resto -     &#8216;o&#8217;<br />
Todos -     &#8216;a&#8217;</p>
<p><span style="font-size: 130%;"><span style="font-weight: bold;">Acciones</span></span></p>
<p>Conceder un permiso -&#8217;+&#8217;<br />
Retirar un permiso - &#8216;-&#8217;</p>
<p><span style="font-size: 130%;"><span style="font-weight: bold;">Permisos</span></span></p>
<p>Lectura - &#8216;r&#8217;<br />
Escritura - &#8216;w&#8217;<br />
Ejecución - &#8216;x&#8217;</p>
<p>Así por ejemplo si queremos añadirle permisos de lectura y ejecución a los 3 niveles de un archivo hariamos lo siguiente:</p>
<p><span style="font-style: italic;"></p>
<blockquote><p>chmod a+rx archivo</p></blockquote>
<p></span><br />
Si quisieramos quitarle a un archivo el permiso de lectura al resto del mundo haríamos lo siguiente:</p>
<p><span style="font-style: italic;"></p>
<blockquote><p>chmod o-r archivo</p></blockquote>
<p></span><br />
<span style="font-size: 180%;"><span style="font-weight: bold;">Modo Implícito</span></span></p>
<p>Este método consiste en modificar la máscara de bits que controla realmente los permisos. En esta máscara se asignan 3 bits a cada nivel, cada bit corresponde a un permiso (rwx), con lo cual cada terna funcionará del siguiente modo:</p>
<p>Lectura - 100 = 4<br />
Escritura - 010 =2<br />
Ejecución - 001 = 1</p>
<p>La combinación de estos permisos equivale a un número decimal, luego a la hora de asignar permisos hay que hacer la suma total que nos daría el valor exacto de permisos que tendrá cada nivel. Funcionaría de la siguiente manera:</p>
<blockquote style="font-style: italic;"><p>chmod &#8220;valor propietario&#8221;"valor grupo&#8221;"valor resto&#8221; &#8220;archivo&#8221;</p></blockquote>
<p>De este modo si quisieramos activar los permisos de lectura y escritura del propietario, los de ejecución del grupo y desactivar todos del resto haríamos lo siguiente:</p>
<blockquote style="font-style: italic;"><p>chmod 610 archivo</p></blockquote>
<p>Con lo que la salida del <span style="font-style: italic;">ls</span> sería la siguiente:</p>
<p><span style="font-style: italic;"></p>
<blockquote><p>-rw&#8212;x&#8212;</p></blockquote>
<p></span>Cuando se usa el modo implícito hay que tener en cuenta que estamos modificando todos los permisos de cada nivel así que hay poner correctamente el número para no desactivar permisos sin darnos cuenta.</p>
]]></content:encoded>
			<wfw:commentRss>http://blaster.comunidad-itsjr.com.mx/archives/271/feed</wfw:commentRss>
		</item>
		<item>
		<title>que son los ataques Smurf</title>
		<link>http://blaster.comunidad-itsjr.com.mx/archives/270</link>
		<comments>http://blaster.comunidad-itsjr.com.mx/archives/270#comments</comments>
		<pubDate>Sun, 01 Jun 2008 15:29:24 +0000</pubDate>
		<dc:creator>blaster</dc:creator>
		
		<category><![CDATA[seguridad]]></category>

		<guid isPermaLink="false">http://blaster.comunidad-itsjr.com.mx/?p=270</guid>
		<description><![CDATA[Consiste en mandar paquetes ICMP de &#8220;echo request&#8221; (como los de un ping) con una falsa dirección de origen (la IP de la víctima) a una dirección de difusión (&#8221;broadcast&#8221;). De esta forma alcanzarán muchas máquinas, cada una de las cuales enviará sus paquetes de respuesta a la dirección origen de la petición (cuyos datos [...]]]></description>
			<content:encoded><![CDATA[<p>Consiste en mandar paquetes ICMP de &#8220;echo request&#8221; (como los de un ping) con una falsa dirección de origen (la IP de la víctima) a una dirección de difusión (&#8221;broadcast&#8221;). De esta forma alcanzarán muchas máquinas, cada una de las cuales enviará sus paquetes de respuesta a la dirección origen de la petición (cuyos datos estaban falseados y apuntaban a la víctima). El resultado es que la máquina víctima se ve inundada de paquetes IP, resultando en una saturación de su enlace (algo así como si le hubieran hecho un ping a lo grande).</p>
<p>Desgraciadamente la víctima no puede hacer nada para evitarlo. La solución está en manos de los administradores de red, los cuales deben configurar adecuadamente sus routers para filtrar los paquetes ICMP de petición indeseados (broadcast) o bien configurar sus máquinas para que no respondan a dichos paquetes. Es decir, que lo que se parchea son las máquinas/redes que puedan actuar de intermediarias (inocentes) en el ataque y no la máquina víctima.</p>
<p>De igual forma también se podría evitar el ataque si el router/firewall de salida del atacante (p.ej. el ISP al que pertenece) estuviera convenientemente configurado para evitar spoofing. Esto se haría filtrando todos los paquetes de salida que tuvieran una dirección source (origen) que no perteneciera a la red interna (desde la cual salimos).</p>
<p>Para más información sobre &#8220;smurf&#8221; os remito a:</p>
<p>http://www.quadrunner.com/~c-huegen/smurf.txt</p>
]]></content:encoded>
			<wfw:commentRss>http://blaster.comunidad-itsjr.com.mx/archives/270/feed</wfw:commentRss>
		</item>
		<item>
		<title>ataque DNS Inject</title>
		<link>http://blaster.comunidad-itsjr.com.mx/archives/269</link>
		<comments>http://blaster.comunidad-itsjr.com.mx/archives/269#comments</comments>
		<pubDate>Sun, 01 Jun 2008 15:27:59 +0000</pubDate>
		<dc:creator>blaster</dc:creator>
		
		<category><![CDATA[seguridad]]></category>

		<guid isPermaLink="false">http://blaster.comunidad-itsjr.com.mx/?p=269</guid>
		<description><![CDATA[Con esta técnica conseguimos spoofear nuestro hostname, es decir, que un servidor nos asocie el nombre de host que queramos (y no el que tiene realmente, que es único) (en realidad, puede haber más de uno, pero sólo uno es el real, lo que se conoce como &#8220;canonical name&#8221; mientras que los demás son simples [...]]]></description>
			<content:encoded><![CDATA[<p>Con esta técnica conseguimos spoofear nuestro hostname, es decir, que un servidor nos asocie el nombre de host que queramos (y no el que tiene realmente, que es único) (en realidad, puede haber más de uno, pero sólo uno es el real, lo que se conoce como &#8220;canonical name&#8221; mientras que los demás son simples &#8220;aliases&#8221;).</p>
<p>La explicación detallada es compleja y excede los objetivos de este documento. A título informativo paso a esbozar o perfilar lo que sería el Inject.</p>
<p>Cada servidor (ya sea de IRC, ftp, étc) tiene asociado uno o más &#8220;servidores de nombres&#8221; (NS, del inglés: Name Server) que resuelven todas las peticiones de conexión que le llegan: para cada IP que peticiona conexión buscan y almacenan el hostname correspondiente para su posterior uso. El proceso sería el siguiente:</p>
<p>- un usuario de la máquina A intenta conectarse a un puerto de la máquina B (el servidor IRC, ftp, &#8230;).<br />
- B recibe la dirección IP desde la que peticionamos (la de A) y se la entrega a C (otro host: el NS) para que la resuelva.<br />
- C resuelve y devuelve su respuesta a B.<br />
- B se &#8220;cree&#8221; la respuesta y la cachea en memoria.</p>
<p>Ahora tiene un par IP-hostname. A partir de este momento nosotros estamos identificados en el servidor con el hostname dado anteriormente por el NS.</p>
<p>Como se puede intuir el truco está en forzar al NS a que de una respuesta falsa (siempre en favor nuestro :-)). Digamos que modificamos los datos del NS para que responda a nuestra IP con el hostname que nosotros queremos y no con el que debería hacerlo realmente. Se dice que hemos &#8220;inyectado&#8221; (injectado, en inglés :-P) el NS.</p>
<p>El cómo hacer esto último es lo complicado y sólo voy a decir que el truco se basa en la &#8220;resolución recursiva&#8221; de los NS (cuando un NS no sabe la respuesta a la petición que le ha llegado lanza una nueva petición a otro NS, que posiblemente sí sepa la respuesta, y así sucesivamente &#8211;&gt; de ahí la &#8220;recursividad&#8221;) y en tener finalmente un NS trucado que de respuestas falsas y que nosotros reprogramamos a nuestro gusto.</p>
<p>La principal ventaja es una vez más el anonimato (aparte de poder ir vacilando por el IRC con una identidad del tipo root@nasa.gov :-O).</p>
]]></content:encoded>
			<wfw:commentRss>http://blaster.comunidad-itsjr.com.mx/archives/269/feed</wfw:commentRss>
		</item>
		<item>
		<title>ataque de DNS Spoofing</title>
		<link>http://blaster.comunidad-itsjr.com.mx/archives/268</link>
		<comments>http://blaster.comunidad-itsjr.com.mx/archives/268#comments</comments>
		<pubDate>Sun, 01 Jun 2008 15:05:50 +0000</pubDate>
		<dc:creator>blaster</dc:creator>
		
		<category><![CDATA[seguridad]]></category>

		<guid isPermaLink="false">http://blaster.comunidad-itsjr.com.mx/?p=268</guid>
		<description><![CDATA[Se describe como un servidor DNS que hace uso de información falsa recibida desde un host que no es autoridad para la información. Es una amenaza significativa para la seguridad de las organizaciones que no han tomado medidas para protegerse de ella. El DNS Spoofing puede permitir a los atacantes acceder al correo de un [...]]]></description>
			<content:encoded><![CDATA[<p>Se describe como un servidor DNS que hace uso de información falsa recibida desde un host que no es autoridad para la información. Es una amenaza significativa para la seguridad de las organizaciones que no han tomado medidas para protegerse de ella. El DNS Spoofing puede permitir a los atacantes acceder al correo de un sitio, y puede hacer que los usuarios sean redirigidos a sitios Web incorrectos incluso proporcionando una abertura para un ataque de Negación de Servicio.</p>
<p>Ejemplos de modus operandi:<br />
Escenario: La compañía, TAMJTeK Inc., está compitiendo para acabar el desarrollo del último software de juegos antes de que el capital de la empresa salga. Se comienza a anunciar el aviso pendiente de una brecha en tecnología de este juego en el sitio Web de Internet. Usted tiene una llamada de uno de los socios de la empresa. Ella desea saber por que termina llegando a <a rel="nofollow" href="http://www.hackncrack.net/">http://www.hackncrack.net</a> cuando intenta llegar a <a rel="nofollow" href="http://www.tamjtek.com/">http://www.tamjtek.com</a>. Usted intenta conectarse al sitio Web y, seguro, termina llegando a <a rel="nofollow" href="http://www.hackncrac.net/">http://www.hackncrac.net</a>. Usted prueba algunos otros sitios y todo parece muy bien excepto, que encuentra que su competidor más fuerte ha anunciado una brecha en el mismo juego. Su sitio Web demuestra una imagen de su juego, la cual parece notablemente similar a la suya con aspectos virtualmente idénticos. ¿Coincidencia? Quizás no.</p>
<p>En este año una aplicación desarrollada descubre que un número substancial de compañías en línea son vulnerables a DNS Spoofing. Esta vulnerabilidad hace que el escenario de TAMJTeK Inc. sea posible. Un ejemplo muy conocido de DNS Spoofing ocurrió en 1997 cuando Eugene Kashpureff redirigió a los que intentaban conectarse al registrar de dominios InterNIC y los llevaba a su propio sitio Web AlterNIC. EL señor Kashpureff utilizó el método de agregar un registro de datos falso en la respuesta de la consulta. Más recientemente, el DNS Spoofing y el secuestro de dominios fueron logrados usando solamente correo electrónico y un fax.</p>
<p>Ejemplo 1: Asume los siguientes dos dominios, hackncrack.net y tamjtek.com con las siguientes configuraciones:</p>
<p>Hackncrack.net  (10.0.0.0)          Tamjtek.com (11.0.0.0)<br />
Ns1.hackncrack.net (10.0.0.5)       ns1.tamjtek.com (11.0.0.5)<br />
<a rel="nofollow" href="http://www.hackncrack.net/">http://www.hackncrack.net</a>(10.0.0.6)        <a rel="nofollow" href="http://www.tamjtek.com/">http://www.tamjtek.com</a>(11.0.0.6)</p>
<p>El atacante ha modificado el servidor de nombres Hackncrack para responder a una consulta recursiva para los registros DNS Hackncrack con un falso registro autoritario, mapeando <a rel="nofollow" href="http://www.tamjtek.com/">http://www.tamjtek.com</a> a la dirección IP 10.0.0.6. El atacante entonces dirige una consulta al servidor de nombres TAMJTeK preguntando por los registros DNS sobre el sitio del atacante. El servidor de nombres TAMJTeK resuelve la consulta yendo al servidor de nombres Hackncrack. Desde que el servidor de nombres TAMJTeK no esta protegido contra DNS Spoofing, acepta y almacena el registro falso que incluye la respuesta. Siempre que una consulta se haga al sitio Web de TAMJTeK, el registro para el sitio Web Hacncrack será regresado y todo será redireccionado a <a rel="nofollow" href="http://www.hacckncrack.net/">http://www.hacckncrack.net</a>. El atacante en Hackncrack puede también engañar un registro MX para dirigir el correo de TAMJTeK a su servidor de correo. Un registro falso MX puede desapercibir una cantidad de tiempo significativa si el atacante esta bien informado.</p>
<p>Ejemplo 2: Prediciendo el número de consulta ID, un atacante puede realizar otra adaptación de DNS Spoofing personificando un servidor de nombres. El protocolo DNS usa el protocolo UDP para comunicarse. Dada la naturaleza sin conexión de UDP, DNS es diseñado para establecer comunicaciones ordenadas entre equipos. Esto es logrado identificando datagramas con un número de consulta ID. El host que inicia la consulta asigna este número. En las versiones anteriores de BIND, este se incrementaba secuencialmente para cada nueva consulta. Con este ejemplo, podra observar como el atacante engaña a los usuarios de TAMJTeK.com haciendo parecer que ellos van a <a rel="nofollow" href="http://www.anybank.com/">http://www.AnyBank.com</a> cuando, en realidad, se están conectando a <a rel="nofollow" href="http://www.hackncrack.net/">http://www.Hackncrack.net</a>. El atacante en Hackncrack.net consulta TAMJTeK.com para la información que los atacantes poseen del dominio. El servidor de nombres TAMJTeK resuelve las consultas referidas a Hackncrack.net El servidor de nombres del atacante regresa la información correcta sobre sí mismo a TAMJTeK.com y el servidor de nombres de la víctima lo reenvía al host del atacante que inició la consulta. Para montar este ataque, el intruso tiene que, primero, aprender cual es el número ID de la consulta. Escuchando los datos durante la consulta se puede obtener éste. Una vez que el número ID sea disponible, el atacante hace un datagrama de la respuesta del DNS con información falsa: <a rel="nofollow" href="http://www.anybank.com/">http://www.AnyBank.com</a> = 10.0.0.6 y lo configura como si la fuente fuera ns.AnyBank.com. El atacante inicia una consulta para TAMJTaK.com preguntando por información sobre AnyBank.com e inserta el datagrama modificado en la línea como la respuesta. De nuevo, el servidor de nombres inseguro TAMJTeK.com acepta y almacena los datos. Cuando los usuarios de TAMJTeK intentan conectarse a <a rel="nofollow" href="http://www.anybank.com/">http://www.AnyBank.com</a>, ellos son redirigidos a una página Web específica en el servidor Web Hackncrack que contiene exactamente la información de la página de la cuenta AnyBank.com. En este punto, el atacante puede recolectar cuentas de usuarios y números de PIN a voluntad.</p>
<p>Ejemplo 3: Este ejemplo no describe un ataque DNS Spoofing en el sentido técnico más estricto del término pero, los resultados al final son los mismos y se puede decir que este estilo de ataque tiene el potencial para “envenenar” la caché de cada servidor de nombres en el Internet. Network Solutions Inc. fue el primero y sigue siendo uno de los primeros en registrar nombres de dominio. Durante el proceso de registro, NSI ofrece tres métodos de autorización y autenticación para proteger los registros contra actualizaciones no autorizadas. Estos métodos son colectivamente referidos por NSI como “Guardian”. El contacto personal que esta listado en el registro de nombre de dominio, también es conocido como un Guardian. Estos métodos son:</p>
<p>1. Mail-Form (Mínima Seguridad): El contacto somete una dirección de correo electrónico de la cual toda la administración de registro origine. Cuando un cambio de registro se somete a la NSI vía correo electrónico, la dirección de correo electrónico fuente es comprada con la dirección de correo sometida durante el inicio del dominio original.<br />
2. Cryp-Password (Un poco de Seguridad): Durante la disposición inicial, el contacto escoge una contraseña. Esta contraseña es cifrada y almacenada en la base de datos del NSI. Cuando el administrador somete un cambio de registro, la versión en texto plano de la contraseña es incluida. NSI cifra el texto plano de la contraseña que acompaña la petición de cambio y la compara con la original.<br />
3. PGP (Más Seguridad): NSI soporta mensajes cifrados con PGP si se originaron desde una plataforma Unix. Ninguna otra plataforma es soportada en este momento.</p>
<p>Los nombres conocidos como Nike, Net Media, Web Networks, Exodus y el Consorcio World Wide Web han sido afectados por la trampa del proceso de autentificación de la actualización de registros DNS. Durante un incidente, las pertenencias de Internet.com y otros 1300 dominios fueron transferidos lejos de Net Media cuando NSI recibió un fax que consistía en documentos falsos. Llevó varios días para que el dueño legal de los documentos retomara el control de los mismos. Imagine el estrago de algunos que justo al inicio de leer el correo electrónico corporativo, fueron redirigidos durante la confusión. Obviamente, cuanto más seguro el proceso de autentificación, más seguros los registros del dominio.</p>
<p>Una posible solución sería eliminar las relaciones de confianza basadas en la dirección IP o el nombre de las máquinas, sustituyéndolas por relaciones basadas en claves criptográficas; el cifrado y el filtrado de las conexiones que pueden aceptar nuestras máquinas también son unas medidas de seguridad importantes de cara a evitar el spoofing.</p>
<p>Fuentes:<br />
<a rel="nofollow" href="http://www.ibiblio.org/pub/linux/docs/LuCaS/Manuales-LuCAS/doc-unixsec/unixsec-html/node274.html">http://www.ibiblio.org/pub/linux/docs/LuCaS/Manuales-LuCAS/doc-unixsec/unixsec-html/node274.html</a><br />
<a rel="nofollow" href="http://www.seguridad.unam.mx/labsec/tuto/?id=135&amp;ap=articulo&amp;cabecera=2">http://www.seguridad.unam.mx/labsec/tuto/?id=135&amp;ap=articulo&amp;cabecera=2</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blaster.comunidad-itsjr.com.mx/archives/268/feed</wfw:commentRss>
		</item>
		<item>
		<title>Introducción al editor de textos más usado en UNIX (vi)</title>
		<link>http://blaster.comunidad-itsjr.com.mx/archives/266</link>
		<comments>http://blaster.comunidad-itsjr.com.mx/archives/266#comments</comments>
		<pubDate>Wed, 21 May 2008 15:02:42 +0000</pubDate>
		<dc:creator>blaster</dc:creator>
		
		<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://blaster.comunidad-itsjr.com.mx/?p=266</guid>
		<description><![CDATA[vi es un EDITOR, no un PROCESADOR DE TEXTOS. Está hecho para escribir y modificar ficheros de texto sencillos, programas, etc. No permite justificar párrafos, utilizar distintos tipos de letra, escribir a varias columnas, insertar gráficos, etc. No hay ningún programa de estas características que se proporcione con UNIX. Normalmente, es necesario adquirirlos por separado.
El [...]]]></description>
			<content:encoded><![CDATA[<p>vi es un EDITOR, no un PROCESADOR DE TEXTOS. Está hecho para escribir y modificar ficheros de texto sencillos, programas, etc. No permite justificar párrafos, utilizar distintos tipos de letra, escribir a varias columnas, insertar gráficos, etc. No hay ningún programa de estas características que se proporcione con UNIX. Normalmente, es necesario adquirirlos por separado.</p>
<p>El editor <em>vi</em> es el más utilizado en ordenadores que utilizen el sistema operativo UNIX. Los usuarios no informáticos lo consideran demasidao complicado, sobre todo acostumbrados a los editores del sistema operativo DOS. Por eso se tiende a considerarlo muy atrasado, sin embargo es realmente potente. Su dificultad de manejo se justifica por las características de los terminales que había cuando fue diseñado y porque un objetivo primordial de su diseñador fue que pudiera ser utilizado en casi cualquier tipo de terminal por lo que no requiere el uso de teclas especiales, como las de movimiento del cursor o las de función (aunque en la mayoría de los terminales, las teclas de flechas sí se pueden utilizar, si se desea). Claro, esto es a costa de su sencillez de manejo. Es más sencillo para un usuario pulsar, por ejemplo, la tecla <code>F10</code> para grabar el fichero que <code>:w</code>.</p>
<h2><a name="2">Comandos e introducción de texto</a></h2>
<p>Por tanto, queda claro que no se pueden usar las teclas de función. En el <em>vi</em> a muchas funciones (como grabar fichero, borrar líneas, etc) se accede de dos formas posibles:</p>
<dl>
<dt><strong><strong>Usando la tecla <code>Ctrl</code></strong></strong></dt>
<dd>Pulsar esa tecla (también llamada <em>Control</em>) junto con otra tecla alfabética. Por ejemplo, si dejo pulsada la tecla <code>Ctrl</code> mientras pulso <code>f</code>, avanzaré una página en mi documento. Hay que hacer notar que esto es posible porque todos los terminales generan el mismo código numérico al pulsar <code><code>Ctrl</code></code> junto con una letra, por tanto no hay problema de incompatibilidad entre fabricantes,</p>
</dd>
<dt><strong><strong>Usando comandos compuestos de teclas normales</strong></strong></dt>
<dd>Estos ultimos requieren una explicación. A base de utilizar sólo comandos compuestos por la tecla <code>Ctrl</code> y otra letra alfabética, tengo sólo 26 posibilidades (a&#8230;z) ya que <code>Ctrl-a</code> genera el mismo código que <code>Ctrl-A</code> (aquí no hay diferencia entre minúsculas y mayúsculas).  Si no puedo usar las teclas de función ni otras especiales (por incompatibilidad entre fabricantes), ¿cómo puedo accder a las muchas funciones que tiene el editor? Pues mediante teclas normales. Pero si me dicen que el símbolo <code>$</code> significa <em>ir al final de la línea</em>, esto no parece lógico, porque si pulso ese carácter, aparecerá en la pantalla tal como lo escribo.</p>
</dd>
</dl>
<p>Por eso el <em>vi</em> tiene dos modos de funcionamiento, entre los cuales el usuario debe alternar continuamente durante una sesión de edición:</p>
<dl>
<dt><strong><strong>Modo edición</strong></strong></dt>
<dd>Todo lo que escribo, aparece en pantalla, como es habitual en todos los editores.</p>
</dd>
<dt><strong><strong>Modo comando</strong></strong></dt>
<dd>Lo que escribo estando en este modo (al cual se accede pulsando la tecla <code>ESC</code>, llamada también <em>escape</em>), las teclas tienen un significado especial. Por ejemplo, <code>$</code> mueve el cursor hasta el final de la línea, <code>j</code> lo mueve una línea hacia abajo, <code>:w</code> graba el fichero, <code>:q</code> es para salir del editor.</p>
</dd>
</dl>
<p>Del modo <em>edición</em> se pasa al modo comando usando la tecla <code>ESC</code>. Del modo <em>comando</em> se pasa al modo edición con alguna de las siguientes teclas:  <code>i</code>,<code>I</code>,<code>a</code>,<code>A</code>,<code>o</code>,<code>O</code> (y alguna otra).</p>
<p>Hay que tener presente que al entrar en el editor <em>vi</em>, el modo inicial es el <strong>MODO COMANDO</strong>.</p>
<h2><a name="3">Entrada al editor <em>vi</em></a></h2>
<p>Si estamos en un terminal trabajando con un ordenador central que funcione con el sistema operativo UNIX (en cualquiera de sus muchas variantes), usaremos el programa <em>vi</em> para editar un fichero con el siguiente comando:</p>
<pre>vi fichero</pre>
<p>Tras ejecutar ese comando, se borra la pantalla y, si el fichero ya existía previemente, aparece su contenido. Si no existía, quedan todas las líneas de la pantalla vacías pero con una tilde (~) al principio. Con esa tilde representa el <em>vi</em> las líneas que están vacías.</p>
<p>Si no ocurre de esta forma y la pantalla queda desencajada, el problema puede estar relacionado con la variable <code>TERM</code>. Véase <a href="http://www.uco.es/sistemas/terminales_unix.html">Manejo de terminales en UNIX</a> para saber cómo solucionarlo.</p>
<p>Como dijimos antes, nada más entrar en el <em>vi</em>, estamos en el <strong>MODO COMANDO</strong>. Podemos usar aquí cualquiera de los comandos que veremos más adelante aplicables en este modo (y que están resumidos al final de este documento). Si queremos escribir algo en el fichero, iremos (en el modo comando) al lugar donde deseamos empezar a escribir y pulsaremos una de las teclas que nos pasan al <strong>MODO EDICION</strong>. En ese momento, todo lo que escribamos aparecerá en la pantalla.</p>
<p>Una cosa que hay que tener en cuenta en el manejo del <em>vi</em> es que conviene estar el máximo tiempo posible en el modo COMANDO, pues así las modificaciones no deseadas en el texto son menores. En cuanto terminemos de escribir, debemos pulsar <code>ESC</code> para ir al modo comando. Si queremos editar en otra parte del fichero, iremos a esa parte en este modo y en ahí pasaremos de nuevo al modo edición.</p>
<h2><a name="4">Primeros comandos</a></h2>
<p>Antes que nada, tendremos que empezar a escribir algo en un fichero. Si vamos a llamar a este con el nombre <em>primero</em>, ejecutamos desde UNIX:</p>
<pre>vi primero</pre>
<p>Al pulsar la tecla <em>INTRO</em> aparece la pantalla vacía con una tilde al principio de cada línea. Estamos en modo comando, por lo que para comenzar a escribir hay que pasar al modo edición. La forma más habitual de hacer esto es con el comando <code>i</code>. Al pulsar esa letra, no ocurre nada, no vemos ningún cambio en la pantalla, pero el modo a cambiado al de EDICION.</p>
<p>Comenzamos ahora a escribir y el texto va apareciendo en la pantalla. Si escribimos más letras de las que caben en el ancho de la misma (normalmente 80 caracteres), continuarán por la línea siguiente.</p>
<p>Si nos equivocamos en una letra, podemos usar la tecla de borrado (normalmente tiene la inscripción <code>&lt;-</code> o <code>Backspace</code>) para eliminar la última letra escrita. Si seguimos pulsando la tecla, borraremos las letras anteriores. Pero sólo podemos borrar así las últimas que hayamos escrito. Si escribimos un texto, luego pasamos al modo comando para hacer algo, y luego otra vez al modo edición, la tecla de borrado no me sirve para borrar lo que escribí antes. Habrá que moverse al sitio donde quiero borrar y usar el comando para ello. Algunos de los comandos que usaremos para estas operaciones (todos ellos se utilizan en MODO COMANDO) son (atención a la diferencia entre mayúsculas y minúsculas):</p>
<table border="1">
<tbody>
<tr>
<td><code>i</code></td>
<td>Pasar a modo EDICION (ya se ha explicado)</td>
</tr>
<tr>
<td><code>h</code></td>
<td>Desplaza el cursor una posición a la izquierda</td>
</tr>
<tr>
<td><code>j</code></td>
<td>Idem a la línea inferior</td>
</tr>
<tr>
<td><code>k</code></td>
<td>Idem a la línea superior</td>
</tr>
<tr>
<td><code>l</code></td>
<td>Idem una posición a la derecha</td>
</tr>
<tr>
<td><code>^f</code></td>
<td>Desplaza el cursor una pántalla hacia adelante (unas 24 líneas)</td>
</tr>
<tr>
<td><code>^b</code></td>
<td>Idem hacia atrás</td>
</tr>
<tr>
<td><code>^g</code></td>
<td>Nos informa del nombre del fichero que estamos editando, del número de la línea en la que estamos, y del número total de líneas del fichero.</td>
</tr>
<tr>
<td><code>G</code></td>
<td>Ir al final del fichero.</td>
</tr>
<tr>
<td><code>1G</code></td>
<td>Ir al principio del fichero.</td>
</tr>
<tr>
<td><code>x</code></td>
<td>Borra el carácter sobre el que está el cursor</td>
</tr>
<tr>
<td><code>dd</code></td>
<td>Borra la línea sobre la que está el cursor</td>
</tr>
<tr>
<td><code>^</code></td>
<td>Desplaza el cursor al principio de la línea actual</td>
</tr>
<tr>
<td><code>$</code></td>
<td>Idem al final de la línea</td>
</tr>
<tr>
<td><code>:w!</code></td>
<td>Graba el fichero (y seguimos dentro del <em>vi</em>)</td>
</tr>
<tr>
<td><code>:q!</code></td>
<td>Salir del editor, sin grabarlo previamente</td>
</tr>
<tr>
<td><code>:wq!</code></td>
<td>Salir del editor, grabando previamente el fichero</td>
</tr>
<tr>
<td></td>
</tr>
</tbody>
</table>
<p>En la mayoría de terminales, se pueden usar las teclas de flechas en lugar de <code>h</code>, <code>j</code>, <code>k</code>, <code>l</code>. Hay que aclarar dos cosas en esta lista:</p>
<p>En primer lugar, usaremos la nomenclatura <code>^f</code> para indicar que se mantiene pulsada la tecla <code><code>Ctrl</code></code> mientras pulsamos <code>f</code>.</p>
<p>En segundo lugar, el comando <code>1G</code> es especial porque lleva un número al  comienzo. Cuando ocurre esto, se considera como si dijéramos <em>ejecuta el comando G con el argumento 1</em>. Casi todos los comandos pueden llevar un número delante. En el caso del comando <code>G</code>, el número indica a qué línea del fichero queremos ir. Así, <code>1G</code> significa <em>ir a la línea 1</em>, <code>20G</code> es ir a la línea 20. Una sóla <code>G</code> indica <em>ir a la última línea</em>.</p>
<p>En la mayoría de los comandos, un número precediendo al comando significa <em>ejecuta n veces este comando</em>. Así, si <code>dd</code> significa <em>borrar una línea</em>, <code>5dd</code> significa <em>borrar 5 líneas</em> (la actual y las cuatro siguientes).</p>
<p>Los comandos que se ejecutan en modo comando no aparecen por pantalla, a excepción de los que empiezan por <code>/</code>,<code>?</code> o <code>:</code></p>
<h2><a name="5">Otros comandos para pasar al modo edición</a></h2>
<p>Ya hemos mencionado que para entrar en el modo edición se usa el comando <code>i</code> (de insertar). Al pulsarlo, lo que escribamos se añade justo donde está el cursor. A veces, debemos usar otro comando. Este es el caso de tener que añadir texto al final de una línea. Si tenemos una línea tal como la siguiente:</p>
<pre>En un lugar de la Mancha</pre>
<p>Si nos desplazamos al final para añadir lo que falta, el cursor no pasará más allá de la última <em>a</em> (nunca se puede mover el cursor después del último  carácter de una línea). Si ahora pulsamos <code>i</code> y escribimos un texo, éste se insertará entra la <code>h</code> y la <code>a</code>. Lo que queremos en este caso no es INSERTAR, sino AÑADIR. Para ello se usa el comando <code>a</code>. Al introducirlo, el cursor -que estaba, recordemos, encima de la <em>o</em>- se sitúa después de esta letra, permitiéndonos escribir ahí.</p>
<p>Otro caso que se puede presentar es la nedesidad de escribir texto ANTES de la primera línea. ¿Cómo podemos hacerlo?. Si pulsamo <code>i</code>, insertamos texto en la línea actual. Se podría hacer lo siguiente:</p>
<ul>
<li>Situar el cursor al principio de la primera línea</li>
<li>Pulsar <code>i</code> para insertar</li>
<li>Pulsar INTRO para insertar una línea en blanco</li>
<li>Pulsar ESC para pasar al modo comando</li>
<li>Pulsar <code>k</code> (o flecha arriba) para subir a la línea anterior</li>
<li>Pulsar <code>i</code> para insertar</li>
</ul>
<p>Ya hemos abierto una línea y podemos escribir. Pulsando <em>INTRO</em> podemos abrir más líneas si queremos. Para evitar esa secuencia tan tediosa, hay otro comando significa <em>abrir una línea antes de la que está el cursor y pasar en ella al modo edición</em>. Este comando es <code>O</code> (o mayúscula).</p>
<p>Un comando relacionado es <code>o</code> (o minúscula) que significa <em>abrir una línea después de la actual y pasar en ella al modo edición</em>. La usaremos por ejemplo para añadi líneas al final del fichero.</p>
<p>Resumimos los comandos para pasar al modo edición (hay alguno más pero estos son los más habituales):</p>
<table border="1">
<tbody>
<tr>
<td><code>i</code></td>
<td>Insertar texo delante de donde está el cursor</td>
</tr>
<tr>
<td><code>a</code></td>
<td>Añadir texto a continuación de donde está el cursor</td>
</tr>
<tr>
<td><code>O</code></td>
<td>Abrir una línea antes de la actual y editar en ella</td>
</tr>
<tr>
<td><code>o</code></td>
<td>Abrir una línea después de la actual y editar en ella</td>
</tr>
<tr>
<td></td>
</tr>
</tbody>
</table>
<p>Practiquemos con un ejemplo. Tenemos el texto:</p>
<pre>Con diez cañones por banda,
No cruza el mar sino vuela,
un velero bergantín.</pre>
<p>Evidentemente, falta el segundo verso. Si queremos escribirlo ahora, vamos a indicar tres formas de hacerlo (suponemos que estamos en modo comando):</p>
<dl>
<dt><strong><strong>Forma 1</strong></strong></dt>
<dd>
<ol>
<li>Ir a la primera línea.</li>
<li>Ir al final de ella (con <code>$</code> o pulsando <code>l</code> hasta llegar al final)</li>
<li>Pulsar <code>a</code> para añadir</li>
<li>Pulsar <em>INTRO</em>. Esto inserta un salto de línea, o sea, una línea nueva y deja el cursor al principio de la misma. Ya podemos escribir</li>
</ol>
</dd>
<dt><strong><strong>Forma 2</strong></strong></dt>
<dd>
<ol>
<li>Ir a la primera línea</li>
<li>Pulsa <code>o</code>. Esto inserta una línea debajo y pone el cursor en ella. Ya podemos escribir.</li>
</ol>
</dd>
<dt><strong><strong>Forma 3</strong></strong></dt>
<dd>
<ol>
<li>Ir a la segunda línea</li>
<li>Pulsar <code>O</code>. Esto inserta una línea encima de la actual y pone el cursor en ella. Ya podemos escribir.</li>
</ol>
</dd>
</dl>
<h2><a name="6">Borrar y copiar</a></h2>
<p>En cualquier editor, las operaciones de borrado y copiado de texto son muy importantes, pues se usan muy a menudo. Ya mencionamos en el apartado 3 algunos comandos para borrar. Damos aquí una lista más amplia:</p>
<table border="1">
<tbody>
<tr>
<td><code>x</code></td>
<td>Borra el carácter sobre el que está el cursor.</td>
</tr>
<tr>
<td><code>dd</code></td>
<td>Borra la línea en la que está el cursor.</td>
</tr>
<tr>
<td><code>d$</code></td>
<td>Borra desde el cursor hasta el final de la línea.</td>
</tr>
<tr>
<td><code>J</code></td>
<td>Une, al final de la línea actual, la siguiente (borra la separación entre ambas).</td>
</tr>
<tr>
<td><code>:1,10d</code></td>
<td>Borra las líneas 1 a la 10.</td>
</tr>
<tr>
<td><code>:10,$d</code></td>
<td>Borra las líneas desde la número 10 hasta la última.</td>
</tr>
<tr>
<td><code>:,$d</code></td>
<td>Borra las líneas comprendidas entre la actual y la última.</td>
</tr>
<tr>
<td></td>
</tr>
</tbody>
</table>
<p>Para copiar texto de un sitio del fichero a otro, primero hay que marcar el texto que vamos a copiar, luego ir al sitio donde queremos copiarlo, y dar la orden de copia. Esta orden de copia es el comando <code>p</code>. Hay varia formas de marcar el texto que queremos copiar. Por ejemplo:</p>
<table border="1">
<tbody>
<tr>
<td><code>Y</code></td>
<td>Marca la línea actual.</td>
</tr>
<tr>
<td><code>3Y</code></td>
<td>Marca tres líneas (la actual y las dos siguientes).</td>
</tr>
<tr>
<td><code>:1,y</code></td>
<td>Marca desde la primera línea hasta la actual.</td>
</tr>
<tr>
<td><code>:,$y</code></td>
<td>Marca desde la línea actual hasta el final.</td>
</tr>
<tr>
<td></td>
</tr>
</tbody>
</table>
<p>Por ejemplo, si tenemos el texto:</p>
<pre>Con diez cañones por banda,
viento an popa a toda vela.
No cruza el mar sino vuela,
un velero bergantin.</pre>
<p>Queremos copiar las dos primeras líneas al final del texto. Para ello, situamos el cursor en la primera línea (se supone que estamos en modo comando; para asegurarnos, no está de más pulsa la tecla ESC) y usamos el comando <code>2Y</code> (marcar dos líneas). A continuación, movemos el cursor hasta la última línea y usamos el comando <code>p</code> (este comando añade las líneas marcadas en la línea SIGUIENTE a la que está el cursor).</p>
<p>Si queremos copiar de la línea actual sólo lo que hay desde el cursor hasta el final, marcamos eso con <code>y$</code>. Para marcar desde el principio de la línea hasta el cursor: <code>y^</code>. Luego vamos al sitio donde queramos pegarlo y usamos el comando <code>p</code>.</p>
<h2><a name="7">Rangos de líneas</a></h2>
<p>En algunos comandos, como vimos por ejemplo en el caso de <code>dd</code>, podemos indicar el rango de líneas en que hay que aplicarlo. Por ejemplo, <code>10dd</code> significa borrar 10 líneas (la actual y las 9 siguientes). ¿Y si queremos borrar todas las líneas desde donde estamos hasta el final del fichero? No es necesario contar cuántas son, pues podemos hacer <code>:,$d</code></p>
<p>El comando <code>:d</code> también sive para borrar líneas. A la mayoría de los comandos que comienzan por <code>:</code>,<code>/</code>,<code>?</code> podemos aplicar un rango de líneas a las que queremos aplicar el comando. Ese rango puede ser o un número de línea o un par de ellas separadas por coma. Si dejamos una sin número, indica la línea actual. Un signo <code>$</code> indica la última línea. Ejemplos:</p>
<table border="1">
<tbody>
<tr>
<td><code>:1,d</code></td>
<td>Borra desde la primera línea hasta la actual</td>
</tr>
<tr>
<td><code>:1,$d</code></td>
<td>Borra todo el fichero</td>
</tr>
<tr>
<td><code>:,$d</code></td>
<td>Borra desde la línea actual al final</td>
</tr>
<tr>
<td><code>:1,10d</code></td>
<td>Borra las 10 primeras líneas</td>
</tr>
<tr>
<td></td>
</tr>
</tbody>
</table>
<p>Puede haber un problema si queremos borrar un tango de líneas pero no sabemos cuáles son sus números. Para ello el <em>vi</em> tiene un comando que hace que todas las líneas aparezcan en pantalla numeradas:</p>
<pre>:set number</pre>
<p><em>vi</em> tiene unos cuantos comandos para activar y desactivar determinadas características. Una lista exhaustiva se da al final de este manual. Si se desea usar siempre el <em>vi</em> con las líneas numeradas, en vez de escribi siempre el comando, se puede añadir esa línea al fichero <code>.exrc</code> de nuestro directorio actual.</p>
<p>Hemos visto cómo referirnos a la primera línea, a la última, la actual y a cualquier línea por su número. También podemos indicar líneas por su posición relativa a la actual:</p>
<table border="1">
<tbody>
<tr>
<td><code>:,+5d</code></td>
<td>Borrar la línea actual y las cinco siguientes.</td>
</tr>
<tr>
<td><code>:-2,+2y</code></td>
<td>Marca desde dos líneas antes de la actual hasta dos después</td>
</tr>
<tr>
<td></td>
</tr>
</tbody>
</table>
<h2><a name="8">Búsqueda y sustitución</a></h2>
<p>El editor <em>vi</em> es bastante potente en lo que se refiere a búsqueda y sustitución de texto, pues no se limita a palabras exactas, sino que puede tratar con patrones. Podemos pedirle, por ejemplo, que busque las líneas que comienzan por un número, o las palabras que tienen 7 caracteres, etc. La sintaxis de estos patrones es algo complicada, pero no está de más aprenderla si se va a trabajar frecuentemente con UNIX, pues muchos otros programas utilizan una sintaxis muy semejante. Los comandos para buscar son:</p>
<table border="1">
<tbody>
<tr>
<td><code>/</code></td>
<td>Buscar hacia adelante (desde el cursor hasta el final del fichero)</td>
</tr>
<tr>
<td><code>?</code></td>
<td>Buscar hacia atrás (desde el cursor al principio del fichero)</td>
</tr>
<tr>
<td></td>
</tr>
</tbody>
</table>
<p>Al usar cualquiera de estos comandos, aparece en la última línea de la pantalla dicho comando (sea <code>/</code> o <code>?</code>) y el cursor a continuación. Ahí debemos introducir lo que queremos buscar, e INTRO a continuación. Si el texto o patrón es encontrado, el cursor se posicionará en él. Pulsando sucesivamente <code>/</code> o <code>?</code> seguidos de <em>INTRO</em> (es decir, sin introducir texto de búsqueda), se localizará la siguiente (en caso de /) o anterior (en caso de ?) ocurrencia del texto buscado.</p>
<p>La explicación de los patrones de búsqueda está más allá de este texto (está explicada en la página de manual UNIX del comando <code>ed</code>; se puede ver con la orden orden <code>man ed</code>), pero debemos explicar algunas cosas. Por ejemplo, el patrón</p>
<pre> ^[0-9]:</pre>
<p>buscará las líneas que comienzen (esto se indica con <code>^</code>) por un dígito (indicado por <code>[0-9]</code>) y luego el carácter <code>:</code>. otro ejemplo:</p>
<pre> ^.. ...$</pre>
<p>Busca las líneas compuestas unicamente por dos caracteres, un espacio y 3 caracteres más. El carácter <code>^</code> indica el comienzo de línea; el <code>$</code> indica el final de línea y el punto un carácter cualquiera. Así estamos indicando que entre el principio y el final sólo debe haber dos caracteres cualesquiera, un espacio y otros tres caracteres.</p>
<p>El problema que se plantea es cuando queremos buscar el texto</p>
<pre> 100$</pre>
<p>Si lo buscamos con /100$, el signo $ se interpretará como fin de línea.  Nosotros no queremos que sea así, sino buscar en el texto ese carácter. El mismo problema tenemos con los signos que tienen un sentido especial (como <code>^</code>,<code>[</code>,<code>]</code>,<code>.</code>). Estos caracteres deben ir con el signo <code>[bsol  ]</code> delante para que se tomen literalmente, sin su sentido especial. Así para buscar <code>100$</code></p>
<p>sería:</p>
<pre>/100\$</pre>
<p>Esto se aplica a los siguientes caracteres:</p>
<pre>     ^ $ . [ ] / \</pre>
<p>Para <code>SUSTITUIR</code> texto, se usa el comando:</p>
<pre> :s/texto a buscar/texto sustituto/</pre>
<p>Al introducir <code>:s</code>, el cursor va a la última línea de la pantalla y ahí escribimos el resto del comando. Eso sustituirá en la línea actual el <em>texto a buscar</em> por <em>texto sustituido</em>. Si queremos hacer esta operación en todo el fichero, haremos:</p>
<pre> :1,$s/texto a buscar/texto sustituto/</pre>
<p>Vemos que entre el carácter <code>:</code>y la letra <code>s</code> podemos indicar el rango de líneas.</p>
<p>El comando <code>s</code> sustituye, como hemos dicho, un texto por otro, pero sólo la primera vez que aparezca el <em>texto a buscar</em> en cada línea. Si queremos sustituir todas las veces que aparezca, añadimos al final <code>g</code>:</p>
<pre> :1,$s/texto a buscar/texto sustituto/g</pre>
<p>Como ya hemos dicho, en la página del manual del comando <code>ed</code> se explica todo esto en más profundidad.</p>
<h2><a name="9">Otras posibilidades</a></h2>
<p>Algunas de las muchas posibilidades adicionales que permite el <em>vi</em>, pero que no vamos a detallar son:</p>
<dl>
<dt><strong><strong>Registros</strong></strong></dt>
<dd>Los registros son como zonas de memoria donde podemos guardar trozos de texto para pegarlos en otros lugares. Ya vimos cómo hacer esto con los comandos <code>Y</code>, <code>y</code> y <code>p</code>, pero sólo con un trozo a la vez.</p>
</dd>
<dt><strong><strong>Marcar lugares del texto</strong></strong></dt>
<dd>Podemos marcar puntos determinados del texto y movernos de unos a otros de forma sencilla.</p>
</dd>
<dt><strong><strong>Macros</strong></strong></dt>
<dd>Si hay secuencias de teclas que repetimos muy a menudo, podemos definir un comando especial que realice todos ellos con sólo dar ese comando.</p>
</dd>
</dl>
<p>Por último, en la siguiente table mencionamos algunos comandos útiles (atención a la mayúsculas y minúsculas, ya que al no ser comandos que se usan con la tecla <code><code>Ctrl</code></code> esto es importante):</p>
<table border="1">
<tbody>
<tr>
<td><code>.</code></td>
<td>Repite el último comando.</td>
</tr>
<tr>
<td><code>u</code></td>
<td>Deshacer el último cambio (undo).</td>
</tr>
<tr>
<td><code>J</code></td>
<td>Pega la línea siguiente al final de la actual.</td>
</tr>
<tr>
<td><code>%</code></td>
<td>Si usamos este comando cuando el cursor está situado sobre alguno de estos caracteres: <code>(</code>,<code>{</code>,<code>[</code> o sus correspondiente cerrados, el cursor se va hacia el lugar del documento donde esté el que lo cierra (o abre). Esto es muy interesante cuando se están editando programas.</td>
</tr>
<tr>
<td><code>:e</code>fichero</td>
<td>Abandonar el documento actual y cargar el otro <code>fichero</code>. Si no hemos grabado el actual, no nos lo permitirá a menos que usemos el comando <code>:e! fichero</code>.</td>
</tr>
<tr>
<td><code>:r</code>fichero</td>
<td>Carga el contenido del <code>fichero</code> en el lugar del documento actual donde esté el cursor.</td>
</tr>
<tr>
<td><code>:w fichero</code></td>
<td>Grabar el documento con el nombre <code>fichero</code> (que puede no coincidir con el nombre de que estamos editando).</td>
</tr>
<tr>
<td><code>:,$w fichero</code></td>
<td>Grabar desde la línea actual hasta el final en el <code>fichero</code>.</td>
</tr>
<tr>
<td><code>:n</code></td>
<td>Si hemos ejecutado el <em>vi</em> con varios nombres, por ejemplo: <code>vi *.c</code>, con este comando abandonamos el actual y pasamos a editar el siguiente. Si no hemos grabado el actual no nos lo permitirá a menos que usemos <code>:n!</code>.</td>
</tr>
<tr>
<td><code>^l</code></td>
<td>Si aparecen mensajes por la pantalla o ésta se queda desajustada, con este comando la <em>refrescamos</em>.</td>
</tr>
<tr>
<td><code>c$</code></td>
<td><em>Cambiar hasta el final de la línea</em>. Tras escribir este comando, todo lo que escribamos a continuación hasta que pulsemos <code>ESC</code> sustituirá a lo que había desde el cursor hasta el final de la línea.</td>
</tr>
<tr>
<td><code>c^</code></td>
<td>Lo mismo pero sustituirá a lo que hay desde el principio de la línea hasta el cursor.</td>
</tr>
<tr>
<td><code>cw</code></td>
<td>Lo mismo pero sustituirá a la palabra sobre la que está el cursor.</td>
</tr>
<tr>
<td><code>:!sh</code></td>
<td>Ejecutar una subshell donde podemos escribir comandos del sistema operativo. Cuando la abandonemos (con <code>exit</code>) volvemos al <em>vi</em>.</td>
</tr>
<tr>
<td></td>
</tr>
</tbody>
</table>
<p>Para terminar, admitir que a pesar de su potencia es difícil dominar todo lo que hemos visto, y difícil es explicarlo, pero creo que se entiende facilmente la lógica de sus comandos, y a veces aunque no se sepa qué comando existe para hacer algo, se puede deducir. Por ejemplo, ¿ cómo marco la palabra actual y las tres siguientes para pegarlas en otro lado? No es difícil pensar que será el mismo comando para marcar una palabra, <code>yw</code> repetida tres veces, por tanto: <code>3yw</code>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blaster.comunidad-itsjr.com.mx/archives/266/feed</wfw:commentRss>
		</item>
		<item>
		<title>Qué es la normalización de bases de datos y para que sirve ?</title>
		<link>http://blaster.comunidad-itsjr.com.mx/archives/265</link>
		<comments>http://blaster.comunidad-itsjr.com.mx/archives/265#comments</comments>
		<pubDate>Sun, 27 Apr 2008 01:49:53 +0000</pubDate>
		<dc:creator>blaster</dc:creator>
		
		<category><![CDATA[Bases de datos]]></category>

		<guid isPermaLink="false">http://blaster.comunidad-itsjr.com.mx/?p=265</guid>
		<description><![CDATA[ Normalización es un conjunto de reglas que sirven para ayudar a los diseñadores a desarrollar un esquema que minimice los problemas de lógica. Cada regla está basada en la que le antecede. La normalización se adoptó porque el viejo estilo de poner todos los datos en un solo lugar, como un archivo o una [...]]]></description>
			<content:encoded><![CDATA[<p><span class="latestforum" style="font-family: arial; font-size: xx-small;"><span class="vertruco"> Normalización es un conjunto de reglas que sirven para ayudar a los diseñadores a desarrollar un esquema que minimice los problemas de lógica. Cada regla está basada en la que le antecede. La normalización se adoptó porque el viejo estilo de poner todos los datos en un solo lugar, como un archivo o una tabla de la base de datos, era ineficiente y conducía a errores de lógica cuando se trataba de manipular los datos. Por ejemplo, vea la base de datos MiTienda. Si almacena todos los datos en la tabla Clientes, ésta podría verse como se muestra a continuación:</p>
<p>Clientes</p>
<p>ID_Cliente Nombre</p>
<p>Apellidos</p>
<p>Nombre_Producto1 Costo_Producto1</p>
<p>Imagen_Producto1 Nombre_Producto2 Costo_Producto2</p>
<p>Imagen_Producto2 Fecha_Pedido</p>
<p>Cantidad_Pedido</p>
<p>Nombre_Cia_Envios</p>
<p>La tabla se ha descrito de manera abreviada pero aun así representa la idea general.</p>
<p>¿Cómo podría añadir un nuevo cliente en su tabla Clientes? Debería añadir un producto y un pedido también. ¿Qué tal si quisiera emitir un informe de todos los productos que vende? No podría separar fácilmente los productos de los clientes con una simple instrucción SQL. Lo bello de las bases de datos relacionales, si están bien diseñadas, es que puede hacer esto fácilmente.</p>
<p>La nomlalización también hace las cosas fáciles de entender. Los seres humanos tenemos la tendencia de simplificar las cosas al máximo. Lo hacemos con casi todo desde los animales hasta con los automóviles. Vemos una imagen de gran tamaño y la hacemos menos compleja agrupando cosas similares juntas. Las guías que la nomlalización provee crean el marco de referencia para simplificar la estructura. En su base de datos de muestra es fácil detectar que usted tiene tres diferentes grupos: clientes, productos y pedidos. Si sigue las guías de la nomlalización, podría crear las tablas basándose en estos grupos.</p>
<p>El proceso de nomlalización tiene un nombre y una serie de reglas para cada fase. Esto puede parecer un poco confuso al principio, pero poco a poco irá entendiendo el proceso, así como las razones para hacerlo de esta manera. A la mayoría de la gente le encantan las hojas de cálculo por la forma en la que manejan sus datos. El tiempo que le lleve reconfigurar su esquema para ajustarlo al proceso de nomlalización, siempre será bien Iinvertido. Al fin y al cabo, esto le tomará menos tiempo que el que tendría que invertir , para cortar y pegar sus columnas de datos para generar el infomle que quiere su jefe.</p>
<p>Otra ventaja de la nomlalización de su base de datos es el consumo de espacio. Una base de datos nomlalizada puede ocupar menos espacio en disco que una no nomlalizada. Hay menos repetición de datos, lo que tiene como consecuencia un mucho menor uso de espacio en disco.</p>
<p>Grados de normalización</p>
<p>Existen básicamente tres niveles de normalización: Primera Fomla Normal (1NF), Segunda Fomla Normal (2NF) y Tercera Fomla Normal (3NF). Cada una de estas formas tiene sus propias reglas. Cuando una base de datos se conforma a un nivel, se considera nomlalizada a esa forma de nomlalización. Por ejemplo, supongamos que su</p>
<p>base de datos cumple con todas las reglas del segundo nivel de nomlalización. Se considera que está en la Segunda Fomla Normal. No siempre es una buena idea tener una base de datos conformada en el nivel más alto de normalización. Puede llevar aun nivel de complejidad que pudiera ser evitado si estuviera en un nivel más bajo de normalización.</p>
<p>Primera Forma Normal</p>
<p>La regla de la Primera Forma Normal establece que las columnas repetidas deben eliminarse y colocarse en tablas separadas. Ésta es una regla muy fácil de seguir. Observe el esquema de la tabla Clientes de la base de datos.</p>
<p>.</p>
<p>Clientes</p>
<p>ID Cliente</p>
<p>Nombre</p>
<p>Apellidos</p>
<p>Nombre_Producto1</p>
<p>Costo_Producto1</p>
<p>Imagen_Producto1</p>
<p>Nombre_Producto2</p>
<p>Costo_Producto2</p>
<p>Imagen_Producto2</p>
<p>Fecha_Pedido</p>
<p>Cantidad_Pedido</p>
<p>Nombre Cia Envios</p>
<p>&#8211;</p>
<p>La tabla tiene varias columnas repetidas. Éstas se refieren principalmente a los productos. De acuerdo con la regla, debe eliminar las columnas repetidas y crearles su propia tabla.</p>
<p>Eliminación de datos repetidos en una base de datos</p>
<p>Clientes                                                                                   Pedidos</p>
<p>ID_Clientes                                                                             Nombre_Productos</p>
<p>Nombre                                                                                   Costo_Producto</p>
<p>Apellidos                                                                                 Imagen_Producto</p>
<p>Direccion</p>
<p>Numero_Pedido</p>
<p>Fecha_Pedido</p>
<p>Cantidad_Pedido</p>
<p>Clave_Cia_Envios</p>
<p>Nombre_Ci_ Envios</p>
<p>&#8211;</p>
<p>Ahora tiene dos tablas. Pero todavía hay un problema. No hay forma de relacionar los datos de la tabla original con los de la nueva tabla. Para hacerlo, debe añadir un campo clave a la segunda tabla de forma que se establezca la relación. Añada a la tabla Productos una clave primaria que se llame ID_Producto y añada una clave a la tabla Clientes que la relacione con la tabla Productos. El campo ID_Producto es el candidato ideal.</p>
<p>Primera Forma Normal</p>
<p>Clientes                                                                                   Pedidos</p>
<p>ID_Productos                                                                         ID_Productos</p>
<p>ID_Clientes                                                                            Nombre_Productos</p>
<p>Nombre                                                                                   Costo_Producto</p>
<p>Apellidos                                                                                 Imagen_Producto</p>
<p>Direccion</p>
<p>Numero_Pedido</p>
<p>Fecha_Pedido</p>
<p>Cantidad_Pedido</p>
<p>Clave_Cia_Envios</p>
<p>&#8211;</p>
<p>Así, se ha establecido una relación uno a varios. Ésta representa lo que la base de datos estará haciendo en la vida real. El cliente tendrá muchos productos que podrá comprar,</p>
<p>sin importar cuántos otros clientes quieran comprarlos también. Además, el cliente necesitará haber pedido un producto para ser un cliente. Usted ya no está obligado a añadir</p>
<p>un cliente cada vez que añade un nuevo producto a su inventario.</p>
<p>Poner la base de datos en la Primera Forma Normal resuelve el problema de los encabezados de columna múltiples. Muy a menudo, los diseñadores de bases de datos inexpertos harán algo similar a la tabla no normalizada. Una y otra vez, crearán columnas que representen los mismos datos. En una empresa de servicios de electricidad, había una base de datos para el control de refacciones de una planta nuclear. La tabla de su base de datos, la cual contenía los números de parte de las refacciones, tenía una columna repetida más de treinta veces. Cada vez que una nueva parte se tenía que dar de alta, se creaba una nueva columna para almacenar la información. Obviamente, el diseño de la base de datos era bastante pobre y, por lo mismo, resultaba una pesadilla para sus programadores/administradores.</p>
<p>La normalización ayuda a clarificar la base de datos ya organizarla en partes más pequeñas y más fáciles de entender. En lugar de tener que entender una tabla gigantesca y monolítica que tiene muchos diferentes aspectos, usted sólo tiene que entender objetos pequeños y más tangibles, así como las relaciones que guardan con otros objetos también pequeños. No es necesario mencionar que un mejor entendimiento del funcionamiento de su base de datos conducirá aun mejor aprovechamiento de sus activos.</p>
<p>Segunda Forma Normal</p>
<p>La regla de la Segunda Forma Normal establece que todas las dependencias parciales se deben eliminar y separar dentro de sus propias tablas. Una depen dencia parcial es un término que describe a aquellos datos que no dependen de la clave de la tabla para identificarlos. En la base de datos de muestra, la información de pedidos está en cada uno de los registros. Sería mucho más simple utilizar únicamente el número del pedido. El resto de la información podría residir en su propia tabla. Una vez que haya organizado la información de pedidos.</p>
<p>Eliminación de las dependencias parciales -Segunda Forma Normal</p>
<p>Clientes Pedidos Productos</p>
<p>ID_Productos ID_Productos ID_Producto</p>
<p>ID_Clientes Nombre_Productos Fecha_Compra</p>
<p>Nombre Cantidad_Pedido Costos_Productos</p>
<p>Apellidos Imagen_Producto</p>
<p>Direccion</p>
<p>Numero_Pedido</p>
<p>Nombre_Cia_Envios</p>
<p>De nuevo, al organizar el esquema de esta forma puede reflejar el mundo real en su base de datos. Tendría que hacer algunos cambios en sus reglas del negocio para que esto fuera aplicable, pero para ilustrar la normalización, así está bien.</p>
<p>Una de las mayores desventajas de la normalización es el tiempo que lleva hacerlo. La mayoría de la gente está demasiado ocupada, y emplear tiempo para asegurarse de que sus datos están normalizados cuando todo funciona más o menos bien, parece ser un desperdicio de tiempo. Pero no es así. Usted tendrá que emplear más tiempo arreglando una base de datos no normalizada que el que emplearía en una normalizada.</p>
<p>Al haber alcanzado la Segunda Forma Normal, usted puede disfrutar de algunas de las ventajas de las bases de datos relacionales. Por ejemplo, puede añadir nuevas columnas a la tabla Clientes sin afectar a las tablas Productos y Pedidos. Lo mismo aplica para las otras tablas. Alcanzar este nivel de normalización permite que los datos se acomoden de una manera natural dentro de los límites esperados.</p>
<p>Una vez que ha alcanzado el nivel de la Segunda Forma Normal, se han controlado la mayoría de los problemas de lógica. Puede insertar un registro sin un exceso de datos en la mayoría de las tablas. Observando un poco más de cerca la tabla Clientes, vemos la columna Nombre_Cia_Envios. Ésta no es dependiente del cliente. El siguiente nivel de normalización explicará cómo solucionar esto.</p>
<p>Tercera Forma Normal</p>
<p>La regla de la Tercera Forma Normal señala que hay que eliminar y separar cualquier dato que no sea clave. El valor de esta columna debe depender de la clave. Todos los valores deben identificarse únicamente por la clave. En la base de datos de muestra, la tabla Clientes contiene la columna Nombre_Cia_Envios, la cual no se identifica únicamente por la clave. Podría separar estos datos de la tabla y ponerlos en una tabla aparte.</p>
<p>Eliminación de los datos que no son claves para la Tercera Forma Normal</p>
<p>Clientes Productos PedidoMaestro PedidoDetallado Cias_Envios</p>
<p>ID_cliente ID_Producto ID_Pedido ID_PedidoDetallado ID_Cia_Envios</p>
<p>ID_Producto Nombre_Producto Fecha_Pedido ID_Pedido Nombre_Cia_Envios.</p>
<p>Numero_Pedido       Costos_Productos         Cantidad_Pedidos           Fecha_Pedido</p>
<p>ID_Cia_Envios           Foto_Producto                                                             Cantidad_Pedido</p>
<p>Nombre</p>
<p>Apellidos</p>
<p>Direccion</p>
<p>Ahora todas sus tablas están en la Tercera Forma Normal. Esto le da más flexibilidad y previene errores de lógica cuando inserta o borra registros. Cada columna en la tabla está identificada de manera única por la clave, y no hay datos repetidos. Esto provee un esquema limpio y elegante, que es fácil de trabajar y expandir.</p>
<p>Qué tan lejos debe llevar la normalización</p>
<p>La siguiente decisión es ¿qué tan lejos debe llevar la normalización? La normalización es una ciencia subjetiva. Determinar las necesidades de simplificación depende de usted. Si su base de datos va a proveer información aun solo usuario para un propósito simple y existen pocas posibilidades de expansión, normalizar sus datos hasta la 3FN sea quizá algo extremoso. Las reglas de normalización existen como guías para crear tablas que sean fáciles de manejar, así como flexibles y eficientes.</p>
<p>A veces puede ocurrir que normalizar sus datos hasta el nivel más alto no tenga sentido. Por ejemplo, suponga que añade una columna extra para la dirección en su base de datos. Es muy normal tener dos líneas para la dirección. El esquema de la tabla podría verse como se muestra a continuación:</p>
<p>ID_Cliente</p>
<p>Nombre</p>
<p>Apellidos</p>
<p>Direccion1</p>
<p>Direccion2</p>
<p>De acuerdo con las reglas, si aplica la Primera Forma Normal, la columna de dirección debería sacarse de esta tabla y reemplazarse con la clave de una nueva tabla. El resultado de este esquema se muestra a continuación:</p>
<p>ID_Ciente              ID_Direccion</p>
<p>Nombre                 ID_Cliente</p>
<p>Apellidos               Direccion</p>
<p>La base de datos ahora cumple con la Primera Forma Normal. Los clientes pueden tener más de una dirección. El problema aquí es que usted ha complicado demasiado una idea simple, por tratar de seguir las reglas de normalización. En el ejemplo mostrado, la segunda dirección es totalmente opcional. Está ahí sólo para colectar información que pudiera utilizarse como información de contacto. No hay necesidad de partir la tabla en dos y forzar las reglas de la normalización. En esta instancia, el exceso de normalización frustra el propósito para el que se utilizan los datos. Añade, de manera innecesaria, un nivel más de complejidad. Una buena forma de determinar si está llevando demasiado lejos su normalización, es ver el número de tablas que tiene. Un número grande de tablas pudiera indicar que está normalizando demasiado. Observe su esquema.</p>
<p>¿Está dividiendo tablas sólo para seguir las reglas o estas divisiones son en verdad prácticas? Éstas son el tipo de cosas que usted, el diseñador de la base de datos, necesita decidir. La experiencia y el sentido común lo pueden auxiliar para tomar la decisión correcta. La normalización no es una ciencia exacta. Es subjetiva.</p>
<p>Existen seis niveles más de normalización que no se han discutido aquí. Ellos son Forma Normal Boyce-Codd, Cuarta Forma Normal (4NF), Quinta Forma Normal (5NF) o</p>
<p>Forma Normal de Proyección-Unión, Forma Normal de Proyección-Unión Fuerte, Forma Normal de Proyección-Unión Extra Fuerte y Forma Normal de Clave de Dominio. Estas formas de normalización pueden llevar las cosas más allá de lo que necesita. Éstas existen para hacer una base de datos realmente relacional. Tienen que ver principalmente con dependencias múltiples y claves relacionales.</p>
<p>En resumen</p>
<p>La normalización es una técnica que se utiliza para crear relaciones lógicas apropiadas entre tablas de una base de datos.</p>
<p>Ayuda a prevenir errores lógicos en la manipulación de datos. La normalización facilita también agregar nuevas columnas sin romper el esquema actual ni las relaciones.</p>
<p>Existen varios niveles de normalización: Primera Forma Normal, Segunda Forma Normal, Tercera Forma Normal, Forma Normal Boyce-Codd, Cuarta Forma Normal, Quinta Forma Normal o Forma Normal de Proyección-Unión, Forma Normal de Proyección-Unión Fuerte, Forma Normal de Proyección-Unión Extra Fuerte y Forma</p>
<p>Normal de Clave de Dominio. Cada nuevo nivel o forma lo acerca más a hacer su base de datos verdaderamente relacional.</p>
<p>Se discutieron las primeras tres formas. Éstas proveen suficiente nivel de normalización para cumplir con las necesidades de la mayoría de las bases de datos.</p>
<p>Normalizar demasiado puede conducir a tener una base de datos ineficiente y hacer a su esquema demasiado complejo para trabajar. Un balance apropiado de sentido común y</p>
<p>práctico puede ayudarle a decidir cuándo normalizar. </span><span class="vertruco"> </span></p>
<p></span></p>
]]></content:encoded>
			<wfw:commentRss>http://blaster.comunidad-itsjr.com.mx/archives/265/feed</wfw:commentRss>
		</item>
		<item>
		<title>Un poco acerca de CHMOD</title>
		<link>http://blaster.comunidad-itsjr.com.mx/archives/263</link>
		<comments>http://blaster.comunidad-itsjr.com.mx/archives/263#comments</comments>
		<pubDate>Wed, 23 Apr 2008 02:35:40 +0000</pubDate>
		<dc:creator>blaster</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blaster.comunidad-itsjr.com.mx/?p=263</guid>
		<description><![CDATA[Una de las dudas mas habituales cuando nos enfrentamos a la instalación de scripts (perl, php) es la asignación de los permisos correspondientes. Las preguntas sobre CHMOD suelen ser las mas habituales en todos los foros que se dedican a estos temas. En este artículo abordaremos que son los permisos, para que sirven, y como [...]]]></description>
			<content:encoded><![CDATA[<p>Una de las dudas mas habituales cuando nos enfrentamos a la instalación de scripts (perl, php) es la asignación de los permisos correspondientes. Las preguntas sobre CHMOD suelen ser las mas habituales en todos los foros que se dedican a estos temas. En este artículo abordaremos que son los permisos, para que sirven, y como asignarlos.</p>
<h2>Los script y los permisos</h2>
<p><tt>CHMOD</tt> (&#8221;Change mode&#8221;) es un comando UNIX que permite cambiar los permisos de acceso de un archivo. Cada archivo tiene nueve clases de acceso, que pueden ser permitidas o denegadas. Se pueden aplicar diferentes permisos al <strong class="function">dueño</strong> del fichero, al <strong class="function">grupo</strong> al que el fichero pertenece y al <strong class="function">resto</strong> de usuarios. Cada una de estas tres clases de usuarios (dueño, grupo, resto de usuarios) puede tener permisos de <strong class="function">lectura, escritura y ejecución</strong></p>
<p>Al instalar cualquier archivo en una página web, podemos definir sus propiedades, para determinar en que forma será accesible para los visitantes de la página.<br />
Estas propiedades son lo que llamamos permisos y segun cuales asignemos a cada archivo este será solo de lectura, de escritura o ejecutable, o cualquier combinación de los tres.</p>
<p>Piensa por ejemplo en una página de html sencilla, respecto de la cual solo nos interesa garantizar que todo el mundo pueda verla pero no modificarla; el archivo que contiene esa página necesita unicamente permisos de lectura, pero no de ejecución ni de escritura. Por contra, si se trata de un script, necesitará probablemente permisos de lectura y de ejecución, etc.</p>
<h2>La orden CHMOD</h2>
<p>En este documento nos referimos a la asignación de permisos en servidores unix (unix, linux, freebsd, todos ellos pertenecientes a la familia unix, y con diferencia los mas difundidos en la red). La asignación de permisos se hace mediante el comando CHMOD. Por eso, cuando al leer las instrucciones de instalación de cualquier aplicación web te encuentres con la misteriosa frase &#8220;haz <tt>chmod 666 tal_archivo.htm</tt>&#8221; ten en consideración que nos estan diciendo los permisos que ese archivo necesita.</p>
<p>Los servidores Windows tienen su propio sistema de permisos, en los que no vamos a entrar aqui.</p>
<h2>El concepto de usuario en UNIX</h2>
<p>El sistema operativo UNIX esta diseñado para ser multiusuario. Por ello UNIX permite tres niveles de acceso a los archivos, para tres categorias diferentes de usuarios:</p>
<p><strong>owner</strong> (propietario) La persona que el sistema reconoce como dueño del archivo.</p>
<p><strong>Group</strong> (grupo): Conjunto de usuarios con permisos similares. Muy usado en entornos de trabajo, es de escasa aplicación en páginas web.</p>
<p><strong>Other</strong> (otros): Cualquier otra persona.</p>
<p>Es un error asociar el concepto de usuario a una persona real. Se trata de una abstracción, que se refiere no a personas sino a categorias. Por ejemplo, si nosotros creamos un script, somos efectivamente sus autores y propietarios; pero ese script esta destinado a la red. Nosotros, y el resto de personas, accederan al archivo no a traves de nuestra maquina local sino por internet. Es frecuente en los servidores la creación de usuarios genéricos (root, www, www-user etc). En definitiva no olvides que cuando asignas permisos a un script, el owner puede ser cualquiera que visite la página, lo cual será necesario si como es normal se trata de scripts que se administran via web.</p>
<h2>Tipos de permiso de acceso:</h2>
<p><strong>Read</strong> (lectura): Permiso para ver el archivo o directorio, sin hacer cambios.</p>
<p><strong>Write</strong> (escritura): Permiso de escritura: puede escribir el archivo, y por tanto, cambiarlo.</p>
<p><strong>Execute</strong> (ejecución): El archivo o directorio puede ser ejecutado. Se usa para directorios con scripts, formularios, etc &#8230;</p>
<p>Y tratándose de directorios:</p>
<p><strong>read</strong> listar los archivos de un directorio</p>
<p><strong>write</strong> añadir nuevos archivos al directorio</p>
<p><strong>execute</strong> acceder a los archivos del directorio</p>
<h2>Como conozco los permisos de un archivo ?</h2>
<p>Si tenemos acceso ftp al servidor, tecleamos el comando <tt>ls -l</tt> y vemos algo asi:</p>
<pre>-rw-r--r--   1 irvnet   irvnet       1272 Sep 28 07:31 index.php
| //  /       |         |           |                     |
| | |   |        |         |          tamaño           nombre del archivo
| | |   |        |         |_ nombre grupo
| | |   |        |
| | |   |        |_ nombre usuario
| | |   |
| | |   |_ Permisos genericos
| | |
| | |_ Los siguientes tres digitos los permisos del Group
| |
| |___ los siguientes tres caracteres determinan los permisos del owner:
|      r de real, lectura; w, write, escritura y x de
|       execute, ejecución
|
|
|___ El primer carácter indica si nos encontramos ante un directorio o un
fichero: d significa directorio, - significa fichero,
l significa link</pre>
<p>Advierte que tenemos TRES categorias de usuarios (&#8221;user,&#8221; &#8220;group,&#8221; y &#8220;other&#8221;) y para categoria pueden asignarse TRES tipos de permisos: &#8220;r,&#8221; &#8220;w,&#8221; y &#8220;x&#8221;.</p>
<h2>Fijando permisos</h2>
<p>La orden chmod puede usarse con letras o numeros. La forma mas corriente es expresar los permisos numericamente. Seguro que lo has visto por ahi, chmod 777 etc &#8230;<br />
Para comprender el significado tienes que tener en cuenta que convencionalmente 4 significa permiso de lectura. 2 permiso de escritura y 1 permiso de ejecución. Sumando estos valores vemos que un archivo puede tener los siguientes permisos (por cada tipo de usuario):</p>
<pre>	4= lectura
2= escritura
1= ejecución

6 (4+2)= lectura y escritura
5 (4+1)= lectura y ejecución
3 (2+1)= escritura y ejecución
7 (4+2+1)= lectura, escritura y ejecución</pre>
<p>Todo ello para los tres tipos de usuario.</p>
<p>Asi, un <tt>chmod file 777</tt> significa que owner, group y others tienen permiso de lectura, escritura y ejecución. <tt>chmod 766</tt> significa que el owner tiene permiso de lectura, escritura y ejecución, y el group y others permiso de lectura y escritura. <tt>Chmod 744</tt> significa que el owner tiene permisos de lectura, escritura y ejecución, y group y others unicamente permisos de lectura.</p>
<p>Como ves, son tres digitos, de izquierda a derecha designan los permisos del owner, group y others.</p>
<p>Vemos a continuación su equivalente en letras:</p>
<pre>0  =  ---  =  sin acceso
1  =  --x  =  ejecución
2  =  -w-  =  escritura
3  =  -wx  =  escritura y ejecución
4  =  r--  =  lectura
5  =  r-x  =  lectura y ejecución
6  =  rw-  =  lectura y escritura
7  =  rwx  =  lectura, escritura y ejecución</pre>
<p>Asi, en el ejemplo de antes:</p>
<pre>		rw-r--r--</pre>
<p>significa que el owner tiene permisos de lectura y escritura (rw-); el group permisos de lectura unicamente (r&#8211;) y other, permiso de lectura (r&#8211;). ¿como seria el equivamente numerico? sería chmod 644.</p>
<p>La sintaxis para usar chmod con texto:</p>
<p><tt>chmod [ugo][+-][rwx] [nombre_archivo]</tt></p>
<p>Donde [u=user, g=group y o=other]; [+/- activa o desactiva los atributos siguientes] [r=read, w=write, x=execute]</p>
<p>Por ejemplo, <tt>chmod go+r index.php</tt> significa que asignamos permisos de lectura para group y others en index.php</p>
<p>De esta forma solo cambiamos los atributos que especificamos, pero no alteramos otros compatibles que pudieran estar asignados anteriormente) por ejemplo, no modifica la atribucion anterior a group de un permiso de ejecución).</p>
<p>Si queremos fijar de nuevo todos los permisos, la sintaxis sería:</p>
<p><tt>chmod go=r index.php</tt> donde asignamos a group y other permiso de lectura sobre index.php y eliminamos cualquier otro permiso para ambos.</p>
<p>Ten encuenta asimismo que puedes usar comodines:</p>
<p><tt>chmod 644 *.html</tt> etc &#8230;</p>
<h2>Calculando valores chmod</h2>
<p><script>
// Chmod calculator. This is useful when setting permissions on cgi files using FTP
// Copyright Peter Crouch 2000. All rights reserved.
// Visit http://www.perlbay.com for other thing written by me
//Visit http://javascriptkit.com for this script and more</p>
<p>function calculator(user, number){
// Owner
if (user == "owner" &amp;&amp; number == "4"){var box = eval("document.chmod.owner4")}
if (user == "owner" &amp;&amp; number == "2"){var box = eval("document.chmod.owner2")}
if (user == "owner" &amp;&amp; number == "1"){var box = eval("document.chmod.owner1")}
// Group
if (user == "group" &amp;&amp; number == "4"){var box = eval("document.chmod.group4")}
if (user == "group" &amp;&amp; number == "2"){var box = eval("document.chmod.group2")}
if (user == "group" &amp;&amp; number == "1"){var box = eval("document.chmod.group1")}
// Other
if (user == "other" &amp;&amp; number == "4"){var box = eval("document.chmod.other4")}
if (user == "other" &amp;&amp; number == "2"){var box = eval("document.chmod.other2")}
if (user == "other" &amp;&amp; number == "1"){var box = eval("document.chmod.other1")}
if (box.checked == true){
if (user == "owner"){
document.chmod.h_owner.value += ("+number")
var a= (document.chmod.h_owner.value)
var b= eval(a)
document.chmod.h_owner.value=b
document.chmod.t_owner.value=b
}if (user == "group"){
document.chmod.h_group.value += ("+number")
var a= (document.chmod.h_group.value)
var b= eval(a)
document.chmod.h_group.value=b
document.chmod.t_group.value=b
}if (user == "other"){
document.chmod.h_other.value += ("+number")
var a= (document.chmod.h_other.value)
var b= eval(a)
document.chmod.h_other.value=b
document.chmod.t_other.value=b
}
}
if (box.checked == false){
if (user == "owner"){
if (document.chmod.h_owner.value == ""){
document.chmod.t_owner.value=""
}else {
var a=(document.chmod.h_owner.value);
b=a-(number);
c=eval(b);
document.chmod.h_owner.value=c
document.chmod.t_owner.value=c
}}if (user == "group"){
if (document.chmod.h_group.value == ""){
document.chmod.t_group.value=""
}else {
var a=(document.chmod.h_group.value);
b=a-(number);
c=eval(b);
document.chmod.h_group.value=c
document.chmod.t_group.value=c
}}if (user == "other"){
if (document.chmod.h_other.value == ""){
document.chmod.t_other.value=""
}else {
var a=(document.chmod.h_other.value);
b=a-(number);
c=eval(b);
document.chmod.h_other.value=c
document.chmod.t_other.value=c
}}
}}
</script></p>
<form>
<input name="h_owner" type="hidden" />
<input name="h_group" type="hidden" />
<input name="h_other" type="hidden" />
<table border="0" cellspacing="1" cellpadding="5" bgcolor="#000000">
<tbody>
<tr bgcolor="#ffffff">
<td colspan="4"><strong>Chmod</strong></td>
</tr>
<tr align="center" bgcolor="#ffffff">
<td><strong>Permission</strong></td>
<td><strong>Owner</strong></td>
<td><strong>Group</strong></td>
<td><strong>Other</strong></td>
</tr>
<tr align="center" bgcolor="#ffffff">
<td><strong>Read</strong></td>
<td>
<input title="calculator('owner', 4) null" onclick="calculator('owner', 4)" name="owner4" type="checkbox" value="4" /></td>
<td>
<input onclick="calculator('group', 4)" name="group4" type="checkbox" value="4" /></td>
<td>
<input onclick="calculator('other', 4)" name="other4" type="checkbox" value="4" /></td>
</tr>
<tr align="center" bgcolor="#ffffff">
<td><strong>Write</strong></td>
<td>
<input title="calculator('owner', 2) null" onclick="calculator('owner', 2)" name="owner2" type="checkbox" value="2" /></td>
<td>
<input onclick="calculator('group', 2)" name="group2" type="checkbox" value="2" /></td>
<td>
<input onclick="calculator('other', 2)" name="other2" type="checkbox" value="2" /></td>
</tr>
<tr align="center" bgcolor="#ffffff">
<td><strong>Execute</strong></td>
<td>
<input title="calculator('owner', 1) null" onclick="calculator('owner', 1)" name="owner1" type="checkbox" value="1" /></td>
<td>
<input onclick="calculator('group', 1)" name="group1" type="checkbox" value="1" /></td>
<td>
<input onclick="calculator('other', 1)" name="other1" type="checkbox" value="1" /></td>
</tr>
<tr align="center" bgcolor="#ffffff">
<td></td>
<td>
<input name="t_owner" size="1" type="text" /></td>
<td>
<input name="t_group" size="1" type="text" /></td>
<td>
<input name="t_other" size="1" type="text" /></td>
</tr>
</tbody>
</table>
</form>
<p><span style="font-family: arial;">This free script provided by</span> <span style="font-family: arial,helvetica;"><a href="http://javascriptkit.com/">JavaScript Kit</a></span></p>
<h2>caso práctico, phpnuke:</h2>
<p><em>Este apartado se mantiene como simple ejemplo. Las ultimas versiones de php-nuke NO precisan permisos de archivo especiales.</em></p>
<p>Si leemos el install de phpnuke (versiones antiguas anteriores a la 6.0), por ejemplo, el de la versión 4.4, encontramos:</p>
<p>&#8220;&#8230; In order to use the File Manager, please be sure to chmod 666 ALL files and 777 ALL directories.<br />
4) Also, to activate Headlines you &#8220;need&#8221; to chmod 777 the &#8220;cache&#8221; directory, otherwise headlines won&#8217;t work.<br />
&#8230;.<br />
NOTE: If you want to edit config.php file from web browser remember to chmod 666 the file config.php or your changes will not be saved! If can&#8217;t execute chmod just edit the file by hand and re-upload it to your server&#8221;.</p>
<p>Bueno, aqui nos están diciendo que si queremos utilizar el &#8220;administrador de archivos&#8221; hay que asignar permisos 666 a todos los archivos, es decir, ya sabemos, permisos de lectura y escritura para TODOS los usuarios (owner, group, other) y 777 a todos los directorios (permiso para listar archivos, subir archivos, acceder archivos en el directorio, a los tres grupos de usuarios).</p>
<p>Para activar las headlines chmod 777 el directorio cache: listar archivos, subir archivos, acceder archivos en el directorio, a los tres grupos de usuarios.</p>
<p>Para modificar las preferencias de nuestra página via web (a traves de admin.php) debemos asignar a config.php permiso 666, es decir, permisos de lectura y escritura. De otra forma, si no tiene permisos de escritura, no se guardaran los cambios.</p>
<h2>Materialmente, como se hace?</h2>
<p><strong>WS_FTP</strong>: click derecho sobre el archivo o directorio, y elegir &#8220;chmod&#8221; en el menu emergente. O tambien, click derecho y elegir del menu &#8220;SITE&#8221;, y en la barra que sale escribir el comando UNIX, por ejemplo, &#8220;chmod 666 config.php&#8221;.</p>
<p><strong>CuteFTP</strong>: click derecho sobre el archivo o carpeta y elegir &#8220;Change file attributes&#8221; del menu emergente. Para ver los permisos en la ventana, click derecho sobre la ventana y elegir &#8220;Long listing&#8221;.</p>
<p><strong>Telnet</strong>: Conectados al servidor, simplemente tecleamos chmod 666 config.php</p>
<p><strong>HTML-kit</strong> Selecciona el archivo en el worksplace; click en el botón secundario del ratón y selecciona <tt>Set permissions</tt>. Obtendras una ventana donde podrás fijar el valor CHMOD chequeando casillas con los permisos, o bien introduciendo directamente su traducción numérica</p>
]]></content:encoded>
			<wfw:commentRss>http://blaster.comunidad-itsjr.com.mx/archives/263/feed</wfw:commentRss>
		</item>
		<item>
		<title>Como gravar video tutoriales en linux ( ubuntu)</title>
		<link>http://blaster.comunidad-itsjr.com.mx/archives/262</link>
		<comments>http://blaster.comunidad-itsjr.com.mx/archives/262#comments</comments>
		<pubDate>Fri, 18 Apr 2008 15:29:12 +0000</pubDate>
		<dc:creator>blaster</dc:creator>
		
		<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://blaster.comunidad-itsjr.com.mx/?p=262</guid>
		<description><![CDATA[he probado toda clase de sistemas para hacerlo y nunca me funcionó alguno, pero por fin encontré una solución que me funcionó. Se llama RecordMyDesktop y se instala muy fácilmente con dpkg -i archivo.deb o con gdebi haciendo doble click sobre él.
Hay que bajar los siguientes 2 archivos e instalarlos en orden para no tener [...]]]></description>
			<content:encoded><![CDATA[<p>he probado toda clase de sistemas para hacerlo y nunca me funcionó alguno, pero por fin encontré una solución que <span style="font-weight: bold;">me</span> funcionó. Se llama RecordMyDesktop y se instala muy fácilmente con dpkg -i archivo.deb o con gdebi haciendo doble click sobre él.</p>
<p>Hay que bajar los siguientes 2 archivos e instalarlos en orden para no tener problemas de dependencias:<br />
RecordMyDesktop<br />
gtk-RecordMyDesktop</p>
<p>Y listo&#8230; instalados, luego para ejecutarlo nos vamos a Inicio/Sonido y Video/gtk-recordmydesktop.</p>
]]></content:encoded>
			<wfw:commentRss>http://blaster.comunidad-itsjr.com.mx/archives/262/feed</wfw:commentRss>
		</item>
		<item>
		<title>Que son Árboles Binarios de Búsqueda en Java y para que sirven ?</title>
		<link>http://blaster.comunidad-itsjr.com.mx/archives/261</link>
		<comments>http://blaster.comunidad-itsjr.com.mx/archives/261#comments</comments>
		<pubDate>Tue, 15 Apr 2008 16:05:43 +0000</pubDate>
		<dc:creator>blaster</dc:creator>
		
		<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://blaster.comunidad-itsjr.com.mx/?p=261</guid>
		<description><![CDATA[

En estos días he tenido la necesidad de ver ciertas operaciones que se implementan el los árboles binarios de búsqueda (Binary Search Trees), y en este sitio encontré una implementación particularmente interesante, espero que les sea de utilidad.
En ciencias de la computación, un árbol binario de búsqueda es un árbol que tiene las siguientes propiedades:

Cada [...]]]></description>
			<content:encoded><![CDATA[<div class="entry">
<div class="snap_preview">
<p>En estos días he tenido la necesidad de ver ciertas operaciones que se implementan el los árboles binarios de búsqueda (Binary Search Trees), y en <a href="http://http//www.java-tips.org/java-se-tips/java.lang/binary-search-tree-implementation-in-java.html">este sitio</a> encontré una implementación particularmente interesante, espero que les sea de utilidad.</p>
<p>En ciencias de la computación, un árbol binario de búsqueda es un árbol que tiene las siguientes propiedades:</p>
<ul>
<li>Cada nodo tiene un valor</li>
<li>Se define un orden total sobre esos valores</li>
<li>El subárbol izquierdo de un nodo contiene valores menores o iguales que el valor de dicho nodo.</li>
<li>El subárbol derecho de un nodo contiene valores mayores o iguales que el valor de dicho nodo.</li>
</ul>
<p>La ventaja más notable de los árboles binarios de búsqueda es que los algoritmos de ordenación y búsqueda relacionados como transversal inorden pueden ser muy eficientes.</p>
<p>Los árboles binarios de búsqueda son una estructura de datos fundamental usada para construir más estructuras de datos abstractas como conjuntos y arrays asociativos.<br />
<code> <span style="color: #3f7f5f;">// BinarySearchTree class</span><br />
<span style="color: #3f7f5f;">//</span><br />
<span style="color: #3f7f5f;">// CONSTRUCTION: with no initializer</span><br />
<span style="color: #3f7f5f;">//</span><br />
<span style="color: #3f7f5f;">// ******************PUBLIC OPERATIONS*********************</span><br />
<span style="color: #3f7f5f;">// void insert( x )       –&gt; Insert x</span><br />
<span style="color: #3f7f5f;">// void remove( x )       –&gt; Remove x</span><br />
<span style="color: #3f7f5f;">// void removeMin( )      –&gt; Remove minimum item</span><br />
<span style="color: #3f7f5f;">// Comparable find( x )   –&gt; Return item that matches x</span><br />
<span style="color: #3f7f5f;">// Comparable findMin( )  –&gt; Return smallest item</span><br />
<span style="color: #3f7f5f;">// Comparable findMax( )  –&gt; Return largest item</span><br />
<span style="color: #3f7f5f;">// boolean isEmpty( )     –&gt; Return true if empty; else false</span><br />
<span style="color: #3f7f5f;">// void makeEmpty( )      –&gt; Remove all items</span><br />
<span style="color: #3f7f5f;">// ******************ERRORS********************************</span><br />
<span style="color: #3f7f5f;">// Exceptions are thrown by insert, remove, and removeMin if warranted</span></code></p>
<p><span style="color: #3f5fbf;">/**</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;">* Implements an unbalanced binary search tree.</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;">* Note that all “matching” is based on the compareTo method.</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;">* </span><span style="color: #7f9fbf;">@author </span><span style="color: #3f5fbf;">Mark Allen Weiss</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;">*/</span><br />
<span style="color: #7f0055;"><strong>public class </strong></span><span style="color: #000000;">BinarySearchTree </span><span style="color: #000000;">{</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> /**</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> * Construct the tree.</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> */</span><br />
<span style="color: #7f0055;"><strong>public </strong></span><span style="color: #000000;">BinarySearchTree</span><span style="color: #000000;">( ) {</span><br />
<span style="color: #000000;">root = </span><span style="color: #7f0055;"><strong>null</strong></span><span style="color: #000000;">;</span><br />
<span style="color: #000000;">}</span><br />
<span style="color: #ffffff;"> </span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> /**</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> * Insert into the tree.</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> * </span><span style="color: #7f9fbf;">@param </span><span style="color: #3f5fbf;">x the item to insert.</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> * </span><span style="color: #7f9fbf;">@throws </span><span style="color: #3f5fbf;">DuplicateItemException if x is already present.</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> */</span><br />
<span style="color: #ffffff;"> </span><span style="color: #7f0055;"><strong> public </strong></span><span style="color: #7f0055;"><strong>void </strong></span><span style="color: #000000;">insert</span><span style="color: #000000;">( </span><span style="color: #000000;">Comparable x </span><span style="color: #000000;">) {</span><br />
<span style="color: #ffffff;"> </span><span style="color: #000000;"> root = insert</span><span style="color: #000000;">( </span><span style="color: #000000;">x, root </span><span style="color: #000000;">)</span><span style="color: #000000;">;</span><br />
<span style="color: #ffffff;"> </span><span style="color: #000000;"> }</span><br />
<span style="color: #ffffff;"> </span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> /**</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> * Remove from the tree..</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> * </span><span style="color: #7f9fbf;">@param </span><span style="color: #3f5fbf;">x the item to remove.</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> * </span><span style="color: #7f9fbf;">@throws </span><span style="color: #3f5fbf;">ItemNotFoundException if x is not found.</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> */</span><br />
<span style="color: #ffffff;"> </span><span style="color: #7f0055;"><strong> public </strong></span><span style="color: #7f0055;"><strong>void </strong></span><span style="color: #000000;">remove</span><span style="color: #000000;">( </span><span style="color: #000000;">Comparable x </span><span style="color: #000000;">) {</span><br />
<span style="color: #ffffff;"> </span><span style="color: #000000;"> root = remove</span><span style="color: #000000;">( </span><span style="color: #000000;">x, root </span><span style="color: #000000;">)</span><span style="color: #000000;">;</span><br />
<span style="color: #ffffff;"> </span><span style="color: #000000;"> }</span><br />
<span style="color: #ffffff;"> </span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> /**</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> * Remove minimum item from the tree.</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> * </span><span style="color: #7f9fbf;">@throws </span><span style="color: #3f5fbf;">ItemNotFoundException if tree is empty.</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> */</span><br />
<span style="color: #ffffff;"> </span><span style="color: #7f0055;"><strong> public </strong></span><span style="color: #7f0055;"><strong>void </strong></span><span style="color: #000000;">removeMin</span><span style="color: #000000;">( ) {</span><br />
<span style="color: #ffffff;"> </span><span style="color: #000000;"> root = removeMin</span><span style="color: #000000;">( </span><span style="color: #000000;">root </span><span style="color: #000000;">)</span><span style="color: #000000;">;</span><br />
<span style="color: #ffffff;"> </span><span style="color: #000000;"> }</span><br />
<span style="color: #ffffff;"> </span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> /**</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> * Find the smallest item in the tree.</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> * </span><span style="color: #7f9fbf;">@return </span><span style="color: #3f5fbf;">smallest item or null if empty.</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> */</span><br />
<span style="color: #ffffff;"> </span><span style="color: #7f0055;"><strong> public </strong></span><span style="color: #000000;">Comparable findMin</span><span style="color: #000000;">( ) {</span><br />
<span style="color: #ffffff;"> </span><span style="color: #7f0055;"><strong> return </strong></span><span style="color: #000000;">elementAt</span><span style="color: #000000;">( </span><span style="color: #000000;">findMin</span><span style="color: #000000;">( </span><span style="color: #000000;">root </span><span style="color: #000000;">) )</span><span style="color: #000000;">;</span><br />
<span style="color: #ffffff;"> </span><span style="color: #000000;"> }</span><br />
<span style="color: #ffffff;"> </span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> /**</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> * Find the largest item in the tree.</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> * </span><span style="color: #7f9fbf;">@return </span><span style="color: #3f5fbf;">the largest item or null if empty.</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> */</span></p>
<p><span style="color: #7f0055;"><strong> public </strong></span><span style="color: #000000;">Comparable findMax</span><span style="color: #000000;">( ) {</span><br />
<span style="color: #ffffff;"> </span><span style="color: #7f0055;"><strong> return </strong></span><span style="color: #000000;">elementAt</span><span style="color: #000000;">( </span><span style="color: #000000;">findMax</span><span style="color: #000000;">( </span><span style="color: #000000;">root </span><span style="color: #000000;">) )</span><span style="color: #000000;">;</span><br />
<span style="color: #ffffff;"> </span><span style="color: #000000;"> }</span><br />
<span style="color: #ffffff;"> </span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> /**</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> * Find an item in the tree.</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> * </span><span style="color: #7f9fbf;">@param </span><span style="color: #3f5fbf;">x the item to search for.</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> * </span><span style="color: #7f9fbf;">@return </span><span style="color: #3f5fbf;">the matching item or null if not found.</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> */</span><br />
<span style="color: #ffffff;"> </span><span style="color: #7f0055;"><strong> public </strong></span><span style="color: #000000;">Comparable find</span><span style="color: #000000;">( </span><span style="color: #000000;">Comparable x </span><span style="color: #000000;">) {</span><br />
<span style="color: #ffffff;"> </span><span style="color: #7f0055;"><strong> return </strong></span><span style="color: #000000;">elementAt</span><span style="color: #000000;">( </span><span style="color: #000000;">find</span><span style="color: #000000;">( </span><span style="color: #000000;">x, root </span><span style="color: #000000;">) )</span><span style="color: #000000;">;</span><br />
<span style="color: #ffffff;"> </span><span style="color: #000000;"> }</span><br />
<span style="color: #ffffff;"> </span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> /**</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> * Make the tree logically empty.</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> */</span><br />
<span style="color: #ffffff;"> </span><span style="color: #7f0055;"><strong> public </strong></span><span style="color: #7f0055;"><strong>void </strong></span><span style="color: #000000;">makeEmpty</span><span style="color: #000000;">( ) {</span><br />
<span style="color: #ffffff;"> </span><span style="color: #000000;"> root = </span><span style="color: #7f0055;"><strong>null</strong></span><span style="color: #000000;">;</span><br />
<span style="color: #ffffff;"> </span><span style="color: #000000;"> }</span><br />
<span style="color: #ffffff;"> </span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> /**</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> * Test if the tree is logically empty.</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> * </span><span style="color: #7f9fbf;">@return </span><span style="color: #3f5fbf;">true if empty, false otherwise.</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> */</span><br />
<span style="color: #ffffff;"> </span><span style="color: #7f0055;"><strong> public </strong></span><span style="color: #7f0055;"><strong>boolean </strong></span><span style="color: #000000;">isEmpty</span><span style="color: #000000;">( ) {</span><br />
<span style="color: #ffffff;"> </span><span style="color: #7f0055;"><strong> return </strong></span><span style="color: #000000;">root == </span><span style="color: #7f0055;"><strong>null</strong></span><span style="color: #000000;">;</span><br />
<span style="color: #ffffff;"> </span><span style="color: #000000;"> }</span><br />
<span style="color: #ffffff;"> </span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> /**</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> * Internal method to get element field.</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> * </span><span style="color: #7f9fbf;">@param </span><span style="color: #3f5fbf;">t the node.</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> * </span><span style="color: #7f9fbf;">@return </span><span style="color: #3f5fbf;">the element field or null if t is null.</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> */</span><br />
<span style="color: #ffffff;"> </span><span style="color: #7f0055;"><strong> private </strong></span><span style="color: #000000;">Comparable elementAt</span><span style="color: #000000;">( </span><span style="color: #000000;">BinaryNode t </span><span style="color: #000000;">) {</span><br />
<span style="color: #ffffff;"> </span><span style="color: #7f0055;"><strong> return </strong></span><span style="color: #000000;">t == </span><span style="color: #7f0055;"><strong>null </strong></span><span style="color: #000000;">? </span><span style="color: #7f0055;"><strong>null </strong></span><span style="color: #000000;">: t.element;</span><br />
<span style="color: #ffffff;"> </span><span style="color: #000000;"> }</span><br />
<span style="color: #ffffff;"> </span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> /**</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> * Internal method to insert into a subtree.</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> * </span><span style="color: #7f9fbf;">@param </span><span style="color: #3f5fbf;">x the item to insert.</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> * </span><span style="color: #7f9fbf;">@param </span><span style="color: #3f5fbf;">t the node that roots the tree.</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> * </span><span style="color: #7f9fbf;">@return </span><span style="color: #3f5fbf;">the new root.</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> * </span><span style="color: #7f9fbf;">@throws </span><span style="color: #3f5fbf;">DuplicateItemException if x is already present.</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;">*/</span><br />
<span style="color: #ffffff;"> </span><span style="color: #7f0055;"><strong> protected </strong></span><span style="color: #000000;">BinaryNode insert</span><span style="color: #000000;">( </span><span style="color: #000000;">Comparable x, BinaryNode t </span><span style="color: #000000;">) {</span><br />
<span style="color: #ffffff;"> </span><span style="color: #7f0055;"><strong> if</strong></span><span style="color: #000000;">( </span><span style="color: #000000;">t == </span><span style="color: #7f0055;"><strong>null </strong></span><span style="color: #000000;">)</span><br />
<span style="color: #000000;"> t = </span><span style="color: #7f0055;"><strong>new </strong></span><span style="color: #000000;">BinaryNode</span><span style="color: #000000;">( </span><span style="color: #000000;">x </span><span style="color: #000000;">)</span><span style="color: #000000;">;</span><br />
<span style="color: #7f0055;"><strong> else if</strong></span><span style="color: #000000;">( </span><span style="color: #000000;">x.compareTo</span><span style="color: #000000;">( </span><span style="color: #000000;">t.element </span><span style="color: #000000;">) </span><span style="color: #000000;">&lt; </span><span style="color: #990000;">0 </span><span style="color: #000000;">)</span><br />
<span style="color: #000000;"> t.left = insert</span><span style="color: #000000;">( </span><span style="color: #000000;">x, t.left </span><span style="color: #000000;">)</span><span style="color: #000000;">;</span><br />
<span style="color: #7f0055;"><strong> else if</strong></span><span style="color: #000000;">( </span><span style="color: #000000;">x.compareTo</span><span style="color: #000000;">( </span><span style="color: #000000;">t.element </span><span style="color: #000000;">) </span><span style="color: #000000;">&gt; </span><span style="color: #990000;">0 </span><span style="color: #000000;">)</span><br />
<span style="color: #000000;"> t.right = insert</span><span style="color: #000000;">( </span><span style="color: #000000;">x, t.right </span><span style="color: #000000;">)</span><span style="color: #000000;">;</span><br />
<span style="color: #7f0055;"><strong> else</strong></span><br />
<span style="color: #7f0055;"><strong> throw new </strong></span><span style="color: #000000;">DuplicateItemException</span><span style="color: #000000;">( </span><span style="color: #000000;">x.toString</span><span style="color: #000000;">( ) )</span><span style="color: #000000;">; </span><span style="color: #3f7f5f;">// Duplicate</span><br />
<span style="color: #7f0055;"><strong> return </strong></span><span style="color: #000000;">t;</span><br />
<span style="color: #ffffff;"> </span><span style="color: #000000;">}</span><br />
<span style="color: #ffffff;"> </span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> /**</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> * Internal method to remove from a subtree.</span><br />
<span style="color: #3f5fbf;">* </span><span style="color: #7f9fbf;">@param </span><span style="color: #3f5fbf;">x the item to remove.</span><br />
<span style="color: #3f5fbf;">* </span><span style="color: #7f9fbf;">@param </span><span style="color: #3f5fbf;">t the node that roots the tree.</span><br />
<span style="color: #3f5fbf;">* </span><span style="color: #7f9fbf;">@return </span><span style="color: #3f5fbf;">the new root.</span><br />
<span style="color: #3f5fbf;">* </span><span style="color: #7f9fbf;">@throws </span><span style="color: #3f5fbf;">ItemNotFoundException if x is not found.</span><br />
<span style="color: #3f5fbf;">*/</span><br />
<span style="color: #ffffff;"> </span><span style="color: #7f0055;"><strong> protected </strong></span><span style="color: #000000;">BinaryNode remove</span><span style="color: #000000;">( </span><span style="color: #000000;">Comparable x, BinaryNode t </span><span style="color: #000000;">) {</span><br />
<span style="color: #ffffff;"> </span><span style="color: #7f0055;"><strong> if</strong></span><span style="color: #000000;">( </span><span style="color: #000000;">t == </span><span style="color: #7f0055;"><strong>null </strong></span><span style="color: #000000;">)</span><br />
<span style="color: #ffffff;"> </span><span style="color: #7f0055;"><strong> throw new </strong></span><span style="color: #000000;">ItemNotFoundException</span><span style="color: #000000;">( </span><span style="color: #000000;">x.toString</span><span style="color: #000000;">( ) )</span><span style="color: #000000;">;</span><br />
<span style="color: #7f0055;"><strong> if</strong></span><span style="color: #000000;">( </span><span style="color: #000000;">x.compareTo</span><span style="color: #000000;">( </span><span style="color: #000000;">t.element </span><span style="color: #000000;">) </span><span style="color: #000000;">&lt; </span><span style="color: #990000;">0 </span><span style="color: #000000;">)</span><br />
<span style="color: #000000;"> t.left = remove</span><span style="color: #000000;">( </span><span style="color: #000000;">x, t.left </span><span style="color: #000000;">)</span><span style="color: #000000;">;</span><br />
<span style="color: #7f0055;"><strong> else if</strong></span><span style="color: #000000;">( </span><span style="color: #000000;">x.compareTo</span><span style="color: #000000;">( </span><span style="color: #000000;">t.element </span><span style="color: #000000;">) </span><span style="color: #000000;">&gt; </span><span style="color: #990000;">0 </span><span style="color: #000000;">)</span><br />
<span style="color: #000000;"> t.right = remove</span><span style="color: #000000;">( </span><span style="color: #000000;">x, t.right </span><span style="color: #000000;">)</span><span style="color: #000000;">;</span><br />
<span style="color: #7f0055;"><strong> else if</strong></span><span style="color: #000000;">( </span><span style="color: #000000;">t.left != </span><span style="color: #7f0055;"><strong>null </strong></span><span style="color: #000000;">&amp;&amp; t.right != </span><span style="color: #7f0055;"><strong>null </strong></span><span style="color: #000000;">) </span><span style="color: #3f7f5f;">// Two children</span><br />
<span style="color: #000000;"> {</span><br />
<span style="color: #000000;"> t.element = findMin</span><span style="color: #000000;">( </span><span style="color: #000000;">t.right </span><span style="color: #000000;">)</span><span style="color: #000000;">.element;</span><br />
<span style="color: #000000;"> t.right = removeMin</span><span style="color: #000000;">( </span><span style="color: #000000;">t.right </span><span style="color: #000000;">)</span><span style="color: #000000;">;</span><br />
<span style="color: #000000;"> } </span><span style="color: #7f0055;"><strong>else</strong></span><br />
<span style="color: #000000;"> t = </span><span style="color: #000000;">( </span><span style="color: #000000;">t.left != </span><span style="color: #7f0055;"><strong>null </strong></span><span style="color: #000000;">) </span><span style="color: #000000;">? t.left : t.right;</span><br />
<span style="color: #7f0055;"><strong> return </strong></span><span style="color: #000000;">t;</span><br />
<span style="color: #ffffff;"> </span><span style="color: #000000;">}</span><br />
<span style="color: #ffffff;"> </span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> /**</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> * Internal method to remove minimum item from a subtree.</span><br />
<span style="color: #3f5fbf;">* </span><span style="color: #7f9fbf;">@param </span><span style="color: #3f5fbf;">t the node that roots the tree.</span><br />
<span style="color: #3f5fbf;">*</span><span style="color: #7f9fbf;">@return </span><span style="color: #3f5fbf;">the new root.</span><br />
<span style="color: #3f5fbf;">* </span><span style="color: #7f9fbf;">@throws </span><span style="color: #3f5fbf;">ItemNotFoundException if x is not found.</span><br />
<span style="color: #3f5fbf;">*/</span><br />
<span style="color: #7f0055;"><strong>protected </strong></span><span style="color: #000000;">BinaryNode removeMin</span><span style="color: #000000;">( </span><span style="color: #000000;">BinaryNode t </span><span style="color: #000000;">) {</span><br />
<span style="color: #7f0055;"><strong>if</strong></span><span style="color: #000000;">( </span><span style="color: #000000;">t == </span><span style="color: #7f0055;"><strong>null </strong></span><span style="color: #000000;">)</span><br />
<span style="color: #7f0055;"><strong>throw new </strong></span><span style="color: #000000;">ItemNotFoundException</span><span style="color: #000000;">( )</span><span style="color: #000000;">;</span><br />
<span style="color: #7f0055;"><strong>else if</strong></span><span style="color: #000000;">( </span><span style="color: #000000;">t.left != </span><span style="color: #7f0055;"><strong>null </strong></span><span style="color: #000000;">) {</span><br />
<span style="color: #000000;">t.left = removeMin</span><span style="color: #000000;">( </span><span style="color: #000000;">t.left </span><span style="color: #000000;">)</span><span style="color: #000000;">;</span><br />
<span style="color: #7f0055;"><strong> return </strong></span><span style="color: #000000;">t;</span><br />
<span style="color: #000000;">} </span><span style="color: #7f0055;"><strong>else</strong></span><br />
<span style="color: #7f0055;"><strong>return </strong></span><span style="color: #000000;">t.right;</span><br />
<span style="color: #ffffff;"> </span><span style="color: #000000;">}</span><br />
<span style="color: #ffffff;"> </span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> /**</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> * Internal method to find the smallest item in a subtree.</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> * </span><span style="color: #7f9fbf;">@param </span><span style="color: #3f5fbf;">t the node that roots the tree.</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> * </span><span style="color: #7f9fbf;">@return </span><span style="color: #3f5fbf;">node containing the smallest item.</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> */</span><br />
<span style="color: #ffffff;"> </span><span style="color: #7f0055;"><strong> protected </strong></span><span style="color: #000000;">BinaryNode findMin</span><span style="color: #000000;">( </span><span style="color: #000000;">BinaryNode t </span><span style="color: #000000;">) {</span><br />
<span style="color: #ffffff;"> </span><span style="color: #7f0055;"><strong> if</strong></span><span style="color: #000000;">( </span><span style="color: #000000;">t != </span><span style="color: #7f0055;"><strong>null </strong></span><span style="color: #000000;">)</span><br />
<span style="color: #ffffff;"> </span><span style="color: #7f0055;"><strong> while</strong></span><span style="color: #000000;">( </span><span style="color: #000000;">t.left != </span><span style="color: #7f0055;"><strong>null </strong></span><span style="color: #000000;">)</span><br />
<span style="color: #ffffff;"> </span><span style="color: #000000;"> t = t.left;</span><br />
<span style="color: #ffffff;"> </span><br />
<span style="color: #ffffff;"> </span><span style="color: #7f0055;"><strong> return </strong></span><span style="color: #000000;">t;</span><br />
<span style="color: #ffffff;"> </span><span style="color: #000000;"> }</span><br />
<span style="color: #ffffff;"> </span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> /**</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> * Internal method to find the largest item in a subtree.</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> * </span><span style="color: #7f9fbf;">@param </span><span style="color: #3f5fbf;">t the node that roots the tree.</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> * </span><span style="color: #7f9fbf;">@return </span><span style="color: #3f5fbf;">node containing the largest item.</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> */</span><br />
<span style="color: #ffffff;"> </span><span style="color: #7f0055;"><strong> private </strong></span><span style="color: #000000;">BinaryNode findMax</span><span style="color: #000000;">( </span><span style="color: #000000;">BinaryNode t </span><span style="color: #000000;">) {</span><br />
<span style="color: #ffffff;"> </span><span style="color: #7f0055;"><strong> if</strong></span><span style="color: #000000;">( </span><span style="color: #000000;">t != </span><span style="color: #7f0055;"><strong>null </strong></span><span style="color: #000000;">)</span><br />
<span style="color: #ffffff;"> </span><span style="color: #7f0055;"><strong> while</strong></span><span style="color: #000000;">( </span><span style="color: #000000;">t.right != </span><span style="color: #7f0055;"><strong>null </strong></span><span style="color: #000000;">)</span><br />
<span style="color: #ffffff;"> </span><span style="color: #000000;"> t = t.right;</span><br />
<span style="color: #ffffff;"> </span><br />
<span style="color: #ffffff;"> </span><span style="color: #7f0055;"><strong> return </strong></span><span style="color: #000000;">t;</span><br />
<span style="color: #ffffff;"> </span><span style="color: #000000;"> }</span><br />
<span style="color: #ffffff;"> </span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> /**</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> * Internal method to find an item in a subtree.</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> * </span><span style="color: #7f9fbf;">@param </span><span style="color: #3f5fbf;">x is item to search for.</span><br />
<span style="color: #ffffff;"> </span><span style="color: #3f5fbf;"> * </span><span style="color: #7f9fbf;">@param </span><span style="color: #3f5fbf;">t the node that roots the tr