Archive

Archive for the ‘programacion’ Category

twitter-node https fix

November 1st, 2011 No comments
nodejs twitter-node

nodejs twitter-node

twitter streaming api

twitter streaming api

Como muchos sabran, hace un tiempo el steaming api de twitter solo funciona con https.

Para nodejs existe el modulo twitter-node, que permitia consumir este streaming, pero dejo de funcionar por el tema del https.

Aca adjunto el index.js de ese modulo (el codigo js que lo hace funcionar) fixeado para que trabajo con https.

Como fix extra, también deje habilitado el debug (propiedad que existía pero no hacia nada).

 

//Fixed by Cesar Casas (lortmorris@gmail.com)
var https         = require('https'),
    query        = require('querystring'),
    Parser       = require('./parser'),
    EventEmitter = require('events').EventEmitter,
    Buffer       = require('buffer').Buffer;

// process.mixin is gone, a function for replacement
function extend(a, b) {
  Object.keys(b).forEach(function (key) {
    a[key] = b[key];
  });
  return a;
}

// Creates a streaming connection with twitter, and pushes any incoming
// statuses to a tweet event.
//
// options - optional Object that specifies custom configuration values.
//
// Valid option keys:
//
// port      - Integer of proxy port
// host      - String or ip address of the proxy server.  Defaults to 'stream.twitter.com'.
// path      - String of the base path for the request.
// action    - String part of the URL that specifies what to query for.
// track     - Array of keywords to filter.  See track()
// following - Array of userIDs to filter.  See follow()
// locations - Array of lat/long tuples.  See location()
// params    - Extra HTTP params Object to send with the request.
// user      - String Twitter login name or email.
// password  - String Twitter password.
//
// Returns TwitterNode instance.
var TwitterNode = exports.TwitterNode = function(options) {
  EventEmitter.call(this);
  if(!options) options = {};
  var self           = this;
  this.port          = options.port      || 80;
  this.host          = options.host      || 'stream.twitter.com';
  this.path          = options.path      || '/1/statuses/';
  this.action        = options.action    || 'filter';
  this.trackKeywords = options.track     || [];
  this.following     = options.follow    || [];
  this.locations     = options.locations || [];
  this.params        = options.params    || {};
  this.user          = options.user;
  this.password      = options.password;
  this.headers       = { "User-Agent": 'Twitter-Node' };
  this.debug         = options.debug || false;
  this.parser        = new Parser();
  this.parser.addListener('object', processJSONObject(this));
  this.parser.addListener('error', function (error) {
    self.emit('error', new Error('TwitterNode parser error: ' + error.message));
  });
  if (options.headers) {
    extend(this.headers, options.headers);
  }
}

TwitterNode.prototype = Object.create(EventEmitter.prototype);

// Track the following keyword.  If called multiple times, all words are sent
// as a comma-separated parameter to Twitter.
//
// See: http://apiwiki.twitter.com/Streaming-API-Documentation#track
//
// word - String word to track.
//
// Returns nothing.
TwitterNode.prototype.track = function track(word) {
  this.trackKeywords.push(word);
  return this;
};

// Follow the given twitter user (specified by their userID, not screen name)
// If called multiple times, all userIDs are sent as a comma-separated
// parameter to Twitter.
//
// See: http://apiwiki.twitter.com/Streaming-API-Documentation#follow
//
// userID - Integer userID to track.
//
// Returns nothing.
TwitterNode.prototype.follow = function follow(userId) {
  this.following.push(userId);
  return this;
};

// Match tweets in the given bounding box.
//
// See: http://apiwiki.twitter.com/Streaming-API-Documentation#locations
//
// Example: location(-122.75, 36.8, -121.75, 37.8) // SF
//
// lng1, lat1 - southwest corner of the bounding box.
// lng2, lat2 - northeast corner.
//
// Returns nothing.
TwitterNode.prototype.location = function location(lng1, lat1, lng2, lat2) {
  this.locations.push(lng1, lat1, lng2, lat2)
  return this;
};

