GithubHelp home page GithubHelp logo

zakame / hashids.pm Goto Github PK

View Code? Open in Web Editor NEW
16.0 5.0 6.0 169 KB

Hashids, ported for Perl

Home Page: http://hashids.org/perl

License: MIT License

Perl 99.12% Raku 0.88%
hashids perl database-ids hash ids encoding perl-module cpan hacktoberfest

hashids.pm's Introduction

Actions Status Coverage Status MetaCPAN Release Build Status

NAME

Hashids - generate short hashes from numbers

SYNOPSIS

use Hashids;
my $hashids = Hashids->new('this is my salt');

# encrypt a single number
my $hash = $hashids->encode(123);          # 'YDx'
my $number = $hashids->decode('YDx');      # 123

# or a list
$hash = $hashids->encode(1, 2, 3);         # 'laHquq'
my @numbers = $hashids->decode('laHquq');  # (1, 2, 3)

# also get results in an arrayref
my $numbers = $hashids->decode('laHquq');  # [1, 2, 3]

DESCRIPTION

This is a port of the Hashids JavaScript library for Perl.

Hashids was designed for use in URL shortening, tracking stuff, validating accounts or making pages private (through abstraction.) Instead of showing items as 1, 2, or 3, you could show them as b9iLXiAa, EATedTBy, and Aaco9cy5. Hashes depend on your salt value.

IMPORTANT: This implementation follows the v1.0.0 API release of hashids.js. An older API of hashids.js (v0.1.4) can be found in Hashids version 0.08 and earlier releases; if you have code that depends on this API version, please use a tool like Carton to pin your Hashids install to the older version.

This implementation is also compatible with the v0.3.x hashids.js API.

METHODS

new

my $hashids = Hashids->new();

Make a new Hashids object. This constructor accepts a few options:

my $hashids = Hashids->new(
    salt          => 'this is my salt',
    alphabet      => 'abcdefghijklmnop',
    minHashLength => 8
);
  • salt

    Salt string, this should be unique per Hashids object. Must be either as long or shorter than the alphabet length, as a longer salt string than the alphabet introduces false collisions.

  • alphabet

    Alphabet set to use. This is optional as Hashids comes with a default set suitable for URL shortening. Should you choose to supply a custom alphabet, make sure that it is at least 16 characters long, has no spaces, and only has unique characters.

  • minHashLength

    Minimum hash length. Use this to control how long the generated hash string should be.

You can also construct with just a single argument for the salt, leaving the alphabet and minHashLength at their defaults:

my $hashids = Hashids->new('this is my salt');

encode

my $hash = $hashids->encode($x, [$y, $z, ...]);

Encode a single number (or a list of numbers) into a hash string.

encrypt

Alias for "encode", for compatibility with v0.3.x hashids.js API.

encode_hex

my $hash = $hashids->encode_hex('deadbeef');

Encode a hex string into a hash string.

decode

my $number = $hashids->decode($hash);

Decode a hash string into its number (or numbers.) Returns either a simple scalar if it is a single number, an arrayref of numbers if it decrypted a set, or undef if given bad input. Use "ref" in perlfunc on the result to ensure proper usage.

You can also retrieve the result as a proper list by assigning it to an array variable, by doing so you will always get a list of one or more numbers that are decrypted from the hash, or the empty list if none were found:

my @numbers = $hashids->decode($hash);

decrypt

Alias for this "decode", for compatibility with v0.3.x hashids.js API.

decode_hex

my $hex_string = $hashids->decode_hex($hash);

Opposite of "encode_hex". Unlike "decode", this will always return a string, including the empty string if the hash is invalid.

SEE ALSO

Hashids

LICENSE

The MIT License (MIT)

Copyright (C) Zak B. Elep.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

AUTHOR

Zak B. Elep [email protected]

Original Hashids JavaScript library written by Ivan Akimov

THANKS

Props to Jofell Gallardo for pointing this excellent project to me in the first place.

Many thanks to C. A. Church and Troy Morehouse for their fixes and updates.

hashids.pm's People

Contributors

bayashi avatar thisdroneeatspeople avatar tmorehouse avatar zakame avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

hashids.pm's Issues

Hashids.pm Unable to Decode Hashes it Encodes

There is a bug in version 1.000000 that results in many of the hashes generated by encode() not returning the same value when decode() is called on the hash. The following test script shows an example of this behavior:

#!/usr/bin/perl

use Hashids;
my $i = Hashids->new('EFEWFWfesfwe942',  minHashLength => 10);
foreach(1..100) {
        my $f = $i->encode($_);
        my $a = $i->decode($f);
        if( $a != $_ ) {
                print "$_ FAILED WITH HASH $f, GOT: $a\n";
        }
}

When run, we get the following output:

# perl qwk.pl
34 FAILED WITH HASH Zj2p0ZDrwK, GOT: 
78 FAILED WITH HASH Zj2p0BZDrw, GOT:

