lunes, 20 de julio de 2009

*FIX* mod_rewrite: could not init rewrite log lock in child

Error al momento de enjaular apache y su respectiva solución.

Error
[crit] (2)No such file or directory: mod_rewrite: could not init rewrite log lock in child

Agregar esto

<ifmodule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_METHOD} ^TRACE
RewriteRule .* - [F]
</IfModule>

O esto:

<ifmodule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_METHOD} ^TRACE
RewriteRule .* - [F]
RewriteLog /var/log/apache2/rewrite.log
RewriteLogLevel 0
</IfModule>

Saludos.

jueves, 16 de julio de 2009

Pasar de extención nrg a iso en linux, cuando nrg2iso no funciona.

El otro dia me tope con la desagradable sorpresa al momento de intentar pasar una imagen nrg a iso con nrg2iso, lo cual desafortunadamente no funciono...

Buscando dentro de los repositorios de debian y/o ubuntu, encontre una aplicación llamada "iat" la cual cumple la misma función.

yo@mi-maquina:~$ apt-cache search iat && su root -c "apt-get install iat"
Password:

Y listo...
La forma de utilizar el programa, es a prueba de $%&/()!·$...
o sea...

yo@mi-maquina:~$ iat imagen.nrg nueva_imagen.iso

Saludos.

martes, 23 de junio de 2009

Problemas con locate + FreeBSD.

Uno de los problemas que me he encontrado al momento de leer foros de freebsd, es que en la mayoria de los casos no pueden utilizar el comando "locate", debido a que la forma de actualizar la base de datos interna, no es la misma que en linux.

Bueno, lo unico que tienen que hacer es ejecutar:

/usr/libexec/locate.updatedb

Aunque si quieren actualizar esto al modo linux, solo basta con hacer un simple enlace simbolico...

ln -s /usr/libexec/locate.updatedb /usr/bin/updatedb

Saludos.

lunes, 9 de marzo de 2009

Levantando un simple servidor DNS interno y externo con vistas.

Primero que todo "Hola", ya procedamos...
que necesitamos?
un servidor de nombre 2 tarjetas de red un cafe expreso sera suficiente, ya que este tema es bastante simple.

Instalando bind...
No explicare como hacerlo ya que es demasiado simple...
un ./configure --opciones && make && make install, y listo...

Antes de comenzar con la edición de los archivos debemos tener en cuenta o en su defecto saber que red interna tenemos...
En mi caso la "10.10.1.x".
Y como ip publica usaremos la 200.111.111.11.

Comenzamos la edición del corazon del dns...
en mi caso : "/etc/bind/named.conf"

Agregamos la siguiente vista interna:

view "internal" {
match-clients {10.10.1.0/24; 127.0.0.0/8;};
recursion yes;

zone "." {
type hint;
file "/etc/bind/db.root";
};

zone "dominio.cl" {
type master;
file "/etc/bind/internal.dominio.cl";
allow-transfer {any;};
allow-update {none;};
};
zone "localhost" {
type master;
file "/etc/bind/db.local";
};

zone "127.in-addr.arpa" {
type master;
file "/etc/bind/db.127";
};

zone "0.in-addr.arpa" {
type master;
file "/etc/bind/db.0";
};

zone "255.in-addr.arpa" {
type master;
file "/etc/bind/db.255";
};
};

Ahora la vista "externa":

view "external" {
match-clients {any;};
recursion no;
zone "dominio.cl" {
type master;
notify yes;
file "/etc/bind/external.dominio.cl";
};
};

Cabe destacar que por motivos de seguridad tenemos denegado la recursion a las zonas externas.

Bien...
Ahora vamos por la configuración de los archivos en si.

primero internal.dominio.cl

$TTL 1D ; 1 day
@ IN SOA ns.dominio.cl. info.dominio.cl. (
2009022777 ; Serial number
1600 ;
300 ; 5 minutes retry
17280 ; 2 days expiry
43200) ; 12 hours minimum
IN NS ns.dominio.cl.
IN MX 10 mail.dominio.cl.
IN A 10.10.1.2
$ORIGIN dominio.cl.
ns A 10.10.1.2
mail A 10.10.1.1
www A 10.10.1.2

