Perl for ISAPI and CRLF

Perl for ISAPI and CRLF

am 03.02.2009 20:09:39 von Jenda Krynicky

I have ActivePerl v5.8.8 build 822 and Windblows Vista Home Premium
with its builtin IIS (but I see the same behaviour under MS Windows
Server 2003) and was using the following to print the CGI headers:

print "HTTP/1.0 200 OK\n" if($ENV{'PerlXS'} eq 'PerlIS');
print "Content-type: text/html\n\n";

Which works with all browsers I know of under both perl.exe and
PerlIS.dll, but the current version of .Net complains with "The
server committed a protocol violation. Section=ResponseStatusLine" if
the script runs under PerlIS. I used a HTTP sniffer and found out
that if I use perl.exe the \n is turned to CRLF, if I do not, it
produces just LF. I tried to add

binmode( STDOUT, ':crlf');

but that did not make any difference. I had to create a custom
PerlIO::via filter.

Why? And has this changed in a later version of ActivePerl? Hopefully
within the 5.8 series. As I'd like the content to end up having CRLF,
but do not want to have to place \x0D into all the heredocs and other
places, I'd rather if I could have \n turned to CRLF under PerlIS.dll

## CGI/ISAPI script
use strict;
use warnings;
no warnings qw(uninitialized);

if ($ENV{'PerlXS'} eq 'PerlIS') {
print "HTTP/1.0 200 OK\x0D\x0A";
print "Content-type: text/plain\x0D\x0A\x0D\x0A";
#=rem

eval <<'*END*';
package PerlIO::via::MyCRLF;

sub PUSHED {
return bless \*PUSHED,$_[0]
}
sub POPPED {return 1}
sub WRITE {
my ($self, $buffer, $fh) = @_; $buffer =~
s/(?:\x0D\x0A?|\x0A)/\x0D\x0A/sg;
print $fh $buffer;
return length($buffer);
}
package main;
binmode(STDOUT, ':via(MyCRLF)');
*END*

#=cut
#binmode(STDOUT, ':crlf');

} else {
print "Content-type: text/plain\n\n";
}

print "First line\nSecond line\n";
__END__

## test script
use LWP::Simple;

my $exe_url = 'http://.../test.pl';
my $dll_url = 'http://.../test.plx';

my $exe_content = get $exe_url;
my $dll_content = get $dll_url;

if ($exe_content =~ /\x0D\x0A/) {
print "EXE returned CRLF\n";
} elsif ($exe_content =~ /\x0A/) {
print "EXE returned LF\n";
} elsif ($exe_content =~ /\x0D/) {
print "EXE returned CR\n";
} else {
print "EXE returned no newlines!!!\n"
}

if ($dll_content =~ /\x0D\x0A/) {
print "DLL returned CRLF\n";
} elsif ($dll_content =~ /\x0A/) {
print "DLL returned LF\n";
} elsif ($dll_content =~ /\x0D/) {
print "DLL returned CR\n";
} else {
print "DLL returned no newlines!!!\n"
}
__END__


Jenda
===== Jenda@Krynicky.cz === http://Jenda.Krynicky.cz =====
When it comes to wine, women and song, wizards are allowed
to get drunk and croon as much as they like.
-- Terry Pratchett in Sourcery

_______________________________________________
ActivePerl mailing list
ActivePerl@listserv.ActiveState.com
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs

Re: Perl for ISAPI and CRLF

am 04.02.2009 02:31:48 von Bill Luebkert

Jenda Krynicky wrote:

How's it going man - long time no talk.

> I have ActivePerl v5.8.8 build 822 and Windblows Vista Home Premium
> with its builtin IIS (but I see the same behaviour under MS Windows
> Server 2003) and was using the following to print the CGI headers:
>
> print "HTTP/1.0 200 OK\n" if($ENV{'PerlXS'} eq 'PerlIS');
> print "Content-type: text/html\n\n";
>
> Which works with all browsers I know of under both perl.exe and
> PerlIS.dll, but the current version of .Net complains with "The
> server committed a protocol violation. Section=ResponseStatusLine" if
> the script runs under PerlIS. I used a HTTP sniffer and found out
> that if I use perl.exe the \n is turned to CRLF, if I do not, it
> produces just LF. I tried to add
>
> binmode( STDOUT, ':crlf');
>
> but that did not make any difference. I had to create a custom
> PerlIO::via filter.

perl581delta:
....
* The "CR CR LF" problem of has been fixed, binmode(FH, ":crlf") is now
effectively a no-op.

> Why? And has this changed in a later version of ActivePerl? Hopefully
> within the 5.8 series. As I'd like the content to end up having CRLF,
> but do not want to have to place \x0D into all the heredocs and other
> places, I'd rather if I could have \n turned to CRLF under PerlIS.dll

