Sha: add structured answer

master
Matt Miller 2014-10-15 13:48:25 +02:00
parent 51639f4d2f
commit 26a4b122b3
3 changed files with 223 additions and 80 deletions

View File

@ -4,8 +4,8 @@ package DDG::Goodie::Sha;
use DDG::Goodie;
use Digest::SHA;
zci is_cached => 1;
zci answer_type => "sha";
zci is_cached => 1;
primary_example_queries 'SHA this';
secondary_example_queries 'sha-512 that', 'sha512sum dim-dims', 'sha hash of "this and that"';
@ -19,58 +19,32 @@ attribution web => [ 'https://www.duckduckgo.com', 'DuckDuckGo' ],
twitter => ['http://twitter.com/duckduckgo', 'duckduckgo'];
triggers query => qr/^sha\-?(1|224|256|384|512|)(?:sum|) (hex|base64|)\s*(.*)$/i;
sub html_output {
my ($str, $sha, $sha_version) = @_;
# prevent XSS
$str = html_enc($str);
return "<div class='zci--sha'>"
."<span class='text--secondary'>$sha_version of \"$str\"</span><br/>"
."<span class='text--primary'>$sha</span>"
."</div>";
}
triggers query => qr/^sha\-?(?<ver>1|224|256|384|512|)?(?:sum|)\s*(?<enc>hex|base64|)\s*(?<str>.*)$/i;
handle query => sub {
my $command1 = $1 || '';
my $command2 = $2 || '';
my $str = $3 || '';
#warn "CMD 1: '$command1'\tCMD 2: '$command2'\tSTR: '$str'\n";
my $ver = $+{'ver'} || 1;
my $enc = lc $+{'enc'} || 'hex';
my $str = $+{'str'} || '';
$str =~ s/^hash\s+(.*\S+)/$1/; # Remove 'hash' in queries like 'sha hash this'
$str =~ s/^of\s+(.*\S+)/$1/; # Remove 'of' in queries like 'sha hash of this'
$str =~ s/^\"(.*)\"$/$1/; # remove quotes (e.g. sha1 "this string")
$str =~ s/^hash\s+(.*\S+)/$1/; # Remove 'hash' in queries like 'sha hash this'
$str =~ s/^of\s+(.*\S+)/$1/; # Remove 'of' in queries like 'sha hash of this'
$str =~ s/^\"(.*)\"$/$1/; # remove quotes (e.g. sha1 "this string")
return unless $str;
# return if there is nothing left to hash
return unless ($str);
my $func_name = 'Digest::SHA::sha' . $ver . '_' . $enc;
my $func = \&$func_name;
my $sha;
if ( $command1 eq '224' ) {
$sha = $command2 eq 'base64' ? Digest::SHA::sha224_base64($str) : Digest::SHA::sha224_hex($str);
}
elsif ( $command1 eq '256' ) {
$sha = $command2 eq 'base64' ? Digest::SHA::sha256_base64($str) : Digest::SHA::sha256_hex($str);
}
elsif ( $command1 eq '384' ) {
$sha = $command2 eq 'base64' ? Digest::SHA::sha384_base64($str) : Digest::SHA::sha384_hex($str);
}
elsif ( $command1 eq '512' ) {
$sha = $command2 eq 'base64' ? Digest::SHA::sha512_base64($str) : Digest::SHA::sha512_hex($str);
}
else {
$command1 = '1';
$sha = $command2 eq 'base64' ? Digest::SHA::sha1_base64($str) : Digest::SHA::sha1_hex($str);
}
my $out = $func->($str);
my $pre_len = length($out) % 4;
my $pad = ($enc eq 'base64' && $pre_len) ? 4 - $pre_len : 0;
$out .= '=' x $pad if ($pad);
# pad with '=' until base64 output length is a multiple of 4
if ($command2 eq 'base64'){
while (length($sha) % 4) {
$sha .= '=';
}
}
return $sha, html => html_output($str, $sha, "SHA-$command1");
return $out,
structured_answer => {
input => [html_enc($str)],
operation => 'SHA-' . $ver . ' ' . $enc . ' hash',
result => $out
};
};
1;

View File

@ -1,5 +0,0 @@
.zci--answer .zci--sha {
font-weight: 300;
padding: .25em 0;
word-wrap: break-word;
}

230
t/Sha.t
View File