Aca le estamos diciendo que el servidor NS es la ip del servidor de nombre...
en mi caso: 10.10.1.2, el servidor de correo esta en la ip 10.10.1.1
y bueno...
el resto es deducible.

Ahora vamos con external.dominio.cl
$TTL 1D ; 1 day
@ IN SOA ns.dominio.cl. info.dominio.cl. (
2009022777 ; Serial number
1600 ;
300 ; 5 minutes retry
17280 ; 2 days expiry
43200
) ; 12 hours minimum

IN NS ns.dominio.cl.
IN MX 0 mail.dominio.cl.
IN A 200.111.111.111

$ORIGIN dominio.cl.
ns IN A 200.111.111.112
www IN A 200.111.111.112
mail IN A 200.111.111.111


Una vez tenemos todos nuestros registros agregado a los archivos, procedemos reiniciar el servicio...

Con el tipico "/etc/init.d/{bind,named} restart"
o si no con un simple "kill -9 $PID && named"

En fin...
eso es todo.

Saludos.

sábado, 7 de marzo de 2009

Fecha en php

El motivo de esta entrada, es que varias veces foreando, me he encontrado con la pregunta...
"Como pongo la fecha en español con la funcion date de php?".

Por ello, he creado un script simple, sin muchas lineas, las cuales les ayudaran para ello.

<?php
$meses=array(
"Janaury"=>"Enero",
"Febraury"=>"Febrero",
"March"=>"Marzo",
"April"=>"Abril",
"May"=>"Mayo",
"June"=>"Junio",
"July"=>"Julio",
"August"=>"Agosto",
"September"=>"Septiembre",
"October"=>"Octubre",
"November"=>"Noviembre",
"December"=>"Diciembre"
);

$semana=array(
"Monday"=>"Lunes",
"Tuesday"=>"Martes",
"Wednesday"=>"Miercoles",
"Thursday"=>"Jueves",
"Friday"=>"Viernes",
"Saturday"=>"Sabado",
"Sunday"=>"Domingo"
);
echo $meses[date("F")]." - ".$semana[date("l")];
?>

Al final aparece como usarlo...

por ejemplo si queremos imprimir en pantalla, hoy es sabado 7 de Marzo del 2009

solo tendriamos que escribir:

echo "hoy es ".$semana[date("l")]." de ".$meses[date("F")]." del ".date("Y");


Saludos.

martes, 24 de febrero de 2009

Agis + php + GotoIfTime + mysql + asterisk = Un par de horas de trabajo.

Bueno...
Primero que todo "hola", ya mucho saludo...

El motivo de esta entrada es ayudar a los Sysadmin que tienen bajo responsabilidad servidores asterisk.
Con el fin de que la telefonia, no se transforme en un abuso despues del horario laboral.

Caso hipotetico:
- Supongamos que el horario laboral de una empresa es entre las 09 y 19 hrs entre lunes a viernes,
una vez que todo el personal se halla retirado de las dependencias de su empresa, llega la persona encargada de realizar el aseo a esta. A lo que vamos, es que nadie nos asegura que esta persona, no se pondra a realizar largas llamadas con coste para la empresa.

Entonces, nos quedan 3 opciones...
- Limitamos para que nadie realice llamadas.
- Dejamos el sistema abierto y que llame descontroladamente.
- Generamos un sistema de autentificación el cual funcionara despues de la jornada laboral.

Obviamente descartaremos las primeras 2 opciones.
En la tercera opción, la podemos realizar de 2 formas...
Una con authenticate y disa, las cuales me dio flojera adentrarme en el tema...
y la otra con Agi y bases de datos...

Obviamente, por el titulo de esta entrada, ya sabran cual usaremos esta vez.
ya...
manos a la obra...
lo primero que necesitaremos es:
Un servidor corriendo con asterisk, lo ideal que la distribución sea Debian en el caso de linux.
Ya que Redhat y CentOS apéstan.

Necesitaremos:
php5
php5-mysql
php5-cli
mysql-server
y amigos (o sea... dependencias).
phpagi v2.

Una vez que tengan todo esto instalado,
Procederemos a la configuración.

Todos las AGI de asterisk, por defecto se encuentran en el directorio "/var/lib/asterisk/agi-bin"
Las AGI son como los cgi del http, esto quiere decir que a nuestra central le haremos ejecutar un archivo, al cual le pasaremos parametros de asterisk para que ejecute de mejor forma el proceso.

