Perl-Win32-ASP FAQ

This FAQ assumes your Perl version is ActiveState 316 - if you don't have it then get it now.

  1. Why should I use PerlScript
  2. How do I convert from VB Script to PerlScript
  3. How do I use Session Objects
  4. How do I use Cookies
  5. How do I access form variables
  6. How do I exit/end a script
  7. Can I call a VB Script Function from PerlScript
  8. My function parameters are corrupt, what happened
  9. How secure is PerlScript
  10. Where can I download PerlScript?
  11. How do I iterate over a collection?
  12. How do you use BinaryWrite?

1. Why should I use PerlScript

Q: What is the advantage of PerlScript over CGI programming with Perl?

A: The first issue is speed. Most importantly PerlScript (ASP) is multi-threaded (not that the script writer will ever notice) which means that one instance of PerlScript is started (with the web server) and threads are spawned to process the scripts. This is different to Perl.exe which has to launch in a separate memory space from the web server and be launched for each and every script. PerlIS gets around some of the problems, but it appears that PerlScript is faster (in my examples anyway!).

Secondly PerlScript gives you access to a number of useful things:

Finally PerlScript embeds within the HTML, so you don't have to be a programmer to get a grasp of what's going on. Let me show you two equivalent scripts:

formproc.pl
===========

require 'cgi-lib.pl';

&ReadParse(*input);
print <<EOF;
<HTML>
<HEAD>
<TITLE>Form Values</TITLE>
</HEAD>
<BODY>
<H1>Form Values</H1>
Value of Text1 = $input{'Text1'}
</BODY>
</HTML>

formproc.asp
============
<%@ LANGUAGE = PerlScript %>
<%
use Win32::ASP;
%>
<HTML>
<HEAD>
<TITLE>Form Values</TITLE>
</HEAD>
<BODY>
<H1>Form Values</H1>
Value of Text1 = <%= GetFormValue('Text1') %>
</BODY>
</HTML>

OK, so it's not a great example because of the lack of complexity. But anyone coming to the second script won't have to deal with the <<EOF things found in so many scripts.

Top

2. How do I convert from VB Script to PerlScript

Q: There doesn't appear to be any documentation for PerlScript (ASP) - where can I find it?

A: You're reading it :-) Seriously though, ASP is simply an interface to a COM object model. Using ASP in PerlScript is the same as using Win32::OLE. The pre-defined objects are:

	VBScript				PerlScript
	--------				----------
	Session					$Session
	Response				$Response
	Request					$Request
	Server					$Server
	Application				$Application *

* There appear to be problems with the Application object in PerlScript

To access the members of each object use the "->" arrow. Properties are accessed using $Object->{PropertyName} and functions using $Object->Func().

Example 1:
To get at the QueryString collection * in the Request object use:

$FormVariableQ = $Request->QueryString("Q")->Item();

* collections act like functions that return RequestDictionaries, get each item in the dictionary with a call to Item($i)

Example 2:
To set a page to expire immediately (no caching) use:

$Response->{Expires} = 0;

If you get stuck on anything use OLE Viewer and look at the Microsoft Active Server Pages object model, it's an awful lot easier to figure out things that way than using the VB Script oriented documentation.

Top

3. How do I use Session objects?

A: Look at the sample that comes with PerlScript 313.

# get the value associated with 'MyVar'
# increment the value then store it back
$var = $Session->{'MyVar'};
$var++;
$Session->{'MyVar'} = $var;

Simple eh?

You can use the session object for example to store a persistent database connection (This makes your app VERY fast):

In Global.asa

<OBJECT RUNAT=Server SCOPE=Session ID=Conn PROGID="ADODB.Connection">
</OBJECT>

<SCRIPT RUNAT=Server LANGUAGE=PerlScript>
sub Session_OnStart {
	$Conn->Open( "DSN=TESTING;UID=dba;PWD=sql" );
}
</SCRIPT>

In your ASP file

<%
$Conn->Execute(...);
...
%>

Note: I couldn't get this to work in ActivePerl (builds 500 and 501).

Top

4. How do I use Cookies?

To read a single cookie use:

my $CookieVal = $Request->Cookies('CookieName')->{Item};

To read a cookie that is a dictionary:

# Repeat for different values of SubCookie.
# NB: SubCookie MUST be in capitals, even if you set it in lower case.
my $CookieVal = $Request->Cookies('CookieName')->Item('SUBCOOKIE');

To set a single cookie use:

$Response->Cookies('CookieName')->{Value} = $Value;

To set a cookie that is a dictionary:

# Repeat for different values of SubCookie
# DOES NOT WORK UNDER "use strict";
$Response->Cookies('CookieName')->{SubCookie} = $Value;

To set multiple cookie values at once:

# DOES NOT WORK UNDER "use strict";
Win32::OLE::with($Response->Cookies('CookieName'),
SubCookie1 => $Val1,
SubCookie2 => $Val2,
SubCookie3 => $Val3);

Other cookie properties:

