Author Topic: CGI Programming II  (Read 55509 times)

Support

  • Administrator
  • *****
  • Posts: 19
    • View Profile
CGI Programming II
« on: October 08, 2009, 03:11:23 PM »
This thread is an attempt to introduce CGI programming using Basic as your server side CGI scripting language. The goal is to show how using Basic as your server side scripting language and interacting with the browser client via CGI and JavaScript can provide feature rich applications with desktop like  functionality. This tutorial will be Linux / Apache based.

Support

  • Administrator
  • *****
  • Posts: 19
    • View Profile
CGI Programming II - Hello World
« Reply #1 on: October 08, 2009, 03:12:51 PM »
When you enter a link in your browser address bar, the web server either loads a static html document and sends it verbatim to the browser or executes a CGI program to send the html to the browser.

Static HTML
Code: [Select]
<html>
<head>
<title>Hello World</title>
</head>
<body>
<h2>Hello world!</h2>
</body>
</html>

Perl Script
Code: [Select]
#!/usr/bin/perl -wT
print "Content-type: text/html\n\n";
print "<html><head><title>Hello World</title></head>\n";
print "<body>\n";
print "<h2>Hello world!</h2>\n";
print "</body></html>\n";

ScriptBasic Script
Code: [Select]
#!/usr/bin/scriba -c

INCLUDE cgi.bas

cgi::Header 200,"text/html"
cgi::FinishHeader

PRINT """<html>
<head>
<title>Hello World</title>
</head>
<body>
<h2>Hello world!</h2>
</body>
</html>
"""

The CGI program has the advantage of dynamically creating html content based on session variables, form data and database access. The next installment will show interaction with the browser client using a form to collect user input and pass that data to the CGI program to validate and process.

Support

  • Administrator
  • *****
  • Posts: 19
    • View Profile
CGI Programming II - Echo Example
« Reply #2 on: October 08, 2009, 03:14:30 PM »
CGI is not a language. It's a protocol that can be used to communicate between Web forms and your program. A CGI script can be written in any language that can read STDIN, write to STDOUT, and read environment variables.

The following echo CGI program is a great way to see what is happening between the browser and the web server when a page is submitted. There are two primary requests made to the server. The GET request is normally used for the initial page load of the document. The POST request works like the GET but also passes the <form> variables to your CGI program via STDIN. When your CGI program is called by the web server, the system environment variables are web server based and not the OS based variables you would find if running your program in a console. Your CGI program uses it's STDOUT (print) function to send the generated HTML to the browser. This is really CGI in a nutshell and what everything else is built on.

BCX Echo
Code: [Select]
DIM POST$

PRINT "Content-type: text/html"
PRINT ""
PRINT "<HTML>"
PRINT "<HEAD>"
PRINT "<TITLE>Echo CGI</TITLE>"
PRINT "</HEAD>"
PRINT "<BODY>"
PRINT "<H1>View CGI Parameters</H1>"
PRINT "This page shows the CGI parameters by submitting to itself."
PRINT "<PRE>"
PRINT ""
PRINT "CGI system variables"
PRINT "--------------------"
PRINT ""
PRINT "ServerSoftware  = ", ENVIRON$("SERVER_SOFTWARE")
PRINT "ServerName      = ", ENVIRON$("SERVER_NAME")
PRINT "GatewayInterface= ", ENVIRON$("GATEWAY_INTERFACE")
PRINT "ServerProtocol  = ", ENVIRON$("SERVER_PROTOCOL")
PRINT "ServerPort      = ", ENVIRON$("SERVER_PORT")
PRINT "RequestMethod   = ", ENVIRON$("REQUEST_METHOD")
PRINT "PathInfo        = ", ENVIRON$("PATH_INFO")
PRINT "PathTranslated  = ", ENVIRON$("PATH_TRANSLATED")
PRINT "ScriptName      = ", ENVIRON$("SCRIPT_NAME")
PRINT "GET QueryString = ", ENVIRON$("QUERY_STRING")
IF ENVIRON$("REQUEST_METHOD") = "POST" THEN
  INPUT POST$
ELSE
  POST$ = ""
END IF
PRINT "POST Form Data  = ", POST$
PRINT "RemoteHost      = ", ENVIRON$("REMOTE_HOST")
PRINT "RemoteAddress   = ", ENVIRON$("REMOTE_ADDR")
PRINT "AuthType        = ", ENVIRON$("AUTH_TYPE")
PRINT "RemoteUser      = ", ENVIRON$("REMOTE_USER")
PRINT "RemoteIdent     = ", ENVIRON$("REMOTE_IDENT")
PRINT "ContentType     = ", ENVIRON$("CONTENT_TYPE")
PRINT "ContentLength   = ", ENVIRON$("CONTENT_LENGTH")
PRINT "UserAgent       = ", ENVIRON$("HTTP_USER_AGENT")
PRINT "Cookie          = ", ENVIRON$("HTTP_COOKIE")
PRINT "Referer         = ", ENVIRON$("HTTP_REFERER")
PRINT "Password        = ", ENVIRON$("HTTP_PASSWORD")
PRINT "</PRE>"
PRINT "<TABLE><TR><TD BORDER=0 BGCOLOR='EEEEEE'><PRE>"
PRINT "A simple form to POST parameters:<BR>"
PRINT "<FORM METHOD='POST' ACTION='/cgi-bin/echo.cgi'>"
PRINT "<INPUT TYPE='TEXT' VALUE='DEFAULT TEXT' NAME='TEXT-FIELD'>"
PRINT "<INPUT TYPE='SUBMIT' NAME='SUBMIT-BUTTON' VALUE=' POST '>"
PRINT "</FORM></PRE></TD>"
PRINT "<TD BORDER=1 width='20'>&nbsp;</TD>"
PRINT "<TD BORDER=0 BGCOLOR='EEEEEE'><PRE>"
PRINT "A simple form to GET parameters:<BR>"
PRINT "<FORM METHOD='GET' ACTION='/cgi-bin/echo.cgi'>"
PRINT "<INPUT TYPE='TEXT' VALUE='DEFAULT TEXT' NAME='TEXT-FIELD'>"
PRINT "<INPUT TYPE='SUBMIT' NAME='SUBMIT-BUTTON' VALUE=' GET '>"
PRINT "</FORM></PRE></TD></TR></TABLE>"
PRINT "</BODY></HTML>"

