~ubuntu-branches/ubuntu/natty/otrs2/natty-updates

« back to all changes in this revision

Viewing changes to Kernel/cpan-lib/Mail/Address.pm

  • Committer: Package Import Robot
  • Author(s): Torsten Werner
  • Date: 2007-04-14 17:58:55 UTC
  • mto: (20.1.1 squeeze)
  • mto: This revision was merged to the branch mainline in revision 6.
  • Revision ID: package-import@ubuntu.com-20070414175855-9ne0w01yu1q44ch0
Tags: upstream-2.1.7
ImportĀ upstreamĀ versionĀ 2.1.7

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
# Mail::Address.pm
2
2
#
3
3
# Copyright (c) 1995-2001 Graham Barr <gbarr@pobox.com>.  All rights reserved.
4
 
# Copyright (c) 2002-2003 Mark Overmeer <mailtools@overmeer.net>
 
4
# Copyright (c) 2002-2005 Mark Overmeer <mailtools@overmeer.net>
5
5
# This program is free software; you can redistribute it and/or
6
6
# modify it under the same terms as Perl itself.
7
7
 
10
10
 
11
11
use Carp;
12
12
use vars qw($VERSION);
13
 
use locale;
 
13
# use locale;   removed in version 1.74, because it causes taint problems
14
14
 
15
 
$VERSION = "1.60";
 
15
$VERSION = "1.74";
16
16
sub Version { $VERSION }
17
17
 
18
18
#
25
25
    my $self = @_ && ref $_[0] ? shift : undef;
26
26
 
27
27
    local $_ = shift or return '';
28
 
    
 
28
 
 
29
    # Using encodings, too hard. See Mail::Message::Field::Full.
 
30
    return '' if m/\=\?.*?\?\=/;
 
31
 
29
32
    # Bug in unicode \U, perl 5.8.0 breaks when casing utf8 in regex
30
33
    if($] eq 5.008)
31
34
    {   require utf8;
41
44
    return "" if /^[\d ]+$/;
42
45
 
43
46
    # remove outermost parenthesis
44
 
    s/^\((.*)\)$/$1/g;
 
47
    s/^\((.*)\)$/$1/;
45
48
 
46
49
    # remove outer quotation marks
47
 
    s/^"|"$//g;
48
 
 
49
 
    # remove embedded comments
50
 
    s/\(.*\)//g;
 
50
    s/^"(.*)"$/$1/;
 
51
 
 
52
    # remove minimal embedded comments
 
53
    s/\(.*?\)//g;
 
54
 
 
55
    # remove all escapes
 
56
    s/\\//g;
 
57
 
 
58
    # remove internal quotation marks
 
59
    s/^"(.*)"$/$1/;
51
60
 
52
61
    # reverse "Last, First M." if applicable
53
62
    s/^([^\s]+) ?, ?(.*)$/$2 $1/;
67
76
        s/\bo'(\w)/O'\u$1/igo;
68
77
 
69
78
        # Roman numerals, eg 'Level III Support'
70
 
        s/\b(x*(ix)?v*(iv)?i*)\b/\U$1/igo; 
 
79
        s/\b(x*(ix)?v*(iv)?i*)\b/\U$1/igo;
71
80
    }
72
81
 
73
82
    # some cleanup
81
90
sub _tokenise {
82
91
 local($_) = join(',', @_);
83
92
 my(@words,$snippet,$field);
84
 
 
 
93
 
85
94
 s/\A\s+//;
86
95
 s/[\r\n]+/ /g;
87
96
 
 
97
#use Scalar::Util qw/tainted/;
 
98
#warn tainted($_);
88
99
 while ($_ ne '')
89
100
  {
90
101
   $field = '';
113
124
     next;
114
125
    }
115
126
 
116
 
      s/^("([^"\\]|\\.)*")\s*//       # "..."
117
 
   || s/^(\[([^\]\\]|\\.)*\])\s*//    # [...]
