#!/usr/bin/perl -Tw # # Author : C Matthew Curtin # Created On : <1997/11/23 14:41:40> # Last Modified By: $Author: cmcurtin $ # Last Modified On: $Date: 2003/07/23 15:31:53 $ # Version : $Revision: 1.2 $ # Status : Fully functional, per spec. See BUGS. # # =pod =head1 NAME link-exchange.cgi -- A CGI program to manage a WWW link exchange. =head1 DESCRIPTION B provide a link exchange service, whereby everyone part of a "link exchange" or "web ring" can put a link on their page to the URL where this program is running. This program will then return an HTTP redirect to another page on the webring. The URL to this program can be any of the following: =over 4 =item http://your-server/path-to-program/link-exchange.cgi?next This will send the client to the next URL on the list, in the order of the I<$urldb> file. If the current URL is last on the list, the client will be sent to the first. =item http://your-server/path-to-program/link-exchange.cgi?prev This will send the client to the previous URL on the list, in the order of the I<$urldb> file. If the current URL is the first, the client will be directed to the last. =item http://your-server/path-to-program/link-exchange.cgi?rand This will send the client to a random URL from the I<$urldb> file. It will not send the client back to the current URL. =item http://your-server/path-to-program/link-exchange.cgi Not specifying a query string at all will make the program behave the same as if it were called with "?next". =back =head1 FILES There are two files of direct interest to B. =over 4 =item I<$urldb> This is a database of URLs in the link exchange. This is simply a newline-delimited flat file. It should be trivial to maintain this file. By default, it is called F, though you may specify any file you like by editing the source. The file will look something like this: http://first/url/ http://second.url/ http://third.url/~etc/ =item I<$urllog> This is a logfile kept by B that reports each time the program is called, the URL that links to it, the URL to which it sends the requesting client, and the ID of the client (browser type). It is in the following format: [timestamp] remote_host referer "client identification" By default its name is F but that can be changed by editing the source. =back =head1 BUGS The "random URL" could be a little more intelligent by trying to keep track of which clients have been sent to various sites. This could allow B to ensure that a client sees all of the sites in a link exchange before handing out repeats. Perhaps that feature will exist in a future version. This could probably be rewritten to be more pretty, using functions, having a nice little main block to control things, and all that. But then, maybe that would have been overkill for such a little program. Maybe not. =head1 AUTHOR Copyright © 1997 Matt Curtin Do whatever you want with this program, except one thing: you may not repackage it and call it your own. My original authorship and copyright notice must remain intact with any version or derivative work. Is that asking too much? If you do hack it to do something more useful, please throw me mail at cmcurtin@interhack.net. Thanks! =cut # our environment... require 5.003; use strict; use CGI; use CGI::Carp; # some variables we need... my $cgi = CGI->new(); my $urldb = "link-exchange.urls"; my $urllog = "link-exchange.log"; my @urls; my $rec_no; my $now = scalar localtime; my $remote_host = $cgi->remote_host; my $query_string; my $foo; if ($cgi->query_string) { ($foo, $query_string) = split(/=/, $cgi->query_string()); } else { $query_string = ""; } my $referer; if ($cgi->referer) { $referer = $cgi->referer(); } else { $referer = ""; } my $user_agent; if ($cgi->user_agent) { $user_agent=$cgi->user_agent; } else { $user_agent = ""; } my $returnurl; my $place; # slurp in the URL database, and figure out where the person who # linked to us is in that list open(URLDB, "< $urldb") || croak "Cap'n, she can't open $urldb!: $!\n"; while() { $rec_no++; chomp; if(grep(/^$referer$/, $_) || $referer eq "") { $place = $rec_no; } push(@urls, $_); } close URLDB; # write the log open(LOG, ">> $urllog") || croak "Could not open log $urllog: $!\n"; print LOG "[" . $now . "] $remote_host $query_string $referer \"$user_agent\"\n"; close LOG; if (lc($query_string) eq "next") { if ($place == scalar @urls) { $place = 0; } $returnurl = $urls[$place++]; } elsif (lc($query_string) eq "prev") { if ($place == 0) { $place = scalar @urls; } $returnurl = $urls[$place - 2]; } else { # not `next' or `prev', so assume `rand' srand(time ^ $$); my $number = int(rand(scalar @urls - 1)); $number++ if ($number == $place - 1); # don't hit the same site again $returnurl = $urls[$number]; } # and then reply... print <