ScriptBasic Echo
Code: [Select]
#! /usr/bin/scriba -c
global const nl = "\n"
Const NumberOfCookies = 3

include cgi.bas

option cgi$Method cgi::Get or cgi::Upload

' cgi::RequestBasicAuthentication "login password"
cgi::Header 200,"text/html"

'
' We are setting several cookies. The expire time is ten seconds so you can test that
' the cookies are being sent by the browser. Remeber, their only valid for 10 seconds so
' be quick with a submit
'
for i=1 to NumberOfCookies
  ' cookie(i) is i, no domain is defined, path is /, expires after 10 seconds, not secure
  cgi::SetCookie "cookie" & i,i,undef,"/",gmtime()+10,false
next i

cgi::FinishHeader

'-------------------------------------------------------
print """<HTML>
<HEAD>
<title>CGI parameter testing</title>
</HEAD>
<BODY><font face="VERDANA" size="2">
<H1>View CGI Parameters</H1>
This page shows the cgi parameters the way it was uploaded.
<!-- here is the result of the previous HTTP request -->
<FONT SIZE="3">
<PRE>

CGI system variables
--------------------

"""
'-------------------------------------------------------

print "ServerSoftware  = ",cgi::ServerSoftware(), nl
print "ServerName      = ",cgi::ServerName(), nl
print "GatewayInterface= ",cgi::GatewayInterface(),nl
print "ServerProtocol  = ",cgi::ServerProtocol(), nl
print "ServerPort      = ",cgi::ServerPort(), nl
print "RequestMethod   = ",cgi::RequestMethod(), nl
print "PathInfo        = ",cgi::PathInfo(), nl
print "PathTranslated  = ",cgi::PathTranslated(), nl
print "ScriptName      = ",cgi::ScriptName(), nl
print "QueryString     = ",cgi::QueryString(), nl
print "RemoteHost      = ",cgi::RemoteHost(), nl
print "RemoteAddress   = ",cgi::RemoteAddress(), nl
print "AuthType        = ",cgi::AuthType(), nl
print "RemoteUser      = ",cgi::RemoteUser(), nl
print "RemoteIdent     = ",cgi::RemoteIdent(), nl
print "ContentType     = ",cgi::ContentType(), nl
print "ContentLength   = ",cgi::ContentLength(), nl
print "UserAgent       = ",cgi::UserAgent(), nl
print "Cookie          = ",cgi::RawCookie(), nl

print "Referer         = ",cgi::Referer(),nl
print "Password        = ",Environ("HTTP_PASSWORD"),nl
print "Full auth string= ",Environ("HTTP_AUTHORIZATION"),nl
print "\nCookies:\n"
for i=1 to NumberOfCookies
  print "cookie" & i," ",cgi::Cookie("cookie" & i),"\n"
next i

print "Text field using Param(\"TEXT-FIELD\") is ",cgi::Param("TEXT-FIELD"),nl,nl


if cgi::RequestMethod() = "GET" then
  print "GET text field using GetParam(\"TEXT-FIELD\") is ",cgi::GetParam("TEXT-FIELD"),nl
end if

if cgi::RequestMethod() = "POST" then
  print "POST text field using PostParam(\"TEXT-FIELD\") is ",cgi::PostParam("TEXT-FIELD"),nl
  if cgi::ContentType() like "multipart*" then
    print "Original file name is ",cgi::FileName("FILE-UPLOAD-NAME"),nl
    if cgi::FileLength("FILE-UPLOAD-NAME") > 0 then
      print "File with a length of ",cgi::FileLength("FILE-UPLOAD-NAME")," bytes was saved\n"
      on error goto NoSave
      cgi::SaveFile "FILE-UPLOAD-NAME","/var/www/vhosts/scriptbasic.org/httpdocs/upload/newup.txt"
    else
      print "There is no uploaded file."
    end if
  end if
end if