118
 
   || s/^([^\s\Q()<>\@,;:\\".[]\E]+)\s*//
119
 
   || s/^([\Q()<>\@,;:\\".[]\E])\s*//
120
 
     and do { push(@words, $1); next; };
 
127
    if( s/^("(?:[^"\\]+|\\.)*")\s*//       # "..."
 
128
     || s/^(\[(?:[^\]\\]+|\\.)*\])\s*//    # [...]
 
129
     || s/^([^\s()<>\@,;:\\".[\]]+)\s*//
 
130
     || s/^([()<>\@,;:\\".[\]])\s*//
 
131
    )
 
132
    {   push(@words, $1);
 
133
        next;
 
134
    }
121
135
 
122
 
   croak "Unrecognised line: $_";
 
136
    croak "Unrecognised line: $_";
123
137
  }
124
138
 
125
 
 push(@words, ",");
 
139
  push(@words, ",");
126
140
 
127
 
 \@words;
 
141
  \@words;
128
142
}
129
143
 
130
144
sub _find_next {
133
147
 my $len = shift;
134
148
 while($idx < $len) {
135
149
   my $c = $tokens->[$idx];
136
 
   return $c if($c eq "," || $c eq "<");
 
150
   return $c if $c eq ',' || $c eq ';' || $c eq '<';
137
151
   $idx++;
138
152
 }
139
153
 return "";
147
161
 my $o = undef;
148
162
 
149
163
 if(@{$phrase} || @{$comment} || @{$address}) {
150
 
  $o = $pkg->new(join(" ",@{$phrase}), 
 
164
  $o = $pkg->new(join(" ",@{$phrase}),
151
165
                 join("", @{$address}),
152
166
                 join(" ",@{$comment}));
153
167
  @{$phrase} = ();
195
209
  elsif($_ eq '>') {
196
210
   $depth-- if $depth;
197
211
  }
198
 
  elsif($_ eq ',') {
 
212
  elsif($_ eq ',' || $_ eq ';') {
199
213
   warn "Unmatched '<>' in $line" if($depth);
200
214
   my $o = _complete($pkg,\@phrase, \@address, \@comment);
201
215
   push(@objs, $o) if(defined $o);
239
253
 
240
254
 
241
255
sub format {
242
 
 my @fmts = ();
 
256
 my @fmts  = ();
243
257
 my $me;
244
258
 
 
259
 my $atext = '[\-\w !#$%&\'*+/=?^`{|}~]';
 
260
 
245
261
 foreach $me (@_) {
246
262
   my($phrase,$addr,$comment) = @{$me};
247
263
   my @tmp = ();
248
264
 
249
265
   if(defined $phrase && length($phrase)) {
250
 
    push(@tmp, $phrase);
251
 
    push(@tmp, "<" . $addr . ">") if(defined $addr && length($addr));
 
266
     push @tmp, $phrase =~ /^(?:\s*$atext\s*)+$/ ? $phrase
 
267
              : $phrase =~ /(?<!\\)"/            ? $phrase
 
268
              :                                    qq("$phrase");
 
269
 
 
270
     push(@tmp, "<" . $addr . ">") if(defined $addr && length($addr));
252
271
   }
253
272
   else {
254
273
    push(@tmp, $addr) if(defined $addr && length($addr));
265
284
}
266
285
 
267
286
 
268
 
sub name 
 
287
sub name
269
288
{
270
289
    my $me = shift;
271
290
    my $phrase = $me->phrase;
272
291
    my $addr = $me->address;
273
 
    
 
292
 
274
293
    $phrase  = $me->comment unless(defined($phrase) && length($phrase));
275
294
    my $name = $me->_extract_name($phrase);
276
 
    
 
295
 
277
296
    # first.last@domain address
278
297
    if($name eq '' && $addr =~ /([^\%\.\@_]+([\._][^\%\.\@_]+)+)[\@\%]/o)
279
298
    {
280
299
        ($name = $1) =~ s/[\._]+/ /go;
281
300
        $name = _extract_name($name);
282
301
    }
283
 
    
284
 
    if($name eq '' && $addr =~ m#/g=#oi)        
 
302
 
 
303
    if($name eq '' && $addr =~ m#/g=#oi)
285
304
    # X400 style address
286
305
    {
287
306
        my ($f) = $addr =~ m#g=([^/]*)#oi;
288
307
        my ($l) = $addr =~ m#s=([^/]*)#io;
289
 
        
 
308
 
290
309
        $name = _extract_name($f . " " . $l);
291
 
    }   
292
 
       
 
310
    }
 
311
 
293
312
       return length($name) ? $name : undef;
294
313
}
295
314
 
296
315
 
297
316
sub host {
298
317
 my $me = shift;
299
 
 my $addr = $me->address;
 
318
 my $addr = $me->address || '';
300
319
 my $i = rindex($addr,'@');
301
320
 
302
321
 my $host = ($i >= 0) ? substr($addr,$i+1) : undef;
338
357
=head1 SYNOPSIS
339
358
 
340
359
    use Mail::Address;
341
 
    
 
360
 
342
361
    my @addrs = Mail::Address->parse($line);
343
 
    
 
362
 
344
363
    foreach $addr (@addrs) {
345
364
        print $addr->format,"\n";
346
365
    }
347
366
 
348
367
=head1 DESCRIPTION
349
368
 
350
 
C<Mail::Address> extracts and manipulates RFC822 compilant email
351
 
addresses. As well as being able to create C<Mail::Address> objects
352
 
in the normal manner, C<Mail::Address> can extract addresses from
353
 
the To and Cc lines found in an email message.
 
369
C<Mail::Address> extracts and manipulates email addresses from a message
 
370
header.  It cannot be used to extract addresses from some random text.
 
371
You can use this module to create RFC822 compliant fields.
 
372
 
 
373
Although C<Mail::Address> is a very popular subject for books, and is
 
374
used in many applications, it does a very poor job on the more complex
 
375
message fields.  It does only handle simple address formats (which
 
376
covers about 95% of what can be found). Problems are with
 
377
 
 
378
=over 4
 
379
 
 
380
=item *
 
381
 
 
382
no support for address groups, even not with the semi-colon as
 
383
separator between addresses
 
384
 
 
385
=item *
 
386
 
 
387
Limitted support for escapes in phrases and comments.  There are
 
388
cases where it can get wrong.
 
389
 
 
390
=item *
 
391
 
 
392
You have to take care of most escaping when you create an address yourself:
 
393
C<Mail::Address> does not do that for you.
 
394
 
 
395
=back
 
396
 
 
397
Often requests are made to improve this situation, but this is not a
 
398
good idea, where it will break zillions of existing applications.  If
 
399
you wish for a fully RFC2822 compliant implementation you may take a look
 
400
at L<Mail::Message::Field::Full>, part of MailBox.
 
401
 
 
402
Example:
 
403
 
 
404
  my $s = Mail::Message::Field::Full->parse($header);
 
405
  # ref $s isa Mail::Message::Field::Addresses;
 
406
 
 
407
  my @g = $s->groups;          # all groups, at least one
 
408
  # ref $g[0] isa Mail::Message::Field::AddrGroup;
 
409
  my $ga = $g[0]->addresses;   # group addresses
 
410
 
 
411
  my @a = $s->addresses;       # all addresses
 
412
  # ref $a[0] isa Mail::Message::Field::Address;
354
413
 
355
414
=head1 CONSTRUCTORS
356
415
 
425
484
 
426
485
=head1 COPYRIGHT
427
486
 
428
 
Copyright (c) 2002-2003 Mark Overmeer, 1995-2001 Graham Barr. All rights
 
487
Copyright (c) 2002-2005 Mark Overmeer, 1995-2001 Graham Barr. All rights
429
488
reserved. This program is free software; you can redistribute it and/or
430
489
modify it under the same terms as Perl itself.
431
490