package Unicode::Utf7;
require 5.000;
require Exporter;

@ISA = qw(Exporter);
@EXPORT = qw(isotoutf7 utf7toiso);


# converts ISO-8859-1 to utf7
sub isotoutf7 {
    my $l = shift;

    $l =~ s/\+/\+-/gs;
    $l =~ s/([^\x21-\x7e]+)/'+' . enb64($1) . '-'/ges;

    return $l;
}

# converts utf7 to ISO-8859-1.
#
# ATTENTION: All Unicodes > 255 are replaced with _.
sub utf7toiso {
    my $l = shift;
    
    $l =~ s/\+-/+ACs-/g;            # arghl!
    $l =~ s/\+(.*?)-/deb64($1)/ge;
    
    return $l;
}



#################################################################

# decode base64
#
# algorithm by Randal Schwartz
# code by bad@ora.de (Christoph Badura)
# modified by Stefan Scholl <stesch@sks.inka.de>
sub deb64 {
    my $l = shift;

    $l =~ tr#A-Za-z0-9+/##cd;             # remove non-base64 chars
    $l =~ tr#A-Za-z0-9+/# -_#;            # convert to uuencoded format
    $len = pack("c", 32 + 0.75*length($l)); # compute length byte
    $l = unpack("u", $len . $l);   # uudecode
    $l =~ s/(.)(.)/$1 ne "\000" ? '_' : $2/ges;
    return $l;
}


# encode base64
#
# algorithm based on an idea by Randal Schwartz
# code by bad@ora.de (Christoph Badura)
# modified by Stefan Scholl <stesch@sks.inka.de>

sub enb64 {
    my $l = shift;
    my ($p, $r);
    my $len;

    $l =~ s/(.)/\x00$1/gs;
    $len = length($l);
    $l .= "\0" x (3 - ($len % 3)) if $len % 3; # pad with nul bytes
    $l = pack("u", $l);                        # uuencode
    
    $r = '';
    foreach $p (split(/\n/, $l)) {
        $p = substr($p, 1);                    # strip length byte
        $p =~ s/\n//gs;                        # deletes newline
        $p =~ tr#` -_#AA-Za-z0-9+/#;           # convert to base64 format
	$p =~ s/A$// if ($len % 3) == 2;       # fix base64 pad chars
	$p =~ s/AA$// if ($len % 3) == 1;
	$r = $r . $p;
    }
    return $r;
}



