<commit_before>app.controller('state', function ($scope, $timeout, $filter,sharedData) {
	var name=sharedData.getName();
	$scope.header=name.name;

	$scope.ok="OK";

	$scope.m = [];
	$scope.mSubBytes = [];
	$scope.mShiftRows = [];
	$scope.mMixColumns = [];

	$scope.process = function(){
		$scope.m = [];
		$scope.mSubBytes = [];
		$scope.mShiftRows = [];
		$scope.mMixColumns = [];
		m = $scope.message.split('');
		for(i=0;i<$scope.message.length;i++){
			$scope.m.push({ascii:m[i],hex:asciiToHex(m[i])});
		}
		for(i=$scope.message.length;i<16;i++){
			$scope.m.push({ascii:"0",hex:"00"});
		}
		sharedData.setMessage($scope.m);

		$scope.mSubBytes = subBytes($scope.m);
		$scope.mShiftRows = shiftRows($scope.mSubBytes);
		$scope.mMixColumns = mixColumns($scope.mShiftRows);

	};

	var asciiToHex = function(ascii){
		return ascii.charCodeAt(0).toString(16);
	};

	var hexToascii = function(hex){
		return String.fromCharCode(parseInt(n, 16));
	};

	var hexTobinary = function(hex){
		hex = "0x"+hex;
		return (Number(hex).toString(2));
	};

	var binaryTodecimal = function(bin){
		return parseInt(bin,2);
	};

	var decimalTohex = function(num){
		return num.toString(16);
	};

	var toDecimal = function(hex){
		if(hex=="a"){
			hex="10";
		}
		if(hex=="b"){
			hex="11";
		}
		if(hex=="c"){
			hex="12";
		}
		if(hex=="d"){
			hex="13";
		}
		if(hex=="e"){
			hex="14";
		}
		if(hex=="f"){
			hex="15";
		}
		return hex;
	}
	var subByte = function(byte){
		var byteArray = byte.split('');
		var x = toDecimal(byteArray[0]);
		var y = toDecimal(byteArray[1]);
		var sBox = [
		["63","7c","77","7b","f2","6b","6f","c5","30","01","67","2b","fe","d7","ab","76"],
		["ca","82","c9","7d","fa","59","47","f0","ad","d4","a2","af","9c","a4","72","c0"],
		["b7","fd","93","26","36","3f","f7","cc","34","a5","e5","f1","71","d8","31","15"],
		["04","c7","23","c3","18","96","05","9a","07","12","80","e2","eb","27","b2","75"],
		["09","83","2c","1a","1b","6e","5a","a0","52","3b","d6","b3","29","e3","2f","84"],
		["53","d1","00","ed","20","fc","b1","5b","6a","cb","be","39","4a","4c","58","cf"],
		["d0","ef","aa","fb","43","4d","33","85","45","f9","02","7f","50","3c","9f","a8"],
		["51","a3","40","8f","92","9d","38","f5","bc","b6","da","21","10","ff","f3","d2"],
		["cd","0c","13","ec","5f","97","44","17","c4","a7","7e","3d","64","5d","19","73"],
		["60","81","4f","dc","22","2a","90","88","46","ee","b8","14","de","5e","0b","db"],
		["e0","32","3a","0a","49","06","24","5c","c2","d3","ac","62","91","95","e4","79"],
		["e7","c8","37","6d","8d","d5","4e","a9","6c","56","f4","ea","65","7a","ae","08"],
		["ba","78","25","2e","1c","a6","b4","c6","e8","dd","74","1f","4b","bd","8b","8a"],
		["70","3e","b5","66","48","03","f6","0e","61","35","57","b9","86","c1","1d","9e"],
		["e1","f8","98","11","69","d9","8e","94","9b","1e","87","e9","ce","55","28","df"],
		["8c","a1","89","0d","bf","e6","42","68","41","99","2d","0f","b0","54","bb","16"]];

		return sBox[x][y];

	};
	var subBytes = function(array){
		var result = [];
		for(i=0;i<array.length;i++){
			result.push({ascii:array[i].ascii,hex:subByte(array[i].hex)});
		}
		return result;
	};
	var shiftForward = function(originalArray,cut,paste){
		//copy original array to the variable we're going to manipulate
		var array = [];
		for (var i=0;i<originalArray.length;i++){
			array[i]=originalArray[i];
		}
		var arrayLength = array.length;
		var a= array.splice(cut,1);
		var b=[];
		//rebuild original array before splice, place the cut value into the paste position in this new array
		for(i=0;i<arrayLength;i++){
			if(i<paste){
				b[i]=array[i];
			}else if (i==paste){
				b[i]=a[0];
			}else{
				b[i]=array[i-1];
			}
		}
		return b;
	};

	var shiftRows = function(state){
		var matrix=[];
		for(i=0;i<state.length;i++){
			matrix[i]=state[i];
		}
		/* increment every five cells, shifting forward every fifth cell forward once and wrapping
		 * around it every five cells. thus turning something that looks like this:
		 * ["00", "01", "02", "03", "10", "11", "12", "13", "20", "21", "22", "23", "30", "31", "32", "33"]
		 * into this:
		 * ["00", "01", "02", "03", "11", "12", "13", "10", "22", "23", "20", "21", "33", "30", "31", "32"]
		 */
		for(i=0,j=0;i<matrix.length;i=i+4,j++){
				a=matrix;
			for(k=0;k<j;k++){
				a=shiftForward(a,i,i+3);
			}
				matrix=a;
		}
		return matrix;
	};

	var eightBit = function(bin){
		//makes sure the binary number is eight bits in length
		b = bin.split('');
		for(i=b.length;i<8;i++){
			b.unshift("0");
		}
		b = b.join("");
		return b;
	};

	var leftShift = function(bin){
		//shifts the binary number one forward, adding a zero to the end;
		b = bin.split('');
		b.push('0');
		b.shift();
		b = b.join("");
		return b;
	};

	var rightShift = function(bin){
		//shifts the binary number one backward, adding a zero to the beginning;
		b = bin.split('');
		b.unshift('0');
		b.splice(-1,1);
		return b.join("");
	};

	var bitMultX = function(hex){
		/*
		 * multiplication of a value by x (ie. by 02) can be implemented as a 1-bit left shift
		 * followed by a conditional bitwise XOR with (0001 1011) if the leftmost bit of the
		 * original value (before the shift) is 1.
		 */
		left = hexTobinary(hex);
		if(left[0]==1){
			x = hexTobinary(decimalTohex(binaryTodecimal(leftShift(eightBit(hexTobinary(hex)))) ^ 27));
		}
		return x;
	};

	//galois field mulitiplation

	var galois = {
		addition:function(bina,binb){
			bina=eightBit(bina).split('');
			binb=eightBit(binb).split('');
			binc=[];
			for(i=0;i<bina.length;i++){
				binc[i]=parseInt(bina[i] ^ binb[i],2);
			}
			return binc;
		},
		multiplication : function(bina, binb) {
			bina = eightBit(bina);
			binb = eightBit(binb);
			p = 0;
			for (i = 0; i < 8; i++) {

				if (binb[7] == 1) {
					p = p ^ (binaryTodecimal(bina));
				}
				highBit = bina[0];
				bina = (leftShift(bina));

				if (highBit == 1) {
					hexA = binaryTodecimal(bina);
					xor = hexA ^ 27;
					bina = (hexTobinary(decimalTohex(xor)));
				}

				binb = (rightShift(binb));

				if (binaryTodecimal(binb) == 0) {
					break;
				}

			}
			return eightBit(hexTobinary(decimalTohex(p)));
		},
		division:function(){
			a = [1,1,1,1,0]; //what you're trying to reduce
			b = [1,0,1,1]; //what you're reducing by
			c = [];
			while(true){
				for(i=0;i<b.length;i++){
					c[i]=a[i]^b[i];
				}
				a = a.slice(b.length);
				p = a.length - b.length;

				//nsole.log("A:"+a+"\nB:"+b+"\nC:"+c);
				c.push(a[0]);
				c.shift();
				//console.log("A:"+a+"\nB:"+b+"\nC:"+c);
				if(a.length==0){
					break;
				}
				a = c;

			}
			return c;
		}
	};

	row = [["02","d4"],["03","bf"],["01","5d"],["01","30"]];
	var computeRow = function(row){
		sum = 0;
		for(m=0;m<row.length;m++){
			product = galois.multiplication(hexTobinary(row[m][0]),hexTobinary(row[m][1]));
			product = binaryTodecimal(product);
			sum = sum ^ product;
		}
		return decimalTohex(sum);
	};

	var mixColumns = function(m){
		var idMatrix = [2,3,1,1,1,2,3,1,1,1,2,3,3,1,1,2];
		//var m = [{ascii:"a", hex:"61", $$hashKey:"3XU"}, {ascii:"b", hex:"d4", $$hashKey:"3XX"}, {ascii:"c", hex:"63", $$hashKey:"3Y0"}, {ascii:"d", hex:"64", $$hashKey:"3Y3"}, {ascii:"e", hex:"65", $$hashKey:"3Y6"}, {ascii:"f", hex:"bf", $$hashKey:"3Y9"}, {ascii:"g", hex:"67", $$hashKey:"3YC"}, {ascii:"h", hex:"68", $$hashKey:"3YF"}, {ascii:"i", hex:"69", $$hashKey:"3YI"}, {ascii:"j", hex:"5d", $$hashKey:"3YL"}, {ascii:"k", hex:"6b", $$hashKey:"3YO"}, {ascii:"l", hex:"6c", $$hashKey:"3YR"}, {ascii:"m", hex:"6d", $$hashKey:"3YU"}, {ascii:"n", hex:"30", $$hashKey:"3YX"}, {ascii:"o", hex:"6f", $$hashKey:"3Z0"}, {ascii:"p", hex:"70", $$hashKey:"3Z3"}];
		var n = [];
		for(copy=0;copy<m.length;copy++){
			n[copy]=m[copy];
		}

		for(w=0;w<4;w++){
			var c = ["d4","bf","5d","30"];
			c[0]=m[w+0].hex;
			c[1]=m[w+4].hex;
			c[2]=m[w+8].hex;
			c[3]=m[w+12].hex;
			var result = [];
			for(x=0;x<16;x=4+x){
				column = [["",""],["",""],["",""],["",""]];
				for (y=0;y<c.length;y++){
					column[y][0]=idMatrix[y+x];
					column[y][1]=c[y];
				}
				console.log("C:\t"+column);
				result[x/4]=computeRow(column);

			}

			n[w+0] =  ({ascii:m[w+0].ascii,hex:result[0]});
			n[w+4] =  ({ascii:m[w+4].ascii,hex:result[1]});
			n[w+8] =  ({ascii:m[w+8].ascii,hex:result[2]});
			n[w+12] = ({ascii:m[w+12].ascii,hex:result[3]});
		}

		return n;
	};
});<commit_msg>Created the bTrunc function which truncates a binary string, removing all of the zeros in the front<commit_after>app.controller('state', function ($scope, $timeout, $filter,sharedData) {
	var name=sharedData.getName();
	$scope.header=name.name;

	$scope.ok="OK";

	$scope.m = [];
	$scope.mSubBytes = [];
	$scope.mShiftRows = [];
	$scope.mMixColumns = [];

	$scope.process = function(){
		$scope.m = [];
		$scope.mSubBytes = [];
		$scope.mShiftRows = [];
		$scope.mMixColumns = [];
		m = $scope.message.split('');
		for(i=0;i<$scope.message.length;i++){
			$scope.m.push({ascii:m[i],hex:asciiToHex(m[i])});
		}
		for(i=$scope.message.length;i<16;i++){
			$scope.m.push({ascii:"0",hex:"00"});
		}
		sharedData.setMessage($scope.m);

		$scope.mSubBytes = subBytes($scope.m);
		$scope.mShiftRows = shiftRows($scope.mSubBytes);
		$scope.mMixColumns = mixColumns($scope.mShiftRows);

	};

	var asciiToHex = function(ascii){
		return ascii.charCodeAt(0).toString(16);
	};

	var hexToascii = function(hex){
		return String.fromCharCode(parseInt(n, 16));
	};

	var hexTobinary = function(hex){
		hex = "0x"+hex;
		return (Number(hex).toString(2));
	};

	var binaryTodecimal = function(bin){
		return parseInt(bin,2);
	};

	var decimalTohex = function(num){
		return num.toString(16);
	};

	var toDecimal = function(hex){
		if(hex=="a"){
			hex="10";
		}
		if(hex=="b"){
			hex="11";
		}
		if(hex=="c"){
			hex="12";
		}
		if(hex=="d"){
			hex="13";
		}
		if(hex=="e"){
			hex="14";
		}
		if(hex=="f"){
			hex="15";
		}
		return hex;
	}
	var subByte = function(byte){
		var byteArray = byte.split('');
		var x = toDecimal(byteArray[0]);
		var y = toDecimal(byteArray[1]);
		var sBox = [
		["63","7c","77","7b","f2","6b","6f","c5","30","01","67","2b","fe","d7","ab","76"],
		["ca","82","c9","7d","fa","59","47","f0","ad","d4","a2","af","9c","a4","72","c0"],
		["b7","fd","93","26","36","3f","f7","cc","34","a5","e5","f1","71","d8","31","15"],
		["04","c7","23","c3","18","96","05","9a","07","12","80","e2","eb","27","b2","75"],
		["09","83","2c","1a","1b","6e","5a","a0","52","3b","d6","b3","29","e3","2f","84"],
		["53","d1","00","ed","20","fc","b1","5b","6a","cb","be","39","4a","4c","58","cf"],
		["d0","ef","aa","fb","43","4d","33","85","45","f9","02","7f","50","3c","9f","a8"],
		["51","a3","40","8f","92","9d","38","f5","bc","b6","da","21","10","ff","f3","d2"],
		["cd","0c","13","ec","5f","97","44","17","c4","a7","7e","3d","64","5d","19","73"],
		["60","81","4f","dc","22","2a","90","88","46","ee","b8","14","de","5e","0b","db"],
		["e0","32","3a","0a","49","06","24","5c","c2","d3","ac","62","91","95","e4","79"],
		["e7","c8","37","6d","8d","d5","4e","a9","6c","56","f4","ea","65","7a","ae","08"],
		["ba","78","25","2e","1c","a6","b4","c6","e8","dd","74","1f","4b","bd","8b","8a"],
		["70","3e","b5","66","48","03","f6","0e","61","35","57","b9","86","c1","1d","9e"],
		["e1","f8","98","11","69","d9","8e","94","9b","1e","87","e9","ce","55","28","df"],
		["8c","a1","89","0d","bf","e6","42","68","41","99","2d","0f","b0","54","bb","16"]];

		return sBox[x][y];

	};
	var subBytes = function(array){
		var result = [];
		for(i=0;i<array.length;i++){
			result.push({ascii:array[i].ascii,hex:subByte(array[i].hex)});
		}
		return result;
	};
	var shiftForward = function(originalArray,cut,paste){
		//copy original array to the variable we're going to manipulate
		var array = [];
		for (var i=0;i<originalArray.length;i++){
			array[i]=originalArray[i];
		}
		var arrayLength = array.length;
		var a= array.splice(cut,1);
		var b=[];
		//rebuild original array before splice, place the cut value into the paste position in this new array
		for(i=0;i<arrayLength;i++){
			if(i<paste){
				b[i]=array[i];
			}else if (i==paste){
				b[i]=a[0];
			}else{
				b[i]=array[i-1];
			}
		}
		return b;
	};

	var shiftRows = function(state){
		var matrix=[];
		for(i=0;i<state.length;i++){
			matrix[i]=state[i];
		}
		/* increment every five cells, shifting forward every fifth cell forward once and wrapping
		 * around it every five cells. thus turning something that looks like this:
		 * ["00", "01", "02", "03", "10", "11", "12", "13", "20", "21", "22", "23", "30", "31", "32", "33"]
		 * into this:
		 * ["00", "01", "02", "03", "11", "12", "13", "10", "22", "23", "20", "21", "33", "30", "31", "32"]
		 */
		for(i=0,j=0;i<matrix.length;i=i+4,j++){
				a=matrix;
			for(k=0;k<j;k++){
				a=shiftForward(a,i,i+3);
			}
				matrix=a;
		}
		return matrix;
	};

	var eightBit = function(bin){
		//makes sure the binary number is eight bits in length
		b = bin.split('');
		for(i=b.length;i<8;i++){
			b.unshift("0");
		}
		b = b.join("");
		return b;
	};

	var leftShift = function(bin){
		//shifts the binary number one forward, adding a zero to the end;
		b = bin.split('');
		b.push('0');
		b.shift();
		b = b.join("");
		return b;
	};

	var rightShift = function(bin){
		//shifts the binary number one backward, adding a zero to the beginning;
		b = bin.split('');
		b.unshift('0');
		b.splice(-1,1);
		return b.join("");
	};

	var bitMultX = function(hex){
		/*
		 * multiplication of a value by x (ie. by 02) can be implemented as a 1-bit left shift
		 * followed by a conditional bitwise XOR with (0001 1011) if the leftmost bit of the
		 * original value (before the shift) is 1.
		 */
		left = hexTobinary(hex);
		if(left[0]==1){
			x = hexTobinary(decimalTohex(binaryTodecimal(leftShift(eightBit(hexTobinary(hex)))) ^ 27));
		}
		return x;
	};

	//galois field mulitiplation

	var galois = {
		addition:function(bina,binb){
			bina=eightBit(bina).split('');
			binb=eightBit(binb).split('');
			binc=[];
			for(i=0;i<bina.length;i++){
				binc[i]=parseInt(bina[i] ^ binb[i],2);
			}
			return binc;
		},
		multiplication : function(bina, binb) {
			bina = eightBit(bina);
			binb = eightBit(binb);
			p = 0;
			for (i = 0; i < 8; i++) {

				if (binb[7] == 1) {
					p = p ^ (binaryTodecimal(bina));
				}
				highBit = bina[0];
				bina = (leftShift(bina));

				if (highBit == 1) {
					hexA = binaryTodecimal(bina);
					xor = hexA ^ 27;
					bina = (hexTobinary(decimalTohex(xor)));
				}

				binb = (rightShift(binb));

				if (binaryTodecimal(binb) == 0) {
					break;
				}

			}
			return eightBit(hexTobinary(decimalTohex(p)));
		},
		division:function(bina,binb){
			a = (bina).split('');
			b = (binb).split('');
			//a = [1,1,1,1,0]; //what you're trying to reduce
			//b = [1,0,1,1]; //what you're reducing by
			c = [];
			while(true){
				for(i=0;i<b.length;i++){
					c[i]=a[i]^b[i];
				}
				a = a.slice(b.length);
				p = a.length - b.length;

				console.log("A:"+a+"\nB:"+b+"\nC:"+c);
				c.push(a[0]);
				c.shift();
				console.log("A:"+a+"\nB:"+b+"\nC:"+c);
				if(a.length==0){
					break;
				}
				a = c;

			}
			return c.join("");
		}
	};
	var bTrunc = function(bin){
		bin = bin.split('');
		l = bin.length;
		for(c=0;c<=l;c++){
			//console.log(c+"/"+l+"\tbin[0]="+bin[0]+"\t"+bin);

			if(bin[0]=="0"){
				bin.shift();
			}
			if(bin[0]=="1"){
				break;
			}

		}
		return bin.join('');
	};
	row = [["02","d4"],["03","bf"],["01","5d"],["01","30"]];
	var computeRow = function(row){
		sum = 0;
		for(m=0;m<row.length;m++){
			product = galois.multiplication(hexTobinary(row[m][0]),hexTobinary(row[m][1]));
			product = binaryTodecimal(product);
			sum = sum ^ product;
		}
		return decimalTohex(sum);
	};

	var mixColumns = function(m){
		var idMatrix = [2,3,1,1,1,2,3,1,1,1,2,3,3,1,1,2];
		//var m = [{ascii:"a", hex:"61", $$hashKey:"3XU"}, {ascii:"b", hex:"d4", $$hashKey:"3XX"}, {ascii:"c", hex:"63", $$hashKey:"3Y0"}, {ascii:"d", hex:"64", $$hashKey:"3Y3"}, {ascii:"e", hex:"65", $$hashKey:"3Y6"}, {ascii:"f", hex:"bf", $$hashKey:"3Y9"}, {ascii:"g", hex:"67", $$hashKey:"3YC"}, {ascii:"h", hex:"68", $$hashKey:"3YF"}, {ascii:"i", hex:"69", $$hashKey:"3YI"}, {ascii:"j", hex:"5d", $$hashKey:"3YL"}, {ascii:"k", hex:"6b", $$hashKey:"3YO"}, {ascii:"l", hex:"6c", $$hashKey:"3YR"}, {ascii:"m", hex:"6d", $$hashKey:"3YU"}, {ascii:"n", hex:"30", $$hashKey:"3YX"}, {ascii:"o", hex:"6f", $$hashKey:"3Z0"}, {ascii:"p", hex:"70", $$hashKey:"3Z3"}];
		var n = [];
		for(copy=0;copy<m.length;copy++){
			n[copy]=m[copy];
		}

		for(w=0;w<4;w++){
			var c = ["d4","bf","5d","30"];
			c[0]=m[w+0].hex;
			c[1]=m[w+4].hex;
			c[2]=m[w+8].hex;
			c[3]=m[w+12].hex;
			var result = [];
			for(x=0;x<16;x=4+x){
				column = [["",""],["",""],["",""],["",""]];
				for (y=0;y<c.length;y++){
					column[y][0]=idMatrix[y+x];
					column[y][1]=c[y];
				}
				console.log("C:\t"+column);
				result[x/4]=computeRow(column);

			}

			n[w+0] =  ({ascii:m[w+0].ascii,hex:result[0]});
			n[w+4] =  ({ascii:m[w+4].ascii,hex:result[1]});
			n[w+8] =  ({ascii:m[w+8].ascii,hex:result[2]});
			n[w+12] = ({ascii:m[w+12].ascii,hex:result[3]});
		}

		return n;
	};
});<|endoftext|>