print """</PRE><TABLE><TR><TD BORDER=0 BGCOLOR="EEEEEE"><PRE>
A simple form to POST parameters:<BR>
<FORM METHOD="POST" ACTION="/cgi-bin/echo.bas">
<INPUT TYPE="TEXT" VALUE="DEFAULT TEXT" NAME="TEXT-FIELD">
<INPUT TYPE="SUBMIT" NAME="SUBMIT-BUTTON" VALUE=" POST ">
</FORM>
</PRE></TD><TD BORDER=1 width="20">&nbsp;</TD><TD BORDER=0 BGCOLOR="EEEEEE"><PRE>
A simple form to GET parameters:<BR>
<FORM METHOD="GET" ACTION="/cgi-bin/echo.bas">
<INPUT TYPE="TEXT" VALUE="DEFAULT TEXT" NAME="TEXT-FIELD">
<INPUT TYPE="SUBMIT" NAME="SUBMIT-BUTTON" VALUE=" GET ">
</FORM>
</PRE></TD></TR></TABLE><PRE>
<hr>
A simple form to UPLOAD a file:<BR>
<FORM METHOD="POST" ACTION="/cgi-bin/echo.bas" ENCTYPE="multipart/form-data">
<INPUT TYPE="TEXT" VALUE="DEFAULT TEXT" NAME="TEXT-FIELD">
<INPUT TYPE="FILE" VALUE="FILE-UPLOAD-VALUE" NAME="FILE-UPLOAD-NAME">
<INPUT TYPE="SUBMIT" NAME="SUBMIT-BUTTON" VALUE="UPLOAD FILE">
</FORM>
<hr>
</BODY>
</HTML>
"""
stop
NoSave:

print "An error has happened saving the file. Code =",error(),nl

resume next

ScriptBasic CGI extension module documentation

Support

  • Administrator
  • *****
  • Posts: 19
    • View Profile
CGI Programming II - MySQL
« Reply #3 on: October 08, 2009, 03:16:09 PM »
Before we get too far down the road, I thought I would introduce database use within your CGI scripts. ScriptBasic uses it's associative array functionality with it's DB interface like PHP does with their MySQL interface.

Table Layout


PHP
Code: [Select]
<html>
<body>
<?
mysql_connect("localhost", "user", "password") or die(mysql_error());
mysql_select_db("dbname") or die(mysql_error());

$result = mysql_query("SELECT * FROM contact");
echo "<TABLE border=1 cellpadding=3>";
while($row = mysql_fetch_assoc($result)){
echo "<TR>",
"<TD>".$row['ID']."</TD>",
"<TD>".$row['NAME']."</TD>",
"<TD>".$row['ADDRESS']."</TD>",
"<TD>".$row['CITY']."</TD>",
"<TD>".$row['STATE']."</TD>",
"<TD>".$row['ZIP']."</TD>",
"<TD>".$row['PHONE']."</TD>",
"<TD>".$row['EMAIL']."</TD>",
"<TD>".$row['URL']."</TD>",
"</TR>";
}
echo "</table>";
?>
</body>
</html>

ScriptBasic
Code: [Select]
#!/usr/bin/scriba -c

INCLUDE cgi.bas
INCLUDE mysql.bas

OPTION cgi$Method cgi::Post or cgi::Get

dbh = mysql::RealConnect("localhost","user","password","dbname")

mysql::query(dbh,"SELECT * FROM contact")

cgi::Header 200,"text/html"
cgi::FinishHeader

PRINT """
<HTML>
<HEAD>
<title>mySQL testing</title>
</HEAD>
<BODY>
"""
PRINT """<FONT face="Verdana, Arial, Helvetica, sans-serif">"""

PRINT """<TABLE border="1" cellpadding="3">"""

WHILE mysql::FetchHash(dbh,column)

PRINT "<TR>"
PRINT "<TD>",column{"ID"},"</TD>"
PRINT "<TD>",column{"NAME"},"</TD>"
PRINT "<TD>",column{"ADDRESS"},"</TD>"
PRINT "<TD>",column{"CITY"},"</TD>"
PRINT "<TD>",column{"STATE"},"</TD>"
PRINT "<TD>",column{"ZIP"},"</TD>"
PRINT "<TD>",column{"PHONE"},"</TD>"
PRINT "<TD>",column{"EMAIL"},"</TD>"
PRINT "<TD>",column{"URL"},"</TD>"
PRINT "</TR>"

WEND

PRINT "</TABLE>"

PRINT "<BR>"
PRINT "The database handle is: <b>",dbh,"</b><BR>"
PRINT "Affected rows by SELECT: <b>",mysql::AffectedRows(dbh),"</b><BR>"
PRINT "Character set name is: <b>",mysql::CharacterSetName(dbh),"</b><BR>"
PRINT "Last error is: <b>",mysql::ErrorMessage(dbh),"</b><BR>"
PRINT "Client info is: <b>",mysql::GetClientInfo(),"</b><BR>"
PRINT "Host info is: <b>",mysql::GetHostInfo(dbh),"</b><BR>"
PRINT "Proto info is: <b>",mysql::GetProtoInfo(dbh),"</b><BR>"
PRINT "Server info is: <b>",mysql::GetServerInfo(dbh),"</b><BR>"
PRINT "PING result: <b>",mysql::Ping(dbh),"</b><BR>"
PRINT "Thread ID: <b>",mysql::ThreadId(dbh),"</b><BR>"
PRINT "Status is: <b>",mysql::Stat(dbh),"</b><BR>"

PRINT "</FONT>"

PRINT """
</BODY>
</HTML>
"""

mysql::Close(dbh)

END

ScriptBasic MySQL extension module documentation

Support

  • Administrator
  • *****
  • Posts: 19
    • View Profile
