MHonArc

 view release on metacpan or  search on metacpan

lib/readmail.pl  view on Meta::CPAN


                while (($pos = index($$body, $boundary, $start_pos)) > -1) {
                    # have to check for case when boundary is a substring
                    #	of another boundary, yuck!
                    $bchkstr = substr($$body, $pos + $blen, 2);
                    unless ($bchkstr =~ /\A\r?\n/ || $bchkstr =~ /\A--/) {
                        # incomplete match, continue search
                        $start_pos = $pos + $blen;
                        next;
                    }
                    $found = 1;
                    push(@parts, substr($$body, 0, $pos));
                    $parts[$#parts] =~ s/^\r//;

                    # prune out part data just grabbed
                    substr($$body, 0, $pos + $blen) = "";

                    # check if hit end
                    if ($$body =~ /\A--/) {
                        $have_end = 1;
                        last;
                    }

                    # remove EOL at the beginning
                    $$body =~ s/\A\r?\n//;
                    $start_pos = 0;
                }
                if ($found) {
                    if (!$have_end) {
                        warn qq/Warning: No end boundary delimiter found in /,
                            qq/message body\n/;
                        push(@parts, $$body);
                        $parts[$#parts] =~ s/^\r//;
                        $$body = "";
                    } else {
                        # discard front-matter
                        shift(@parts);
                    }
                } else {
                    # no boundary separators in message!
                    warn qq/Warning: No boundary delimiters found in /,
                        qq/multipart body\n/;
                    if ($$body =~ m/\A\n[\w\-]+:\s/) {
                        # remove \n added above if part looks like it has
                        # headers.  we keep if it does not to avoid body
                        # data being parsed as a header below.
                        substr($$body, 0, 1) = "";
                    }
                    push(@parts, $$body);
                }

                ## Else treat body as one part
            } else {
                @parts = ($$body);
            }

            ## Process parts
            my (@entity) = ();
            my ($cid, $href, $pctype);
            my %alt_exc        = ();
            my $have_alt_prefs = $isalt && scalar(@_MIMEAltPrefs);
            my $partno         = 0;
            @parts = \(@parts);
            while (defined($part = shift(@parts))) {
                $href = {};
                $partfields = $href->{'fields'} = (MAILread_header($part))[0];
                $href->{'body'}                    = $part;
                $href->{'filtered'}                = 0;
                $partfields->{'x-mha-part-number'} = ++$partno;
                $pctype =
                    extract_ctype($partfields->{'content-type'}, $ctype);

                ## check alternative preferences
                if ($have_alt_prefs) {
                    next if ($alt_exc{$pctype});
                    my $pos = $_MIMEAltPrefs{$pctype};
                    if (defined($pos)) {
                        for (++$pos; $pos <= $#_MIMEAltPrefs; ++$pos) {
                            $alt_exc{$_MIMEAltPrefs[$pos]} = 1;
                        }
                    }
                }

                ## only add to %Cid if not excluded
                if (!&MAILis_excluded($pctype)) {
                    if ($isalt) {
                        unshift(@entity, $href);
                    } else {
                        push(@entity, $href);
                    }
                    $cid = $partfields->{'content-id'}[0]
                        || $partfields->{'message-id'}[0];
                    if (defined($cid)) {
                        $cid =~ s/[\s<>]//g;
                        $Cid{"cid:$cid"} = $href if $cid =~ /\S/;
                    }
                    $cid = undef;
                    if (defined($partfields->{'content-location'})
                        && ($cid = $partfields->{'content-location'}[0])) {
                        my $partbase = $uribase;
                        $cid =~ s/['"\s]//g;
                        if (defined($partfields->{'content-base'})) {
                            $partbase = $partfields->{'content-base'}[0];
                        }
                        $cid = apply_base_url($partbase, $cid);
                        if ($cid =~ /\S/ && !$Cid{$cid}) {
                            $Cid{$cid} = $href;
                        }
                    }
                    if ($cid) {
                        $partfields->{'content-location'} = [$cid];
                    } elsif (!defined($partfields->{'content-base'})) {
                        $partfields->{'content-base'} = [$uribase];
                    }

                    $partfields->{'x-mha-parent-header'} = $fields;
                }
            }

            my ($entity);
        ENTITY: foreach $entity (@entity) {
                if ($entity->{'filtered'}) {
                    next ENTITY;
                }

                ## If content-type not defined for part, then determine
                ## content-type based upon multipart subtype.
                $partfields = $entity->{'fields'};
                if (!defined($partfields->{'content-type'})) {
                    $partfields->{'content-type'} = [
                        ($subtype =~ /digest/)
                        ? 'message/rfc822'
                        : 'text/plain'
                    ];

lib/readmail.pl  view on Meta::CPAN

    my $str     = shift;    # Input string
    my $hasmain = shift;    # Flag if there is a main value to extract

    require MHonArc::RFC822;

    my $parm = {};
    my @toks = MHonArc::RFC822::uncomment($str);
    my ($tok, $name, $value, $charset, $lang, $isPart);

    $parm->{'x-main'} = shift @toks if $hasmain;

    ## Loop thru token list
    while ($tok = shift @toks) {
        next if $tok eq ";";
        ($name, $value) = split(/=/, $tok, 2);
        ## Check if charset/lang specified
        if ($name =~ s/\*$//) {
            if ($value =~ s/^([^']*)'([^']*)'//) {
                ($charset, $lang) = ($1, $2);
            } else {
                ($charset, $lang) = (undef, undef);
            }
        }
        ## Check if parameter is only part
        if ($name =~ s/\*(\d+)$//) {
            $isPart = 1;
        } else {
            $isPart = 0;
        }
        ## Set values for parameter
        $name = lc $name;
        $parm->{$name} = {} unless defined($parm->{$name});
        $parm->{$name}{'charset'} = $charset;
        $parm->{$name}{'lang'}    = $lang;
        ## Check if value is next token
        if ($value eq "") {
            ## If value next token, than it must be quoted
            $value = shift @toks;
            $value =~ s/^"//;
            $value =~ s/"$//;
            $value =~ s/\\//g;
        }
        if ($isPart && defined($parm->{$name}{'vlist'})) {
            push(@{$parm->{$name}{'vlist'}}, $value);
        } else {
            $parm->{$name}{'vlist'} = [$value];
        }
    }

    ## Now we loop thru each parameter and define the final values from
    ## the parts
    foreach $name (keys %$parm) {
        next if $name eq 'x-main';
        $parm->{$name}{'value'} = join("", @{$parm->{$name}{'vlist'}});
    }

    $parm;
}

##---------------------------------------------------------------------------##
##	MAILset_alternative_prefs() is used to set content-type
##	preferences for multipart/alternative entities.  The list
##	specified will supercede the prefered format as denoted by
##	the ording of parts in the entity.
##
##	A content-type listed earlier in the array will be prefered
##	over one later.  For example:
##
##	  MAILset_alternative_prefs('text/plain', 'text/html');
##
##	States that if a multipart/alternative entity contains a
##	text/plain part and a text/html part, the text/plain part will
##	be prefered over the text/html part.
##
sub MAILset_alternative_prefs {
    @_MIMEAltPrefs = map {lc} @_;
    %_MIMEAltPrefs = ();
    my $i = 0;
    my $ctype;
    foreach $ctype (@_MIMEAltPrefs) {
        $_MIMEAltPrefs{$ctype} = $i++;
    }
}

##---------------------------------------------------------------------------##
##	MAILset_charset_aliases() is used to define name aliases for
##	charset names.
##
##	Example usage:
##	  MAILset_charset_aliases( {
##	    'iso-8859-1' =>  [ 'latin1', 'iso_8859_1', '8859-1' ],
##	    'iso-8859-15' => [ 'latin9', 'iso_8859_15', '8859-15' ],
##	  }, $override );
##
sub MAILset_charset_aliases {
    my $map      = shift;
    my $override = shift;

    %MIMECharsetAliases = () if $override;
    my ($charset, $aliases, $alias);
    while (($charset, $aliases) = each(%$map)) {
        $charset = lc $charset;
        foreach $alias (@$aliases) {
            $MIMECharsetAliases{lc $alias} = $charset;
        }
    }
}

##---------------------------------------------------------------------------##
##	MAILload_charset_converter() loads the charset converter function
##	associated with given charset name.
##
##	Example usage:
##	  ($func, $real_charset) = MAILload_charset_converter($charset);
##
##	$func is the reference to the converter function, which may be
##	undef.  $real_charset is the real charset name that should be
##	used when invoking the function.
##
sub MAILload_charset_converter {
    my $charset = lc shift;
    $charset = $MIMECharsetAliases{$charset} if $MIMECharsetAliases{$charset};
    my $func = load_charset($charset);
    if (!defined($func) || !defined(&$func)) {
        $func = load_charset('default');
    }
    ($func, $charset);
}

###############################################################################
##	Private Routines
###############################################################################

##---------------------------------------------------------------------------##
##	Default function for unable to process a part of a multipart



( run in 0.585 second using v1.01-cache-2.11-cpan-8f98c5d2c55 )