Utils.pm 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. package Trog::Utils;
  2. use 5.040;
  3. use re '/aasx';
  4. use UUID;
  5. use HTTP::Tiny::UNIX();
  6. use Plack::MIME;
  7. use Mojo::File;
  8. use File::LibMagic;
  9. use Ref::Util qw{is_hashref};
  10. use Trog::Log qw{WARN};
  11. use Trog::Config();
  12. =head1 Trog::Utils
  13. Odds and ends which are needed in more than one place and belong to no
  14. particular subsystem.
  15. =head1 FUNCTIONS
  16. =head2 coerce_array(SCALAR|ARRAYREF param) = ARRAYREF
  17. Deal with Params which may or may not be arrays.
  18. Query parameters arrive as a bare scalar when the caller passed one of
  19. something and as an arrayref when they passed several, which means every
  20. consumer would otherwise have to check. Returns an empty arrayref for anything
  21. false, so the result is always safe to dereference.
  22. =cut
  23. sub coerce_array ($param) {
  24. my $p = $param || [];
  25. $p = [$param] if $param && ( ref $param ne 'ARRAY' );
  26. return $p;
  27. }
  28. =head2 strip_and_trunc(STRING s) = STRING
  29. Flatten a chunk of post body into something fit for a meta description or
  30. preview blurb -- tags stripped, truncated to 280 characters.
  31. Returns undef when handed nothing, rather than an empty string.
  32. =cut
  33. sub strip_and_trunc ($s) {
  34. return unless $s;
  35. $s =~ s/<[^>]*>//g;
  36. return substr $s, 0, 280;
  37. }
  38. =head2 uuid() = STRING
  39. A fresh UUID. Thin wrapper around UUID::uuid(), so that callers don't have to
  40. care which of the several UUID modules we ended up using.
  41. =cut
  42. sub uuid {
  43. return UUID::uuid();
  44. }
  45. #Stuff that isn't in upstream finders
  46. my %extra_types = (
  47. '.docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
  48. );
  49. =head2 mime_type(STRING file) = STRING
  50. Figure out a file's Content-Type.
  51. Tries the extension first, as that's cheap and right nearly all of the time,
  52. and only falls back to libmagic sniffing the file's contents when the extension
  53. tells us nothing. %extra_types patches in the handful of types the upstream
  54. finders don't know about.
  55. Returns undef if even libmagic can't say.
  56. =cut
  57. sub mime_type ($file) {
  58. # Use libmagic and if that doesn't work try guessing based on extension.
  59. my $mt;
  60. my $mf = Mojo::File->new($file);
  61. my $ext = '.' . $mf->extname();
  62. $mt = Plack::MIME->mime_type($ext) if $ext;
  63. $mt ||= $extra_types{$ext} if exists $extra_types{$ext};
  64. return $mt if $mt;
  65. # If all else fails, time for libmagic
  66. state $magic = File::LibMagic->new;
  67. my $maybe_ct = $magic->info_from_filename($file);
  68. $mt = $maybe_ct->{mime_type} if ( is_hashref($maybe_ct) && $maybe_ct->{mime_type} );
  69. return $mt;
  70. }
  71. 1;