Mojolicious

 view release on metacpan or  search on metacpan

lib/Mojo/Util.pm  view on Meta::CPAN

    join('', map { ucfirst lc } split /_/)
  } split /-/, $str;
}

sub class_to_file {
  my $class = shift;
  $class =~ s/::|'//g;
  $class =~ s/([A-Z])([A-Z]*)/$1 . lc $2/ge;
  return decamelize($class);
}

sub decamelize {
  my $str = shift;
  return $str if $str !~ /^[A-Z]/;

  # snake_case words
  return join '-', map {
    join('_', map {lc} grep {length} split /([A-Z]{1}[^A-Z]*)/)
  } split /::/, $str;
}

sub decrypt_cookie {
  my ($value, $key, $salt) = @_;
  croak 'CryptX 0.080+ required for encrypted cookie support' unless CRYPTX;

  return undef unless $value =~ /^([^-]+)-([^-]+)-([^-]+)$/;
  my ($ct, $iv, $tag) = ($1, $2, $3);
  ($ct, $iv, $tag) = (Crypt::Misc::decode_b64($ct), Crypt::Misc::decode_b64($iv), Crypt::Misc::decode_b64($tag));

  my $dk = $ENCRYPTION{$key}{$salt} ||= Crypt::KeyDerivation::pbkdf2($key, $salt);
  return Crypt::AuthEnc::ChaCha20Poly1305::chacha20poly1305_decrypt_verify($dk, $iv, '', $ct, $tag);
}

sub decode {
  my ($encoding, $bytes) = @_;
  return undef unless eval { $bytes = _encoding($encoding)->decode("$bytes", 1); 1 };
  return $bytes;
}

sub deprecated {
  local $Carp::CarpLevel = 1;
  $ENV{MOJO_FATAL_DEPRECATIONS} ? croak @_ : carp @_;
}

sub dumper { Data::Dumper->new([@_])->Indent(1)->Sortkeys(1)->Terse(1)->Useqq(1)->Dump }

sub encode { _encoding($_[0])->encode("$_[1]", 0) }

sub encrypt_cookie {
  my ($value, $key, $salt) = @_;
  croak 'CryptX 0.080+ required for encrypted cookie support' unless CRYPTX;

  my $dk = $ENCRYPTION{$key}{$salt} ||= Crypt::KeyDerivation::pbkdf2($key, $salt);
  my $iv = Crypt::PRNG::random_bytes(12);
  my ($ct, $tag) = Crypt::AuthEnc::ChaCha20Poly1305::chacha20poly1305_encrypt_authenticate($dk, $iv, '', $value);

  return join '-', Crypt::Misc::encode_b64($ct), Crypt::Misc::encode_b64($iv), Crypt::Misc::encode_b64($tag);
}

sub extract_usage {
  my $file = @_ ? "$_[0]" : (caller)[1];

  open my $handle, '>', \my $output;
  pod2usage -exitval => 'noexit', -input => $file, -output => $handle;
  $output =~ s/^.*\n|\n$//;
  $output =~ s/\n$//;

  return unindent($output);
}

sub generate_secret {
  return encode_base64url(random_bytes(128));
}

sub getopt {
  my ($array, $opts) = map { ref $_[0] eq 'ARRAY' ? shift : $_ } \@ARGV, [];

  my $save   = Getopt::Long::Configure(qw(default no_auto_abbrev no_ignore_case), @$opts);
  my $result = GetOptionsFromArray $array, @_;
  Getopt::Long::Configure($save);

  return $result;
}

sub gunzip {
  my $compressed = shift;
  IO::Uncompress::Gunzip::gunzip \$compressed, \my $uncompressed
    or croak "Couldn't gunzip: $IO::Uncompress::Gunzip::GzipError";
  return $uncompressed;
}

sub gzip {
  my $uncompressed = shift;
  IO::Compress::Gzip::gzip \$uncompressed, \my $compressed or croak "Couldn't gzip: $IO::Compress::Gzip::GzipError";
  return $compressed;
}

sub header_params {
  my $value = shift;

  my $params = {};
  while ($value =~ /\G[;\s]*([^=;, ]+)\s*/gc) {
    my $name = $1;

    # Quoted value
    if ($value =~ /$QUOTED_VALUE_RE/gco) { $params->{$name} //= unquote($1) }

    # Unquoted value
    elsif ($value =~ /$UNQUOTED_VALUE_RE/gco) { $params->{$name} //= $1 }
  }

  return ($params, substr($value, pos($value) // 0));
}

sub html_attr_unescape { _html(shift, 1) }
sub html_unescape      { _html(shift, 0) }

sub humanize_bytes {
  my $size = shift;

  my $prefix = $size < 0 ? '-' : '';



( run in 1.886 second using v1.01-cache-2.11-cpan-4ac696b4eb4 )