MIME::Xparser - A mime parser that is somewhat reminiscent of the way SAX parses XML.


NAME

MIME::Xparser - A mime parser that is somewhat reminiscent of the way SAX parses XML (i.e. it invokes callbacks as things are found).


SYNOPSIS

  use Your_Content_Handler;
  use MIME::Xparser;
  my $handler = new Your_Content_Handler;
  my $parser  = new MIME::Xparser;
  $parser->set_content_handler($handler);
  $parser->start_document();
  while (<YOUR_FILE>)
  {
      $parser->line($_);
  }
  $parser->end_document();


DESCRIPTION

A program which wishes to parse a mime document feeds lines of input to the parser (as shown above).

The parser examines each line fed to it, and invokes a series of handler methods (listed below) at the appropriate time.

The handler methods are provided by the handler class, which you must provide.

Structure methods are used to communicate the structure of the document to your handler.

Data methods are used to pass the lines of data to your handler. The data is not altered. The data is explicitly categorized via the method invoked to pass the data, and implicitly categorized by the sequence of structure calls.

The parser provides no information about the document except the structure.

It is up to the content handler to save and parse out what ever data it needs when handling the document. One utility function is available that may help. A later version of this module may provide some additional assistance, though it will never be the intention of this module to handle the content of a mime document except as required to find its structure.

As mentioned, you must provide the handler. The source code includes several simple handlers at the very top. The distribution includes two sample scripts that define handlers and parse data.


PARSER METHODS

new [ HANDLER-OBJECT (optional) ]

Returns a parser object. You can specifiy the handler at this time if you wish.

set_content_handler HANDLER-OBJECT

Sets the content handler to use. No useful return value.

start_document

Tells the parser you are about to start parsing a document. No useful return value.

end_document

Tells the parser you have finished parsing a document. No useful return value.

in_document

Returns true between calls to start_document and end_document, false otherwise. Useful to see if end_document should be called, which may be useful if a single parser is being used to scan multiple messages (such as in a mailbox).

line A_STRING__ONE_LOGICAL_LINE

This is used to pass the next line of input to the parser. The lines do not need to be terminated with a new line, either CRLF, \n, or anything else. Each string is assumed to be a single logical line of input.

No useful return value.


CALLABLE UTILITY FUNCTIONS

The following may be useful to a handler. These are regular subs, not methods. They are not exported, so you will need to specify them by their full name, or import them yourself.

MIME::Xparser::parse_value STRING

Returns the first value found in the string, either a SINGLE mime token, or a quoted string.

A quoted string value does not include the quotes, and escaped quotes within the value will no longer include the escape character (\).

A token is exactly one token, so (for example) it cannot pull out something like the mime/type (in a single call) because that is two tokens.

The string must already have been trimmed so that the desired value is the first thing in the string.

  E.g.
  
  # a typical header
  $string = "A-typical-Header: something=the-value";
  # get a string that has the desired value at the front
  ($contains_the_value) = $string =~ m/something=(.*)/;
  # and extract that value
  $the_value = MIME::Xparser::parse_value($contains_the_value);
MIME::Xparser::join_header_lines @ARRAY

Returns a string which is the header lines joined together using an algorithm that will work for typical data. I.e. a single white space is removed from the beginning of each line, and any number of trailing \r's or \n's are trimmed from each line, and the resulting lines are joined into a single string.


HANDLER INTERFACE

Your content handler should provide the following methods. AUTOLOAD can be used to reduce the number of methods required.

All methods receive your handler object, as per any method call. Additional parameters only are shown.

STRUCTURE METHODS (no (additional) parameters)

start_document
end_document
start_message
end_message
start_headers
end_headers
start_body
end_body
start_parts
end_parts
start_preamble
end_preamble
start_part
end_part
start_postamble
end_postamble

DATA METHODS (one parameter received)

The four data methods, header, neck, body, and boundary, receive the original data unaltered. I.e. If the strings are echoed as they are received then the original data will be identically reproduced.

header @the_lines_making_up_one_header

The parameter input to the handler is an array of strings which are the lines that make up a single header.

The word header, here, means a single header item, not the entire block of header lines at the top of a mime entity.

neck $null_line

The parameter input to the handler is a single string which is the null line that seperated the headers from the body.

body $one_line_from_the_body

The parameter input to the handler is a single string which is a line of data from the body.

boundary $a_boundary_line

The parameter input to the handler is a single string which is a boundary line found between parts.

METHOD CALL NESTING

The following tries to indicate the nesting of the calls that your handler will see. (1) (2) (3) denotes that one of the indicated sets of calls will be made in any given situation.

Some methods and sets of methods may be invoked multiple times as appropriate, but that is not shown.

  start_document 
      start_message 
          start_headers 
              header
          end_headers 
          neck
      (1) start_body 
              body
          end_body
      (2) start_parts 
              start_preamble 
                  body
              end_preamble 
              boundary
              start_part 
                  start_headers 
                      header
                  end_headers 
                  (1) (2) or (3)
              end_part 
              boundary
              start_postamble 
                  body
              end_postamble 
          end_parts
      (3) start_body 
              start_message
                  (recursively invoke the calls already shown)
              end_message
          end_body 
      end_message
  end_document


VERSION

version 0.4


EXAMPLE

This example displays the structure of the messages in a mail box file. it uses one of the provided example content handlers.

  #!/usr/bin/perl
  # usage: this-file an-mbox-file
  use MIME::Xparser;
  my $handler = new MIME::Xparser::Handler::Structure();
  my $parser  = new MIME::Xparser($handler);
  FOR:
  for (;;)
  { 
    while (<>)
    {
        if (m/^From /)
        {   
            $parser->end_document() if $parser->in_document();
            print "\n$_";
            $parser->start_document();
            next FOR;
        }
        $parser->line($_);
    }
    $parser->end_document() if $parser->in_document();
    last;
  }

ALSO

The distribution includes extract-pl which extracts attachments from a mail box file, and examine-pl which shows the structure of a message and a few keys other bits of data. These illustrate some uses of the module.

The Xparser.pm module includes two trivial handlers at the top of the code. These are both potentially useful and are examples of simple handlers.


INSTALL

  perl Makefile.PL
  make
  make test
  make install

Or simply copy the Xparser.pm file into a MIME subdirectory of your perl @INC path.


BUGS

MIME-Version is found but not used.

Embedded message/rfc822 parts are parsed whether you want them to be or not. (That's not really a bug, and your handler is free to skip them if it wishes.)

Virtually no assistance is provided for the parsing requirements that a handler might have. Again, this is not a bug, though it might be considered a flaw.

The null-line denoting the end of the headers allows for \r in the line. Specifically we test for ^\r?$. This works well on unix systems reading data that may have either \n new lines or \CR\LF (which is the standard for "raw" mail data) but may or may not be appropriate for other systems. Therefore this may or may not be a bug for anyone.

Others - probably?


=cut


AUTHOR

Malcolm Dew-Jones <yf110@victoria.tc.ca>