11 November 1999 A short discussion on creating REXX plugins for NetScape The question is: How can I distribute information to be used by a client side script? And I want to do it in REXX (rather then JAVA). (perhaps plugins is too strong a word; maybe I mean "addon applications"). Let me describe one approach, using a more-or-less realistic example (please forgive me if I get pedantic). Suppose you have a resource that the server wishes to encrypt using some "shared-secret" -- that is, using an algorithim that client and server both know (implying that the client and server "share a secret" that is not communicated with the web request). Yeah, SSL sort of obviates the need for this, but SSL is neither free, easy to program, or unencumbered by licensing restrictions. And besides this is just an example! So, let's say that a request (from username JOE) for a resource http://foo.bar.net/secrets/myfile.1 is recieved by the server (at foo.bar.net), and the server knows how to encrypt this using this 'shared secret' algorithim. For purposes of illustration, let's say it just reverses the message (in practice, something like DES or BLOWFISH could be used, along with a keyphrase known by both parties). The chain of actions would then be: a) server at foo.bar.net gets a request for /secrets/myfile.1 b) server determines (using some kind of access control database) that joe has rights to this file, and that this file should be encrypted using the "reverse" algorihtim c) the server applies the reverse algorithim For example, the REXX code to "reverse encrypt" could be: i1=stream('e:\www\secrets\myfile.1','c','query size') foo=charin('e:\www\secrets\myfile.1',1,i1) stuff=reverse(foo) d) AND HERE IS WHERE IT GETS INTERESTING The server then sends "stuff" back to the client, using some special content-type. That is, it includes a "Content-type" response header. In this case, it could include: content-type: application/x-encrypt-reverse e) Netscape, when it sees this special content-type, will then "call" a special REXX plugin. This REXX plugin MUST be resident on the client's computer; which implies that the client is running os/2, or has some kind of 3rd party rexx interpreter installed. It also implies you have some way of distributing this REXX plugin to interested clients. f) The REXX plugin reads the response, undoes the encryption (in this case, applies reverse again), and displays the results. So -- the client-side question is "how does one do steps e and f". To learn the answer to that question requires that you subscribe to our business-class support, terms negotiable..... just kidding. First, write a simple rexx procedure that "undoes the decryption" -- call it MYPLUG1.CMD. In this case (abstracting from exception handlers, etc): /* myplug1.cmd */ parse arg in1 parse upper var in1 type infile if atype<>'TYPE:REVERSE' then exit /* an inelegant failure! */ ilen=stream(dafile,'c','query size') daresponse=charin(dafile,1,ilen) nustuff=reverse(daresponse) call displayit Let's hold off on the definition of the displayit procedure for a few paragrahs You would then distribute this to your clients, who would then install this somewhere in their PATH. Let's say they copy this to E:\OS2\APPS\MYPLUG1.CMD. Now, the client has to tell Netscape when to use this MYPLUG1.CMD "plugin" a) edit netscapes list of applications. Under ns/os2 4.04 and 4.61 ... Edit-preferences-applications b) Create a new "application". i) hit the new_type button ii) fill in the 4 fields: Descripton of type: anything (for example: "my REXX decryptor" File extension: not critical. Say, .REV Mime Type: CRUCIAL. Fill in the mime-type that the server will use. In this case, application/x-encrypt-reverse (I'm pretty sure that case does not matter). Applicaton to use: CRUCIAL, and a bit tricky. To invoke a rexx program, the trick is to start with a cmd.exe /c. In this case: cmd.exe /C "E:\OS2\APPS\MYPLUG1.CMD type:reverse " iii) save this. Under ns/os2 4.04, hit Okay When Netscape recieves a response with this content-type, it will a) create a temporary file containing the "body" of the response (in this example, this "body" will contain the the reversed secrets/myfile.1). b) call the program with this file name. Thus, , if Netscape created "E:\TEMP\SECRET.ABC", the value of in1 (in the sample code above) would be: type:reverse E:\TEMP\SECRET.ABC Notes: * In general, arguments after the program name (in the above example, the "type:reverse") are optional. Netscape will call the "application to use", including any argument, and add a filename at the end (i.e.; after the "type:reverse"). * The algorithim netscape uses for generating files is a mystery to me. To reiterate, adding additional arguments (such as "type:reverse") is optional. For exampe, one could put a "password" in there if one were using a more realistic encryption (of course, the client would have to use their own value of this password). Note: The first time the client asks for this sort of resource (a resource with an application/x-encrypt-reverse content-type), Netscape might throw up a "what do you want to do with this" screen. The last step in this puzzle is how to "display" the results. Note that MYPLUG1.CMD will be running in its own visible window, so you can have status messages, and query the client for options. Thus, you could simply use SAY to display the response, or save it to a user-specified file. Or you could display it in a second Netscape window. Thus, one candidate for displayit: displayit: tout='e:\temp\foo.1' tmp=charout('e:\temp\foo.1',nustuff,1) foo=stream(tout,'c','close') address cmd '@NETSCAPE file:///'tout foo=deleteme(tout) /* cleanup */ return 1 That about does it. Note that SRE-http uses this strategy for its "shared-secret" encryption -- if you are ambitious you can check out it out (see ENCRYPT.DOC).