Browse Source

Mass tidy

George Baugh 2 years ago
parent
commit
734ac51eb7

+ 1 - 1
bin/build_index.pl

@@ -10,7 +10,7 @@ use Trog::SQLite::TagIndex;
 
 # Use this to build the post index after you import data, otherwise it's not needed
 
-my $conf = Trog::Config::get();
+my $conf   = Trog::Config::get();
 my $search = Trog::Data->new($conf);
 
 Trog::SQLite::TagIndex::build_index($search);

+ 4 - 4
bin/favicon_mongler.pl

@@ -9,10 +9,10 @@ use File::Which    ();
 use File::Copy     ();
 
 die "Usage:\n    favicon_mongler.pl /path/to/favicon.svg" unless $ARGV[0];
-my $icon = Cwd::abs_path($ARGV[0]);
-my $bin = File::Which::which('inkscape');
+my $icon = Cwd::abs_path( $ARGV[0] );
+my $bin  = File::Which::which('inkscape');
 die "Please install inkscape" if !$bin;
-my $dir  = File::Basename::dirname($icon) || die "Can't figure out dir from $icon";
+my $dir = File::Basename::dirname($icon) || die "Can't figure out dir from $icon";
 
 my %files = (
     32  => 'ico',
@@ -29,6 +29,6 @@ foreach my $size ( sort { $b <=> $a } keys(%files) ) {
     print "*** Wrote $dir/favicon-$size.$files{$size} ***\n\n";
 }
 
-File::Copy::copy("$dir/favicon-32.ico", "$dir/favicon.ico");
+File::Copy::copy( "$dir/favicon-32.ico", "$dir/favicon.ico" );
 
 0;

+ 65 - 63
bin/migrate.pl

@@ -17,22 +17,22 @@ my $docroot = "/var/www/teodesian.net/doc";
 
 my $dir = "/var/www/teodesian.net/doc/microblog/";
 
-opendir(my $dh, $dir) or die;
+opendir( my $dh, $dir ) or die;
 my @days = grep { !/^\./ } readdir $dh;
 closedir $dh;
 
 my $ring = JSON::MaybeXS->new();
 foreach my $day (@days) {
 
-    opendir(my $dht, "$dir/$day") or die;
+    opendir( my $dht, "$dir/$day" ) or die;
     my @times = grep { !/^\./ } readdir $dht;
     closedir $dht;
 
-    my ($month,$date,$year) = split(/\./,$day);
+    my ( $month, $date, $year ) = split( /\./, $day );
 
     foreach my $time (@times) {
 
-        my ($hour, $min, $sec) = split(/:/,$time);
+        my ( $hour, $min, $sec ) = split( /:/, $time );
 
         my $data;
         my $file = "$dir/$day/$time";
@@ -46,21 +46,21 @@ foreach my $day (@days) {
         $data = html_post($file) unless $data;
 
         my $dt = DateTime->new(
-            year       => $year + 2000,
-            month      => $month,
-            day        => $date,
-            hour       => $hour,
-            minute     => $min,
-            second     => $sec,
+            year   => $year + 2000,
+            month  => $month,
+            day    => $date,
+            hour   => $hour,
+            minute => $min,
+            second => $sec,
         );
         $data->{created} = $dt->epoch();
 
-        $data->{id} = $data->{created};
-        $data->{tags} = ['public','news'];
+        $data->{id}      = $data->{created};
+        $data->{tags}    = [ 'public', 'news' ];
         $data->{version} = 0;
 
-        open(my $fh, '>', "data/files/$data->{created}") or die;
-        print $fh encode_json([$data]);
+        open( my $fh, '>', "data/files/$data->{created}" ) or die;
+        print $fh encode_json( [$data] );
         close $fh;
     }
 }
@@ -68,17 +68,19 @@ foreach my $day (@days) {
 # Migrate blog posts
 $dir = "$docroot/blog";
 
-opendir(my $bh, $dir) or die;
+opendir( my $bh, $dir ) or die;
 my @blogs = grep { -f "$dir/$_" } readdir $bh;
 closedir $bh;
 
 my $offset = 0;
 
-foreach my $post ( sort {
-    my $anum = $a =~ m/^(\d*)-/;
-    my $bnum = $b =~ m/^(\d*)-/;
-    $b <=> $a
-  }  @blogs) {
+foreach my $post (
+    sort {
+        my $anum = $a =~ m/^(\d*)-/;
+        my $bnum = $b =~ m/^(\d*)-/;
+        $b <=> $a
+    } @blogs
+) {
     my $postname = $post;
     $postname =~ s/^\d*-//g;
     $postname =~ s/\.post$//g;
@@ -87,59 +89,59 @@ foreach my $post ( sort {
     my $data = {
         title => $postname,
         data  => $content,
-        tags  => ['blog','public'],
+        tags  => [ 'blog', 'public' ],
     };
 
-    my (undef, undef, undef, undef, $uid, undef, undef, undef, undef, $ctime) = stat("$dir/$post");
-    my $user = lc(getpwuid($uid));
-    $user = scalar(grep { $user eq $_ } qw{/sbin/nologin www-data}) ? 'nobody' : $user;
+    my ( undef, undef, undef, undef, $uid, undef, undef, undef, undef, $ctime ) = stat("$dir/$post");
+    my $user = lc( getpwuid($uid) );
+    $user = scalar( grep { $user eq $_ } qw{/sbin/nologin www-data} ) ? 'nobody' : $user;
     $data->{user} = $user;
     $ctime += $offset;
     $data->{created} = $ctime;
-    $data->{id} = $ctime;
-    $data->{href} = "/blog/$ctime";
+    $data->{id}      = $ctime;
+    $data->{href}    = "/blog/$ctime";
     $data->{version} = 0;
 
     print "Migrate blog post '$post'\n";
-    open(my $fh, '>', "data/files/$data->{created}") or die;
-    print $fh encode_json([$data]);
+    open( my $fh, '>', "data/files/$data->{created}" ) or die;
+    print $fh encode_json( [$data] );
     close $fh;
 
     $offset--;
 }
 exit 0;
 my $vdir = "$docroot/fileshare/video";
-opendir(my $vh, $vdir) or die;
+opendir( my $vh, $vdir ) or die;
 my @vidyas = grep { -f "$vdir/$_" && $_ =~ m/\.m4v$/ } readdir $vh;
 closedir $vh;
 
-foreach my $vid ( @vidyas ) {
+foreach my $vid (@vidyas) {
     my $postname = $vid;
     $postname =~ s/_/ /g;
     $postname =~ s/\.mv4$//g;
 
     my $data = {
-        title => $postname,
-        data  => "Description forthcoming",
-        tags  => ['video','public'],
+        title   => $postname,
+        data    => "Description forthcoming",
+        tags    => [ 'video', 'public' ],
         preview => "/img/sys/testpattern.jpg",
     };
 
-    my (undef, undef, undef, undef, $uid, undef, undef, undef, undef, $ctime) = stat("$vdir/$vid");
-    my $user = lc(getpwuid($uid));
-    $user = scalar(grep { $user eq $_ } qw{/sbin/nologin www-data}) ? 'nobody' : $user;
-    $data->{user} = $user;
+    my ( undef, undef, undef, undef, $uid, undef, undef, undef, undef, $ctime ) = stat("$vdir/$vid");
+    my $user = lc( getpwuid($uid) );
+    $user            = scalar( grep { $user eq $_ } qw{/sbin/nologin www-data} ) ? 'nobody' : $user;
+    $data->{user}    = $user;
     $data->{created} = $ctime;
-    $data->{id} = $ctime;
-    $data->{href} = "/assets/$ctime-$vid";
+    $data->{id}      = $ctime;
+    $data->{href}    = "/assets/$ctime-$vid";
     $data->{version} = 0;
 
     #Copy over the video
-    File::Copy::copy("$vdir/$vid","www/assets/$ctime-$vid");
+    File::Copy::copy( "$vdir/$vid", "www/assets/$ctime-$vid" );
 
     print "Migrate video '$vid'\n";
-    open(my $fh, '>', "data/files/$data->{created}") or die;
-    print $fh encode_json([$data]);
+    open( my $fh, '>', "data/files/$data->{created}" ) or die;
+    print $fh encode_json( [$data] );
     close $fh;
 }
 
@@ -147,27 +149,27 @@ sub json_remap {
     my $json = shift;
 
     return {
-       preview => $json->{"image"},
-       data       => $json->{"comment"},
-       user       => lc($json->{"poster"}),
-       title      => $json->{"title"},
-       audio_href => $json->{"audio"},
-       href       => $json->{"url"},
-       video_href => $json->{"video"},
+        preview    => $json->{"image"},
+        data       => $json->{"comment"},
+        user       => lc( $json->{"poster"} ),
+        title      => $json->{"title"},
+        audio_href => $json->{"audio"},
+        href       => $json->{"url"},
+        video_href => $json->{"video"},
     };
 }
 
 sub html_post {
-    my $file = shift;
-    my $is_first_link=1;
-    my $data = { data => '', href => '' };
+    my $file          = shift;
+    my $is_first_link = 1;
+    my $data          = { data => '', href => '' };
 
     my $p = HTML::Parser->new(
         handlers => [
             start => [
                 sub {
-                    my ($self,$attr,$text,$tagname) = @_;
-                    if ( $tagname eq 'a' && $is_first_link) {
+                    my ( $self, $attr, $text, $tagname ) = @_;
+                    if ( $tagname eq 'a' && $is_first_link ) {
                         $data->{href} = $attr->{href};
                         return;
                     }
@@ -177,9 +179,9 @@ sub html_post {
                 },
                 'self, attr, text,tagname'
             ],
-            text  => [
+            text => [
                 sub {
-                    my ($self,$attr,$text,$tagname) = @_;
+                    my ( $self, $attr, $text, $tagname ) = @_;
                     if ($is_first_link) {
                         $data->{title} .= $text;
                         return;
@@ -188,11 +190,11 @@ sub html_post {
                 },
                 'self, attr, text,tagname'
             ],
-            end   => [
+            end => [
                 sub {
-                    my ($self,$attr,$text,$tagname) = @_;
-                    if ( $tagname eq 'a' && $is_first_link) {
-                        $is_first_link=0;
+                    my ( $self, $attr, $text, $tagname ) = @_;
+                    if ( $tagname eq 'a' && $is_first_link ) {
+                        $is_first_link = 0;
                         return;
                     }
                     return if $is_first_link;
@@ -205,9 +207,9 @@ sub html_post {
     $p->parse_file($file);
 
     #Get the user name from ownership
-    my (undef, undef, undef, undef, $uid, undef, undef, undef, undef, $ctime) = stat($file);
-    my $user = lc(getpwuid($uid));
-    $user = scalar(grep { $user eq $_ } qw{/sbin/nologin www-data}) ? 'nobody' : $user;
+    my ( undef, undef, undef, undef, $uid, undef, undef, undef, undef, $ctime ) = stat($file);
+    my $user = lc( getpwuid($uid) );
+    $user = scalar( grep { $user eq $_ } qw{/sbin/nologin www-data} ) ? 'nobody' : $user;
     $data->{user} = $user;
 
     $data->{created} = $ctime;

+ 72 - 71
bin/migrate2.pl

@@ -21,30 +21,31 @@ use Trog::SQLite::TagIndex;
 unlink "$FindBin::Bin/../data/posts.db";
 $ENV{NOHUP} = 1;
 
-sub uuid { return UUID::Tiny::create_uuid_as_string(UUID::Tiny::UUID_V1, UUID::Tiny::UUID_NS_DNS); }
+sub uuid { return UUID::Tiny::create_uuid_as_string( UUID::Tiny::UUID_V1, UUID::Tiny::UUID_NS_DNS ); }
 
 # Modify these variables to suit your installation.
-my $user = 'george';
-my @extra_series = (
-);
+my $user         = 'george';
+my @extra_series = ();
 
-my $conf = Trog::Config::get();
+my $conf        = Trog::Config::get();
 my $search_info = Trog::Data->new($conf);
 
 my @all = $search_info->get( raw => 1, limit => 0 );
 
 my %posts;
 foreach my $post (@all) {
-    $posts{$post->{id}} //= [];
+    $posts{ $post->{id} } //= [];
+
     # Re-do the IDs
-    push(@{$posts{$post->{id}}},$post);
+    push( @{ $posts{ $post->{id} } }, $post );
 }
 
-foreach my $timestamp (keys(%posts)) {
+foreach my $timestamp ( keys(%posts) ) {
     my $file_to_kill = "$FindBin::Bin/../data/files/$timestamp";
-    my $new_id = uuid();
+    my $new_id       = uuid();
+
     # Preserve old URLs
-    foreach my $post (@{$posts{$timestamp}}) {
+    foreach my $post ( @{ $posts{$timestamp} } ) {
         delete $post->{app};
         delete $post->{preview_file};
         delete $post->{wallpaper_file};
@@ -58,20 +59,20 @@ foreach my $timestamp (keys(%posts)) {
         $post->{aliases}    = ["/posts/$timestamp"];
         $post->{callback}   = "Trog::Routes::HTML::posts";
         $post->{method}     = 'GET';
-        @{$post->{tags}}    = grep { defined $_ } @{$post->{tags}};
+        @{ $post->{tags} } = grep { defined $_ } @{ $post->{tags} };
 
         $post->{content_type} //= 'text/html';
-        $post->{form}         = 'microblog.tx';
-        $post->{form}         = 'blog.tx' if grep {$_ eq 'blog' } @{$post->{tags}};
-        $post->{form}         = 'file.tx' if $post->{content_type} =~ m/^video\//;
-        $post->{form}         = 'file.tx' if $post->{content_type} =~ m/^audio\//;
-        $post->{form}         = 'file.tx' if $post->{content_type} =~ m/^image\//;
-        if (grep {$_ eq 'about' } @{$post->{tags}}) {
+        $post->{form} = 'microblog.tx';
+        $post->{form} = 'blog.tx' if grep { $_ eq 'blog' } @{ $post->{tags} };
+        $post->{form} = 'file.tx' if $post->{content_type} =~ m/^video\//;
+        $post->{form} = 'file.tx' if $post->{content_type} =~ m/^audio\//;
+        $post->{form} = 'file.tx' if $post->{content_type} =~ m/^image\//;
+        if ( grep { $_ eq 'about' } @{ $post->{tags} } ) {
             $post->{form}       = 'profile.tx';
             $post->{local_href} = "/users/$post->{user}";
             $post->{callback}   = "Trog::Routes::HTML::users";
         }
-        if (grep {$_ eq 'series' } @{$post->{tags}}) {
+        if ( grep { $_ eq 'series' } @{ $post->{tags} } ) {
             $post->{form}       = 'series.tx';
             $post->{callback}   = "Trog::Routes::HTML::series";
             $post->{child_form} = 'microblog.tx';
@@ -80,10 +81,10 @@ foreach my $timestamp (keys(%posts)) {
             $post->{child_form} = 'file.tx' if $post->{title} =~ m/^audio\//;
             $post->{child_form} = 'file.tx' if $post->{title} =~ m/^image\//;
             $post->{local_href} = "/$post->{aclname}";
-            $post->{aliases}    = ["/series/$timestamp", "/series/$new_id"];
+            $post->{aliases}    = [ "/series/$timestamp", "/series/$new_id" ];
         }
 
-        $search_info->write([$post]);
+        $search_info->write( [$post] );
         unlink $file_to_kill if -f $file_to_kill;
     }
 }
@@ -94,56 +95,56 @@ Trog::SQLite::TagIndex::build_routes($search_info);
 
 # Add in the series
 my $series = [
-        {
-            "aclname"    => "series",
-            "acls"       => [],
-            aliases      => [],
-            "callback"   => "Trog::Routes::HTML::series",
-            method       => 'GET',
-            "data"       => "Series",
-            "href"       => "/series",
-            "local_href" => "/series",
-            "preview"    => "/img/sys/testpattern.jpg",
-            "tags"       => [qw{series topbar}],
-            visibility   => 'public',
-            "title"      => "Series",
-            user         => $user,
-            form         => 'series.tx',
-            child_form   => 'series.tx',
-        },
-        {
-            "aclname"    => "about",
-            "acls"       => [],
-            aliases      => [],
-            "callback"   => "Trog::Routes::HTML::series",
-            method       => 'GET',
-            "data"       => "About",
-            "href"       => "/about",
-            "local_href" => "/about",
-            "preview"    => "/img/sys/testpattern.jpg",
-            "tags"       => [qw{series topbar public}],
-            visibility   => 'public',
-            "title"      => "About",
-            user         => $user,
-            form         => 'series.tx',
-            child_form   => 'profile.tx',
-        },
-        {
-            "aclname"      => "admin",
-            acls           => [],
-            aliases        => [],
-            "callback"     => "Trog::Routes::HTML::config",
-            'method'       => 'GET',
-            "content_type" => "text/plain",
-            "data"         => "Config",
-            "href"         => "/config",
-            "local_href"   => "/config",
-            "preview"      => "/img/sys/testpattern.jpg",
-            "tags"         => [qw{admin}],
-            visibility     => 'private',
-            "title"        => "Configure tCMS",
-            user           => $user,
-        },
+    {
+        "aclname"    => "series",
+        "acls"       => [],
+        aliases      => [],
+        "callback"   => "Trog::Routes::HTML::series",
+        method       => 'GET',
+        "data"       => "Series",
+        "href"       => "/series",
+        "local_href" => "/series",
+        "preview"    => "/img/sys/testpattern.jpg",
+        "tags"       => [qw{series topbar}],
+        visibility   => 'public',
+        "title"      => "Series",
+        user         => $user,
+        form         => 'series.tx',
+        child_form   => 'series.tx',
+    },
+    {
+        "aclname"    => "about",
+        "acls"       => [],
+        aliases      => [],
+        "callback"   => "Trog::Routes::HTML::series",
+        method       => 'GET',
+        "data"       => "About",
+        "href"       => "/about",
+        "local_href" => "/about",
+        "preview"    => "/img/sys/testpattern.jpg",
+        "tags"       => [qw{series topbar public}],
+        visibility   => 'public',
+        "title"      => "About",
+        user         => $user,
+        form         => 'series.tx',
+        child_form   => 'profile.tx',
+    },
+    {
+        "aclname"      => "admin",
+        acls           => [],
+        aliases        => [],
+        "callback"     => "Trog::Routes::HTML::config",
+        'method'       => 'GET',
+        "content_type" => "text/plain",
+        "data"         => "Config",
+        "href"         => "/config",
+        "local_href"   => "/config",
+        "preview"      => "/img/sys/testpattern.jpg",
+        "tags"         => [qw{admin}],
+        visibility     => 'private',
+        "title"        => "Configure tCMS",
+        user           => $user,
+    },
 ];
 
-$search_info->add(@$series,@extra_series);
+$search_info->add( @$series, @extra_series );

+ 27 - 27
bin/migrate3.pl

@@ -21,26 +21,26 @@ use Trog::SQLite::TagIndex;
 unlink "$FindBin::Bin/../data/posts.db";
 $ENV{NOHUP} = 1;
 
-sub uuid { return UUID::Tiny::create_uuid_as_string(UUID::Tiny::UUID_V1, UUID::Tiny::UUID_NS_DNS); }
+sub uuid { return UUID::Tiny::create_uuid_as_string( UUID::Tiny::UUID_V1, UUID::Tiny::UUID_NS_DNS ); }
 
 # Modify these variables to suit your installation.
-my $user = 'george';
-my @extra_series = (
-);
+my $user         = 'george';
+my @extra_series = ();
 
-my $conf = Trog::Config::get();
+my $conf        = Trog::Config::get();
 my $search_info = Trog::Data->new($conf);
 
 my @all = $search_info->get( raw => 1, limit => 0 );
 foreach my $post (@all) {
     if ( defined $post->{form} && $post->{form} eq 'series.tx' ) {
-        $post->{tiled} = scalar(grep { $_ eq $post->{local_href} } qw{/files /audio /video /image /series /about});
+        $post->{tiled} = scalar( grep { $_ eq $post->{local_href} } qw{/files /audio /video /image /series /about} );
     }
-    if (!defined $post->{visibility}) {
-        $post->{visibility} = 'public' if grep { $_ eq 'public' } @{$post->{tags}};
-        $post->{visibility} = 'private' if grep { $_ eq 'private' } @{$post->{tags}};
-        $post->{visibility} = 'unlisted' if grep { $_ eq 'unlisted' } @{$post->{tags}};
+    if ( !defined $post->{visibility} ) {
+        $post->{visibility} = 'public'   if grep { $_ eq 'public' } @{ $post->{tags} };
+        $post->{visibility} = 'private'  if grep { $_ eq 'private' } @{ $post->{tags} };
+        $post->{visibility} = 'unlisted' if grep { $_ eq 'unlisted' } @{ $post->{tags} };
     }
+
     # Otherwise re-save the posts with is_video etc
     $search_info->add($post);
 }
@@ -51,23 +51,23 @@ Trog::SQLite::TagIndex::build_routes($search_info);
 
 # Add in the series
 my $series = [
-        {
-            "acls"       => [],
-            aliases      => [],
-            "callback"   => "Trog::Routes::HTML::posts",
-            method       => 'GET',
-            "data"       => "All Posts",
-            "href"       => "/posts",
-            "local_href" => "/posts",
-            "preview"    => "/img/sys/testpattern.jpg",
-            "tags"       => [qw{series}],
-            visibility   => 'unlisted',
-            "title"      => "All Posts",
-            user         => $user,
-            form         => 'series.tx',
-            child_form   => 'series.tx',
-            aclname      => 'posts',
-        },
+    {
+        "acls"       => [],
+        aliases      => [],
+        "callback"   => "Trog::Routes::HTML::posts",
+        method       => 'GET',
+        "data"       => "All Posts",
+        "href"       => "/posts",
+        "local_href" => "/posts",
+        "preview"    => "/img/sys/testpattern.jpg",
+        "tags"       => [qw{series}],
+        visibility   => 'unlisted',
+        "title"      => "All Posts",
+        user         => $user,
+        form         => 'series.tx',
+        child_form   => 'series.tx',
+        aclname      => 'posts',
+    },
 ];
 
 #$search_info->add(@$series,@extra_series);

+ 2 - 1
bin/migrate4.pl

@@ -10,10 +10,11 @@ use FindBin;
 use lib "$FindBin::Bin/../lib";
 
 use Trog::SQLite;
+
 sub _dbh {
     my $file   = 'schema/auth.schema';
     my $dbname = "config/auth.db";
-    return Trog::SQLite::dbh($file,$dbname);
+    return Trog::SQLite::dbh( $file, $dbname );
 }
 
 my $dbh = _dbh();

+ 2 - 1
bin/migrate5.pl

@@ -10,10 +10,11 @@ use FindBin;
 use lib "$FindBin::Bin/../lib";
 
 use Trog::SQLite;
+
 sub _dbh {
     my $file   = 'schema/auth.schema';
     my $dbname = "config/auth.db";
-    return Trog::SQLite::dbh($file,$dbname);
+    return Trog::SQLite::dbh( $file, $dbname );
 }
 
 my $dbh = _dbh();

+ 29 - 28
bin/migrate6.pl

@@ -10,10 +10,11 @@ use FindBin;
 use lib "$FindBin::Bin/../lib";
 
 use Trog::SQLite;
+
 sub _dbh {
     my $file   = 'schema/auth.schema';
     my $dbname = "config/auth.db";
-    return Trog::SQLite::dbh($file,$dbname);
+    return Trog::SQLite::dbh( $file, $dbname );
 }
 
 my $dbh = _dbh();
@@ -28,32 +29,32 @@ use URI::Escape;
 use Data::Dumper;
 
 my $global_changes;
-opendir(my $dh, 'data/files');
-while (my $entry = readdir $dh) {
-	my $fname = "data/files/$entry";
-	next unless -f $fname;
-	my $contents = File::Slurper::read_binary($fname);
-	my $decoded = JSON::MaybeXS::decode_json($contents);
-	next unless List::Util::any { $_->{is_profile} } @$decoded;
-
-	# If the title on the profile post responsds to a username, then let's change that to a display name
-	my $made_changes;
-	foreach my $revision (@$decoded) {
-		my $user = $revision->{title};
-		my $display_name = Trog::Auth::username2display($user);
-		next unless $display_name;
-		print "converting $user to display name $display_name\n";
-		$revision->{title}      = $display_name;
-		$revision->{local_href} = "/users/$display_name";
-		$made_changes = 1;
-	}
-	next unless $made_changes;
-	
-	print "Writing changes to $fname\n";
-	my $encoded = JSON::MaybeXS::encode_json($decoded);
-	File::Slurper::write_binary($fname, $encoded);
-
-	# Next, waste and rebuild the posts index for these user posts
-	$global_changes=1;
+opendir( my $dh, 'data/files' );
+while ( my $entry = readdir $dh ) {
+    my $fname = "data/files/$entry";
+    next unless -f $fname;
+    my $contents = File::Slurper::read_binary($fname);
+    my $decoded  = JSON::MaybeXS::decode_json($contents);
+    next unless List::Util::any { $_->{is_profile} } @$decoded;
+
+    # If the title on the profile post responsds to a username, then let's change that to a display name
+    my $made_changes;
+    foreach my $revision (@$decoded) {
+        my $user         = $revision->{title};
+        my $display_name = Trog::Auth::username2display($user);
+        next unless $display_name;
+        print "converting $user to display name $display_name\n";
+        $revision->{title}      = $display_name;
+        $revision->{local_href} = "/users/$display_name";
+        $made_changes           = 1;
+    }
+    next unless $made_changes;
+
+    print "Writing changes to $fname\n";
+    my $encoded = JSON::MaybeXS::encode_json($decoded);
+    File::Slurper::write_binary( $fname, $encoded );
+
+    # Next, waste and rebuild the posts index for these user posts
+    $global_changes = 1;
 }
 print "Changes made.  Please rebuild the posts index.\n" if $global_changes;

+ 2 - 2
bin/tcms-useradd

@@ -7,9 +7,9 @@ use FindBin::libs;
 
 use Trog::Auth;
 
-my ($user, $display_name, $pass, $contactemail) = @ARGV;
+my ( $user, $display_name, $pass, $contactemail ) = @ARGV;
 
 # TODO better arg handling, etc
 
 Trog::Auth::killsession($user);
-Trog::Auth::useradd($user, $display_name, $pass, ['admin'], $contactemail);
+Trog::Auth::useradd( $user, $display_name, $pass, ['admin'], $contactemail );

+ 3 - 3
bin/totp

@@ -7,10 +7,10 @@ use FindBin::libs;
 
 use Trog::Auth;
 
-my $user = shift @ARGV;
+my $user   = shift @ARGV;
 my $domain = shift @ARGV;
 
-die "Must provide a user" unless $user;
+die "Must provide a user"   unless $user;
 die "Must provide a domain" unless $domain;
 
 my $dbh = Trog::Auth::_dbh();
@@ -19,4 +19,4 @@ my $rows = $dbh->selectall_arrayref( "SELECT name, totp_secret FROM user WHERE n
 die "no such user" unless @$rows;
 my $secret = $rows->[0]->{totp_secret};
 
-print Trog::Auth::expected_totp_code(undef, $secret)."\n";
+print Trog::Auth::expected_totp_code( undef, $secret ) . "\n";

+ 2 - 2
call.pl

@@ -16,8 +16,8 @@ my %env = (
 
 my $limit = $ARGV[3] || 1;
 our $app = \&TCMS::app;
-for (0..$limit) {
-    my $out = $app->(\%env);
+for ( 0 .. $limit ) {
+    my $out = $app->( \%env );
     print $out->[2][0];
 }
 

+ 25 - 20
lib/TCMS.pm

@@ -19,7 +19,7 @@ use DateTime::Format::HTTP();
 use CGI::Cookie ();
 use File::Basename();
 use IO::Compress::Gzip();
-use Time::HiRes      qw{gettimeofday tv_interval};
+use Time::HiRes qw{gettimeofday tv_interval};
 use HTTP::Parser::XS qw{HEADERS_AS_HASHREF};
 use List::Util;
 use URI();
@@ -54,7 +54,7 @@ $routes{'/robots.txt'} = {
     method   => 'GET',
     callback => \&robots,
 };
-my $routes_immutable = clone(\%routes);
+my $routes_immutable = clone( \%routes );
 
 my %aliases = $data->aliases();
 
@@ -64,16 +64,17 @@ my %etags;
 
 # Wrap app to return *our* error handler instead of Plack::Util::run_app's
 my $cur_query = {};
+
 sub app {
     return eval { _app(@_) } || do {
-		my $env = shift;
+        my $env = shift;
         $env->{'psgi.errors'}->print($@);
 
-		# Redact the stack trace past line 1, it usually has things which should not be shown
-		$cur_query->{message} = $@;
-		$cur_query->{message} =~ s/\n.*//g if $cur_query->{message};
+        # Redact the stack trace past line 1, it usually has things which should not be shown
+        $cur_query->{message} = $@;
+        $cur_query->{message} =~ s/\n.*//g if $cur_query->{message};
 
-		return _error($cur_query);
+        return _error($cur_query);
     };
 }
 
@@ -98,14 +99,14 @@ sub _app {
     my $env = shift;
 
     # Discard the path used in the log, it's too long and enough 4xx error code = ban
-    return _toolong({ method => $env->{REQUEST_METHOD}, fullpath => '...' }) if length( $env->{REQUEST_URI} ) > 2048;
+    return _toolong( { method => $env->{REQUEST_METHOD}, fullpath => '...' } ) if length( $env->{REQUEST_URI} ) > 2048;
 
     my $requestid = Trog::Utils::uuid();
     Trog::Log::uuid($requestid);
 
     # Various stuff important for logging requests
     state $domain = eval { Sys::Hostname::hostname() } // $env->{HTTP_X_FORWARDED_HOST} || $env->{HTTP_HOST};
-    my $path = $env->{PATH_INFO};
+    my $path   = $env->{PATH_INFO};
     my $port   = $env->{HTTP_X_FORWARDED_PORT} // $env->{HTTP_PORT};
     my $pport  = defined $port ? ":$port" : "";
     my $scheme = $env->{'psgi.url_scheme'} // 'http';
@@ -169,6 +170,7 @@ sub _app {
 
     # It's mod_rewrite!
     $path = '/index' if $path eq '/';
+
     #XXX this is hardcoded in browsers, so just rewrite the path
     $path = '/img/icon/favicon.ico' if $path eq '/favicon.ico';
 
@@ -199,7 +201,7 @@ sub _app {
     my $active_user = '';
     $Trog::Log::user = 'nobody';
     if ( exists $cookies->{tcmslogin} ) {
-        $active_user = Trog::Auth::session2user( $cookies->{tcmslogin}->value );
+        $active_user     = Trog::Auth::session2user( $cookies->{tcmslogin}->value );
         $Trog::Log::user = $active_user if $active_user;
     }
     $query->{user_acls} = [];
@@ -252,6 +254,7 @@ sub _app {
     #Handle regex/capture routes
     if ( !exists $routes{$path} ) {
         my @captures;
+
         # TODO can optimize by having separate hashes for capture/non-capture routes
         foreach my $pattern ( keys(%routes) ) {
             @captures = $path =~ m/^$pattern$/;
@@ -270,8 +273,8 @@ sub _app {
     $query->{deflate}  = $deflate;
     $query->{user}     = $active_user;
 
-    return _forbidden($query)  if exists $routes{$path}{auth} && !$active_user;
-    return _notfound($query)   unless exists $routes{$path} && ref $routes{$path} eq 'HASH' && keys(%{$routes{$path}});
+    return _forbidden($query) if exists $routes{$path}{auth} && !$active_user;
+    return _notfound($query) unless exists $routes{$path} && ref $routes{$path} eq 'HASH' && keys( %{ $routes{$path} } );
     return _badrequest($query) unless grep { $env->{REQUEST_METHOD} eq $_ } ( $routes{$path}{method} || '', 'HEAD' );
 
     @{$query}{ keys( %{ $routes{$path}{'data'} } ) } = values( %{ $routes{$path}{'data'} } ) if ref $routes{$path}{'data'} eq 'HASH' && %{ $routes{$path}{'data'} };
@@ -289,8 +292,9 @@ sub _app {
     $query->{port}         = $port;
     $query->{lang}         = $lang;
     $query->{accept}       = $accept;
+
     # Redirecting somewhere naughty not allow
-    $query->{to}           = URI->new($query->{to} // '')->path() || $query->{to} if $query->{to};
+    $query->{to} = URI->new( $query->{to} // '' )->path() || $query->{to} if $query->{to};
 
     #XXX there is a trick to now use strict refs, but I don't remember it right at the moment
     {
@@ -318,22 +322,22 @@ This is a "special" route as it needs to know about all the routes in order to d
 
 sub robots ($query) {
     state $etag = "robots-" . time();
+
     # If there's a 'capture' route, we need to format it correctly.
-	state @banned = map { exists $routes{$_}{robot_name} ? $routes{$_}{robot_name} : $_ } grep { $routes{$_}{noindex} } sort keys(%routes);
+    state @banned = map { exists $routes{$_}{robot_name} ? $routes{$_}{robot_name} : $_ } grep { $routes{$_}{noindex} } sort keys(%routes);
 
     return Trog::Renderer->render(
         contenttype => 'text/plain',
-        template => 'robots.tx',
-        data => {
+        template    => 'robots.tx',
+        data        => {
             etag   => $etag,
-			banned => \@banned,
+            banned => \@banned,
             %$query,
         },
         code => 200,
     );
 }
 
-
 sub _generic ( $type, $query ) {
     return _static( "$type.z", $query->{start}, $query->{streaming} ) if -f "www/statics/$type.z";
     return _static( $type,     $query->{start}, $query->{streaming} ) if -f "www/statics/$type";
@@ -362,12 +366,12 @@ sub _badrequest ($query) {
     return _generic( 'badrequest', $query );
 }
 
-sub _toolong($query) {
+sub _toolong ($query) {
     INFO("$query->{method} 419 $query->{fullpath}");
     return _generic( 'toolong', {} );
 }
 
-sub _error($query) {
+sub _error ($query) {
     INFO("$query->{method} 500 $query->{fullpath}");
     return _generic( 'error', $query );
 }
@@ -375,6 +379,7 @@ sub _error($query) {
 sub _static ( $fullpath, $path, $start, $streaming, $last_fetch = 0 ) {
 
     DEBUG("Rendering static for $path");
+
     # XXX because of psgi I can't just vomit the file directly
     if ( open( my $fh, '<', "www/statics/$path" ) ) {
         my $headers = '';

+ 31 - 29
lib/Trog/Auth.pm

@@ -97,7 +97,6 @@ sub username2display ($name) {
     return $rows->[0]{display_name};
 }
 
-
 =head2 acls4user(STRING username) = ARRAYREF
 
 Return the list of ACLs belonging to the user.
@@ -139,7 +138,7 @@ sub totp ( $user, $domain ) {
 
     # Generate a new secret if needed
     my $secret_is_generated = 0;
-    if (!$secret) {
+    if ( !$secret ) {
         $secret_is_generated = 1;
         $totp->valid_secret();
         $secret = $totp->secret();
@@ -156,7 +155,8 @@ sub totp ( $user, $domain ) {
     );
 
     my $qr = "$user\@$domain.bmp";
-    if ( $secret_is_generated ) {
+    if ($secret_is_generated) {
+
         # Liquidate the QR code if it's already there
         unlink "totp/$qr" if -f "totp/$qr";
 
@@ -200,8 +200,8 @@ Return the expected totp code at a given time with a given secret.
 sub expected_totp_code {
     my ( $self, $secret, $when, $digits ) = @_;
     $self //= _totp();
-    $when   //= time;
-    my $period  = 30;
+    $when //= time;
+    my $period = 30;
     $digits //= 6;
     $self->{secret} = $secret;
 
@@ -225,9 +225,9 @@ Clear the totp codes for provided user
 
 =cut
 
-sub clear_totp($user) {
+sub clear_totp ($user) {
     my $dbh = _dbh();
-    my $res = $dbh->do("UPDATE user SET totp_secret=null WHERE name=?", undef, $user) or die "Could not clear user TOTP secrets";
+    my $res = $dbh->do( "UPDATE user SET totp_secret=null WHERE name=?", undef, $user ) or die "Could not clear user TOTP secrets";
     return !!$res;
 }
 
@@ -249,7 +249,7 @@ sub mksession ( $user, $pass, $token ) {
     my $salt   = $records->[0]->{salt};
     my $hash   = sha256( $pass . $salt );
     my $worked = $dbh->selectall_arrayref( "SELECT name, totp_secret FROM user WHERE hash=? AND name = ?", { Slice => {} }, $hash, $user );
-    if (!(ref $worked eq 'ARRAY' && @$worked)) {
+    if ( !( ref $worked eq 'ARRAY' && @$worked ) ) {
         INFO("Failed login for user $user");
         return '';
     }
@@ -259,12 +259,13 @@ sub mksession ( $user, $pass, $token ) {
     # Validate the 2FA Token.  If we have no secret, allow login so they can see their QR code, and subsequently re-auth.
     if ($secret) {
         return '' unless $token;
-        DEBUG("TOTP Auth: Sent code $token, expect ".expected_totp_code($totp, $secret));
+        DEBUG( "TOTP Auth: Sent code $token, expect " . expected_totp_code( $totp, $secret ) );
+
         #XXX we have to force the secret into compliance, otherwise it generates one on the fly, oof
         $totp->{secret} = $secret;
         my $rc = $totp->validate_otp( otp => $token, secret => $secret, tolerance => 3, period => 30, digits => 6 );
         INFO("TOTP Auth failed for user $user") unless $rc;
-        return '' unless $rc;
+        return ''                               unless $rc;
     }
 
     # Issue cookie
@@ -294,12 +295,12 @@ Returns True or False (likely false when user already exists).
 =cut
 
 sub useradd ( $user, $displayname, $pass, $acls, $contactemail ) {
-	die "No username set!" unless $user;
+    die "No username set!"     unless $user;
     die "No display name set!" unless $displayname;
     die "Username and display name cannot be the same" if $user eq $displayname;
-	die "No password set for user!" unless $pass;
-	die "ACLs must be array" unless is_arrayref($acls);
-	die "No contact email set for user!" unless $contactemail;
+    die "No password set for user!"      unless $pass;
+    die "ACLs must be array"             unless is_arrayref($acls);
+    die "No contact email set for user!" unless $contactemail;
 
     my $dbh  = _dbh();
     my $salt = create_uuid();
@@ -314,31 +315,32 @@ sub useradd ( $user, $displayname, $pass, $acls, $contactemail ) {
     return 1;
 }
 
-sub add_change_request ( %args ) {
-    my $dbh  = _dbh();
-    my $res  = $dbh->do( "INSERT INTO change_request (username,token,type,secret) VALUES (?,?,?,?)", undef, $args{user}, $args{token}, $args{type}, $args{secret} );
+sub add_change_request (%args) {
+    my $dbh = _dbh();
+    my $res = $dbh->do( "INSERT INTO change_request (username,token,type,secret) VALUES (?,?,?,?)", undef, $args{user}, $args{token}, $args{type}, $args{secret} );
     return !!$res;
 }
 
-sub process_change_request ( $token ) {
+sub process_change_request ($token) {
     my $dbh  = _dbh();
     my $rows = $dbh->selectall_arrayref( "SELECT username, display_name, type, secret, contact_email FROM change_request_full WHERE processed=0 AND token=?", { Slice => {} }, $token );
     return 0 unless ref $rows eq 'ARRAY' && @$rows;
 
-    my $user = $rows->[0]{username};
-    my $display = $rows->[0]{display_name};
-    my $type = $rows->[0]{type};
-    my $secret = $rows->[0]{secret};
+    my $user         = $rows->[0]{username};
+    my $display      = $rows->[0]{display_name};
+    my $type         = $rows->[0]{type};
+    my $secret       = $rows->[0]{secret};
     my $contactemail = $rows->[0]{contact_email};
 
     state %dispatch = (
         reset_pass => sub {
-            my ($user, $pass) = @_;
-			#XXX The fact that this is an INSERT OR REPLACE means all the entries in change_request for this user will get cascade wiped.  Which is good, as the secrets aren't salted.
-			# This is also why we have to snag the user's ACLs or they will be wiped.
-			my @acls = acls4user($user);
+            my ( $user, $pass ) = @_;
+
+            #XXX The fact that this is an INSERT OR REPLACE means all the entries in change_request for this user will get cascade wiped.  Which is good, as the secrets aren't salted.
+            # This is also why we have to snag the user's ACLs or they will be wiped.
+            my @acls = acls4user($user);
             useradd( $user, $display, $pass, \@acls, $contactemail ) or do {
-               return '';
+                return '';
             };
             killsession($user);
             return "Password set to $pass for $user";
@@ -352,8 +354,8 @@ sub process_change_request ( $token ) {
             return "TOTP auth turned off for $user";
         },
     );
-    my $res = $dispatch{$type}->($user, $secret);
-    $dbh->do("UPDATE change_request SET processed=1 WHERE token=?", undef, $token) or do {
+    my $res = $dispatch{$type}->( $user, $secret );
+    $dbh->do( "UPDATE change_request SET processed=1 WHERE token=?", undef, $token ) or do {
         FATAL("Could not set job with token $token to completed!");
     };
     return $res;

+ 8 - 8
lib/Trog/Component/EmojiPicker.pm

@@ -11,23 +11,23 @@ use Trog::Renderer;
 sub render () {
     state %categorized;
 
-    if (!%categorized) {
+    if ( !%categorized ) {
         my $file = 'www/scripts/list.min.json';
         die "Run make prereq-frontend first" unless -f $file;
 
-        my $raw = File::Slurper::read_binary($file);
+        my $raw    = File::Slurper::read_binary($file);
         my $emojis = Cpanel::JSON::XS::decode_json($raw);
-        foreach my $emoji (@{$emojis->{emojis}}) {
-            $categorized{$emoji->{category}} //= [];
-            push(@{$categorized{$emoji->{category}}}, $emoji->{emoji});
+        foreach my $emoji ( @{ $emojis->{emojis} } ) {
+            $categorized{ $emoji->{category} } //= [];
+            push( @{ $categorized{ $emoji->{category} } }, $emoji->{emoji} );
         }
     }
 
     return Trog::Renderer->render(
         contenttype => 'text/html',
-        component => 1,
-        template  => 'emojis.tx',
-        data      => {
+        component   => 1,
+        template    => 'emojis.tx',
+        data        => {
             categories => \%categorized,
         },
     );

+ 3 - 1
lib/Trog/Data/FlatFile.pm

@@ -73,7 +73,9 @@ sub read ( $self, $query = {} ) {
             next;
         }
         my $parsed;
-        capture_merged { $parsed = eval { $parser->decode($slurped) } };
+        capture_merged {
+            $parsed = eval { $parser->decode($slurped) }
+        };
         if ( !$parsed ) {
 
             # Try and read it in binary in case it was encoded incorrectly the first time

+ 5 - 3
lib/Trog/DataModule.pm

@@ -98,6 +98,7 @@ sub _fixup ( $self, @filtered ) {
         my $subj = $_;
         foreach my $param (qw{href preview video_href audio_href local_href wallpaper}) {
             next unless exists $subj->{$param};
+
             #XXX I don't remember what this fixes, but it also breaks things.  URI::Escape usage instead is indicated.
             $subj->{$param} =~ s/ /%20/g;
         }
@@ -106,9 +107,10 @@ sub _fixup ( $self, @filtered ) {
         my $is_user_page = List::Util::any { $_ eq 'about' } @{ $subj->{tags} };
         if ( !exists $subj->{local_href} ) {
             $subj->{local_href} = "/posts/$subj->{id}";
+
             #XXX this needs to be correctly populated in the form?
             if ($is_user_page) {
-                my $display_name = $subj->{display_name} || Trog::Auth::username2display($subj->{user});
+                my $display_name = $subj->{display_name} || Trog::Auth::username2display( $subj->{user} );
                 die "No display name for user!" unless $display_name;
                 $subj->{local_href} = "/users/$display_name";
             }
@@ -149,11 +151,11 @@ sub filter ( $self, $query, @filtered ) {
 
     #Filter out posts which are too old
     #Coerce older into numeric
-    if ($query->{older}) {
+    if ( $query->{older} ) {
         $query->{older} =~ s/[^0-9]//g;
         @filtered = grep { $_->{created} < $query->{older} } @filtered;
     }
-    if ($query->{newer}) {
+    if ( $query->{newer} ) {
         $query->{newer} =~ s/[^0-9]//g;
         @filtered = grep { $_->{created} > $query->{newer} } @filtered;
     }

+ 44 - 43
lib/Trog/Email.pm

@@ -13,57 +13,58 @@ use Trog::Auth;
 use Trog::Log qw{:all};
 use Trog::Renderer;
 
-sub contact ($user, $from, $subject, $data) {
+sub contact ( $user, $from, $subject, $data ) {
     my $email = Trog::Auth::email4user($user);
     die "No contact email set for user $user!" unless $email;
 
-	my $render = Trog::Renderer->render(
-		contenttype => 'multipart/related',
-		code		 => 200,
-		template     => $data->{template},
-		data         => {
-			method       => 'EMAIL',
-			# Important - this will prevent caching
-			route        => '',
-			%$data,
-		},
-	);
+    my $render = Trog::Renderer->render(
+        contenttype => 'multipart/related',
+        code        => 200,
+        template    => $data->{template},
+        data        => {
+            method => 'EMAIL',
 
-	my $text = $render->{text}[2][0];
-	my $html = $render->{html}[2][0];
+            # Important - this will prevent caching
+            route => '',
+            %$data,
+        },
+    );
 
-	my @parts = (
-		Email::MIME->create(
-			attributes => {
-				content_type => "text/plain",
-				disposition  => "attachment",
-				charset      => 'UTF-8',
-			},
-			body => $text,
-		),
-		Email::MIME->create(
-			attributes => {
-				content_type => "text/html",
-				disposition => "attachment",
-				charset     => "UTF-8",
-			},
-			body => $html,
-		),
-	);
+    my $text = $render->{text}[2][0];
+    my $html = $render->{html}[2][0];
 
-	my $mail = Email::MIME->create(
-		header_str => [
-			From => $from,
-			To => [$email],
-			Subject => $subject,
-		],
-		parts      => \@parts,
-	);
+    my @parts = (
+        Email::MIME->create(
+            attributes => {
+                content_type => "text/plain",
+                disposition  => "attachment",
+                charset      => 'UTF-8',
+            },
+            body => $text,
+        ),
+        Email::MIME->create(
+            attributes => {
+                content_type => "text/html",
+                disposition  => "attachment",
+                charset      => "UTF-8",
+            },
+            body => $html,
+        ),
+    );
+
+    my $mail = Email::MIME->create(
+        header_str => [
+            From    => $from,
+            To      => [$email],
+            Subject => $subject,
+        ],
+        parts => \@parts,
+    );
 
     Email::Sender::Simple->try_to_send($mail) or do {
-		FATAL("Could not send email from $from to $email!");
-	};
-	return 1;
+        FATAL("Could not send email from $from to $email!");
+    };
+    return 1;
 }
 
 1;

+ 1 - 1
lib/Trog/Log.pm

@@ -65,7 +65,7 @@ sub _log {
     my ( $msg, $level ) = @_;
 
     $msg //= "No message passed.  This is almost certainly a bug. ";
-    
+
     #XXX Log lines must start as an ISO8601 date, anything else breaks fail2ban's beautiful mind
     my $tstamp = strftime "%Y-%m-%dT%H:%M:%SZ", gmtime;
     my $uuid   = uuid();

+ 15 - 15
lib/Trog/Renderer.pm

@@ -45,34 +45,34 @@ The idea is that components will be concatenated to other rendered templates unt
 
 =cut
 
-sub render ($class, %options) {
+sub render ( $class, %options ) {
     local $@;
     my $renderer;
-    return _yeet($renderer, "Renderer requires a valid content type to be passed", %options) unless $options{contenttype};
-    my $rendertype = $Trog::Vars::byct{$options{contenttype}};
-    return _yeet($renderer, "Renderer requires a known content type (used $options{contenttype}) to be passed", %options) unless $rendertype;
+    return _yeet( $renderer, "Renderer requires a valid content type to be passed", %options ) unless $options{contenttype};
+    my $rendertype = $Trog::Vars::byct{ $options{contenttype} };
+    return _yeet( $renderer, "Renderer requires a known content type (used $options{contenttype}) to be passed", %options ) unless $rendertype;
     $renderer = $renderers{$rendertype};
-    return _yeet($renderer, "Renderer for $rendertype is not defined!", %options) unless $renderer;
-    return _yeet($renderer, "Status code not provided", %options) if !$options{code} && !$options{component};
-    return _yeet($renderer, "Template data not provided", %options) unless $options{data};
-    return _yeet($renderer, "Template not provided", %options) unless $options{template};
+    return _yeet( $renderer, "Renderer for $rendertype is not defined!", %options ) unless $renderer;
+    return _yeet( $renderer, "Status code not provided",                 %options ) if !$options{code} && !$options{component};
+    return _yeet( $renderer, "Template data not provided",               %options ) unless $options{data};
+    return _yeet( $renderer, "Template not provided",                    %options ) unless $options{template};
 
     #TODO future - save the components too and then compose them?
-    my $skip_save = !$options{component} || !$options{data}{route} || $options{data}{has_query} || $options{data}{user} || ($options{code} // 0) != 200 || Trog::Log::is_debug();
+    my $skip_save = !$options{component} || !$options{data}{route} || $options{data}{has_query} || $options{data}{user} || ( $options{code} // 0 ) != 200 || Trog::Log::is_debug();
 
     my $ret;
     local $@;
     eval {
         $ret = $renderer->(%options);
-        save_render( $options{data}, $ret->[2], %{$ret->[1]}) unless $skip_save;
+        save_render( $options{data}, $ret->[2], %{ $ret->[1] } ) unless $skip_save;
         1;
     } or do {
-        return _yeet($renderer, $@, %options);
+        return _yeet( $renderer, $@, %options );
     };
     return $ret;
 }
 
-sub _yeet ($renderer, $error, %options) {
+sub _yeet ( $renderer, $error, %options ) {
     WARN($error);
 
     # All-else fails error page
@@ -80,10 +80,10 @@ sub _yeet ($renderer, $error, %options) {
     local $@;
     eval {
         $ret = $renderer->(
-            code => 500,
-            template => '500.tx',
+            code        => 500,
+            template    => '500.tx',
             contenttype => 'text/html',
-            data => { %options, content => "<h1>500 Internal Server Error</h1>$error" },
+            data        => { %options, content => "<h1>500 Internal Server Error</h1>$error" },
         );
         1;
     } or do {

+ 15 - 15
lib/Trog/Renderer/Base.pm

@@ -26,8 +26,8 @@ our %renderers;
 sub render (%options) {
     die "Templated renders require a template to be passed" unless $options{template};
 
-    my $template_dir = Trog::Themes::template_dir($options{template}, $options{contenttype}, $options{component});
-    my $t = "$template_dir/$options{template}";
+    my $template_dir = Trog::Themes::template_dir( $options{template}, $options{contenttype}, $options{component} );
+    my $t            = "$template_dir/$options{template}";
     die "Templated renders require an existing template to be passed, got $template_dir/$options{template}" unless -f $t || -s $t;
 
     #TODO make this work with posts all the time
@@ -49,16 +49,16 @@ sub render (%options) {
     );
 
     my $code = $options{code};
-    my $body = encode_utf8($renderers{$template_dir}->render($options{template}, $options{data}));
+    my $body = encode_utf8( $renderers{$template_dir}->render( $options{template}, $options{data} ) );
 
     # Users can supply a post_processor to futz with the output (such as with minifiers) if they wish.
     $body = $options{post_processor}->($body) if $options{post_processor} && ref $options{post_processor} eq 'CODE';
 
     # Users can supply custom headers as part of the data in options.
-    my %headers = headers(\%options, $body);
+    my %headers = headers( \%options, $body );
 
     return $body if $options{component};
-    return [$code, [%headers], [$body]] unless $options{deflate};
+    return [ $code, [%headers], [$body] ] unless $options{deflate};
 
     $headers{"Content-Encoding"} = "gzip";
     my $dfh;
@@ -69,16 +69,16 @@ sub render (%options) {
     return [ $code, [%headers], [$dfh] ];
 }
 
-sub headers ($options,$body) {
-    my $query = $options->{data};
-    my $uh = ref $options->{headers} eq 'HASH' ? $options->{headers} : {};
-    my $ct = $options->{contenttype} eq 'text/html' ? "text/html; charset=UTF-8" : "$options->{contenttype};";
+sub headers ( $options, $body ) {
+    my $query   = $options->{data};
+    my $uh      = ref $options->{headers} eq 'HASH'      ? $options->{headers}        : {};
+    my $ct      = $options->{contenttype} eq 'text/html' ? "text/html; charset=UTF-8" : "$options->{contenttype};";
     my %headers = (
-        'Content-Type'   => $ct,
-        'Content-Length' => length($body),
-        'Cache-Control'  => $query->{cachecontrol} // $Trog::Vars::cache_control{revalidate},
+        'Content-Type'           => $ct,
+        'Content-Length'         => length($body),
+        'Cache-Control'          => $query->{cachecontrol} // $Trog::Vars::cache_control{revalidate},
         'X-Content-Type-Options' => 'nosniff',
-        'Vary'           => 'Accept-Encoding',
+        'Vary'                   => 'Accept-Encoding',
         %$uh,
     );
 
@@ -92,13 +92,13 @@ sub headers ($options,$body) {
     #CSP. Yet another layer of 'no mixed content' plus whitelisted execution of remote resources.
     my $scheme = $query->{scheme} ? "$query->{scheme}:" : '';
 
-    my $conf = Trog::Config::get();
+    my $conf  = Trog::Config::get();
     my $sites = $conf->param('security.allow_embeds_from') // '';
     $headers{'Content-Security-Policy'} .= ";default-src $scheme 'self' 'unsafe-eval' 'unsafe-inline' $sites";
     $headers{'Content-Security-Policy'} .= ";object-src 'none'";
 
     # Force https if we are https
-    $headers{'Strict-Transport-Security'} = 'max-age=63072000' if ($query->{scheme} // '') eq 'https';
+    $headers{'Strict-Transport-Security'} = 'max-age=63072000' if ( $query->{scheme} // '' ) eq 'https';
 
     # We only set etags when users are logged in, cause we don't use statics
     $headers{'ETag'} = $query->{etag} if $query->{etag} && $query->{user};

+ 1 - 1
lib/Trog/Renderer/blob.pm

@@ -17,7 +17,7 @@ sub render (%options) {
     my $code    = delete $options{code};
     my $headers = delete $options{headers};
     my $body    = $options{body};
-    return [$code, [$headers], [$body]];
+    return [ $code, [$headers], [$body] ];
 }
 
 1;

+ 3 - 3
lib/Trog/Renderer/email.pm

@@ -20,9 +20,9 @@ Render emails with both HTML and email parts, and inline all CSS/JS/Images.
 
 # TODO inlining
 sub render (%options) {
-    my $text = Trog::Renderer::Base::render(%options, contenttype => 'text/plain');
-	my $html = Trog::Renderer::html::render(%options, contenttype => 'text/html');
-	return { text => $text, html => $html };
+    my $text = Trog::Renderer::Base::render( %options, contenttype => 'text/plain' );
+    my $html = Trog::Renderer::html::render( %options, contenttype => 'text/html' );
+    return { text => $text, html => $html };
 }
 
 1;

+ 3 - 3
lib/Trog/Renderer/json.pm

@@ -15,7 +15,7 @@ Render JSON.  Rather than be templated, we just run the input thru the encoder.
 =cut
 
 sub render (%options) {
-    my $code    = delete $options{code} // 200;
+    my $code    = delete $options{code}    // 200;
     my $headers = delete $options{headers} // {};
 
     my %h = (
@@ -26,8 +26,8 @@ sub render (%options) {
     delete $options{contenttype};
     delete $options{template};
 
-    my $body    = encode_json($options{data});
-    return [$code, [%h], [$body]];
+    my $body = encode_json( $options{data} );
+    return [ $code, [%h], [$body] ];
 }
 
 1;

+ 131 - 119
lib/Trog/Routes/HTML.pm

@@ -49,7 +49,7 @@ our $categorybar  = 'categories.tx';
 our %routes = (
     default => {
         callback => \&Trog::Routes::HTML::setup,
-		noindex  => 1,
+        noindex  => 1,
     },
     '/index' => {
         method   => 'GET',
@@ -132,25 +132,26 @@ our %routes = (
         callback => \&Trog::Routes::HTML::manual,
     },
     '/password_reset' => {
-        method => 'GET',
+        method   => 'GET',
         callback => \&Trog::Routes::HTML::resetpass,
         noindex  => 1,
     },
     '/request_password_reset' => {
-        method => 'POST',
+        method   => 'POST',
         callback => \&Trog::Routes::HTML::do_resetpass,
         noindex  => 1,
     },
     '/request_totp_clear' => {
-        method => 'POST',
+        method   => 'POST',
         callback => \&Trog::Routes::HTML::do_totp_clear,
         noindex  => 1,
     },
     '/processed' => {
-        method => 'GET',
+        method   => 'GET',
         callback => \&Trog::Routes::HTML::processed,
         noindex  => 1,
     },
+
     # END FAIL2BAN ROUTES
 
     #TODO transform into posts?
@@ -208,7 +209,7 @@ our %routes = (
         callback => \&Trog::Routes::HTML::icon,
     },
     '/styles/rss-style.xsl' => {
-        method => 'GET',
+        method   => 'GET',
         callback => \&Trog::Routes::HTML::rss_style,
     },
 );
@@ -222,7 +223,8 @@ if ($Trog::Themes::theme_dir) {
         require $theme_mod;
         @routes{ keys(%Theme::routes) } = values(%Theme::routes);
         $themed = 1;
-    } else {
+    }
+    else {
         # Use the special "default" theme
         require Theme;
     }
@@ -247,8 +249,8 @@ sub index ( $query, $content = '', $i_styles = [] ) {
     return $content if ref $content eq "ARRAY";
 
     my @styles;
-    unshift( @styles, qw{embed.css}) if $query->{embed};
-    unshift( @styles, qw{screen.css structure.css});
+    unshift( @styles, qw{embed.css} ) if $query->{embed};
+    unshift( @styles, qw{screen.css structure.css} );
     push( @styles, @$i_styles );
     my @p_styles = qw{print.css};
 
@@ -267,17 +269,17 @@ sub index ( $query, $content = '', $i_styles = [] ) {
     # TO support theming we have to do things like this rather than with an include directive in the templates.
     my $htmltitle = Trog::Renderer->render( template => $htmltitle, data => $query, component => 1, contenttype => 'text/html' );
     return $htmltitle if ref $htmltitle eq 'ARRAY';
-    my $midtitle  = Trog::Renderer->render( template => $midtitle,  data => $query, component => 1, contenttype => 'text/html' );
+    my $midtitle = Trog::Renderer->render( template => $midtitle, data => $query, component => 1, contenttype => 'text/html' );
     return $midtitle if ref $midtitle eq 'ARRAY';
-    my $rightbar  = Trog::Renderer->render( template => $rightbar,  data => $query, component => 1, contenttype => 'text/html' );
+    my $rightbar = Trog::Renderer->render( template => $rightbar, data => $query, component => 1, contenttype => 'text/html' );
     return $rightbar if ref $rightbar eq 'ARRAY';
-    my $leftbar   = Trog::Renderer->render( template => $leftbar,   data => $query, component => 1, contenttype => 'text/html' );
+    my $leftbar = Trog::Renderer->render( template => $leftbar, data => $query, component => 1, contenttype => 'text/html' );
     return $leftbar if ref $leftbar eq 'ARRAY';
-    my $topbar    = Trog::Renderer->render( template => $topbar,    data => $query, component => 1, contenttype => 'text/html' );
+    my $topbar = Trog::Renderer->render( template => $topbar, data => $query, component => 1, contenttype => 'text/html' );
     return $topbar if ref $topbar eq 'ARRAY';
-    my $footbar   = Trog::Renderer->render( template => $footbar,   data => $query, component => 1, contenttype => 'text/html' );
+    my $footbar = Trog::Renderer->render( template => $footbar, data => $query, component => 1, contenttype => 'text/html' );
     return $footbar if ref $footbar eq 'ARRAY';
-    my $categorybar   = Trog::Renderer->render( template => $categorybar,   data => { %$query, categories => \@series}, component => 1, contenttype => 'text/html' );
+    my $categorybar = Trog::Renderer->render( template => $categorybar, data => { %$query, categories => \@series }, component => 1, contenttype => 'text/html' );
     return $categorybar if ref $categorybar eq 'ARRAY';
 
     return finish_render(
@@ -379,9 +381,9 @@ Implements the 4XX status codes.  Override templates named the same for theming
 sub _generic_route ( $rname, $code, $title, $query ) {
     $query->{code} = $code;
     $query->{route} //= $rname;
-    $query->{title} = $title;
+    $query->{title}    = $title;
     $query->{template} = "$rname.tx";
-    return Trog::Routes::HTML::index( $query );
+    return Trog::Routes::HTML::index($query);
 }
 
 sub notfound (@args) {
@@ -401,7 +403,7 @@ sub toolong (@args) {
 }
 
 sub error (@args) {
-    return _generic_route( 'error', 500, "Internal Server Error", @args);
+    return _generic_route( 'error', 500, "Internal Server Error", @args );
 }
 
 =head2 redirect, redirect_permanent, see_also
@@ -439,13 +441,13 @@ sub setup ($query) {
     File::Touch::touch("config/setup");
     Trog::Renderer->render(
         template => 'notconfigured.tx',
-        data => {
+        data     => {
             title       => 'tCMS Requires Setup to Continue...',
-            stylesheets => _build_themed_styles(['notconfigured.css']),
+            stylesheets => _build_themed_styles( ['notconfigured.css'] ),
             %$query,
         },
         contenttype => 'text/html',
-        code => 200,
+        code        => 200,
     );
 }
 
@@ -464,14 +466,14 @@ sub totp ($query) {
 
     return Trog::Routes::HTML::index(
         {
-            title       => 'Enable TOTP 2-Factor Auth',
-            theme_dir   => $Trog::Themes::td,
-            uri         => $uri,
-            qr          => $qr,
-            failure     => $failure,
-            message     => $message,
-            template    => 'totp.tx',
-            is_admin    => 1,
+            title     => 'Enable TOTP 2-Factor Auth',
+            theme_dir => $Trog::Themes::td,
+            uri       => $uri,
+            qr        => $qr,
+            failure   => $failure,
+            message   => $message,
+            template  => 'totp.tx',
+            is_admin  => 1,
             %$query,
         },
         undef,
@@ -505,6 +507,7 @@ sub login ($query) {
     my $has_totp = 0;
     if ( $query->{username} && $query->{password} ) {
         if ( !$hasusers ) {
+
             # Make the first user
             Trog::Auth::useradd( $query->{username}, $query->{display_name}, $query->{password}, ['admin'], $query->{contact_email} );
 
@@ -533,20 +536,20 @@ sub login ($query) {
     $query->{failed} //= -1;
     return Trog::Renderer->render(
         template => 'login.tx',
-        data => {
+        data     => {
             title       => 'tCMS 2 ~ Login',
             to          => $query->{to},
             failure     => int( $query->{failed} ),
             message     => int( $query->{failed} ) < 1 ? "Login Successful, Redirecting..." : "Login Failed.",
             btnmsg      => $btnmsg,
-            stylesheets => _build_themed_styles([qw{login.css}]),
+            stylesheets => _build_themed_styles( [qw{login.css}] ),
             theme_dir   => $Trog::Themes::td,
             has_users   => $hasusers,
             %$query,
         },
         headers     => $headers,
         contenttype => 'text/html',
-        code => 200,
+        code        => 200,
     );
 }
 
@@ -603,21 +606,21 @@ sub _setup_initial_db ( $dat, $user, $display_name, $contact_email ) {
             aliases        => [],
         },
         {
-            title      => $display_name,
-            data       => 'Default user',
-            preview    => '/img/avatar/humm.gif',
-            wallpaper  => '/img/sys/testpattern.jpg',
-            tags       => ['about'],
-            visibility => 'public',
-            acls       => ['admin'],
-            local_href => "/users/$display_name",
-			display_name => $display_name,
-			contact_email => $contact_email,
-            callback   => "Trog::Routes::HTML::users",
-            method     => 'GET',
-            user       => $user,
-            form       => 'profile.tx',
-            aliases    => [],
+            title         => $display_name,
+            data          => 'Default user',
+            preview       => '/img/avatar/humm.gif',
+            wallpaper     => '/img/sys/testpattern.jpg',
+            tags          => ['about'],
+            visibility    => 'public',
+            acls          => ['admin'],
+            local_href    => "/users/$display_name",
+            display_name  => $display_name,
+            contact_email => $contact_email,
+            callback      => "Trog::Routes::HTML::users",
+            method        => 'GET',
+            user          => $user,
+            form          => 'profile.tx',
+            aliases       => [],
         },
     );
 }
@@ -640,7 +643,7 @@ Renders the configuration page, or redirects you back to the login page.
 
 =cut
 
-sub config ($query={}) {
+sub config ( $query = {} ) {
     return see_also('/login')                    unless $query->{user};
     return Trog::Routes::HTML::forbidden($query) unless grep { $_ eq 'admin' } @{ $query->{user_acls} };
 
@@ -649,8 +652,8 @@ sub config ($query={}) {
     #XXX ACHTUNG config::simple has this brain damaged behavior of returning a multiple element array when you access something that does not exist.
     #XXX straight up dying would be preferrable.
     #XXX anyways, this means you can NEVER NEVER NEVER access a param from within a hash directly.  YOU HAVE BEEN WARNED!
-    my $theme  = $conf->param('general.theme') // '';
-    my $dm     = $conf->param('general.data_model') // 'DUMMY';
+    my $theme  = $conf->param('general.theme')              // '';
+    my $dm     = $conf->param('general.data_model')         // 'DUMMY';
     my $embeds = $conf->param('security.allow_embeds_from') // '';
 
     return Trog::Routes::HTML::index(
@@ -687,19 +690,19 @@ Routes for user service of their authentication details.
 
 =cut
 
-sub resetpass($query) {
+sub resetpass ($query) {
     $query->{failure} //= -1;
 
     return Trog::Routes::HTML::index(
         {
-            title              => 'Request Authentication Resets',
-            theme_dir          => $Trog::Themes::td,
-            stylesheets        => [qw{config.css}],
-            scripts            => [qw{post.js}],
-            message            => $query->{message},
-            failure            => $query->{failure},
-            scheme             => $query->{scheme},
-            template           => 'resetpass.tx',
+            title       => 'Request Authentication Resets',
+            theme_dir   => $Trog::Themes::td,
+            stylesheets => [qw{config.css}],
+            scripts     => [qw{post.js}],
+            message     => $query->{message},
+            failure     => $query->{failure},
+            scheme      => $query->{scheme},
+            template    => 'resetpass.tx',
             %$query,
         },
         undef,
@@ -707,52 +710,56 @@ sub resetpass($query) {
     );
 }
 
-sub do_resetpass($query) {
+sub do_resetpass ($query) {
     my $user = $query->{username};
+
     # User Does not exist
     return Trog::Routes::HTML::forbidden($query) if !Trog::Auth::user_exists($user);
+
     # User exists, but is not logged in this session
     return Trog::Routes::HTML::forbidden($query) if !$query->{user} && Trog::Auth::user_has_session($user);
 
-    my $token = Trog::Utils::uuid();
+    my $token   = Trog::Utils::uuid();
     my $newpass = $query->{password} // Trog::Utils::uuid();
-    my $res = Trog::Auth::add_change_request( type => 'reset_pass', user => $user, secret => $newpass, token => $token );
-	die "Could not add auth change request!" unless $res;
+    my $res     = Trog::Auth::add_change_request( type => 'reset_pass', user => $user, secret => $newpass, token => $token );
+    die "Could not add auth change request!" unless $res;
 
     # If the user is logged in, just do the deed, otherwise send them the token in an email
-    if ($query->{user}) {
+    if ( $query->{user} ) {
         return see_also("/api/auth_change_request/$token");
     }
     Trog::Email::contact(
-		$user,
-		"root\@$query->{domain}",
-		"$query->{domain}: Password reset URL for $user",
-		{ uri => "$query->{scheme}://$query->{domain}/api/auth_change_request/$token", template => 'password_reset.tx' }
-	);
+        $user,
+        "root\@$query->{domain}",
+        "$query->{domain}: Password reset URL for $user",
+        { uri => "$query->{scheme}://$query->{domain}/api/auth_change_request/$token", template => 'password_reset.tx' }
+    );
     return see_also("/processed");
 }
 
-sub do_totp_clear($query) {
+sub do_totp_clear ($query) {
     my $user = $query->{username};
+
     # User Does not exist
     return Trog::Routes::HTML::forbidden($query) if !Trog::Auth::user_exists($user);
+
     # User exists, but is not logged in this session
     return Trog::Routes::HTML::forbidden($query) if !$query->{user} && Trog::Auth::user_has_session($user);
 
     my $token = Trog::Utils::uuid();
     my $res   = Trog::Auth::add_change_request( type => 'clear_totp', user => $user, token => $token );
-	die "Could not add auth change request!" unless $res;
+    die "Could not add auth change request!" unless $res;
 
     # If the user is logged in, just do the deed, otherwise send them the token in an email
-    if ($query->{user}) {
+    if ( $query->{user} ) {
         return see_also("/api/auth_change_request/$token");
     }
     Trog::Email::contact(
-		$user,
-		"root\@$query->{domain}",
-		"$query->{domain}: Password reset URL for $user",
-		{ uri => "$query->{scheme}://$query->{domain}/api/auth_change_request/$token", template => 'totp_reset.tx' }
-	);
+        $user,
+        "root\@$query->{domain}",
+        "$query->{domain}: Password reset URL for $user",
+        { uri => "$query->{scheme}://$query->{domain}/api/auth_change_request/$token", template => 'totp_reset.tx' }
+    );
     return see_also("/processed");
 }
 
@@ -793,9 +800,9 @@ sub config_save ($query) {
     return see_also('/login')                    unless $query->{user};
     return Trog::Routes::HTML::forbidden($query) unless grep { $_ eq 'admin' } @{ $query->{user_acls} };
 
-    $conf->param( 'general.theme',      $query->{theme} )      if defined $query->{theme};
-    $conf->param( 'general.data_model', $query->{data_model} ) if $query->{data_model};
-    $conf->param( 'security.allow_embeds_from', $query->{embeds} ) if $query->{embeds};
+    $conf->param( 'general.theme',              $query->{theme} )      if defined $query->{theme};
+    $conf->param( 'general.data_model',         $query->{data_model} ) if $query->{data_model};
+    $conf->param( 'security.allow_embeds_from', $query->{embeds} )     if $query->{embeds};
 
     $query->{failure} = 1;
     $query->{message} = "Failed to save configuration!";
@@ -878,16 +885,16 @@ sub profile ($query) {
     return Trog::Routes::HTML::forbidden($query) unless grep { $_ eq 'admin' } @{ $query->{user_acls} };
 
     #TODO allow new users to do something OTHER than be admins
-	#TODO allow username changes
+    #TODO allow username changes
     if ( $query->{password} || $query->{contact_email} ) {
-		my @acls = Trog::Auth::acls4user($query->{username}) || qw{admin};
+        my @acls = Trog::Auth::acls4user( $query->{username} ) || qw{admin};
         Trog::Auth::useradd( $query->{username}, $query->{display_name}, $query->{password}, \@acls, $query->{contact_email} );
     }
 
     #Make sure it is "self-authored", redact pw
     $query->{user} = delete $query->{username};
     delete $query->{password};
-	delete $query->{contact_email};
+    delete $query->{contact_email};
 
     return post_save($query);
 }
@@ -957,13 +964,14 @@ sub avatars ($query) {
 
     my @posts = _post_helper( $query, $tags, $query->{user_acls} );
     if (@posts) {
+
         # Set the eTag so that we don't get a re-fetch
         $query->{etag} = "$posts[0]{id}-$posts[0]{version}";
     }
 
     return Trog::Renderer->render(
         template => 'avatars.tx',
-        data => {
+        data     => {
             users => \@posts,
             %$query,
         },
@@ -982,10 +990,10 @@ sub users ($query) {
 
     # Capture the username
     my ( undef, undef, $display_name ) = split( /\//, $query->{route} );
-	$display_name = URI::Escape::uri_unescape($display_name);
+    $display_name = URI::Escape::uri_unescape($display_name);
 
-	my $username = Trog::Auth::display2username($display_name);
-	return notfound($query) unless $username;
+    my $username = Trog::Auth::display2username($display_name);
+    return notfound($query) unless $username;
 
     $query->{username} //= $username;
     push( @{ $query->{user_acls} }, 'public' );
@@ -1137,7 +1145,7 @@ sub posts ( $query, $direct = 0 ) {
         $_
     } _post_helper( {}, ['series'], $query->{user_acls} );
 
-    my $forms = Trog::Themes::templates_in_dir("forms", 'text/html', 1);
+    my $forms = Trog::Themes::templates_in_dir( "forms", 'text/html', 1 );
 
     my $edittype = $query->{primary_post} ? $query->{primary_post}->{child_form}          : $query->{form};
     my $tiled    = $query->{primary_post} ? !$is_admin && $query->{primary_post}->{tiled} : 0;
@@ -1172,7 +1180,7 @@ sub posts ( $query, $direct = 0 ) {
     #XXX is this even used?
     my $content = Trog::Renderer->render(
         template => 'posts.tx',
-        data => {
+        data     => {
             acls              => \@acls,
             can_edit          => $is_admin,
             forms             => $forms,
@@ -1210,6 +1218,7 @@ sub posts ( $query, $direct = 0 ) {
         contenttype => 'text/html',
         component   => 1,
     );
+
     # Something exploded
     return $content if ref $content eq "ARRAY";
 
@@ -1380,12 +1389,12 @@ sub sitemap ($query) {
     @to_map = sort @to_map unless $is_index;
     my $styles = ['sitemap.css'];
 
-    $query->{title} = "$query->{domain} : Sitemap";
+    $query->{title}    = "$query->{domain} : Sitemap";
     $query->{template} = 'sitemap.tx',
-    $query->{to_map} = \@to_map,
-    $query->{is_index} = $is_index,
-    $query->{route_type} = $route_type,
-    $query->{etag} = $etag;
+      $query->{to_map}     = \@to_map,
+      $query->{is_index}   = $is_index,
+      $query->{route_type} = $route_type,
+      $query->{etag}       = $etag;
 
     return Trog::Routes::HTML::index( $query, undef, $styles );
 }
@@ -1393,14 +1402,14 @@ sub sitemap ($query) {
 sub _rss ( $query, $subtitle, $posts ) {
 
     require XML::RSS;
-    my $rss = XML::RSS->new( version => '2.0', stylesheet => '/styles/rss-style.xsl' );
-    my $now = DateTime->from_epoch( epoch => time() );
+    my $rss  = XML::RSS->new( version => '2.0', stylesheet => '/styles/rss-style.xsl' );
+    my $now  = DateTime->from_epoch( epoch => time() );
     my $port = $query->{port} ? ":$query->{port}" : '';
     $rss->channel(
         title         => "$query->{domain}",
         subtitle      => $subtitle,
         link          => "http://$query->{domain}$port/$query->{route}?format=xml",
-        language      => 'en',                                                   #TODO localization
+        language      => 'en',                                                        #TODO localization
         description   => "$query->{domain} : $query->{route}",
         pubDate       => $now,
         lastBuildDate => $now,
@@ -1427,12 +1436,13 @@ sub _rss ( $query, $subtitle, $posts ) {
 
     return Trog::Renderer->render(
         template => 'raw.tx',
-        data => {
+        data     => {
             etag   => $query->{etag},
             body   => encode_utf8( $rss->as_string ),
             scheme => $query->{scheme},
         },
-        headers     => { 'Content-Disposition' => 'inline; filename="rss.xml"' },
+        headers => { 'Content-Disposition' => 'inline; filename="rss.xml"' },
+
         #XXX if you do the "proper" content-type of application/rss+xml, browsers download rather than display.
         contenttype => "text/xml",
         code        => 200,
@@ -1476,11 +1486,11 @@ sub manual ($query) {
 
     return Trog::Routes::HTML::index(
         {
-            title       => 'tCMS Manual',
-            theme_dir   => $Trog::Themes::td,
-            content     => $content,
-            template    => 'manual.tx',
-            is_admin    => 1,
+            title     => 'tCMS Manual',
+            theme_dir => $Trog::Themes::td,
+            content   => $content,
+            template  => 'manual.tx',
+            is_admin  => 1,
             %$query,
         },
         undef,
@@ -1489,24 +1499,26 @@ sub manual ($query) {
 }
 
 sub processed ($query) {
-    return Trog::Routes::HTML::index({
-        title => "Your request has been processed",
-        theme_dir => $Trog::Themes::td,
-    },
-	"Your request has been processed.<br /><br />You will recieve subsequent communications about this matter via means you have provided earlier.",
-	['post.css']);
+    return Trog::Routes::HTML::index(
+        {
+            title     => "Your request has been processed",
+            theme_dir => $Trog::Themes::td,
+        },
+        "Your request has been processed.<br /><br />You will recieve subsequent communications about this matter via means you have provided earlier.",
+        ['post.css']
+    );
 }
 
 # basically a file rewrite rule for themes
 sub icon ($query) {
     my $path = $query->{route};
-    return Trog::FileHandler::serve(Trog::Themes::themed("img/icon/$path"));
+    return Trog::FileHandler::serve( Trog::Themes::themed("img/icon/$path") );
 }
 
 # TODO make statics, abstract gzipped outputting & header handling
 sub rss_style ($query) {
-    $query->{port} = ":$query->{port}" if $query->{port};
-    $query->{title} = qq{<xsl:value-of select="rss/channel/title"/>};
+    $query->{port}       = ":$query->{port}" if $query->{port};
+    $query->{title}      = qq{<xsl:value-of select="rss/channel/title"/>};
     $query->{no_doctype} = 1;
 
     # Due to this being html rather than XML, we can't use an include directive.
@@ -1523,12 +1535,12 @@ sub rss_style ($query) {
 }
 
 sub _build_themed_styles ($styles) {
-    my @styles = map { Trog::Themes::themed_style("$_") } @{Trog::Utils::coerce_array($styles)};
+    my @styles = map { Trog::Themes::themed_style("$_") } @{ Trog::Utils::coerce_array($styles) };
     return \@styles;
 }
 
 sub _build_themed_scripts ($scripts) {
-    my @scripts = map { Trog::Themes::themed_script("$_") } @{Trog::Utils::coerce_array($scripts)};
+    my @scripts = map { Trog::Themes::themed_script("$_") } @{ Trog::Utils::coerce_array($scripts) };
     return \@scripts;
 }
 
@@ -1541,12 +1553,12 @@ sub finish_render ( $template, $vars, %headers ) {
     $vars->{scripts}     //= [];
 
     # Theme-ize the paths
-    $vars->{stylesheets}  = [map { s/^www\///; $_ } grep { -f $_ } @{_build_themed_styles($vars->{stylesheets})}];
-    $vars->{print_styles} = [map { s/^www\///; $_ } grep { -f $_ } @{_build_themed_styles($vars->{p_styles})}];
-    $vars->{scripts}      = [map { s/^www\///; $_ } grep { -f $_ } @{_build_themed_scripts($vars->{scripts})}];
+    $vars->{stylesheets}  = [ map { s/^www\///; $_ } grep { -f $_ } @{ _build_themed_styles( $vars->{stylesheets} ) } ];
+    $vars->{print_styles} = [ map { s/^www\///; $_ } grep { -f $_ } @{ _build_themed_styles( $vars->{p_styles} ) } ];
+    $vars->{scripts}      = [ map { s/^www\///; $_ } grep { -f $_ } @{ _build_themed_scripts( $vars->{scripts} ) } ];
 
     # Add in avatars.css, it's special
-    push(@{$vars->{stylesheets}},"/styles/avatars.css");
+    push( @{ $vars->{stylesheets} }, "/styles/avatars.css" );
 
     # Absolute-ize the paths for scripts & stylesheets
     @{ $vars->{stylesheets} }  = map { CORE::index( $_, '/' ) == 0 ? $_ : "/$_" } @{ $vars->{stylesheets} };

+ 18 - 17
lib/Trog/Routes/JSON.pm

@@ -40,7 +40,7 @@ our %routes = (
         callback   => \&process_auth_change_request,
         captures   => ['token'],
         noindex    => 1,
-		robot_name => '/api/auth_change_request/*',
+        robot_name => '/api/auth_change_request/*',
     },
 );
 
@@ -64,42 +64,43 @@ sub version ($query) {
 }
 
 sub catalog ($query) {
-	return _render(200, { ETag => 'catalog-' . _version() }, %$cloned);
+    return _render( 200, { ETag => 'catalog-' . _version() }, %$cloned );
 }
 
 sub webmanifest ($query) {
     state $headers  = { ETag => 'manifest-' . _version() };
     state %manifest = (
         "icons" => [
-			{ "src" => "$theme_dir/img/icon/favicon-32.png", "type" => "image/png", "sizes" => "32x32" },
-			{ "src" => "$theme_dir/img/icon/favicon-48.png", "type" => "image/png", "sizes" => "48x48" },
-			{ "src" => "$theme_dir/img/icon/favicon-167.png", "type" => "image/png", "sizes" => "167x167" },
-			{ "src" => "$theme_dir/img/icon/favicon-180.png", "type" => "image/png", "sizes" => "180x180" },
+            { "src" => "$theme_dir/img/icon/favicon-32.png",  "type" => "image/png", "sizes" => "32x32" },
+            { "src" => "$theme_dir/img/icon/favicon-48.png",  "type" => "image/png", "sizes" => "48x48" },
+            { "src" => "$theme_dir/img/icon/favicon-167.png", "type" => "image/png", "sizes" => "167x167" },
+            { "src" => "$theme_dir/img/icon/favicon-180.png", "type" => "image/png", "sizes" => "180x180" },
             { "src" => "$theme_dir/img/icon/favicon-192.png", "type" => "image/png", "sizes" => "192x192" },
             { "src" => "$theme_dir/img/icon/favicon-512.png", "type" => "image/png", "sizes" => "512x512" },
         ],
     );
-	return _render(200, $headers, %manifest );
+    return _render( 200, $headers, %manifest );
 }
 
-sub process_auth_change_request($query) {
+sub process_auth_change_request ($query) {
     my $token = $query->{token};
 
     my $msg = Trog::Auth::process_change_request($token);
     return Trog::Routes::HTML::forbidden($query) unless $msg;
-    return _render(200, undef,
-        	message => $msg,
-        	result  => 'success',
+    return _render(
+        200, undef,
+        message => $msg,
+        result  => 'success',
     );
 }
 
-sub _render ($code, $headers, %data) {
+sub _render ( $code, $headers, %data ) {
     return Trog::Renderer->render(
-        code => 200,
-		data => \%data,
-		template => 'bogus.tx',
-		contenttype => 'application/json',
-		headers     => $headers,
+        code        => 200,
+        data        => \%data,
+        template    => 'bogus.tx',
+        contenttype => 'application/json',
+        headers     => $headers,
     );
 }
 

+ 1 - 1
lib/Trog/SQLite.pm

@@ -46,7 +46,7 @@ sub dbh {
     my $qq = File::Slurper::read_text($schema);
     my $db = DBI->connect( "dbi:SQLite:dbname=$dbname", "", "" );
     $db->{sqlite_allow_multiple_statements} = 1;
-    $db->do($qq) or die "Could not ensure database consistency: ".$db->errstr;
+    $db->do($qq) or die "Could not ensure database consistency: " . $db->errstr;
     $db->{sqlite_allow_multiple_statements} = 0;
     $dbh->{$schema} = $db;
 

+ 1 - 1
lib/Trog/SQLite/TagIndex.pm

@@ -35,7 +35,7 @@ sub routes {
     return () unless ref $rows eq 'ARRAY' && @$rows;
 
     #XXX not sure how this gets escaped going in.
-    my %routes = map { URI::Escape::uri_unescape($_->{route}) => $_ } @$rows;
+    my %routes = map { URI::Escape::uri_unescape( $_->{route} ) => $_ } @$rows;
     return %routes;
 }
 

+ 5 - 6
lib/Trog/Themes.pm

@@ -15,15 +15,15 @@ Utility functions for getting themed paths.
 
 =cut
 
-my $conf         = Trog::Config::get();
+my $conf = Trog::Config::get();
 our $template_dir = 'www/templates';
 our $theme_dir    = '';
 $theme_dir = "www/themes/" . $conf->param('general.theme') if $conf->param('general.theme') && -d "www/themes/" . $conf->param('general.theme');
 our $td = $theme_dir ? "/$theme_dir" : '';
 
-sub template_dir ($template, $content_type, $is_component=0, $is_dir=0) {
+sub template_dir ( $template, $content_type, $is_component = 0, $is_dir = 0 ) {
     my $ct = $Trog::Vars::byct{$content_type};
-    my ($mtd, $mtemp) = ("$theme_dir/templates/$ct", "$template_dir/$ct");
+    my ( $mtd, $mtemp ) = ( "$theme_dir/templates/$ct", "$template_dir/$ct" );
     if ($is_component) {
         $mtd   .= "/components";
         $mtemp .= "/components";
@@ -55,8 +55,8 @@ sub themed_template ($resource) {
     return _dir_for_resource("templates/$resource") . "/templates/$resource";
 }
 
-sub templates_in_dir ($path, $ct, $is_component=0) {
-    $path = template_dir($path, $ct, $is_component, 1)."/$path";
+sub templates_in_dir ( $path, $ct, $is_component = 0 ) {
+    $path = template_dir( $path, $ct, $is_component, 1 ) . "/$path";
     my $forms = [];
     return $forms unless -d $path;
     opendir( my $dh, $path );
@@ -67,5 +67,4 @@ sub templates_in_dir ($path, $ct, $is_component=0) {
     return $forms;
 }
 
-
 1;

+ 4 - 4
lib/Trog/Utils.pm

@@ -28,11 +28,11 @@ sub strip_and_trunc ($s) {
 # Don't do anything if running NOHUP=1, which is useful when doing bulk operations
 sub restart_parent {
     return if $ENV{NOHUP};
-    if ($ENV{PSGI_ENGINE} && $ENV{PSGI_ENGINE} eq 'nginx-unit') {
-        my $conf = Trog::Config->get();
+    if ( $ENV{PSGI_ENGINE} && $ENV{PSGI_ENGINE} eq 'nginx-unit' ) {
+        my $conf         = Trog::Config->get();
         my $nginx_socket = $conf->param('nginx-unit.socket');
-        my $client = HTTP::Tiny::UNIX->new();
-        my $res = $client->request('GET', "http:$nginx_socket//control/applications/tcms/restart" );
+        my $client       = HTTP::Tiny::UNIX->new();
+        my $res          = $client->request( 'GET', "http:$nginx_socket//control/applications/tcms/restart" );
         WARN("could not reload application (got $res->{status} from nginx-unit)!") unless $res->{status} == 200;
         return 1;
     }