Utils.pm 2.5 KB

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