Zero Wind – Jamie Wong Inside the mind of a Waterloo Software Engineering student

19Apr/100

AJAX Method Callbacks and Omegle Voyeur Update

I finally got back around to updating Omegle Voyeur with the ability to interfere, and decided to re-implement the whole thing in jQuery while I'm at it. Since jQuery doesn't come with a built-in method of building classes, I used lowpro for jQuery. It's a port of a class building scheme from Prototype. It doesn't do everything I could have hoped for, but it served most of my needs.

The other thing I implemented was a way of knowing when Omegle is blocking requests. They have a more robust form of detection now - it isn't just manual IP ban. Once you request too many things from them too fast, they start requesting a captcha. Locally, this isn't a problem - I simply embed an iframe with Omegle in it and provide instructions to the user. Hosted, this is a more troublesome problem, since the captcha is directed towards an IP, so it must be responded to from that IP. I have no solution to this problem at the moment, but I'm going to look into implementing the whole thing using Greasemonkey so this isn't an issue at all.

For now, you can see the latest version here: Omegle Voyeur. Don't be surprised if it's down, and please go grab your own copy: Omegle-Voyeur @ github.

Now on to the customary technical concept to go along with my own self promotion.

AJAX Method Callbacks

While passing functions as arguments is a pretty standard thing among almost all languages, attempting to pass methods of specific instances as arguments in Javascript presents an interesting problem. Consider the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function car(price) {
    this.price = price;
 
    this.setPrice = function(price) {
        this.price = price;
    };
}
 
function pass666(func) {
    func(666);
}
 
var redcar = new car(2000);
alert(redcar.price);
redcar.setPrice(123);
alert(redcar.price);
pass666(redcar.setPrice);
alert(redcar.price);

As you might expect, the first two alerts will say 2000 and 123 respectively. But the last one also says 123. Why? It all has to do with what "this" refers to. Both in the initialization of redcar and the modifier call redcar.setPrice, "this" refers to the instance of the function car given the identifier name "redcar". In the pass666 version, "this" refers to the function pass666. As a result, it does nothing to modify the properties of the car because it isn't told anything about redcar.

One way to fix this is to use a placeholder variable. I used "self". Change the definition of car to the following yields the desired result.

1
2
3
4
5
6
7
8
function car(price) {
	this.price = price;
 
	var self = this;
	this.setPrice = function(price) {
		self.price = price;
	};
}

In this example, it's difficult to see why you would ever want to use this in the first place. The reason I encountered this problem is my need to use instance methods as callback functions for AJAX calls. Here's an excerpt of the jQuery version of Omegle Voyeur to see what I'm talking about.

106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
sendQuery: function(target,respFunc) {
	// Send a query to the omegle server
	//log('sending');
	var self = this;
	if (respFunc == null) {
		respFunc = function(self,data) {}
	}
	$.ajax({
		url: 'omegle.php?'+target,
		type: 'GET',
		dataType: 'json',
		success: function(data) {
			respFunc(self,data);
		}
	});
},

Sending a request to the Omegle server is a very common task in Omegle Voyeur, so I wanted all the AJAX requests leaving from the same method. This means I have to accept the callback function as a parameter. I've written all the callback methods to accept a parameter "self" which will refer to the instance of interest.

