diff options
author | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-14 15:54:55 +0000 |
---|---|---|
committer | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-14 15:54:55 +0000 |
commit | d017e93a6a22f6d4c2c7e76deec1cdeca632135e (patch) | |
tree | 7703052799dc65cee9eacf6f573fb5c4afcd3936 |
R6.6 is the Xorg base-lineXORG-MAINXORG-STABLE
55 files changed, 11797 insertions, 0 deletions
diff --git a/cgi-bin/bitmap b/cgi-bin/bitmap new file mode 100644 index 0000000..246b1c8 --- /dev/null +++ b/cgi-bin/bitmap @@ -0,0 +1,241 @@ +#!/usr/local/bin/perl +# $Xorg: bitmap,v 1.3 2000/08/17 19:54:57 cpqbld Exp $ +# CGI script to launch xclock +# + +# define every program we are going to use +$project_root = "XPROJECT_ROOT"; +$command = $project_root . "/bin/bitmap"; +$xfindproxy = $project_root . "/bin/xfindproxy"; +$xauth = $project_root . "/bin/xauth"; + +# address of our proxy manager +$proxymngr = "XPROXYMNGR"; + +# make stderr and stdout unbuffered so nothing get lost +select(STDERR); $| = 1; +select(STDOUT); $| = 1; + +# print out header to content httpd no matter what happens later on +print "Content-type: text/plain\r\n\r\n"; + +# let's try not to leave any file behind us if things go really wrong +sub handler { # 1st argument is signal name + local($sig) = @_; + # send error code first and error msg then + print "1\n"; + print "Error: Caught a SIG$sig -- Oops!\n"; + system "rm -f /tmp/*$$"; + exit(0); +} + +$SIG{'INT'} = 'handler'; +$SIG{'QUIT'} = 'handler'; +$SIG{'TERM'} = 'handler'; +$SIG{'KILL'} = 'handler'; +$SIG{'STOP'} = 'handler'; +# this one is perhaps the most important one, since this is what we should get +# when the user interrupts the GET request. +$SIG{'PIPE'} = 'handler'; + + +###################### +# sub procedures +###################### + +# parse an url param of the form: proto:display[;param] +sub parse_url { + local($input, *proto_ret, *display_ret, *param_ret) = @_; + + # extract param first + ($sub_url, $param_ret) = split(/;/, $input, 2); + # then extract proto and display + ($proto_ret, $display_ret) = split(/:/, $sub_url, 2); + +} + +# parse an auth param of the form: auth=name:key +sub parse_auth { + local($input, *name_ret, *key_ret) = @_; + + if ($input) { + ($param_name, $param_value) = split(/=/, $input, 2); + if ($param_name eq "auth") { + ($name_ret, $key_ret) = split(/:/, $param_value, 2); + } + } +} + +# parse an LBX param of the form: either NO or YES[;auth=...] +sub parse_lbx_param { + local($input, *lbx_ret, *lbx_auth_name_ret, *lbx_auth_key_ret) = @_; + + ($lbx_ret, $lbxparam) = split(/;/, $input, 2); + if ($lbx_ret eq "YES") { + # look for an authentication auth in param + &parse_auth($lbxparam, *lbx_auth_name_ret, *lbx_auth_key_ret); + } +} + +# setup proxy with possible auth, change display parameter when succeeding +sub setup_lbx_proxy { + local(*display, $auth_name, $auth_key) = @_; + + # setup auth file for xfindproxy + if ($auth_name && $auth_key) { + $proxy_input = "/tmp/xlbxauth.$$"; + open(PROXYINPUT, ">$proxy_input"); + print PROXYINPUT "$auth_name\n$auth_key\n"; + close(PROXYINPUT); + $findproxy_param = " -auth <$proxy_input"; + } else { + $findproxy_param = ""; + } + + # remove screen number specification if there is one + ($host, $tmp) = split(/:/, $display); + ($dpy, $screen) = split(/\./, $tmp); + $server = $host . ":" . $dpy; + + # let's get an LBX proxy + open(PROXY, "$xfindproxy -manager $proxymngr -server $server -name LBX $findproxy_param|"); + # get the proxy address from xfindproxy output + while (<PROXY>) { + chop; + ($proxy_dpy, $proxy_port) = split(/:/, $_); + if ($proxy_dpy && $proxy_port) { + # build up the new display name + $display = $proxy_dpy . ":" . $proxy_port; + if ($screen) { + $display .= "." . $screen; + } + last; + } + } + close(PROXY); + + if ($proxy_input) { + system "rm -f $proxy_input"; + } +} + +# add entry in authority file +sub add_auth { + local($display, $auth_name, $auth_key) = @_; + + system "$xauth add $display $auth_name $auth_key"; +} + + +###################### +# the main thing now +###################### + + +# handle both ways of getting query +if ($ENV{'QUERY_STRING'}) +{ + $query = $ENV{'QUERY_STRING'}; +} else { + $query = $ARGV[0]; +} + +if ($query) +{ + $cleanup = ""; + + # parse params + %params = split(/\?/, $query); + foreach $param (split(/\?/, $query)) { + + ($name, $value) = split(/=/, $param, 2); + if ($name eq "WIDTH") { + $width = $value; + } elsif ($name eq "HEIGHT") { + $height = $value; + } elsif ($name eq "UI") { + # look at what we got for the UI parameter, it should be of the + # form: x11:hostname:dpynum[.screen][;auth=...] + &parse_url($value, *proto, *display, *ui_param); + if ($proto eq 'x11') { + $xdisplay = $display; + } else { + # unknown UI protocol!! + } + # look for an authentication auth in param + &parse_auth($ui_param, *xui_auth_name, *xui_auth_key); + + } elsif ($name eq "X-UI-LBX") { + &parse_lbx_param($value, *xui_lbx, + *xui_lbx_auth_name, *xui_lbx_auth_key); + } + } + + # set authority file for X + $ENV{'XAUTHORITY'} = "/tmp/xauth.$$"; + # and define its related cleanup command + $cleanup = "rm -f $ENV{'XAUTHORITY'}"; + + # process params + if ($xdisplay) { + + if ($xui_lbx eq "YES") { + &setup_lbx_proxy(*xdisplay, $xui_lbx_auth_name, $xui_lbx_auth_key); + } + if ($xui_auth_name && $xui_auth_key) { + &add_auth($xdisplay, $xui_auth_name, $xui_auth_key); + } + # add display specification to the command line + $command .= " -display $xdisplay"; + # and put it in the environment too for good measure. + $ENV{'DISPLAY'} = $xdisplay; + } + if ($width && $height) { + # add geometry specification to the command line + $command .= " -geometry ${width}x${height}"; + } + + # Start application followed by a cleanup command in the background. + # The ouput and input need to be redirected, otherwise the CGI process will + # be kept alive by the http server and the browser will keep waiting for + # the end of the stream... + # Catching application's failure is not easy since we want to run it in + # background and therefore we can't get its exit status. However, we can + # catch obvious errors by logging its output and after some time looking + # at whether the application is still running or not. This is determine + # based on some kind of "lock" file. + # This is quite complicated but it allows to get some error report without + # leaving any file behind us in any case. + + $LOCK= "/tmp/lock.$$"; + $LOG= "/tmp/log.$$"; + $LOG2 = "/tmp/log2.$$"; + system "(touch $LOCK; _s=true; $command >$LOG 2>&1 || _s=false; if \$_s; then rm $LOG; else rm $LOCK; fi; if [ -f $LOG2 ]; then rm $LOG2; fi; $cleanup) >/dev/null 2>&1 </dev/null &"; + + # sleep for a while to let the application start or fail + # it's up to you to decide how long it could for the application to fail... + sleep(5); + + # now lets see if the application died + if (open(LOCK, "<$LOCK")) { + close(LOCK); + # the application seems to be running, remove lock and rename the log + # so that it gets removed no matter how the application exits later on + system "rm $LOCK; mv $LOG $LOG2"; + # send success error code as reply + print "0\n"; + } else { + # the lock file is gone, for sure the application has failed so send + # back error code and log + print "1\n"; + system "cat $LOG; rm $LOG"; + } + +} else { + + # reply with an error message + print "This script requires to be given the proper RX arguments +to run successfully. +"; + +} diff --git a/cgi-bin/dtcm b/cgi-bin/dtcm new file mode 100644 index 0000000..4a201ad --- /dev/null +++ b/cgi-bin/dtcm @@ -0,0 +1,281 @@ +#!/usr/local/bin/perl +# $Xorg: dtcm,v 1.3 2000/08/17 19:54:57 cpqbld Exp $ +# CGI script to launch dtcm +# + +# define every program we are going to use +$project_root = "XPROJECT_ROOT"; +$command = "CGIBINDIR/dtcm.sh"; +$xfindproxy = $project_root . "/bin/xfindproxy"; +$xauth = $project_root . "/bin/xauth"; + +# address of our proxy manager +$proxymngr = "XPROXYMNGR"; + +# make stderr and stdout unbuffered so nothing get lost +select(STDERR); $| = 1; +select(STDOUT); $| = 1; + +# print out header to content httpd no matter what happens later on +print "Content-type: text/plain\r\n\r\n"; + +# let's try not to leave any file behind us if things go really wrong +sub handler { # 1st argument is signal name + local($sig) = @_; + # send error code first and error msg then + print "1\n"; + print "Error: Caught a SIG$sig -- Oops!\n"; + system "rm -f /tmp/*$$"; + exit(0); +} + +$SIG{'INT'} = 'handler'; +$SIG{'QUIT'} = 'handler'; +$SIG{'TERM'} = 'handler'; +$SIG{'KILL'} = 'handler'; +$SIG{'STOP'} = 'handler'; +# this one is perhaps the most important one, since this is what we should get +# when the user interrupts the GET request +$SIG{'PIPE'} = 'handler'; + + +###################### +# sub procedures +###################### + +# parse an url param of the form: proto:display[;param] +sub parse_url { + local($input, *proto_ret, *display_ret, *param_ret) = @_; + + # extract param first + ($sub_url, $param_ret) = split(/;/, $input, 2); + # then extract proto and display + ($proto_ret, $display_ret) = split(/:/, $sub_url, 2); + +} + +# parse an auth param of the form: auth=name:key +sub parse_auth { + local($input, *name_ret, *key_ret) = @_; + + if ($input) { + ($param_name, $param_value) = split(/=/, $input, 2); + if ($param_name eq "auth") { + ($name_ret, $key_ret) = split(/:/, $param_value, 2); + } + } +} + +# parse an LBX param of the form: either NO or YES[;auth=...] +sub parse_lbx_param { + local($input, *lbx_ret, *lbx_auth_name_ret, *lbx_auth_key_ret) = @_; + + ($lbx_ret, $lbxparam) = split(/;/, $input, 2); + if ($lbx_ret eq "YES") { + # look for an authentication auth in param + &parse_auth($lbxparam, *lbx_auth_name_ret, *lbx_auth_key_ret); + } +} + +# setup proxy with possible auth, change display parameter when succeeding +sub setup_lbx_proxy { + local(*display, $auth_name, $auth_key) = @_; + + # setup auth file for xfindproxy + if ($auth_name && $auth_key) { + $proxy_input = "/tmp/xlbxauth.$$"; + open(PROXYINPUT, ">$proxy_input"); + print PROXYINPUT "$auth_name\n$auth_key\n"; + close(PROXYINPUT); + $findproxy_param = " -auth <$proxy_input"; + } else { + $findproxy_param = ""; + } + + # remove screen number specification if there is one + ($host, $tmp) = split(/:/, $display); + ($dpy, $screen) = split(/\./, $tmp); + $server = $host . ":" . $dpy; + + # let's get an LBX proxy + open(PROXY, "$xfindproxy -manager $proxymngr -server $server -name LBX $findproxy_param|"); + # get the proxy address from xfindproxy output + while (<PROXY>) { + chop; + ($proxy_dpy, $proxy_port) = split(/:/, $_); + if ($proxy_dpy && $proxy_port) { + # build up the new display name + $display = $proxy_dpy . ":" . $proxy_port; + if ($screen) { + $display .= "." . $screen; + } + last; + } + } + close(PROXY); + + if ($proxy_input) { + system "rm -f $proxy_input"; + } +} + +# add entry in authority file +sub add_auth { + local($display, $auth_name, $auth_key) = @_; + + system "$xauth add $display $auth_name $auth_key"; +} + + +###################### +# the main thing now +###################### + + +# handle both ways of getting query +if ($ENV{'QUERY_STRING'}) +{ + $query = $ENV{'QUERY_STRING'}; +} else { + $query = $ARGV[0]; +} + +if ($query) +{ + $cleanup = ""; + + # parse params + %params = split(/\?/, $query); + foreach $param (split(/\?/, $query)) { + + ($name, $value) = split(/=/, $param, 2); + if ($name eq "WIDTH") { + $width = $value; + } elsif ($name eq "HEIGHT") { + $height = $value; + } elsif ($name eq "UI") { + # look at what we got for the UI parameter, it should be of the + # form: x11:hostname:dpynum[.screen][;auth=...] + &parse_url($value, *proto, *display, *ui_param); + if ($proto eq 'x11') { + $xdisplay = $display; + } else { + # unknown UI protocol!! + } + # look for an authentication auth in param + &parse_auth($ui_param, *xui_auth_name, *xui_auth_key); + + } elsif ($name eq "X-UI-LBX") { + &parse_lbx_param($value, *xui_lbx, + *xui_lbx_auth_name, *xui_lbx_auth_key); + } elsif ($name eq "PRINT") { + # look at what we got for the PRINT parameter, it should be of the + # form: xprint:[printer@]hostname:dpynum[;auth=...] + + &parse_url($value, *proto, *display, *prt_param); + if ($proto eq 'xprint') { + $xprint = $display; + } else { + # unknown PRINT protocol!! + } + # look for an authentication auth in param + &parse_auth($prt_param, *xprt_auth_name, *xprt_auth_key); + + } elsif ($name eq "X-PRINT-LBX") { + &parse_lbx_param($value, *xprt_lbx, + *xprt_lbx_auth_name, *xprt_lbx_auth_key); + } + } + + # set a common authority file for X and XPrint + $ENV{'XAUTHORITY'} = "/tmp/xauth.$$"; + # and define its related cleanup command + $cleanup = "rm -f $ENV{'XAUTHORITY'}"; + + # process params + # Note: we want to process printing first so if for some reason we end up + # with a conflict between the two authorizations, the display one wins + if ($xprint) { + # extract print server from printer specification (xpress@foo:0) + ($xprt_printer, $xprt_display) = split(/\@/, $xprint, 2); + if (! $xprt_display) { + # printer not specified + $xprt_display = $xprt_printer; + $xprt_printer = ""; + } + + if ($xprt_lbx eq "YES") { + &setup_lbx_proxy(*xprt_display, + $xprt_lbx_auth_name, $xprt_lbx_auth_key); + # rebuild printer specification with new xprt_display + $xprint = $xprt_printer . "@" . $xprt_display; + } + if ($xprt_auth_name && $xprt_auth_key) { + &add_auth($xprt_display, $xprt_auth_name, $xprt_auth_key); + } + # specify printer via the environment + $ENV{'XPRINTER'} = $xprint; + $ENV{'XPSERVERLIST'} = $xpr_display; + } + if ($xdisplay) { + + if ($xui_lbx eq "YES") { + &setup_lbx_proxy(*xdisplay, $xui_lbx_auth_name, $xui_lbx_auth_key); + } + if ($xui_auth_name && $xui_auth_key) { + &add_auth($xdisplay, $xui_auth_name, $xui_auth_key); + } + # add display specification to the command line + $command .= " -display $xdisplay"; + # and put it in the environment too for good measure. + $ENV{'DISPLAY'} = $xdisplay; + } + if ($width && $height) { + # add geometry specification to the command line + $command .= " -geometry ${width}x${height}"; + } + + # Start application followed by a cleanup command in the background. + # The ouput and input need to be redirected, otherwise the CGI process will + # be kept alive by the http server and the browser will keep waiting for + # the end of the stream... + # Catching application's failure is not easy since we want to run it in + # background and therefore we can't get its exit status. However, we can + # catch obvious errors by logging its output and after some time looking + # at whether the application is still running or not. This is determine + # based on some kind of "lock" file. + # This is quite complicated but it allows to get some error report without + # leaving any file behind us in any case. + + $LOCK= "/tmp/lock.$$"; + $LOG= "/tmp/log.$$"; + $LOG2 = "/tmp/log2.$$"; + system "(touch $LOCK; _s=true; $command >$LOG 2>&1 || _s=false; if \$_s; then rm $LOG; else rm $LOCK; fi; if [ -f $LOG2 ]; then rm $LOG2; fi; $cleanup) >/dev/null 2>&1 </dev/null &"; + + # sleep for a while to let the application start or fail + # it's up to you to decide how long it could for the application to fail... + sleep(5); + + # now lets see if the application died + if (open(LOCK, "<$LOCK")) { + close(LOCK); + # the application seems to be running, remove lock and rename the log + # so that it gets removed no matter how the application exits later on + system "rm $LOCK; mv $LOG $LOG2"; + # send success error code as reply + print "0\n"; + } else { + # the lock file is gone, for sure the application has failed so send + # back error code and log + print "1\n"; + system "cat $LOG; rm $LOG"; + } + +} else { + + # reply with an error message + print "This script requires to be given the proper RX arguments +to run successfully. +"; + +} diff --git a/cgi-bin/dtcm.sh b/cgi-bin/dtcm.sh new file mode 100644 index 0000000..8e8a117 --- /dev/null +++ b/cgi-bin/dtcm.sh @@ -0,0 +1,7 @@ +#! /bin/csh -f +#$Xorg: dtcm.sh,v 1.3 2000/08/17 19:54:57 cpqbld Exp $ +setenv SHELL /bin/csh +setenv _RLD_ROOT /dev/null +setenv LD_LIBRARY_PATH /tools/packages/cde/alpha/osf1/cde_cst8/dt/lib:/tools/packages/cde/alpha/osf1/cde_cst8/x11/lib:/usr/shlib:/usr/ccs/lib:/usr/lib/cmplrs/cxx:/usr/lib/cmplrs/cc:/usr/lib:/usr/local/lib:/var/shlib +eval `/tools/packages/cde/alpha/osf1/cde_cst8/dt/bin/dtsearchpath | /usr/bin/sed -e 's^/usr/dt^/tools/packages/cde/alpha/osf1/cde_cst8/dt^g'` +exec /tools/packages/cde/alpha/osf1/cde_cst8/dt/bin/dtcm $* diff --git a/cgi-bin/excel b/cgi-bin/excel new file mode 100644 index 0000000..3b68e1e --- /dev/null +++ b/cgi-bin/excel @@ -0,0 +1,228 @@ +#!/usr/local/bin/perl +# $Xorg: excel,v 1.3 2000/08/17 19:54:57 cpqbld Exp $ +# CGI script to launch excel +# + +# define every program we are going to use +$project_root = "XPROJECT_ROOT"; +$command = "/usr/bin/rsh WINCENTERHOST wincenter"; +$xfindproxy = $project_root . "/bin/xfindproxy"; + +# address of our proxy manager +$proxymngr = "XPROXYMNGR"; + +# make stderr and stdout unbuffered so nothing get lost +select(STDERR); $| = 1; +select(STDOUT); $| = 1; + +# print out header to content httpd no matter what happens later on +print "Content-type: text/plain\r\n\r\n"; + +# let's try not to leave any file behind us if things go really wrong +sub handler { # 1st argument is signal name + local($sig) = @_; + # send error code first and error msg then + print "1\n"; + print "Error: Caught a SIG$sig -- Oops!\n"; + system "rm -f /tmp/*$$"; + exit(0); +} + +$SIG{'INT'} = 'handler'; +$SIG{'QUIT'} = 'handler'; +$SIG{'TERM'} = 'handler'; +$SIG{'KILL'} = 'handler'; +$SIG{'STOP'} = 'handler'; +# this one is perhaps the most important one, since this is what we should get +# when the user interrupts the GET request. +$SIG{'PIPE'} = 'handler'; + + +###################### +# sub procedures +###################### + +# parse an url param of the form: proto:display[;param] +sub parse_url { + local($input, *proto_ret, *display_ret, *param_ret) = @_; + + # extract param first + ($sub_url, $param_ret) = split(/;/, $input, 2); + # then extract proto and display + ($proto_ret, $display_ret) = split(/:/, $sub_url, 2); + +} + +# parse an auth param of the form: auth=name:key +sub parse_auth { + local($input, *name_ret, *key_ret) = @_; + + if ($input) { + ($param_name, $param_value) = split(/=/, $input, 2); + if ($param_name eq "auth") { + ($name_ret, $key_ret) = split(/:/, $param_value, 2); + } + } +} + +# parse an LBX param of the form: either NO or YES[;auth=...] +sub parse_lbx_param { + local($input, *lbx_ret, *lbx_auth_name_ret, *lbx_auth_key_ret) = @_; + + ($lbx_ret, $lbxparam) = split(/;/, $input, 2); + if ($lbx_ret eq "YES") { + # look for an authentication auth in param + &parse_auth($lbxparam, *lbx_auth_name_ret, *lbx_auth_key_ret); + } +} + +# setup proxy with possible auth, change display parameter when succeeding +sub setup_lbx_proxy { + local(*display, $auth_name, $auth_key) = @_; + + # setup auth file for xfindproxy + if ($auth_name && $auth_key) { + $proxy_input = "/tmp/xlbxauth.$$"; + open(PROXYINPUT, ">$proxy_input"); + print PROXYINPUT "$auth_name\n$auth_key\n"; + close(PROXYINPUT); + $findproxy_param = " -auth <$proxy_input"; + } else { + $findproxy_param = ""; + } + + # remove screen number specification if there is one + ($host, $tmp) = split(/:/, $display); + ($dpy, $screen) = split(/\./, $tmp); + $server = $host . ":" . $dpy; + + # let's get an LBX proxy + open(PROXY, "$xfindproxy -manager $proxymngr -server $server -name LBX $findproxy_param|"); + # get the proxy address from xfindproxy output + while (<PROXY>) { + chop; + ($proxy_dpy, $proxy_port) = split(/:/, $_); + if ($proxy_dpy && $proxy_port) { + # build up the new display name + $display = $proxy_dpy . ":" . $proxy_port; + if ($screen) { + $display .= "." . $screen; + } + last; + } + } + close(PROXY); + + if ($proxy_input) { + system "rm -f $proxy_input"; + } +} + +###################### +# the main thing now +###################### + + +# handle both ways of getting query +if ($ENV{'QUERY_STRING'}) +{ + $query = $ENV{'QUERY_STRING'}; +} else { + $query = $ARGV[0]; +} + +if ($query) +{ + $cleanup = ""; + + # parse params + %params = split(/\?/, $query); + foreach $param (split(/\?/, $query)) { + + ($name, $value) = split(/=/, $param, 2); + if ($name eq "WIDTH") { + $width = $value; + } elsif ($name eq "HEIGHT") { + $height = $value; + } elsif ($name eq "UI") { + # look at what we got for the UI parameter, it should be of the + # form: x11:hostname:dpynum[.screen][;auth=...] + &parse_url($value, *proto, *display, *ui_param); + if ($proto eq 'x11') { + $xdisplay = $display; + } else { + # unknown UI protocol!! + } + # look for an authentication auth in param + &parse_auth($ui_param, *xui_auth_name, *xui_auth_key); + + } elsif ($name eq "X-UI-LBX") { + &parse_lbx_param($value, *xui_lbx, + *xui_lbx_auth_name, *xui_lbx_auth_key); + } + } + + # process params + if ($xdisplay) { + + if ($xui_lbx eq "YES") { + &setup_lbx_proxy(*xdisplay, $xui_lbx_auth_name, $xui_lbx_auth_key); + } + if ($xui_auth_name && $xui_auth_key) { + $command .= " -auth $xdisplay $xui_auth_name $xui_auth_key"; + } + # add display specification to the command line + $command .= " -display $xdisplay"; + # and put it in the environment too for good measure. + $ENV{'DISPLAY'} = $xdisplay; + } + if ($width && $height) { + # add geometry specification to the command line + $command .= " -geometry ${width}x${height}"; + } + $command .= " -username IUSR_WINDY -password broadway -colors 16 -- C:/MSOffice/Excel/EXCEL.EXE C:/MSOffice/Excel/Examples/SAMPLES.XLS"; + + # Start application followed by a cleanup command in the background. + # The ouput and input need to be redirected, otherwise the CGI process will + # be kept alive by the http server and the browser will keep waiting for + # the end of the stream... + # Catching application's failure is not easy since we want to run it in + # background and therefore we can't get its exit status. However, we can + # catch obvious errors by logging its output and after some time looking + # at whether the application is still running or not. This is determine + # based on some kind of "lock" file. + # This is quite complicated but it allows to get some error report without + # leaving any file behind us in any case. + + $LOCK= "/tmp/lock.$$"; + $LOG= "/tmp/log.$$"; + $LOG2 = "/tmp/log2.$$"; + system "(touch $LOCK; _s=true; $command >$LOG 2>&1 || _s=false; if \$_s; then rm $LOG; else rm $LOCK; fi; if [ -f $LOG2 ]; then rm $LOG2; fi; $cleanup) >/dev/null 2>&1 </dev/null &"; + + # sleep for a while to let the application start or fail + # it's up to you to decide how long it could for the application to fail... + sleep(5); + + # now lets see if the application died + if (open(LOCK, "<$LOCK")) { + close(LOCK); + # the application seems to be running, remove lock and rename the log + # so that it gets removed no matter how the application exits later on + system "rm $LOCK; mv $LOG $LOG2"; + # send success error code as reply + print "0\n"; + } else { + # the lock file is gone, for sure the application has failed so send + # back error code and log + print "1\n"; + system "cat $LOG; rm $LOG"; + } + +} else { + + # reply with an error message + print "This script requires to be given the proper RX arguments +to run successfully. +"; + +} diff --git a/cgi-bin/xclock b/cgi-bin/xclock new file mode 100644 index 0000000..cbc1b83 --- /dev/null +++ b/cgi-bin/xclock @@ -0,0 +1,241 @@ +#!/usr/local/bin/perl +# $Xorg: xclock,v 1.3 2000/08/17 19:54:57 cpqbld Exp $ +# CGI script to launch xclock +# + +# define every program we are going to use +$project_root = "XPROJECT_ROOT"; +$command = $project_root . "/bin/xclock -update 1"; +$xfindproxy = $project_root . "/bin/xfindproxy"; +$xauth = $project_root . "/bin/xauth"; + +# address of our proxy manager +$proxymngr = "XPROXYMNGR"; + +# make stderr and stdout unbuffered so nothing get lost +select(STDERR); $| = 1; +select(STDOUT); $| = 1; + +# print out header to content httpd no matter what happens later on +print "Content-type: text/plain\r\n\r\n"; + +# let's try not to leave any file behind us if things go really wrong +sub handler { # 1st argument is signal name + local($sig) = @_; + # send error code first and error msg then + print "1\n"; + print "Error: Caught a SIG$sig -- Oops!\n"; + system "rm -f /tmp/*$$"; + exit(0); +} + +$SIG{'INT'} = 'handler'; +$SIG{'QUIT'} = 'handler'; +$SIG{'TERM'} = 'handler'; +$SIG{'KILL'} = 'handler'; +$SIG{'STOP'} = 'handler'; +# this one is perhaps the most important one, since this is what we should get +# when the user interrupts the GET request. +$SIG{'PIPE'} = 'handler'; + + +###################### +# sub procedures +###################### + +# parse an url param of the form: proto:display[;param] +sub parse_url { + local($input, *proto_ret, *display_ret, *param_ret) = @_; + + # extract param first + ($sub_url, $param_ret) = split(/;/, $input, 2); + # then extract proto and display + ($proto_ret, $display_ret) = split(/:/, $sub_url, 2); + +} + +# parse an auth param of the form: auth=name:key +sub parse_auth { + local($input, *name_ret, *key_ret) = @_; + + if ($input) { + ($param_name, $param_value) = split(/=/, $input, 2); + if ($param_name eq "auth") { + ($name_ret, $key_ret) = split(/:/, $param_value, 2); + } + } +} + +# parse an LBX param of the form: either NO or YES[;auth=...] +sub parse_lbx_param { + local($input, *lbx_ret, *lbx_auth_name_ret, *lbx_auth_key_ret) = @_; + + ($lbx_ret, $lbxparam) = split(/;/, $input, 2); + if ($lbx_ret eq "YES") { + # look for an authentication auth in param + &parse_auth($lbxparam, *lbx_auth_name_ret, *lbx_auth_key_ret); + } +} + +# setup proxy with possible auth, change display parameter when succeeding +sub setup_lbx_proxy { + local(*display, $auth_name, $auth_key) = @_; + + # setup auth file for xfindproxy + if ($auth_name && $auth_key) { + $proxy_input = "/tmp/xlbxauth.$$"; + open(PROXYINPUT, ">$proxy_input"); + print PROXYINPUT "$auth_name\n$auth_key\n"; + close(PROXYINPUT); + $findproxy_param = " -auth <$proxy_input"; + } else { + $findproxy_param = ""; + } + + # remove screen number specification if there is one + ($host, $tmp) = split(/:/, $display); + ($dpy, $screen) = split(/\./, $tmp); + $server = $host . ":" . $dpy; + + # let's get an LBX proxy + open(PROXY, "$xfindproxy -manager $proxymngr -server $server -name LBX $findproxy_param|"); + # get the proxy address from xfindproxy output + while (<PROXY>) { + chop; + ($proxy_dpy, $proxy_port) = split(/:/, $_); + if ($proxy_dpy && $proxy_port) { + # build up the new display name + $display = $proxy_dpy . ":" . $proxy_port; + if ($screen) { + $display .= "." . $screen; + } + last; + } + } + close(PROXY); + + if ($proxy_input) { + system "rm -f $proxy_input"; + } +} + +# add entry in authority file +sub add_auth { + local($display, $auth_name, $auth_key) = @_; + + system "$xauth add $display $auth_name $auth_key"; +} + + +###################### +# the main thing now +###################### + + +# handle both ways of getting query +if ($ENV{'QUERY_STRING'}) +{ + $query = $ENV{'QUERY_STRING'}; +} else { + $query = $ARGV[0]; +} + +if ($query) +{ + $cleanup = ""; + + # parse params + %params = split(/\?/, $query); + foreach $param (split(/\?/, $query)) { + + ($name, $value) = split(/=/, $param, 2); + if ($name eq "WIDTH") { + $width = $value; + } elsif ($name eq "HEIGHT") { + $height = $value; + } elsif ($name eq "UI") { + # look at what we got for the UI parameter, it should be of the + # form: x11:hostname:dpynum[.screen][;auth=...] + &parse_url($value, *proto, *display, *ui_param); + if ($proto eq 'x11') { + $xdisplay = $display; + } else { + # unknown UI protocol!! + } + # look for an authentication auth in param + &parse_auth($ui_param, *xui_auth_name, *xui_auth_key); + + } elsif ($name eq "X-UI-LBX") { + &parse_lbx_param($value, *xui_lbx, + *xui_lbx_auth_name, *xui_lbx_auth_key); + } + } + + # set authority file for X + $ENV{'XAUTHORITY'} = "/tmp/xauth.$$"; + # and define its related cleanup command + $cleanup = "rm -f $ENV{'XAUTHORITY'}"; + + # process params + if ($xdisplay) { + + if ($xui_lbx eq "YES") { + &setup_lbx_proxy(*xdisplay, $xui_lbx_auth_name, $xui_lbx_auth_key); + } + if ($xui_auth_name && $xui_auth_key) { + &add_auth($xdisplay, $xui_auth_name, $xui_auth_key); + } + # add display specification to the command line + $command .= " -display $xdisplay"; + # and put it in the environment too for good measure. + $ENV{'DISPLAY'} = $xdisplay; + } + if ($width && $height) { + # add geometry specification to the command line + $command .= " -geometry ${width}x${height}"; + } + + # Start application followed by a cleanup command in the background. + # The ouput and input need to be redirected, otherwise the CGI process will + # be kept alive by the http server and the browser will keep waiting for + # the end of the stream... + # Catching application's failure is not easy since we want to run it in + # background and therefore we can't get its exit status. However, we can + # catch obvious errors by logging its output and after some time looking + # at whether the application is still running or not. This is determine + # based on some kind of "lock" file. + # This is quite complicated but it allows to get some error report without + # leaving any file behind us in any case. + + $LOCK= "/tmp/lock.$$"; + $LOG= "/tmp/log.$$"; + $LOG2 = "/tmp/log2.$$"; + system "(touch $LOCK; _s=true; $command >$LOG 2>&1 || _s=false; if \$_s; then rm $LOG; else rm $LOCK; fi; if [ -f $LOG2 ]; then rm $LOG2; fi; $cleanup) >/dev/null 2>&1 </dev/null &"; + + # sleep for a while to let the application start or fail + # it's up to you to decide how long it could for the application to fail... + sleep(5); + + # now lets see if the application died + if (open(LOCK, "<$LOCK")) { + close(LOCK); + # the application seems to be running, remove lock and rename the log + # so that it gets removed no matter how the application exits later on + system "rm $LOCK; mv $LOG $LOG2"; + # send success error code as reply + print "0\n"; + } else { + # the lock file is gone, for sure the application has failed so send + # back error code and log + print "1\n"; + system "cat $LOG; rm $LOG"; + } + +} else { + + # reply with an error message + print "This script requires to be given the proper RX arguments +to run successfully. +"; + +} diff --git a/cgi-bin/xload b/cgi-bin/xload new file mode 100644 index 0000000..c0ab5c8 --- /dev/null +++ b/cgi-bin/xload @@ -0,0 +1,241 @@ +#!/usr/local/bin/perl +# $Xorg: xload,v 1.3 2000/08/17 19:54:57 cpqbld Exp $ +# CGI script to launch xload +# + +# define every program we are going to use +$project_root = "XPROJECT_ROOT"; +$command = $project_root . "/bin/xload -update 1"; +$xfindproxy = $project_root . "/bin/xfindproxy"; +$xauth = $project_root . "/bin/xauth"; + +# address of our proxy manager +$proxymngr = "XPROXYMNGR"; + +# make stderr and stdout unbuffered so nothing get lost +select(STDERR); $| = 1; +select(STDOUT); $| = 1; + +# print out header to content httpd no matter what happens later on +print "Content-type: text/plain\r\n\r\n"; + +# let's try not to leave any file behind us if things go really wrong +sub handler { # 1st argument is signal name + local($sig) = @_; + # send error code first and error msg then + print "1\n"; + print "Error: Caught a SIG$sig -- Oops!\n"; + system "rm -f /tmp/*$$"; + exit(0); +} + +$SIG{'INT'} = 'handler'; +$SIG{'QUIT'} = 'handler'; +$SIG{'TERM'} = 'handler'; +$SIG{'KILL'} = 'handler'; +$SIG{'STOP'} = 'handler'; +# this one is perhaps the most important one, since this is what we should get +# when the user interrupts the GET request. +$SIG{'PIPE'} = 'handler'; + + +###################### +# sub procedures +###################### + +# parse an url param of the form: proto:display[;param] +sub parse_url { + local($input, *proto_ret, *display_ret, *param_ret) = @_; + + # extract param first + ($sub_url, $param_ret) = split(/;/, $input, 2); + # then extract proto and display + ($proto_ret, $display_ret) = split(/:/, $sub_url, 2); + +} + +# parse an auth param of the form: auth=name:key +sub parse_auth { + local($input, *name_ret, *key_ret) = @_; + + if ($input) { + ($param_name, $param_value) = split(/=/, $input, 2); + if ($param_name eq "auth") { + ($name_ret, $key_ret) = split(/:/, $param_value, 2); + } + } +} + +# parse an LBX param of the form: either NO or YES[;auth=...] +sub parse_lbx_param { + local($input, *lbx_ret, *lbx_auth_name_ret, *lbx_auth_key_ret) = @_; + + ($lbx_ret, $lbxparam) = split(/;/, $input, 2); + if ($lbx_ret eq "YES") { + # look for an authentication auth in param + &parse_auth($lbxparam, *lbx_auth_name_ret, *lbx_auth_key_ret); + } +} + +# setup proxy with possible auth, change display parameter when succeeding +sub setup_lbx_proxy { + local(*display, $auth_name, $auth_key) = @_; + + # setup auth file for xfindproxy + if ($auth_name && $auth_key) { + $proxy_input = "/tmp/xlbxauth.$$"; + open(PROXYINPUT, ">$proxy_input"); + print PROXYINPUT "$auth_name\n$auth_key\n"; + close(PROXYINPUT); + $findproxy_param = " -auth <$proxy_input"; + } else { + $findproxy_param = ""; + } + + # remove screen number specification if there is one + ($host, $tmp) = split(/:/, $display); + ($dpy, $screen) = split(/\./, $tmp); + $server = $host . ":" . $dpy; + + # let's get an LBX proxy + open(PROXY, "$xfindproxy -manager $proxymngr -server $server -name LBX $findproxy_param|"); + # get the proxy address from xfindproxy output + while (<PROXY>) { + chop; + ($proxy_dpy, $proxy_port) = split(/:/, $_); + if ($proxy_dpy && $proxy_port) { + # build up the new display name + $display = $proxy_dpy . ":" . $proxy_port; + if ($screen) { + $display .= "." . $screen; + } + last; + } + } + close(PROXY); + + if ($proxy_input) { + system "rm -f $proxy_input"; + } +} + +# add entry in authority file +sub add_auth { + local($display, $auth_name, $auth_key) = @_; + + system "$xauth add $display $auth_name $auth_key"; +} + + +###################### +# the main thing now +###################### + + +# handle both ways of getting query +if ($ENV{'QUERY_STRING'}) +{ + $query = $ENV{'QUERY_STRING'}; +} else { + $query = $ARGV[0]; +} + +if ($query) +{ + $cleanup = ""; + + # parse params + %params = split(/\?/, $query); + foreach $param (split(/\?/, $query)) { + + ($name, $value) = split(/=/, $param, 2); + if ($name eq "WIDTH") { + $width = $value; + } elsif ($name eq "HEIGHT") { + $height = $value; + } elsif ($name eq "UI") { + # look at what we got for the UI parameter, it should be of the + # form: x11:hostname:dpynum[.screen][;auth=...] + &parse_url($value, *proto, *display, *ui_param); + if ($proto eq 'x11') { + $xdisplay = $display; + } else { + # unknown UI protocol!! + } + # look for an authentication auth in param + &parse_auth($ui_param, *xui_auth_name, *xui_auth_key); + + } elsif ($name eq "X-UI-LBX") { + &parse_lbx_param($value, *xui_lbx, + *xui_lbx_auth_name, *xui_lbx_auth_key); + } + } + + # set authority file for X + $ENV{'XAUTHORITY'} = "/tmp/xauth.$$"; + # and define its related cleanup command + $cleanup = "rm -f $ENV{'XAUTHORITY'}"; + + # process params + if ($xdisplay) { + + if ($xui_lbx eq "YES") { + &setup_lbx_proxy(*xdisplay, $xui_lbx_auth_name, $xui_lbx_auth_key); + } + if ($xui_auth_name && $xui_auth_key) { + &add_auth($xdisplay, $xui_auth_name, $xui_auth_key); + } + # add display specification to the command line + $command .= " -display $xdisplay"; + # and put it in the environment too for good measure. + $ENV{'DISPLAY'} = $xdisplay; + } + if ($width && $height) { + # add geometry specification to the command line + $command .= " -geometry ${width}x${height}"; + } + + # Start application followed by a cleanup command in the background. + # The ouput and input need to be redirected, otherwise the CGI process will + # be kept alive by the http server and the browser will keep waiting for + # the end of the stream... + # Catching application's failure is not easy since we want to run it in + # background and therefore we can't get its exit status. However, we can + # catch obvious errors by logging its output and after some time looking + # at whether the application is still running or not. This is determine + # based on some kind of "lock" file. + # This is quite complicated but it allows to get some error report without + # leaving any file behind us in any case. + + $LOCK= "/tmp/lock.$$"; + $LOG= "/tmp/log.$$"; + $LOG2 = "/tmp/log2.$$"; + system "(touch $LOCK; _s=true; $command >$LOG 2>&1 || _s=false; if \$_s; then rm $LOG; else rm $LOCK; fi; if [ -f $LOG2 ]; then rm $LOG2; fi; $cleanup) >/dev/null 2>&1 </dev/null &"; + + # sleep for a while to let the application start or fail + # it's up to you to decide how long it could for the application to fail... + sleep(5); + + # now lets see if the application died + if (open(LOCK, "<$LOCK")) { + close(LOCK); + # the application seems to be running, remove lock and rename the log + # so that it gets removed no matter how the application exits later on + system "rm $LOCK; mv $LOG $LOG2"; + # send success error code as reply + print "0\n"; + } else { + # the lock file is gone, for sure the application has failed so send + # back error code and log + print "1\n"; + system "cat $LOG; rm $LOG"; + } + +} else { + + # reply with an error message + print "This script requires to be given the proper RX arguments +to run successfully. +"; + +} diff --git a/helper/GetUrl.c b/helper/GetUrl.c new file mode 100644 index 0000000..04b4c93 --- /dev/null +++ b/helper/GetUrl.c @@ -0,0 +1,296 @@ +/* $Xorg: GetUrl.c,v 1.4 2001/02/09 02:05:57 xorgcvs Exp $ */ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- +ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABIL- +ITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization from +The Open Group. + +*/ +/* + * This file is really split into two major parts where GetUrl is implemented + * in two completely different ways. + * The first one, which is used when XUSE_WWW is defined uses the standalone + * program "www" to perform the GET request. + * The second one, based on the xtrans layer, performs the GET request + * directly. + */ + +#define Free(b) if (b) free(b) + +#ifdef XUSE_WWW + +#include <stdio.h> +#include <stdlib.h> +#include <X11/Xos.h> /* for strcmp() etc... */ + +/* + * GetUrl first method, using www. + */ + +int +GetUrl(char *url, char **reply_ret, int *len_ret) +{ + char buf[BUFSIZ], *reply, *ptr; + FILE *fp; + int readbytes, size; + + sprintf(buf, "www -source \"%s\"", url); + fp = popen(buf, "r"); + if (fp == NULL) + return 1; + + reply = NULL; + size = 0; + do { + readbytes = fread(buf, sizeof(char), BUFSIZ, fp); + if (readbytes != 0) { + /* malloc enough memory */ + ptr = (char *) realloc(reply, sizeof(char) * size + readbytes); + if (ptr == NULL) { /* memory allocation failed */ + Free(reply); + return 1; + } + reply = ptr; + memcpy(reply + size, buf, readbytes); + size += readbytes; + } + } while (readbytes == BUFSIZ); + pclose(fp); + + *reply_ret = reply; + *len_ret = size; + return 0; +} + +#else /* XUSE_WWW */ + +/* + * GetUrl second method, using the xtrans layer. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> + +/* get definitions for the HTTP protocol */ +#if (defined(__STDC__) && !defined(UNIXCPP)) || defined(ANSICPP) +#define TRANS(func) _HttpTrans##func +#else +#define TRANS(func) _HttpTrans/**/func +#endif +#include <X11/Xtrans.h> + +#define HTTP_CONNECTION_RETRIES 5 + +static XtransConnInfo +OpenConnection(char *hostname, int port) +{ + int retry; /* retry counter */ + XtransConnInfo trans_conn = NULL; /* transport connection object */ + int connect_stat; + char address[128]; /* address passed to the transport layer */ + char protocol[] = "tcp"; /* hardcoded transport */ + + /* make the address of the form: protocol/host:port */ + sprintf(address,"%s/%s:%d", + protocol ? protocol : "", + hostname ? hostname : "", + port); + + /* + * Make the connection. Do retries in case server host has hit its + * backlog (which, unfortunately, isn't distinguishable from there not + * being a server listening at all, which is why we have to not retry + * too many times). + */ + for(retry = HTTP_CONNECTION_RETRIES; retry >= 0; retry--) { + if ((trans_conn = _HttpTransOpenCOTSClient(address)) == NULL) + break; + + if ((connect_stat = _HttpTransConnect(trans_conn, address)) < 0) { + _HttpTransClose(trans_conn); + trans_conn = NULL; + + if (connect_stat == TRANS_TRY_CONNECT_AGAIN) { + sleep(1); + continue; + } else + break; + } + } + + return trans_conn; +} + +static void +CloseConnection(XtransConnInfo trans_conn) +{ + _HttpTransDisconnect(trans_conn); + _HttpTransClose(trans_conn); +} + +static void +SendGetRequest(XtransConnInfo trans_conn, char *filename) +{ + char *request; + char request_format[] = + "GET %s HTTP/1.0\r\nUser-Agent: xrx\r\nAccept: */*\r\n\r\n"; + int request_len = strlen(filename) + sizeof(request_format) + 1; + + /* build request */ + request = (char *)malloc(request_len); + sprintf(request, request_format, filename); + /* send it */ + _HttpTransWrite(trans_conn, request, request_len); + + Free(request); +} + +static int +ReadGetReply(XtransConnInfo trans_conn, char **reply_ret) +{ + char *reply = NULL; + char buf[BUFSIZ]; + int len, nbytes; + + len = 0; + do { + nbytes = _HttpTransRead(trans_conn, buf, BUFSIZ); + if (nbytes > 0) { + reply = (char *)realloc(reply, len + nbytes); + if (reply == NULL) + break; + memcpy(reply + len, buf, nbytes); + len += nbytes; + } + } while (nbytes != 0); + + *reply_ret = reply; + return len; +} + +/* per HTTP 1.0 spec */ +#define HTTP_DEFAULT_PORT 80 + +/* Parse given http url and return hostname, port number and path. + * expected syntax: "http:" "//" host [ ":" port ] [ abs_path ] + * default port: 80 + */ +static int +ParseHttpUrl(char *url, char **hostname_ret, int *port_ret, char **path_ret) +{ + char HTTP[] = "http://"; + char *hostname, *path; + int port; + char *ptr, *bos; + int status = 0; + + /* check if it's an http url */ + if (strncmp(HTTP, url, sizeof(HTTP) - 1)) + return 1; /* this is not an http url */ + + /* parse hostname */ + bos = ptr = url + sizeof(HTTP) - 1; + while (*ptr && *ptr != ':' && *ptr != '/') + ptr++; + if (bos == ptr) + return 1; /* doesn't have any hostname */ + + hostname = (char *)malloc(ptr - bos + 1); + if (hostname == NULL) + return 1; /* not enouch memory */ + memcpy(hostname, bos, ptr - bos); + hostname[ptr - bos] = '\0'; + + /* make sure path is initialized in case of error */ + path = NULL; + + /* parse port */ + if (*ptr != ':' || ! ptr[1]) + port = HTTP_DEFAULT_PORT; + else { + ++ptr; /* skip ':' */ + port = 0; + while (*ptr && *ptr != '/') { + if (isdigit((int) *ptr)) { + port *= 10; + port += *ptr - '0'; + } else { + status = 1; /* bad port specification */ + goto error; + } + ptr++; + } + } + + /* the rest of the url is the path */ + path = (char *)malloc(strlen(ptr) + 1); + if (path == NULL) { + status = 1; /* not enouch memory */ + goto error; + } + strcpy(path, ptr); + + /* set returned value */ + *hostname_ret = hostname; + *port_ret = port; + *path_ret = path; + return 0; + +error: + Free(hostname); + Free(path); + return status; +} + +int +GetUrl(char *url, char **reply_ret, int *len_ret) +{ + char *hostname, *path; + int port; + XtransConnInfo trans; + int status = 0; + + if (ParseHttpUrl(url, &hostname, &port, &path) != 0) + return 1; /* invalid URL */ + + trans = OpenConnection(hostname, port); + if (trans == NULL) { + status = 1; /* connection failed */ + goto end; + } + + SendGetRequest(trans, path); + + *len_ret = ReadGetReply(trans, reply_ret); + + CloseConnection(trans); + +end: + Free(hostname); + Free(path); + return status; +} + + +#endif /* XUSE_WWW */ diff --git a/helper/GetUrl.h b/helper/GetUrl.h new file mode 100644 index 0000000..cb80b9c --- /dev/null +++ b/helper/GetUrl.h @@ -0,0 +1,36 @@ +/* $Xorg: GetUrl.h,v 1.4 2001/02/09 02:05:57 xorgcvs Exp $ */ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- +ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABIL- +ITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization from +The Open Group. + +*/ + +#ifndef _GetUrl_h +#define _GetUrl_h + +extern int +GetUrl(char *url, char **reply_ret, int *len_ret); + +#endif /* _GetUrl_h */ diff --git a/helper/helper.c b/helper/helper.c new file mode 100644 index 0000000..9842623 --- /dev/null +++ b/helper/helper.c @@ -0,0 +1,529 @@ +/* $Xorg: helper.c,v 1.4 2001/02/09 02:05:57 xorgcvs Exp $ */ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- +ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABIL- +ITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization from +The Open Group. + +*/ + +#include <X11/Xlib.h> +#include <X11/Xos.h> +#include <X11/extensions/security.h> +#include <X11/Intrinsic.h> + +#include <stdlib.h> +#include <stdio.h> +#include <sys/stat.h> +#include <limits.h> /* for MAXHOSTNAMELEN */ +/* and in case we didn't get it from the headers above */ +#ifndef MAXHOSTNAMELEN +# define MAXHOSTNAMELEN 256 +#endif + +#include "Rx.h" +#include "RxI.h" /* for Strncasecmp */ +#include "XUrls.h" +#include "GetUrl.h" +#include "XAuth.h" +#include "XDpyName.h" +#include "Prefs.h" + + +#define DEFAULT_TIMEOUT 300 +#define NO_TIMEOUT 0 + +/* a few global */ +Display *pdpy; +int security_event_type_base; +XSecurityAuthorization ui_auth_id; +XSecurityAuthorization print_auth_id; + +#define RevokedEventType \ + (security_event_type_base + XSecurityAuthorizationRevoked) + +/* read file in memory and return character stream */ +static char * +ReadFile(char *filename) +{ + int fd; + struct stat st; + char *stream; + + if ((fd = open(filename, O_RDONLY)) < 0) + return(0); + fstat(fd, &st); + stream = (char *)malloc(st.st_size+1); + if (stream == 0) + return(0); + if ((st.st_size = read(fd, stream, st.st_size)) < 0) { + free(stream); + return(0); + } + close(fd); + stream[st.st_size] = '\0'; + return stream; +} + + +static Display * +OpenXPrintDisplay(Display *dpy, char **printer_return) +{ + char *pdpy_name; + Display *pdpy; + pdpy_name = GetXPrintDisplayName(printer_return); + if (pdpy_name != NULL) { + pdpy = XOpenDisplay(pdpy_name); + free(pdpy_name); + } else { + /* no server specified, + let's see if the video server could do it */ + int dummy; + if (XQueryExtension(dpy, "XpExtension", &dummy, &dummy, &dummy)) + pdpy = dpy; + else + pdpy = NULL; + } + return pdpy; +} + +static void +CloseXPrintDisplay(Display *dpy, Display *pdpy) +{ + if (pdpy != NULL && pdpy != dpy) + XCloseDisplay(pdpy); +} + +/* process the given RxParams and make the RxReturnParams */ +static int +ProcessUIParams(Display *dpy, + Boolean trusted, Boolean use_fwp, Boolean use_lbx, + RxParams *in, RxReturnParams *out, char **x_ui_auth_ret) +{ + char *fwp_dpyname = NULL; + XSecurityAuthorization dum; + char *x_ui_auth = NULL; + Display *rdpy; + char *real_display; + + if (in->x_ui_auth[0] != 0) + GetXAuth(dpy, in->x_ui_auth[0], in->x_ui_auth_data[0], + trusted, None, DEFAULT_TIMEOUT, True, + &x_ui_auth, &ui_auth_id, &security_event_type_base); + else if (in->x_auth[0] != 0) + GetXAuth(dpy, in->x_auth[0], in->x_auth_data[0], + trusted, None, DEFAULT_TIMEOUT, True, + &x_ui_auth, &ui_auth_id, &security_event_type_base); + + /* make sure we use the server the user wants us to use */ + rdpy = dpy; + real_display = getenv("XREALDISPLAY"); + if (real_display != NULL) { + rdpy = XOpenDisplay(real_display); + if (rdpy == NULL) + rdpy = dpy; + } + + /* let's see whether we have a firewall proxy */ + if (use_fwp) { + fwp_dpyname = GetXFwpDisplayName(DisplayString(rdpy)); + if (fwp_dpyname == NULL) + /* + * We were supposed to use the firewall proxy but we + * couldn't get a connection. There is no need to + * continue. + */ + return 1; + } + + if (fwp_dpyname != NULL) { + out->ui = GetXUrl(fwp_dpyname, x_ui_auth, in->action); + free(fwp_dpyname); + } else + out->ui = GetXUrl(DisplayString(rdpy), x_ui_auth, in->action); + + if (in->x_ui_lbx == RxTrue) { + if (use_lbx == True) { + int dummy; + /* let's see whether the server supports LBX or not */ + if (XQueryExtension(rdpy, "LBX", &dummy, &dummy, &dummy)) { + out->x_ui_lbx = RxTrue; + + /* let's get a key for the proxy now */ + if (in->x_ui_lbx_auth[0] != 0) { + GetXAuth(dpy, in->x_ui_lbx_auth[0], + in->x_ui_lbx_auth_data[0], + trusted, None, DEFAULT_TIMEOUT, False, + &out->x_ui_lbx_auth, &dum, &dummy); + } else if (in->x_auth[0] != 0) + GetXAuth(dpy, in->x_auth[0], in->x_auth_data[0], + trusted, None, DEFAULT_TIMEOUT, False, + &out->x_ui_lbx_auth, &dum, &dummy); + } else { + out->x_ui_lbx = RxFalse; + fprintf(stderr, "Warning: Cannot setup LBX as requested, \ +LBX extension not supported\n"); + } + } else + out->x_ui_lbx = RxFalse; + } else /* it's either RxFalse or RxUndef */ + out->x_ui_lbx = in->x_ui_lbx; + + if (rdpy != dpy) + XCloseDisplay(rdpy); + + *x_ui_auth_ret = x_ui_auth; + + return 0; +} + + +static int +ProcessPrintParams(Display *dpy, + Boolean trusted, Boolean use_fwp, Boolean use_lbx, + RxParams *in, RxReturnParams *out, char *x_ui_auth) +{ + char *printer = NULL; + char *auth = NULL; + XSecurityAuthorization dum; + char *pfwp_dpyname = NULL; + int dummy; + + pdpy = OpenXPrintDisplay(dpy, &printer); + if (pdpy == NULL) { + fprintf(stderr, "Warning: Cannot setup X printer as requested, \ +no server found\n"); + return 0; + } + + /* create a key only when the video server is not the print + server or when we didn't create a key yet */ + if (pdpy != dpy || x_ui_auth == NULL) { + /* if the application has a GUI we can't guess when it will really + connect to the print server so we need an auth which never expires, + on the other hand if the application happens not to have any GUI + we can expect it to connect to the print server pretty soon */ + unsigned int timeout = ui_auth_id != 0 ? NO_TIMEOUT : DEFAULT_TIMEOUT; + if (in->x_print_auth[0] != 0) + GetXAuth(pdpy, in->x_print_auth[0], in->x_print_auth_data[0], + trusted, None, timeout, False, + &auth, &print_auth_id, &dummy); + else if (in->x_auth[0] != 0) + GetXAuth(pdpy, in->x_auth[0], in->x_auth_data[0], + trusted, None, timeout, False, + &auth, &print_auth_id, &dummy); + } + /* let's see whether we have a firewall proxy */ + if (use_fwp) { + pfwp_dpyname = GetXFwpDisplayName(DisplayString(pdpy)); + if (pfwp_dpyname == NULL) + /* + * We were supposed to use the firewall proxy but we + * couldn't get a connection. There is no need to + * continue. + */ + return 1; + } + + if (pfwp_dpyname != NULL) { + out->print = GetXPrintUrl(pfwp_dpyname, printer, auth, in->action); + free(pfwp_dpyname); + } else + out->print = GetXPrintUrl(DisplayString(pdpy), printer, auth, in->action); + + if (auth != NULL) + free(auth); + + if (in->x_print_lbx == RxTrue) { + if (use_lbx == True) { + if (pdpy == dpy && in->x_ui_lbx == RxTrue) { + /* the video server is the print server and we already + know whether it supports LBX or not */ + out->x_print_lbx = out->x_ui_lbx; + } else { + /* let's see whether the server supports LBX or not */ + if (XQueryExtension(pdpy, "LBX", &dummy, &dummy, &dummy)) { + out->x_print_lbx = RxTrue; + + /* let's get a key for the proxy now */ + if (in->x_print_lbx_auth[0] != 0) { + GetXAuth(pdpy, in->x_print_lbx_auth[0], + in->x_print_lbx_auth_data[0], + trusted, None, DEFAULT_TIMEOUT, False, + &out->x_print_lbx_auth, &dum, &dummy); + } else if (in->x_auth[0] != 0) + GetXAuth(pdpy, in->x_auth[0], in->x_auth_data[0], + trusted, None, DEFAULT_TIMEOUT, False, + &out->x_print_lbx_auth, &dum, &dummy); + } else { + out->x_print_lbx = RxFalse; + fprintf(stderr, "Warning: Cannot setup LBX as \ +requested, LBX extension not supported\n"); + } + } + } else + out->x_print_lbx = RxFalse; + } else /* it's either RxFalse or RxUndef */ + out->x_print_lbx = in->x_print_lbx; + + if (printer != NULL) + free(printer); + + return 0; +} + +static int +ProcessParams(Display *dpy, Preferences *prefs, RxParams *in, + RxReturnParams *out) +{ + char *x_ui_auth = NULL; + char webserver[MAXHOSTNAMELEN]; + Boolean trusted, use_fwp, use_lbx; + int return_value = 0; + + /* init return struture */ + memset(out, 0, sizeof(RxReturnParams)); + out->x_ui_lbx = RxUndef; + out->x_print_lbx = RxUndef; + out->action = in->action; + + if (in->embedded != RxUndef) + out->embedded = RxFalse; /* we cannot perform embbeding from helper */ + else + out->embedded = RxUndef; + + out->width = in->width; + out->height = in->height; + + ComputePreferences(prefs, + ParseHostname(in->action, webserver, MAXHOSTNAMELEN) ? webserver : NULL, + &trusted, &use_fwp, &use_lbx); + + if (in->ui[0] == XUI) /* X display needed */ + return_value = ProcessUIParams(dpy, trusted, use_fwp, use_lbx, + in, out, &x_ui_auth); + + if (in->print[0] == XPrint) /* XPrint server needed */ + return_value = ProcessPrintParams(dpy, trusted, use_fwp, use_lbx, + in, out, x_ui_auth); + + if (x_ui_auth != NULL) + free(x_ui_auth); + + return return_value; +} + +#define CONTENT_TYPE "Content-type" +#define TEXT_PLAIN "text/plain" + +/* parse CGI reply looking for error status line, + * and return following message + */ +int +ParseReply(char *reply, int reply_len, char **reply_ret, int *reply_len_ret) +{ + char *ptr, *end; + int status = 0; + + /* look for content-type field */ + end = reply + reply_len; + ptr = reply; + while (Strncasecmp(ptr, CONTENT_TYPE, sizeof(CONTENT_TYPE) - 1) != 0 && + ptr < end) { + /* goto the next line */ + while (*ptr != '\n' && ptr < end) + ptr++; + if (ptr != end) + ptr++; + } + + if (ptr < end) { /* if we found it */ + /* skip to field value */ + ptr += sizeof(CONTENT_TYPE); + while (isspace(*ptr) && ptr < end) + ptr++; + if (Strncasecmp(ptr, TEXT_PLAIN, sizeof(TEXT_PLAIN) - 1) == 0) { + /* go to the next line */ + while (*ptr != '\n' && ptr < end) + ptr++; + if (ptr == end) /* input truncated */ + goto exit; + ptr++; + /* skip the next line should be empty (except for \r) */ + while (*ptr != '\n' && ptr < end) + ptr++; + if (ptr == end) /* input truncated */ + goto exit; + ptr++; + /* now should be the error code */ + if (isdigit(*ptr)) { + status = atoi(ptr); + /* go to the next line */ + while (*ptr != '\n' && ptr < end) + ptr++; + if (ptr == end) /* input truncated */ + goto exit; + ptr++; + goto exit; + } else /* input truncated */ + goto exit; + } + } +exit: + *reply_ret = ptr; + *reply_len_ret = reply_len - (ptr - reply); + return status; +} + + +/* + * The following event dispatcher is in charge of revoking the print + * authorization when the video authorization is (which means the application + * using it is gone). + * We can then exit since we do not have anything else to do. + */ +Boolean +RevokeD(XEvent *xev) +{ + if (xev->type == RevokedEventType) { /* should always be true */ + XSecurityAuthorizationRevokedEvent *ev; + ev = (XSecurityAuthorizationRevokedEvent *) xev; + if (ev->auth_id == ui_auth_id) { /* should always be true */ + XSecurityRevokeAuthorization(pdpy, print_auth_id); + exit(0); + } + } + return True; +} + +int +main(int argc, char *argv[]) +{ + char *stream; + char **rx_argn, **rx_argv; + int rx_argc; + RxParams params; + RxReturnParams return_params; + char *query, *reply, *msg; + int reply_len, msg_len; + Widget toplevel; + XtAppContext app_context; + Preferences prefs; + + /* init global variables */ + pdpy = NULL; + security_event_type_base = 0; + ui_auth_id = 0; + print_auth_id = 0; + + rx_argc = 0; + + toplevel = XtAppInitialize(&app_context, "Xrx", 0, 0, +#if XtSpecificationRelease > 4 + &argc, +#else + (Cardinal *)&argc, +#endif + argv, 0, 0, 0); + + if (argc < 2) { + fprintf(stderr, "Usage: %s <file>\n", argv[0]); + exit(1); + } + + if ((stream = ReadFile(argv[1])) == 0) { + fprintf(stderr, "%s: cannot open file %s\n", argv[0], argv[1]); + exit(1); + } + + if (RxReadParams(stream, &rx_argn, &rx_argv, &rx_argc) != 0) { + fprintf(stderr, "%s: invalid file %s\n", argv[0], argv[1]); + exit(1); + } + + RxInitializeParams(¶ms); + + if (RxParseParams(rx_argn, rx_argv, rx_argc, ¶ms, 0) != 0) { + fprintf(stderr, "%s: invalid params\n", argv[0]); + exit(1); + } + GetPreferences(toplevel, &prefs); + + /* set up return parameters */ + if (ProcessParams(XtDisplay(toplevel), &prefs, + ¶ms, &return_params) != 0) { + fprintf(stderr, "%s: failed to process params\n", argv[0]); + exit(1); + } + + /* make query */ + query = RxBuildRequest(&return_params); + if (query == NULL) { + fprintf(stderr, "%s: failed to make query\n", argv[0]); + exit(1); + } + + /* perform GET request */ + if (GetUrl(query, &reply, &reply_len) != 0) { + fprintf(stderr, "%s: GET request failed\n", argv[0]); + exit(1); + } + + if (reply) { + if (ParseReply(reply, reply_len, &msg, &msg_len) != 0) { + fprintf(stderr, "%s: Remote execution failed\n", argv[0]); + fwrite(msg, msg_len, 1, stderr); + } + } + + /* if we didn't create any authorization for printing or + if the application is only using the print server, exit here */ + if (print_auth_id == 0 || ui_auth_id == 0) + exit (0); + + /* otherwise, free as much as we can now */ + if (rx_argc != 0) { + int i; + for (i = 0; i < rx_argc; i++) { + free(rx_argn[i]); + free(rx_argv[i]); + } + free(rx_argn); + free(rx_argv); + } + RxFreeParams(¶ms); + RxFreeReturnParams(&return_params); + + free(stream); + free(query); + if (reply) + free(reply); + + FreePreferences(&prefs); + + /* and setup event dispatcher so we catch the video key revocation */ + XtSetEventDispatcher(XtDisplay(toplevel), RevokedEventType, RevokeD); + + /* then wait for it... */ + XtAppMainLoop(app_context); +} diff --git a/helper/xrx.man b/helper/xrx.man new file mode 100644 index 0000000..fc5d90d --- /dev/null +++ b/helper/xrx.man @@ -0,0 +1,134 @@ +.\" $Xorg: xrx.man,v 1.4 2001/02/09 02:05:57 xorgcvs Exp $ +.\" Copyright 1996, 1998 The Open Group +.\" +.\" Permission to use, copy, modify, distribute, and sell this software and its +.\" documentation for any purpose is hereby granted without fee, provided that +.\" the above copyright notice appear in all copies and that both that +.\" copyright notice and this permission notice appear in supporting +.\" documentation. +.\" +.\" The above copyright notice and this permission notice shall be included +.\" in all copies or substantial portions of the Software. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +.\" OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +.\" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +.\" IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +.\" OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +.\" ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +.\" OTHER DEALINGS IN THE SOFTWARE. +.\" +.\" Except as contained in this notice, the name of The Open Group shall +.\" not be used in advertising or otherwise to promote the sale, use or +.\" other dealings in this Software without prior written authorization +.\" from The Open Group. +.\" +.TH XRX 1 "Release 6.4" "X Version 11" +.SH NAME +xrx - RX helper program +.SH SYNOPSIS +\fBxrx\fP [\-\fItoolkitoption\fP ...] \fIfilename\fP +.SH DESCRIPTION +The helper program may be used with any Web browser to interpret documents +in the RX MIME type format and start remote applications. +.PP +\fBxrx\fP reads in the RX document specified by its \fIfilename\fP, from +which it gets the list of services the application wants to use. Based on +this information, \fBxrx\fP sets the various requested services, including +creating authorization keys if your X server supports the SECURITY +extension. It then passes the relevant data, such as the X display name, to +the application through an HTTP GET request of the associated CGI +script. The Web server then executes the CGI script to start the +application. The client runs on the web server host connected to your X +server. +.PP +.SH INSTALLATION +You need to configure your web browser to use \fBxrx\fP for RX documents. +Generally the following line in your $HOME/.mailcap is enough: + application/x-rx; xrx %s +.PP +However, you may need to refer to your web browser's documentation for exact +instructions on configuring helper applications. +.PP +Once correctly configured, your browser will activate the helper program +whenever you retrieve any document of the MIME type \fIapplication/x-rx\fP. +.PP +.SH OPTIONS +The \fIxrx\fP helper program accepts all of the standard X Toolkit command +line options such as: +.TP 8 +.B \-xrm \fIresourcestring\fP +This option specifies a resource string to be used. There may be several +instances of this option on the command line. +.PP +.SH RESOURCES +The application class name of the \fIxrx\fP program is Xrx and it +understands the following application resource names and classes: +.\".in +1in +.TP 8 +.B "xrxHasFirewallProxy (\fPclass\fB XrxHasFirewallProxy)" +Specifies whether an X server firewall proxy (see xfwp) is running and +should be used. Default is ``False.'' +.TP 8 +.B "xrxInternalWebServers (\fPclass\fB XrxInternalWebServers)" +The web servers for which the X server firewall proxy should not be used +(only relevant when \fBxrxHasFirewallProxy\fP is ``True''). Its value is a +comma separated list of mask/value pairs to be used to filter internal +web servers, based on their address. The mask part specifies which segments +of the address are to be considered and the value part specifies what the +result should match. For instance the following list: + + 255.255.255.0/198.112.45.0, 255.255.255.0/198.112.46.0 + +matches the address sets: 198.112.45.* and 198.112.46.*. More precisely, +the test is (address & mask) == value. +.TP 8 +.B "xrxFastWebServers (\fPclass\fB XrxFastWebServers)" +The web servers for which LBX should not be used. The resource value is a +list of address mask/value pairs, as previously described. +.TP 8 +.B "xrxTrustedWebServers (\fPclass\fB XrxTrustedWebServers)" +The web servers from which remote applications should be run as trusted +clients. The default is to run remote applications as untrusted +clients. The resource value is a list of address mask/value pairs, as +previously described. +.PP +.SH ENVIRONMENT + +The \fIxrx\fP helper program uses the standard X environment variables +such as ``DISPLAY'' to get the default X server host and display +number. If the RX document requests X-UI-LBX service and the default X +server does not advertise the LBX extension, \fIxrx\fP will look for the +environment variable ``XREALDISPLAY'' to get a second address for your X +server and look for the LBX extension there. When running your browser +through \fIlbxproxy\fP you will need to set XREALDISPLAY to the actual +address of your server if you wish remote applications to be able to use +LBX across the Internet. +.PP +If the RX document requests XPRINT service, \fIxrx\fP looks for the +variable ``XPRINTER'' to get the printer name and X Print server address to +use. If the server address is not specified as part of XPRINTER, \fIxrx\fP +uses the first one specified through the variable ``XPSERVERLIST'' when it +is set. When it is not \fIxrx\fP then tries to use the video server as the +print server. If the printer name is not specified via XPRINTER, \fIxrx\fP +looks for it in the variables ``PDPRINTER'', then ``LPDEST'', and finally +``PRINTER'', +.PP +Finally, if you are using a firewall proxy, \fIxrx\fP will look for +``PROXY_MANAGER'' to get the address of your proxy manager (see +proxymngr). When not specified it will use ":6500" as the default. +.PP +.SH KNOWN BUG +When an authorization key is created for a remote application to use the X +Print service, the helper program has to create the key with an infinite +timeout since nobody knows when the application will actually connect to +the X Print server. Therefore, in this case, the helper program stays +around to revoke the key when the application goes away (that is when its +video key expires). However, if the helper program dies unexpectedly the +print authorization key will never get revoked. +.PP +.SH SEE ALSO +libxrx (1), xfwp (1), lbxproxy (1), proxymngr (1), +The RX Document specification +.SH AUTHOR +Arnaud Le Hors, X Consortium diff --git a/htdocs/bitmap b/htdocs/bitmap new file mode 100644 index 0000000..934fe47 --- /dev/null +++ b/htdocs/bitmap @@ -0,0 +1,12 @@ +<!-- $Xorg: bitmap,v 1.3 2000/08/17 19:54:58 cpqbld Exp $ --> +<PARAM Name=VERSION Value=1.0> +<PARAM Name=REQUIRED-SERVICES Value=UI> +<PARAM Name=UI Value=X> +<PARAM Name=ACTION Value=http://WEBSERVER/cgi-bin/bitmap.pl> +<PARAM Name=WIDTH Value=200> +<PARAM Name=HEIGHT Value=200> +<PARAM Name=EMBEDDED Value=YES> +<PARAM Name=AUTO_START Value=YES> +<PARAM Name=X-UI-INPUT-METHOD VALUE=YES;foo> +<PARAM Name=X-UI-LBX Value=YES> +<PARAM Name=X-AUTH VALUE=MIT-MAGIC-COOKIE-1> diff --git a/htdocs/bitmap.html b/htdocs/bitmap.html new file mode 100644 index 0000000..242b867 --- /dev/null +++ b/htdocs/bitmap.html @@ -0,0 +1,23 @@ +<!--$Xorg: bitmap.html,v 1.3 2000/08/17 19:54:58 cpqbld Exp $--> +<html> +<head> + <title>X Applications on the Web - bitmap demo page. </title> +</head> + +<body> +<a name="begin"> +<h1> X Applications on the Web - bitmap <br> Demo page. </h1> + +<hr> + +Here is a simple demo of the RX plug-in used to launch the bitmap program +over the web. In addition, if you are using Netscape Navigator with +the embedding capabable plug-in, the bitmap program should appear embedded +within this page. + +<p> +When embedded, bitmap's window should be here: +<EMBED version=1.0 type=application/x-rx src="bitmap.rx" width=420 height=570> + +</body> +</html> diff --git a/htdocs/dtcm b/htdocs/dtcm new file mode 100644 index 0000000..9d617ce --- /dev/null +++ b/htdocs/dtcm @@ -0,0 +1,12 @@ +<!-- $Xorg: dtcm,v 1.3 2000/08/17 19:54:58 cpqbld Exp $ --> +<PARAM Name=VERSION Value=1.0> +<PARAM Name=REQUIRED-SERVICES Value=UI> +<PARAM Name=UI Value=X> +<PARAM Name=PRINT Value=XPRINT> +<PARAM Name=ACTION Value=http://WEBSERVER/cgi-bin/dtcm.pl> +<PARAM Name=WIDTH Value=500> +<PARAM Name=HEIGHT Value=300> +<PARAM Name=EMBEDDED Value=YES> +<PARAM Name=X-UI-LBX Value=YES> +<PARAM Name=X-PRINT-LBX Value=NO> +<PARAM Name=X-AUTH VALUE=MIT-MAGIC-COOKIE-1> diff --git a/htdocs/dtcm.html b/htdocs/dtcm.html new file mode 100644 index 0000000..6f9f450 --- /dev/null +++ b/htdocs/dtcm.html @@ -0,0 +1,23 @@ +<!--$Xorg: dtcm.html,v 1.3 2000/08/17 19:54:58 cpqbld Exp $--> +<html> +<head> + <title>X Applications on the Web - Demo page. </title> +</head> + +<body> +<a name="begin"> +<h1> X Applications on the Web - Dtcm <br> Demo page. </h1> + +<hr> + +Here is a simple demo of the RX plug-in used to launch the dtcm program +over the web. In addition, if you are using Netscape Navigator with +the embedding capabable plug-in, the dtcm program should appear embedded +within this page. + +<p> +When embedded, dtcm's window should be here: +<EMBED version=1.0 type=application/x-rx src="dtcm.rx" width=500 height=300> + +</body> +</html> diff --git a/htdocs/excel b/htdocs/excel new file mode 100644 index 0000000..2a453b0 --- /dev/null +++ b/htdocs/excel @@ -0,0 +1,11 @@ +<!-- $Xorg: excel,v 1.3 2000/08/17 19:54:58 cpqbld Exp $ --> +<PARAM Name=VERSION Value=1.0> +<PARAM Name=REQUIRED-SERVICES Value=UI> +<PARAM Name=UI Value=X> +<PARAM Name=ACTION Value=http://WEBSERVER/cgi-bin/excel.pl> +<PARAM Name=WIDTH Value=640> +<PARAM Name=HEIGHT Value=480> +<PARAM Name=EMBEDDED Value=YES> +<PARAM Name=X-UI-LBX Value=YES> +<PARAM Name=X-UI-INPUT-METHOD VALUE=YES;foo> +<PARAM Name=X-AUTH VALUE=MIT-MAGIC-COOKIE-1> diff --git a/htdocs/excel.html b/htdocs/excel.html new file mode 100644 index 0000000..d5ce718 --- /dev/null +++ b/htdocs/excel.html @@ -0,0 +1,23 @@ +<!--$Xorg: excel.html,v 1.3 2000/08/17 19:54:58 cpqbld Exp $--> +<html> +<head> + <title>X Applications on the Web - Excel demo page. </title> +</head> + +<body> +<a name="begin"> +<h1> X Applications on the Web - Excel <br> Demo page. </h1> + +<hr> + +Here is a simple demo of the RX plug-in used to launch Microsoft Excel +over the web. In addition, if you are using Netscape Navigator with +the embedding capabable plug-in, Excel should appear embedded +within this page. + +<p> +When embedded, Excel's window should be here: +<EMBED version=1.0 type=application/x-rx src="excel.rx" width=640 height=480> + +</body> +</html> diff --git a/htdocs/xclock b/htdocs/xclock new file mode 100644 index 0000000..86d21fa --- /dev/null +++ b/htdocs/xclock @@ -0,0 +1,11 @@ +<!-- $Xorg: xclock,v 1.3 2000/08/17 19:54:58 cpqbld Exp $ --> +<PARAM Name=VERSION Value=1.0> +<PARAM Name=REQUIRED-SERVICES Value=UI> +<PARAM Name=UI Value=X> +<PARAM Name=ACTION Value=http://WEBSERVER/cgi-bin/xclock.pl> +<PARAM Name=WIDTH Value=200> +<PARAM Name=HEIGHT Value=200> +<PARAM Name=EMBEDDED Value=YES> +<PARAM Name=X-UI-INPUT-METHOD VALUE=YES;foo> +<PARAM Name=X-UI-LBX Value=YES> +<PARAM Name=X-AUTH VALUE=MIT-MAGIC-COOKIE-1> diff --git a/htdocs/xclock.html b/htdocs/xclock.html new file mode 100644 index 0000000..024ec25 --- /dev/null +++ b/htdocs/xclock.html @@ -0,0 +1,23 @@ +<!--$Xorg: xclock.html,v 1.3 2000/08/17 19:54:58 cpqbld Exp $--> +<html> +<head> + <title>X Applications on the Web - xclock demo page. </title> +</head> + +<body> +<a name="begin"> +<h1> X Applications on the Web - xclock <br> Demo page. </h1> + +<hr> + +Here is a simple demo of the RX plug-in used to launch the xclock program +over the web. In addition, if you are using Netscape Navigator with +the embedding capabable plug-in, the xclock program should appear embedded +within this page. + +<p> +When embedded, xclock's window should be here: +<EMBED version=1.0 type=application/x-rx src="xclock.rx" width=200 height=200> + +</body> +</html> diff --git a/htdocs/xload b/htdocs/xload new file mode 100644 index 0000000..8e01606 --- /dev/null +++ b/htdocs/xload @@ -0,0 +1,11 @@ +<!-- $Xorg: xload,v 1.3 2000/08/17 19:54:59 cpqbld Exp $ --> +<PARAM Name=VERSION Value=1.0> +<PARAM Name=REQUIRED-SERVICES Value=UI> +<PARAM Name=UI Value=X> +<PARAM Name=ACTION Value=http://WEBSERVER/cgi-bin/xload.pl> +<PARAM Name=WIDTH Value=200> +<PARAM Name=HEIGHT Value=150> +<PARAM Name=EMBEDDED Value=YES> +<PARAM Name=X-UI-INPUT-METHOD VALUE=YES;foo> +<PARAM Name=X-UI-LBX Value=YES> +<PARAM Name=X-AUTH VALUE=MIT-MAGIC-COOKIE-1> diff --git a/htdocs/xload.html b/htdocs/xload.html new file mode 100644 index 0000000..362c4b9 --- /dev/null +++ b/htdocs/xload.html @@ -0,0 +1,23 @@ +<!--$Xorg: xload.html,v 1.3 2000/08/17 19:54:59 cpqbld Exp $--> +<html> +<head> + <title>X Applications on the Web - Demo page. </title> +</head> + +<body> +<a name="begin"> +<h1> X Applications on the Web <br> Demo page. </h1> + +<hr> + +Here is a simple demo of the RX plug-in used to launch the xload program +over the web. In addition, if you are using Netscape Navigator with +the embedding capabable plug-in, the xload program should appear embedded +within this page. + +<p> +When embedded, xload's window should be here: +<EMBED version=1.0 type=application/x-rx src="xload.rx" width=100 height=100> + +</body> +</html> diff --git a/libxplugin/README b/libxplugin/README new file mode 100644 index 0000000..775db40 --- /dev/null +++ b/libxplugin/README @@ -0,0 +1,6 @@ +$Xorg: README,v 1.3 2000/08/17 19:54:59 cpqbld Exp $ + +This library exists solely to get the new extensions linked into the +Netscape Plug-in. Once vendors start shipping R7 versions of libXext.so +then there will be no need for this library. + diff --git a/plugin/Global.c b/plugin/Global.c new file mode 100644 index 0000000..3372f48 --- /dev/null +++ b/plugin/Global.c @@ -0,0 +1,97 @@ +/* $Xorg: Global.c,v 1.4 2001/02/09 02:05:57 xorgcvs Exp $ */ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- +ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABIL- +ITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization from +The Open Group. + +*/ + +#include "RxPlugin.h" + +#include <stdio.h> + +/* global variable to handle data global to all instances */ +PluginGlobal RxGlobal; + + +NPError +NPP_Initialize(void) +{ +#ifdef PLUGIN_TRACE + (void) fprintf (stderr, "%s\n", "NPP_Initialize"); +#endif + RxGlobal.has_appgroup = RxUndef; + RxGlobal.has_real_server = RxUndef; + RxGlobal.has_ui_lbx = RxUndef; + RxGlobal.has_print_lbx = RxUndef; + RxGlobal.has_printer = RxUndef; + RxGlobal.has_ui_fwp = RxUndef; + RxGlobal.has_print_fwp = RxUndef; + RxGlobal.pdpy_name = NULL; + RxGlobal.printer_name = NULL; + RxGlobal.fwp_dpyname = NULL; + RxGlobal.pfwp_dpyname = NULL; + RxGlobal.ice_conn = NULL; + RxGlobal.pm_opcode = 0; + RxGlobal.get_prefs = True; + RxGlobal.dpy = NULL; + RxGlobal.pdpy = NULL; + RxGlobal.wm_delete_window = 0; + RxGlobal.wm_protocols = 0; + return NPERR_NO_ERROR; +} + +void +NPP_Shutdown(void) +{ +#ifdef PLUGIN_TRACE + (void) fprintf (stderr, "%s\n", "NPP_Shutdown"); +#endif +/* + * Netscape doesn't try to cache plug-ins at all, and it unloads + * the plug-in immediately after the last instance that uses it is + * gone. So if you load a page that uses the plug-in, and then reload + * the page, Netscape will unload the plug-in and call NPP_Shutdown. + * Then it will reload the plug-in and call NPP_Initialize. And when + * it reloads it, zeroes the plug-in's DATA segment so even if we + * tried to be smart in NPP_Initialize, Netscape would defeat us + * anyway. + */ + if (RxGlobal.pdpy_name != NULL) + NPN_MemFree(RxGlobal.pdpy_name); + if (RxGlobal.printer_name != NULL) + NPN_MemFree(RxGlobal.printer_name); + if (RxGlobal.fwp_dpyname != NULL) + NPN_MemFree(RxGlobal.fwp_dpyname); + if (RxGlobal.pfwp_dpyname != NULL) + NPN_MemFree(RxGlobal.pfwp_dpyname); + if (RxGlobal.get_prefs == False) + FreePreferences(&RxGlobal.prefs); + if (RxGlobal.pdpy != NULL && RxGlobal.pdpy != RxGlobal.dpy) + XCloseDisplay(RxGlobal.pdpy); + if (RxGlobal.ice_conn) { + IceProtocolShutdown (RxGlobal.ice_conn, RxGlobal.pm_opcode); + IceCloseConnection (RxGlobal.ice_conn); + } +} diff --git a/plugin/Main.c b/plugin/Main.c new file mode 100644 index 0000000..913f235 --- /dev/null +++ b/plugin/Main.c @@ -0,0 +1,630 @@ +/* $Xorg: Main.c,v 1.5 2001/02/09 02:05:57 xorgcvs Exp $ */ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- +ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABIL- +ITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization from +The Open Group. + +*/ + +/* + * RX plug-in module based on the UnixTemplate file provided by Netcape. + */ + +/* -*- Mode: C; tab-width: 4; -*- */ +/****************************************************************************** + * Copyright 1996 Netscape Communications. All rights reserved. + ******************************************************************************/ +/* + * UnixShell.c + * + * Netscape Client Plugin API + * - Function that need to be implemented by plugin developers + * + * This file defines a "Template" plugin that plugin developers can use + * as the basis for a real plugin. This shell just provides empty + * implementations of all functions that the plugin can implement + * that will be called by Netscape (the NPP_xxx methods defined in + * npapi.h). + * + * dp Suresh <dp@netscape.com> + * + */ + +#include <ctype.h> +#include <stdlib.h> +#include "RxPlugin.h" +#include "X11/StringDefs.h" + + +/*********************************************************************** + * Utility functions to deal with list of arguments + ***********************************************************************/ + +/* Free list of arguments */ +static void +FreeArgs(char* argn[], char* argv[], int argc) +{ + int i; + if (argc != 0) { + for (i = 0; i < argc; i++) { + NPN_MemFree(argn[i]); + NPN_MemFree(argv[i]); + } + NPN_MemFree(argn); + NPN_MemFree(argv); + } +} + +/* Copy list 2 to list 1 */ +static NPError +CopyArgs(char** argn1[], char** argv1[], int16* argc1, + char* argn2[], char* argv2[], int16 argc2) +{ + char **argn, **argv; + int i; + + argn = (char **)NPN_MemAlloc(sizeof(char *) * argc2); + if (!argn) + return NPERR_OUT_OF_MEMORY_ERROR; + argv = (char **)NPN_MemAlloc(sizeof(char *) * argc2); + if (!argv) { + NPN_MemFree(argn); + return NPERR_OUT_OF_MEMORY_ERROR; + } + memset(argn, 0, sizeof(char *) * argc2); + memset(argv, 0, sizeof(char *) * argc2); + for (i = 0; i < argc2; i++) { + char *name, *value; + name = (char *)NPN_MemAlloc(strlen(argn2[i]) + 1); + if (!name) { + FreeArgs(argn, argv, i - 1); + return NPERR_OUT_OF_MEMORY_ERROR; + } + strcpy(name, argn2[i]); + value = (char *)NPN_MemAlloc(strlen(argv2[i]) + 1); + if (!value) { + NPN_MemFree(name); + FreeArgs(argn, argv, i - 1); + return NPERR_OUT_OF_MEMORY_ERROR; + } + strcpy(value, argv2[i]); + argn[i] = name; + argv[i] = value; + } + *argc1 = argc2; + *argn1 = argn; + *argv1 = argv; + + return NPERR_NO_ERROR; +} + + +char* +NPP_GetMIMEDescription(void) +{ + return(PLUGIN_MIME_DESCRIPTION); +} + +NPError +NPP_GetValue(void *future, NPPVariable variable, void *value) +{ + NPError err = NPERR_NO_ERROR; + + switch (variable) { + case NPPVpluginNameString: + *((char **)value) = PLUGIN_NAME; + break; + case NPPVpluginDescriptionString: + *((char **)value) = PLUGIN_DESCRIPTION; + break; + default: + err = NPERR_GENERIC_ERROR; + } + return err; +} + +jref +NPP_GetJavaClass() +{ + return NULL; +} + +NPError +NPP_New(NPMIMEType pluginType, + NPP instance, + uint16 mode, + int16 argc, + char* argn[], + char* argv[], + NPSavedData* saved) +{ + PluginInstance* This; + + if (instance == NULL) + return NPERR_INVALID_INSTANCE_ERROR; + + instance->pdata = NPN_MemAlloc(sizeof(PluginInstance)); + + This = (PluginInstance*) instance->pdata; + + if (This == NULL) + return NPERR_OUT_OF_MEMORY_ERROR; + + This->instance = instance; + if (argc != 0) { /* copy the arguments list */ + if (CopyArgs(&This->argn, &This->argv, &This->argc, + argn, argv, argc) == NPERR_OUT_OF_MEMORY_ERROR) { + NPN_MemFree(This); + return NPERR_OUT_OF_MEMORY_ERROR; + } + } else { + This->argc = 0; + This->argn = This->argv = NULL; + } + This->parse_reply = 0; + This->status = 0; + This->dont_reparent = RxUndef; + This->state = LOADING; + This->status_widget = NULL; + This->plugin_widget = NULL; + RxpNew(This); + + return NPERR_NO_ERROR; +} + + +NPError +NPP_Destroy(NPP instance, NPSavedData** save) +{ + PluginInstance* This; + + if (instance == NULL) + return NPERR_INVALID_INSTANCE_ERROR; + + This = (PluginInstance*) instance->pdata; + + /* PLUGIN DEVELOPERS: + * If desired, call NP_MemAlloc to create a + * NPSavedDate structure containing any state information + * that you want restored if this plugin instance is later + * recreated. + */ + + if (This != NULL) { + RxpDestroy(This); + if (This->argc != 0) + FreeArgs(This->argn, This->argv, This->argc); + if (This->query != NULL) + NPN_MemFree(This->query); + NPN_MemFree(instance->pdata); + instance->pdata = NULL; + } + + return NPERR_NO_ERROR; +} + + +/* private buffer structure */ +typedef struct { + char *buf; + uint32 size; +} RxStreamBuf; + +NPError +NPP_NewStream(NPP instance, + NPMIMEType type, + NPStream *stream, + NPBool seekable, + uint16 *stype) +{ + PluginInstance* This; + RxStreamBuf *streambuf; + + if (instance == NULL) + return NPERR_INVALID_INSTANCE_ERROR; + + This = (PluginInstance*) instance->pdata; + + if (This->parse_reply != 0) + return NPERR_NO_ERROR; + + /* malloc structure to store RX document */ + streambuf = (RxStreamBuf *) NPN_MemAlloc(sizeof(RxStreamBuf)); + if (streambuf == NULL) + return NPERR_OUT_OF_MEMORY_ERROR; + + streambuf->buf = NULL; + streambuf->size = 0; + stream->pdata = (void *) streambuf; + + return NPERR_NO_ERROR; +} + + +/* PLUGIN DEVELOPERS: + * These next 2 functions are directly relevant in a plug-in which + * handles the data in a streaming manner. If you want zero bytes + * because no buffer space is YET available, return 0. As long as + * the stream has not been written to the plugin, Navigator will + * continue trying to send bytes. If the plugin doesn't want them, + * just return some large number from NPP_WriteReady(), and + * ignore them in NPP_Write(). For a NP_ASFILE stream, they are + * still called but can safely be ignored using this strategy. + */ + +int32 STREAMBUFSIZE = 0X0FFFFFFF; /* If we are reading from a file in NPAsFile + * mode so we can take any size stream in our + * write call (since we ignore it) */ + +int32 +NPP_WriteReady(NPP instance, NPStream *stream) +{ + PluginInstance* This; + if (instance != NULL) + This = (PluginInstance*) instance->pdata; + + return STREAMBUFSIZE; +} + +int32 +NPP_Write(NPP instance, NPStream *stream, int32 offset, int32 len, void *buf) +{ + PluginInstance* This; + + if (instance == NULL) + return len; + + This = (PluginInstance*) instance->pdata; + + if (This->parse_reply == 0) { + /* copy stream buffer to private storage, concatenating if necessary: + * since Netscape doesn't provide an NPN_MemRealloc we must do + * a new malloc, copy, and free :-( + */ + RxStreamBuf *streambuf = (RxStreamBuf *) stream->pdata; + uint32 size = streambuf->size; + char *cbuf; + + /* if first chunk add 1 for null terminating character */ + if (size == 0) + size++; + + size += len; + cbuf = (char *) NPN_MemAlloc(size); + if (cbuf == NULL) + return -1; + if (streambuf->size != 0) { + memcpy(cbuf, streambuf->buf, streambuf->size - 1); + memcpy(cbuf + streambuf->size - 1, ((char *)buf), len); + /* free old storage */ + NPN_MemFree((void *) streambuf->buf); + } else + memcpy(cbuf, ((char *)buf), len); + cbuf[size - 1] = '\0'; + /* store new buffer */ + streambuf->buf = cbuf; + streambuf->size = size; +#ifdef PLUGIN_TRACE + fprintf(stderr, "write %s:\n", PLUGIN_NAME); + fwrite(buf, len, 1, stderr); + fprintf(stderr, "\n"); +#endif + } else { + int l = len; + if (This->parse_reply == 1) { + /* look for status line */ + char *ptr = strchr(buf, '\n'); + if (ptr != NULL && isdigit(((char *)buf)[0])) { + This->status = (short) atoi((char *)buf); + /* skip status line */ + l -= ptr - (char *)buf + 1; + buf = ptr + 1; + if (This->status != 0) { + fprintf(stderr, + "%s: Application failed to start properly\n", + PLUGIN_NAME); + } + } + This->parse_reply = 2; + } + /* simply prints out whatever we get, and let netscape display it + in a dialog */ + fwrite(buf, l, 1, stderr); + } + + return len; /* The number of bytes accepted */ +} + +void +StartApplication(PluginInstance* This) +{ + NPError err; + +#ifndef NO_STARTING_STATE + RxpSetStatusWidget(This, STARTING); +#else + RxpSetStatusWidget(This, RUNNING); +#endif + + /* perform GET request + * throwing away the response. + */ + err = NPN_GetURL(This->instance, This->query, NULL); + This->parse_reply = 1; /* we want to print out the answer */ +} + +void +StartCB(Widget widget, XtPointer client_data, XtPointer call_data) +{ + PluginInstance* This = (PluginInstance*) client_data; +#if 0 + XtUnmapWidget(widget); +#endif + XtDestroyWidget(widget); + StartApplication(This); +} + +#if defined(linux) || (defined(sun) && !defined(SVR4)) +/* deficient linux linker semantics */ +static WidgetClass xmLabelGadgetClass; +static WidgetClass xmPushButtonGadgetClass; +#else +extern WidgetClass xmLabelGadgetClass; +extern WidgetClass xmPushButtonGadgetClass; +#endif + +void +RxpSetStatusWidget(PluginInstance* This, PluginState state) +{ + Arg args[5]; + int n; + XrmDatabase db; + char* return_type; + XrmValue return_value; + + if (This->status_widget) { + XtDestroyWidget(This->status_widget); + This->status_widget = NULL; + } + if (This->plugin_widget == NULL) + return; + + db = XtDatabase (XtDisplay (This->plugin_widget)); + + if (!XrmGetResource (db, "RxPlugin_BeenHere", "RxPlugin_BeenHere", + &return_type, &return_value)) { + + XrmPutStringResource (&db, "*Rx_Loading.labelString", "Loading..."); + XrmPutStringResource (&db, "*Rx_Starting.labelString", "Starting..."); + XrmPutStringResource (&db, "*Rx_Start.labelString", "Start"); + XrmPutStringResource (&db, "RxPlugin_BeenHere", "YES"); + } +#if defined(linux) || (defined(sun) && !defined(SVR4)) + /* + lame loader semantics mean we have to go fishing around to + come up with widget class records so we can create some widgets. + + Names of widgets changed in 4.x, so look for those names too + for linux. + + If Microsoft ever does IE for Linux we'll have to figure out + those names too. + */ + if (xmLabelGadgetClass == NULL) { + Widget w; + + w = XtNameToWidget (This->toplevel_widget, "*topLeftArea.urlLabel"); + if (w == NULL) + w = XtNameToWidget (This->toplevel_widget, "*urlBar.urlLocationLabel"); + xmLabelGadgetClass = XtClass (w); + w = XtNameToWidget (This->toplevel_widget, "*toolBar.abort"); + if (w == NULL) + w = XtNameToWidget (This->toplevel_widget, "*PopupMenu.openCustomUrl"); + xmPushButtonGadgetClass = XtClass (w); + } +#endif + + n = 0; + XtSetArg(args[n], "shadowThickness", 1); n++; + XtSetArg(args[n], XtNwidth, This->width); n++; + XtSetArg(args[n], XtNheight, This->height); n++; + if (state == LOADING) { + /* create a label */ + This->status_widget = + XtCreateManagedWidget("Rx_Loading", xmLabelGadgetClass, + This->plugin_widget, args, n); +#ifndef NO_STARTING_STATE + } else if (state == STARTING) { + /* create a label */ + This->status_widget = + XtCreateManagedWidget("Rx_Starting", xmLabelGadgetClass, + This->plugin_widget, args, n); +#endif + } else if (state == WAITING) { + /* create a push button */ + This->status_widget = + XtCreateManagedWidget("Rx_Start", xmPushButtonGadgetClass, + This->plugin_widget, args, n); + XtAddCallback(This->status_widget, "activateCallback", StartCB, This); + } else if (state == RUNNING) { + /* nothing else to be done */ + } + This->state = state; +} + + +NPError +NPP_DestroyStream(NPP instance, NPStream *stream, NPError reason) +{ + PluginInstance* This; + RxStreamBuf *streambuf = (RxStreamBuf *) stream->pdata; + char **rx_argn, **rx_argv; + int rx_argc; + RxParams params; + RxReturnParams return_params; + NPError status = NPERR_NO_ERROR; + + if (instance == NULL) + return NPERR_INVALID_INSTANCE_ERROR; + + This = (PluginInstance*) instance->pdata; + + if (This->parse_reply != 0) { + fflush(stderr); + if (This->status != 0) /* if error occured change widget status */ + RxpSetStatusWidget(This, WAITING); + return NPRES_DONE; + } + + memset(¶ms, 0, sizeof(RxParams)); + memset(&return_params, 0, sizeof(RxReturnParams)); + rx_argc = 0; + + if (reason != NPRES_DONE) { + status = NPERR_GENERIC_ERROR; + goto exit; + } + + /* read params from stream */ + if (RxReadParams(streambuf->buf, &rx_argn, &rx_argv, &rx_argc) != 0) { + fprintf(stderr, "%s: invalid file %s\n", PLUGIN_NAME, stream->url); + status = NPERR_GENERIC_ERROR; + goto exit; + } + + RxInitializeParams(¶ms); + + /* parse RX params */ + if (RxParseParams(rx_argn, rx_argv, rx_argc, ¶ms, 0) != 0) { + fprintf(stderr, "%s: invalid RX params\n", PLUGIN_NAME); + status = NPERR_GENERIC_ERROR; + goto exit; + } + + /* parse HTML params */ + if (RxParseParams(This->argn, This->argv, This->argc, ¶ms, 0) != 0) { + fprintf(stderr, "%s: invalid HTML params\n", PLUGIN_NAME); + status = NPERR_GENERIC_ERROR; + goto exit; + } + + /* set up return parameters */ + if (RxpProcessParams(This, ¶ms, &return_params) != 0) { + fprintf(stderr, "%s: failed to process params\n", PLUGIN_NAME); + status = NPERR_GENERIC_ERROR; + goto exit; + } + + /* make query */ + This->query = RxBuildRequest(&return_params); + if (This->query == NULL) { + fprintf(stderr, "%s: failed to make query\n", PLUGIN_NAME); + status = NPERR_GENERIC_ERROR; + goto exit; + } + + if (params.auto_start != RxFalse) /* default is auto start */ + StartApplication(This); + else + RxpSetStatusWidget(This, WAITING); + +exit: + /* free all forms of params */ + FreeArgs(rx_argn, rx_argv, rx_argc); + FreeArgs(This->argn, This->argv, This->argc); + This->argc = 0; + RxFreeParams(¶ms); + RxFreeReturnParams(&return_params); + /* free private storage */ + if (streambuf->buf != NULL) + NPN_MemFree(streambuf->buf); + NPN_MemFree(stream->pdata); + + return status; +} + +void +NPP_StreamAsFile(NPP instance, NPStream *stream, const char* fname) +{ + PluginInstance* This; + if (instance != NULL) + This = (PluginInstance*) instance->pdata; +} + + +void +NPP_Print(NPP instance, NPPrint* printInfo) +{ + if(printInfo == NULL) + return; + + if (instance != NULL) { + PluginInstance* This = (PluginInstance*) instance->pdata; + + if (printInfo->mode == NP_FULL) { + /* + * PLUGIN DEVELOPERS: + * If your plugin would like to take over + * printing completely when it is in full-screen mode, + * set printInfo->pluginPrinted to TRUE and print your + * plugin as you see fit. If your plugin wants Netscape + * to handle printing in this case, set + * printInfo->pluginPrinted to FALSE (the default) and + * do nothing. If you do want to handle printing + * yourself, printOne is true if the print button + * (as opposed to the print menu) was clicked. + * On the Macintosh, platformPrint is a THPrint; on + * Windows, platformPrint is a structure + * (defined in npapi.h) containing the printer name, port, + * etc. + */ + + void* platformPrint = + printInfo->print.fullPrint.platformPrint; + NPBool printOne = + printInfo->print.fullPrint.printOne; + + /* Do the default*/ + printInfo->print.fullPrint.pluginPrinted = FALSE; + } + else { /* If not fullscreen, we must be embedded */ + /* + * PLUGIN DEVELOPERS: + * If your plugin is embedded, or is full-screen + * but you returned false in pluginPrinted above, NPP_Print + * will be called with mode == NP_EMBED. The NPWindow + * in the printInfo gives the location and dimensions of + * the embedded plugin on the printed page. On the + * Macintosh, platformPrint is the printer port; on + * Windows, platformPrint is the handle to the printing + * device context. + */ + + NPWindow* printWindow = + &(printInfo->print.embedPrint.window); + void* platformPrint = + printInfo->print.embedPrint.platformPrint; + } + } +} diff --git a/plugin/NewNDest.c b/plugin/NewNDest.c new file mode 100644 index 0000000..bee8bf3 --- /dev/null +++ b/plugin/NewNDest.c @@ -0,0 +1,71 @@ +/* $Xorg: NewNDest.c,v 1.4 2001/02/09 02:05:57 xorgcvs Exp $ */ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- +ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABIL- +ITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization from +The Open Group. + +*/ + +#include "RxPlugin.h" + +/*********************************************************************** + * Functions to init and free private members + ***********************************************************************/ + +void +RxpNew(PluginInstance *This) +{ +#ifdef PLUGIN_TRACE + fprintf (stderr, "%s\n", "RxpNew"); +#endif + This->x_ui_auth_id = 0; + This->x_print_auth_id = 0; + This->app_group = 0; + This->toplevel_widget = NULL; + This->client_windows = NULL; + This->nclient_windows = 0; +} + +void +RxpDestroy(PluginInstance *This) +{ +#ifdef PLUGIN_TRACE + fprintf (stderr, "%s\n", "RxpDestroy"); +#endif + if (RxGlobal.dpy != NULL) { + RxpWmDelWinHandler (This->toplevel_widget, (XtPointer) This, NULL, NULL); + RxpRemoveDestroyCallback(This); + if (This->x_ui_auth_id != 0) + XSecurityRevokeAuthorization(RxGlobal.dpy, This->x_ui_auth_id); + if (This->app_group != None) + XagDestroyApplicationGroup (RxGlobal.dpy, This->app_group); + RxpTeardown (This); + } + if (RxGlobal.pdpy != NULL) { + if (This->x_print_auth_id != 0) + XSecurityRevokeAuthorization(RxGlobal.pdpy, This->x_print_auth_id); + } + if (This->client_windows) NPN_MemFree (This->client_windows); + RxpNew (This); +} diff --git a/plugin/PProcess.c b/plugin/PProcess.c new file mode 100644 index 0000000..d2f2faf --- /dev/null +++ b/plugin/PProcess.c @@ -0,0 +1,1017 @@ +/* $Xorg: PProcess.c,v 1.6 2001/02/09 02:05:57 xorgcvs Exp $ */ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- +ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABIL- +ITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization from +The Open Group. + +*/ + +#include "RxPlugin.h" +#include "XUrls.h" +#include "XAuth.h" +#include "XDpyName.h" +#include "Prefs.h" +#include <X11/StringDefs.h> + +#include <limits.h> /* for MAXHOSTNAMELEN */ +/* and in case we didn't get it from the headers above */ +#ifndef MAXHOSTNAMELEN +# define MAXHOSTNAMELEN 256 +#endif + +#ifdef XUSE_XTREGISTERWINDOW +extern void _XtRegisterWindow (Window window, Widget widget); +#define XtRegisterDrawable(d,win,wid) _XtRegisterWindow(win,wid) +extern void _XtUnregisterWindow (Window window, Widget widget); +#define UnregisterDrawable(win,wid) _XtUnregisterWindow(win,wid) +#else +#define UnregisterDrawable(win,wid) XtUnregisterDrawable(XtDisplay(wid),win) +#endif + +/* timeout for authorizations */ +#define DEFAULT_TIMEOUT 300 +#define NO_TIMEOUT 0 + +/*********************************************************************** + * Try and do something sensible about window geometry + ***********************************************************************/ +static void +GetWindowGeometry( + Display* dpy, + Window win, + Position* x, + Position* y, + Dimension* width, + Dimension* height, + Dimension* border_width, + /* the following doesn't really belong here but it saves us from doing + another XGetWindowAttributes later on */ + Colormap *cmap) +{ + long mask; + XSizeHints* sizehints = XAllocSizeHints(); + XWindowAttributes wattr; + + if (XGetWindowAttributes (dpy, win, &wattr)) { + *x = wattr.x; + *y = wattr.y; + *width = wattr.width; + *height = wattr.height; + *border_width = wattr.border_width; + *cmap = wattr.colormap; + } + if (sizehints) { + XGetWMNormalHints (dpy, win, sizehints, &mask); + + if (mask & USPosition|PPosition) { + *x = sizehints->x; + *y = sizehints->y; + *width = sizehints->width; + *height = sizehints->height; + XFree ((char*) sizehints); + return; + } + XFree ((char*) sizehints); + } + *x = 0; + *y = 0; + *width = 0; + *height = 0; +} + +/*********************************************************************** + * a set of utility functions to manipulate Windows lists + ***********************************************************************/ +static Bool +IsInWinList(Window *list, int count, Window win) +{ + int i; + for (i = 0; i < count; i++, list++) + if (*list == win) + return True; + return False; +} + +static void +AppendToWinList(Window **new_list, int *new_count, + Window *list, int count, Window win) +{ + *new_count = count + 1; + *new_list = (Window*) malloc(sizeof(Window) * *new_count); + memcpy(*new_list, list, sizeof(Window) * count); + (*new_list)[count] = win; +} + +static void +PrependToWinList(Window **new_list, int *new_count, + Window *list, int count, Window win) +{ + *new_count = count + 1; + *new_list = (Window*) malloc(sizeof(Window) * *new_count); + (*new_list)[0] = win; + memcpy(*new_list + 1, list, sizeof(Window) * count); +} + +/* rotate the list so the given window is at the beginning of it */ +static void +SetFirstWinList(Window *list, int count, Window win) +{ + int i; + + /* look for the given window starting from the end */ + list += count - 1; + for (i = 0; i < count; i++, list--) + if (*list == win) + break; + if (i < count) { /* when we found it rotate from there */ + /* shift every element to the right */ + for (i++; i < count; i++) { + list--; + list[1] = list[0]; + } + /* and set the first one */ + *list = win; + } +} + +/* rotate the list so the given window which should be the first item is + at the end of it */ +static void +SetLastWinList(Window *list, int count, Window win) +{ + if (*list == win) { + int i; + /* shift every element to the left */ + for (i = 0; i < count - 1; i++, list++) + list[0] = list[1]; + /* and set the last one */ + *list = win; + } +} + +static void +RemoveFromWinList(Window **wlist, int *count, Window win) +{ + Window *list = *wlist; + int i; + /* look for the window to remove */ + for (i = 0; i < *count; i++, list++) + if (*list == win) { + (*count)--; + break; + } + /* then simply shift following elements to the left */ + for (; i < *count; i++, list++) + list[0] = list[1]; +} + +static void +ConcatWinLists(Window **list, int *count, + Window *list1, int count1, + Window *list2, int count2) +{ + *count = count1 + count2; + *list = (Window*) malloc(sizeof(Window) * *count); + memcpy(*list, list1, sizeof(Window) * count1); + memcpy(*list + count1, list2, sizeof(Window) * count2); +} + +static void +SubstractWinLists(Window **wlist, int *count, + Window *list1, int count1) +{ + Window *list = *wlist; + int i, j; + /* look for the beginning of the list to remove */ + for (i = 0; i < *count; i++, list++) + if (*list == *list1) + break; + /* skip the list to remove stopping at the end of one of the lists + or at the first alien element */ + for (j = 0; j < count1 && i + j < *count; j++, list1++) + if (list[j] != *list1) + break; + /* then shift following elements */ + *count -= j; + for (; i < *count; i++, list++) + list[0] = list[j]; +} + +/*********************************************************************** + * Add window to the WM_COLORMAP_WINDOWS property on the Netscape + * toplevel widget if necessary + ***********************************************************************/ +static void +SetWMColormap(PluginInstance* This, Window win) +{ + int i; + Colormap top_cmap; + Arg arg; + + /* get window's record */ + for (i = 0; i < This->nclient_windows; i++) + if ((This->client_windows[i].win = win)) + break; + + if (i == This->nclient_windows) + return; + + /* if window's colormap is different from toplevel's one set property */ + XtSetArg(arg, XtNcolormap, &top_cmap); + XtGetValues(This->toplevel_widget, &arg, 1); + if (This->client_windows[i].colormap != top_cmap) { + Window *cur_list; + int cur_count = 0; + + /* if there is already a non empty list we need to update it */ + if (XGetWMColormapWindows(RxGlobal.dpy, XtWindow(This->toplevel_widget), + &cur_list, &cur_count) == True && + cur_count != 0) { + + if (IsInWinList(cur_list, cur_count, win)) { + /* window is already in the list just move it in first place */ + SetFirstWinList(cur_list, cur_count, win); + XSetWMColormapWindows(RxGlobal.dpy, + XtWindow(This->toplevel_widget), + cur_list, cur_count); + } else { + /* window is not in the list add it in first place */ + Window *new_list; + int new_count; + + PrependToWinList(&new_list, &new_count, + cur_list, cur_count, win); + XSetWMColormapWindows(RxGlobal.dpy, + XtWindow(This->toplevel_widget), + new_list, new_count); + free(new_list); + } + } else { /* no list yet so lets make one */ + Window list[2]; + + list[0] = win; + list[1] = XtWindow(This->toplevel_widget); + XSetWMColormapWindows(RxGlobal.dpy, XtWindow(This->toplevel_widget), + list, 2); + } + if (cur_count != 0) + XFree(cur_list); + } +} + +/*********************************************************************** + * Move window at the end of the WM_COLORMAP_WINDOWS property list on + * the Netscape toplevel widget + ***********************************************************************/ +static void +UnsetWMColormap(PluginInstance* This, Window win) +{ + Window *list; + int count = 0; + + if (XGetWMColormapWindows(RxGlobal.dpy, XtWindow(This->toplevel_widget), + &list, &count) == True && count != 0) { + SetLastWinList(list, count, win); + XSetWMColormapWindows(RxGlobal.dpy, XtWindow(This->toplevel_widget), + list, count); + } + if (count != 0) + XFree(list); +} + +/*********************************************************************** + * Remove window from the WM_COLORMAP_WINDOWS property on the Netscape + * toplevel widget + ***********************************************************************/ +static void +ResetWMColormap(PluginInstance* This, Window win) +{ + Window *list; + int count = 0; + + if (XGetWMColormapWindows(RxGlobal.dpy, XtWindow(This->toplevel_widget), + &list, &count) == True && count != 0) { + RemoveFromWinList(&list, &count, win); + + if (count > 1) + XSetWMColormapWindows(RxGlobal.dpy, XtWindow(This->toplevel_widget), + list, count); + else { /* remove list when it becomes useless */ + Atom prop; + + prop = XInternAtom (RxGlobal.dpy, "WM_COLORMAP_WINDOWS", False); + XDeleteProperty(RxGlobal.dpy, XtWindow(This->toplevel_widget), prop); + } + } + if (count != 0) + XFree(list); +} + +/*********************************************************************** + * Event Handler to reparent client window under plugin window + ***********************************************************************/ +/* static */ void +SubstructureRedirectHandler ( + Widget widget, + XtPointer client_data, + XEvent* event, + Boolean* cont) +{ + windowrec* new_list; + PluginInstance* This = (PluginInstance*) client_data; + +#ifdef PLUGIN_TRACE + fprintf (stderr, "%s\n", "SubstructureRedirectHandler"); + fprintf (stderr, "This: 0x%x\n", This); +#endif + + switch (event->type) { + case ConfigureRequest: + { + XWindowChanges config; + config.x = event->xconfigurerequest.x; + config.y = event->xconfigurerequest.y; + config.width = event->xconfigurerequest.width; + config.height = event->xconfigurerequest.height; + config.border_width = event->xconfigurerequest.border_width; + config.sibling = event->xconfigurerequest.above; + config.stack_mode = event->xconfigurerequest.detail; +#if 0 + fprintf (stderr, "configuring at %dx%d+%d+%d\n", + config.width, config.height, config.x, config.y); +#endif + XConfigureWindow (RxGlobal.dpy, + event->xconfigurerequest.window, + event->xconfigurerequest.value_mask, + &config); + } + break; + + case MapRequest: + + RxpSetStatusWidget(This, RUNNING); + + { + Window for_win; + int i; + + if (XGetTransientForHint (RxGlobal.dpy, event->xmaprequest.window, + &for_win)) { + for (i = 0; i < This->nclient_windows; i++) + if (for_win == This->client_windows[i].win) + XMapWindow (RxGlobal.dpy, event->xmaprequest.window); + return; + } + } + new_list = (windowrec*) + NPN_MemAlloc (sizeof (windowrec) * (This->nclient_windows + 1)); + if (new_list) { + Position x, y; + Dimension width, height; + Dimension border_width; + Colormap cmap; + int n; + Atom* wm_proto; + windowrec* wp; + Window destwin = XtWindow (This->plugin_widget); + + This->nclient_windows++; + if (This->nclient_windows > 1) + memcpy ((void*) new_list, (void*) This->client_windows, + (This->nclient_windows - 1) * sizeof (windowrec)); + if (This->client_windows) + NPN_MemFree (This->client_windows); + This->client_windows = new_list; + + x = y = 0; + width = height = border_width = 0; + GetWindowGeometry (RxGlobal.dpy, event->xmaprequest.window, + &x, &y, &width, &height, &border_width, &cmap); + + wp = &This->client_windows[This->nclient_windows - 1]; + wp->win = event->xmaprequest.window; + wp->x = x; wp->y = y; + wp->width = width; wp->height = height; + wp->border_width = border_width; + wp->flags = RxpMapped; + wp->colormap = cmap; + + if (XGetWMProtocols (RxGlobal.dpy, wp->win, &wm_proto, &n)) { + int i; + Atom* ap; + + for (i = 0, ap = wm_proto; i < n; i++, ap++) { + if (*ap == RxGlobal.wm_delete_window) + wp->flags |= RxpWmDelWin; + } + if (wm_proto) XFree ((char*) wm_proto); + } + + XSelectInput(RxGlobal.dpy, wp->win, + EnterWindowMask | LeaveWindowMask); + XtRegisterDrawable (RxGlobal.dpy, wp->win, This->plugin_widget); + XReparentWindow (RxGlobal.dpy, wp->win, destwin, wp->x, wp->y); + XMapWindow (RxGlobal.dpy, wp->win); + } + break; + } +} + +/*********************************************************************** + * Event Handler to forward WM_DELETE_WINDOW events to the client windows + ***********************************************************************/ +void +RxpWmDelWinHandler ( + Widget widget, + XtPointer client_data, + XEvent* event, + Boolean* cont) +{ + PluginInstance* This = (PluginInstance*) client_data; + int i; + + if (event == NULL || + (event->type == ClientMessage && + event->xclient.message_type == RxGlobal.wm_protocols && + event->xclient.data.l[0] == RxGlobal.wm_delete_window)) { + for (i = 0; i < This->nclient_windows; i++) { + if (This->client_windows[i].flags & RxpWmDelWin) { + XClientMessageEvent ev; + + ev.type = ClientMessage; + ev.window = This->client_windows[i].win; + ev.message_type = RxGlobal.wm_protocols; + ev.format = 32; + ev.data.l[0] = RxGlobal.wm_delete_window; + ev.data.l[1] = XtLastTimestampProcessed (XtDisplay (widget)); + XSendEvent (RxGlobal.dpy, ev.window, FALSE, 0L, (XEvent*) &ev); + } + } + } +} + +/*********************************************************************** + * Event Handler to forward ConfigureNotify events to the client windows + ***********************************************************************/ +static void +StructureNotifyHandler ( + Widget widget, + XtPointer client_data, + XEvent* event, + Boolean* cont) +{ + PluginInstance* This = (PluginInstance*) client_data; + +#ifdef PLUGIN_TRACE + fprintf (stderr, "%s\n", "StructureNotifyHandler"); +#endif + + switch (event->type) { + + /* + * For the testplugin, which uses a ScrolledWindow, the clipped + * window, i.e. This->plugin, is "configured" when the user pans + * around the ScrolledWindow. The Netscape scrolled-window is + * different. It moves-and-resizes the clip window, causing the + * child, i.e. This->plugin, to be "dragged" up by win-gravity. + */ + case ConfigureNotify: + case GravityNotify: + if (This->plugin_widget == NULL) + return; + + { + int i; + Position x, y; + XConfigureEvent sendev; + + XtTranslateCoords (This->plugin_widget, 0, 0, &x, &y); + for (i = 0; i < This->nclient_windows; i++) { + sendev.type = ConfigureNotify; + sendev.send_event = True; + sendev.event = sendev.window = This->client_windows[i].win; + sendev.x = x + This->client_windows[i].x; + sendev.y = y + This->client_windows[i].y; + sendev.width = This->client_windows[i].width; + sendev.height = This->client_windows[i].height; + sendev.border_width = This->client_windows[i].border_width; + sendev.above = None; + sendev.override_redirect = False; + if (!XSendEvent (RxGlobal.dpy, This->client_windows[i].win, + False, StructureNotifyMask, + (XEvent*) &sendev)) + (void) fprintf (stderr, "%s\n", "XSendEvent Failed"); + } + } + break; + + default: + break; + } +} + +/*********************************************************************** + * Event Handler to detect the destruction of a client window + ***********************************************************************/ +static void +SubstructureNotifyHandler ( + Widget widget, + XtPointer client_data, + XEvent* event, + Boolean* cont) +{ + PluginInstance* This = (PluginInstance*) client_data; + +#ifdef PLUGIN_TRACE + fprintf (stderr, "%s\n", "SubstructureNotifyHandler"); +#endif + + if (event->type == DestroyNotify) { + int i; +#ifdef PLUGIN_TRACE + fprintf (stderr, "%s\n", "DestroyNotify"); +#endif + for (i = 0; i < This->nclient_windows; i++) + if (This->client_windows[i].win == event->xdestroywindow.window) { + This->nclient_windows--; + if (This->nclient_windows > 0) { + /* remove this window from the list */ + for (; i < This->nclient_windows; i++) + This->client_windows[i] = This->client_windows[i + 1]; + } else { /* no more client windows! */ + /* get back to user to restart the application */ + RxpSetStatusWidget(This, WAITING); + } + ResetWMColormap(This, event->xdestroywindow.window); + UnregisterDrawable(event->xdestroywindow.window, + This->plugin_widget); + break; + } + + } +} + +/*********************************************************************** + * Arrange to receive (synthetic) ConfigureNotify events on the proper + * windows of this instance and relay them to the embedded apps + ***********************************************************************/ +static void +SetupStructureNotify (PluginInstance* This) +{ + /* Get ConfigureNotify when the browser is moved */ + XtAddRawEventHandler (This->toplevel_widget, + StructureNotifyMask, + False, + StructureNotifyHandler, + (XtPointer) This); + + XtAddRawEventHandler (This->toplevel_widget, + NoEventMask, + True, + RxpWmDelWinHandler, + (XtPointer) This); +#if 0 + XmAddWMProtocolCallback (This->toplevel_widget, + RxGlobal.wm_delete_window, + RxpWmDelWinHandler, + (XtPointer) This); +#endif +} + +/*********************************************************************** + * Event Handler to deal with colormap settings + ***********************************************************************/ +static void +CrossingHandler ( + Widget widget, + XtPointer client_data, + XEvent* event, + Boolean* cont) +{ + PluginInstance* This = (PluginInstance*) client_data; + +#ifdef PLUGIN_TRACE + fprintf (stderr, "%s: 0x%x\n", "CrossingHandler", event->xany.window); +#endif + + if (event->xany.window != XtWindow(This->plugin_widget) && + event->xcrossing.detail != NotifyInferior) { + if (event->type == EnterNotify) { +#ifdef PLUGIN_TRACE + fprintf (stderr, "%s\n", "EnterNotify"); +#endif + SetWMColormap(This, event->xany.window); + } else if (event->type == LeaveNotify) { +#ifdef PLUGIN_TRACE + fprintf (stderr, "%s\n", "LeaveNotify"); +#endif + UnsetWMColormap(This, event->xany.window); + } + } +} + +/*********************************************************************** + * Setup various event handlers on the plugin widget + ***********************************************************************/ +void +RxpSetupPluginEventHandlers (PluginInstance* This) +{ + int i; + + /* Get ConfigureNotify and GravityNotify on the plugin */ + XtAddEventHandler (This->plugin_widget, + StructureNotifyMask, + False, + StructureNotifyHandler, + (XtPointer) This); + /* Arrange to receive DestroyNotify events on the clients windows. */ + XtAddEventHandler (This->plugin_widget, + SubstructureNotifyMask, + False, + SubstructureNotifyHandler, + (XtPointer) This); + /* Arrange to receive MapRequest and ConfigureRequest events on the + * netscape plug-in widget. */ + XtAddRawEventHandler(This->plugin_widget, + SubstructureRedirectMask, + False, + SubstructureRedirectHandler, + (XtPointer) This); + XtRegisterDrawable (RxGlobal.dpy, This->app_group, This->plugin_widget); + + /* Arrange to receive Enter and Leave Notify events on application's + toplevel windows */ + XtAddRawEventHandler(This->plugin_widget, + EnterWindowMask | LeaveWindowMask, + False, + CrossingHandler, + (XtPointer) This); + for (i = 0; i < This->nclient_windows; i++) { + XtRegisterDrawable (RxGlobal.dpy, + This->client_windows[i].win, This->plugin_widget); + } +} + +/*********************************************************************** + * The instance is gone. Remove Event Handlers so that they aren't + * called with a reference to the old instance. + ***********************************************************************/ +void +RxpTeardown (PluginInstance* This) +{ + if (This->toplevel_widget != NULL) { + /* ConfigureNotify on top level */ + XtRemoveRawEventHandler (This->toplevel_widget, + StructureNotifyMask, + False, + StructureNotifyHandler, + (XtPointer) This); + XtRemoveRawEventHandler (This->toplevel_widget, + NoEventMask, + True, + RxpWmDelWinHandler, + (XtPointer) This); +#if 0 + XmRemoveWMProtocolCallback (This->toplevel_widget, + RxGlobal.wm_delete_window, + RxpWmDelWinHandler, + (XtPointer) This); +#endif + } +} + +/*********************************************************************** + * Process the given RxParams and make the RxReturnParams + ***********************************************************************/ + +static int +ProcessUIParams(PluginInstance* This, + Boolean trusted, Boolean use_fwp, Boolean use_lbx, + RxParams *in, RxReturnParams *out, char **x_ui_auth_ret) +{ + XSecurityAuthorization dum; + int dummy; + char *display_name; + + This->app_group = None; + if (out->embedded != RxFalse) { /* default is embedded */ + /* let's see whether the server supports AppGroups or not */ + if (RxGlobal.has_appgroup == RxUndef) { + if (XQueryExtension(RxGlobal.dpy, "XC-APPGROUP", + &dummy, &dummy, &dummy) && + XagQueryVersion (RxGlobal.dpy, &dummy, &dummy)) + RxGlobal.has_appgroup = RxTrue; + else + RxGlobal.has_appgroup = RxFalse; + } + if (RxGlobal.has_appgroup == RxTrue) { + Screen *scr; + Colormap cmap; + Arg arg; + + /* use plugin's colormap as the default colormap */ + XtSetArg(arg, XtNcolormap, &cmap); + XtGetValues(This->plugin_widget, &arg, 1); + scr = XtScreen(This->plugin_widget); + if (cmap == DefaultColormapOfScreen(scr)) { + XagCreateEmbeddedApplicationGroup (RxGlobal.dpy, None, + cmap, + BlackPixelOfScreen(scr), + WhitePixelOfScreen(scr), + &This->app_group); + } else { + XColor black, white; + Pixel pixels[2]; + + black.red = black.green = black.blue = 0; + XAllocColor(RxGlobal.dpy, cmap, &black); + white.red = white.green = white.blue = 65535; + XAllocColor(RxGlobal.dpy, cmap, &white); + XagCreateEmbeddedApplicationGroup (RxGlobal.dpy, None, + cmap, + pixels[0] = black.pixel, + pixels[1] = white.pixel, + &This->app_group); + XFreeColors(RxGlobal.dpy, cmap, pixels, 2, 0); + } + SetupStructureNotify (This); + RxpSetupPluginEventHandlers (This); + } else { /* too bad */ + out->embedded = RxFalse; + fprintf(stderr, "Warning: Cannot perform embedding as \ +requested, APPGROUP extension not supported\n"); + } + } + + if (in->x_ui_auth[0] != 0) { + GetXAuth(RxGlobal.dpy, in->x_ui_auth[0], in->x_ui_auth_data[0], + trusted, This->app_group, False, DEFAULT_TIMEOUT, + x_ui_auth_ret, &This->x_ui_auth_id, &dummy); + } else if (in->x_auth[0] != 0) + GetXAuth(RxGlobal.dpy, in->x_auth[0], in->x_auth_data[0], + trusted, This->app_group, False, DEFAULT_TIMEOUT, + x_ui_auth_ret, &This->x_ui_auth_id, &dummy); + + /* make sure we use the server the user wants us to use */ + if (RxGlobal.has_real_server == RxUndef) { + Display *rdpy = RxGlobal.dpy; + char *real_display = getenv("XREALDISPLAY"); + RxGlobal.has_real_server = RxFalse; + if (real_display != NULL) { + rdpy = XOpenDisplay(real_display); + if (rdpy == NULL) + rdpy = RxGlobal.dpy; + else + RxGlobal.has_real_server = RxTrue; + } + /* let's see now whether the server supports LBX or not */ + if (XQueryExtension(rdpy, "LBX", &dummy, &dummy, &dummy)) + RxGlobal.has_ui_lbx = RxTrue; + else + RxGlobal.has_ui_lbx = RxFalse; + + if (rdpy != RxGlobal.dpy) + XCloseDisplay(rdpy); + } + if (RxGlobal.has_real_server == RxTrue) + display_name = getenv("XREALDISPLAY"); + else + display_name = DisplayString(RxGlobal.dpy); + + /* let's see whether we have a firewall proxy */ + if (use_fwp == True && RxGlobal.has_ui_fwp == RxUndef) { + RxGlobal.fwp_dpyname = GetXFwpDisplayName(display_name); + if (RxGlobal.fwp_dpyname != NULL) + RxGlobal.has_ui_fwp = RxTrue; + else { + /* + * We were supposed to use the firewall proxy but we + * couldn't get a connection. There is no need to + * continue. + */ + return 1; + } + } + if (use_fwp == True && RxGlobal.has_ui_fwp == RxTrue) + out->ui = GetXUrl(RxGlobal.fwp_dpyname, *x_ui_auth_ret, in->action); + else + out->ui = GetXUrl(display_name, *x_ui_auth_ret, in->action); + + if (in->x_ui_lbx == RxTrue) { + if (use_lbx == True) { + if (RxGlobal.has_ui_lbx == RxTrue) { + out->x_ui_lbx = RxTrue; + + /* let's get a key for the proxy now */ + if (in->x_ui_lbx_auth[0] != 0) { + GetXAuth(RxGlobal.dpy, in->x_ui_lbx_auth[0], + in->x_ui_lbx_auth_data[0], + trusted, None, False, DEFAULT_TIMEOUT, + &out->x_ui_lbx_auth, &dum, &dummy); + } else if (in->x_auth[0] != 0) + GetXAuth(RxGlobal.dpy, in->x_auth[0], in->x_auth_data[0], + trusted, None, False, DEFAULT_TIMEOUT, + &out->x_ui_lbx_auth, &dum, &dummy); + } else { + out->x_ui_lbx = RxFalse; + fprintf(stderr, "Warning: Cannot setup LBX as requested, \ +LBX extension not supported\n"); + } + } else + out->x_ui_lbx = RxFalse; + } else /* it's either RxFalse or RxUndef */ + out->x_ui_lbx = in->x_ui_lbx; + + return 0; +} + +static int +ProcessPrintParams(PluginInstance* This, + Boolean trusted, Boolean use_fwp, Boolean use_lbx, + RxParams *in, RxReturnParams *out, char *x_ui_auth) +{ + char *auth = NULL; + XSecurityAuthorization dum; + int dummy; + + /* let's find out if we have a print server */ + if (RxGlobal.has_printer == RxUndef) { + RxGlobal.pdpy_name = GetXPrintDisplayName(&RxGlobal.printer_name); + if (RxGlobal.pdpy_name != NULL) { + /* open connection to the print server */ + RxGlobal.pdpy = XOpenDisplay(RxGlobal.pdpy_name); + if (RxGlobal.pdpy != NULL) + RxGlobal.has_printer = RxTrue; + else + RxGlobal.has_printer = RxFalse; + } else { + /* no server specified, + let's see if the video server could do it */ + if (XQueryExtension(RxGlobal.dpy, "XpExtension", + &dummy, &dummy, &dummy)) { + RxGlobal.has_printer = RxTrue; + RxGlobal.pdpy = RxGlobal.dpy; + } else + RxGlobal.has_printer = RxFalse; + } + } + if (RxGlobal.has_printer == RxFalse) { + fprintf(stderr, "Warning: Cannot setup X printer as requested, \ +no server found\n"); + return 0; + } + + /* create a key only when the video server is not the print + server or when we didn't create a key yet */ + if (RxGlobal.pdpy != RxGlobal.dpy || x_ui_auth == NULL) { + if (in->x_print_auth[0] != 0) + GetXAuth(RxGlobal.pdpy, in->x_print_auth[0], + in->x_print_auth_data[0], + trusted, None, False, NO_TIMEOUT, + &auth, &This->x_print_auth_id, &dummy); + else if (in->x_auth[0] != 0) + GetXAuth(RxGlobal.pdpy, in->x_auth[0], in->x_auth_data[0], + trusted, None, False, NO_TIMEOUT, + &auth, &This->x_print_auth_id, &dummy); + } + + /* let's see whether we have a firewall proxy */ + if (use_fwp == True && RxGlobal.has_print_fwp == RxUndef) { + RxGlobal.pfwp_dpyname = GetXFwpDisplayName(DisplayString(RxGlobal.pdpy)); + if (RxGlobal.pfwp_dpyname != NULL) + RxGlobal.has_print_fwp = RxTrue; + else { + /* + * We were supposed to use the firewall proxy but we + * couldn't get a connection. There is no need to + * continue. + */ + return 1; + } + } + if (use_fwp == True && RxGlobal.has_print_fwp == RxTrue) + out->print = GetXPrintUrl(RxGlobal.pfwp_dpyname, + RxGlobal.printer_name, auth, + in->action); + else + out->print = GetXPrintUrl(DisplayString(RxGlobal.pdpy), + RxGlobal.printer_name, auth, + in->action); + + if (auth != NULL) + NPN_MemFree(auth); + + if (in->x_print_lbx == RxTrue) { + if (use_lbx == True) { + /* let's see whether the server supports LBX or not */ + if (RxGlobal.has_print_lbx == RxUndef) { + if (RxGlobal.pdpy == RxGlobal.dpy && + RxGlobal.has_ui_lbx != RxUndef) { + /* the video server is the print server and we already + know whether it supports LBX or not */ + RxGlobal.has_print_lbx = RxGlobal.has_ui_lbx; + } else { + if (XQueryExtension(RxGlobal.pdpy, "LBX", + &dummy, &dummy, &dummy)) + RxGlobal.has_print_lbx = RxTrue; + else + RxGlobal.has_print_lbx = RxFalse; + } + } + if (RxGlobal.has_print_lbx == RxTrue) { + out->x_print_lbx = RxTrue; + if (RxGlobal.pdpy != RxGlobal.dpy) { + /* let's get a key for the proxy now */ + if (in->x_print_lbx_auth[0] != 0) { + GetXAuth(RxGlobal.pdpy, in->x_print_lbx_auth[0], + in->x_print_lbx_auth_data[0], + trusted, None, False, DEFAULT_TIMEOUT, + &out->x_print_lbx_auth, &dum, &dummy); + } else if (in->x_auth[0] != 0) + GetXAuth(RxGlobal.pdpy, in->x_auth[0], + in->x_auth_data[0], + trusted, None, False, DEFAULT_TIMEOUT, + &out->x_print_lbx_auth, &dum, &dummy); + } + } else { + out->x_print_lbx = RxFalse; + fprintf(stderr, "Warning: Cannot setup LBX as \ +requested, LBX extension not supported\n"); + } + } else + out->x_print_lbx = RxFalse; + } else /* it's either RxFalse or RxUndef */ + out->x_print_lbx = in->x_print_lbx; + + return 0; +} + +int +RxpProcessParams(PluginInstance* This, RxParams *in, RxReturnParams *out) +{ + char *x_ui_auth = NULL; + char webserver[MAXHOSTNAMELEN]; + Boolean trusted, use_fwp, use_lbx; + int return_value = 0; + +#ifdef PLUGIN_TRACE + fprintf (stderr, "%s\n", "RxpProcessParams"); + fprintf (stderr, "This: 0x%x\n", This); +#endif + + /* init return struture */ + memset(out, 0, sizeof(RxReturnParams)); + out->x_ui_lbx = RxUndef; + out->x_print_lbx = RxUndef; + out->action = in->action; + + if (in->embedded != RxUndef) + out->embedded = in->embedded; + else + out->embedded = RxUndef; + + out->width = in->width; + out->height = in->height; + + if (RxGlobal.get_prefs == True) { + GetPreferences(This->toplevel_widget, &RxGlobal.prefs); + RxGlobal.get_prefs = False; + } + ComputePreferences(&RxGlobal.prefs, + ParseHostname(in->action, webserver, MAXHOSTNAMELEN) ? webserver : NULL, + &trusted, &use_fwp, &use_lbx); + + if (in->ui[0] == XUI) /* X display needed */ + return_value = ProcessUIParams(This, trusted, use_fwp, use_lbx, + in, out, &x_ui_auth); + + if (in->print[0] == XPrint) /* XPrint server needed */ + return_value = ProcessPrintParams(This, trusted, use_fwp, use_lbx, + in, out, x_ui_auth); + + if (x_ui_auth != NULL) + NPN_MemFree(x_ui_auth); + + return return_value; +} diff --git a/plugin/RxPlugin.h b/plugin/RxPlugin.h new file mode 100644 index 0000000..9b97789 --- /dev/null +++ b/plugin/RxPlugin.h @@ -0,0 +1,171 @@ +/* $Xorg: RxPlugin.h,v 1.4 2001/02/09 02:05:57 xorgcvs Exp $ */ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- +ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABIL- +ITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization from +The Open Group. + +*/ + +/* + * RX plug-in header file, based on the UnixTemplate file provided by Netcape. + */ + +/* -*- Mode: C; tab-width: 4; -*- */ +/****************************************************************************** + * Copyright 1996 Netscape Communications. All rights reserved. + ******************************************************************************/ +/* + * UnixShell.c + * + * Netscape Client Plugin API + * - Function that need to be implemented by plugin developers + * + * This file defines a "Template" plugin that plugin developers can use + * as the basis for a real plugin. This shell just provides empty + * implementations of all functions that the plugin can implement + * that will be called by Netscape (the NPP_xxx methods defined in + * npapi.h). + * + * dp Suresh <dp@netscape.com> + * + */ + +#ifndef _RxPlugin_h +#define _RxPLugin_h + +#include "npapi.h" +#include <X11/Xos.h> +#include <X11/Intrinsic.h> +#include <X11/extensions/Xag.h> +#include <X11/extensions/security.h> +#include <X11/ICE/ICElib.h> +#include <stdio.h> +#include "Rx.h" +#include "Prefs.h" + +/*********************************************************************** + * Instance state information about the plugin. + * + * PLUGIN DEVELOPERS: + * Use this struct to hold per-instance information that you'll + * need in the various functions in this file. + ***********************************************************************/ + +typedef enum { + RxpNoflags = 0, + RxpWmDelWin = (1 << 0), + RxpMapped = (1 << 4) +} WindowFlags; + +typedef struct { + Window win; + Position x,y; + Dimension width,height; + Dimension border_width; + WindowFlags flags; + Colormap colormap; +} windowrec; + +typedef enum { LOADING, STARTING, WAITING, RUNNING } PluginState; + +typedef struct _PluginInstance +{ + NPP instance; + int16 argc; /* HTML arguments given by Netscape */ + char **argn; + char **argv; + short parse_reply; /* 0 - no + 1 - look for status line + 2 - done */ + short status; /* returned application status */ + RxBool dont_reparent; /* whether client windows need reparent*/ + char *query; + PluginState state; + Widget status_widget; + Widget plugin_widget; + Dimension width, height; + /* The following fields need to be taken care by RxpNew & RxpDestroy */ + XSecurityAuthorization x_ui_auth_id; + XSecurityAuthorization x_print_auth_id; + XAppGroup app_group; + Widget toplevel_widget; + windowrec *client_windows; + int nclient_windows; +} PluginInstance; + +typedef struct _PluginGlobal { + Boolean inited; + RxBool has_appgroup; + RxBool has_real_server; + RxBool has_ui_lbx; + RxBool has_print_lbx; + RxBool has_printer; + RxBool has_ui_fwp; + RxBool has_print_fwp; + char *pdpy_name; + char *printer_name; + char *fwp_dpyname; + char *pfwp_dpyname; + struct _IceConn* ice_conn; + int pm_opcode; + Preferences prefs; + Boolean get_prefs; + Display* dpy; + Display* pdpy; + Atom wm_delete_window; + Atom wm_protocols; +} PluginGlobal; + +extern PluginGlobal RxGlobal; + + +#define PLUGIN_NAME "RX Plug-in" +#define PLUGIN_DESCRIPTION "X Remote Activation Plug-in" +#define PLUGIN_MIME_DESCRIPTION \ + "application/x-rx:xrx:X Remote Activation Plug-in" + + +/* functions to init and free private members */ +extern void RxpNew(PluginInstance*); +extern void RxpDestroy(PluginInstance*); + +extern int +RxpProcessParams(PluginInstance*, RxParams*, RxReturnParams*); + +extern void +RxpSetStatusWidget(PluginInstance*, PluginState); + +extern void +RxpSetupPluginEventHandlers(PluginInstance*); + +extern void +RxpTeardown (PluginInstance*); + +extern void +RxpWmDelWinHandler (Widget, XtPointer, XEvent*, Boolean*); + +extern void +RxpRemoveDestroyCallback (PluginInstance*); + +#endif diff --git a/plugin/SetWin.c b/plugin/SetWin.c new file mode 100644 index 0000000..3e60f75 --- /dev/null +++ b/plugin/SetWin.c @@ -0,0 +1,213 @@ +/* $Xorg: SetWin.c,v 1.4 2001/02/09 02:05:57 xorgcvs Exp $ */ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- +ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABIL- +ITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization from +The Open Group. + +*/ + +/* + * RX plug-in module based on the UnixTemplate file provided by Netcape. + */ + +/* -*- Mode: C; tab-width: 4; -*- */ +/****************************************************************************** + * Copyright 1996 Netscape Communications. All rights reserved. + ******************************************************************************/ +/* + * UnixShell.c + * + * Netscape Client Plugin API + * - Function that need to be implemented by plugin developers + * + * This file defines a "Template" plugin that plugin developers can use + * as the basis for a real plugin. This shell just provides empty + * implementations of all functions that the plugin can implement + * that will be called by Netscape (the NPP_xxx methods defined in + * npapi.h). + * + * dp Suresh <dp@netscape.com> + * + */ + +#include "RxPlugin.h" +#include <X11/StringDefs.h> + +/*********************************************************************** + * Sometimes the plugin widget gets stupidly destroyed, that is whenever + * Netscape relayouts the page. This callback reparents the client + * windows to the root window so they do not get destroyed as well. + * Eventually the NPP_SetWindow function should be called and we'll + * reparent them back under the plugin. + ***********************************************************************/ +static void +DestroyCB (Widget widget, XtPointer client_data, XtPointer call_data) +{ + PluginInstance* This = (PluginInstance*) client_data; + int i; +#ifdef PLUGIN_TRACE + fprintf (stderr, "DestroyCB, This: 0x%x\n", This); +#endif + if (widget == This->plugin_widget) { + This->plugin_widget = NULL; + This->status_widget = NULL; + } + if (This->dont_reparent == RxFalse) { + for (i = 0; i < This->nclient_windows; i++) { + XUnmapWindow (RxGlobal.dpy, This->client_windows[i].win); + This->client_windows[i].flags &= ~RxpMapped; + + XReparentWindow (RxGlobal.dpy, This->client_windows[i].win, + (XtScreen (widget))->root, 0, 0); + } + This->dont_reparent = RxTrue; + } else + This->dont_reparent = RxFalse; + /* + * not worth removing event handlers on this widget since it's + * about to be destroyed anyway. + */ +} + + +/*********************************************************************** + * Sometimes the plugin widget gets stupidly resized, because of poor + * geometry when its child (that is the status widget) gets destroyed. + * So this callback resizes it back to the right size. + * Note that this could lead to an endless battle, but it appears that + * it doesn't so far... + ***********************************************************************/ +static void +ResizeCB (Widget widget, XtPointer client_data, XtPointer call_data) +{ + PluginInstance* This = (PluginInstance*) client_data; + Arg args[5]; + int n; + +#ifdef PLUGIN_TRACE + fprintf (stderr, "ResizeCB, This: 0x%x\n", This); +#endif + /* make sure plugin widget gets the same size back */ + n = 0; + XtSetArg(args[n], XtNwidth, This->width); n++; + XtSetArg(args[n], XtNheight, This->height); n++; + XtSetValues(This->plugin_widget, args, n); +} + +static Widget +FindToplevel(Widget widget) +{ + while (XtParent(widget) != NULL && !XtIsTopLevelShell(widget)) + widget = XtParent(widget); + + return widget; +} + +/*********************************************************************** + * This function gets called first when the plugin widget is created and + * then whenever the plugin is changed. + ***********************************************************************/ +NPError +NPP_SetWindow(NPP instance, NPWindow* window) +{ + PluginInstance* This; + Widget netscape_widget; + + if (instance == NULL) + return NPERR_INVALID_INSTANCE_ERROR; + + if (window == NULL) + return NPERR_NO_ERROR; + + /* + * PLUGIN DEVELOPERS: + * Before setting window to point to the + * new window, you may wish to compare the new window + * info to the previous window (if any) to note window + * size changes, etc. + */ + This = (PluginInstance*) instance->pdata; +#ifdef PLUGIN_TRACE + fprintf(stderr, "SetWindow 0x%x.\n", (Window) window->window); + fprintf(stderr, "This: 0x%x\n", This); + if (This->plugin_widget) + fprintf(stderr, "This->plugin_widget: 0x%x\n", This->plugin_widget); +#endif + if (RxGlobal.dpy == NULL) { + RxGlobal.dpy = ((NPSetWindowCallbackStruct *)window->ws_info)->display; + RxGlobal.wm_delete_window = + XInternAtom (RxGlobal.dpy, "WM_DELETE_WINDOW", TRUE); + RxGlobal.wm_protocols = XInternAtom (RxGlobal.dpy, "WM_PROTOCOLS", TRUE); + } + netscape_widget = XtWindowToWidget(RxGlobal.dpy, (Window) window->window); + if (This->toplevel_widget == NULL) + This->toplevel_widget = FindToplevel(netscape_widget); + + if (This->plugin_widget != netscape_widget) { + + /* We have a new widget store it */ + This->plugin_widget = netscape_widget; + This->width = window->width; + This->height = window->height; + + XtAddCallback (This->plugin_widget, XtNdestroyCallback, + DestroyCB, (XtPointer) This); + XtAddCallback (This->plugin_widget, "resizeCallback", + ResizeCB, (XtPointer) This); + + if (This->app_group) + RxpSetupPluginEventHandlers (This); + + if (This->nclient_windows > 0) { + int i; + + /* We already have the client, so we need to reparent it to the + new window */ + for (i = 0; i < This->nclient_windows; i++) { + XReparentWindow(RxGlobal.dpy, This->client_windows[i].win, + XtWindow(netscape_widget), + This->client_windows[i].x, + This->client_windows[i].y); + if (This->dont_reparent == RxTrue) { + XMapWindow (RxGlobal.dpy, This->client_windows[i].win); + This->client_windows[i].flags |= RxpMapped; + } + } + } else /* no client window, display status widget */ + RxpSetStatusWidget(This, This->state); + if (This->dont_reparent != RxFalse) /* can be True or Undef */ + This->dont_reparent = RxFalse; + else + This->dont_reparent = RxTrue; + } + return NPERR_NO_ERROR; +} + +void +RxpRemoveDestroyCallback(PluginInstance *This) +{ + if (This->plugin_widget != NULL) + XtRemoveCallback(This->plugin_widget, XtNdestroyCallback, + DestroyCB, (XtPointer) This); +} diff --git a/plugin/common/npunix.c b/plugin/common/npunix.c new file mode 100644 index 0000000..bedd861 --- /dev/null +++ b/plugin/common/npunix.c @@ -0,0 +1,407 @@ +/* $Xorg: npunix.c,v 1.3 2000/08/17 19:54:59 cpqbld Exp $ */ +/* + * npunix.c + * + * Netscape Client Plugin API + * - Wrapper function to interface with the Netscape Navigator + * + * dp Suresh <dp@netscape.com> + * + *---------------------------------------------------------------------- + * PLUGIN DEVELOPERS: + * YOU WILL NOT NEED TO EDIT THIS FILE. + *---------------------------------------------------------------------- + */ + +#define XP_UNIX 1 + +#include <stdio.h> +#include "npapi.h" +#include "npupp.h" + +/* + * Define PLUGIN_TRACE to have the wrapper functions print + * messages to stderr whenever they are called. + */ + +#ifdef PLUGIN_TRACE +#include <stdio.h> +#define PLUGINDEBUGSTR(msg) fprintf(stderr, "%s\n", msg) +#else +#define PLUGINDEBUGSTR(msg) +#endif + + +/*********************************************************************** + * + * Globals + * + ***********************************************************************/ + +static NPNetscapeFuncs gNetscapeFuncs; /* Netscape Function table */ + + +/*********************************************************************** + * + * Wrapper functions : plugin calling Netscape Navigator + * + * These functions let the plugin developer just call the APIs + * as documented and defined in npapi.h, without needing to know + * about the function table and call macros in npupp.h. + * + ***********************************************************************/ + +void +NPN_Version(int* plugin_major, int* plugin_minor, + int* netscape_major, int* netscape_minor) +{ + *plugin_major = NP_VERSION_MAJOR; + *plugin_minor = NP_VERSION_MINOR; + + /* Major version is in high byte */ + *netscape_major = gNetscapeFuncs.version >> 8; + /* Minor version is in low byte */ + *netscape_minor = gNetscapeFuncs.version & 0xFF; +} + +NPError +NPN_GetValue(NPP instance, NPNVariable variable, void *r_value) +{ + return CallNPN_GetValueProc(gNetscapeFuncs.getvalue, + instance, variable, r_value); +} + +NPError +NPN_GetURL(NPP instance, const char* url, const char* window) +{ + return CallNPN_GetURLProc(gNetscapeFuncs.geturl, instance, url, window); +} + +NPError +NPN_PostURL(NPP instance, const char* url, const char* window, + uint32 len, const char* buf, NPBool file) +{ + return CallNPN_PostURLProc(gNetscapeFuncs.posturl, instance, + url, window, len, buf, file); +} + +NPError +NPN_RequestRead(NPStream* stream, NPByteRange* rangeList) +{ + return CallNPN_RequestReadProc(gNetscapeFuncs.requestread, + stream, rangeList); +} + +NPError +NPN_NewStream(NPP instance, NPMIMEType type, const char *window, + NPStream** stream_ptr) +{ + return CallNPN_NewStreamProc(gNetscapeFuncs.newstream, instance, + type, window, stream_ptr); +} + +int32 +NPN_Write(NPP instance, NPStream* stream, int32 len, void* buffer) +{ + return CallNPN_WriteProc(gNetscapeFuncs.write, instance, + stream, len, buffer); +} + +NPError +NPN_DestroyStream(NPP instance, NPStream* stream, NPError reason) +{ + return CallNPN_DestroyStreamProc(gNetscapeFuncs.destroystream, + instance, stream, reason); +} + +void +NPN_Status(NPP instance, const char* message) +{ + CallNPN_StatusProc(gNetscapeFuncs.status, instance, message); +} + +const char* +NPN_UserAgent(NPP instance) +{ + return CallNPN_UserAgentProc(gNetscapeFuncs.uagent, instance); +} + +void* +NPN_MemAlloc(uint32 size) +{ + return CallNPN_MemAllocProc(gNetscapeFuncs.memalloc, size); +} + +void NPN_MemFree(void* ptr) +{ + CallNPN_MemFreeProc(gNetscapeFuncs.memfree, ptr); +} + +uint32 NPN_MemFlush(uint32 size) +{ + return CallNPN_MemFlushProc(gNetscapeFuncs.memflush, size); +} + +void NPN_ReloadPlugins(NPBool reloadPages) +{ + CallNPN_ReloadPluginsProc(gNetscapeFuncs.reloadplugins, reloadPages); +} + +JRIEnv* NPN_GetJavaEnv() +{ + return CallNPN_GetJavaEnvProc(gNetscapeFuncs.getJavaEnv); +} + +jref NPN_GetJavaPeer(NPP instance) +{ + return CallNPN_GetJavaPeerProc(gNetscapeFuncs.getJavaPeer, + instance); +} + + +/*********************************************************************** + * + * Wrapper functions : Netscape Navigator -> plugin + * + * These functions let the plugin developer just create the APIs + * as documented and defined in npapi.h, without needing to + * install those functions in the function table or worry about + * setting up globals for 68K plugins. + * + ***********************************************************************/ + +NPError +Private_New(NPMIMEType pluginType, NPP instance, uint16 mode, + int16 argc, char* argn[], char* argv[], NPSavedData* saved) +{ + NPError ret; + PLUGINDEBUGSTR("New"); + ret = NPP_New(pluginType, instance, mode, argc, argn, argv, saved); + return ret; +} + +NPError +Private_Destroy(NPP instance, NPSavedData** save) +{ + PLUGINDEBUGSTR("Destroy"); + return NPP_Destroy(instance, save); +} + +NPError +Private_SetWindow(NPP instance, NPWindow* window) +{ + NPError err; + PLUGINDEBUGSTR("SetWindow"); + err = NPP_SetWindow(instance, window); + return err; +} + +NPError +Private_NewStream(NPP instance, NPMIMEType type, NPStream* stream, + NPBool seekable, uint16* stype) +{ + NPError err; + PLUGINDEBUGSTR("NewStream"); + err = NPP_NewStream(instance, type, stream, seekable, stype); + return err; +} + +int32 +Private_WriteReady(NPP instance, NPStream* stream) +{ + unsigned int result; + PLUGINDEBUGSTR("WriteReady"); + result = NPP_WriteReady(instance, stream); + return result; +} + +int32 +Private_Write(NPP instance, NPStream* stream, int32 offset, int32 len, + void* buffer) +{ + unsigned int result; + PLUGINDEBUGSTR("Write"); + result = NPP_Write(instance, stream, offset, len, buffer); + return result; +} + +void +Private_StreamAsFile(NPP instance, NPStream* stream, const char* fname) +{ + PLUGINDEBUGSTR("StreamAsFile"); + NPP_StreamAsFile(instance, stream, fname); +} + + +NPError +Private_DestroyStream(NPP instance, NPStream* stream, NPError reason) +{ + NPError err; + PLUGINDEBUGSTR("DestroyStream"); + err = NPP_DestroyStream(instance, stream, reason); + return err; +} + + +void +Private_Print(NPP instance, NPPrint* platformPrint) +{ + PLUGINDEBUGSTR("Print"); + NPP_Print(instance, platformPrint); +} + +JRIGlobalRef +Private_GetJavaClass(void) +{ + jref clazz = NPP_GetJavaClass(); + if (clazz) { + JRIEnv* env = NPN_GetJavaEnv(); + return JRI_NewGlobalRef(env, clazz); + } + return NULL; +} + +/*********************************************************************** + * + * These functions are located automagically by netscape. + * + ***********************************************************************/ + +/* + * NP_GetMIMEDescription + * - Netscape needs to know about this symbol + * - Netscape uses the return value to identify when an object instance + * of this plugin should be created. + */ +char * +NP_GetMIMEDescription(void) +{ + return NPP_GetMIMEDescription(); +} + +/* + * NP_GetValue [optional] + * - Netscape needs to know about this symbol. + * - Interfaces with plugin to get values for predefined variables + * that the navigator needs. + */ +NPError +NP_GetValue(void *future, NPPVariable variable, void *value) +{ + return NPP_GetValue(future, variable, value); +} + +/* + * NP_Initialize + * - Netscape needs to know about this symbol. + * - It calls this function after looking up its symbol before it + * is about to create the first ever object of this kind. + * + * PARAMETERS + * nsTable - The netscape function table. If developers just use these + * wrappers, they dont need to worry about all these function + * tables. + * RETURN + * pluginFuncs + * - This functions needs to fill the plugin function table + * pluginFuncs and return it. Netscape Navigator plugin + * library will use this function table to call the plugin. + * + */ +NPError +NP_Initialize(NPNetscapeFuncs* nsTable, NPPluginFuncs* pluginFuncs) +{ + NPError err = NPERR_NO_ERROR; + + PLUGINDEBUGSTR("NP_Initialize"); + + /* validate input parameters */ + + if ((nsTable == NULL) || (pluginFuncs == NULL)) + err = NPERR_INVALID_FUNCTABLE_ERROR; + + /* + * Check the major version passed in Netscape's function table. + * We won't load if the major version is newer than what we expect. + * Also check that the function tables passed in are big enough for + * all the functions we need (they could be bigger, if Netscape added + * new APIs, but that's OK with us -- we'll just ignore them). + * + */ + + if (err == NPERR_NO_ERROR) { + if ((nsTable->version >> 8) > NP_VERSION_MAJOR) + err = NPERR_INCOMPATIBLE_VERSION_ERROR; + if (nsTable->size < sizeof(NPNetscapeFuncs)) + err = NPERR_INVALID_FUNCTABLE_ERROR; + if (pluginFuncs->size < sizeof(NPPluginFuncs)) + err = NPERR_INVALID_FUNCTABLE_ERROR; + } + + + if (err == NPERR_NO_ERROR) { + /* + * Copy all the fields of Netscape function table into our + * copy so we can call back into Netscape later. Note that + * we need to copy the fields one by one, rather than assigning + * the whole structure, because the Netscape function table + * could actually be bigger than what we expect. + */ + gNetscapeFuncs.version = nsTable->version; + gNetscapeFuncs.size = nsTable->size; + gNetscapeFuncs.posturl = nsTable->posturl; + gNetscapeFuncs.geturl = nsTable->geturl; + gNetscapeFuncs.requestread = nsTable->requestread; + gNetscapeFuncs.newstream = nsTable->newstream; + gNetscapeFuncs.write = nsTable->write; + gNetscapeFuncs.destroystream = nsTable->destroystream; + gNetscapeFuncs.status = nsTable->status; + gNetscapeFuncs.uagent = nsTable->uagent; + gNetscapeFuncs.memalloc = nsTable->memalloc; + gNetscapeFuncs.memfree = nsTable->memfree; + gNetscapeFuncs.memflush = nsTable->memflush; + gNetscapeFuncs.reloadplugins = nsTable->reloadplugins; + gNetscapeFuncs.getJavaEnv = nsTable->getJavaEnv; + gNetscapeFuncs.getJavaPeer = nsTable->getJavaPeer; + gNetscapeFuncs.getvalue = nsTable->getvalue; + + /* + * Set up the plugin function table that Netscape will use to + * call us. Netscape needs to know about our version and size + * and have a UniversalProcPointer for every function we + * implement. + */ + pluginFuncs->version = (NP_VERSION_MAJOR << 8) + NP_VERSION_MINOR; + pluginFuncs->size = sizeof(NPPluginFuncs); + pluginFuncs->newp = NewNPP_NewProc(Private_New); + pluginFuncs->destroy = NewNPP_DestroyProc(Private_Destroy); + pluginFuncs->setwindow = NewNPP_SetWindowProc(Private_SetWindow); + pluginFuncs->newstream = NewNPP_NewStreamProc(Private_NewStream); + pluginFuncs->destroystream = NewNPP_DestroyStreamProc(Private_DestroyStream); + pluginFuncs->asfile = NewNPP_StreamAsFileProc(Private_StreamAsFile); + pluginFuncs->writeready = NewNPP_WriteReadyProc(Private_WriteReady); + pluginFuncs->write = NewNPP_WriteProc(Private_Write); + pluginFuncs->print = NewNPP_PrintProc(Private_Print); + pluginFuncs->event = NULL; + pluginFuncs->javaClass = Private_GetJavaClass(); + + err = NPP_Initialize(); + } + + return err; +} + +/* + * NP_Shutdown [optional] + * - Netscape needs to know about this symbol. + * - It calls this function after looking up its symbol after + * the last object of this kind has been destroyed. + * + */ +NPError +NP_Shutdown(void) +{ + PLUGINDEBUGSTR("NP_Shutdown"); + NPP_Shutdown(); + return NPERR_NO_ERROR; +} diff --git a/plugin/include/jri.h b/plugin/include/jri.h new file mode 100644 index 0000000..4391455 --- /dev/null +++ b/plugin/include/jri.h @@ -0,0 +1,639 @@ +/* $Xorg: jri.h,v 1.3 2000/08/17 19:55:00 cpqbld Exp $ */ +/* -*- Mode: C; tab-width: 4; -*- */ +/******************************************************************************* + * Java Runtime Interface + * Copyright (c) 1996 Netscape Communications Corporation. All rights reserved. + ******************************************************************************/ + +#ifndef JRI_H +#define JRI_H + +#include "jritypes.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/******************************************************************************* + * JRIEnv + ******************************************************************************/ + +/* The type of the JRIEnv interface. */ +typedef struct JRIEnvInterface JRIEnvInterface; + +/* The type of a JRIEnv instance. */ +typedef const JRIEnvInterface* JRIEnv; + +/******************************************************************************* + * JRIEnv Operations + ******************************************************************************/ + +#define JRI_LoadClass(env, buf, bufLen) \ + (((*(env))->LoadClass)(env, JRI_LoadClass_op, buf, bufLen)) + +#define JRI_FindClass(env, name) \ + (((*(env))->FindClass)(env, JRI_FindClass_op, name)) + +#define JRI_Throw(env, obj) \ + (((*(env))->Throw)(env, JRI_Throw_op, obj)) + +#define JRI_ThrowNew(env, clazz, message) \ + (((*(env))->ThrowNew)(env, JRI_ThrowNew_op, clazz, message)) + +#define JRI_ExceptionOccurred(env) \ + (((*(env))->ExceptionOccurred)(env, JRI_ExceptionOccurred_op)) + +#define JRI_ExceptionDescribe(env) \ + (((*(env))->ExceptionDescribe)(env, JRI_ExceptionDescribe_op)) + +#define JRI_ExceptionClear(env) \ + (((*(env))->ExceptionClear)(env, JRI_ExceptionClear_op)) + +#define JRI_NewGlobalRef(env, ref) \ + (((*(env))->NewGlobalRef)(env, JRI_NewGlobalRef_op, ref)) + +#define JRI_DisposeGlobalRef(env, gref) \ + (((*(env))->DisposeGlobalRef)(env, JRI_DisposeGlobalRef_op, gref)) + +#define JRI_GetGlobalRef(env, gref) \ + (((*(env))->GetGlobalRef)(env, JRI_GetGlobalRef_op, gref)) + +#define JRI_SetGlobalRef(env, gref, ref) \ + (((*(env))->SetGlobalRef)(env, JRI_SetGlobalRef_op, gref, ref)) + +#define JRI_IsSameObject(env, a, b) \ + (((*(env))->IsSameObject)(env, JRI_IsSameObject_op, a, b)) + +#define JRI_NewObject(env) ((*(env))->NewObject) +#define JRI_NewObjectV(env, clazz, methodID, args) \ + (((*(env))->NewObjectV)(env, JRI_NewObject_op_va_list, clazz, methodID, args)) +#define JRI_NewObjectA(env, clazz, method, args) \ + (((*(env))->NewObjectA)(env, JRI_NewObject_op_array, clazz, methodID, args)) + +#define JRI_GetObjectClass(env, obj) \ + (((*(env))->GetObjectClass)(env, JRI_GetObjectClass_op, obj)) + +#define JRI_IsInstanceOf(env, obj, clazz) \ + (((*(env))->IsInstanceOf)(env, JRI_IsInstanceOf_op, obj, clazz)) + +#define JRI_GetMethodID(env, clazz, name, sig) \ + (((*(env))->GetMethodID)(env, JRI_GetMethodID_op, clazz, name, sig)) + +#define JRI_CallMethod(env) ((*(env))->CallMethod) +#define JRI_CallMethodV(env, obj, methodID, args) \ + (((*(env))->CallMethodV)(env, JRI_CallMethod_op_va_list, obj, methodID, args)) +#define JRI_CallMethodA(env, obj, methodID, args) \ + (((*(env))->CallMethodA)(env, JRI_CallMethod_op_array, obj, methodID, args)) + +#define JRI_CallMethodBoolean(env) ((*(env))->CallMethodBoolean) +#define JRI_CallMethodBooleanV(env, obj, methodID, args) \ + (((*(env))->CallMethodBooleanV)(env, JRI_CallMethodBoolean_op_va_list, obj, methodID, args)) +#define JRI_CallMethodBooleanA(env, obj, methodID, args) \ + (((*(env))->CallMethodBooleanA)(env, JRI_CallMethodBoolean_op_array, obj, methodID, args)) + +#define JRI_CallMethodByte(env) ((*(env))->CallMethodByte) +#define JRI_CallMethodByteV(env, obj, methodID, args) \ + (((*(env))->CallMethodByteV)(env, JRI_CallMethodByte_op_va_list, obj, methodID, args)) +#define JRI_CallMethodByteA(env, obj, methodID, args) \ + (((*(env))->CallMethodByteA)(env, JRI_CallMethodByte_op_array, obj, methodID, args)) + +#define JRI_CallMethodChar(env) ((*(env))->CallMethodChar) +#define JRI_CallMethodCharV(env, obj, methodID, args) \ + (((*(env))->CallMethodCharV)(env, JRI_CallMethodChar_op_va_list, obj, methodID, args)) +#define JRI_CallMethodCharA(env, obj, methodID, args) \ + (((*(env))->CallMethodCharA)(env, JRI_CallMethodChar_op_array, obj, methodID, args)) + +#define JRI_CallMethodShort(env) ((*(env))->CallMethodShort) +#define JRI_CallMethodShortV(env, obj, methodID, args) \ + (((*(env))->CallMethodShortV)(env, JRI_CallMethodShort_op_va_list, obj, methodID, args)) +#define JRI_CallMethodShortA(env, obj, methodID, args) \ + (((*(env))->CallMethodShortA)(env, JRI_CallMethodShort_op_array, obj, methodID, args)) + +#define JRI_CallMethodInt(env) ((*(env))->CallMethodInt) +#define JRI_CallMethodIntV(env, obj, methodID, args) \ + (((*(env))->CallMethodIntV)(env, JRI_CallMethodInt_op_va_list, obj, methodID, args)) +#define JRI_CallMethodIntA(env, obj, methodID, args) \ + (((*(env))->CallMethodIntA)(env, JRI_CallMethodInt_op_array, obj, methodID, args)) + +#define JRI_CallMethodLong(env) ((*(env))->CallMethodLong) +#define JRI_CallMethodLongV(env, obj, methodID, args) \ + (((*(env))->CallMethodLongV)(env, JRI_CallMethodLong_op_va_list, obj, methodID, args)) +#define JRI_CallMethodLongA(env, obj, methodID, args) \ + (((*(env))->CallMethodLongA)(env, JRI_CallMethodLong_op_array, obj, methodID, args)) + +#define JRI_CallMethodFloat(env) ((*(env))->CallMethodFloat) +#define JRI_CallMethodFloatV(env, obj, methodID, args) \ + (((*(env))->CallMethodFloatV)(env, JRI_CallMethodFloat_op_va_list, obj, methodID, args)) +#define JRI_CallMethodFloatA(env, obj, methodID, args) \ + (((*(env))->CallMethodFloatA)(env, JRI_CallMethodFloat_op_array, obj, methodID, args)) + +#define JRI_CallMethodDouble(env) ((*(env))->CallMethodDouble) +#define JRI_CallMethodDoubleV(env, obj, methodID, args) \ + (((*(env))->CallMethodDoubleV)(env, JRI_CallMethodDouble_op_va_list, obj, methodID, args)) +#define JRI_CallMethodDoubleA(env, obj, methodID, args) \ + (((*(env))->CallMethodDoubleA)(env, JRI_CallMethodDouble_op_array, obj, methodID, args)) + +#define JRI_GetFieldID(env, clazz, name, sig) \ + (((*(env))->GetFieldID)(env, JRI_GetFieldID_op, clazz, name, sig)) + +#define JRI_GetField(env, obj, fieldID) \ + (((*(env))->GetField)(env, JRI_GetField_op, obj, fieldID)) + +#define JRI_GetFieldBoolean(env, obj, fieldID) \ + (((*(env))->GetFieldBoolean)(env, JRI_GetFieldBoolean_op, obj, fieldID)) + +#define JRI_GetFieldByte(env, obj, fieldID) \ + (((*(env))->GetFieldByte)(env, JRI_GetFieldByte_op, obj, fieldID)) + +#define JRI_GetFieldChar(env, obj, fieldID) \ + (((*(env))->GetFieldChar)(env, JRI_GetFieldChar_op, obj, fieldID)) + +#define JRI_GetFieldShort(env, obj, fieldID) \ + (((*(env))->GetFieldShort)(env, JRI_GetFieldShort_op, obj, fieldID)) + +#define JRI_GetFieldInt(env, obj, fieldID) \ + (((*(env))->GetFieldInt)(env, JRI_GetFieldInt_op, obj, fieldID)) + +#define JRI_GetFieldLong(env, obj, fieldID) \ + (((*(env))->GetFieldLong)(env, JRI_GetFieldLong_op, obj, fieldID)) + +#define JRI_GetFieldFloat(env, obj, fieldID) \ + (((*(env))->GetFieldFloat)(env, JRI_GetFieldFloat_op, obj, fieldID)) + +#define JRI_GetFieldDouble(env, obj, fieldID) \ + (((*(env))->GetFieldDouble)(env, JRI_GetFieldDouble_op, obj, fieldID)) + +#define JRI_SetField(env, obj, fieldID, value) \ + (((*(env))->SetField)(env, JRI_SetField_op, obj, fieldID, value)) + +#define JRI_SetFieldBoolean(env, obj, fieldID, value) \ + (((*(env))->SetFieldBoolean)(env, JRI_SetFieldBoolean_op, obj, fieldID, value)) + +#define JRI_SetFieldByte(env, obj, fieldID, value) \ + (((*(env))->SetFieldByte)(env, JRI_SetFieldByte_op, obj, fieldID, value)) + +#define JRI_SetFieldChar(env, obj, fieldID, value) \ + (((*(env))->SetFieldChar)(env, JRI_SetFieldChar_op, obj, fieldID, value)) + +#define JRI_SetFieldShort(env, obj, fieldID, value) \ + (((*(env))->SetFieldShort)(env, JRI_SetFieldShort_op, obj, fieldID, value)) + +#define JRI_SetFieldInt(env, obj, fieldID, value) \ + (((*(env))->SetFieldInt)(env, JRI_SetFieldInt_op, obj, fieldID, value)) + +#define JRI_SetFieldLong(env, obj, fieldID, value) \ + (((*(env))->SetFieldLong)(env, JRI_SetFieldLong_op, obj, fieldID, value)) + +#define JRI_SetFieldFloat(env, obj, fieldID, value) \ + (((*(env))->SetFieldFloat)(env, JRI_SetFieldFloat_op, obj, fieldID, value)) + +#define JRI_SetFieldDouble(env, obj, fieldID, value) \ + (((*(env))->SetFieldDouble)(env, JRI_SetFieldDouble_op, obj, fieldID, value)) + +#define JRI_IsSubclassOf(env, a, b) \ + (((*(env))->IsSubclassOf)(env, JRI_IsSubclassOf_op, a, b)) + +#define JRI_GetStaticMethodID(env, clazz, name, sig) \ + (((*(env))->GetStaticMethodID)(env, JRI_GetStaticMethodID_op, clazz, name, sig)) + +#define JRI_CallStaticMethod(env) ((*(env))->CallStaticMethod) +#define JRI_CallStaticMethodV(env, clazz, methodID, args) \ + (((*(env))->CallStaticMethodV)(env, JRI_CallStaticMethod_op_va_list, clazz, methodID, args)) +#define JRI_CallStaticMethodA(env, clazz, methodID, args) \ + (((*(env))->CallStaticMethodA)(env, JRI_CallStaticMethod_op_array, clazz, methodID, args)) + +#define JRI_CallStaticMethodBoolean(env) ((*(env))->CallStaticMethodBoolean) +#define JRI_CallStaticMethodBooleanV(env, clazz, methodID, args) \ + (((*(env))->CallStaticMethodBooleanV)(env, JRI_CallStaticMethodBoolean_op_va_list, clazz, methodID, args)) +#define JRI_CallStaticMethodBooleanA(env, clazz, methodID, args) \ + (((*(env))->CallStaticMethodBooleanA)(env, JRI_CallStaticMethodBoolean_op_array, clazz, methodID, args)) + +#define JRI_CallStaticMethodByte(env) ((*(env))->CallStaticMethodByte) +#define JRI_CallStaticMethodByteV(env, clazz, methodID, args) \ + (((*(env))->CallStaticMethodByteV)(env, JRI_CallStaticMethodByte_op_va_list, clazz, methodID, args)) +#define JRI_CallStaticMethodByteA(env, clazz, methodID, args) \ + (((*(env))->CallStaticMethodByteA)(env, JRI_CallStaticMethodByte_op_array, clazz, methodID, args)) + +#define JRI_CallStaticMethodChar(env) ((*(env))->CallStaticMethodChar) +#define JRI_CallStaticMethodCharV(env, clazz, methodID, args) \ + (((*(env))->CallStaticMethodCharV)(env, JRI_CallStaticMethodChar_op_va_list, clazz, methodID, args)) +#define JRI_CallStaticMethodCharA(env, clazz, methodID, args) \ + (((*(env))->CallStaticMethodCharA)(env, JRI_CallStaticMethodChar_op_array, clazz, methodID, args)) + +#define JRI_CallStaticMethodShort(env) ((*(env))->CallStaticMethodShort) +#define JRI_CallStaticMethodShortV(env, clazz, methodID, args) \ + (((*(env))->CallStaticMethodShortV)(env, JRI_CallStaticMethodShort_op_va_list, clazz, methodID, args)) +#define JRI_CallStaticMethodShortA(env, clazz, methodID, args) \ + (((*(env))->CallStaticMethodShortA)(env, JRI_CallStaticMethodShort_op_array, clazz, methodID, args)) + +#define JRI_CallStaticMethodInt(env) ((*(env))->CallStaticMethodInt) +#define JRI_CallStaticMethodIntV(env, clazz, methodID, args) \ + (((*(env))->CallStaticMethodIntV)(env, JRI_CallStaticMethodInt_op_va_list, clazz, methodID, args)) +#define JRI_CallStaticMethodIntA(env, clazz, methodID, args) \ + (((*(env))->CallStaticMethodIntA)(env, JRI_CallStaticMethodInt_op_array, clazz, methodID, args)) + +#define JRI_CallStaticMethodLong(env) ((*(env))->CallStaticMethodLong) +#define JRI_CallStaticMethodLongV(env, clazz, methodID, args) \ + (((*(env))->CallStaticMethodLongV)(env, JRI_CallStaticMethodLong_op_va_list, clazz, methodID, args)) +#define JRI_CallStaticMethodLongA(env, clazz, methodID, args) \ + (((*(env))->CallStaticMethodLongA)(env, JRI_CallStaticMethodLong_op_array, clazz, methodID, args)) + +#define JRI_CallStaticMethodFloat(env) ((*(env))->CallStaticMethodFloat) +#define JRI_CallStaticMethodFloatV(env, clazz, methodID, args) \ + (((*(env))->CallStaticMethodFloatV)(env, JRI_CallStaticMethodFloat_op_va_list, clazz, methodID, args)) +#define JRI_CallStaticMethodFloatA(env, clazz, methodID, args) \ + (((*(env))->CallStaticMethodFloatA)(env, JRI_CallStaticMethodFloat_op_array, clazz, methodID, args)) + +#define JRI_CallStaticMethodDouble(env) ((*(env))->CallStaticMethodDouble) +#define JRI_CallStaticMethodDoubleV(env, clazz, methodID, args) \ + (((*(env))->CallStaticMethodDoubleV)(env, JRI_CallStaticMethodDouble_op_va_list, clazz, methodID, args)) +#define JRI_CallStaticMethodDoubleA(env, clazz, methodID, args) \ + (((*(env))->CallStaticMethodDoubleA)(env, JRI_CallStaticMethodDouble_op_array, clazz, methodID, args)) + +#define JRI_GetStaticFieldID(env, clazz, name, sig) \ + (((*(env))->GetStaticFieldID)(env, JRI_GetStaticFieldID_op, clazz, name, sig)) + +#define JRI_GetStaticField(env, clazz, fieldID) \ + (((*(env))->GetStaticField)(env, JRI_GetStaticField_op, clazz, fieldID)) + +#define JRI_GetStaticFieldBoolean(env, clazz, fieldID) \ + (((*(env))->GetStaticFieldBoolean)(env, JRI_GetStaticFieldBoolean_op, clazz, fieldID)) + +#define JRI_GetStaticFieldByte(env, clazz, fieldID) \ + (((*(env))->GetStaticFieldByte)(env, JRI_GetStaticFieldByte_op, clazz, fieldID)) + +#define JRI_GetStaticFieldChar(env, clazz, fieldID) \ + (((*(env))->GetStaticFieldChar)(env, JRI_GetStaticFieldChar_op, clazz, fieldID)) + +#define JRI_GetStaticFieldShort(env, clazz, fieldID) \ + (((*(env))->GetStaticFieldShort)(env, JRI_GetStaticFieldShort_op, clazz, fieldID)) + +#define JRI_GetStaticFieldInt(env, clazz, fieldID) \ + (((*(env))->GetStaticFieldInt)(env, JRI_GetStaticFieldInt_op, clazz, fieldID)) + +#define JRI_GetStaticFieldLong(env, clazz, fieldID) \ + (((*(env))->GetStaticFieldLong)(env, JRI_GetStaticFieldLong_op, clazz, fieldID)) + +#define JRI_GetStaticFieldFloat(env, clazz, fieldID) \ + (((*(env))->GetStaticFieldFloat)(env, JRI_GetStaticFieldFloat_op, clazz, fieldID)) + +#define JRI_GetStaticFieldDouble(env, clazz, fieldID) \ + (((*(env))->GetStaticFieldDouble)(env, JRI_GetStaticFieldDouble_op, clazz, fieldID)) + +#define JRI_SetStaticField(env, clazz, fieldID, value) \ + (((*(env))->SetStaticField)(env, JRI_SetStaticField_op, clazz, fieldID, value)) + +#define JRI_SetStaticFieldBoolean(env, clazz, fieldID, value) \ + (((*(env))->SetStaticFieldBoolean)(env, JRI_SetStaticFieldBoolean_op, clazz, fieldID, value)) + +#define JRI_SetStaticFieldByte(env, clazz, fieldID, value) \ + (((*(env))->SetStaticFieldByte)(env, JRI_SetStaticFieldByte_op, clazz, fieldID, value)) + +#define JRI_SetStaticFieldChar(env, clazz, fieldID, value) \ + (((*(env))->SetStaticFieldChar)(env, JRI_SetStaticFieldChar_op, clazz, fieldID, value)) + +#define JRI_SetStaticFieldShort(env, clazz, fieldID, value) \ + (((*(env))->SetStaticFieldShort)(env, JRI_SetStaticFieldShort_op, clazz, fieldID, value)) + +#define JRI_SetStaticFieldInt(env, clazz, fieldID, value) \ + (((*(env))->SetStaticFieldInt)(env, JRI_SetStaticFieldInt_op, clazz, fieldID, value)) + +#define JRI_SetStaticFieldLong(env, clazz, fieldID, value) \ + (((*(env))->SetStaticFieldLong)(env, JRI_SetStaticFieldLong_op, clazz, fieldID, value)) + +#define JRI_SetStaticFieldFloat(env, clazz, fieldID, value) \ + (((*(env))->SetStaticFieldFloat)(env, JRI_SetStaticFieldFloat_op, clazz, fieldID, value)) + +#define JRI_SetStaticFieldDouble(env, clazz, fieldID, value) \ + (((*(env))->SetStaticFieldDouble)(env, JRI_SetStaticFieldDouble_op, clazz, fieldID, value)) + +#define JRI_NewString(env, unicode, len) \ + (((*(env))->NewString)(env, JRI_NewString_op, unicode, len)) + +#define JRI_GetStringLength(env, string) \ + (((*(env))->GetStringLength)(env, JRI_GetStringLength_op, string)) + +#define JRI_GetStringChars(env, string) \ + (((*(env))->GetStringChars)(env, JRI_GetStringChars_op, string)) + +#define JRI_NewStringUTF(env, utf, len) \ + (((*(env))->NewStringUTF)(env, JRI_NewStringUTF_op, utf, len)) + +#define JRI_GetStringUTFLength(env, string) \ + (((*(env))->GetStringUTFLength)(env, JRI_GetStringUTFLength_op, string)) + +#define JRI_GetStringUTFChars(env, string) \ + (((*(env))->GetStringUTFChars)(env, JRI_GetStringUTFChars_op, string)) + +#define JRI_NewScalarArray(env, length, elementSig, initialElements) \ + (((*(env))->NewScalarArray)(env, JRI_NewScalarArray_op, length, elementSig, initialElements)) + +#define JRI_GetScalarArrayLength(env, array) \ + (((*(env))->GetScalarArrayLength)(env, JRI_GetScalarArrayLength_op, array)) + +#define JRI_GetScalarArrayElements(env, array) \ + (((*(env))->GetScalarArrayElements)(env, JRI_GetScalarArrayElements_op, array)) + +#define JRI_NewObjectArray(env, length, elementClass, initialElement) \ + (((*(env))->NewObjectArray)(env, JRI_NewObjectArray_op, length, elementClass, initialElement)) + +#define JRI_GetObjectArrayLength(env, array) \ + (((*(env))->GetObjectArrayLength)(env, JRI_GetObjectArrayLength_op, array)) + +#define JRI_GetObjectArrayElement(env, array, index) \ + (((*(env))->GetObjectArrayElement)(env, JRI_GetObjectArrayElement_op, array, index)) + +#define JRI_SetObjectArrayElement(env, array, index, value) \ + (((*(env))->SetObjectArrayElement)(env, JRI_SetObjectArrayElement_op, array, index, value)) + +#define JRI_RegisterNatives(env, clazz, nameAndSigArray, nativeProcArray) \ + (((*(env))->RegisterNatives)(env, JRI_RegisterNatives_op, clazz, nameAndSigArray, nativeProcArray)) + +#define JRI_UnregisterNatives(env, clazz) \ + (((*(env))->UnregisterNatives)(env, JRI_UnregisterNatives_op, clazz)) + +/******************************************************************************* + * JRIEnv Interface + ******************************************************************************/ + +struct java_lang_Class; +struct java_lang_Throwable; +struct java_lang_Object; +struct java_lang_String; + +struct JRIEnvInterface { + void* reserved0; + void* reserved1; + void* reserved2; + struct java_lang_Class* (*LoadClass)(JRIEnv* env, jint op, jbyte* a, jsize aLen); + struct java_lang_Class* (*FindClass)(JRIEnv* env, jint op, const char* a); + void (*Throw)(JRIEnv* env, jint op, struct java_lang_Throwable* a); + void (*ThrowNew)(JRIEnv* env, jint op, struct java_lang_Class* a, const char* b); + struct java_lang_Throwable* (*ExceptionOccurred)(JRIEnv* env, jint op); + void (*ExceptionDescribe)(JRIEnv* env, jint op); + void (*ExceptionClear)(JRIEnv* env, jint op); + jglobal (*NewGlobalRef)(JRIEnv* env, jint op, void* a); + void (*DisposeGlobalRef)(JRIEnv* env, jint op, jglobal a); + void* (*GetGlobalRef)(JRIEnv* env, jint op, jglobal a); + void (*SetGlobalRef)(JRIEnv* env, jint op, jglobal a, void* b); + jbool (*IsSameObject)(JRIEnv* env, jint op, void* a, void* b); + void* (*NewObject)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, ...); + void* (*NewObjectV)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, va_list c); + void* (*NewObjectA)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, JRIValue* c); + struct java_lang_Class* (*GetObjectClass)(JRIEnv* env, jint op, void* a); + jbool (*IsInstanceOf)(JRIEnv* env, jint op, void* a, struct java_lang_Class* b); + jint (*GetMethodID)(JRIEnv* env, jint op, struct java_lang_Class* a, const char* b, const char* c); + void* (*CallMethod)(JRIEnv* env, jint op, void* a, jint b, ...); + void* (*CallMethodV)(JRIEnv* env, jint op, void* a, jint b, va_list c); + void* (*CallMethodA)(JRIEnv* env, jint op, void* a, jint b, JRIValue* c); + jbool (*CallMethodBoolean)(JRIEnv* env, jint op, void* a, jint b, ...); + jbool (*CallMethodBooleanV)(JRIEnv* env, jint op, void* a, jint b, va_list c); + jbool (*CallMethodBooleanA)(JRIEnv* env, jint op, void* a, jint b, JRIValue* c); + jbyte (*CallMethodByte)(JRIEnv* env, jint op, void* a, jint b, ...); + jbyte (*CallMethodByteV)(JRIEnv* env, jint op, void* a, jint b, va_list c); + jbyte (*CallMethodByteA)(JRIEnv* env, jint op, void* a, jint b, JRIValue* c); + jchar (*CallMethodChar)(JRIEnv* env, jint op, void* a, jint b, ...); + jchar (*CallMethodCharV)(JRIEnv* env, jint op, void* a, jint b, va_list c); + jchar (*CallMethodCharA)(JRIEnv* env, jint op, void* a, jint b, JRIValue* c); + jshort (*CallMethodShort)(JRIEnv* env, jint op, void* a, jint b, ...); + jshort (*CallMethodShortV)(JRIEnv* env, jint op, void* a, jint b, va_list c); + jshort (*CallMethodShortA)(JRIEnv* env, jint op, void* a, jint b, JRIValue* c); + jint (*CallMethodInt)(JRIEnv* env, jint op, void* a, jint b, ...); + jint (*CallMethodIntV)(JRIEnv* env, jint op, void* a, jint b, va_list c); + jint (*CallMethodIntA)(JRIEnv* env, jint op, void* a, jint b, JRIValue* c); + jlong (*CallMethodLong)(JRIEnv* env, jint op, void* a, jint b, ...); + jlong (*CallMethodLongV)(JRIEnv* env, jint op, void* a, jint b, va_list c); + jlong (*CallMethodLongA)(JRIEnv* env, jint op, void* a, jint b, JRIValue* c); + jfloat (*CallMethodFloat)(JRIEnv* env, jint op, void* a, jint b, ...); + jfloat (*CallMethodFloatV)(JRIEnv* env, jint op, void* a, jint b, va_list c); + jfloat (*CallMethodFloatA)(JRIEnv* env, jint op, void* a, jint b, JRIValue* c); + jdouble (*CallMethodDouble)(JRIEnv* env, jint op, void* a, jint b, ...); + jdouble (*CallMethodDoubleV)(JRIEnv* env, jint op, void* a, jint b, va_list c); + jdouble (*CallMethodDoubleA)(JRIEnv* env, jint op, void* a, jint b, JRIValue* c); + jint (*GetFieldID)(JRIEnv* env, jint op, struct java_lang_Class* a, const char* b, const char* c); + void* (*GetField)(JRIEnv* env, jint op, void* a, jint b); + jbool (*GetFieldBoolean)(JRIEnv* env, jint op, void* a, jint b); + jbyte (*GetFieldByte)(JRIEnv* env, jint op, void* a, jint b); + jchar (*GetFieldChar)(JRIEnv* env, jint op, void* a, jint b); + jshort (*GetFieldShort)(JRIEnv* env, jint op, void* a, jint b); + jint (*GetFieldInt)(JRIEnv* env, jint op, void* a, jint b); + jlong (*GetFieldLong)(JRIEnv* env, jint op, void* a, jint b); + jfloat (*GetFieldFloat)(JRIEnv* env, jint op, void* a, jint b); + jdouble (*GetFieldDouble)(JRIEnv* env, jint op, void* a, jint b); + void (*SetField)(JRIEnv* env, jint op, void* a, jint b, void* c); + void (*SetFieldBoolean)(JRIEnv* env, jint op, void* a, jint b, jbool c); + void (*SetFieldByte)(JRIEnv* env, jint op, void* a, jint b, jbyte c); + void (*SetFieldChar)(JRIEnv* env, jint op, void* a, jint b, jchar c); + void (*SetFieldShort)(JRIEnv* env, jint op, void* a, jint b, jshort c); + void (*SetFieldInt)(JRIEnv* env, jint op, void* a, jint b, jint c); + void (*SetFieldLong)(JRIEnv* env, jint op, void* a, jint b, jlong c); + void (*SetFieldFloat)(JRIEnv* env, jint op, void* a, jint b, jfloat c); + void (*SetFieldDouble)(JRIEnv* env, jint op, void* a, jint b, jdouble c); + jbool (*IsSubclassOf)(JRIEnv* env, jint op, struct java_lang_Class* a, struct java_lang_Class* b); + jint (*GetStaticMethodID)(JRIEnv* env, jint op, struct java_lang_Class* a, const char* b, const char* c); + void* (*CallStaticMethod)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, ...); + void* (*CallStaticMethodV)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, va_list c); + void* (*CallStaticMethodA)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, JRIValue* c); + jbool (*CallStaticMethodBoolean)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, ...); + jbool (*CallStaticMethodBooleanV)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, va_list c); + jbool (*CallStaticMethodBooleanA)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, JRIValue* c); + jbyte (*CallStaticMethodByte)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, ...); + jbyte (*CallStaticMethodByteV)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, va_list c); + jbyte (*CallStaticMethodByteA)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, JRIValue* c); + jchar (*CallStaticMethodChar)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, ...); + jchar (*CallStaticMethodCharV)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, va_list c); + jchar (*CallStaticMethodCharA)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, JRIValue* c); + jshort (*CallStaticMethodShort)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, ...); + jshort (*CallStaticMethodShortV)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, va_list c); + jshort (*CallStaticMethodShortA)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, JRIValue* c); + jint (*CallStaticMethodInt)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, ...); + jint (*CallStaticMethodIntV)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, va_list c); + jint (*CallStaticMethodIntA)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, JRIValue* c); + jlong (*CallStaticMethodLong)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, ...); + jlong (*CallStaticMethodLongV)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, va_list c); + jlong (*CallStaticMethodLongA)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, JRIValue* c); + jfloat (*CallStaticMethodFloat)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, ...); + jfloat (*CallStaticMethodFloatV)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, va_list c); + jfloat (*CallStaticMethodFloatA)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, JRIValue* c); + jdouble (*CallStaticMethodDouble)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, ...); + jdouble (*CallStaticMethodDoubleV)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, va_list c); + jdouble (*CallStaticMethodDoubleA)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, JRIValue* c); + jint (*GetStaticFieldID)(JRIEnv* env, jint op, struct java_lang_Class* a, const char* b, const char* c); + void* (*GetStaticField)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b); + jbool (*GetStaticFieldBoolean)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b); + jbyte (*GetStaticFieldByte)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b); + jchar (*GetStaticFieldChar)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b); + jshort (*GetStaticFieldShort)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b); + jint (*GetStaticFieldInt)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b); + jlong (*GetStaticFieldLong)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b); + jfloat (*GetStaticFieldFloat)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b); + jdouble (*GetStaticFieldDouble)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b); + void (*SetStaticField)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, void* c); + void (*SetStaticFieldBoolean)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, jbool c); + void (*SetStaticFieldByte)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, jbyte c); + void (*SetStaticFieldChar)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, jchar c); + void (*SetStaticFieldShort)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, jshort c); + void (*SetStaticFieldInt)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, jint c); + void (*SetStaticFieldLong)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, jlong c); + void (*SetStaticFieldFloat)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, jfloat c); + void (*SetStaticFieldDouble)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, jdouble c); + struct java_lang_String* (*NewString)(JRIEnv* env, jint op, const jchar* a, jint b); + jint (*GetStringLength)(JRIEnv* env, jint op, struct java_lang_String* a); + const jchar* (*GetStringChars)(JRIEnv* env, jint op, struct java_lang_String* a); + struct java_lang_String* (*NewStringUTF)(JRIEnv* env, jint op, const jbyte* a, jint b); + jint (*GetStringUTFLength)(JRIEnv* env, jint op, struct java_lang_String* a); + const jbyte* (*GetStringUTFChars)(JRIEnv* env, jint op, struct java_lang_String* a); + void* (*NewScalarArray)(JRIEnv* env, jint op, jint a, const char* b, const jbyte* c); + jint (*GetScalarArrayLength)(JRIEnv* env, jint op, void* a); + jbyte* (*GetScalarArrayElements)(JRIEnv* env, jint op, void* a); + void* (*NewObjectArray)(JRIEnv* env, jint op, jint a, struct java_lang_Class* b, void* c); + jint (*GetObjectArrayLength)(JRIEnv* env, jint op, void* a); + void* (*GetObjectArrayElement)(JRIEnv* env, jint op, void* a, jint b); + void (*SetObjectArrayElement)(JRIEnv* env, jint op, void* a, jint b, void* c); + void (*RegisterNatives)(JRIEnv* env, jint op, struct java_lang_Class* a, char** b, void** c); + void (*UnregisterNatives)(JRIEnv* env, jint op, struct java_lang_Class* a); +}; + +/******************************************************************************* + * JRIEnv Operation IDs + ******************************************************************************/ + +typedef enum JRIEnvOperations { + JRI_Reserved0_op, + JRI_Reserved1_op, + JRI_Reserved2_op, + JRI_LoadClass_op, + JRI_FindClass_op, + JRI_Throw_op, + JRI_ThrowNew_op, + JRI_ExceptionOccurred_op, + JRI_ExceptionDescribe_op, + JRI_ExceptionClear_op, + JRI_NewGlobalRef_op, + JRI_DisposeGlobalRef_op, + JRI_GetGlobalRef_op, + JRI_SetGlobalRef_op, + JRI_IsSameObject_op, + JRI_NewObject_op, + JRI_NewObject_op_va_list, + JRI_NewObject_op_array, + JRI_GetObjectClass_op, + JRI_IsInstanceOf_op, + JRI_GetMethodID_op, + JRI_CallMethod_op, + JRI_CallMethod_op_va_list, + JRI_CallMethod_op_array, + JRI_CallMethodBoolean_op, + JRI_CallMethodBoolean_op_va_list, + JRI_CallMethodBoolean_op_array, + JRI_CallMethodByte_op, + JRI_CallMethodByte_op_va_list, + JRI_CallMethodByte_op_array, + JRI_CallMethodChar_op, + JRI_CallMethodChar_op_va_list, + JRI_CallMethodChar_op_array, + JRI_CallMethodShort_op, + JRI_CallMethodShort_op_va_list, + JRI_CallMethodShort_op_array, + JRI_CallMethodInt_op, + JRI_CallMethodInt_op_va_list, + JRI_CallMethodInt_op_array, + JRI_CallMethodLong_op, + JRI_CallMethodLong_op_va_list, + JRI_CallMethodLong_op_array, + JRI_CallMethodFloat_op, + JRI_CallMethodFloat_op_va_list, + JRI_CallMethodFloat_op_array, + JRI_CallMethodDouble_op, + JRI_CallMethodDouble_op_va_list, + JRI_CallMethodDouble_op_array, + JRI_GetFieldID_op, + JRI_GetField_op, + JRI_GetFieldBoolean_op, + JRI_GetFieldByte_op, + JRI_GetFieldChar_op, + JRI_GetFieldShort_op, + JRI_GetFieldInt_op, + JRI_GetFieldLong_op, + JRI_GetFieldFloat_op, + JRI_GetFieldDouble_op, + JRI_SetField_op, + JRI_SetFieldBoolean_op, + JRI_SetFieldByte_op, + JRI_SetFieldChar_op, + JRI_SetFieldShort_op, + JRI_SetFieldInt_op, + JRI_SetFieldLong_op, + JRI_SetFieldFloat_op, + JRI_SetFieldDouble_op, + JRI_IsSubclassOf_op, + JRI_GetStaticMethodID_op, + JRI_CallStaticMethod_op, + JRI_CallStaticMethod_op_va_list, + JRI_CallStaticMethod_op_array, + JRI_CallStaticMethodBoolean_op, + JRI_CallStaticMethodBoolean_op_va_list, + JRI_CallStaticMethodBoolean_op_array, + JRI_CallStaticMethodByte_op, + JRI_CallStaticMethodByte_op_va_list, + JRI_CallStaticMethodByte_op_array, + JRI_CallStaticMethodChar_op, + JRI_CallStaticMethodChar_op_va_list, + JRI_CallStaticMethodChar_op_array, + JRI_CallStaticMethodShort_op, + JRI_CallStaticMethodShort_op_va_list, + JRI_CallStaticMethodShort_op_array, + JRI_CallStaticMethodInt_op, + JRI_CallStaticMethodInt_op_va_list, + JRI_CallStaticMethodInt_op_array, + JRI_CallStaticMethodLong_op, + JRI_CallStaticMethodLong_op_va_list, + JRI_CallStaticMethodLong_op_array, + JRI_CallStaticMethodFloat_op, + JRI_CallStaticMethodFloat_op_va_list, + JRI_CallStaticMethodFloat_op_array, + JRI_CallStaticMethodDouble_op, + JRI_CallStaticMethodDouble_op_va_list, + JRI_CallStaticMethodDouble_op_array, + JRI_GetStaticFieldID_op, + JRI_GetStaticField_op, + JRI_GetStaticFieldBoolean_op, + JRI_GetStaticFieldByte_op, + JRI_GetStaticFieldChar_op, + JRI_GetStaticFieldShort_op, + JRI_GetStaticFieldInt_op, + JRI_GetStaticFieldLong_op, + JRI_GetStaticFieldFloat_op, + JRI_GetStaticFieldDouble_op, + JRI_SetStaticField_op, + JRI_SetStaticFieldBoolean_op, + JRI_SetStaticFieldByte_op, + JRI_SetStaticFieldChar_op, + JRI_SetStaticFieldShort_op, + JRI_SetStaticFieldInt_op, + JRI_SetStaticFieldLong_op, + JRI_SetStaticFieldFloat_op, + JRI_SetStaticFieldDouble_op, + JRI_NewString_op, + JRI_GetStringLength_op, + JRI_GetStringChars_op, + JRI_NewStringUTF_op, + JRI_GetStringUTFLength_op, + JRI_GetStringUTFChars_op, + JRI_NewScalarArray_op, + JRI_GetScalarArrayLength_op, + JRI_GetScalarArrayElements_op, + JRI_NewObjectArray_op, + JRI_GetObjectArrayLength_op, + JRI_GetObjectArrayElement_op, + JRI_SetObjectArrayElement_op, + JRI_RegisterNatives_op, + JRI_UnregisterNatives_op +} JRIEnvOperations; + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#endif /* JRI_H */ +/******************************************************************************/ diff --git a/plugin/include/jri_md.h b/plugin/include/jri_md.h new file mode 100644 index 0000000..1ba1c64 --- /dev/null +++ b/plugin/include/jri_md.h @@ -0,0 +1,501 @@ +/* $Xorg: jri_md.h,v 1.3 2000/08/17 19:55:01 cpqbld Exp $ */ +/* -*- Mode: C; tab-width: 4; -*- */ +/******************************************************************************* + * Java Runtime Interface - Machine Dependent Types + * Copyright (c) 1996 Netscape Communications Corporation. All rights reserved. + ******************************************************************************/ + +#ifndef JRI_MD_H +#define JRI_MD_H + +#include <assert.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/******************************************************************************* + * WHAT'S UP WITH THIS FILE? + * + * This is where we define the mystical JRI_PUBLIC_API macro that works on all + * platforms. If you're running with Visual C++, Symantec C, or Borland's + * development environment on the PC, you're all set. Or if you're on the Mac + * with Metrowerks, Symantec or MPW with SC you're ok too. For UNIX it shouldn't + * matter. + * + * On UNIX though you probably care about a couple of other symbols though: + * IS_LITTLE_ENDIAN must be defined for little-endian systems + * HAVE_LONG_LONG must be defined on systems that have 'long long' integers + * HAVE_ALIGNED_LONGLONGS must be defined if long-longs must be 8 byte aligned + * HAVE_ALIGNED_DOUBLES must be defined if doubles must be 8 byte aligned + * IS_64 must be defined on 64-bit machines (like Dec Alpha) + ******************************************************************************/ + +/* DLL Entry modifiers... */ + +/* PC */ +#if defined(XP_PC) || defined(_WINDOWS) || defined(WIN32) || defined(_WIN32) +# include <windows.h> +# if defined(_MSC_VER) +# if defined(WIN32) || defined(_WIN32) +# define JRI_PUBLIC_API(ResultType) _declspec(dllexport) ResultType +# define JRI_CALLBACK +# else /* !_WIN32 */ +# if defined(_WINDLL) +# define JRI_PUBLIC_API(ResultType) ResultType __cdecl __export __loadds +# define JRI_CALLBACK __loadds +# else /* !WINDLL */ +# define JRI_PUBLIC_API(ResultType) ResultType __cdecl __export +# define JRI_CALLBACK __export +# endif /* !WINDLL */ +# endif /* !_WIN32 */ +# elif defined(__BORLANDC__) +# if defined(WIN32) || defined(_WIN32) +# define JRI_PUBLIC_API(ResultType) __export ResultType +# define JRI_CALLBACK +# else /* !_WIN32 */ +# define JRI_PUBLIC_API(ResultType) ResultType _cdecl _export _loadds +# define JRI_CALLBACK _loadds +# endif +# else +# error Unsupported PC development environment. +# endif +# ifndef IS_LITTLE_ENDIAN +# define IS_LITTLE_ENDIAN +# endif + +/* Mac */ +#elif macintosh || Macintosh || THINK_C +# if defined(__MWERKS__) /* Metrowerks */ +# if !__option(enumsalwaysint) +# error You need to define 'Enums Always Int' for your project. +# endif +# if defined(GENERATING68K) && !GENERATINGCFM +# if !__option(fourbyteints) +# error You need to define 'Struct Alignment: 68k' for your project. +# endif +# endif /* !GENERATINGCFM */ +# elif defined(__SC__) /* Symantec */ +# error What are the Symantec defines? (warren@netscape.com) +# elif macintosh && applec /* MPW */ +# error Please upgrade to the latest MPW compiler (SC). +# else +# error Unsupported Mac development environment. +# endif +# define JRI_PUBLIC_API(ResultType) ResultType +# define JRI_CALLBACK + +/* Unix or else */ +#else +# define JRI_PUBLIC_API(ResultType) ResultType +# define JRI_CALLBACK +#endif + +#ifndef FAR /* for non-Win16 */ +#define FAR +#endif + +/******************************************************************************/ + +/* Java Scalar Types */ + +typedef unsigned char jbool; +typedef char jbyte; +typedef short jchar; +typedef short jshort; +#ifdef IS_64 /* XXX ok for alpha, but not right on all 64-bit architectures */ +typedef unsigned int juint; +typedef int jint; +#else +typedef unsigned long juint; +typedef long jint; +#endif +typedef float jfloat; +typedef double jdouble; + +typedef juint jsize; + +/******************************************************************************* + * jlong : long long (64-bit signed integer type) support. + ******************************************************************************/ + +/* +** Bit masking macros. (n must be <= 31 to be portable) +*/ +#define JRI_BIT(n) ((juint)1 << (n)) +#define JRI_BITMASK(n) (JRI_BIT(n) - 1) + +#ifdef HAVE_LONG_LONG + +#if !(defined(WIN32) || defined(_WIN32)) +typedef long long jlong; +typedef unsigned long long julong; + +#define jlong_MAXINT 0x7fffffffffffffffLL +#define jlong_MININT 0x8000000000000000LL +#define jlong_ZERO 0x0LL + +#else +typedef LONGLONG jlong; +typedef DWORDLONG julong; + +#define jlong_MAXINT 0x7fffffffffffffffi64 +#define jlong_MININT 0x8000000000000000i64 +#define jlong_ZERO 0x0i64 + +#endif + +#define jlong_IS_ZERO(a) ((a) == 0) +#define jlong_EQ(a, b) ((a) == (b)) +#define jlong_NE(a, b) ((a) != (b)) +#define jlong_GE_ZERO(a) ((a) >= 0) +#define jlong_CMP(a, op, b) ((a) op (b)) + +#define jlong_AND(r, a, b) ((r) = (a) & (b)) +#define jlong_OR(r, a, b) ((r) = (a) | (b)) +#define jlong_XOR(r, a, b) ((r) = (a) ^ (b)) +#define jlong_OR2(r, a) ((r) = (r) | (a)) +#define jlong_NOT(r, a) ((r) = ~(a)) + +#define jlong_NEG(r, a) ((r) = -(a)) +#define jlong_ADD(r, a, b) ((r) = (a) + (b)) +#define jlong_SUB(r, a, b) ((r) = (a) - (b)) + +#define jlong_MUL(r, a, b) ((r) = (a) * (b)) +#define jlong_DIV(r, a, b) ((r) = (a) / (b)) +#define jlong_MOD(r, a, b) ((r) = (a) % (b)) + +#define jlong_SHL(r, a, b) ((r) = (a) << (b)) +#define jlong_SHR(r, a, b) ((r) = (a) >> (b)) +#define jlong_USHR(r, a, b) ((r) = (julong)(a) >> (b)) +#define jlong_ISHL(r, a, b) ((r) = ((jlong)(a)) << (b)) + +#define jlong_L2I(i, l) ((i) = (int)(l)) +#define jlong_L2UI(ui, l) ((ui) =(unsigned int)(l)) +#define jlong_L2F(f, l) ((f) = (l)) +#define jlong_L2D(d, l) ((d) = (l)) + +#define jlong_I2L(l, i) ((l) = (i)) +#define jlong_UI2L(l, ui) ((l) = (ui)) +#define jlong_F2L(l, f) ((l) = (f)) +#define jlong_D2L(l, d) ((l) = (d)) + +#define jlong_UDIVMOD(qp, rp, a, b) \ + (*(qp) = ((julong)(a) / (b)), \ + *(rp) = ((julong)(a) % (b))) + +#else /* !HAVE_LONG_LONG */ + +typedef struct { +#ifdef IS_LITTLE_ENDIAN + juint lo, hi; +#else + juint hi, lo; +#endif +} jlong; +typedef jlong julong; + +extern jlong jlong_MAXINT, jlong_MININT, jlong_ZERO; + +#define jlong_IS_ZERO(a) (((a).hi == 0) && ((a).lo == 0)) +#define jlong_EQ(a, b) (((a).hi == (b).hi) && ((a).lo == (b).lo)) +#define jlong_NE(a, b) (((a).hi != (b).hi) || ((a).lo != (b).lo)) +#define jlong_GE_ZERO(a) (((a).hi >> 31) == 0) + +/* + * NB: jlong_CMP and jlong_UCMP work only for strict relationals (<, >). + */ +#define jlong_CMP(a, op, b) (((int32)(a).hi op (int32)(b).hi) || \ + (((a).hi == (b).hi) && ((a).lo op (b).lo))) +#define jlong_UCMP(a, op, b) (((a).hi op (b).hi) || \ + (((a).hi == (b).hi) && ((a).lo op (b).lo))) + +#define jlong_AND(r, a, b) ((r).lo = (a).lo & (b).lo, \ + (r).hi = (a).hi & (b).hi) +#define jlong_OR(r, a, b) ((r).lo = (a).lo | (b).lo, \ + (r).hi = (a).hi | (b).hi) +#define jlong_XOR(r, a, b) ((r).lo = (a).lo ^ (b).lo, \ + (r).hi = (a).hi ^ (b).hi) +#define jlong_OR2(r, a) ((r).lo = (r).lo | (a).lo, \ + (r).hi = (r).hi | (a).hi) +#define jlong_NOT(r, a) ((r).lo = ~(a).lo, \ + (r).hi = ~(a).hi) + +#define jlong_NEG(r, a) ((r).lo = -(int32)(a).lo, \ + (r).hi = -(int32)(a).hi - ((r).lo != 0)) +#define jlong_ADD(r, a, b) { \ + jlong _a, _b; \ + _a = a; _b = b; \ + (r).lo = _a.lo + _b.lo; \ + (r).hi = _a.hi + _b.hi + ((r).lo < _b.lo); \ +} + +#define jlong_SUB(r, a, b) { \ + jlong _a, _b; \ + _a = a; _b = b; \ + (r).lo = _a.lo - _b.lo; \ + (r).hi = _a.hi - _b.hi - (_a.lo < _b.lo); \ +} \ + +/* + * Multiply 64-bit operands a and b to get 64-bit result r. + * First multiply the low 32 bits of a and b to get a 64-bit result in r. + * Then add the outer and inner products to r.hi. + */ +#define jlong_MUL(r, a, b) { \ + jlong _a, _b; \ + _a = a; _b = b; \ + jlong_MUL32(r, _a.lo, _b.lo); \ + (r).hi += _a.hi * _b.lo + _a.lo * _b.hi; \ +} + +/* XXX _jlong_lo16(a) = ((a) << 16 >> 16) is better on some archs (not on mips) */ +#define _jlong_lo16(a) ((a) & JRI_BITMASK(16)) +#define _jlong_hi16(a) ((a) >> 16) + +/* + * Multiply 32-bit operands a and b to get 64-bit result r. + * Use polynomial expansion based on primitive field element (1 << 16). + */ +#define jlong_MUL32(r, a, b) { \ + juint _a1, _a0, _b1, _b0, _y0, _y1, _y2, _y3; \ + _a1 = _jlong_hi16(a), _a0 = _jlong_lo16(a); \ + _b1 = _jlong_hi16(b), _b0 = _jlong_lo16(b); \ + _y0 = _a0 * _b0; \ + _y1 = _a0 * _b1; \ + _y2 = _a1 * _b0; \ + _y3 = _a1 * _b1; \ + _y1 += _jlong_hi16(_y0); /* can't carry */ \ + _y1 += _y2; /* might carry */ \ + if (_y1 < _y2) _y3 += 1 << 16; /* propagate */ \ + (r).lo = (_jlong_lo16(_y1) << 16) + _jlong_lo16(_y0); \ + (r).hi = _y3 + _jlong_hi16(_y1); \ +} + +/* + * Divide 64-bit unsigned operand a by 64-bit unsigned operand b, setting *qp + * to the 64-bit unsigned quotient, and *rp to the 64-bit unsigned remainder. + * Minimize effort if one of qp and rp is null. + */ +#define jlong_UDIVMOD(qp, rp, a, b) jlong_udivmod(qp, rp, a, b) + +extern JRI_PUBLIC_API(void) +jlong_udivmod(julong *qp, julong *rp, julong a, julong b); + +#define jlong_DIV(r, a, b) { \ + jlong _a, _b; \ + juint _negative = (int32)(a).hi < 0; \ + if (_negative) { \ + jlong_NEG(_a, a); \ + } else { \ + _a = a; \ + } \ + if ((int32)(b).hi < 0) { \ + _negative ^= 1; \ + jlong_NEG(_b, b); \ + } else { \ + _b = b; \ + } \ + jlong_UDIVMOD(&(r), 0, _a, _b); \ + if (_negative) \ + jlong_NEG(r, r); \ +} + +#define jlong_MOD(r, a, b) { \ + jlong _a, _b; \ + juint _negative = (int32)(a).hi < 0; \ + if (_negative) { \ + jlong_NEG(_a, a); \ + } else { \ + _a = a; \ + } \ + if ((int32)(b).hi < 0) { \ + jlong_NEG(_b, b); \ + } else { \ + _b = b; \ + } \ + jlong_UDIVMOD(0, &(r), _a, _b); \ + if (_negative) \ + jlong_NEG(r, r); \ +} + +/* + * NB: b is a juint, not jlong or julong, for the shift ops. + */ +#define jlong_SHL(r, a, b) { \ + if (b) { \ + jlong _a; \ + _a = a; \ + if ((b) < 32) { \ + (r).lo = _a.lo << (b); \ + (r).hi = (_a.hi << (b)) | (_a.lo >> (32 - (b))); \ + } else { \ + (r).lo = 0; \ + (r).hi = _a.lo << ((b) & 31); \ + } \ + } else { \ + (r) = (a); \ + } \ +} + +/* a is an int32, b is int32, r is jlong */ +#define jlong_ISHL(r, a, b) { \ + if (b) { \ + jlong _a; \ + _a.lo = (a); \ + _a.hi = 0; \ + if ((b) < 32) { \ + (r).lo = (a) << (b); \ + (r).hi = ((a) >> (32 - (b))); \ + } else { \ + (r).lo = 0; \ + (r).hi = (a) << ((b) & 31); \ + } \ + } else { \ + (r).lo = (a); \ + (r).hi = 0; \ + } \ +} + +#define jlong_SHR(r, a, b) { \ + if (b) { \ + jlong _a; \ + _a = a; \ + if ((b) < 32) { \ + (r).lo = (_a.hi << (32 - (b))) | (_a.lo >> (b)); \ + (r).hi = (int32)_a.hi >> (b); \ + } else { \ + (r).lo = (int32)_a.hi >> ((b) & 31); \ + (r).hi = (int32)_a.hi >> 31; \ + } \ + } else { \ + (r) = (a); \ + } \ +} + +#define jlong_USHR(r, a, b) { \ + if (b) { \ + jlong _a; \ + _a = a; \ + if ((b) < 32) { \ + (r).lo = (_a.hi << (32 - (b))) | (_a.lo >> (b)); \ + (r).hi = _a.hi >> (b); \ + } else { \ + (r).lo = _a.hi >> ((b) & 31); \ + (r).hi = 0; \ + } \ + } else { \ + (r) = (a); \ + } \ +} + +#define jlong_L2I(i, l) ((i) = (l).lo) +#define jlong_L2UI(ui, l) ((ui) = (l).lo) +#define jlong_L2F(f, l) { double _d; jlong_L2D(_d, l); (f) = (float) _d; } + +#define jlong_L2D(d, l) { \ + int32 _negative; \ + jlong _absval; \ + \ + _negative = (l).hi >> 31; \ + if (_negative) { \ + jlong_NEG(_absval, l); \ + } else { \ + _absval = l; \ + } \ + (d) = (double)_absval.hi * 4.294967296e9 + _absval.lo; \ + if (_negative) \ + (d) = -(d); \ +} + +#define jlong_I2L(l, i) ((l).hi = (i) >> 31, (l).lo = (i)) +#define jlong_UI2L(l, ui) ((l).hi = 0, (l).lo = (ui)) +#define jlong_F2L(l, f) { double _d = (double) f; jlong_D2L(l, _d); } + +#define jlong_D2L(l, d) { \ + int _negative; \ + double _absval, _d_hi; \ + jlong _lo_d; \ + \ + _negative = ((d) < 0); \ + _absval = _negative ? -(d) : (d); \ + \ + (l).hi = (juint)(_absval / 4.294967296e9); \ + (l).lo = 0; \ + jlong_L2D(_d_hi, l); \ + _absval -= _d_hi; \ + _lo_d.hi = 0; \ + if (_absval < 0) { \ + _lo_d.lo = (juint) -_absval; \ + jlong_SUB(l, l, _lo_d); \ + } else { \ + _lo_d.lo = (juint) _absval; \ + jlong_ADD(l, l, _lo_d); \ + } \ + \ + if (_negative) \ + jlong_NEG(l, l); \ +} + +#endif /* !HAVE_LONG_LONG */ + +/******************************************************************************/ +/* +** JDK Stuff -- This stuff is still needed while we're using the JDK +** dynamic linking strategy to call native methods. +*/ + +typedef union JRI_JDK_stack_item { + /* Non pointer items */ + jint i; + jfloat f; + jint o; + /* Pointer items */ + void *h; + void *p; + unsigned char *addr; +#ifdef IS_64 + double d; + long l; /* == 64bits! */ +#endif +} JRI_JDK_stack_item; + +typedef union JRI_JDK_Java8Str { + jint x[2]; + jdouble d; + jlong l; + void *p; + float f; +} JRI_JDK_Java8; + +#ifdef HAVE_ALIGNED_LONGLONGS +#define JRI_GET_INT64(_t,_addr) ( ((_t).x[0] = ((jint*)(_addr))[0]), \ + ((_t).x[1] = ((jint*)(_addr))[1]), \ + (_t).l ) +#define JRI_SET_INT64(_t, _addr, _v) ( (_t).l = (_v), \ + ((jint*)(_addr))[0] = (_t).x[0], \ + ((jint*)(_addr))[1] = (_t).x[1] ) +#else +#define JRI_GET_INT64(_t,_addr) (*(jlong*)(_addr)) +#define JRI_SET_INT64(_t, _addr, _v) (*(jlong*)(_addr) = (_v)) +#endif + +/* If double's must be aligned on doubleword boundaries then define this */ +#ifdef HAVE_ALIGNED_DOUBLES +#define JRI_GET_DOUBLE(_t,_addr) ( ((_t).x[0] = ((jint*)(_addr))[0]), \ + ((_t).x[1] = ((jint*)(_addr))[1]), \ + (_t).d ) +#define JRI_SET_DOUBLE(_t, _addr, _v) ( (_t).d = (_v), \ + ((jint*)(_addr))[0] = (_t).x[0], \ + ((jint*)(_addr))[1] = (_t).x[1] ) +#else +#define JRI_GET_DOUBLE(_t,_addr) (*(jdouble*)(_addr)) +#define JRI_SET_DOUBLE(_t, _addr, _v) (*(jdouble*)(_addr) = (_v)) +#endif + +/******************************************************************************/ +#ifdef __cplusplus +} +#endif +#endif /* JRI_MD_H */ +/******************************************************************************/ diff --git a/plugin/include/jritypes.h b/plugin/include/jritypes.h new file mode 100644 index 0000000..3b84641 --- /dev/null +++ b/plugin/include/jritypes.h @@ -0,0 +1,181 @@ +/* $Xorg: jritypes.h,v 1.3 2000/08/17 19:55:01 cpqbld Exp $ */ +/* -*- Mode: C; tab-width: 4; -*- */ +/******************************************************************************* + * Java Runtime Interface + * Copyright (c) 1996 Netscape Communications Corporation. All rights reserved. + ******************************************************************************/ + +#ifndef JRITYPES_H +#define JRITYPES_H + +#include "jri_md.h" +#include <stddef.h> +#include <stdlib.h> +#include <stdarg.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/******************************************************************************* + * Types + ******************************************************************************/ + +struct JRIEnvInterface; + +typedef void* JRIRef; +typedef void* JRIGlobalRef; + +typedef jint JRIInterfaceID[4]; +typedef jint JRIFieldID; +typedef jint JRIMethodID; + +/* synonyms: */ +typedef JRIGlobalRef jglobal; +typedef JRIRef jref; + +typedef union JRIValue { + jbool z; + jbyte b; + jchar c; + jshort s; + jint i; + jlong l; + jfloat f; + jdouble d; + jref r; +} JRIValue; + +typedef JRIValue jvalue; + +typedef enum JRIBoolean { + JRIFalse = 0, + JRITrue = 1 +} JRIBoolean; + +typedef enum JRIConstant { + JRIUninitialized = -1 +} JRIConstant; + +/* convenience types: */ +typedef JRIRef jbooleanArray; +typedef JRIRef jbyteArray; +typedef JRIRef jcharArray; +typedef JRIRef jshortArray; +typedef JRIRef jintArray; +typedef JRIRef jlongArray; +typedef JRIRef jfloatArray; +typedef JRIRef jdoubleArray; +typedef JRIRef jobjectArray; +typedef JRIRef jstringArray; +typedef JRIRef jarrayArray; + +#define JRIConstructorMethodName "<init>" + +/******************************************************************************* + * Signature Construction Macros + ******************************************************************************/ + +/* +** These macros can be used to construct signature strings. Hopefully their names +** are a little easier to remember than the single character they correspond to. +** For example, to specify the signature of the method: +** +** public int read(byte b[], int off, int len); +** +** you could write something like this in C: +** +** char* readSig = JRISigMethod(JRISigArray(JRISigByte) +** JRISigInt +** JRISigInt) JRISigInt; +** +** Of course, don't put commas between the types. +*/ +#define JRISigArray(T) "[" T +#define JRISigByte "B" +#define JRISigChar "C" +#define JRISigClass(name) "L" name ";" +#define JRISigFloat "F" +#define JRISigDouble "D" +#define JRISigMethod(args) "(" args ")" +#define JRISigNoArgs "" +#define JRISigInt "I" +#define JRISigLong "J" +#define JRISigShort "S" +#define JRISigVoid "V" +#define JRISigBoolean "Z" + +/******************************************************************************* + * Environments + ******************************************************************************/ + +extern JRI_PUBLIC_API(const struct JRIEnvInterface**) +JRI_GetCurrentEnv(void); + +/******************************************************************************* + * Specific Scalar Array Types + ******************************************************************************/ + +/* +** The JRI Native Method Interface does not support boolean arrays. This +** is to allow Java runtime implementations to optimize boolean array +** storage. Using the ScalarArray operations on boolean arrays is bound +** to fail, so convert any boolean arrays to byte arrays in Java before +** passing them to a native method. +*/ + +#define JRI_NewByteArray(env, length, initialValues) \ + JRI_NewScalarArray(env, length, JRISigByte, (jbyte*)(initialValues)) +#define JRI_GetByteArrayLength(env, array) \ + JRI_GetScalarArrayLength(env, array) +#define JRI_GetByteArrayElements(env, array) \ + JRI_GetScalarArrayElements(env, array) + +#define JRI_NewCharArray(env, length, initialValues) \ + JRI_NewScalarArray(env, ((length) * sizeof(jchar)), JRISigChar, (jbyte*)(initialValues)) +#define JRI_GetCharArrayLength(env, array) \ + JRI_GetScalarArrayLength(env, array) +#define JRI_GetCharArrayElements(env, array) \ + ((jchar*)JRI_GetScalarArrayElements(env, array)) + +#define JRI_NewShortArray(env, length, initialValues) \ + JRI_NewScalarArray(env, ((length) * sizeof(jshort)), JRISigShort, (jbyte*)(initialValues)) +#define JRI_GetShortArrayLength(env, array) \ + JRI_GetScalarArrayLength(env, array) +#define JRI_GetShortArrayElements(env, array) \ + ((jshort*)JRI_GetScalarArrayElements(env, array)) + +#define JRI_NewIntArray(env, length, initialValues) \ + JRI_NewScalarArray(env, ((length) * sizeof(jint)), JRISigInt, (jbyte*)(initialValues)) +#define JRI_GetIntArrayLength(env, array) \ + JRI_GetScalarArrayLength(env, array) +#define JRI_GetIntArrayElements(env, array) \ + ((jint*)JRI_GetScalarArrayElements(env, array)) + +#define JRI_NewLongArray(env, length, initialValues) \ + JRI_NewScalarArray(env, ((length) * sizeof(jlong)), JRISigLong, (jbyte*)(initialValues)) +#define JRI_GetLongArrayLength(env, array) \ + JRI_GetScalarArrayLength(env, array) +#define JRI_GetLongArrayElements(env, array) \ + ((jlong*)JRI_GetScalarArrayElements(env, array)) + +#define JRI_NewFloatArray(env, length, initialValues) \ + JRI_NewScalarArray(env, ((length) * sizeof(jfloat)), JRISigFloat, (jbyte*)(initialValues)) +#define JRI_GetFloatArrayLength(env, array) \ + JRI_GetScalarArrayLength(env, array) +#define JRI_GetFloatArrayElements(env, array) \ + ((jfloat*)JRI_GetScalarArrayElements(env, array)) + +#define JRI_NewDoubleArray(env, length, initialValues) \ + JRI_NewScalarArray(env, ((length) * sizeof(jdouble)), JRISigDouble, (jbyte*)(initialValues)) +#define JRI_GetDoubleArrayLength(env, array) \ + JRI_GetScalarArrayLength(env, array) +#define JRI_GetDoubleArrayElements(env, array) \ + ((jdouble*)JRI_GetScalarArrayElements(env, array)) + +/******************************************************************************/ +#ifdef __cplusplus +} +#endif +#endif /* JRITYPES_H */ +/******************************************************************************/ diff --git a/plugin/include/npapi.h b/plugin/include/npapi.h new file mode 100644 index 0000000..598faa1 --- /dev/null +++ b/plugin/include/npapi.h @@ -0,0 +1,393 @@ +/* $Xorg: npapi.h,v 1.3 2000/08/17 19:55:02 cpqbld Exp $ */ +/* -*- Mode: C; tab-width: 4; -*- */ +/* + * npapi.h Revision: 1.76 + * Netscape client plug-in API spec + */ + +#ifndef _NPAPI_H_ +#define _NPAPI_H_ + +#include "jri.h" /* Java Runtime Interface */ + + +/* XXX this needs to get out of here */ +#if defined(__MWERKS__) +#ifndef XP_MAC +#define XP_MAC +#endif +#endif + + + +/*----------------------------------------------------------------------*/ +/* Plugin Version Constants */ +/*----------------------------------------------------------------------*/ + +#define NP_VERSION_MAJOR 0 +#define NP_VERSION_MINOR 9 + + + +/*----------------------------------------------------------------------*/ +/* Definition of Basic Types */ +/*----------------------------------------------------------------------*/ + +#ifndef _UINT16 +typedef unsigned short uint16; +#endif +#ifndef _UINT32 +#if defined(__alpha) +typedef unsigned int uint32; +#else /* __alpha */ +typedef unsigned long uint32; +#endif /* __alpha */ +#endif +#ifndef _INT16 +typedef short int16; +#endif +#ifndef _INT32 +#if defined(__alpha) +typedef int int32; +#else /* __alpha */ +typedef long int32; +#endif /* __alpha */ +#endif + +#ifndef FALSE +#define FALSE (0) +#endif +#ifndef TRUE +#define TRUE (1) +#endif +#ifndef NULL +#define NULL (0L) +#endif + +typedef unsigned char NPBool; +typedef void* NPEvent; +typedef int16 NPError; +typedef int16 NPReason; +typedef char* NPMIMEType; + + + +/*----------------------------------------------------------------------*/ +/* Structures and definitions */ +/*----------------------------------------------------------------------*/ + +/* + * NPP is a plug-in's opaque instance handle + */ +typedef struct _NPP +{ + void* pdata; /* plug-in private data */ + void* ndata; /* netscape private data */ +} NPP_t; + +typedef NPP_t* NPP; + + +typedef struct _NPStream +{ + void* pdata; /* plug-in private data */ + void* ndata; /* netscape private data */ + const char* url; + uint32 end; + uint32 lastmodified; + void* notifyData; +} NPStream; + + +typedef struct _NPByteRange +{ + int32 offset; /* negative offset means from the end */ + uint32 length; + struct _NPByteRange* next; +} NPByteRange; + + +typedef struct _NPSavedData +{ + int32 len; + void* buf; +} NPSavedData; + + +typedef struct _NPRect +{ + uint16 top; + uint16 left; + uint16 bottom; + uint16 right; +} NPRect; + + +#ifdef XP_UNIX +/* + * Unix specific structures and definitions + */ +#include <X11/Xlib.h> + +/* + * Callback Structures. + * + * These are used to pass additional platform specific information. + */ +enum { + NP_SETWINDOW = 1 +}; + +typedef struct +{ + int32 type; +} NPAnyCallbackStruct; + +typedef struct +{ + int32 type; + Display* display; + Visual* visual; + Colormap colormap; + unsigned int depth; +} NPSetWindowCallbackStruct; + +/* + * List of variable names for which NPP_GetValue shall be implemented + */ +typedef enum { + NPPVpluginNameString = 1, + NPPVpluginDescriptionString +} NPPVariable; + +/* + * List of variable names for which NPN_GetValue is implemented by Mozilla + */ +typedef enum { + NPNVxDisplay = 1, + NPNVxtAppContext +} NPNVariable; + +#endif /* XP_UNIX */ + + +typedef struct _NPWindow +{ + void* window; /* Platform specific window handle */ + uint32 x; /* Position of top left corner relative */ + uint32 y; /* to a netscape page. */ + uint32 width; /* Maximum window size */ + uint32 height; + NPRect clipRect; /* Clipping rectangle in port coordinates */ + /* Used by MAC only. */ +#ifdef XP_UNIX + void * ws_info; /* Platform-dependent additonal data */ +#endif /* XP_UNIX */ +} NPWindow; + + +typedef struct _NPFullPrint +{ + NPBool pluginPrinted; /* Set TRUE if plugin handled fullscreen */ + /* printing */ + NPBool printOne; /* TRUE if plugin should print one copy */ + /* to default printer */ + void* platformPrint; /* Platform-specific printing info */ +} NPFullPrint; + +typedef struct _NPEmbedPrint +{ + NPWindow window; + void* platformPrint; /* Platform-specific printing info */ +} NPEmbedPrint; + +typedef struct _NPPrint +{ + uint16 mode; /* NP_FULL or NP_EMBED */ + union + { + NPFullPrint fullPrint; /* if mode is NP_FULL */ + NPEmbedPrint embedPrint; /* if mode is NP_EMBED */ + } print; +} NPPrint; + + +#ifdef XP_MAC +/* + * Mac-specific structures and definitions. + */ + +#include <Quickdraw.h> +#include <Events.h> + +typedef struct NP_Port +{ + CGrafPtr port; /* Grafport */ + int32 portx; /* position inside the topmost window */ + int32 porty; +} NP_Port; + +/* + * Non-standard event types that can be passed to HandleEvent + */ +#define getFocusEvent (osEvt + 16) +#define loseFocusEvent (osEvt + 17) +#define adjustCursorEvent (osEvt + 18) + +#endif /* XP_MAC */ + + +/* + * Values for mode passed to NPP_New: + */ +#define NP_EMBED 1 +#define NP_FULL 2 + +/* + * Values for stream type passed to NPP_NewStream: + */ +#define NP_NORMAL 1 +#define NP_SEEK 2 +#define NP_ASFILE 3 +#define NP_ASFILEONLY 4 + +#define NP_MAXREADY (((unsigned)(~0)<<1)>>1) + + + +/*----------------------------------------------------------------------*/ +/* Error and Reason Code definitions */ +/*----------------------------------------------------------------------*/ + +/* + * Values of type NPError: + */ +#define NPERR_BASE 0 +#define NPERR_NO_ERROR (NPERR_BASE + 0) +#define NPERR_GENERIC_ERROR (NPERR_BASE + 1) +#define NPERR_INVALID_INSTANCE_ERROR (NPERR_BASE + 2) +#define NPERR_INVALID_FUNCTABLE_ERROR (NPERR_BASE + 3) +#define NPERR_MODULE_LOAD_FAILED_ERROR (NPERR_BASE + 4) +#define NPERR_OUT_OF_MEMORY_ERROR (NPERR_BASE + 5) +#define NPERR_INVALID_PLUGIN_ERROR (NPERR_BASE + 6) +#define NPERR_INVALID_PLUGIN_DIR_ERROR (NPERR_BASE + 7) +#define NPERR_INCOMPATIBLE_VERSION_ERROR (NPERR_BASE + 8) +#define NPERR_INVALID_PARAM (NPERR_BASE + 9) +#define NPERR_INVALID_URL (NPERR_BASE + 10) +#define NPERR_FILE_NOT_FOUND (NPERR_BASE + 11) +#define NPERR_NO_DATA (NPERR_BASE + 12) +#define NPERR_STREAM_NOT_SEEKABLE (NPERR_BASE + 13) + +/* + * Values of type NPReason: + */ +#define NPRES_BASE 0 +#define NPRES_DONE (NPRES_BASE + 0) +#define NPRES_NETWORK_ERR (NPRES_BASE + 1) +#define NPRES_USER_BREAK (NPRES_BASE + 2) + +/* + * Don't use these obsolete error codes any more. + */ +#define NP_NOERR NP_NOERR_is_obsolete_use_NPERR_NO_ERROR +#define NP_EINVAL NP_EINVAL_is_obsolete_use_NPERR_GENERIC_ERROR +#define NP_EABORT NP_EABORT_is_obsolete_use_NPRES_USER_BREAK + +/* + * Version feature information + */ +#define NPVERS_HAS_STREAMOUTPUT 8 +#define NPVERS_HAS_NOTIFICATION 9 +#define NPVERS_HAS_LIVECONNECT 9 + + +/*----------------------------------------------------------------------*/ +/* Function Prototypes */ +/*----------------------------------------------------------------------*/ + +#if defined(_WINDOWS) && !defined(WIN32) +#define NP_LOADDS _loadds +#else +#define NP_LOADDS +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * NPP_* functions are provided by the plugin and called by the navigator. + */ + +#ifdef XP_UNIX +char* NPP_GetMIMEDescription(void); +NPError NPP_GetValue(void *instance, NPPVariable variable, + void *value); +#endif /* XP_UNIX */ +NPError NPP_Initialize(void); +void NPP_Shutdown(void); +NPError NP_LOADDS NPP_New(NPMIMEType pluginType, NPP instance, + uint16 mode, int16 argc, char* argn[], + char* argv[], NPSavedData* saved); +NPError NP_LOADDS NPP_Destroy(NPP instance, NPSavedData** save); +NPError NP_LOADDS NPP_SetWindow(NPP instance, NPWindow* window); +NPError NP_LOADDS NPP_NewStream(NPP instance, NPMIMEType type, + NPStream* stream, NPBool seekable, + uint16* stype); +NPError NP_LOADDS NPP_DestroyStream(NPP instance, NPStream* stream, + NPReason reason); +int32 NP_LOADDS NPP_WriteReady(NPP instance, NPStream* stream); +int32 NP_LOADDS NPP_Write(NPP instance, NPStream* stream, int32 offset, + int32 len, void* buffer); +void NP_LOADDS NPP_StreamAsFile(NPP instance, NPStream* stream, + const char* fname); +void NP_LOADDS NPP_Print(NPP instance, NPPrint* platformPrint); +int16 NPP_HandleEvent(NPP instance, void* event); +void NPP_URLNotify(NPP instance, const char* url, + NPReason reason, void* notifyData); +jref NPP_GetJavaClass(void); + + +/* + * NPN_* functions are provided by the navigator and called by the plugin. + */ + +#ifdef XP_UNIX +NPError NPN_GetValue(NPP instance, NPNVariable variable, + void *value); +#endif /* XP_UNIX */ +void NPN_Version(int* plugin_major, int* plugin_minor, + int* netscape_major, int* netscape_minor); +NPError NPN_GetURLNotify(NPP instance, const char* url, + const char* target, void* notifyData); +NPError NPN_GetURL(NPP instance, const char* url, + const char* target); +NPError NPN_PostURLNotify(NPP instance, const char* url, + const char* target, uint32 len, + const char* buf, NPBool file, + void* notifyData); +NPError NPN_PostURL(NPP instance, const char* url, + const char* target, uint32 len, + const char* buf, NPBool file); +NPError NPN_RequestRead(NPStream* stream, NPByteRange* rangeList); +NPError NPN_NewStream(NPP instance, NPMIMEType type, + const char* target, NPStream** stream); +int32 NPN_Write(NPP instance, NPStream* stream, int32 len, + void* buffer); +NPError NPN_DestroyStream(NPP instance, NPStream* stream, + NPReason reason); +void NPN_Status(NPP instance, const char* message); +const char* NPN_UserAgent(NPP instance); +void* NPN_MemAlloc(uint32 size); +void NPN_MemFree(void* ptr); +uint32 NPN_MemFlush(uint32 size); +void NPN_ReloadPlugins(NPBool reloadPages); +JRIEnv* NPN_GetJavaEnv(void); +jref NPN_GetJavaPeer(NPP instance); + + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif /* _NPAPI_H_ */ diff --git a/plugin/include/npupp.h b/plugin/include/npupp.h new file mode 100644 index 0000000..dfd4974 --- /dev/null +++ b/plugin/include/npupp.h @@ -0,0 +1,996 @@ +/* $Xorg: npupp.h,v 1.3 2000/08/17 19:55:02 cpqbld Exp $ */ +/* -*- Mode: C; tab-width: 4; -*- */ +/* + * npupp.h Revision: 1.37 + * function call mecahnics needed by platform specific glue code. + */ + + +#ifndef _NPUPP_H_ +#define _NPUPP_H_ + +#ifndef GENERATINGCFM +#define GENERATINGCFM 0 +#endif + +#ifndef _NPAPI_H_ +#include "npapi.h" +#endif + +#include "jri.h" + +/****************************************************************************************** + plug-in function table macros + for each function in and out of the plugin API we define + typedef NPP_FooUPP + #define NewNPP_FooProc + #define CallNPP_FooProc + for mac, define the UPP magic for PPC/68K calling + *******************************************************************************************/ + + +/* NPP_Initialize */ + +#if GENERATINGCFM +typedef UniversalProcPtr NPP_InitializeUPP; + +enum { + uppNPP_InitializeProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(0)) + | RESULT_SIZE(SIZE_CODE(0)) +}; + +#define NewNPP_InitializeProc(FUNC) \ + (NPP_InitializeUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_InitializeProcInfo, GetCurrentArchitecture()) +#define CallNPP_InitializeProc(FUNC) \ + (void)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_InitializeProcInfo) + +#else + +typedef void (*NPP_InitializeUPP)(void); +#define NewNPP_InitializeProc(FUNC) \ + ((NPP_InitializeUPP) (FUNC)) +#define CallNPP_InitializeProc(FUNC) \ + (*(FUNC))() + +#endif + + +/* NPP_Shutdown */ + +#if GENERATINGCFM +typedef UniversalProcPtr NPP_ShutdownUPP; + +enum { + uppNPP_ShutdownProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(0)) + | RESULT_SIZE(SIZE_CODE(0)) +}; + +#define NewNPP_ShutdownProc(FUNC) \ + (NPP_ShutdownUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_ShutdownProcInfo, GetCurrentArchitecture()) +#define CallNPP_ShutdownProc(FUNC) \ + (void)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_ShutdownProcInfo) + +#else + +typedef void (*NPP_ShutdownUPP)(void); +#define NewNPP_ShutdownProc(FUNC) \ + ((NPP_ShutdownUPP) (FUNC)) +#define CallNPP_ShutdownProc(FUNC) \ + (*(FUNC))() + +#endif + + +/* NPP_New */ + +#if GENERATINGCFM +typedef UniversalProcPtr NPP_NewUPP; + +enum { + uppNPP_NewProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPMIMEType))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(uint16))) + | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(int16))) + | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(char **))) + | STACK_ROUTINE_PARAMETER(6, SIZE_CODE(sizeof(char **))) + | STACK_ROUTINE_PARAMETER(7, SIZE_CODE(sizeof(NPSavedData *))) + | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) +}; + +#define NewNPP_NewProc(FUNC) \ + (NPP_NewUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_NewProcInfo, GetCurrentArchitecture()) +#define CallNPP_NewProc(FUNC, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7) \ + (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_NewProcInfo, \ + (ARG1), (ARG2), (ARG3), (ARG4), (ARG5), (ARG6), (ARG7)) +#else + +typedef NPError (*NPP_NewUPP)(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, char* argn[], char* argv[], NPSavedData* saved); +#define NewNPP_NewProc(FUNC) \ + ((NPP_NewUPP) (FUNC)) +#define CallNPP_NewProc(FUNC, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7) \ + (*(FUNC))((ARG1), (ARG2), (ARG3), (ARG4), (ARG5), (ARG6), (ARG7)) + +#endif + + +/* NPP_Destroy */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPP_DestroyUPP; +enum { + uppNPP_DestroyProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPSavedData **))) + | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) +}; +#define NewNPP_DestroyProc(FUNC) \ + (NPP_DestroyUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_DestroyProcInfo, GetCurrentArchitecture()) +#define CallNPP_DestroyProc(FUNC, ARG1, ARG2) \ + (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_DestroyProcInfo, (ARG1), (ARG2)) +#else + +typedef NPError (*NPP_DestroyUPP)(NPP instance, NPSavedData** save); +#define NewNPP_DestroyProc(FUNC) \ + ((NPP_DestroyUPP) (FUNC)) +#define CallNPP_DestroyProc(FUNC, ARG1, ARG2) \ + (*(FUNC))((ARG1), (ARG2)) + +#endif + + +/* NPP_SetWindow */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPP_SetWindowUPP; +enum { + uppNPP_SetWindowProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPWindow *))) + | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) +}; +#define NewNPP_SetWindowProc(FUNC) \ + (NPP_SetWindowUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_SetWindowProcInfo, GetCurrentArchitecture()) +#define CallNPP_SetWindowProc(FUNC, ARG1, ARG2) \ + (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_SetWindowProcInfo, (ARG1), (ARG2)) + +#else + +typedef NPError (*NPP_SetWindowUPP)(NPP instance, NPWindow* window); +#define NewNPP_SetWindowProc(FUNC) \ + ((NPP_SetWindowUPP) (FUNC)) +#define CallNPP_SetWindowProc(FUNC, ARG1, ARG2) \ + (*(FUNC))((ARG1), (ARG2)) + +#endif + + +/* NPP_NewStream */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPP_NewStreamUPP; +enum { + uppNPP_NewStreamProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPMIMEType))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(NPStream *))) + | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(NPBool))) + | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(uint16 *))) + | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) +}; +#define NewNPP_NewStreamProc(FUNC) \ + (NPP_NewStreamUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_NewStreamProcInfo, GetCurrentArchitecture()) +#define CallNPP_NewStreamProc(FUNC, ARG1, ARG2, ARG3, ARG4, ARG5) \ + (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_NewStreamProcInfo, (ARG1), (ARG2), (ARG3), (ARG4), (ARG5)) +#else + +typedef NPError (*NPP_NewStreamUPP)(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16* stype); +#define NewNPP_NewStreamProc(FUNC) \ + ((NPP_NewStreamUPP) (FUNC)) +#define CallNPP_NewStreamProc(FUNC, ARG1, ARG2, ARG3, ARG4, ARG5) \ + (*(FUNC))((ARG1), (ARG2), (ARG3), (ARG4), (ARG5)) +#endif + + +/* NPP_DestroyStream */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPP_DestroyStreamUPP; +enum { + uppNPP_DestroyStreamProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPStream *))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(NPReason))) + | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) +}; +#define NewNPP_DestroyStreamProc(FUNC) \ + (NPP_DestroyStreamUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_DestroyStreamProcInfo, GetCurrentArchitecture()) +#define CallNPP_DestroyStreamProc(FUNC, NPParg, NPStreamPtr, NPReasonArg) \ + (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_DestroyStreamProcInfo, (NPParg), (NPStreamPtr), (NPReasonArg)) + +#else + +typedef NPError (*NPP_DestroyStreamUPP)(NPP instance, NPStream* stream, NPReason reason); +#define NewNPP_DestroyStreamProc(FUNC) \ + ((NPP_DestroyStreamUPP) (FUNC)) +#define CallNPP_DestroyStreamProc(FUNC, NPParg, NPStreamPtr, NPReasonArg) \ + (*(FUNC))((NPParg), (NPStreamPtr), (NPReasonArg)) + +#endif + + +/* NPP_WriteReady */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPP_WriteReadyUPP; +enum { + uppNPP_WriteReadyProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPStream *))) + | RESULT_SIZE(SIZE_CODE(sizeof(int32))) +}; +#define NewNPP_WriteReadyProc(FUNC) \ + (NPP_WriteReadyUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_WriteReadyProcInfo, GetCurrentArchitecture()) +#define CallNPP_WriteReadyProc(FUNC, NPParg, NPStreamPtr) \ + (int32)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_WriteReadyProcInfo, (NPParg), (NPStreamPtr)) + +#else + +typedef int32 (*NPP_WriteReadyUPP)(NPP instance, NPStream* stream); +#define NewNPP_WriteReadyProc(FUNC) \ + ((NPP_WriteReadyUPP) (FUNC)) +#define CallNPP_WriteReadyProc(FUNC, NPParg, NPStreamPtr) \ + (*(FUNC))((NPParg), (NPStreamPtr)) + +#endif + + +/* NPP_Write */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPP_WriteUPP; +enum { + uppNPP_WriteProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPStream *))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(int32))) + | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(int32))) + | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(void*))) + | RESULT_SIZE(SIZE_CODE(sizeof(int32))) +}; +#define NewNPP_WriteProc(FUNC) \ + (NPP_WriteUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_WriteProcInfo, GetCurrentArchitecture()) +#define CallNPP_WriteProc(FUNC, NPParg, NPStreamPtr, offsetArg, lenArg, bufferPtr) \ + (int32)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_WriteProcInfo, (NPParg), (NPStreamPtr), (offsetArg), (lenArg), (bufferPtr)) + +#else + +typedef int32 (*NPP_WriteUPP)(NPP instance, NPStream* stream, int32 offset, int32 len, void* buffer); +#define NewNPP_WriteProc(FUNC) \ + ((NPP_WriteUPP) (FUNC)) +#define CallNPP_WriteProc(FUNC, NPParg, NPStreamPtr, offsetArg, lenArg, bufferPtr) \ + (*(FUNC))((NPParg), (NPStreamPtr), (offsetArg), (lenArg), (bufferPtr)) + +#endif + + +/* NPP_StreamAsFile */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPP_StreamAsFileUPP; +enum { + uppNPP_StreamAsFileProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPStream *))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(const char *))) + | RESULT_SIZE(SIZE_CODE(0)) +}; +#define NewNPP_StreamAsFileProc(FUNC) \ + (NPP_StreamAsFileUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_StreamAsFileProcInfo, GetCurrentArchitecture()) +#define CallNPP_StreamAsFileProc(FUNC, ARG1, ARG2, ARG3) \ + (void)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_StreamAsFileProcInfo, (ARG1), (ARG2), (ARG3)) + +#else + +typedef void (*NPP_StreamAsFileUPP)(NPP instance, NPStream* stream, const char* fname); +#define NewNPP_StreamAsFileProc(FUNC) \ + ((NPP_StreamAsFileUPP) (FUNC)) +#define CallNPP_StreamAsFileProc(FUNC, ARG1, ARG2, ARG3) \ + (*(FUNC))((ARG1), (ARG2), (ARG3)) +#endif + + +/* NPP_Print */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPP_PrintUPP; +enum { + uppNPP_PrintProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPPrint *))) + | RESULT_SIZE(SIZE_CODE(0)) +}; +#define NewNPP_PrintProc(FUNC) \ + (NPP_PrintUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_PrintProcInfo, GetCurrentArchitecture()) +#define CallNPP_PrintProc(FUNC, NPParg, voidPtr) \ + (void)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_PrintProcInfo, (NPParg), (voidPtr)) + +#else + +typedef void (*NPP_PrintUPP)(NPP instance, NPPrint* platformPrint); +#define NewNPP_PrintProc(FUNC) \ + ((NPP_PrintUPP) (FUNC)) +#define CallNPP_PrintProc(FUNC, NPParg, NPPrintArg) \ + (*(FUNC))((NPParg), (NPPrintArg)) + +#endif + + +/* NPP_HandleEvent */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPP_HandleEventUPP; +enum { + uppNPP_HandleEventProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(void *))) + | RESULT_SIZE(SIZE_CODE(sizeof(int16))) +}; +#define NewNPP_HandleEventProc(FUNC) \ + (NPP_HandleEventUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_HandleEventProcInfo, GetCurrentArchitecture()) +#define CallNPP_HandleEventProc(FUNC, NPParg, voidPtr) \ + (int16)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_HandleEventProcInfo, (NPParg), (voidPtr)) + +#else + +typedef int16 (*NPP_HandleEventUPP)(NPP instance, void* event); +#define NewNPP_HandleEventProc(FUNC) \ + ((NPP_HandleEventUPP) (FUNC)) +#define CallNPP_HandleEventProc(FUNC, NPParg, voidPtr) \ + (*(FUNC))((NPParg), (voidPtr)) + +#endif + + +/* NPP_URLNotify */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPP_URLNotifyUPP; +enum { + uppNPP_URLNotifyProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(const char*))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(NPReason))) + | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(void*))) + | RESULT_SIZE(SIZE_CODE(SIZE_CODE(0))) +}; +#define NewNPP_URLNotifyProc(FUNC) \ + (NPP_URLNotifyUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_URLNotifyProcInfo, GetCurrentArchitecture()) +#define CallNPP_URLNotifyProc(FUNC, ARG1, ARG2, ARG3, ARG4) \ + (void)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_URLNotifyProcInfo, (ARG1), (ARG2), (ARG3), (ARG4)) + +#else + +typedef void (*NPP_URLNotifyUPP)(NPP instance, const char* url, NPReason reason, void* notifyData); +#define NewNPP_URLNotifyProc(FUNC) \ + ((NPP_URLNotifyUPP) (FUNC)) +#define CallNPP_URLNotifyProc(FUNC, ARG1, ARG2, ARG3, ARG4) \ + (*(FUNC))((ARG1), (ARG2), (ARG3), (ARG4)) + +#endif + + + + +/* + * Netscape entry points + */ + +#ifdef XP_UNIX + +/* NPN_GetValue */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_GetValueUPP; +enum { + uppNPN_GetValueProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPNVariable))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(void *))) + | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) +}; +#define NewNPN_GetValueProc(FUNC) \ + (NPN_GetValueUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_GetValueProcInfo, GetCurrentArchitecture()) +#define CallNPN_GetURNotifyLProc(FUNC, ARG1, ARG2, ARG3) \ + (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_GetValueProcInfo, (ARG1), (ARG2), (ARG3)) +#else + +typedef NPError (*NPN_GetValueUPP)(NPP instance, NPNVariable variable, void *ret_alue); +#define NewNPN_GetValueProc(FUNC) \ + ((NPN_GetValueUPP) (FUNC)) +#define CallNPN_GetValueProc(FUNC, ARG1, ARG2, ARG3) \ + (*(FUNC))((ARG1), (ARG2), (ARG3)) +#endif + +#endif /* XP_UNIX */ + + + +/* NPN_GetUrlNotify */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_GetURLNotifyUPP; +enum { + uppNPN_GetURLNotifyProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(const char*))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(const char*))) + | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(void*))) + | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) +}; +#define NewNPN_GetURLNotifyProc(FUNC) \ + (NPN_GetURLNotifyUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_GetURLNotifyProcInfo, GetCurrentArchitecture()) +#define CallNPN_GetURLNotifyProc(FUNC, ARG1, ARG2, ARG3, ARG4) \ + (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_GetURLNotifyProcInfo, (ARG1), (ARG2), (ARG3), (ARG4)) +#else + +typedef NPError (*NPN_GetURLNotifyUPP)(NPP instance, const char* url, const char* window, void* notifyData); +#define NewNPN_GetURLNotifyProc(FUNC) \ + ((NPN_GetURLNotifyUPP) (FUNC)) +#define CallNPN_GetURLNotifyProc(FUNC, ARG1, ARG2, ARG3, ARG4) \ + (*(FUNC))((ARG1), (ARG2), (ARG3), (ARG4)) +#endif + + +/* NPN_PostUrlNotify */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_PostURLNotifyUPP; +enum { + uppNPN_PostURLNotifyProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(const char*))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(const char*))) + | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(uint32))) + | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(const char*))) + | STACK_ROUTINE_PARAMETER(6, SIZE_CODE(sizeof(NPBool))) + | STACK_ROUTINE_PARAMETER(7, SIZE_CODE(sizeof(void*))) + | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) +}; +#define NewNPN_PostURLNotifyProc(FUNC) \ + (NPN_PostURLNotifyUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_PostURLNotifyProcInfo, GetCurrentArchitecture()) +#define CallNPN_PostURLNotifyProc(FUNC, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7) \ + (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_PostURLNotifyProcInfo, (ARG1), (ARG2), (ARG3), (ARG4), (ARG5), (ARG6), (ARG7)) +#else + +typedef NPError (*NPN_PostURLNotifyUPP)(NPP instance, const char* url, const char* window, uint32 len, const char* buf, NPBool file, void* notifyData); +#define NewNPN_PostURLNotifyProc(FUNC) \ + ((NPN_PostURLNotifyUPP) (FUNC)) +#define CallNPN_PostURLNotifyProc(FUNC, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7) \ + (*(FUNC))((ARG1), (ARG2), (ARG3), (ARG4), (ARG5), (ARG6), (ARG7)) +#endif + + +/* NPN_GetUrl */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_GetURLUPP; +enum { + uppNPN_GetURLProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(const char*))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(const char*))) + | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) +}; +#define NewNPN_GetURLProc(FUNC) \ + (NPN_GetURLUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_GetURLProcInfo, GetCurrentArchitecture()) +#define CallNPN_GetURLProc(FUNC, ARG1, ARG2, ARG3) \ + (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_GetURLProcInfo, (ARG1), (ARG2), (ARG3)) +#else + +typedef NPError (*NPN_GetURLUPP)(NPP instance, const char* url, const char* window); +#define NewNPN_GetURLProc(FUNC) \ + ((NPN_GetURLUPP) (FUNC)) +#define CallNPN_GetURLProc(FUNC, ARG1, ARG2, ARG3) \ + (*(FUNC))((ARG1), (ARG2), (ARG3)) +#endif + + +/* NPN_PostUrl */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_PostURLUPP; +enum { + uppNPN_PostURLProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(const char*))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(const char*))) + | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(uint32))) + | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(const char*))) + | STACK_ROUTINE_PARAMETER(6, SIZE_CODE(sizeof(NPBool))) + | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) +}; +#define NewNPN_PostURLProc(FUNC) \ + (NPN_PostURLUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_PostURLProcInfo, GetCurrentArchitecture()) +#define CallNPN_PostURLProc(FUNC, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6) \ + (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_PostURLProcInfo, (ARG1), (ARG2), (ARG3), (ARG4), (ARG5), (ARG6)) +#else + +typedef NPError (*NPN_PostURLUPP)(NPP instance, const char* url, const char* window, uint32 len, const char* buf, NPBool file); +#define NewNPN_PostURLProc(FUNC) \ + ((NPN_PostURLUPP) (FUNC)) +#define CallNPN_PostURLProc(FUNC, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6) \ + (*(FUNC))((ARG1), (ARG2), (ARG3), (ARG4), (ARG5), (ARG6)) +#endif + + +/* NPN_RequestRead */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_RequestReadUPP; +enum { + uppNPN_RequestReadProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPStream *))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPByteRange *))) + | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) +}; +#define NewNPN_RequestReadProc(FUNC) \ + (NPN_RequestReadUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_RequestReadProcInfo, GetCurrentArchitecture()) +#define CallNPN_RequestReadProc(FUNC, stream, range) \ + (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_RequestReadProcInfo, (stream), (range)) + +#else + +typedef NPError (*NPN_RequestReadUPP)(NPStream* stream, NPByteRange* rangeList); +#define NewNPN_RequestReadProc(FUNC) \ + ((NPN_RequestReadUPP) (FUNC)) +#define CallNPN_RequestReadProc(FUNC, stream, range) \ + (*(FUNC))((stream), (range)) + +#endif + + +/* NPN_NewStream */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_NewStreamUPP; +enum { + uppNPN_NewStreamProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPMIMEType))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(const char *))) + | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(NPStream **))) + | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) +}; +#define NewNPN_NewStreamProc(FUNC) \ + (NPN_NewStreamUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_NewStreamProcInfo, GetCurrentArchitecture()) +#define CallNPN_NewStreamProc(FUNC, npp, type, window, stream) \ + (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_NewStreamProcInfo, (npp), (type), (window), (stream)) + +#else + +typedef NPError (*NPN_NewStreamUPP)(NPP instance, NPMIMEType type, const char* window, NPStream** stream); +#define NewNPN_NewStreamProc(FUNC) \ + ((NPN_NewStreamUPP) (FUNC)) +#define CallNPN_NewStreamProc(FUNC, npp, type, window, stream) \ + (*(FUNC))((npp), (type), (window), (stream)) + +#endif + + +/* NPN_Write */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_WriteUPP; +enum { + uppNPN_WriteProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPStream *))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(int32))) + | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(void*))) + | RESULT_SIZE(SIZE_CODE(sizeof(int32))) +}; +#define NewNPN_WriteProc(FUNC) \ + (NPN_WriteUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_WriteProcInfo, GetCurrentArchitecture()) +#define CallNPN_WriteProc(FUNC, npp, stream, len, buffer) \ + (int32)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_WriteProcInfo, (npp), (stream), (len), (buffer)) + +#else + +typedef int32 (*NPN_WriteUPP)(NPP instance, NPStream* stream, int32 len, void* buffer); +#define NewNPN_WriteProc(FUNC) \ + ((NPN_WriteUPP) (FUNC)) +#define CallNPN_WriteProc(FUNC, npp, stream, len, buffer) \ + (*(FUNC))((npp), (stream), (len), (buffer)) + +#endif + + +/* NPN_DestroyStream */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_DestroyStreamUPP; +enum { + uppNPN_DestroyStreamProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP ))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPStream *))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(NPReason))) + | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) +}; +#define NewNPN_DestroyStreamProc(FUNC) \ + (NPN_DestroyStreamUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_DestroyStreamProcInfo, GetCurrentArchitecture()) +#define CallNPN_DestroyStreamProc(FUNC, npp, stream, reason) \ + (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_DestroyStreamProcInfo, (npp), (stream), (reason)) + +#else + +typedef NPError (*NPN_DestroyStreamUPP)(NPP instance, NPStream* stream, NPReason reason); +#define NewNPN_DestroyStreamProc(FUNC) \ + ((NPN_DestroyStreamUPP) (FUNC)) +#define CallNPN_DestroyStreamProc(FUNC, npp, stream, reason) \ + (*(FUNC))((npp), (stream), (reason)) + +#endif + + +/* NPN_Status */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_StatusUPP; +enum { + uppNPN_StatusProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(char *))) +}; + +#define NewNPN_StatusProc(FUNC) \ + (NPN_StatusUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_StatusProcInfo, GetCurrentArchitecture()) +#define CallNPN_StatusProc(FUNC, npp, msg) \ + (void)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_StatusProcInfo, (npp), (msg)) + +#else + +typedef void (*NPN_StatusUPP)(NPP instance, const char* message); +#define NewNPN_StatusProc(FUNC) \ + ((NPN_StatusUPP) (FUNC)) +#define CallNPN_StatusProc(FUNC, npp, msg) \ + (*(FUNC))((npp), (msg)) + +#endif + + +/* NPN_UserAgent */ +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_UserAgentUPP; +enum { + uppNPN_UserAgentProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | RESULT_SIZE(SIZE_CODE(sizeof(const char *))) +}; + +#define NewNPN_UserAgentProc(FUNC) \ + (NPN_UserAgentUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_UserAgentProcInfo, GetCurrentArchitecture()) +#define CallNPN_UserAgentProc(FUNC, ARG1) \ + (const char*)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_UserAgentProcInfo, (ARG1)) + +#else + +typedef const char* (*NPN_UserAgentUPP)(NPP instance); +#define NewNPN_UserAgentProc(FUNC) \ + ((NPN_UserAgentUPP) (FUNC)) +#define CallNPN_UserAgentProc(FUNC, ARG1) \ + (*(FUNC))((ARG1)) + +#endif + + +/* NPN_MemAlloc */ +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_MemAllocUPP; +enum { + uppNPN_MemAllocProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(uint32))) + | RESULT_SIZE(SIZE_CODE(sizeof(void *))) +}; + +#define NewNPN_MemAllocProc(FUNC) \ + (NPN_MemAllocUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_MemAllocProcInfo, GetCurrentArchitecture()) +#define CallNPN_MemAllocProc(FUNC, ARG1) \ + (void*)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_MemAllocProcInfo, (ARG1)) + +#else + +typedef void* (*NPN_MemAllocUPP)(uint32 size); +#define NewNPN_MemAllocProc(FUNC) \ + ((NPN_MemAllocUPP) (FUNC)) +#define CallNPN_MemAllocProc(FUNC, ARG1) \ + (*(FUNC))((ARG1)) + +#endif + + +/* NPN__MemFree */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_MemFreeUPP; +enum { + uppNPN_MemFreeProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(void *))) +}; + +#define NewNPN_MemFreeProc(FUNC) \ + (NPN_MemFreeUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_MemFreeProcInfo, GetCurrentArchitecture()) +#define CallNPN_MemFreeProc(FUNC, ARG1) \ + (void)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_MemFreeProcInfo, (ARG1)) + +#else + +typedef void (*NPN_MemFreeUPP)(void* ptr); +#define NewNPN_MemFreeProc(FUNC) \ + ((NPN_MemFreeUPP) (FUNC)) +#define CallNPN_MemFreeProc(FUNC, ARG1) \ + (*(FUNC))((ARG1)) + +#endif + + +/* NPN_MemFlush */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_MemFlushUPP; +enum { + uppNPN_MemFlushProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(uint32))) + | RESULT_SIZE(SIZE_CODE(sizeof(uint32))) +}; + +#define NewNPN_MemFlushProc(FUNC) \ + (NPN_MemFlushUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_MemFlushProcInfo, GetCurrentArchitecture()) +#define CallNPN_MemFlushProc(FUNC, ARG1) \ + (uint32)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_MemFlushProcInfo, (ARG1)) + +#else + +typedef uint32 (*NPN_MemFlushUPP)(uint32 size); +#define NewNPN_MemFlushProc(FUNC) \ + ((NPN_MemFlushUPP) (FUNC)) +#define CallNPN_MemFlushProc(FUNC, ARG1) \ + (*(FUNC))((ARG1)) + +#endif + + + +/* NPN_ReloadPlugins */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_ReloadPluginsUPP; +enum { + uppNPN_ReloadPluginsProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPBool))) + | RESULT_SIZE(SIZE_CODE(0)) +}; + +#define NewNPN_ReloadPluginsProc(FUNC) \ + (NPN_ReloadPluginsUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_ReloadPluginsProcInfo, GetCurrentArchitecture()) +#define CallNPN_ReloadPluginsProc(FUNC, ARG1) \ + (void)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_ReloadPluginsProcInfo, (ARG1)) + +#else + +typedef void (*NPN_ReloadPluginsUPP)(NPBool reloadPages); +#define NewNPN_ReloadPluginsProc(FUNC) \ + ((NPN_ReloadPluginsUPP) (FUNC)) +#define CallNPN_ReloadPluginsProc(FUNC, ARG1) \ + (*(FUNC))((ARG1)) + +#endif + + +/* NPN_GetJavaEnv */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_GetJavaEnvUPP; +enum { + uppNPN_GetJavaEnvProcInfo = kThinkCStackBased + | RESULT_SIZE(SIZE_CODE(sizeof(JRIEnv*))) +}; + +#define NewNPN_GetJavaEnvProc(FUNC) \ + (NPN_GetJavaEnvUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_GetJavaEnvProcInfo, GetCurrentArchitecture()) +#define CallNPN_GetJavaEnvProc(FUNC) \ + (JRIEnv*)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_GetJavaEnvProcInfo) + +#else + +typedef JRIEnv* (*NPN_GetJavaEnvUPP)(void); +#define NewNPN_GetJavaEnvProc(FUNC) \ + ((NPN_GetJavaEnvUPP) (FUNC)) +#define CallNPN_GetJavaEnvProc(FUNC) \ + (*(FUNC))() + +#endif + + +/* NPN_GetJavaPeer */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_GetJavaPeerUPP; +enum { + uppNPN_GetJavaPeerProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | RESULT_SIZE(SIZE_CODE(sizeof(jref))) +}; + +#define NewNPN_GetJavaPeerProc(FUNC) \ + (NPN_GetJavaPeerUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_GetJavaPeerProcInfo, GetCurrentArchitecture()) +#define CallNPN_GetJavaPeerProc(FUNC, ARG1) \ + (jref)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_GetJavaPeerProcInfo, (ARG1)) + +#else + +typedef jref (*NPN_GetJavaPeerUPP)(NPP instance); +#define NewNPN_GetJavaPeerProc(FUNC) \ + ((NPN_GetJavaPeerUPP) (FUNC)) +#define CallNPN_GetJavaPeerProc(FUNC, ARG1) \ + (*(FUNC))((ARG1)) + +#endif + + + + +/****************************************************************************************** + * The actual plugin function table definitions + *******************************************************************************************/ + +typedef struct _NPPluginFuncs { + uint16 size; + uint16 version; + NPP_NewUPP newp; + NPP_DestroyUPP destroy; + NPP_SetWindowUPP setwindow; + NPP_NewStreamUPP newstream; + NPP_DestroyStreamUPP destroystream; + NPP_StreamAsFileUPP asfile; + NPP_WriteReadyUPP writeready; + NPP_WriteUPP write; + NPP_PrintUPP print; + NPP_HandleEventUPP event; + NPP_URLNotifyUPP urlnotify; + JRIGlobalRef javaClass; +} NPPluginFuncs; + +typedef struct _NPNetscapeFuncs { + uint16 size; + uint16 version; + NPN_GetURLUPP geturl; + NPN_PostURLUPP posturl; + NPN_RequestReadUPP requestread; + NPN_NewStreamUPP newstream; + NPN_WriteUPP write; + NPN_DestroyStreamUPP destroystream; + NPN_StatusUPP status; + NPN_UserAgentUPP uagent; + NPN_MemAllocUPP memalloc; + NPN_MemFreeUPP memfree; + NPN_MemFlushUPP memflush; + NPN_ReloadPluginsUPP reloadplugins; + NPN_GetJavaEnvUPP getJavaEnv; + NPN_GetJavaPeerUPP getJavaPeer; + NPN_GetURLNotifyUPP geturlnotify; + NPN_PostURLNotifyUPP posturlnotify; +#ifdef XP_UNIX + NPN_GetValueUPP getvalue; +#endif /* XP_UNIX */ +} NPNetscapeFuncs; + + + +#ifdef XP_MAC +/****************************************************************************************** + * Mac platform-specific plugin glue stuff + *******************************************************************************************/ + +/* + * Main entry point of the plugin. + * This routine will be called when the plugin is loaded. The function + * tables are passed in and the plugin fills in the NPPluginFuncs table + * and NPPShutdownUPP for Netscape's use. + */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPP_MainEntryUPP; +enum { + uppNPP_MainEntryProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPNetscapeFuncs*))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPPluginFuncs*))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(NPP_ShutdownUPP*))) + | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) +}; +#define NewNPP_MainEntryProc(FUNC) \ + (NPP_MainEntryUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_MainEntryProcInfo, GetCurrentArchitecture()) +#define CallNPP_MainEntryProc(FUNC, netscapeFunc, pluginFunc, shutdownUPP) \ + CallUniversalProc((UniversalProcPtr)(FUNC), (ProcInfoType)uppNPP_MainEntryProcInfo, (netscapeFunc), (pluginFunc), (shutdownUPP)) + +#else + +typedef NPError (*NPP_MainEntryUPP)(NPNetscapeFuncs*, NPPluginFuncs*, NPP_ShutdownUPP*); +#define NewNPP_MainEntryProc(FUNC) \ + ((NPP_MainEntryUPP) (FUNC)) +#define CallNPP_MainEntryProc(FUNC, netscapeFunc, pluginFunc, shutdownUPP) \ + (*(FUNC))((netscapeFunc), (pluginFunc), (shutdownUPP)) + +#endif +#endif /* MAC */ + + +#ifdef _WINDOWS + +#ifdef __cplusplus +extern "C" { +#endif + +/* plugin meta member functions */ + +NPError WINAPI NP_GetEntryPoints(NPPluginFuncs* pFuncs); + +NPError WINAPI NP_Initialize(NPNetscapeFuncs* pFuncs); + +NPError WINAPI NP_Shutdown(); + +#ifdef __cplusplus +} +#endif + +#endif /* _WINDOWS */ + +#ifdef XP_UNIX + +#ifdef __cplusplus +extern "C" { +#endif + +/* plugin meta member functions */ + +char* NP_GetMIMEDescription(void); +NPError NP_Initialize(NPNetscapeFuncs*, NPPluginFuncs*); +NPError NP_Shutdown(void); + +#ifdef __cplusplus +} +#endif + +#endif /* XP_UNIX */ + +#endif /* _NPUPP_H_ */ diff --git a/plugin/libxrx.man b/plugin/libxrx.man new file mode 100644 index 0000000..6ceca60 --- /dev/null +++ b/plugin/libxrx.man @@ -0,0 +1,152 @@ +.\" $Xorg: libxrx.man,v 1.4 2001/02/09 02:05:57 xorgcvs Exp $ +.\" Copyright 1996, 1998 The Open Group +.\" +.\" Permission to use, copy, modify, distribute, and sell this software and its +.\" documentation for any purpose is hereby granted without fee, provided that +.\" the above copyright notice appear in all copies and that both that +.\" copyright notice and this permission notice appear in supporting +.\" documentation. +.\" +.\" The above copyright notice and this permission notice shall be included +.\" in all copies or substantial portions of the Software. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +.\" OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +.\" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +.\" IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +.\" OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +.\" ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +.\" OTHER DEALINGS IN THE SOFTWARE. +.\" +.\" Except as contained in this notice, the name of The Open Group shall +.\" not be used in advertising or otherwise to promote the sale, use or +.\" other dealings in this Software without prior written authorization +.\" from The Open Group. +.\" +.TH LIBXRX 1 "Release 6.4" "X Version 11" +.SH NAME +libxrx - RX Netscape Navigator Plug-in +.SH DESCRIPTION +The \fBRX Plug-in\fP may be used with Netscape Navigator (3.0 or later) to +interpret documents in the RX MIME type format and start remote +applications. +.PP +The \fBRX Plug-in\fP reads an RX document, from which it gets the list +of services the application wants to use. Based on this information, the +\fBRX Plug-in\fP sets the various requested services, including creating +authorization keys if your X server supports the SECURITY extension. It +then passes the relevant data, such as the X display name, to the +application through an HTTP GET request of the associated CGI script. The +Web server then executes the CGI script to start the application. The +client runs on the web server host connected to your X server. In +addition when the RX document is used within the EMBED tag (a Netscape +extension to HTML), the \fBRX Plug-in\fP uses the XC-APPGROUP extension, if +it is supported by your X server, to cause the remote application to be +embedded within the browser page from which it was launched. +.PP +.SH INSTALLATION +To install the \fBRX Plug-in\fP so that Netscape Navigator can use it, find +the file named libxrx.so.6.3 or libxrx.sl.6.3 (or similar, depending on +your platform) in <ProjectRoot>/lib (e.g. /usr/X11R6.4/lib) and copy it to +either /usr/local/lib/netscape/plugins or $HOME/.netscape/plugins. Do +not install the symlinks libxrx.so or libxrx.sl; they would confuse +Netscape. +.PP +If you have configured Netscape Navigator to use the RX helper program +(\fBxrx\fP), you must reconfigure it. Generally you simply need to remove +or comment out the line you may have previously added in your mailcap file +to use the RX helper program. +Otherwise the plug-in will not be enabled. (The usual comment character for +mailcap is ``#''.) +.PP +If you are already running Netscape Navigator, you need to exit and restart +it after copying the plug-in library so the new plug-in will be found. +Once this is done you can check that Navigator has successfully loaded the +plug-in by checking the ``About Plug-ins'' page from the Help menu. This +should show something like: + + RX Plug-in + + File name: /usr/local/lib/netscape/plugins/libxrx.sl.6.3 + + X Remote Activation Plug-in + + Mime Type Description Suffixes Enabled + application/x-rx X Remote Activation Plug-in xrx Yes + +.PP +Once correctly configured, Netscape Navigator will activate the \fBRX +Plug-in\fP whenever you retrieve any document of the MIME type +\fIapplication/x-rx\fP. +.PP +.SH RESOURCES +The \fBRX Plug-in\fP looks for resources associated with the widget +\fBnetscape.Navigator (\fPclass\fB Netscape.TopLevelShell)\fP and +understands the following resource names and classes: +.\".in +1in +.TP 8 +.B "xrxHasFirewallProxy (\fPclass\fB XrxHasFirewallProxy)" +Specifies whether an X server firewall proxy (see xfwp) is running and +should be used. Default is ``False.'' The X firewall proxy uses +the X Security Extension and this extension will only allow clients +to connect to the X server if host-based authentication is turned +on. See \fBxfwp(1)\fP for more information. +.TP 8 +.B "xrxInternalWebServers (\fPclass\fB XrxInternalWebServers)" +The web servers for which the X server firewall proxy should not be used +(only relevant when \fBxrxHasFirewallProxy\fP is ``True''). Its value is a +comma separated list of mask/value pairs to be used to filter internal +web servers, based on their address. The mask part specifies which segments +of the address are to be considered and the value part specifies what the +result should match. For instance the following list: + + 255.255.255.0/198.112.45.0, 255.255.255.0/198.112.46.0 + +matches the address sets: 198.112.45.* and 198.112.46.*. More precisely, +the test is (address & mask) == value. +.TP 8 +.B "xrxFastWebServers (\fPclass\fB XrxFastWebServers)" +The web servers for which LBX should not be used. The resource value is a +list of address mask/value pairs, as previously described. +.TP 8 +.B "xrxTrustedWebServers (\fPclass\fB XrxTrustedWebServers)" +The web servers from which remote applications should be run as trusted +clients. The default is to run remote applications as untrusted +clients. The resource value is a list of address mask/value pairs, as +previously described. +.PP +.SH ENVIRONMENT +If the RX document requests X-UI-LBX service and the default X server does +not advertise the LBX extension, the \fIRX Plug-in\fP will look for the +environment variable ``XREALDISPLAY'' to get a second address for your X +server and look for the LBX extension there. When running your browser +through \fIlbxproxy\fP you will need to set XREALDISPLAY to the actual +address of your server if you wish remote applications to be able to use +LBX across the Internet. +.PP +If the RX document requests XPRINT service, \fIRX Plug-in\fP looks for the +variable ``XPRINTER'' to get the printer name and X Print server address to +use. If the server address is not specified as part of XPRINTER, \fIRX +Plug-in\fP uses the first one specified through the variable +``XPSERVERLIST'' when it is set. When it is not \fIRX Plug-in\fP then tries +to use the video server as the print server. If the printer name is not +specified via XPRINTER, \fIRX Plug-in\fP looks for it in the variables +``PDPRINTER'', then ``LPDEST'', and finally ``PRINTER'', +.PP +Finally, if you are using a firewall proxy, \fIRX Plug-in\fP will look for +``PROXY_MANAGER'' to get the address of your proxy manager (see +proxymngr). When not specified it will use ":6500" as the default. +.PP +.SH KNOWN BUG +When an authorization key is created for a remote application to use the X +Print service, the \fBRX Plug-in\fP has to create the key with an infinite +timeout since nobody knows when the application will actually connect to +the X Print server. It then revokes the key when its instance is destroyed +(that is when you go to another page). However, if the Plug-in does not get +destroyed properly, which happens when Netscape Navigator dies +unexpectedly, the print authorization key will never get revoked. +.PP +.SH SEE ALSO +xrx (1), xfwp (1), lbxproxy (1), proxymngr (1), The RX Document specification +.SH AUTHORS +Arnaud Le Hors and Kaleb Keithley, X Consortium diff --git a/plugin/stubs.c b/plugin/stubs.c new file mode 100644 index 0000000..4aab758 --- /dev/null +++ b/plugin/stubs.c @@ -0,0 +1,15 @@ +/* $Xorg: stubs.c,v 1.3 2000/08/17 19:54:59 cpqbld Exp $ */ +/* -*- Mode: C; tab-width: 4; -*- */ +/******************************************************************************* + * Simple LiveConnect Sample Plugin + * Copyright (c) 1996 Netscape Communications. All rights reserved. + ******************************************************************************/ + +/* +** Ok, so we don't usually include .c files (only .h files) but we're +** doing it here to avoid some fancy make rules. First pull in the common +** glue code: +*/ +#ifdef XP_UNIX +#include "common/npunix.c" +#endif diff --git a/rx/BuildReq.c b/rx/BuildReq.c new file mode 100644 index 0000000..50ba6b5 --- /dev/null +++ b/rx/BuildReq.c @@ -0,0 +1,150 @@ +/* $Xorg: BuildReq.c,v 1.4 2001/02/09 02:05:58 xorgcvs Exp $ */ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- +ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABIL- +ITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization from +The Open Group. + +*/ + +#include "RxI.h" + +/* build the GET request to perform to launch the remote application */ +char * +RxBuildRequest(RxReturnParams *params) +{ + char *request, *ptr; + int len, action_len, embed_len, width_len, height_len, + ui_len, print_len, x_ui_lbx_len, x_print_lbx_len; + char width_str[10], height_str[10]; + + /* the action parameter is mandatory */ + if (params->action == NULL) + return NULL; + + /* + * compute string size + */ + action_len = embed_len = width_len = height_len = 0; + ui_len = print_len = x_ui_lbx_len = x_print_lbx_len = 0; + + len = (action_len = strlen(params->action)) + 1; /* URL + delimiter */ + + /* RX_EMBEDDED + "=" + value + delimiter, + sizeof including '\0' no need to add anything for the delimiter */ + if (params->embedded != RxUndef) + len += (embed_len = sizeof(RX_EMBEDDED) + + (params->embedded == RxTrue ? sizeof(RX_YES) : sizeof(RX_NO))); + + /* RX_WIDTH + "=" + value + delimiter */ + if (params->width != RxUndef) { + sprintf(width_str, "%d", params->width); + len += (width_len = sizeof(RX_WIDTH) + strlen(width_str) + 1); + } + /* RX_HEIGHT + "=" + value + delimiter */ + if (params->height != RxUndef) { + sprintf(height_str, "%d", params->height); + len += (height_len = sizeof(RX_HEIGHT) + strlen(height_str) + 1); + } + if (params->ui != NULL) + /* "UI=" + URL + delimiter */ + len += (ui_len = sizeof(RX_UI)+ strlen(params->ui) + 1); + if (params->print != NULL) + /* "PRINT=" + URL + delimiter */ + len += (print_len = sizeof(RX_PRINT) + strlen(params->print) + 1); + + /* RX_X_UI_LBX + "=" + value + delimiter, + sizeof including '\0' no need to add anything for the delimiter */ + if (params->x_ui_lbx != RxUndef) { + x_ui_lbx_len = sizeof(RX_X_UI_LBX); + if (params->x_ui_lbx == RxTrue) { + x_ui_lbx_len += sizeof(RX_YES); + if (params->x_ui_lbx_auth != NULL) /* 6 for ";auth=" */ + x_ui_lbx_len += strlen(params->x_ui_lbx_auth) + 6; + } else + x_ui_lbx_len += sizeof(RX_NO); + len += x_ui_lbx_len; + } + + /* RX_X_PRINT_LBX + "=" + value + delimiter, + sizeof including '\0' no need to add anything for the delimiter */ + if (params->x_print_lbx != RxUndef) { + x_print_lbx_len = sizeof(RX_X_PRINT_LBX); + if (params->x_print_lbx == RxTrue) { + x_print_lbx_len += sizeof(RX_YES); + if (params->x_print_lbx_auth != NULL) /* 6 for ";auth=" */ + x_print_lbx_len += strlen(params->x_print_lbx_auth) + 6; + } else + x_print_lbx_len += sizeof(RX_NO); + len += x_print_lbx_len; + } + + /* + * malloc string and set it + */ + request = ptr = (char *)Malloc(len); + strcpy(ptr, params->action); + ptr += action_len; + if (embed_len != 0) { + sprintf(ptr, "%c%s=%s", RX_QUERY_DELIMITER, RX_EMBEDDED, + (params->embedded == RxTrue ? RX_YES : RX_NO)); + ptr += embed_len; /* be careful delimiter is included here */ + } + if (width_len != 0) { + sprintf(ptr, "%c%s=%s", RX_QUERY_DELIMITER, RX_WIDTH, width_str); + ptr += width_len; + } + if (height_len != 0) { + sprintf(ptr, "%c%s=%s", RX_QUERY_DELIMITER, RX_HEIGHT, height_str); + ptr += height_len; + } + if (ui_len != 0) { + sprintf(ptr, "%c%s=%s", RX_QUERY_DELIMITER, RX_UI, params->ui); + ptr += ui_len; + } + if (print_len != 0) { + sprintf(ptr, "%c%s=%s", RX_QUERY_DELIMITER, RX_PRINT, params->print); + ptr += print_len; + } + if (x_ui_lbx_len != 0) { + if (params->x_ui_lbx == RxTrue && params->x_ui_lbx_auth != NULL) + sprintf(ptr, "%c%s=%s;auth=%s", RX_QUERY_DELIMITER, RX_X_UI_LBX, + RX_YES, params->x_ui_lbx_auth); + else + sprintf(ptr, "%c%s=%s", RX_QUERY_DELIMITER, RX_X_UI_LBX, + (params->x_ui_lbx == RxTrue ? RX_YES : RX_NO)); + ptr += x_ui_lbx_len; + } + if (x_print_lbx_len != 0) { + if (params->x_print_lbx == RxTrue + && params->x_print_lbx_auth != NULL) + sprintf(ptr, "%c%s=%s;auth=%s", RX_QUERY_DELIMITER, + RX_X_PRINT_LBX, RX_YES, params->x_print_lbx_auth); + else + sprintf(ptr, "%c%s=%s", RX_QUERY_DELIMITER, RX_X_PRINT_LBX, + (params->x_print_lbx == RxTrue ? RX_YES : RX_NO)); + ptr += x_print_lbx_len; + } + + return request; +} diff --git a/rx/PParse.c b/rx/PParse.c new file mode 100644 index 0000000..07e360b --- /dev/null +++ b/rx/PParse.c @@ -0,0 +1,460 @@ +/* $Xorg: PParse.c,v 1.4 2001/02/09 02:05:58 xorgcvs Exp $ */ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- +ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABIL- +ITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization from +The Open Group. + +*/ + +#include "RxI.h" + +#define RX_DEFAULT_VERSION 1 +#define RX_DEFAULT_REVISION 0 + + +typedef struct { + char *string; + int length; + int index; +} Token; + +/* macros to make token tables */ +#define TOKEN(s, i) { s, sizeof(s) - 1, i } +#define NULLTOKEN { NULL, 0, 0 } + +/* tables of tokens, + each token is made of a string and its associated enum value. + */ +static Token RxServices[] = { + TOKEN(RX_UI, UI), + TOKEN(RX_PRINT, Print), + NULLTOKEN +}; + +static Token RxUIs[] = { + TOKEN("X", XUI), + NULLTOKEN +}; + +static Token RxPrints[] = { + TOKEN("XPrint", XPrint), + NULLTOKEN +}; + + +static Token RxXAuthentications[] = { + TOKEN("MIT-MAGIC-COOKIE-1", MitMagicCookie1), + NULLTOKEN +}; + +#ifdef NEED_STRCASECMP +/* + * in case str[n]casecmp are not provided by the system here are some + * which do the trick + */ +int +_RxStrcasecmp(register const char *s1, register const char *s2) +{ + register int c1, c2; + + while (*s1 && *s2) { + c1 = tolower(*s1); + c2 = tolower(*s2); + if (c1 != c2) + return (c1 - c2); + s1++; + s2++; + } + return (int) (*s1 - *s2); +} + +int +_RxStrncasecmp(register const char *s1, register const char *s2, size_t n) +{ + register int c1, c2; + const char *l1 = s1 + n; + const char *l2 = s2 + n; + + while (*s1 && *s2 && s1 < l1 && s2 < l2) { + c1 = tolower(*s1); + c2 = tolower(*s2); + if (c1 != c2) + return (c1 - c2); + s1++; + s2++; + } + if (s1 < l1 && s2 < l2) + return (int) (*s1 - *s2); + else if (s1 < l1) + return (int) *s1; + else if (s2 < l2) + return (int) *s2; + return 0; +} +#endif + +/* string copy functions */ +static char * +strcopy(char *src) +{ + char *cpy = (char *)Malloc(strlen(src) + 1); + if (cpy) + strcpy(cpy, src); + return cpy; +} + +static char * +strncopy(char *src, int n) +{ + char *cpy = (char *)Malloc(n + 1); + if (cpy) { + strncpy(cpy, src, n); + cpy[n] = '\0'; + } + return cpy; +} + + +/* print out warning message */ +#define WARNING(m, p) if (debug != 0) Warning(m, p) +static void +Warning(char *message, char *param) +{ + fprintf(stderr, "Warning: %s%s\n", message, param); +} + +#define WARNINGN(m, p, n) if (debug != 0) WarningN(m, p, n) +static void +WarningN(char *message, char *param, int param_len) +{ + fprintf(stderr, "Warning: %s", message); + fwrite((void *)param, sizeof(char), param_len, stderr); + putc('\n', stderr); +} + +/* print out error message */ +static void +Error(char *message, char *param) +{ + fprintf(stderr, "Error: %s%s\n", message, param); +} + +/* look for a known token and return its index or 0 */ +static int +LookForToken(char *string, Token *token) +{ + for (; token->string != NULL; token++) + if (Strncasecmp(string, token->string, token->length) == 0) + return token->index; + return 0; +} + +/* parse a comma separated list string: a,b,c + for each element look for a known token, + when found store the associated index in the given index table, + when not found print out a WARNING and skip, + terminate the index table with 0, + return number of recognized tokens. + Note that no array bound verification is done! + */ +static int +ParseList(char *value, Token *tokens, int *indices, int debug) +{ + char *next; + int token; + int n = 0; + + do { + token = LookForToken(value, tokens); + next = strchr(value, ','); + + /* if unknown token print out WARNING */ + if (token == 0) { + if (next != NULL) { + /* not a NULL terminated string, so make one */ + char buf[BUFSIZ]; + int len = (next - value < BUFSIZ) ? next - value : BUFSIZ; + + strncpy(buf, value, len); + buf[len] = '\0'; + WARNING("unknown parameter value: ", buf); + } else + WARNING("unknown parameter value: ", value); + } else + indices[n++] = token; + + if (next != NULL) + value = next + 1; + } while (next); + + indices[n] = 0; + + return n; +} + +/* Parse a comma separated list of pairs name[:value] such as: A:a,B,C:c + for each element look for a known token, + when found store the associated index in the given index table and copy + the associated value, + when not found print out a WARNING and skip, + terminate the index table with 0, + return number of recognized tokens. + Note that no array bound verification is done! + */ +static int +ParseAuthList(char *value, Token *tokens, int *indices, char **values, + int debug) +{ + char *next, *ptr; + int token; + int n = 0; + + do { + token = LookForToken(value, tokens); + ptr = strchr(value, ':'); + next = strchr(((ptr != NULL) ? ptr : value), ','); + + /* if unknown token print out WARNING */ + if (token == 0) { + if (next != NULL) { + /* not a NULL terminated string, so make one */ + char buf[BUFSIZ]; + int len = (next - value < BUFSIZ) ? next - value : BUFSIZ; + + strncpy(buf, value, len); + buf[len] = '\0'; + WARNING("unknown parameter value: ", buf); + } else + WARNING("unknown parameter value: ", value); + } else { + indices[n] = token; + if (ptr != NULL) { /* there is an associated data */ + if (next != NULL) + values[n++] = strncopy(ptr + 1, next - ptr); + else + values[n++] = strcopy(ptr + 1); + } else + values[n++] = NULL; + } + + if (next != NULL) + value = next + 1; + } while (next); + + indices[n] = 0; + + return n; +} + +/* parse a boolean string value returning 0 on success, 1 otherwise */ +static int +ParseBoolean(char *strvalue, RxBool *value_ret) +{ + if (Strcasecmp(strvalue, RX_YES) == 0) { + *value_ret = RxTrue; + return 0; + } else if (Strcasecmp(strvalue, RX_NO) == 0) { + *value_ret = RxFalse; + return 0; + } + return 1; +} + +/* parse an X-UI-INPUT-METHOD parameter value */ +static int +ParseXInputMethod(char *value, + RxBool *input_method_ret, char **input_method_url_ret, + int debug) +{ + char *url; + + url = strchr(value, ';'); + if (url != NULL) { + if (strncmp(value, RX_YES, sizeof(RX_YES) - 1) == 0) { + *input_method_ret = RxTrue; + *input_method_url_ret = strcopy(url + 1); + } else if (strncmp(value, RX_YES, sizeof(RX_YES) - 1) == 0) + *input_method_ret = RxFalse; + else + WARNINGN("not a boolean value: ", value, url - value); + } else { + if (ParseBoolean(value, input_method_ret) != 0) + WARNING("not a boolean value: ", value); + } + return 0; +} + + +/* parse an RX parameter */ +static int +ParseParam(char *name, char *value, RxParams *params, int debug) +{ + if (Strcasecmp(name, RX_ACTION) == 0) { + Free(params->action); + params->action = strcopy(value); + } else if (Strcasecmp(name, RX_EMBEDDED) == 0) { + if (ParseBoolean(value, ¶ms->embedded) != 0) + WARNING("not a boolean value: ", value); + } else if (Strcasecmp(name, RX_AUTO_START) == 0) { + if (ParseBoolean(value, ¶ms->auto_start) != 0) + WARNING("not a boolean value: ", value); + } else if (Strcasecmp(name, RX_WIDTH) == 0) + params->width = atoi(value); + else if (Strcasecmp(name, RX_HEIGHT) == 0) + params->height = atoi(value); + else if (Strcasecmp(name, RX_APP_GROUP) == 0) { + Free(params->app_group); + params->app_group = strcopy(value); + } else if (Strcasecmp(name, RX_REQUIRED_SERVICES) == 0) + ParseList(value, RxServices, (int*)params->required_services, debug); + else if (Strcasecmp(name, RX_UI) == 0) + ParseList(value, RxUIs, (int*)params->ui, debug); + else if (Strcasecmp(name, RX_PRINT) == 0) + ParseList(value, RxPrints, (int*)params->print, debug); + else if (Strcasecmp(name, RX_X_UI_INPUT_METHOD) == 0) + ParseXInputMethod(value, ¶ms->x_ui_input_method, + ¶ms->x_ui_input_method_url, debug); + else if (Strcasecmp(name, RX_X_AUTH) == 0) + ParseAuthList(value, RxXAuthentications, + (int*)params->x_auth, params->x_auth_data, debug); + else if (Strcasecmp(name, RX_X_UI_AUTH) == 0) + ParseAuthList(value, RxXAuthentications, + (int*)params->x_ui_auth, params->x_ui_auth_data, debug); + else if (Strcasecmp(name, RX_X_PRINT_AUTH) == 0) + ParseAuthList(value, RxXAuthentications, + (int*)params->x_print_auth, params->x_print_auth_data, + debug); + else if (Strcasecmp(name, RX_X_UI_LBX_AUTH) == 0) + ParseAuthList(value, RxXAuthentications, + (int*)params->x_ui_lbx_auth, + params->x_ui_lbx_auth_data, debug); + else if (Strcasecmp(name, RX_X_PRINT_LBX_AUTH) == 0) + ParseAuthList(value, RxXAuthentications, + (int*)params->x_print_lbx_auth, + params->x_print_lbx_auth_data, + debug); + else if (Strcasecmp(name, RX_X_UI_LBX) == 0) { + if (ParseBoolean(value, ¶ms->x_ui_lbx) != 0) + WARNING("not a boolean value: ", value); + } else if (Strcasecmp(name, RX_X_PRINT_LBX) == 0) { + if (ParseBoolean(value, ¶ms->x_print_lbx) != 0) + WARNING("not a boolean value: ", value); + } else /* unknown parameter */ + WARNING("unknown parameter name: ", name); + return 0; +} + +/* parse a list of RX arguments storing result in the given RxParams struct, + * since this function might be called several times using the same structure, + * it is assumed that the structure is correctly initialized. + */ +int +RxParseParams(char *argn[], char *argv[], int argc, RxParams *params, + int debug) +{ + int i; + int version, revision; + + if (argc == 0) + return 0; + + /* the first param should be the Version number */ + if (Strcasecmp(argn[0], RX_VERSION) == 0) { + if (sscanf(argv[0], "%d.%d", &version, &revision) == 2) { + params->version = version; + params->revision = revision; + } else { + Error("invalid version identifier: ", argv[0]); + return 1; + } + argn++; + argv++; + i = 1; + } else { + /* no version identifier assume 1.0 */ + params->version = RX_DEFAULT_VERSION; + params->revision = RX_DEFAULT_REVISION; + i = 0; + } + + /* parse given params */ + for (; i < argc; i++, argn++, argv++) + if (ParseParam(*argn, *argv, params, debug)) + return 1; + + return 0; +} + +/* Initialize RxParams structure */ +void +RxInitializeParams(RxParams *params) +{ + memset(params, 0, sizeof(RxParams)); + params->embedded = RxUndef; + params->auto_start = RxUndef; + params->width = RxUndef; + params->height = RxUndef; + /* init X params */ + params->x_ui_input_method = RxUndef; + params->x_ui_input_method_url = NULL; + params->x_ui_lbx = RxUndef; + params->x_print_lbx = RxUndef; +} + +void +FreeAuthListData(char **list) +{ + while (*list != NULL) + Free(*list++); +} + +/* Free data stored in RxParams structure */ +int +RxFreeParams(RxParams *params) +{ + Free(params->action); + Free(params->app_group); + + Free(params->x_ui_input_method_url); + FreeAuthListData(params->x_auth_data); + FreeAuthListData(params->x_ui_auth_data); + FreeAuthListData(params->x_print_auth_data); + FreeAuthListData(params->x_ui_lbx_auth_data); + FreeAuthListData(params->x_print_lbx_auth_data); + + return 0; +} + +/* Free data stored in RxReturnParams structure */ +int +RxFreeReturnParams(RxReturnParams *params) +{ + /* action is only a reference - do not free */ + Free(params->ui); + Free(params->print); + + Free(params->x_ui_lbx_auth); + Free(params->x_print_lbx_auth); + return 0; +} diff --git a/rx/PRead.c b/rx/PRead.c new file mode 100644 index 0000000..ce09217 --- /dev/null +++ b/rx/PRead.c @@ -0,0 +1,274 @@ +/* $Xorg: PRead.c,v 1.4 2001/02/09 02:05:58 xorgcvs Exp $ */ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- +ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABIL- +ITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization from +The Open Group. + +*/ + +#include "RxI.h" +#include <ctype.h> + + +/* Not null terminated string */ +typedef struct { + char *ptr; /* beginning of string */ + int length; /* length of string */ +} NString; + + +#ifdef NETSCAPE_PLUGIN +/* utility function for netscape plugin where realloc is not available + * it's too bad we need both the old size and the new one... + */ +void * +_RxRealloc(void *p, size_t olds, size_t s) +{ + void *np = Malloc(s); + if (np) { + memcpy(np, p, olds); + Free(p); + } + return np; +} +#endif + + +/* get next word and return trailing stream */ +static char * +NextWord(char *stream, char *limit, NString *word) +{ + /* skip leading whitespace */ + while (isspace((int) *stream) && *stream && stream != limit) + stream++; + word->ptr = stream; + /* go to first whitespace */ + while (!isspace((int) *stream) && *stream && stream != limit) + stream++; + word->length = stream - word->ptr; + return stream; +} + + +/* get next chunk of text, with possible quoted sections, + and return trailing stream */ +static char * +NextChunk(char *stream, char *limit, NString *word) +{ + /* skip leading whitespace */ + while (isspace((int) *stream) && *stream && stream != limit) + stream++; + word->ptr = stream; + + /* go to first whitespace or end of string */ + while (!isspace((int) *stream) && *stream && stream != limit) { + if (*stream == '"' || *stream == '\'') { + char quote = *stream; + do + stream++; + while (*stream != quote && *stream && stream != limit); + if (*stream && stream != limit) + stream++; + break; + } else + stream++; + } + word->length = stream - word->ptr; + return stream; +} + + +/* get next SGML element "< ... >" and return next trailing stream */ +static char * +NextElement(char *stream, NString *element) +{ + + /* look for opening bracket */ + while (*stream != '<' && *stream) + stream++; + + element->ptr = stream; + + /* look for closing bracket */ + while (*stream != '>' && *stream) + stream++; + + element->length = stream - element->ptr; + + return *stream ? stream + 1 : stream; +} + + +/* seek next PARAM element content: "<PARAM ... >" (delimiters excluded) + and return next trailing stream */ +static char * +NextParam(char *stream, NString *param) +{ + NString element, word; + + do { + stream = NextElement(stream, &element); + + if (element.length) + /* get element name */ + (void) NextWord(element.ptr + 1, element.ptr + element.length - 1, + &word); + else { + /* no more elements stop here */ + param->ptr = 0; + param->length = 0; + + return stream; + } + + /* check if it's a PARAM element */ + } while(word.length != 5 && memcmp("PARAM", word.ptr, 5) != 0 && *stream); + + param->ptr = word.ptr + word.length; + param->length = element.length - word.length - 1; /* delimiters excluded */ + + return stream; +} + + +/* return literal value as a Null terminated string, + removing possible quotes and extra whitespace */ +static char * +GetLiteralValue(NString *literal) +{ + char *ptr, *limit, *value, *vptr; + char quote; + int skip; + + value = vptr = (char *)Malloc(literal->length + 1); + if (!value) + return 0; + + ptr = literal->ptr; + limit = ptr + literal->length; + quote = (*ptr == '"' || *ptr == '\'') ? *ptr++ : '\0'; + skip = 0; + do + if (isspace((int) *ptr)) { + if (!skip) { + *vptr++ = ' '; + skip = 1; + } + ptr++; + } else { + skip = 0; + *vptr++ = *ptr++; + } + while (*ptr != quote && ptr != limit); + *vptr = '\0'; + + return value; +} + + +/* parse PARAM tag content: " NAME=... VALUE=... " */ +static int +ParseParam(NString *param, char **name_ret, char **value_ret) +{ + NString word, name, value; + char *stream = param->ptr; + char *limit = param->ptr + param->length; + + /* look for the name part */ + do + stream = NextChunk(stream, limit, &word); + while (word.length < 5 && memcmp("NAME=", word.ptr, 5 != 0) && *stream); + if (stream == limit) + return 1; + name.ptr = word.ptr + 5; + name.length = word.length - 5; + *name_ret = GetLiteralValue(&name); + + /* look for the value part */ + do + stream = NextChunk(stream, limit, &word); + while (word.length < 6 && memcmp("VALUE=", word.ptr, 6) != 0 && *stream); + value.ptr = word.ptr + 6; + value.length = word.length - 6; + *value_ret = GetLiteralValue(&value); + + return 0; +} + +/* how much we make a params array bigger every time we reach the limit */ +#define PARAMSINC 10 + +/* read an RX document stream and augment the given list of arguments */ +int +RxReadParams(char *stream, + char **argn_ret[], char **argv_ret[], int *argc_ret) +{ + char **argv, **argn; + int argc, n; + NString param; + char *name, *value; + int status; + + status = 0; + argc = n = 0; + argn = argv = NULL; + if (stream != NULL) { + do { + stream = NextParam(stream, ¶m); + if (param.length != 0 && ParseParam(¶m, &name, &value) == 0) { + argc++; + if (n == 0) { /* alloc first block */ + n = PARAMSINC; + argn = (char **)Malloc(sizeof(char *) * n); + if (!argn) + return 1; + argv = (char **)Malloc(sizeof(char *) * n); + if (!argv) { + Free(argn); + return 1; + } + } + if (argc % PARAMSINC == 0) { /* we need to add a block */ + n += PARAMSINC; + argn = (char **) + Realloc(argn, sizeof(char *) * argc, sizeof(char *) * n); + argv = (char **) + Realloc(argv, sizeof(char *) * argc, sizeof(char *) * n); + if (!argn || !argv) { + argc--; + status = 1; + break; + } + } + argn[argc - 1] = name; + argv[argc - 1] = value; + } + } while (*stream); + } + *argn_ret = argn; + *argv_ret = argv; + *argc_ret = argc; + + return status; +} diff --git a/rx/Prefs.c b/rx/Prefs.c new file mode 100644 index 0000000..428cf62 --- /dev/null +++ b/rx/Prefs.c @@ -0,0 +1,273 @@ +/* $Xorg: Prefs.c,v 1.5 2001/02/09 02:05:58 xorgcvs Exp $ */ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- +ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABIL- +ITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization from +The Open Group. + +*/ + +#include "Prefs.h" +#include <ctype.h> +#include "RxI.h" /* for Malloc & Free */ +#include <X11/StringDefs.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <netdb.h> + +typedef struct { + Boolean has_fwp; + String internal_webservers; /* servers for which we won't use a fwp */ + String trusted_webservers; + String fast_webservers; /* servers for which we won't use lbx */ +} Prefs; + +#define offset(field) XtOffsetOf(Prefs, field) + +static XtResource resources[] = { + { "XrxHasFirewallProxy", "xrxHasFirewallProxy", + XtRBoolean, sizeof(Boolean), + offset(has_fwp), XtRImmediate, (caddr_t) False }, + { "XrxInternalWebServers", "xrxInternalWebServers", + XtRString, sizeof(String), + offset(internal_webservers), XtRImmediate, (caddr_t) NULL }, + { "XrxTrustedWebServers", "xrxTrustedWebServers", + XtRString, sizeof(String), + offset(trusted_webservers), XtRImmediate, (caddr_t) NULL }, + { "XrxFastWebServers", "xrxFastWebServers", XtRString, sizeof(String), + offset(fast_webservers), XtRImmediate, (caddr_t) NULL } +}; + + +/* + * Return the next available element in a list of AddressFilters, making the + * list bigger when necessary. + */ +/* how much bigger we make the list every time we reach the limit */ +#define SIZEINC 8 + +static AddressFilter * +NextAFListElem(AddressFilter **list, int *count) +{ + AddressFilter *l; + int n; + + l = *list; + n = *count; + + /* first make sure the list is big enough */ + if (n == 0) { + l = (AddressFilter *)Malloc(sizeof(AddressFilter) * SIZEINC); + if (l == NULL) + return NULL; + *list = l; + } else if (n % SIZEINC == 0) { /* we need to enlarge the list */ + l = (AddressFilter *)Realloc(l, sizeof(AddressFilter) * n, + sizeof(AddressFilter) * (n + SIZEINC)); + if (l == NULL) + return NULL; + *list = l; + } + /* then just return the first available element */ + *count = n + 1; + return (*list) + n; +} + +/* + * find the end of next element of a comma separated string, + * returning the pointer to the trailing string or NULL if there is none + */ +static char * +NextListElem(char *ptr, char **end_ret) +{ + char *end = strchr(ptr, ','); + if (end != NULL) { + /* skip comma and possible following space */ + ptr = end + 1; + while (*ptr && isspace(*ptr)) + ptr++; + } else { + end = ptr + strlen(ptr); + ptr = NULL; + } + *end_ret = end; + return ptr; +} + + +/* + * retreive the two parts of mask/value from the given string, specified by + * its beginning and end, and copy them into the given buffers + */ +static int +ParseListElem(char *bos, char *eos, + char *buf1, int len1, char *buf2, int len2) +{ + char *sep = strchr(bos, '/'); + if (sep != NULL) { + int len = sep - bos; + if (len < len1) { + strncpy(buf1, bos, len); + buf1[len] = '\0'; + /* now deal with the second part */ + bos = sep + 1; + len = eos - bos; + if (len < len2) { + strncpy(buf2, bos, len); + buf2[len] = '\0'; + return 1; + } + } + } + return 0; /* failed */ +} + + +/* + * parse a comma separated list of AddressFilters: mask/value + */ +static void +ParseList(String string, AddressFilter **list_return, int *count_return) +{ + char *ptr, *boe, *eoe; +#define BUFLEN 32 + char mask[BUFLEN], value[BUFLEN]; + AddressFilter *elem; + + *list_return = NULL; + *count_return = 0; + if (string == NULL || *string == '\0') + return; + + ptr = string; + do { + boe = ptr; + ptr = NextListElem(ptr, &eoe); + if (boe && eoe) { + elem = NULL; + if (ParseListElem(boe, eoe, mask, BUFLEN, value, BUFLEN) != 0) { + unsigned long imask = inet_addr(mask); + unsigned long ivalue = inet_addr(value); + if (((long) imask) != -1 && ((long) ivalue) != -1) { + elem = NextAFListElem(list_return, count_return); + elem->mask = imask; + elem->value = ivalue; + } + } + if (elem == NULL) { + /* copy whathever we can in one of our bufs to print it out */ +#define MYMIN(a,b) ((a) > (b) ? (b) : (a)) + int len = MYMIN(eoe - boe, BUFLEN - 1); + strncpy(mask, boe, len); + mask[len] = '\0'; + fprintf(stderr, + "Could not convert \"%s\" into a pair mask/value\n", + mask); + } + } + } while (ptr && *ptr); +} + +void +GetPreferences(Widget widget, Preferences *preferences) +{ + Prefs prefs; + XtGetApplicationResources(widget, &prefs, + resources, XtNumber(resources), + NULL, 0); + + preferences->has_fwp = prefs.has_fwp; + ParseList(prefs.internal_webservers, + &preferences->internal_webservers, + &preferences->internal_webservers_count); + ParseList(prefs.trusted_webservers, + &preferences->trusted_webservers, + &preferences->trusted_webservers_count); + ParseList(prefs.fast_webservers, + &preferences->fast_webservers, + &preferences->fast_webservers_count); +} + +void +FreePreferences(Preferences *preferences) +{ + if (preferences->internal_webservers) + Free(preferences->internal_webservers); + if (preferences->trusted_webservers) + Free(preferences->trusted_webservers); + if (preferences->fast_webservers) + Free(preferences->fast_webservers); +} + +static Boolean +FilterHost(char *hostname, AddressFilter *filters, int count) +{ + struct hostent *host; + unsigned int addr; + int i; + + if (count == 0 || filters == NULL) + return False; + + /* first find the host address number */ + host = gethostbyname(hostname); + if (host == NULL || host->h_addrtype != AF_INET) + /* host or address type unknown */ + return False; + + addr = ((struct in_addr*) host->h_addr_list[0])->s_addr; + + for (i = 0; i < count; i++, filters++) + if ((addr & filters->mask) == (filters->value & filters->mask)) + return True; + + return False; +} + +void +ComputePreferences(Preferences *prefs, char *webserver, + Boolean *trusted_ret, Boolean *use_fwp_ret, Boolean *use_lbx_ret) +{ + if (webserver != NULL) { + if (prefs->has_fwp == True) { + *use_fwp_ret = + FilterHost(webserver, + prefs->internal_webservers, + prefs->internal_webservers_count) ? False : True; + } else + *use_fwp_ret = False; + + *trusted_ret = FilterHost(webserver, + prefs->trusted_webservers, + prefs->trusted_webservers_count); + *use_lbx_ret = FilterHost(webserver, + prefs->fast_webservers, + prefs->fast_webservers_count) ? False : True; + } else { + /* can't do much without webserver name */ + *use_fwp_ret = prefs->has_fwp; + *trusted_ret = False; + *use_lbx_ret = True; + } +} diff --git a/rx/Prefs.h b/rx/Prefs.h new file mode 100644 index 0000000..6c7462d --- /dev/null +++ b/rx/Prefs.h @@ -0,0 +1,56 @@ +/* $Xorg: Prefs.h,v 1.4 2001/02/09 02:05:58 xorgcvs Exp $ */ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- +ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABIL- +ITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization from +The Open Group. + +*/ + +#ifndef _Prefs_h +#define _Prefs_h + +#include <X11/Intrinsic.h> + +typedef struct { + unsigned int mask; + unsigned int value; +} AddressFilter; + +typedef struct { + Boolean has_fwp; + AddressFilter *internal_webservers; + AddressFilter *trusted_webservers; + AddressFilter *fast_webservers; + int internal_webservers_count; + int trusted_webservers_count; + int fast_webservers_count; +} Preferences; + + +extern void GetPreferences(Widget widget, Preferences *preferences); +extern void FreePreferences(Preferences *preferences); +extern void ComputePreferences(Preferences *preferences, char *webserver, + Boolean *trusted_ret, Boolean *use_fwp_ret, Boolean *use_lbx_ret); + +#endif /* _Prefs_h */ @@ -0,0 +1,129 @@ +/* $Xorg: Rx.h,v 1.4 2001/02/09 02:05:58 xorgcvs Exp $ */ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- +ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABIL- +ITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization from +The Open Group. + +*/ + +#ifndef _Rx_h +#define _Rx_h + +/* a fancy Boolean type */ +typedef enum { RxUndef=-1, RxFalse=0, RxTrue=1 } RxBool; + + +/* various enums, starting from index 1, + with a dummy last value allowing to easily get the size, + new values must be inserted before the last one */ +typedef enum { UI=1, Print, LASTService } RxService; +typedef enum { XUI=1, LASTUIProtocol } RxUIProtocol; +typedef enum { XPrint=1, LASTPrintProtocol } RxPrintProtocol; + +typedef enum { MitMagicCookie1=1, LASTXAuthentication } RxXAuthentication; + +/* for each of the above enum define the corresponding max array size, + counting 1 for NULL terminating */ +#define MAX_SERVICES LASTService +#define MAX_UIPROTOS LASTUIProtocol +#define MAX_PRINTPROTOS LASTPrintProtocol + +#define MAX_XAUTHENTICATIONS LASTXAuthentication + +/* RxParams structure, + designed so it can handle whatever parameter is defined in an RX document */ +typedef struct { + short version; /* document version number */ + short revision; /* document revision number */ + + char *action; /* URL */ + RxBool embedded; + RxBool auto_start; + int width; + int height; + char *app_group; /* application group name */ + + /* NULL terminated "lists" */ + RxService required_services[MAX_SERVICES]; + RxUIProtocol ui[MAX_UIPROTOS]; + RxPrintProtocol print[MAX_PRINTPROTOS]; + + /* private params */ + RxBool x_ui_input_method; + char *x_ui_input_method_url; + + RxBool x_ui_lbx; + RxBool x_print_lbx; + + RxXAuthentication x_auth[MAX_XAUTHENTICATIONS]; + char *x_auth_data[MAX_XAUTHENTICATIONS]; + + RxXAuthentication x_ui_auth[MAX_XAUTHENTICATIONS]; + char *x_ui_auth_data[MAX_XAUTHENTICATIONS]; + + RxXAuthentication x_print_auth[MAX_XAUTHENTICATIONS]; + char *x_print_auth_data[MAX_XAUTHENTICATIONS]; + + RxXAuthentication x_ui_lbx_auth[MAX_XAUTHENTICATIONS]; + char *x_ui_lbx_auth_data[MAX_XAUTHENTICATIONS]; + + RxXAuthentication x_print_lbx_auth[MAX_XAUTHENTICATIONS]; + char *x_print_lbx_auth_data[MAX_XAUTHENTICATIONS]; + +} RxParams; + + +typedef struct { + RxBool embedded; + int width; + int height; + char *action; + char *ui; /* URL */ + char *print; /* URL */ + + /* private params */ + RxBool x_ui_lbx; + char *x_ui_lbx_auth; + RxBool x_print_lbx; + char *x_print_lbx_auth; +} RxReturnParams; + + +/* functions */ +extern int +RxReadParams(char *stream, + char **argn_ret[], char **argv_ret[], int *argc_ret); + +extern void RxInitializeParams(RxParams *params); + +extern int +RxParseParams(char *argn[], char *argv[], int argc, RxParams *params, + int debug); /* (1/0) */ + +extern char *RxBuildRequest(RxReturnParams *params); + +extern int RxFreeParams(RxParams *params); +extern int RxFreeReturnParams(RxReturnParams *params); + +#endif /* _Rx_h */ diff --git a/rx/RxI.h b/rx/RxI.h new file mode 100644 index 0000000..d652c14 --- /dev/null +++ b/rx/RxI.h @@ -0,0 +1,95 @@ +/* $Xorg: RxI.h,v 1.4 2001/02/09 02:05:58 xorgcvs Exp $ */ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- +ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABIL- +ITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization from +The Open Group. + +*/ + +#ifndef _RxI_h +#define _RxI_h + +#include "Rx.h" +#include <X11/Xos.h> /* for strcmp() etc... */ +#include <stdlib.h> +#include <stdio.h> + + +/* "wrappers" to std functions */ +#ifdef NETSCAPE_PLUGIN +#include "npapi.h" +#define Malloc(s) NPN_MemAlloc(s) +#define Realloc(p, olds, s) _RxRealloc(p, olds, s) +#define Free(p) { if (p) NPN_MemFree(p); } +extern void * _RxRealloc(void *p, size_t olds, size_t s); +#else +#define Malloc(s) malloc(s) +#define Realloc(p, olds, s) realloc(p, s) +#define Free(p) { if (p) free(p); } +#endif + +#ifdef NEED_STRCASECMP +#define Strcasecmp(s1,s2) _RxStrcasecmp(s1,s2) +#define Strncasecmp(s1,s2,n) _RxStrncasecmp(s1,s2,n) +extern int _RxStrcasecmp(const char *, const char *); +extern int _RxStrncasecmp(const char *, const char *, size_t); +#else +#define Strcasecmp(s1,s2) strcasecmp(s1,s2) +#define Strncasecmp(s1,s2,n) strncasecmp(s1,s2,n) +#endif + +/* recognized parameter names */ +#define RX_VERSION "VERSION" +#define RX_ACTION "ACTION" +#define RX_EMBEDDED "EMBEDDED" +#define RX_AUTO_START "AUTO-START" +#define RX_WIDTH "WIDTH" +#define RX_HEIGHT "HEIGHT" +#define RX_APP_GROUP "APP-GROUP" +#define RX_REQUIRED_SERVICES "REQUIRED-SERVICES" +#define RX_UI "UI" +#define RX_PRINT "PRINT" + +/* X protocol private parameter names */ +#define RX_X_UI_INPUT_METHOD "X-UI-INPUT-METHOD" +#define RX_X_UI_LBX "X-UI-LBX" +#define RX_X_PRINT_LBX "X-PRINT-LBX" +#define RX_X_AUTH "X-AUTH" +#define RX_X_UI_AUTH "X-UI-AUTH" +#define RX_X_PRINT_AUTH "X-PRINT-AUTH" +#define RX_X_UI_LBX_AUTH "X-UI-LBX-AUTH" +#define RX_X_PRINT_LBX_AUTH "X-PRINT-LBX-AUTH" + + +/* recognized parameter values */ +#define RX_YES "YES" +#define RX_NO "NO" + + +/* HTTP GET request delimiters */ +#define RX_QUERY_DELIMITER '?' +#define RX_PARAM_DELIMITER ';' + + +#endif /* _RxI_h */ diff --git a/rx/XAuth.c b/rx/XAuth.c new file mode 100644 index 0000000..89e904b --- /dev/null +++ b/rx/XAuth.c @@ -0,0 +1,163 @@ +/* $Xorg: XAuth.c,v 1.4 2001/02/09 02:05:58 xorgcvs Exp $ */ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- +ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABIL- +ITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization from +The Open Group. + +*/ + +#include "RxI.h" +#ifdef XFUNCPROTO_NOT_AVAILABLE +#include <X11/Xfuncproto.h> +#endif +#include <X11/Xlib.h> +#include <X11/extensions/security.h> +#ifndef XFUNCPROTO_NOT_AVAILABLE +#include <X11/Xauth.h> +#endif + +static void +printhexdigit(char *ptr, unsigned int d) +{ + if (d > 9) + d += 'A' - 10; + else + d += '0'; + + sprintf(ptr, "%c", d); +} + +static void +printhex(char *buffer, unsigned char *data, int len) +{ + char *ptr; + unsigned int c; + + ptr = buffer; + while (len--) { + c = *data++; + printhexdigit(ptr++, c >> 4); + printhexdigit(ptr++, c & 0xf); + } + *ptr = '\0'; +} + +static int +MakeAuthString(char *auth_name, char *data, int len, char **auth_ret) +{ + char *auth, *ptr; + int name_len; + + name_len = strlen(auth_name); + /* we'll have the name + ':' + 2 characters per byte + '\0' */ + auth = (char *) Malloc(name_len + 1 + 2*len + 1); + if (auth == NULL) + return 1; + + strcpy(auth, auth_name); + ptr = auth + name_len; + *ptr++ = ':'; + printhex(ptr, (unsigned char *)data, len); + + *auth_ret = auth; + + return 0; +} + +int +GetXAuth(Display *dpy, RxXAuthentication auth_name, char *auth_data, + Bool trusted, XID group, unsigned int timeout, Bool want_revoke_event, + char **auth_string_ret, XSecurityAuthorization *auth_id_ret, + int *event_type_base_ret) +{ + unsigned int trust = + trusted ? XSecurityClientTrusted : XSecurityClientUntrusted; + int dum, major_version, minor_version; + int status; + Xauth *auth_in, *auth_return; + XSecurityAuthorizationAttributes xsa; + unsigned long xsamask; + + auth_return = NULL; + if (!XQueryExtension(dpy, "SECURITY", &dum, event_type_base_ret, &dum)) { + fprintf(stderr, "Warning: Cannot setup authorization as requested, \ +SECURITY extension not supported\n"); + return 1; + } + + if (auth_name == MitMagicCookie1) { + auth_in = XSecurityAllocXauth(); + auth_in->name = "MIT-MAGIC-COOKIE-1"; + } else { + fprintf(stderr, + "Error: Unknown authentication protocol name requested\n"); + return 1; + } + /* auth_data is not used for now */ + + status = XSecurityQueryExtension(dpy, &major_version, &minor_version); + if (status == 0) { + fprintf(stderr, "Error: Failed to setup authorization\n"); + goto error; + } + + auth_in->name_length = strlen(auth_in->name); + if (auth_in->data) + auth_in->data_length = strlen(auth_in->data); + + xsa.timeout = timeout; + xsa.trust_level = trust; + xsa.group = group; + xsamask = XSecurityTimeout | XSecurityTrustLevel | XSecurityGroup; + if (want_revoke_event == True) { + xsa.event_mask = XSecurityAuthorizationRevokedMask; + xsamask |= XSecurityEventMask; + } + auth_return = XSecurityGenerateAuthorization(dpy, auth_in, xsamask, + &xsa, auth_id_ret); + if (auth_return == 0) { + fprintf(stderr, + "Error: Failed to setup authorization, cannot create key\n"); + goto error; + } + status = MakeAuthString(auth_in->name, + auth_return->data, auth_return->data_length, + auth_string_ret); + if (status != 0) { + fprintf(stderr, + "Error: Failed to setup authorization, not enough memory\n"); + goto error; + } + XSecurityFreeXauth(auth_in); + XSecurityFreeXauth(auth_return); + + return 0; + +error: + XSecurityFreeXauth(auth_in); + if (auth_return != NULL) + XSecurityFreeXauth(auth_return); + + return 1; +} diff --git a/rx/XAuth.h b/rx/XAuth.h new file mode 100644 index 0000000..f7c6624 --- /dev/null +++ b/rx/XAuth.h @@ -0,0 +1,39 @@ +/* $Xorg: XAuth.h,v 1.4 2001/02/09 02:05:58 xorgcvs Exp $ */ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- +ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABIL- +ITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization from +The Open Group. + +*/ + +#ifndef _XAuth_h +#define _XAuth_h + +extern int +GetXAuth(Display *dpy, RxXAuthentication auth_name, char *auth_data, + Bool trusted, XID group, unsigned int timeout, Bool want_revoke_event, + char **auth_string_ret, XSecurityAuthorization *auth_id_ret, + int *event_type_base_ret); + +#endif /* _XAuth_h */ diff --git a/rx/XDpyName.c b/rx/XDpyName.c new file mode 100644 index 0000000..0a5c006 --- /dev/null +++ b/rx/XDpyName.c @@ -0,0 +1,513 @@ +/* $Xorg: XDpyName.c,v 1.5 2001/02/09 02:05:58 xorgcvs Exp $ */ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- +ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABIL- +ITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization from +The Open Group. + +*/ + +#ifdef XP_UNIX +#include "RxPlugin.h" /* for PluginGlobal */ +#endif +#include "RxI.h" + +#include <X11/Xlib.h> +#include <X11/Xos.h> + +#include <stdlib.h> +#include <stdio.h> + +#include <X11/Xfuncs.h> +#include <X11/Xmd.h> +#include <X11/ICE/ICElib.h> +#include <X11/ICE/ICEmsg.h> +#include <X11/ICE/ICEproto.h> +#include <X11/PM/PM.h> +#include <X11/PM/PMproto.h> + +#define DEFAULT_PROXY_MANAGER ":6500" + +/* + * Pad to a 64 bit boundary + */ + +#define PAD64(_bytes) ((8 - ((unsigned int) (_bytes) % 8)) % 8) + +#define PADDED_BYTES64(_bytes) (_bytes + PAD64 (_bytes)) + + +/* + * Number of 8 byte units in _bytes. + */ + +#define WORD64COUNT(_bytes) (((unsigned int) ((_bytes) + 7)) >> 3) + + +/* + * Compute the number of bytes for a STRING representation + */ + +#define STRING_BYTES(_str) (2 + (_str ? strlen (_str) : 0) + \ + PAD64 (2 + (_str ? strlen (_str) : 0))) + + + +#define SKIP_STRING(_pBuf, _swap) \ +{ \ + CARD16 _len; \ + EXTRACT_CARD16 (_pBuf, _swap, _len); \ + _pBuf += _len; \ + if (PAD64 (2 + _len)) \ + _pBuf += PAD64 (2 + _len); \ +} + +/* + * STORE macros + */ + +#define STORE_CARD16(_pBuf, _val) \ +{ \ + *((CARD16 *) _pBuf) = _val; \ + _pBuf += 2; \ +} + +#define STORE_STRING(_pBuf, _string) \ +{ \ + int _len = _string ? strlen (_string) : 0; \ + STORE_CARD16 (_pBuf, _len); \ + if (_len) { \ + memcpy (_pBuf, _string, _len); \ + _pBuf += _len; \ + } \ + if (PAD64 (2 + _len)) \ + _pBuf += PAD64 (2 + _len); \ +} + + +/* + * EXTRACT macros + */ + +#define EXTRACT_CARD16(_pBuf, _swap, _val) \ +{ \ + _val = *((CARD16 *) _pBuf); \ + _pBuf += 2; \ + if (_swap) \ + _val = lswaps (_val); \ +} + +#define EXTRACT_STRING(_pBuf, _swap, _string) \ +{ \ + CARD16 _len; \ + EXTRACT_CARD16 (_pBuf, _swap, _len); \ + _string = (char *) malloc (_len + 1); \ + memcpy (_string, _pBuf, _len); \ + _string[_len] = '\0'; \ + _pBuf += _len; \ + if (PAD64 (2 + _len)) \ + _pBuf += PAD64 (2 + _len); \ +} + + +/* + * Byte swapping + */ + +/* byte swap a long literal */ +#define lswapl(_val) ((((_val) & 0xff) << 24) |\ + (((_val) & 0xff00) << 8) |\ + (((_val) & 0xff0000) >> 8) |\ + (((_val) >> 24) & 0xff)) + +/* byte swap a short literal */ +#define lswaps(_val) ((((_val) & 0xff) << 8) | (((_val) >> 8) & 0xff)) + + +#define CHECK_AT_LEAST_SIZE(_iceConn, _majorOp, _minorOp, _expected_len, _actual_len, _severity) \ + if ((((_actual_len) - SIZEOF (iceMsg)) >> 3) > _expected_len) \ + { \ + _IceErrorBadLength (_iceConn, _majorOp, _minorOp, _severity); \ + return; \ + } + + +#define CHECK_COMPLETE_SIZE(_iceConn, _majorOp, _minorOp, _expected_len, _actual_len, _pStart, _severity) \ + if (((PADDED_BYTES64((_actual_len)) - SIZEOF (iceMsg)) >> 3) \ + != _expected_len) \ + { \ + _IceErrorBadLength (_iceConn, _majorOp, _minorOp, _severity); \ + IceDisposeCompleteMessage (iceConn, _pStart); \ + return; \ + } + +static void PMprocessMessages (); + +#ifdef XP_UNIX +#define PMOPCODE RxGlobal.pm_opcode +#define ICECONN RxGlobal.ice_conn +#else +static int pm_opcode; +#define PMOPCODE pm_opcode +#define ICECONN ice_conn +#endif + +static int PMversionCount = 1; +static IcePoVersionRec PMversions[] = + {{PM_MAJOR_VERSION, PM_MINOR_VERSION, PMprocessMessages}}; + +typedef struct { + int status; + char *addr; + char *error; +} GetProxyAddrReply; + +static int findproxy (proxyname, manager, server, name) + char* proxyname; + char* manager; + char* server; + char* name; +{ +#ifndef XP_UNIX + IceConn ice_conn; +#endif + IceProtocolSetupStatus setupstat; + char *vendor = NULL; + char *release = NULL; + pmGetProxyAddrMsg *pMsg; + char *pData; + int len; + IceReplyWaitInfo replyWait; + GetProxyAddrReply reply; + int majorVersion, minorVersion; + Bool gotReply, ioErrorOccured; + char errorString[255]; + + /* + * Register support for PROXY_MANAGEMENT. + */ + + if (PMOPCODE == 0) { + if ((PMOPCODE = IceRegisterForProtocolSetup ( + PM_PROTOCOL_NAME, + "XC", "1.0", + PMversionCount, PMversions, + 0, /* authcount */ + NULL, /* authnames */ + NULL, /* authprocs */ + NULL /* IceIOErrorProc */ )) < 0) { + fprintf (stderr, + "Could not register PROXY_MANAGEMENT protocol with ICE\n"); + return 0; + } + + if ((ICECONN = IceOpenConnection ( + manager, NULL, 0, 0, 256, errorString)) == NULL) { + fprintf (stderr, + "Could not open ICE connection to proxy manager\n (%s)\n", + errorString); + return 0; + } + + setupstat = IceProtocolSetup (ICECONN, PMOPCODE, NULL, + False /* mustAuthenticate */, + &majorVersion, &minorVersion, + &vendor, &release, 256, errorString); + + if (setupstat != IceProtocolSetupSuccess) { + IceCloseConnection (ICECONN); + fprintf (stderr, + "Could not initialize proxy management protocol\n (%s)\n", + errorString); + fprintf (stderr, "%d\n", setupstat); + return 0; + } + } + + /* + * Now send the GetProxyAddr request. + */ + + len = STRING_BYTES (name) + STRING_BYTES (server) + + STRING_BYTES ("") + STRING_BYTES (""); + + IceGetHeaderExtra (ICECONN, PMOPCODE, PM_GetProxyAddr, + SIZEOF (pmGetProxyAddrMsg), WORD64COUNT (len), + pmGetProxyAddrMsg, pMsg, pData); + + pMsg->authLen = 0; + + STORE_STRING (pData, name); + STORE_STRING (pData, server); + STORE_STRING (pData, ""); /* host address, if there was any */ + STORE_STRING (pData, ""); /* start options, if there were any */ + + IceFlush (ICECONN); + + replyWait.sequence_of_request = IceLastSentSequenceNumber (ICECONN); + replyWait.major_opcode_of_request = PMOPCODE; + replyWait.minor_opcode_of_request = PM_GetProxyAddr; + replyWait.reply = (IcePointer) &reply; + + gotReply = False; + ioErrorOccured = False; + + while (!gotReply && !ioErrorOccured) { + ioErrorOccured = (IceProcessMessages ( + ICECONN, &replyWait, &gotReply) == IceProcessMessagesIOError); + + if (ioErrorOccured) { + fprintf (stderr, "IO error occured\n"); + IceCloseConnection (ICECONN); + return 0; + } else if (gotReply) { + if (reply.status == PM_Success) { + strcpy (proxyname, reply.addr); + } else { + fprintf (stderr, "Error from proxy manager: %s\n", + reply.error); + return 0; + } + } + } + return 1; +} + + + +static void +PMprocessMessages (iceConn, clientData, opcode, + length, swap, replyWait, replyReadyRet) + +IceConn iceConn; +IcePointer clientData; +int opcode; +unsigned long length; +Bool swap; +IceReplyWaitInfo *replyWait; +Bool *replyReadyRet; + +{ + if (replyWait) + *replyReadyRet = False; + + switch (opcode) { + case PM_GetProxyAddrReply: + + if (!replyWait || + replyWait->minor_opcode_of_request != PM_GetProxyAddr) { + _IceReadSkip (iceConn, length << 3); + + _IceErrorBadState (iceConn, PMOPCODE, + PM_GetProxyAddrReply, IceFatalToProtocol); + } else { + pmGetProxyAddrReplyMsg *pMsg; + char *pData, *pStart; + GetProxyAddrReply *reply = + (GetProxyAddrReply *) (replyWait->reply); + + CHECK_AT_LEAST_SIZE (iceConn, PMOPCODE, opcode, + length, SIZEOF (pmGetProxyAddrReplyMsg), IceFatalToProtocol); + + IceReadCompleteMessage (iceConn, SIZEOF (pmGetProxyAddrReplyMsg), + pmGetProxyAddrReplyMsg, pMsg, pStart); + + if (!IceValidIO (iceConn)) { + IceDisposeCompleteMessage (iceConn, pStart); + return; + } + + pData = pStart; + + SKIP_STRING (pData, swap); /* proxy-address */ + SKIP_STRING (pData, swap); /* failure-reason */ + + CHECK_COMPLETE_SIZE (iceConn, PMOPCODE, opcode, + length, pData - pStart + SIZEOF (pmGetProxyAddrReplyMsg), + pStart, IceFatalToProtocol); + + pData = pStart; + + EXTRACT_STRING (pData, swap, reply->addr); + EXTRACT_STRING (pData, swap, reply->error); + + reply->status = pMsg->status; + *replyReadyRet = True; + + IceDisposeCompleteMessage (iceConn, pStart); + } + break; + + default: + _IceErrorBadMinor (iceConn, PMOPCODE, opcode, IceCanContinue); + _IceReadSkip (iceConn, length << 3); + break; + } +} + + + +/* This function returns the X Print Display name and the printer name. + * Both are copies which the caller is responsible to free. + */ +char * +GetXPrintDisplayName(char **printer_return) +{ + char *display_name, *pdpy_name; + char *ptr, *printer_name; + + display_name = getenv("XPRINTER"); + + if (display_name != NULL) { + /* if name is of the form "xprint:display" change it to "display" + * Note: this is quite unlikely to happen for now but it might in the + * future... I guess this is what some call forward compatibility ?-) + */ + if (strncmp(display_name, "xprint:", 7) == 0) + pdpy_name = display_name + 7; + else + pdpy_name = display_name; + + ptr = strchr(pdpy_name, '@'); + if (ptr != NULL) { + /* server specified, store printer and remove it from + * display name */ + printer_name = (char *)Malloc(ptr - pdpy_name + 1); + if (printer_name != NULL) { + strncpy(printer_name, pdpy_name, ptr - pdpy_name); + printer_name[ptr - pdpy_name] = '\0'; + } + ptr++; + pdpy_name = (char *)Malloc(strlen(ptr) + 1); + if (pdpy_name != NULL) + strcpy(pdpy_name, ptr); + } else { + printer_name = (char *)Malloc(strlen(pdpy_name) + 1); + if (printer_name != NULL) + strcpy(printer_name, pdpy_name); + pdpy_name = NULL; + } + } else { + pdpy_name = NULL; + /* look for printer name in other variables */ + printer_name = getenv("PDPRINTER"); + if (printer_name == NULL) { + printer_name = getenv("LPDEST"); + if (printer_name == NULL) + printer_name = getenv("PRINTER"); + } + /* make a copy */ + if (printer_name != NULL) { + ptr = printer_name; + printer_name = (char *)Malloc(strlen(ptr) + 1); + if (printer_name != NULL) + strcpy(printer_name, ptr); + } + } + + /* if no server was specified in XPRINTER, look at XPSERVERLIST */ + if (pdpy_name == NULL) { + char *servers_list = getenv("XPSERVERLIST"); + if (servers_list != NULL && servers_list[0] != '\0') { + /* use the first one from the server list */ + ptr = strchr(servers_list, ' '); + if (ptr != NULL) { + pdpy_name = (char *) Malloc(ptr - servers_list + 1); + if (pdpy_name != NULL) { + strncpy(pdpy_name, servers_list, ptr - servers_list); + pdpy_name[ptr - servers_list] = '\0'; + } + } else { + pdpy_name = (char *) Malloc(strlen(servers_list) + 1); + if (pdpy_name != NULL) + strcpy(pdpy_name, servers_list); + } + } + } + *printer_return = printer_name; + return pdpy_name; +} + +#define MAXLEN 256 + +char * +GetXFwpDisplayName(char *dpy_name) +{ +#if 0 + char *fwp_dpy_name, *ptr, *limit; + FILE *in; + int c, status; +#else + char *fwp_dpy_name; +#endif + char buf[MAXLEN]; + char *proxy_mngr; + + /* first, let's figure out where the proxy manager should be */ + proxy_mngr = getenv("PROXY_MANAGER"); + if (proxy_mngr == NULL) + proxy_mngr = DEFAULT_PROXY_MANAGER; + +#if 0 + /* now let's see if we can find a firewall proxy */ + sprintf(buf, + "xfindproxy -manager %s -server %s -name xfwp 2>/dev/null", + proxy_mngr, dpy_name); + in = popen(buf, "r"); + if (in != NULL) { + ptr = buf; + limit = buf + MAXLEN - 1; + /* read in first line */ + while ((c = fgetc(in)) != EOF && c != '\n' && ptr < limit) + *ptr++ = c; + status = pclose(in); + + (void) fprintf (stderr, "buf: %s\n", buf); + (void) fprintf (stderr, "status: %d\n", status); + (void) fprintf (stderr, "ptr: %p, buf: %p\n", ptr, buf); + if (status == -1 || ptr == buf) { + perror ("too bad"); + /* xfindproxy failed, consider we do not have a firewall */ + fwp_dpy_name = NULL; + } else { + /* make sure we have a NULL terminated string */ + *ptr = '\0'; + fwp_dpy_name = (char *) Malloc(ptr - buf + 1); + if (fwp_dpy_name != NULL) + strcpy(fwp_dpy_name, buf); + } + } else { + /* failed to run xfindproxy, consider that we don't have a firewall */ + fwp_dpy_name = NULL; + } +#else + fwp_dpy_name = NULL; + if (findproxy (buf, proxy_mngr, dpy_name, "xfwp")) { + fwp_dpy_name = (char *) Malloc (strlen (buf) + 1); + if (fwp_dpy_name != NULL) + strcpy (fwp_dpy_name, buf); + } +#endif + + return fwp_dpy_name; +} diff --git a/rx/XDpyName.h b/rx/XDpyName.h new file mode 100644 index 0000000..93f4b12 --- /dev/null +++ b/rx/XDpyName.h @@ -0,0 +1,39 @@ +/* $Xorg: XDpyName.h,v 1.4 2001/02/09 02:05:58 xorgcvs Exp $ */ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- +ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABIL- +ITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization from +The Open Group. + +*/ + +#ifndef _XDpyName_h +#define _XDpyName_h + +extern char * +GetXPrintDisplayName(char **printer_return); + +extern char * +GetXFwpDisplayName(char *dpy_name); + +#endif diff --git a/rx/XUrls.c b/rx/XUrls.c new file mode 100644 index 0000000..28d5540 --- /dev/null +++ b/rx/XUrls.c @@ -0,0 +1,360 @@ +/* $Xorg: XUrls.c,v 1.4 2001/02/09 02:05:58 xorgcvs Exp $ */ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- +ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABIL- +ITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization from +The Open Group. + +*/ + +#include "RxI.h" +#include <sys/utsname.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <netdb.h> +#include <stdlib.h> +#include <limits.h> /* for MAXHOSTNAMELEN */ +#include <errno.h> +#ifdef X_NOT_STDC_ENV +extern int errno; +#endif + +/* and in case we didn't get it from the headers above */ +#ifndef MAXHOSTNAMELEN +# define MAXHOSTNAMELEN 256 +#endif + +/* + * Return a good hostname, even on multi-homed hosts, e.g. machines + * connected to the internet via PPP which also have a local network + * are multi-homed. + * + * This might still fail to provide the right name if netscape is + * running on a different host than it is being displayed on. E.g, + * + * netscapehost <--ethernet--> display host <--ppp--//--> webserver + * + * The display host is multi-homed and has the nodename myhost.mynet + * as far as netscape and the netscape host are concerned, but has + * the name pppX.myispnet to the outside world. When this happens the + * user is going to have to set the XREALDISPLAY environment variable + * when they run netscape like this. + */ +static char* +MyBestHostname ( + char* myname, + int myname_len, + char* display_name, + char* dest_url) +{ + struct sockaddr_in local, remote; + struct hostent* hp; + struct utsname host; + int s, rv, namelen; + char dest_hostname[MAXHOSTNAMELEN + 1]; + + *myname = '\0'; + + /* if of the form ":0.0" get the real hostname */ + if (display_name[0] == ':') { + +/* for some reason this doesn't work on Solaris 2.x */ +#if !(defined(sun) && defined(SVR4)) + ParseHostname (dest_url, dest_hostname, sizeof dest_hostname); + + hp = gethostbyname (dest_hostname); + + if (hp) { + memcpy (&remote.sin_addr, hp->h_addr_list[0], sizeof remote.sin_addr); + remote.sin_port = htons(60000); + remote.sin_family = AF_INET; +#ifdef BSD44SOCKETS + remote.sin_len = sizeof remote; +#endif + + local.sin_addr.s_addr = htonl(INADDR_ANY); + local.sin_port = htons(60000); + local.sin_family = AF_INET; +#ifdef BSD44SOCKETS + local.sin_len = sizeof remote; +#endif + + s = socket(PF_INET, SOCK_DGRAM, 0); + if (s != -1) { + do { + rv = bind (s, (struct sockaddr*) &local, sizeof local); + local.sin_port = htons (ntohs (local.sin_port) + 1); + } while (rv == -1 && errno == EADDRINUSE); + + if (rv != -1) { + do { + rv = connect (s, (struct sockaddr*) &remote, sizeof remote); + remote.sin_port = htons (ntohs (remote.sin_port) + 1); + } while (rv == -1 && errno == EADDRINUSE); + + if (rv != -1) { + namelen = sizeof local; + rv = getsockname (s, (struct sockaddr*) &local, &namelen); + + if (rv != -1) { + hp = gethostbyaddr ((char*) &local.sin_addr.s_addr, + sizeof local.sin_addr.s_addr, + AF_INET); + if (hp) { + strncpy (myname, hp->h_name, myname_len); + myname[MAXHOSTNAMELEN] = '\0'; + close (s); + return display_name; + } + } + } + } + close (s); + } + } +#endif + /* none of the above worked, punt */ + + uname(&host); + strncpy (myname, host.nodename, myname_len); + myname[MAXHOSTNAMELEN] = '\0'; + } else { /* otherwise believe the display_name */ + char *ptr; + + ptr = strchr(display_name, ':'); + if (ptr == NULL) { + /* if there's no ":0" in the name, just copy it */ + strncpy(myname, display_name, myname_len); + myname[MAXHOSTNAMELEN] = '\0'; + } else { + /* otherwise copy everthing up to the ":0" */ + strncpy(myname, display_name, ptr - display_name); + myname[ptr - display_name] = '\0'; + return ptr; + } + } + return display_name; +} + + +/* return the Url of the user's X display + * this must be of the form: + * x11: [protocol/] [hostname] : [:] displaynumber [.screennumber] \ + * [ ; auth= auth_data ] + */ +char * +GetXUrl(char *display_name, char *auth, char* dest_url) +{ + char *dpy_name, *proto; + char *url, *ptr; + char *name; + struct hostent *host; + int len, proto_len, dpy_len, name_len, auth_len; + char hostname[MAXHOSTNAMELEN + 1]; + + len = 5; /* this is for "x11:" */ + + /* if of the form "x11:display" change it to "display" */ + if (strncmp(display_name, "x11:", 4) == 0) + dpy_name = display_name + 4; + else + dpy_name = display_name; + + /* if protocol is specified store it and remove it from display name */ + ptr = strchr(dpy_name, '/'); + if (ptr != NULL) { + proto = dpy_name; + proto_len = ptr - dpy_name; + dpy_name = ptr + 1; + /* if local forget it */ + if (strncmp(proto, "local", proto_len) == 0) + proto_len = 0; + } else + proto_len = 0; + + /* if of the form "unix:0.0" change it to ":0.0" */ + if (strncmp(dpy_name, "unix", 4) == 0) + dpy_name += 4; + + dpy_name = MyBestHostname (hostname, MAXHOSTNAMELEN, dpy_name, dest_url); + host = gethostbyname(hostname); + name = host->h_name; + name_len = strlen(name); + + dpy_len = dpy_name == NULL ? 0 : strlen(dpy_name); + auth_len = auth == NULL ? 0 : 6 + strlen(auth); /* 6 for ";auth=" */ + len += proto_len + 1 + name_len + dpy_len + auth_len; + + url = ptr = (char *)Malloc(len); + if (url == NULL) + return NULL; + + strcpy(ptr, "x11:"); + ptr += 4; + if (proto_len != 0) { + strncpy(ptr, proto, proto_len + 1); + ptr += proto_len + 1; + } + if (name_len != 0) { + strcpy(ptr, name); + ptr += name_len; + } + if (dpy_len != 0) { + strcpy(ptr, dpy_name); + ptr += dpy_len; + } + if (auth_len != 0) + sprintf(ptr, ";auth=%s", auth); + else + *ptr = '\0'; + + return url; +} + + +/* return the Url of the user's XPrint server + * this must be of the form: + * xprint: [printername@] [protocol/] [hostname] : [:] displaynumber \ + * [ ; auth= auth_data ] + */ +char * +GetXPrintUrl(char *display_name, char *printer, char *auth, char* dest_url) +{ + char *dpy_name, *proto; + char *url, *ptr; + char *name; + struct hostent *host; + int len, proto_len, dpy_len, name_len, auth_len, printer_len; + char hostname[MAXHOSTNAMELEN + 1]; + + len = 7; /* this is for "xprint:" */ + + /* if of the form "xprint:display" change it to "display" */ + if (strncmp(display_name, "xprint:", 7) == 0) + dpy_name = display_name + 7; + else + dpy_name = display_name; + + /* if protocol is specified store it and remove it from display name */ + ptr = strchr(dpy_name, '/'); + if (ptr != NULL) { + proto = dpy_name; + proto_len = ptr - dpy_name; + dpy_name = ptr + 1; + /* if local forget it */ + if (strncmp(proto, "local", proto_len) == 0) + proto_len = 0; + } else + proto_len = 0; + + /* if of the form "unix:0.0" change it to ":0.0" */ + if (strncmp(dpy_name, "unix", 4) == 0) + dpy_name += 4; + + dpy_name = MyBestHostname (hostname, MAXHOSTNAMELEN, dpy_name, dest_url); + host = gethostbyname(hostname); + name = host->h_name; + + /* if a screen number is specified strip it - not valid for printing */ + ptr = strchr(dpy_name, '.'); + if (ptr != NULL) + dpy_len = ptr - dpy_name; + else + dpy_len = strlen(dpy_name); + + name_len = strlen(name); + printer_len = printer ? strlen(printer) : 0; + auth_len = auth == NULL ? 0 : 6 + strlen(auth); /* 6 for ";auth=" */ + len += printer_len + 1 + proto_len + 1 + name_len + dpy_len + auth_len; + + url = ptr = (char *)Malloc(len); + if (url == NULL) + return NULL; + + strcpy(ptr, "xprint:"); + ptr += 7; + if (printer_len != 0) { + strcpy(ptr, printer); + ptr += printer_len; + *ptr++ = '@'; + } + if (proto_len != 0) { + strncpy(ptr, proto, proto_len + 1); + ptr += proto_len + 1; + } + if (name_len != 0) { + strcpy(ptr, name); + ptr += name_len; + } + if (dpy_len != 0) { + strncpy(ptr, dpy_name, dpy_len); + ptr += dpy_len; + } + if (auth_len != 0) + sprintf(ptr, ";auth=%s", auth); + else + *ptr = '\0'; + + return url; +} + +/* + * Extract the hostname of a given url. The hostname is copied to the given + * buffer if it is big enough and its length is returned. + * This relies strongly on the following expected syntax: + * scheme : [//] hostname [: port] [/path] + */ +int +ParseHostname(char *url, char *buf, int buflen) +{ + char *ptr, *begin; + + if (url == NULL) + return 0; + + /* skip scheme part */ + ptr = strchr(url, ':'); + if (ptr != NULL) + ptr++; + else + ptr = url; + /* skip possible "//" */ + while (*ptr && *ptr == '/') + ptr++; + begin = ptr; + /* look for possible port specification */ + ptr = strchr(begin, ':'); + if (ptr == NULL) { + /* look for possible path */ + ptr = strchr(begin, '/'); + if (ptr == NULL) + ptr += strlen(begin); + } + if (ptr - begin < buflen) { + strncpy(buf, begin, ptr - begin); + buf[ptr - begin] = '\0'; + return ptr - begin; + } else + return 0; +} diff --git a/rx/XUrls.h b/rx/XUrls.h new file mode 100644 index 0000000..9c54e77 --- /dev/null +++ b/rx/XUrls.h @@ -0,0 +1,37 @@ +/* $Xorg: XUrls.h,v 1.4 2001/02/09 02:05:58 xorgcvs Exp $ */ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- +ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABIL- +ITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization from +The Open Group. + +*/ + +#ifndef _XUrls_h +#define _XUrls_h + +extern char *GetXUrl(char *display, char *auth, char* dest); +extern char *GetXPrintUrl(char *display, char *printer, char *auth, char* dest); +extern int ParseHostname(char *url, char *buf, int buflen); + +#endif /* _XUrls_h */ diff --git a/testplugin/testplugin.c b/testplugin/testplugin.c new file mode 100644 index 0000000..7132be4 --- /dev/null +++ b/testplugin/testplugin.c @@ -0,0 +1,671 @@ +/* $Xorg: testplugin.c,v 1.4 2001/02/09 02:05:58 xorgcvs Exp $ */ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- +ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABIL- +ITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization from +The Open Group. + +*/ +/* + * This is a (not so) basic program to "test" a netscape plugin. + * It exercises the plugin in a way close (I hope) to how netscape does. + * It is designed to allow minimal debugging of the plugin, with the + * possibility of using purify. + * + * Arnaud Le Hors + */ + +#include <stdio.h> +#include <Xm/Form.h> +#include <Xm/DrawingA.h> +#include <Xm/ScrolledW.h> +#include <Xm/PushB.h> +#ifdef SUPPORT_EDITRES +#include <X11/Xmu/Editres.h> +#endif + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <sys/uio.h> +#include <unistd.h> +#if defined(SYSV) || defined(SVR4) +#include <string.h> +#else +#include <strings.h> +#endif + +#include "npapi.h" + +/* default mime type */ +#ifndef MIMETYPE +#define MIMETYPE "undefined" +#endif + +/* define how many bytes should be read at most */ +#ifndef READNBYTES +#define READNBYTES 100 +#endif + +/* default plugin size */ +#define DEFAULT_WIDTH 50 +#define DEFAULT_HEIGHT 50 + + +#ifdef PLUGIN_TRACE +#define PRINTTRACE(msg) fprintf(stderr, msg) +#else +#define PRINTTRACE(msg) +#endif + +/* different possible states */ +typedef enum { + SETUP, SETUPWINDOW, PROCESSINPUT, SETUPSTREAM, PROCESSREPLY, DONE +} State; + +/* main structure */ +typedef struct { + State state; + char **plugin_argn; + char **plugin_argv; + int plugin_argc; + uint32 width; + uint32 height; + Widget plugin; + char *src; + NPStream **streams; + int nstreams; + int streams_len; + Bool setup_window; +} AppData; + +/* create plugin instance */ +void +SetupPlugin(NPP instance) +{ + AppData *data = (AppData *)instance->ndata; + NPError status; + + /* NPError NPP_Initialize(void) */ + PRINTTRACE(" NPP_Initialize\n"); + status = NPP_Initialize(); + + /* + * NPError NPP_New(NPMIMEType *pluginType, NPP instance, uint16 mode, + * int16 argc, char *argn[], char *argv[], NPSavedData *saved) + */ + PRINTTRACE(" NPP_New\n"); + status = NPP_New(MIMETYPE, instance, 0, + data->plugin_argc, data->plugin_argn, data->plugin_argv, + NULL); +} + + +void +SetupPluginWindow(NPP instance) +{ + AppData *data = (AppData *)instance->ndata; + NPError status; + NPSetWindowCallbackStruct window_data; + NPWindow window; + + /* setup window structure */ + window_data.type = 0; /* what's this supposed to be ? */ + window_data.display = XtDisplay(data->plugin); + window_data.visual = DefaultVisual(window_data.display, + DefaultScreen(window_data.display)); + window_data.colormap = DefaultColormap(window_data.display, + DefaultScreen(window_data.display)); + window_data.depth = DefaultDepth(window_data.display, + DefaultScreen(window_data.display)); + + window.window = (void *) XtWindow(data->plugin); + window.x = 0; + window.y = 0; + window.width = data->width; + window.height = data->height; + window.ws_info = (void *) &window_data; + + /* NPError NPP_SetWindow(NPP instance, NPWindow *window) */ + PRINTTRACE(" NPP_SetWindow\n"); + status = NPP_SetWindow(instance, &window); +} + +void +MakeStream(NPP instance, const char *url, const char *window, FILE *fp) +{ + AppData *data = (AppData *)instance->ndata; + NPStream *stream, **ptr; + char *urlcopy; + + /* setup a stream */ + stream = (NPStream *) malloc(sizeof(NPStream)); + if (stream == NULL) { + fprintf(stderr, "cannot malloc enough memory: %d\n", + sizeof(NPStream)); + exit(1); + } + + urlcopy = (char *) malloc(strlen(url) + 1); + if (urlcopy == NULL) { + fprintf(stderr, "cannot malloc enough memory: %d\n", + strlen(url) + 1); + exit(1); + } + strcpy(urlcopy, url); + + stream->ndata = (void *) fp; + stream->pdata = NULL; + stream->url = urlcopy; + /* if target window different from plugin window throw reply away */ + stream->end = (window == NULL) ? 0 : -1; + stream->lastmodified = 0; /* I don't have this info */ + stream->notifyData = NULL; /* I don't support this for now */ + + /* add it to the queue */ + data->nstreams++; + if (data->nstreams > data->streams_len) { + ptr = (NPStream **) realloc(data->streams, + sizeof(NPStream *) * data->nstreams); + if (ptr == NULL) { + fprintf(stderr, "cannot malloc enough memory: %d\n", + sizeof(NPStream *) * data->nstreams); + exit(1); + } + data->streams = ptr; + data->streams_len = data->nstreams; + } + data->streams[data->nstreams - 1] = stream; +} + +void +DestroyStream(NPP instance, int i) +{ + AppData *data = (AppData *)instance->ndata; + /* + * NPError NPP_DestroyStream(NPP instance, NPStream *stream, + * NPError reason) + */ + PRINTTRACE(" NPP_DestroyStream\n"); + NPP_DestroyStream(instance, data->streams[i], NPRES_DONE); + if (data->streams[i]->url != NULL) + free((void *)data->streams[i]->url); + free(data->streams[i]); +} + +void +CloseStream(NPP instance, int i) +{ + AppData *data = (AppData *)instance->ndata; + FILE *fp = (FILE *) data->streams[i]->ndata; + + DestroyStream(instance, 0); + /* remove from queue */ + data->nstreams--; + for (i = 0; i < data->nstreams; i++) + data->streams[i] = data->streams[i + 1]; +} + +void +WriteStreamProc(NPP instance, int *fd, XtInputId *id) +{ + AppData *data = (AppData *)instance->ndata; + FILE *fp = (FILE *) data->streams[0]->ndata; + NPError status; + char buf[BUFSIZ]; + int32 readysize, readb, len; + + /* int32 NPP_WriteReady(NPP instance, NPStream *stream) */ + PRINTTRACE(" NPP_WriteReady\n"); + readysize = NPP_WriteReady(instance, data->streams[0]); + + /* make sure we won't read more than our buf size */ + if (readysize > BUFSIZ) + readysize = BUFSIZ; + + /* force a smaller read size so NPP_Write is called more than once, + this is just for the purpose of testing! */ + if (readysize > READNBYTES) + len = READNBYTES; + else /* take half of the given value */ + len = (readysize >> 1); + + /* read next chunk of data */ + len = fread(buf, sizeof(char), len, fp); + + if (len != 0) { /* send it to plugin */ + /* + * int32 NPP_Write(NPP instance, NPStream *stream, int32 offset, + * int32 len, void *buf); + */ + PRINTTRACE(" NPP_Write\n"); + readb = NPP_Write(instance, data->streams[0], data->streams[0]->end, + len, buf); + + /* plugin should have read all of it since we read less than readysize, + * if it read less than what it claimed it was ready to use bark */ + if (readb < len) { + fprintf(stderr, + "plugin claimed to be ready to read %d but only read %d\n", + readysize, readb); + exit(1); + } + data->streams[0]->end += len; + } else { /* no more to read */ + XtRemoveInput(*id); + data->state = DONE; + } +} + +/* destroy plugin */ +void +ShutdownPlugin(NPP instance) +{ + AppData *data = (AppData *)instance->ndata; + NPSavedData *saved_data = NULL; + + if (data->streams != NULL) { + int i; + for (i = 0; i < data->nstreams; i++) + DestroyStream(instance, i); + free(data->streams); + } + PRINTTRACE(" NPP_Destroy\n"); + NPP_Destroy(instance, &saved_data); + if (saved_data != NULL) + free(saved_data); /* so this is not reported as memory leak */ + PRINTTRACE(" NPP_Shutdown\n"); + NPP_Shutdown(); +} + +/* quit callback: shutdown plugin and exit */ +void +QuitCB(Widget widget, XtPointer closure, XtPointer call_data) +{ + ShutdownPlugin((NPP) closure); + exit(0); +} + +/* resize handler: like Netscape change the plugin widget */ +void +ResizeEH(Widget toplevel, XtPointer client_data, XEvent *event, Boolean *cont) +{ + if (event->type == ConfigureNotify) { + NPP instance = (NPP) client_data; + AppData *data = (AppData *)instance->ndata; + Arg args[10]; + int n; + Widget oldplugin, scrolledW; + Dimension width, height; + + /* remove the current plugin from its parent's geometry management */ + oldplugin = data->plugin; + + if (XtIsRealized(oldplugin) == False) + return; + + /* we only want to deal with resize */ + if (event->xconfigure.x != 0 || event->xconfigure.y != 0) + return; + + scrolledW = XtParent(XtParent(oldplugin)); + XtUnmanageChild(oldplugin); + + /* create a copy of the plugin widget */ + n = 0; + XtSetArg(args[n], XmNwidth, &width); n++; + XtSetArg(args[n], XmNheight, &height); n++; + XtGetValues(oldplugin, args, n); + + n = 0; + XtSetArg(args[n], XmNwidth, width); n++; + XtSetArg(args[n], XmNheight, height); n++; + XtSetArg(args[n], XmNmarginWidth, 0); n++; + XtSetArg(args[n], XmNmarginHeight, 0); n++; + XtSetArg(args[n], XmNresizePolicy, XmRESIZE_NONE); n++; + data->plugin = XmCreateDrawingArea(scrolledW, "plugin", args, n); + + n = 0; + XtSetArg(args[n], XmNworkWindow, data->plugin); n++; + XtSetValues(scrolledW, args, n); + XtManageChild(data->plugin); + + /* then destroy the old plugin widget */ + XtDestroyWidget(oldplugin); + + data->setup_window = True; + } +} + +/* build a GUI with a form containing a ScrolledWindow over a DrawingArea for + the plugin and a button to quit */ +Widget +BuildGUI(Widget toplevel, Dimension width, Dimension height, NPP instance) +{ + Widget form, scrolledW, plugin, button; + Arg args[10]; + int n; + + XtAddRawEventHandler(toplevel, StructureNotifyMask, False, + ResizeEH, instance); + + form = XmCreateForm(toplevel, "form", NULL, 0); + + n = 0; + XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++; + XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++; + XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++; + button = XmCreatePushButton(form, "quit", args, n); + XtAddCallback(button, XmNactivateCallback, QuitCB, instance); + + n = 0; + XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++; + XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++; + XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++; + XtSetArg(args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++; + XtSetArg(args[n], XmNbottomWidget, button); n++; + XtSetArg(args[n], XmNscrollBarDisplayPolicy, XmSTATIC); n++; + XtSetArg(args[n], XmNscrollingPolicy, XmAUTOMATIC); n++; + scrolledW = XmCreateScrolledWindow(form, "scrolledWindow", args, n); + + n = 0; + XtSetArg(args[n], XmNwidth, width); n++; + XtSetArg(args[n], XmNheight, height); n++; + XtSetArg(args[n], XmNmarginWidth, 0); n++; + XtSetArg(args[n], XmNmarginHeight, 0); n++; + XtSetArg(args[n], XmNresizePolicy, XmRESIZE_NONE); n++; + plugin = XmCreateDrawingArea(scrolledW, "plugin", args, n); + + n = 0; + XtSetArg(args[n], XmNworkWindow, plugin); n++; + XtSetValues(scrolledW, args, n); + + XtManageChild(plugin); + XtManageChild(scrolledW); + XtManageChild(button); + XtManageChild(form); + return plugin; +} + +/* parse program arguments and return plugin arguments list */ +void +ParseProgramArgs(int pg_argc, char **pg_argv, + int *argc_ret, char ***argn_ret, char ***argv_ret) +{ + int argc, i; + char **argn, **argv, *ptr; + + argn = (char **)malloc(sizeof(char *) * pg_argc); + argv = (char **)malloc(sizeof(char *) * pg_argc); + if (argn == NULL || argv == NULL) { + fprintf(stderr, "cannot malloc enough memory: %d\n", + sizeof(char *) * pg_argc); + exit(1); + } + argc = 0; + for (i = 0; i < pg_argc; i++) { + /* look for arguments of the form "name=value", skip malformed ones */ + ptr = strchr(pg_argv[i], '='); + if (ptr != NULL) { + /* "split" the string and store both parts */ + *ptr = '\0'; + argn[argc] = pg_argv[i]; + argv[argc] = ptr + 1; + argc++; + } else + fprintf(stderr, "invalid argument: %s\n", pg_argv[i]); + } + *argn_ret = argn; + *argv_ret = argv; + *argc_ret = argc; +} + + +/* retreive src, width, and height arguments value */ +void +ParsePluginArgs(int argc, char **argn, char **argv, + char **src_ret, int *width_ret, int *height_ret) +{ + int i; + + *src_ret = NULL; + *width_ret = DEFAULT_WIDTH; + *height_ret = DEFAULT_HEIGHT; + /* dumb look up */ + for (i = 0; i < argc; i++) { + if (strcasecmp(argn[i], "src") == 0) + *src_ret = argv[i]; + else if (strcasecmp(argn[i], "width") == 0) + *width_ret = atoi(argv[i]); + else if (strcasecmp(argn[i], "height") == 0) + *height_ret = atoi(argv[i]); + } +} + +/* main routine exercising the plug-in within a state machine */ +Boolean +MainWorkProc(XtPointer closure) +{ + NPP instance = (NPP) closure; + AppData *data = (AppData *)instance->ndata; + NPError status; + + switch (data->state) { + case SETUP: + /* create plugin instance */ + SetupPlugin(instance); + data->state = SETUPWINDOW; + break; + + case SETUPWINDOW: + /* create plugin window */ + SetupPluginWindow(instance); + data->state = PROCESSINPUT; + break; + + case PROCESSINPUT: + /* set default next state, + may be overriden by the call to GetURL */ + data->state = DONE; + + /* perform GET request on input data */ + if (data->src != NULL) { + status = NPN_GetURL(instance, data->src, NULL); + data->state = SETUPSTREAM; + } + break; + + case SETUPSTREAM: + /* if there is a GET request in progress setup to process reply */ + if (data->streams != NULL && data->nstreams != 0) { + if (data->streams[0]->end == -1) /* throw it away */ + fprintf(stderr, + "GetURL request response is thrown away (sorry)\n"); + else { + /* + * NPError NPP_NewStream(NPP instance, NPMIMEType type, + * NPStream *stream, NPBool seekable, uint16* stype) + */ + PRINTTRACE(" NPP_NewStream\n"); + status = NPP_NewStream(instance, MIMETYPE, data->streams[0], + FALSE, (uint16*)NP_NORMAL); + /* and add a handler for it */ + XtAppAddInput(XtWidgetToApplicationContext(data->plugin), + fileno((FILE *)(data->streams[0]->ndata)), + (XtPointer) XtInputReadMask, + (XtInputCallbackProc) WriteStreamProc, + (XtPointer) instance); + } + } + data->state = PROCESSREPLY; + break; + + case PROCESSREPLY: + /* if no more query responses are pending move to next state */ + if (data->streams == NULL || data->nstreams == 0 || + data->streams[0]->end == -1) + data->state = DONE; /* no more to be read */ + break; + + case DONE: + /* if there is a registered stream close it */ + if (data->streams != NULL && data->nstreams != 0) { + CloseStream(instance, 0); + if (data->nstreams > 0) { + /* then call for process of next reply */ + data->state = SETUPSTREAM; + return False; /* work proc is to be called again */ + } + } + /* then exit from state machine */ + return True; /* work proc is to be removed */ + } + return False; /* work proc is to be called again */ +} + +main(int argc, char **argv) +{ + Widget toplevel, plugin; + XtAppContext app_context; + NPP_t instance; + AppData app_data; + char **plugin_argn, **plugin_argv; + int plugin_argc; + char *src; + int width, height; + XEvent event; + + if (argc < 2 || !strncmp(argv[1], "-h", 2) || !strncmp(argv[1], "-?", 2)) { + fprintf(stderr, + "Usage: %s src=url [width=w] [height=h] [name=value ...]\n", + argv[0]); + exit(1); + } + + /* build GUI */ + toplevel = XtAppInitialize(&app_context, "Plugin Test", 0, 0, + &argc, argv, 0, 0, 0); +#ifdef SUPPORT_EDITRES + XtAddEventHandler(toplevel, 0, True, _XEditResCheckMessages, NULL); +#endif + + ParseProgramArgs(argc - 1, argv + 1, + &plugin_argc, &plugin_argn, &plugin_argv); + + ParsePluginArgs(plugin_argc, plugin_argn, plugin_argv, + &src, &width, &height); + + /* make sure width and height are valid */ + if (width < 0 || height < 0) { + fprintf(stderr, "invalid size specification (< 0) width=%d height=%d", + width, height); + exit(1); + } + + if (src == NULL) { + fprintf(stderr, "source argument required!\n"); + exit(1); + } + + plugin = + BuildGUI(toplevel, (Dimension)width, (Dimension)height, &instance); + + /* setup instance structure */ + app_data.state = SETUP; + app_data.plugin_argn = plugin_argn; + app_data.plugin_argv = plugin_argv; + app_data.plugin_argc = plugin_argc; + app_data.width = (uint32) width; + app_data.height = (uint32) height; + app_data.plugin = plugin; + app_data.src = src; + app_data.streams = NULL; + app_data.nstreams = 0; + app_data.streams_len = 0; + app_data.setup_window = False; + instance.ndata = (void *) &app_data; + + /* register main work proc (heart of the beast) */ + XtAppAddWorkProc(app_context, MainWorkProc, &instance); + + XtRealizeWidget(toplevel); + + /* wait for user to quit */ + for (;;) { + XtAppNextEvent (app_context, &event); + XtDispatchEvent (&event); + if (app_data.setup_window) { + SetupPluginWindow(&instance); + app_data.setup_window = False; + } + } +} + + +/* + * Netscape Methods + */ + +void * +NPN_MemAlloc(uint32 size) +{ + return malloc(size); +} + +uint32 +NPN_MemFlush(uint32 size) +{ + /* do nothing */ + return 0; +} + +void +NPN_MemFree(void *ptr) +{ + free(ptr); +} + +/* This is an asynchronous function, so perform request, setup stream for + * reply, and put it in the queue. */ +NPError +NPN_GetURL(NPP instance, const char *url, const char *window) +{ + AppData *data = (AppData *)instance->ndata; + char buf[BUFSIZ]; + FILE *fp; + + if (url == NULL) + return NPERR_INVALID_URL; + + /* perform request using "www" */ + sprintf(buf, "www -source \"%s\"", url); + fp = popen(buf, "r"); + if (fp == NULL) { + fprintf(stderr, "GetURL request failed on: %s\n", url); + return NPERR_INVALID_URL; + } + + MakeStream(instance, url, window, fp); + + return NPERR_NO_ERROR; +} diff --git a/testplugin/testplugin.man b/testplugin/testplugin.man new file mode 100644 index 0000000..6c1edc8 --- /dev/null +++ b/testplugin/testplugin.man @@ -0,0 +1,66 @@ +.\" $Xorg: testplugin.man,v 1.4 2001/02/09 02:05:58 xorgcvs Exp $ +.\" Copyright 1996, 1998 The Open Group +.\" +.\" Permission to use, copy, modify, distribute, and sell this software and its +.\" documentation for any purpose is hereby granted without fee, provided that +.\" the above copyright notice appear in all copies and that both that +.\" copyright notice and this permission notice appear in supporting +.\" documentation. +.\" +.\" The above copyright notice and this permission notice shall be included +.\" in all copies or substantial portions of the Software. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +.\" OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +.\" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +.\" IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +.\" OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +.\" ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +.\" OTHER DEALINGS IN THE SOFTWARE. +.\" +.\" Except as contained in this notice, the name of The Open Group shall +.\" not be used in advertising or otherwise to promote the sale, use or +.\" other dealings in this Software without prior written authorization +.\" from The Open Group. +.TH TESTPLUGIN 1 "Release 6.4" "X Version 11" +.SH NAME +testplugin - a Netscape Plug-in test bed utility +.SH SYNOPSIS +.B testplugin +src=\fIurl\fP +[width=\fIwidth\fP] +[height=\fIheight\fP] +[\fIname\fP=\fIvalue\fP] ... +.SH DESCRIPTION +This program is designed to provide a means for testing Netscape Navigator +UNIX plug-ins. It exercises the plug-in in a way close (I hope) to how +Navigator does, and because it is a standalone program it allows you to run +it through debugger and to use various program analysis tools. +.PP +The line-mode browser \fBwww\fP, must be in your \fBPATH\fP to be able to +use testplugin successfully. +.SH ARGUMENTS +.PP +.TP 8 +.B src=\fIurl\fP +This argument specifies the source document to use. It should be of the MIME +type your plug-in is expecting since unlike within Netscape, no type checking +is done and the document is simply streamed to the plug-in. +.PP +.TP 8 +.B [width=\fIwidth\fP] [height=\fIheight\fP] +These options allow to specify the plug-in window size. +.PP +.TP 8 +.B [\fIname\fP=\fIvalue\fP]... +In addition to the arguments described above, any other argument can be +specified and will be passed uninterpreted to the plug-in (through the +NPP_New method). +.SH CURRENT LIMITATIONS +I've not implemented all of the "Netscape Methods", but only the ones I've +needed so far. Also the "Plug-in Methods" are not called in every possible +manner so it does not provide a 100% testing coverage. +.SH "SEE ALSO" +www(1), Netscape Navigator Documentation +.SH AUTHOR +Arnaud Le Hors, X Consortium diff --git a/xnest-plugin/NewNDest.c b/xnest-plugin/NewNDest.c new file mode 100644 index 0000000..52b038c --- /dev/null +++ b/xnest-plugin/NewNDest.c @@ -0,0 +1,65 @@ +/* $Xorg: NewNDest.c,v 1.4 2001/02/09 02:05:58 xorgcvs Exp $ */ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- +ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABIL- +ITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization from +The Open Group. + +*/ + +#include "RxPlugin.h" +#include <sys/types.h> +#include <signal.h> + + +NPError +NPP_Initialize(void) +{ + RxpInitXnestDisplayNumbers(); + return NPERR_NO_ERROR; +} + +void +NPP_Shutdown(void) +{ +} + +/*********************************************************************** + * Functions to init and free private members + ***********************************************************************/ + +void +RxpNew(PluginInstance *This) +{ + This->window = None; + This->child_pid = 0; + This->toplevel_widget = NULL; +} + +void +RxpDestroy(PluginInstance *This) +{ + /* kill child process */ + kill(This->child_pid, SIGKILL); + RxpFreeXnestDisplayNumber(This->display_num); +} diff --git a/xnest-plugin/PProcess.c b/xnest-plugin/PProcess.c new file mode 100644 index 0000000..b90ae6c --- /dev/null +++ b/xnest-plugin/PProcess.c @@ -0,0 +1,71 @@ +/* $Xorg: PProcess.c,v 1.4 2001/02/09 02:05:58 xorgcvs Exp $ */ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- +ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABIL- +ITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization from +The Open Group. + +*/ + +#include "RxPlugin.h" +#include "XUrls.h" + +/*********************************************************************** + * Process the given RxParams and make the RxReturnParams + ***********************************************************************/ +int +RxpProcessParams(PluginInstance* This, RxParams *in, RxReturnParams *out) +{ + /* init return struture */ + memset(out, 0, sizeof(RxReturnParams)); + out->x_ui_lbx = RxUndef; + out->x_print_lbx = RxUndef; + + out->action = in->action; + if (in->embedded != RxUndef) + out->embedded = RxTrue; /* we do support embbeding! */ + else + out->embedded = RxUndef; + + out->width = in->width; + out->height = in->height; + + if (in->ui[0] == XUI) { /* X display needed */ + out->ui = GetXUrl(RxpXnestDisplay(This->display_num), NULL, in->action); + + if (in->x_ui_lbx != RxUndef) + out->x_ui_lbx = RxFalse; /* we do not support LBX */ + else + out->x_ui_lbx = RxUndef; + } + + if (in->print[0] == XPrint) { /* XPrint server needed */ + out->print = NULL; + + if (in->x_print_lbx != RxUndef) + out->x_print_lbx = RxFalse; /* we do not support LBX */ + else + out->x_print_lbx = RxUndef; + } + return 0; +} diff --git a/xnest-plugin/RxPlugin.h b/xnest-plugin/RxPlugin.h new file mode 100644 index 0000000..ce7c420 --- /dev/null +++ b/xnest-plugin/RxPlugin.h @@ -0,0 +1,119 @@ +/* $Xorg: RxPlugin.h,v 1.4 2001/02/09 02:05:58 xorgcvs Exp $ */ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- +ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABIL- +ITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization from +The Open Group. + +*/ + +/* + * RX plug-in header file, based on the UnixTemplate file provided by Netcape. + */ + +/* -*- Mode: C; tab-width: 4; -*- */ +/****************************************************************************** + * Copyright 1996 Netscape Communications. All rights reserved. + ******************************************************************************/ +/* + * UnixShell.c + * + * Netscape Client Plugin API + * - Function that need to be implemented by plugin developers + * + * This file defines a "Template" plugin that plugin developers can use + * as the basis for a real plugin. This shell just provides empty + * implementations of all functions that the plugin can implement + * that will be called by Netscape (the NPP_xxx methods defined in + * npapi.h). + * + * dp Suresh <dp@netscape.com> + * + */ + +#ifndef _RxPlugin_h +#define _RxPLugin_h + +#include "npapi.h" +#include <X11/Xos.h> +#include <X11/Intrinsic.h> +#include <stdio.h> +#include "Rx.h" + + +/*********************************************************************** + * Instance state information about the plugin. + * + * PLUGIN DEVELOPERS: + * Use this struct to hold per-instance information that you'll + * need in the various functions in this file. + ***********************************************************************/ + +typedef enum { LOADING, /* STARTING, */ WAITING, RUNNING} PluginState; + +typedef struct _PluginInstance +{ + NPP instance; + int16 argc; /* HTML arguments given by Netscape */ + char **argn; + char **argv; + short parse_reply; /* 0 - no + 1 - look for status line + 2 - done */ + short status; /* returned application status */ + RxBool dont_reparent; /* whether client windows need reparent*/ + char *query; + PluginState state; + Widget status_widget; + Widget plugin_widget; + Dimension width, height; + /* The following fields need to be taken care by RxpNew & RxpDestroy */ + Window window; + pid_t child_pid; + int display_num; /* Xnest display number */ + Widget toplevel_widget; +} PluginInstance; + +#define PLUGIN_NAME "RX Xnest Plug-in" +#define PLUGIN_DESCRIPTION "This X Remote Activation Plug-in uses the \ +Xnest program to perform embedding of X applications." +#define PLUGIN_MIME_DESCRIPTION \ + "application/x-rx:xrx:X Remote Activation Plug-in" + + +/* functions to init and free private members */ +extern void RxpNew(PluginInstance *This); +extern void RxpDestroy(PluginInstance *This); + +extern int +RxpProcessParams(PluginInstance* This, RxParams *in, RxReturnParams *out); + +extern void +RxpSetStatusWidget(PluginInstance*, PluginState); + +extern void RxpInitXnestDisplayNumbers(); +extern int RxpXnestDisplayNumber(); +extern void RxpFreeXnestDisplayNumber(int i); +extern char * RxpXnestDisplay(int display_number); + +#endif diff --git a/xnest-plugin/SetWin.c b/xnest-plugin/SetWin.c new file mode 100644 index 0000000..33e80a6 --- /dev/null +++ b/xnest-plugin/SetWin.c @@ -0,0 +1,216 @@ +/* $Xorg: SetWin.c,v 1.4 2001/02/09 02:05:58 xorgcvs Exp $ */ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- +ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABIL- +ITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization from +The Open Group. + +*/ + +/* + * RX plug-in module based on the UnixTemplate file provided by Netcape. + */ + +/* -*- Mode: C; tab-width: 4; -*- */ +/****************************************************************************** + * Copyright 1996 Netscape Communications. All rights reserved. + ******************************************************************************/ +/* + * UnixShell.c + * + * Netscape Client Plugin API + * - Function that need to be implemented by plugin developers + * + * This file defines a "Template" plugin that plugin developers can use + * as the basis for a real plugin. This shell just provides empty + * implementations of all functions that the plugin can implement + * that will be called by Netscape (the NPP_xxx methods defined in + * npapi.h). + * + * dp Suresh <dp@netscape.com> + * + */ + +#include "RxPlugin.h" +#include <X11/StringDefs.h> + +/*********************************************************************** + * Sometimes the plugin widget gets stupidly destroyed, that is whenever + * Netscape relayouts the page. This callback reparents the Xnest + * window to the root window so it does not get destroyed as well. + * Eventually the NPP_SetWindow function should be called and we'll + * reparent it back under the plugin. + ***********************************************************************/ +static void +DestroyCB (Widget widget, XtPointer client_data, XtPointer call_data) +{ + PluginInstance* This = (PluginInstance*) client_data; + int i; +#ifdef PLUGIN_TRACE + fprintf (stderr, "DestroyCB, This: 0x%x\n", This); +#endif + This->plugin_widget = NULL; + This->status_widget = NULL; + if (This->dont_reparent == RxFalse) { + XUnmapWindow(XtDisplay(widget), This->window); + XReparentWindow(XtDisplay(widget), This->window, + RootWindowOfScreen(XtScreen(widget)), 0, 0); + This->dont_reparent = RxTrue; + } else + This->dont_reparent = RxFalse; + /* + * not worth removing event handlers on this widget since it's + * about to be destroyed anyway. + */ +} + + +/*********************************************************************** + * Sometimes the plugin widget gets stupidly resized, because of poor + * geometry when its child (that is the status widget) gets destroyed. + * So this callback resizes it back to the right size. + * Note that this could lead to an endless battle, but it appears that + * it doesn't so far... + ***********************************************************************/ +static void +ResizeCB (Widget widget, XtPointer client_data, XtPointer call_data) +{ + PluginInstance* This = (PluginInstance*) client_data; + Arg args[5]; + int n; + +#ifdef PLUGIN_TRACE + fprintf (stderr, "ResizeCB, This: 0x%x\n", This); +#endif + /* make sure plugin widget gets the same size back */ + n = 0; + XtSetArg(args[n], XtNwidth, This->width); n++; + XtSetArg(args[n], XtNheight, This->height); n++; + XtSetValues(This->plugin_widget, args, n); +} + +static Widget +FindToplevel(Widget widget) +{ + while (XtParent(widget) != NULL && !XtIsTopLevelShell(widget)) + widget = XtParent(widget); + + return widget; +} + +/*********************************************************************** + * This function gets called first when the plugin widget is created and + * then whenever the plugin is changed. + ***********************************************************************/ +NPError +NPP_SetWindow(NPP instance, NPWindow* window) +{ + PluginInstance* This; + Display *display; + Widget netscape_widget; + pid_t pid; + + if (instance == NULL) + return NPERR_INVALID_INSTANCE_ERROR; + + if (window == NULL) + return NPERR_NO_ERROR; + + This = (PluginInstance*) instance->pdata; + + /* + * PLUGIN DEVELOPERS: + * Before setting window to point to the + * new window, you may wish to compare the new window + * info to the previous window (if any) to note window + * size changes, etc. + */ + display = ((NPSetWindowCallbackStruct *)window->ws_info)->display; + netscape_widget = XtWindowToWidget(display, (Window) window->window); + if (This->toplevel_widget == NULL) + This->toplevel_widget = FindToplevel(netscape_widget); + + if (This->plugin_widget != netscape_widget) { + + /* We have a new widget store it */ + This->plugin_widget = netscape_widget; + This->width = window->width; + This->height = window->height; + + XtAddCallback (This->plugin_widget, XtNdestroyCallback, + DestroyCB, (XtPointer) This); + XtAddCallback (This->plugin_widget, "resizeCallback", + ResizeCB, (XtPointer) This); + + if (This->window == None) { + + This->window = XCreateSimpleWindow(display, (Window)window->window, + 0, 0, + window->width, window->height, + 0, 0, 0); + XMapWindow(display, This->window); + + This->display_num = RxpXnestDisplayNumber(); +#ifdef PLUGIN_TRACE + fprintf(stderr, "Windows: %ld %ld\n", + (Window) window->window, XtWindow(This->window)); +#endif + pid = fork(); + if (pid == 0) { /* child process */ + static char *argv[] = { + "Xnest", + "-ac", /* no access control (sic!) */ + ":00", /* display number */ + "-parent", + "01234567890123456789", /* parent window id */ + NULL + }; + close(ConnectionNumber(display)); + + sprintf(argv[2], ":%d", This->display_num); + sprintf(argv[4], "%ld", This->window); + /* exec Xnest */ + execvp("Xnest", argv); + perror("Xnest"); + return NPERR_GENERIC_ERROR; + } else { /* parent process */ + /* store child pid so we can kill it later on */ + This->child_pid = pid; + } + } else { + /* Xnest is either under the RootWindow or the old widget */ + XReparentWindow(display, This->window, (Window)window->window, + 0, 0); + if (This->dont_reparent == RxTrue) + XMapWindow(display, This->window); + if (This->state != RUNNING) + RxpSetStatusWidget(This, This->state); + } + if (This->dont_reparent != RxFalse) /* can be True or Undef */ + This->dont_reparent = RxFalse; + else + This->dont_reparent = RxTrue; + } + + return NPERR_NO_ERROR; +} diff --git a/xnest-plugin/XnestDis.c b/xnest-plugin/XnestDis.c new file mode 100644 index 0000000..10dddf0 --- /dev/null +++ b/xnest-plugin/XnestDis.c @@ -0,0 +1,106 @@ +/* $Xorg: XnestDis.c,v 1.4 2001/02/09 02:05:58 xorgcvs Exp $ */ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- +ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABIL- +ITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization from +The Open Group. + +*/ + +#include "RxPlugin.h" + +/*********************************************************************** + * Utility functions and global variable to manage display numbers + ***********************************************************************/ + +/* maximum numbers of concurrent instances */ +#define MAX_PLUGINS 10 + +/* start from 5 to avoid possible conflict with multi-display X server */ +#define XNEST_OFFSET 5 + +/* global allowing to know which display numbers are in use */ +static int16 xnest_display_numbers[MAX_PLUGINS]; + +void +RxpInitXnestDisplayNumbers() +{ + memset(xnest_display_numbers, 0, sizeof(int16) * MAX_PLUGINS); +} + +/* function returning first display number available */ +int +RxpXnestDisplayNumber() +{ + int i; + for (i = 0; i < MAX_PLUGINS; i++) + if (xnest_display_numbers[i] == 0) { + xnest_display_numbers[i] = 1; + return i + XNEST_OFFSET; + } + /* no more available */ + return -1; +} + +/* function returning first display number available */ +void +RxpFreeXnestDisplayNumber(int i) +{ + xnest_display_numbers[i - XNEST_OFFSET] = 0; +} + +/* function returning display name with specified display number */ +char * +RxpXnestDisplay(int display_number) +{ + static char name[1024]; + char *display_name, *dpy_name, *display_num, *screen_num; + + display_name = getenv("DISPLAY"); + if (display_name == NULL) + return NULL; + + /* if of the form x11:display skip scheme part */ + if (strncmp(display_name, "x11:", 4) == 0) + dpy_name = display_name + 4; + else + dpy_name = display_name; + + /* display number is after next ":" character */ + display_num = strchr(dpy_name, ':'); + if (display_num == NULL) /* invalid display specification */ + return NULL; + + /* copy display name up to the display number */ + strncpy(name, display_name, display_num - display_name); + + /* override display_number */ + sprintf(name + (display_num - display_name), ":%d", display_number); + + /* append screen number */ + screen_num = strchr(display_num, '.'); + if (screen_num != NULL) + strcat(name, screen_num); + + return name; +} |