Articles Archive
Articles Search
Director Wiki
 

Shockwave Chat

March 12, 1998
by Andrew White

Introduction

The major feature of the recent FileMaker Pro 4.0 database application from Claris (now FileMaker, Inc. ) was the integration of web hosting features into the database application itself rather than using a third party web server and and plugin. While this may seem irrelevant to Director developers, for those lucky enough to have their PC and Macs permanently connected to the Internet via leased lines it does open up some interesting possibilities.

In this article I'll talk about what those possibilities are and how to take advantage of them in your Shockwave movies. I'll be using an online chat system as an example to show how the whole thing hangs together.

FileMaker Pro as a CGI

The vast majority of the CGIs used on the Web are there to provide some way retrieve information from the client and then process it some way, after which the results are returned to the client. The search engine is a classic example of this use, and usually the PERL language comes into the equation at some point - either the whole CGI is implemented in PERL or it is used as a interface to a backend database server running SQL or something similar.

Instead of learning a new (albeit useful :-) ) programming language, why not build solutions based upon the groundwork of other. By using FileMaker Pro as the CGI application you are gifted all of the searching, indexing & data storage you could ever possibly need - all contained within a single file, thereby bypassing any overhead associated with accessing multiple files incurred by the underlying operating system. The only cloud on the horizon is how to host the database files on the Internet.

The current situation exists because the majority of servers on the Internet use a variant of UNIX and can't run standard desktop application software without some kind of emulation package. This situation is changing very rapidly though as more and more companies are linked to the Internet and even if you aren't linked yourself then there are third party hosting services specifically for FileMaker Pro which run on NT and MacOS servers.

If you have no experience of using FileMaker Pro or any similar type of database software then you might want to read this simple introduction.

Shockwave Chat Example

Creating the databases

The first stage in the process is to define and create our databases for holding our data. We will keep things simple in this example but there is no reason why it can't have additional databases defining rooms etc.

Users Database

Firstly we create the users database which is used to hold the current settings for each person in the chat system. We define six fields, although only four of them are absolutely necessary.

Field Name

Field Description

User

This is the key field identifies a person in the chat system. Data validation is switched on ensuring that the field is unique, i.e. no two records have the same User field.

Real Name

This field holds the person's real name. This field is not essential but could be useful in tracking someone down who abuses the system.

Email

Similar to the field above, the email field is not essential and is just there so that if people have any problems the administrator can contact them.

Room

This field holds the current room in which the person is chatting. When the person logs on a script is run which sets this to the value contained within the Entrance global field. In this example the range of rooms is stored in a static value list but there is no reason why a dynamic database driven room system could not be implemented instead.

Online

This field tracks whether the users is currently online. This field is set by the logon and logout scripts.

Entrance

This is a global field that defines the first room in the chat system for

After defining all of the fields this is what the users database looks like.

Chat Database

The chat database holds the actual messages that people send. It uses five fields and one relationship. The match field for the relationship is the User field and this is used to auto enter the room field.

Field Name

Field Description

User

This field identifies the user that created the message.

Room

This field identifies the room that the user was in when the message was created. This field is auto entered based on the relationship from the User match field.

Date

The date that the message was created. This is set by auto entering.

Time

The time that the message was created. This is set by auto entering.

Message

The field holds the actual text of the message.

After defining all of the fields this is what the chat database looks like.


Constructing Format Files

The way that FileMaker works as a CGI is that any queries submitted by the client and then processed are passed through a parser which formats the returned document based on a format file. Within a format file are custom tags which are replace with data from the database. There are additional tags which also allow you to insert things like the current time & date.

The great thing about these format files is that they don't need to be HTML files - they can be ordinary text files. This means that with careful formatting FileMaker Pro can return a string representation as a list which can be then converted into a list simply by using the lingo function value() - no messy and time consuming parsing of HTML documents. Also the size of the return document is much smaller - no more than a few bytes.

The list of replacement tags is very extensive but this example only make use of a few, which are:

Format File

Description

[FMP-Record] [/FMP-Record]

All text within this tag pair is repeated for every returned record.

[FMP-Field: name]

This tag is replaced by data from the appropriate field

