From 2bfb3046cc83bffcebedfe2356ecb40bd70a51e8 Mon Sep 17 00:00:00 2001 From: Banana Date: Wed, 15 Jun 2011 16:48:40 +0200 Subject: [PATCH] dropped pgsql support since the popularity is too low. --- insipid-config.cgi.example | 42 +- lib/Insipid/DBInstall.pm | 12 +- lib/Insipid/Database.pm | 6 +- lib/Insipid/JSON.pm | 844 ++++++++++++++++---------------- lib/Insipid/Main.pm | 17 +- lib/Insipid/Schemas.pm | 401 ++++++--------- lib/Insipid/Snapshots.pm | 970 ++++++++++++++++++------------------- lib/Insipid/Tags.pm | 6 +- 8 files changed, 1076 insertions(+), 1222 deletions(-) diff --git a/insipid-config.cgi.example b/insipid-config.cgi.example index 8227a7d..6d7d020 100755 --- a/insipid-config.cgi.example +++ b/insipid-config.cgi.example @@ -1,22 +1,20 @@ -# This is the database configuration for Insipid. The "dbtype" parameter -# can be either "mysql" for the MySQL database or "Pg" for PostgreSQL. -dbname = insipid_luke -dbuser = luke -dbpass = dbpass -dbtype = mysql - -# If you'd like the Insipid database tables to use a prefix, uncomment -# this line. -#dbprefix = insipid_ - -# The base URI to your installation. -pagepath = /Luke - -# If your webserver is not running on port 80 and it doesn't properly set -# the SERVER_PORT variable, set it here. -#server_port = 8080 - -# The login name and password for using the Insipid interface. -username = luke -userpass = yourpassword - +# This is the database configuration for Insipid. +dbname = insipid_luke +dbuser = luke +dbpass = dbpass + +# If you'd like the Insipid database tables to use a prefix, uncomment +# this line. +#dbprefix = insipid_ + +# The base URI to your installation. +pagepath = /Luke + +# If your webserver is not running on port 80 and it doesn't properly set +# the SERVER_PORT variable, set it here. +#server_port = 8080 + +# The login name and password for using the Insipid interface. +username = luke +userpass = yourpassword + diff --git a/lib/Insipid/DBInstall.pm b/lib/Insipid/DBInstall.pm index f1b075a..e5da07f 100755 --- a/lib/Insipid/DBInstall.pm +++ b/lib/Insipid/DBInstall.pm @@ -43,11 +43,7 @@ sub install { $dbpass = getconfig('dbpass'); $dbhost = getconfig('dbhost'); - if(defined(getconfig('dbtype'))) { - $dbtype = getconfig('dbtype'); - } else { - $dbtype = 'mysql'; - } + $dbtype = 'mysql'; $dsn = "DBI:$dbtype:dbname=$dbname;host=$dbhost"; $dbh = DBI->connect($dsn, $dbuser, $dbpass, { 'RaiseError' => 0}) or die $DBI::errstr; @@ -57,11 +53,7 @@ sub install { print "

