Move from mod_perl to being a PSGI app.
[pr0n] / perl / Sesse / pr0n / Rotate.pm
1 package Sesse::pr0n::Rotate;
2 use strict;
3 use warnings;
4
5 use Sesse::pr0n::Common qw(error dberror);
6
7 sub handler {
8         my $r = shift;
9         my $dbh = Sesse::pr0n::Common::get_dbh();
10         my ($user, $takenby) = Sesse::pr0n::Common::check_access($r);
11         return Sesse::pr0n::Common::generate_401($r) if (!defined($user));
12
13         # FIXME: People can rotate and delete across vhosts using this interface.
14         # We should add some sanity checks.
15
16         my @to_purge = ();
17
18         Sesse::pr0n::Common::header($r, "Rotation/deletion results");
19
20         my $res = Plack::Response->new(200);
21         my $io = IO::String->new;
22
23         {
24                 # Enable transactions and error raising temporarily
25                 local $dbh->{RaiseError} = 1;
26
27                 my @params = $r->param();
28                 my $key;
29                 for $key (@params) {
30                         local $dbh->{AutoCommit} = 0;
31
32                         # Rotation
33                         if ($key =~ /^rot-(\d+)-(90|180|270)$/ && $r->param($key) eq 'on') {
34                                 my ($id, $rotval) = ($1,$2);
35                                 my $fname = Sesse::pr0n::Common::get_disk_location($r, $id);
36                                 push @to_purge, Sesse::pr0n::Common::get_all_cache_urls($r, $dbh, $id);
37                                 (my $tmpfname = $fname) =~ s/\.jpg$/-tmp.jpg/;
38
39                                 system("/usr/bin/jpegtran -rotate $rotval -copy all < '$fname' > '$tmpfname' && /bin/mv '$tmpfname' '$fname'") == 0
40                                         or return error($r, "Rotation of $id [/usr/bin/jpegtran -rotate $rotval -copy all < '$fname' > '$tmpfname' && /bin/mv '$tmpfname' '$fname'] failed: $!.");
41                                 $io->print("    <p>Rotated image ID `$id' by $rotval degrees.</p>\n");
42
43                                 if ($rotval == 90 || $rotval == 270) {
44                                         my $q = $dbh->do('UPDATE images SET height=width,width=height WHERE id=?', undef, $id)
45                                                 or return dberror($r, "Size clear of $id failed");
46                                         $dbh->do('UPDATE last_picture_cache SET last_update=CURRENT_TIMESTAMP WHERE (vhost,event)=( SELECT vhost,event FROM images WHERE id=? )',
47                                                 undef, $id)
48                                                 or return dberror($r, "Cache invalidation at $id failed");
49                                 }
50                         } elsif ($key =~ /^del-(\d+)$/ && $r->param($key) eq 'on') {
51                                 my $id = $1;
52                                 push @to_purge, Sesse::pr0n::Common::get_all_cache_urls($r, $dbh, $id);
53                                 {
54
55                                         eval {
56                                                 $dbh->do('UPDATE last_picture_cache SET last_update=CURRENT_TIMESTAMP WHERE (vhost,event)=( SELECT vhost,event FROM images WHERE id=? )',
57                                                         undef, $id);
58                                                 $dbh->do('INSERT INTO deleted_images SELECT * FROM images WHERE id=?',
59                                                         undef, $id);
60                                                 $dbh->do('DELETE FROM exif_info WHERE image=?',
61                                                         undef, $id);
62                                                 $dbh->do('DELETE FROM images WHERE id=?',
63                                                         undef, $id);
64                                         };
65                                         if ($@) {
66 # Some error occurred, rollback and bomb out
67                                                 $dbh->rollback;
68                                                 return dberror($r, "Transaction aborted because $@");
69                                         }
70                                 }
71                                 $io->print("    <p>Deleted image `$id'.</p>\n");
72                         }
73                 }
74         }
75         
76         my $event = $r->param('event');
77         $dbh->do('UPDATE last_picture_cache SET last_update=CURRENT_TIMESTAMP WHERE vhost=? AND event=?', undef, Sesse::pr0n::Common::get_server_name($r), $event)
78                 or return dberror($r, "Cache invalidation failed");
79
80         push @to_purge, "/$event/";
81         push @to_purge, "/+all/";
82         Sesse::pr0n::Common::purge_cache($r, $res, @to_purge);
83
84         Sesse::pr0n::Common::footer($r, $io);
85         $io->setpos(0);
86         $res->body($io);
87         return $res;
88 }
89
90 1;
91
92