[open-ils-commits] [GIT] Evergreen ILS branch rel_2_3 updated. 842f8f854ecf7004436b0799f43297c04d3752b6

Evergreen Git git at git.evergreen-ils.org
Wed Aug 15 22:26:17 EDT 2012


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Evergreen ILS".

The branch, rel_2_3 has been updated
       via  842f8f854ecf7004436b0799f43297c04d3752b6 (commit)
       via  ec2ed411a8c8df894d5e54c1980f6660cd5f0238 (commit)
      from  3bde56c32c3de88112bfae364d992a40b1cc19ec (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 842f8f854ecf7004436b0799f43297c04d3752b6
Author: Thomas Berezansky <tsbere at mvlc.org>
Date:   Fri Aug 10 10:44:47 2012 -0400

    Stage 2: Staff Client
    
    Robustify the oils protocol:
    
    1 - In the event of a problem URL, abort with about:blank.
    
    This prevents a segfault!
    
    2 - In the event of the TPac, or KPac, wrap the channel we return.
    
    The wrapper helps with redirects, but if applied to XMLHttpRequests will
    cause full breakage.
    
    Without the wrapper redirects end up setting URLs to https://host/...
    
    Signed-off-by: Thomas Berezansky <tsbere at mvlc.org>
    Signed-off-by: Dan Scott <dscott at laurentian.ca>

diff --git a/Open-ILS/xul/staff_client/components/oils_protocol.js b/Open-ILS/xul/staff_client/components/oils_protocol.js
index 6210e9b..d986aa8 100644
--- a/Open-ILS/xul/staff_client/components/oils_protocol.js
+++ b/Open-ILS/xul/staff_client/components/oils_protocol.js
@@ -1,6 +1,181 @@
 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
 
-// This component is intended to handle remote XUL requests
+// These components are intended to handle remote XUL requests
+
+// FIRST, if we don't have bind, add a workaroundish thing.
+// If we stop caring about firefox/xulrunner < 4 we can ditch this.
+if (!Function.prototype.bind) {
+  Function.prototype.bind = function (oThis) {
+    if (typeof this !== "function") {
+      // closest thing possible to the ECMAScript 5 internal IsCallable function
+      throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
+    }
+ 
+    var aArgs = Array.prototype.slice.call(arguments, 1),
+        fToBind = this,
+        fNOP = function () {},
+        fBound = function () {
+          return fToBind.apply(this instanceof fNOP && oThis
+                                 ? this
+                                 : oThis,
+                               aArgs.concat(Array.prototype.slice.call(arguments)));
+        };
+ 
+    fNOP.prototype = this.prototype;
+    fBound.prototype = new fNOP();
+ 
+    return fBound;
+  };
+}
+
+// First we define a channel wrapper.
+// We need this to handle redirects properly.
+// Things we care about:
+// Intercepting the URI
+// Intercepting things that get a channel in callbacks
+//
+// We define what we need for those.
+// wrap_channel(_mode) handles all of the other fun we then have to worry about.
+
+function oilsChannel() {
+}
+
+oilsChannel.prototype = {
+    QueryInterface: XPCOMUtils.generateQI([
+        Components.interfaces.nsIChannel,
+        Components.interfaces.nsIHttpChannel,
+        Components.interfaces.nsIHttpChannelInternal,
+        Components.interfaces.nsIRequest,
+        Components.interfaces.nsIInterfaceRequestor,
+        Components.interfaces.nsIChannelEventSink,
+        Components.interfaces.nsIProgressEventSink,
+        Components.interfaces.nsIHttpEventSink,
+        Components.interfaces.nsIStreamListener,
+        Components.interfaces.nsIAuthPrompt2,
+        Components.interfaces.nsIRequestObserver,
+        Components.interfaces.nsIUploadChannel
+    ]),
+    _internal_channel: null,
+    _internal_uri: null,
+    _redirect_notificationCallbacks: null,
+    _redirect_streamListener: null,
+    wrap_channel: function(channel, uri) {
+        this._internal_channel = channel;
+        this._internal_uri = uri;
+        this.wrap_channel_mode(channel.QueryInterface(Components.interfaces.nsIRequest)); // Basic request stuff
+        this.wrap_channel_mode(channel.QueryInterface(Components.interfaces.nsIChannel)); // Basic channel stuff
+        this.wrap_channel_mode(channel.QueryInterface(Components.interfaces.nsIHttpChannel)); // Basic HTTP stuff
+        this.wrap_channel_mode(channel.QueryInterface(Components.interfaces.nsIHttpChannelInternal)); // To pretend we are internal-ish
+        this.wrap_channel_mode(channel.QueryInterface(Components.interfaces.nsIUploadChannel)); // To make POST work
+    },
+    wrap_channel_mode: function(channel) {
+        for( var item in channel ) {
+            try {
+                if(this[item] || typeof this[item] != 'undefined')
+                    continue;
+            } catch (E) { continue; }
+            try {
+                var isfunc = false;
+                try {
+                    isfunc = (/[Ff]unction/.test(typeof channel[item])) || typeof channel[item].bind != 'undefined';
+                } catch (E) {}
+                if(isfunc) {
+                    try {
+                        this[item] = (function(thisItem){ return channel[thisItem].bind(channel); })(item);
+                    } catch (E) {}
+                } else {
+                    try {
+                        this.__defineGetter__(item, (function(thisItem) { return function() { return channel[thisItem]; } })(item));
+                    } catch (E) {}
+                    try {
+                        this.__defineSetter__(item, (function(thisItem) { return function(val) { return channel[thisItem] = val; } })(item));
+                    } catch (E) {}
+                }
+            } catch (E) {}
+        }
+    },
+    get notificationCallbacks() {
+        // for a number of reasons we don't admit to re-writing these things here
+        return this._redirect_notificationCallbacks;
+    },
+    set notificationCallbacks(val) {
+        if (val) {
+            this._internal_channel.notificationCallbacks = this.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
+            this._redirect_notificationCallbacks = val;
+        } else {
+            this._internal_channel.notificationCallbacks = null;
+            this._redirect_notificationCallbacks = null;
+        }
+        this._internal_channel.notificationCallbacks = val;
+    },
+    get URI() {
+        return this._internal_uri;
+    },
+    asyncOpen: function(aListener, aContext) {
+        this._redirect_streamListener = aListener;
+        this._internal_channel.asyncOpen(this.QueryInterface(Components.interfaces.nsIStreamListener), aContext);
+    },
+    open: function() {
+        return this._internal_channel.open();
+    },
+    getInterface: function(aIID) {
+        try {
+            if (this.QueryInterface(aIID) && this._redirect_notificationCallbacks.getInterface(aIID)) {
+                return this.QueryInterface(aIID);
+            }
+        } catch(e) {}
+        // Pass onto the forwarding target as a last resort.
+        return this._redirect_notificationCallbacks.getInterface(aIID);
+    },
+    onChannelRedirect: function(oldChannel, newChannel, flags) {
+        var redirect = this._redirect_notificationCallbacks.getInterface(Components.interfaces.nsIChannelEventSink);
+        return redirect.onChannelRedirect(this.QueryInterface(Components.interfaces.nsIChannel), newChannel, flags);
+    },
+    asyncOnChannelRedirect: function(oldChannel, newChannel, flags, callback) {
+        var redirect = this._redirect_notificationCallbacks.getInterface(Components.interfaces.nsIChannelEventSink);
+        return redirect.asyncOnChannelRedirect(this.QueryInterface(Components.interfaces.nsIChannel), newChannel, flags, callback);
+    },
+    onProgress: function(aRequest, aContext, aProgress, aProgressMax) {
+        var redirect = this._redirect_notificationCallbacks.getInterface(Components.interfaces.nsIProgressEventSink);
+        return redirect.onProgress(this.QueryInterface(Components.interfaces.nsIRequest), aContext, aProgress, aProgressMax);
+    },
+    onStatus: function(aRequest, aContext, aStatus, aStatusArg) {
+        var redirect = this._redirect_notificationCallbacks.getInterface(Components.interfaces.nsIProgressEventSink);
+        return redirect.onStatus(this.QueryInterface(Components.interfaces.nsIRequest), aContext, aStatus, aStatusArg);
+    },
+    onRedirect: function(httpChannel, newChannel) {
+        var redirect = this._redirect_notificationCallbacks.getInterface(Components.interfaces.nsIHttpEventSink);
+        return redirect.onRedirect(this.QueryInterface(Components.interfaces.nsIHttpChannel), newChannel);
+    },
+    asyncPromptAuth: function(aChannel, aCallback, aContext, level, authInfo) {
+        var redirect = this._redirect_notificationCallbacks.getInterface(Components.interfaces.nsIAuthPrompt2);
+        return redirect.asyncPromptAuth(this.QueryInterface(Components.interfaces.nsIChannel), aCallback, aContext, level, authInfo);
+    },
+    promptAuth: function(aChannel, level, authInfo) {
+        var redirect = this._redirect_notificationCallbacks.getInterface(Components.interfaces.nsIAuthPrompt2);
+        return redirect.promptAuth(this.QueryInterface(Components.interfaces.nsIChannel), level, authInfo);
+    },
+    onStartRequest: function(aRequest, aContext) {
+        if ( aRequest == this._internal_channel )
+            this._redirect_streamListener.onStartRequest(this.QueryInterface(Components.interfaces.nsIRequest), aContext);
+        else
+            this._redirect_streamListener.onStartRequest(aRequest, aContext);
+    },
+    onStopRequest: function(aRequest, aContext, aStatusCode) {
+        if ( aRequest == this._internal_channel )
+            this._redirect_streamListener.onStopRequest(this.QueryInterface(Components.interfaces.nsIRequest), aContext, aStatusCode);
+        else
+            this._redirect_streamListener.onStopRequest(aRequest, aContext, aStatusCode);
+    },
+    onDataAvailable: function(aRequest, aContext, aInputStream, aOffset, aCount) {
+        if ( aRequest == this._internal_channel )
+            this._redirect_streamListener.onDataAvailable(this.QueryInterface(Components.interfaces.nsIRequest), aContext, aInputStream, aOffset, aCount);
+        else
+            this._redirect_streamListener.onDataAvailable(aRequest, aContext, aInputStream, aOffset, aCount);
+    },
+}
+
+// This handles the actual security-related elements of the protocol wrapper
 
 function oilsProtocol() {}
 
@@ -17,7 +192,7 @@ oilsProtocol.prototype = {
     newChannel: function(aURI) {
         var ios = Components.classes["@mozilla.org/network/io-service;1"].getService(Components.interfaces.nsIIOService);
         var host;
-        switch(aURI.spec.replace(/^oils:\/\/([^\/]*)\/.*$/,'$1')) {
+        switch(aURI.host) {
             case 'remote':
                 var data_cache = Components.classes["@open-ils.org/openils_data_cache;1"].getService().wrappedJSObject.data;
                 host = data_cache.server_unadorned;
@@ -28,14 +203,12 @@ oilsProtocol.prototype = {
                 // NOTE: I honestly don't know how dangerous this might be, but I can't imagine it is worse than the previous "grant the domain permissions to do anything" model.
                 host = null;
                 break;
-            default:
-                return null; // Bad input. Not really sure what to do.
-                break;
         }
-        if(!host) return null; // Not really sure what to do when we don't have the data we need. Unless manual entry is happening, though, shouldn't be an issue.
+        if(!host)
+            return ios.newChannel("about:blank", null, null); // Bad input. Not really sure what to do. Returning a dummy channel does prevent a crash, though!
         var chunk = aURI.spec.replace(/^oils:\/\/[^\/]*\//,'');
         var channel = ios.newChannel("https://" + host + "/" + chunk, null, null).QueryInterface(Components.interfaces.nsIHttpChannel);
-        channel.setRequestHeader("OILS-Wrapper", "true", false);
+        channel.QueryInterface(Components.interfaces.nsIHttpChannel).setRequestHeader("OILS-Wrapper", "true", false);
         if(this._system_principal == null) {
             // We don't have the owner?
             var chrome_service = Components.classesByID['{61ba33c0-3031-11d3-8cd0-0060b0fc14a3}'].getService().QueryInterface(Components.interfaces.nsIProtocolHandler);
@@ -46,6 +219,15 @@ oilsProtocol.prototype = {
             chrome_request.cancel(0x804b0002);
         }
         if (this._system_principal) channel.owner = this._system_principal;
+        // This is a workaround.
+        // We can't wrap all the time because XMLHttpRequests are busted by us doing so.
+        // If we don't wrap, redirects in the Template Toolkit OPAC break out of the protocol.
+        // So wrap only if we are in the catalog!
+        if (aURI.path.match(/^\/eg\/[ok]pac/)) {
+            var outChannel = new oilsChannel();
+            outChannel.wrap_channel(channel, aURI);
+            return outChannel;
+        }
         return channel;
     },
     allowPort: function(aPort, aScheme) {
@@ -61,4 +243,3 @@ if (XPCOMUtils.generateNSGetFactory)
     var NSGetFactory = XPCOMUtils.generateNSGetFactory([oilsProtocol]);
 else
     var NSGetModule = XPCOMUtils.generateNSGetModule([oilsProtocol]);
-

commit ec2ed411a8c8df894d5e54c1980f6660cd5f0238
Author: Thomas Berezansky <tsbere at mvlc.org>
Date:   Tue Aug 7 20:15:24 2012 -0400

    Stage 1: Perl
    
    Attempt to ensure that we always write to oils://remote when needed.
    
    Signed-off-by: Thomas Berezansky <tsbere at mvlc.org>
    Signed-off-by: Dan Scott <dscott at laurentian.ca>

diff --git a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader.pm b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader.pm
index f7220b1..5d536dd 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader.pm
@@ -146,8 +146,9 @@ sub load {
         # when they're already logged in.
         return $self->generic_redirect(
             sprintf(
-                "https://%s%s/myopac/main",
-                $self->apache->hostname, $self->ctx->{opac_root}
+                "%s://%s%s/myopac/main",
+                $self->ctx->{proto},
+                $self->ctx->{hostname}, $self->ctx->{opac_root}
             )
         );
     }
@@ -202,7 +203,7 @@ sub load {
 # -----------------------------------------------------------------------------
 sub redirect_ssl {
     my $self = shift;
-    my $new_page = sprintf('https://%s%s', $self->apache->hostname, $self->apache->unparsed_uri);
+    my $new_page = sprintf('%s://%s%s', ($self->ctx->{is_staff} ? 'oils' : 'https'), $self->ctx->{hostname}, $self->apache->unparsed_uri);
     return $self->generic_redirect($new_page);
 }
 
@@ -212,7 +213,7 @@ sub redirect_ssl {
 # -----------------------------------------------------------------------------
 sub redirect_auth {
     my $self = shift;
-    my $login_page = sprintf('https://%s%s/login', $self->apache->hostname, $self->ctx->{opac_root});
+    my $login_page = sprintf('%s://%s%s/login',($self->ctx->{is_staff} ? 'oils' : 'https'), $self->ctx->{hostname}, $self->ctx->{opac_root});
     my $redirect_to = uri_escape($self->apache->unparsed_uri);
     return $self->generic_redirect("$login_page?redirect_to=$redirect_to");
 }
@@ -250,11 +251,12 @@ sub load_common {
     my $oils_wrapper = $self->apache->headers_in->get('OILS-Wrapper') || '';
     $ctx->{is_staff} = ($oils_wrapper =~ /true/);
     $ctx->{proto} = 'oils' if $ctx->{is_staff};
+    $ctx->{hostname} = 'remote' if $ctx->{is_staff};
     $ctx->{physical_loc} = $self->get_physical_loc;
 
     # capture some commonly accessed pages
-    $ctx->{home_page} = 'http://' . $self->apache->hostname . $self->ctx->{opac_root} . "/home";
-    $ctx->{logout_page} = 'https://' . $self->apache->hostname . $self->ctx->{opac_root} . "/logout";
+    $ctx->{home_page} = $ctx->{proto} . '://' . $ctx->{hostname} . $self->ctx->{opac_root} . "/home";
+    $ctx->{logout_page} = ($ctx->{proto} eq 'http' ? 'https' : $ctx->{proto} ) . '://' . $ctx->{hostname} . $self->ctx->{opac_root} . "/logout";
 
     if($e->authtoken($self->cgi->cookie(COOKIE_SES))) {
 
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Account.pm b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Account.pm
index c11efe1..81edf81 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Account.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Account.pm
@@ -592,7 +592,7 @@ sub handle_hold_update {
             'open-ils.circ.hold.update.batch.atomic',
             $e->authtoken, undef, \@vals
         )->gather(1);   # LFW XXX test for failure
-        $url = 'https://' . $self->apache->hostname . $self->ctx->{opac_root} . '/myopac/holds';
+        $url = $self->ctx->{proto} . '://' . $self->ctx->{hostname} . $self->ctx->{opac_root} . '/myopac/holds';
         foreach my $param (('loc', 'qtype', 'query')) {
             if ($self->cgi->param($param)) {
                 $url .= ";$param=" . uri_escape($self->cgi->param($param));
@@ -1806,7 +1806,7 @@ sub load_myopac_bookbag_update {
     # This url intentionally leaves off the edit_notes parameter, but
     # may need to add some back in for paging.
 
-    my $url = "https://" . $self->apache->hostname .
+    my $url = $self->ctx->{proto} . "://" . $self->ctx->{hostname} .
         $self->ctx->{opac_root} . "/myopac/lists?";
 
     foreach my $param (('loc', 'qtype', 'query', 'sort')) {
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Container.pm b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Container.pm
index 481099f..445654d 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Container.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Container.pm
@@ -170,8 +170,8 @@ sub mylist_warning_redirect {
 
     my $base_url = sprintf(
         "%s://%s%s/temp_warn",
-        $self->cgi->https ? 'https' : 'http',
-        $self->apache->hostname,
+        $self->ctx->{proto},
+        $self->ctx->{hostname},
         $self->ctx->{opac_root}
     );
 
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Search.pm b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Search.pm
index cecf0f0..30de8e1 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Search.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Search.pm
@@ -514,8 +514,8 @@ sub check_1hit_redirect {
 
     my $base_url = sprintf(
         '%s://%s%s/record/%s',
-        ($ctx->{is_staff} ? 'oils' : $ctx->{proto}),
-        ($ctx->{is_staff} ? 'remote' : $self->apache->hostname),
+        $self->ctx->{proto},
+        $self->ctx->{hostname},
         $self->ctx->{opac_root},
         $$rec_ids[0],
     );
@@ -683,9 +683,9 @@ sub call_number_browse_standalone {
 
     if (my $cnfrag = $self->cgi->param("query")) {
         my $url = sprintf(
-            'http%s://%s%s/cnbrowse?cn=%s',
-            $self->cgi->https ? "s" : "",
-            $self->apache->hostname,
+            '%s://%s%s/cnbrowse?cn=%s',
+            $self->ctx->{proto},
+            $self->ctx->{hostname},
             $self->ctx->{opac_root},
             $cnfrag # XXX some kind of escaping needed here?
         );
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGKPacLoader.pm b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGKPacLoader.pm
index 2f0e49e..77a7eae 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGKPacLoader.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGKPacLoader.pm
@@ -241,7 +241,7 @@ sub load_kpac_config {
     $ctx->{kpac_layout} = $layout;
     $ctx->{kpac_config} = $kpac_config;
     $ctx->{kpac_root} = $ctx->{base_path} . "/kpac"; 
-    $ctx->{home_page} = 'http://' . $self->apache->hostname . $ctx->{kpac_root} . "/home";
+    $ctx->{home_page} = $ctx->{proto} . '://' . $ctx->{hostname} . $ctx->{kpac_root} . "/home";
     $ctx->{global_search_filter} = $kpac_config->{global_filter};
 }
 

-----------------------------------------------------------------------

Summary of changes:
 .../src/perlmods/lib/OpenILS/WWW/EGCatLoader.pm    |   14 +-
 .../lib/OpenILS/WWW/EGCatLoader/Account.pm         |    4 +-
 .../lib/OpenILS/WWW/EGCatLoader/Container.pm       |    4 +-
 .../perlmods/lib/OpenILS/WWW/EGCatLoader/Search.pm |   10 +-
 .../src/perlmods/lib/OpenILS/WWW/EGKPacLoader.pm   |    2 +-
 .../xul/staff_client/components/oils_protocol.js   |  197 +++++++++++++++++++-
 6 files changed, 207 insertions(+), 24 deletions(-)


hooks/post-receive
-- 
Evergreen ILS


More information about the open-ils-commits mailing list