<commit_before>/**
 * Manages the creation and updating of the various
 * controllers for the layout.
 *
 * Copyright 2015 Ethan Smith
 */

var _ = require('underscore'),
    Marionette = require('backbone.marionette'),
    ControlBones = require('./ControlBones'),

    // Config
    Layout = require('../layout'),

    // View
    AffixedView = require('../view/AffixedView'),
    SummaryBlock = require('../view/SummaryBlock'),

    // Model
    AmountEntryCollection = require('../model/AmountEntryCollection'),
    SummaryModel = require('../model/SummaryModel');

var PrimaryDisplayController = function(options) {
   var self = this;

   // Copy all options to object
   _.each(options, function(value, key) {
      self[key] = value;
   });

   this.view = new AffixedView();
   this.data = {};
};

PrimaryDisplayController.prototype = {

   /**
    * @param rawData { ... } - Parsed data to render
    * @return Marionette.ItemView
    */
   render: function(rawData) {
      var self = this,
          subviews;

      this.data = rawData;

      subviews = this._assembleSubviews(Layout, 0);

      this.view.on('show', function() {
         _.each(subviews, function (view) {
            self.view.affixOnShow(view);
         });
      });

      return this.view;
   },

   /**
    * @param layout Layout
    * @param depth Integer
    * @return [Marionette.ItemView]
    */
   _assembleSubviews: function(layout, depth) {
      var self = this;

      return _.map(layout, function(config) {
         var preferredSource = config.sources || config.source,
             supplementary = config.supplementary,
             model = self._createCollection(self.data, preferredSource),
             type = config.type;

         // When `supplementary` is used, go and map the values to each of
         // the requested fields. Since we don't know what type they are
         // supposed to be, just copy the data across.
         if (supplementary) {
            supplementary = _.mapObject(supplementary, function (key) {
               return self.data[key];
            });
         }

         if (typeof type === 'function') {
            return self._createSubview(type, config, model, supplementary, depth);
         } else if (type === 'bundle') {
            return self._assembleBundle(config, depth);
         }

         throw "Unknown type: " + type;
      });
   },

   /**
    * @param config { ... }
    * @param depth Integer
    * @return Marionette.ItemView
    */
   _assembleBundle: function(config, depth) {
      var block = new SummaryBlock({
         model: new SummaryModel({
            nestDepth: depth,
            header: config.options.title
         })
      }),
         childViews =  this._assembleSubviews(config.items, depth + 1),
         container = new AffixedView();

      block.on('show', function() {
         block.content.show(container);
      });

      container.on('show', function() {
         _.each(childViews, function (view) {
            container.affixOnShow(view);
         });
      });

      return block;
   },

   /**
    * @param controllerType ControlBones
    * @param config { ... }
    * @param depth Integer
    * @return Marionette.ItemView
    */
   _createSubview: function(controllerType, config, model, supplementaryFields, depth) {
      var controller = new controllerType(_.defaults(config.options, { nestDepth: depth }));

      controller.on('collection:updated', function(collection) {
         if (config.source === undefined) {
            throw 'Update event was called when we do not have a single source. Multisource updates are not supported at this time.';
         }

         // Update the source data with the updates
         // this.data[config.source] = collection.toJSON();

         // Re-render using updated data
         // renderFromSourceIntoView(data, container);
      });

      return controller.render(model, supplementaryFields);
   },

   /**
    * Recursively create the collections from its field name for the
    * source data. When the field is an object or array, try to create
    * sub models from its contents.
    *
    * @param rawData Object
    * @param field String, Array, Object
    * @return String, Array, or Object
    */
   _createCollection: function(rawData, field) {
      var self = this;

      if (Array.isArray(field)) {
         return _.map(field, function(sourceField) {
            return self._createCollection(rawData, sourceField);
         });
      } else if (field && (typeof field  === "object")) {
         return _.object(_.keys(field), self._createCollection(rawData, _.values(field)));
      }

      return new AmountEntryCollection(rawData[field]);
   }
};