CGI Programming II - Client (browser) Scripting
« Reply #4 on: October 08, 2009, 03:18:15 PM »
Quote
JavaScript and Java

A common misconception is that JavaScript is similar or closely related to Java; this is not so. Both have a C-like syntax, are object-oriented, are typically sandboxed and are widely used in client-side Web applications, but the similarities end there. Java has static typing; JavaScript's typing is dynamic (meaning a variable can hold an object of any type and cannot be restricted). Java is loaded from compiled bytecode; JavaScript is loaded as human-readable code. C is their last common ancestor language.

Nonetheless, JavaScript was designed with Java's syntax and standard library in mind. In particular, all Java keywords are reserved in JavaScript, JavaScript's standard library follows Java's naming conventions, and JavaScript's Math and Date classes are based on those from Java 1.0.

I'm working on a ScriptBasic address book like example that will show using a hidden IFrame and AJAX (using Prototype) to submit requests to the server to allow browsing records without refreshing the page. The following article is from the Apple site back in 2002. (before everyone started touting AJAX as the answer to client/server web scripting)

Remote Scripting with IFRAME

Scripting Iframes - Tutorial and Examples

I thought I would post this example as a preface to how the upcoming address book example in ScriptBasic will work.

Code: [Select]
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
        "http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd">
<html><head><title>Remote Scripting with an IFrame - complexer client page</title>
<meta http-equiv="pragma" content="no-cache">
<script type="text/javascript">

var IFrameObj; // our IFrame object
function callToServer(theFormName) {
if (!document.createElement) {return true};
var IFrameDoc;

// We'll build our URL by checking which state
// has been selected in the drop down menu
var stateEl = document.forms[theFormName].state
var theState = stateEl.options[stateEl.selectedIndex].value
if (theState=='') {return false}; // no state has been selected
var URL = "http://developer.apple.com/internet/webcontent/states/"+theState+".html"

//provide a "loading" message
var responseMessage = document.getElementById('responseMessage');
responseMessage.style.display = 'inline';
responseMessage.innerHTML = 'loading data...';

if (!IFrameObj && document.createElement) {
// create the IFrame and assign a reference to the
// object to our global variable IFrameObj.
// this will only happen the first time
// callToServer() is called
try {
var tempIFrame=document.createElement('iframe');
tempIFrame.setAttribute('id','RSIFrame');
tempIFrame.style.border='0px';
tempIFrame.style.width='0px';
tempIFrame.style.height='0px';
IFrameObj = document.body.appendChild(tempIFrame);

if (document.frames) {
// this is for IE5 Mac, because it will only
// allow access to the document object
// of the IFrame if we access it through
// the document.frames array
IFrameObj = document.frames['RSIFrame'];
}
} catch(exception) {
// This is for IE5 PC, which does not allow dynamic creation
// and manipulation of an iframe object. Instead, we'll fake
// it up by creating our own objects.
iframeHTML='<iframe id="RSIFrame" style="';
iframeHTML+='border:0px;';
iframeHTML+='width:0px;';
iframeHTML+='height:0px;';
iframeHTML+='"><\/iframe>';
document.body.innerHTML+=iframeHTML;
IFrameObj = new Object();
IFrameObj.document = new Object();
IFrameObj.document.location = new Object();
IFrameObj.document.location.iframe = document.getElementById('RSIFrame');
IFrameObj.document.location.replace = function(location) {
this.iframe.src = location;
}
}
}

if (navigator.userAgent.indexOf('Gecko') !=-1 && !IFrameObj.contentDocument) {
// we have to give NS6 a fraction of a second
// to recognize the new IFrame
setTimeout('callToServer("'+theFormName+'")',10);
return false;
}

if (IFrameObj.contentDocument) {
// For NS6
IFrameDoc = IFrameObj.contentDocument;
} else if (IFrameObj.contentWindow) {
// For IE5.5 and IE6
IFrameDoc = IFrameObj.contentWindow.document;
} else if (IFrameObj.document) {
// For IE5
IFrameDoc = IFrameObj.document;
} else {
return true;
}

IFrameDoc.location.replace(URL);
return false;
}

// handleResponse is passed two parameters when called from the onload
// event of the pages loaded in the hidden IFRAME:
// st: a string indicating which state is being loaded
// doc: the document object of the page loaded in the IFRAME
function handleResponse(st, doc) {
// get a reference to the multiple select list, which we will populate
// with the data from the document loaded in the IFRAME
var namesEl = document.forms.stateForm.zipNames

// clear earlier records from the multiple select list
namesEl.length = 0

// get a reference to the DIV containing the data for this state
var dataEl = doc.getElementById(st)

// get a reference to the collection of the children elements of
// our DIV containing the data (this collection is the DIVs containing
// the actual zip names)
namesColl = dataEl.childNodes

// for easy scripting, assign the number of ZIP names for this state
// to a variable
var numNames = namesColl.length

// iterate through the collection of zip Names and
// create an option element for each one
for (var q=0; q<numNames; q++) {
if (namesColl[q].nodeType!=1) continue; // it's not an element node, let's skedaddle
var str = '' // used to store the text we'll use in the new option
str+= namesColl[q].id + ' ('

// get a reference to the collection of the children elements of
// this DIV (this collection contains the zip codes that fall under this zip name)

var zipsColl = doc.getElementById(namesColl[q].id).childNodes
var numZips = zipsColl.length

// iterate through this collection of zips and each one to the string
for (var r=0; r<numZips; r++) {
if (zipsColl[r].nodeType!=1) continue; // it's not an element node, let's skedaddle
str += zipsColl[r].id + ' '
}
str+= ')'

// create a new option element and add it to the zipNames form element
newOption = new Option(str)
namesEl.options[namesEl.length] = newOption
}

//provide a "success" message
var responseMessage = document.getElementById('responseMessage');
responseMessage.innerHTML = 'loaded records from <a href="'+doc.location+'">this external file<\/a>.';
}
</script>