TwitterNode.prototype.stream = function stream() {
  if (this._clientResponse && this._clientResponse.connection) {
    this._clientResponse.socket.end();
  }

  if (this.action === 'filter' && this.buildParams() === '') return;

	var headers = extend({}, this.headers),
      twit    = this,
      request;

  headers['Host'] = this.host;

  if (this.user) {
    headers['Authorization'] = basicAuth(this.user, this.password);
  }

var options = {
  host: this.host,
  port: this.port,
  path: this.requestUrl(),
  method: 'GET',
  headers : headers
};

if(this.debug) console.log(options);

var req = https.request(options, function(res) {

if(this.debug)  console.log("statusCode: ", res.statusCode);
if(this.debug)  console.log("headers: ", res.headers);

  res.on('data', function(d) {
    twit._receive(d);
    if(this.debug) process.stdout.write(d);
  });

  res.on('response', function(d) {
	    twit._clientResponse = d;
	    if(this.debug) process.stdout.write(d);
	  });

  res.on('end', function() {
      twit.emit('end', this);
      twit.emit('close', this);
    });

});

req.end();

req.on('error', function(e) {
  console.error(e);
});

  return this;
};

// UTILITY METHODS

// Passes the received data to the streaming JSON parser.
//
// chunk - String data received from the HTTP stream.
//
// Returns nothing.
TwitterNode.prototype._receive = function(chunk) {
  this.parser.receive(chunk);
  return this;
};

// Builds the URL for the streaming request.
//
// Returns a String absolute URL.
TwitterNode.prototype.requestUrl = function() {
  var url =  this.path + this.action + ".json" + this.buildParams();
	console.log('make url: ', url);

	return url;
};

// Builds the GET params for the streaming request.
//
// Returns URI encoded string: "?track=LOST"
TwitterNode.prototype.buildParams = function() {
  var options = {};
  extend(options, this.params);
  if (this.trackKeywords.length > 0) options.track = this.trackKeywords.join(",");
  if (this.following.length > 0)     options.follow = this.following.join(",");
  if (this.locations.length > 0)     options.locations = this.locations.join(",");
  if (options.track || options.follow || options.locations) {
    return "?" + query.stringify(options);
  }
  return "";
};

// Base64 encodes the given username and password.
//
// user - String Twitter screen name or email.
// pass - String password.
//
// Returns a Basic Auth header fit for HTTP.
var basicAuth = function basicAuth(user, pass) {
  return "Basic " + new Buffer(user + ":" + pass).toString('base64');
};

// Creates a callback for the object Event of the JSON Parser.
//
// twit - an instance of this TwitterNode.
//
// Returns a function to be passed to the addListener call on the parser.
var processJSONObject = function processJSONObject(twit) {
  return function(tweet) {
    if (tweet.limit) {
      twit.emit('limit', tweet.limit);
    } else if (tweet['delete']) {
      twit.emit('delete', tweet['delete']);
    } else {
      twit.emit('tweet', tweet);
    }
  };
};

Utilidades para el manejo del flujo asincrónico en NodeJS

nodejs

nodejs

Los que programan en NodeJS seguramente habrán notado lo dificil que es seguir el flujo del programa cuando tenemos varias llamadas a funciones que realizan operaciones asincronicas.
Los casos mas comunes que se suelen dar son donde tenemos que realizar 2 o mas operaciones asincrónicas en serie o en paralelo y debemos determinar cuando se han finalizado de procesar.
Para ello hay varias librerías que nos ayudan a escribir código mas legible y ahorrarnos un poco de indentación, pero la verdad es que, en mi opinión, la mayoría son demasiado complejas y tienen demasiados “features” para resolver problemas sencillos.
Basandome en algunas de estas librerías y algunos conceptos que leí por ahí, desarrollé unas utilidades simples.

1) forEachAsync: Permite realizar una operación asincrónica en cada iteración y continuar a la siguiente al finalizarla.

 

Array.prototype.forEachAsync = function(iterator, then) {
	var self = this;
	var loop = function(i) {
		if (i < self.length) {
			iterator(self[i], function() {
				loop(i+1);
			});
		}
		else {
			then();
		}
	};
	loop(0);
};

