Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

180 lines
4.5 KiB

  1. package HTTP::Headers::Util;
  2. use strict;
  3. use vars qw($VERSION @ISA @EXPORT_OK);
  4. $VERSION = sprintf("%d.%02d", q$Revision: 1.9 $ =~ /(\d+)\.(\d+)/);
  5. require Exporter;
  6. @ISA=qw(Exporter);
  7. @EXPORT_OK=qw(split_header_words join_header_words);
  8. =head1 NAME
  9. HTTP::Headers::Util - Header value parsing utility functions
  10. =head1 SYNOPSIS
  11. use HTTP::Headers::Util qw(split_header_words);
  12. @values = split_header_words($h->header("Content-Type"));
  13. =head1 DESCRIPTION
  14. This module provides a few functions that helps parsing and
  15. construction of valid HTTP header values. None of the functions are
  16. exported by default.
  17. The following functions are available:
  18. =over 4
  19. =item split_header_words( @header_values )
  20. This function will parse the header values given as argument into a
  21. list of anonymous arrays containing key/value pairs. The function
  22. knows how to deal with ",", ";" and "=" as well as quoted values after
  23. "=". A list of space separated tokens are parsed as if they were
  24. separated by ";".
  25. If the @header_values passed as argument contains multiple values,
  26. then they are treated as if they were a single value separated by
  27. comma ",".
  28. This means that this function is useful for parsing header fields that
  29. follow this syntax (BNF as from the HTTP/1.1 specification, but we relax
  30. the requirement for tokens).
  31. headers = #header
  32. header = (token | parameter) *( [";"] (token | parameter))
  33. token = 1*<any CHAR except CTLs or separators>
  34. separators = "(" | ")" | "<" | ">" | "@"
  35. | "," | ";" | ":" | "\" | <">
  36. | "/" | "[" | "]" | "?" | "="
  37. | "{" | "}" | SP | HT
  38. quoted-string = ( <"> *(qdtext | quoted-pair ) <"> )
  39. qdtext = <any TEXT except <">>
  40. quoted-pair = "\" CHAR
  41. parameter = attribute "=" value
  42. attribute = token
  43. value = token | quoted-string
  44. Each I<header> is represented by an anonymous array of key/value
  45. pairs. The value for a simple token (not part of a parameter) is C<undef>.
  46. Syntactically incorrect headers will not necessary be parsed as you
  47. would want.
  48. This is easier to describe with some examples:
  49. split_header_words('foo="bar"; port="80,81"; discard, bar=baz')
  50. split_header_words('text/html; charset="iso-8859-1");
  51. split_header_words('Basic realm="\"foo\\bar\""');
  52. will return
  53. [foo=>'bar', port=>'80,81', discard=> undef], [bar=>'baz' ]
  54. ['text/html' => undef, charset => 'iso-8859-1']
  55. [Basic => undef, realm => '"foo\bar"']
  56. =cut
  57. sub split_header_words
  58. {
  59. my(@val) = @_;
  60. my @res;
  61. for (@val) {
  62. my @cur;
  63. while (length) {
  64. if (s/^\s*(=*[^\s=;,]+)//) { # 'token' or parameter 'attribute'
  65. push(@cur, $1);
  66. # a quoted value
  67. if (s/^\s*=\s*\"([^\"\\]*(?:\\.[^\"\\]*)*)\"//) {
  68. my $val = $1;
  69. $val =~ s/\\(.)/$1/g;
  70. push(@cur, $val);
  71. # some unquoted value
  72. } elsif (s/^\s*=\s*([^;,\s]*)//) {
  73. my $val = $1;
  74. $val =~ s/\s+$//;
  75. push(@cur, $val);
  76. # no value, a lone token
  77. } else {
  78. push(@cur, undef);
  79. }
  80. } elsif (s/^\s*,//) {
  81. push(@res, [@cur]) if @cur;
  82. @cur = ();
  83. } elsif (s/^\s*;// || s/^\s+//) {
  84. # continue
  85. } else {
  86. die "This should not happen: '$_'";
  87. }
  88. }
  89. push(@res, \@cur) if @cur;
  90. }
  91. @res;
  92. }
  93. =item join_header_words( @arrays )
  94. This will do the opposite of the conversion done by split_header_words().
  95. It takes a list of anonymous arrays as arguments (or a list of
  96. key/value pairs) and produces a single header value. Attribute values
  97. are quoted if needed.
  98. Example:
  99. join_header_words(["text/plain" => undef, charset => "iso-8859/1"]);
  100. join_header_words("text/plain" => undef, charset => "iso-8859/1");
  101. will both return the string:
  102. text/plain; charset="iso-8859/1"
  103. =cut
  104. sub join_header_words
  105. {
  106. @_ = ([@_]) if @_ && !ref($_[0]);
  107. my @res;
  108. for (@_) {
  109. my @cur = @$_;
  110. my @attr;
  111. while (@cur) {
  112. my $k = shift @cur;
  113. my $v = shift @cur;
  114. if (defined $v) {
  115. if ($v =~ /^\w+$/) {
  116. $k .= "=$v";
  117. } else {
  118. $v =~ s/([\"\\])/\\$1/g; # escape " and \
  119. $k .= qq(="$v");
  120. }
  121. }
  122. push(@attr, $k);
  123. }
  124. push(@res, join("; ", @attr)) if @attr;
  125. }
  126. join(", ", @res);
  127. }
  128. 1;
  129. __END__
  130. =back
  131. =head1 COPYRIGHT
  132. Copyright 1997-1998, Gisle Aas
  133. This library is free software; you can redistribute it and/or
  134. modify it under the same terms as Perl itself.
  135. =cut