By Bernhard Rupp
LLNL-BBRP, L-452, Livermore, CA 94551
CGI scripting
There is a little CGI script that decodes a space group. Just enter a valid space goup symbol or a spacegroup number (1-230) and voila! here we go:
Cool, isn't it? So how does it work?
Introduction
The web pages you actually see are the client side of a client-server connection through the internet. If your browser (the client) wants to see a web page, for example, it sends a request to the host you specify in the URL (Uniform Resource Locator) using the specified protocol (HTTP in this case, Hyper Text Transfer Protocol). example for a URL : http://www-structure.llnl.gov/default.html (protocol://site.domain/document). The site name is nothing but a name assigned to the IP address of the machine (128.115.150.112) running the (web) server. (NOTE : in this context the server is a program running the web service on the machine, not the computer itself - the computer is the host).
When the server recieves such a request, it responds and sends back a page, or whatever the request was for. The language in which the server and client communicate is HTML (Hyper Text Markup Language). Beyond static requests for web pages, one may want the server to execute a certain task (such as searching a data base or decode a space group). There must be a mechanism for the server to receive information about what to do and to hand it down to the application that handles the request. This interface is the CGI (Common Gateway Interface). The server essentially sets certain system environment variables, which the called program can read and process. The output is passed back to the server forwarding it through the internet to the requesting browser which displays the result. You may want to check out the Microsoft Internet Deveolopment CD or the other references for more information on the subject.
Example
In this web page I used following script to create the input box and define the action to be taken :
<form action="/cgi-bin/sexie32.exe" method="GET"> <p>Enter a spacegroup or spacegroup number <input type="text" size="11" name="spcgrp"> and hit enter</p> </form>
This minimal code creates the above input box, assigns the input to the variable named 'spcgrp' and executes the program sexie32 which does the job. How do I get the space group variable into the program? By specifying GET as method, the server adds the variable name and its contents after a question mark to the program name and stores this string in an environment variable QUERY_STRING. All the program does is read this environment variable string, decode it, and after the calculation, write the result as an HTML file to the standard output (console) which the server redirects to the requester. Most scripting languages provide libraries and one does not have to deal with the details of reading the system environment.
FORTRAN
As scientists, we may have a useful program in FORTAN that does a nice job and it would be desirable to make it available on the web. The obvious benefit is that you do not have to deal with platform and implementation issues - no unvalidated version proliferation, no source code mess etc - the application runs on your host computer, and the browsers take care of the platform specific implementation. All of a sudden your old F66 code has a graphical windows interface!
Subroutine WEBSPC reads the environment variables and returns the spacegroup string to the main routine :
subroutine webspc (spcgrp,title,igr,ierr) WEBS0001 c ----------------------------------------------------------------------WEBS0002 c returns space group passed from web server through GET method WEBS0003 c ----------------------------------------------------------------------WEBS0004 USE MSFLIB WEBS0005 integer*4 lstr WEBS0006 integer igr(36) WEBS0007 character today*24,spcgrp*10,title*60,usradd*15,fname*60,qstr*80 WEBS0008 character usrnam*80,browsr*80 WEBS0009 WEBS0010 c --- Set spacegroup blank WEBS0011 spcgrp=' ' WEBS0012 ierr=0 WEBS0013
Here is how to read the environment variables which were set by the server according to the action instructions in the HTML code fragment above. You'll find a listing of other variables that are set in most books on web programming (some of them are read by webspc as well). The key is QUERY_STRING which contains the variable part of the URL constructed by the action listed above:
http://www-structure.llnl.gov/cgi-bin/sexie32.exe?spcgrp=I+4%2Fm+m+m
QUERY_STRING contains: spcgrp=I+4%2Fm+m+m (NOTE: if you enter the URL above or click it, the CGI script will actually be executed). Notice also that the CGI interface substitutes blanks with + signs and special characters with their hexadecimal code preceeded by a % sign (e.g., the slash is %2F). The actual input string in the box was 'I 4/m m m' in this case.
WEBS0014 c --- get the client name and the query_string from environment WEBS0015 ladd = GETENVQQ('REMOTE_ADDR', usradd) WEBS0016 lnam = GETENVQQ('REMOTE_USR', usrnam) WEBS0017 lbrs = GETENVQQ('HTTP_USER_AGENT', browsr) WEBS0018 lstr = GETENVQQ('QUERY_STRING', qstr) WEBS0019 WEBS0020 c --- read space group - if an integer decode by number WEBS0021 read(qstr,'(7x,i3)',err=0001) ispa WEBS0022 c --- if we get here, it was read successfully as a number WEBS0023
Note that I use the error label when reading the symbol as a integer to distinguish whether a space group symbol or a space group number was entered.
call spsymc (spcgrp,ispa) WEBS0024 c --- ispa returns the symbol now proceed with checks WEBS0025 goto 2002 WEBS0026 WEBS0027 c --- parse the input string if not a number WEBS0028 0001 continue WEBS0029 ilen=lstr-7 WEBS0030 j=0 WEBS0031 c --- begin loop over query_string WEBS0032
Notice that the CGI interface substitutes blanks with + signs and special characters with hexadecimal code preceeded by a % sign (e.g., / is %2F), so we need to parse that string:
i=8 WEBS0033 1000 continue WEBS0034 c --- replace + with blank WEBS0035 if (qstr(i:i).eq.'+') then WEBS0036 j=j+1 WEBS0037 spcgrp(j:j)=' ' WEBS0038 i=i+1 WEBS0039 c --- replace special character hex code with character WEBS0040 else if (qstr(i:i).eq.'%') then WEBS0041 c --- %2F is slash WEBS0042 if (qstr(i+1:i+2).eq.'2F') then WEBS0043 j=j+1 WEBS0044 spcgrp(j:j)='/' WEBS0045 i=i+3 WEBS0046 end if WEBS0047 else WEBS0048 j=j+1 WEBS0049 spcgrp(j:j)=qstr(i:i) WEBS0050 i=i+1 WEBS0051 end if WEBS0052 c --- repeat until finished with string WEBS0053 if (i.lt.(ilen+8)) goto 1000 WEBS0054 WEBS0055 c --- now check if a valid space group symbol WEBS0056 2002 call upstrg(spcgrp,10) WEBS0057 read(spcgrp,'(10a1)') (igr(i), i=1,10) WEBS0058 ispa=0 WEBS0059 call spsymc (spcgrp,ispa) WEBS0060 WEBS0061 c --- get a date string, format is :Wed Nov 20 15:33:29 1996 WEBS0062 call fdate (today) WEBS0063 title='Webjob on '//today(1:10)//today(20:24)//' at'// WEBS0064 & today(11:19) //' from '//usradd WEBS0065
The program also keeps a log of the users. You can look at it : http://www-structure.llnl.gov/webjobs.html (see the variable fname below).
c --- log the job WEBS0066 fname='C:\inetsrv\wwwroot\webjobs.html' WEBS0067 open (66,file=fname,access='append',position='append') WEBS0068 c --- overwrite old </body> tag WEBS0069 backspace (66) WEBS0070 write(66,'(a,a,a)')' <p>Date : '//today//'<br>' WEBS0071 write(66,'(a,a,a)')' Client : '//usradd(1:ladd)//'<br>' WEBS0072 write(66,'(a,a,a)')' Browser : '//browsr(1:lbrs)//'<br>' WEBS0073 write(66,'(a,a,a)')' Spacegr: '//spcgrp//'<br>' WEBS0074 if (ispa.lt.0) then WEBS0075 write(66,'(a)')' Status : failed!</p>' WEBS0076 else WEBS0077 write(66,'(a)')' Status : ok</p>' WEBS0078 end if WEBS0079 write(66,'(a)') ' <hr>' WEBS0080 write(66,'(a)') ' </BODY>' WEBS0081 close(66) WEBS0082 c --- if something went wrong, return message and termination signal WEBS0083 if (ispa.lt.0) then WEBS0084 call webtxt (1,spcgrp) WEBS0085 ierr=1 WEBS0086 close(5) WEBS0087 return WEBS0088 else WEBS0089 close(5) WEBS0090 return WEBS0091 end if WEBS0092 return WEBS0093 end WEBS0094
The variable spcgrp gets returned to the main routine which decodes the space group. The output is written to a file, and all that is needed is a tiny routine to write this output as a HTML file to the standard output (console).
subroutine htmake HTMA0001 HTMA0002 character*80 line HTMA0003 HTMA0004 open(6,file='sexie.out') HTMA0005 write(*,*)'Content-type: text/html' HTMA0006 write(*,*) HTMA0007 write(*,*)'<BODY bgcolor="#FFFDE6" TEXT="#0000FF">' HTMA0008 write(*,*)'<TITLE>Space group decoding</TITLE>' HTMA0009 write(*,*)'<pre>' HTMA0010 do i=1,100000 HTMA0011 read(6,'(1x,a)',end=9999) line HTMA0012 write(*,'(1x,a)') line HTMA0013 end do HTMA0014 9999 close(6) HTMA0015 open(6,file='xyz.txt') HTMA0016 write(*,'(//a//)') HTMA0017 & ' Alternate listing of symmetry operators follows' HTMA0018 do i=1,100000 HTMA0019 read(6,'(1x,a)',end=9990) line HTMA0020 write(*,'(1x,a)') line HTMA0021 end do HTMA0022 9990 close(6) HTMA0023 write(*,*) '</pre>' HTMA0024 write(*,*) '</BODY>' HTMA0025 return HTMA0026 end HTMA0027
So, that's all there is to basic CGI scripting. Just go ahead, write a little code fragment yourself and play around a little. I used Microsoft Frontpage [2] to create my site and the forms, and Microsoft FORTRAN professional edition for the F90 programming. Your FORTRAN compiler may use a different way to get the environment variables, but you should be able to find this in your documentation. Of course, this is NOT an encouragement to write CGI scripts in Fortran. The executables are bulky and full with overhead, and for many tasks, C, Pearl, J++ etc are faster. But if you have a solid peace of code, hey, why not make it useable on the web!
References
[1] CGI developer's guide, E.E.Kim,
SamsNet Publishing (1996)
[2] http://www.microsoft.com/frontpage/documents/technical11/default.htm
[3] Mastering Internet Development, Micosoft CD-ROM
Back to X-ray Facility Introduction
LLNL Disclaimer
This World Wide Web site conceived and maintained by
Bernhard Rupp (br@llnl.gov)
Last revised April 06, 1999 11:04
UCRL-MI-125269