Creating tables..."; - if($dbtype eq 'mysql') { - @creates = split(/\;/, $createMySQL); - } else { - @creates = split(/\;/, $createPostgres); - } + @creates = split(/\;/, $createMySQL); foreach(@creates) { my $sql = $_; diff --git a/lib/Insipid/Database.pm b/lib/Insipid/Database.pm index f6463f3..10938e1 100755 --- a/lib/Insipid/Database.pm +++ b/lib/Insipid/Database.pm @@ -45,11 +45,7 @@ $dbuser = getconfig('dbuser'); $dbpass = getconfig('dbpass'); $dbhost = getconfig('dbhost'); -if(defined(getconfig('dbtype'))) { - $dbtype = getconfig('dbtype'); -} else { - $dbtype = 'mysql'; -} +$dbtype = 'mysql'; $dsn = "DBI:$dbtype:dbname=$dbname;host=$dbhost"; $dbh = DBI->connect($dsn, $dbuser, $dbpass, { 'RaiseError' => 0}) or die $DBI::errstr; diff --git a/lib/Insipid/JSON.pm b/lib/Insipid/JSON.pm index eb7460a..e9c5ca9 100755 --- a/lib/Insipid/JSON.pm +++ b/lib/Insipid/JSON.pm @@ -1,427 +1,417 @@ -#!/usr/bin/perl -# -# Copyright (C) 2008 Luke Reeves -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -# USA -# - -package Insipid::JSON; - -use strict; -use warnings; - -use vars qw(@ISA @EXPORT @EXPORT_OK); -use CGI qw/:standard/; -use CGI::Carp qw(fatalsToBrowser); -use Insipid::Config; -use Insipid::Database; -use Insipid::Sessions; -use Date::Format; -use Date::Parse; - -require Exporter; - -@ISA = qw(Exporter); - -@EXPORT = qw( -send_json_tags -send_json_posts -); - -my $query = ''; -my $last_page = 0; - - - -sub send_json_tags { - my ($sql, $sth); - - # Building up JSON structure before parsing the data: - my ($json_prefix,$json_suffix); - # limiting url_param('callback') to a reasonable length (100): - if((defined(url_param('callback'))) && (length(url_param('callback')) < 100)){ - $json_prefix = ''.url_param('callback').'({'; - $json_suffix = '})'; - } elsif(url_param('raw') eq 1) { - $json_prefix = '{'; - $json_suffix = '}'; - } else { - $json_prefix = 'if(typeof(Insipid) == \'undefined\') Insipid = {}; Insipid.tags = {'; - $json_suffix = '}'; - } - #limiting tags count, only if url_param('count') is a valid integer: - my $limit ; - if (url_param('count') =~ /^[+-]?\d+$/) { - $limit = ' limit '.url_param('count') ; - } - - - - # If the user has already chosen a tag, get the intersection list - if((url_param('tag')) && (logged_in() eq 1)) { - $sql = "select $tbl_tags.name,count(*) from $tbl_bookmarks - inner join $tbl_bookmark_tags as bt1 on - ($tbl_bookmarks.id = bt1.bookmark_id) - inner join $tbl_tags on - ($tbl_tags.id = bt1.tag_id) - inner join $tbl_bookmark_tags as bt2 on - ($tbl_bookmarks.id = bt2.bookmark_id) - inner join $tbl_tags as t2 on - (t2.id = bt2.tag_id and t2.name = ?) - where ($tbl_tags.name != ?) - group by $tbl_tags.name $limit"; - $sth = $dbh->prepare($sql); - $sth->execute(url_param('tag'), url_param('tag')); - print $json_prefix ; - if($sth->rows ne 0) { - my $icount = 1 ; - while(my @r = $sth->fetchrow_array()) { - json_show_tag($icount, $sth->rows, $r[0], $r[1]); - $icount++ ; - } - } - print $json_suffix ; - return ; - } else { - - # Access_spec contains a where clause to count only public bookmarks - # if the user is not logged in - my $access_where = ""; - if(logged_in() eq 0) { - $access_where = " where ($tbl_bookmarks.access_level = 1) "; - } - - my $order_clause; - if($dbtype eq "Pg") { - $order_clause = "order by upper($tbl_tags.name)"; - } else { - $order_clause = "order by $tbl_tags.name"; - } - - $sql = "select $tbl_tags.name, count(*) - from $tbl_bookmarks - inner join $tbl_bookmark_tags on - ($tbl_bookmarks.id = $tbl_bookmark_tags.bookmark_id) - inner join $tbl_tags on - ($tbl_tags.id = $tbl_bookmark_tags.tag_id) - $access_where - group by $tbl_tags.name - $order_clause - $limit"; - - $sth = $dbh->prepare($sql); - $sth->execute; - print $json_prefix; - if($sth->rows ne 0) { - my $icount = 1; - while(my @r = $sth->fetchrow_array()) { - json_show_tag($icount, $sth->rows, $r[0], $r[1]); - $icount++; - } - } - print $json_suffix; - return; - } -} - -sub json_show_tag { - my($icount, $rowscount, $tag, $tagcount) = (@_); - $tag =~ s/\"/\\"/g ; - my $json_txt = ''; - $json_txt = $json_txt.'"'.$tag.'":'.$tagcount; - if ($icount ne $rowscount){ - $json_txt = $json_txt.','; - } - print $json_txt ; -} - -sub send_json_posts { - - # Building up JSON structure before parsing the data: - my ($json_prefix,$json_suffix); - # limiting url_param('callback') to a reasonable length: - if((defined(url_param('callback'))) && (length(url_param('callback')) < 100)){ - $json_prefix = ''.url_param('callback').'(['; - $json_suffix = '])'; - } elsif(url_param('raw') eq 1) { - $json_prefix = '['; - $json_suffix = ']'; - } else { - $json_prefix = 'if(typeof(Insipid) == \'undefined\') Insipid = {}; Insipid.posts = ['; - $json_suffix = ']'; - } - #limiting posts count to url_param('count') , setting hard limit to 100 and default limit to 50 : - my $limit ; - if ((url_param('count') =~ /^[+-]?\d+$/) && (url_param('count') < 101)) { - $limit = url_param('count') ; - } else { - $limit = 50 ; - } - - my ($subquery, $sql, $sth, @parms, @wheres, @hr); - - # this first query will be used to select from a set, like when a user - # drills in on a specific tag or to get a smaller view of the entire - # dataset (for paging purposes). - - # MySQL and postgres have slightly different syntax here... - if ($dbtype eq 'mysql') { - $sql = "select $tbl_bookmarks.id from $tbl_bookmarks"; - } elsif ($dbtype eq 'Pg') { - $sql = "select $tbl_bookmarks.id, $tbl_bookmarks.date - from $tbl_bookmarks"; - } - - # Limit to tags - if(defined(url_param('tag'))) { - # Join the tag tables only when necessary - - if(url_param('tag') =~ / /) { - my @tags = split(/ /, url_param('tag')); - my $icount = 1; - - foreach(@tags) { - push(@parms, $_); - $sql = "$sql inner join $tbl_bookmark_tags - as bt$icount on - ($tbl_bookmarks.id = - bt$icount.bookmark_id) - inner join $tbl_tags as t$icount on - (t$icount.id = bt$icount.tag_id - and t$icount.name = ?) "; - $icount++; - } - } else { - $sql = "$sql - left join $tbl_bookmark_tags on - ($tbl_bookmarks.id = - $tbl_bookmark_tags.bookmark_id) - inner join $tbl_tags on - ($tbl_tags.id = $tbl_bookmark_tags.tag_id) - where ($tbl_tags.name = ?)"; - push(@parms, url_param('tag')); - } - - } - - # Search - # ?q= - $query = url_param('q'); - if($query ne "") { - if((get_option("public_searches") eq "yes") || (logged_in() eq 1)) { - my $sparm = $query; - if(length($sparm) > 2) { - $sql = "$sql where ($tbl_bookmarks.title like ?)"; - $sparm =~ s/\%//; - $sparm = "\%$sparm\%"; - push(@parms, $sparm); - } - } - } - - # order - $sql = "$sql order by $tbl_bookmarks.date desc"; - - # paging functionality - $sql = "$sql limit $limit"; - - - if(url_param('page')) { - my $offset = ((url_param('page') - 1) * $limit); - $sql = "$sql offset $offset"; - } - - $sth = $dbh->prepare($sql); - $sth->execute(@parms); - - $subquery = ""; - if($sth->rows > 0) { - if($sth->rows ne $limit) { $last_page = 1; } - - $subquery = " $tbl_bookmarks.id in ("; - - while(@hr = $sth->fetchrow_array) { - $subquery = $subquery . "$hr[0],"; - } - chop($subquery); # Strip off the last delimiter - - $subquery = $subquery . ")"; - } else { - # no bookmarks found: - ################### - print $json_prefix ; - print $json_suffix ; - ################### - return; - } - - @parms = (); - @wheres = (); - - $sql = "select - $tbl_bookmarks.id, - $tbl_bookmarks.title, - $tbl_bookmarks.description, - $tbl_bookmarks.access_level, - $tbl_bookmarks.url, - $tbl_tags.name, - $tbl_bookmarks.date, - $tbl_pagecache.date as cache_date, - $tbl_bookmarks.md5 - from $tbl_bookmarks - left join $tbl_bookmark_tags on - ($tbl_bookmarks.id = $tbl_bookmark_tags.bookmark_id) - left join $tbl_tags on - ($tbl_tags.id = $tbl_bookmark_tags.tag_id) - left join $tbl_pagecache on - ($tbl_bookmarks.md5 = $tbl_pagecache.md5)"; - - # Don't show private marks for non-logged in users - if(logged_in() eq 0) { - push(@wheres, "$tbl_bookmarks.access_level"); - push(@parms, "1"); - } - - my $max = @wheres; - if($max ne 0) { - $sql = "$sql where ("; - my $count = 1; - - foreach (@wheres) { - $sql = "$sql $_ = ?"; - if($count < $max) { - $sql = "$sql and "; - } - $count++; - } - - $sql = "$sql )"; - if($subquery ne "") { $sql = "$sql and $subquery"; } - } else { - if($subquery ne "") { $sql = "$sql where $subquery "; } - } - - # append sort order. - $sql = "$sql order by $tbl_bookmarks.date desc"; - - $sth = $dbh->prepare($sql); - $sth->execute(@parms); - - my %last; - $last{id} = -1; - - - ################### - print $json_prefix ; - ################### - - while(@hr = $sth->fetchrow_array) { - if($last{id} eq -1) { - $last{id} = $hr[0]; - $last{title} = $hr[1]; - $last{description} = $hr[2]; - $last{access_level} = $hr[3]; - $last{url} = $hr[4]; - $last{tags} = ""; - $last{timestamp} = $hr[6]; - } - - if($hr[0] ne $last{id}) { - # the id changed, so show the last mark. - json_show_post(0,$last{id}, $last{title}, $last{description}, $last{access_level}, $last{url}, $last{tags}, $last{timestamp}); - - # Swap the new one in. - $last{id} = $hr[0]; - $last{title} = $hr[1]; - $last{description} = $hr[2]; - $last{access_level} = $hr[3]; - $last{url} = $hr[4]; - $last{tags} = $hr[5]; - $last{timestamp} = $hr[6]; - } else { - # Add tag to the current bookmark - if(defined($hr[5])) { - $last{tags} = "$last{tags} $hr[5]"; - } - } - } - - if($last{id} ne -1) { - json_show_post(1,$last{id}, $last{title}, $last{description}, $last{access_level}, $last{url}, $last{tags}, $last{timestamp}); - } - - ################### - print $json_suffix ; - ################### -} - - -sub json_show_post { - my($last_mark, $id, $title, $description, $access_level, $url, - $tags, $timestamp) = (@_); - $title =~ s/\"/\\"/g ; - $description =~ s/\"/\\"/g ; - $tags =~ s/\"/\\"/g ; - my $json_txt = '{'; - - if($access_level eq 0) { - $json_txt = $json_txt.'"u":"'.$site_url.'/insipid.cgi?go='.$id.'",'; - $json_txt = $json_txt.'"d":"'.$title.'",'; - } else { - $json_txt = $json_txt.'"u":"'.$url.'",'; - $json_txt = $json_txt.'"d":"'.$title.'",'; - } - - if($description){ - $json_txt = $json_txt.'"n":"'.$description.'",'; - } - - my $timestr = ''; - if(logged_in() eq 1) { - $timestr = time2str('%Y-%m-%d %T EST', $timestamp, 'EST'); - } else { - $timestr = time2str('%Y-%m-%d', $timestamp, 'EST'); - } - - $json_txt = $json_txt.'"dt":"'.$timestr.'"'; - - if($tags) { - $json_txt = $json_txt.',"t":['; - my $cur; - my @tags = split(/\ /, $tags); - my $icount = 1 ; - foreach my $tag (@tags) { - if($tag){ - $json_txt = $json_txt.'"'.$tag.'"'; - if ($icount ne @tags){ - $json_txt = $json_txt.','; - } - } - $icount++ ; - } - $json_txt = $json_txt.']'; - } - - $json_txt = $json_txt.'}'; - - if($last_mark ne 1){ - $json_txt = $json_txt.','; - } - - print $json_txt ; -} -1; -__END__ +#!/usr/bin/perl +# +# Copyright (C) 2008 Luke Reeves +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# + +package Insipid::JSON; + +use strict; +use warnings; + +use vars qw(@ISA @EXPORT @EXPORT_OK); +use CGI qw/:standard/; +use CGI::Carp qw(fatalsToBrowser); +use Insipid::Config; +use Insipid::Database; +use Insipid::Sessions; +use Date::Format; +use Date::Parse; + +require Exporter; + +@ISA = qw(Exporter); + +@EXPORT = qw( +send_json_tags +send_json_posts +); + +my $query = ''; +my $last_page = 0; + + + +sub send_json_tags { + my ($sql, $sth); + + # Building up JSON structure before parsing the data: + my ($json_prefix,$json_suffix); + # limiting url_param('callback') to a reasonable length (100): + if((defined(url_param('callback'))) && (length(url_param('callback')) < 100)){ + $json_prefix = ''.url_param('callback').'({'; + $json_suffix = '})'; + } elsif(url_param('raw') eq 1) { + $json_prefix = '{'; + $json_suffix = '}'; + } else { + $json_prefix = 'if(typeof(Insipid) == \'undefined\') Insipid = {}; Insipid.tags = {'; + $json_suffix = '}'; + } + #limiting tags count, only if url_param('count') is a valid integer: + my $limit ; + if (url_param('count') =~ /^[+-]?\d+$/) { + $limit = ' limit '.url_param('count') ; + } + + + + # If the user has already chosen a tag, get the intersection list + if((url_param('tag')) && (logged_in() eq 1)) { + $sql = "select $tbl_tags.name,count(*) from $tbl_bookmarks + inner join $tbl_bookmark_tags as bt1 on + ($tbl_bookmarks.id = bt1.bookmark_id) + inner join $tbl_tags on + ($tbl_tags.id = bt1.tag_id) + inner join $tbl_bookmark_tags as bt2 on + ($tbl_bookmarks.id = bt2.bookmark_id) + inner join $tbl_tags as t2 on + (t2.id = bt2.tag_id and t2.name = ?) + where ($tbl_tags.name != ?) + group by $tbl_tags.name $limit"; + $sth = $dbh->prepare($sql); + $sth->execute(url_param('tag'), url_param('tag')); + print $json_prefix ; + if($sth->rows ne 0) { + my $icount = 1 ; + while(my @r = $sth->fetchrow_array()) { + json_show_tag($icount, $sth->rows, $r[0], $r[1]); + $icount++ ; + } + } + print $json_suffix ; + return ; + } else { + + # Access_spec contains a where clause to count only public bookmarks + # if the user is not logged in + my $access_where = ""; + if(logged_in() eq 0) { + $access_where = " where ($tbl_bookmarks.access_level = 1) "; + } + + my $order_clause; + $order_clause = "order by $tbl_tags.name"; + + $sql = "select $tbl_tags.name, count(*) + from $tbl_bookmarks + inner join $tbl_bookmark_tags on + ($tbl_bookmarks.id = $tbl_bookmark_tags.bookmark_id) + inner join $tbl_tags on + ($tbl_tags.id = $tbl_bookmark_tags.tag_id) + $access_where + group by $tbl_tags.name + $order_clause + $limit"; + + $sth = $dbh->prepare($sql); + $sth->execute; + print $json_prefix; + if($sth->rows ne 0) { + my $icount = 1; + while(my @r = $sth->fetchrow_array()) { + json_show_tag($icount, $sth->rows, $r[0], $r[1]); + $icount++; + } + } + print $json_suffix; + return; + } +} + +sub json_show_tag { + my($icount, $rowscount, $tag, $tagcount) = (@_); + $tag =~ s/\"/\\"/g ; + my $json_txt = ''; + $json_txt = $json_txt.'"'.$tag.'":'.$tagcount; + if ($icount ne $rowscount){ + $json_txt = $json_txt.','; + } + print $json_txt ; +} + +sub send_json_posts { + + # Building up JSON structure before parsing the data: + my ($json_prefix,$json_suffix); + # limiting url_param('callback') to a reasonable length: + if((defined(url_param('callback'))) && (length(url_param('callback')) < 100)){ + $json_prefix = ''.url_param('callback').'(['; + $json_suffix = '])'; + } elsif(url_param('raw') eq 1) { + $json_prefix = '['; + $json_suffix = ']'; + } else { + $json_prefix = 'if(typeof(Insipid) == \'undefined\') Insipid = {}; Insipid.posts = ['; + $json_suffix = ']'; + } + #limiting posts count to url_param('count') , setting hard limit to 100 and default limit to 50 : + my $limit ; + if ((url_param('count') =~ /^[+-]?\d+$/) && (url_param('count') < 101)) { + $limit = url_param('count') ; + } else { + $limit = 50 ; + } + + my ($subquery, $sql, $sth, @parms, @wheres, @hr); + + # this first query will be used to select from a set, like when a user + # drills in on a specific tag or to get a smaller view of the entire + # dataset (for paging purposes). + + $sql = "select $tbl_bookmarks.id from $tbl_bookmarks"; + + # Limit to tags + if(defined(url_param('tag'))) { + # Join the tag tables only when necessary + + if(url_param('tag') =~ / /) { + my @tags = split(/ /, url_param('tag')); + my $icount = 1; + + foreach(@tags) { + push(@parms, $_); + $sql = "$sql inner join $tbl_bookmark_tags + as bt$icount on + ($tbl_bookmarks.id = + bt$icount.bookmark_id) + inner join $tbl_tags as t$icount on + (t$icount.id = bt$icount.tag_id + and t$icount.name = ?) "; + $icount++; + } + } else { + $sql = "$sql + left join $tbl_bookmark_tags on + ($tbl_bookmarks.id = + $tbl_bookmark_tags.bookmark_id) + inner join $tbl_tags on + ($tbl_tags.id = $tbl_bookmark_tags.tag_id) + where ($tbl_tags.name = ?)"; + push(@parms, url_param('tag')); + } + + } + + # Search + # ?q= + $query = url_param('q'); + if($query ne "") { + if((get_option("public_searches") eq "yes") || (logged_in() eq 1)) { + my $sparm = $query; + if(length($sparm) > 2) { + $sql = "$sql where ($tbl_bookmarks.title like ?)"; + $sparm =~ s/\%//; + $sparm = "\%$sparm\%"; + push(@parms, $sparm); + } + } + } + + # order + $sql = "$sql order by $tbl_bookmarks.date desc"; + + # paging functionality + $sql = "$sql limit $limit"; + + + if(url_param('page')) { + my $offset = ((url_param('page') - 1) * $limit); + $sql = "$sql offset $offset"; + } + + $sth = $dbh->prepare($sql); + $sth->execute(@parms); + + $subquery = ""; + if($sth->rows > 0) { + if($sth->rows ne $limit) { $last_page = 1; } + + $subquery = " $tbl_bookmarks.id in ("; + + while(@hr = $sth->fetchrow_array) { + $subquery = $subquery . "$hr[0],"; + } + chop($subquery); # Strip off the last delimiter + + $subquery = $subquery . ")"; + } else { + # no bookmarks found: + ################### + print $json_prefix ; + print $json_suffix ; + ################### + return; + } + + @parms = (); + @wheres = (); + + $sql = "select + $tbl_bookmarks.id, + $tbl_bookmarks.title, + $tbl_bookmarks.description, + $tbl_bookmarks.access_level, + $tbl_bookmarks.url, + $tbl_tags.name, + $tbl_bookmarks.date, + $tbl_pagecache.date as cache_date, + $tbl_bookmarks.md5 + from $tbl_bookmarks + left join $tbl_bookmark_tags on + ($tbl_bookmarks.id = $tbl_bookmark_tags.bookmark_id) + left join $tbl_tags on + ($tbl_tags.id = $tbl_bookmark_tags.tag_id) + left join $tbl_pagecache on + ($tbl_bookmarks.md5 = $tbl_pagecache.md5)"; + + # Don't show private marks for non-logged in users + if(logged_in() eq 0) { + push(@wheres, "$tbl_bookmarks.access_level"); + push(@parms, "1"); + } + + my $max = @wheres; + if($max ne 0) { + $sql = "$sql where ("; + my $count = 1; + + foreach (@wheres) { + $sql = "$sql $_ = ?"; + if($count < $max) { + $sql = "$sql and "; + } + $count++; + } + + $sql = "$sql )"; + if($subquery ne "") { $sql = "$sql and $subquery"; } + } else { + if($subquery ne "") { $sql = "$sql where $subquery "; } + } + + # append sort order. + $sql = "$sql order by $tbl_bookmarks.date desc"; + + $sth = $dbh->prepare($sql); + $sth->execute(@parms); + + my %last; + $last{id} = -1; + + + ################### + print $json_prefix ; + ################### + + while(@hr = $sth->fetchrow_array) { + if($last{id} eq -1) { + $last{id} = $hr[0]; + $last{title} = $hr[1]; + $last{description} = $hr[2]; + $last{access_level} = $hr[3]; + $last{url} = $hr[4]; + $last{tags} = ""; + $last{timestamp} = $hr[6]; + } + + if($hr[0] ne $last{id}) { + # the id changed, so show the last mark. + json_show_post(0,$last{id}, $last{title}, $last{description}, $last{access_level}, $last{url}, $last{tags}, $last{timestamp}); + + # Swap the new one in. + $last{id} = $hr[0]; + $last{title} = $hr[1]; + $last{description} = $hr[2]; + $last{access_level} = $hr[3]; + $last{url} = $hr[4]; + $last{tags} = $hr[5]; + $last{timestamp} = $hr[6]; + } else { + # Add tag to the current bookmark + if(defined($hr[5])) { + $last{tags} = "$last{tags} $hr[5]"; + } + } + } + + if($last{id} ne -1) { + json_show_post(1,$last{id}, $last{title}, $last{description}, $last{access_level}, $last{url}, $last{tags}, $last{timestamp}); + } + + ################### + print $json_suffix ; + ################### +} + + +sub json_show_post { + my($last_mark, $id, $title, $description, $access_level, $url, + $tags, $timestamp) = (@_); + $title =~ s/\"/\\"/g ; + $description =~ s/\"/\\"/g ; + $tags =~ s/\"/\\"/g ; + my $json_txt = '{'; + + if($access_level eq 0) { + $json_txt = $json_txt.'"u":"'.$site_url.'/insipid.cgi?go='.$id.'",'; + $json_txt = $json_txt.'"d":"'.$title.'",'; + } else { + $json_txt = $json_txt.'"u":"'.$url.'",'; + $json_txt = $json_txt.'"d":"'.$title.'",'; + } + + if($description){ + $json_txt = $json_txt.'"n":"'.$description.'",'; + } + + my $timestr = ''; + if(logged_in() eq 1) { + $timestr = time2str('%Y-%m-%d %T EST', $timestamp, 'EST'); + } else { + $timestr = time2str('%Y-%m-%d', $timestamp, 'EST'); + } + + $json_txt = $json_txt.'"dt":"'.$timestr.'"'; + + if($tags) { + $json_txt = $json_txt.',"t":['; + my $cur; + my @tags = split(/\ /, $tags); + my $icount = 1 ; + foreach my $tag (@tags) { + if($tag){ + $json_txt = $json_txt.'"'.$tag.'"'; + if ($icount ne @tags){ + $json_txt = $json_txt.','; + } + } + $icount++ ; + } + $json_txt = $json_txt.']'; + } + + $json_txt = $json_txt.'}'; + + if($last_mark ne 1){ + $json_txt = $json_txt.','; + } + + print $json_txt ; +} +1; +__END__ diff --git a/lib/Insipid/Main.pm b/lib/Insipid/Main.pm index bce5329..2d85217 100755 --- a/lib/Insipid/Main.pm +++ b/lib/Insipid/Main.pm @@ -553,7 +553,7 @@ sub do_import { my ($omd5, $ourl, $otype, $olength, $odate, $sql, $oadd, $omod, $otags); my $ispec = ''; - if ($dbtype eq 'mysql') {$ispec = " ignore ";} + $ispec = " ignore "; $sql = "insert $ispec into pagecache_references (md5_parent, md5_child) values(?,?)"; @@ -668,12 +668,7 @@ sub do_import { $insert_snapshot->bind_param(3, $otype); $insert_snapshot->bind_param(4, $olength); - if ($dbtype eq "Pg") { - $insert_snapshot->bind_param(5, decode_base64($cbuffer), - SQL_VARBINARY); - } else { - $insert_snapshot->bind_param(5, decode_base64($cbuffer)); - } + $insert_snapshot->bind_param(5, decode_base64($cbuffer)); $insert_snapshot->bind_param(6, $odate); $insert_snapshot->execute; @@ -854,13 +849,7 @@ sub show_bookmarks { # drills in on a specific tag or to get a smaller view of the entire # dataset (for paging purposes). - # MySQL and postgres have slightly different syntax here... - if ($dbtype eq 'mysql') { - $sql = "select $tbl_bookmarks.id from $tbl_bookmarks"; - } elsif ($dbtype eq 'Pg') { - $sql = "select $tbl_bookmarks.id, $tbl_bookmarks.date - from $tbl_bookmarks"; - } + $sql = "select $tbl_bookmarks.id from $tbl_bookmarks"; # Limit to tags if (defined(url_param('tag'))) { diff --git a/lib/Insipid/Schemas.pm b/lib/Insipid/Schemas.pm index 6463aaf..4c3c293 100755 --- a/lib/Insipid/Schemas.pm +++ b/lib/Insipid/Schemas.pm @@ -1,252 +1,149 @@ -#!/usr/bin/perl -# -# Copyright (C) 2008 Luke Reeves -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -# USA -# - -package Insipid::Schemas; - -use strict; -use warnings; -use Insipid::Config; - -use vars qw( -@ISA -@EXPORT -$createMySQL -$createPostgres -); - -use Exporter; - -@ISA = qw(Exporter); - -@EXPORT = qw( -$version -$createMySQL -$createPostgres -); - -# Insipid will check the database version number on each initialization of -# the options table (every hit essentially) and upgrade the tables if there's -# any mismatch. -our $version = "0.9.20"; - -our $createPostgres = <new(timeout=>30); -if(get_option('proxy_host') ne '') { - my $proxy_host = get_option('proxy_host'); - my $proxy_port = get_option('proxy_port'); - $ua->proxy(['http', 'ftp'], "http://$proxy_host:$proxy_port/"); -} - - -my $referer = ""; - -sub export_snapshots { - my ($writer) = (@_); - my ($sql, $sth, @rs); - - # Export the objects - $writer->startTag('objects'); - $sql = "select md5, url, content_type, content_length, date, content - from $tbl_pagecache"; - $sth = $dbh->prepare($sql); - $sth->execute(); - - while(@rs = $sth->fetchrow_array()) { - $writer->startTag('object', - 'md5' => $rs[0], - 'url' => $rs[1], - 'type' => $rs[2], - 'length' => $rs[3], - 'date' => $rs[4] - ); - $writer->characters(encode_base64($rs[5])); - $writer->endTag("object"); - } - $writer->endTag('objects'); - - # Export the relationships - $writer->startTag('relationships'); - - $sql = "select md5_parent, md5_child from $tbl_pagecache_references"; - $sth = $dbh->prepare($sql); - $sth->execute(); - - while(@rs = $sth->fetchrow_array()) { - $writer->startTag("relationship", - "parent" => $rs[0], - "child" => $rs[1]); - $writer->endTag("relationship"); - } - - $writer->endTag("relationships"); - -} - -# TODO: Make the insert_snapshot callable by this and the import method. -sub fetch_url { - my ($url, $roverride) = (@_); - - # TODO: No. - if(defined($roverride)) { $referer = $roverride; } - my $md5 = md5_hex($url); - - my $req = HTTP::Request->new(GET => $url) or die "Can't fetch page: $!\n"; - - if($referer ne '') { $req->header( referer => $referer ); } - - my $res = $ua->request($req); - - if($res->is_success) { - my $content = $res->content; - - # Shove the unparsed page into the cache. - my $sql = "insert into $tbl_pagecache(md5, url, content_type, - content_length, content, date) - values ( ? , ? , ? , ? , ? , ? )"; - - my $sth = $dbh->prepare($sql); - my $ct = $res->header('Content-Type'); - if(length($ct) > 50) { $ct = substr($ct, 0, 50); } - - $sth->bind_param(1, $md5); - $sth->bind_param(2, $url); - $sth->bind_param(3, $ct); - $sth->bind_param(4, length($content)); - - # Postgres needs escaping for the binary data. - if($dbtype eq 'Pg') { - $sth->bind_param(5, $content, SQL_VARBINARY); - } else { - $sth->bind_param(5, $content); - } - $sth->bind_param(6, time()); - $sth->execute; - - if($sth->err) { - # print $sth->errstr; - # print "
"; - return 1; - } else { - if($ct =~ /text\/html/i) { - print '
Parsing page... '; - parsepage($url, $content, $ct); - print 'done.'; - } - - return 0; - } - } else { - my $err = $res->status_line; - print "$err
"; - - return 1; - } -} - -sub show_snapshot { - my ($md5) = (@_); - my ($sql, $sth, @row); - my %internalLinks = (); - - $sql = "select content_type,content,url,date,content_length - from $tbl_pagecache where (md5 = ?)"; - - $sth = $dbh->prepare($sql); - $sth->execute($md5); - - @row = $sth->fetchrow_array; - - if(!@row) { - print 'Content-Type: text/plain\r\n\r\n'; - print "Can't find cached item \"$md5\""; - return; - } - - - # Check for IMS request. - my $ims = http('If-Modified-Since'); - if($ims) { - - my $t = str2time($ims); - - if($row[3] <= $t) { - # Return a 304 not modified. - print 'Status: 304 Not Modified\r\n'; - return; - } - } - - my $dt = ims_time($row[3]); - print "Last-Modified: $dt\r\n"; - print "Content-Type: $row[0]\r\n"; - - if($row[0] =~ /text\/html/i) { - # Now we get a list of URLs that can be redirected to our - # local snapshot cache. We'll use that to build a hash of - # URL->MD5 values and match outputted links against that. - my ($resql, $resth, @rerow); - $resql = "select $tbl_pagecache_references.md5_child, - $tbl_pagecache.url - from $tbl_pagecache_references - inner join $tbl_pagecache on - ($tbl_pagecache_references.md5_child = - $tbl_pagecache.md5) - where (md5_parent = ?)"; - $resth = $dbh->prepare($resql); - $resth->execute($md5); - - while(@rerow = $resth->fetchrow_array()) { - $internalLinks{$rerow[1]} = $rerow[0]; - } - - print "\r\n"; - my $p = Insipid::Parser->new($row[2], undef); - $p->setSnapshotMap(\%internalLinks); - - if($row[0] =~ /utf/i) { - $p->utf8_mode(1); - } - $p->parse($row[1]); - } else { - print "Content-Length: $row[4]\r\n"; - print "\r\n"; - print $row[1]; - } - - exit; -} - -sub show_details { - my ($md5) = @_; - my ($sth, $sql); - - $sql = "select $tbl_bookmarks.title from $tbl_bookmarks - where ($tbl_bookmarks.md5 = ?)"; - $sth = $dbh->prepare($sql); - $sth->execute($md5); - my @row = $sth->fetchrow_array(); - - print '

Cache Details for "'; - print escapeHTML($row[0]); - print '"

'; - print '
'; - - $sql = "select $tbl_pagecache.md5, $tbl_pagecache.url, - $tbl_pagecache.content_type, - $tbl_pagecache.content_length, - pg2.md5_parent, count(*) - from $tbl_pagecache_references - inner join $tbl_pagecache on - ($tbl_pagecache_references.md5_child = - $tbl_pagecache.md5) - left join $tbl_pagecache_references as pg2 on - (pg2.md5_child = $tbl_pagecache.md5) - where ($tbl_pagecache_references.md5_parent = ?) - group by $tbl_pagecache.md5, $tbl_pagecache.url, - $tbl_pagecache.content_type, pg2.md5_parent, - $tbl_pagecache.content_length, pg2.md5_child - order by $tbl_pagecache.url"; - - $sth = $dbh->prepare($sql); - $sth->execute($md5); - - while(my @rs = $sth->fetchrow_array()) { - print ''; - } - - print '
ViewURL'; - print 'TypeSizeRef Count
'; - my $ss = "$snapshot_url$rs[0]"; - - print "live/snapshot"; - print ''; - print $rs[1]; - print ''; - print $rs[2]; - print ''; - print $rs[3]; - print ''; - print $rs[5]; - print '
'; -} - -# -# Show a nice menu of the users snapshots. -# -sub show_snapshots { - - # If a snapshot was asked to be deleted - if(defined(param('delete'))) { - delete_snapshot(param('delete')); - } - - if(defined(param('md5'))) { - show_details(param('md5')); - return; - } - - my $tcount = 0; - my $tsize = 0; - - my $sql = "select $tbl_pagecache.md5, $tbl_bookmarks.title, - $tbl_pagecache.date, - $tbl_pagecache.content_length + - coalesce(sum(p2.content_length), 0), - count(*) - 1, $tbl_bookmarks.access_level - from $tbl_pagecache - inner join $tbl_bookmarks on - ($tbl_bookmarks.md5 = $tbl_pagecache.md5) - left join $tbl_pagecache_references on - ($tbl_pagecache.md5 = $tbl_pagecache_references.md5_parent) - left join $tbl_pagecache as p2 on - (p2.md5 = $tbl_pagecache_references.md5_child) - group by - $tbl_bookmarks.access_level, - $tbl_pagecache.md5, $tbl_bookmarks.title, - $tbl_pagecache.date, $tbl_pagecache.content_length - order by $tbl_pagecache.date desc"; - my $sth = $dbh->prepare($sql); - $sth->execute; - - print '
'; - - my $count = 0; - - while(my @r = $sth->fetchrow_array) { - - $count++; - - my $color; - if(($count % 2) eq 1) { - $color = ' bgcolor="#EEEEEE" '; - } else { - $color = ''; - } - - print ""; - print ''; - my $timestr = time2str('%Y-%m-%d', $r[2], 'EST'); - my $count = $r[4] + 1; $tcount += $count; - $tsize += $r[3]; - print ""; - print ""; - - my $link = "$site_url/insipid.cgi?op=snapshots&md5=$r[0]"; - - if($count ne 1) { - print ""; - } else { - print ""; - } - - print '"; - print ''; - } - - print ''; - print ""; - print ""; - - print "
Page'; - print 'DateSizeObjectsFunctions
'; - - print ""; - if($r[5] eq 0) { print ''; } - print $r[1]; - if($r[5] eq 0) { print ''; } - print '$timestr$r[3]$count$count'; - print "delete,"; - print " "; - print "fetch linked objects
Total $tsize$tcount 
"; -} - -# This fetches all linked-to objects (specifically images for now) -# for a cached page. -sub fetch_related { - my ($md5) = (@_); - - my $sql = "select content, url - from $tbl_pagecache where (md5 = ?)"; - my $sth = $dbh->prepare($sql); - $sth->execute($md5); - - my @r = $sth->fetchrow_array(); - - my $p = Insipid::LinkExtractor->new($r[1]); - $p->parse($r[0]); - -} - -# Deletes a snapshot and all orphan cache children, taking into -# account the fact that items can be shared across cached pages. -# -# This is horribly expensive, and someday I'll replace it with -# a much nicer function. -sub delete_snapshot { - my ($md5) = (@_); - - # The snapshot - my $sql = "delete from $tbl_pagecache where (md5 = ?)"; - my $delstatement = $dbh->prepare($sql); - $delstatement->execute($md5); - - # References - $sql = "delete from $tbl_pagecache_references where (md5_parent = ?)"; - my $sth = $dbh->prepare($sql); - $sth->execute($md5); - - # Orpans - blow away any md5s in the pagecache table that aren't - # referenced as a child in the references table. First, get a list - # of valid MD5s. - $sql = "select distinct md5_child from $tbl_pagecache_references"; - $sth = $dbh->prepare($sql); - $sth->execute(); - - my $subquery = ''; - while(my @r = $sth->fetchrow_array) { - if($subquery ne '') { $subquery = $subquery . ','; } - $subquery = "$subquery '$r[0]'"; - } - - $sql = "select distinct md5_parent from $tbl_pagecache_references"; - $sth = $dbh->prepare($sql); - $sth->execute(); - while(my @r = $sth->fetchrow_array) { - if($subquery ne '') { $subquery = $subquery . ','; } - $subquery = "$subquery '$r[0]'"; - } - - if($subquery eq '') { - $sql = "delete from $tbl_pagecache;"; - } else { - $sql = "delete from $tbl_pagecache where md5 not in ($subquery)"; - } - - $sth = $dbh->prepare($sql); - $sth->execute(); -} - -sub do_snapshot { - # Save the page. - print '

'; - - my ($bookmark_id) = (@_); - my $sql = "select url,md5,title from $tbl_bookmarks where (id = ?)"; - my $sth = $dbh->prepare($sql); - $sth->execute($bookmark_id); - my @row = $sth->fetchrow_array; - - if(@row) { - print "

Fetching \"$row[2]\"...

\n"; - $referer = $row[0]; - fetch_url(@row); - } else { - die "Couldn't find the row for id $bookmark_id!"; - } -} - -sub parsepage { - my ($url, $content, $content_type) = (@_); - - my $p = Insipid::Parser->new($url, \&fetch_url); - if($content_type =~ /utf/i) { - $p->utf8_mode(1); - } - - $p->parse($content); -} - -1; -__END__ +#!/usr/bin/perl +# +# Copyright (C) 2008 Luke Reeves +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# + +package Insipid::Snapshots; + +use strict; +use warnings; + +use vars qw(@ISA @EXPORT); +use Insipid::Config; +use Insipid::Database; +use Insipid::Util; +use Insipid::LinkExtractor; +use Insipid::Parser; +use CGI qw/:standard/; +use CGI::Carp qw(fatalsToBrowser); +use Date::Format; +use Date::Parse; +use Date::Parse; +use Digest::MD5 qw(md5 md5_hex); +use DBI qw/:sql_types/;; +use LWP::UserAgent; +use HTTP::Request; +use MIME::Base64; +use XML::Writer; + +require Exporter; + + +@ISA = qw(Exporter); + +@EXPORT = qw( +show_snapshots +do_snapshot +delete_snapshot +export_snapshots +show_snapshot +fetch_related +parsepage +fetch_url +); + +my $ua = LWP::UserAgent->new(timeout=>30); +if(get_option('proxy_host') ne '') { + my $proxy_host = get_option('proxy_host'); + my $proxy_port = get_option('proxy_port'); + $ua->proxy(['http', 'ftp'], "http://$proxy_host:$proxy_port/"); +} + + +my $referer = ""; + +sub export_snapshots { + my ($writer) = (@_); + my ($sql, $sth, @rs); + + # Export the objects + $writer->startTag('objects'); + $sql = "select md5, url, content_type, content_length, date, content + from $tbl_pagecache"; + $sth = $dbh->prepare($sql); + $sth->execute(); + + while(@rs = $sth->fetchrow_array()) { + $writer->startTag('object', + 'md5' => $rs[0], + 'url' => $rs[1], + 'type' => $rs[2], + 'length' => $rs[3], + 'date' => $rs[4] + ); + $writer->characters(encode_base64($rs[5])); + $writer->endTag("object"); + } + $writer->endTag('objects'); + + # Export the relationships + $writer->startTag('relationships'); + + $sql = "select md5_parent, md5_child from $tbl_pagecache_references"; + $sth = $dbh->prepare($sql); + $sth->execute(); + + while(@rs = $sth->fetchrow_array()) { + $writer->startTag("relationship", + "parent" => $rs[0], + "child" => $rs[1]); + $writer->endTag("relationship"); + } + + $writer->endTag("relationships"); + +} + +# TODO: Make the insert_snapshot callable by this and the import method. +sub fetch_url { + my ($url, $roverride) = (@_); + + # TODO: No. + if(defined($roverride)) { $referer = $roverride; } + my $md5 = md5_hex($url); + + my $req = HTTP::Request->new(GET => $url) or die "Can't fetch page: $!\n"; + + if($referer ne '') { $req->header( referer => $referer ); } + + my $res = $ua->request($req); + + if($res->is_success) { + my $content = $res->content; + + # Shove the unparsed page into the cache. + my $sql = "insert into $tbl_pagecache(md5, url, content_type, + content_length, content, date) + values ( ? , ? , ? , ? , ? , ? )"; + + my $sth = $dbh->prepare($sql); + my $ct = $res->header('Content-Type'); + if(length($ct) > 50) { $ct = substr($ct, 0, 50); } + + $sth->bind_param(1, $md5); + $sth->bind_param(2, $url); + $sth->bind_param(3, $ct); + $sth->bind_param(4, length($content)); + + $sth->bind_param(5, $content); + + $sth->bind_param(6, time()); + $sth->execute; + + if($sth->err) { + # print $sth->errstr; + # print "
"; + return 1; + } else { + if($ct =~ /text\/html/i) { + print '
Parsing page... '; + parsepage($url, $content, $ct); + print 'done.'; + } + + return 0; + } + } else { + my $err = $res->status_line; + print "$err
"; + + return 1; + } +} + +sub show_snapshot { + my ($md5) = (@_); + my ($sql, $sth, @row); + my %internalLinks = (); + + $sql = "select content_type,content,url,date,content_length + from $tbl_pagecache where (md5 = ?)"; + + $sth = $dbh->prepare($sql); + $sth->execute($md5); + + @row = $sth->fetchrow_array; + + if(!@row) { + print 'Content-Type: text/plain\r\n\r\n'; + print "Can't find cached item \"$md5\""; + return; + } + + + # Check for IMS request. + my $ims = http('If-Modified-Since'); + if($ims) { + + my $t = str2time($ims); + + if($row[3] <= $t) { + # Return a 304 not modified. + print 'Status: 304 Not Modified\r\n'; + return; + } + } + + my $dt = ims_time($row[3]); + print "Last-Modified: $dt\r\n"; + print "Content-Type: $row[0]\r\n"; + + if($row[0] =~ /text\/html/i) { + # Now we get a list of URLs that can be redirected to our + # local snapshot cache. We'll use that to build a hash of + # URL->MD5 values and match outputted links against that. + my ($resql, $resth, @rerow); + $resql = "select $tbl_pagecache_references.md5_child, + $tbl_pagecache.url + from $tbl_pagecache_references + inner join $tbl_pagecache on + ($tbl_pagecache_references.md5_child = + $tbl_pagecache.md5) + where (md5_parent = ?)"; + $resth = $dbh->prepare($resql); + $resth->execute($md5); + + while(@rerow = $resth->fetchrow_array()) { + $internalLinks{$rerow[1]} = $rerow[0]; + } + + print "\r\n"; + my $p = Insipid::Parser->new($row[2], undef); + $p->setSnapshotMap(\%internalLinks); + + if($row[0] =~ /utf/i) { + $p->utf8_mode(1); + } + $p->parse($row[1]); + } else { + print "Content-Length: $row[4]\r\n"; + print "\r\n"; + print $row[1]; + } + + exit; +} + +sub show_details { + my ($md5) = @_; + my ($sth, $sql); + + $sql = "select $tbl_bookmarks.title from $tbl_bookmarks + where ($tbl_bookmarks.md5 = ?)"; + $sth = $dbh->prepare($sql); + $sth->execute($md5); + my @row = $sth->fetchrow_array(); + + print '

Cache Details for "'; + print escapeHTML($row[0]); + print '"

'; + print '
'; + + $sql = "select $tbl_pagecache.md5, $tbl_pagecache.url, + $tbl_pagecache.content_type, + $tbl_pagecache.content_length, + pg2.md5_parent, count(*) + from $tbl_pagecache_references + inner join $tbl_pagecache on + ($tbl_pagecache_references.md5_child = + $tbl_pagecache.md5) + left join $tbl_pagecache_references as pg2 on + (pg2.md5_child = $tbl_pagecache.md5) + where ($tbl_pagecache_references.md5_parent = ?) + group by $tbl_pagecache.md5, $tbl_pagecache.url, + $tbl_pagecache.content_type, pg2.md5_parent, + $tbl_pagecache.content_length, pg2.md5_child + order by $tbl_pagecache.url"; + + $sth = $dbh->prepare($sql); + $sth->execute($md5); + + while(my @rs = $sth->fetchrow_array()) { + print ''; + } + + print '
ViewURL'; + print 'TypeSizeRef Count
'; + my $ss = "$snapshot_url$rs[0]"; + + print "live/snapshot"; + print ''; + print $rs[1]; + print ''; + print $rs[2]; + print ''; + print $rs[3]; + print ''; + print $rs[5]; + print '
'; +} + +# +# Show a nice menu of the users snapshots. +# +sub show_snapshots { + + # If a snapshot was asked to be deleted + if(defined(param('delete'))) { + delete_snapshot(param('delete')); + } + + if(defined(param('md5'))) { + show_details(param('md5')); + return; + } + + my $tcount = 0; + my $tsize = 0; + + my $sql = "select $tbl_pagecache.md5, $tbl_bookmarks.title, + $tbl_pagecache.date, + $tbl_pagecache.content_length + + coalesce(sum(p2.content_length), 0), + count(*) - 1, $tbl_bookmarks.access_level + from $tbl_pagecache + inner join $tbl_bookmarks on + ($tbl_bookmarks.md5 = $tbl_pagecache.md5) + left join $tbl_pagecache_references on + ($tbl_pagecache.md5 = $tbl_pagecache_references.md5_parent) + left join $tbl_pagecache as p2 on + (p2.md5 = $tbl_pagecache_references.md5_child) + group by + $tbl_bookmarks.access_level, + $tbl_pagecache.md5, $tbl_bookmarks.title, + $tbl_pagecache.date, $tbl_pagecache.content_length + order by $tbl_pagecache.date desc"; + my $sth = $dbh->prepare($sql); + $sth->execute; + + print '
'; + + my $count = 0; + + while(my @r = $sth->fetchrow_array) { + + $count++; + + my $color; + if(($count % 2) eq 1) { + $color = ' bgcolor="#EEEEEE" '; + } else { + $color = ''; + } + + print ""; + print ''; + my $timestr = time2str('%Y-%m-%d', $r[2], 'EST'); + my $count = $r[4] + 1; $tcount += $count; + $tsize += $r[3]; + print ""; + print ""; + + my $link = "$site_url/insipid.cgi?op=snapshots&md5=$r[0]"; + + if($count ne 1) { + print ""; + } else { + print ""; + } + + print '"; + print ''; + } + + print ''; + print ""; + print ""; + + print "
Page'; + print 'DateSizeObjectsFunctions
'; + + print ""; + if($r[5] eq 0) { print ''; } + print $r[1]; + if($r[5] eq 0) { print ''; } + print '$timestr$r[3]$count$count'; + print "delete,"; + print " "; + print "fetch linked objects
Total $tsize$tcount 
"; +} + +# This fetches all linked-to objects (specifically images for now) +# for a cached page. +sub fetch_related { + my ($md5) = (@_); + + my $sql = "select content, url + from $tbl_pagecache where (md5 = ?)"; + my $sth = $dbh->prepare($sql); + $sth->execute($md5); + + my @r = $sth->fetchrow_array(); + + my $p = Insipid::LinkExtractor->new($r[1]); + $p->parse($r[0]); + +} + +# Deletes a snapshot and all orphan cache children, taking into +# account the fact that items can be shared across cached pages. +# +# This is horribly expensive, and someday I'll replace it with +# a much nicer function. +sub delete_snapshot { + my ($md5) = (@_); + + # The snapshot + my $sql = "delete from $tbl_pagecache where (md5 = ?)"; + my $delstatement = $dbh->prepare($sql); + $delstatement->execute($md5); + + # References + $sql = "delete from $tbl_pagecache_references where (md5_parent = ?)"; + my $sth = $dbh->prepare($sql); + $sth->execute($md5); + + # Orpans - blow away any md5s in the pagecache table that aren't + # referenced as a child in the references table. First, get a list + # of valid MD5s. + $sql = "select distinct md5_child from $tbl_pagecache_references"; + $sth = $dbh->prepare($sql); + $sth->execute(); + + my $subquery = ''; + while(my @r = $sth->fetchrow_array) { + if($subquery ne '') { $subquery = $subquery . ','; } + $subquery = "$subquery '$r[0]'"; + } + + $sql = "select distinct md5_parent from $tbl_pagecache_references"; + $sth = $dbh->prepare($sql); + $sth->execute(); + while(my @r = $sth->fetchrow_array) { + if($subquery ne '') { $subquery = $subquery . ','; } + $subquery = "$subquery '$r[0]'"; + } + + if($subquery eq '') { + $sql = "delete from $tbl_pagecache;"; + } else { + $sql = "delete from $tbl_pagecache where md5 not in ($subquery)"; + } + + $sth = $dbh->prepare($sql); + $sth->execute(); +} + +sub do_snapshot { + # Save the page. + print '

'; + + my ($bookmark_id) = (@_); + my $sql = "select url,md5,title from $tbl_bookmarks where (id = ?)"; + my $sth = $dbh->prepare($sql); + $sth->execute($bookmark_id); + my @row = $sth->fetchrow_array; + + if(@row) { + print "

Fetching \"$row[2]\"...

\n"; + $referer = $row[0]; + fetch_url(@row); + } else { + die "Couldn't find the row for id $bookmark_id!"; + } +} + +sub parsepage { + my ($url, $content, $content_type) = (@_); + + my $p = Insipid::Parser->new($url, \&fetch_url); + if($content_type =~ /utf/i) { + $p->utf8_mode(1); + } + + $p->parse($content); +} + +1; +__END__ diff --git a/lib/Insipid/Tags.pm b/lib/Insipid/Tags.pm index 4844a15..fae6374 100755 --- a/lib/Insipid/Tags.pm +++ b/lib/Insipid/Tags.pm @@ -200,11 +200,7 @@ sub show_tags { } my $order_clause; - if($dbtype eq "Pg") { - $order_clause = "order by upper($tbl_tags.name)"; - } else { - $order_clause = "order by $tbl_tags.name"; - } + $order_clause = "order by $tbl_tags.name"; $sql = "select $tbl_tags.name, count(*) from $tbl_bookmarks -- 2.39.5