Ejemplo:

[1,2,3,4,5].forEachAsync(function(item, next) {
	console.log('item ' + item);
	setTimeout(function() {
		next(); // avanzamos al siguiente item, alias ‘continue’
	}, 500);
}, function() {
	console.log('end');
});

2) forEachAsyncParallel: Parecido a la versión anterior pero permite n cantidad de operaciones simultaneas.

Array.prototype.forEachAsyncParallel = function(iterator, max, then) {
	var self = this;
	var count = 0, index = 0;
	var loop = function() {
		if (index == self.length && count == 0) then();
		else if (index < self.length) {
			count++;
			iterator(self[index++], function() {
				count--;
				loop();
			});
		}
	};
	if (self.length == 0) then();
	for (var i = 0, len = Math.min(max, self.length); i < len && index < self.length; i++) loop();
};

Ejemplo:

[1,2,3,4,5].forEachAsyncParallel(function(item, next) {
	console.log('item ' + item);
	setTimeout(function() {
		next();
	}, 500);
}, 2, function() {
	console.log('end');
});

3) Futuros / continuaciones
Podemos aplicar el concepto de “currying” y hacer una función que nos ayude a encapsular una operación asincrónica para recuperar el resultado mas adelante.
Este concepto consiste en derivar una funcion de n parámetros en una que solo acepte un parámetro. Si aplicamos esto al callback podemos hacer lo siguiente:

function searchApi(url, callback) {
	// async op...
}
function readFile(path, callback) {
	// async op...
}

// creamos funciones especializadas
function curriedSearchApi(url) {
	return future(searchApi, arguments, 1);
}
function curriedReadFile(path) {
	return future(readFile, arguments, 1);
}

// iniciamos las operaciones...
var apiSearch = curriedSearchApi('http://google.com?q=lalala');
var fileReader = curriedReadFile('/etc/passwd');

// mas adelante...
apiSearch(function(err, result) {
	fileReader(function(err, result) {
		// terminaron ambas operaciones, hacemos algo con ambos resultados
	});
});

Y aquí está la implementación de “future”:

function future(fn, args, i) {
	var done, err, result;
	var cb = function(e, r) {
		done = true;
		err = e,
		result = r;
	};
	args = Array.prototype.slice.call(args);
	args[i || 1] = function(e, r) {
		cb(e, r);
	};
	fn.apply(this, args);
	return function(_) {
		if (done) _(err, result);
		else cb = _;
	};
}

Como se ve, lo que hacemos es llamar a la funcion fn con los argumentos recibidos. i indica el índice que ocupa el callback en el objeto arguments.
Creamos nuestro propio callback que va a almacenar el resultado y retornamos una función cuyo único parámetro es un callback.
Si al momento de llamar esta función ya teníamos el resultado, simplemente lo devolvemos, caso contrario se reemplaza el callback por el nuevo.

Hay varias formas de resolver los casos anteriores, algunas tan sencillas como usar contadores y otras algo rebuscadas pero que en definitiva ayudan a mantener legible el código.
Pueden ver la lista de módulos que ayudan a resolver este tipo de problemas aquí: https://github.com/joyent/node/wiki/modules#async-flow

Espero les haya gustado, hasta la próxima! :D

Consejos de timezone by Demian Rodriguez

June 2nd, 2011 2 comments

time zone, el gran problema de la programacion. Consejos y trucos

Timezone, consejos y trucos para php, mysql y nodejs

Demian Rodriguez nos da unos consejos para minimizar estos problemas.

1) Establecer como timezone default “UTC” tanto en el server como en la base de datos.
Ej en Debian:

#dpkg-reconfigure tzdata
#restart mysql

2) Para el caso de MySQL, las columnas de tipo DATE, DATETIME o TIME no almacenan info sobre el timezone, uno es responsable de saber en que formato esta la fecha para despues mostrarla correctamente al usuario. Para esto es recomendable guardar todas las fechas en UTC.

3) Al mostrar una fecha al usuario se debe convertir al timezone adecuado. Como?

PHP:

// mostrar
$fechaDeMysql = "2011-06-01 08:30:20";
$date = new DateTime($fechaDeMysql, new DateTimeZone("UTC"));
$date->setTimeZone(date_default_timezone_get());
$date->format(...);

// guardar
$fechaQueVieneDeNoseDonde = 'Mon, 15 Aug 2005 15:52:01 +0300'; // ya tiene timezone
$date = new DateTime($fechaQueVieneDeNoseDonde);
$date->setTimeZone(new DateTimeZone("UTC"));
// guardarla en mysql...

NodeJS:
Si aca no mostramos nada al usuario es re facil, no hay que hacer nada :)
El proceso usa el tz del SO. Pero tambien lo podemos forzar seteando la variable de entorno al principio del script:

process.env.TZ = 'UTC';

Como obtener una fecha de la db y mostrarla al usuario en el TZ correcto? No se, es una incógnita como sabe JS en que TZ está la fecha que saque de la db. Lo pregunté aca: https://github.com/felixge/node-mysql/pull/55

// guardar
/**
 * metodo re copado para formatear fechas :)
 * return formatted date as yyyy-mm-dd H:i:s using UTC
 */
Date.prototype.formatUTC = function() {
	function pad(n) {
		return n < 10 ? '0' + n : n
	}
	var d = this;
	return d.getUTCFullYear()+'-'
	  + pad(d.getUTCMonth()+1)+'-'
	  + pad(d.getUTCDate())+' '
	  + pad(d.getUTCHours())+':'
	  + pad(d.getUTCMinutes())+':'
	  + pad(d.getUTCSeconds());
};

var fechaParaInsertar = new Date('Mon, 15 Aug 2005 15:52:01 +0300').formatUTC();

Qbasic en javascript

May 13th, 2011 1 comment
qbasic javascript codigo en basic

qbasic javascript codigo en basic

Sin dudas algunas JavaScript es el lenguaje mas flexible del cual disponemos hoy en dia.

Su capacidad de estar presente tanto del lado del Cliente (mas que nada por frameworks como mootools, jquery, etc) y actualmente del lado del servidor (enter ellos el incomparable NodeJS) lo convierte en una opcion de potencial practicamente infinito, y hoy presentaremos algo que demuestra lo que decimos.

Navegando en internet en busqueda de nuevas tendencias o novedades de JavaScript me he topado con algo que realmente me parecio brillante, y es nada mas y nada menos que un interprete (con editor y todo) de QBasic.

Para los que no sepan (mas que nada los jovenes) QBasic era un lenguaje de progamacion bastante usado para aprender a hacer los primeros sistemitas, usado para juegos y poco para tareas administrativas, QBasic fue sin duda en la primer pasion de los que hoy son denominados “Sr. en programacion o Ninjas”.

Bien, entendamos que necesitamos (en forma muy grosera obvio) para tener un lenguaje de programacion (mas que nada si tiene editor).

Primero que nada, el editor en si, es decir, una “gui” o “pantalla” donde podamos escribir nuestro codigo, que nos advierta de alguna mala sintaxis, o que nos sugiera correciones.

Por otro lado, necesitamos un “compilador” que no presisamente pase nuestro codigo fuente a codigo maquina, puede simplemente hacer un paso intermedio, como por ejemplo generar bytecode, es decir, un grupo de instrucciones que seran interpretados por una maquina virtual.

Si hablamos de una maquina virtual, necesitamos “algo” que interprete los bytecodes y en base a los mismos “haga algo”.

Bueno, lo que hoy les traigo son todos esos pasos, desde el editor hasta la maquina virtual, 100% escrito en JavaScript.

El unico requisito para que todo esto funcione correctamente es contar con un navegador que soporte Canvas… y obviamente se recomienda chrome o firefox.

qbasic javascript bytecode editor

qbasic javascript bytecode editor

Para verlo funcionando hacer click aca

qbasic javascript demo game

qbasic javascript demo game

Aca les dejo los archivos JS para que vean de que se trata por separado.

CodeGenerator

console

GlrParser

qbasic

RuleParser

RuleSet

Tokenizer

