package HTTP::Headers::Util; use strict; use vars qw($VERSION @ISA @EXPORT_OK); $VERSION = sprintf("%d.%02d", q$Revision: 1.2 $ =~ /(\d+)\.(\d+)/); require Exporter; @ISA=qw(Exporter); @EXPORT_OK=qw(split_header_words join_header_words); =head1 NAME HTTP::Headers::Util - Header value parsing utility functions =head1 SYNOPSIS use HTTP::Headers::Util qw(split_header_words); @values = split_header_words($h->header("Content-Type")); =head1 DESCRIPTION This module provide a few functions that helps parsing and construction of valid header values. None of the functions are exported by default. The following functions are provided: =over 4 =item split_header_words( @header_values ) This function will split the header values given as argument into a list of anonymous arrays containing key/value pairs. The function know how to deal with ",", ";" and "=" as well as quoted values. Multiple values are treated as if they were separated by comma. This is easier to describe with an example: split_header_words('foo="bar"; port="80,81"; discard, bar=baz') split_header_words('text/html; charset="iso-8859-1"); will return [foo=>'bar', port=>'80,81', discard=> undef], [bar=>'baz' ] ['text/html' => undef, charset => 'iso-8859-1'] =cut sub split_header_words { my(@val) = @_; my @res; for (@val) { my @cur; while (length) { if (s/^\s*(=*[^\s=;,]+)//) { push(@cur, $1); if (s/^\s*=\s*\"([^\"\\]*(?:\\.[^\"\\]*)*)\"//) { my $val = $1; $val =~ s/\\(.)/$1/g; push(@cur, $val); } elsif (s/^\s*=\s*([^;,]+)//) { my $val = $1; $val =~ s/\s+$//; push(@cur, $val); } else { push(@cur, undef); } } elsif (s/^\s*,//) { push(@res, [@cur]); @cur = (); } elsif (s/^\s*;?//) { # continue } else { warn "This should not happen: $_\n"; } } push(@res, \@cur) if @cur; } @res; } =item join_header_words( @arrays ) This will do the opposite convertion of what split_header_words() does. It takes a list of anonymous arrays as argument and produce a single header value. Attribute values are quoted if needed. Example: join_header_words(["text/plain" => undef, charset => "iso-8859/1"]); =cut sub join_header_words { my @res; for (@_) { my @cur = @$_; my @attr; while (@cur) { my $k = shift @cur; my $v = shift @cur; if (defined $v) { if ($v =~ /^\w+$/) { $k .= "=$v"; } else { $v =~ s/([\"\\])/\\$1/g; # escape " and \ $k .= qq(="$v"); } } push(@attr, $k); } push(@res, join("; ", @attr)) if @attr; } join(", ", @res); } 1; __END__ =back =head1 COPYRIGHT Copyright 1997, Gisle Aas This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut