SendMail
class for this purpose. The only methods of SendMail
are send
, to send the message, and errorCode
and errorMessage
, to interpret an error.
For example, the following script sends mail to vpg with the specified subject and body for the message:
<server>The following table describes the properties of the
SMName = new SendMail();
SMName.To = "[email protected]";
SMName.From = "[email protected]";
SMName.Subject = "Here's the information you wanted";
SMName.Body = "sharm, maldives, phuket, coral sea, taveuni, maui,
cocos island, marathon cay, san salvador";
SMName.send();
</server>
SendMail
class. The To
and From
properties are required; all other properties are optional.
Table 14.1 Properties of the
SendMail
class
A comma-delimited list of primary recipients of the message. | |
A comma-delimited list of additional recipients of the message. | |
SendMail
class are included in the header of the message when it is actually sent. For example, the following code sends a message to bill
from vpg
, setting vpg
's organization field to Royal Airways. Replies to the message go to vpgboss
.
mailObj["Reply-to"] = "vpgboss";For more information on predefined header fields, refer to RFC 822
mailObj.Organization = "Royal Airways";
mailObj.From = "vpg";
mailObj.To = "bill";
mailObj.send();
, the standard for the format of internet text messages.
The SendMail
class allows you to send either simple text-only mail messages or complex MIME-compliant mail. You can also add attachments to your message. To send a MIME message, add a Content-type
property to the SendMail
object and set its value to the MIME type of the message.
For example, the following code segment sends a GIF image:
<server>
SMName = new SendMail();
SMName.To = "[email protected]";
SMName.From = "[email protected]";
SMName.Subject = "Here's the image file you wanted";
SMName["Content-type"] = "image/gif";
SMName["Content-Transfer-Encoding"] = "base64";
// In this next statement, image2.gif must be base 64 encoded.
// If you use uuencode to encode the GIF file, delete the header
// (for example, "begin 644 image2.gif") and the trailer ("end").
fileObj = new File("/usr/somebody/image2.gif");
openFlag = fileObj.open("r");Some MIME types may need more information. For example, if the content type is
if ( openFlag ) {
len = fileObj.getLength();
SMName.Body = fileObj.read(len);
SMName.send();
}
</server>
multipart/mixed
, you must also specify a boundary separator for one or more different sets of data in the body. For example, the following code sends a multipart message containing two parts, both of which are plain text:
<server>Here the file
SMName = new SendMail();
SMName.To = "[email protected]";
SMName.From = "[email protected]";
SMName.Subject = "Here's the information you wanted";
SMName["Content-type"]
= "multipart/mixed; boundary=\"simple boundary\"";
fileObj = new File("/usr/vpg/multi.txt");
openFlag = fileObj.open("r");
if ( openFlag ) {
len = fileObj.getLength();
SMName.Body = fileObj.read(len);
SMName.send();
}
</server>
multi.txt
contains the following multipart message:
This is the place for preamble.
It is to be ignored.
It is a handy place for an explanatory note to non-MIME compliant readers.
--simple boundary
This is the first part of the body.
This does NOT end with a line break.
--simple boundary
Content-Type: text/plain; charset=us-ascii
This is the second part of the body.
It DOES end with a line break
--simple boundary--You can nest multipart messages. That is, if you have a message whose content type is multipart, you can include another multipart message in its body. In such cases, be careful to ensure that each nested multipart entity uses a different boundary delimiter. For details on MIME types, refer to RFC 1341, the MIME standard. For more information on sending mail messages with JavaScript, see the description of this class in the Server-Side JavaScript Reference.
This is the epilogue. It is also to be ignored.
File
class that enables applications to write to the server's file system. This is useful for generating persistent HTML files and for storing information without using a database server. One of the main advantages of storing information in a file instead of in JavaScript objects is that the information is preserved even if the server goes down.
File
class. A JavaScript application can read
or write files anywhere the operating system allows, potentially including
sensitive system files. You should be sure your application does not allow an
intruder to read password files or other sensitive information or to write files at
will. Take care that the filenames you pass to its methods cannot be modified
by an intruder.
For example, do not use client
or request
properties as filenames, because the values may be accessible to an intruder through cookies or URLs. In such cases, the intruder can modify cookie or URL values to gain access to sensitive files.
For similar security reasons, Navigator does not provide automatic access to the file system of client machines. If needed, the user can save information directly to the client file system by making appropriate menu choices in Navigator.
File
class, use the standard JavaScript syntax for object creation:
fileObjectName = new File("path");Here,
fileObjectName
is the name by which you refer to the file, and path
is the complete file path. The path should be in the format of the server's file system, not a URL path.
You can display the name of a file by using the write
function, with the File
object as its argument. For example, the following statement displays the filename:
x = new File("\path\file.txt");
write(x);
File
object, you use the open
method to open the file so that you can read from it or write to it. The open
method has the following syntax:
result = fileObjectName.open("mode");This method returns
true
if the operation is a success and false
otherwise. If the file is already open, the operation fails and the original file remains open.
The parameter mode
is a string that specifies the mode in which to open the file. The following table describes how the file is opened for each mode.
Mode |
Description
|
|
|
|
|
|
| |
---|
close
method. If the file is not open, close
fails. This method returns true
if successful and false
otherwise.
lock
and follow them with unlock
.
If only one application can modify the same file, you can obtain the lock within the project
object. If more than one application can access the same file, however, obtain the lock within the server
object.
For example, suppose you have created a file called myFile
. Then you could use it as follows:
if ( project.lock() ) {In this way, only one user of the application has modify to the file at one time. Alternatively, for finer locking control you could create your own instance of the
myFile.open("r");
// ... use the file as needed ...
myFile.close();
project.unlock();
}
Lock
class to control access to a file. This is described in "Using Instances of Lock" on page 269.
File
class has a number of methods that you can use once a file is open:
setPosition
, getPosition
, eof
. Use these methods to set and get the current pointer position in the file and determine whether the pointer is at the end of the file.read
, readln
, readByte
.write
, writeln
, writeByte
, flush
.byteToString
, stringToByte
. Use these methods to convert a single number to a character and vice versa.getLength
, exists
, error
, clearError
. Use these methods to get information about a file and to get and clear error status.File
object has a pointer that indicates the current position in the file. When you open a file, the pointer is either at the beginning or at the end of the file, depending on the mode you used to open it. In an empty file, the beginning and end of the file are the same.
The setPosition
method positions the pointer within the file, returning true
if successful and false
otherwise.
fileObj.setPosition(position);Here,
fileObj.setPosition(position, reference);
fileObj
is a File
object, position
is an integer indicating where to position the pointer, and reference
indicates the reference point for position
, as follows:
getPosition
method returns the current position in the file, where the first byte in the file is always byte 0. This method returns -1 if there is an error.
fileObj.getPosition();The
eof
method returns true
if the pointer is at the end of the file and false
otherwise. This method returns true
after the first read operation that attempts to read past the end of the file.
fileObj.eof();
read
, readln
, and readByte
methods to read from a file.
The read
method reads the specified number of bytes from a file and returns a string.
fileObj.read(count);Here,
fileObj
is a File
object, and count
is an integer specifying the number of bytes to read. If count
specifies more bytes than are left in the file, then the method reads to the end of the file.
The readln
method reads the next line from the file and returns it as a string.
fileObj.readln();Here,
fileObj
is a File
object. The line-separator characters (either \r\n
on Windows or just \n
on Unix or Macintosh) are not included in the string. The character \r
is skipped; \n
determines the actual end of the line. This compromise gets reasonable behavior on all platforms.
The readByte
method reads the next byte from the file and returns the numeric value of the next byte, or -1.
fileObj.readByte();
write
, writeln
, writeByte
, and flush
.
The write
method writes a string to the file. It returns true
if successful and false
otherwise.
fileObj.write(string);Here,
fileObj
is a File
object, and string
is a JavaScript string.
The writeln
method writes a string to the file, followed by \n
(\r\n
in text mode on Windows). It returns true
if the write was successful and false
otherwise.
fileObj.writeln(string);The
writeByte
method writes a byte to the file. It returns true
if successful and false
otherwise.
fileObj.writeByte(number);Here,
fileObj
is a File
object and number
is a number.
When you use any of these methods, the file contents are buffered internally. The flush
method writes the buffer to the file on disk. This method returns true
if successful and false
otherwise.
fileObj.flush();
byteToString
and stringToByte
methods of the File
class convert data between these formats.
The byteToString
method converts a number into a one-character string. This method is static. You can use the File
class object itself, and not an instance, to call this method.
File.byteToString(number);If the argument is not a number, the method returns the empty string. The
stringToByte
method converts the first character of its argument, a string, into a number. This method is also static.
File.stringToByte(string);The method returns the numeric value of the first character, or 0.
File
methods to get information on files and to work with the error status.
The getLength
method returns the number characters in a text file or the number of bytes in any other file. It returns -1 if there is an error.
fileObj.getLength();The
exists
method returns true
if the file exists and false
otherwise.
fileObj.exists();The
error
method returns the error status, or -1 if the file is not open or cannot be opened. The error status is a nonzero value if an error occurred and 0 otherwise (no error). Error status codes are platform dependent; refer to your operating system documentation.
fileObj.error();The
clearError
method clears both the error status (the value of error
) and the value of eof
.
fileObj.clearError();
File
class. If you install it, be sure to restrict access so that unauthorized persons cannot view files on your server. For information on restricting access to an application, see "Deploying an Application" on page 68.
The following code from the viewer
sample application creates a File
class, opens it for reading, and generates HTML that echoes the lines in the file, with a hard line break after each line.
x = new File("\tmp\names.txt");
fileIsOpen = x.open("r");
if (fileIsOpen) {
write("file name: " + x + "<BR>");
while (!x.eof()) {
line = x.readln();
if (!x.eof())
write(line+"<br>");
}
if (x.error() != 0)
write("error reading file" + "<BR>");
x.close();
}
Important Be careful when using native functions with your application. Native functions can compromise security if the native program processes a command-line entry from the user (for example, a program that allows users to enter operating system or shell commands). This functionality is dangerous because an intruder can attach additional commands using semicolons to append multiple statements. It is best to avoid command-line input, unless you strictly check it.Using native functions in an application is useful in these cases:
jsaccall
contains source and header files illustrating how to call functions in external libraries from a JavaScript application.
In the Application Manager, you associate an external library with a particular application. However, once associated with any installed application, an external library can be used by all installed applications.
Follow these steps to use a native function library in a JavaScript application:
registerCFunction
to identify the library functions to be called and callC
to call those functions. (See "Registering Native Functions" on page 290 and "Using Native Functions in JavaScript" on page 290.)Important You must restart your server to install a library to use with an application. You must restart the server any time you add new library files or change the names of the library files used by an application.
jsaccall.h
provided in js\samples\jsaccall\
.
This directory also includes the source code for a sample application that calls a C function defined in jsaccall.c
. Refer to these files for more specific guidelines on writing C functions for use with JavaScript.
Functions to be called from JavaScript must be exported and must conform to this type definition:
typedef void (*LivewireUserCFunction)
(int argc, struct LivewireCCallData argv[],
struct LivewireCCallData* result, pblock* pb,
Session* sn, Request* rq);
Important After you enter the paths of library files in the Application Manager, you must restart your server for the changes to take effect. You must then be sure to compile and restart your application.Once you have identified an external library using the Application Manager, all applications running on the server can call functions in the library (by using
registerCFunction
and callC
).
registerCFunction
to register a native function for use with a JavaScript application. This function has the following syntax:
registerCFunction(JSFunctionName, libraryPath, CFunctionName);Here,
JSFunctionName
is the name of the function as it will be called in JavaScript with the callC
function. The libraryPath
parameter is the full pathname of the library, using the conventions of your operating system and the CFunctionName
parameter is the name of the C function as it is defined in the library. In this method call, you must use the exact case shown in the Application Manager, even on NT.
NOTE:
Backslash (\) is a special character in JavaScript, so you must use either
forward slash (/) or a double backslash (\\) to separate Windows directory and
filenames in libraryPath
.
This function returns true
if it registers the function successfully and false
otherwise. The function might fail if JavaScript cannot find the library at the specified location or the specified function inside the library.
An application must use registerCFunction
to register a function before it can use callC
to call it. Once the application registers the function, it can call the function any number of times. A good place to register functions is in an application's initial page.
callC
to call it. This function has the following syntax:
callC(JSFunctionName, arguments);Here,
JSFunctionName
is the name of the function as it was identified with registerCFunction
and arguments
is a comma-delimited list of arguments to the native function. The arguments can be any JavaScript values: strings, numbers, Boolean values, objects, or null. The number of arguments must match the number of arguments required by the external function. Although you can specify a JavaScript object as an argument, doing so is rarely useful, because the object is converted to a string before being passed to the external function.
This function returns a string value returned by the external function. The callC
function can return only string values.
The jsaccall
sample JavaScript application illustrates the use of native functions. The jsaccall
directory includes C source code (in jsaccall.c
) that defines a C function named mystuff_EchoCCallArguments
. This function accepts any number of arguments and then returns a string containing HTML listing the arguments. This sample illustrates calling C functions from a JavaScript application and returning values.
To run jsaccall
, you must compile jsaccall.c
with your C compiler. Command lines for several common compilers are provided in the comments in the file.
The following JavaScript statements (taken from jsaccall.html
) register the C function as echoCCallArguments
in JavaScript, call the function echoCCallArguments
, and then generate HTML based on the value returned by the function.
var isRegistered = registerCFunction("echoCCallArguments",The
"c:\\mycode\\mystuff.dll", "mystuff_EchoCCallArguments");
if (isRegistered == true) {
var returnValue = callC("echoCCallArguments",
"first arg",
42,
true,
"last arg");
write(returnValue);
}
else {
write("registerCFunction() returned false, "
+ "check server error log for details")
}
echoCCallArguments
function creates a string result containing HTML that reports both the type and the value of each of the JavaScript arguments passed to it. If the registerCFunction
returns true, the code above generates this HTML:
argc = 4<BR>
argv[0].tag: string; value = first arg<BR>
argv[1].tag: double; value = 42<BR>
argv[2].tag: boolean; value = true<BR>
argv[3].tag: string; value = last arg<BR>
application/x-www-form-urlencoded
. The runtime engine also automatically handles requests with this content type. In these situations, you rarely need direct access to the request or response header. If, however, your application uses a different content type, it must be able to manipulate the request header itself.
Conversely, the typical response sent from the server to the client has the text/html
content type. The runtime engine automatically adds that content type to its responses. If you want a different content type in the response, you must provide it yourself.
To support these needs, the JavaScript runtime engine on the server allows your application to access (1) the header of any request and (2) the raw body of a request that has a nonstandard content type. You already control the body of the response through the SERVER
tag and your HTML tags. The functionality described in this section also allows you to control the header of the response.
You can use this functionality for various purposes. For example, as described in "Using Cookies" on page 230, you can communicate between the client and server processes using cookies. Also, you can use this functionality to support a file upload.
The World Wide Web Consortium publishes online information about the HTTP protocol and information that can be sent using that protocol. See, for example, HTTP Specifications and Drafts.
httpHeader
method of the request
object. This method returns an object whose properties and values correspond to the name/value pairs of the header.
For example, if the request contains a cookie, header["cookie"]
or header.cookie
is its value. The cookie
property, containing all of the cookie's name/value pairs (with the values encoded as described in "Using Cookies" on page 230), must be parsed by your application.
The following code prints the properties and values of the header:
var header = request.httpHeader();
var count = 0;
var i;
for (i in header ) {If you submitted a form using the
write(count + ". " + i + " " + header[i] + "<br>\n");
count++;
}
GET
method, your output might look like this:
0. connection Keep-AliveIf you used the
1. user-agent Mozilla/4.0b1 (WinNT; I)
2. host piccolo:2020
3. accept image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
POST
method to submit your form, your output might look like this:
0. referer http://piccolo:2020/world/hello.html
1. connection Keep-Alive
2. user-agent Mozilla/4.0b1 (WinNT; I)
3. host piccolo:2020
4. accept image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
5. cookie NETSCAPE_LIVEWIRE.oldname=undefined; NETSCAPE_LIVEWIRE.number=0
6. content-type multipart/form-data; boundary=---------------------------79741602416605
7. content-length 208
application/x-www-form-urlencoded
. Upon receiving a request with this content type, the JavaScript runtime engine on the server processes the request using the data in the body of the request. In this situation, you cannot directly access the raw data of the request body. (Of course, you can access its content through the request
and client
objects constructed by the runtime engine.)
If, however, the request has any other content type, the runtime engine does not automatically process the request body. In this situation, it is up to your application to decide what to do with the content.
Presumably, another page of your application posted the request for this page. Therefore, your application must expect to receive unusual content types and should know how to handle them.
To access the body of a request, you use the getPostData
method of the request
object. This method takes as its parameter the number of characters of the body to return. If you specify 0, it returns the entire body. The return value is a string containing the requested characters. If there is no available data, the method returns the empty string.
You can use this method to get all of the characters at once, or you can read chunks of data. Think of the body of the request as a stream of characters. As you read them, you can only go forward; you can't read the same characters multiple times.
To assign the entire request body to the postData
variable, you can use the following statement:
postData = request.getPostData(0);If you specify 0 as the parameter, the method gets the entire request. You can explicitly find out how many characters are in the information using the header's
content-length
property, as follows:
length = parseInt(header["content-length"], 10);To get the request body in smaller chunks, you can specify a different parameter. For example, the following code processes the request body in chunks of 20 characters:
var length = parseInt(header["content-length"], 10);
var i = 0;
while (i < length) {Of course, this would be a sensible approach only if you knew that chunks consisting of 20 characters of information were meaningful in the request body.
postData = request.getPostData(20);
// ...process postData...
i = i + 20;
}
text/html
) to the response header. If you want a custom header, you must first remove the old default content type from the header and then add the new one. You do so with the addResponseHeader
and deleteResponseHeader
functions.
For example, if your response uses royalairways-format
as a custom content type, you would specify it this way:
deleteResponseHeader("content-type");You can use the
addResponseHeader("content-type","royalairways-format");
addResponseHeader
function to add any other information you want to the response header.
Important Remember that the header is sent with the first part of the response. Therefore, you should call these functions early in the script on each page. In particular, you should ensure that the response header is set before any of these happen:
flush
function to clear the output buffer.redirect
function to change client requests.Last Updated: 11/12/98 15:29:35