$Response->Cookies('CookieName')->Item('Expires')->{Value} = "December 31, 2005";
$Response->Cookies('CookieName')->Item('Path')->{Value} = "/"; # Available on whole server
$Response->Cookies('CookieName')->Item('Domain')->{Value} = "server.com"; # Only returned on server.com domain
$Response->Cookies('CookieName')->Item('Secure')->{Value} = 1; # Boolean - set to 1 for secure cookies

Iterating over cookies:

To iterate over all the cookies returned:

foreach my $f (Win32::OLE::in ($Request->Cookies)) {
    Print "\n<br>", $f, " = ", $Request->Cookies($f)->{Item} ;
}

(assumes Win32::ASP is loaded)

To iterate over a single cookie's dictionary:

foreach my $f (Win32::OLE::in ($Request->Cookies('CookieName'))) {
    Print "\n<br>", $f, " : ", $Request->Cookies('CookieName')->Item($f);
}

Caveat's

Cookies do not get set if you specify an undef value.

Cookies do not get set (or return an error which it does in VBScript) if you try and set a cookie after sending any output whatsoever. You can overcome this by setting $Response->{Buffer} = 1;

There are problems under "use strict;" - the collection as hash ref hack doesn't work, so you can't do $Response->Cookies->{Name} = $Value any more (and should avoid doing it anyway), however that hack is the only way to set sub cookies at the moment. To quote Jan Dubois on this (thanks Jan!):

"I'm afraid that this involves "SetProperty with arguments" functionality. This is not yet implemented in Win32::OLE and was undocumented in the old OLE.pm module. Of course you had the special case of "SetProperty with single argument" as a byproduct of the collection/property dualism hack."

Top

5. How do I access form variables

Q: Form variables seem to be different depending on whether you use POST or GET, cgi-lib/CGI.pm were never like this. I want to use GET to develop and POST for production, how can I do this easily?

A: OK, so this is just a plug, but you need my Win32::ASP module. It contains a functions called GetFormValue which takes a Form name (the text from NAME="..." on your form) and optionally an index. See the documentation for why the index is there. Get it from:

http://come.to/fastnet/
Top

6. How do I exit/end a script

Q: Why doesn't die or exit stop my script?

A: Because the engine processes the whole of the script, only stopping if it comes across a $Response->End(). To get around this, and make programming easier for perl programmers, use Win32::ASP as mentioned above and you get all the functionality of die and exit back again...

Top

7. Can I call a VB Script Function from PerlScript?

Q: When I try to call a VB Script function from my PerlScript, it says the function doesn't exist.

A: You need to call it as:

$ScriptingNamespace->VBScriptFunctionName();
Top

8. My function parameters are corrupt, what happened?

Q: When I call a PerlScript function from VB Script it corrupts the parameters. Is it something I'm doing wrong?

A: No. This is a bug in PerlScript that is being worked on. For now there is a work around: use a session object to pass the parameter.

Top

9. How secure is PerlScript?

A: See the PerlScript security warning I posted, other than that it's secure - probably more so than VBScript.

Top

10. Where can I download PerlScript?

A: http://www.activestate.com/

Get yourself a copy of ActivePerl, and select PerlScript when installing.

Top

11. How do I iterate over a collection?

A: This assumes you are using ActivePerl (perl 5.005 and above)

Use the "in" function in Win32::OLE:

foreach $f (Win32::OLE::in ($Request->Form)) {
# Do something with $f here
}

Top

12. How do you use BinaryWrite?

BinaryWrite is needed if, for example, you want to send a GIF to the browser instead of HTML. The problem is that internally Perl doesn't support unicode (yet), which are strings that are wider than ordinary ASCII (an 8bit string representation). OLE (and thus the ASP object model) expects unicode wherever it goes, and so it converts to unicode whenever you pass a scalar to an OLE function. In order to do this perl (really Win32::OLE) simply pads with nulls. This breaks things like GIFs being sent. The way around it is to use the Win32::OLE::Variant module to explicitly convert to a variant first before outputting:

<%@ ENABLESESSIONSTATE=FALSE LANGUAGE=PerlScript %>
<%
use Win32::OLE::Variant;
$Response->{ContentType} = 'image/gif';
my $filename = $Server->MapPath('aspfdr.gif');
my $buf;
open ( FILE, $filename );
read ( FILE, $buf, 10000 );
close FILE;
# This converts to a variant unicode value
my $variant = Win32::OLE::Variant->new( VT_UI1, $buf );
$Response->BinaryWrite($variant);
%>

Or use the latest Win32::ASP module and the Win32::ASP::BinaryWrite function to hide the conversion.

Top

-----------------------------------------------------------
This FAQ is Copyright © Fastnet Software Ltd, 1998 - All rights reserved.
For your use it is released under the same licence as Perl itself, and
may be distributed under the same terms and conditions.
Mailto:sergeant@geocities.com for praise/flames/criticism or
just to drop me a line, or visit my web site at
http://come.to/fastnet