TypeChecker

types

virtualmachine

 

Tambien para que todo funcione, necesitan una imagen de mapa de caracteres y les paso el ejemplo (archivo.bas).

test.bas

charmap qbasic javascript

charmap qbasic javascript

Introduccion y conceptos basicos de la programacion

April 19th, 2011 No comments
introduccion a la programacion

introduccion a la programacion

Cuando hablamos de programacion y somos programadores, rara vez entendemos a que llamamos “conceptos basicos”.

Como filosofia de vida me baso en reducir todo problema a su minima expresion, lo que tambien me llevo a intentar entender cada uno de los elementos que componen mi dia a dia, y al ser un programador, mi dia a dia es programar.

Desde hace mucho tiempo me dedico al estudio de los conceptos mas simples hasta lo mas complejos, me gusta entender como cada vez que precionamos una tecla en un chat, esa “letra” tecleada llega a otro monitor.

Podemos pensar que “viajo” por la internet y llego a otra computadora. En un estudio un poquito mas profundo podemos decir que al precionar la tecla el microprocesador del teclado interpreto el codigo binario de la misma, envio la informacion al mother, la misma lo capturo, fue interpretado, el SO tomo el evento, lo envio al spooler de eventos, algun programa lo capturo, lo proceso, y decidio que debia ser parte de un datagrama que fue enviado por el protocolo tcp/ip, udp o el que quieran y el mismo salio por la internet.
Obvio que podemos ir mas adentro del asunto, podemos empezar a ver que es un datagrama, como el SO se comunica con la placa de red, que son los protocolos, que son las capa de comunicacion de red, y todo lo que pasa para que algo que arranco como un impulso electronico, se convirtio en un proceso de software, volvio a ser un impulso electronico enviado desde nuestra placa de red, pasando por el modem, llegando a algun router del ISP, el mismo lo tomo, lo envio a otro lado, viajo por todo el mundo hasta finalmente llegar al destinatario, donde el proceso de decodificar un impulso electronico y convertirlo en una letrita en la pantalla arranco nuevamente.

Si, es una verdadera molestia pensar en estudiar todo eso, pero la realidad es que mientras mas aprendemos sobre esos detalles es cuando mas entendemos lo que hacemos dia a dia.
Este articulo no intenta ser una queja camuflada, ni explicar la diferencia entre “programar” y “ser programador”, pero si es una llamada de atencion para todos aquellos colegas que pasan la vida programando solo que los que le da de comer y no se ponen a ver mas alla (en pocas palabras solo ven el arbol y no el fucking bosque).

Como escribir todos los distintos procesos seria una demanda de tiempo del cual no dispongo, les propongo adjuntar libros y documentos que revelaran la informacion necesaria para que cada uno luego pueda seguir profundizando en los distintos procesos internos (en como los impulsos son convertidos en algo mas virtual).

 

introduccion a la informatica

introduccion a la informatica

El primer texto nos explica las bases de la informatica desde un punto de vista mas hardcode, donde veremos un poco de historia (mas que nada que las computadoras conceptualmente existen desde hace mas de 200 anios), y pasaremos hasta un punto evolutivo donde nacio finalmente la magia… la programacion.

Tambien al final existen unos ejercicios, que serian muy interesantes ver los resultados enviados por alguno de los miembros de esta lista.

Aca les dejo el indice del texto.

 

 

 

Contenido

1. Introduccion y conceptos basicos
1.0.1. Definicion de Informatica
1.0.2. Evolucion historica
1.1. Ambito de aplicacion
1.2. Tipos de computadores
1.3. La m ́quina de von Neumann
1.4. El funcionamiento del computador digital
1.4.1. Sistemas de numeracion
1.4.2. Medida de vol ́menes de informacion binaria
1.4.3. Sistemas de codificacion de la informacion
1.4.4. Programas e instrucciones
1.4.5. El funcionamiento de un programa
1.5. El software basico de un sistema
1.5.1. Niveles de abstracci on
1.5.2. El Sistema Operativo
1.5.3. Tipos de programas
1.6. Apendice: Representacion de numeros
1.7. Apendice: Historia del transistor
1.8. Ejercicios
1.9. Referencias de consulta

 