</head>
<body>

<div id="theFormDiv">
<form name="stateForm" id="stateForm" action="server.html">
Select a state from this menu:
<select name="state" onchange="callToServer(this.form.name)">
<option selected value="">
<option value="AL"> Alabama
<option value="AK"> Alaska
<option value="AZ"> Arizona
<option value="AR"> Arkansas
<option value="CA"> California
<option value="CO"> Colorado
<option value="CT"> Connecticut
<option value="DE"> Delaware
<option value="DC"> District of Columbia
<option value="FL"> Florida
<option value="GA"> Georgia
<option value="HI"> Hawaii
<option value="ID"> Idaho
<option value="IL"> Illinois
<option value="IN"> Indiana
<option value="IA"> Iowa
<option value="KS"> Kansas
<option value="KY"> Kentucky
<option value="LA"> Louisiana
<option value="ME"> Maine
<option value="MD"> Maryland
<option value="MA"> Massachusetts
<option value="MI"> Michigan
<option value="MN"> Minnesota
<option value="MS"> Mississippi
<option value="MO"> Missouri
<option value="MT"> Montana
<option value="NE"> Nebraska
<option value="NV"> Nevada
<option value="NH"> New Hampshire
<option value="NJ"> New Jersey
<option value="NM"> New Mexico
<option value="NY"> New York
<option value="NC"> North Carolina
<option value="ND"> North Dakota
<option value="OH"> Ohio
<option value="OK"> Oklahoma
<option value="OR"> Oregon
<option value="PA"> Pennsylvania
<option value="RI"> Rhode Island
<option value="SC"> South Carolina
<option value="SD"> South Dakota
<option value="TN"> Tennessee
<option value="TX"> Texas
<option value="UT"> Utah
<option value="VT"> Vermont
<option value="VA"> Virginia
<option value="WA"> Washington
<option value="WV"> West Virginia
<option value="WI"> Wisconsin
<option value="WY"> Wyoming
</select><br><br>
Once a state has been selected, the multiple select list below will be populated with a partial list of Zip code names drawn from a database of html files that are loaded via a hidden IFRAME. (Zip code data drawn from sources on <a href="http://www.census.gov/geo/www/gazetteer/places.html">the US Census Bureau site</a>).
<select multiple="multiple" name="zipNames" style="width:100%; height:400px">
</select><br><br>
</form>
</div>

<div id="responseMessage" style="display:none"></div>
</body>
</html>

In another life when I was into panorama photography, I used the NASA equirectanglar Blue Marble image in a Java Applet viewer I normally used to display 360 'virtual tour' images. The projection is if the surface of the earth was painted on the inside of a sphere and your standing in the middle. Google Maps has been scripted into to the demo as well.

Take the Earth for a spin

Note: Drag (or use arrow keys) the image to pan around the globe. (+/- for zoom)

Hint: If you click on the Google graphic, (lower left corner of map) it will open a new tab in Google Maps with your current view setting.

Code: [Select]
<html>
<head>
<title>The Blue Marble</title>
<script src="http://maps.google.com/maps?file=api&amp;v=2&amp;sensor=false&amp;key=ABQIAAAAKVmOoKOF2E2u7QCPFHa89hQHrkFAUW_sbTtysgTBKCd6Skuu4hRoWJVnHTyx78GAQyuNGDLOIxcAPw" type="text/javascript"></script>
<script type="text/javascript">
var map;
function onLoad() {
map = new GMap2(document.getElementById("map"));
map.addControl(new GLargeMapControl());
map.addControl(new GMapTypeControl());
map.setCenter(new GLatLng(0,0), 4);
}
function setloc() {
map.setCenter(new GLatLng(parseFloat(document.forms["cn"].lat.value), parseFloat(document.forms["cn"].lon.value)), 8);
}
</script>
<script language="JavaScript1.1">
function getview(p,t,f) {
document.cn.pan.value = p ;
document.cn.tilt.value = t ;
}
</script>
</head>
<body onload="onLoad()">
<applet code=ptviewer.class width=674 height=444 archive="ptviewer.jar">
   <param name="file" value="earth_2700x1350.jpg">
   <param name="wait" value="globe.gif">
   <param name="fov" value="68">
   <param name="quality" value="6">
   <param name="cursor" value="MOVE">
   <param name=shotspot0 value="x330 y203 q i'targetbw.gif'">
   <param name=showToolbar value="true">
   <param name=imgLoadFeedback value="false">
   <param name="fovmin" value="35">
   <param name="fovmax" value="90">
   <param name="getview" value="getview">
