% $OpenXM: OpenXM/src/kan96xx/Doc/cgi.sm1,v 1.18 2020/03/12 07:33:03 takayama Exp $ % OpenXM/src/polymake/cgi/cgi-polymake.sh % is a shell script to call sm1/polymake as a CGI script. % Override as /doPolymake {doPolymake.OoHG} def if you need. /cgi.verbose 0 def [(plugin-cgi) [(Key words: ) ( cgiUrlEncodingToKeyValuePair) ( cgiKeyValuePairToHttpString) ( cgiKeyValuePairToUrlEncodingString) ( cgiStringToUrlEncoding) ( cgiUrlEncodedStringToObj) ( cgiHttpToKeyValuePair) ]] putUsages % A sample code % (OpenXM) cgiQueryGoogle --> it does not work well. /cgiQueryGoogle { /key set [[(URL),(/search)], [(hl),(ja)], [(ie),(UTF-8)], [(q),key]] /kv set [(cgiKeyValuePairToUrlEncodingString) kv] extension /sss set [(GET ) , sss , ( HTTP/0.9) , nl , nl ] cat /sss2 set [(sm1.socket) (connect) [80 (www.google.co.jp)]] extension 0 get /goo set [(sm1.socket) (write) [goo sss2]] extension goo readHTTP0 /pp set pp message [(sm1.socket) (close) [goo]] extension [(cgiHttpToKeyValuePair) pp] extension /pp2 set } def % A sample % (www.math.kobe-u.ac.jp) cgiGetIndex /cgiGetIndex { /url set [[(URL),(/index.html)] ] /kv set [(cgiKeyValuePairToUrlEncodingString) kv] extension /sss set % [(GET ) , sss , ( HTTP/0.9) , nl , nl ] cat /sss2 set [(GET ) , sss , ( HTTP/0.9) , nl , (HOST: ) , url , nl nl ] cat /sss2 set sss2 message [(sm1.socket) (connect) [80 url]] extension 0 get /goo set [(sm1.socket) (write) [goo sss2]] extension goo readHTTP0 /pp set pp message [(sm1.socket) (close) [goo]] extension [(cgiHttpToKeyValuePair) pp] extension /pp2 set } def [(readHTTP0) [(fd readHTTP0 result-str) (Read data from fd until the connection is closed.) (Example:) $[(sm1.socket) (connect) [80 (www.math.kobe-u.ac.jp)]] extension $ $ 0 get /goo set $ $goo readHTTP0 /pp set pp message$ $[(sm1.socket) (close) [goo]] extension $ ]] putUsages /readHTTP0 { /arg1 set [/fd /sss /pp /pp2 /nn] pushVariables [ /fd arg1 def /sss [ ] def { [(sm1.socket) (select) [fd -1]] extension { } { (select error) error } ifelse [(sm1.socket) (read) [fd]] extension /pp set pp length 0 eq { exit } { } ifelse sss pp append /sss set } loop sss cat /arg1 set ] pop popVariables arg1 } def % ----------------------- server side ----------------------- % command filename action /cgiPolymake.polymakeName (polymake) def %/cgiPolymake.polymakeName (polymake_dummy) def %/cgiPolymake.polymakeName (hoge) def /cgiPolymake.log 1 def [(cgiPolymake) [(Make sm1 to a polymake server based on CGI/OoHG) $ sm1 -q -s "[(parse) (cgi.sm1) pushfile] extension cgiPolymake quit " $ ]] putUsages % Server-side-script % oxMessageBody=action input-data-for-polymake % t.t : oxMessageBody=FACETS++POINTS%0A1+0+0+%0A1+1+0+%0A1+0+1%0A % t?oxMe... % env CONTENT_LENGTH=57 sm1 -q -s "[(parse) (cgi.sm1) pushfile] extension cgiPolymake quit " ) nl (Input
action polymake-data
) nl (Example:
 ) nl
    (FACETS  POINTS) nl
    (1 0 0 ) nl
    (1 1 0 ) nl
    (1 0 1 ) nl
    (
) nl (
) nl () nl () nl (
) nl () nl ] cat def /cgi.body.http0 (Content-Type: text/plain) def /cgiPolymake.0 { /arg1 set [/sss /kv /comm /i /acti0 /pError] pushVariables [ /sss arg1 def % Step 1. analyze the query string in URL encoding. [(cgiUrlEncodingToKeyValuePair) sss] extension /kv set kv (oxMessageBody) getNode /comm set % [nl nl] cat message sss message kv message % for debug. % Step 2. Extract action part and file part for polymake. comm (array) dc /comm set /i 0 def [ 0 1, comm length 1 sub { /i set comm,i,get 33 lt { exit } { comm,i,get } ifelse } for ] /acti0 set acti0 { (string) dc } map cat /acti0 set /cgi.body comm def 0 1 i { cgi.body rest /cgi.body set } for cgi.body { (string) dc } map cat /cgi.body set % Step 3. Calling polymake % acti0 cgi.body /pError [ ] def % cgi.body --> oxsVarToFile(), value is not a string object ... % [(polymake) (stringInOut://cgi.body) acti0] addStdoutStderr % It is not a bug; .body is removed from the variable name. /cgi_body cgi.body def [cgiPolymake.polymakeName (stringInOut://cgi_body.poly) acti0] addStdoutStderr oxshell pop pError [@@@stdout @@@stderr] append /pError set /cgi.body cgi_body def ] pop popVariables } def /cgi.test0 { [[(URL) (hoge)] [(oxMessageBody) [(FACETS ) (POINTS) nl (1 0 0) nl (1 1 0) nl (1 0 1) nl (1 1 1) nl ] cat ]] /ff set [(cgiKeyValuePairToUrlEncodingString) ff] extension /ff1 set ff1 message ff1 cgiPolymake.0 cgi.body message } def /cgiReplyInHttp0 { /arg1 set [/ss /sskv] pushVariables [ /ss arg1 def [[(Content-Body) ss] % [(Content-Type) (text/plain)] [(oxshell-stdout) [(cgiStringToUrlEncoding) @@@stdout] extension] [(oxshell-stderr) [(cgiStringToUrlEncoding) @@@stderr] extension] ] /sskv set [(cgiKeyValuePairToHttpString) sskv] extension /arg1 set ] pop arg1 } def % ------------ client side script --------------- /cgiQueryPolymake.hostname (polymake.math.kobe-u.ac.jp) def /cgiQueryPolymake.cginame (/cgi-bin/cgi-polymake.sh) def %This host and cgi are version 2.0 polymake. dim, ... are different with new versions. /cgiQueryPolymake { cgiQueryPolymake.curl } def %/cgiQueryPolymake { cgiQueryPolymake.native } def /cgiQueryPolymake.curl { /arg2 set /arg1 set [/saction /sfile /ff /ff1 /sss2 /goo /pp /pp2 /key /body /fd /pid] pushVariables [ /saction arg1 def /sfile arg2 def % step1. Generate query in URL encoding. [(http://) cgiQueryPolymake.hostname cgiQueryPolymake.cginame] cat /ff1 set % full URL necessary for virtual host of apache. [[(oxMessageBody) [saction ( ) sfile nl ] cat ] ] /ff set ff 0 get 0 get /key set ff 0 get 1 get /body set /pid [(getpid)] extension toString def % step 2. Call the server and get the response in pp /cgi.verbose 1 def [(/tmp/sm1-q-cgi.txt) pid] cat (w) file /fd set fd body writestring fd closefile % [(curl) (--form) [key (=@/tmp/sm1-q-cgi.txt)] cat ff1] /ff set % ff addStdoutStderr oxshell @@@stdout /pp set [(curl --form ) [key (=@/tmp/sm1-q-cgi.txt) pid ( )] cat ff1 (>/tmp/sm1-q-cgi-out.txt) pid] cat /ff set ff system [nl [(/tmp/sm1-q-cgi-out.txt) pid] cat pushfile] cat /pp set %% Store workfiles under OpenXM_tmp [(mkdir -p ) [(getenv) (OpenXM_tmp)] extension] cat system [(mv /tmp/sm1-q-cgi.txt) pid ( ) [(getenv) (OpenXM_tmp)] extension] cat system [(mv /tmp/sm1-q-cgi-out.txt) pid ( ) [(getenv) (OpenXM_tmp)] extension] cat system cgi.verbose { pp message } { } ifelse [(cgiHttpToKeyValuePair) pp] extension /pp2 set pp2 message % step 3. Analyze the response. [pp2 (Content-Body) getNode pp2 (oxshell-stdout) getNode pp2 (oxshell-stderr) getNode ] /arg1 set ] pop popVariables arg1 } def /cgiQueryPolymake.native { /arg2 set /arg1 set [/saction /sfile /ff /ff1 /sss2 /goo /pp /pp2] pushVariables [ /saction arg1 def /sfile arg2 def % step1. Generate query in URL encoding. [(http://) cgiQueryPolymake.hostname cgiQueryPolymake.cginame] cat /ff1 set % full URL necessary for virtual host of apache. [[(oxMessageBody) [saction ( ) sfile nl ] cat ] ] /ff set [(cgiKeyValuePairToUrlEncodingString) ff] extension /ff set [(POST ) , ff1 , ( HTTP/0.9) , nl , % (Connection: Keep-Alive) , nl , (HOST: ) cgiQueryPolymake.hostname , nl , (Content-length: ) , ff length (dollar) dc , nl , nl ff nl] cat /sss2 set % step 2. Call the server and get the response in pp [(sm1.socket) (connect) [80 cgiQueryPolymake.hostname]] extension 0 get /goo set [(sm1.socket) (write) [goo sss2]] extension goo readHTTP0 /pp set % For the case of error. [(regexec) (200 OK) [pp]] extension length 0 eq { (sss2=) message sss2 message (pp=) message pp message (cgi.sm1: there seems to be an error in the HTTP connection.) } { } ifelse cgi.verbose { pp message } { } ifelse [(sm1.socket) (close) [goo]] extension [(cgiHttpToKeyValuePair) pp] extension /pp2 set % step 3. Analyze the response. [pp2 (Content-Body) getNode pp2 (oxshell-stdout) getNode pp2 (oxshell-stderr) getNode ] /arg1 set ] pop popVariables arg1 } def /cgi.test1 { (FACETS) [(POINTS) nl (1 0 0 ) nl (1 1 0 ) nl (1 0 1 ) nl ] cat cgiQueryPolymake message } def % Overrides doPolymake %/doPolymake { doPolymake.OoHG } def %/polymake.start { polymake.start.OoHG } def [(doPolymake.OoHG) [(doPolymake.local calls the local polymake.) (This function calls http://polymake.math.kobe-u.ac.jp/cgi-bin/cgi-polymake.sh) (to make a computation in polymake.) (The host name and the cgi name are set to the variable) ( cgiQueryPolymake.hostname and cgiQueryPolymake.cginame) (See doPolymake for the syntax. doPolymake.OoHG may overrides doPolymake.) (If you use curl to call the server execute) ( usePolymake.OoHG.curl) (after loading cgi.sm1) ]] putUsages /doPolymake.OoHG { /arg1 set [/in-doPolymake.OoHG /pAction /pData /pNative /ptree /pResult /pError ] pushVariables [ arg1 0 get /pAction set arg1 1 get /pData set polymake.start.OoHG /pError [ ] def %% step 1: polymake tfb ===> polymake native data @@@polymake.k0.ccc ( polymake=Object; ) oxexecutestring @@@polymake.k0.ccc ( QuoteMode(1); ) oxexecutestring @@@polymake.k0.ccc [pData ( ;)] cat oxexecutestring @@@polymake.k0.ccc oxpopcmo /ptree set @@@polymake.k0.ccc ( QuoteMode(0); ) oxexecutestring [(treeToPolymake) ptree] extension /pNative set %% step 2: calling the polymake % [(which) (polymake)] oxshell tag 0 eq 1 % always call web service { % cgi-polymake (Trying web service.) message pAction pNative cgiQueryPolymake /doPolymake.OoHG.result set doPolymake.OoHG.result /@@@doPolymake.vars set [(regexec) (Not Found) [doPolymake.OoHG.result 0 get ]] extension length 0 eq not { doPolymake.OoHG.result message (The polymake cgi seems to be out of service.) error } { } ifelse doPolymake.OoHG.result 0 get /pNative set pError doPolymake.OoHG.result rest append /pError set } { % local polymake [(polymake) (stringInOut://pNative.poly) pAction] addStdoutStderr oxshell pop pError [@@@stdout @@@stderr] append /pError set } ifelse %% step 3: polymake native data to polymake tfb [(polymake2tfb) (<) (stringIn://pNative) (>) (stringOut://pResult) (2>) (stringOut://@@@stderr)] oxshell pop pError [@@@stderr] append /pError set %% step 4: get also tree style data. @@@polymake.k0.ccc ( polymake=Object; ) oxexecutestring @@@polymake.k0.ccc ( QuoteMode(1); ) oxexecutestring @@@polymake.k0.ccc [pResult ( ;)] cat oxexecutestring @@@polymake.k0.ccc oxpopcmo /ptree set @@@polymake.k0.ccc ( QuoteMode(0); ) oxexecutestring [pResult ptree pError] /arg1 set ] pop popVariables arg1 } def /polymake.start.OoHG { (ox.k0.loaded) boundp { } { [(parse) (ox.sm1) pushfile] extension /@@@polymake.k0.ccc [ ] def } ifelse @@@polymake.k0.ccc [ ] eq { k0connectr /@@@polymake.k0.ccc oxk0.ccc def /oxk0.ccc [ ] def @@@polymake.k0.ccc oxsetmathcap @@@polymake.k0.ccc oxmathcap } { } ifelse @@@polymake.k0.ccc 0 get (closed) eq { k0connectr /@@@polymake.k0.ccc oxk0.ccc def /oxk0.ccc [ ] def @@@polymake.k0.ccc oxsetmathcap @@@polymake.k0.ccc oxmathcap } { } ifelse [(which) (polymake2tfb)] oxshell tag 0 eq { (polymake2tfb is not installed in this system.) error } { } ifelse } def /usePolymake.local { /doPolymake { doPolymake.local } def /polymake.start { polymake.start.local } def } def /usePolymake.OoHG.native { /doPolymake { doPolymake.OoHG } def /polymake.start { polymake.start.OoHG } def /cgiQueryPolymake { cgiQueryPolymake.native } def } def /usePolymake.OoHG.curl { [(which) (curl)] oxshell tag 0 eq { (Error in usePolymake.OoHG.curl: curl is not found.) error } { } ifelse /doPolymake { doPolymake.OoHG } def /polymake.start { polymake.start.OoHG } def /cgiQueryPolymake { cgiQueryPolymake.curl } def } def [(usePolymake.local) [(doPolymake calls local polymake) ]] putUsages [(usePolymake.OoHG.native) [(doPolymake = doPolymake.OoHG with cgiQueryPolymake.native) (cf. doPolymake.OoHG) (hostname is set in cgiQueryPolymake.hostname) (cginame is set in cgiQueryPolymake.cginame) ]] putUsages [(usePolymake.OoHG.curl) [(doPolymake = doPolymake.OoHG with cgiQueryPolymake.curl) (It should be used when cgiQueryPolymake.native does not work) (over, e.g., a reverse proxy.) (The command curl is required. cf. cgi.verbose, doPolymake.OoHG) (hostname is set in cgiQueryPolymake.hostname) (cginame is set in cgiQueryPolymake.cginame) ]] putUsages