RETRIEVING DATA FROM AN EXTERNAL CGI PROGRAM
This tutorial explains how a Flash 4 movie can retrieve data from an external CGI program. To understand this tutorial, it's recommended that you are already familiar with:
- how to access variables in Flash 4
- Flash 4 Action Scripting
- how to program in Perl or C
- how to run and create CGI (Common Gateway Interface) programs
Flash 4 has a capability to communicate with an external CGI program by using the LoadVariables function. This is quite powerful, for example, you can have a create a database front-end in Flash, online greeting card, chat application, and so on.
The Flash 4 documentation on this subject is very minimal, hopefully, this tutorial can supplement the reader's knowledge on this somewhat obscure matter.
Example 1: Hello World
This is a very basic Flash movie that calls a Perl script and then retrieve data from the Perl script. Click the orange button to retrieve the data. The Perl script on this example is very simple. It simply sends a string back to the Flash movie. The string is "Hello".
The Flash movie above uses the Load Variables function to call a Perl script (hello.pl) to retrieve a variable, specifically:
- When the orange button is pressed, the Flash movie will run hello.pl, and
- in turns, hello.pl will send a variable called "message" with the value of "Hello" to the Flash movie.
- The Flash movie then prints out the value of the variable "message" onto the text box.
The orange button's "On (Press)" method is associated to a call to LoadVariables function in Flash 4. (PS: You won't see LoadVariables listed on the pull down, instead, select Load/Unload Movie first, and then click the Load variables into location - see picture below).
Some words about the parameters:
This is where the external program/script resides. (Note: for the above example, the URL must be replaced with the appropriate location of the server.)
Level - this is the level of the movie, if your Flash movie have not loaded any other movie using LoadMovie, then this should be 0 (0 refers to the first scene, main timeline).
Target - this is useful if you want the variables returned by the external program to be assigned to a movie clip, instead of to the scene's main timeline. If you understand TellTarget, this is similar and should be quite clear to you, hopefully after experimenting with it for a while. What this does is this: if Target is specified, then when the external program sends the data to the Flash movie, then the data is sent to the targeted movie clip (instead of sending the data to the main timeline).
If you have a movie clip named "Receiver" on the main timeline; and on the example above, you set Target to "/Receiver", then once the data is transferred, you will have a variable named "/Receiver:message"
This is only relevant if you're sending data to the external program. If you're only retrieving data from (and not sending any data to) the external program, set this to Don't send.
Caution: Based on my experiement, if you use Don't Send, then the next time you call the same LoadVariables, then the external program might not be re-executed; and the data might be reloaded from the memory or disk cache instead. This is a problem if the external program is supposed to send a different data every time it's executed - such as real time data.
In that case, use Send using GET or Send using POST to force Flash to not reload from cache. You can force the external program to be re-executed with this trick (See Example 2). Note: Send using POST seems to be more reliable in preventing caching. Ugh, scratch this paragraph. It turns out that something else is going on here. Please see: Caching Problem discussion.
And this is the Perl script:
#!/usr/bin/perl ############ # Sample interface to a Flash program. # F. Permadi # Created Jan 2000 ########### # print out the content type header # (this must be present as the first line # printed by the CGI program, if not, # this script will not work!) ########### print "Content-type:text/plain\n\n"; ########### # the following print statement will pass the # string "Hello" into a variable... # named "message" in Flash. ########### print "message=Hello"; exit 0;
The first line outputted by the external CGI program must be:Content-Type:text/plain\n\n
In Perl:print "Content-Type:text/plain\n\n";
This line very important because this is the way your web server can identify the MIME type of the data that is being sent by the CGI program . If you're not sure what this means, don't worry. Just make sure to the first thing the cgi program print to the standard output is that line exactly as it appears. Do not leave out the two "\n"s at the end. If you do, then some browsers will not be able to run the program at all. (You can probably get by using Content-Type:text/html\n\n, but there's no point since we're only sending text data.)
The Data Must Be Assigned to Variable(s)
When Flash4 receive data from an external program, the data must be formatted in a certain format. The format is actually quite simple:
1) All data must be preceded by a variable name. (i.e.: The variable name is how Flash, and you know how to access the data. Without it, there's no way of accessing the data.)
2) It must be in a standard MIME encoded format. More about this later.
Sending just one variable
Passing one variable is very simple. Just print to the standard output using the following format:variableName=variableValue
Note that you may not use any <SPACE> on the variable name, and also do not put any <SPACE> before or after the = sign. (But, what if you need to use <SPACE>? More about this later.) Also, the variable name being sent by the CGI program must match the variable name in your Flash movie. For example:
On "hello.pl" the last line with the print statement is:print "message=Hello";
This means that "hello.pl" will pass a variable named "message," with the value of "Hello" to the Flash movie (if the variable does not exists on the Flash movie yet, it will be created automatically). The variable will be put on the scene's timeline or the targeted Movie Clip.
To send a variable named "score" with the value of "95", have the CGI program print out the following:score=95
In Perl:print "score=95";
Also, note that if the value contains <SPACE> character, then you must replace the occurrence of the <SPACE> character with a + sign. For example, suppose that the variable "message" contains the value of "Good Morning" then the proper way to send it will be:message=Good+Morning
In Perl:print "message=Good+Morning";
This is explained more on another section below.
Sending more than one variables
If the CGI program needs to send more than one variable, you must print it out with the following format:variable1Name=variable1Value&variable2Name=variable2Value
To send a variable named "score" with the value of "95"; and another variable named "firstName" with the value of "John", then have the CGI program print out the following:score=95&firstName=John
Just remember that the & sign acts as a separator between variableName=variableValue pairs. If you have more than 3 variables, just append each variableName=variableValue pair with & sign like above. (As always, do not not use any <SPACE> on a variable name, and do not put any space before or after the = and & sign)
The Data Transfer Might not Occur Immediately
Once you call the LoadVariables function in Flash4, the Flash movie will immediately execute the CGI program, but it will not wait for the data from the CGI program to arrive. This means that Flash will immediately execute the next statement in the Flash code (or play the next frame in the movie), even though the data transfer might not be completed yet (i.e.: the Flash movie will not wait for the external program to complete its execution). For this reason, before using the data, you should always have the Flash movie check whether the data transfer has been completed or not.
The simplest way to do this is to have a variable as a "flag" in the Flash movie. Set "flag" to "0" just before calling LoadVariables. Then, have the external program send back a different value of "flag" to the Flash movie at the end of the data stream. For example:
In Flash pseudo code below, Frame 1 calls the external program, then the code does a loop until the data transfer has been completed.
Set variable: "flag" = "0"
If ("flag" ne "0") then
If flag is no longer 0, then data transfer is complete, do something
Goto and Play Frame 2
The External Program Must Reside on the Same Subdomain as the Flash Movie
For security reasons, this is a restriction built in Flash 4. This is a good thing because you don't want other people to run your programs, thereby wasting your bandwidth allocation; on the other hand, if you do not have cgi-bin access, this is a bad thing. Oh well... just be aware of this restriction. So, for example, if the Flash movie clip is located at www.someserver.com, then the external program must also be located at that domain or its subdomain, in this case someserver.com (they don't have to be on the same directory).
Data Transferred is String Type
The data retrieved by Flash from an external CGI program is theoretically text (or String data type in Flash). If you need to convert it to number, to be safe, you should do so after the data is transferred (you can use the Flash 4's Int function to convert string to integer).
Do Not Use <SPACE>
This has been mentioned above, but it's worth repeating. If the variable value contains <SPACE> character, then replace the occurrence of the <SPACE> character with the + sign. For example, suppose the variable "fullName" contains the value of "John Smith" then the way to send it will be:fullName=John+Smith
and not like belowfullName=John Smith
Flash will automatically convert the + sign to <SPACE>. If you're not very familiar with CGI, this might seems weird, but this is standard CGI encoding requirement, so it's important and proper to follow. There're some other characters that needs to be encoded as well. For a complete reference, I suggest consulting a CGI reference.
Example 2: Server Date and Time
This example below is very similar to the first example. It fetches and displays the time from the server. When the button is clicked, it calls LoadVariables to load the current server date and time. (Note: my server's date and time might not match your time zone.)
The Flash movie contain 5 variables,
hours, mins, secs to represent time; and day, and mo to represent the date. All these variables are on the main timelines. The Update Time button On (Press) function is like this:
Notice that in the Variable section, I use Send using POST even though I have no need to send anything. What happens here is that all the variables on the current timeline will be passed to the cgi-program. Since one the variables will always differ (the /:secs will always be different, it's a timer), it forces the browser to not reload data from cache. If this is set to Don't send, the second time the "Update Time" button is clicked, the time will not change, which will be wrong.
The CGI script is written in Perl. Below is the content of time2.pl.
#!/usr/bin/perl ############### # Sends date and time # F. Permadi, March 2000 ################# ($svrSecs,$svrMins,$svrHours,$day,$mo)=localtime(time); print "Content-type:text/plain\n\n"; print "hours=$svrHours&mins=$svrMins&secs=$svrSecs"; $mo++; print "&day=$day&mo=$mo"; exit 0;
A side note about this example: Theoretically, it's possible to make this example auto-update every second. However, the main disadvantage to that is that the Flash movie must repeatedly execute the CGI program in order to do the update. This is a waste of bandwidth and could potentially burden the server machine.
(C) F. Permadi