#!/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 home.\n"; } #print "end...\n";