descomprimir el archivo phpagi-2.14.tar.gz (este es el usado en este ejemplo, aunque la version puede variar) dentro del directorio "/var/lib/asterisk/agi-bin", lo cual nos dara un directorio llamado "phpagi-2.14/", renombrenlo como quieran, es cosa de cada uno...

El tema es que en mi caso particular lo deje tal cual.:

pbx:~# ls /var/lib/asterisk/agi-bin/phpagi-2.14
COPYING docs mkdocs.php phpagi-asmanager.php phpagi-fastagi.php phpagi.php README

ya...
ahora procederemos a crear una nueva entrada en el dialplan (extensions.conf).

Con su editor de texto favorito editen el archivo...
en mi caso estoy acostumbrado a "vi".
############################################

Asterisk

############################################
pbx:~# vi /etc/asterisk/extensions.conf #### y agregamos lo siguiente.

[locales_prueba]
exten => _XXXXXXX,1,GotoIfTime(9:00-19:00|mon-fri|*|*?dentrohorario,${EXTEN},1)
exten => _XXXXXXX,n,Answer
exten => _XXXXXXX,n,Agi(logea|${EXTEN}|${CALLERID(NUM)})
exten => _XXXXXXX,n,hangup

[dentrohorario]
exten => _XXXXXXX,1,Dial(Zap/g1/${EXTEN},50)
exten => _XXXXXXX,n,hangup

######### EOF

la primera entrada es la que le definiremos a los usuarios SIP como contexto.
En la primera prioridad del contexto vemos algo como GotoIfTime, hare una explicación corta, ya que me cargan las explicaciones largas...
Quiere decir que haga un salto a otro contexto u otra prioridad si se cumple la condición del horario.
es decir... que si se encuentra dentro del horario, entonces salte al contexto [dentrohorario] que ejecute la primera prioridad de la llamada...
me entienden?...
un poco mas simple....

si realizan una llamada dentro del horario al telefono 1111111, entonces esta le pasa la llamada al contexto [dentrohorario] y la prioridad 1, que esta vendria ejecutando la llamada.
Si esto no fuera asi, entonces ejecutaria la prioridad 2 dentro del contexto [locales_prueba], la cual lo que hace es ejecutar el script AGI llamado logea, con sus respectivos parametros.

${EXTEN} = "Telefono de destino, o sea... a que numero se esta llamando (1111111)".
${CALLERID(NUM)} = "Quien es el que realiza la llamada".

################################

phpagi

################################

Una vez destarjetezeado el archivo (que chileno), ingresamos a el...
pbx:~# cd /var/lib/asterisk/agi-bin/phpagi-2.14/
pbx:~# ls
CHANGELOG CVS fastagi.xinetd phpagi.example.conf README.phpagi README.phpagi-asmanager README.phpagi-fastagi

Aca lo unico que nos interesa es el archivo phpagi.example.conf, el cual copiaremos a /etc/asterisk/phpagi.conf

posterior a ello, editamos el archivo:

pbx:~# vi /etc/asterisk/phpagi.conf
Lo unico que editamos es la seccion [phpagi] y modificamos los parametros.
[phpagi]
debug=true
error_handler=true
admin=tu@correo
hostname=el_host_de_la_maquina_de_asterisk
tempdir=/var/spool/asterisk/tmp/

############ EOF ################

Ahora procederemos a configurar nuestros scripts.
Primero debemos crear una base de datos para los usuarios y las claves.

pbx:~# mysql asterisk
mysql> create table usuario ( id_usuario int(10) not null auto_increment, nombre_usuario char(100) not null default'', clave_usuario char(64) not null default'', primary key(id_usuario));

#### Donde nombre_usuario contendra el numero que realiza la llamada, enrealidad deberia llamarse numero_usuario, pero ahi lo modifican ustedes, ya que esto es un mero y funcional ejemplo del mini sistema.

Una vez generada la tabla para los usuarios, le agregamos uno de prueba...
insert into usuario values (0,'123','e10adc3949ba59abbe56e057f20f883e');

La clave del usuario es "123456" (sin comillas), esto es sumamente facil con php y la funcion md5
resumido...

hagan un script php y pongan lo siguiente:

vi archivo.php e ingresan esto a continuación.