module.exports = PrimaryDisplayController;
<commit_msg>Rerender on collection update<commit_after>/**
 * Manages the creation and updating of the various
 * controllers for the layout.
 *
 * Copyright 2015 Ethan Smith
 */

var _ = require('underscore'),
    Marionette = require('backbone.marionette'),
    ControlBones = require('./ControlBones'),

    // Config
    Layout = require('../layout'),

    // View
    AffixedView = require('../view/AffixedView'),
    SummaryBlock = require('../view/SummaryBlock'),

    // Model
    AmountEntryCollection = require('../model/AmountEntryCollection'),
    SummaryModel = require('../model/SummaryModel');

var PrimaryDisplayController = function(options) {
   var self = this;

   // Copy all options to object
   _.each(options, function(value, key) {
      self[key] = value;
   });

   this.view = new AffixedView();
   this.data = {};
};

PrimaryDisplayController.prototype = {

   /**
    * @param rawData { ... } - Parsed data to render
    * @return Marionette.ItemView
    */
   render: function(rawData) {
      var self = this,
          subviews;

      this.view.empty();

      this.data = rawData;
      subviews = this._assembleSubviews(Layout, 0);

      this.view.once('show', function() {
         _.each(subviews, function (view) {
            self.view.affixOnShow(view);
         });
      });

      return this.view;
   },

   /**
    * Reloads the view from the stored data
    */
   rerender: function() {
      this.render(this.data);
      this.view.trigger('show');
   },

   /**
    * @param layout Layout
    * @param depth Integer
    * @return [Marionette.ItemView]
    */
   _assembleSubviews: function(layout, depth) {
      var self = this;

      return _.map(layout, function(config) {
         var preferredSource = config.sources || config.source,
             supplementary = config.supplementary,
             model = self._createCollection(self.data, preferredSource),
             type = config.type;

         // When `supplementary` is used, go and map the values to each of
         // the requested fields. Since we don't know what type they are
         // supposed to be, just copy the data across.
         if (supplementary) {
            supplementary = _.mapObject(supplementary, function (key) {
               return self.data[key];
            });
         }

         if (typeof type === 'function') {
            return self._createSubview(type, config, model, supplementary, depth);
         } else if (type === 'bundle') {
            return self._assembleBundle(config, depth);
         }

         throw "Unknown type: " + type;
      });
   },

   /**
    * @param config { ... }
    * @param depth Integer
    * @return Marionette.ItemView
    */
   _assembleBundle: function(config, depth) {
      var block = new SummaryBlock({
         model: new SummaryModel({
            nestDepth: depth,
            header: config.options.title
         })
      }),
         childViews =  this._assembleSubviews(config.items, depth + 1),
         container = new AffixedView();

      block.on('show', function() {
         block.content.show(container);
      });

      container.once('show', function() {
         _.each(childViews, function (view) {
            container.affixOnShow(view);
         });
      });

      return block;
   },

   /**
    * @param controllerType ControlBones
    * @param config { ... }
    * @param depth Integer
    * @return Marionette.ItemView
    */
   _createSubview: function(controllerType, config, model, supplementaryFields, depth) {
      var controller = new controllerType(_.defaults(config.options, { nestDepth: depth })),
          self = this;

      controller.on('collection:updated', function(collection) {
         if (config.source === undefined) {
            throw 'Update event was called when we do not have a single source. Multisource updates are not supported at this time.';
         }

         // Update the source data with the updates
         self.data[config.source] = collection.toJSON();

         self.rerender();
      });

      return controller.render(model, supplementaryFields);
   },

   /**
    * Recursively create the collections from its field name for the
    * source data. When the field is an object or array, try to create
    * sub models from its contents.
    *
    * @param rawData Object
    * @param field String, Array, Object
    * @return String, Array, or Object
    */
   _createCollection: function(rawData, field) {
      var self = this;

      if (Array.isArray(field)) {
         return _.map(field, function(sourceField) {
            return self._createCollection(rawData, sourceField);
         });
      } else if (field && (typeof field  === "object")) {
         return _.object(_.keys(field), self._createCollection(rawData, _.values(field)));
      }

      return new AmountEntryCollection(rawData[field]);
   }
};

module.exports = PrimaryDisplayController;
<|endoftext|>


<commit_before>'use strict';

var fs = require('fs-extra');

var fileUtils = rootRequire('utils/file-utils');
var authenticationUtils = rootRequire('utils/authentication-utils');
var model = rootRequire('models/model');
var cloudstorage = rootRequire('libs/cloudstorage/cloudstorage');

module.exports.controller = function(app) {

    /**
     * GET /me
     * Get authenticated user profile information
     */
    app.get('/me', authenticationUtils.ensureAuthenticated, function(req, res) {

        model.User.find({
            where: {
                id: req.user
            }
        }).then(function(user) {
            res.send(user);
        });
    });

    /**
     * GET /me
     * Get authenticated user profile information
     */
    app.get('/me/cart', authenticationUtils.ensureAuthenticated, function(req, res) {

        model.User.find({
            where: {
                id: req.user
            }
        }).then(function(user) {

            user.getCartItems({
                include: [{
                        model: model.Track,
                        include: [{
                            model: model.Artist,
                            as: 'Producer'
                        }]
                    }, // load all pictures
                    {
                        model: model.Release,
                        include: [{
                            model: model.Track
                        }]
                    }, // load the profile picture. Notice that the spelling must be the exact same as the one in the association
                ]
            }).success(function(items) {
                res.send(items);
            })

        })
    });

    app.get('/me/cart/currency', authenticationUtils.ensureAuthenticated, function(req, res) {
        if (req.user) {
            // THERE IS A User, let's loook up his id

            /*
            model.User.find({
                where: {
                    id: req.user
                }
            }).then(function(user) {

                user.getCurrency({

                }).success(function(currency) {
                    res.send(currency)
                })

            })
            */
            model.Currency.find({
                where: {
                    id: 1
                }
            }).then(function(currency) {
                res.send(currency)
            })
        } else {
            // there is no user yet, let's pick a standard one
            model.Currency.find({
                where: {
                    id: 1
                }
            }).then(function(currency) {
                res.send(currency)
            })
        }

    });

    /**
     * PUT /api/me
     * Update the authenticated user profile information
     **/
    app.post('/me/cart/release/:id', authenticationUtils.ensureAuthenticated, function(req, res) {
        var releaseId = req.params.id
        model.User.find({
            where: {
                id: req.user
            }
        }).then(function(user) {
            if (!user) {
                return res.status(400).send({
                    message: 'User not found'
                });
            }

            model.CartItem.create({
                UserId: req.user,
                ReleaseId: releaseId
            }).success(function(cartItem) {
                res.send();
            })
        });
    });

    app.post('/me/cart/track/:id', authenticationUtils.ensureAuthenticated, function(req, res) {
        var trackId = req.params.id
        model.User.find({
            where: {
                id: req.user
            }
        }).then(function(user) {
            if (!user) {
                return res.status(400).send({
                    message: 'User not found'
                });
            }

            model.CartItem.create({
                UserId: req.user,
                TrackId: trackId
            }).success(function(cartItem) {
                res.send();
            })
        });
    });

    app.delete('/me/cart/track/:id', authenticationUtils.ensureAuthenticated, function(req, res) {
        var trackId = req.params.id;
        console.log("DELETE TRACK")
        model.CartItem.findOne({
            where: {
                UserId: req.user,
                TrackId: trackId
            }
        }).then(function(cartItem) {
            cartItem.destroy().then(function() {
                res.send();
            })
            console.log(cartItem)
        });
    });

    app.delete('/me/cart/release/:id', authenticationUtils.ensureAuthenticated, function(req, res) {
        var releaseId = req.params.id;
        console.log("DELETE RELEASE")
        model.CartItem.findOne({
            where: {
                UserId: req.user,
                ReleaseId: releaseId
            }
        }).then(function(cartItem) {
            cartItem.destroy().then(function() {
                res.send();
            })
            console.log(cartItem)
        });
    });

    /**
     * GET /me/companies/
     * Get all companies managed by the authenticated user or all companies in the system
     * if the user is admin
     */
    app.get('/me/companies', authenticationUtils.ensureAuthenticated, function(req, res) {

        model.User.find({
            where: {
                id: req.user
            }
        }).then(function(user) {
            if (user.isAdmin) {
                model.Company.findAll().success(function(companies) {
                    res.send(companies);
                })
            } else {
                user.getCompanies().success(function(companies) {
                    res.send(companies);
                })
            }

        })
    });

    /**
     * GET /me/labels/
     * Get all labels managed by the authenticated user or all labels in the system
     * if the user is admin
     */
    app.get('/me/labels', authenticationUtils.ensureAuthenticated, function(req, res) {

        model.User.find({
            where: {
                id: req.user
            }
        }).then(function(user) {
            if (user.isAdmin) {
                model.Label.findAll().success(function(labels) {
                    res.send(labels);
                })
            } else {
                user.getLabels().success(function(labels) {
                    res.send(labels);
                })
            }
        })
    });

    /**
     * GET /me/artists/
     * Get all artists managed by the authenticated user
     */
    app.get('/me/artists', authenticationUtils.ensureAuthenticated, function(req, res) {

        model.User.find({
            where: {
                id: req.user
            }
        }).then(function(user) {
            if (user.isAdmin) {
                model.Artist.findAll().success(function(artists) {
                    res.send(artists);
                })
            } else {
                user.getArtists().success(function(artists) {
                    res.send(artists);
                })
            }

        })
    });

    /**
     * PUT /api/me
     * Update the authenticated user profile information
     **/
    app.put('/me', authenticationUtils.ensureAuthenticated, function(req, res) {
        model.User.find({
            where: {
                id: req.user
            }
        }).then(function(user) {
            if (!user) {
                return res.status(400).send({
                    message: 'User not found'
                });
            }
            user.displayName = req.body.displayName || user.displayName;
            user.email = req.body.email || user.email;
            user.save(function(err) {
                res.status(200).end();
            });
        });
    });

    /**
     * POST /upload/profilePicture/:width/:height/
     * Upload user profile picture to the CDN, original size and resized
     **/
    app.post('/upload/profilePicture/:width/:height/',
        authenticationUtils.ensureAuthenticated,
        fileUtils.uploadFunction(fileUtils.localImagePath, fileUtils.remoteImagePath),
        fileUtils.resizeFunction(fileUtils.localImagePath, fileUtils.remoteImagePath),
        function(req, res, next) {

            model.User.find({
                where: {
                    id: req.user
                }
            }).then(function(user) {
                // We store CDN address as avatar
                var oldAvatar = user.avatar;
                var oldFullSizeAvatar = user.fullSizeAvatar;
                user.avatar = fileUtils.remoteImagePath(req, req.uploadedFile[0].resizedFilename);
                user.fullSizeAvatar = fileUtils.remoteImagePath(req, req.uploadedFile[0].filename);
                user.save().then(function(user) {
                    // we remove old avatars from the CDN
                    cloudstorage.remove(oldAvatar);
                    cloudstorage.remove(oldFullSizeAvatar);
                    // We remove temporarily stored files
                    fs.unlink(fileUtils.localImagePath(req, req.uploadedFile[0].filename));
                    fs.unlink(fileUtils.localImagePath(req, req.uploadedFile[0].resizedFilename));

                    res.writeHead(200, {
                        "content-type": "text/html"
                    }); //http response header
                    res.end(JSON.stringify(req.uploadedFile));
                });
            }); /* Database read callback */
        }); /* POST /upload/profilePicture/:width/:height/ */

    /**
     * GET /users/search/
     * Look for a user by displayName
     **/
    app.get('/users/search/:searchString', authenticationUtils.ensureAuthenticated, authenticationUtils.ensureAdmin, function(req, res) {
        var searchString = req.params.searchString;
        model.User.findAll({
            where: {
                displayName: searchString
            }
        }).then(function(users) {
            console.log(users)
            res.send(users);
        });
    });

} /* End of users controller */<commit_msg>added comment for future extension<commit_after>'use strict';

