Errata

Writing Apache Modules with Perl and C

Errata for Writing Apache Modules with Perl and C

Submit your own errata for this product.

The errata list is a list of errors and their corrections that were found after the product was released.

The following errata were submitted by our customers and have not yet been approved or disproved by the author or editor. They solely represent the opinion of the customer.

Color Key: Serious technical mistake Minor technical mistake Language or formatting error Typo Question Note Update

Version Location Description Submitted by Date submitted
Printed Page 23
5th paragraph

This is a serious error (I think!). For poeple wanting to install Apache
with mod_perl into a specified final destination, you use the APACHE_PREFIX
option. This forces the final 'make install' command to automatically copy
the final httpd executeable (with embedded perl interpreter) and it's support
files to the specified destination.

The only problem is that this switch only works correctly if specified with
the USE_APACI=1 option enabled. This option is omitted from page 23,24,25
but Appendix B page 645 states (correctly) that you need the USE_APACI option
for APACHE_PREFIX to work.

Anonymous   
Printed Page 26
Win32Installation

I assume this book is a little old now, but I just purchased it. Anyway, on
CPAN under author Jeffrey_Baker there is no Win32 distribution file for
mod_perl? I searched hi and low, and it does not exist. I cannot load the
mod_perl from page 26 and 27 on my NT box. There must be a update to this,
or something.

Anonymous   
Printed Page 29
4th full paragraph

"We'll need to tell Apache to load and run the startup file at launch time.
Open perl.conf (actually, any of the configuration files will do) ...."

should read (I think)

"We'll need to tell Apache to load and run the startup file at launch time.
Open httpd.conf(actually, any of the configuration files will do) ...."

Anonymous   
Printed Page 36
Apache configuration settings following second paragraph

My system is Debian 3.0r1:

<CVSENV>root@d3020g:~/d3020g/etc/apache# apache -v
Server version: Apache/1.3.26 (Unix) Debian GNU/Linux
Server built: Oct 26 2002 09:15:15

The SetHandler directive given in the Eagle book, p. 36:

SetHandler hello-handler

Generates a error message in the Apache error.log:

[Tue Feb 24 22:26:18 2004] [error] [client 192.168.1.2] File does not exist:
<path_to_Location>

Per the comments given in mod_hello.c generated by:

apxs -n hello -g

The SetHandler directive needs to be:

SetHandler hello

Anonymous   
Printed Page 80
line 9

"Malcom" should read "Malcolm".

Anonymous   
Printed Page 90
1st code example

It says "-e $r->finfo" when it should say "-e $file".

And, a few lines later it says "unless (-r _)" when it should say "unless -r $file".

Anonymous   
Printed Page 107
line -12

ucfirst(...) should probably ucfirst(lc(...)) if you're really "tidying them
up" and "canonicalizing" them as the text claims.

Anonymous   
Printed Page 108
line 26


"rarely seen >&= notation"

Really, the "&=" is the rarely seen part, ">" is just an ordinary
open-for-output marker.

Anonymous   
Printed Page 115
code following 4th paragraph

The line

} continue {

has no effect and should be deleted.

Anonymous   
Printed Page 121
In the code snippet, the second line


$r-.set_last_modified;

should read

$r->set_last_modified;

The third line,

my $rc = $r-> meets_conditions

should read

my $rc = $r->meets_conditions;

Anonymous   
Printed Page 123
line 19

"unless" should read "if".

Anonymous   
Printed Page 123
In Example 4-7


return OK unless $r->header_only;

should read

return OK if $r->header_only;

This is similar to the change you made for the 6/99 printing on page 146.

Anonymous   
Printed Page 144
line 2

The Apache ALIAS directive has two arguments, which should agree on the
last char being a slash or not. The last word of the first sentence should
say "/perl/" instead of "/perl". The actual directive in the preceding
paragraph is correct.

Anonymous   
Printed Page 150 & 156
the code

Where the script parses param('action') in the CASE: statement, the line that reads:

/^view/i and do { view_guestbook(1); last CASE; };

the parameter of '1' causes an error under the 'use strict' pragma:

[error] Can't use string ("1") as a symbol ref while "strict refs" in use
at /path/to/guestbook_lean.pl line 109.

Anonymous   
Printed Page 152
locking not really needed if you use atomicity of append

Anonymous   
Printed Page 214
MAC by concatenating and crypto-hashing:

OK for what you're doing there, but change it only slightly (as readers are
likely to do) and there's a security hole like one that affected PGP. If you
keep "bit boundaries" outside the hash then you can change the "protected"
information. Roughly, PGP concatenated the bits of n and e and "protected"
them. But the "number of bits in n" was kept outside. An attacker could
construct a key by moving the boundary (one bit less/more for n; one bit
more/less for e) and they'd hash the same. Security is always difficult to
explain but it might be worth at least telling readers to include "boundaries"
or "counts" before concatenation and hashing.

Anonymous   
Printed Page 219
CBC:

I haven't read through this in great detail but key reuse or IV (of the crypto
kind, not the perl kind :-) reuse can totally remove any crypto protection
when non-crypto kinds (like most readers) try to roll their own
chaining/streaming crypto.

Anonymous   
Printed Page 219
Footnote

France has now legalised crypto, if I recall.

Anonymous   
Printed Page 226
line 22

"peak" should read "peek".

Anonymous   
Printed Page 230
line 11

At least add PostgreSQL and Informix to the initial list :-)

Anonymous   
Printed Page 230
Footnote

