use
vars
qw($VERSION @ISA %EXPORT_TAGS @EXPORT @EXPORT_OK)
;
$VERSION
=
'5.32'
;
@ISA
=
qw(Exporter)
;
%EXPORT_TAGS
= (
'all'
=> [
qw(
CGIFile
StockSelect StockName StockPath StockType PathMove
GetImage SaveImageFile MirrorImageFile
CopyPhotoFile SavePhotoFile
GetMedia SaveMediaFile SaveFile DeleteFile UnZipFile
GetImageSize ResizeDimensions GetGravatar
)
]
);
@EXPORT_OK
= ( @{
$EXPORT_TAGS
{
'all'
} } );
@EXPORT
= ( @{
$EXPORT_TAGS
{
'all'
} } );
use
constant
MaxDefaultImageWidth
=> 800;
use
constant
MaxDefaultImageHeight
=> 600;
use
constant
MaxDefaultThumbWidth
=> 200;
use
constant
MaxDefaultThumbHeight
=> 200;
{
my
@CHARS
= (
qw/A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
a b c d e f g h i j k l m n o p q r s t u v w x y z
0 1 2 3 4 5 6 7 8 9 _
/
);
my
%stock
;
my
%image_store
;
sub
CGIFile {
my
$param
=
shift
;
my
$stock
=
shift
|| 1;
_init_stock()
unless
(
%stock
);
$stock
= 1
unless
(
$stock
{
$stock
});
my
$path
=
"$settings{webdir}/$stock{$stock}->{path}"
;
mkpath(
$path
);
if
(
$image_store
{
$param
}) {
if
(
$image_store
{
$param
}[3] !=
$stock
) {
my
$source
=
"$settings{webdir}/$image_store{$param}[1]"
;
my
$target
=
"$path/$image_store{$param}[0].$image_store{$param}[2]"
;
copy(
$source
,
$target
);
$target
=~ s!^
$settings
{webdir}/!!;
$image_store
{
$param
}[1] =
$target
;
$image_store
{
$param
}[3] =
$stock
;
}
return
@{
$image_store
{
$param
}};
}
my
$fn
=
$cgi
->param(
$param
);
LogDebug(
"CGIFile: $param fn=$fn"
);
return
unless
(
$fn
);
my
(
$bytes
,
$filename
,
$dir
,
$name
,
$suffix
);
eval
{
my
$f
=
$cgi
->upload(
$param
) ||
die
"Cannot access filehandle\n"
;
(
$name
,
$dir
,
$suffix
) = fileparse(
$fn
,
qr/\.[^.]*/
);
my
$tries
= 0;
while
(1) {
last
if
(
$tries
++ > 10);
$filename
=
"$path/"
. _randname(
'imgXXXXXX'
) .
lc
(
$suffix
);
next
if
(-f
$filename
);
last
;
}
my
$buffer
= read_file(
$f
,
binmode
=>
':raw'
);
$bytes
=
length
(
$buffer
);
write_file(
$filename
, {
binmode
=>
':raw'
},
$buffer
);
};
die
$@
if
$@;
if
(
$bytes
== 0) {
LogError(
"CGIFile: no bytes read for input file [$param]"
);
return
;
}
$filename
=~ s!^
$settings
{webdir}/!!;
$image_store
{
$param
} = [
$name
,
$filename
,
$suffix
,
$stock
];
return
(
$name
,
$filename
,
$suffix
);
}
sub
StockName {
my
$stock
=
shift
|| 1;
_init_stock()
unless
(
%stock
);
return
$stock
{
$stock
}->{title};
}
sub
StockPath {
my
$stock
=
shift
|| 1;
_init_stock()
unless
(
%stock
);
return
$stock
{
$stock
}->{path};
}
sub
StockType {
my
$stock
=
shift
||
'DRAFT'
;
_init_stock()
unless
(
%stock
);
for
(
keys
%stock
) {
return
$_
if
(
$stock
{
$_
}->{title} eq
$stock
);
}
return
1;
}
sub
StockSelect {
my
$opt
=
shift
|| 0;
my
$blank
=
shift
|| 1;
_init_stock()
unless
(
%stock
);
my
$html
=
"<select name='type'>"
;
$html
.=
"<option value='0'>Select</option>"
if
(
defined
$blank
&&
$blank
== 1);
foreach
(
sort
{
$a
<=>
$b
}
keys
%stock
) {
$html
.=
"<option value='$_'"
;
$html
.=
' selected="selected"'
if
(
$opt
==
$_
);
$html
.=
">$stock{$_}->{title}</option>"
;
}
$html
.=
"</select>"
;
return
$html
;
}
sub
PathMove {
my
(
$stockid
,
$link
) =
@_
;
my
(
$path
,
$name
) = (
$link
=~ m!(.+)/([^/]+)!);
return
$link
if
(
$stock
{
$stockid
}->{path} eq
$path
);
my
$old
=
"$settings{webdir}/$link"
;
my
$new
=
"$settings{webdir}/$stock{$stockid}->{path}/$name"
;
rename
$old
,
$new
;
return
"$stock{$stockid}->{path}/$name"
;
}
sub
_init_stock {
my
@rows
=
$dbi
->GetQuery(
'hash'
,
'AllImageStock'
);
$stock
{
$_
->{stockid}} =
$_
for
(
@rows
);
}
sub
_randname {
my
$path
=
shift
;
$path
=~ s/X(?=X*\z)/
$CHARS
[
int
(
rand
(
$#CHARS
) ) ]/ge;
return
$path
;
}
}
sub
GetImage {
my
$imageid
=
shift
;
my
@rows
=
$dbi
->GetQuery(
'hash'
,
'GetImageByID'
,
$imageid
);
return
()
unless
(
@rows
);
my
(
$x
,
$y
);
if
(
$rows
[0]->{dimensions}) {
(
$x
,
$y
) =
split
(
"x"
,
$rows
[0]->{dimensions});
}
else
{
(
$x
,
$y
) = imgsize(
$settings
{webdir}.
'/'
.
$rows
[0]->{
link
});
}
return
(
$rows
[0]->{tag},
$rows
[0]->{
link
},
$rows
[0]->{href},
$x
,
$y
);
}
sub
MirrorImageFile {
my
(
$source
,
$stock
,
$xmax
,
$ymax
) =
@_
;
my
$stockid
= StockType(
$stock
);
my
$name
= basename(
$source
);
my
$file
= StockPath(
$stockid
) .
'/'
.
$name
;
my
$target
=
$settings
{
'webdir'
} .
'/'
.
$file
;
my
$mechanize
= WWW::Mechanize->new();
$mechanize
->mirror(
$source
,
$target
);
if
(
$xmax
&&
$ymax
) {
my
$i
= Labyrinth::DIUtils->new(
$target
);
$i
->reduce(
$xmax
,
$ymax
);
}
my
(
$size_x
,
$size_y
) = imgsize(
$target
);
my
$imageid
= SaveImage(
undef
,
$name
,
$file
,
$stockid
,
undef
,
$size_x
.
'x'
.
$size_y
);
return
(
$imageid
,
$file
);
}
sub
SaveImageFile {
my
%hash
=
@_
;
my
$param
=
$hash
{param};
my
$xmax
=
$hash
{width} ||
$settings
{maxdefaultimagewidth} || MaxDefaultImageWidth;
my
$ymax
=
$hash
{height} ||
$settings
{maxdefaultimageheight} || MaxDefaultImageHeight;
my
$imageid
=
$hash
{imageid};
my
$stock
= StockType(
$hash
{stock});
return
unless
(
$param
&&
$cgiparams
{
$param
});
my
(
$name
,
$filename
) = CGIFile(
$param
,
$stock
);
return
1
unless
(
$name
);
eval
{
LogDebug(
"reducing '$settings{webdir}/$filename' to $xmax x $ymax"
);
my
$i
= Labyrinth::DIUtils->new(
"$settings{webdir}/$filename"
);
$i
->reduce(
$xmax
,
$ymax
);
};
LogDebug(
"error reducing '$settings{webdir}/$filename': $@"
)
if
($@);
my
(
$size_x
,
$size_y
) = imgsize(
"$settings{webdir}/$filename"
);
$imageid
= SaveImage(
$imageid
,
$name
,
$filename
,
$stock
,
$hash
{href},
$size_x
.
'x'
.
$size_y
);
return
(
$imageid
,
$filename
);
}
sub
GetImageSize {
my
(
$link
,
$size
,
$width
,
$height
,
$maxwidth
,
$maxheight
) =
@_
;
$maxwidth
||=
$settings
{maxdefaultimagewidth} || MaxDefaultImageWidth;
$maxheight
||=
$settings
{maxdefaultimageheight} || MaxDefaultImageHeight;
my
(
$w
,
$h
) =
$size
?
split
(
'x'
,
$size
) : (0,0);
(
$w
,
$h
) = imgsize(
"$settings{webdir}/$link"
)
unless
(
$w
||
$h
);
(
$width
,
$height
) = (
$w
,
$h
)
unless
(
$width
||
$height
);
if
(
defined
$width
&&
defined
$height
&&
$width
>
$height
&&
$width
>
$maxwidth
) {
$width
=
$maxwidth
;
$height
= 0;
}
elsif
(
defined
$width
&&
defined
$height
&&
$width
<
$height
&&
$height
>
$maxheight
) {
$height
=
$maxheight
;
$width
= 0;
}
elsif
(
defined
$width
&&
$width
>
$maxwidth
) {
$width
=
$maxwidth
;
$height
= 0;
}
elsif
(
defined
$height
&&
$height
>
$maxheight
) {
$height
=
$maxheight
;
$width
= 0;
}
if
(
$width
&&
$height
) {
}
elsif
(
$width
&& !
$height
) {
$height
=
int
(
$h
* (
$width
/
$w
));
}
elsif
(!
$width
&&
$height
) {
$width
=
int
(
$w
* (
$height
/
$h
));
}
return
(
$width
,
$height
);
}
sub
ResizeDimensions {
my
(
$dimensions
,
$file
,
$maxwidth
,
$maxheight
) =
@_
;
my
$toobig
= 0;
my
(
$x
,
$y
);
if
(
$tvars
{data}->{dimensions}) {
(
$x
,
$y
) =
split
(
"x"
,
$tvars
{data}->{dimensions});
}
else
{
(
$x
,
$y
) = imgsize(
$file
)
if
(-f
$file
);
}
return
unless
(
$x
&&
$y
);
return
(
$x
,
$y
,
$toobig
)
unless
(
$maxwidth
&&
$maxheight
);
return
(
$x
,
$y
,
$toobig
)
if
(
$x
<=
$maxwidth
&&
$y
<=
$maxheight
);
$toobig
= 1;
my
$xr
=
$maxwidth
?
$maxwidth
/
$x
: 0;
my
$yr
=
$maxheight
?
$maxheight
/
$y
: 0;
if
(
$xr
<=
$yr
) {
$x
*=
$xr
;
$y
*=
$xr
;
}
else
{
$x
*=
$yr
;
$y
*=
$yr
;
}
return
(
int
(
$x
),
int
(
$y
),
$toobig
);
}
sub
GetGravatar {
my
(
$id
,
$email
) =
@_
;
my
$nophoto
= uri_escape(
$settings
{nophoto});
return
$nophoto
unless
(
$id
);
my
$user
= GetUser(
$id
);
return
$nophoto
unless
(
$user
);
return
.
'gravatar_id='
.md5_hex(
$email
)
.
'&default='
.
$nophoto
.
'&size=80'
;
}
sub
CopyPhotoFile {
my
%hash
=
@_
;
my
$photo
=
$hash
{photo};
my
$xmax
=
$hash
{width} ||
$settings
{maxdefaultimagewidth} || MaxDefaultImageWidth;
my
$ymax
=
$hash
{height} ||
$settings
{maxdefaultimageheight} || MaxDefaultImageHeight;
my
$stock
= StockType(
$hash
{stock});
return
unless
(
$photo
);
my
@rs
=
$dbi
->GetQuery(
'hash'
,
'GetPhotoDetail'
,
$photo
);
my
$name
= basename(
$rs
[0]->{image});
return
1
unless
(
$name
);
my
$source
=
"$settings{webdir}/photos/$rs[0]->{image}"
;
my
$target
=
"$settings{webdir}/images/draft/$name"
;
copy(
$source
,
$target
);
my
$i
= Labyrinth::DIUtils->new(
$target
);
$i
->reduce(
$xmax
,
$ymax
);
my
(
$size_x
,
$size_y
) = imgsize(
$target
);
$target
=~ s!
$settings
{webdir}/!!;
my
$imageid
= SaveImage(
undef
,
$name
,
$target
,
$stock
,
$hash
{href},
$size_x
.
'x'
.
$size_y
);
return
(
$imageid
,
$target
);
}
sub
SavePhotoFile {
my
%hash
=
@_
;
my
$param
=
$hash
{param} ||
return
;
my
$path
=
$hash
{path} ||
return
;
my
$page
=
$hash
{page} ||
return
;
my
$iwidth
=
$hash
{iwidth} ||
$settings
{maxdefaultimagewidth} || MaxDefaultImageWidth;
my
$iheight
=
$hash
{iheight} ||
$settings
{maxdefaultimageheight} || MaxDefaultImageHeight;
my
$twidth
=
$hash
{twidth} ||
$settings
{maxdefaultthumbwidth} || MaxDefaultThumbWidth;
my
$theight
=
$hash
{theight} ||
$settings
{maxdefaultthumbheight} || MaxDefaultThumbHeight;
my
$order
=
$hash
{order} || 1;
my
$tag
=
$hash
{tag};
my
$stock
= StockType(
$hash
{stock});
return
unless
(
$cgiparams
{
$param
});
my
(
$name
,
$filename
,
$extn
) = CGIFile(
$param
,
$stock
);
return
1
unless
(
$name
);
$tag
=
$name
unless
(
defined
$tag
);
my
$file
=
lc
(
$name
);
$file
=~ s/\s+//g;
my
$source
=
"$settings{webdir}/$filename"
;
my
$target
=
"$settings{webdir}/$path/$file$extn"
;
copy(
$source
,
$target
);
$source
=
"$settings{webdir}/$path/$file$extn"
;
$target
=
"$settings{webdir}/$path/$file-thumb$extn"
;
copy(
$source
,
$target
);
eval
{
LogDebug(
"reducing '$source' to $iwidth x $iheight"
);
my
$i
= Labyrinth::DIUtils->new(
$source
);
$i
->reduce(
$iwidth
,
$iheight
);
};
eval
{
LogDebug(
"reducing '$target' to $twidth x $theight"
);
my
$t
= Labyrinth::DIUtils->new(
$target
);
$t
->reduce(
$twidth
,
$theight
);
};
my
(
$size_x
,
$size_y
) = imgsize(
$source
);
$source
=~ s!
$settings
{webdir}/(photos/)?!!;
$target
=~ s!
$settings
{webdir}/(photos/)?!!;
my
$photoid
=
$dbi
->IDQuery(
'SavePhoto'
,
$page
,
$target
,
$source
,
$size_x
.
'x'
.
$size_y
,
$tag
,
$order
);
MetaSave(
$photoid
,[
'Photo'
],
split
(/[ ,]+/,
$name
));
return
(
$photoid
,
$name
);
}
sub
GetMedia {
my
$imageid
=
shift
;
my
@rows
=
$dbi
->GetQuery(
'hash'
,
'GetImageByID'
,
$imageid
);
return
()
unless
(
@rows
);
return
(
$rows
[0]->{tag},
$rows
[0]->{
link
},
$rows
[0]->{href});
}
sub
SaveMediaFile {
my
%hash
=
@_
;
my
$param
=
$hash
{param};
my
$imageid
=
$hash
{imageid};
my
$stock
= StockType(
$hash
{stock});
return
unless
(
$param
&&
$cgiparams
{
$param
});
my
(
$name
,
$filename
) = CGIFile(
$param
,
$stock
);
return
1
unless
(
$name
);
$imageid
= SaveImage(
$imageid
,
$name
,
$filename
,
$stock
,
$hash
{href},
''
);
return
(
$imageid
,
$filename
);
}
sub
SaveFile {
my
%hash
=
@_
;
my
$param
=
$hash
{param};
my
$stock
= StockType(
$hash
{stock});
return
unless
(
$param
&&
$cgiparams
{
$param
});
my
(
$name
,
$filename
) = CGIFile(
$param
,
$stock
,1);
return
unless
(
$name
);
return
$filename
;
}
sub
DeleteFile {
my
%hash
=
@_
;
my
$file
=
$hash
{file};
unlink
$file
;
}
sub
ImageCheck {
my
$imageid
=
shift
;
foreach
my
$plugin
(get_plugins) {
return
1
if
(
$plugin
->ImageCheck(
$imageid
) );
}
return
0;
}
sub
SaveImage {
my
(
$imageid
,
@fields
) =
@_
;
if
(
$imageid
) {
$dbi
->DoQuery(
'SaveImage'
,
@fields
,
$imageid
); }
else
{
$imageid
=
$dbi
->IDQuery(
'AddImage'
,
@fields
); }
return
$imageid
;
}
sub
UnZipFile {
my
$file
=
shift
;
return
unless
(
$file
=~ /(.*)\.(zip|tar|tar\.gz|tgz)$/);
my
$path
= $1;
return
unless
(
$path
);
my
$ae
= Archive::Extract->new(
archive
=>
"$settings{webdir}/$file"
);
my
$ok
=
$ae
->extract(
to
=>
"$settings{webdir}/$path"
);
unless
(
$ok
) {
LogError(
"UnZip failure: file=[$file], path=[$path], error: "
.
$ae
->error);
rmtree(
"$settings{webdir}/$path"
);
unlink
(
"$settings{webdir}/$file"
);
return
;
}
my
@files
=
map
{
my
$x
=
$_
;
$x
=~ s!
$settings
{webdir}/!!;
$x
} File::Find::Rule->file()->name(
'*'
)->in(
"$settings{webdir}/$path"
);
unless
(
@files
> 0) {
LogError(
"UnZip failure: file=[$file], path=[$path], error: No files in archive."
);
rmtree(
"$settings{webdir}/$path"
);
unlink
(
"$settings{webdir}/$file"
);
return
;
}
return
$files
[0]
if
(
@files
== 1);
my
@html
=
grep
{/^
index
.html?$/}
@files
;
return
$html
[0]
if
(
@html
);
@html
=
grep
{/\.html?$/}
@files
;
return
$html
[0]
if
(
@html
);
return
$files
[0];
}
1;