</applet>
<table>
<form name="cn">
  <tr>
    <td width="145">North&#176; (+)<br><input type="text" size=18 ID="lat" name="tilt" value="" ><br>South&#176; (-)</td>
    <td width="145">East&#176; (+)<br><input type="text" size=18 ID="lon" name="pan" value="" ><br>West&#176; (-)</td>
    <td width="145" align="middle"><input type="button" name=mapit value=" MAP " onclick="setloc()"></td>
  </tr>
</form>
</table>
<br>
<div id="map" style="width: 674px; height: 444px"></div>
</body>
</html>

Support

  • Administrator
  • *****
  • Posts: 19
    • View Profile
CGI Programming II - AJAX
« Reply #5 on: October 08, 2009, 03:19:37 PM »
I haven't been much of a AJAX fan due to the layers of protocol getting something simple like a remote/hidden submit to work in my applications. I stumbled across a really nice AJAX framework that I thought I would share and include as part of this tutorial.

Prototype JavaScript Framework


Quote from: Bruce Perry - www.xml.com
Why Prototype?

Why didn't I just create a plain old JavaScript object (POJO) for my application, instead of introducing an open source library? For one, Prototype includes a nifty collection of JavaScript shortcuts that reduce typing and help avoid the reinvention of the wheel. The commonly touted shortcut is $("mydiv"), which is a Prototype function that returns a Document Object Model (DOM) Element associated with the HTML tag with id "mydiv". That sort of concision alone is probably worth the cost of setting up Prototype. It's the equivalent of:

document.getElementById("mydiv");

Another useful Prototype shortcut is $F("mySelect"), for returning the value of an HTML form element on a web page, such as a selection list. Once you get used to Prototype's austere, Perlish syntax, you will use these shortcuts all the time. Prototype also contains numerous custom objects, methods, and extensions to built-in JavaScript objects, such as the Enumeration and Hash objects (which I discuss below).

Finally, Prototype also wraps the functionality of XMLHttpRequest with its own Ajax.Request and related objects, so that you don't have to bother with writing code for instantiating this object for various browsers.

Quote
Try.these

Try.these(Function...) -> firstOKResult

Accepts an arbitrary number of functions and returns the result of the first one that doesn't throw an error.


More on AJAX soon ...

Your probably saying at this point, "What does JavaScript & AJAX have to do with CGI programming with Basic." If your interested in creating desktop like applications in a browser then what CGI is to the server, JavaScript (AJAX) is to the client. Your CGI applications are responsible for dynamically creating HTML/JavaScript and sending it back to the client. (a stream of text which your browser interprets to render your pages) You can request a static HTML page, a page dynamically created based on criteria and a page with embedded localized/remote scripting.

Support

  • Administrator
  • *****
  • Posts: 19
    • View Profile
CGI Programming II - Shopping Cart
« Reply #6 on: October 08, 2009, 03:27:47 PM »
I recently had to write a shopping cart for a client's site running ScriptBasic and thought I would add it to my CGI tutorial.

This cart can add / remove items and calculates the total with a check for a minimum quantity of 5.

Code: [Select]
' Program: cart
' Version: 1.0
'    Date: 2009-08-15
'      By: JRS

GLOBAL CONST NL = "\n"

INCLUDE cgi.bas
INCLUDE mysql.bas
INCLUDE mt.bas
INCLUDE t.bas

OPTION cgi$Method cgi::Get OR cgi::Post

session_id = cgi::Cookie("CART")

New_Session:

IF session_id = undef THEN
  session_id = mt::NewSessionId()
  mt::SetSessionId(session_id)
ELSE
  IF mt::CheckSessionId(session_id) = False THEN
    session_id = undef
    GOTO New_Session
  END IF
  mt::SetSessionId(session_id)
END IF

dbh = mysql::Connect("CART_DB")

' *** START GET ***
IF cgi::RequestMethod() = "GET" THEN

' Check for Add/Remove/Display Mode
module_number = cgi::GetParam("module")
IF module_number = undef THEN
  cartmode = "display"
ELSE
  cartmode = "add"
END IF

' Check for existing cart array
cartstr = mt::GetSessionVariable("cartstr")
IF cartstr = undef THEN
  itemcount = 0
ELSE
  t::StringToArray(mycart, cartstr)
  itemcount = UBOUND(mycart)
END IF
IF cartmode = "add" THEN itemcount += 1

' REMOVE Mode
delmod = cgi::GetParam("remove")
IF delmod >= 1 AND delmod <= itemcount THEN
  thisline = 1
  UNDEF tmpcart
  FOR x = 1 TO itemcount
    IF delmod <> x THEN
      tmpcart[thisline,0] = thisline
      tmpcart[thisline,1] = mycart[x,1]
      tmpcart[thisline,2] = mycart[x,2]
      tmpcart[thisline,3] = mycart[x,3]
      tmpcart[thisline,4] = mycart[x,4]
      tmpcart[thisline,5] = mycart[x,5]
      thisline += 1
    END IF
  NEXT x
  UNDEF mycart 
  mycart = tmpcart
  itemcount -= 1
  IF itemcount = 0 THEN
    UNDEF cartstr, mycart
    mt::SetSessionVariable("cartstr", undef)
  ELSE
    cartstr = t::ArrayToString(mycart)
    mt::SetSessionVariable("cartstr", cartstr)
  END IF
END IF