MySQL licence change

Anonymous   
Printed Page 240
line 3

split(':', ...) should read split(/:/, ...) (and similarly anywhere else).

Anonymous   
Printed Page 246
Example 5-7

The use of split and join causes trailing slashes in URIs to be silently
dropped. This can cause extra internal redirects in the case where the URI
refers to a directory, with the dubious side-effect of causing the browser to
effectively lose the session information.

I have found that the equivalent of adding

$new_uri .= '/' if substr($r->uri, -1, 1) eq '/';

before the

$r->uri( $new_uri );

line solves this problem.

Anonymous   
Printed Page 280
last line

Delete "(hits)" and append it to the previous (comment) line.

Anonymous   
Printed Page 281
Line 4 is a duplicate comment.

Anonymous   
Printed Page 286
line -2

regexp should allow "-" in domain name (and arguably should disallow "_" in
domain name since w matches underscore but it's an illegal character in
domains which well-run places now enforce).

Anonymous   
Printed Page 291
Footnote

Actually, the salt is mainly to make it much less likely that two people who
pick the same password on a non-shadowed system will end up with the same
crypted password (and hence can use their own password to log into the other's
account).

Anonymous   
Printed Page 297
line -1

split(/s+/, ...) should read split(' ', ...). (Even if you are guaranteed
that there's no leading whitespace, the "turn leading whitespace into a null
first field" behaviour of /s+/ is more confusing then the simple split(' ',
...) which Does The Right Thing.

Anonymous   
Printed Page 331
2nd paragraph

In my module-writing adventures, I noticed (after a very long debugging session!)
that the child init handler is not called for each virtual server. Rather, it's
called only once, with the "main" server as the first argument. The same seems to
hold true for the child exit handler. This, at least for C modules -- mod_perl
modules may behave differently.

A clarification on this point would have saved me some hair, hopefully it can help
someone else. Of course, everyone's writing 2.0 modules these days...

Anonymous   
Printed Page 334
4th Paragraph Apache::DefaultTrans handler

The TransHandler is supposed to return BAD_REQUEST if the uri does not have a
'/' as the first character, or if there is a '*' anywhere in it.

The code given is:

if ($uri !~ m:^/: or index($uri, '*')) {

however, index returns -1 if there is no '*', not zero (0). Therefore
the code should be:

if ($uri !~ m:^/: or (index($uri, '*') >= 0)) {

Anonymous   
Printed Page 334
Translation Handler code sample

This line:

$r->log->error("Invalid URI in request ", $r->the_request);

should be

$r->log_error("Invalid URI in request ", $r->the_request);

(This is in the 03/1999 printing, I have not seen it listed in errata for
later versions either...)

Anonymous   
Printed Page 347
line -12

>&= should be just &= (see note for p108).

Anonymous   
Printed Page 347
line -7

Big nasty security hole if put together with an upload facility that allows
users to pick their own filename (such as the usual "; rm -rf /").

Anonymous   
Printed Page 468
The second example on p. 128 of the Eagle book sets the content type and

sends the HTTP headers itself before running a subrequest.

However, on p. 468, the documentation for the run() method says in part:

When you invoke the subrequest's response handler in
this way, it will do everything a response handler is
supposed to, including sending the HTTP headers and the
document body. ... If you are invoking the subrequest
uri() method from within your own content handler, you
must not set the HTTP headers and document body
yourself ...

These seem to contradict each other. From testing, however, it seems as though
the example on p. 128 is correct and the documentation on p. 468 isn't.

Anonymous   
Printed Page 514
end of "int allowed" description

I believe

r->allowed = M_GET | M_HEAD;

should be

r->allowed = (1 << M_GET) | (1 << M_HEAD);

Anonymous   
Printed Page 515

The first line reads:

int length;

where it should read

int clength;

as the variable clength holds the request (C)ontent (Length).

Anonymous   
Printed Page 515
top of page

The request_rec description on page 515 states that "long length" holds the
outgoing Content-length. It should be "long clength."

Anonymous   
Printed Page 528
description of ap_pstrndup() near bottom of page

The description states "This is a version of ap_pstrdup(), but it only
allocates and copies n bytes." According to the source (and common sense) it
actually allocates n+1 bytes, copies n bytes and NUL-terminates the new string.

Anonymous   
Printed Page 547
Example 10-4

I suggest that "int rc" should be initialed as DECLINED or otherelse. Because
"if(ap_should_client_bolck(r))" maybe return 'false', it results in return
uninitialized "rc".

Anonymous   
Printed Page 562
APLOG_WARN is actually called APLOG_WARNING.

Anonymous   
Printed Page 569
bottom half of page

In the example for the ap_satisfies function, you have:

" if (!(r->satisfies == SATISFY_ANY && ap_some_auth_required(r))) "

However, in the declaration for the request_rec, I cannot find a "satisfies" member.
Don't you instead mean:

" if (!(ap_satisfies(r)==SATISFY_ANY && ap_some_auth_required(r))) "

Anonymous   
Printed Page 628
There's a bug in Example 11-6 if compiled on a WIN32 platform.

The WIN32 version returns back to the caller, but

r->filename and
r->args

have been overwritten with values for the ap_call_exec function. In UNIX,
this is not a problem because the code exits after the exec. But in Windows,
the exec returns and code continues with these bogus values.

Anonymous   
Printed Page 649
bottom of page

Do s/.makepl_args.mod_perl/.makepl_args.mod_perl/

(??)

Anonymous