@ -1,5 +1,6 @@
#!/usr/bin/env perl
use utf8;
use strict;
use warnings;
use Test::More;
@ -9,37 +10,210 @@ zci answer_type => 'sha';
zci is_cached => 1;
ddg_goodie_test(
[qw(
DDG::Goodie::Sha
)],
'shasum the duckdukcgo serach engine' => test_zci('8af70bf86260fec05d7cc89e0f0be2aa3db5e5e4', html=>qr/.*/),
'sha1sum the duckdukcgo serach engine' => test_zci('8af70bf86260fec05d7cc89e0f0be2aa3db5e5e4', html=>qr/.*/),
'sha-1 the duckdukcgo serach engine' => test_zci('8af70bf86260fec05d7cc89e0f0be2aa3db5e5e4', html=>qr/.*/),
'sha256sum base64 the duckdukcgo serach engine' => test_zci('XUKkFU44G21/OPBB47hIwC3Q1lb1Cl8ktI2GjyCDFrM=', html=>qr/.*/),
'sha256sum base64 the duckdukcgo serach engine' => test_zci('XUKkFU44G21/OPBB47hIwC3Q1lb1Cl8ktI2GjyCDFrM=', html=>qr/.*/),
'sha-256 base64 the duckdukcgo serach engine' => test_zci('XUKkFU44G21/OPBB47hIwC3Q1lb1Cl8ktI2GjyCDFrM=', html=>qr/.*/),
'sha-1 base64 lorem ipsum' => test_zci('v7d1mmfa62VBBJC02Yu52n0eos4=', html=>qr/.*/),
'sha-224 base64 lorem ipsum' => test_zci('4ZHt8GAFcSWDUYztkswqwvrI1uRiOwIaUHNqkQ==', html=>qr/.*/),
'sha-256 base64 lorem ipsum' => test_zci('Xiv1fT9AxLbfadrxk2y3ZvgyN0tPwCWafL/wbi9w8mk=', html=>qr/.*/),
'sha-384 base64 lorem ipsum' => test_zci('WXSTps8SiXV1JOVN/W9oszLHIUpxajNYkR71wJkHrcimVKGMHXIeGDsAJfmW9uJG', html=>qr/.*/),
'sha-512 base64 lorem ipsum' => test_zci('+A7r2aq7GhX7hp7VaNhYpcDco9XaB6QQ4b2Yh2ORjZc+NEgUYl98hEaVst42/9J68pDQ40NixR3uWUfVjUBSeg==', html=>qr/.*/),
'shasum hex this' => test_zci('c2543fff3bfa6f144c2f06a7de6cd10c0b650cae', html=>qr/.*/),
'sha224sum base64 this' => test_zci('kFct0af7OnZ8E66tO0CmyDv1uXW7nSRHon3JYg==', html=>qr/.*/),
[qw( DDG::Goodie::Sha)],
'shasum the duckdukcgo serach engine' => test_zci(
'8af70bf86260fec05d7cc89e0f0be2aa3db5e5e4',
structured_answer => {
input => ['the duckdukcgo serach engine'],
operation => 'SHA-1 hex hash',
result => '8af70bf86260fec05d7cc89e0f0be2aa3db5e5e4'
}
),
'sha1sum the duckdukcgo serach engine' => test_zci(
'8af70bf86260fec05d7cc89e0f0be2aa3db5e5e4',
structured_answer => {
input => ['the duckdukcgo serach engine'],
operation => 'SHA-1 hex hash',
result => '8af70bf86260fec05d7cc89e0f0be2aa3db5e5e4'
}
),
'sha-1 the duckdukcgo serach engine' => test_zci(
'8af70bf86260fec05d7cc89e0f0be2aa3db5e5e4',
structured_answer => {
input => ['the duckdukcgo serach engine'],
operation => 'SHA-1 hex hash',
result => '8af70bf86260fec05d7cc89e0f0be2aa3db5e5e4'
}
),
'sha256sum base64 the duckdukcgo serach engine' => test_zci(
'XUKkFU44G21/OPBB47hIwC3Q1lb1Cl8ktI2GjyCDFrM=',
structured_answer => {
input => ['the duckdukcgo serach engine'],
operation => 'SHA-256 base64 hash',
result => 'XUKkFU44G21/OPBB47hIwC3Q1lb1Cl8ktI2GjyCDFrM='
}
),
'sha256sum base64 the duckdukcgo serach engine' => test_zci(
'XUKkFU44G21/OPBB47hIwC3Q1lb1Cl8ktI2GjyCDFrM=',
structured_answer => {
input => ['the duckdukcgo serach engine'],
operation => 'SHA-256 base64 hash',
result => 'XUKkFU44G21/OPBB47hIwC3Q1lb1Cl8ktI2GjyCDFrM='
}
),
'sha-256 base64 the duckdukcgo serach engine' => test_zci(
'XUKkFU44G21/OPBB47hIwC3Q1lb1Cl8ktI2GjyCDFrM=',
structured_answer => {
input => ['the duckdukcgo serach engine'],
operation => 'SHA-256 base64 hash',
result => 'XUKkFU44G21/OPBB47hIwC3Q1lb1Cl8ktI2GjyCDFrM='
}
),
'sha-1 base64 lorem ipsum' => test_zci(
'v7d1mmfa62VBBJC02Yu52n0eos4=',
structured_answer => {
input => ['lorem ipsum'],
operation => 'SHA-1 base64 hash',
result => 'v7d1mmfa62VBBJC02Yu52n0eos4='
}
),
'sha-224 base64 lorem ipsum' => test_zci(
'4ZHt8GAFcSWDUYztkswqwvrI1uRiOwIaUHNqkQ==',
structured_answer => {
input => ['lorem ipsum'],
operation => 'SHA-224 base64 hash',
result => '4ZHt8GAFcSWDUYztkswqwvrI1uRiOwIaUHNqkQ=='
}
),
'sha-256 base64 lorem ipsum' => test_zci(
'Xiv1fT9AxLbfadrxk2y3ZvgyN0tPwCWafL/wbi9w8mk=',
structured_answer => {
input => ['lorem ipsum'],
operation => 'SHA-256 base64 hash',
result => 'Xiv1fT9AxLbfadrxk2y3ZvgyN0tPwCWafL/wbi9w8mk='
}
),
'sha-384 base64 lorem ipsum' => test_zci(
'WXSTps8SiXV1JOVN/W9oszLHIUpxajNYkR71wJkHrcimVKGMHXIeGDsAJfmW9uJG',
structured_answer => {
input => ['lorem ipsum'],
operation => 'SHA-384 base64 hash',
result => 'WXSTps8SiXV1JOVN/W9oszLHIUpxajNYkR71wJkHrcimVKGMHXIeGDsAJfmW9uJG'
}
),
'sha-512 base64 lorem ipsum' => test_zci(
'+A7r2aq7GhX7hp7VaNhYpcDco9XaB6QQ4b2Yh2ORjZc+NEgUYl98hEaVst42/9J68pDQ40NixR3uWUfVjUBSeg==',
structured_answer => {
input => ['lorem ipsum'],
operation => 'SHA-512 base64 hash',
result => '+A7r2aq7GhX7hp7VaNhYpcDco9XaB6QQ4b2Yh2ORjZc+NEgUYl98hEaVst42/9J68pDQ40NixR3uWUfVjUBSeg=='
}
),
'shasum hex this' => test_zci(
'c2543fff3bfa6f144c2f06a7de6cd10c0b650cae',
structured_answer => {
input => ['this'],
operation => 'SHA-1 hex hash',
result => 'c2543fff3bfa6f144c2f06a7de6cd10c0b650cae'
}
),
'sha224sum base64 this' => test_zci(
'kFct0af7OnZ8E66tO0CmyDv1uXW7nSRHon3JYg==',
structured_answer => {
input => ['this'],
operation => 'SHA-224 base64 hash',
result => 'kFct0af7OnZ8E66tO0CmyDv1uXW7nSRHon3JYg=='
}
),
'sha1sum "this"' => test_zci('c2543fff3bfa6f144c2f06a7de6cd10c0b650cae', html=>qr/.*SHA-1 of "this".*/),
'sha "this' => test_zci('e1ea2c30284aa81804b52c034c997b06c5d7d4d9', html=>qr/.*SHA-1 of "&quot;this".*/),
'sha this"' => test_zci('2d9d48e524574ae527fbd5e55ea2e7dcba84d4f9', html=>qr/.*SHA-1 of "this&quot;".*/),
'sha "this and "that""' => test_zci('aa6b22799b19374a5d01f07167fd0f3bea897bd0', html=>qr/.*SHA-1 of "this and &quot;that&quot;".*/),
'sha1sum "this"' => test_zci(
'c2543fff3bfa6f144c2f06a7de6cd10c0b650cae',
structured_answer => {
input => ['this'],
operation => 'SHA-1 hex hash',
result => 'c2543fff3bfa6f144c2f06a7de6cd10c0b650cae'
}
),
'sha "this' => test_zci(
'e1ea2c30284aa81804b52c034c997b06c5d7d4d9',
structured_answer => {
input => ['&quot;this'],
operation => 'SHA-1 hex hash',
result => 'e1ea2c30284aa81804b52c034c997b06c5d7d4d9'
}
),
'sha this"' => test_zci(
'2d9d48e524574ae527fbd5e55ea2e7dcba84d4f9',
structured_answer => {
input => ['this&quot;'],
operation => 'SHA-1 hex hash',
result => '2d9d48e524574ae527fbd5e55ea2e7dcba84d4f9'
}
),
'sha "this and "that""' => test_zci(
'aa6b22799b19374a5d01f07167fd0f3bea897bd0',
structured_answer => {
input => ['this and &quot;that&quot;'],
operation => 'SHA-1 hex hash',
result => 'aa6b22799b19374a5d01f07167fd0f3bea897bd0'
}
),
'sha hash of "this and that"' => test_zci('4f813651453b11db74cbc36ccddea13f109e8412', html=>qr/.*/),
'sha hash of this and that' => test_zci('4f813651453b11db74cbc36ccddea13f109e8412', html=>qr/.*/),
'sha hash this and that' => test_zci('4f813651453b11db74cbc36ccddea13f109e8412', html=>qr/.*/),
'sha256 base64 hash of "this and that"' => test_zci('6GPBrEJhmitCmgh3WmrNif9MLGuNrhLjRhpfpjsvkvU=', html=>qr/.*/),
'shasum <script>alert( "hello" )<script>' => test_zci('10c4a3b691419901a56fade7e4b5e04fe4ef6570', html=> qr/.*SHA-1 of "&lt;script&gt;alert\( &quot;hello&quot; \)&lt;script&gt;".*/),
'shasum script>ALERT hello script>' => test_zci('9ef5127abf5a46ef82a1bc10e6a8447a205644cd', html=>qr/.*SHA-1 of "script&gt;ALERT hello script&gt;".*/),
'sha1 & / " \\\' ; < > ' => test_zci('58ae7fba7b9df6da46cb42e6e3ad2ddc3f6a2a58', html=>qr/.*SHA-1 of "&amp; \/ &quot; \\&#39; ; &lt; &gt;".*/),
'sha hash of "this and that"' => test_zci(
'4f813651453b11db74cbc36ccddea13f109e8412',
structured_answer => {
input => ['this and that'],
operation => 'SHA-1 hex hash',
result => '4f813651453b11db74cbc36ccddea13f109e8412'
}
),
'sha hash of this and that' => test_zci(
'4f813651453b11db74cbc36ccddea13f109e8412',
structured_answer => {
input => ['this and that'],
operation => 'SHA-1 hex hash',
result => '4f813651453b11db74cbc36ccddea13f109e8412'
}
),
'sha hash this and that' => test_zci(
'4f813651453b11db74cbc36ccddea13f109e8412',
structured_answer => {
input => ['this and that'],
operation => 'SHA-1 hex hash',
result => '4f813651453b11db74cbc36ccddea13f109e8412'
}
),
'sha256 base64 hash of "this and that"' => test_zci(
'6GPBrEJhmitCmgh3WmrNif9MLGuNrhLjRhpfpjsvkvU=',
structured_answer => {
input => ['this and that'],
operation => 'SHA-256 base64 hash',
result => '6GPBrEJhmitCmgh3WmrNif9MLGuNrhLjRhpfpjsvkvU='
}
),
'shasum <script>alert( "hello" )<script>' => test_zci(
'10c4a3b691419901a56fade7e4b5e04fe4ef6570',
structured_answer => {
input => ['&lt;script&gt;alert( &quot;hello&quot; )&lt;script&gt;'],
operation => 'SHA-1 hex hash',
result => '10c4a3b691419901a56fade7e4b5e04fe4ef6570'
}
),
'shasum script>ALERT hello script>' => test_zci(
'9ef5127abf5a46ef82a1bc10e6a8447a205644cd',
structured_answer => {
input => ['script&gt;ALERT hello script&gt;'],
operation => 'SHA-1 hex hash',
result => '9ef5127abf5a46ef82a1bc10e6a8447a205644cd'
}
),
'sha1 & / " \\\' ; < > ' => test_zci(
'58ae7fba7b9df6da46cb42e6e3ad2ddc3f6a2a58',
structured_answer => {
input => ['&amp; / &quot; \&#39; ; &lt; &gt;'],
operation => 'SHA-1 hex hash',
result => '58ae7fba7b9df6da46cb42e6e3ad2ddc3f6a2a58'
}
),
'sha password' => test_zci(
'5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8',
structured_answer => {
input => ['password'],
operation => 'SHA-1 hex hash',
result => '5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8'
}
),
);
done_testing;