[FMP-ValueList: name]
[/FMP-ValueList]

The text within this tag pair is repeated for every item within the value list defined in the FMPro database.

[FMP-ValueListItem]

This tag is replaced by the current FileMaker Pro value list item

[FMP-CurrentTime]

This tag is replaced with the current server time

[FMP-CurrentDate]

This tag is replaced with the current server date

[FMP-CurrentError]

This tag is replaced with the current server error number

For a full list of tags see the CDML reference database in the Web Tools folder within your FileMaker folder.

If you are using text format files then you need to be very careful when editing them. Ensure that there are no trailing returns, and any text within a [FMP-Record] tag pair needs to be there otherwise the value function will fail and your variable reference will be void.

GET v POST

There are two methods of submitting data to a CGI - GET and POST. GET requires all of the data to be passed in the URL, whereas POST appends the data to the input stream. This means GET is very limited in posting large quantities of data, whereas POST can handle virtually unlimited amounts. Unfortunately netLingo in Director only support the GET method, although the current beta release of XtraNet now has POST support. With the current problems involved in getting xtras downloaded into the browser support folder this means most Shockwave solutions will have to use GET. This means that the amount of data that can be passed is currently limited to 1 KB (including the domain name portion), though some browsers have problems with such long URLs so the TETOTOYTM (Test early, test often and test on your target machine) acronym applies.

Constructing URLs

There are a number of portions to a URL, these being:

URL Segment

Description

Base URL

This is the server URL on which FileMaker Pro is running.

CGI Action

This is the actual CGI call and is always FMPro?

Variable Tags

These tags specify a number of things not least of which are the database to perform the action on. For every URL you'll probably use the many of the following tags.

  • -DB
  • -Error
  • -Format
  • -Lay
  • -Op
  • -RecID
  • -Script

Parameters

This is the actual field data that you want the action to be performed upon. They generally take the form of a name value pair, e.g. user=AndyW

Action Tag

This tag specifies what FMPro action is to be performed and can be one of:

  • -Delete
  • -Dup
  • -Edit
  • -Find
  • -FindAll
  • -FindAny
  • -Img
  • -New
  • -View

These tags would be linked together into one URL using the & character to give you something like:

http:/www.yourserver.com/FMPro?
Db=users.fp3&-Lay=users&-Format=users.txt&-Find

Consult the CDML reference database for further information on what each of the tags does.

Encoding data

One problem with the GET method is that a lot of the characters can confuse the browser so they need to be encoded into a hexadecimal representation, e.g. a space needs to be converted to %20. The following two handlers perform this operation


-- Encode a string into a URL safe form
on encode inStr
  
  set outStr = ""
  set numChars = length(inStr)
  
  -- These chars are ok in a URL and
  -- don't need converting
  set legalChars = "ABCDEFGHIJKLMNOPQRS ¬
    TUVWXYZ0123456789"
  
  repeat with i = 1 to numChars
    
    -- We get and delete the first char 
    -- every time so that Director doesn't 
    -- have to move into the string.
    set currChar = char 1 of inStr
    delete char 1 of inStr
    
    if legalChars contains currChar then
      -- Legal char so just append
      set outStr = outStr & currChar
    else if currChar = QUOTE then
      -- Convert " to " & QUOTE & "
          -- so that when value()
      -- is performed the list is valid
      set outStr = outStr & "%22%20%26%20 ¬
            QUOTE%20%26%20%22"
    else if currChar = RETURN then
      -- Convert RETURN to " & RETURN & "
          -- so that when value()
      -- is performed the list is valid
      set outStr = outStr & "%22%20%26%20 ¬
            RETURN%20%26%20%22"
    else if currChar = numToChar(194) then
      -- Convert ¬ to " & numToChar(194)
          -- & " so that when value()
      -- is performed the list is valid
      set outStr = outStr & "%22%20%26%20numToChar ¬
              %28194%29%20%26%20%22"
    else
      -- Just a standard char like ? 
      -- so convert to hex
      set outStr = outStr & "%" & ¬
              decToHex(charToNum(currChar))
    end if
    
  end repeat
  
  return outStr
  