Descargar: Elementos De Programacion Introduccion y Conceptos Basicos

Sintetizador con html5 via PCM

April 7th, 2011 No comments

Nunca dejamos de descubrir nuevas cosas que podemos hacer con JavaScript, HTML5, css3, etc.

En esta oportunidad les presento riffwave, una libreria en JavaScript que genera usando el tag audio de html5 sonidos por medio de PCM (MIC en Castellano).

Aca va el ejemplo de como se usa la libreria.

 

var data = []; // just an array
for (var i=0; i<10000; i++) data[i] = Math.round(255 * Math.random()); // fill data with random samples
var wave = new RIFFWAVE(data); // create the wave file
var audio = new Audio(wave.dataURI); // create the HTML5 audio element
audio.play(); // some noise

aca les dejo la web de la libreria http://www.codebase.es/riffwave/ riffwave

Aca dejo el codigo de la libreria para los que quieran copiar y pega directamente.

/*
 * RIFFWAVE.js v0.02 - Audio encoder for HTML5 

Arkanoid en javascript con jquery

April 7th, 2011 No comments

Aca les presentamos una seria de proyectos personales (experimentos) del site http://hakim.se/experiments

La verdad es que el que mas me gusto fue el Arkanoid escrito con jquery, muy simpatico y original.

 

arkanoid en jquery

arkanoid en jquery

Otro que esta realmente copado es el siguiente: http://hakim.se/experiments/html5/core/01/#

Es un lindo juego, muy adictivo!.

Mas ejemplos de lindos juegos en javascript con modelos matematicos interesantes: http://sinuousgame.com/

 

NodeJS, documentacion en español

March 14th, 2011 2 comments

Muchos programadores no son muy adeptos al ingles, es por eso que buscan en forma desesperada informacion en español.

En el caso de NodeJS tenemos algunos recursos.

El primero es en si este Blog, donde vamos a ir agregando documentacion, codigos de ejemplos, etc.

Como otras alternativas tenemos nodejs.es : http://www.nodejs.es

Recomiendo seguir al usuario: @nodejs_es ya que ahi podremos estar mas “al dia” con las publicaciones del blog de nodejs.es.

En si nodejs.es es un blog, con articulos sobre lo que va saliendo de la tecnologia node, pero tambien tenemos toda la documentacion oficial traducida, los ejemplos, etc.

NodeJs documentacion en espanol

NodeJs documentacion en espanol

ThreadsTabs for Mootools 1.2 o Mootools 1.3

January 27th, 2011 No comments

Por una necesidad de un cliente, escribi esta clase simple y rapida, que permite saber cuantos tabs estan instanciados con el mismo site.

Tambien podemos saber si los cierra por accion de usuario o por timeout.

Estare subiendo las actualizaciones.

/**
Threads v1.0

Manejo de mensajes entre distintos tabs del navegador para un mismo Site.

@Autor Cesar Casas
@Version 1.0
@WebSite http://cesarcasas.com.ar

**/

var Threads={};

/** Conf Class settings **/

Threads.keyThread=12312123; //la key unica de cada tab, con new Date() y el metodo que nos guste la podemos armar
Threads.keyGroupThread="__ThreadGroupKEY"; //el nombre de la cookie con el que manejamos todo

/** Source
 *
 *
 */

Threads.CookieOptions={
		domain:window.location.hostname
		,duration: 0

	};

Threads.cookieSetFunction = function(c_name,value,expiredays){

	Cookie.write(c_name, value, Threads.CookieOptions);
	return ;

}

Threads.cookieReadFunction = function(name) {

	var myCookie = Cookie.read(name);
	if(myCookie == null) return "";
	return myCookie;

}

Threads.getAllThreads=function(){
	var actual=Threads.cookieReadFunction(Threads.keyGroupThread);

	var empty={};
	if(actual=="" || actual==undefined || actual=="undefined") {

		return empty;
	}
	else {

		return JSON.decode(actual);
	}
}