var fs = require('fs-extra');

var fileUtils = rootRequire('utils/file-utils');
var authenticationUtils = rootRequire('utils/authentication-utils');
var model = rootRequire('models/model');
var cloudstorage = rootRequire('libs/cloudstorage/cloudstorage');

module.exports.controller = function(app) {

    /**
     * GET /me
     * Get authenticated user profile information
     */
    app.get('/me', authenticationUtils.ensureAuthenticated, function(req, res) {

        model.User.find({
            where: {
                id: req.user
            }
        }).then(function(user) {
            res.send(user);
        });
    });

    /**
     * GET /me
     * Get authenticated user profile information
     */
    app.get('/me/cart', authenticationUtils.ensureAuthenticated, function(req, res) {

        model.User.find({
            where: {
                id: req.user
            }
        }).then(function(user) {

            user.getCartItems({
                include: [{
                        model: model.Track,
                        include: [{
                            model: model.Artist,
                            as: 'Producer'
                        }]
                    }, // load all pictures
                    {
                        model: model.Release,
                        include: [{
                            model: model.Track
                        }]
                    }, // load the profile picture. Notice that the spelling must be the exact same as the one in the association
                ]
            }).success(function(items) {
                res.send(items);
            })

        })
    });

    app.get('/me/cart/currency', authenticationUtils.ensureAuthenticated, function(req, res) {
        // QUESTION:  shall we change CURRENCY at every connection ?
        // A User that lives in london, is traveling to US, which currency shall we display?

        if (req.user) {
            // THERE IS A User, let's loook up his id

            model.User.find({
                where: {
                    id: req.user
                }
            }).then(function(user) {

                user.getCurrency({

                }).success(function(currency) {
                    res.send(currency)
                })

            })

        } else {
            // there is no user yet, let's pick a standard currency
            //
            // TODO :  implement geoIP here.

            model.Currency.find({
                where: {
                    id: 1
                }
            }).then(function(currency) {
                res.send(currency)
            })
        }

    });

    /**
     * PUT /api/me
     * Update the authenticated user profile information
     **/
    app.post('/me/cart/release/:id', authenticationUtils.ensureAuthenticated, function(req, res) {
        var releaseId = req.params.id
        model.User.find({
            where: {
                id: req.user
            }
        }).then(function(user) {
            if (!user) {
                return res.status(400).send({
                    message: 'User not found'
                });
            }

            model.CartItem.create({
                UserId: req.user,
                ReleaseId: releaseId
            }).success(function(cartItem) {
                res.send();
            })
        });
    });

    app.post('/me/cart/track/:id', authenticationUtils.ensureAuthenticated, function(req, res) {
        var trackId = req.params.id
        model.User.find({
            where: {
                id: req.user
            }
        }).then(function(user) {
            if (!user) {
                return res.status(400).send({
                    message: 'User not found'
                });
            }

            model.CartItem.create({
                UserId: req.user,
                TrackId: trackId
            }).success(function(cartItem) {
                res.send();
            })
        });
    });

    app.delete('/me/cart/track/:id', authenticationUtils.ensureAuthenticated, function(req, res) {
        var trackId = req.params.id;
        console.log("DELETE TRACK")
        model.CartItem.findOne({
            where: {
                UserId: req.user,
                TrackId: trackId
            }
        }).then(function(cartItem) {
            cartItem.destroy().then(function() {
                res.send();
            })
            console.log(cartItem)
        });
    });

    app.delete('/me/cart/release/:id', authenticationUtils.ensureAuthenticated, function(req, res) {
        var releaseId = req.params.id;
        console.log("DELETE RELEASE")
        model.CartItem.findOne({
            where: {
                UserId: req.user,
                ReleaseId: releaseId
            }
        }).then(function(cartItem) {
            cartItem.destroy().then(function() {
                res.send();
            })
            console.log(cartItem)
        });
    });

    /**
     * GET /me/companies/
     * Get all companies managed by the authenticated user or all companies in the system
     * if the user is admin
     */
    app.get('/me/companies', authenticationUtils.ensureAuthenticated, function(req, res) {

        model.User.find({
            where: {
                id: req.user
            }
        }).then(function(user) {
            if (user.isAdmin) {
                model.Company.findAll().success(function(companies) {
                    res.send(companies);
                })
            } else {
                user.getCompanies().success(function(companies) {
                    res.send(companies);
                })
            }

        })
    });

    /**
     * GET /me/labels/
     * Get all labels managed by the authenticated user or all labels in the system
     * if the user is admin
     */
    app.get('/me/labels', authenticationUtils.ensureAuthenticated, function(req, res) {

        model.User.find({
            where: {
                id: req.user
            }
        }).then(function(user) {
            if (user.isAdmin) {
                model.Label.findAll().success(function(labels) {
                    res.send(labels);
                })
            } else {
                user.getLabels().success(function(labels) {
                    res.send(labels);
                })
            }
        })
    });

    /**
     * GET /me/artists/
     * Get all artists managed by the authenticated user
     */
    app.get('/me/artists', authenticationUtils.ensureAuthenticated, function(req, res) {

        model.User.find({
            where: {
                id: req.user
            }
        }).then(function(user) {
            if (user.isAdmin) {
                model.Artist.findAll().success(function(artists) {
                    res.send(artists);
                })
            } else {
                user.getArtists().success(function(artists) {
                    res.send(artists);
                })
            }

        })
    });

    /**
     * PUT /api/me
     * Update the authenticated user profile information
     **/
    app.put('/me', authenticationUtils.ensureAuthenticated, function(req, res) {
        model.User.find({
            where: {
                id: req.user
            }
        }).then(function(user) {
            if (!user) {
                return res.status(400).send({
                    message: 'User not found'
                });
            }
            user.displayName = req.body.displayName || user.displayName;
            user.email = req.body.email || user.email;
            user.save(function(err) {
                res.status(200).end();
            });
        });
    });

    /**
     * POST /upload/profilePicture/:width/:height/
     * Upload user profile picture to the CDN, original size and resized
     **/
    app.post('/upload/profilePicture/:width/:height/',
        authenticationUtils.ensureAuthenticated,
        fileUtils.uploadFunction(fileUtils.localImagePath, fileUtils.remoteImagePath),
        fileUtils.resizeFunction(fileUtils.localImagePath, fileUtils.remoteImagePath),
        function(req, res, next) {

            model.User.find({
                where: {
                    id: req.user
                }
            }).then(function(user) {
                // We store CDN address as avatar
                var oldAvatar = user.avatar;
                var oldFullSizeAvatar = user.fullSizeAvatar;
                user.avatar = fileUtils.remoteImagePath(req, req.uploadedFile[0].resizedFilename);
                user.fullSizeAvatar = fileUtils.remoteImagePath(req, req.uploadedFile[0].filename);
                user.save().then(function(user) {
                    // we remove old avatars from the CDN
                    cloudstorage.remove(oldAvatar);
                    cloudstorage.remove(oldFullSizeAvatar);
                    // We remove temporarily stored files
                    fs.unlink(fileUtils.localImagePath(req, req.uploadedFile[0].filename));
                    fs.unlink(fileUtils.localImagePath(req, req.uploadedFile[0].resizedFilename));

                    res.writeHead(200, {
                        "content-type": "text/html"
                    }); //http response header
                    res.end(JSON.stringify(req.uploadedFile));
                });
            }); /* Database read callback */
        }); /* POST /upload/profilePicture/:width/:height/ */

    /**
     * GET /users/search/
     * Look for a user by displayName
     **/
    app.get('/users/search/:searchString', authenticationUtils.ensureAuthenticated, authenticationUtils.ensureAdmin, function(req, res) {
        var searchString = req.params.searchString;
        model.User.findAll({
            where: {
                displayName: searchString
            }
        }).then(function(users) {
            console.log(users)
            res.send(users);
        });
    });

} /* End of users controller */<|endoftext|>


<commit_before>'use strict'

const { EventEmitter } = require('events')

const Result = require('./result')
const utils = require('./utils')

class Query extends EventEmitter {
  constructor(config, values, callback) {
    super()

    config = utils.normalizeQueryConfig(config, values, callback)

    this.text = config.text
    this.values = config.values
    this.rows = config.rows
    this.types = config.types
    this.name = config.name
    this.binary = config.binary
    // use unique portal name each time
    this.portal = config.portal || ''
    this.callback = config.callback
    this._rowMode = config.rowMode
    if (process.domain && config.callback) {
      this.callback = process.domain.bind(config.callback)
    }
    this._result = new Result(this._rowMode, this.types)

    // potential for multiple results
    this._results = this._result
    this.isPreparedStatement = false
    this._canceledDueToError = false
    this._promise = null
    this._hasSentSync = false
  }