end
-- Convert a decimal number into hex
on decToHex decNum
  
  set hexNum = ""
  
  -- Repeatedly divide by 16 until the original
  -- number is equal to or less than 15
  repeat while decNum > 15
    
    set currMod = decNum mod 16
    set decNum = decNum / 16
    
    -- If the 
    if currMod < 10 then
      set hexNum = currMod & hexNum
    else
      set hexNum = numToChar(55 + currMod) & hexNum 
    end if
    
  end repeat
  
  if decNum < 10 then
    set hexNum = decNum & hexNum 
  else
    set hexNum = numToChar(55 + decNum) & hexNum 
  end if
  
  return hexNum
  
end

Note that special handling of the carriage return, quote and line continuation characters means that the data will look a little strange in FMPro. Take out these lines if you want the data in FMPro to read correctly but be aware that value will fail when the data is returned unless some extra parsing is done before using value()

Rather building a URL build concatenating together huge chunks of text, add each segment to a linear list and then pass it through the following handler which concatenates all of the items in a list into one string.


-- Assemble a list of strings into one string
on buildURL inLst
  
  set outStr = ""
  
  repeat with i in inLst
    set outStr = outStr & i
  end repeat
  
  return outStr
  
end

This will turn ["http://www.host.com/","FMPro?","-Db=users.fp3","&-FindAll"] into:

"http://www.host.com/FMPro?-Db=users.fp3&-FindAll"

Submitting the URL

Once you have your URL you then need to submit it. All netLingo operations are asynchronous, so you cannot use a repeat loop structure to wait for the data to be returned. This means you have to loop using a exitFrame handler which repeatedly calls netDone to see if the operation is complete.

When you have many net operations happening in rapid succession then using exitFrame can rapidly become very complex - a better way to handle this is to using an autonomous lingo object which sits in the actorList until the operation is complete and then cleans up after itself and calls the appropriate handler to act upon the returned data.

This parent script is such an object - just create the object using new and pass in the URL and handler names along with an object reference if your using an object to handle the returned data. You can even specify an error method if a net error occurs but it's not required and if it isn't specified then the object quietly deletes itself with any error message being displayed.


-- Parent script to handle asynchronous 
-- getNetText calls
property callbackMethod
property callbackObj
property errorCBObj
property errorCBMethod
property netID

on new me, URL, cbMethod, cbObj, errMethod, errObj
  
  -- Store the callback references
  set callbackMethod = cbMethod
  set callbackObj = cbObj
  set errorCBMethod = errMethod
  set errorCBObj = errObj
  
  -- Start the net operation
  set netID = getNetText(URL)
  
  add the actorList, me
  
  return me
  
end

on stepFrame me
  
  -- Check to see if we're done
  if netDone(netID) then
    
    -- We've completed so delete ourselves
    deleteOne the actorList, me
    
    -- Check that the op was performed succesfully
    
    if netError(netID) = "OK" then
      
      -- If we have a callback object then use call,
      -- otherwise we use do for global methods
            
      if objectP(callbackObj) then
        call callbackMethod, callbackObj, ¬
          netTextResult(netID) 
      else
        do callbackMethod & " netTextResult(netID)"
      end if
      
    else
      
      -- If we have a error callback 
      -- object then use call,otherwise
      -- if we have and error method use do
      
      if objectP(errorCBObj) then
        call errorCBMethod, errorCBObj, ¬
           netError(netID) 
      else if stringP(errorCBMethod) then
        do errorCBMethod & " netError(netID)"
      end if
      
    end if
    
  end if
  
end

Parsing the result

Once the data has been returned then it's simply a matter of using the value function to turn the string into a list before extracting the data using getaProp or getAt. This code snippet is from the chat control parent script:


-- Parse the result of the logon process
on logonResponse me, result
  
  -- Convert the string into a property list
  set resultList = value(result)
  
  -- Check to see if value return a property list
  if ilk(resultList) = #propList then
    
    -- If the property list contains 
    -- an error property then an 
    -- error occured so handle accordingly
    if getPropAt(resultList,1) = #error then
      
      case getaProp(resultList,#error) of
          
        -- The user doesn't exist so 
        -- create a new record
        401: newUser me
        
        -- Display a generic alert 
        -- for all other errors
        otherwise
          
          alert "An unknown server error occured." ¬
                & RETURN & "Please try again later."
          
      end case
      
    else
      
      -- Grab the data from the 
      -- property list and store
      -- them in the object's properties
      set recID = "&-RecID=" & ¬
         getaProp(resultList, #recID)
      set lastTime = getaProp(resultList, #time)
      set lastDate = getaProp(resultList, #date)
      set room = getaProp(resultList, #room)
      -- The logon process was successful so 
      -- change the mode property
      set state = #online
      -- Get the list of rooms and the users 
      -- in the current room
      getRooms me
      getIRUsers me
      
    end if
    
  else
    
    -- The value() function failed so 
    -- just display a generic error
    alert "An unknown server error occured." ¬
          & RETURN & "Please try again later."
    
  end if
  
end

If you're planning on editing records then it's a good idea to grab the record id and store it in a property. This id number is unique to a record and never changes, even if other records are deleted. The -RecID variable tag is required for editing records in a URL.

Chat.dir - The Director Movie

I won't go into too much detail about the movie as the downloadable sample has plenty of comments in the scripts, but the basic functionality consists of three tabbed panes which are:

Message Pane

The message pane is the main screen where all of the chatting is done. There are four text fields which hold the incoming messages, the outgoing message, the users in the current room and the rooms available on the system. The are three buttons Logon, Logout and Send - all of which do the obvious. Before the user can send a message they have to logon and if the movie is quit then the stop movie handler sends the logout command to tidy things up.

Status Pane

This pane has one function - it shows the list of people online even if the users is offline. This allows the users to set the update frequency to 5 or 10 mins and then keep an eye out for someone they're trying to chat to.

Options Pane

The options pane is where the base URL of the chat server is set. Also the user's settings are stored here along with the frequency with which updates are fetched.

Chat Parent Script

The chat parent script controls the submitting of URLs and the display of the results. Although it is lengthy it consists of mainly a series of initiator and responder methods along with a stepFrame method which handles the submitting of URLs.

An initiator method builds a URL and then submits it using the asynchronous getNetText object outlined above, along with the name of the appropriate responder method. When the getNetText operation is complete the responder method is called and the data is formatted appropriately.

Other Possibilities

There are a number of possibilities which can be achieved with using FileMaker as a CGI engine, here are just a few of them:

I hope you agree that using a database product such as FileMaker Pro offers some interesting possibilities for enhancing interaction with your Shockwave movies but there's no need to restrict them to just Shockwave - the above techniques will function just as well in web enabled projectors or even within the authoring environment as a MIAW authoring tool. If you're working on a distributed project then using a networked database can really give you an edge.

Further info

There is a downloadable demo of FileMaker Pro which is restricted to 50 records available from the Claris web site

Web Sites

Mailing lists

Mailing List Name

Description

FMPro

This is a general FileMaker Pro list - good for all round design issues.

FMPro-L

This is another general FileMaker Pro list - good for all round design issues. The traffic on FMPro and FMPro-L is very high (more than 80 messages per day per list).

FMP-Web

This list is dedicated to using the web features of FMPro 4 and it's CDML tag library.

FMPro-cgi

This list is dedicated to the use of FMPro as a CGI using any of the third party products such as Lasso, Tango and Web FM or the built-in Web Companion.

Lasso

This list is dedicated to using BlueWorld's Lasso plugin and CGI which links a standard web server with FileMaker Pro. Since the Web Companion is based on Lasso 2.0, this list is useful to people who are using the built-in features of FMPro 4 as the tags are very similar.

The source files for this article, including FMP files, are available for download (SIT or ZIP).

Andrew White is a senior partner in Cathode, a multimedia partnership based in the West Midlands, UK. He has been using Director since it was VideoWorks and has produced Director and Shockwave work for a number of clients including HP, NCR, Budwieser, Polaroid, Digital and Sun. Contact Details: Andrew White Cathode, UK Tel: +44 (0) 1203 689395 Email: andyw@cathode.co.uk

Copyright 1997-2017, Director Online. Article content copyright by respective authors.