' ADD Mode
IF cartmode = "add" THEN
  mycart[itemcount, 0] = itemcount
  mycart[itemcount, 1] = module_number
  mysql::query(dbh,"SELECT PTITLE,PPRICE FROM Modules WHERE PNUM = '" & module_number & "'")
  mysql::FetchArray(dbh, modrow)
  mycart[itemcount, 2] = modrow[0]
  mycart[itemcount, 3] = modrow[1]
  mycart[itemcount, 4] = 5
  mycart[itemcount, 5] = FORMAT("%~####.00~", 5 * modrow[1])
  cartstr = t::ArrayToString(mycart)
  mt::SetSessionVariable("cartstr", cartstr)
END IF

' Cart Empty
IF ISUNDEF(mycart) THEN
  cgi::Header 302,"text/html"
  PRINT "Location: /home/curricula\n"
  cgi::SetCookie("CART", session_id, undef, undef, gmtime() + 2700, false)
  cgi::FinishHeader
  END
END IF
' *** END GET ***

ELSE

' *** START POST ***
IF cgi::PostParam("button") = "Continue to Checkout" THEN
  cgi::Header 302,"text/html"
  PRINT "Location: /home/checkout\n"
  cgi::SetCookie("CART", session_id, undef, undef, gmtime() + 2700, false)
  cgi::FinishHeader
  END
END IF

cartstr = mt::GetSessionVariable("cartstr")
t::StringToArray(mycart, cartstr)
itemcount = UBOUND(mycart)
FOR x = 1 TO itemcount
  mycart[x, 4] = cgi::PostParam("line" & x)
  IF VAL(mycart[x,4]) < 5 THEN
    mycart[x,4] = 5
  END IF
  mycart[x, 5] = FORMAT("%~####.00~", mycart[x,4] * mycart[x,3])
NEXT x
cartstr = t::ArrayToString(mycart)
mt::SetSessionVariable("cartstr", cartstr)
END IF
' *** END POST ***

' Build Standard Header
cgi::Header(200, "text/html")
cgi::SetCookie("CART", session_id, undef, undef, gmtime() + 2700, false)
cgi::FinishHeader()

PRINT """
<HTML>
<HEAD>
<TITLE>Order Cart</TITLE>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<STYLE type=text/css>A {
TEXT-DECORATION: underline
}
A:active { + 1
COLOR: #103366; TEXT-DECORATION: underline
} - 1
A:hover {
COLOR: #103366; TEXT-DECORATION: underline
}
A:visited {
COLOR: #666666; TEXT-DECORATION: underline
}
</STYLE>
</HEAD>
<BODY BGCOLOR=#FFFFFF text="#000000" link="#103366" vlink="#666666" leftmargin="0" topmargin="0" alink="#666666"  background="/media/CART/images/background.gif">
"""

INCLUDE "header"

PRINT """ 
<TABLE WIDTH=775 BORDER=0 CELLPADDING=0 CELLSPACING=0>
  <TR>
    <TD VALIGN=TOP bgcolor="#103366" width="70" height="523" style="border:1px solid; border-color : #000000;">
"""

INCLUDE "left_nav"

PRINT """
    </TD>
    <TD VALIGN=TOP WIDTH=757 height="523" bgcolor="#FFFFFF">
      <table border=0 cellspacing=0 cellpadding=0 width=672>
        <tr align="right">
          <td height="22" colspan=3>&nbsp;</td>
        </tr>
        <tr valign="top">
          <td valign="top">
            <TABLE CELLSPACING="0" CELLPADDING="18" BORDER="0"><TR VALIGN="TOP"><TD WIDTH="100%" ALIGN="LEFT">
            <font color="#000000" size="2" face="verdana"><a href="/home/curricula">Return to Section Listing</a></font><BR><BR>
            <font color="#000000" size="2" face="verdana">
            <BR>
            <FONT face="verdana,arial" size=3 style="font-size:18px;" class=font.normal color="#103366"><B>Order Cart</B></font><BR><BR>
            <TABLE border=1 cellspacing=2 cellpadding=4 width=100%>
            <form method=post action="/home/cart">
              <TR VALIGN="Top">
                <TD WIDTH=80 align=center bgcolor="#103366"><FONT face="verdana,arial" size=1 style="font-size:10px;" class=font.normal color=#FFFFFF><B>Module #</B></font><BR><IMG SRC="/media/CART/images/spacer.gif" WIDTH=80 HEIGHT=1 border=0></td>
                <TD WIDTH=100% align=left bgcolor="#103366"><FONT face="verdana,arial" size=1 style="font-size:10px;" class=font.normal color=#FFFFFF><B>Module Title</B></font></td>
                <TD WIDTH=80 align=center bgcolor="#103366"><FONT face="verdana,arial" size=1 style="font-size:10px;" class=font.normal color=#FFFFFF><B>Price</B></font><BR><IMG SRC="/media/CART/images/spacer.gif" WIDTH=80 HEIGHT=1 border=0></td>
                <TD WIDTH=60 align=center bgcolor="#103366"><FONT face="verdana,arial" size=1 style="font-size:10px;" class=font.normal color=#FFFFFF><B>Quantity</B></font><BR><IMG SRC="/media/CART/images/spacer.gif" WIDTH=60 HEIGHT=1 border=0></td>
                <TD WIDTH=80 align=center bgcolor="#103366"><FONT face="verdana,arial" size=1 style="font-size:10px;" class=font.normal color=#FFFFFF><B>Subtotal</B></font><BR><IMG SRC="/media/CART/images/spacer.gif" WIDTH=80 HEIGHT=1 border=0></td>
              </tr>
""" 
FOR x = 1 TO itemcount
PRINT """
              <TR VALIGN="Top">
                <TD WIDTH=80 align=center><FONT face="verdana,arial" size=1 style="font-size:10px;" class=font.normal>""" & mycart[x,1] & """<BR><a href="/home/cart?remove=""" & mycart[x,0] & """\">REMOVE</a></font></td>
                 <TD WIDTH=200 align=left><FONT face="verdana,arial" size=1 style="font-size:10px;" class=font.normal><B>""" & mycart[x,2] & """</B></font></td>
                <TD WIDTH=80 align=center><FONT face="verdana,arial" size=1 style="font-size:10px;" class=font.normal>""" & FORMAT("%~$##.00~",mycart[x,3]) & """</font></td>
                <TD WIDTH=60 align=center><input type=text name="line""" & x & """\" value=\"""" & mycart[x,4] & """\" size="4" style="text-align:right;"></td>
                <TD WIDTH=80 align=right><FONT face="verdana,arial" size=1 style="font-size:10px;" class=font.normal><B>""" & FORMAT("%~$#,###.00~",mycart[x,5]) & """</B></font></td>
              </tr>
              <TR VALIGN="Top">
                <TD colspan=4 align=right bgcolor="#103366"><IMG SRC="/media/CART/images/spacer.gif" WIDTH=10 HEIGHT=1 border=0></td>
              </tr>
"""
NEXT x

