CGI/Comments
This is discussion page for comments on the CGI framework.
See also Web/Comments for related General forum threads:
-- Oleg Kobchenko <<DateTime(2007-01-15T08:53:50Z)>> ----
Possible JHP change
Would the following change to the qkeys function in JHP be sensible? It seems to me it would enable the use of the qparam function for form data as well as query strings?
qkeys=: 3 : 0 if. 0~:nc<'CGIKEYS' do. if. 'application/x-www-form-urlencoded'-: 2!:5 'CONTENT_TYPE' do. inpt=: stdin '' else. inpt=: 2!:5 'QUERY_STRING' end. 'CGIKEYS CGIVALS'=: a:"_`(<"1@|:)@.(0<#) qsparse inpt end. CGIKEYS )
-- Ric Sherlock <<DateTime(2007-03-27T22:12:03Z)>> ----
Cookies with JHP
I couldn't find any existing facility to add Cookies in JHP. After some research into how cookies are set etc, I came up with the two functions below that could be added to jhp.ijs.
In a JHP page they could be used like this.
<% SetCookie 'foo=bar;' %> <% DeleteCookie 'oldfoo' %> <% ContentType'text/html' %> <html><head>...
The two functions are:
NB.*SetCookie v writes line to delete/expire a cookie NB. y is string to set cookie NB. e.g. SetCookie 'foo=bar;' NB. e.g. SetCookie 'foo=bar; domain=domain.com; path=/; expires=Fri, 29-Mar-2007 13:46:00 GMT' SetCookie=: 3 : 0 if. 0 <: nc<'CookiesSet_j_' do. CookiesSet_j_=: CookiesSet_j_;y else. CookiesSet_j_=: y end. print 'Set-Cookie: ',":y ) NB.*DeleteCookie v writes line to delete/expire a cookie NB. y is string - name of cookie to delete NB. e.g. DeleteCookie 'foo' DeleteCookie=: 3 : 0 ck=.y,'=;' expire=. ' expires=Thu, 01-Jan-1970 00:00:00 GMT;' SetCookie ck,expire )
-- Ric Sherlock <<DateTime(2007-03-27T22:19:17Z)>> ----
stderr definition for Win32 in JHP?
Looking through jhp.ijs I see that stdin, stdout & stderr are defined at the start of the script for a Unix-based system. At the end of the script a check is done to see if the system is running Windows and if so overwrites the definitions of stdin & stdout with the Windows equivalents. My question is whether stderr should also be redefined.
It is set at the start of the script using 1!:2&5 which I understand from the documentation of Foreign conjunctions is Unix only. Should it be redefined at the end of the script something like this?
stderr_z_=: [: WriteFile_j_ (GetStdHandle_j_ _12) ; , ; # ; ,@2: ; 0:
To be honest I haven't worked out all of the things this sentence is doing, but am assuming it should be similar to stdout except for the different handle value.
I haven't noticed anything suggesting that this is currently a problem in JHP, just looked like an inconsistency.
-- Ric Sherlock <<DateTime(2007-03-29T02:32:47Z)>> ----
- The stdout routine was redefined for Windows because the standard output behaves badly: instead of treating end of lines as is, it adds CR, which makes it impossible to output binary data like images that used in JHP. On the other hand stderr is actually supported for Windows too, and as I believe is written to the log file by the web server. It does not need the binary format, so it's OK to use 1!:2&5. -- Oleg Kobchenko <<DateTime(2007-03-29T06:19:24Z)>>
Parsing multipart/form-data in JHP
Here is a first draft of some changes to JHP that would enable it to parse forms & files uploaded using the multipart/form-data content type. It is very verbose and certainly not as elegant as the rest of JHP, but it seems to work so hopefully it can act as a starting point.
The qkeys verb has been extended. Four extra global nouns are defined for multipart/form-data (CGIISFL -boolean, is the key a file; CGIFNMS -for files, the filenames to write uploaded file data to; CGICTPS -for files, the content-type; CGIFDAT - for files, the file data).
qkeys=: 3 : 0 if. -.isnoun 'CGIKEYS' do. select. env 'REQUEST_METHOD' case. 'GET' do. q=. env 'QUERY_STRING' 'CGIKEYS CGIVALS'=: a:"_`(<"1@|:)@.(0<#) qsparse q case. 'POST' do. q=. stdin '' select. (]{.~';'i.~]) env 'CONTENT_TYPE' case. 'application/x-www-form-urlencoded' do. 'CGIKEYS CGIVALS'=: a:"_`(<"1@|:)@.(0<#) qsparse q case. 'multipart/form-data' do. NB. t=. q fwrite jpath '~CGI/tmp/temp.stdin' NB. dat=. qmparse q 'CGIKEYS CGIVALS CGIISFL CGIFNMS CGICTPS CGIFDAT'=: a:"_`(<"1@|:)@.(0<#) qmparse q case. do. NB. signal invalid CONTENT_TYPE end. case. do. NB. signal invalid Method end. end. CGIKEYS )
The following verb qmparse has been added to do the parsing work for this form of data.
qmparse=: 3 : 0 (env 'CONTENT_TYPE') qmparse y : bd=. x ([}.~[:>:i.) '=' NB. get boundary dat=. (#bd)}.each (bd E. y) <;.1 y NB. box each section ndx=. {.each I. each (<CRLF,CRLF) E. each dat NB. find header/body split dat=. (0&<@:>ndx)#dat NB. drop out non-fields ndx=. (0&<@:>ndx)# ndx dat=. ndx split each dat NB. split header/body hdrs=. 0{::each dat dat=. 1{::each dat s=. 'name=' ndx=. {.each I. each (<s) E. each hdrs NB. find string starts ndx=. (<#s) + each ndx NB. add string lengths keys=. ndx }.each hdrs NB. drop til after keys=. (*./\each -. each keys e. each <';',CR)# each keys NB. drop everything from ; or CR keys=. keys-.each <'"' NB. remove "s s=. 'filename=' ndx=. {.each I. each (<s) E. each hdrs isfile=. 0&<@:>ndx NB. is section a file? ndx=. (<#s) + each isfile#ndx fnmes=. ndx }. each isfile#hdrs fnmes=. (*./\each -. each fnmes e. each <';',CR)# each fnmes fnmes=. fnmes-.each <'"' s=. 'Content-Type: ' ndx=. {.each I. each (<s) E. each isfile#hdrs ndx=. (<#s)+each ndx contypes=. ndx }. each isfile#hdrs contypes=. (*./\each -. each contypes e. each <';',CR)# each contypes contypes=. contypes-.each <'" ' dat=. _4}.each 4}.each dat NB. drop 2CRLFs at start and CRLF-- at end fdat=. isfile#dat dat=. fnmes (I.isfile) }dat NB. for files replace value with filename isfull=. 0&<@:>#each fdat if. +./isfull do. NB. create filenames for writing if data exists tp=. jpath '~CGI/tmp/' NB. path for temp folder fnmes=. (<tp), each isfull#fnmes NB. ***generate new unique mangled filenames here?? end. fnmes=. isfile expand ,.fnmes contypes=. isfile expand ,.contypes fdat=. isfile expand ,.fdat keys,.dat,.(<@>isfile),.fnmes,.contypes,.fdat )
-- Ric Sherlock <<DateTime(2007-05-29T17:01:22Z)>>