#!/usr/bin/php5 -q
<?php
$string="123456";
$clave=md5($string);
printf("$clave\n");
?>

pbx:~# chmod +x archivo.php
pbx:~# ./archivo.php
e10adc3949ba59abbe56e057f20f883e
pbx:~#

ahora bien...
Necesitamos crear el archivo "logeo" el cual contendra la logica que procesara los nombres de usuarios y a su vez les solicitara la clave correspondiente.

#!/usr/bin/php5 -q
<?php
$org=$argv[2];
$dst=$argv[1];
require ("phpagi-2.14/phpagi.php");
error_reporting(E_ALL);
$agi = new AGI();
$agi->answer();
$agi->text2wav("Porfavor ingrese su clave");
$recoje=$agi->get_data('beep',3000,10);
$clavex=$recoje['result'];
if(!empty($clavex)){
$host="localhost";
$user="USUARIO";
$pass="PASSWORD";
$db="asterisk";
$con=mysql_connect($host,$user,$pass) or die(mysql_error());
mysql_select_db($db,$con);
$clave=md5($clavex);
$sql=mysql_query("select * from usuario where nombre_usuario='$org' and clave_usuario='$clave'",$con);
$rs=mysql_fetch_array($sql);
$logeado=$rs['nombre_usuario'];
if(empty($logeado)){
$agi->text2wav("La clave ingresada es incorrecta Adios");
} else {
$agi->exec("Dial Zap/g1/$dst,50");
}
mysql_close($con);
} else {
$agi->text2wav("El tiempo de espera ha concluido Adios");
}
$agi->Hangup();
?>

############
Aca hay un tema que no se ha tocado, y que es el que el lector actualemente se haya dado cuenta...
es sobre "text2wav", creo que con solo leer sabran para que sirve...
Para esto necesitamos el programa festival el cual pasa de texto a voz, pero sinceramente las voces por defecto son demasiado roboticas, asi que les aconsejaria que siguieran el siguiente "howto" el cual explica como instalarlo y dejarlo funcional:

festival en spanish (Coño!)
############

Ahora bien...
Para que los mismos usuarios realicen sus propios cambios de claves, sin necesidad que nos esten molestando, o por solamente dejar esto mas transparente, realizamos el siguiente AGI (cambiarclave).
Que a continuación se muestra.:

#!/usr/bin/php5 -q
<?php
require("phpagi-2.14/phpagi.php");
$host="localhost";
$user="USUARIO";
$pass="PASSWORD";
$db="asterisk";
$con=mysql_connect($host,$user,$pass) or die(mysql_error());
mysql_select_db($db,$con);
error_reporting(E_ALL);
$org=$argv[1];
$agi=new AGI();
$agi->answer();
$agi->text2wav("Por favor ingrese su actual clave");
$datos=$agi->get_data('beep',3000,10);
$clave=$datos['result'];
if(!empty($clave)){
$clave=md5($clave);
$sql=mysql_query("select clave_usuario from usuario where nombre_usuario='$org'",$con);
$res=mysql_fetch_array($sql);
$cl=$res['clave_usuario'];
do {
$agi->text2wav("La clave ingresada es incorrecta");
$agi->text2wav("Por favor ingrese su actual clave");
$datos=$agi->get_data('beep',3000,10);
$clave=$datos['result'];
$clave=md5($clave);
} while($cl!=$clave);
$agi->text2wav("Por favor ingrese su nueva clave");
$actualiza1=$agi->get_data('beep',3000,15);
$nueva=$actualiza1['result'];
$agi->text2wav("Reingrese la nueva clave");
$actualiza2=$agi->get_data('beep',3000,15);
$nclave=$actualiza2['result'];
do {
$agi->text2wav("Las claves no coinciden");
$agi->text2wav("Por favor ingrese su nueva clave");
$actualiza1=$agi->get_data('beep',3000,15);
$nueva=$actualiza1['result'];
$agi->text2wav("Reingrese la nueva clave");
$actualiza2=$agi->get_data('beep',3000,15);
$nclave=$actualiza2['result'];
} while($nclave!=$nueva);
if($nclave==$nueva){
$clave_nueva=md5($nclave);
$update="update usuario set clave_usuario='$clave_nueva' where nombre_usuario='$org'";
mysql_query($update,$con);
$agi->text2wav("La clave ha sido cambiada exitosamente su nueva clave es $nclave");
$agi->text2wav("adios");
$agi->hangup();
}
mysql_close($con);
} else {
$agi->text2wav("El tiempo limite ha sido excedido adios");
$agi->hangup();
}
?>

