Hi all,
in my last posting I said that I thought that theres a little bug in mylinks.cgi
Somehow nowbody didn't really figured out what I ment - now my exact explanation. (Eliot - hope you see that this is a bug now )
---
We have two persons and two computers
Person 1: Links Admin and Computer 1: Server
Person 2: Links visitor and Computer 2: HomePC
Now P2 visits page of P1 and thinks that there's a cool link (ID=5). He bookmarks it.
Now C1 sets a cookie on C2.
One week later P1 sees that ID=5 is broken for an unknown reason. He deletes it in Links admin so the link is not longer avaiable.
One week later P2 comes back to the site and wants to view mylinks.cgi
The cookie is stil stored on his computer with link ID=5 in it.
Now when he views mylinks.cgi he don't see the bookmark anymore (because it has been deleted by P1) but instead of this he sees a bookmark with "Unknown Tag: Title" - Instead of the real bookmarked title.
Thats a bug isn't it ?
---
Ok and heres my solution:
change mylinks.cgi to this
#############################################################################
# mylinks.cgi
#
#############################################################################
# Script written by Jerry Su, jsu7785@email.com
#
# -------------------------------------------------------------------------
#
# PROGRAM NAME: MyLinks
#
# VERSION: 1.0
#
# LAST MODIFIED: 11/29/99
#
# =========================================================================
#
# REQUIRED MODULES: CGI.pm, CGI/Carp.pm
#
# =========================================================================
#
# COPYRIGHT NOTICE:
#
#
#
# Copyright (c)1999-2000 Jerry Su. All Rights Reserved.
#
#
#
# MyLinks is redistributed AS-IS, with no guarantees or warrantees of any
#
# kind. The author of the script will not be held liable to any damage,
#
# both direct or indirect, that this script may cause you.
#
#
#
# If you have any questions or comments, please email jsu7785@email.com
#
#############################################################################
# Cookie information.
my %cookie = (
name => 'MyLinks',
expires => '+3y',
path => '/',
domain => '.eurotango.org'
);
# Deliminator (MUST BE A LETTER [no symbols or numbers]!)
my $delim = 'A';
# Links to display per page.
my $per_page = 10;
# Characters used in encoding/decoding.
my @e = qw!0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z!;
# Load required modules and libraries.
# ---------------------------------------------------
use CGI ();
use CGI::Carp qw/fatalsToBrowser/;
require "admin/links.cfg";
require "$db_lib_path/db_utils.pl";
require "$db_lib_path/links.def";
$build_use_templates ?
require "$db_lib_path/site_html_templates.pl" :
require "$db_lib_path/site_html.pl";
$|++;
# ========================================================
&main ();
sub main {
# ---------------------------------------------------
# Determine what to do.
#
my $in = new CGI;
if ($in->param('add')) { &add ($in); }
elsif ($in->param('delete')) { &delete ($in); }
elsif ($in->param('help')) { &help ($in); }
else { &display ($in); }
}
# ==============================================================
sub add {
# --------------------------------------------------------
# Adds an ID from the users cookie.
#
my $in = shift;
my $id = $in->param('add');
my $c = $in->cookie($cookie{'name'});
# Make sure we have a valid ID.
unless ($id =~ m,^\d+$,) {
print $in->header();
&site_html_myadderror ("Invalid Link ID: $id");
return;
}
my (%rec) = &get_record ($id);
if ($rec{$db_key} ne $id) {
print $in->header();
&site_html_myadderror ("Unkown Link ID: $id");
return;
}
my $e = &encode ($id);
my @c = split $delim, $c;
my %c = map { $_ => 1 } @c;
# Check to see if the ID is in the cookie.
if ($c{$e}) {
print $in->header();
&site_html_myadderror ("Already in Cookie: $id $e");
return;
}
# Make the cookie.
my $cookie = $in->cookie (
-name => $cookie{'name'},
-value => (join $delim, @c, $e),
-expires => $cookie{'expires'},
-path => $cookie{'path'},
-domain => $cookie{'domain'}
);
# Set the cookie and print the header.
print $in->header ( -cookie => $cookie );
&site_html_myadd (%rec);
}
sub delete {
# --------------------------------------------------------
# Deletes an ID from the users cookie.
#
my $in = shift;
my $id = $in->param('delete');
my $c = $in->cookie($cookie{'name'});
# If ID equals to 'all', delete all.
if ($id =~ m,^ALL$,i) {
# Make the cookie.
my $cookie = $in->cookie (
-name => $cookie{'name'},
-value => '',
-expires => '-1s',
-path => $cookie{'path'},
-domain => $cookie{'domain'}
);
# Set the cookie and print the header.
print $in->header ( -cookie => $cookie );
&site_html_mydeleteall ( { total => $#c+1 } );
return;
}
# Make sure we have a valid ID.
unless ($id =~ m,^\d+$,) {
print $in->header();
&site_html_mydeleteerror ("Invalid Link ID: $id");
return;
}
my (%rec) = &get_record ($id);
if ($rec{$db_key} ne $id) {
print $in->header();
&site_html_mydeleteerror ("Unkown Link ID: $id");
return;
}
my @c = split $delim, $c;
my %c = map { $_ => 1 } @c;
my $e = &encode ($id);
# Check to see if the id is in the cookie.
if (!$c{$e}) {
print $in->header();
&site_html_mydeleteerror ("Not in Cookie: $id");
return;
}
# Make the cookie.
my $cookie = $in->cookie (
-name => $cookie{'name'},
-value => (join $delim, grep {!/^$e$/} @c),
-expires => $cookie{'expires'},
-path => $cookie{'path'},
-domain => $cookie{'domain'}
);
# Set the cookie and print the header.
print $in->header ( -cookie => $cookie );
&site_html_mydelete (%rec);
}
sub help {
#---------------------------------------------------------
# Help Menu for people to set their Cookies.
my $in = shift;
print $in->header();
&site_html_myhelp;
return;
}
sub display {
# --------------------------------------------------------
# Creates page for links to be displayed.
#
my (%links, %cat, %rec);
foreach (@c) {
last if ($_ eq "");
%rec = &get_record ($_);
%{$links{$_}} = %rec;
push (@{$cat{$rec{Category}}}, $_);
}
CAT: foreach (sort keys %cat) {
$OUT{links} .= qq~<p>$_<br>~;
LINK: foreach (@{$cat{$_}}) {
$OUT{links} .= &site_html_mylink (%{$links{$_}});
}
}
my $in = shift;
my @c = split $delim, $in->cookie($cookie{'name'});
my $p = $in->param('page') | | 1;
my (%OUT, $start);
my $broken = "0";
$OUT{'total'} = $#c+1;
$OUT{'links'} = "";
$OUT{'span'} = "";
if ($OUT{'total'} > 0) {
$tpages = int $OUT{'total'}/$per_page + (($OUT{'total'} % $per_page) ? 1 : 0);
$p = 1 if ($p > $tpages);
my $start = ($p-1) * $per_page;
my $url = $ENV{'SCRIPT_NAME'};
# Builds the span pages.
if ($tpages > 1) {
my $prev = $p-1;
my $next = $p+1;
if ($p > 1) {
$OUT{'span'} .= qq~<a href="$url~;
$OUT{'span'} .= qq~?page=$prev~ if ($prev > 1);
$OUT{'span'} .= qq~"><b>< Previous</b></a> <a href="$url">1</a> ~;
if ($prev > 1) {
for (2 .. $prev) { $OUT{'span'} .= qq~<a href="$url?page=$_">$_</a> ~; }
}
}
else { $OUT{'span'} .= qq~< Previous ~; }
$OUT{'span'} .= qq~<b>$p</b> ~;
if ($p < $tpages) {
for ($next .. $tpages) { $OUT{'span'} .= qq~<a href="$url?page=$_">$_</a> ~; }
$OUT{'span'} .= qq~<a href="$url?page=$next"><b>Next ></b></a>~;
}
else { $OUT{'span'} .= qq~Next >~; }
}
# Builds the links.
foreach (@c[$start .. ($start + $per_page - 1)]) {
last if ($_ eq "");
my @exist = &get_record (&decode ($_));
my $ex = @exist;
if ($ex > 1) {
$OUT{'links'} .= &site_html_mylink (@exist);
}
else {
$broken++;
next;
}
}
}
$OUT{'totallinks'} = $OUT{'total'}-$broken;
# Builds the MyLinks page.
print $in->header();
&site_html_myhome ( { %OUT } );
}
sub encode {
# --------------------------------------------------------
# Encodes ID into a alphanumeric smaller value.
#
my $in = shift;
my ($out);
while ($in >= ($#e+1)) {
$out = $e[$in % ($#e+1)] . $out;
$in = int $in/($#e+1);
}
$out = $e[$in] . $out;
return $out;
}
sub decode {
# --------------------------------------------------------
# Decodes ID from an alphanumeric smaller value.
#
my $in = shift;
my ($y, $out);
my $x = 0;
my %e = map { $_ => $x++; } @e;
for ($x = 0; $x < length($in); $x++) {
$y = substr ($in, $x, 1);
$out = $out * ($#e+1) + $e{$y};
}
return $out;
}and replace the <%total%> - tag in your mylinks templates to <%totallinks%> - if you have.
Then replace this eurotango.org/links/site_html_templates.txt with your subs in site_html_templaes.pl
Then rename your templates to the templatenames in my site_html_templates.txt if they differ.
That should be all.
Here's the whole mylinks.cgi to download
eurotango.org/links/mylinks.txt
Don't forget to change the domain to yours.
---
Now what I wanna know is whether someone can make a better code out of my modification. I don't think that I have chosen the best solution to fix this bug - but it works
I thought about adding a routine here
$broken++;
next;
}which deletes the entry of the deleted Link in the cookie but I don't know how to do that right now.
Maybe there is anyone who could do some better coding...
cya all,
nikolai
[This message has been edited by DigitalFusion (edited April 02, 2000).]
in my last posting I said that I thought that theres a little bug in mylinks.cgi
Somehow nowbody didn't really figured out what I ment - now my exact explanation. (Eliot - hope you see that this is a bug now )
---
We have two persons and two computers
Person 1: Links Admin and Computer 1: Server
Person 2: Links visitor and Computer 2: HomePC
Now P2 visits page of P1 and thinks that there's a cool link (ID=5). He bookmarks it.
Now C1 sets a cookie on C2.
One week later P1 sees that ID=5 is broken for an unknown reason. He deletes it in Links admin so the link is not longer avaiable.
One week later P2 comes back to the site and wants to view mylinks.cgi
The cookie is stil stored on his computer with link ID=5 in it.
Now when he views mylinks.cgi he don't see the bookmark anymore (because it has been deleted by P1) but instead of this he sees a bookmark with "Unknown Tag: Title" - Instead of the real bookmarked title.
Thats a bug isn't it ?
---
Ok and heres my solution:
change mylinks.cgi to this
Code:
#!/usr/local/bin/perl #############################################################################
# mylinks.cgi
#
#############################################################################
# Script written by Jerry Su, jsu7785@email.com
#
# -------------------------------------------------------------------------
#
# PROGRAM NAME: MyLinks
#
# VERSION: 1.0
#
# LAST MODIFIED: 11/29/99
#
# =========================================================================
#
# REQUIRED MODULES: CGI.pm, CGI/Carp.pm
#
# =========================================================================
#
# COPYRIGHT NOTICE:
#
#
#
# Copyright (c)1999-2000 Jerry Su. All Rights Reserved.
#
#
#
# MyLinks is redistributed AS-IS, with no guarantees or warrantees of any
#
# kind. The author of the script will not be held liable to any damage,
#
# both direct or indirect, that this script may cause you.
#
#
#
# If you have any questions or comments, please email jsu7785@email.com
#
#############################################################################
# Cookie information.
my %cookie = (
name => 'MyLinks',
expires => '+3y',
path => '/',
domain => '.eurotango.org'
);
# Deliminator (MUST BE A LETTER [no symbols or numbers]!)
my $delim = 'A';
# Links to display per page.
my $per_page = 10;
# Characters used in encoding/decoding.
my @e = qw!0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z!;
# Load required modules and libraries.
# ---------------------------------------------------
use CGI ();
use CGI::Carp qw/fatalsToBrowser/;
require "admin/links.cfg";
require "$db_lib_path/db_utils.pl";
require "$db_lib_path/links.def";
$build_use_templates ?
require "$db_lib_path/site_html_templates.pl" :
require "$db_lib_path/site_html.pl";
$|++;
# ========================================================
&main ();
sub main {
# ---------------------------------------------------
# Determine what to do.
#
my $in = new CGI;
if ($in->param('add')) { &add ($in); }
elsif ($in->param('delete')) { &delete ($in); }
elsif ($in->param('help')) { &help ($in); }
else { &display ($in); }
}
# ==============================================================
sub add {
# --------------------------------------------------------
# Adds an ID from the users cookie.
#
my $in = shift;
my $id = $in->param('add');
my $c = $in->cookie($cookie{'name'});
# Make sure we have a valid ID.
unless ($id =~ m,^\d+$,) {
print $in->header();
&site_html_myadderror ("Invalid Link ID: $id");
return;
}
my (%rec) = &get_record ($id);
if ($rec{$db_key} ne $id) {
print $in->header();
&site_html_myadderror ("Unkown Link ID: $id");
return;
}
my $e = &encode ($id);
my @c = split $delim, $c;
my %c = map { $_ => 1 } @c;
# Check to see if the ID is in the cookie.
if ($c{$e}) {
print $in->header();
&site_html_myadderror ("Already in Cookie: $id $e");
return;
}
# Make the cookie.
my $cookie = $in->cookie (
-name => $cookie{'name'},
-value => (join $delim, @c, $e),
-expires => $cookie{'expires'},
-path => $cookie{'path'},
-domain => $cookie{'domain'}
);
# Set the cookie and print the header.
print $in->header ( -cookie => $cookie );
&site_html_myadd (%rec);
}
sub delete {
# --------------------------------------------------------
# Deletes an ID from the users cookie.
#
my $in = shift;
my $id = $in->param('delete');
my $c = $in->cookie($cookie{'name'});
# If ID equals to 'all', delete all.
if ($id =~ m,^ALL$,i) {
# Make the cookie.
my $cookie = $in->cookie (
-name => $cookie{'name'},
-value => '',
-expires => '-1s',
-path => $cookie{'path'},
-domain => $cookie{'domain'}
);
# Set the cookie and print the header.
print $in->header ( -cookie => $cookie );
&site_html_mydeleteall ( { total => $#c+1 } );
return;
}
# Make sure we have a valid ID.
unless ($id =~ m,^\d+$,) {
print $in->header();
&site_html_mydeleteerror ("Invalid Link ID: $id");
return;
}
my (%rec) = &get_record ($id);
if ($rec{$db_key} ne $id) {
print $in->header();
&site_html_mydeleteerror ("Unkown Link ID: $id");
return;
}
my @c = split $delim, $c;
my %c = map { $_ => 1 } @c;
my $e = &encode ($id);
# Check to see if the id is in the cookie.
if (!$c{$e}) {
print $in->header();
&site_html_mydeleteerror ("Not in Cookie: $id");
return;
}
# Make the cookie.
my $cookie = $in->cookie (
-name => $cookie{'name'},
-value => (join $delim, grep {!/^$e$/} @c),
-expires => $cookie{'expires'},
-path => $cookie{'path'},
-domain => $cookie{'domain'}
);
# Set the cookie and print the header.
print $in->header ( -cookie => $cookie );
&site_html_mydelete (%rec);
}
sub help {
#---------------------------------------------------------
# Help Menu for people to set their Cookies.
my $in = shift;
print $in->header();
&site_html_myhelp;
return;
}
sub display {
# --------------------------------------------------------
# Creates page for links to be displayed.
#
my (%links, %cat, %rec);
foreach (@c) {
last if ($_ eq "");
%rec = &get_record ($_);
%{$links{$_}} = %rec;
push (@{$cat{$rec{Category}}}, $_);
}
CAT: foreach (sort keys %cat) {
$OUT{links} .= qq~<p>$_<br>~;
LINK: foreach (@{$cat{$_}}) {
$OUT{links} .= &site_html_mylink (%{$links{$_}});
}
}
my $in = shift;
my @c = split $delim, $in->cookie($cookie{'name'});
my $p = $in->param('page') | | 1;
my (%OUT, $start);
my $broken = "0";
$OUT{'total'} = $#c+1;
$OUT{'links'} = "";
$OUT{'span'} = "";
if ($OUT{'total'} > 0) {
$tpages = int $OUT{'total'}/$per_page + (($OUT{'total'} % $per_page) ? 1 : 0);
$p = 1 if ($p > $tpages);
my $start = ($p-1) * $per_page;
my $url = $ENV{'SCRIPT_NAME'};
# Builds the span pages.
if ($tpages > 1) {
my $prev = $p-1;
my $next = $p+1;
if ($p > 1) {
$OUT{'span'} .= qq~<a href="$url~;
$OUT{'span'} .= qq~?page=$prev~ if ($prev > 1);
$OUT{'span'} .= qq~"><b>< Previous</b></a> <a href="$url">1</a> ~;
if ($prev > 1) {
for (2 .. $prev) { $OUT{'span'} .= qq~<a href="$url?page=$_">$_</a> ~; }
}
}
else { $OUT{'span'} .= qq~< Previous ~; }
$OUT{'span'} .= qq~<b>$p</b> ~;
if ($p < $tpages) {
for ($next .. $tpages) { $OUT{'span'} .= qq~<a href="$url?page=$_">$_</a> ~; }
$OUT{'span'} .= qq~<a href="$url?page=$next"><b>Next ></b></a>~;
}
else { $OUT{'span'} .= qq~Next >~; }
}
# Builds the links.
foreach (@c[$start .. ($start + $per_page - 1)]) {
last if ($_ eq "");
my @exist = &get_record (&decode ($_));
my $ex = @exist;
if ($ex > 1) {
$OUT{'links'} .= &site_html_mylink (@exist);
}
else {
$broken++;
next;
}
}
}
$OUT{'totallinks'} = $OUT{'total'}-$broken;
# Builds the MyLinks page.
print $in->header();
&site_html_myhome ( { %OUT } );
}
sub encode {
# --------------------------------------------------------
# Encodes ID into a alphanumeric smaller value.
#
my $in = shift;
my ($out);
while ($in >= ($#e+1)) {
$out = $e[$in % ($#e+1)] . $out;
$in = int $in/($#e+1);
}
$out = $e[$in] . $out;
return $out;
}
sub decode {
# --------------------------------------------------------
# Decodes ID from an alphanumeric smaller value.
#
my $in = shift;
my ($y, $out);
my $x = 0;
my %e = map { $_ => $x++; } @e;
for ($x = 0; $x < length($in); $x++) {
$y = substr ($in, $x, 1);
$out = $out * ($#e+1) + $e{$y};
}
return $out;
}
Then replace this eurotango.org/links/site_html_templates.txt with your subs in site_html_templaes.pl
Then rename your templates to the templatenames in my site_html_templates.txt if they differ.
That should be all.
Here's the whole mylinks.cgi to download
eurotango.org/links/mylinks.txt
Don't forget to change the domain to yours.
---
Now what I wanna know is whether someone can make a better code out of my modification. I don't think that I have chosen the best solution to fix this bug - but it works
I thought about adding a routine here
Code:
else { $broken++;
next;
}
Maybe there is anyone who could do some better coding...
cya all,
nikolai
[This message has been edited by DigitalFusion (edited April 02, 2000).]