# Now generate things to be inserted.
-$def{'PROXY_ARCH_PATH'} = "use constant PROXY_ARCH_PATH => '".$set{'proxy_data_path'}."archive/';";
-$def{'ARCH_PATH'} = "use constant ARCH_PATH => '".$set{'data_path'}."group/';";
-$def{'GROUPSETTINGS_PATH'}= "use constant GROUPSETTINGS_PATH => '".$set{'data_path'}."groupsettings/';";
-$def{'KEY_BITS'} = "use constant KEY_BITS => ".$set{'key_bits'}.";";
-$def{'MAX_REDIRECTIONS'} = "use constant MAX_REDIRECTIONS => ".$set{'max_redirections'}.";";
-
-
-$def{'PROXY_LIB'} = "use lib '".$set{'proxy_lib_path'}."';";
+$def{'PROXY_ARCH_PATH'} = "use constant PROXY_ARCH_PATH => '".$set{'proxy_data_path'}."archive/';";
+$def{'ARCH_PATH'} = "use constant ARCH_PATH => '".$set{'data_path'}."group/';";
+$def{'GROUPSETTINGS_PATH'} = "use constant GROUPSETTINGS_PATH => '".$set{'data_path'}."groupsettings/';";
+$def{'KEY_BITS'} = "use constant KEY_BITS => ".$set{'key_bits'}.";";
+$def{'MAX_REDIRECTIONS'} = "use constant MAX_REDIRECTIONS => ".$set{'max_redirections'}.";";
+$def{'IF_CSS_PATH'} = "use constant IF_CSS_PATH => '".$set{'interface_path'}."/if.css';";
+$def{'INTERFACE_PATH'} = "use constant INTERFACE_PATH => '".$set{'interface_path'}."/view';";
+$def{'LOGIN_PATH'} = "use constant LOGIN_PATH => '".$set{'interface_path'}."/view/login';";
+$def{'LIST_PATH'} = "use constant LIST_PATH => '".$set{'interface_path'}."/view/list';";
+$def{'GROUP_PATH'} = "use constant GROUP_PATH => '".$set{'interface_path'}."/view/group';";
+$def{'PASS_PATH'} = "use constant PASS_PATH => '".$set{'data_path'}."pass/';";
+$def{'ACCESS_PATH'} = "use constant ACCESS_PATH => '".$set{'data_path'}."access/';";
+$def{'TIMEOUT_UNLOCK'} = "use constant TIMEOUT_UNLOCK => ".$set{'timeout_unlock'}.";";
+$def{'TIMEOUT_INACT'} = "use constant TIMEOUT_INACT => ".$set{'timeout_inact'}.";";
+
+
+$def{'PROXY_LIB'} = "use lib '".$set{'proxy_lib_path'}."';";
+$def{'FACEBUG_LIB'} = "use lib '".$set{'lib_path'}."';";
$def{'PATH'} = "\$ENV{'PATH'} = '".$set{'path'}."';";
$def{'PERL'} = "#!".$set{'perl'};
-$def{'BOT_CRONTAB'} = $set{'bot_crontab'}.' '.$set{'bin_path'}.'bot'.(($set{'bot_args'} ne '')?(' '.$set{'bot_args'}):'');
+$def{'INTERFACE_PL'} = '#define INTERFACE_PL "'.$set{'bin_path'}.'interface.pl"';
+$def{'INTERFACE_PL_ERRLOG'} = '#define INTERFACE_PL_ERRLOG "'.$set{'log_path'}.'interface-stderr.log"';
+
+$def{'BOT_CRONTAB'} = $set{'bot_crontab'}.' '.$set{'bin_path'}.'bot'.(($set{'bot_args'} ne '')?(' '.$set{'bot_args'}):'').' >'.$set{'log_path'}.'bot.log';
$def{'CC'} = 'CC='.$set{'gcc'};
$def{'CF'} = 'CF='.$set{'c_flags'};
$def{'PL'} = 'PL='.$set{'perl'};
$def{'MV'} = 'MV='.$set{'mv'};
-$def{'CP'} = 'CM='.$set{'cp'};
+$def{'CP'} = 'CP='.$set{'cp'};
$def{'RM'} = 'RM='.$set{'rm'};
$def{'OD'} = 'OD='.$set{'bin_path'};
+$def{'WD'} = 'WD='.$set{'www_path'};
+$def{'LD'} = 'LD='.$set{'lib_path'};
$def{'CM'} = 'CM='.$set{'chmod'};
--- /dev/null
+/* Currently, it's identical to botm.css, the default style of\r
+ 1190.bicyclesonthemoon.info. May be changed in the future. */\r
+\r
+html\r
+{\r
+ background-color: #ffffff;\r
+ border-color: #000000;\r
+ color: #000000;\r
+}\r
+a\r
+{\r
+ border-color: #0057af;\r
+ color: #0057af;\r
+ text-decoration:underline;\r
+}\r
+a:visited\r
+{\r
+ border-color: #bb6622;\r
+ color: #bb6622;\r
+}\r
+a:hover\r
+{\r
+ border-color: #bb6622;\r
+ color: #bb6622;\r
+}\r
+a:hover:visited\r
+{\r
+ border-color: #0057af;\r
+ color: #0057af;\r
+}\r
+::selection\r
+{\r
+ color: #ffffff;\r
+ background-color: #bb6622;\r
+}\r
+.br\r
+{\r
+ border-color: #bb6622!important;\r
+ color: #bb6622!important;\r
+}\r
+.ni\r
+{\r
+ border-color: #0057af!important;\r
+ color: #0057af!important;\r
+}\r
+.bi\r
+{\r
+ border-color: #ffffff!important;\r
+ color: #ffffff!important;\r
+}\r
+\r
+form.hl {\r
+ display: inline;\r
+}\r
+\r
+table.pl\r
+{\r
+ border-color: #0057af;\r
+ border-width: 4px 16px 16px 16px;\r
+ border-style: solid;\r
+ border-spacing: 0px;\r
+}\r
+div.pl\r
+{\r
+ border-color: #0057af;\r
+ border-width: 4px 16px 16px 16px;\r
+ border-style: solid;\r
+ /* border-spacing: 0px; */\r
+}\r
+div.in\r
+{\r
+ display: inline-block;\r
+}\r
+div.le\r
+{\r
+ float: left;\r
+}\r
+div.pr\r
+{\r
+ float: right;\r
+}\r
+.tp\r
+{\r
+ text-align: right;\r
+}\r
+div.pls\r
+{\r
+ text-align: center;\r
+ font-weight: bold;\r
+ color: #ffffff;\r
+ background-color: #0057af;\r
+ width: 100%;\r
+}\r
+div.plt\r
+{\r
+ color: #ffffff;\r
+ background-color: #0057af;\r
+ width: 100%;\r
+ clear: both;\r
+}\r
+div.plw\r
+{\r
+ background-color: #ffffff;\r
+ color: #000000;\r
+ padding: 4px;\r
+ clear: both;\r
+}\r
+tr.plw\r
+{\r
+ background-color: #ffffff;\r
+ color: #000000;\r
+}\r
+tr.plv\r
+{\r
+ background-color: #D9ECFF;\r
+ color: #000000;\r
+}\r
+tr.plt\r
+{\r
+ color: #ffffff;\r
+ background-color: #0057af;\r
+}\r
+tr.pls\r
+{\r
+ text-align: center;\r
+ font-weight: bold;\r
+ color: #ffffff;\r
+ background-color: #0057af;\r
+}\r
+td.plk\r
+{\r
+ padding: 4px 8px;\r
+}\r
+input.hl {\r
+ background:none!important;\r
+ border:none!important; \r
+ padding:0!important;\r
+/* font-family:inherit;\r
+ font-size:inherit; */\r
+ font: inherit;\r
+ text-decoration:underline;\r
+ border-color: #0057af;\r
+ color: #0057af;\r
+}\r
+input.hl:hover {\r
+ border-color: #bb6622;\r
+ color: #bb6622;\r
+}\r
+input.pt\r
+{\r
+ border-color: #0057af;\r
+ color: #000000;\r
+ background-color: #ffffff;\r
+ border-width: 2px;\r
+ border-style: solid;\r
+ margin: 2px;\r
+}\r
+input.pt:focus\r
+{\r
+ border-color: #bb6622;\r
+}\r
+select.pk\r
+{\r
+ border-color: #0057af;\r
+ color: #000000;\r
+ background-color: #ffffff;\r
+ border-width: 2px;\r
+ border-style: solid;\r
+ margin: 2px;\r
+}\r
+select.pk:focus\r
+{\r
+ border-color: #bb6622;\r
+}\r
+input.pk\r
+{\r
+ border-color: #0057af;\r
+ color: #000000;\r
+ background-color: #ffffff;\r
+ border-width: 2px;\r
+ border-style: solid;\r
+ margin: 2px;\r
+}\r
+input.pk:focus\r
+{\r
+ border-color: #bb6622;\r
+}\r
+textarea.pt\r
+{\r
+ border-color: #0057af;\r
+ color: #000000;\r
+ background-color: #ffffff;\r
+ border-width: 0px;\r
+ border-style: solid;\r
+ width: 100%;\r
+ resize: none;\r
+}\r
+blockquote.pq\r
+{\r
+ color: #000000;\r
+ background-color: #ffffff;\r
+ text-decoration: inherit;\r
+ font: inherit;\r
+ border-color: #bb6622;\r
+ border-width: 4px;\r
+ border-style: solid;\r
+ padding: 2px;\r
+}\r
+cite.pq\r
+{\r
+ text-decoration: inherit;\r
+ font: inherit;\r
+ /* font-weight: bold; */\r
+}\r
+dl.pq\r
+{\r
+ color: #000000;\r
+ background-color: #ffffff;\r
+ border-color: #0057af;\r
+ border-width: 4px;\r
+ border-style: solid;\r
+ padding: 2px;\r
+}\r
+dt.pq\r
+{\r
+ color: #0057af;\r
+ font-weight: bold;\r
+}\r
+code.pq\r
+{\r
+ max-height: 200px;\r
+ overflow: auto;\r
+ white-space: normal;\r
+ display: block;\r
+}
\ No newline at end of file
--- /dev/null
+###PERL;
+
+# interface.pl is generated from interface.1.pl
+
+#interface list/thread/post/postreply ???
+
+use strict;
+#use warnings;
+###PROXY_LIB;
+###FACEBUG_LIB;
+use proxy_lib qw(entityencode getcgi urldecode readconfigfile);
+use facebug_lib qw(key);
+
+###IF_CSS_PATH;
+###LOGIN_PATH;
+###PASS_PATH;
+###ACCESS_PATH;
+###INTERFACE_PATH;
+###LIST_PATH;
+###GROUP_PATH;
+###KEY_BITS;
+###TIMEOUT_UNLOCK;
+###TIMEOUT_INACT;
+###GROUPSETTINGS_PATH;
+
+my %http;
+my %cgi;
+
+my $mode;
+my $method;
+my $IP;
+my $id;
+my $skey;
+
+my $time = time();
+srand ($time-$$);
+
+delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
+###PATH;
+
+
+if ($ENV{'REQUEST_METHOD'} =~ /^(HEAD|GET|POST)$/) {
+ $method=$1;
+}
+else{
+ exit failpage("Status: 405 Method Not Allowed\nAllow: GET, POST, HEAD\n","405 Method Not Allowed","The interface does not support the $ENV{'REQUEST_METHOD'} method.");
+}
+
+%http = gethttpheader (\%ENV);
+%cgi = getcgi($ENV{'QUERY_STRING'});
+
+if ($method eq 'POST') {
+ if ($http{'content-type'} eq 'application/x-www-form-urlencoded') {
+ my %cgipost=getcgi( <STDIN> );
+ foreach my $ind (keys %cgipost) {
+ $cgi{$ind}=$cgipost{$ind};
+ }
+ }
+ else{
+ exit failpage("Status: 415 Unsupported Media Type\n","415 Unsupported Media Type","Unsupported Content-type: $http{'content-type'}.");
+ }
+}
+
+if ($ENV{'PATH_INFO'} =~ /^\/(list|group|thread|post|image|login|logout)(\/((.+)\/?)?)?$/) {
+ $mode = $1;
+ $id = $4;
+}
+elsif ($ENV{'PATH_INFO'} =~ /^\/?$/) {
+ $mode = 'list';
+ $id = '';
+}
+else{
+ exit failpage("Status: 404 Not Found\n","404 Not Found\n","Path \"$ENV{'PATH_INFO'}\" is not part of the interface.");
+}
+
+if($cgi{'id'} ne '') {
+ $id = $cgi{'id'};
+}
+
+
+if(defined($http{'expect'})) {
+ exit failpage("Status: 406 Not Acceptable\n","406 Not Acceptable","\"Expect\" header field not supported.");
+}
+
+if ($ENV{'REMOTE_ADDR'} =~ /^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)$/) {
+ $IP=$1;
+}
+else{
+ exit failpage("Status: 500 Internal Server Error\n","500 Internal Server Error","Can't get your IP.");
+}
+
+if ($mode !~ /^(login|logout)$/) {
+ unless ($skey=access($time,$IP,$cgi{'skey'})) {
+ exit loginpage ("You must log in to access this $mode.","Status: 403 Forbidden\n");
+ }
+ if($id =~ /^([0-9\/]*)$/) {
+ $id = $1;
+ }
+ elsif ($mode !~ /^(list)$/) {
+ exit failpage("Status: 404 Not Found\n","404 Not Found\n"," \"$id\" is not a valid $mode ID.");
+ }
+}
+
+
+if($mode eq 'login') {
+ exit login();
+}
+elsif ($mode eq 'list') {
+ exit list();
+}
+
+exit loginpage ("$mode --- $id");
+
+
+sub list {
+ my $dir;
+ my $groupfile;
+ my %group;
+ my $even;
+ my $groupid;
+
+ if ($method eq 'HEAD') {
+ print "Status: 200 Ok\n\n";
+ return;
+ }
+
+ opendir ($dir, GROUPSETTINGS_PATH) or return failpage("Status: 500 Internal Server Error\n","500 Internal Server Error","Can't access group list.");
+
+ print "Content-type: text/html\n\n";
+ print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "">'."\n";
+ print '<html lang="en"><head>'."\n";
+ print '<title>List of facebook groups</title>'."\n";
+ print '<meta http-equiv="Content-type" content="text/html; charset=UTF-8">'."\n";
+ print '<link rel="stylesheet" href="'.IF_CSS_PATH.'">'."\n";
+ print '</head><body>'."\n";
+ print '<h1>List of facebook groups</h1>'."\n";
+ print '<table class="pl"><tr class="pls"><td colspan="2">Available groups</td></tr>'."\n";
+ print '<tr class="plt"><td class="plk">name</td><td class="plk">action</td></tr>'."\n";
+
+ $even=0;
+
+ ###PAGE???
+ while (defined ($groupid = readdir $dir)) {
+ if ($groupid =~ /^([0-9]+)$/) {
+ %group = readconfigfile(GROUPSETTINGS_PATH.$1);
+ }
+ else {
+ next;
+ }
+ if ($group{'id'} =~ /^([0-9]+)$/) {
+ $groupid=$1;
+ }
+ else {
+ next;
+ }
+ $even = !$even;
+ print '<tr class="'.($even?'plw':'plv').'"><td class="plk">'.entityencode($group{'name'}).'</td><td class="plk"><form method="post" action="'.GROUP_PATH.'/'.$groupid.'" class="hl"><input type="hidden" name="skey" value="'.$skey.'"><input type="submit" value="show chronological" class="pk"></form> <form method="post" action="'.GROUP_PATH.'/'.$groupid.'" class="hl"><input type="hidden" name="skey" value="'.$skey.'"><input type="hidden" name="rev" value="1"><input type="submit" value="show antichronological" class="pk"></form></td></tr>'."\n";
+ }
+
+ print '</table></body></html>'."\n";
+ closedir ($dir);
+}
+
+sub access {
+ (my $time, my $ip, my $key) = @_;
+ my $timeout_unlock = TIMEOUT_UNLOCK*60;
+ my $timeout_inact = TIMEOUT_INACT*60;
+ my $accesspath='';
+ my $accessfile;
+ my $lasttime;
+ my $unlocktime;
+ my $lastip;
+ my $username;
+
+ if($key =~ /^([0-9A-Fa-f]+)$/){
+ $key=$1;
+ }
+ else{
+ return 0;
+ }
+ if ($ip =~ /^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)$/) {
+ $ip = $1;
+ }
+ else {
+ return 0;
+ }
+ if ($time =~ /^([0-9]+)$/) {
+ $time=int($1);
+ }
+ else{
+ return 0;
+ }
+
+ $accesspath=ACCESS_PATH.$key;
+
+ if (! (-e $accesspath)) {
+ return 0;
+ }
+
+ elsif (open ($accessfile,"+<",$accesspath)) {
+ unless (flock ($accessfile, 2)) {
+ close ($accessfile);
+ return 0;
+ }
+ $unlocktime=<$accessfile>;
+ $lasttime=<$accessfile>;
+ $lastip=<$accessfile>;
+ $username=<$accessfile>;
+
+ $unlocktime =~ s/[\r\n]//g;
+ $lasttime =~ s/[\r\n]//g;
+ $lastip =~ s/[\r\n]//g;
+ $username =~ s/[\r\n]//g;
+
+ if ($unlocktime =~ /^([0-9]+)$/) {
+ $unlocktime=int($1);
+ }
+ else {
+ close ($accessfile);
+ return 0;
+ }
+ if ($lasttime =~ /^([0-9]+)$/) {
+ $lasttime=int($1);
+ }
+ else {
+ close ($accessfile);
+ return 0;
+ }
+ if ($lastip =~ /^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)$/) {
+ $ip = $1;
+ }
+ else {
+ close ($accessfile);
+ return 0;
+ }
+
+ if ((abs($time-$unlocktime)>$timeout_unlock) or (abs($time-$lasttime)>$timeout_inact) or ($ip ne $lastip)){
+ close ($accessfile);
+ unlink $accesspath;
+ return 0;
+ }
+ else {
+ if (seek($accessfile, 0, 0)) {
+ print $accessfile "$unlocktime\n$time\n$ip\n$username\n";
+ truncate ($accessfile , tell($accessfile));
+ }
+ close ($accessfile);
+ return $key;
+ }
+ }
+ else {
+ return 0;
+ }
+}
+
+sub login {
+ my $passpath;
+ my $passfile;
+ my $accesspath;
+ my $accessfile;
+ my $pass;
+ my $key;
+ my $username;
+
+ if($cgi{'username'} eq '') {
+ return loginpage ("Username missing.","Status: 403 Forbidden\n");
+ }
+ if($cgi{'password'} eq '') {
+ return loginpage ("Password missing.","Status: 403 Forbidden\n");
+ }
+ if ($cgi{'username'} =~ /^([A-Za-z0-9_]+)$/){
+ $username = $1;
+ }
+ else {
+ return loginpage('Wrong username or password.',"Status: 403 Forbidden\n");
+ }
+
+ $passpath = PASS_PATH.$username;
+ open($passfile, "<", $passpath) or return loginpage('Wrong username or password.',"Status: 403 Forbidden\n");
+ $pass = <$passfile>;
+ close($passfile);
+ $pass =~ s/[\r\n]//g;
+ $pass = urldecode($pass);
+
+ if ($pass ne $cgi{'password'}){
+ return loginpage('Wrong username or password.',"Status: 403 Forbidden\n");
+ }
+
+ $key=key(KEY_BITS);
+ $accesspath=ACCESS_PATH.$key;
+
+ open ($accessfile,">",$accesspath) or return loginpage("Couldn't create temporary file $accesspath.","Status: 500 Internal Server Error\n");
+ print $accessfile "$time\n$time\n$IP\n$username\n";
+ close ($accessfile);
+
+ if($method eq 'HEAD') {
+ print "Status: 200 Ok\n";
+ return;
+ }
+ print "Content-type: text/html\n\n";
+ print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "">'."\n";
+ print '<html lang="en"><head>'."\n";
+ print '<title>Login successful</title>'."\n";
+ print '<meta http-equiv="Content-type" content="text/html; charset=UTF-8">'."\n";
+ print '<link rel="stylesheet" href="'.IF_CSS_PATH.'">'."\n";
+ print '</head><body>'."\n";
+ print '<h1>Login successful</h1>'."\n";
+ print '<p><b class="ni">You have successfully logged in.</b></p>'."\n";
+ print '<form method="post" action="'.LIST_PATH.'">'."\n";
+ print '<input type="submit" value="show the list" class="pk"><br>'."\n";
+ print '<input type="hidden" name="skey" value="'.entityencode($key).'">'."\n";
+ print '</form></body></html>'."\n";
+}
+
+
+sub gethttpheader {
+ (my $env) = @_;
+
+ my %http;
+
+ foreach my $ind (keys %$env) {
+ my $name = '';
+ my $value= '';
+
+ if ($ind =~ /^HTTP_([A-Z0-9_]+)$/) {
+ $name=$1;
+ }
+ elsif ($ind =~ /^(CONTENT_[A-Z0-9_]+)$/) {
+ $name=$1;
+ }
+ else{
+ next;
+ }
+ $name =~ s/_/-/g;
+ $name = lc($name);
+ if ($$env{$ind} =~ /^([\x20-\x7e]*)$/) {
+ $value=$1;
+ }
+ else {
+ next;
+ }
+ $http{$name}=$value;
+ }
+ return %http;
+}
+
+
+# Function for showing the login form page.
+# arguments: 1 - additional message (optional), 2 - additional header fields
+# (optional)
+sub loginpage {
+ (my $message, my $header)=@_;
+ if($header ne ''){
+ print $header;
+ }
+ if($method eq 'HEAD') {
+ print "\n";
+ return;
+ }
+ print "Content-type: text/html\n\n";
+ print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "">'."\n";
+ print '<html lang="en"><head>'."\n";
+ print '<title>Log in to the facebook interface</title>'."\n";
+ print '<meta http-equiv="Content-type" content="text/html; charset=UTF-8">'."\n";
+ print '<link rel="stylesheet" href="'.IF_CSS_PATH.'">'."\n";
+ print '</head><body>'."\n";
+ print '<h1>Log in to the facebook interface</h1>'."\n";
+ if($message ne ''){
+ print '<p><b class="br">'.entityencode($message).'</b></p>'."\n";
+ }
+ print '<form method="post" action="'.LOGIN_PATH.'"><table>'."\n";
+ print '<tr><td><b>Username: <b></td><td><input type="text" name="username" class="pt"></td></tr>'."\n";
+ print '<tr><td><b>Password: <b></td><td><input type="password" name="password" class="pt"></td></tr>'."\n";
+ print '</table><input type="submit" value="log in" class="pk">'."\n";
+ print '</form></body></html>'."\n";
+}
+
+sub failpage {
+ (my $header, my $title, my $message)=@_;
+ if($header ne ''){
+ print $header;
+ }
+ if($method eq 'HEAD') {
+ print "\n";
+ return;
+ }
+ print "Content-type: text/html\n\n";
+ print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "">'."\n";
+ print '<html lang="en"><head>'."\n";
+ if($title ne ''){
+ print '<title>'.entityencode($title).'</title>'."\n";
+ }
+ print '<meta http-equiv="Content-type" content="text/html; charset=UTF-8">'."\n";
+ print '<link rel="stylesheet" href="'.IF_CSS_PATH.'">'."\n";
+ print '</head><body>'."\n";
+ if($title ne ''){
+ print "<h1>$title</h1>"."\n";
+ }
+ if($message ne ''){
+ print '<p><b class="br">'.entityencode($message).'</b></p>'."\n";
+ }
+ print '<form class="hl" method="post" action="'.INTERFACE_PATH.'">';
+ if($cgi{'skey'} =~ /^([A-Fa-f0-9]+)$/){
+ print '<input type="hidden" name="skey" value="'.$1.'">';
+ }
+ print '<input type="submit" value="back to the interface" class="pk"></form>'."\n";
+ print '</body></html>'."\n";
+}