  requiresPreparation() {
    // named queries must always be prepared
    if (this.name) {
      return true
    }
    // always prepare if there are max number of rows expected per
    // portal execution
    if (this.rows) {
      return true
    }
    // don't prepare empty text queries
    if (!this.text) {
      return false
    }
    // prepare if there are values
    if (!this.values) {
      return false
    }
    return this.values.length > 0
  }

  _checkForMultirow() {
    // if we already have a result with a command property
    // then we've already executed one query in a multi-statement simple query
    // turn our results into an array of results
    if (this._result.command) {
      if (!Array.isArray(this._results)) {
        this._results = [this._result]
      }
      this._result = new Result(this._rowMode, this.types)
      this._results.push(this._result)
    }
  }

  // associates row metadata from the supplied
  // message with this query object
  // metadata used when parsing row results
  handleRowDescription(msg) {
    this._checkForMultirow()
    this._result.addFields(msg.fields)
    this._accumulateRows = this.callback || !this.listeners('row').length
  }

  handleDataRow(msg) {
    let row

    if (this._canceledDueToError) {
      return
    }

    try {
      row = this._result.parseRow(msg.fields)
    } catch (err) {
      this._canceledDueToError = err
      return
    }

    this.emit('row', row, this._result)
    if (this._accumulateRows) {
      this._result.addRow(row)
    }
  }

  handleCommandComplete(msg, connection) {
    this._checkForMultirow()
    this._result.addCommandComplete(msg)
    // need to sync after each command complete of a prepared statement
    this.maybeSync(connection)
  }

  // if a named prepared statement is created with empty query text
  // the backend will send an emptyQuery message but *not* a command complete message
  // execution on the connection will hang until the backend receives a sync message
  handleEmptyQuery(connection) {
    this.maybeSync(connection)
  }

  handleError(err, connection) {
    // need to sync after error during a prepared statement
    this.maybeSync(connection)
    if (this._canceledDueToError) {
      err = this._canceledDueToError
      this._canceledDueToError = false
    }
    // if callback supplied do not emit error event as uncaught error
    // events will bubble up to node process
    if (this.callback) {
      return this.callback(err)
    }
    this.emit('error', err)
  }

  handleReadyForQuery(con) {
    if (this._canceledDueToError) {
      return this.handleError(this._canceledDueToError, con)
    }
    if (this.callback) {
      this.callback(null, this._results)
    }
    this.emit('end', this._results)
  }

  // In postgres 9.x & 10.x the backend sends both a CommandComplete and ErrorResponse
  // to the same query when it times out due to a statement_timeout on rare, random occasions.  If we send sync twice we will receive
  // to ReadyForQuery messages .  I hink this might be a race condition in some versions of postgres, but I'm not sure...
  // the docs here: https://www.postgresql.org/docs/9.6/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY
  // say "Therefore, an Execute phase is always terminated by the appearance of exactly one of these messages:
  // CommandComplete, EmptyQueryResponse (if the portal was created from an empty query string), ErrorResponse, or PortalSuspended."
  maybeSync(connection) {
    if (this.isPreparedStatement && !this._hasSentSync) {
      this._hasSentSync = true
      connection.sync()
    }
  }

  submit(connection) {
    if (typeof this.text !== 'string' && typeof this.name !== 'string') {
      return new Error('A query must have either text or a name. Supplying neither is unsupported.')
    }
    const previous = connection.parsedStatements[this.name]
    if (this.text && previous && this.text !== previous) {
      return new Error(`Prepared statements must be unique - '${this.name}' was used for a different statement`)
    }
    if (this.values && !Array.isArray(this.values)) {
      return new Error('Query values must be an array')
    }
    if (this.requiresPreparation()) {
      this.prepare(connection)
    } else {
      connection.query(this.text)
    }
    return null
  }

  hasBeenParsed(connection) {
    return this.name && connection.parsedStatements[this.name]
  }

  handlePortalSuspended(connection) {
    this._getRows(connection, this.rows)
  }

  _getRows(connection, rows) {
    connection.execute({
      portal: this.portal,
      rows: rows,
    })
    connection.flush()
  }

  // http://developer.postgresql.org/pgdocs/postgres/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY
  prepare(connection) {
    // prepared statements need sync to be called after each command
    // complete or when an error is encountered
    this.isPreparedStatement = true

    // TODO refactor this poor encapsulation
    if (!this.hasBeenParsed(connection)) {
      connection.parse({
        text: this.text,
        name: this.name,
        types: this.types,
      })
    }

    if (this.values) {
      try {
        this.values = this.values.map(utils.prepareValue)
      } catch (err) {
        this.handleError(err, connection)
        return
      }
    }

    connection.bind({
      portal: this.portal,
      statement: this.name,
      values: this.values,
      binary: this.binary,
    })

    connection.describe({
      type: 'P',
      name: this.portal || '',
    })

    this._getRows(connection, this.rows)
  }

  handleCopyInResponse(connection) {
    connection.sendCopyFail('No source stream defined')
  }

  // eslint-disable-next-line no-unused-vars
  handleCopyData(msg, connection) {
    // noop
  }
}

module.exports = Query
<commit_msg>Change when sync is sent during pipelining<commit_after>'use strict'

const { EventEmitter } = require('events')

const Result = require('./result')
const utils = require('./utils')

class Query extends EventEmitter {
  constructor(config, values, callback) {
    super()

    config = utils.normalizeQueryConfig(config, values, callback)

    this.text = config.text
    this.values = config.values
    this.rows = config.rows
    this.types = config.types
    this.name = config.name
    this.binary = config.binary
    // use unique portal name each time
    this.portal = config.portal || ''
    this.callback = config.callback
    this._rowMode = config.rowMode
    if (process.domain && config.callback) {
      this.callback = process.domain.bind(config.callback)
    }
    this._result = new Result(this._rowMode, this.types)

    // potential for multiple results
    this._results = this._result
    this.isPreparedStatement = false
    this._canceledDueToError = false
    this._promise = null
    this._hasSentSync = false
  }

  requiresPreparation() {
    // named queries must always be prepared
    if (this.name) {
      return true
    }
    // always prepare if there are max number of rows expected per
    // portal execution
    if (this.rows) {
      return true
    }
    // don't prepare empty text queries
    if (!this.text) {
      return false
    }
    // prepare if there are values
    if (!this.values) {
      return false
    }
    return this.values.length > 0
  }

  _checkForMultirow() {
    // if we already have a result with a command property
    // then we've already executed one query in a multi-statement simple query
    // turn our results into an array of results
    if (this._result.command) {
      if (!Array.isArray(this._results)) {
        this._results = [this._result]
      }
      this._result = new Result(this._rowMode, this.types)
      this._results.push(this._result)
    }
  }

  // associates row metadata from the supplied
  // message with this query object
  // metadata used when parsing row results
  handleRowDescription(msg) {
    this._checkForMultirow()
    this._result.addFields(msg.fields)
    this._accumulateRows = this.callback || !this.listeners('row').length
  }

  handleDataRow(msg) {
    let row

    if (this._canceledDueToError) {
      return
    }

    try {
      row = this._result.parseRow(msg.fields)
    } catch (err) {
      this._canceledDueToError = err
      return
    }

    this.emit('row', row, this._result)
    if (this._accumulateRows) {
      this._result.addRow(row)
    }
  }

  handleCommandComplete(msg, connection) {
    this._checkForMultirow()
    this._result.addCommandComplete(msg)
    // need to sync after each command complete of a prepared statement
    // if we were using a row count which results in multiple calls to _getRows
    if (this.rows) {
      this.maybeSync(connection)
    }
  }

  // if a named prepared statement is created with empty query text
  // the backend will send an emptyQuery message but *not* a command complete message
  // execution on the connection will hang until the backend receives a sync message
  handleEmptyQuery(connection) {
    // this.maybeSync(connection)
  }

  handleError(err, connection) {
    // need to sync after error during a prepared statement
    // this.maybeSync(connection)
    if (this._canceledDueToError) {
      err = this._canceledDueToError
      this._canceledDueToError = false
    }
    // if callback supplied do not emit error event as uncaught error
    // events will bubble up to node process
    if (this.callback) {
      return this.callback(err)
    }
    this.emit('error', err)
  }

  handleReadyForQuery(con) {
    if (this._canceledDueToError) {
      return this.handleError(this._canceledDueToError, con)
    }
    if (this.callback) {
      this.callback(null, this._results)
    }
    this.emit('end', this._results)
  }

  // In postgres 9.x & 10.x the backend sends both a CommandComplete and ErrorResponse
  // to the same query when it times out due to a statement_timeout on rare, random occasions.  If we send sync twice we will receive
  // to ReadyForQuery messages .  I hink this might be a race condition in some versions of postgres, but I'm not sure...
  // the docs here: https://www.postgresql.org/docs/9.6/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY
  // say "Therefore, an Execute phase is always terminated by the appearance of exactly one of these messages:
  // CommandComplete, EmptyQueryResponse (if the portal was created from an empty query string), ErrorResponse, or PortalSuspended."
  maybeSync(connection) {
    if (this.isPreparedStatement) {
      this._hasSentSync = true
      connection.sync()
    }
  }

  submit(connection) {
    if (typeof this.text !== 'string' && typeof this.name !== 'string') {
      return new Error('A query must have either text or a name. Supplying neither is unsupported.')
    }
    const previous = connection.parsedStatements[this.name]
    if (this.text && previous && this.text !== previous) {
      return new Error(`Prepared statements must be unique - '${this.name}' was used for a different statement`)
    }
    if (this.values && !Array.isArray(this.values)) {
      return new Error('Query values must be an array')
    }
    if (this.requiresPreparation()) {
      this.prepare(connection)
    } else {
      connection.query(this.text)
    }
    return null
  }

  hasBeenParsed(connection) {
    return this.name && connection.parsedStatements[this.name]
  }

  handlePortalSuspended(connection) {
    this._getRows(connection, this.rows)
  }

  _getRows(connection, rows) {
    connection.execute({
      portal: this.portal,
      rows: rows,
    })
    if (!rows) {
      this.maybeSync(connection)
    } else {
      connection.flush()
    }
  }

  // http://developer.postgresql.org/pgdocs/postgres/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY
  prepare(connection) {
    // prepared statements need sync to be called after each command
    // complete or when an error is encountered
    this.isPreparedStatement = true

    // TODO refactor this poor encapsulation
    if (!this.hasBeenParsed(connection)) {
      connection.parse({
        text: this.text,
        name: this.name,
        types: this.types,
      })
    }

    if (this.values) {
      try {
        this.values = this.values.map(utils.prepareValue)
      } catch (err) {
        this.handleError(err, connection)
        return
      }
    }

    connection.bind({
      portal: this.portal,
      statement: this.name,
      values: this.values,
      binary: this.binary,
    })

    connection.describe({
      type: 'P',
      name: this.portal || '',
    })

    this._getRows(connection, this.rows)
  }

  handleCopyInResponse(connection) {
    connection.sendCopyFail('No source stream defined')
  }

  // eslint-disable-next-line no-unused-vars
  handleCopyData(msg, connection) {
    // noop
  }
}

module.exports = Query
<|endoftext|>


<commit_before>window.cls || (window.cls = {});

cls.CookieManagerView = function(id, name, container_class)
{
  this._cookie_dict = {};
  this._flattened_cookies = [];
  this._rts = {};
  this._tabledef = {
    groups: {
      hostandpath: {
        label:    "Host and path",
        grouper:  function(obj) {
          return window.views.cookie_manager._rts[obj.runtimes[0]].hostname + window.views.cookie_manager._rts[obj.runtimes[0]].pathname;
        },
        renderer: function(groupvalue, obj) {
          var obj = obj[0];
          var runtime = window.views.cookie_manager._rts[obj.runtimes[0]];
          return window.templates.cookie_manager.hostname_group_render(runtime);
        }
      }
    },
    columns: {
      domain: {
        label: ui_strings.S_LABEL_COOKIE_MANAGER_COOKIE_DOMAIN
      },
      name: {
        label:    ui_strings.S_LABEL_COOKIE_MANAGER_COOKIE_NAME,
        renderer: function(obj) {
          if(obj.is_editable)
          {
            return window.templates.cookie_manager.table_view.editable_name(obj.name, obj.objectref);
          }
          else
          {
            return obj.name;
          }
        }
      },
      value: {
        label:    ui_strings.S_LABEL_COOKIE_MANAGER_COOKIE_VALUE,
        renderer: function(obj) {
          if(obj.is_editable)
          {
            return window.templates.cookie_manager.table_view.editable_value(decodeURIComponent(obj.value), obj.objectref);
          }
          else
          {
            return obj.value;
          }
        }
      },
      path: {
        label:    ui_strings.S_LABEL_COOKIE_MANAGER_COOKIE_PATH,
        renderer: function(obj) {
          return obj.path;
        }
      },
      expires: {
        label:    ui_strings.S_LABEL_COOKIE_MANAGER_COOKIE_EXPIRES,
        renderer: function(obj) {
          var parsedDate=new Date(obj.expires*1000);
          if(new Date().getTime() < parsedDate.getTime())
          {
            return parsedDate.toUTCString();
          }
          return window.templates.cookie_manager.table_view.expires_0values();
        }
      },
      isSecure: {
        label:    ui_strings.S_LABEL_COOKIE_MANAGER_SECURE_CONNECTIONS_ONLY,
        renderer: function(obj) { return obj.isSecure? "Yes":""; }
      },
      isHTTPOnly: {
        label:    ui_strings.S_LABEL_COOKIE_MANAGER_HTTP_ONLY,
        renderer: function(obj) { return obj.isHTTPOnly? "Yes":""; }
      },
      remove: {
        label:    "",
        renderer: function(obj) { return window.templates.cookie_manager.table_view.remove_button(obj.objectref); }
      }
    }
  };
  this.createView = function(container)
  {
    this._flattened_cookies = this._flatten_cookies(this._cookie_dict);
    container.clearAndRender(new SortableTable(this._tabledef, this._flattened_cookies).render());

    var table = document.getElementsByClassName("cookie_manager")[0].getElementsByClassName("sortable-table")[0];
    var obj = ObjectRegistry.get_instance().get_object(table.getAttribute("data-object-id"));
    // group by host and path as that is what's used for the actual query
    obj.group("hostandpath");
    table.re_render(obj.render());

    // render cookie adding
    container.render(window.templates.cookie_manager.add_cookie_form(this._rts));
    window.eventHandlers.change['cookiemanager-add-cookie-domain-select']();
    // render clear and update button. todo: move to where it always appears
    container.render(window.templates.cookie_manager.clear_and_refetch_button());
  };

  this._on_active_tab = function(msg)
  {
    // cleanup view
    this.clearAllContainers();

    // cleanup runtimes directory
    for(var item in this._rts)
    {
      // item is a string, rt_id is a number which can now be compared with what's in msg.activeTab
      var rt_id = this._rts[item].rt_id;
      if(msg.activeTab.indexOf(rt_id) === -1)
      {
        // runtime was not active and is to be removed from this._rts
        delete this._rts[rt_id];
        // loop over existing cookies to remove the rt_id from the runtimes of each
        for(var domain in this._cookie_dict)
        {
          if(this._cookie_dict[domain].runtimes && (this._cookie_dict[domain].runtimes.indexOf(rt_id) !== -1))
          {
            var index = this._cookie_dict[domain].runtimes.indexOf(rt_id);
            this._cookie_dict[domain].runtimes.splice(index,1);
          }
        }
      }
    }

    for (var i=0; i < msg.activeTab.length; i++)
    {
      var rt_id = msg.activeTab[i];
      if(!this._rts[rt_id])
      {
        this._rts[rt_id]={rt_id: rt_id, get_domain_is_pending: true};
      }
      this._request_runtime_details(this._rts[rt_id]);
    };
  };

  this._request_runtime_details = function(rt_object) {
    var script = "return JSON.stringify({hostname: location.hostname || '', pathname: location.pathname || ''})";
    var tag = tagManager.set_callback(this, this._handle_get_domain,[rt_object.rt_id]);
    services['ecmascript-debugger'].requestEval(tag,[rt_object.rt_id, 0, 0, script]);
  }

  this._refetch = function() {
    for (var rt_id in this._rts) {
      this._rts[rt_id].get_domain_is_pending = true;
      this._request_runtime_details(this._rts[rt_id]);
    };
  }

  this._handle_get_domain = function(status, message, rt_id)
  {
    var data = JSON.parse(message[2]);
    var hostname = data.hostname;
    var pathname = data.pathname;
    this._rts[rt_id].get_domain_is_pending = false;
    this._rts[rt_id].hostname = hostname;
    this._rts[rt_id].pathname = pathname;

    (function(context)
    {
      for (var key in context._rts)
      {
        if(context._rts[key]["get_domain_is_pending"] !== false)
        {
          return;
        }
      };
      context._clean_domains_and_ask_for_cookies.call(context,context._rts)
    })(this);
  }

  this._clean_domains_and_ask_for_cookies = function(runtime_list)
  {
    // check this._cookies for domains that aren't in any runtime anymore, modifies "this._cookies" directly
    this._clean_domain_list(this._cookie_dict, runtime_list);
    // go over runtimes and ask for cookies once per domain
    for (var str_rt_id in runtime_list)
    {
      var runtime = runtime_list[str_rt_id];
      var rt_domain = runtime.hostname;
      var rt_pathname = runtime.pathname;
      if(rt_domain) // avoids "" values occuring on opera:* pages for example
      {
        if(!this._cookie_dict[rt_domain+rt_pathname])
        {
          this._cookie_dict[rt_domain+rt_pathname] = {
            runtimes: [runtime.rt_id]
          }
        }
        else
        {
          if(this._cookie_dict[rt_domain+rt_pathname].runtimes.indexOf(runtime.rt_id) === -1)
          {
            this._cookie_dict[rt_domain+rt_pathname].runtimes.push(runtime.rt_id);
          }
        }

        // avoid repeating cookie requests for domains being in more than one runtime
        if(!this._cookie_dict[rt_domain+rt_pathname].get_cookies_is_pending)
        {
          this._cookie_dict[rt_domain+rt_pathname].get_cookies_is_pending = true;
          var tag = tagManager.set_callback(this, this._handle_cookies,[rt_domain,rt_pathname]);
          services['cookie-manager'].requestGetCookie(tag,[rt_domain,rt_pathname]);
        }
      }
    }
  }

  this._handle_cookies = function(status, message, domain, path)
  {
    this._cookie_dict[domain+path].get_cookies_is_pending=false;
    if(message.length > 0)
    {
      var cookies = message[0];
      this._cookie_dict[domain+path].cookies=[];
      for (var i=0; i < cookies.length; i++) {
        var cookie_info = cookies[i];
        this._cookie_dict[domain+path].cookies.push({
          domain:     cookie_info[0],
          path:       cookie_info[1],
          name:       cookie_info[2],
          value:      cookie_info[3],
          expires:    cookie_info[4],
          isSecure:   cookie_info[5],
          isHTTPOnly: cookie_info[6]
        });
      };
    }
    window.views.cookie_manager.update();
  };

  this._handle_changed_cookies = function(status, message)
  {
    window.views.cookie_manager._refetch();
  };

  this._init = function(id, update_event_name)
  {
    window.messages.addListener('active-tab', this._on_active_tab.bind(this));
    this.init(id, name, container_class);
  };

  // Helpers
  this._clean_domain_list = function(cookies, runtime_list)
  {
    for (var domain in cookies)
    {
      var was_found_in_runtime = false;
      for (var rtid in runtime_list)
      {
        if(runtime_list[rtid].domain === domain)
        {
          was_found_in_runtime = true;
          break;
        }
      };
      if(!was_found_in_runtime)
      {
        delete cookies[domain];
      }
    };
  }
  this._flatten_cookies = function(cookies)
  {
    var flattened_cookies = [];
    for (var id in cookies)
    {
      var domaincookies = cookies[id];
      if (domaincookies.cookies)
      {
        for (var i=0; i < domaincookies.cookies.length ;i++)
        {
          var current_cookie = domaincookies.cookies[i];
          var flattened_cookie = {
            objectref:   current_cookie.domain + "/" + current_cookie.path + current_cookie.name + (parseInt(Math.random()*99999)),
            runtimes:    domaincookies.runtimes,
            is_editable: (function(cookie){
              /**
               * Decides if the cookie name & value can be edited.
               * Must remove the cookie.path condition when CORE-35055 is fixed, must remove
               * the cookie.domain when a new "add cookie" interface from CORE-35370 is used
               * (allows specifying the domain when creating new cookie)
              */
              if(
                cookie.isHTTPOnly ||
                cookie.path ||
                cookie.domain != window.views.cookie_manager._rts[domaincookies.runtimes[0]].hostname
              )
              {
                return false;
              }
              return true;
            })(current_cookie)
          };
          for (var key in current_cookie) {
            flattened_cookie[key] = current_cookie[key];
          };
          flattened_cookies.push(flattened_cookie);
        };
      }
    }
    return flattened_cookies;
  }
  // End Helpers
  this._init(id, name);
};

cls.CookieManagerView.prototype = ViewBase;
<commit_msg>Formatting..<commit_after>window.cls || (window.cls = {});

