<commit_before>"use strict";

describe("stream/node", function () {

    function NodeMockedStream () {
        this._events = {};
    }

    NodeMockedStream.prototype = {

        _events: {},

        _fire: function (event) {
            var parameters = [].slice.call(arguments, 1);
            this._events[event].apply(null, parameters);
        },

        on: function (event, callback) {
            assert(!this._events[event]);
            this._events[event] = callback;
            return this;
        },

        once: function (event, callback) {
            return this.on(event, function () {
                callback();
                delete this._events[event];
            }.bind(this));
        }

    };

    if (gpf.hosts.nodejs === gpf.host()) {

        describe("gpf.node.ReadableStream", function () {

            it("configures the stream by hooking the events", function (done) {
                var mockedStream = new NodeMockedStream(),
                    iReadableStream = new gpf.node.ReadableStream(mockedStream),
                    iWritableString = new gpf.stream.WritableString();
                assert("function" === typeof mockedStream._events.error);
                iReadableStream.read(iWritableString)
                    .then(done, done);
                assert("function" === typeof mockedStream._events.data);
                assert("function" === typeof mockedStream._events.end);
                mockedStream._fire("end");
            });

            it("supports several read events", function (done) {
                var mockedStream = new NodeMockedStream(),
                    iReadableStream = new gpf.node.ReadableStream(mockedStream),
                    iWritableString = new gpf.stream.WritableString();
                iReadableStream.read(iWritableString)
                    .then(function () {
                        assert(iWritableString.toString() === "Hello World");
                    })
                    .then(done, done);
                // 'Simple' state engine to simulate data flow
                var paused = false,
                    step = 0;
                mockedStream.pause = function () {
                    assert(!paused);
                    paused = true;
                };
                mockedStream.resume = function () {
                    assert(paused);
                    paused = false;
                    setTimeout(function () {
                        ++step;
                        if (1 === step) {
                            mockedStream._fire("data", "World");
                        } else {
                            mockedStream._fire("end");
                        }
                    }, 0);
                };
                mockedStream._fire("data", "Hello ");
            });

            it("handles errors", function (done) {
                var mockedStream = new NodeMockedStream(),
                    iReadableStream = new gpf.node.ReadableStream(mockedStream),
                    iWritableString = new gpf.stream.WritableString();
                iReadableStream.read(iWritableString)
                    .then(function () {
                        assert(false);
                    })
                    .then(undefined, function (e) {
                        assert(e === "error");
                    })
                    .then(done, done);
                // 'Simple' state engine to simulate data & error flow
                var paused = false;
                mockedStream.pause = function () {
                    assert(!paused);
                    paused = true;
                };
                mockedStream.resume = function () {
                    assert(paused);
                    paused = false;
                    setTimeout(function () {
                        mockedStream._fire("error", "error");
                    }, 0);
                };
                mockedStream._fire("data", "Hello ");
            });

            it("handles errors of write stream", function (done) {
                var mockedStream = new NodeMockedStream(),
                    iReadableStream = new gpf.node.ReadableStream(mockedStream),
                    iMockedWritableStream = {
                        write: function (buffer) {
                            return Promise.reject(buffer);
                        }
                    };
                mockedStream.pause = function () {};
                iReadableStream.read(iMockedWritableStream)
                    .then(function () {
                        assert(false); // Should not succeed
                    }, function (e) {
                        assert(e === "error");
                    })
                    .then(done, done);
                mockedStream._fire("data", "error");
            });

            it("prevents any subsequent use when an error occurred", function (done) {
                var mockedStream = new NodeMockedStream(),
                    iReadableStream = new gpf.node.ReadableStream(mockedStream),
                    iWritableString = new gpf.stream.WritableString();
                iReadableStream.read(iWritableString)
                    .then(function () {
                        assert(false);
                    })
                    .then(undefined, function (e) {
                        assert(e === "error");
                        return iReadableStream.read(iWritableString);
                    })
                    .then(undefined, function (e) {
                        assert(e instanceof gpf.Error.InvalidStreamState);
                    })
                    .then(done, done);
                mockedStream._fire("error", "error");
            });

            it("prevents any subsequent use when ended", function (done) {
                var mockedStream = new NodeMockedStream(),
                    iReadableStream = new gpf.node.ReadableStream(mockedStream),
                    iWritableString = new gpf.stream.WritableString();
                iReadableStream.read(iWritableString)
                    .then(function () {
                        return iReadableStream.read(iWritableString);
                    })
                    .then(undefined, function (e) {
                        assert(e instanceof gpf.Error.InvalidStreamState);
                    })
                    .then(done, done);
                mockedStream._fire("end");
            });

        });

        describe("gpf.node.ReadableStream", function () {

            it("configures the stream by hooking the events", function () {
                var mockedStream = new NodeMockedStream(),
                    iWritableStream = new gpf.node.WritableStream(mockedStream);
                assert(iWritableStream); // avoid JSHint error
                assert("function" === typeof mockedStream._events.error);
            });

            it("passes the buffer to the inner stream", function (done) {
                var mockedStream = new NodeMockedStream(),
                    iWritableStream = new gpf.node.WritableStream(mockedStream);
                assert("function" === typeof mockedStream._events.error);
                mockedStream.write = function (buffer) {
                    assert(buffer === "Hello World");
                    return true;
                };
                iWritableStream.write("Hello World")
                    .then(done, done);
                assert(!mockedStream._events.drain);
            });

            it("supports several write calls", function (done) {
                var mockedStream = new NodeMockedStream(),
                    iWritableStream = new gpf.node.WritableStream(mockedStream),
                    concatenatedBuffer = "";
                assert("function" === typeof mockedStream._events.error);
                mockedStream.write = function (buffer) {
                    concatenatedBuffer += buffer;
                    return true;
                };
                iWritableStream.write("Hello ")
                    .then(function () {
                        return iWritableStream.write("World");
                    })
                    .then(function () {
                        assert(concatenatedBuffer === "Hello World");
                    })
                    .then(done, done);
                assert(!mockedStream._events.drain);
            });

            it("waits for the drain event if the stream is full", function (done) {
                var mockedStream = new NodeMockedStream(),
                    iWritableStream = new gpf.node.WritableStream(mockedStream),
                    drained = false;
                assert("function" === typeof mockedStream._events.error);
                mockedStream.write = function (buffer) {
                    assert(buffer === "Hello World");
                    return false;
                };
                iWritableStream.write("Hello World")
                    .then(function () {
                        assert(drained);
                        assert(!mockedStream._events.drain); // once has been used
                    })
                    .then(done, done);
                assert("function" === typeof mockedStream._events.drain);
                drained = true;
                mockedStream._fire("drain");
            });

            it("handles errors", function (done) {
                var mockedStream = new NodeMockedStream(),
                    iWritableStream = new gpf.node.WritableStream(mockedStream);
                assert("function" === typeof mockedStream._events.error);
                mockedStream.write = function () {
                    mockedStream._fire("error", "error");
                };
                iWritableStream.write("Hello World")
                    .then(undefined, function (e) {
                        assert(e === "error");
                    })
                    .then(done, done);
            });

            it("prevents any subsequent use when an error occurred", function (done) {
                var mockedStream = new NodeMockedStream(),
                    iWritableStream = new gpf.node.WritableStream(mockedStream);
                assert("function" === typeof mockedStream._events.error);
                mockedStream.write = function () {
                    mockedStream._fire("error", "error");
                };
                iWritableStream.write("Hello World")
                    .then(undefined, function (e) {
                        assert(e === "error");
                        return iWritableStream.write("Hello World");
                    })
                    .then(undefined, function (e) {
                        assert(e instanceof gpf.Error.InvalidStreamState);
                    })
                    .then(done, done);
            });

        });

    }

});
<commit_msg>Deepscan.io feedback (#229)<commit_after>"use strict";

describe("stream/node", function () {

    function NodeMockedStream () {
        this._events = {};
    }

    NodeMockedStream.prototype = {

        _events: {},

        _fire: function (event) {
            var parameters = [].slice.call(arguments, 1);
            this._events[event].apply(null, parameters);
        },

        on: function (event, callback) {
            assert(!this._events[event]);
            this._events[event] = callback;
            return this;
        },

        once: function (event, callback) {
            return this.on(event, function () {
                callback();
                delete this._events[event];
            }.bind(this));
        }

    };

    if (gpf.hosts.nodejs === gpf.host()) {

        describe("gpf.node.ReadableStream", function () {

            it("configures the stream by hooking the events", function (done) {
                var mockedStream = new NodeMockedStream(),
                    iReadableStream = new gpf.node.ReadableStream(mockedStream),
                    iWritableString = new gpf.stream.WritableString();
                assert("function" === typeof mockedStream._events.error);
                iReadableStream.read(iWritableString)
                    .then(done, done);
                assert("function" === typeof mockedStream._events.data);
                assert("function" === typeof mockedStream._events.end);
                mockedStream._fire("end");
            });

            it("supports several read events", function (done) {
                var mockedStream = new NodeMockedStream(),
                    iReadableStream = new gpf.node.ReadableStream(mockedStream),
                    iWritableString = new gpf.stream.WritableString();
                iReadableStream.read(iWritableString)
                    .then(function () {
                        assert(iWritableString.toString() === "Hello World");
                    })
                    .then(done, done);
                // 'Simple' state engine to simulate data flow
                var paused = false,
                    step = 0;
                mockedStream.pause = function () {
                    assert(!paused);
                    paused = true;
                };
                mockedStream.resume = function () {
                    assert(paused);
                    paused = false;
                    setTimeout(function () {
                        ++step;
                        if (1 === step) {
                            mockedStream._fire("data", "World");
                        } else {
                            mockedStream._fire("end");
                        }
                    }, 0);
                };
                mockedStream._fire("data", "Hello ");
            });

            it("handles errors", function (done) {
                var mockedStream = new NodeMockedStream(),
                    iReadableStream = new gpf.node.ReadableStream(mockedStream),
                    iWritableString = new gpf.stream.WritableString();
                iReadableStream.read(iWritableString)
                    .then(function () {
                        assert(false);
                    })
                    .then(undefined, function (e) {
                        assert(e === "error");
                    })
                    .then(done, done);
                // 'Simple' state engine to simulate data & error flow
                var paused = false;
                mockedStream.pause = function () {
                    assert(!paused);
                    paused = true;
                };
                mockedStream.resume = function () {
                    assert(paused);
                    paused = false;
                    setTimeout(function () {
                        mockedStream._fire("error", "error");
                    }, 0);
                };
                mockedStream._fire("data", "Hello ");
            });

            it("handles errors of write stream", function (done) {
                var mockedStream = new NodeMockedStream(),
                    iReadableStream = new gpf.node.ReadableStream(mockedStream),
                    iMockedWritableStream = {
                        write: function (buffer) {
                            return Promise.reject(buffer);
                        }
                    };
                mockedStream.pause = function () {};
                iReadableStream.read(iMockedWritableStream)
                    .then(function () {
                        assert(false); // Should not succeed
                    }, function (e) {
                        assert(e === "error");
                    })
                    .then(done, done);
                mockedStream._fire("data", "error");
            });

            it("prevents any subsequent use when an error occurred", function (done) {
                var mockedStream = new NodeMockedStream(),
                    iReadableStream = new gpf.node.ReadableStream(mockedStream),
                    iWritableString = new gpf.stream.WritableString();
                iReadableStream.read(iWritableString)
                    .then(function () {
                        assert(false);
                    })
                    .then(undefined, function (e) {
                        assert(e === "error");
                        return iReadableStream.read(iWritableString);
                    })
                    .then(undefined, function (e) {
                        assert(e instanceof gpf.Error.InvalidStreamState);
                    })
                    .then(done, done);
                mockedStream._fire("error", "error");
            });

            it("prevents any subsequent use when ended", function (done) {
                var mockedStream = new NodeMockedStream(),
                    iReadableStream = new gpf.node.ReadableStream(mockedStream),
                    iWritableString = new gpf.stream.WritableString();
                iReadableStream.read(iWritableString)
                    .then(function () {
                        return iReadableStream.read(iWritableString);
                    })
                    .then(undefined, function (e) {
                        assert(e instanceof gpf.Error.InvalidStreamState);
                    })
                    .then(done, done);
                mockedStream._fire("end");
            });

        });

        describe("gpf.node.ReadableStream", function () {

            it("configures the stream by hooking the events", function () {
                var mockedStream = new NodeMockedStream(),
                    iWritableStream = new gpf.node.WritableStream(mockedStream);
                assert("function" === typeof iWritableStream.write); // avoid JSHint error
                assert("function" === typeof mockedStream._events.error);
            });

            it("passes the buffer to the inner stream", function (done) {
                var mockedStream = new NodeMockedStream(),
                    iWritableStream = new gpf.node.WritableStream(mockedStream);
                assert("function" === typeof mockedStream._events.error);
                mockedStream.write = function (buffer) {
                    assert(buffer === "Hello World");
                    return true;
                };
                iWritableStream.write("Hello World")
                    .then(done, done);
                assert(!mockedStream._events.drain);
            });

            it("supports several write calls", function (done) {
                var mockedStream = new NodeMockedStream(),
                    iWritableStream = new gpf.node.WritableStream(mockedStream),
                    concatenatedBuffer = "";
                assert("function" === typeof mockedStream._events.error);
                mockedStream.write = function (buffer) {
                    concatenatedBuffer += buffer;
                    return true;
                };
                iWritableStream.write("Hello ")
                    .then(function () {
                        return iWritableStream.write("World");
                    })
                    .then(function () {
                        assert(concatenatedBuffer === "Hello World");
                    })
                    .then(done, done);
                assert(!mockedStream._events.drain);
            });

            it("waits for the drain event if the stream is full", function (done) {
                var mockedStream = new NodeMockedStream(),
                    iWritableStream = new gpf.node.WritableStream(mockedStream),
                    drained = false;
                assert("function" === typeof mockedStream._events.error);
                mockedStream.write = function (buffer) {
                    assert(buffer === "Hello World");
                    return false;
                };
                iWritableStream.write("Hello World")
                    .then(function () {
                        assert(drained);
                        assert(!mockedStream._events.drain); // once has been used
                    })
                    .then(done, done);
                assert("function" === typeof mockedStream._events.drain);
                drained = true;
                mockedStream._fire("drain");
            });

            it("handles errors", function (done) {
                var mockedStream = new NodeMockedStream(),
                    iWritableStream = new gpf.node.WritableStream(mockedStream);
                assert("function" === typeof mockedStream._events.error);
                mockedStream.write = function () {
                    mockedStream._fire("error", "error");
                };
                iWritableStream.write("Hello World")
                    .then(undefined, function (e) {
                        assert(e === "error");
                    })
                    .then(done, done);
            });

            it("prevents any subsequent use when an error occurred", function (done) {
                var mockedStream = new NodeMockedStream(),
                    iWritableStream = new gpf.node.WritableStream(mockedStream);
                assert("function" === typeof mockedStream._events.error);
                mockedStream.write = function () {
                    mockedStream._fire("error", "error");
                };
                iWritableStream.write("Hello World")
                    .then(undefined, function (e) {
                        assert(e === "error");
                        return iWritableStream.write("Hello World");
                    })
                    .then(undefined, function (e) {
                        assert(e instanceof gpf.Error.InvalidStreamState);
                    })
                    .then(done, done);
            });

        });

    }

});
<|endoftext|>


<commit_before>module.exports = addSubnodes;

function addSubnodes(root, node) {
  var subnodesGroup = root.append("g").attr("class", "subnodes");
  subnodesGroup.selectAll("g")
    .data(node.subnodes)
    .enter().append("g")
      .attr("class", function(d) { return "subnode " + d.class; })
      .each(function(d, i) {
        const parent = d3.select(this);

        // Create the circle and text nodes within the subnode group
        var circleDom = parent.append("circle")
          .attr("cx", i * 22)
          .attr("cy", "0")
          .attr("r", "10");
        var textDom = parent.append("text")
          .text(d.label)
          .attr("x", i * 22)
          .attr("y", "5");

        // Center the text within the circle
        var circleBox = circleDom.node().getBBox();
        var textBox = textDom.node().getBBox();
        textDom.attr("transform", "translate(" +
          -(textBox.width / 2) + "," +
          -((circleBox.height - textBox.height - 5) / 2) + ")");

        // Make the tooltip if requested.
        if (d.tooltip) {
          const tooltipGroup = parent.append('g').attr('class', 'qc-tooltip');

          // Append the tooltip text and measure its dimensions so we can size the surrounding
          // rectangle.
          tooltipGroup.append('text')
            .text(d.ref['@type'][0])
            .attr('x', 5)
            .attr('y', 60);
          const labelBBox = tooltipGroup.node().getBBox();

          // Append the tooltip rectangle.
          tooltipGroup.insert('rect', 'text')
            .attr('x', 0)
            .attr('y', 50)
            .attr('width', labelBBox.width + 10)
            .attr('height', labelBBox.height + 5);
          const tooltipBBox = tooltipGroup.node().getBBox();

          // Center the group on the parent node for the width of the text.
          tooltipGroup.attr('transform', `translate(${(-tooltipBBox.width / 2) + (i * 22)},0)`);
        }
      });

  return subnodesGroup;
}
<commit_msg>Still trying to get positioning<commit_after>module.exports = addSubnodes;

function addSubnodes(root, node) {
  var subnodesGroup = root.append("g").attr("class", "subnodes");
  subnodesGroup.selectAll("g")
    .data(node.subnodes)
    .enter().append("g")
      .attr("class", function(d) { return "subnode " + d.class; })
      .each(function(d, i) {
        const parent = d3.select(this);

        // Create the circle and text nodes within the subnode group
        var circleDom = parent.append("circle")
          .attr("cx", i * 22)
          .attr("cy", "0")
          .attr("r", "10");
        var textDom = parent.append("text")
          .text(d.label)
          .attr("x", i * 22)
          .attr("y", "5");

        // Center the text within the circle
        var circleBox = circleDom.node().getBBox();
        var textBox = textDom.node().getBBox();
        textDom.attr("transform", "translate(" +
          -(textBox.width / 2) + "," +
          -((circleBox.height - textBox.height - 5) / 2) + ")");

        // Make the tooltip if requested.
        if (d.tooltip) {
          const tooltipGroup = parent.append('g').attr('class', 'qc-tooltip');

          // Append the tooltip text and measure its dimensions so we can size the surrounding
          // rectangle.
          tooltipGroup.append('text')
            .text(d.ref['@type'][0])
            .attr('x', 5)
            .attr('y', 0);
          const labelBBox = tooltipGroup.node().getBBox();

          // Append the tooltip rectangle.
          tooltipGroup.insert('rect', 'text')
            .attr('x', 0)
            .attr('y', 10)
            .attr('width', labelBBox.width + 10)
            .attr('height', labelBBox.height + 5);
          const tooltipBBox = tooltipGroup.node().getBBox();

          // Center the group on the parent node for the width of the text.
          tooltipGroup.attr('transform', `translate(${(-tooltipBBox.width / 2) + (i * 22)},0)`);
        }
      });

  return subnodesGroup;
}
<|endoftext|>


<commit_before>
var common = require('./../config/common.js');
var configSmartPay = common.config();
var crypto = require('crypto');
var zlib = require('zlib');

// Using https://docs.adyen.com/developers/ecommerce-integration/hmac-signature-calculation for sending and receiving payments

module.exports = {

    // sets application payment data
    addApplicationData: function(appid, formFields, applicationDetail, application, userDocumentCount, loggedIn) {

        var documentCount = userDocumentCount.doc_count;
        var documentCountLabel = documentCount == 1 ? 'document.' : 'documents.';
        var orderData = 'You are paying to legalise ' + documentCount + ' ' + documentCountLabel;

        if(loggedIn === true) {
            orderData = orderData + '

When adding a new card, you\'ll see a \'Remember these details\' box. Untick this box if you don\'t want to save your card for future applications.';
        }

        formFields.merchantReference = application.unique_app_id;
        formFields.orderData = orderData;
        formFields.paymentAmount = Math.round(applicationDetail.payment_amount * 1e2); // multiply by 100 to get value in minor currency
        formFields.merchantReturnData = appid;

        formFields.allowedMethods = ''; //pre-selection of card type (obsolete)

        return formFields;
    },

    // set the date fields to one day in the future
    addDateFields: function(formFields) {

        var shipBeforeDate = new Date();
        shipBeforeDate.setDate(shipBeforeDate.getDate() + 1);
        var shipBeforeDateValue = shipBeforeDate.toISOString().substr(0, 10);

        var sessionValidityDate = new Date();
        sessionValidityDate.setMinutes(sessionValidityDate.getMinutes() + configSmartPay.configs.sessionValidity);
        var sessionValidityValue = sessionValidityDate.toISOString().substr(0, 19) + 'Z';

        // add date fields to form array
        formFields.shipBeforeDate = shipBeforeDateValue;
        formFields.sessionValidity = sessionValidityValue;

        // return to caller
        return formFields;
    },

    // adds data required for saving card details
    addOneClickFields : function(appid, formFields, userDetails, applicationDetail) {

        var oneclick_reference = applicationDetail.oneclick_reference;

        // if there is a user session active, get their recurring payment reference
        // and set the relevant optional fields in the SmartPay request object
        if (oneclick_reference != '0')
        {
            formFields.shopperReference = oneclick_reference;
            formFields.recurringContract = 'ONECLICK';
            formFields.shopperEmail = userDetails.email;
        }

        // return to caller
        return formFields;
    },

    lookupPaymentMethod : function(paymentMethod) {
        return configSmartPay.paymentMethods[paymentMethod];
    },

    // compress order data using gzip, encode in base64
    // also converts the order data into HTML fragment first
    compressAndEncodeOrderData : function (formFields) {

        // put order data value into HTML paragraph tags
        var htmlFragment = '
' + formFields.orderData + '
';

        // compress using gzip and encode in base64 format
        // (blocking call so no need for callback)
        htmlFragment = zlib.gzipSync(htmlFragment).toString('base64');

        // assign encoded value back into the formFields array
        formFields.orderData = htmlFragment;

        // return to caller
        return formFields;
    },

    // calculates the signature using HMAC code
    //
    calculateMerchantSignature: function(formFields) {

        // get HMAC secret key
        var hmacKey = configSmartPay.configs.HMAC;

        var data = {
            paymentAmount      : formFields.paymentAmount,
            currencyCode       : configSmartPay.configs.currencyCode,
            shipBeforeDate     : formFields.shipBeforeDate,
            merchantReference  : formFields.merchantReference,
            skinCode           : configSmartPay.configs.skinCode,
            merchantAccount    : configSmartPay.configs.merchantAccount,
            sessionValidity    : formFields.sessionValidity,
            shopperEmail       : formFields.shopperEmail || '',
            shopperReference   : formFields.shopperReference || '',
            recurringContract  : formFields.recurringContract || '',
            allowedMethods     : formFields.allowedMethods,
            blockedMethods     : '',
            shopperStatement   : '',
            billingAddressType : '',
            skipSelection      : ((formFields.allowedMethods !== '') ? 'true' : ''),
            orderData          : formFields.orderData,
            merchantReturnData : formFields.merchantReturnData,
            resURL             : configSmartPay.configs.resultURL
        }

        //sort the payment details into alphabetical order (sorted by key)
        var orderedData = {};
        Object.keys(data).sort().forEach(function(key) {
            orderedData[key] = data[key];
        });

        //Concatenate all the keys together, followed by all the values delimited by colon (key:key:key:key:value:value:value:value)
        var keys = []
        var values = []
        for (var key in orderedData) {
            keys.push(key)
            values.push(orderedData[key].toString().replace(/:/g,'\\:'))
        }
        var signingString = keys.concat(values).join(":");

        // calculate HMAC string and encode in base64
        var hash = crypto.createHmac('sha256', new Buffer(hmacKey, 'hex')).update(signingString, 'utf-8').digest('base64');

        // return to caller
        return hash;
    },

    // decode signature returned from SmartPay to verify data integrity using HMAC code
    decodeReturnedMerchantSignature: function(queryString) {

        // get HMAC secret key
        var hmacKey = configSmartPay.configs.HMAC;

        // get hold of query string parameters
        var data = {
            authResult : queryString.authResult,
            pspReference : queryString.pspReference,
            merchantReference : queryString.merchantReference,
            skinCode : queryString.skinCode,
            merchantReturnData : ((queryString.merchantReturnData !== undefined) ? queryString.merchantReturnData : ''),
            paymentMethod : queryString.paymentMethod,
            shopperLocale: queryString.shopperLocale,
            skinCode: queryString.skinCode
        }

        //sort the payment details into alphabetical order (sorted by key)
        var orderedData = {};
        Object.keys(data).sort().forEach(function(key) {
            //console.log("key " + JSON.stringify(key) + " and " + data[key])
            orderedData[key] = data[key];
        });

        //Concatenate all the keys together, followed by all the values delimited by colon (key:key:key:key:value:value:value:value)
        var keys = []
        var values = []
        for (var key in orderedData) {
            //console.log(orderedData[key])
            keys.push(key)
            values.push(orderedData[key].toString().replace(/:/g,'\\:'))
        }
        var queryStringValues = keys.concat(values).join(":");

        // encoded signature we are validating against
        var merchantSig = queryString.merchantSig;

        // calculate HMAC string and encode in base64
        var hash = crypto.createHmac('sha256',  new Buffer(hmacKey, 'hex')).update(queryStringValues, 'utf-8').digest('base64');

        return (hash === merchantSig);
    },

    buildParameters: function(formFields, merchantSignature) {
        var params = {
            paymentAmount      : formFields.paymentAmount,
            currencyCode       : configSmartPay.configs.currencyCode,
            shipBeforeDate     : formFields.shipBeforeDate,
            merchantReference  : formFields.merchantReference,
            skinCode           : configSmartPay.configs.skinCode,
            merchantAccount    : configSmartPay.configs.merchantAccount,
            sessionValidity    : formFields.sessionValidity,
            shopperEmail       : formFields.shopperEmail || '',
            shopperReference   : formFields.shopperReference || '',
            recurringContract  : formFields.recurringContract || '',
            allowedMethods     : formFields.allowedMethods,
            blockedMethods     : '',
            shopperStatement   : '',
            billingAddressType : '',
            skipSelection      : ((formFields.allowedMethods !== '') ? 'true' : ''),
            orderData          : formFields.orderData,
            merchantReturnData : formFields.merchantReturnData,
            resURL             : configSmartPay.configs.resultURL,
            merchantSig        : merchantSignature
        };

        return params;
    },

    loggedInStatus: function amILoggedIn(req) {
        if (req.session && req.session.passport && req.session.passport.user) {
            return true;
        }
        else {
            return false;
        }
    },

    /**
     * Get the email address of the current in User
     * @param req
     * @returns email {string}
     */
    loggedInUserEmail: function whatsUsersEmail(req)
    {
        if (req.session && req.session.passport && req.session.passport.user && req.session.email && req.session.email !== null) {
            return req.session.email;
        } else {
            return 'Not Logged In';
        }
    },

    isSessionValid: function getSomeSessionInfo(req) {
        if (typeof(req.session.appSubmittedStatus) != 'undefined') {
            console.log('session is valid - proceed to payment unsuccessful page');
            return true;
        }else{
            console.log('session is invalid - proceed to session expiry page');
            return false;
        }
    }

};
<commit_msg>Check for authResult before trying to process the response<commit_after>
var common = require('./../config/common.js');
var configSmartPay = common.config();
var crypto = require('crypto');
var zlib = require('zlib');

// Using https://docs.adyen.com/developers/ecommerce-integration/hmac-signature-calculation for sending and receiving payments

module.exports = {

    // sets application payment data
    addApplicationData: function(appid, formFields, applicationDetail, application, userDocumentCount, loggedIn) {

        var documentCount = userDocumentCount.doc_count;
        var documentCountLabel = documentCount == 1 ? 'document.' : 'documents.';
        var orderData = 'You are paying to legalise ' + documentCount + ' ' + documentCountLabel;

        if(loggedIn === true) {
            orderData = orderData + '

When adding a new card, you\'ll see a \'Remember these details\' box. Untick this box if you don\'t want to save your card for future applications.';
        }

        formFields.merchantReference = application.unique_app_id;
        formFields.orderData = orderData;
        formFields.paymentAmount = Math.round(applicationDetail.payment_amount * 1e2); // multiply by 100 to get value in minor currency
        formFields.merchantReturnData = appid;

        formFields.allowedMethods = ''; //pre-selection of card type (obsolete)

        return formFields;
    },

    // set the date fields to one day in the future
    addDateFields: function(formFields) {

        var shipBeforeDate = new Date();
        shipBeforeDate.setDate(shipBeforeDate.getDate() + 1);
        var shipBeforeDateValue = shipBeforeDate.toISOString().substr(0, 10);

        var sessionValidityDate = new Date();
        sessionValidityDate.setMinutes(sessionValidityDate.getMinutes() + configSmartPay.configs.sessionValidity);
        var sessionValidityValue = sessionValidityDate.toISOString().substr(0, 19) + 'Z';

        // add date fields to form array
        formFields.shipBeforeDate = shipBeforeDateValue;
        formFields.sessionValidity = sessionValidityValue;

        // return to caller
        return formFields;
    },

    // adds data required for saving card details
    addOneClickFields : function(appid, formFields, userDetails, applicationDetail) {

        var oneclick_reference = applicationDetail.oneclick_reference;

        // if there is a user session active, get their recurring payment reference
        // and set the relevant optional fields in the SmartPay request object
        if (oneclick_reference != '0')
        {
            formFields.shopperReference = oneclick_reference;
            formFields.recurringContract = 'ONECLICK';
            formFields.shopperEmail = userDetails.email;
        }

        // return to caller
        return formFields;
    },

    lookupPaymentMethod : function(paymentMethod) {
        return configSmartPay.paymentMethods[paymentMethod];
    },

    // compress order data using gzip, encode in base64
    // also converts the order data into HTML fragment first
    compressAndEncodeOrderData : function (formFields) {

        // put order data value into HTML paragraph tags
        var htmlFragment = '
' + formFields.orderData + '
';

        // compress using gzip and encode in base64 format
        // (blocking call so no need for callback)
        htmlFragment = zlib.gzipSync(htmlFragment).toString('base64');

        // assign encoded value back into the formFields array
        formFields.orderData = htmlFragment;

        // return to caller
        return formFields;
    },

    // calculates the signature using HMAC code
    //
    calculateMerchantSignature: function(formFields) {

        // get HMAC secret key
        var hmacKey = configSmartPay.configs.HMAC;

        var data = {
            paymentAmount      : formFields.paymentAmount,
            currencyCode       : configSmartPay.configs.currencyCode,
            shipBeforeDate     : formFields.shipBeforeDate,
            merchantReference  : formFields.merchantReference,
            skinCode           : configSmartPay.configs.skinCode,
            merchantAccount    : configSmartPay.configs.merchantAccount,
            sessionValidity    : formFields.sessionValidity,
            shopperEmail       : formFields.shopperEmail || '',
            shopperReference   : formFields.shopperReference || '',
            recurringContract  : formFields.recurringContract || '',
            allowedMethods     : formFields.allowedMethods,
            blockedMethods     : '',
            shopperStatement   : '',
            billingAddressType : '',
            skipSelection      : ((formFields.allowedMethods !== '') ? 'true' : ''),
            orderData          : formFields.orderData,
            merchantReturnData : formFields.merchantReturnData,
            resURL             : configSmartPay.configs.resultURL
        }

        //sort the payment details into alphabetical order (sorted by key)
        var orderedData = {};
        Object.keys(data).sort().forEach(function(key) {
            orderedData[key] = data[key];
        });

        //Concatenate all the keys together, followed by all the values delimited by colon (key:key:key:key:value:value:value:value)
        var keys = []
        var values = []
        for (var key in orderedData) {
            keys.push(key)
            values.push(orderedData[key].toString().replace(/:/g,'\\:'))
        }
        var signingString = keys.concat(values).join(":");

        // calculate HMAC string and encode in base64
        var hash = crypto.createHmac('sha256', new Buffer(hmacKey, 'hex')).update(signingString, 'utf-8').digest('base64');

        // return to caller
        return hash;
    },

    // decode signature returned from SmartPay to verify data integrity using HMAC code
    decodeReturnedMerchantSignature: function(queryString) {

        if (queryString.authResult == 'AUTHORISED') {
        // get HMAC secret key
        var hmacKey = configSmartPay.configs.HMAC;

        // get hold of query string parameters
        var data = {
            authResult: queryString.authResult,
            pspReference: queryString.pspReference,
            merchantReference: queryString.merchantReference,
            skinCode: queryString.skinCode,
            merchantReturnData: ((queryString.merchantReturnData !== undefined) ? queryString.merchantReturnData : ''),
            paymentMethod: queryString.paymentMethod,
            shopperLocale: queryString.shopperLocale,
            skinCode: queryString.skinCode
        }

        //sort the payment details into alphabetical order (sorted by key)
        var orderedData = {};
        Object.keys(data).sort().forEach(function (key) {
            //console.log("key " + JSON.stringify(key) + " and " + data[key])
            orderedData[key] = data[key];
        });

        //Concatenate all the keys together, followed by all the values delimited by colon (key:key:key:key:value:value:value:value)
        var keys = []
        var values = []
        for (var key in orderedData) {
            //console.log(orderedData[key])
            keys.push(key)
            values.push(orderedData[key].toString().replace(/:/g, '\\:'))
        }
        var queryStringValues = keys.concat(values).join(":");

        // encoded signature we are validating against
        var merchantSig = queryString.merchantSig;

        // calculate HMAC string and encode in base64
        var hash = crypto.createHmac('sha256', new Buffer(hmacKey, 'hex')).update(queryStringValues, 'utf-8').digest('base64');

        return (hash === merchantSig);
    }
    else {
            return false
        }
    },

    buildParameters: function(formFields, merchantSignature) {
        var params = {
            paymentAmount      : formFields.paymentAmount,
            currencyCode       : configSmartPay.configs.currencyCode,
            shipBeforeDate     : formFields.shipBeforeDate,
            merchantReference  : formFields.merchantReference,
            skinCode           : configSmartPay.configs.skinCode,
            merchantAccount    : configSmartPay.configs.merchantAccount,
            sessionValidity    : formFields.sessionValidity,
            shopperEmail       : formFields.shopperEmail || '',
            shopperReference   : formFields.shopperReference || '',
            recurringContract  : formFields.recurringContract || '',
            allowedMethods     : formFields.allowedMethods,
            blockedMethods     : '',
            shopperStatement   : '',
            billingAddressType : '',
            skipSelection      : ((formFields.allowedMethods !== '') ? 'true' : ''),
            orderData          : formFields.orderData,
            merchantReturnData : formFields.merchantReturnData,
            resURL             : configSmartPay.configs.resultURL,
            merchantSig        : merchantSignature
        };

        return params;
    },

    loggedInStatus: function amILoggedIn(req) {
        if (req.session && req.session.passport && req.session.passport.user) {
            return true;
        }
        else {
            return false;
        }
    },

    /**
     * Get the email address of the current in User
     * @param req
     * @returns email {string}
     */
    loggedInUserEmail: function whatsUsersEmail(req)
    {
        if (req.session && req.session.passport && req.session.passport.user && req.session.email && req.session.email !== null) {
            return req.session.email;
        } else {
            return 'Not Logged In';
        }
    },

    isSessionValid: function getSomeSessionInfo(req) {
        if (typeof(req.session.appSubmittedStatus) != 'undefined') {
            console.log('session is valid - proceed to payment unsuccessful page');
            return true;
        }else{
            console.log('session is invalid - proceed to session expiry page');
            return false;
        }
    }

};
<|endoftext|>


<commit_before>/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
*/

/**
 * Execute a cordova command.  It is up to the native side whether this action
 * is synchronous or asynchronous.  The native side can return:
 *      Synchronous: PluginResult object as a JSON string
 *      Asynchrounous: Empty string ""
 * If async, the native side will cordova.callbackSuccess or cordova.callbackError,
 * depending upon the result of the action.
 *
 * @param {Function} success    The success callback
 * @param {Function} fail       The fail callback
 * @param {String} service      The name of the service to use
 * @param {String} action       Action to be run in cordova
 * @param {String[]} [args]     Zero or more arguments to pass to the method
 */
var cordova = require('cordova'),
    callback = require('cordova/plugin/android/callback'),
    polling = require('cordova/plugin/android/polling'),
    nativeApiProvider = require('cordova/plugin/android/nativeapiprovider'),
    jsToNativeBridgeMode,
    nativeToJsBridgeMode,
    jsToNativeModes = {
        PROMPT: 0,
        JS_OBJECT: 1,
        // This mode is currently for benchmarking purposes only. It must be enabled
        // on the native side through the ENABLE_LOCATION_CHANGE_EXEC_MODE
        // constant within CordovaWebViewClient.java before it will work.
        LOCATION_CHANGE: 2
    },
    nativeToJsModes = {
        // Polls for messages using the JS->Native bridge.
        POLLING: 0,
        // Does an XHR to a local server, which will send back messages. This is
        // broken on ICS when a proxy server is configured.
        HANGING_GET: 1,
        // For LOAD_URL to be viable, it would need to have a work-around for
        // the bug where the soft-keyboard gets dismissed when a message is sent.
        LOAD_URL: 2,
        // For the ONLINE_EVENT to be viable, it would need to intercept all event
        // listeners (both through addEventListener and window.ononline) as well
        // as set the navigator property itself.
        ONLINE_EVENT: 3,
        // Uses reflection to access private APIs of the WebView that can send JS
        // to be executed.
        // Requires Android 3.2.4 or above.
        PRIVATE_API: 4
    };

function androidExec(success, fail, service, action, args) {
    // Set default bridge modes if they have not already been set.
    if (jsToNativeBridgeMode === undefined) {
        androidExec.setJsToNativeBridgeMode(jsToNativeModes.PROMPT);
    }
    androidExec.setNativeToJsBridgeMode(nativeToJsModes.ONLINE_EVENT);

    var callbackId = service + cordova.callbackId++,
        argsJson = JSON.stringify(args);
    if (success || fail) {
        cordova.callbacks[callbackId] = {success:success, fail:fail};
    }

    if (jsToNativeBridgeMode == jsToNativeModes.LOCATION_CHANGE) {
        window.location = 'http://cdv_exec/' + service + '#' + action + '#' + callbackId + '#' + argsJson;
    } else {
        var messages = nativeApiProvider.get().exec(service, action, callbackId, argsJson);
        // Explicit cast to string is required on Android 2.1 to convert from
        // a Java string to a JS string.
        if (messages) {
            messages = String(messages);
        }
        androidExec.processMessages(messages);
    }
}

function hookOnlineApis() {
    function proxyEvent(e) {
        cordova.fireWindowEvent(e.type);
    }
    // The network module takes care of firing online and offline events.
    // It currently fires them only on document though, so we bridge them
    // to window here (while first listening for exec()-releated online/offline
    // events).
    window.addEventListener('online', polling.pollOnce, false);
    window.addEventListener('offline', polling.pollOnce, false);
    cordova.addWindowEventHandler('online');
    cordova.addWindowEventHandler('offline');
    document.addEventListener('online', proxyEvent, false);
    document.addEventListener('offline', proxyEvent, false);
}

hookOnlineApis();

androidExec.jsToNativeModes = jsToNativeModes;
androidExec.nativeToJsModes = nativeToJsModes;

androidExec.setJsToNativeBridgeMode = function(mode) {
    if (mode == jsToNativeModes.JS_OBJECT && !window._cordovaNative) {
        console.log('Falling back on PROMPT mode since _cordovaNative is missing.');
        mode = jsToNativeModes.PROMPT;
    }
    nativeApiProvider.setPreferPrompt(mode == jsToNativeModes.PROMPT);
    jsToNativeBridgeMode = mode;
};

androidExec.setNativeToJsBridgeMode = function(mode) {
    if (mode == nativeToJsBridgeMode) {
        return;
    }
    if (nativeToJsBridgeMode == nativeToJsModes.POLLING) {
        polling.stop();
    } else if (nativeToJsBridgeMode == nativeToJsModes.HANGING_GET) {
        callback.stop();
    }

    nativeToJsBridgeMode = mode;
    // Tell the native side to switch modes.
    nativeApiProvider.get().setNativeToJsBridgeMode(mode);

    if (mode == nativeToJsModes.POLLING) {
        polling.start();
    } else if (mode == nativeToJsModes.HANGING_GET) {
        callback.start();
    }
};

// Processes a single message, as encoded by NativeToJsMessageQueue.java.
function processMessage(message) {
    try {
        var firstChar = message.charAt(0);
        if (firstChar == 'J') {
            eval(message.slice(1));
        } else if (firstChar == 'S' || firstChar == 'F') {
            var success = firstChar == 'S';
            var keepCallback = message.charAt(1) == '1';
            var spaceIdx = message.indexOf(' ', 2);
            var status = +message.slice(2, spaceIdx);
            var nextSpaceIdx = message.indexOf(' ', spaceIdx + 1);
            var callbackId = message.slice(spaceIdx + 1, nextSpaceIdx);
            var payloadKind = message.charAt(nextSpaceIdx + 1);
            var payload;
            if (payloadKind == 's') {
                payload = message.slice(nextSpaceIdx + 2);
            } else if (payloadKind == 't') {
                payload = true;
            } else if (payloadKind == 'f') {
                payload = false;
            } else if (payloadKind == 'n') {
                payload = +message.slice(nextSpaceIdx + 2);
            } else {
                payload = JSON.parse(message.slice(nextSpaceIdx + 1));
            }
            cordova.callbackFromNative(callbackId, success, status, payload, keepCallback);
        } else {
            console.log("processMessage failed: invalid message:" + message);
        }
    } catch (e) {
        console.log("processMessage failed: Message: " + message);
        console.log("processMessage failed: Error: " + e);
        console.log("processMessage failed: Stack: " + e.stack);
    }
}

// This is called from the NativeToJsMessageQueue.java.
androidExec.processMessages = function(messages) {
    while (messages) {
        if (messages == '*') {
            window.setTimeout(polling.pollOnce, 0);
            break;
        }
        var spaceIdx = messages.indexOf(' ');
        var msgLen = +messages.slice(0, spaceIdx);
        var message = messages.substr(spaceIdx + 1, msgLen);
        messages = messages.slice(spaceIdx + msgLen + 1);
        processMessage(message);
    }
};

module.exports = androidExec;
<commit_msg>[android] Set default bridge to ONLINE_EVENTS (take 2)<commit_after>/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
*/

/**
 * Execute a cordova command.  It is up to the native side whether this action
 * is synchronous or asynchronous.  The native side can return:
 *      Synchronous: PluginResult object as a JSON string
 *      Asynchrounous: Empty string ""
 * If async, the native side will cordova.callbackSuccess or cordova.callbackError,
 * depending upon the result of the action.
 *
 * @param {Function} success    The success callback
 * @param {Function} fail       The fail callback
 * @param {String} service      The name of the service to use
 * @param {String} action       Action to be run in cordova
 * @param {String[]} [args]     Zero or more arguments to pass to the method
 */
var cordova = require('cordova'),
    callback = require('cordova/plugin/android/callback'),
    polling = require('cordova/plugin/android/polling'),
    nativeApiProvider = require('cordova/plugin/android/nativeapiprovider'),
    jsToNativeModes = {
        PROMPT: 0,
        JS_OBJECT: 1,
        // This mode is currently for benchmarking purposes only. It must be enabled
        // on the native side through the ENABLE_LOCATION_CHANGE_EXEC_MODE
        // constant within CordovaWebViewClient.java before it will work.
        LOCATION_CHANGE: 2
    },
    nativeToJsModes = {
        // Polls for messages using the JS->Native bridge.
        POLLING: 0,
        // Does an XHR to a local server, which will send back messages. This is
        // broken on ICS when a proxy server is configured.
        HANGING_GET: 1,
        // For LOAD_URL to be viable, it would need to have a work-around for
        // the bug where the soft-keyboard gets dismissed when a message is sent.
        LOAD_URL: 2,
        // For the ONLINE_EVENT to be viable, it would need to intercept all event
        // listeners (both through addEventListener and window.ononline) as well
        // as set the navigator property itself.
        ONLINE_EVENT: 3,
        // Uses reflection to access private APIs of the WebView that can send JS
        // to be executed.
        // Requires Android 3.2.4 or above.
        PRIVATE_API: 4
    },
    jsToNativeBridgeMode,  // Set lazily.
    nativeToJsBridgeMode = nativeToJsModes.ONLINE_EVENT;

function androidExec(success, fail, service, action, args) {
    // Set default bridge modes if they have not already been set.
    if (jsToNativeBridgeMode === undefined) {
        androidExec.setJsToNativeBridgeMode(jsToNativeModes.JS_OBJECT);
    }

    var callbackId = service + cordova.callbackId++,
        argsJson = JSON.stringify(args);
    if (success || fail) {
        cordova.callbacks[callbackId] = {success:success, fail:fail};
    }

    if (jsToNativeBridgeMode == jsToNativeModes.LOCATION_CHANGE) {
        window.location = 'http://cdv_exec/' + service + '#' + action + '#' + callbackId + '#' + argsJson;
    } else {
        var messages = nativeApiProvider.get().exec(service, action, callbackId, argsJson);
        // Explicit cast to string is required on Android 2.1 to convert from
        // a Java string to a JS string.
        if (messages) {
            messages = String(messages);
        }
        androidExec.processMessages(messages);
    }
}

function hookOnlineApis() {
    function proxyEvent(e) {
        cordova.fireWindowEvent(e.type);
    }
    // The network module takes care of firing online and offline events.
    // It currently fires them only on document though, so we bridge them
    // to window here (while first listening for exec()-releated online/offline
    // events).
    window.addEventListener('online', polling.pollOnce, false);
    window.addEventListener('offline', polling.pollOnce, false);
    cordova.addWindowEventHandler('online');
    cordova.addWindowEventHandler('offline');
    document.addEventListener('online', proxyEvent, false);
    document.addEventListener('offline', proxyEvent, false);
}

hookOnlineApis();

androidExec.jsToNativeModes = jsToNativeModes;
androidExec.nativeToJsModes = nativeToJsModes;

androidExec.setJsToNativeBridgeMode = function(mode) {
    if (mode == jsToNativeModes.JS_OBJECT && !window._cordovaNative) {
        console.log('Falling back on PROMPT mode since _cordovaNative is missing.');
        mode = jsToNativeModes.PROMPT;
    }
    nativeApiProvider.setPreferPrompt(mode == jsToNativeModes.PROMPT);
    jsToNativeBridgeMode = mode;
};

androidExec.setNativeToJsBridgeMode = function(mode) {
    if (mode == nativeToJsBridgeMode) {
        return;
    }
    if (nativeToJsBridgeMode == nativeToJsModes.POLLING) {
        polling.stop();
    } else if (nativeToJsBridgeMode == nativeToJsModes.HANGING_GET) {
        callback.stop();
    }

    nativeToJsBridgeMode = mode;
    // Tell the native side to switch modes.
    nativeApiProvider.get().setNativeToJsBridgeMode(mode);

    if (mode == nativeToJsModes.POLLING) {
        polling.start();
    } else if (mode == nativeToJsModes.HANGING_GET) {
        callback.start();
    }
};

// Processes a single message, as encoded by NativeToJsMessageQueue.java.
function processMessage(message) {
    try {
        var firstChar = message.charAt(0);
        if (firstChar == 'J') {
            eval(message.slice(1));
        } else if (firstChar == 'S' || firstChar == 'F') {
            var success = firstChar == 'S';
            var keepCallback = message.charAt(1) == '1';
            var spaceIdx = message.indexOf(' ', 2);
            var status = +message.slice(2, spaceIdx);
            var nextSpaceIdx = message.indexOf(' ', spaceIdx + 1);
            var callbackId = message.slice(spaceIdx + 1, nextSpaceIdx);
            var payloadKind = message.charAt(nextSpaceIdx + 1);
            var payload;
            if (payloadKind == 's') {
                payload = message.slice(nextSpaceIdx + 2);
            } else if (payloadKind == 't') {
                payload = true;
            } else if (payloadKind == 'f') {
                payload = false;
            } else if (payloadKind == 'n') {
                payload = +message.slice(nextSpaceIdx + 2);
            } else {
                payload = JSON.parse(message.slice(nextSpaceIdx + 1));
            }
            cordova.callbackFromNative(callbackId, success, status, payload, keepCallback);
        } else {
            console.log("processMessage failed: invalid message:" + message);
        }
    } catch (e) {
        console.log("processMessage failed: Message: " + message);
        console.log("processMessage failed: Error: " + e);
        console.log("processMessage failed: Stack: " + e.stack);
    }
}

// This is called from the NativeToJsMessageQueue.java.
androidExec.processMessages = function(messages) {
    while (messages) {
        if (messages == '*') {
            window.setTimeout(polling.pollOnce, 0);
            break;
        }
        var spaceIdx = messages.indexOf(' ');
        var msgLen = +messages.slice(0, spaceIdx);
        var message = messages.substr(spaceIdx + 1, msgLen);
        messages = messages.slice(spaceIdx + msgLen + 1);
        processMessage(message);
    }
};

module.exports = androidExec;
<|endoftext|>


<commit_before>"use strict";
var inherits = require('util').inherits;
var EventEmitter = require('events').EventEmitter;

var ConnectionsDict = require('./connections_dict');

// NOTE implements Unit
var Connections = function () {
	EventEmitter.call(this);

	this.connections = {};
	this.connectionCount = 0;

	this.userConnections = new ConnectionsDict();
	this.endpointConnections = new ConnectionsDict();
};
inherits(Connections, EventEmitter);

Connections.prototype.unitInit = function (units) {
	var mechanics = units.require('core.lowlevel').socket;
	if (mechanics != null)
	{
		var self = this;
		mechanics.on('connect', function (connection) {
			self.add(connection);
		});
		mechanics.on('disconnect', function (connection) {
			self.remove(connection);
		});
	}
};

Connections.prototype.isPresent = function (userId) {
	return userId in this.userConnections.dict;
};

Connections.prototype.getEndpoint = function (connection) {
	return connection.userData.endpointInfo;
};

Connections.prototype.registerEndpoint = function (connection, endpointInfo) {
	this.emit('endpoint_register', connection, endpointInfo);

	this.unregisterEndpoint(connection); // one endpoint per connection please

	connection.userData.endpointInfo = endpointInfo;

	this.userConnections.add(endpointInfo.userId, connection);

	var endpointKey = this.getEndpointKey(endpointInfo);
	this.endpointConnections.add(endpointKey, connection);
};

Connections.prototype.unregisterEndpoint = function (connection) {
	var endpointInfo = connection.userData.endpointInfo;

	if (endpointInfo != null)
	{
		if (endpointInfo.userId != null)
		{
			this.userConnections.remove(endpointInfo.userId, connection);
		}

		if (endpointInfo.endpointId != null)
		{
			var endpointKey = this.getEndpointKey(endpointInfo);
			this.endpointConnections.remove(endpointKey, connection);
		}

		this.emit('endpoint_unregistered', connection, endpointInfo);
	}
};

Connections.prototype.getEndpointKey = function (endpointInfo) {
	return [endpointInfo.userId, endpointInfo.endpointId].join('\n');
};

Connections.prototype.add = function (connection) {
	connection.userData = connection.userData || {};
	connection.userData.startTime = Date.now();
	var id = connection.id;
	if (!(id in this.connections))
	{
		this.connectionCount++;
	}
	this.connections[id] = connection;
};

Connections.prototype.remove = function (connection) {
	var id = connection.id;
	if (id in this.connections)
	{
		this.connectionCount--;
		delete this.connections[id];
	}

	this.unregisterEndpoint(connection);
};

Connections.prototype.getUserConnections = function (userId) {
	return this.userConnections.get(userId);
};

Connections.prototype.getEndpointConnections = function (endpointInfo) {
	var endpointKey = this.getEndpointKey(endpointInfo);
	return this.endpointConnections.get(endpointKey);
};

module.exports = Connections;
<commit_msg>connections now allow endpoints without userId<commit_after>"use strict";
var inherits = require('util').inherits;
var EventEmitter = require('events').EventEmitter;

var ConnectionsDict = require('./connections_dict');

// NOTE implements Unit
var Connections = function () {
	EventEmitter.call(this);

	this.connections = {};
	this.connectionCount = 0;

	this.userConnections = new ConnectionsDict();
	this.endpointConnections = new ConnectionsDict();
};
inherits(Connections, EventEmitter);

Connections.prototype.unitInit = function (units) {
	var mechanics = units.require('core.lowlevel').socket;
	if (mechanics != null)
	{
		var self = this;
		mechanics.on('connect', function (connection) {
			self.add(connection);
		});
		mechanics.on('disconnect', function (connection) {
			self.remove(connection);
		});
	}
};

Connections.prototype.isPresent = function (userId) {
	return userId in this.userConnections.dict;
};

Connections.prototype.getEndpoint = function (connection) {
	return connection.userData.endpointInfo;
};

Connections.prototype.registerEndpoint = function (connection, endpointInfo) {
	this.emit('endpoint_register', connection, endpointInfo);

	this.unregisterEndpoint(connection); // one endpoint per connection please

	connection.userData.endpointInfo = endpointInfo;

	if (endpointInfo.userId != null) {
		this.userConnections.add(endpointInfo.userId, connection);
	}

	var endpointKey = this.getEndpointKey(endpointInfo);
	this.endpointConnections.add(endpointKey, connection);
};

Connections.prototype.unregisterEndpoint = function (connection) {
	var endpointInfo = connection.userData.endpointInfo;

	if (endpointInfo != null)
	{
		if (endpointInfo.userId != null)
		{
			this.userConnections.remove(endpointInfo.userId, connection);
		}

		if (endpointInfo.endpointId != null)
		{
			var endpointKey = this.getEndpointKey(endpointInfo);
			this.endpointConnections.remove(endpointKey, connection);
		}

		this.emit('endpoint_unregistered', connection, endpointInfo);
	}
};

Connections.prototype.getEndpointKey = function (endpointInfo) {
	return [endpointInfo.userId, endpointInfo.endpointId].join('\n');
};

Connections.prototype.add = function (connection) {
	connection.userData = connection.userData || {};
	connection.userData.startTime = Date.now();
	var id = connection.id;
	if (!(id in this.connections))
	{
		this.connectionCount++;
	}
	this.connections[id] = connection;
};

Connections.prototype.remove = function (connection) {
	var id = connection.id;
	if (id in this.connections)
	{
		this.connectionCount--;
		delete this.connections[id];
	}

	this.unregisterEndpoint(connection);
};

Connections.prototype.getUserConnections = function (userId) {
	return this.userConnections.get(userId);
};

Connections.prototype.getEndpointConnections = function (endpointInfo) {
	var endpointKey = this.getEndpointKey(endpointInfo);
	return this.endpointConnections.get(endpointKey);
};

module.exports = Connections;
<|endoftext|>


<commit_before>'use strict';

/**
 * Confirm study details pages load and display appropriate content.
 */

const config = require('config');
const client = require('./lib/client').client;
const study = require('./lib/study')(client, config);
const micis = require('./lib/auth/micis')(client);
const should = require('should');
const noop = require('lodash/noop');

/**
 * Navigate to a single study.
 *
 * This rolls re-used navigation to the "NITEST" study into a reusable function.
 *
 * @todo  Roll this into reusable lib.
 *
 * @param  {function}  cb Callback fired after navigation completes
 * @return {undefined}
 */
function navigateToSingleStudy(cb) {
  const callback = cb instanceof Function ? cb : noop;

  study.goToView('NITEST').waitForPaginationComplete().call(callback);
}

describe('Study details', function studyDetails() {
  this.timeout(config.defaultTimeout);

  before('initialize', (done) => {
    client.clientReady.then(() => {
      if (!micis.loggedOn) {
        micis.logon();
      }

      client.call(done);
    });
  });

  /**
   * Ensure that the subject trackers CRM app loads. This requires fetching lots
   * of data for the server, so `waitForExist` with a long timeout is employed.
   */
  describe('subject trackers', () => {
    before(navigateToSingleStudy);

    it('should navigate to subject tracker', (done) => {
      client
        .click('input[data-hook=subject-tracker-button]')
        .waitForVisible('.ui-dialog', 100, (err, res) => {
          if (res) {
            client.click('.ui-dialog .ui-button-success');
          }

          client.call(done);
        });
    });
    it('should show subject tracker', (done) => {
      client
        .waitForPaginationComplete()
        .waitForExist('#tracker-study-subject-details tbody tr', 3500, (err) => {
          if (err) {
            throw err;
          }
        })
        .call(done);
    });
    it('should display subject rows', (done) => {
      client
        .waitForExist('#tracker-study-subject-details tbody tr', 4000, (err) => {
          if (err) {
            throw err;
          }
        })
        .elements('#tracker-study-subject-details tbody tr', (err, res) => {
          if (err) {
            throw err;
          }

          should(res.value.length).be.above(0);
        })
        .call(done);
    });
  });

  /**
   * Ensure the view subjects table exists and loads.
   */
  describe('view subjects', () => {
    before(navigateToSingleStudy);

    it('should navigate to view subjects page', (done) => {
      client
        .click('input[data-hook=view-subjects-btn]')
        .waitForPaginationComplete()
        .call(done);
    });

    it('should display subjects in a table', (done) => {
      client
        .waitForExist('.dataTables_scrollBody tr', 500)
        .elements('.dataTables_scrollBody tr', (err, res) => {
          if (err) {
            throw err;
          }

          /**
           * The subjects table should have subjects in it,
           * represented by this `table`'s `tr`s.
           */
          should(res.value.length).be.above(0);
        })
        .call(done);
    });
  });

  /**
   * Ensure the study access table exists and loads.
   */
  describe('list study access', () => {
    before(navigateToSingleStudy);

    it('should navigate to study access page', (done) => {
      client
        .click('#frmAccess input[type=button]')
        .waitForPaginationComplete()
        .call(done);
    });

    it('should display', (done) => {
      client
        .elements('.box-container > table tr', (err, res) => {
          if (err) {
            throw err;
          }

          /**
           * Confirm the user access table has rows. The first row
           * functions as column headings, so the number of rows
           * should be greater than 1.
           */
          should(res.value.length).be.above(1);
        })
        .call(done);
    });
  });
});
<commit_msg>Correct study access table row selector.<commit_after>'use strict';

/**
 * Confirm study details pages load and display appropriate content.
 */

const config = require('config');
const client = require('./lib/client').client;
const study = require('./lib/study')(client, config);
const micis = require('./lib/auth/micis')(client);
const should = require('should');
const noop = require('lodash/noop');

/**
 * Navigate to a single study.
 *
 * This rolls re-used navigation to the "NITEST" study into a reusable function.
 *
 * @todo  Roll this into reusable lib.
 *
 * @param  {function}  cb Callback fired after navigation completes
 * @return {undefined}
 */
function navigateToSingleStudy(cb) {
  const callback = cb instanceof Function ? cb : noop;

  study.goToView('NITEST').waitForPaginationComplete().call(callback);
}

describe('Study details', function studyDetails() {
  this.timeout(config.defaultTimeout);

  before('initialize', (done) => {
    client.clientReady.then(() => {
      if (!micis.loggedOn) {
        micis.logon();
      }

      client.call(done);
    });
  });

  /**
   * Ensure that the subject trackers CRM app loads. This requires fetching lots
   * of data for the server, so `waitForExist` with a long timeout is employed.
   */
  describe('subject trackers', () => {
    before(navigateToSingleStudy);

    it('should navigate to subject tracker', (done) => {
      client
        .click('input[data-hook=subject-tracker-button]')
        .waitForVisible('.ui-dialog', 100, (err, res) => {
          if (res) {
            client.click('.ui-dialog .ui-button-success');
          }

          client.call(done);
        });
    });
    it('should show subject tracker', (done) => {
      client
        .waitForPaginationComplete()
        .waitForExist('#tracker-study-subject-details tbody tr', 3500, (err) => {
          if (err) {
            throw err;
          }
        })
        .call(done);
    });
    it('should display subject rows', (done) => {
      client
        .waitForExist('#tracker-study-subject-details tbody tr', 4000, (err) => {
          if (err) {
            throw err;
          }
        })
        .elements('#tracker-study-subject-details tbody tr', (err, res) => {
          if (err) {
            throw err;
          }

          should(res.value.length).be.above(0);
        })
        .call(done);
    });
  });

  /**
   * Ensure the view subjects table exists and loads.
   */
  describe('view subjects', () => {
    before(navigateToSingleStudy);

    it('should navigate to view subjects page', (done) => {
      client
        .click('input[data-hook=view-subjects-btn]')
        .waitForPaginationComplete()
        .call(done);
    });

    it('should display subjects in a table', (done) => {
      client
        .waitForExist('.dataTables_scrollBody tr', 500)
        .elements('.dataTables_scrollBody tr', (err, res) => {
          if (err) {
            throw err;
          }

          /**
           * The subjects table should have subjects in it,
           * represented by this `table`'s `tr`s.
           */
          should(res.value.length).be.above(0);
        })
        .call(done);
    });
  });

  /**
   * Ensure the study access table exists and loads.
   */
  describe('list study access', () => {
    before(navigateToSingleStudy);

    it('should navigate to study access page', (done) => {
      client
        .click('#frmAccess input[type=button]')
        .waitForPaginationComplete()
        .call(done);
    });

    it('should display', (done) => {
      client
        .elements('#list_access tbody tr', (err, res) => {
          if (err) {
            throw err;
          }

          /**
           * Confirm the user access table has rows. The first row
           * functions as column headings, so the number of rows
           * should be greater than 1.
           */
          should(res.value.length).be.above(1);
        })
        .call(done);
    });
  });
});
<|endoftext|>


<commit_before>'use strict';

var path = require('path');

module.exports = function (options) {
  var seneca = this;
  var plugin = 'cd-auth';
  var version = '1.0';

  options = seneca.util.deepextend({
    prefix: '/api/'
  }, options);

  seneca.add({ role: plugin, spec: 'web' }, spec_web);

  function spec_web(args, done) {
    var public_folder = path.join(__dirname, 'public');

    done(null, {
      name: 'auth',
      public: public_folder
    });
  }

  seneca.add({ init: plugin }, function (args, done) {
    var seneca = this;

    seneca.act({ role: plugin, spec: 'web' }, function (err, spec) {
      if (err) { return done(err); }

      var prefix = '/content/' + spec.name;

      seneca.act({ role: 'web', use: function (req, res, next) {
        if(req.url === '/' && req.user && req.user.login){
          res.redirect(302, '/dashboard/dojo-list');
        }
        else {
          return next();
        }
      }});

      done();
    });
  });

  return {
    name: plugin
  };
};
<commit_msg>Redirect loggedin user when trying to access register and login pages<commit_after>'use strict';

var path = require('path');

module.exports = function (options) {
  var seneca = this;
  var plugin = 'cd-auth';
  var version = '1.0';

  options = seneca.util.deepextend({
    prefix: '/api/'
  }, options);

  seneca.add({ role: plugin, spec: 'web' }, spec_web);

  function spec_web(args, done) {
    var public_folder = path.join(__dirname, 'public');

    done(null, {
      name: 'auth',
      public: public_folder
    });
  }

  seneca.add({ init: plugin }, function (args, done) {
    var seneca = this;

    seneca.act({ role: plugin, spec: 'web' }, function (err, spec) {
      if (err) { return done(err); }

      var prefix = '/content/' + spec.name;

      var redirectArr = ['/', '/register', '/login'];

      seneca.act({ role: 'web', use: function (req, res, next) {
        if((redirectArr.indexOf(req.url) > -1) && req.user && req.user.login){
          res.redirect(302, '/dashboard/dojo-list');
        }
        else {
          return next();
        }
      }});

      done();
    });
  });

  return {
    name: plugin
  };
};
<|endoftext|>