]> 91.132.146.200 Git - insipid.git/commitdiff
dropped pgsql support since the popularity is too low.
authorBanana <banana@starscream.de>
Wed, 15 Jun 2011 14:48:40 +0000 (16:48 +0200)
committerBanana <banana@starscream.de>
Wed, 15 Jun 2011 14:48:40 +0000 (16:48 +0200)
insipid-config.cgi.example
lib/Insipid/DBInstall.pm
lib/Insipid/Database.pm
lib/Insipid/JSON.pm
lib/Insipid/Main.pm
lib/Insipid/Schemas.pm
lib/Insipid/Snapshots.pm
lib/Insipid/Tags.pm

index 8227a7d97a5dae9ac0c38d989bfaff035f37b8ca..6d7d020ef49b4753dba438c82281524061ebf4e8 100755 (executable)
@@ -1,22 +1,20 @@
-# This is the database configuration for Insipid.  The "dbtype" parameter\r
-# can be either "mysql" for the MySQL database or "Pg" for PostgreSQL.\r
-dbname = insipid_luke\r
-dbuser = luke\r
-dbpass = dbpass\r
-dbtype = mysql\r
-\r
-# If you'd like the Insipid database tables to use a prefix, uncomment\r
-# this line.\r
-#dbprefix = insipid_\r
-\r
-# The base URI to your installation.\r
-pagepath = /Luke\r
-\r
-# If your webserver is not running on port 80 and it doesn't properly set\r
-# the SERVER_PORT variable, set it here.\r
-#server_port = 8080\r
-\r
-# The login name and password for using the Insipid interface.\r
-username = luke\r
-userpass = yourpassword\r
-\r
+# 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
+
index f1b075abea056509f415ad13deff9dc85f69cb91..e5da07ff09835a90eb0c56a50f76014aae25d7d3 100755 (executable)
@@ -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 "<p>Creating tables...";
 