cls.CookieManagerView = function(id, name, container_class)
{
  this._cookie_dict = {};
  this._flattened_cookies = [];
  this._rts = {};
  this._tabledef = {
    groups: {
      hostandpath: {
        label:    "Host and path",
        grouper:  function(obj) {
          return window.views.cookie_manager._rts[obj.runtimes[0]].hostname + window.views.cookie_manager._rts[obj.runtimes[0]].pathname;
        },
        renderer: function(groupvalue, obj) {
          var obj = obj[0];
          var runtime = window.views.cookie_manager._rts[obj.runtimes[0]];
          return window.templates.cookie_manager.hostname_group_render(runtime);
        }
      }
    },
    columns: {
      domain: {
        label: ui_strings.S_LABEL_COOKIE_MANAGER_COOKIE_DOMAIN
      },
      name: {
        label:    ui_strings.S_LABEL_COOKIE_MANAGER_COOKIE_NAME,
        renderer: function(obj) {
          if(obj.is_editable)
          {
            return window.templates.cookie_manager.table_view.editable_name(obj.name, obj.objectref);
          }
          else
          {
            return obj.name;
          }
        }
      },
      value: {
        label:    ui_strings.S_LABEL_COOKIE_MANAGER_COOKIE_VALUE,
        renderer: function(obj) {
          if(obj.is_editable)
          {
            return window.templates.cookie_manager.table_view.editable_value(decodeURIComponent(obj.value), obj.objectref);
          }
          else
          {
            return obj.value;
          }
        }
      },
      path: {
        label:    ui_strings.S_LABEL_COOKIE_MANAGER_COOKIE_PATH,
        renderer: function(obj) {
          return obj.path;
        }
      },
      expires: {
        label:    ui_strings.S_LABEL_COOKIE_MANAGER_COOKIE_EXPIRES,
        renderer: function(obj) {
          var parsedDate=new Date(obj.expires*1000);
          if(new Date().getTime() < parsedDate.getTime())
          {
            return parsedDate.toUTCString();
          }
          return window.templates.cookie_manager.table_view.expires_0values();
        }
      },
      isSecure: {
        label:    ui_strings.S_LABEL_COOKIE_MANAGER_SECURE_CONNECTIONS_ONLY,
        renderer: function(obj) { return obj.isSecure? "Yes":""; }
      },
      isHTTPOnly: {
        label:    ui_strings.S_LABEL_COOKIE_MANAGER_HTTP_ONLY,
        renderer: function(obj) { return obj.isHTTPOnly? "Yes":""; }
      },
      remove: {
        label:    "",
        renderer: function(obj) { return window.templates.cookie_manager.table_view.remove_button(obj.objectref); }
      }
    }
  };
  this.createView = function(container)
  {
    this._flattened_cookies = this._flatten_cookies(this._cookie_dict);
    container.clearAndRender(new SortableTable(this._tabledef, this._flattened_cookies).render());

    var table = document.getElementsByClassName("cookie_manager")[0].getElementsByClassName("sortable-table")[0];
    var obj = ObjectRegistry.get_instance().get_object(table.getAttribute("data-object-id"));
    // group by host and path as that is what's used for the actual query
    obj.group("hostandpath");
    table.re_render(obj.render());

    // render cookie adding
    container.render(window.templates.cookie_manager.add_cookie_form(this._rts));
    window.eventHandlers.change['cookiemanager-add-cookie-domain-select']();
    // render clear and update button. todo: move to where it always appears
    container.render(window.templates.cookie_manager.clear_and_refetch_button());
  };

  this._on_active_tab = function(msg)
  {
    // cleanup view
    this.clearAllContainers();

    // cleanup runtimes directory
    for(var item in this._rts)
    {
      // item is a string, rt_id is a number which can now be compared with what's in msg.activeTab
      var rt_id = this._rts[item].rt_id;
      if(msg.activeTab.indexOf(rt_id) === -1)
      {
        // runtime was not active and is to be removed from this._rts
        delete this._rts[rt_id];
        // loop over existing cookies to remove the rt_id from the runtimes of each
        for(var domain in this._cookie_dict)
        {
          if(this._cookie_dict[domain].runtimes && (this._cookie_dict[domain].runtimes.indexOf(rt_id) !== -1))
          {
            var index = this._cookie_dict[domain].runtimes.indexOf(rt_id);
            this._cookie_dict[domain].runtimes.splice(index,1);
          }
        }
      }
    }

    for (var i=0; i < msg.activeTab.length; i++)
    {
      var rt_id = msg.activeTab[i];
      if(!this._rts[rt_id])
      {
        this._rts[rt_id]={rt_id: rt_id, get_domain_is_pending: true};
      }
      this._request_runtime_details(this._rts[rt_id]);
    };
  };

  this._request_runtime_details = function(rt_object) {
    var script = "return JSON.stringify({hostname: location.hostname || '', pathname: location.pathname || ''})";
    var tag = tagManager.set_callback(this, this._handle_get_domain,[rt_object.rt_id]);
    services['ecmascript-debugger'].requestEval(tag,[rt_object.rt_id, 0, 0, script]);
  }

  this._refetch = function() {
    for (var rt_id in this._rts) {
      this._rts[rt_id].get_domain_is_pending = true;
      this._request_runtime_details(this._rts[rt_id]);
    };
  }

  this._handle_get_domain = function(status, message, rt_id)
  {
    const DATA = 2;
    var parsed_data = JSON.parse(message[2]);
    var hostname = parsed_data.hostname;
    var pathname = parsed_data.pathname;
    this._rts[rt_id].get_domain_is_pending = false;
    this._rts[rt_id].hostname = hostname;
    this._rts[rt_id].pathname = pathname;

    (function(context)
    {
      for (var key in context._rts)
      {
        if(context._rts[key]["get_domain_is_pending"] !== false)
        {
          return;
        }
      };
      context._clean_domains_and_ask_for_cookies.call(context,context._rts)
    })(this);
  }

  this._clean_domains_and_ask_for_cookies = function(runtime_list)
  {
    // check this._cookies for domains that aren't in any runtime anymore, modifies "this._cookies" directly
    this._clean_domain_list(this._cookie_dict, runtime_list);
    // go over runtimes and ask for cookies once per domain
    for (var str_rt_id in runtime_list)
    {
      var runtime = runtime_list[str_rt_id];
      var rt_domain = runtime.hostname;
      var rt_pathname = runtime.pathname;
      if(rt_domain) // avoids "" values occuring on opera:* pages for example
      {
        if(!this._cookie_dict[rt_domain+rt_pathname])
        {
          this._cookie_dict[rt_domain+rt_pathname] = {
            runtimes: [runtime.rt_id]
          }
        }
        else
        {
          if(this._cookie_dict[rt_domain+rt_pathname].runtimes.indexOf(runtime.rt_id) === -1)
          {
            this._cookie_dict[rt_domain+rt_pathname].runtimes.push(runtime.rt_id);
          }
        }

        // avoid repeating cookie requests for domains being in more than one runtime
        if(!this._cookie_dict[rt_domain+rt_pathname].get_cookies_is_pending)
        {
          this._cookie_dict[rt_domain+rt_pathname].get_cookies_is_pending = true;
          var tag = tagManager.set_callback(this, this._handle_cookies,[rt_domain,rt_pathname]);
          services['cookie-manager'].requestGetCookie(tag,[rt_domain,rt_pathname]);
        }
      }
    }
  }

  this._handle_cookies = function(status, message, domain, path)
  {
    const COOKIE = 0;
    this._cookie_dict[domain+path].get_cookies_is_pending=false;
    if(message.length > 0)
    {
      var cookies = message[COOKIE];
      this._cookie_dict[domain+path].cookies=[];
      for (var i=0; i < cookies.length; i++) {
        var cookie_info = cookies[i];
        this._cookie_dict[domain+path].cookies.push({
          domain:     cookie_info[0],
          path:       cookie_info[1],
          name:       cookie_info[2],
          value:      cookie_info[3],
          expires:    cookie_info[4],
          isSecure:   cookie_info[5],
          isHTTPOnly: cookie_info[6]
        });
      };
    }
    window.views.cookie_manager.update();
  };

  this._handle_changed_cookies = function(status, message)
  {
    window.views.cookie_manager._refetch();
  };

  this._init = function(id, update_event_name)
  {
    window.messages.addListener('active-tab', this._on_active_tab.bind(this));
    this.init(id, name, container_class);
  };

  // Helpers
  this._clean_domain_list = function(cookies, runtime_list)
  {
    for (var domain in cookies)
    {
      var was_found_in_runtime = false;
      for (var rtid in runtime_list)
      {
        if(runtime_list[rtid].domain === domain)
        {
          was_found_in_runtime = true;
          break;
        }
      };
      if(!was_found_in_runtime)
      {
        delete cookies[domain];
      }
    };
  }
  this._flatten_cookies = function(cookies)
  {
    var flattened_cookies = [];
    for (var id in cookies)
    {
      var domaincookies = cookies[id];
      if (domaincookies.cookies)
      {
        for (var i=0; i < domaincookies.cookies.length ;i++)
        {
          var current_cookie = domaincookies.cookies[i];
          var flattened_cookie = {
            objectref:   current_cookie.domain + "/" + current_cookie.path + current_cookie.name + (parseInt(Math.random()*99999)),
            runtimes:    domaincookies.runtimes,
            is_editable: (function(cookie){
              /**
               * Decides if the cookie name & value can be edited.
               * Must remove the cookie.path condition when CORE-35055 is fixed, must remove
               * the cookie.domain when a new "add cookie" interface from CORE-35370 is used
               * (allows specifying the domain when creating new cookie)
              */
              if(
                cookie.isHTTPOnly ||
                cookie.path ||
                cookie.domain != window.views.cookie_manager._rts[domaincookies.runtimes[0]].hostname
              )
              {
                return false;
              }
              return true;
            })(current_cookie)
          };
          for (var key in current_cookie) {
            flattened_cookie[key] = current_cookie[key];
          };
          flattened_cookies.push(flattened_cookie);
        };
      }
    }
    return flattened_cookies;
  }
  // End Helpers
  this._init(id, name);
};

cls.CookieManagerView.prototype = ViewBase;
<|endoftext|>


<commit_before>/* eslint react/no-multi-comp:0, no-console:0 */

import 'rc-tree-select/assets/index.css';
import './demo.less';
import React from 'react';
import ReactDOM from 'react-dom';
import 'rc-dialog/assets/index.less';
import Dialog from 'rc-dialog';
import TreeSelect, { TreeNode, SHOW_PARENT } from 'rc-tree-select';
import { gData } from './util';