Obviously it's got something to do with the IS version. You should
check for kicks to see what binmode returns (T/F) when you do the :crlf
option on STDOUT. There's no chance that another FH is being used/selected
instead of STDOUT is there (when running in the IS env) ?

Have you tried a test case using CGI.pm to do the headers ? I personally
don't use it, but it would handle the headers for you and if it fails,
you can pretty much chalk it up to PerlIS. CGI always uses CRLF I believe
on Dozers.



_______________________________________________
ActivePerl mailing list
ActivePerl@listserv.ActiveState.com
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs

RE: Perl for ISAPI and CRLF

am 04.02.2009 03:15:47 von Jan Dubois

On Tue, 03 Feb 2009, Jenda Krynicky wrote:
>
> I have ActivePerl v5.8.8 build 822 and Windblows Vista Home Premium
> with its builtin IIS (but I see the same behaviour under MS Windows
> Server 2003) and was using the following to print the CGI headers:
>
> print "HTTP/1.0 200 OK\n" if($ENV{'PerlXS'} eq 'PerlIS');
> print "Content-type: text/html\n\n";
>
> Which works with all browsers I know of under both perl.exe and
> PerlIS.dll, but the current version of .Net complains with "The
> server committed a protocol violation. Section=ResponseStatusLine" if
> the script runs under PerlIS. I used a HTTP sniffer and found out
> that if I use perl.exe the \n is turned to CRLF, if I do not, it
> produces just LF. I tried to add
>
> binmode( STDOUT, ':crlf');
>
> but that did not make any difference. I had to create a custom
> PerlIO::via filter.
>
> Why? And has this changed in a later version of ActivePerl? Hopefully
> within the 5.8 series. As I'd like the content to end up having CRLF,
> but do not want to have to place \x0D into all the heredocs and other
> places, I'd rather if I could have \n turned to CRLF under PerlIS.dll

I don't think there have been any changes in PerlIS in this area.

I suspect that the binmode() call doesn't work because the :crlf layer
is special: it is not a real layer, but it just sets a bit on a lower
layer to do the translation. But it looks like the ISAPI code is
executed at a higher layer, checks that the output goes to STDOUT
and passes the data on to IIS instead. Similar things would happen
for STDERR. Seems like a bug.

But why would you want LF -> CRLF translation outside the http header?
For content-type text/html this should not make any difference in the
body of the response.

Cheers,
-Jan


_______________________________________________
ActivePerl mailing list
ActivePerl@listserv.ActiveState.com
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs

Re: Perl for ISAPI and CRLF

am 04.02.2009 15:04:43 von Jenda Krynicky

From: Bill Luebkert
> Jenda Krynicky wrote:
> How's it going man - long time no talk.

Well, you know :-)

> Obviously it's got something to do with the IS version. You should
> check for kicks to see what binmode returns (T/F) when you do the :crlf
> option on STDOUT.

I did check that, it returns true.

> There's no chance that another FH is being used/selected
> instead of STDOUT is there (when running in the IS env) ?

Not really, but since its running under PerlIS.dll I believe the
STDOUT is quite special

> Have you tried a test case using CGI.pm to do the headers ? I personally
> don't use it, but it would handle the headers for you and if it fails,
> you can pretty much chalk it up to PerlIS. CGI always uses CRLF I believe
> on Dozers.

CGI.pm does
binmode(STDOUT);
on Windows, DOS, OS2 or Cygwin and then uses \015\012 (unless on VMS
or an EBCDIC system).


I thought I could rather

binmode( STDOUT, ':crlf');

and have \n turned to CRLF everywhere.

From: Jan Dubois <
> But why would you want LF -> CRLF translation outside the http
> header? For content-type text/html this should not make any
> difference in the body of the response.

The script I actually ran into problems with was using text/xml where
is should not matter either but ... some clients are insanely picky
and do not use proper parsers.

In either case I think it will be best to

binmode(STDOUT); # for perl.exe and in case you change PerlIS.dll
print "HTTP/1.0 200 OK\x0D\x0A" if($ENV{'PerlXS'} eq 'PerlIS');
print "Content-type: text/html\x0D\x0A\x0D\x0A";


And in case I do need the CRLF in the body (eg. if I generate a CSV
file ... MS Excel doesn't like using just LF) and do not want to have
to specify CRLF everywhere I can use the PerlIO::via::MyCRLF.


Thanks, Jenda
===== Jenda@Krynicky.cz === http://Jenda.Krynicky.cz =====
When it comes to wine, women and song, wizards are allowed
to get drunk and croon as much as they like.
-- Terry Pratchett in Sourcery

_______________________________________________
ActivePerl mailing list
ActivePerl@listserv.ActiveState.com
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs