home *** CD-ROM | disk | FTP | other *** search
/ PC Professionell 2004 December / PCpro_2004_12.ISO / files / webserver / tsw / TSW_3.4.0.exe / Apache2 / perl / Field.pm < prev    next >
Encoding:
Perl POD Document  |  2003-09-22  |  9.2 KB  |  512 lines

  1. # Mail::Field.pm
  2. #
  3. # Copyright (c) 1995-2001 Graham Barr. All rights reserved.
  4. # Copyright (c) 2002-2003 Mark Overmeer <mailtools@overmeer.net>
  5. # This program is free software; you can redistribute it and/or
  6. # modify it under the same terms as Perl itself.
  7.  
  8. package Mail::Field;
  9.  
  10. # $Id: //depot/MailTools/Mail/Field.pm#7 $
  11.  
  12. use Carp;
  13. use strict;
  14. use vars qw($AUTOLOAD $VERSION);
  15.  
  16. $VERSION = "1.60";
  17.  
  18. unless(defined &UNIVERSAL::can) {
  19.     *UNIVERSAL::can = sub {
  20.     my($obj,$meth) = @_;
  21.     my $pkg = ref($obj) || $obj;
  22.     my @pkg = ($pkg);
  23.     my %done;
  24.     while(@pkg) {
  25.             $pkg = shift @pkg;
  26.             next if exists $done{$pkg};
  27.             $done{$pkg} = 1;
  28.  
  29.         no strict 'refs';
  30.  
  31.             unshift @pkg,@{$pkg . "::ISA"}
  32.             if(@{$pkg . "::ISA"});
  33.             return \&{$pkg . "::" . $meth}
  34.             if defined(&{$pkg . "::" . $meth});
  35.     }
  36.     undef;
  37.     }
  38. }
  39.  
  40. sub _header_pkg_name
  41. {
  42.  my($header) = lc shift;
  43.  
  44.  $header =~ s/((\b|_)\w)/\U$1/gio;
  45.  
  46.  if (length($header) > 8)
  47.   {
  48.    my @header = split /[-_]+/, $header;
  49.    my $chars = int((7 + @header) / @header) || 1;
  50.    $header = substr(join('', map { substr($_,0,$chars) } @header),0,8);
  51.   }
  52.  else
  53.   {
  54.    $header =~ s/[-_]+//go;
  55.   }
  56.  
  57.  'Mail::Field::' . $header;
  58. }
  59.  
  60. ##
  61. ## Use the import method to load the sub-classes
  62. ##
  63.  
  64. sub _require_dir
  65. {
  66.  my($pkg,$dir,$dir_sep) = @_;
  67.  
  68.  if(opendir(DIR,$dir))
  69.   {
  70.    my @inc =  ();
  71.    my $f;
  72.  
  73.    foreach $f (readdir(DIR))
  74.     {
  75.      next
  76.     unless $f =~ /^([\w\-]+)/;
  77.  
  78.      my $p = $1;
  79.      my $n = $dir . $dir_sep . $p;
  80.  
  81.      if(-d $n )
  82.       {
  83.        _require_dir( $pkg . "::" . $f, $n, $dir_sep);
  84.       }
  85.      else
  86.       {
  87.        $p =~ s/-/_/go;
  88.        eval "require ${pkg}::$p"
  89.       }
  90.     }
  91.    closedir(DIR);
  92.   }
  93. }
  94.  
  95. sub import
  96. {
  97.  my $pkg = shift;
  98.  
  99.  if(@_)
  100.   {
  101.    local $_;
  102.    map { 
  103.         eval "require " . _header_pkg_name($_) || die $@;
  104.        } @_;
  105.   }
  106.  else
  107.   {
  108.    my($f,$dir,$dir_sep);
  109.    foreach $f (keys %INC)
  110.     {
  111.      if($f =~ /^Mail(\W)Field\W/i)
  112.       {
  113.        $dir_sep = $1;
  114.        $dir = ($INC{$f} =~ /(.*Mail\W+Field)/i)[0] . $dir_sep;
  115.        last;
  116.       }
  117.     }
  118.    _require_dir('Mail::Field', $dir, $dir_sep);
  119.   }
  120. }
  121.  
  122.  
  123. ##
  124. ## register a header class, this creates a new method in Mail::Field
  125. ## which will call new on that class
  126. ##
  127.  
  128. sub register
  129. {
  130.  my $self = shift;
  131.  my $method = lc shift;
  132.  my $pkg = shift || ref($self) || $self;
  133.  
  134.  $method =~ tr/-/_/;
  135.  
  136.  $pkg = _header_pkg_name($method)
  137.     if($pkg eq "Mail::Field");
  138.  
  139.  croak "Re-register of $method"
  140.     if Mail::Field->can($method);
  141.  
  142.  no strict 'refs';
  143.  *{$method} = sub {
  144.     shift;
  145.     unless ($pkg->can('stringify')) {
  146.         eval "require $pkg" || die $@;
  147.     }
  148.     $pkg->_build(@_);
  149.  };
  150.  
  151. }
  152.  
  153. ##
  154. ## the *real* constructor
  155. ## if called with one argument then the `parse' method will be called
  156. ## otherwise the `create' method is called
  157. ##
  158.  
  159. sub _build
  160. {
  161.  my $type = shift;
  162.  my $self = bless {}, $type;
  163.  
  164.  @_ == 1 ? $self->parse(@_)
  165.      : $self->create(@_);
  166. }
  167.  
  168. sub new
  169. {
  170.  my $self  = shift; # ignored
  171.  my $field = lc shift;
  172.  
  173.  $field =~ tr/-/_/;
  174.  
  175.  $self->$field(@_);
  176. }
  177.  
  178. ##
  179. ## A default create method. This allows us to do
  180. ## $s = Mail::Field->new('Subject', Text => "joe");
  181. ## $s = Mail::Field->new('Subject', "joe");
  182. ##
  183.  
  184. sub create
  185. {
  186.  my $self = shift;
  187.  my %arg = @_;
  188.  
  189.  $self = bless {}, $self
  190.     unless ref($self);
  191.  
  192.  %$self = ();
  193.  
  194.  $self->set(\%arg);
  195. }
  196.  
  197. ##
  198. ## A default create method. This allows us to do
  199. ## $s = Mail::Field->new('Subject');
  200. ##
  201.  
  202. sub parse
  203. {
  204.  my $self = shift;
  205.  my $type = ref($self) || $self;
  206.  
  207.  croak "$type: Cannot parse";
  208. }
  209.  
  210. ##
  211. ## either get the text, or parse a new one
  212. ##
  213.  
  214. sub text
  215. {
  216.  my $self = shift;
  217.  @_ ? $self->parse(@_)
  218.     : $self->stringify;
  219. }
  220.  
  221. ##
  222. ## Return the tag (in the correct case) for this item
  223. ##
  224.  
  225. sub tag
  226. {
  227.  my $self = shift;
  228.  my $tag = ref($self) || $self;
  229.  
  230.  $tag =~ s/.*:://o;
  231.  $tag =~ s/_/-/og;
  232.  
  233.  join('-',
  234.     map { /^[b-df-hj-np-tv-z]+$|^MIME$/i ? uc($_) : ucfirst(lc($_)) }
  235.        split('-', $tag)
  236.      );
  237. }
  238.  
  239. ##
  240. ## a constructor
  241. ## create a new object by extracting from a Mail::Header object
  242. ##
  243.  
  244. sub extract
  245. {
  246.  my $self = shift;
  247.  
  248.  my $tag  = shift;
  249.  my $head = shift;
  250.  
  251.  my $method = lc $tag;
  252.  $method =~ tr/-/_/;
  253.  
  254.  my $text;
  255.  
  256.  if(@_ == 0 && wantarray)
  257.   {
  258.    my @ret = ();
  259.  
  260.    foreach $text ($head->get($tag))
  261.     {
  262.      chomp($text);
  263.  
  264.      push(@ret, $self->$method($text));
  265.     }
  266.  
  267.    return @ret;
  268.   }
  269.  
  270.  my $idx  = shift || 0;
  271.  
  272.  $text = $head->get($tag,$idx) or
  273.     return undef;
  274.  
  275.  chomp($text);
  276.  
  277.  $self->$method($text);
  278. }
  279.  
  280. ##
  281. ## Autoload sub-classes, or, if the .pm file cannot be found, create a dummy
  282. ## sub-class based on Mail::Field::Generic
  283. ##
  284.  
  285. sub AUTOLOAD
  286. {
  287.  my $method = $AUTOLOAD;
  288.  
  289.  $method =~ s/.*:://o;
  290.  
  291.  croak "Undefined subroutine &$AUTOLOAD called"
  292.     unless $method =~ /^[^A-Z\x00-\x1f\x80-\xff :]+$/o;
  293.  
  294.  my $pkg = _header_pkg_name($method);
  295.  
  296.  unless(eval "require " . $pkg)
  297.   {
  298.    my $tag = $method;
  299.  
  300.    $tag =~ s/_/-/og;
  301.    $tag = join('-',
  302.              map { /^[b-df-hj-np-tv-z]+$|^MIME$/i ? uc($_) : ucfirst(lc($_)) }
  303.                 split('-', $tag));
  304.  
  305.    no strict;
  306.    @{$pkg . "::ISA"} = qw(Mail::Field::Generic);
  307.    *{$pkg . "::tag"} = sub { $tag };
  308.   }
  309.  
  310.   $pkg->register($method)
  311.     unless(Mail::Field->can($method));
  312.  
  313.  goto &$AUTOLOAD;
  314. }
  315.  
  316. ##
  317. ## prevent the calling of AUTOLOAD for DESTROY :-)
  318. ##
  319.  
  320. sub DESTROY {}
  321.  
  322. ##
  323. ## A generic package for those not defined in thier own package. This is
  324. ## fine for fields like Subject, X-Mailer etc. where the field holds only
  325. ## a string of no particular importance/format.
  326. ##
  327.  
  328. package Mail::Field::Generic;
  329.  
  330. use Carp;
  331. use vars qw(@ISA);
  332.  
  333. @ISA = qw(Mail::Field);
  334.  
  335. sub create
  336. {
  337.  my $self = shift;
  338.  my %arg = @_;
  339.  my $text = delete $arg{Text} || "";
  340.  
  341.  croak "Unknown options " . join(",", keys %arg)
  342.     if %arg;
  343.  
  344.  $self->{Text} = $text;
  345.  
  346.  $self;
  347. }
  348.  
  349. sub parse
  350. {
  351.  my $self = shift;
  352.  
  353.  $self->{Text} = shift || "";
  354.  $self;
  355. }
  356.  
  357. sub stringify
  358. {
  359.  my $self = shift;
  360.  $self->{Text};
  361. }
  362.  
  363. 1;
  364.  
  365. __END__
  366.  
  367. =head1 NAME
  368.  
  369. Mail::Field - Base class for manipulation of mail header fields
  370.  
  371. =head1 SYNOPSIS
  372.  
  373.     use Mail::Field;
  374.     
  375.     $field = Mail::Field->new('Subject', 'some subject text');
  376.     print $field->tag,": ",$field->stringify,"\n";
  377.  
  378.     $field = Mail::Field->subject('some subject text');
  379.  
  380. =head1 DESCRIPTION
  381.  
  382. C<Mail::Field> is a base class for packages that create and manipulate
  383. fields from Email (and MIME) headers. Each different field will have its
  384. own sub-class, defining its own interface.
  385.  
  386. This document describes the minimum interface that each sub-class should
  387. provide, and also guidlines on how the field specific interface should be
  388. defined. 
  389.  
  390. =head1 CONSTRUCTOR
  391.  
  392. Mail::Field, and it's sub-classes define several methods which return
  393. new objects. These can all be termed to be constructors.
  394.  
  395. =over 4
  396.  
  397. =item new ( TAG [, STRING | OPTIONS ] )
  398.  
  399. The new constructor will create an object in the class which defines
  400. the field specified by the tag argument.
  401.  
  402. After creation of the object :-
  403.  
  404. If the tag argument is followed by a single string then the C<parse> method
  405. will be called with this string.
  406.  
  407. If the tag argument is followed by more than one arguments then the C<create>
  408. method will be called with these arguments.
  409.  
  410. =item extract ( TAG, HEAD [, INDEX ] )
  411.  
  412. This constuctor takes as arguments the tag name, a C<Mail::Head> object
  413. and optionally an index.
  414.  
  415. If the index argument is given then C<extract> will retrieve the given tag
  416. from the C<Mail::Head> object and create a new C<Mail::Field> based object.
  417. I<undef> will be returned in the field does not exist.
  418.  
  419. If the index argument is not given the the result depends on the context
  420. in which C<extract> is called. If called in a scalar context the result
  421. will be as if C<extract> was called with an index value of zero. If called
  422. in an array context then all tags will be retrieved and a list of
  423. C<Mail::Field> objects will be returned.
  424.  
  425. =item combine ( FIELD_LIST )
  426.  
  427. This constructor takes as arguments a list of C<Mail::Field> objects, which
  428. should all be of the same sub-class, and creates a new object in that same
  429. class.
  430.  
  431. This constructor is nor defined in C<Mail::Field> as there is no generic
  432. way to combine the various field types. Each sub-class should define
  433. its own combine constructor, if combining is possible/allowed.
  434.  
  435. =back
  436.  
  437. =head1 METHODS
  438.  
  439. =over 4
  440.  
  441. =item parse
  442.  
  443. =item set
  444.  
  445. =item tag
  446.  
  447. =item stringify
  448.  
  449. =back
  450.  
  451. =head1 SUB-CLASS PACKAGE NAMES
  452.  
  453. All sub-classes should be called Mail::Field::I<name> where I<name> is
  454. derived from the tag using these rules.
  455.  
  456. =over 4
  457.  
  458. =item *
  459.  
  460. Consider a tag as being made up of elements separated by '-'
  461.  
  462. =item *
  463.  
  464. Convert all characters to lowercase except the first in each element, which
  465. should be uppercase.
  466.  
  467. =item *
  468.  
  469. I<name> is then created from these elements by using the first
  470. N characters from each element.
  471.  
  472. =item *
  473.  
  474. N is calculated by using the formula :-
  475.  
  476.     int((7 + #elements) / #elements)
  477.  
  478. =item *
  479.  
  480. I<name> is then limited to a maximum of 8 characters, keeping the first 8
  481. characters
  482.  
  483. =back
  484.  
  485. For an example of this take a look at the definition of the 
  486. C<_header_pkg_name> subroutine in C<Mail::Field>
  487.  
  488. =head1 AUTHOR
  489.  
  490. Graham Barr.
  491.  
  492. Maintained by Mark Overmeer <mailtools@overmeer.net>
  493.  
  494. =head1 SEE ALSO
  495.  
  496. L<MIME::*>s
  497.  
  498. =head1 CREDITS
  499.  
  500. Eryq <eryq@rhine.gsfc.nasa.gov> - for all the help in defining this package
  501. so that C<Mail::*> and C<MIME::*> can be integrated together.
  502.  
  503. =head1 COPYRIGHT
  504.  
  505. Copyright (c) 2002-2003 Mark Overmeer, 1995-2001 Graham Barr. All rights
  506. reserved. This program is free software; you can redistribute it and/or
  507. modify it under the same terms as Perl itself.
  508.  
  509. =cut
  510.  
  511.  
  512.