|
|
|
To access the contents, click the chapter and section titles.
Platinum Edition Using HTML 4, XML, and Java 1.2
(Publisher: Macmillan Computer Publishing)
Author(s): Eric Ladd
ISBN: 078971759x
Publication Date: 11/01/98
Planning Your Script
Now that youve seen a scripts basic structure, youre ready to learn how to plan a script from the ground up:
- 1. Take your time defining the programs task. Think it through thoroughly. Write it down and trace the program logic. When youre satisfied that you understand the input, output and the transform process youll have to do, proceed.
- 2. Order a pizza and a good supply of your favorite beverage, lock yourself in for the night, and come out the next day with a finished program. This sounds cute, but it is oddly good advice. Sometimes, it seems as if more bugs stem from interruptions while programmingwhich cause loss of concentrationthan from any other source. And while youre sequestered, dont forget to document your code as you write it.
- 3. Test, test, test. Use every browser known to mankind and every sort of input you can think of. Especially test for the situations in which users enter 32KB of data in a 10-byte field (using MAXSIZE within your input tag does not protect you from receiving more input than expected), or they enter control codes where youre expecting plain text.
- 4. Document the program as a whole, toonot just the individual steps within itso that others who have to maintain or adapt your code will understand what you were trying to do.
Step 1, of course, is this sections topic, so well look at that process in more depth:
- If your script will handle form variables, plan out each one: its name, expected length, and data type.
- As you copy variables from QUERY_STRING or STDIN, check for proper type and length. A favorite trick of UNIX hackers is to overflow the input buffer purposely. Because of the way some scripting languages (notably sh and bash) allocate memory for variables, this sometimes gives the hacker access to areas of memory that should be protected, enabling them to place executable instructions in your scripts heap or stack space.
- Use sensible variable names. A pointer to the QUERY_STRING environment variable should be called something such as pQueryString, not p2. This not only helps debugging at the beginning but makes maintenance and modification much easier. No matter how brilliant a coder you are, chances are good that a year from now you wont remember that p1 points to CONTENT_TYPE and p2 points to QUERY_STRING.
- Distinguish between system-level parameters that affect how your program operates and user-level parameters that provide instance-specific information. In a script to send email, for example, dont let the user specify the IP number of the SMTP host. This information shouldnt even appear on the form in a hidden variable. Its instance independent and should therefore be a system-level parameter. In Windows NT, store this information in the Registry or an .ini file. In UNIX, store it in a configuration file or system environment variable.
- If your script will shell out to the system to launch another program or script, dont pass user-supplied variables unchecked. Especially in UNIX systems, where the system() call can contain pipe or redirection characters, leaving variables unchecked can spell disaster. Clever users and malicious hackers can copy sensitive information or destroy data this way. If you cant avoid system() calls altogether, plan for them carefully. Define exactly what can get passed as a parameter and know which bits will come from the user. Include an algorithm to parse for suspect character strings and exclude them.
- If your script will access external files, plan how youll handle concurrency. You may lock part or all of a data file, you may establish a semaphore, or you may use a file as a semaphore. If you take chances, youll be sorry. Never assume that because your script is the only program to access a given file that you dont need to worry about concurrency. Five copies of your script might be running at the same time, satisfying requests from five users.
- If you lock files, use the least-restrictive lock required. If youre only reading a data file, lock out writes while youre reading and release the file immediately afterward. If youre updating a record, lock just that one record (or byte range). Ideally, your locking logic should immediately surround the actual I/O calls. Dont open a file at the beginning of your program and lock it until you terminate. If you must do this, open the file but leave it unlocked until youre actually about to use it. This will enable other applications or other instances of your script to work smoothly and quickly.
- Prepare graceful exits for unexpected events. If, for instance, your program requires exclusive access to a particular resource, be prepared to wait a reasonable amount of time and then die gracefully. Never code a wait-forever call. When your program dies from a fatal error, make sure that it reports the error first. Error reports should use plain, sensible language. When possible, also write the error to a log file so the system administrator knows of it.
- If youre using a GUI language (for example, Visual Basic) for your CGI script, dont let untrapped errors result in a message box onscreen. This is a server application; chances are excellent that no one will be around to notice and clear the error, and your application will hang until the next time an administrator chances by. Trap all errors! Work around those you can live with and treat all others as fatal.
- Write pseudocode for your routines at least to the point of general logical structure before firing up the editor. It often helps to build stub routines so that you can use the actual calls in your program while youre still developing. A stub routine is a quick and dirty routine that doesnt actually process anything; it just accepts the inputs the final routine will be expecting and outputs a return code consistent with what the final routine would produce.
- For complex projects, a data flow chart can be invaluable. Data flow should remain distinct from logic flow; your data travels in a path through the program and is owned by various pieces along the way, no matter how its transformed by the subroutines.
|