total_qty = 0
total_amt = 0

FOR x = 1 TO itemcount
  total_qty = total_qty + mycart[x,4]
  total_amt = total_amt + mycart[x,5]
NEXT x   

IF total_qty >= 5  AND total_qty <= 10 THEN
  shipping = 5.00
ELSE IF total_qty >= 11 AND total_qty <= 25 THEN
  shipping = 10.00
ELSE IF total_qty >= 26 AND total_qty <= 50 THEN
  shipping="15.00"
ELSE
  shipping="20.00"
END IF

PRINT """
              <TR VALIGN="Top">
                <TD colspan=4 align=right bgcolor="#e1e1e1"><FONT face="verdana,arial" size=1 style="font-size:10px;" class=font.normal><B>Subtotal</B></font><IMG SRC="/media/CART/images/spacer.gif" WIDTH=10 HEIGHT=1 border=0></td>
                <TD WIDTH=80 align=right><FONT face="verdana,arial" size=1 style="font-size:10px;" class=font.normal><B>""" & FORMAT("%~$#,###.00~",total_amt) & """</B></font><BR><IMG SRC="/media/CART/images/spacer.gif" WIDTH=80 HEIGHT=1 border=0></td>
              </tr>

              <TR VALIGN="Top">
                <TD colspan=4 align=right bgcolor="#e1e1e1"><FONT face="verdana,arial" size=1 style="font-size:10px;" class=font.normal><B>Shipping & Handling<BR></B></font><IMG SRC="/media/CART/images/spacer.gif" WIDTH=10 HEIGHT=1 border=0></td>
                <TD WIDTH=80 align=right><FONT face="verdana,arial" size=1 style="font-size:10px;" class=font.normal><B>""" & FORMAT("%~$#,###.00~",shipping) & """</B></font><BR><IMG SRC="/media/CART/images/spacer.gif" WIDTH=80 HEIGHT=1 border=0></td>
              </tr>
"""

total_inv = total_amt + shipping

PRINT """
              <TR VALIGN="Top">
                <TD colspan=4 align=right bgcolor="#e1e1e1"><FONT face="verdana,arial" size=1 style="font-size:10px;" class=font.normal><B>Total Due</B></font><IMG SRC="/media/CART/images/spacer.gif" WIDTH=10 HEIGHT=1 border=0></td>
                <TD WIDTH=80 align=right><FONT face="verdana,arial" size=1 style="font-size:10px;" class=font.normal><B>""" & FORMAT("%~$#,###.00~",total_inv) & """</B></font><BR><IMG SRC="/media/CART/images/spacer.gif" WIDTH=80 HEIGHT=1 border=0></td>
              </tr>
            </table>
            <BR><BR>
            <FONT face="verdana,arial" size=1 style="font-size:10px;" class=font.normal><input type=submit name=button value="Change Quantities"> You can modify all of the quantity boxes, then click here. <BR><BR>
            <input type=submit name=button value="Continue to Checkout"></form>
            <BR><BR><BR><BR></font><br>
          </TD>
        </TR>
      </TABLE>
      <p><font size="2" face="verdana"> </font><br>
      <font size="2" face="verdana">&nbsp;</font>
      <center>
      </center></p>
    </td>
  </tr>
  <tr>
  </tr>
 </table>
    </TD></TR><tr><TD COLSPAN=5 bgcolor="#0C0533" height="20" align="center"><font color="#CCCCCC" face="Verdana, Arial, Helvetica, sans-serif" size="1">Copyright © 2000-2009&nbsp;&nbsp;DBA Company</font></td>
</tr></TABLE>
</center>
<map name="Map3">
  <area shape="rect" coords="5,0,283,91" href="/home/start">
</map>
</BODY>
</HTML>
"""