SPECweb2009 Release 1.20 E-commerce Workload Pseudocode

Version 1.20, Last modified 2010-04-29

The pseudo code specification provided is a description of the actual work that needs to be implemented. This is required so that results will be comparable. Any dynamic implementation must follow the specification exactly. This means that all operations specified, such as loops and searches, should be executed for each request. Unless otherwise specified, results or intermediate results from previous operations or requests should not be cached.

To provide the flexibility needed to implement this code on any platform and in any desired scripting language, the subroutines listed in the pseudo code may be inlined or subdivided into smaller subroutines as long as the algorithms implemented by the subroutines are performed exactly as described.

The dynamic operations must be executed by separate dynamic modules. The dynamic code must be written in a widely-used scripting language. Script implementations in PHP and JSP are supplied with the kit.

1.1.1 Definitions of Terms

BESIM
Backend Simulator, that resides on a separate physical machine than the primary SUT.  See User's Guide for more details.
QUERYSTRING
Information following the '?' in the URL.
PADDING
A file generated by wafgen that brings the dynamic script up to the sizes observed in real-world pages (that use JavaScript, CSS, etc.)
SESSION_ARRAY
A property of the scripting engine that provides some stateful way of maintaining variables across page executions (may not necessarily be an array)
Redirect
A case where the web server must send back HTTP status code 307, along with a "Location:" header indicating the URL the client will be redirected to.

Note: Directories are specified in this document with a forward slash, '/', however, this in no way implies that one has to follow this convention. Use what works on one's operating system.

1.1.2 Specification of Return Formats

All of the dynamic requests return one of the following types of HTML pages to the client. These formats must be followed precisely for the client software to understand the returned pages. This includes the blank line between the headers and the <html> tag.

Square brackets, [], are used to denote either a looping construct (If/Else/End If, Foreach, etc.), or where appropriate text should be substituted. This text should contain only the required information.  The text may NOT be padded in any way to create a fixed length field.

Curly braces, {}, are used to denote an array that can contain multiple variables inside of it.  Arrays are not strictly required for implementing these constructs; they are used to indicate a logical grouping of variables.

Extra headers required by the web server are allowed. The formats simply show the minimum required by the benchmark.

Standard Page Template
HTTP 200 OK
Content-type: text/html
Cache-Control: no-cache
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" >
<head>
    <title>SPECweb2009: eCommerce - [TITLE]</title>
    <style type="text/css" title="mainStyle">
        @import "style.css";
    </style>
</head>
<body>
<!-- SPECweb2009 Dynamic Data Area -->
[If POST variables exist]
    <h3>POST Vars</h3>
    <table>
        <colgroup>
            <col class="field" />
            <col class="value" />
            <col class="value" />
        </colgroup>
        <tr>
            <th>Variable</th>
            <th>Value</th>
            <th>Description</th></tr>
    [Foreach POST variable]
        <tr>
            <td>[POST variable name]</td>
            <td>[POST variable value]</td>
            <td> </td></tr>
    [End Foreach]
    </table>
[End If]
[If GET variables exist]
    <h3>GET Vars</h3>
    <table>
        <colgroup>
            <col class="field" />
            <col class="value" />
            <col class="value" />
        </colgroup>
        <tr>
            <th>Variable</th>
            <th>Value</th>
            <th>Description</th></tr>
    [Foreach GET variable]
        <tr>
            <td>[GET variable name]</td>
            <td>[GET variable value]</td>
            <td>[GET variable description]</td></tr>
    [End Foreach]
    </table>
[End If]
[If Report Messages exist]
    <h3>Debug Messages</h3>
    <table>
    [Foreach Report Message]
        <tr class="[Report Errorlevel: info, error, or warning]">
            <td class="type">[Report Errorlevel]</td>
            <td class="message">[Report Message Text]</td></tr>
    [End Foreach]
    </table>
[End If]
<!-- SPECweb2009 Displayable Page Title -->
<h1>SPECweb2009: eCommerce - [TITLE]</h1>
<!-- SPECweb2009 User Action Area for Links and Forms -->
[BODY]
<!-- SPECweb2009 Embedded Text -->
<pre>
[PADDING]</pre>
</body>
</html>
Error Page Template
HTTP 200 OK
Content-type: text/html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" >
<head>
        <meta http-equiv="content-type" content="text/html; charset=iso-8858-1"/>  
        <link href="style.css" rel="stylesheet" type="text/css">
        <title>SPECweb2009: Ecommerce Error</title>
</head>
<body>
<!-- SPECweb2009 Error Page -->
<div class="error">
        <h1>Script Error</h1>
        <p>[MESSAGE]</p></div>
</body>
</html>