Para habilitar este servicio.
debemos generar una nueva entrada al contexto de los usuarios, por ejemplo designemosles el numero "222", la sintaxis seria la siguiente:

exten => 222,1,Answer
exten => 222,n,Agi(cambiarclave|${CALLERID(NUM)})
exten => 222,n,Hangup

Dentro del contexto definido para los usuarios, que no se les olvide...
En este caso ponganlo dentro locales_prueba y dentrohorario.

Solo nos queda darles permiso de ejecución a los archivos.
esto seria:

pbx:~# cd /var/lib/asterisk/agi-bin
pbx:/var/lib/asterisk/agi-bin# chmod +x logeo cambiarclave

y Realizamos las pruebas correspondiente...

Espero que les sirva, y he intentado no dejar nada en el tintero...
si falta algo o no funciona, posteenlo y lo respondere a la brevedad...

Dedicatoria:

- A mi compare Poncio Monsalvez (talla interna).
- A mi PC que le cayo cafe en el teclado el dia de hoy, pero ni se quejo.
- Al Juan por hablar estupideces...
- Al Poncio que me presiona para que le envie los tips.

Eso seria...

Fuentes:
http://phylevn.mexrom.net/index.php/blog/show/Como_implementar_un_AGI_con_PHP_en_un_conmutador_de_VoIP_sobre_Asterisk.html
http://google.cl
http://www.voip-info.org

jueves, 29 de enero de 2009

Tomcat +ssl +jboss

Es un asco...
recorri bastantes foros buscando la bendita forma de como hacerlo...
hasta que di con una solución...
la mas practica y simple que habia visto...
por mi parte tambien pense que se podia hacer, pero me deje guiar por la documentación.
beps
solución simple.


openssl genrsa -out key.pem 2048
openssl req -new -x509 -key key.pem -out cert.pem -days 365
openssl pkcs12 -export -in cert.pem -inkey key.pem -out cert.p12 -name

Asegurence de ponerle clave al certificado.

posteriormente, modificar el server.xml de tomcat.

<connector port="8443" address="${jboss.bind.address}" maxthreads="100" strategy="ms" maxhttpheadersize="8192" emptysessionpath="true" scheme="https" secure="true" clientauth="false" keystoretype="PKCS12" keystorefile="/path/al/archivo/conf/ssl/cert.p12" keystorepass="LA_PASS_QUE_LE_PONEMOS_AL_CERTIFICADO" sslprotocol="TLS">


Despues reiniciar el servicio.

/opt/jboss-4.2.2.GA/bin/shutdown.sh -S
nohup /opt/jboss-4.2.2.GA/bin/run.sh -b 0.0.0.0 &

realizamos un nmap y que lindo

el puerto 8443 esta en escucha...
abrimos firefox y aceptamos el certificado autofirmado y felices para siempre :D

Para dejarlo transparente...
deben modificar el mod_jk, pero eso sera en otra ocación miren que ahora estoy chato
xD
bye

viernes, 23 de enero de 2009

Dolor de cabeza por ruby +mongrel +windows +postgresql

Como se hace mensión en el titulo, estos 2 ultimos dias han sido algo desagradables...

Comenzamos el dia en una prestigiosa empresa vinicola en a la cual debia levantar una aplicación escrita en ruby, pero en un ambiente windows.

Lo primero que se me vino a la mente fue...
"Descargar la aplicación y derivados, hacer un par de configuraciones y en 1 hora deberia estar listo, incluyendo las pruebas para que el cliente estubiese conforme".
Resultado "LAS PELOTAS"
6 horas me tomo el chiste...
Detalle de la aventura...

Llevaba en mi buen pendrive las aplicaciones o sea:
- Ruby 1.8.x
- PostgreSQL 8.3.x
- Apache 2.2.x

Comenzamos la instalación con ruby...
Ningún problema, pero para mi desagradable sorpresa, necesitaba algunas librerias las cuales se instalaban via "gem", lo cual en esa situación me complico un poco debido a que en la empresa a la cual fui, por defecto tienen denegado el acceso a internet excepto el puerto 80...
Desconosco el protocolo de comunicación que utiliza 'gem', pero el punto es que no pude instalarlo tan rapido como ubiese querido...

