Files
tyforum/script/attach_list.pl
2023-10-16 19:17:15 +09:00

348 lines
12 KiB
Perl
Executable File

#!/usr/bin/perl
#------------------------------------------------------------------------------
# mwForum - Web-based discussion forum
# Copyright (c) 1999-2015 Markus Wichitill
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#------------------------------------------------------------------------------
use strict;
use warnings;
no warnings qw(uninitialized redefine);
# Imports
use TyfMain;
#------------------------------------------------------------------------------
# Init
my ( $m, $cfg, $lng, $user, $userId )
= TyfMain->new( $_[0], autocomplete => 1 );
$m->cacheUserStatus() if $userId;
# Check if access should be denied
$cfg->{attachList} || $user->{admin} or $m->error('errNoAccess');
$cfg->{attachList} != 2 || $userId or $m->error('errNoAccess');
# Print header
$m->printHeader();
# Get CGI parameters
my $page = $m->paramInt('pg') || 1;
my $words = $m->paramStr('words');
my $userName = $m->paramStr('user');
my $categBoardIdStr = $m->paramStrId('board') || "0"; # Sanitize later
my $field = $m->paramStrId('field') || 'filename';
my $minAge = $m->paramInt('min');
my $maxAge = $m->paramInt('max');
my $order = $m->paramStr('order') || 'desc';
my $gallery = $m->paramBool('gallery');
# Enforce valid options
$minAge = $m->min( $minAge, 24855 );
$maxAge = $m->min( $maxAge, 24855 );
$field = 'filename' if $field !~ /^(?:filename|caption)\z/;
$order = 'desc' if $order !~ /^(?:asc|desc)\z/;
$gallery = 0 if !$cfg->{attachGallery};
# Preserve parameters in links
my @params = (
words => $words,
user => $userName,
board => $categBoardIdStr,
field => $field,
min => $minAge,
max => $maxAge,
order => $order,
gallery => $gallery
);
# Get visible boards with attachments enabled
my $boards = $m->fetchAllHash( "
SELECT boards.*,
categories.title AS categTitle
FROM boards AS boards
INNER JOIN categories AS categories
ON categories.id = boards.categoryId
WHERE boards.attach > 0
ORDER BY categories.pos, boards.pos" );
@$boards = grep( $m->boardVisible($_), @$boards );
# Search words
my $fieldStr = "attachments.$field";
my $like = $m->{pgsql} ? 'ILIKE' : 'LIKE';
my $wordsLike = $m->dbEscLike($words);
my @words = $wordsLike =~ /"[^"]+"|[^"\s]+/g;
splice( @words, 10 ) if @words > 10;
my @wordPreds = ();
my @wordValues = ();
for ( my $i = 0; $i < @words; $i++ ) {
$words[$i] =~ s/"//g;
$words[$i] = $m->escHtml( $words[$i] );
push @wordPreds, "$fieldStr $like :word$i";
push @wordValues, "word$i" => "%$words[$i]%";
}
my $wordStr = @wordPreds ? "AND (" . join( " AND ", @wordPreds ) . ")" : "";
# Search username
my $userNameLike = "%" . $m->dbEscLike($userName) . "%";
my $userNameStr = $userName ? "AND posts.userNameBak LIKE :userNameLike" : "";
# Limit to age
my $minAgeStr = $minAge ? "AND posts.postTime < :now - :minAge * 86400" : "";
my $maxAgeStr = $maxAge ? "AND posts.postTime > :now - :maxAge * 86400" : "";
# Limit to category or board
my $boardJoinStr = "";
my $boardStr = "";
my $boardId = 0;
if ( $categBoardIdStr =~ /^bid([0-9]+)\z/ ) {
$boardStr = "AND posts.boardId = $1";
$boardId = $1;
}
elsif ( $categBoardIdStr =~ /^cid([0-9]+)\z/ ) {
$boardJoinStr
= "INNER JOIN boards AS boards ON boards.id = posts.boardId";
$boardStr = "AND boards.categoryId = $1";
$boardId = 0;
}
# Get ids of attachments
my $galleryStr = $gallery ? "AND attachments.webImage > 0" : "";
my @boardIds = map( $_->{id}, @$boards );
my $attachments = $m->fetchAllArray( "
SELECT attachments.id
FROM attachments AS attachments
INNER JOIN posts AS posts
ON posts.id = attachments.postId
$boardJoinStr
WHERE posts.boardId IN (:boardIds)
$wordStr
$userNameStr
$minAgeStr
$maxAgeStr
$galleryStr
$boardStr
ORDER BY attachments.id $order",
{ @wordValues,
userNameLike => $userNameLike,
now => $m->{now},
minAge => $minAge,
maxAge => $maxAge,
boardIds => \@boardIds
} );
# Print page bar
my $attachmentsPP
= $gallery ? ( $cfg->{attachGallPP} || 12 ) : ( $cfg->{attachPP} || 25 );
my $pageNum = int( @$attachments / $attachmentsPP )
+ ( @$attachments % $attachmentsPP != 0 );
my @pageLinks
= $pageNum < 2
? ()
: $m->pageLinks( 'attach_list', \@params, $page, $pageNum );
my @navLinks
= ( { url => $m->url('forum_show'), txt => 'comUp', ico => 'up' } );
$m->printPageBar(
mainTitle => $lng->{aliTitle},
navLinks => \@navLinks,
pageLinks => \@pageLinks
);
# Get attachments on page
my @pageAttachIds
= @$attachments[ ( $page - 1 )
* $attachmentsPP .. $m->min( $page * $attachmentsPP,
scalar @$attachments )
- 1 ];
@pageAttachIds = map( $_->[0], @pageAttachIds );
$attachments = $m->fetchAllHash( "
SELECT attachments.*,
posts.userId, posts.userNameBak
FROM attachments AS attachments
INNER JOIN posts AS posts
ON posts.id = attachments.postId
WHERE attachments.id IN (:pageAttachIds)
ORDER BY attachments.id $order",
{ pageAttachIds => \@pageAttachIds } );
# Determine checkbox, radiobutton and listbox states
my $galleryChk = $gallery ? 'checked' : "";
my %state = (
$categBoardIdStr => 'selected',
$field => 'selected',
$order => 'selected'
);
# Display age 0 as empty string
$minAge = $minAge ? $minAge : "";
$maxAge = $maxAge ? $maxAge : "";
# Escape submitted values
my $wordsEsc = $m->escHtml($words);
my $userNameEsc = $m->escHtml($userName);
# Print attachment list form
print
"<form action=\"attach_list$m->{ext}\" method=\"GET\">\n",
"<div class=\"frm\">\n",
"<div class=\"hcl\"><span class=\"htt\">$lng->{aliLfmTtl}</span></div>\n",
"<div class=\"ccl\">\n",
"<div class=\"cli\">\n",
"<label>$lng->{aliLfmWords}\n",
"<input type=\"text\" name=\"words\" size=\"20\" value=\"$wordsEsc\" autofocus></label>\n",
"<label>$lng->{aliLfmUser}\n",
"<input type=\"text\" class=\"acu acs\" name=\"user\" size=\"15\" value=\"$userNameEsc\"></label>\n",
"<label>$lng->{aliLfmBoard}\n",
"<select name=\"board\" size=\"1\">\n",
"<option value=\"0\">$lng->{seaBoardAll}</option>\n";
my $lastCategoryId = 0;
for my $board (@$boards) {
if ( $lastCategoryId != $board->{categoryId} ) {
$lastCategoryId = $board->{categoryId};
my $sel = $state{"cid$board->{categoryId}"};
print
"<option value=\"cid$board->{categoryId}\" $sel>$board->{categTitle}</option>\n";
}
my $sel = $state{"bid$board->{id}"};
print
"<option value=\"bid$board->{id}\" $sel>- $board->{title}</option>\n";
}
print
"</select></label>\n",
"</div>\n",
"<div class=\"cli\">\n",
"<label>$lng->{aliLfmField}\n",
"<select name=\"field\" size=\"1\">\n",
"<option value=\"filename\" $state{filename}>$lng->{aliLfmFldFnm}</option>\n",
"<option value=\"caption\" $state{caption}>$lng->{aliLfmFldCpt}</option>\n",
"</select></label>\n",
"<datalist id=\"age\">\n",
"<option value=\"1\">\n",
"<option value=\"7\">\n",
"<option value=\"30\">\n",
"<option value=\"90\">\n",
"<option value=\"365\">\n",
"</datalist>\n",
"<label>$lng->{aliLfmMinAge}\n",
"<input type=\"text\" name=\"min\" size=\"3\" maxlength=\"4\" list=\"age\" value=\"$minAge\"></label>\n",
"<label>$lng->{aliLfmMaxAge}\n",
"<input type=\"text\" name=\"max\" size=\"3\" maxlength=\"4\" list=\"age\" value=\"$maxAge\"></label>\n",
"<label>$lng->{aliLfmOrder}\n",
"<select name=\"order\" size=\"1\">\n",
"<option value=\"desc\" $state{desc}>$lng->{aliLfmOrdDsc}</option>\n",
"<option value=\"asc\" $state{asc}>$lng->{aliLfmOrdAsc}</option>\n",
"</select></label>\n",
$cfg->{attachGallery}
? "<label><input type=\"checkbox\" name=\"gallery\" value=\"1\""
. " $galleryChk>$lng->{aliLfmGall}</label>\n"
: "", $m->submitButton( 'aliLfmListB', 'search' ),
"</div>\n",
"</div>\n",
"</div>\n",
"</form>\n\n";
# Print normal attachment list
if ( !$gallery ) {
print
"<table class=\"tbl\">\n",
"<tr class=\"hrw\">\n",
"<th>$lng->{aliLstFile}</th>\n",
"<th>$lng->{aliLstCapt}</th>\n",
"<th>$lng->{aliLstSize}</th>\n",
"<th>$lng->{aliLstPost}</th>\n",
"<th>$lng->{aliLstUser}</th>\n",
"</tr>\n";
for my $attach (@$attachments) {
my $fileName = $attach->{fileName};
my $postId = $attach->{postId};
my $postIdMod = $postId % 100;
my $attShowUrl
= $attach->{webImage}
? $m->url( 'attach_show', aid => $attach->{id} )
: "$cfg->{attachUrlPath}/$postIdMod/$postId/$fileName";
my $postUrl = $m->url( 'topic_show', pid => $postId );
my $size = -s $m->encFsPath(
"$cfg->{attachFsPath}/$postIdMod/$postId/$fileName");
my $sizeStr = $m->formatSize($size);
my $userUrl = $m->url( 'user_info', uid => $attach->{userId} );
my $userNameStr = $attach->{userNameBak} || " - ";
$userNameStr = "<a href=\"$userUrl\">$userNameStr</a>"
if $attach->{userId} > 0;
print
"<tr class=\"crw\">\n",
"<td><a href=\"$attShowUrl\">$fileName</a></td>\n",
"<td>$attach->{caption}</td>\n",
"<td>$sizeStr</td>\n",
"<td><a href=\"$postUrl\">$postId</a></td>\n",
"<td>$userNameStr</td>\n",
"</tr>\n";
}
print "</table>\n\n";
}
# Print attachment image gallery
else {
print "<table class=\"tbl igl\">\n<tr class=\"crw\">\n";
for ( my $i = 0; $i < @$attachments; $i++ ) {
print "</tr><tr class=\"crw\">\n" if $i && $i % 4 == 0;
# Determine values
my $attach = @$attachments[$i];
my $fileName = $attach->{fileName};
my $postId = $attach->{postId};
my $postIdMod = $postId % 100;
my $imgFile = "$cfg->{attachFsPath}/$postIdMod/$postId/$fileName";
my $imgUrl = "$cfg->{attachUrlPath}/$postIdMod/$postId/$fileName";
my $imgShowUrl = $m->url( 'attach_show', aid => $attach->{id} );
my $thbFile = $imgFile;
my $thbUrl = $imgUrl;
$thbFile =~ s!\.(?:jpg|png|gif)\z!.thb.jpg!i;
$thbUrl =~ s!\.(?:jpg|png|gif)\z!.thb.jpg!i;
my $size = -s $m->encFsPath($imgFile);
my $sizeStr = $m->formatSize($size);
my $useThb = -f $m->encFsPath($thbFile) || $m->addThumbnail($imgFile);
my $postUrl = $m->url( 'topic_show', pid => $postId );
my $src = $useThb ? $thbUrl : $imgUrl;
my $thbStr
= $useThb >= 0
? "<img class=\"igl\" src=\"$src\" title=\"$sizeStr\" alt=\"\">"
: ( $size ? "?" : "404" );
# Print image and file size
print
"<td>\n",
"<div><a href=\"$postUrl\">$thbStr</a></div>\n",
"<div><a href=\"$imgShowUrl\">$fileName</a></div>\n",
"<div>$attach->{caption}</div>\n",
"</td>\n";
}
# Print rest of table
my $empty = 4 - @$attachments % 4;
$empty = 0 if $empty == 4;
print "<td></td>\n" while $empty-- > 0;
print
"</tr>\n",
"</table>\n\n";
}
# Log action and finish
$m->logAction( 3, 'attach', 'list', $userId, $boardId );
$m->printFooter();
$m->finish();