This aspect is one of the many things that makes Prototype's class system superior to jQuery's. However, since jQuery makes a lot of other things nicer and the two libraries don't play together very well, I decided to port over to jQuery nonetheless. In Prototype, there's a function called bind (not to be confused with jQuery's bind which does something completely different,) which solves this problem elegantly.

To fix the redcar problem with the aid of Prototype without having to use a placeholder variable, you can use bind like so:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function car(price) {
    this.price = price;
 
    this.setPrice = function(price) {
        this.price = price;
    };
}
 
function pass666(func) {
    func(666);
}
 
var redcar = new car(2000);
alert(redcar.price);
redcar.setPrice(123);
alert(redcar.price);
 
pass666(redcar.setPrice.bind(redcar));
 
alert(redcar.price);

The line

18
pass666(redcar.setPrice.bind(redcar));

is what makes this work out. We're explicitly saying that we want setPrice executed from the scope of the instance.

If I ever have to hire someone for a web development job, I'll be sure to ask something about this.

14Nov/091

Omegle Voyeur – Multiple Connections

In case you haven't read the post about all my projects, here's a description of what Omegle Voyeur is:

Omegle is a website where you are connected to a stranger for a chat. It is dominated mostly by trolls whose primary purpose is to coerce you into a cyber session and then switch genders or to make you lose the game. Talking to these people is a rather tiresome endeavour, but seeing exactly what happens in these conversations is interesting. Omegle Voyeur is a way of watching a conversation which you aren't part of. What Voyeur does is form two simultaneous connections and then pass the input of one to the output of the other. This sets you up as a conversation proxy, allowing you to watch. Currently, this is exclusively a "sit and watch" program. Later I intend to add functionality to add more than 2 people into a conversation, automatically name the participants so it will be obvious that there are more than 2 people in the conversation, and allow the ability to interfere (mute participants/say things yourself) with a conversation. This concept was spawned during discussion (read: boredom) at CCC Stage 2, 2009.

In terms of technology, Omegle Voyeur is primarily one big Javascript Prototype class. Prototype is a Javascript Framework which makes the creation and maintenance of classes, conversion of data into JSON for transfer, and sending AJAX requests much, much easier.

There's also a very small bit of code in php which is able to be so short because it uses the incredible program cUrl. cUrl is a command line utility for grabbing data from websites using their URL. libcurl facilititates the use of curl in php without having to write your own wrapper.

Below is some php code I use to make curl even easier than it already is. simple_get($url) will return the HTTP GET result from the url specified. simple_post works similarly, but delivers data using the payload.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?
// Simple cUrl
// Simple get and post requests 
function simple_get($url) {
    $c = curl_init();
    curl_setopt($c, CURLOPT_URL, $url);
    curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
    $result = curl_exec($c);
    curl_close($c);
    return $result;
}
 
function simple_post($url,$payload) {
    $c = curl_init();
    curl_setopt($c, CURLOPT_URL, $url);
    curl_setopt($c, CURLOPT_POST, true);
    curl_setopt($c, CURLOPT_POSTFIELDS, $payload);
    curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
    $result = curl_exec($c);
    curl_close($c);
    return $result;
}
?>

When I started working on this project today (well, I suppose that would be last night now... wonder if I'll see the sunrise) I figured it would be a good time to get used to using git, so I made a repository using github. So far I'm enjoying git. Everything seems to act pretty much the way you'd expect to, and I already had to do a revert once I realized my logic was wrong for the way I was structuring my code.

You can see the github for Omegle Voyeur here: http://github.com/phleet/Omegle-Voyeur Feel free to design your own stuff with the all the code there - just be sure to link back here, or to the github page.

In any case, the thing the majority of the people reading this are probably interested in are the result. Things I've updated since last time are primarily aesthetic and behind the scenes, but I did add the ability to connect one person to more than one other person, and the connections don't have to be mutual. In the first 3 way conversation example, 1 can only speak to 2, 2 can only speak to 3 and 3 can only speak to 1. It leads to some rather confused people.

You can see the current running version here: Omegle Voyeur. EDIT: It seems that after being posted on reddit, omegle has (manually?) IP blocked me. The source should still work, so feel free to try it out yourself. You can go grab XAMPP to run it locally. For the time being, you can view it here: Omegle Voyeur

A quick note on how I figured out the Omegle communication protocol. The entire code governing the process is conveniently kept here: http://omegle.com/static/omegle.js?27 Unless you enjoy reading 1000s of characters on a single line, you can use the JS Beautifier to clean it up to a readable state.