1.2.1 Pseudocode for BESIM query subroutine

    [If BESIM_COUNT > 1]   (NOTE: BESIM_COUNT defined from the init page below)
        Seed random number generator (if necessary)
        Select a BESIM_HOST and BESIM_PORT to use below (random or round-robin)
    [End If]
    Open (or reuse a previously opened) socket to BeSim
    [If HTTP request to "http://' + BESIM_HOST + ':' + BESIM_PORT + BESIM_URI + "?2&[REQUEST]" unsuccessful]
        Report Error Message = 'Failed to open BeSim stream', ErrorLevel = 'error'
	Return empty array
    [End If]
    Skip past '<pre>' tag in BESIM response
    Set Errno = [First line in BESIM response after '<pre>' line]
    [If Errno not 0]
         Report Error Message = 'BeSim returned with an error number: ' + Errno, Errorlevel = 'error'
         Return empty array
    [End If]

    [Foreach line in BESIM response until line == '</pre>']
          BESIM_RESULTS_ARRAY += line;
    [End Foreach]

    Return BESIM_RESULTS_ARRAY

1.2.2 Pseudocode for init page

Sample request:
GET /ecommerce/init.php?BESIM_HOST=besimhost1+besimhost2&BESIM_PORT=81+82&BESIM_URI=/isapi-bin/ \
besim_zisapi.api&BESIM_PERSISTENT=true&PADDING_DIR=/www/web2009/ecommerce/dynamic_ \
padding/&SMARTY_DIR=/www/web2009/Smarty-2.6.6/libs/&SMARTY_SUPPORT_DIR=/www/web200 \
5/ecommerce/&SEND_CONTENT_LENGTH=true HTTP/1.1
    [Foreach name, value pair in QUERYSTRING]
        Set name = value   (NOTE: these must persist across script executions)
    [End Foreach]
    Set BESIM_COUNT = [# BESIM_HOST/BESIM_PORT pairs]

    Set SERVER_TIME = [# milliseconds since the Unix Epoch]

    Return Page with HTML = 
<html>
        <head>
                <title>SPECweb2009 Ecommerce Workload Init</title>
        </head>
        <body>
<P>SERVER_SOFTWARE = [Substitute web server variable: "SERVER_SOFTWARE"]</P>
<P>REMOTE_ADDR = [Substitute web server variable: "REMOTE_ADDR"]</P>
<P>SCRIPT_NAME = [Substitute web server variable: "SCRIPT_NAME"]</P>
<P>QUERY_STRING = [Substitute web server variable: "QUERY_STRING"]</P>
<P>SERVER_TIME = [SERVER_TIME]</P>
        </body>
</html>

1.2.3 Pseudocode for index page

Sample requests:
GET /ecommerce/index.php
GET /ecommerce/index.php?c=ARS06
    [If QUERYSTRING['c'] not set]
         QUERYSTRING['c'] = 'CAD01'
    [End If]
    Set TITLE = 'Home Page'
    Set REGIONS_ARRAY = [BESIM query with REQUEST = '11']
    Set BODY = 
    <form action="[INDEX SCRIPT NAME]" method="GET">
        <h3>Select Your Region</h3>
        <select name="c">
[Foreach region in REGIONS_ARRAY]
	[If QUERYSTRING['c'] == region]
	   <option selected>[region]</option>
	[Else]
           <option>[region]</option>
	[End If]
[End Foreach]
        </select>
        <input type="submit" value="go">
    </form>
    
    <form action="search.php" method="GET">
        <h3>Search</h3>
        <input type=hidden name="c" value="{QUERYSTRING['c']}">
        <input name="kw" type="text" value="" size="30">
        <select name=seg>
        	<option value="all">Entire site</option>
	        <option value="products">Products</option>
	        <option value="services">Services</option>
	        <option value="techsupport">Technical Support</option>
	        <option value="accessories">Accessories</option>
        </select>
        <input type="submit" value="Search">
    </form>
    
    <h3>Browse: Choose customer type:</h3>
[Foreach customer_type_short, customer_type_long from CUSTOMER_TYPES_ARRAY]
	<a href="browse.php?c={QUERYSTRING['c']}&s=[customer_type_short]">[customer_type_long]</a>
[End Foreach]
    [If '[PADDING_DIRECTORY]/index' exists]
        Set PADDING = File contents of '[PADDING_DIRECTORY]/index'
    [Else]
        Print 'Unable to locate padding file.'
    [End If]
    Return Standard Page Template

1.2.4 Pseudocode for search page

Sample request: GET /ecommerce/search.php?c=ARS06&kw=5+GHz+desktops&seg=all
    [Check for GET variables: 'c', 'seg', 'kw']
    Set SEARCH_RESULTS_ARRAY = [BESIM query with REQUEST = '1&{QUERYSTRING['seg']}&{QUERYSTRING['kw']}']
    Set TOTAL_RESULTS = [# SEARCH_RESULTS_ARRAY entries]
    Set TITLE = 'Search Results'
    Set BODY = 
    <h3>Your search returned <em>[TOTAL_RESULTS]</em> results</h3>
    <table>
  [If SEARCH_RESULTS_ARRAY contains entries:]
    [Foreach line in SEARCH_RESULTS_ARRAY]
        <tr>
            <td colspan="2"><h4>{line[CATEGORY]} results</h4></td></tr>
        <tr>
            <td><a href="{line[URL]}">{line[PRODUCT]}</a></td>
            <td>{line[DESCRIPTION]}</td></tr>
    [End Foreach]
  [Else]
        <tr>
            <td>Your search returned no results.</td></tr>
  [End If]
    </table>
    
    <form action="search.php" method="GET">
        <input type="hidden" name="c" value="{QUERYSTRING['c']}">
        <h3>New search</h3>
        <select name="seg">
	        <option value="all">Search entire site</option>
	        <option value="products">Products</option>
	        <option value="services">Services</option>
	        <option value="techsupport">Technical Support</option>
	        <option value="accessories">Accessories</option></select>   
        <input name="kw" type="text" value="" size="30">
        <input type="submit" value="Search"></form>
    <a href="index.php?c={QUERYSTRING['c']}">Home page</a>

<ul>
    [Foreach line in PRODUCT_LISTING_ARRAY]
<li><a href="product.php?id={line[ID]}">{line[NAME]}</a></li>
    [End Foreach]
</ul>
    [If '[PADDING_DIRECTORY]/catalog' exists]
        Set PADDING = File contents of '[PADDING_DIRECTORY]/catalog'
    [Else]
        Print 'Unable to locate padding file.'
    [End If]
    Return Standard Page Template

1.2.5 Pseudocode for browse page

Sample request: GET /ecommerce/browse.php?c=INR72&s=mlb
    Set TITLE = 'Browse Page'
    [Check for GET variables: 'c', 's']
    Set PRODUCTS_ARRAY = [BESIM query with REQUEST = '2&{QUERYSTRING['s']}']
    Set BODY = 
    <h3>Choose a product for <em>{customer_type{QUERYSTRING['s']}}</em></h3>
    <ul>
    [Foreach line in PRODUCTS_ARRAY]
        <li><a href="browse_productline.php?c={QUERYSTRING['c']}&s={QUERYSTRING['s']} \
&p={line}">{line}</a></li>
    [End Foreach]
    </ul>
    <a href="index.php?c={QUERYSTRING['c']}">Home Page</a>

    [If '[PADDING_DIRECTORY]/browse' exists]
        Set PADDING = File contents of '[PADDING_DIRECTORY]/browse'
    [Else]
        Print 'Unable to locate padding file.'
    [End If]
    Return Standard Page Template

1.2.6 Pseudocode for browse_productline page

Sample request: GET /ecommerce/browse_productline.php?c=INR72&s=mlb&p=CD-ROMs74
    Set TITLE = 'Browse Product Line'
    [Check for GET variables: 's', 'p']
    Set PRODUCT_MODELS_ARRAY = [BESIM query with REQUEST = '3&{QUERYSTRING['c']}&{QUERYSTRING['s']}&{QUERYSTRING['p']}']
    Set BODY = 
    [Foreach product in PRODUCT_MODELS_ARRAY]
    <div class="miniProduct">
       <h3>{product[ID]}</h3>
            <ul>
		<li>{product[Feature0]}</li>
		<li>{product[Feature1]}</li>
                ...
		<li>{product[FeatureN]}</li>
            </ul>
            <a href="productdetail.php?c={QUERYSTRING['c']}&s={QUERYSTRING['s']}&i={product[ID]}">More Details</a>
    </div>
    [End Foreach]
    <p>Back to:
        <a href="index.php?c={QUERYSTRING['c']}">Home page</a>
        <a href="browse.php?c={QUERYSTRING['c']}&s={QUERYSTRING['s']}">{customer_type{QUERYSTRING['s']}}</a></p>
    [If '[PADDING_DIRECTORY]/browse_productline' exists]
        Set PADDING = File contents of '[PADDING_DIRECTORY]/browse_productline'
    [Else]
        Print 'Unable to locate padding file.'
    [End If]
    Return Standard Page Template

1.2.7 Pseudocode for productdetail page

Sample request: GET /ecommerce/productdetail.php?c=CAD01&s=smb&i=Networks01
    Set TITLE = 'Product Details'
    [Check for GET variables: 'c', 's', 'i']
    Set PRODUCT_DETAILS_ARRAY = [BESIM query with REQUEST = '4&{QUERYSTRING['c']}&{QUERYSTRING['s']}&{QUERYSTRING['i']}']
    Set BODY = 
    <h3>Product detail for <em>{QUERYSTRING['i']}</em>:</h3>
    <ul>
    [Foreach productdetail in PRODUCT_DETAILS_ARRAY]
        <li>{productdetail}</li>
    [End Foreach]
    </ul>
    <a href="customize.php?c={QUERYSTRING['c']}&s={QUERYSTRING['s']}&i={QUERYSTRING['i']}">Customize It</a>

    <p>Back to:
        <a href="index.php?c={QUERYSTRING['c']}">Home page</a>
        <a href="browse.php?c={QUERYSTRING['c']}&s={QUERYSTRING['s']}">{customer_type{QUERYSTRING['s']}}</a></p>
    [If '[PADDING_DIRECTORY]/productdetail' exists]
        Set PADDING = File contents of '[PADDING_DIRECTORY]/productdetail'
    [Else]
        Print 'Unable to locate padding file.'
    [End If]
    Return Standard Page Template

1.2.8 Pseudocode for customize page

Sample requests:
    Set TITLE = 'Customize Product'
    [Check for GET variables: 'c', 's', 'i']
    [If {SESSION_ARRAY['page']} not set]
      Set {SESSION_ARRAY['page']} = 1
      Set {SESSION_ARRAY['backend_price']} = 0.00
    [End If]
    [If {QUERYSTRING['page']} is set]
      Set {SESSION_ARRAY['page']} = {QUERYSTRING['page']}
    [End If]

    [If {POST_DATA['customize_submit']} is set]

        [Foreach POST_DATA name/value pair]
            [Store POSTed customizations in SESSION_ARRAY]
        [End Foreach]

        Set BACKEND_PRICE_ARRAY = [BESIM query with REQUEST = '6&{QUERYSTRING['i']}&' + [POST_DATA values, separated by '&']]
        Set {SESSION_ARRAY['backend_price']} = BACKEND_PRICE_ARRAY['price']
        Set {SESSION_ARRAY['backend_currency']} = BACKEND_PRICE_ARRAY['currency']

        [If {POST_DATA['customize_submit'] == "Continue"]
            [If {SESSION_ARRAY['page']} < 3]
                 {SESSION_ARRAY['page']} += 1;
        [Else If {POST_DATA['customize_submit'] == "AddtoCart"]
            Delete {SESSION_ARRAY['page']}
            Redirect to Cart page with QUERYSTRING intact
        [End If]

    [End If]
    Set CONFIG_CHOICES_ARRAY = [BESIM query with REQUEST = '5&{QUERYSTRING['s']}&{QUERYSTRING['i']}&{SESSION_ARRAY['page']}']
    Set TOTAL_PRICE = {SESSION_ARRAY['backend_price']}

    [Foreach config_choice in CONFIG_CHOICES_ARRAY]
        [If POST_DATA{config_choice[ComponentType]} not set]
            Set POST_DATA{config_choice[ComponentType]} = config_choice[ComponentID]
        [End If]
        [If POST_DATA{config_choice[ComponentType]} == config_choice[ComponentID] ]
            TOTAL_PRICE += config_choice[Price]
        [End If]


    [End Foreach]
    Set BODY = 
    <h2>Configuration options for {QUERYSTRING['i']}:</h2>
    <form action="[CURRENT_PAGE_FILENAME]?{QUERYSTRING}" method="POST">
       [Foreach ComponentType in CONFIG_CHOICES_ARRAY]
        <h3>[ComponentType] configuration options</h3>
         [Foreach config_choice in CONFIG_CHOICES_ARRAY]
          <input type="radio" name="[ComponentType]" value="{config_choice[ComponentID]}"
          [If POST_DATA{config_choice[ComponentType]} == config_choice[ComponentID] ]
            <input type="radio" name="[ComponentType]" value="{config_choice[ComponentID]}" checked>
          [Else
            <input type="radio" name="[ComponentType]" value="{config_choice[ComponentID]}">
          [End If]
          {config_choice[ComponentName]} [{config_choice[ComponentPrice]} {config_choice[Currency]}]
          <br />
         [End Foreach]
       [End Foreach]
        <input type="submit" name="customize_submit" value="Update">
       [If {SESSION_ARRAY['page']} == 3]
        <input type="submit" name="customize_submit" value="AddtoCart">
       [Else]
        <input type="submit" name="customize_submit" value="Continue">
       [End If]
        <br />
        Total price: [TOTAL_PRICE] {SESSION_ARRAY['backend_currency']}
    </form>

    <p>Back to:
        <a href="index.php?c={QUERYSTRING['c']}">Home page</a>
        <a href="browse.php?c={QUERYSTRING['c']}&s={QUERYSTRING['s']}">{customer_type{QUERYSTRING['s']}}</a></p>
    [If '[PADDING_DIRECTORY]/customize' exists]
        Set PADDING = File contents of '[PADDING_DIRECTORY]/customize
    [Else]
        Print 'Unable to locate padding file.'
    [End If]
    Return Standard Page Template

1.2.9 Pseudocode for cart page

Sample requests:
 
    [If SESSION_ARRAY not set]
       Return Error Page with message = 'Session does not exist'
    [End If]
    Set TITLE = 'Your Cart'
    [Check for GET variables: 'c', 's']
    [If {QUERYSTRING['i']} is set]
       item = QUERYSTRING['i']
       [If {SESSION_ARRAY['cart'][item]} is not set]
           {SESSION_ARRAY['cart'][item]} = 1;
       [Else]
           {SESSION_ARRAY['cart'][item]} += 1;
       [End If]
    [Else if POST_DATA['cart_submit'] is set]
       [Foreach POST_DATA name/value pair as item, quantity]
           {SESSION_ARRAY['cart'][item]} = quantity
           [If quantity < 1]
              Delete {SESSION_ARRAY['cart'][item]}
           [End If]
       [End Foreach]
       [If POST_DATA['cart_submit'] == 'checkout']
           Redirect to SSL Login page with QUERYSTRING, and "&action=checkout" appended
       [Else if POST_DATA['cart_submit'] == 'SaveCart']
           [If {SESSION_ARRAY['email']} is set]
              Redirect to Cart page with QUERYSTRING, and "&action=SaveCart" appended
           [Else]
              Redirect to SSL Login page with QUERYSTRING, and "&action=SaveCart" appended
           [End If]
       [End If]
     [End If]

     [If QUERYSTRING['action'] is set to 'SaveCart']
          REQUEST = '9&{SESSION_ARRAY['email']}&' + [# items in {SESSION_ARRAY['cart']}]'
          [Foreach item, quantity in {SESSION_ARRAY['cart']}]
             REQUEST += '&' + item + '&' + quantity + '&' + [# of components]
             [Foreach component in {SESSION_ARRAY[item]}]
                 REQUEST += '&' + component
             [End Foreach]
          [End Foreach]
          Set savecart_confirmation = [BESIM query with REQUEST]
          [If savecart_confirmation is set, and is > 0]
             Report "Cart Saved", Errorlevel = 'info'
          [Else]
             Report "Problem saving cart.", Errorlevel = 'warning'
          [End If]
      [End If]

      Set TOTAL_CART_PRICE = 0
      [Foreach item,quantity in {SESSION_ARRAY['cart']}]
         [If {SESSION_ARRAY['price'][item]} not set]
            REQUEST = '6&' + item
            [Foreach component in {SESSION_ARRAY['item']}]
                REQUEST += '&' + component
            [End Foreach]
            Set item_price = [BESIM query with REQUEST]
            {SESSION_ARRAY['price'][item]} = item_price
         [End If]
         {SESSION_ARRAY['total_price'][item] = {SESSION_ARRAY['price'][item]} * quantity (note: format to two decimal places)
         Set TOTAL_CART_PRICE += {SESSION_ARRAY['total_price'][item]}  (note: format to two decimal places)

    Set BODY = 
    <form action="[Current Page]?c={QUERYSTRING['c']}&s={QUERYSTRING['s']}" method="POST">
        <table id="cart">
            <tr>
                <th>Item</th>
                <th>Customizations</th>
                <th>Quantity</th>
                <th>Unit Price</th>
                <th>Total</th></tr>
            [Foreach item in {SESSION_ARRAY['cart']}
            <tr>
                <td>[item.name]</td>
                <td>
                  [Foreach component in {SESSION_ARRAY['item']}]
                     [component.type]: [component.selection]<br />
                  [End Foreach]
                </td>
                <td><input type="text" name="[item.name]" value="[item.quantity]" size=4></td>
                <td>${SESSION_ARRAY['price'][item]}</td>
                <td>${SESSION_ARRAY['total_price'][item]}</td></tr>
            [End Foreach]
            <tr>
                <td id="totalLabel" colspan=4>Total:</td>
                <td>$[TOTAL_CART_PRICE]</td></tr>
            <tr>
                <td colspan="5" class="buttonPanel"><input type="submit" name="cart_submit" value="Update">
                <input type="submit" name="cart_submit" value="SaveCart">
                <input type="submit" name="cart_submit" value="checkout"></td></tr>
        </table>
    </form>

    <p>Back to:
        <a href="index.php?c={QUERYSTRING['c']}">Home page</a>
        <a href="browse.php?c={QUERYSTRING['c']}&s={QUERYSTRING['s']}">{customer_type{QUERYSTRING['s']}}</a></p>
    [If '[PADDING_DIRECTORY]/cart' exists]
        Set PADDING = File contents of '[PADDING_DIRECTORY]/cart
    [Else]
        Print 'Unable to locate padding file.'
    [End If]
    Return Standard Page Template

1.2.10 Pseudocode for login page (SSL)

Sample requests:
    [If SESSION_ARRAY not set]
       Return Error Page with message = 'Session does not exist'
    [End If]
    Set TITLE = 'Login Page'
    [Check for GET variables: 'c', 's']

    [If POST_DATA['login_submit'] is set]
       [If POST_DATA['email'] or POST_DATA['password'] is empty]
           Report "Incorrect email/password pair", Errorlevel = 'warning'
       [Else]
          Set submitted_password = [MD5 hash of POST_DATA['password']]
          Set stored_password = [BESIM query with REQUEST = '7&' + POST_DATA['email']]
          [If submitted_password == stored_password]
              {SESSION_ARRAY['email']} = POST_DATA['email'] 
          [Else]
              Report "Incorrect email/password pair", Errorlevel = 'warning'
          [End If]
       [End If]
    [Else If POST_DATA['register_submit'] is set]
       [Foreach field in POST_DATA['email', 'email2', 'password', 'password2', 'fname', 'lname']]
           [If field is empty]
              Report "[field] is a required field.", Errorlevel = 'warning'
           [End If]
       [End Foreach]

       [If POST_DATA['email'] does not match regular expression:
           /^([a-zA-Z0-9_\-\.]+)@((([0-9]{1,3}\.){3}[0-9]{1,3})|([a-zA-Z]+\.)+[a-zA-Z]{2,4})/ ]
            Report "The email field is invalid.", Errorlevel = 'warning'
       [Else If POST_DATA['email'] not equal to POST_DATA['email2'] ]
            Report "The email field do not match.", Errorlevel = 'warning'
       [End If]

       [If POST_DATA['password'] not equal to POST_DATA['password2'] ]
            Report "The passwords fields do not match.", Errorlevel = 'warning'
       [Else If POST_DATA['email'] not equal to POST_DATA['email2'] ]
            Report "The email field do not match.", Errorlevel = 'warning'
       [End If]

       [If no errors encountered]
           confirmation_number = [BESIM query with REQUEST = '8&' + POST_DATA['fname'] + '&' + POST_DATA['lname'] + '&' \
                                 POST_DATA['email'] + '&' + POST_DATA['password']]
           {SESSION_ARRAY['user_registration_confirmation']} = confirmation_number
           {SESSION_ARRAY['email']} = POST_DATA['email']
       [End If]

       [If {SESSION_ARRAY['email']} is set]
           [If {QUERYSTRING['action']} == "SaveCart"]
               Redirect to Cart Page with QUERYSTRING intact
           [Else]
               Redirect to Shipping Page (SSL)
           [End If]
       [End If]
    Set BODY = 
    <h3>Existing users sign in here</h3>
    <form action="[Current Page Name]?[QUERYSTRING]" method="POST">
        <table>
            <tr>
                <td>E-mail</td>
                <td><input type="text" name="email"></td></tr>
            <tr>
                <td>Password</td>
                <td><input type="password" name="password"></td></tr>
            <tr>
                <td colspan="2" class="buttonPanel"><input type="submit" name="login_submit" value="Login"></tr>
        </table>
    </form>

    <h3>New Users sign up here</h3>
    <form action="[Current Page Name]?[QUERYSTRING]" method="POST">
        <table>
            <tr>
                <td>First Name</td>
                <td><input type="text" name="fname" value="{POSTDATA['fname']}"></td></tr>
            <tr>
                <td>Last Name</td>
                <td><input type="text" name="lname" value="{POSTDATA['lname']}"></td></tr>
            <tr>
                <td>E-mail</td>
                <td><input type="text" name="email" value="{POSTDATA['email']}"></td></tr>
            <tr>
                <td>Confirm E-mail</td>
                <td><input type="text" name="email2" value="{POSTDATA['email2']}"></td></tr>
            <tr>
                <td>Password</td>
                <td><input type="password" name="password"></td></tr>
            <tr>
                <td>Confirm Password</td>
                <td><input type="password" name="password2"</td></tr>
            <tr>
                <td colspan="2" class="buttonPanel"><input type="submit" name="register_submit" value="Register"></tr>
        </table>
    </form>

    <p>Back to:
        <a href="index.php?c={QUERYSTRING['c']}">Home page</a>
        <a href="browse.php?c={QUERYSTRING['c']}&s={QUERYSTRING['s']}">{customer_type{QUERYSTRING['s']}}</a></p>
    [If '[PADDING_DIRECTORY]/login' exists]
        Set PADDING = File contents of '[PADDING_DIRECTORY]/login
    [Else]
        Print 'Unable to locate padding file.'
    [End If]
    Return Standard Page Template

1.2.11 Pseudocode for shipping page (SSL)

Sample request:
POST /ecommerce/shipping.php?c=CAD01&s=mlb&action=checkout HTTP/1.1
Content-Length: 125

fname=John&lname=Doe&address=Birch+Ln&city=Easton&state=OH&zip=14112&phone=223-334-4456&shipping=Two_Day&ship_submit=Continue
(NOTE: shipping = Next_Day|Two_Day|Five_Day)
    [If SESSION_ARRAY not set]
       Return Error Page with message = 'Session does not exist'
    [End If]
    Set TITLE = 'Shipping Details'
    [Check for GET variables: 'c', 's']

    [If {SESSION_ARRAY['email']} not set]
        Report "User is not logged in", Errorlevel = 'error'
    [End If]

    [If POST_DATA['ship_submit'] is set]
       [Foreach field in POST_DATA['fname', 'lname', 'address', 'city', 'shipping', 'state', 'zip', 'shipping']]
           [If field is empty]
              Report "[field] is a required field.", Errorlevel = 'warning'
           [End If]
       [End Foreach]

       [If POST_DATA['state'] does not match regular expression: /[a-zA-Z]{2}/ ]
            Report "State field is invalid.", Errorlevel = 'warning'
       [End If]

       [If POST_DATA['zip'] does not match regular expression: /(\d{5}-\d{4}|\d{5})/ ]
            Report "Zip field is invalid.", Errorlevel = 'warning'
       [End If]

       [If POST_DATA['phone'] does not match regular expression: /\d{3}-\d{3}-\d{4}/ ]
            Report "Phone field is invalid.", Errorlevel = 'warning'
       [End If]

       [If no errors encountered]
           [Foreach name, value pair in POST_DATA]
               Store name, value in SESSION_ARRAY (i.e. SESSION_ARRAY['shipping'])
           [End Foreach]
               Redirect to Billing Page (SSL) with QUERYSTRING intact
       [End If]

    Set BODY = 
    <h3>Please enter your shipping details (all fields required)</h3>
    <form action="[Current Page Name]?[QUERYSTRING]" method="POST">
        <table>
            <tr>
                <td>First name</td>
                <td><input type="text" name="fname" value="{POSTDATA['fname']}"></td></tr>
            <tr>
                <td>Last name</td>
                <td><input type="text" name="lname" value="{POSTDATA['lname']}"></td></tr>
            <tr>
                <td>Address</td>
                <td><input type="text" name="address" value="{POSTDATA['address']}"></td></tr>
            <tr>
                <td>City</td>
                <td><input type="text" name="city" value="{POSTDATA['city']}"></td></tr>
            <tr>
                <td>State</td>
                <td><input type="text" name="state" size="2" maxlength="2" value="{POSTDATA['state']}"></td></tr>
            <tr>
                <td>Zip (nnnnn)</td>
                <td><input type="text" name="zip" size="5" maxlength="5" value="{POSTDATA['zip']}"></td></tr>
            <tr>
                <td>Phone (nnn-nnn-nnnn)</td>
                <td><input type="text" name="phone" value="{POSTDATA['phone']}"></td></tr>
            <tr>
                <td colspan="2">Shipping method</td></tr>
            <tr>
          [If {POSTDATA['shipping']} == "Next_Day"]
                <td colspan="2"><input type="radio" name="shipping" value="Next_Day" checked>Next Day</td></tr>
          [Else]
                <td colspan="2"><input type="radio" name="shipping" value="Next_Day">Next Day</td></tr>
          [End If]
            <tr>
          [If {POSTDATA['shipping']} == "Two_Day"]
                <td colspan="2"><input type="radio" name="shipping" value="Two_Day" checked>2nd Business Day</td></tr>
          [Else]
                <td colspan="2"><input type="radio" name="shipping" value="Two_Day">2nd Business Day</td></tr>
          [End If]
            <tr>
          [If {POSTDATA['shipping']} == "Five_Day"]
                <td colspan="2"><input type="radio" name="shipping" value="Five_Day" checked>3-5 day Ground</td></tr>
          [Else]
                <td colspan="2"><input type="radio" name="shipping" value="Five_Day">3-5 day Ground</td></tr>
          [End If]
            <tr>
                <td align="center" colspan="2"><input type="submit" name="ship_submit" value="Continue"></td></tr>
        </table>
    </form>
    <p>Back to:
        <a href="index.php?c={QUERYSTRING['c']}">Home page</a>
        <a href="browse.php?c={QUERYSTRING['c']}&s={QUERYSTRING['s']}">{customer_type{QUERYSTRING['s']}}</a></p>
    [If '[PADDING_DIRECTORY]/shipping' exists]
        Set PADDING = File contents of '[PADDING_DIRECTORY]/shipping
    [Else]
        Print 'Unable to locate padding file.'
    [End If]
    Return Standard Page Template

1.2.12 Pseudocode for billing page (SSL)

Sample request:
POST /ecommerce/billing.php?c=CAD01&s=mlb&action=checkout HTTP/1.1
Content-Length: 178

fname=John&lname=Doe&address=Aspen+Rd&city=Northford&state=PA&zip=01812&phone=123-234-3456&cc_type=Visa&cc_num=9841499563221977&cc_expmonth=2004&cc_expyear=8&bill_submit=Continue
(NOTE: cc_type = Visa|Mastercard|Amex)

    [If SESSION_ARRAY not set]
       Return Error Page with message = 'Session does not exist'
    [End If]
    Set TITLE = 'Billing Details'
    [Check for GET variables: 'c', 's']

    [If {SESSION_ARRAY['email']} not set]
        Report "User is not logged in", Errorlevel = 'error'
    [End If]

    [If POST_DATA['bill_submit'] is set]
       [Foreach field in POST_DATA['fname', 'lname', 'address', 'city', 'cc_type', 'state', \
                                   'zip', 'cc_num', 'phone', 'cc_expmonth', 'cc_expyear']]
           [If field is empty]
              Report "[field] is a required field.", Errorlevel = 'warning'
           [End If]
       [End Foreach]

       [If POST_DATA['state'] does not match regular expression: /[a-zA-Z]{2}/ ]
            Report "State field is invalid.", Errorlevel = 'warning'
       [End If]

       [If POST_DATA['zip'] does not match regular expression: /(\d{5}-\d{4}|\d{5})/ ]
            Report "Zip field is invalid.", Errorlevel = 'warning'
       [End If]

       [If POST_DATA['cc_num'] does not match regular expression: /\d{16}/ ]
            Report "Credit card field is invalid.", Errorlevel = 'warning'
       [End If]

       [If POST_DATA['phone'] does not match regular expression: /\d{3}-\d{3}-\d{4}/ ]
            Report "Phone field is invalid.", Errorlevel = 'warning'
       [End If]

       [If no errors encountered]
           [Foreach name, value pair in POST_DATA]
               Store name, value in SESSION_ARRAY (i.e. SESSION_ARRAY['billing'])
           [End Foreach]
               Redirect to Confirmation Page (SSL) with QUERYSTRING intact
       [End If]

    Set BODY = 
    <h3>Please enter your billing details (all fields required)</h3>
    <form action="billing.php?{QUERYSTRING}" method="POST">
        <table>
            <tr>
                <th colspan="2">Billing information</th></tr>
            <tr>
                <td>First name</td>
                <td><input type="text" name="fname" value="{POSTDATA['fname']}"></td></tr>
            <tr>
                <td>Last name</td>
                <td><input type="text" name="lname" value="{POSTDATA['lname']}"></td></tr>
            <tr>
                <td>Address</td>
                <td><input type="text" name="address" value="{POSTDATA['address']}"></td></tr>
            <tr>
                <td>City</td>
                <td><input type="text" name="city" value="{POSTDATA['city']}"></td></tr>
            <tr>
                <td>State</td>
                <td><input type="text" name="state" size="2" maxlength="2" value="{POSTDATA['state']}"></td></tr>
            <tr>
                <td>Zip (nnnnn)</td>
                <td><input type="text" name="zip" size="5" maxlength="5" value="{POSTDATA['zip']}"></td></tr>
            <tr>
                <td>Phone (nnn-nnn-nnnn)</td>
                <td><input type="text" name="phone" value="{POSTDATA['phone']}"></td></tr>     
            <tr>
                <th colspan="2">Credit Card information</th></tr>
            <tr>
                <td>Card type</td>
                <td>    
                    <select name="cc_type">
                        <option value="">Select Card Type
                        <option value="Visa">Visa
                        <option value="Mastercard">Mastercard
                        <option value="Amex">Amex</select></td></tr>
            <tr>
                <td>Card number (16 digits)</td>
                <td><input type="text" name="cc_num" value="{POSTDATA['cc_num']}"></td></tr>
            <tr>
                <td>Expiration date</td>
                <td>
                    <select name="cc_expmonth">
                        <OPTION VALUE="">Month
                        <OPTION VALUE="1">Jan<OPTION VALUE="2">Feb<OPTION VALUE="3">Mar<OPTION VALUE="4">Apr
                        <OPTION VALUE="5">May<OPTION VALUE="6">Jun<OPTION VALUE="7">Jul<OPTION VALUE="8">Aug
                        <OPTION VALUE="9">Sep<OPTION VALUE="10">Oct<OPTION VALUE="11">Nov<OPTION VALUE="12">Dec</select>
                    <select name="cc_expyear">
                        <option value="">Year
                        <option value="2004">2004<option value="2005">2005
                        <option value="2006">2006<option value="2007">2007
                        <option value="2008">2008<option value="2009">2009
                        <option value="2010">2010</select></td></tr>
            <tr>
                <td align="center" colspan="2">
                    <input type="submit" name="bill_submit" value="Continue"></td></tr>
        </table>
    </form>

    <p>Back to:
        <a href="index.php?c={QUERYSTRING['c']}">Home page</a>
        <a href="browse.php?c={QUERYSTRING['c']}&s={QUERYSTRING['s']}">{customer_type{QUERYSTRING['s']}}</a></p>
    [If '[PADDING_DIRECTORY]/billing' exists]
        Set PADDING = File contents of '[PADDING_DIRECTORY]/billing
    [Else]
        Report 'Unable to locate padding file.', Errorlevel = 'error'
    [End If]
    Return Standard Page Template

1.2.13 Pseudocode for confirmation page (SSL)

Sample request:
POST /ecommerce/confirm.php?c=CAD01&s=mlb&action=checkout HTTP/1.1
Content-Length: 22

confirm_submit=Confirm

    [If SESSION_ARRAY not set]
       Return Error Page with message = 'Session does not exist'
    [End If]

    [If any of following SESSION_ARRAY variables is not set: email, billing, shipping, cart]
       Report "Missing session variables.", Errorlevel = 'error'
    [End If]

    [If number of items in {SESSION_ARRAY['cart']} < 1]
       Report "Cart is empty", Errorlevel = 'error'
    [End If]

    [Check for GET variables: 'c', 's']

    Set TOTAL_PRICE = 0
    [Foreach item, quantity in {SESSION_ARRAY['cart']}]
        TOTAL_PRICE += quantity * {SESSION_ARRAY['price'][item]}
    [End Foreach]
    Format TOTAL_PRICE to 2 decimal places

    [If POST_DATA['confirm_submit'] is set]
       Set REQUEST = '10&' . {SESSION_ARRAY['email']}
       [Foreach shipping_information in {SESSION_ARRAY['shipping']}]
          Set REQUEST += '&' + shipping_information
       [End Foreach]
       [Foreach billing_information in {SESSION_ARRAY['billing']}]
          Set REQUEST += '&' + billing_information
       [End Foreach]
       Set REQUEST += '&' + [# items in {SESSION_ARRAY['cart']}]
       [Foreach item, quantity in {SESSION_ARRAY['cart']}]
          Set REQUEST += '&' + item + '&' + quantity + '&' + [# components in SESSION_ARRAY[item]]
          [Foreach component in SESSION_ARRAY[item]]
              Set REQUEST += '&' + component
          [End Foreach]
       [End Foreach]
       Set CONFIRMATION_ARRAY = [BESIM query with request = REQUEST]
       Set SHIP_DATE = {CONFIRMATION_ARRAY[ship_date]}
       Set CONFIRMATION_NUM = {CONFIRMATION_ARRAY[confirmation_num]}
       Set TITLE = 'Order Processed'
    [Else]
       Set TITLE = 'Verify Order'
    [End If]
   

    Set BODY = 
    <h3>Cart</h3>
    <table id="cart">
        <tr>
            <th>Item</th>
            <th>Customizations</th>
            <th>Quantity</th>
            <th>Unit Price</th>
            <th>Total</th></tr>
        [Foreach item in {SESSION_ARRAY['cart']}]
            <td>[item.name]</td>
            <td>
            [Foreach component_type, component_selected in {SESSION_ARRAY[item]}
              [component_type]: [component_selected]<br />
            [End Foreach]
            </td>
            <td>[item.quantity]</td>
            <td>{SESSION_ARRAY['price'][item]}</td>
            <td>{SESSION_ARRAY['total_price'][item]}</td></tr>
        [End Foreach]
        <tr>
            <td id="totalLabel" colspan=4>Total:</td>
            <td>$[TOTAL_PRICE]</td></tr>
    </table>
    <h3>Shipping Information</h3>
    <table>
        <tr>
            <th>Name</th>
            <th>Address</th>
            <th>City</th>
            <th>State</th>
            <th>Zip</th>
            <th>Phone</th>
            <th>Shipping</th>
        </tr>
        <tr>
            <td>{SESSION_ARRAY['shipping']['fname']} {SESSION_ARRAY['shipping']['lname']}</td>
            <td>{SESSION_ARRAY['shipping']['address']}</td>
            <td>{SESSION_ARRAY['shipping']['city']}</td>
            <td>{SESSION_ARRAY['shipping']['state']}</td>
            <td>{SESSION_ARRAY['shipping']['zip']}</td>
            <td>{SESSION_ARRAY['shipping']['phone']}</td>
            <td>{SESSION_ARRAY['shipping']['shipping']}</td>
        </tr></table>
    <h3>Billing Information</h3>
    <table>
        <tr>
            <th>Name</th>
            <th>Address</th>
            <th>Address</th>
            <th>City</th>
            <th>State</th>
            <th>Zip</th>
            <th>Phone</th>
            <th>Credit Card</th>
        </tr>
        <tr>
            <td>{SESSION_ARRAY['billing']['fname']} {SESSION_ARRAY['billing']['lname']}</td>
            <td>{SESSION_ARRAY['billing']['address']}</td>
            <td>{SESSION_ARRAY['billing']['city']}</td>
            <td>{SESSION_ARRAY['billing']['state']}</td>
            <td>{SESSION_ARRAY['billing']['zip']}</td>
            <td>{SESSION_ARRAY['billing']['phone']}</td>
            <td>{SESSION_ARRAY['billing']['cc_type']} <br />
            Expires: {SESSION_ARRAY['billing']['cc_expmonth']}/{SESSION_ARRAY['billing']['cc_expyear']}</td>
        </tr></table>
  [If POST_DATA['confirm_submit'] is set]
    <h3>Order Confirmed</h3>
    <table>
        <tr>
            <td>Ship Date</td>
            <td>[SHIP_DATE]</td></tr>
        <tr>
            <td>Confirmation Num</td>
            <td>[CONFIRMATION_NUM]</td></tr>
    </table>
  [Else]
        Please review your order above then click Confirm.
        <form action="[Current Page Name]?[QUERYSTRING]" method="POST">
            <input type="submit" name="confirm_submit" value="Confirm"></form>
  [End If]

    <p>Back to:
        <a href="index.php?c={QUERYSTRING['c']}">Home page</a>
        <a href="browse.php?c={QUERYSTRING['c']}&s={QUERYSTRING['s']}">{customer_type{QUERYSTRING['s']}}</a></p>
    [If POST_DATA['confirm_submit'] is set]
        Delete SESSION_ARRAY
    [End If]

    [If '[PADDING_DIRECTORY]/confirm' exists]
        Set PADDING = File contents of '[PADDING_DIRECTORY]/confirm
    [Else]
        Report 'Unable to locate padding file.', Errorlevel = 'error'
    [End If]
    Return Standard Page Template

Copyright © 2005-2010 Standard Performance Evaluation Corporation.  All rights reserved.