Index: Changes.txt =================================================================== --- Changes.txt (revision 0) +++ Changes.txt (revision 0) @@ -0,0 +1,13 @@ +SAJAX CHANGELOG +--------------- + +Sajax version 0.6 (March 8, 2005) + +* Layout of archive changed; base folder changed; subfolders added for backends +* [php] Used short open tags by default. Thanks to Matthew M. Vince. +* [perl] Backend port added. Thanks to Nathan Schmidt, Jason Purdy and Nate + Mueller. +* [python] Backend port added. Thanks to Adam Collard. Please note that + this port is licensed under the Creative Commons "By" License version + 2.0. + Index: perl/example_multiply.cgi =================================================================== --- perl/example_multiply.cgi (revision 0) +++ perl/example_multiply.cgi (revision 0) @@ -0,0 +1,113 @@ +#! /usr/bin/perl -w + +# Perl version cloned from the original PHP by http://www.modernmethod.com/sajax/ +# I've left commented-out examples in the code for running with static methods. +# For moving to ModPerl it's important to no be redefining subs all the time, +# so this code adds the rs_register(funcname,coderef) call, which takes a coderef +# rather than the name of a sub to be called. + + +use Sajax; +use CGI; + +my $q = new CGI; + +my $rv = ""; + +$rv .= "content-type: text/html\n\n"; + + +=pod +#for static method calls +sub Sajax::multiply { + my($x, $y)=@_; + return $x * $y; +} +sub Sajax::divide { + my($x, $y)=@_; + return $x / $y; +} +=cut + +#equivalent modperl methods +my $msub = sub { + my($x, $y)=@_; + return $x * $y; +}; +my $dsub = sub { + my($x, $y)=@_; + return $x / $y; +}; + + + +Sajax::rs_init(); + +#register static methods (called by name) +#Sajax::rs_export("multiply","divide"); + +#modperl methods (called as anonymous coderefs) +Sajax::rs_register("multiply",$msub); +Sajax::rs_register("divide",$dsub); + + +my $handled_value = Sajax::rs_handle_client_request($q); + +if(defined $handled_value) { + $rv .= $handled_value; +} else { + +$rv .= "\n\nMultiplier\n\n\n\n"; +$rv .= < + + * + + = + + + + + + +
+ Show source + + +EOT +} + + +print $rv; + + + Index: perl/Readme.txt =================================================================== --- perl/Readme.txt (revision 0) +++ perl/Readme.txt (revision 0) @@ -0,0 +1,7 @@ +SAJAX PERL BACKEND +------------------ + +Contributed and copyighted by Nathan Schmidt (http://www.hinathan.com/). +Additional guidance and consultation by Jason Purdy and Nate Mueller. + + Index: perl/Sajax.pm =================================================================== --- perl/Sajax.pm (revision 0) +++ perl/Sajax.pm (revision 0) @@ -0,0 +1,183 @@ +package Sajax; +use Data::Dumper; + +my $rs_debug_mode = 0; +my $rs_js_has_been_shown = 0; +my %rs_export_list = (); +my %rs_coderef_list = (); + +sub incl_sajax { +} +sub rs_init { + $rs_debug_mode = 0; + $rs_js_has_been_shown = 0; + %rs_export_list = (); + %rs_coderef_list = (); + +} + +sub rs_handle_client_request { + my($q)=@_; + my $rv=""; + + if (!defined $q->param("rs")) { + return undef; + } + + my $func_name = $q->param("rs"); + + if ( defined $rs_export_list{$func_name}) { + $rv .= "+:"; + eval { + $rv .= &$func_name($q->param("rsargs")); + }; + if($@) { + print STDERR "Err:[$@]\n"; + } + } elsif ( defined $rs_coderef_list{$func_name}) { + $rv .= "+:"; + my $cr = $rs_coderef_list{$func_name}; + eval { + $rv .= &$cr($q->param("rsargs")); + }; + if($@) { + print STDERR "Err:[$@]\n"; + } + } else { + $rv .= "-:$func_name not callable"; + } + + return $rv; +} + +sub rs_show_common_js() { + my $rv = ""; + my $debug_mode = $rs_debug_mode ? "true" : "false"; + my $CC = "\n// Perl backend version (c) copyright 2005 Nathan Schmidt"; + $CC = ""; + $rv .= <url(-query=>1); + if ($uri =~ m/\?/) { + $uri .= "&rs=".rs_urlencode($func_name); + } else { + $uri .= "?rs=".rs_urlencode($func_name); + } + + my $urie = rs_esc($uri); + + $rv .= <$dt $msg
\n"); + fwrite($f, "$dt $msg
\n"); fclose($f); } @@ -75,6 +75,8 @@ var handle; handle = document.getElementById("handle").value; line = document.getElementById("line").value; + if (line == "") + return; x_add_line("[" + handle + "] " + line, add_cb); document.getElementById("line").value = ""; } @@ -83,6 +85,11 @@ + Sajax + - + This example illustrates the simplest possible graffiti wall. + It isn't meant to be perfect, featureful, or even useful.
+ ; + var rs_debug_mode = ; function rs_debug(text) { if (rs_debug_mode) @@ -83,12 +86,13 @@ ?> - // wrapper for + // wrapper for - function x_() { + function x_() { // count args; build URL var i, x, n; - var url = "", a = x_.arguments; + var url = ""; + var a = x_.arguments; for (i = 0; i < a.length-1; i++) url = url + "&rsargs[]=" + escape(a[i]); url = url + "&rsrnd=" + new Date().getTime(); @@ -109,8 +113,8 @@ a[a.length-1](data); } x.send(null); - rs_debug("x_ url = " + url); - rs_debug("x_ waiting.."); + rs_debug("x_ url = " + url); + rs_debug("x_ waiting.."); delete x; } Index: php/Readme.txt =================================================================== --- php/Readme.txt (revision 0) +++ php/Readme.txt (revision 0) @@ -0,0 +1,7 @@ +SAJAX PHP BACKEND +----------------- + +Contributed and copyighted by Thomas Lackner and ModernMethod +(http://www.modernmethod.com/). + + Index: python/License.txt =================================================================== --- python/License.txt (revision 0) +++ python/License.txt (revision 0) @@ -0,0 +1,4 @@ +This work is licensed under the Creative Commons Attribution License. To +view a copy of this license, visit +http://creativecommons.org/licenses/by/2.0/ or send a letter to Creative +Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA. Index: python/multiply.py =================================================================== --- python/multiply.py (revision 0) +++ python/multiply.py (revision 0) @@ -0,0 +1,48 @@ +#!/usr/bin/env python +import cgitb;cgitb.enable() +import sajax1 + +def multiply(x,y): + try: + float_x, float_y = float(x), float(y) + except: + return 0 + return float_x * float_y + +sajax1.init() +sajax1.export(multiply) +sajax1.handle_client_request() + +print """ + + + PyMuptiplier + + + + + * + + = + + + + +""" % locals() \ No newline at end of file Index: python/Readme.txt =================================================================== --- python/Readme.txt (revision 0) +++ python/Readme.txt (revision 0) @@ -0,0 +1,9 @@ +SAJAX PYTHON BACKEND +-------------------- + +Contributed and copyighted by Adam Collard. Additional guidance and +consultation by Carlos Bueno. + +IMPORTANT: This backend is NOT licensed under the BSD-L. It is licensed +under the Creative Commons "By" License version 2.0. Please see +License.txt for details. Index: python/sajax1.py =================================================================== --- python/sajax1.py (revision 0) +++ python/sajax1.py (revision 0) @@ -0,0 +1,130 @@ +#!/usr/bin/env python +import cgi +import cgitb; cgitb.enable() +import os +import sys +import datetime +import urllib + +print "Content-type: text/html" + +debug_mode = False +export_list = {} +js_has_been_shown = False + +form = cgi.FieldStorage() + +def init(): + pass + +def handle_client_request(): + func_name = form.getfirst('rs') + if func_name is None: + return + + # Bust cache in the head + print "Expires: Mon, 26 Jul 1997 05:00:00 GMT" + print "Last-Modified: %s GMT" % datetime.datetime.utcnow().strftime("%a, %d %m %H:%M:%S")# always modified + print "Cache-Control: no-cache, must-revalidate" # HTTP/1.1 + print "Pragma: no-cache" # HTTP/1.0 + print + + if not func_name in export_list: + print "-:%s not callable" % func_name + else: + print "+:", + rsargs = form.getlist('rsargs[]') + result = export_list[func_name](*rsargs) + print result + sys.exit() + +def show_common_js(): + js_debug_mode = str(debug_mode).lower() + print """\ + // remote scripting library + // (c) copyright 2005 modernmethod, inc + var rs_debug_mode = %(js_debug_mode)s; + var rs_obj = false; + var rs_callback = false; + + function rs_debug(text) { + if (rs_debug_mode) + alert("RSD: " + text) + } + + function rs_init_object() { + rs_debug("rs_init_object() called..") + + var A; + try { + A=new ActiveXObject("Msxml2.XMLHTTP"); + } catch (e) { + try { + A=new ActiveXObject("Microsoft.XMLHTTP"); + } catch (oc) { + A=null; + } + } + if(!A && typeof XMLHttpRequest != "undefined") + A = new XMLHttpRequest(); + if (!A) + rs_debug("Could not create connection object."); + return A; + } + """ % locals() + + +def escape(val): + return val.replace('"', '\\\\"') + +def show_one(func_name): + uri = os.environ['REQUEST_URI'] + if uri.find('?') == -1: + uri += "?rs=%s" % urllib.quote_plus(func_name) + else: + uri += "&rs=%s" % urllib.quote_plus(func_name) + escapeduri = escape(uri) + print """ + // wrapper for %(func_name)s + function x_%(func_name)s(){ + // count args; build URL + var i, x, n; + var url = "%(escapeduri)s", a = x_%(func_name)s.arguments; + for (i = 0; i < a.length-1; i++) + url = url + "&rsargs[]=" + escape(a[i]); + x = rs_init_object(); + x.open("GET", url, true); + x.onreadystatechange = function() { + if (x.readyState != 4) + return; + rs_debug("received " + x.responseText); + + var status; + var data; + status = x.responseText.charAt(0); + data = x.responseText.substring(2); + if (status == "-") + alert("Error: " + callback_n); + else + a[a.length-1](data); + } + x.send(null); + rs_debug("x_%(func_name)s url = " + url); + rs_debug("x_%(func_name)s waiting.."); + } + + """ % locals() + +def export(*args): + decorated = [(f.func_name, f) for f in args] + export_list.update(dict(decorated)) + +def show_javascript(): + global js_has_been_shown + if not js_has_been_shown: + show_common_js() + js_has_been_shown = True + + for func_name in export_list.iterkeys(): + show_one(func_name) + Index: python/wall.py =================================================================== --- python/wall.py (revision 0) +++ python/wall.py (revision 0) @@ -0,0 +1,84 @@ +#!/usr/bin/env python +import cgi +import cgitb;cgitb.enable() +import datetime +import os + +import sajax1 + +def colourify_ip(ip): + colour = ''.join(['%02x' % int(part) for part in ip.split('.')[-3:]]) + return colour + +def add_line(msg): + f = open("/tmp/wall.html","a") + dt = datetime.datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S") + msg = cgi.escape(msg) + remote = os.environ['REMOTE_ADDR'] + colour = colourify_ip(remote) + f.write('%(dt)s %(msg)s
\n' % locals()) + f.close() + +def refresh(): + f = open("/tmp/wall.html") + return '\n'.join(list(f)[-25:]) + +sajax1.init() +sajax1.export(refresh, add_line) +sajax1.handle_client_request() + +print """ + + + PyWall + + + + + + Sajax - Wall Example
+ + + + +
+
Loading..
+ + + +""" % locals() Index: Readme.txt =================================================================== --- Readme.txt (revision 0) +++ Readme.txt (revision 0) @@ -0,0 +1,14 @@ +WELCOME TO SAJAX +---------------- + +Sajax is a cross-platform, cross-browser web scripting toolkit +that makes it easy to expose functions in your code to JavaScript. + +For more information about Sajax, please see the homepage: + + http://www.modernmethod.com/sajax/ + +In this archive you will find a folder for each platform that is +currently supported. Please see individual documentation in each +folder for specific errata. +