|
|
@@ -0,0 +1,305 @@ |
|
|
#!/usr/bin/perl |
|
|
|
|
|
|
|
|
|
|
|
use Mysql; |
|
|
use strict; |
|
|
use vars qw($school_name); |
|
|
use vars qw($pass); |
|
|
|
|
|
require "./cgi-lib.pl"; |
|
|
#do "./school_name.pl"; |
|
|
do "../password.pl"; |
|
|
|
|
|
my (%input, $text, $field); |
|
|
&ReadParse(\%input); |
|
|
|
|
|
my @rawCookies = split (/; /,$ENV{'HTTP_COOKIE'}); |
|
|
my %cookies; |
|
|
|
|
|
foreach(@rawCookies){ |
|
|
my ($key, $val) = split (/=/,$_); |
|
|
$cookies{$key} = $val; |
|
|
} |
|
|
|
|
|
my $id = $input{id}; |
|
|
my $user = $input{user}; |
|
|
my $code = $input{code}; |
|
|
my $course = 0;#$input{course}; |
|
|
my @node; |
|
|
my @edge; |
|
|
#my $db_data = Mysql->connect("69.28.179.12", "login", "mark", $pass); |
|
|
my $db_data = Mysql->connect("$cookies{host}", "$cookies{db}", "mark", $pass); |
|
|
my $map; |
|
|
if ($ENV{'HTTP_HOST'} =~ m/^(.*)\.thefacebook\.com/) { |
|
|
$map = $1; |
|
|
} |
|
|
my $cookie_host = $cookies{host}; |
|
|
my $cookie_db = $cookies{db}; |
|
|
my $sql = "SELECT * FROM school_data where map='$map'"; |
|
|
my $retval = $db_data->query($sql); |
|
|
my %rs = $retval->fetchhash(); |
|
|
my $host = $rs{ip}; |
|
|
my $dbname = $rs{db}; |
|
|
#my $sql = "INSERT INTO viz (user,map,host,db) VALUES ('$user', '$map','$host', '$dbname')"; |
|
|
#$db_data->query($sql); |
|
|
my $db = Mysql->connect($host, $dbname, "mark", $pass); |
|
|
#my $db = Mysql->connect("69.28.179.11", "facebook", "mark", $pass); |
|
|
my $retval; my $sql; |
|
|
my %privacy; |
|
|
my $num_degrees = 1; |
|
|
my @already_expanded; |
|
|
my %cs; |
|
|
|
|
|
sub morph { |
|
|
my ($number) = @_; |
|
|
return ((((($number % 7) * 13) % 17) * 19) % 23); |
|
|
} |
|
|
|
|
|
sub share_course { |
|
|
my ($user1, $user2) = @_; |
|
|
$sql = "SELECT count(*) as count FROM course as course1, course as course2 WHERE " . |
|
|
"course1.id = '$user1' AND course2.id = '$user2' AND course1.course_id = course2.course_id"; |
|
|
$retval = $db->query($sql); |
|
|
my %rs = $retval->fetchhash(); |
|
|
return $rs{count}; |
|
|
} |
|
|
|
|
|
sub is_one_degree { |
|
|
my ($user1, $user2) = @_; |
|
|
$sql = "SELECT count(*) as count FROM friend WHERE user1 = '$user1' AND user2 = '$user2'"; |
|
|
$retval = $db->query($sql); |
|
|
my %rs = $retval->fetchhash(); |
|
|
return $rs{count}; |
|
|
} |
|
|
|
|
|
sub is_two_degrees { |
|
|
#my ($user1, $user2) = @_; |
|
|
#$sql = "SELECT count(*) as count FROM friend as f1, friend as f2 " . |
|
|
# "WHERE f1.user1 = '$user1' AND f1.user2 = f2.user1 AND f2.user2 = '$user2'"; |
|
|
#my %rs = $retval->fetchhash(); |
|
|
#return $rs{count}; |
|
|
return 0; |
|
|
} |
|
|
|
|
|
sub is_three_degrees { |
|
|
#my ($user1, $user2) = @_; |
|
|
return 0; |
|
|
} |
|
|
|
|
|
sub can_see { |
|
|
my ($user, $id, $type) = @_; |
|
|
if ($user eq $id) { return 1; } |
|
|
$sql = "SELECT house, year, " . $type . "_domain, " . $type . "_type, " . |
|
|
$type . "_allow FROM info WHERE info.id = '$id'"; |
|
|
$retval = $db->query($sql); |
|
|
my %control = $retval->fetchhash(); |
|
|
my $allow = $control{$type . '_allow'}; |
|
|
my $domain = $control{$type . '_domain'}; |
|
|
my $privacy_type = $privacy{$type}; |
|
|
if (($domain eq "" or ($privacy{email} =~ m/$domain$/)) and |
|
|
($control{$type . '_type'} =~ m/-$privacy_type/)) { |
|
|
if ($allow =~ m/-1/) { |
|
|
$cs{$id} = 1; |
|
|
return 1; |
|
|
} elsif (($allow =~ m/-2/) and $privacy{year} eq $control{year}) { |
|
|
$cs{$id} = 1; |
|
|
return 1; |
|
|
} elsif (($allow =~ m/-3/) and $privacy{house} eq $control{house}) { |
|
|
$cs{$id} = 1; |
|
|
return 1; |
|
|
} elsif (($allow =~ m/-4/) and share_course($user, $id)) { |
|
|
$cs{$id} = 1; |
|
|
return 1; |
|
|
} elsif (($allow =~ m/-5/) and is_one_degree($user, $id)) { |
|
|
$cs{$id} = 1; |
|
|
return 1; |
|
|
} elsif (($allow =~ m/-6/) and is_two_degrees($user, $id)) { |
|
|
$cs{$id} = 1; |
|
|
return 1; |
|
|
} elsif (($allow =~ m/-7/) and is_three_degrees($user, $id)) { |
|
|
$cs{$id} = 1; |
|
|
return 1; |
|
|
} |
|
|
} |
|
|
return 0; |
|
|
} |
|
|
|
|
|
sub find_node { |
|
|
my ($id, $type) = @_; |
|
|
for (my $i = 0; $i < @node; $i++) { |
|
|
if ($node[$i]{id} eq $id and $node[$i]{type} eq $type) { |
|
|
return $i; |
|
|
} |
|
|
} |
|
|
return -1; |
|
|
} |
|
|
|
|
|
sub find_connections { |
|
|
my ($this, $degree, $is_course) = @_; |
|
|
my ($type, $type_id); |
|
|
if (!$is_course) { |
|
|
$already_expanded[@already_expanded] = $this; |
|
|
$sql = "SELECT * FROM friend WHERE user1 = '$this' LIMIT 0, 200"; |
|
|
$type = "friend"; |
|
|
$type_id = 1; |
|
|
} else { |
|
|
$sql = "SELECT * FROM course WHERE course_id = '$this'"; |
|
|
$type = "course"; |
|
|
$type_id = 0; |
|
|
} |
|
|
my $return = $db->query($sql); |
|
|
while (my %row = $return->fetchhash()) { |
|
|
my $new_id; |
|
|
if (!$is_course) { |
|
|
# get the new id from the friend pair |
|
|
#if ($row{user1} eq $this) { |
|
|
# $new_id = $row{user2}; |
|
|
#} else { |
|
|
# $new_id = $row{user1}; |
|
|
#} |
|
|
$new_id = $row{user2}; |
|
|
} else { |
|
|
$new_id = $row{id}; |
|
|
} |
|
|
if ($degree > $num_degrees or $cs{$new_id} or can_see($user, $new_id, $type)) { |
|
|
# see if the id is already a node; if not, add it |
|
|
my $node_exists = 0; |
|
|
for (my $i = 0; $i < @node and !$node_exists; $i++) { |
|
|
if ($node[$i]{id} eq $new_id and $node[$i]{type} eq 1) { |
|
|
$node_exists = 1; |
|
|
} |
|
|
} |
|
|
if (!$node_exists and $degree <= $num_degrees) { |
|
|
my $next_node = @node; |
|
|
$node[$next_node]{id} = $new_id; |
|
|
$node[$next_node]{type} = 1; |
|
|
} |
|
|
# see if there's an edge between the two already; if not, add it |
|
|
if ($node_exists or $degree <= $num_degrees) { |
|
|
my $edge_exists = 0; |
|
|
my $this_index = find_node ($this, $type_id); |
|
|
my $new_index = find_node ($new_id, 1); |
|
|
for (my $i = 0; $i < @edge and !$edge_exists; $i++) { |
|
|
if (($edge[$i][0] eq $this_index and $edge[$i][1] eq $new_index) or |
|
|
($edge[$i][0] eq $new_index and $edge[$i][1] eq $this_index)) { |
|
|
$edge_exists = 1; |
|
|
} |
|
|
} |
|
|
if (!$edge_exists) { |
|
|
my $next_edge = @edge; |
|
|
$edge[$next_edge][0] = $this_index; |
|
|
$edge[$next_edge][1] = $new_index; |
|
|
} |
|
|
} |
|
|
# if we want to consider friends farther out, do so now |
|
|
if ($degree < $num_degrees + 1) { |
|
|
my $expansion_exists = 0; |
|
|
for (my $i = 0; $i < @already_expanded and !$expansion_exists; $i++) { |
|
|
if ($already_expanded[$i] eq $new_id) { |
|
|
$expansion_exists = 1; |
|
|
} |
|
|
} |
|
|
if (!$expansion_exists) { |
|
|
if (!$is_course or can_see ($user, $new_id, "friend")) { |
|
|
find_connections ($new_id, $degree + 1, 0); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
sub identify_nodes { |
|
|
for (my $i = 0; $i < @node; $i++) { |
|
|
if ($node[$i]{type}) { |
|
|
$sql = "SELECT name FROM info WHERE id = '" . $node[$i]{id} . "'"; |
|
|
} else { |
|
|
$sql = "SELECT name FROM course_list WHERE id = '" . $node[$i]{id} . "'"; |
|
|
} |
|
|
$retval = $db->query($sql); |
|
|
my %row = $retval->fetchhash(); |
|
|
$node[$i]{name} = $row{name}; |
|
|
} |
|
|
} |
|
|
|
|
|
if ($code == &morph($user) and &can_see($user, $id, "friend")) { |
|
|
# figure out what's going into the graph |
|
|
$sql = "SELECT email, house, year FROM info WHERE info.id = '$user'"; |
|
|
$retval = $db->query($sql); |
|
|
%privacy = $retval->fetchhash(); |
|
|
$node[0]{id} = $id; |
|
|
if ($course) { |
|
|
$node[0]{type} = 0; |
|
|
} else { |
|
|
$node[0]{type} = 1; |
|
|
} |
|
|
find_connections ($id, 1, $course); |
|
|
identify_nodes (); |
|
|
# generate the graph file |
|
|
my $o; |
|
|
my $outfile = "/tmp/thefacebook-$id-graph-" . time(); |
|
|
open $o, "> $outfile"; |
|
|
# headers |
|
|
print $o "graph g {\n"; |
|
|
print $o "start=\"yes\"\n"; |
|
|
print $o "size=\"20,20\"\n"; |
|
|
print $o "page=\"20,20\"\n"; |
|
|
print $o "maxiter=1000\n"; |
|
|
print $o "resolution=100\n"; |
|
|
print $o "center=true\n"; |
|
|
print $o "bgcolor=white\n"; |
|
|
print $o "title=\"A Graph\"\n"; |
|
|
# nodes |
|
|
print $o "node [shape=box,fontname=\"Tahoma\",style=filled]\n"; |
|
|
for (my $i = 0; $i < @node; $i++) { |
|
|
my $name = $node[$i]{name}; |
|
|
$name =~ s/[^A-Z0-9'. ]//gi; |
|
|
my ($red, $green, $blue); |
|
|
do { |
|
|
$red = int(rand() * 201); |
|
|
$green = int(rand() * 201); |
|
|
$blue = int(rand() * 56) + 200; |
|
|
} while ($red + $green + $blue < 400); |
|
|
my $extra = ""; |
|
|
if ($i eq 0) { |
|
|
$extra = ",fontsize=32,label=\"$name\""; |
|
|
} else { |
|
|
$extra = ",fontsize=24,label=\"$name\""; |
|
|
} |
|
|
printf $o "n$i [color=\"#%02x%02x%02x\"$extra]\n", $red, $green, $blue; |
|
|
} |
|
|
# edges |
|
|
print $o "edge [len=8,color=\"#555555\"]\n"; |
|
|
for (my $i = 0; $i < @edge; $i++) { |
|
|
my $name1 = $node[$edge[$i][0]]{name}; |
|
|
my $name2 = $node[$edge[$i][1]]{name}; |
|
|
print $o "n$edge[$i][0] -- n$edge[$i][1] [dir=both,weight=1]\n"; |
|
|
#print $o "$name1 -- $name2 [dir=both,weight=1]\n"; |
|
|
} |
|
|
# footer |
|
|
print $o "}\n\n"; |
|
|
# compile the graph and output |
|
|
my $cmd = "nice neato -Tsvgz $outfile|"; |
|
|
print "Content-Encoding: gzip\n"; |
|
|
print "Content-Type: image/svg+xml\n\n"; |
|
|
#print "Content-Type: text/html\n\n"; |
|
|
my $file; |
|
|
my $pid = open ($file, $cmd); |
|
|
while (my $line = <$file>) { |
|
|
print $line; |
|
|
} |
|
|
close $o; |
|
|
unlink $outfile; |
|
|
#print "what is up..\n"; |
|
|
} else { |
|
|
print &PrintHeader; |
|
|
print "Authentication failed. Return <a href='http://"; |
|
|
print $school_name; |
|
|
print ".thefacebook.com/home.php'>home</a>.\n"; |
|
|
} |
|
|
|
|
|
#print "end...\n"; |
|
|
|
|
|
|
|
|
|