Ya...
Nos comunicamos con el administrador de red para solicitar permiso y que nos permitiera el acceso total a la ip que tenia ese equipo.
La buena noticia es que se logro la comunicación necesaria para que comenzase la descarga.
La mala noticia es que el enlace internacional que tiene esa empresa es un asco.

Mientras que se realizaba la descarga de las librerias, nos encontramos con otra desagradable sorpresa...
El paquete de instalación de postgres al finalizar la instalación encontraba un error y no permitia continuar con esta y comenzaba a desinstalarse...
"Bendita suerte..."
Lo unico que se me ocurrio en ese momento fue downgradear la versión la cual se iba a instalar en dicho equipo...
o sea...
volver a la versión 8.2.x, la cual al comenzar a descargar nos demoramos cerca de 3 horas en bajar todas las librerias necesarias de ruby y tambien postgres 8.2.x.

3 horas despues estaba instalando postgres 8.2.x, el cual al finalizar la instalación me arrojo un error de permisos... (lo raro es que estabamos con un usuario el cual tenia privilegios de administrador), pero en fin "Es windows" y ya no me sorprende los errores tontos que este trae...
Le pregunte la password de administrador, cosa que no tenia idea...
Despues de llamar a la mesa de ayuda de la empresa, intentamos todas las contraseñas posibles que ellos nos decian, PERO NINGUNA FUNCIONO!!!...
ahora viene la parte (Ley de murphy).
Intentamos sin usar clave y voila!, funciono...
En fin, se instalo postgres sin ningún inconveniente.

Pero...
Para mi desagradable sorpresa, nos encontramos con un problema con las librerias de postgres, ya que no se instalaba de la misma forma que en Unix.

En windows el paquete se llama:
ruby-postgres
y en Unix solo se llama:
postgres

o sea... debiamos instalar en windows de la siguiente manera...
gem install ruby-postgres
en vez de:
gem install postgres

En teoria, una vez realizado esto, el tema de la sincronización con la base de datos deberia quedar resuelto.
Cosa que no fue tan asi...
debido a que nos pedia algunas librerias de postgres, mas conocidas como las "postgres-dev" en Unix.
La solución encontrada por aca fue que debiamos realizar una copia de X librerias al directorio de Ruby.
En este caso C:\ruby\bin desde C:\path\postgresql\bin
estos son:

- comerr32.dll
- krb5_32.dll
- k5sprt32.dll
- libeay32.dll
- libpq.dll
- libiconv2.dll
- libintl3.dll
- ssleay32.dll
- gssapi32.dll

Yo felizmente pensaba...
Por fin... ahora levanto el servicio y chao!...
Me limito a decir que solo me que quede con las ganas, ya que al correr el comando:
// En la directorio de la aplicación.

mongrel_rails start -d -p 3000 -e production
Y me sorprendo con lo que me arroja de vuelta es un lindo error que dice que win32 no soporta este servicio...
Fue cuando dije...
"Este sera un laaaaaaargo dia..."
Afortunadamente, san google siempre esta ahi cuando tenemos problemas.
No recuerdo con exactitud que pagina es pero, pongo la solución.

mongrel_rails service::install -N NOMBRE_APLICACION -c "C:\APLICACION" -p 3000 -e production

seguido por:
net start NOMBRE_APLICACION

y listo.
Problema solucionado.
Ahora el tema era que se iniciara automaticamente...
Con la primera linea, si se percatan dice... "service::install"
con esto creamos una entrada en "services.msc", y solo nos faltaria modificarla para que el servicio se iniciara automaticamente al prender el equipo.

Nos fuimos a Inicio, ejecutar y ahi escribimos: services.msc
buscamos el nombre que le pusimos al servicio... En este ejemplo "NOMBRE_APLICACION"
y lo editamos, y le decimos que se inicie automaticamente...

Despues de realizar unas pruebas con internet explorer, decidimos a cambiar a firefox
ya que no habria por IE, pero si con firefox...

Bueno...
demostrado que el tema fue solucionado, el cliente se quedo tranquilo
Fin.

NO QUIERO SABER MAS DE WINDOWS!!!