Renderizador de variantes varias de Mandelbrot
Pues eso, que he ampliado y traducido a C++ este script, debería ser bastante portable, todo es estándar (bueeeno, los pthreads...), lo único que me preocupan son las tuplas que tenían una ruta curiosa ¿? enfin, que debería funcionar bien, la memoria está bastante pulida y tal ( aunque todos sabemos como son estas cosas xD ).
Se puede descargar de este repo [ https://gitorious.org/rand/ff ], compila
con make
(en Unix debería detectar solo el número de núcleos, en todo caso
se puede especificar con -t <hilos>
), se pueden ver los parámetros con ./ff
-h
, ahora algunas pruebas con los modos nuevos... ( las 3 primeras están
rotadas 90 grados )
[caption id="attachment_920" align="aligncenter" width="580" caption="Buddhabrot: -a -i 1000 -m 100 -d 120 -r 10000000 -w 3000 -h 3000"][/ caption]
[caption id="attachment_921" align="aligncenter" width="580" caption="Anti buddhabrot: -aa -i 1000 -m 100 -d 120 -r 10000000 -w 3000 -h 3000"][/caption]
[caption id="attachment_922" align="aligncenter" width="580" caption="Buddhabrot Hologram: -ho -a -i 1000 -m 100 -r 100000000 -w 1200 - h 1200 -d 150"][/caption]
[caption id="attachment_926" align="aligncenter" width="600" caption="Julia basado en buddhabrot: -a -i 500 -m 100 -r 1000000 -j -1.1 0.1 -b"][/caption]
Y hay un par más subidas a deviantart ( de las que no recuerdo los parámetros :P )
http://kenkeiras.deviantart.com/art/Bodhi-bird-263712574
http://kenkeiras.deviantart.com/art/Anti-Buddhabrot-263741789
Eso es todo, hasta otra
[Referencias]
http://www.superliminal.com/fractals/bbrot/bbrot.htm
http://www.superliminal.com/fractals/bgram/bgram.html
Librería necesaria para instalar Freenet en Trisquel 5 [tip]
Después de 20 minutos buscando por qué fallaba ( no da error, solo no muestra el interfaz del instalador :P ), y antes de que le pase a alguien más: sudo apt-get install openjdk-6-jre
Ojalá todo fuera tan fácil de solucionar xD
Conocer en número de nucleos en Unix [C]
Muy rápidamente...
El número de nucleos de CPU se puede ver a través del directorio "/sys/ devices/system/cpu/", así que aprovechando que en Poesia_binaria_hay_un_post sobre_como_leer_directorios_en_C... aquí está un código que lee, la idea sería usar la función para usar el número correcto de hilos/procesos [getcpus.c]
include
include
include
include
define CPU_PATH "/sys/devices/system/cpu/"
int getCores(){
DIR *dir;
struct dirent* it;
int count = 0;
int i, isCpu;
dir = opendir(CPU_PATH);
if (dir == NULL){
exit(1);
}
while((it = readdir(dir)) != NULL){
if (strncmp(it->d_name, "cpu", 3) == 0){
isCpu = 1;
for(i = 3; it->d_name[i] != '\0'; i++){
if ((it->d_name[i] < '0')||(it->d_name[i] > '9')){
isCpu = 0;
break;
}
}
count += isCpu;
}
}
closedir(dir);
return count;
}
int main(int argc, char **argv){
printf("Encontrado(s): %i nucleo(s)\n", getCores());
return 0;
}
Hasta la próxima
Writting a brainf*ck parser with BLK
At last! at this time BLK can compile a reasonable C subset... well, ok, it needs pointers and structures in order to have something decent, but the former are picky to simulate in a interpreter, and the structures are in the way. The important thing is that the general structure is more or less stable, even inside the prototyping branch, a consecuence is that is open to any participation :), so let's see an example of how to write a little brainf*ck parser.
The first thing we'll do is to import the bytecode manager and prepare a constant to hold the memory size, in this case it will be a static
1 2 3 |
|
The parser will be encapsulated in a class with the following scheme
1 2 3 4 5 |
|
Now comes the class intializer function, it receives the bytecode manager as the only parameter
1 2 |
|
Now we have to prepare a space to hold the code, it gets grouped in frames (which nearly matches the concept of C blocks, they can represent functions, loops or condicionals), at least one is needed in the code to be executable by the interpreter, let's call it '_start'
1 2 |
|
The syntax is:
1 |
|
Now we can define variables and operations inside that, let's manually create a cursor variable to point the current memory position and assign it the value 0
1 2 |
|
Here we have two more functions, the first one, Bytecode_manager.add_variable
receives the variable name, it's type, the frame and optionally a comment about
the variable as parameters.
Bytecode_manager.add_op
adds an operation to the frame, the first parameter is
the type of operation, the second one, a reference to the variable where the
result will be stored, as third the function parámeters (it would be a list if
there's more than one), and at last the frame.
It's also posible to create a new type to represent our variables, for example an array to keep track of the memory. Types are represented as dictionaries, al least with the attribute 'byte_size' with the obvious use, there are, too, other useful values like 'structure', which tells the size of the dimensions of the type, for example [2, 3] for a 2x3 array
1 2 |
|
The same can be done with variable references, if they are passed as dictionaries, it's possible to tell in 'pos' which part should be taken into account
1 2 3 |
|
The rest of the parse function doens't need anything new, just ADD_OP and SUB_OP over the two references we just defined, all less the '[' which will be mentioned next
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
|
To add a flow contro operation we'll use Bytecode_manager.add_branch
,
pasing as first parameter the branching type
(WHILE_BRANCH
, IF_BRANCH
, ELSE_BRANCH
or DO_WHILE_BRANCH
),
the second is the condition, if it's different than 0, the conditional is
executed or the loop keeps running, the third is the frame, it
also optionally accepts two more, one for the operations which take place
before the condition is checked and the last one for operations which takes
place befere from the second iteration on, this operation returns a frame for
the operations which takes place inside it.
1 |
|
The rest of the code is generic enough to barely need any explanation
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
|
Lo que si que se hace necesario mencionar es Bytecode_manager.add_entry_point
que indica la función por la que entrar y Bytecode_manager.save
para guardar
el código
Which does need get mentioned is Bytecode_manager.add_entry_point
to point the
entry function and Bytecode_manager.save
to save the code
O que si que é necesario mencionar é Bytecode_manager.add_entry_point
que
indica a función pola que entrar, e Bytecode_manager.save
para garda-lo código
The full source code is here:
See you
Modificando `wardrive-android`
Bueno, pues aquí estamos, reestrenando blog :D
La aplicación Wardrive de android es una excelente herramienta para mapear redes con el móvil, que además está liberada bajo la licencia GNU GPLv3, en este post veremos como añadirle la opción de enviar la base de datos a un servidor web remoto.
Captura de la aplicación tomada del_repositorio
Lo primero que tenemos que hacer es descargar el código fuente, con svn checkout http://wardrive-android.googlecode.com/svn/trunk/ wardrive- android-read-only
Una vez hecho esto, lo abrimos con el IDE que prefiramos ( no me pararé a explicar como instalar los complementos para desarrollar para Android, se puede encontrar con una simple búsqueda ).
En el caso de NetBeans nos notificará que hay un problema, si hacemos click con el botón derecho en el proyecto y pulsamos en "Resolver problemas de referencia", dirá que '"Android_gapi_1.6" platform not found'. Si pulsamos en el botón resolver abrirá el gestor de plataformas, así que solo tenemos que seleccionar "Add platform".
El tipo de plataforma a instalar será "Google android ..."
A continuación tendremos que seleccionar la ruta al SDK
Y por último darle un nombre, "Android_gapi_1.6", y seleccionar la plataforma objetivo.
Una vez solucionados los problemas con el IDE, si no existe hay que crear un Dispositivo Android Virtual que incluya las API de Google, utilizadas para mostrar los mapas.
Ahora toca liarse con el código...
Primero añadiremos la opción de enviar los datos a la lista de opciones que
se accede a través del Menú > More. Este menú se encuentra en el
archivo options_menu.xml, en el directorio /res/menu , debajo de la siguiente
línea añadimos la misma modificada para nuestra opción:
El archivo quedaría por ejemplo así:
Además habría que añadir la cadena que tendría en cada idioma a los
archivos string.xml, aunque con añadirlo a la que se muestra por defecto es
suficiente en las pruebas dio problemas al añadirlo solo por defecto, aquí se
explica el paso para ponerlo en inglés. Podemos encontrar los valores en el
directorio /res/values-/ , buscamos la línea que contenga MENU_SEND_TO_WIGLE,
y la copiamos modificando los valores necesarios, es decir, añadimos esta
línea:
Hecho esto, ya se muestra la opción, aunque lo único que hace es mostrar el 'about':
Lo que queda por cambiar es la acción que se toma al pulsar el botón, esto se define en el case de la función onOptionsItemSelecteddel archivomain.java, bajo este switch: switch (item.getItemId())
Añadimos nuestro case: case R.menu_id.SEND_TO_SERVER:
showDialog(Constants.DIALOG_SERVER_UPLOAD);
break;
Bien, vamos entonces con el diálogo, al switch de la función protected Dialog onCreateDialog(int id) (~línea 625 ), hay que añadirle un nuevo case que tome la URL y nos la pase a una función para manejarla: case Constants.DIALOG_SERVER_UPLOAD:
builder = new AlertDialog.Builder(this);
final EditText URIinput = new EditText(this);
URIinput.setText("");
builder.setView(URIinput);
builder.setPositiveButton(getString(R.string.OK), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
String uri = URIinput.getText().toString().trim();
send_to_server(uri);
}
});
builder.setNegativeButton(getString(R.string.NO),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
send_to_server(null);
}
});
return builder.create();
Lógicamente hay que añadir un valor DIALOG_SERVER_UPLOAD a la clase Constants en Constants.java, como public static final int DIALOG_SERVER_UPLOAD = DIALOG_WIGLE_UPLOAD + 1;
Además hay que importar android.widget.EditText, que se utiliza en el Dialog.
Todo lo que queda por escribir es la función send_to_server(), que hace return
si el string es null o envía el archivo a la url en un POST multipart,
nombrandolo como 'wardrive'.
public void send_to_server(String url){
if(url == null){
return;
}
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(url);
File f = new File("/sdcard/wardrive.kml");
try {
MultipartEntity entity = new MultipartEntity();
entity.addPart("wardrive", new FileBody(f));
httppost.setEntity(entity);
httpclient.execute(httppost);
} catch (Exception e) {
}
}
Para esta función se requiere tener los .jar apache-mime4j, httpmime, httpclient y httpcore en el directorio de compilación e importar esto: import android.widget.EditText;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
Nota: lógicamente hay que exportar el KML antes de enviarlo al servidor
El código fuente resultante: wardrive-mod.zip
Y compilado: wardrive.apk
Y eso es todo, nos vemos. [Referencias] http://code.google.com/p/wardrive-android/ http://www.softwarepassion.com/android-series-get-post-and-multipart-post- requests/ https://code.google.com/p/androidmcr/source/browse/trunk/MCR/apache-mime4j- 0.6.jar?r=85 https://code.google.com/p/google-secure-data-connector/source/browse/trunk/ data-connector-agent/third-party/httpcomponents-client-4.0.1/httpmime- 4.0.1.jar?r=525
Como hacer las imagenes que ponen ip, navegador...
Para esto necesitaremos un servidor HTTP ( como apache ) y PHP, las dos cosas es lo tipico que se encuentra en un hosting gratuito ( aqui hay una lista )
Si lo vamos a alojar nosotros mismos necesitaremos habilitar el paquete php-gd para esto edita el php.ini, descomenta la linea de ";extension=php_gd2.dll" (quitale el ';'... en algunos casos es un '#') En debian/ubuntu se hace con "sudo apt-get install php5-gd"
Vamos alla...
Buscamos una imagen, la imagen sera la base, conviene que sea lo mas uniforme posible para que quede bien, yo escogí esta, aun que no sea la mas apropiada
Preparamos el codigo en PHP
El siguiente codigo es el que escribira en la imagen
Como funciona? (Para l@s que no les guste leer los comentarios del codigo)
Se usan dos funciones (navegador y os), que buscan en la cadena del "User- Agent", alguna parte conocida (Firefox, MSIE, etc...), y que devuelven el navegador y el sistema operativo del usuario
El resto es PHP,
$back="esfera.png"; //Imagen de fondo $img=imagecreatefrompng($back); //Se crea la imagen (desde un png)
Como indican los comentarios, la primera linea es saber donde esta la imagen base, la segunda es para importarla como PNG, tambien se puede hacer para jpg
imagecreatefromjpeg
o con gif
imagecreatefromgif
(aqui hay mas funciones parecidas: http://us3.php.net/manual- lookup.php?pattern=imageCreateFrom&lang=es)
$fcolor=ImageColorAllocate($img,255,120,0); // El color de las letras ($img,r,g,b)
Prepara el color de las letras en la imagen (recuerda que la imagen esta en $img), el color se asigna en rgb, de 0 a 255 (esta combinacion, "255,120,0", seria naranja)
$ip=$_SERVER['REMOTE_ADDR']; //La ip esta en la variable
Guarda la ip (que esta en la variable $_SERVER['REMOTE_ADDR'])
ImageString($img,5,65,75,"IP: $ip",$fcolor);
Escribe en la imagen, con tamaño de letra 5, desde el pixel 65 (horizontal) y el 75 (vertical), la cadena "IP: $ip",en el color $fcolor
El resto es hacer lo mismo con lo que nos interesa (lenguaje, navegador,etc...)
Y despues
Header("Content-Type: image/png"); // Avisamos que es una imagen png
Avisamos al navegador para que reconozca lo que viene ahora como una imagen png (si es jpg, habria que poner "image/png")
Y los dos ultimos pasos
ImagePNG($img); // Convertimos a png ImageDestroy($img); // Liberamos el espacio
Resultado:
Suerte y hasta otra
Gráficos de tortuga sobre imágenes en Python
Pues hoy traigo una mini-libraría que se apoya en PIL para hacer gráficos de tortuga directamente sobre imágenes [ imgturtle.py ]:
Dibujado con este script [ dragon.py ]
La idea es que se acerque lo máximo posible a la implementación oficial de los gráficos_de_tortuga_de_python con el añadido de poder guardar las imágenes ( y más velocidad me atrevería a decir ).
Al comenzar hay que crear un objeto imgturtle, que maneja la imágen, al inicializar el objeto se debe pasar un parámetro, una tupla de números que defina el tamaño en 'x' y en 'y' de la imágen o bien una cadena con el nombre del archivo del que se va a partir:
t = imgturtle( ( x, y ) ) # Nueva imágen
t = imgturtle( argv[ 1 ] ) # Imágen basada en otra
Una vez creado el objeto se puede disponer de los métodos habituales de estos gráficos:
imgturtle.clear( ): # Vuelve a la imágen original
imgturtle.reset( ): # Reinicia la tortuga
imgturtle.save( fname ): # Guarda la imágen
imgturtle.rt( angle ): # Gira a la derecha con un ángulo || imgturtle.right()
imgturtle.lt( angle ): # Gira a la izquierda con un ángulo || imgturtle.left ()
imgturtle.fd( steps ): # Avanza unos pasos || imgturtle.forward()
imgturtle.bk( steps ): # Retrocede unos pasos || imgturtle.backward( )
imgturtle.pu( ): # Levanta el lápiz
imgturtle.seth( angle ): # Establece el ángulo ||imgturtle.setheading()
imgturtle.goto( x, y ): # Se mueve hasta una posición
imgturtle.pencolor( color ): # Establece el color que se pinta
imgturtle.home( ): # Vuelve a la posición inicial
imgturtle.pd( ): # Baja el lápiz || imgturtle.pendown() imgturtle.down()
imgturtle.pu( ):# Levanta el lápiz || imgturtle.penup() imgturtle.up()
imgturtle.heading( ): # Devuelve el ángulo de la tortuga
imgturtle.pos( ):# Devuelve la posición de la tortuga || imgturtle.position()
Nota: el sistema de coordenadas no está centrado en ( 0, 0 ), sinó en x / 2, y / 2
imgturtle.isdown( ): # Si el lápiz está bajado
Y eso es todo, por último un ejemplo dibujando sobre una imágen ya existente [ rayar.py ]. Original:
Después de "$ ./rayar.py base.png out.png":
Hasta otra
Recuperar una "HOME" cifrada desde un live cd
Supongamos que hemos cifrado la carpeta de usuario (Trisquel y Ubuntu dan esa posibilidad al instalarlo), y por cosas de la vida perdemos la posibilidad de acceder al SO, pero seguimos teniendo acceso a la particion con los datos ( y la clave, se entiende ). Esto es lo que podríamos hacer desde un LiveCD para volver a montar la partición:
Nota: substituye $DRIVE por la ruta hacia la particion home + .ecryptfs, por ejemplo sería /media/blablabla/.ecryptfs/
[ 1 ] Obtener clave del sistema de cifrado, contenida en $DRIVE/<nombre de usuario>/.ecryptfs/wrapped-passphrase , y envuelta con la contraseña del usuario.
1 2 3 |
|
Entonces e25c829b60e65e63a1ec2b9581ae4d4a sería la clave con la que se cifraron los datos, pero queda otra, a partir de Ubuntu 9.04 se cifran por defecto tambié los nombres de archivo.
[ 2 ] Obtener la clave que cifra los nombres de los archivos.
1 2 3 4 |
|
La segunda, b906f5e58bfbce18, es la que cifra los nombres de los archivos.
[ 3 ] Montar el sistema de archivos.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
|
Ya está!
Y, aunque no sea necesario decirlo, para desmontar el sistema de archivos al final:
1 |
|
Hasta otra
Ojo con las @ en las url
Cuidado con ellas, que el navegador piensa que lo que va antes es el usuario [ y contraseña ] para acceder a la pagina, algo como http://google.es: blablabla@codigoparallevar.co.cc/blog.
Si entras en esa pagina acabaras en codigoparallevar.co.cc, y con un blablabla
algo extenso puede pasar por un link legítimo, curiosamente distintos
navegadores reaccionan de distinta forma:
* Firefox 6.0.2 release: muestra un popup con el texto 'Está a punto de
iniciar sesión en el sitio "codigoparallevar.co.cc" con el nombre de
usuario "google%2Ees", pero el sitio web no requiere autenticación. Es
posíble que esto sea un intento de engaño'.
* Midori 0.2.4, Chromium 12, links2 y Chrome(por piou) : no muestra
ningún aviso y en la url no muestra lo que hay antes del @.
* Lynx: Muestra un aviso 'Alert!: Address contains a username: google.es:
blablabla' mientras carga, después lo muestra ( en este caso no se
muestra la URL ).
* Opera (por helq): No muestra ningún mensaje.
*
* Elinks (por mungu): no muestra nada
*
Sabeis como reaccionan otros navegadores?
El hackmeeting de este año es en A Coruña
**** Hackmeeting@A_Corunha ****
**** 21, 22 y 23 de Octubre ****
**** ¿Qué es Hackmeeting? ****
=====================================================================
Hackmeeting es un encuentro libre y autogestionado que gira en torno
a las nuevas tecnologías, sus implicaciones sociales, la libre
circulación de saberes y técnicas, la privacidad, la creación
colectiva, el conflicto telemático... Está destinado a todo tipo de
personas que tengan una mente abierta y curiosa con ganas de
compartir sus experiencias y vivirlo participando en la coordinación
como una más. Algunas charlas y talleres exigen conocimientos
informáticos avanzados, otros no; y otros ni informáticos.
( Sacado_del_Wiki )
El hackmeeting de este año se celebra en A Coruña ( que a mano que me queda! ^^ ), ya hay propuesto_un_nodo_sobre_IPv6 y hay información varia en el Wiki.
Ahí nos vemos... a ver si saco tiempo para proponer un nodo sobre redes anónimas :)