=encoding UTF-8

=head1 NAME

Unicode::Confuse - Identify and replace Unicode confusables

=head1 SYNOPSIS

    
    use utf8;
    use Unicode::Confuse ':all';
    if (confusable ('ρ')) {
        my $canonical = canonical ('ρ');
        print "'ρ' is confusable with $canonical.\n";
        my @similar = similar ($canonical);
        print "$canonical is also confusable with @similar.\n";
    }
    

produces output

    'ρ' is confusable with p.
    p is also confusable with p ρ ϱ р ⍴ ⲣ ｐ 𝐩 𝑝 𝒑 𝓅 𝓹 𝔭 𝕡 𝖕 𝗉 𝗽 𝘱 𝙥 𝚙 𝛒 𝛠 𝜌 𝜚 𝝆 𝝔 𝞀 𝞎 𝞺 𝟈.

(This example is included as L<F<synopsis.pl>|https://fastapi.metacpan.org/source/BKB/Unicode-Confusables-0.05/examples/synopsis.pl> in the distribution.)

=head1 VERSION

This documents version 0.05 of Unicode-Confuse
corresponding to L<git commit 4a97ea6b65f148a559b21ebde80b189257d16b1c|https://github.com/benkasminbullock/unicode-confuse/commit/4a97ea6b65f148a559b21ebde80b189257d16b1c> released on Thu Apr 29 11:49:01 2021 +0900.

This Perl module incorporates Unicode Security Mechanisms for UTS #39 version 13.0.0 dated 2020-02-13, 01:38:49 GMT, copyright © 2020 Unicode®, Inc.. For terms of use, see L<http://www.unicode.org/terms_of_use.html>.

=head1 DESCRIPTION

This module offers functions for dealing with Unicode "confusables",
characters which look similar to one another but are represented by
different Unicode code points.

=head1 FUNCTIONS

=head2 canonical

   my $canonical = canonical ($c);

If C<$c> is a confusable, give the canonical form of C<$c>. If $c is
already the canonical form of itself, return $c. If C<$c> is not a
confusable, this returns the undefined value. "Canonical" here just
means the character which is used as a representative of the group of
confusables in the L</Unicode data files>.

=head2 confusable

    if (confusable ($c)) {
        # do something.
    }

This returns a true or false value depending on whether C<$c> is a
confusable. This matches C<$c> against a large regex in
L<Unicode::Confuse::Regex>.

=head2 similar

    my @similar = similar ('p');

Return a list of confusables which are similar to the given input. If
the input is not a confusable, an empty list is returned.

The first character in C<@similar> is the canonical form, and the
remaining characters are the other confusables associated with that
canonical form. These remaining characters, if more than one, are
sorted by code point.

=head3 Example: obfuscate text

This example obfuscates strings by substituting confusable letters
with substitutes picked at random from the confusable data for the
letters.

    
    use utf8;
    use Unicode::Confuse ':all';
    
    sub obfuscate
    {
        for (@_) {
            my @letters = split '', $_;
            my $out = '';
            my $ok;
            for my $letter (@letters) {
                my @similar = similar ($letter);
                if (@similar) {
                    $ok = 1;
                    my $n = scalar (@similar);
                    my $r = int (rand ($n));
                    $out .= $similar[$r];
                }
                else {
                    $out .= $letter;
                }
            }
            if (! $ok) {
                print "No confusables in '$_'.\n";
            }
            else {
                print "$_ -> $out\n";
            }
        }
    }
    
    obfuscate ('paypal', '月火水木金土日');

produces output

    paypal -> 𝘱𝒂𝐲𝓅𝖺𝜤
    月火水木金土日 -> 月火水木金⼠⽇

(This example is included as L<F<obfuscate.pl>|https://fastapi.metacpan.org/source/BKB/Unicode-Confusables-0.05/examples/obfuscate.pl> in the distribution.)

=head1 DEPENDENCIES

=over

=item L<File::Slurper>

This is used by the parsing module L<Unicode::Confuse::Parse>.

=item L<JSON::Parse>

This is used to parse the JSON-formatted file of confusables
distributed with the module.

=back 

=head1 BUGS

=over

=item Unicode specifications

This does not even attempt to replicate the Unicode requirements for
software for handling confusables. In other words, this Perl module
makes no claim whatsoever to be "An implementation claiming
conformance to this specification" as described in the text of the
L</Unicode Consortium specification>.

=item Data quality

The data in the Unicode confusables file is of mixed quality, with
nearly identical or indistinguishable characters muddled together with
things which are clearly quite different from one another.

=back

=head1 SEE ALSO

=head2 In this distribution

The script F<make-confusables.pl>, available only in the github
repository, makes the data files for this Perl distribution.

L<Unicode::Confuse::Parse> is used to parse the data file
(F<confusables.txt>). It is used by F<make-confusables.pl>.

L<Unicode::Confuse::Regex> is generated by F<make-confusables.pl>. It
matches all confusables.

The unexported variable C<$Unicode::Confuse::data> contains the
complete confusable data. C<< $data->{confusables} >> contains a map
from confusables to the canonical format, and C<< $data->{reverse} >>
contains a map from the canonical form to an array containing the
corresponding set of confusables, which may have only one member.

=head2 Unicode Consortium information

=over

=item Unicode Consortium specification

See L<http://www.unicode.org/reports/tr39> for the Unicode Consortium
specification.

=item Unicode data files

The following links point to the latest data files:

=over

=item L<The data used by this module|https://www.unicode.org/Public/security/latest/confusables.txt>

=item L<The same data in a different format|https://www.unicode.org/Public/security/latest/confusablesSummary.txt>

=back

=item L<Unicode Utilities: Confusables|https://util.unicode.org/UnicodeJsps/confusables.jsp>

The utility says

=over

With this demo, you can supply an Input string and see the
combinations that are confusable with it, using data collected by the
Unicode consortium.

=back

=back

=head1 AUTHOR

Ben Bullock, <bkb@cpan.org>

=head1 COPYRIGHT & LICENCE

This package and associated files are copyright (C) 
2021
Ben Bullock.

You can use, copy, modify and redistribute this package and associated
files under the Perl Artistic Licence or the GNU General Public
Licence.
