lib/Odin.pm: New function for inserting records into databases.
[odin-cgi] / lib / Odin.pm
index 551c51f..27b2e8b 100644 (file)
@@ -5,6 +5,7 @@ package Odin;
 use DBI;
 use Digest::SHA qw(sha256_hex);
 use MIME::Base64;
+use POSIX;
 
 ###--------------------------------------------------------------------------
 ### Early utilities.
@@ -33,6 +34,8 @@ our @URLPAT = (
   qr{^https?://}
 );
 
+our $PASTEMAXLEN = 1024*1024;
+
 our %COOKIE_DEFAULTS = (
   -httponly => undef,
   -max_age => 3600
@@ -85,6 +88,26 @@ sub nice_name ($) {
   return lc $s;
 }
 
+sub print_columns (@) {
+  my @col = reverse @_;
+  my @fmt = ();
+  my @val = ();
+  while (@col && $col[1] eq "") { splice @col, 0, 2; }
+  my ($wd, $v) = splice @col, 0, 2;
+  push @fmt, "%s"; push @val, $v;
+  while (@col) {
+    my ($wd, $v) = splice @col, 0, 2;
+    push @fmt, "%-${wd}s";
+    push @val, $v;
+  }
+  printf join("  ", reverse @fmt) . "\n", reverse @val;
+}
+
+sub fmt_time ($) {
+  my ($t) = @_;
+  return $t == -1 ? "--" : strftime "%Y-%m-%d %H:%M:%S %z", localtime $t;
+}
+
 ###--------------------------------------------------------------------------
 ### Database utilities.
 
@@ -129,6 +152,18 @@ sub xact (&$) {
   die $exc;
 }
 
+sub insert_record ($$%) {
+  my ($db, $table, %fields) = @_;
+  my @var = ();
+  my @val = ();
+
+  for my $v (keys %fields) {
+    push @var, $v;
+    push @val, $fields{$v};
+  }
+  $db->do("INSERT INTO $table (" . join(", ", @var) . ")
+          VALUES (" . join(", ", map { "?" } @var) . ")", undef, @val);
+}
 
 ###--------------------------------------------------------------------------
 ### Sequence numbers and tagging.
@@ -261,9 +296,8 @@ sub new_shorturl ($) {
        undef, $WHOCMP, $url);
     unless (defined $tag) {
       $tag = encode_tag(next_seq($db, "odin_shorturl_seq"));
-      $db->do("INSERT INTO odin_shorturl (tag, stamp, owner, url)
-              VALUES (?, ?, ?, ?)", undef,
-             $tag, $NOW, $WHO, $url);
+      insert_record $db, "odin_shorturl",
+       tag => $tag, stamp => $NOW, owner => $WHO, url => $url;
     }
   } $db;
   return $tag;
@@ -325,10 +359,9 @@ sub new_pastebin (\%) {
   merge_hash %$new, %PASTEBIN_DEFAULTS;
   xact {
     $tag = encode_tag next_seq $db, "odin_pastebin_seq";
-    $db->do("INSERT INTO odin_pastebin
-              (tag, stamp, edithash, owner, $PASTEBIN_PROPCOLS)
-            VALUES (?, ?, ?, ?, $PASTEBIN_PROPPLACES)", undef,
-           $tag, $NOW, $hash, $WHO, @{$new}{@PASTEBIN_PROPS});
+    insert_record $db, "odin_pastebin",
+      tag => $tag, stamp => $NOW, edithash => $hash, owner => $WHO,
+      %$new;
   } $db;
   return $tag, $editkey;
 }
@@ -427,6 +460,8 @@ sub tidy_pastebin_content ($) {
   return undef unless defined $content;
   $content =~ tr/\r//d;
   $content =~ s/([^\n])\z/$1\n/;
+  length $content <= $PASTEMAXLEN or
+    fail "invalid paste content", ".badpaste";
   return $content;
 }