Of course, if we extend the sequence, we continue to get more non-matching numbers.

Digging into the code of Hashids.pm, we found starting at line #209:

    if ( my $lottery = substr $hash, 0, 1 ) {
        $hash = substr $hash, 1;

        my $sep = join '|', @{ $self->seps };
        @hash = grep { !/^$/ } split /$sep/ => $hash;

        my @alphabet = @{ $self->chars };
        for my $part (@hash) {
            my @s = ( $lottery, split( // => $self->salt ), @alphabet )
                [ 0 .. @alphabet ];

            @alphabet = $self->_consistentShuffle( \@alphabet, \@s );
            push @$res => $self->_unhash( $part, \@alphabet );
        }
    }

The issue at-hand seems to be that it is perfectly reasonable for $lottery to return 0 and the test to fail, resulting in no decoding of the hash.

I am going to submit a pull request in a moment with a fix and test case to check for the same issue in the future.

infinite loop

$ perl -v

This is perl 5, version 18, subversion 2 (v5.18.2) built for x86_64-linux
(with 1 registered patch, see perl -V for more detail)

This triggers an infinite loop:

#!/usr/bin/env perl

use strict;
use warnings;
use Hashids;
use bignum;

my $hasher = Hashids->new;
my $hash = $hasher->encode(222);
print "Hash: $hash\n";

The problem appears to be the "use bignum" here. In Util->to_alphabet, this is generating a fractional result:

$num /= @alphabet;

and it goes on indefinitely due to this test: while ( $num != 0 );

Truncating the value fixes it:
$num = int($num / @alphabet);

Encrypt results not same as Python or JavaScript Hashids

Using the salt test and encrypting the integers 1, 2, 3, both Python and JavaScript versions of the module prints 9mc2s0, but the Perl version prints 9xt8SB

In Python:

from hashids import Hashids
hashids = Hashids(salt='test')
result = hashids.encode(1, 2, 3)
print(result) # prints 9mc2s0

In JavaScript:

var Hashids = require('hashids');
var hashids = new Hashids('test');
var result = hashids.encode(1, 2, 3);
console.log(result); // prints 9mc2s0

In Perl:

use Hashids;
my $hashids = Hashids->new( salt => 'test' );
my $result = $hashids->encrypt(1, 2, 3);
say $result; # prints 9xt8SB

EDIT: Realized that this was tested using v0.08. Will retest with latest version and change the status of the issue accordingly.

subclass overriding encrypt() breaks decrypt()

Given a subclass with overriden salt and encrypt():

package InheritanceTest;
use Moo;
extends 'Hashids';

has extra_number => ( is => 'ro', required => 1 );
has '+salt' => ( default => sub {'I want peppers'} );

around encrypt => sub {
    my ( $orig, $self, @args ) = @_;
    $self->$orig( $self->extra_number, @args );
};

1;

and test script:

use InheritanceTest;

my $hashids = InheritanceTest->new(extra_number => 123);
my $hash    = $hashids->encrypt(4,5,6);
my $numbers = $hashids->decrypt($hash);

print "$hash -> ", join ',' => @$numbers;

running it seems to give the hash, but not the decoded [4,5,6]:

ybjubtLHr -> % 

("%" is from my zsh.)

Ultimately I want to override decrypt() as well.

Fix {en,de}code_hex() on 32-bit

ubuntu@ip-10-28-248-157:~/.cpanm/work/1410945139.22296/Hashids-1.000000$ perl '-V:use64.*'
use64bitall='undef';
use64bitint='undef';
ubuntu@ip-10-28-248-157:~/.cpanm/work/1410945139.22296/Hashids-1.000000$ prove -l
t/00_compile.t ... ok
t/01_hashids.t ... 1/9 Integer overflow in hexadecimal number at /home/ubuntu/.cpanm/work/1410945139.22296/Hashids-1.000000/lib/Hashids.pm line 115.
    # Child (encode hex strings) exited without calling finalize()

#   Failed test 'encode hex strings'
#   at /home/ubuntu/.plenv/versions/5.20.0/lib/perl5/5.20.0/Test/Builder.pm line 276.
# Looks like you planned 9 tests but ran 7.
# Looks like you failed 1 test of 7 run.
# Looks like your test exited with 29 just after 7.
t/01_hashids.t ... Dubious, test returned 29 (wstat 7424, 0x1d00)
Failed 3/9 subtests
t/02_subclass.t .. ok

Test Summary Report
-------------------
t/01_hashids.t (Wstat: 7424 Tests: 7 Failed: 1)
  Failed test:  7
  Non-zero exit status: 29
  Parse errors: Bad plan.  You planned 9 tests but ran 7.
Files=3, Tests=12,  0 wallclock secs ( 0.05 usr  0.01 sys +  0.24 cusr  0.02 csys =  0.32 CPU)
Result: FAIL
ubuntu@ip-10-28-248-157:~/.cpanm/work/1410945139.22296/Hashids-1.000000$

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.