-       if($dbtype eq 'mysql') {
-               @creates = split(/\;/, $createMySQL);
-       } else {
-               @creates = split(/\;/, $createPostgres);
-       }
+       @creates = split(/\;/, $createMySQL);
 
        foreach(@creates) {
                my $sql = $_;
index f6463f3a5bdc35da6eeaa960ff64949ce9f1219c..10938e1e698a92c2f03bc28237fe09bd771d760b 100755 (executable)
@@ -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;
index eb7460a8e3092ec0f4fc1468cf385116fc021f0e..e9c5ca973d768523fcff756dcf64423da401295b 100755 (executable)
-#!/usr/bin/perl\r
-#\r
-# Copyright (C) 2008 Luke Reeves\r
-#\r
-# This program is free software; you can redistribute it and/or modify\r
-# it under the terms of the GNU General Public License as published by\r
-# the Free Software Foundation; either version 2 of the License, or\r
-# (at your option) any later version.\r
-#\r
-# This program is distributed in the hope that it will be useful,\r
-# but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-# GNU General Public License for more details.\r
-#\r
-# You should have received a copy of the GNU General Public License\r
-# along with this program; if not, write to the Free Software\r
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307\r
-# USA\r
-#\r
-\r
-package Insipid::JSON;\r
-\r
-use strict;\r
-use warnings;\r
-\r
-use vars qw(@ISA @EXPORT @EXPORT_OK);\r
-use CGI qw/:standard/;\r
-use CGI::Carp qw(fatalsToBrowser);\r
-use Insipid::Config;\r
-use Insipid::Database;\r
-use Insipid::Sessions;\r
-use Date::Format;\r
-use Date::Parse;\r
-\r
-require Exporter;\r
-\r
-@ISA = qw(Exporter);\r
-\r
-@EXPORT = qw(\r
-send_json_tags\r
-send_json_posts\r
-);\r
-\r
-my $query = '';\r
-my $last_page = 0;\r
-\r
-\r
-\r
-sub send_json_tags {\r
-       my ($sql, $sth);\r
-       \r
-       # Building up JSON structure before parsing the data:\r
-       my ($json_prefix,$json_suffix);\r
-       # limiting url_param('callback')  to a reasonable length (100): \r
-       if((defined(url_param('callback'))) && (length(url_param('callback')) < 100)){\r
-               $json_prefix = ''.url_param('callback').'({';\r
-               $json_suffix = '})';\r
-               }  elsif(url_param('raw') eq 1) {\r
-                               $json_prefix = '{';\r
-                               $json_suffix = '}';\r
-                       } else {\r
-                                       $json_prefix = 'if(typeof(Insipid) == \'undefined\') Insipid = {}; Insipid.tags = {';\r
-                                       $json_suffix = '}';\r
-                               }\r
-       #limiting tags count, only if url_param('count') is a valid integer:\r
-       my $limit ;\r
-       if (url_param('count') =~ /^[+-]?\d+$/) {\r
-               $limit = ' limit '.url_param('count') ;\r
-       }\r
-\r
-\r
-\r
-       # If the user has already chosen a tag, get the intersection list\r
-       if((url_param('tag')) && (logged_in() eq 1)) {\r
-               $sql = "select $tbl_tags.name,count(*) from $tbl_bookmarks\r
-                       inner join $tbl_bookmark_tags as bt1 on\r
-                               ($tbl_bookmarks.id = bt1.bookmark_id)\r
-                       inner join $tbl_tags on\r
-                               ($tbl_tags.id = bt1.tag_id)\r
-                       inner join $tbl_bookmark_tags as bt2 on\r
-                               ($tbl_bookmarks.id = bt2.bookmark_id)\r
-                       inner join $tbl_tags as t2 on\r
-                               (t2.id = bt2.tag_id and t2.name = ?)\r
-                       where ($tbl_tags.name != ?)\r
-                       group by $tbl_tags.name $limit";\r
-               $sth = $dbh->prepare($sql);\r
-               $sth->execute(url_param('tag'), url_param('tag'));\r
-       print $json_prefix ;\r
-       if($sth->rows ne 0) {\r
-               my $icount = 1 ;\r
-               while(my @r = $sth->fetchrow_array()) {\r
-                       json_show_tag($icount, $sth->rows, $r[0], $r[1]);\r
-                       $icount++ ;\r
-               }\r
-       }\r
-       print $json_suffix ;    \r
-       return ;\r
-       } else {\r
-\r
-       # Access_spec contains a where clause to count only public bookmarks\r
-       # if the user is not logged in\r
-       my $access_where = "";\r
-       if(logged_in() eq 0) {\r
-               $access_where = " where ($tbl_bookmarks.access_level = 1) ";\r
-       }\r
-\r
-       my $order_clause;\r
-       if($dbtype eq "Pg") {\r
-               $order_clause = "order by upper($tbl_tags.name)";\r
-       } else {\r
-               $order_clause = "order by $tbl_tags.name";\r
-       }\r
-\r
-       $sql = "select $tbl_tags.name, count(*)\r
-                  from $tbl_bookmarks\r
-                  inner join $tbl_bookmark_tags on\r
-                       ($tbl_bookmarks.id = $tbl_bookmark_tags.bookmark_id)\r
-                  inner join $tbl_tags on\r
-                       ($tbl_tags.id = $tbl_bookmark_tags.tag_id)\r
-                  $access_where\r
-                  group by $tbl_tags.name\r
-                  $order_clause \r
-                  $limit";\r
-\r
-       $sth = $dbh->prepare($sql);\r
-       $sth->execute;\r
-       print $json_prefix;\r
-       if($sth->rows ne 0) {\r
-               my $icount = 1;\r
-               while(my @r = $sth->fetchrow_array()) {\r
-                       json_show_tag($icount, $sth->rows, $r[0], $r[1]);       \r
-                       $icount++;\r
-               }\r
-       }\r
-       print $json_suffix;\r
-       return;\r
-       }\r
-}\r
-\r
-sub json_show_tag {\r
-       my($icount, $rowscount, $tag, $tagcount) = (@_);\r
-       $tag =~ s/\"/\\"/g ;\r
-       my $json_txt = '';\r
-       $json_txt = $json_txt.'"'.$tag.'":'.$tagcount;\r
-       if ($icount ne $rowscount){\r
-               $json_txt = $json_txt.',';\r
-       }\r
-       print $json_txt ;\r
-}\r
-\r
-sub send_json_posts {\r
-       \r
-       # Building up JSON structure before parsing the data:\r
-       my ($json_prefix,$json_suffix);\r
-       # limiting url_param('callback')  to a reasonable length: \r
-       if((defined(url_param('callback'))) && (length(url_param('callback')) < 100)){\r
-               $json_prefix = ''.url_param('callback').'([';\r
-               $json_suffix = '])';\r
-               }  elsif(url_param('raw') eq 1) {\r
-                               $json_prefix = '[';\r
-                               $json_suffix = ']';\r
-                       } else {\r
-                                       $json_prefix = 'if(typeof(Insipid) == \'undefined\') Insipid = {}; Insipid.posts = [';\r
-                                       $json_suffix = ']';\r
-                               }\r
-       #limiting posts count to  url_param('count') , setting hard limit to 100 and  default limit to 50 :\r
-       my $limit ;\r
-       if ((url_param('count') =~ /^[+-]?\d+$/) && (url_param('count') < 101)) {\r
-               $limit = url_param('count') ;\r
-       } else {\r
-               $limit = 50 ;\r
-       }\r
-       \r
-       my ($subquery, $sql, $sth, @parms, @wheres, @hr);\r
-\r
-       # this first query will be used to select from a set, like when a user\r
-       # drills in on a specific tag or to get a smaller view of the entire\r
-       # dataset (for paging purposes).\r
-\r
-       # MySQL and postgres have slightly different syntax here...\r
-       if ($dbtype eq 'mysql') {\r
-           $sql = "select $tbl_bookmarks.id from $tbl_bookmarks";\r
-       } elsif ($dbtype eq 'Pg') {\r
-           $sql = "select $tbl_bookmarks.id, $tbl_bookmarks.date\r
-               from $tbl_bookmarks";\r
-       }\r
-\r
-       # Limit to tags\r
-       if(defined(url_param('tag'))) {\r
-       # Join the tag tables only when necessary\r
-\r
-               if(url_param('tag') =~ / /) {\r
-                       my @tags = split(/ /, url_param('tag'));\r
-                       my $icount = 1;\r
-\r
-                       foreach(@tags) {\r
-                               push(@parms, $_);\r
-                               $sql = "$sql inner join $tbl_bookmark_tags\r
-                                               as bt$icount on\r
-                                         ($tbl_bookmarks.id =\r
-                                               bt$icount.bookmark_id)\r
-                                       inner join $tbl_tags as t$icount on\r
-                                          (t$icount.id = bt$icount.tag_id\r
-                                               and t$icount.name = ?) ";\r
-                               $icount++;\r
-                       }\r
-               } else {\r
-                       $sql = "$sql\r
-                               left join $tbl_bookmark_tags on\r
-                                 ($tbl_bookmarks.id =\r
-                                       $tbl_bookmark_tags.bookmark_id)\r
-                               inner join $tbl_tags on\r
-                                 ($tbl_tags.id = $tbl_bookmark_tags.tag_id)\r
-                                 where ($tbl_tags.name = ?)";\r
-                       push(@parms, url_param('tag'));\r
-               }\r
-\r
-       }\r
-\r
-       # Search \r
-       # ?q=\r
-       $query = url_param('q');\r
-       if($query ne "") {\r
-               if((get_option("public_searches") eq "yes") || (logged_in() eq 1)) {\r
-                       my $sparm = $query;\r
-                       if(length($sparm) > 2) {\r
-                               $sql = "$sql where ($tbl_bookmarks.title like ?)";\r
-                               $sparm =~ s/\%//;\r
-                               $sparm = "\%$sparm\%";\r
-                               push(@parms, $sparm);\r
-                       }\r
-               }\r
-       }\r
-\r
-       # order\r
-       $sql = "$sql order by $tbl_bookmarks.date desc";\r
-\r
-       # paging functionality\r
-       $sql = "$sql limit $limit";\r
-       \r
-       \r
-       if(url_param('page')) {\r
-           my $offset = ((url_param('page') - 1) * $limit);\r
-           $sql = "$sql offset $offset";\r
-       }\r
-\r
-       $sth = $dbh->prepare($sql);\r
-       $sth->execute(@parms);\r
-\r
-       $subquery = "";\r
-       if($sth->rows > 0) {\r
-               if($sth->rows ne $limit) { $last_page = 1; }\r
-\r
-               $subquery = " $tbl_bookmarks.id in (";\r
-\r
-               while(@hr = $sth->fetchrow_array) {\r
-                       $subquery = $subquery . "$hr[0],";\r
-               }\r
-               chop($subquery); # Strip off the last delimiter\r
-\r
-               $subquery = $subquery . ")";\r
-       } else {\r
-               # no bookmarks found:\r
-               ###################\r
-               print $json_prefix ;\r
-               print $json_suffix ;\r
-               ###################\r
-               return;\r
-       }\r
-\r
-       @parms = ();\r
-       @wheres = ();\r
-\r
-        $sql = "select\r
-                 $tbl_bookmarks.id,\r
-                 $tbl_bookmarks.title,\r
-                 $tbl_bookmarks.description,\r
-                 $tbl_bookmarks.access_level,\r
-                 $tbl_bookmarks.url,\r
-                 $tbl_tags.name,\r
-                 $tbl_bookmarks.date,\r
-                 $tbl_pagecache.date as cache_date,\r
-                 $tbl_bookmarks.md5\r
-               from $tbl_bookmarks\r
-               left join $tbl_bookmark_tags on\r
-                 ($tbl_bookmarks.id = $tbl_bookmark_tags.bookmark_id)\r
-               left join $tbl_tags on\r
-                 ($tbl_tags.id = $tbl_bookmark_tags.tag_id)\r
-               left join $tbl_pagecache on\r
-                 ($tbl_bookmarks.md5 = $tbl_pagecache.md5)";\r
-\r
-       # Don't show private marks for non-logged in users\r
-       if(logged_in() eq 0) {\r
-         push(@wheres, "$tbl_bookmarks.access_level");\r
-         push(@parms, "1");\r
-       }\r
-\r
-       my $max = @wheres;\r
-       if($max ne 0) {\r
-         $sql = "$sql where (";\r
-         my $count = 1;\r
-\r
-         foreach (@wheres) {\r
-           $sql = "$sql $_ = ?";\r
-           if($count < $max) {\r
-             $sql = "$sql and ";\r
-           }\r
-           $count++;\r
-         }\r
-\r
-         $sql = "$sql )";\r
-         if($subquery ne "") { $sql = "$sql and $subquery"; }\r
-       } else {\r
-         if($subquery ne "") { $sql = "$sql where $subquery "; }\r
-       }\r
-\r
-    # append sort order.\r
-       $sql = "$sql order by $tbl_bookmarks.date desc";\r
-\r
-       $sth = $dbh->prepare($sql);\r
-        $sth->execute(@parms);\r
-\r
-       my %last;\r
-       $last{id} = -1;\r
-       \r
-       \r
-       ###################\r
-       print $json_prefix ;\r
-       ###################\r
-       \r
-       while(@hr = $sth->fetchrow_array) {\r
-               if($last{id} eq -1) {\r
-                 $last{id} = $hr[0];\r
-                 $last{title} = $hr[1];\r
-                 $last{description} = $hr[2];\r
-                 $last{access_level} = $hr[3];\r
-                 $last{url} = $hr[4];\r
-                 $last{tags} = "";\r
-                 $last{timestamp} = $hr[6];\r
-               }\r
-\r
-               if($hr[0] ne $last{id}) {\r
-                 # the id changed, so show the last mark.\r
-                 json_show_post(0,$last{id}, $last{title}, $last{description}, $last{access_level}, $last{url}, $last{tags}, $last{timestamp});\r
-\r
-                 # Swap the new one in.\r
-                 $last{id} = $hr[0];\r
-                 $last{title} = $hr[1];\r
-                 $last{description} = $hr[2];\r
-                 $last{access_level} = $hr[3];\r
-                 $last{url} = $hr[4];\r
-                 $last{tags} = $hr[5];\r
-                 $last{timestamp} = $hr[6];\r
-               } else {\r
-                 # Add tag to the current bookmark\r
-                 if(defined($hr[5])) {\r
-                   $last{tags} = "$last{tags} $hr[5]";\r
-                 }\r
-               }\r
-       }\r
-\r
-       if($last{id} ne -1) {\r
-               json_show_post(1,$last{id}, $last{title}, $last{description}, $last{access_level}, $last{url}, $last{tags}, $last{timestamp});\r
-       }\r
-\r
-       ###################\r
-       print $json_suffix ;\r
-       ###################\r
-}\r
-\r
-\r
-sub json_show_post {\r
-       my($last_mark, $id, $title, $description, $access_level, $url,\r
-               $tags, $timestamp) = (@_);\r
-       $title =~ s/\"/\\"/g ;\r
-       $description =~ s/\"/\\"/g ;\r
-       $tags =~ s/\"/\\"/g ;\r
-       my $json_txt = '{';\r
-       \r
-       if($access_level eq 0) {\r
-               $json_txt = $json_txt.'"u":"'.$site_url.'/insipid.cgi?go='.$id.'",';\r
-               $json_txt = $json_txt.'"d":"'.$title.'",';\r
-       } else {\r
-               $json_txt = $json_txt.'"u":"'.$url.'",';\r
-               $json_txt = $json_txt.'"d":"'.$title.'",';\r
-       }\r
-\r
-       if($description){\r
-               $json_txt = $json_txt.'"n":"'.$description.'",';\r
-       }\r
-       \r
-       my $timestr = '';\r
-       if(logged_in() eq 1) {\r
-               $timestr = time2str('%Y-%m-%d %T EST', $timestamp, 'EST');\r
-       } else {\r
-               $timestr = time2str('%Y-%m-%d', $timestamp, 'EST');\r
-       }\r
-\r
-       $json_txt = $json_txt.'"dt":"'.$timestr.'"';\r
-\r
-       if($tags) {\r
-               $json_txt = $json_txt.',"t":[';\r
-               my $cur;\r
-               my @tags = split(/\ /, $tags);\r
-               my $icount = 1 ;\r
-               foreach my $tag (@tags) {\r
-                       if($tag){\r
-                               $json_txt = $json_txt.'"'.$tag.'"';\r
-                                       if ($icount ne @tags){\r
-                                               $json_txt = $json_txt.',';\r
-                                       }\r
-                       }\r
-               $icount++ ;\r
-               }\r
-               $json_txt = $json_txt.']';  \r
-       }\r
-       \r
-       $json_txt = $json_txt.'}';\r
-       \r
-       if($last_mark ne 1){\r
-               $json_txt = $json_txt.','; \r
-       }\r
-       \r
-       print $json_txt ;\r
-}\r
-1;\r
-__END__\r
+#!/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__
index bce532929d3745751cdb96cb4079ec5b6c3e8724..2d85217ee5c64f16e76f681f0aa9720962bf28f8 100755 (executable)
@@ -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'))) {
index 6463aaf0b40225c8059e7f2789db7989f14720d4..4c3c293ab512aad2fccd91af96fe4aa768e639a2 100755 (executable)
-#!/usr/bin/perl\r
-#\r
-# Copyright (C) 2008 Luke Reeves\r
-#\r
-# This program is free software; you can redistribute it and/or modify\r
-# it under the terms of the GNU General Public License as published by\r
-# the Free Software Foundation; either version 2 of the License, or\r
-# (at your option) any later version.\r
-#\r
-# This program is distributed in the hope that it will be useful,\r
-# but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-# GNU General Public License for more details.\r
-#\r
-# You should have received a copy of the GNU General Public License\r
-# along with this program; if not, write to the Free Software\r
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307\r
-# USA\r
-#\r
-\r
-package Insipid::Schemas;\r
-\r
-use strict;\r
-use warnings;\r
-use Insipid::Config;\r
-\r
-use vars qw(\r
-@ISA\r
-@EXPORT\r
-$createMySQL\r
-$createPostgres\r
-);\r
-\r
-use Exporter;\r
-\r
-@ISA = qw(Exporter);\r
-\r
-@EXPORT = qw(\r
-$version\r
-$createMySQL\r
-$createPostgres\r
-);\r
-\r
-# Insipid will check the database version number on each initialization of\r
-# the options table (every hit essentially) and upgrade the tables if there's\r
-# any mismatch.\r
-our $version = "0.9.20";\r
-\r
-our $createPostgres = <<CPOSTGRES;\r
-CREATE TABLE $tbl_authentication (\r
-       session_id CHAR(32) NOT NULL UNIQUE,\r
-       create_time INT,\r
-       PRIMARY KEY(session_id)\r
-);\r
-\r
-CREATE TABLE $tbl_bookmarks (\r
-       id SERIAL,\r
-       url TEXT NOT NULL,\r
-       md5 CHAR(32) NOT NULL UNIQUE,\r
-       date INT NOT NULL DEFAULT 0,\r
-       title VARCHAR(255) NOT NULL,\r
-       description TEXT NOT NULL,\r
-       access_level INT NOT NULL DEFAULT 0,\r
-       PRIMARY KEY(id)\r
-);\r
-\r
-\r
-CREATE TABLE $tbl_tags (\r
-       id SERIAL,\r
-       name VARCHAR(255) NOT NULL UNIQUE,\r
-       PRIMARY KEY(id),\r
-       UNIQUE(name)\r
-);\r
-\r
-CREATE TABLE $tbl_bookmark_tags (\r
-       bookmark_id SERIAL,\r
-       tag_id INT NOT NULL,\r
-       PRIMARY KEY(bookmark_id, tag_id)\r
-);\r
-\r
-CREATE TABLE $tbl_options (\r
-        name VARCHAR(255) NOT NULL UNIQUE,\r
-        description TEXT NOT NULL,\r
-        value TEXT NOT NULL,\r
-        PRIMARY KEY(name)\r
-);\r
-\r
-CREATE TABLE $tbl_pagecache (\r
-        md5 CHAR(32) NOT NULL DEFAULT '',\r
-        url TEXT NOT NULL DEFAULT '',\r
-        content_type VARCHAR(50),\r
-        content_length INT NOT NULL DEFAULT 0,\r
-        content bytea,\r
-        date INT NOT NULL DEFAULT 0,\r
-        PRIMARY KEY(md5)\r
-);\r
-\r
-CREATE TABLE $tbl_pagecache_references (\r
-        md5_parent CHAR(32) NOT NULL DEFAULT '',\r
-        md5_child CHAR(32) NOT NULL DEFAULT '',\r
-        PRIMARY KEY(md5_parent, md5_child)\r
-);\r
-\r
-INSERT INTO $tbl_options VALUES (\r
-  'feed_name',\r
-  'The title of your feed (e.g. My Bookmarks)',\r
-  'Bookmarks'\r
-);\r
-\r
-INSERT INTO $tbl_options VALUES (\r
-  'site_name',\r
-  'The title of the main page (e.g. My Bookmarks)',\r
-  'My Bookmarks'\r
-);\r
-\r
-\r
-INSERT INTO $tbl_options VALUES (\r
-  'public_searches',\r
-  'Allow public searches - when set to yes, any visitor can search your bookmarks.',\r
-  'no'\r
-);\r
-\r
-INSERT INTO $tbl_options VALUES(\r
-  'version',\r
-  'Internal Insipid version number',\r
-  '$version'\r
-);\r
-\r
-INSERT INTO $tbl_options VALUES(\r
-  'proxy_host',\r
-  'The proxy server (if any) to use when making page snapshots.',\r
-  ''\r
-);\r
-\r
-INSERT INTO $tbl_options VALUES(\r
-  'proxy_port',\r
-  'Your proxy port number.',\r
-  '3128'\r
-);\r
-\r
-INSERT INTO $tbl_options VALUES(\r
-  'use_rewrite',\r
-  'Use mod_rewrite - disable this if you do not want .htaccess-controlled URLs, or if your Apache does not have the rewrite module installed.',\r
-  'no'\r
-);\r
-\r
-CPOSTGRES\r
-\r
-\r
-our $createMySQL = <<CMYSQL;\r
-CREATE TABLE IF NOT EXISTS $tbl_authentication (\r
-       session_id CHAR(32) NOT NULL UNIQUE,\r
-       create_time INT,\r
-       PRIMARY KEY(session_id)\r
-);\r
-\r
-CREATE TABLE IF NOT EXISTS $tbl_bookmarks (\r
-       id INT AUTO_INCREMENT NOT NULL,\r
-       url TEXT NOT NULL DEFAULT '',\r
-       md5 CHAR(32) NOT NULL DEFAULT '' UNIQUE,\r
-       date INT NOT NULL DEFAULT 0,\r
-       title VARCHAR(255) NOT NULL DEFAULT '',\r
-       description TEXT NOT NULL DEFAULT '',\r
-       access_level INT NOT NULL DEFAULT 0,\r
-       PRIMARY KEY(id)\r
-);\r
-\r
-\r
-CREATE TABLE IF NOT EXISTS $tbl_tags (\r
-       id INT AUTO_INCREMENT NOT NULL,\r
-       name VARCHAR(255) NOT NULL DEFAULT '' UNIQUE,\r
-       PRIMARY KEY(id)\r
-);\r
-\r
-CREATE TABLE IF NOT EXISTS $tbl_bookmark_tags (\r
-       bookmark_id INT NOT NULL,\r
-       tag_id INT NOT NULL,\r
-       PRIMARY KEY(bookmark_id, tag_id),\r
-       INDEX(bookmark_id),\r
-       INDEX(tag_id)\r
-);\r
-\r
-\r
-CREATE TABLE IF NOT EXISTS $tbl_options (\r
-        name VARCHAR(255) NOT NULL UNIQUE,\r
-        description TEXT NOT NULL DEFAULT '',\r
-        value TEXT NOT NULL DEFAULT '',\r
-        PRIMARY KEY(name)\r
-);\r
-\r
-CREATE TABLE IF NOT EXISTS $tbl_pagecache (\r
-        md5 CHAR(32) NOT NULL DEFAULT '',\r
-        url TEXT NOT NULL DEFAULT '',\r
-        content_type VARCHAR(50),\r
-        content_length INT NOT NULL DEFAULT 0,\r
-        content LONGBLOB,\r
-        date INT NOT NULL DEFAULT 0,\r
-        PRIMARY KEY(md5)\r
-);\r
-\r
-CREATE TABLE IF NOT EXISTS $tbl_pagecache_references (\r
-        md5_parent CHAR(32) NOT NULL DEFAULT '',\r
-        md5_child CHAR(32) NOT NULL DEFAULT '',\r
-        PRIMARY KEY(md5_parent, md5_child)\r
-);\r
-\r
-INSERT IGNORE INTO $tbl_options VALUES(\r
-  'feed_name',\r
-  'The title of your feed (e.g. My Bookmarks)',\r
-  'Bookmarks'\r
-);\r
-\r
-INSERT IGNORE INTO $tbl_options VALUES(\r
-  'site_name',\r
-  'The title of the main page (e.g. My Bookmarks)',\r
-  'My Bookmarks'\r
-);\r
-\r
-INSERT IGNORE INTO $tbl_options VALUES(\r
-  'public_searches',\r
-  'Allow public searches - when set to yes, any visitor can search your bookmarks.',\r
-  'no'\r
-);\r
-\r
-INSERT IGNORE INTO $tbl_options VALUES(\r
-  'proxy_host',\r
-  'The proxy server (if any) to use when making page snapshots.',\r
-  ''\r
-);\r
-\r
-\r
-INSERT IGNORE INTO $tbl_options VALUES(\r
-  'proxy_port',\r
-  'Your proxy port number.',\r
-  '3128'\r
-);\r
-\r
-INSERT IGNORE INTO $tbl_options VALUES(\r
-  'version',\r
-  'Internal Insipid version number',\r
-  '$version'\r
-);\r
-\r
-INSERT IGNORE INTO $tbl_options VALUES(\r
-  'use_rewrite',\r
-  'Use mod_rewrite - disable this if you do not want .htaccess-controlled URLs, or if your Apache does not have the rewrite module installed.',\r
-  'no'\r
-);\r
-CMYSQL\r
-\r
-1;\r
-__END__\r
+#!/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
+);
+
+use Exporter;
+
+@ISA = qw(Exporter);
+
+@EXPORT = qw(
+$version
+$createMySQL
+);
+
+# 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 = "1.0";
+
+our $createMySQL = <<CMYSQL;
+CREATE TABLE IF NOT EXISTS $tbl_authentication (
+       session_id CHAR(32) NOT NULL UNIQUE,
+       create_time INT,
+       PRIMARY KEY(session_id)
+);
+
+CREATE TABLE IF NOT EXISTS $tbl_bookmarks (
+       id INT AUTO_INCREMENT NOT NULL,
+       url TEXT NOT NULL DEFAULT '',
+       md5 CHAR(32) NOT NULL DEFAULT '' UNIQUE,
+       date INT NOT NULL DEFAULT 0,
+       title VARCHAR(255) NOT NULL DEFAULT '',
+       description TEXT NOT NULL DEFAULT '',
+       access_level INT NOT NULL DEFAULT 0,
+       PRIMARY KEY(id)
+);
+
+
+CREATE TABLE IF NOT EXISTS $tbl_tags (
+       id INT AUTO_INCREMENT NOT NULL,
+       name VARCHAR(255) NOT NULL DEFAULT '' UNIQUE,
+       PRIMARY KEY(id)
+);
+
+CREATE TABLE IF NOT EXISTS $tbl_bookmark_tags (
+       bookmark_id INT NOT NULL,
+       tag_id INT NOT NULL,
+       PRIMARY KEY(bookmark_id, tag_id),
+       INDEX(bookmark_id),
+       INDEX(tag_id)
+);
+
+
+CREATE TABLE IF NOT EXISTS $tbl_options (
+        name VARCHAR(255) NOT NULL UNIQUE,
+        description TEXT NOT NULL DEFAULT '',
+        value TEXT NOT NULL DEFAULT '',
+        PRIMARY KEY(name)
+);
+
+CREATE TABLE IF NOT EXISTS $tbl_pagecache (
+        md5 CHAR(32) NOT NULL DEFAULT '',
+        url TEXT NOT NULL DEFAULT '',
+        content_type VARCHAR(50),
+        content_length INT NOT NULL DEFAULT 0,
+        content LONGBLOB,
+        date INT NOT NULL DEFAULT 0,
+        PRIMARY KEY(md5)
+);
+
+CREATE TABLE IF NOT EXISTS $tbl_pagecache_references (
+        md5_parent CHAR(32) NOT NULL DEFAULT '',
+        md5_child CHAR(32) NOT NULL DEFAULT '',
+        PRIMARY KEY(md5_parent, md5_child)
+);
+
+INSERT IGNORE INTO $tbl_options VALUES(
+  'feed_name',
+  'The title of your feed (e.g. My Bookmarks)',
+  'Bookmarks'
+);
+
+INSERT IGNORE INTO $tbl_options VALUES(
+  'site_name',
+  'The title of the main page (e.g. My Bookmarks)',
+  'My Bookmarks'
+);
+
+INSERT IGNORE INTO $tbl_options VALUES(
+  'public_searches',
+  'Allow public searches - when set to yes, any visitor can search your bookmarks.',
+  'no'
+);
+
+INSERT IGNORE INTO $tbl_options VALUES(
+  'proxy_host',
+  'The proxy server (if any) to use when making page snapshots.',
+  ''
+);
+
+
+INSERT IGNORE INTO $tbl_options VALUES(
+  'proxy_port',
+  'Your proxy port number.',
+  '3128'
+);
+
+INSERT IGNORE INTO $tbl_options VALUES(
+  'version',
+  'Internal Insipid version number',
+  '$version'
+);
+
+INSERT IGNORE INTO $tbl_options VALUES(
+  'use_rewrite',
+  'Use mod_rewrite - disable this if you do not want .htaccess-controlled URLs, or if your Apache does not have the rewrite module installed.',
+  'no'
+);
+CMYSQL
+
+1;
+__END__
index ea93dd4e79d8edc217dbe49df9dc2e61d577497f..74dd92fbb5d292fb97976f2bd3ee7f1ecde7a9e6 100755 (executable)
-#!/usr/bin/perl\r
-#\r
-# Copyright (C) 2008 Luke Reeves\r
-#\r
-# This program is free software; you can redistribute it and/or modify\r
-# it under the terms of the GNU General Public License as published by\r
-# the Free Software Foundation; either version 2 of the License, or\r
-# (at your option) any later version.\r
-#\r
-# This program is distributed in the hope that it will be useful,\r
-# but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-# GNU General Public License for more details.\r
-#\r
-# You should have received a copy of the GNU General Public License\r
-# along with this program; if not, write to the Free Software\r
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307\r
-# USA\r
-#\r
-\r
-package Insipid::Snapshots;\r
-\r
-use strict;\r
-use warnings;\r
-\r
-use vars qw(@ISA @EXPORT);\r
-use Insipid::Config;\r
-use Insipid::Database;\r
-use Insipid::Util;\r
-use Insipid::LinkExtractor;\r
-use Insipid::Parser;\r
-use CGI qw/:standard/;\r
-use CGI::Carp qw(fatalsToBrowser);\r
-use Date::Format;\r
-use Date::Parse;\r
-use Date::Parse;\r
-use Digest::MD5 qw(md5 md5_hex);\r
-use DBI qw/:sql_types/;;\r
-use LWP::UserAgent;\r
-use HTTP::Request;\r
-use MIME::Base64;\r
-use XML::Writer;\r
-\r
-require Exporter;\r
-\r
-\r
-@ISA = qw(Exporter);\r
-\r
-@EXPORT = qw(\r
-show_snapshots\r
-do_snapshot\r
-delete_snapshot\r
-export_snapshots\r
-show_snapshot\r
-fetch_related\r
-parsepage\r
-fetch_url\r
-);\r
-\r
-my $ua = LWP::UserAgent->new(timeout=>30);\r
-if(get_option('proxy_host') ne '') {\r
-       my $proxy_host = get_option('proxy_host');\r
-       my $proxy_port = get_option('proxy_port');\r
-       $ua->proxy(['http', 'ftp'], "http://$proxy_host:$proxy_port/");\r
-}\r
-       \r
-\r
-my $referer = "";\r
-\r
-sub export_snapshots {\r
-       my ($writer) = (@_);\r
-       my ($sql, $sth, @rs);\r
-\r
-       # Export the objects\r
-       $writer->startTag('objects');\r
-       $sql = "select md5, url, content_type, content_length, date, content\r
-               from $tbl_pagecache";\r
-       $sth = $dbh->prepare($sql);\r
-       $sth->execute();\r
-       \r
-       while(@rs = $sth->fetchrow_array()) {\r
-               $writer->startTag('object',\r
-                               'md5' => $rs[0],\r
-                               'url' => $rs[1],\r
-                               'type' => $rs[2],\r
-                               'length' => $rs[3],\r
-                               'date' => $rs[4]\r
-                               );\r
-               $writer->characters(encode_base64($rs[5]));\r
-               $writer->endTag("object");\r
-       }\r
-       $writer->endTag('objects');     \r
-\r
-       # Export the relationships \r
-       $writer->startTag('relationships');\r
-\r
-       $sql = "select md5_parent, md5_child from $tbl_pagecache_references";\r
-       $sth = $dbh->prepare($sql);\r
-       $sth->execute();\r
-\r
-       while(@rs = $sth->fetchrow_array()) {\r
-               $writer->startTag("relationship",\r
-                               "parent" => $rs[0],\r
-                               "child" => $rs[1]);\r
-               $writer->endTag("relationship");\r
-       }\r
-       \r
-       $writer->endTag("relationships");\r
-\r
-}\r
-\r
-# TODO: Make the insert_snapshot callable by this and the import method.\r
-sub fetch_url {\r
-       my ($url, $roverride) = (@_);\r
-\r
-       # TODO: No.\r
-       if(defined($roverride)) { $referer = $roverride; }\r
-       my $md5 = md5_hex($url);\r
-\r
-       my $req = HTTP::Request->new(GET => $url) or die "Can't fetch page: $!\n";\r
-\r
-       if($referer ne '') { $req->header( referer => $referer ); }\r
-\r
-       my $res = $ua->request($req);\r
-\r
-       if($res->is_success) {\r
-               my $content = $res->content;\r
-\r
-               # Shove the unparsed page into the cache.\r
-               my $sql = "insert into $tbl_pagecache(md5, url, content_type, \r
-                               content_length, content, date)\r
-                       values ( ? , ? , ? , ? , ? , ? )";\r
-\r
-               my $sth = $dbh->prepare($sql);\r
-               my $ct = $res->header('Content-Type');\r
-               if(length($ct) > 50) { $ct = substr($ct, 0, 50); }\r
-\r
-               $sth->bind_param(1, $md5);\r
-               $sth->bind_param(2, $url);\r
-               $sth->bind_param(3, $ct);\r
-               $sth->bind_param(4, length($content));\r
-\r
-               # Postgres needs escaping for the binary data.\r
-               if($dbtype eq 'Pg') {\r
-                       $sth->bind_param(5, $content, SQL_VARBINARY);\r
-               } else {\r
-                       $sth->bind_param(5, $content);\r
-               }\r
-               $sth->bind_param(6, time());\r
-               $sth->execute;\r
-\r
-               if($sth->err) {\r
-               #       print $sth->errstr;\r
-               #       print "<br />";\r
-                       return 1;                        \r
-               } else {\r
-                       if($ct =~ /text\/html/i) {\r
-                               print '<br />Parsing page... ';\r
-                               parsepage($url, $content, $ct);\r
-                               print 'done.';\r
-                       }\r
-\r
-                       return 0;\r
-               }\r
-       } else {\r
-               my $err = $res->status_line;\r
-               print "$err<br />";\r
-\r
-               return 1;\r
-       }\r
-}\r
-\r
-sub show_snapshot {\r
-       my ($md5) = (@_);\r
-       my ($sql, $sth, @row);\r
-       my %internalLinks = ();\r
-\r
-       $sql = "select content_type,content,url,date,content_length\r
-                       from $tbl_pagecache where (md5 = ?)";\r
-               \r
-       $sth = $dbh->prepare($sql);\r
-       $sth->execute($md5);\r
-       \r
-       @row = $sth->fetchrow_array;\r
-       \r
-       if(!@row) {\r
-               print 'Content-Type: text/plain\r\n\r\n';\r
-               print "Can't find cached item \"$md5\"";\r
-               return;\r
-       }\r
-\r
-\r
-       # Check for IMS request.\r
-       my $ims = http('If-Modified-Since');\r
-       if($ims) { \r
-\r
-               my $t = str2time($ims);\r
-\r
-               if($row[3] <= $t) {\r
-                       # Return a 304 not modified.\r
-                       print 'Status: 304 Not Modified\r\n';\r
-                       return;\r
-               }\r
-       }\r
-       \r
-       my $dt = ims_time($row[3]);\r
-       print "Last-Modified: $dt\r\n";\r
-       print "Content-Type: $row[0]\r\n";\r
-\r
-       if($row[0] =~ /text\/html/i) {\r
-               # Now we get a list of URLs that can be redirected to our \r
-               # local snapshot cache. We'll use that to build a hash of \r
-               # URL->MD5 values and match outputted links against that.\r
-               my ($resql, $resth, @rerow);\r
-               $resql = "select $tbl_pagecache_references.md5_child,\r
-                       $tbl_pagecache.url\r
-                       from $tbl_pagecache_references\r
-                       inner join $tbl_pagecache on \r
-                               ($tbl_pagecache_references.md5_child = \r
-                                       $tbl_pagecache.md5)\r
-                       where (md5_parent = ?)";\r
-               $resth = $dbh->prepare($resql);\r
-               $resth->execute($md5);\r
-\r
-               while(@rerow = $resth->fetchrow_array()) {\r
-                       $internalLinks{$rerow[1]} = $rerow[0];\r
-               }\r
-\r
-               print "\r\n";\r
-               my $p = Insipid::Parser->new($row[2], undef);\r
-               $p->setSnapshotMap(\%internalLinks);\r
-               \r
-               if($row[0] =~ /utf/i) {\r
-                       $p->utf8_mode(1);\r
-               }\r
-               $p->parse($row[1]);\r
-       } else {\r
-               print "Content-Length: $row[4]\r\n";\r
-               print "\r\n";\r
-               print $row[1];\r
-       }\r
-\r
-       exit;\r
-}\r
-\r
-sub show_details {\r
-       my ($md5) = @_;\r
-       my ($sth, $sql);\r
-       \r
-       $sql = "select $tbl_bookmarks.title from $tbl_bookmarks\r
-               where ($tbl_bookmarks.md5 = ?)";\r
-       $sth = $dbh->prepare($sql);\r
-       $sth->execute($md5);\r
-       my @row = $sth->fetchrow_array();\r
-\r
-       print '<h3>Cache Details for "';\r
-       print escapeHTML($row[0]);\r
-       print '"</h3>';\r
-       print '<br /><center><table cellpadding="5"><tr><th>View</th><th>URL</th><th>';\r
-       print 'Type</th><th>Size</th><th>Ref Count</th></tr>';\r
-\r
-       $sql = "select $tbl_pagecache.md5, $tbl_pagecache.url, \r
-                       $tbl_pagecache.content_type,\r
-                       $tbl_pagecache.content_length, \r
-                       pg2.md5_parent, count(*)\r
-                       from $tbl_pagecache_references\r
-                       inner join $tbl_pagecache on \r
-                               ($tbl_pagecache_references.md5_child = \r
-                                       $tbl_pagecache.md5)\r
-                       left join $tbl_pagecache_references as pg2 on \r
-                               (pg2.md5_child = $tbl_pagecache.md5)\r
-                       where ($tbl_pagecache_references.md5_parent = ?)\r
-                       group by $tbl_pagecache.md5, $tbl_pagecache.url, \r
-                               $tbl_pagecache.content_type, pg2.md5_parent, \r
-                               $tbl_pagecache.content_length, pg2.md5_child\r
-                       order by $tbl_pagecache.url";\r
-                               \r
-       $sth = $dbh->prepare($sql);\r
-       $sth->execute($md5);\r
-\r
-       while(my @rs = $sth->fetchrow_array()) {\r
-               print '<tr><td>';\r
-               my $ss = "$snapshot_url$rs[0]";\r
-               \r
-               print "<a href=\"$rs[1]\">live</a>/<a href=\"$ss\">snapshot</a>";\r
-               print '</td><td>';\r
-               print $rs[1];\r
-               print '</td><td>';\r
-               print $rs[2];\r
-               print '</td><td>';\r
-               print $rs[3];\r
-               print '</td><td>';\r
-               print $rs[5];\r
-               print '</td></tr>';\r
-       }\r
-\r
-       print '</table></center>';\r
-}\r
-\r
-#\r
-# Show a nice menu of the users snapshots.\r
-#\r
-sub show_snapshots {\r
-\r
-       # If a snapshot was asked to be deleted\r
-       if(defined(param('delete'))) {\r
-               delete_snapshot(param('delete'));\r
-       }\r
-\r
-       if(defined(param('md5'))) {\r
-               show_details(param('md5'));\r
-               return;\r
-       }\r
-\r
-       my $tcount = 0;\r
-       my $tsize = 0;\r
-       \r
-       my $sql = "select $tbl_pagecache.md5, $tbl_bookmarks.title, \r
-                               $tbl_pagecache.date,\r
-                               $tbl_pagecache.content_length + \r
-                               coalesce(sum(p2.content_length), 0), \r
-                               count(*) - 1, $tbl_bookmarks.access_level\r
-                       from $tbl_pagecache \r
-                       inner join $tbl_bookmarks on \r
-                               ($tbl_bookmarks.md5 = $tbl_pagecache.md5)\r
-                       left join $tbl_pagecache_references on \r
-                          ($tbl_pagecache.md5 = $tbl_pagecache_references.md5_parent) \r
-                       left join $tbl_pagecache as p2 on\r
-                          (p2.md5 = $tbl_pagecache_references.md5_child)\r
-                       group by \r
-                               $tbl_bookmarks.access_level,\r
-                               $tbl_pagecache.md5, $tbl_bookmarks.title,\r
-                               $tbl_pagecache.date, $tbl_pagecache.content_length\r
-                       order by $tbl_pagecache.date desc";\r
-       my $sth = $dbh->prepare($sql);\r
-       $sth->execute;\r
-       \r
-       print '<br /><center><table cellpadding=\"5\"><tr><th>Page</th><th>';\r
-       print 'Date</th><th>Size</th><th>Objects</th><th>Functions</th></tr>';\r
-\r
-       my $count = 0;\r
-\r
-       while(my @r = $sth->fetchrow_array) {\r
-\r
-               $count++;\r
-               \r
-               my $color;\r
-               if(($count % 2) eq 1) {\r
-                       $color = ' bgcolor="#EEEEEE" ';\r
-               } else {\r
-                       $color = '';\r
-               }\r
-               \r
-               print "<tr $color>";\r
-               print '<td>';\r
-               \r
-               print "<a href=\"$snapshot_url$r[0]\">";\r
-               if($r[5] eq 0) { print '<i>'; }\r
-               print $r[1];\r
-               if($r[5] eq 0) { print '</i>'; }\r
-               print '</a></td>';\r
-               my $timestr = time2str('%Y-%m-%d', $r[2], 'EST');\r
-               my $count = $r[4] + 1; $tcount += $count;\r
-               $tsize += $r[3];\r
-               print "<td align=\"center\">$timestr</td>";\r
-               print "<td align=\"center\">$r[3]</td>";\r
-\r
-               my $link = "$site_url/insipid.cgi?op=snapshots&md5=$r[0]";\r
-\r
-               if($count ne 1) {\r
-                       print "<td align=\"center\"><a href=\"$link\">$count</a></td>";\r
-               } else {\r
-                       print "<td align=\"center\">$count</td>";\r
-               }\r
-               \r
-               print '<td>';\r
-               print "<a href=\"insipid.cgi?op=snapshots&delete=$r[0]\">delete</a>,";\r
-               print " <a href=\"insipid.cgi?op=fetchrelated&id=$r[0]\">";\r
-               print "fetch linked objects</a></td>";\r
-               print '</tr>';\r
-       }\r
-\r
-       print '<tr><td><b>Total</b></td><td>&nbsp;</td>';\r
-       print "<td align=\"center\"><b>$tsize</b></td>";\r
-       print "<td align=\"center\"><b>$tcount</b></td><td>&nbsp;</td></tr>";\r
-       \r
-       print "</table></center>";\r
-}\r
-\r
-# This fetches all linked-to objects (specifically images for now)\r
-# for a cached page.\r
-sub fetch_related {\r
-       my ($md5) = (@_);\r
-\r
-       my $sql = "select content, url\r
-               from $tbl_pagecache where (md5 = ?)";\r
-       my $sth = $dbh->prepare($sql);\r
-       $sth->execute($md5);\r
-\r
-       my @r = $sth->fetchrow_array();\r
-\r
-       my $p = Insipid::LinkExtractor->new($r[1]);\r
-       $p->parse($r[0]);\r
-\r
-}\r
-\r
-# Deletes a snapshot and all orphan cache children, taking into\r
-# account the fact that items can be shared across cached pages.\r
-#\r
-# This is horribly expensive, and someday I'll replace it with\r
-# a much nicer function.\r
-sub delete_snapshot {\r
-       my ($md5) = (@_);\r
-       \r
-       # The snapshot\r
-       my $sql = "delete from $tbl_pagecache where (md5 = ?)";\r
-       my $delstatement = $dbh->prepare($sql);\r
-       $delstatement->execute($md5);\r
-\r
-       # References\r
-       $sql = "delete from $tbl_pagecache_references where (md5_parent = ?)";\r
-       my $sth = $dbh->prepare($sql);\r
-       $sth->execute($md5);\r
-       \r
-       # Orpans - blow away any md5s in the pagecache table that aren't \r
-       # referenced as a child in the references table. First, get a list\r
-       # of valid MD5s.\r
-       $sql = "select distinct md5_child from $tbl_pagecache_references";\r
-       $sth = $dbh->prepare($sql);\r
-       $sth->execute();\r
-\r
-       my $subquery = '';\r
-       while(my @r = $sth->fetchrow_array) {\r
-               if($subquery ne '') { $subquery = $subquery . ','; }\r
-               $subquery = "$subquery '$r[0]'";\r
-       }\r
-       \r
-       $sql = "select distinct md5_parent from $tbl_pagecache_references";\r
-       $sth = $dbh->prepare($sql);\r
-       $sth->execute();\r
-       while(my @r = $sth->fetchrow_array) {\r
-               if($subquery ne '') { $subquery = $subquery . ','; }\r
-               $subquery = "$subquery '$r[0]'";\r
-       }\r
-\r
-       if($subquery eq '') {\r
-               $sql = "delete from $tbl_pagecache;";\r
-       } else {\r
-               $sql = "delete from $tbl_pagecache where md5 not in ($subquery)";\r
-       }\r
-       \r
-       $sth = $dbh->prepare($sql);\r
-       $sth->execute();\r
-}\r
-\r
-sub do_snapshot {\r
-       # Save the page.\r
-       print '<br /><br />';\r
-       \r
-       my ($bookmark_id) = (@_);\r
-       my $sql = "select url,md5,title from $tbl_bookmarks where (id = ?)";\r
-        my $sth = $dbh->prepare($sql);\r
-       $sth->execute($bookmark_id);\r
-       my @row = $sth->fetchrow_array;\r
-\r
-       if(@row) {\r
-               print "<p>Fetching \"<b>$row[2]</b>\"...</p>\n";\r
-               $referer = $row[0];\r
-               fetch_url(@row);        \r
-       } else {\r
-               die "Couldn't find the row for id $bookmark_id!";\r
-       }\r
-}\r
-\r
-sub parsepage {\r
-       my ($url, $content, $content_type) = (@_);\r
-\r
-       my $p = Insipid::Parser->new($url, \&fetch_url);\r
-       if($content_type =~ /utf/i) { \r
-               $p->utf8_mode(1);\r
-       }\r
-\r
-       $p->parse($content);\r
-}\r
-\r
-1;\r
-__END__\r
+#!/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 "<br />";
+                       return 1;                        
+               } else {
+                       if($ct =~ /text\/html/i) {
+                               print '<br />Parsing page... ';
+                               parsepage($url, $content, $ct);
+                               print 'done.';
+                       }
+
+                       return 0;
+               }
+       } else {
+               my $err = $res->status_line;
+               print "$err<br />";
+
+               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 '<h3>Cache Details for "';
+       print escapeHTML($row[0]);
+       print '"</h3>';
+       print '<br /><center><table cellpadding="5"><tr><th>View</th><th>URL</th><th>';
+       print 'Type</th><th>Size</th><th>Ref Count</th></tr>';
+
+       $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 '<tr><td>';
+               my $ss = "$snapshot_url$rs[0]";
+               
+               print "<a href=\"$rs[1]\">live</a>/<a href=\"$ss\">snapshot</a>";
+               print '</td><td>';
+               print $rs[1];
+               print '</td><td>';
+               print $rs[2];
+               print '</td><td>';
+               print $rs[3];
+               print '</td><td>';
+               print $rs[5];
+               print '</td></tr>';
+       }
+
+       print '</table></center>';
+}
+
+#
+# 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 '<br /><center><table cellpadding=\"5\"><tr><th>Page</th><th>';
+       print 'Date</th><th>Size</th><th>Objects</th><th>Functions</th></tr>';
+
+       my $count = 0;
+
+       while(my @r = $sth->fetchrow_array) {
+
+               $count++;
+               
+               my $color;
+               if(($count % 2) eq 1) {
+                       $color = ' bgcolor="#EEEEEE" ';
+               } else {
+                       $color = '';
+               }
+               
+               print "<tr $color>";
+               print '<td>';
+               
+               print "<a href=\"$snapshot_url$r[0]\">";
+               if($r[5] eq 0) { print '<i>'; }
+               print $r[1];
+               if($r[5] eq 0) { print '</i>'; }
+               print '</a></td>';
+               my $timestr = time2str('%Y-%m-%d', $r[2], 'EST');
+               my $count = $r[4] + 1; $tcount += $count;
+               $tsize += $r[3];
+               print "<td align=\"center\">$timestr</td>";
+               print "<td align=\"center\">$r[3]</td>";
+
+               my $link = "$site_url/insipid.cgi?op=snapshots&md5=$r[0]";
+
+               if($count ne 1) {
+                       print "<td align=\"center\"><a href=\"$link\">$count</a></td>";
+               } else {
+                       print "<td align=\"center\">$count</td>";
+               }
+               
+               print '<td>';
+               print "<a href=\"insipid.cgi?op=snapshots&delete=$r[0]\">delete</a>,";
+               print " <a href=\"insipid.cgi?op=fetchrelated&id=$r[0]\">";
+               print "fetch linked objects</a></td>";
+               print '</tr>';
+       }
+
+       print '<tr><td><b>Total</b></td><td>&nbsp;</td>';
+       print "<td align=\"center\"><b>$tsize</b></td>";
+       print "<td align=\"center\"><b>$tcount</b></td><td>&nbsp;</td></tr>";
+       
+       print "</table></center>";
+}
+
+# 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 '<br /><br />';
+       
+       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 "<p>Fetching \"<b>$row[2]</b>\"...</p>\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__
index 4844a150b9917994d2ccfb4690ecb24c0ec30548..fae6374927e211421fe4c6f5f9b06eeb39bb9d85 100755 (executable)
@@ -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