summaryrefslogtreecommitdiff
path: root/bin
diff options
context:
space:
mode:
authorJules Laplace <carbon@melanarchy.org>2013-08-02 17:14:26 -0500
committerJules Laplace <carbon@melanarchy.org>2013-08-02 17:14:26 -0500
commit79670053c7247d3a49b607960efd284e93f057e5 (patch)
tree9617f6eefa38b2686ae409bf75cc27a340444eda /bin
parentc53827d5d044ae5ca7ebb27acb404b7a8988918e (diff)
install.pl
Diffstat (limited to 'bin')
-rwxr-xr-xbin/change-password.pl38
-rwxr-xr-xbin/flushrms.pl31
-rwxr-xr-xbin/flushzips.pl54
-rwxr-xr-xbin/keyword-export.pl156
-rwxr-xr-xbin/keyword-import.pl252
-rw-r--r--bin/localbucky.pm62
-rw-r--r--bin/participation_matrix.pl35
-rwxr-xr-xbin/populate-avatars.pl26
-rwxr-xr-xbin/populate-thumbs.pl48
-rwxr-xr-xbin/username-export.pl165
-rwxr-xr-xbin/whenis.pl7
11 files changed, 874 insertions, 0 deletions
diff --git a/bin/change-password.pl b/bin/change-password.pl
new file mode 100755
index 0000000..0b82bea
--- /dev/null
+++ b/bin/change-password.pl
@@ -0,0 +1,38 @@
+#!/usr/bin/perl
+
+BEGIN
+ {
+ our $BUCKY = "/cgi-bin/bucky";
+ our $BUCKY_DB = "bucky";
+ our $BUCKY_DB_CNF = "/var/www/vhosts/carbonpictures.com/.bucky.cnf";
+ }
+
+use lib "/var/www/vhosts/carbonpictures.com/bucky/lib";
+use Bucky1;
+
+our $dbh = DBI->connect ($dsn);
+#our $DEBUG = 1;
+
+my ($user, $pw) = @ARGV;
+
+do_password_reset($user, $pw, $pw);
+
+$dbh->disconnect();
+
+sub do_password_reset
+ {
+ my ($user, $pw1, $pw2) = @_;
+ if (length($pw1) && length($pw2))
+ {
+ if ($pw1 eq $pw2)
+ {
+ update_password($user, crypt($pw1,lc($user)));
+ print qq(password changed for $user<br>\n);
+ }
+ else
+ {
+ print "passwords don't match!<br>\n";
+ }
+ }
+ }
+
diff --git a/bin/flushrms.pl b/bin/flushrms.pl
new file mode 100755
index 0000000..058b582
--- /dev/null
+++ b/bin/flushrms.pl
@@ -0,0 +1,31 @@
+#!/usr/bin/perl
+
+use localbucky;
+use lib "/var/www/vhosts/carbonpictures.com/bucky/lib";
+use Bucky1;
+
+$dbh = DBI->connect ("DBI:mysql:$BUCKY_DB:localhost;mysql_read_default_file=$BUCKY_DB_CNF");
+
+# $DEBUG = 1;
+
+$threads = get_threads();
+$fucker = "";
+$max = 1;
+
+foreach $t (@$threads)
+ {
+ $fucker = add_key($fucker, $t->{id});
+ $max = $t->{id} if ($t->{id} > $max);
+ }
+
+for ($i = 32; $i <= $max; $i++)
+ {
+ if (-e "$data_path/$i" && !check_key($fucker, $i))
+ {
+ print "Deleting $i\n";
+ system("/bin/rm", "-rf", "$data_path/$i");
+ }
+ }
+
+$dbh->disconnect();
+
diff --git a/bin/flushzips.pl b/bin/flushzips.pl
new file mode 100755
index 0000000..392e782
--- /dev/null
+++ b/bin/flushzips.pl
@@ -0,0 +1,54 @@
+#!/usr/bin/perl
+
+use localbucky;
+use lib "/var/www/vhosts/carbonpictures.com/bucky/lib";
+use Bucky1;
+
+$dbh = DBI->connect ("DBI:mysql:$BUCKY_DB:localhost;mysql_read_default_file=$BUCKY_DB_CNF");
+
+#our $dbh = DBI->connect ($dsn);
+#our $DEBUG = 1;
+
+my $threads = get_threads();
+my ($zips, $zip_size) = find_all_zips($threads);
+print STDERR scalar(@$zips)." in ".hushsize($zip_size)."\n";
+foreach my $f (@$zips)
+ {
+ delete_file($f);
+ }
+$dbh->disconnect();
+
+sub find_all_zips
+ {
+ my ($threads) = @_;
+ my @zips;
+ my $zip_size = 0;
+ foreach my $t (@$threads)
+ {
+ my $files = get_files($t->{id});
+ my $zip_file = generate_zip_filename($t);
+ foreach my $f (@$files)
+ {
+ next unless $f->{filename} eq $zip_file;
+ push @zips, $f;
+ $zip_size += $f->{size};
+ }
+ }
+ return \@zips, $zip_size;
+ }
+
+sub delete_file
+ {
+ my ($f) = @_;
+ my $file_path = join "/", $data_path, $f->{thread}, $f->{filename};
+ if (! -e $file_path)
+ {
+ print STDERR "DNE: $file_path ...\n";
+ return;
+ }
+ delete_file_record($f->{id});
+ system($RM_PATH, "-f", $file_path);
+ update_thread_size($f->{thread});
+ print STDERR qq(deleted $file_path\n);
+ }
+
diff --git a/bin/keyword-export.pl b/bin/keyword-export.pl
new file mode 100755
index 0000000..4f04579
--- /dev/null
+++ b/bin/keyword-export.pl
@@ -0,0 +1,156 @@
+#!/usr/bin/perl
+
+use lib "/var/www/vhosts/carbonpictures.com/bucky/lib";
+use Bucky;
+
+$dbh = DBI->connect ($dsn);
+
+# get keyword + threads
+my $target = $ARGV[0];
+
+if ($target > 0)
+ {
+ my ($t) = get_thread($target);
+ export_thread($t);
+ }
+else
+ {
+ export_keyword($target);
+ }
+
+$dbh->disconnect();
+
+sub export_keyword
+ {
+ my ($keyword) = @_;
+
+ print "Exporting keyword $keyword\n";
+ my $kw = get_keyword($keyword);
+ if ($kw == -1)
+ { print "No such keyword: $kw\n"; quit_out(); }
+ my $threads = get_full_threads_by_keyword($keyword);
+
+ # mkdir keyword, chdir
+ mkdir ("$keyword");
+ chdir ("$keyword");
+
+ open FILE, ">keyword" or die $!;
+ foreach my $key (keys %$kw)
+ {
+ print FILE "$key:".$kw->{$key}."\n";
+ }
+ close FILE;
+
+ # foreach thread:
+ foreach my $thread (@$threads)
+ {
+ export_thread($thread);
+ }
+
+ chdir("..");
+ }
+
+sub export_thread
+ {
+ my ($thread) = @_;
+
+ # get all comments & files
+ my $comments = get_comments($thread->{id});
+ my $files = get_files($thread->{id});
+
+ mkdir ("$thread->{id}");
+ chdir ("$thread->{id}");
+
+ print "thread $thread->{id} -- $thread->{title}\n";
+ print "comments: $thread->{comments}\n";
+ print "files: $thread->{files}\n";
+
+ open THREAD, ">thread" or die $!;
+ foreach my $key (keys %$thread)
+ {
+ print THREAD "$key:".$thread->{$key}."\n";
+ }
+ print THREAD "\n";
+ close THREAD;
+
+ # cat each comment & file to text files based on id
+ foreach my $comment (keys %$comments)
+ {
+ my $c = $comments->{$comment};
+ open COMMENT, ">comment.".$c->{id} or die $!;
+ foreach my $key (keys %$c)
+ {
+ next if ($key eq "comment");
+ print COMMENT "$key:".$c->{$key}."\n";
+ }
+ print COMMENT "\n";
+ print COMMENT $c->{comment};
+ close COMMENT;
+ }
+
+ foreach my $f (@$files)
+ {
+ open FILE, ">file.".$f->{id} or die $!;
+ foreach my $key (keys %$f)
+ {
+ print FILE "$key:".$f->{$key}."\n";
+ }
+ close FILE;
+ }
+
+ if (-e "$data_path/$thread->{id}")
+ {
+ print "Copying ...\n";
+ mkdir ("data/");
+ system ("/bin/cp -r $data_path/$thread->{id}/* data/")
+ }
+
+ chdir ("..");
+ print "\n";
+ }
+
+sub get_full_threads_by_keyword
+ {
+ my ($keyword, $private) = @_;
+ my @rows;
+ my $query;
+ my @keys = qw(id title username keyword createdate lastmodified size private allowed flagged color);
+ my $rows = 0;
+
+ $keyword = $dbh->quote($keyword);
+ $query = "SELECT id,title,username,keyword,createdate,lastmodified,size,private,allowed,flagged,color FROM threads WHERE keyword=$keyword";
+ if (defined($private) && $private)
+ {
+ $query .= " AND (ISNULL(private) OR private = '')";
+ }
+
+ print $query."<br>" if ($DEBUG);
+ $sth = $dbh->prepare($query);
+ $sth->execute();
+ while (my (@row) = $sth->fetchrow_array())
+ {
+ my %temphash;
+ for (my $i = 0; $i < @row; $i++)
+ {
+ $temphash{$keys[$i]} = $row[$i];
+ }
+ $rows[$rows] = \%temphash;
+ $rows++;
+ }
+ $sth->finish();
+
+ if ($rows == 0)
+ {
+ print "No threads!\n" if ($DEBUG);
+ return -1;
+ }
+
+ for (my $i = 0; $i < @rows; $i++)
+ {
+ $rows[$i]{comments} = count_comments($rows[$i]{id});
+ $rows[$i]{files} = count_files($rows[$i]{id});
+ }
+
+ return \@rows;
+ }
+
diff --git a/bin/keyword-import.pl b/bin/keyword-import.pl
new file mode 100755
index 0000000..1a377bb
--- /dev/null
+++ b/bin/keyword-import.pl
@@ -0,0 +1,252 @@
+#!/usr/bin/perl
+
+use lib "/bucky/lib";
+use Bucky;
+
+$dbh = DBI->connect ($dsn);
+
+# get keyword + threads
+my $target = $ARGV[0];
+my @dirs;
+my %threads, %comments, %files;
+our %keywords = get_keywords();
+my $keyword;
+
+if ($target > 0)
+ {
+ push @dirs, $target if (-e $target && -d $target);
+ }
+else
+ {
+ $keyword = $ARGV[0];
+ print "Importing keyword $keyword\n";
+ @dirs = dir_list("$keyword/");
+ chdir("$keyword/");
+ }
+
+# read in all data...
+foreach my $dir (@dirs)
+ {
+ next if ($dir eq "keyword");
+ my @files = dir_list("$dir/");
+ my $t, $c, $f;
+
+ print "Reading in thread $dir ...\n";
+ foreach my $filename (@files)
+ {
+ next if ($filename !~ /(thread|comment|file)/);
+ my ($type, $id) = split /\./, $filename, 2;
+ my $file = read_file("$dir/$filename");
+
+ if ($type eq "thread")
+ {
+ $t = flat2thread($file);
+ $threads{$t->{id}} = $t;
+ print "t.$t->{id} ";
+ }
+ elsif ($type eq "comment")
+ {
+ $c = flat2comment($file);
+ $comments{$c->{id}} = $c;
+ print "c.$c->{id} ";
+ }
+ elsif ($type eq "file")
+ {
+ $f = flat2file($file);
+ if (-e "$dir/data/$f->{filename}")
+ {
+ $files{$f->{id}} = $f;
+ print "f.$f->{id} ";
+ }
+ else
+ {
+ print "No data for $f->{filename} !\n"
+ }
+ }
+ }
+ print "$t->{title}";
+ print "\n";
+ }
+
+print "\n";
+
+# now that data is all in a structure,
+# parse through threads, comments, files IN ORDER
+# get "real" thread ids to update "thread" when you next encounter it...
+# as comments are created, keep track of "real ids".. update "parent_id != -1" where appropriate
+# as files are created, update parent_id and move files
+
+# if keyword does not exist, create it.
+#my $realk = get_keyword($keyword);
+#if ($realk == -1)
+# {
+# my $file = read_file("keyword");
+# my $k = flat2thread($file);
+# instantiate_keyword($k);
+# }
+
+my %realthread = (-1 => -1);
+my %realcomment = (-1 => -1);
+my %realfile = (-1 => -1);
+
+foreach my $tid (sort { $a <=> $b } keys %threads)
+ {
+ my $t = $threads{$tid};
+ my $fakeid = instantiate_thread($t);
+ print "thread $t->{id} => $fakeid\n";
+ $realthread{$t->{id}} = $fakeid;
+ $ttot++;
+ }
+
+foreach my $cid (sort { $a <=> $b } keys %comments)
+ {
+ my $c = $comments{$cid};
+ my $fakeid = instantiate_comment($c, $realthread{$c->{thread}}, $realcomment{$c->{parent_id}});
+ print "comment $c->{id} => $fakeid\n";
+ print " .. new thread: $c->{thread} -> $realthread{$c->{thread}}\n";
+ print " .. new parent: $c->{parent_id} -> $realcomment{$c->{parent_id}}\n"
+ if ($c->{parent_id} != -1);
+ $realcomment{$c->{id}} = $fakeid;
+ $ctot++;
+ }
+
+foreach my $fid (sort { $a <=> $b } keys %files)
+ {
+ my $f = $files{$fid};
+ my $realt = $realthread{$f->{parent_id}};
+ my $fakeid = instantiate_file($f, $realt);
+ mkdir ("$data_path/$realt/") unless (-e "$data_path/$realt/");
+ mkdir ("$data_path/$realt/.thumb/") unless (-e "$data_path/$realt/.thumb/");
+ system("/bin/chmod 777 $data_path/$realt/.thumb");
+ system ("/bin/cp \"$f->{parent_id}/data/$f->{filename}\" $data_path/$realt/");
+ print "file $f->{id} => $fakeid\n";
+
+ print " .. new thread: $f->{parent_id} -> $realthread{$f->{parent_id}}\n";
+ $realfile{$f->{id}} = $fakeid;
+ $ftot++;
+ $sizetot += $f->{size};
+ }
+
+print "Import successful!\nTotal: $ttot.t $ctot.c $ftot.f ($sizetot b.)\n";
+
+$dbh->disconnect();
+
+###########################
+
+sub instantiate_keyword
+ {
+ my ($k) = @_;
+ my %nk =
+ (
+ keyword => $k->{keyword},
+ threads => " ",
+ owner => $k->{username},
+ public => $k->{public},
+ agglutinate => $k->{agglutinate},
+ color => $k->{color}
+ );
+ add_keyword(\%nk);
+ }
+
+sub instantiate_thread
+ {
+ my ($t) = @_;
+ my %nt =
+ (
+ title => $t->{title},
+ username => $t->{username},
+ keyword => (exists ($keywords{$t->{keyword}}) ? $t->{keyword} : ""),
+ createdate => $t->{createdate},
+ lastmodified => $t->{lastmodified},
+ size => $t->{size},
+ private => $t->{private},
+ allowed => $t->{allowed},
+ flagged => $t->{flagged},
+ color => $t->{color},
+ display => $t->{display}
+ );
+ my $thread_id = add_thread_by_hash(\%nt);
+ die if ($thread_id == -1);
+ return $thread_id;
+ }
+
+sub instantiate_comment
+ {
+ my ($c, $newt, $newp) = @_;
+ my $comment_id = add_comment($newt, $newp, $c->{username}, $c->{comment}, $c->{date});
+ return $comment_id;
+ }
+
+sub instantiate_file
+ {
+ my ($f, $newt) = @_;
+ my $file_id = add_file($newt, $f->{username}, $f->{filename}, $f->{size}, $f->{date});
+ return $file_id;
+ }
+
+###########################
+
+sub dir_list
+ {
+ my ($d) = @_;
+ opendir (DIR, $d) or die "couldn't list: $d, $!";
+ @files = grep (!/^\./, sort readdir (DIR));
+ closedir DIR;
+ return @files;
+ }
+
+sub flat2hash
+ {
+ my ($file) = @_;
+ my %hash;
+ foreach my $line (@$file)
+ {
+ $line =~ s/\r//;
+ chomp $line;
+ last if (!$line);
+ last if ($line eq "\n");
+ my ($k, $v) = split /:/, $line, 2;
+ $hash{$k} = $v;
+ }
+ return \%hash;
+ }
+
+sub flat2comment
+ {
+ my ($file) = @_;
+ my $comment_hash = flat2hash($file);
+ my $reading = 0;
+ foreach my $line (@$file)
+ {
+ $line =~ s/\r//;
+ if (!$line && !$reading)
+ { $reading = 1; next; }
+ next unless ($reading);
+ $comment_hash->{comment} .= $line;
+ }
+ return $comment_hash;
+ }
+
+sub flat2file
+ {
+ my ($file) = @_;
+ return flat2hash($file);
+ }
+
+sub flat2thread
+ {
+ my ($file) = @_;
+ return flat2hash($file);
+ }
+
+sub read_file
+ {
+ my ($file) = @_;
+ my @out;
+
+ open F, $file or die "problem with $file $!";
+ @out=<F>;
+ close F;
+ return \@out;
+ }
+
diff --git a/bin/localbucky.pm b/bin/localbucky.pm
new file mode 100644
index 0000000..abf82e6
--- /dev/null
+++ b/bin/localbucky.pm
@@ -0,0 +1,62 @@
+#!/usr/bin/perl
+
+# Change this to point to Bucky library directory, where packages are installed
+use lib "/var/www/vhosts/carbonpictures.com/bucky/lib";
+
+# Change this to point to the directory of random texts
+our $BUCKY_FORTUNES = "/var/www/vhosts/carbonpictures.com/bucky/fortune";
+
+# Change this to point to the URL preamble for Bucky's script directory, where cgi-bin scripts are installed
+BEGIN
+ {
+ our $BUCKY = "/cgi-bin/bucky";
+ our $BUCKY_DB = "bucky";
+ our $BUCKY_DB_CNF = "/var/www/vhosts/carbonpictures.com/.bucky.cnf";
+ }
+
+#our $BUCKY = "";
+
+our $BUCKY_NAME = 'bucky';
+our $BUCKY_SHORT_NAME = 'bucky';
+our $BUCKY_COOKIE_DOMAIN = 'carbonpictures.com';
+our $BUCKY_HOST = 'www.carbonpictures.com'; # url domain
+
+our $BUCKY_ADMINISTRATOR = 'jules';
+our $BUCKY_DEFAULT_BOXES = " welcome bPod radio postform hootbox photostream ";
+our $BUCKY_DEFAULT_KEYWORD = 'NONE'; # default should be 'NONE'
+our $BUCKY_TIMEZONE_OFFSET = 5; # correct your server's offset from GMT
+our $BUCKY_DUDER_NOUN = 'duder'; # singular noun accepting courtesy 's'
+
+our $BUCKY_LOGIN_WELCOME = "welcome to bucky"; # welcome on login screen
+
+# bucky non-css colors
+our $BUCKY_COLOR_HR = "#201010";
+
+our $BUCKY_INDEX_LIMIT = 50;
+
+# bPod: URLs, colors
+our $BPOD_URL_SERVICES_KEYWORDS = $BUCKY_HOST . "$BUCKY/services_k";
+our $BPOD_URL_SERVICES_THREADS = $BUCKY_HOST . "$BUCKY/services_th?k=";
+our $BPOD_URL_SERVICES_FILES = $BUCKY_HOST . "$BUCKY/services_f?pid=";
+our $BPOD_URL_PREAMBLE_FILES = $BUCKY_HOST . "/bucky/data/";
+our $BPOD_URL_DETAILS = $BUCKY_HOST . "$BUCKY/details/";
+our $BPOD_COLOR_UI_GRADIENT_1 = "0xE6F0F0";
+our $BPOD_COLOR_UI_GRADIENT_2 = "0xD8E0EC";
+our $BPOD_COLOR_UI_STROKE = "0x201010";
+
+# thread url format: /details (== 0) or individually by /keyword (== 1)
+our $BUCKY_KEYWORD_IN_DETAILS_URL = 0;
+
+our $ZIP_BUTTON_ENABLED = 1;
+
+# (shoutcast) radio status
+our $RADIO_STATUS_ENABLED = 1;
+our $RADIO_STATUS_URL = "http://radiofreehanoi.com/status";
+our $RADIO_INFO_URL = "http://radiofreehanoi.com/info";
+
+
+# Load bucky packages
+use Bucky1;
+
+1;
+
diff --git a/bin/participation_matrix.pl b/bin/participation_matrix.pl
new file mode 100644
index 0000000..4742183
--- /dev/null
+++ b/bin/participation_matrix.pl
@@ -0,0 +1,35 @@
+#!/usr/bin/perl
+
+$dbh = DBI->connect ($dsn);
+
+our ($USER, $lastlog) = checkin();
+our $loggedin = ($USER != -1);
+
+my ($threads) = get_threads();
+my ($keywords) = get_keywords();
+
+open HMATRIX, ">".$BUCKY_CONFIG->{BASE_PATH}."/docs/hmatrix.html";
+
+print HMATRIX "<html><body>";
+foreach $t (keys (%$threads))
+ {
+ my ($files, $comments) = get_attachments($t);
+ }
+
+sub check_user_hash
+ {
+ my ($userhash, $fakehash) = @_;
+ foreach $k (keys %$fakehash)
+ {
+ $userhash->{$fakehash->{username}} += 1;
+ }
+ }
+
+sub get_attachments
+ {
+ my ($id) = @_;
+ my $files = get_files($t->{id});
+ my $comments = get_comments ($t->{id});
+
+ return ($files, $comments) ;
+ }
diff --git a/bin/populate-avatars.pl b/bin/populate-avatars.pl
new file mode 100755
index 0000000..ee9f4fd
--- /dev/null
+++ b/bin/populate-avatars.pl
@@ -0,0 +1,26 @@
+#!/usr/bin/perl
+
+$ENV{HTTPS} = "on";
+
+use localbucky;
+
+$DEBUG = 1;
+
+$dbh = DBI->connect ($dsn);
+
+my $users = get_all_users();
+
+system("chmod", "-R", "777", "$data_path/profile");
+
+foreach my $u (@$users)
+ {
+ update_profile_thumb($u->{username});
+ print "\n";
+ }
+
+system("chmod", "-R", "777", "$data_path/profile");
+
+# system("chown", "-R", "nobody:nobody", "$data_path/profile");
+
+$dbh->disconnect();
+
diff --git a/bin/populate-thumbs.pl b/bin/populate-thumbs.pl
new file mode 100755
index 0000000..ff22207
--- /dev/null
+++ b/bin/populate-thumbs.pl
@@ -0,0 +1,48 @@
+#!/usr/bin/perl
+
+$ENV{HTTPS} = "on";
+
+use localbucky;
+
+
+$dbh = DBI->connect ($dsn);
+
+my $doit_id = $ARGV[0];
+
+if (length($doit_id))
+ {
+ my $thread = get_thread($doit_id);
+ check_and_render($thread);
+ }
+else
+ {
+ my $threads = get_threads();
+ foreach my $t (@$threads)
+ {
+ check_and_render($t);
+ }
+ }
+
+sub check_and_render
+ {
+ my ($t) = @_;
+ my $path = qq($data_path/$t->{id}/.thumb);
+ my $printed = 0;
+ my $files = get_files($t->{id});
+ foreach $f (@$files)
+ {
+ next unless ($f->{filename} =~ /(gif|jpe?g|png)$/i);
+ next unless (-e "$data_path/$f->{parent_id}/$f->{filename}");
+ system($RM_PATH, "-f", "$path/t.".(lc($f->{filename})));
+ if (! $printed)
+ { print qq(Generating thumbs for $t->{id} -- $t->{title}\n); $printed++; }
+ print "$f->{filename} ";
+ make_image_thumb({ file => $f, maxwidth => 145, maxheight => 110, key => $THUMB_LIBRARY_PREFIX });
+ }
+ print qq(\n\n) if ($printed);
+ }
+
+# system("chown", "-R", "carbon:psacln", "$data_path");
+
+$dbh->disconnect();
+
diff --git a/bin/username-export.pl b/bin/username-export.pl
new file mode 100755
index 0000000..38024ed
--- /dev/null
+++ b/bin/username-export.pl
@@ -0,0 +1,165 @@
+#!/usr/bin/perl
+
+$DEBUG = 1;
+
+use lib "../cgi-bin";
+use localbucky;
+
+$dbh = DBI->connect ($dsn);
+
+# get keyword + threads
+
+if (@ARGV > 0)
+ {
+ export_users(@ARGV);
+ }
+
+$dbh->disconnect();
+
+sub export_users
+ {
+ print "Exporting users @_\n";
+ my $threads = get_full_threads_by_username(@_);
+
+ print "Got " . @$threads . " threads";
+
+ # mkdir username, chdir
+ mkdir ($_[0]);
+ chdir ($_[0]);
+
+ # foreach thread:
+ foreach my $thread (@$threads)
+ {
+ export_thread($thread);
+ }
+
+ chdir("..");
+ }
+
+sub export_thread
+ {
+ my ($thread) = @_;
+
+ # get all comments & files
+ my $comments = get_comments($thread->{id});
+ my $files = get_files($thread->{id});
+
+ mkdir ("$thread->{id}");
+ chdir ("$thread->{id}");
+
+ print "thread $thread->{id} -- $thread->{title}\n";
+ print "comments: $thread->{comments}\n";
+ print "files: $thread->{files}\n";
+
+ open THREAD, ">thread" or die $!;
+ foreach my $key (keys %$thread)
+ {
+ print THREAD "$key:".$thread->{$key}."\n";
+ }
+ print THREAD "\n";
+ close THREAD;
+
+ # cat each comment & file to text files based on id
+ foreach my $comment (keys %$comments)
+ {
+ my $c = $comments->{$comment};
+ open COMMENT, ">comment.".$c->{id} or die $!;
+ foreach my $key (keys %$c)
+ {
+ next if ($key eq "comment");
+ print COMMENT "$key:".$c->{$key}."\n";
+ }
+ print COMMENT "\n";
+ print COMMENT $c->{comment};
+ close COMMENT;
+ }
+
+ foreach my $f (@$files)
+ {
+ open FILE, ">file.".$f->{id} or die $!;
+ foreach my $key (keys %$f)
+ {
+ print FILE "$key:".$f->{$key}."\n";
+ }
+ close FILE;
+ }
+
+ if (-e "$data_path/$thread->{id}")
+ {
+ print "Copying ...\n";
+ mkdir ("data/");
+ system ("/bin/cp -r $data_path/$thread->{id}/* data/")
+ }
+
+ chdir ("..");
+ print "\n";
+ }
+
+sub get_full_threads_by_username
+ {
+ my @usernames = @_;
+ my @rows;
+ my $query;
+ my @keys = qw(id title username keyword createdate lastmodified size private allowed flagged color);
+ my $rc = 0;
+
+ my $threadz = {};
+ for my $username (@usernames) {
+ print $username . "\n";
+ my $quser = $dbh->quote($username);
+
+ $query = "SELECT thread FROM comments WHERE username=$quser GROUP BY thread";
+ print $query . "\n";
+ $sth = $dbh->prepare($query);
+ $sth->execute();
+ while (my (@row) = $sth->fetchrow_array()) {
+ $threadz->{$row[0]} = 1;
+ }
+
+ $query = "SELECT thread FROM files WHERE username=$quser GROUP BY thread";
+ print $query . "\n";
+ $sth = $dbh->prepare($query);
+ $sth->execute();
+ while (my (@row) = $sth->fetchrow_array()) {
+ $threadz->{$row[0]} = 1;
+ }
+ }
+ my $values = join ",", sort keys %$threadz;
+
+ $query = "SELECT id,title,username,keyword,createdate,lastmodified,size,private,allowed,flagged,color FROM threads WHERE id IN ($values)";
+# if (defined($private) && $private)
+# {
+# $query .= " AND (ISNULL(private) OR private = '')";
+# }
+
+ print $query."<br>" if ($DEBUG);
+ $sth = $dbh->prepare($query);
+ $sth->execute();
+ while (my (@row) = $sth->fetchrow_array())
+ {
+ my %temphash;
+ for (my $i = 0; $i < @row; $i++)
+ {
+ $temphash{$keys[$i]} = $row[$i];
+ }
+ $rows[$rc] = \%temphash;
+ $rc++;
+ }
+ $sth->finish();
+
+ if ($rc == 0)
+ {
+ print "No threads!\n" if ($DEBUG);
+ return -1;
+ }
+
+ for (my $i = 0; $i < @rows; $i++)
+ {
+ $rows[$i]{comments} = count_comments($rows[$i]{id});
+ $rows[$i]{files} = count_files($rows[$i]{id});
+ }
+
+ return \@rows;
+ }
+
+
diff --git a/bin/whenis.pl b/bin/whenis.pl
new file mode 100755
index 0000000..0d37892
--- /dev/null
+++ b/bin/whenis.pl
@@ -0,0 +1,7 @@
+#!/usr/bin/perl
+
+use localbucky;
+
+my $when = $ARGV[0];
+
+print verbosedate($when)."\n";