Threads.removeOldInstances=function(instanceID){
	Threads.Notify();
	var instanceID = instanceID || '';
	var allThreads=Threads.getAllThreads();
	var CurrentTime=new Date().getTime();

 	//Threads.cookieSetFunction(Threads.keyGroupThread, "{}");

	 for (var key in allThreads) {

		var diff=(CurrentTime-allThreads[key].time);

		if(diff > 5000 || allThreads[key].id==instanceID){
			Threads.callThreadClose(allThreads[key]);
			delete(allThreads[key]);

		}
	};
	Threads.cookieSetFunction(Threads.keyGroupThread, JSON.encode(allThreads));

};

Threads.count=function(){
	var all=Threads.getAllThreads();

	var x=0;
	for (var key in all) {
		x++;
	};
	return x;
}

Threads.existInstance=function(data){
	var allThreads=Threads.getAllThreads();

	var exist=false;
	 for (var key in allThreads) {
		if(allThreads[key].id==Threads.keyThread) {
			exist=true;

		}
	};

	if(!exist) Threads.callThreadOpen(data);
};

Threads.Notify=function(instanceID){
	var instanceID = instanceID || Threads.keyThread
	var data={
			'id': instanceID
			,'time':new Date().getTime()

	};

	Threads.existInstance(data);
	var allThreads=Threads.getAllThreads();

	var str="allThreads._"+(Threads.keyThread)+" = data";

	eval(str);

	Threads.cookieSetFunction(Threads.keyGroupThread, JSON.encode(allThreads));

}

Threads.pingThreadRequest=function(){
	Threads.removeOldInstances();
}

Threads.callThreadClose=function(thread){
	Threads.isThreadClose(thread);
}

Threads.callThreadOpen=function(thread){
	Threads.isThreadOpen(thread);
}

/**
override functions body for callbacks 

*/

Threads.isThreadClose=function(){};
Threads.isThreadOpen=function(){};

window.addEvent("domready", function(){
		Threads.pingThreadRequest.periodical(1000);

		Threads.isThreadClose=function(th){
			//console.log("se cerro un tabs por timeout", th);
		};

		Threads.isThreadOpen=function(th){
			//console.log("se abrio un tab nuevo", th);
		};

});

descompilar (swf) flash con ubuntu

December 29th, 2010 No comments

Esto es facil, no es descompilar en forma literal, sino obtener una salida con todas las funciones y operaciones de un swf.

Para los users de debian o ubuntu, solo basta con

sudo apt-get install flasm

Una vez instalado, hacemos

flasm -d archivo.swf > salida.dat

Nos genera un archivo con la info del swf, sus operaciones, funciones, etc.

Ejemplo de salida

movie 'index2.swf' compressed // flash 9, total frames: 1, frame rate: 24 fps, 930x700 px

  // unknown tag 88 length 135

  defineMovieClip 4 // total frames: 1
  end // of defineMovieClip 4

  defineMovieClip 5 // total frames: 1
  end // of defineMovieClip 5

  exportAssets
    5 as 'subbt'
  end // of exportAssets

  frame 0
    constants 'overlay', '_width', 'Stage', 'width', '_height', 'height', 'onEntersFrame', 'onResize', 'com', 'global', 'app', 'addEventListener', 'target', 'type', 'di
spatchEvent', 'main', '_xscale', '_yscale', 'bg', 'section', 'sendEvent', '_x', 'time', 'y', 'loadedID', 'mosesSupposes', 'fuse', 'Fuse', 'start', 'GETDATA', 'Settings'
, 'mainplace', 'CMSConnector', 'onLoad', 'settings', 'init', 'call', 'align', 'TL', 'scaleMode', 'noScale', 'FuseFMP', 'PennerEasing', 'ZigoEngine', 'register', 'this',
 'mx', 'events', 'EventDispatcher', 'initialize', '_alpha', 'onPress', 'useHandCursor', 'addListener', 'getPath', 'admin/files/', '?', 'Math', 'random', 'loadSettings' 

    function onResize ()
      push 'overlay'
      getVariable
      push '_width', 'Stage'
      getVariable
      push 'width'