diff options
-rw-r--r-- | README | 55 | ||||
-rw-r--r-- | lib/Apache/Inject.pm | 16 | ||||
-rw-r--r-- | lib/Apache/Inject/Filter.pm | 32 |
3 files changed, 69 insertions, 34 deletions
@@ -116,31 +116,36 @@ OPERATION and forwards their combined contents. CAVEATS - Apache::Inject::Filter uses a regular expression to determine the proper - location of the injected header. It supports all valid HTML. However, it - does not parse embedded CSS and JavaScript, which means that it is - *possible* to construct an example where it will fail: - - <script> - /* this looks like the closing tag for script: </script> */ - /* this looks like an opening tag for a new element: <title> */ - </script> - <body> - This is where the header <i>should</i> be inserted. - <script> - /* this looks like the closing tag for the title: </title> - This is where the header is <i>actually</i> inserted. - */ - </script> - </body> - - This specific type of document, however, is *incredibly* unlikely. In - this case, an ad-hoc solution is simpler, more efficient and more - maintainable than a general one. - - On FreeBSD, you may need to enable the accf_http kernel module in order - for the tests to work. Note that Apache::Inject works fine without the - module; it is only the tests that require it. + * Apache::Inject::Filter uses a regular expression to determine the + proper location of the injected header. It supports all valid HTML. + However, it does not parse embedded CSS and JavaScript, which means + that it is *possible* to construct an example where it will fail: + + <script> + /* this looks like the closing tag for script: </script> */ + /* this looks like an opening tag for a new element: <title> */ + </script> + <body> + This is where the header <i>should</i> be inserted. + <script> + /* this looks like the closing tag for the title: </title> + This is where the header is <i>actually</i> inserted. + */ + </script> + </body> + + This specific type of document, however, is *incredibly* unlikely. + In this case, an ad-hoc solution is simpler, more efficient and more + maintainable than a general one. + + * Because of how Apache filters work, Inject may fail to find the end + of the <head> if the <head> is very long (in my experience over 7000 + characters). If this happens, it will decline the request, and the + contents will be served as though Inject had not been enabled. + + * On FreeBSD, you may need to enable the accf_http kernel module in + order for the tests to work. Note that Apache::Inject works fine + without the module; it is only the tests that require it. DIAGNOSTICS Apache::Inject and Apache::Inject::Filter log all errors and warnings to diff --git a/lib/Apache/Inject.pm b/lib/Apache/Inject.pm index 1d6f49b..68e003e 100644 --- a/lib/Apache/Inject.pm +++ b/lib/Apache/Inject.pm @@ -182,6 +182,10 @@ intelligently and forwards their combined contents. =head1 CAVEATS +=over + +=item * + Apache::Inject::Filter uses a regular expression to determine the proper location of the injected header. It supports all valid HTML. However, it does not parse embedded CSS and JavaScript, which means @@ -204,10 +208,22 @@ This specific type of document, however, is I<incredibly> unlikely. In this case, an ad-hoc solution is simpler, more efficient and more maintainable than a general one. +=item * + +Because of how Apache filters work, Inject may fail to find the end +of the E<lt>headE<gt> if the E<lt>headE<gt> is very long (in my +experience over 7000 characters). If this happens, it will decline +the request, and the contents will be served as though Inject had +not been enabled. + +=item * + On FreeBSD, you may need to enable the accf_http kernel module in order for the tests to work. Note that Apache::Inject works fine without the module; it is only the tests that require it. +=back + =head1 DIAGNOSTICS Apache::Inject and Apache::Inject::Filter log all errors and diff --git a/lib/Apache/Inject/Filter.pm b/lib/Apache/Inject/Filter.pm index f87cdc1..67511e2 100644 --- a/lib/Apache/Inject/Filter.pm +++ b/lib/Apache/Inject/Filter.pm @@ -49,15 +49,29 @@ sub handler : FilterRequestHandler { return DECLINED; } - my ($buf, $content); - $content .= $buf while $f->read($buf); - return DECLINED if not $content =~ /$doc/; - - $f->print($+{head}) if $+{head}; - inject($f, "InjectHead"); - $f->print($+{body}) if $+{body}; - inject($f, "InjectFoot"); - $f->print($+{rest}) if $+{rest}; + # First pass + if (not $f->ctx) { + my ($buf, $content); + $content .= $buf while $f->read($buf); + if (not $content =~ /$doc/) { + $f->r->warn('Inject: Cannot find <body> (<head> too long?)'); + return DECLINED; + } + + $f->print($+{head}) if $+{head}; + inject($f, "InjectHead"); + $f->print($+{body}) if $+{body}; + inject($f, "InjectFoot"); + $f->print($+{rest}) if $+{rest}; + + $f->ctx(1); + } + + # Any subsequent pass + else { + my $buf; + $f->print($buf) while $f->read($buf); + } return OK; } |