const Demo = React.createClass({
  getInitialState() {
    return {
      visible: false,
      inputValue: '0-0-0-label',
      value: '0-0-0-value',
      // value: ['0-0-0-0-value', '0-0-0-1-value', '0-0-0-2-value'],
      multipleValue: [],
      simpleTreeData: [
        {'key': 1, 'pId': 0, 'label': 'test1'},
        {'key': '1-1', 'pId': 0, 'label': 'test1'},
        {'key': 11, 'pId': 1, 'label': 'test11'},
        {'key': 12, 'pId': 1, 'label': 'test12'},
        {'key': 111, 'pId': 11, 'label': 'test111'},
      ],
      treeDataSimpleMode: {
        id: 'key',
        rootPId: 0,
      },
    };
  },
  onClick() {
    this.setState({
      visible: true,
    });
  },
  onClose() {
    this.setState({
      visible: false,
    });
  },
  onSearch(value) {
    console.log(value, arguments);
  },
  onChange(value) {
    console.log('onChange', arguments);
    this.setState({value});
  },
  onMultipleChange(value) {
    console.log('onMultipleChange', arguments);
    this.setState({multipleValue: value});
  },
  onSelect() {
    // use onChange instead
    console.log(arguments);
  },
  filterTreeNode(input, child) {
    return String(child.props.title).indexOf(input) === 0;
  },
  render() {
    return (

tree-select in dialog

        <button className="btn btn-primary" onClick={this.onClick}>show dialog</button>
        {this.state.visible ? <Dialog
          visible={this.state.visible}
          animation="zoom"
          maskAnimation="fade"
          onClose={this.onClose}
          style={{ width: 600, height: 400 }}
          >
          <TreeSelect style={{width: 300}} transitionName="rc-tree-select-dropdown-slide-up"
                      choiceTransitionName="rc-tree-select-selection__choice-zoom"
                      dropdownStyle={{maxHeight: 200, overflow: 'auto', zIndex: 1500 }}
                      placeholder={请下拉选择}
                      searchPlaceholder="please search"
                      showSearch allowClear treeLine
                      inputValue={this.state.inputValue}
                      value={this.state.value}
                      treeData={gData}
                      treeNodeFilterProp="label"
                      filterTreeNode={false}
                      onSearch={this.onSearch}
                      onChange={this.onChange}
                      onSelect={this.onSelect} />
        </Dialog> : null}

single select

        <TreeSelect style={{width: 300}} transitionName="rc-tree-select-dropdown-slide-up"
                    choiceTransitionName="rc-tree-select-selection__choice-zoom"
                    dropdownStyle={{maxHeight: 200, overflow: 'auto'}}
                    placeholder={请下拉选择}
                    searchPlaceholder="please search"
                    showSearch allowClear treeLine
                    inputValue={this.state.inputValue}
                    value={this.state.value}
                    treeData={gData}
                    treeNodeFilterProp="label"
                    filterTreeNode={false}
                    onSearch={this.onSearch}
                    onChange={this.onChange}
                    onSelect={this.onSelect} />

multiple select

        <TreeSelect style={{width: 300}} transitionName="rc-tree-select-dropdown-slide-up"
                    choiceTransitionName="rc-tree-select-selection__choice-zoom"
                    dropdownStyle={{maxHeight: 200, overflow: 'auto'}}
                    placeholder={请下拉选择}
                    searchPlaceholder="please search"
                    multiple
                    inputValue={this.state.inputValue}
                    value={this.state.multipleValue}
                    treeData={gData}
                    treeNodeFilterProp="title"
                    onChange={this.onMultipleChange}
                    onSelect={this.onSelect} />

check select

        <TreeSelect style={{width: 300}} transitionName="rc-tree-select-dropdown-slide-up"
                    choiceTransitionName="rc-tree-select-selection__choice-zoom"
                    dropdownStyle={{maxHeight: 200, overflow: 'auto'}}
                    dropdownPopupAlign={{ overflow: { adjustY: 0, adjustX: 0 } }}
                    placeholder={请下拉选择}
                    searchPlaceholder="please search"
                    treeLine maxTagTextLength={10}
                    inputValue={null}
                    value={this.state.value}
                    treeData={gData}
                    treeNodeFilterProp="title"
                    treeCheckable showCheckedStrategy={SHOW_PARENT}
                    onChange={this.onChange}
                    onSelect={this.onSelect} />

use treeDataSimpleMode

        <TreeSelect style={{width: 300}}
                    dropdownStyle={{maxHeight: 200, overflow: 'auto'}}
                    placeholder={请下拉选择}
                    searchPlaceholder="please search"
                    treeLine maxTagTextLength={10}
                    inputValue={'test111'}
                    value={this.state.value}
                    treeData={this.state.simpleTreeData}
                    treeNodeFilterProp="title"
                    treeDataSimpleMode={this.state.treeDataSimpleMode}
                    treeCheckable showCheckedStrategy={SHOW_PARENT}
                    onChange={this.onChange}
                    onSelect={this.onSelect} />

use TreeNode Component (not recommend)

        <TreeSelect style={{width: 200}}
                    dropdownStyle={{maxHeight: 200, overflow: 'auto'}}
                    value={this.state.value || 'leaf1'}
                    treeDefaultExpandAll
                    treeNodeFilterProp="title"
                    filterTreeNode={this.filterTreeNode}
                    onChange={this.onChange}>
          <TreeNode value="parent 1" title="parent 1" key="0-1">
            <TreeNode value="parent 1-0" title="parent 1-0" key="0-1-0">
              <TreeNode value="leaf1" title="my leaf" key="random" />
              <TreeNode value="leaf2" title="your leaf" key="random1" disabled />
            </TreeNode>
            <TreeNode value="parent 1-1" title="parent 1-1" key="0-1-1">
              <TreeNode value="sss" title={sss} key="random3" />
              <TreeNode value="same value" title="same txtle" key="0-1-1-1">
                <TreeNode value="same value" title="same titlexd" key="0-1-1-1-0" />
              </TreeNode>
            </TreeNode>
          </TreeNode>
          <TreeNode value="same value" title="same title" key="0-2">
            <TreeNode value="2same value" title="2same title" key="0-2-0" />
          </TreeNode>
          <TreeNode value="same value" title="same title" key="0-3" />
          <TreeNode value="same value" title="same title" key="0-4" />
          <TreeNode value="same value" title="same title" key="0-5" />
        </TreeSelect>

    );
  },
});

ReactDOM.render(<Demo />, document.getElementById('__react-content'));
<commit_msg>fix dialog demo<commit_after>/* eslint react/no-multi-comp:0, no-console:0 */

import 'rc-tree-select/assets/index.less';
import './demo.less';
import React from 'react';
import ReactDOM from 'react-dom';
import 'rc-dialog/assets/index.css';
import Dialog from 'rc-dialog';
import TreeSelect, { TreeNode, SHOW_PARENT } from 'rc-tree-select';
import { gData } from './util';

const Demo = React.createClass({
  getInitialState() {
    return {
      visible: false,
      inputValue: '0-0-0-label',
      value: '0-0-0-value',
      // value: ['0-0-0-0-value', '0-0-0-1-value', '0-0-0-2-value'],
      multipleValue: [],
      simpleTreeData: [
        {'key': 1, 'pId': 0, 'label': 'test1'},
        {'key': '1-1', 'pId': 0, 'label': 'test1'},
        {'key': 11, 'pId': 1, 'label': 'test11'},
        {'key': 12, 'pId': 1, 'label': 'test12'},
        {'key': 111, 'pId': 11, 'label': 'test111'},
      ],
      treeDataSimpleMode: {
        id: 'key',
        rootPId: 0,
      },
    };
  },
  onClick() {
    this.setState({
      visible: true,
    });
  },
  onClose() {
    this.setState({
      visible: false,
    });
  },
  onSearch(value) {
    console.log(value, arguments);
  },
  onChange(value) {
    console.log('onChange', arguments);
    this.setState({value});
  },
  onMultipleChange(value) {
    console.log('onMultipleChange', arguments);
    this.setState({multipleValue: value});
  },
  onSelect() {
    // use onChange instead
    console.log(arguments);
  },
  filterTreeNode(input, child) {
    return String(child.props.title).indexOf(input) === 0;
  },
  render() {
    return (

tree-select in dialog

        <button className="btn btn-primary" onClick={this.onClick}>show dialog</button>
        {this.state.visible ? <Dialog
          visible={this.state.visible}
          animation="zoom"
          maskAnimation="fade"
          onClose={this.onClose}
          style={{ width: 600, height: 400 }}
          >
          <TreeSelect style={{width: 300}} transitionName="rc-tree-select-dropdown-slide-up"
                      choiceTransitionName="rc-tree-select-selection__choice-zoom"
                      dropdownStyle={{maxHeight: 200, overflow: 'auto', zIndex: 1500 }}
                      placeholder={请下拉选择}
                      searchPlaceholder="please search"
                      showSearch allowClear treeLine
                      inputValue={this.state.inputValue}
                      value={this.state.value}
                      treeData={gData}
                      treeNodeFilterProp="label"
                      filterTreeNode={false}
                      onSearch={this.onSearch}
                      onChange={this.onChange}
                      onSelect={this.onSelect} />
        </Dialog> : null}

single select

        <TreeSelect style={{width: 300}} transitionName="rc-tree-select-dropdown-slide-up"
                    choiceTransitionName="rc-tree-select-selection__choice-zoom"
                    dropdownStyle={{maxHeight: 200, overflow: 'auto'}}
                    placeholder={请下拉选择}
                    searchPlaceholder="please search"
                    showSearch allowClear treeLine
                    inputValue={this.state.inputValue}
                    value={this.state.value}
                    treeData={gData}
                    treeNodeFilterProp="label"
                    filterTreeNode={false}
                    onSearch={this.onSearch}
                    onChange={this.onChange}
                    onSelect={this.onSelect} />

multiple select

        <TreeSelect style={{width: 300}} transitionName="rc-tree-select-dropdown-slide-up"
                    choiceTransitionName="rc-tree-select-selection__choice-zoom"
                    dropdownStyle={{maxHeight: 200, overflow: 'auto'}}
                    placeholder={请下拉选择}
                    searchPlaceholder="please search"
                    multiple
                    inputValue={this.state.inputValue}
                    value={this.state.multipleValue}
                    treeData={gData}
                    treeNodeFilterProp="title"
                    onChange={this.onMultipleChange}
                    onSelect={this.onSelect} />

check select

        <TreeSelect style={{width: 300}} transitionName="rc-tree-select-dropdown-slide-up"
                    choiceTransitionName="rc-tree-select-selection__choice-zoom"
                    dropdownStyle={{maxHeight: 200, overflow: 'auto'}}
                    dropdownPopupAlign={{ overflow: { adjustY: 0, adjustX: 0 } }}
                    placeholder={请下拉选择}
                    searchPlaceholder="please search"
                    treeLine maxTagTextLength={10}
                    inputValue={null}
                    value={this.state.value}
                    treeData={gData}
                    treeNodeFilterProp="title"
                    treeCheckable showCheckedStrategy={SHOW_PARENT}
                    onChange={this.onChange}
                    onSelect={this.onSelect} />

use treeDataSimpleMode

        <TreeSelect style={{width: 300}}
                    dropdownStyle={{maxHeight: 200, overflow: 'auto'}}
                    placeholder={请下拉选择}
                    searchPlaceholder="please search"
                    treeLine maxTagTextLength={10}
                    inputValue={'test111'}
                    value={this.state.value}
                    treeData={this.state.simpleTreeData}
                    treeNodeFilterProp="title"
                    treeDataSimpleMode={this.state.treeDataSimpleMode}
                    treeCheckable showCheckedStrategy={SHOW_PARENT}
                    onChange={this.onChange}
                    onSelect={this.onSelect} />

use TreeNode Component (not recommend)

        <TreeSelect style={{width: 200}}
                    dropdownStyle={{maxHeight: 200, overflow: 'auto'}}
                    value={this.state.value || 'leaf1'}
                    treeDefaultExpandAll
                    treeNodeFilterProp="title"
                    filterTreeNode={this.filterTreeNode}
                    onChange={this.onChange}>
          <TreeNode value="parent 1" title="parent 1" key="0-1">
            <TreeNode value="parent 1-0" title="parent 1-0" key="0-1-0">
              <TreeNode value="leaf1" title="my leaf" key="random" />
              <TreeNode value="leaf2" title="your leaf" key="random1" disabled />
            </TreeNode>
            <TreeNode value="parent 1-1" title="parent 1-1" key="0-1-1">
              <TreeNode value="sss" title={sss} key="random3" />
              <TreeNode value="same value" title="same txtle" key="0-1-1-1">
                <TreeNode value="same value" title="same titlexd" key="0-1-1-1-0" />
              </TreeNode>
            </TreeNode>
          </TreeNode>
          <TreeNode value="same value" title="same title" key="0-2">
            <TreeNode value="2same value" title="2same title" key="0-2-0" />
          </TreeNode>
          <TreeNode value="same value" title="same title" key="0-3" />
          <TreeNode value="same value" title="same title" key="0-4" />
          <TreeNode value="same value" title="same title" key="0-5" />
        </TreeSelect>

    );
  },
});

ReactDOM.render(<Demo />, document.getElementById('__react-content'));
<|endoftext|>


<commit_before>var moonbridge = angular.module("api.moonbridge",["ngResource",'restangular']);
moonbridge.config(["RestangularProvider",function(RestangularProvider){
    RestangularProvider.setRestangularFields({
        id: "_id"
    });
    RestangularProvider.setBaseUrl("/api/v1/");
}]);
moonbridge.factory('moonbridge', ['Restangular', function (Restangular) {
    return Restangular;
} ]);
<commit_msg>added moonbirdge<commit_after>var moonbridge = angular.module("api.moonbridge",['restangular']);
moonbridge.config(["RestangularProvider",function(RestangularProvider){
    RestangularProvider.setRestangularFields({
        id: "_id"
    });
    RestangularProvider.setBaseUrl("/api/v1/");
}]);
moonbridge.factory('moonbridge', ['Restangular', function (Restangular) {
    return Restangular;
} ]);
<|endoftext|>