<commit_before>"use strict";

ckan.module('mdedit_create_input', function ($, _) {
    // Parameter from template
    var origin;
    var count;
    var values=["", "", "","","",""];
    var labels=["", "", "","","",""];
    var pholder=["", "", "","","",""];
    var field_name;
    var selectoptions="";
    var str_sep = '';
    var white_space = '';
   // global vars
    var max = 5;
    var next = 0;

  return {
    initialize: function () {
         console.log("Data initialized for element: ", this.el);

        $.proxyAll(this, /_on/);
        this.el.on('click', this._onClick);

        origin = this.options.origin;
        field_name = this.options.field_name;
        var strcount = this.options.count;
        count = parseInt (strcount);
        str_sep = this.options.strsep;
        white_space = this.options.whitespace;
        selectoptions = this.options.stroptions;

        switch (count)
        {
          case 5:
                values[5] = this.options.field5;
                labels[5] = this.options.label5;
                pholder[5] = this.options.pholder5;
          case 4:
                values[4] = this.options.field4;
                labels[4] = this.options.label4;
                pholder[4] = this.options.pholder4;
          case 3:
                values[3] = this.options.field3;
                labels[3] = this.options.label3;
                pholder[3] = this.options.pholder3;
          case 2:
                values[2] = this.options.field2;
                labels[2] = this.options.label2;
                pholder[2] = this.options.pholder2;

          case 1:
                values[1] = this.options.field1;
                labels[1] = this.options.label1;
                pholder[1] = this.options.pholder1;
        }

        if (origin != "button"){
          // Wird schon durch click initiiert
            this.createInput();
        }
    },

    _onClick: function(event) {

        for (var i = 1; i<=count; i++)
        {
          values[i] = "";
        }

        this.createInput();
    },

    createInput: function () {
        next = next + 1;
        console.log ("CreateInpput: next = " + next);
        // when field or imagename was not filled out last time, it gets filled out with 'true' and therefore it is here set to '' again

        for (var i = 1; i<=count; i++)
        {
          if (values[i]==true)
            values[i] = "";
          if (labels[i]==true)
            labels[i] = "";
          if (pholder[i]==true)
            pholder[i] = "";
        }

      /***************************** new Input and ggf select  ****************************************/

        var newInput = [$(),$(),$(),$(),$(),$()]; //max + 1
        var removeButton = $('
<button id="remove-' + next + '" class="btn btn-danger remove-me" >-</button>');

        /**************************************************************/
        //check whether we have a select and convert optionsstring
        var checkselect = selectoptions.toString();

        console.log("*************checkselect:" + checkselect);

        var selectinput = false;

        var corrected_count = count;

        if (checkselect.indexOf('<option') > -1) {

          // NOPE: otpions already transformed
          selectinput = true;
           console.log ("NOPE");

        }
        else if (checkselect.indexOf(str_sep) > -1) {

            selectinput = true;

            // Whitespaces from template string turn into cr here - replaced by ~;
            // reinsert whitespaces here
            var so = selectoptions.replace(/~/g, " ");

            // Separated options via # see mdedit_contains.html!
            so = so.split(/#/);

            // Build options string
            var sostring ="";
            for (var i=0; i< so.length; i+=2){

                sostring+='<option value="';
                sostring+= so[i];

                if (so[i] === values[count]) // select field is Number 'count' field
                    sostring+='" selected>';
                else
                    sostring+='">';
                sostring+= so[i+1];
                sostring+='</option>';
                console.log(so[i]);
                console.log(values[count]);
            }

            console.log(sostring);
            selectoptions = sostring;
        }
        else { // No select field: One more input field
          corrected_count +=1;
        }

        /**************************************************************/

        if (corrected_count > 0)
            $("#field_contains").append(removeButton);

        for (var i = 1; i< corrected_count; i++)
        {
          // Set the values only the first time we are here
            newInput[i]= $('
' + labels[i]+ '<input  class="input form-control" id="field' + i + next + '" name="'+ field_name + '" type="text" placeholder="'+  pholder[i] + ' "  value="' + values[i] + '" style ="margin-left:2%;margin-bottom:5%"/></input>');
            console.log("NewInput: " + i);
            console.log(newInput[i]);
          $("#field_contains").append(newInput[i]);
        }

        if (selectinput) {
             var newSelect1= $('
' + labels[count]+ '<select id="field' + count + next + '" name="'+ field_name + '" type="select"  selected="' + values[count] + '" style ="margin-left:2%;margin-bottom:5%"/>');
             var newSelect2= $('</select>');
             var select_options =$(selectoptions);

            if (corrected_count > 0) {
              $("#field_contains").append(newSelect1);
              $("#field" + count + next).append(select_options);
              $("#field_contains").append(newSelect2);
            }
         }

        $('.remove-me').click(function(e){
            e.preventDefault();

            var fieldNum = this.id.substr(this.id.indexOf("-") + 1);

            var fieldId, labelId, brId;
            var brb = "#brb" + fieldNum;

            $(this).remove();
            $(brb).remove();

            for (var i = 1; i<= corrected_count; i++){

              fieldId = "#field" +i+ fieldNum;
              labelId = "#label-field" +i+ fieldNum;
              brId = "#br" +i+ fieldNum;
              $(fieldId).remove();
              $(labelId).remove();
              $(brId).remove();

            }

          });

    } // create_input

  }; // return
}); // module
<commit_msg>fix enter bug<commit_after>"use strict";

ckan.module('mdedit_create_input', function ($, _) {
    // Parameter from template
    var origin;
    var count;
    var values=["", "", "","","",""];
    var labels=["", "", "","","",""];
    var pholder=["", "", "","","",""];
    var field_name;
    var selectoptions="";
    var str_sep = '';
    var white_space = '';
   // global vars
    var max = 5;
    var next = 0;

  return {
    initialize: function () {
         console.log("Data initialized for element: ", this.el);

        $.proxyAll(this, /_on/);
        this.el.on('click', this._onClick);

        origin = this.options.origin;
        field_name = this.options.field_name;
        var strcount = this.options.count;
        count = parseInt (strcount);
        str_sep = this.options.strsep;
        white_space = this.options.whitespace;
        selectoptions = this.options.stroptions;

        switch (count)
        {
          case 5:
                values[5] = this.options.field5;
                labels[5] = this.options.label5;
                pholder[5] = this.options.pholder5;
          case 4:
                values[4] = this.options.field4;
                labels[4] = this.options.label4;
                pholder[4] = this.options.pholder4;
          case 3:
                values[3] = this.options.field3;
                labels[3] = this.options.label3;
                pholder[3] = this.options.pholder3;
          case 2:
                values[2] = this.options.field2;
                labels[2] = this.options.label2;
                pholder[2] = this.options.pholder2;

          case 1:
                values[1] = this.options.field1;
                labels[1] = this.options.label1;
                pholder[1] = this.options.pholder1;
        }

        if (origin != "button"){
          // Wird schon durch click initiiert
            this.createInput();
        }
    },

    _onClick: function(event) {

        //console.log("cklick");
        for (var i = 1; i<=count; i++)
        {
          values[i] = "";
        }

        this.createInput();
    },

    createInput: function () {
        next = next + 1;
      //  console.log ("CreateInpput: next = " + next);
        // when field or imagename was not filled out last time, it gets filled out with 'true' and therefore it is here set to '' again

        for (var i = 1; i<=count; i++)
        {
          if (values[i]==true)
            values[i] = "";
          if (labels[i]==true)
            labels[i] = "";
          if (pholder[i]==true)
            pholder[i] = "";
        }

      /***************************** new Input and ggf select  ****************************************/

        var newInput = [$(),$(),$(),$(),$(),$()]; //max + 1
        var removeButton = $('
<button id="remove-' + next + '" class="btn btn-danger remove-me" type="button" >-</button>');

        /**************************************************************/
        //check whether we have a select and convert optionsstring
        var checkselect = selectoptions.toString();

      //  console.log("*************checkselect:" + checkselect);

        var selectinput = false;

        var corrected_count = count;

        if (checkselect.indexOf('<option') > -1) {

          // NOPE: otpions already transformed
          selectinput = true;
        //   console.log ("NOPE");

        }
        else if (checkselect.indexOf(str_sep) > -1) {

            selectinput = true;

            // Whitespaces from template string turn into cr here - replaced by ~;
            // reinsert whitespaces here
            var so = selectoptions.replace(/~/g, " ");

            // Separated options via # see mdedit_contains.html!
            so = so.split(/#/);

            // Build options string
            var sostring ="";
            for (var i=0; i< so.length; i+=2){

                sostring+='<option value="';
                sostring+= so[i];

                if (so[i] === values[count]) // select field is Number 'count' field
                    sostring+='" selected>';
                else
                    sostring+='">';
                sostring+= so[i+1];
                sostring+='</option>';
          //      console.log(so[i]);
          //      console.log(values[count]);
            }

          //  console.log(sostring);
            selectoptions = sostring;
        }
        else { // No select field: One more input field
          corrected_count +=1;
        }

        /**************************************************************/

        if (corrected_count > 0)
            $("#field_contains").append(removeButton);

        for (var i = 1; i< corrected_count; i++)
        {
          // Set the values only the first time we are here
            newInput[i]= $('
' + labels[i]+ '<input  class="input form-control" id="field' + i + next + '" name="'+ field_name + '" type="text" placeholder="'+  pholder[i] + ' "  value="' + values[i] + '" style ="margin-left:2%;margin-bottom:5%"/></input>');
          //  console.log("NewInput: " + i);
          //  console.log(newInput[i]);
          $("#field_contains").append(newInput[i]);
        }

        if (selectinput) {
             var newSelect1= $('
' + labels[count]+ '<select id="field' + count + next + '" name="'+ field_name + '" type="select"  selected="' + values[count] + '" style ="margin-left:2%;margin-bottom:5%"/>');
             var newSelect2= $('</select>');
             var select_options =$(selectoptions);

            if (corrected_count > 0) {
              $("#field_contains").append(newSelect1);
              $("#field" + count + next).append(select_options);
              $("#field_contains").append(newSelect2);
            }
         }

        $('.remove-me').click(function(e){
            e.preventDefault();

            var fieldNum = this.id.substr(this.id.indexOf("-") + 1);

            var fieldId, labelId, brId;
            var brb = "#brb" + fieldNum;

            $(this).remove();
            $(brb).remove();

            for (var i = 1; i<= corrected_count; i++){

              fieldId = "#field" +i+ fieldNum;
              labelId = "#label-field" +i+ fieldNum;
              brId = "#br" +i+ fieldNum;
              $(fieldId).remove();
              $(labelId).remove();
              $(brId).remove();

            }

          });

    } // create_input

  }; // return
}); // module
<|endoftext|>


<commit_before>(function (enyo, scope) {
	/**
	* {@link moon.Button} is an {@link enyo.Button} with Moonstone styling applied.
	* The color of the button may be customized by specifying a background color.
	*
	* For more information, see the documentation on
	* [Buttons]{@linkplain docs/building-apps/controls/buttons.html} in the
	* Enyo Developer Guide.
	*
	* @class moon.Button
	* @extends enyo.Button
	* @mixes moon.MarqueeSupport
	* @ui
	* @public
	*/

	enyo.kind(
		/** @lends moon.Button.prototype */ {

		/**
		* @private
		*/
		name: 'moon.Button',

		/**
		* @private
		*/
		kind: 'enyo.Button',

		/**
		* @private
		*/
		mixins: ['moon.MarqueeSupport'],

		/**
		* @private
		* @lends moon.Button.prototype
		*/
		published: {

			/**
			*
			* A boolean parameter affecting the size of the button. If `true`, the
			* button's diameter will be set to 60px. However, the button's tap target
			* will still have a diameter of 78px, with an invisible DOM element wrapping the small
			* button to provide the larger tap zone.
			*
			* @type {Boolean}
			* @default false
			* @public
			*/
			small: false,

			/**
			* A boolean parameter affecting the minimum width of the button. When `true`,
			* the minimum width will be set to 180px (or 130px if [small]{@link moon.Button#small}
			* is `true`). If `false`, the minimum width will be set to the current value of
			* `@moon-button-height` (thus forcing the button to be no smaller than a circle with
			* diameter `@moon-button-height`).
			*
			* @type {Boolean}
			* @default true
			* @public
			*/
			minWidth: true,

			/**
			* When `true`, the content will have locale-safe uppercasing applied.
			*
			* @type {Boolean}
			* @default true
			* @public
			*/
			contentUpperCase: true
		},

		/**
		* @private
		*/
		classes: 'moon-large-button-text moon-button enyo-unselectable',

		/**
		* @private
		*/
		spotlight: true,

		/**
		* @private
		*/
		handlers: {

			/**
			* `onSpotlightSelect` simulates `mousedown`.
			*
			* @private
			*/
			onSpotlightKeyDown	: 'depress',

			/**
			* `onSpotlightKeyUp` simulates `mouseup`.
			*
			* @private
			*/
			onSpotlightKeyUp	: 'undepress',

			/**
			* Also make sure we remove the pressed class if focus is removed from
			* this item before it receives a keyup.
			*
			* @private
			*/
			onSpotlightBlur		: 'undepress',

			/**
			* The handler for `onSpotlightFocused` bubbles a `requestScrollIntoView` event.
			*
			* @private
			*/
			onSpotlightFocused	: 'spotFocused'
		},

		/**
		* On creation, updates based on value of `this.small`.
		*
		* @private
		*/
		initComponents: function () {
			if (!(this.components && this.components.length > 0)) {
				this.createComponent({name: 'client', kind:'moon.MarqueeText', isChrome: true});
				this.createComponent({name: 'tapArea', classes: 'button-tap-area', isChrome: true});
			}
			this.smallChanged();
			this.minWidthChanged();
			this.inherited(arguments);
		},

		/**
		* Adds `pressed` CSS class.
		*
		* @private
		*/
		depress: function (inSender, inEvent) {
			if (inEvent.keyCode === 13) {
				this.addClass('pressed');
			}
		},

		/**
		* Bubbles `requestScrollIntoView` event.
		*
		* @fires moon.Scroller#onRequestScrollIntoView
		* @private
		*/
		spotFocused: function (inSender, inEvent) {
			if (inEvent.originator === this) {
				this.bubble('onRequestScrollIntoView');
			}
		},

		/**
		* Removes `pressed` CSS class.
		*
		* @private
		*/
		undepress: function () {
			this.removeClass('pressed');
		},

		/**
		* If `this.small` is `true`, `taparea` dimensions are increased.
		*
		* @private
		*/
		smallChanged: function () {
			if (this.small) {
				this.addClass('small');
				this.addClass('moon-small-button-text');
			} else {
				this.removeClass('small');
				this.removeClass('moon-small-button-text');
			}
			this.contentChanged();
		},

		/**
		* Override to handle potential child components.
		*
		* @private
		*/
		contentChanged: function () {
			var content = this.getContent();
			if (this.$.client) {
				this.$.client.setContent( this.getContentUpperCase() ? enyo.toUpperCase(content) : content );
			} else {
				this.inherited(arguments);
			}
		},

		/**
		* @private
		*/
		contentUpperCaseChanged: function () {
			this.contentChanged();
		},

		/**
		* @private
		*/
		minWidthChanged: function () {
			if (this.minWidth) {
				this.addClass('min-width');
			} else {
				this.removeClass('min-width');
			}
		},

		/**
		* @private
		*/
		showingChanged: function () {
			this.inherited(arguments);
			if (!this.showing && this.hasClass('pressed')) {
				this.undepress();
			}
		}
	});

})(enyo, this);
<commit_msg>BHV-13973 Ignore unnecessary notification. Currently calling setContent method for moon.Button makes additional notification. However, this notification is useless because we can get or set content through content of Button, not client's content.<commit_after>(function (enyo, scope) {
	/**
	* {@link moon.Button} is an {@link enyo.Button} with Moonstone styling applied.
	* The color of the button may be customized by specifying a background color.
	*
	* For more information, see the documentation on
	* [Buttons]{@linkplain docs/building-apps/controls/buttons.html} in the
	* Enyo Developer Guide.
	*
	* @class moon.Button
	* @extends enyo.Button
	* @mixes moon.MarqueeSupport
	* @ui
	* @public
	*/

	enyo.kind(
		/** @lends moon.Button.prototype */ {

		/**
		* @private
		*/
		name: 'moon.Button',

		/**
		* @private
		*/
		kind: 'enyo.Button',

		/**
		* @private
		*/
		mixins: ['moon.MarqueeSupport'],

		/**
		* @private
		* @lends moon.Button.prototype
		*/
		published: {

			/**
			*
			* A boolean parameter affecting the size of the button. If `true`, the
			* button's diameter will be set to 60px. However, the button's tap target
			* will still have a diameter of 78px, with an invisible DOM element wrapping the small
			* button to provide the larger tap zone.
			*
			* @type {Boolean}
			* @default false
			* @public
			*/
			small: false,

			/**
			* A boolean parameter affecting the minimum width of the button. When `true`,
			* the minimum width will be set to 180px (or 130px if [small]{@link moon.Button#small}
			* is `true`). If `false`, the minimum width will be set to the current value of
			* `@moon-button-height` (thus forcing the button to be no smaller than a circle with
			* diameter `@moon-button-height`).
			*
			* @type {Boolean}
			* @default true
			* @public
			*/
			minWidth: true,

			/**
			* When `true`, the content will have locale-safe uppercasing applied.
			*
			* @type {Boolean}
			* @default true
			* @public
			*/
			contentUpperCase: true
		},

		/**
		* @private
		*/
		classes: 'moon-large-button-text moon-button enyo-unselectable',

		/**
		* @private
		*/
		spotlight: true,

		/**
		* @private
		*/
		handlers: {

			/**
			* `onSpotlightSelect` simulates `mousedown`.
			*
			* @private
			*/
			onSpotlightKeyDown	: 'depress',

			/**
			* `onSpotlightKeyUp` simulates `mouseup`.
			*
			* @private
			*/
			onSpotlightKeyUp	: 'undepress',

			/**
			* Also make sure we remove the pressed class if focus is removed from
			* this item before it receives a keyup.
			*
			* @private
			*/
			onSpotlightBlur		: 'undepress',

			/**
			* The handler for `onSpotlightFocused` bubbles a `requestScrollIntoView` event.
			*
			* @private
			*/
			onSpotlightFocused	: 'spotFocused'
		},

		/**
		* On creation, updates based on value of `this.small`.
		*
		* @private
		*/
		initComponents: function () {
			if (!(this.components && this.components.length > 0)) {
				this.createComponent({name: 'client', kind:'moon.MarqueeText', isChrome: true});
				this.createComponent({name: 'tapArea', classes: 'button-tap-area', isChrome: true});
			}
			this.smallChanged();
			this.minWidthChanged();
			this.inherited(arguments);
		},

		/**
		* Adds `pressed` CSS class.
		*
		* @private
		*/
		depress: function (inSender, inEvent) {
			if (inEvent.keyCode === 13) {
				this.addClass('pressed');
			}
		},

		/**
		* Bubbles `requestScrollIntoView` event.
		*
		* @fires moon.Scroller#onRequestScrollIntoView
		* @private
		*/
		spotFocused: function (inSender, inEvent) {
			if (inEvent.originator === this) {
				this.bubble('onRequestScrollIntoView');
			}
		},

		/**
		* Removes `pressed` CSS class.
		*
		* @private
		*/
		undepress: function () {
			this.removeClass('pressed');
		},

		/**
		* If `this.small` is `true`, `taparea` dimensions are increased.
		*
		* @private
		*/
		smallChanged: function () {
			if (this.small) {
				this.addClass('small');
				this.addClass('moon-small-button-text');
			} else {
				this.removeClass('small');
				this.removeClass('moon-small-button-text');
			}
			this.contentChanged();
		},

		/**
		* Override to handle potential child components.
		*
		* @private
		*/
		contentChanged: function () {
			var content = this.getContent();
			if (this.$.client) {
				this.$.client.content = this.getContentUpperCase() ? enyo.toUpperCase(content) : content;
			} else {
				this.inherited(arguments);
			}
		},

		/**
		* @private
		*/
		contentUpperCaseChanged: function () {
			this.contentChanged();
		},

		/**
		* @private
		*/
		minWidthChanged: function () {
			if (this.minWidth) {
				this.addClass('min-width');
			} else {
				this.removeClass('min-width');
			}
		},

		/**
		* @private
		*/
		showingChanged: function () {
			this.inherited(arguments);
			if (!this.showing && this.hasClass('pressed')) {
				this.undepress();
			}
		}
	});

})(enyo, this);
<|endoftext|>


<commit_before>/**
	_moon.Button_ is an enyo.Button with Moonstone
	styling applied. The color of the button may be customized by specifying a
	background color.

	For more information, see the documentation on
	Buttons in the
	Enyo Developer Guide.
*/

enyo.kind({
	name		: 'moon.Button',
	kind		: 'enyo.Button',
	publiched	: {
		/**
			_small_ is a parameter to indicates the size of button.
			If it has true value, diameter of this button is 60px.
			However, the tap-target for button still has 78px, so it has
			invisible DOM which wrap this small button to provide wider tap zone.

		*/
		small	: false,
	},
	targetLayer	: "",
	classes		: 'moon-button enyo-unselectable',
	spotlight	: true,

	handlers: {
		onSpotlightSelect	: 'depress',
		onSpotlightKeyUp	: 'undepress'
	},

	create: function() {
		this.inherited(arguments);
		this.smallChanged();
	},

	depress: function() {
		this.addClass('pressed');
	},

	undepress: function() {
		this.removeClass('pressed');
	},

	smallChanged: function() {
		this.addRemoveClass('small', this.small);
		if(this.small) {
			this.targetLayer = new moon.TargetLayer({addBefore: this, owner: this.owner});
		}
	},

	rendered: function() {
		if(this.small) {
			if (!this.targetLayer.hasNode()) {
				this.targetLayer.render(this.parent.node);
			}
			this.appendNodeToParent(this.targetLayer.node);
			/**
				for event propagation from button to target Tap
			*/
			this.setContainer(this.targetLayer);
		}
		this.inherited(arguments);
	},
});

enyo.kind({
	name: "moon.TargetLayer",
	classes: "small-decorator",
	spotlight	: true,

	handlers: {
		onenter	: 'enter',
		onleave	: 'leave'
	},

	render: function(node) {
		if (node) {
			this.parentNode = node;
		}
		return this.inherited(arguments);
	},

	enter: function(inSender, inEvent) {
		this.controls[0].addClass("spotlight");
		return true;
	},

	leave: function(inSender, inEvent) {
		this.controls[0].removeClass("spotlight");
		return true;
	}
})<commit_msg>GF-5039: Fix typo<commit_after>/**
	_moon.Button_ is an enyo.Button with Moonstone
	styling applied. The color of the button may be customized by specifying a
	background color.

	For more information, see the documentation on
	Buttons in the
	Enyo Developer Guide.
*/

enyo.kind({
	name		: 'moon.Button',
	kind		: 'enyo.Button',
	published	: {
		/**
			_small_ is a parameter to indicates the size of button.
			If it has true value, diameter of this button is 60px.
			However, the tap-target for button still has 78px, so it has
			invisible DOM which wrap this small button to provide wider tap zone.

		*/
		small	: false,
	},
	targetLayer	: "",
	classes		: 'moon-button enyo-unselectable',
	spotlight	: true,

	handlers: {
		onSpotlightSelect	: 'depress',
		onSpotlightKeyUp	: 'undepress'
	},

	create: function() {
		this.inherited(arguments);
		this.smallChanged();
	},

	depress: function() {
		this.addClass('pressed');
	},

	undepress: function() {
		this.removeClass('pressed');
	},

	smallChanged: function() {
		this.addRemoveClass('small', this.small);
		if(this.small) {
			this.targetLayer = new moon.TargetLayer({addBefore: this, owner: this.owner});
		}
	},

	rendered: function() {
		if(this.small) {
			if (!this.targetLayer.hasNode()) {
				this.targetLayer.render(this.parent.node);
			}
			this.appendNodeToParent(this.targetLayer.node);
			/**
				for event propagation from button to target Tap
			*/
			this.setContainer(this.targetLayer);
		}
		this.inherited(arguments);
	},
});

enyo.kind({
	name: "moon.TargetLayer",
	classes: "small-decorator",
	spotlight	: true,

	handlers: {
		onenter	: 'enter',
		onleave	: 'leave'
	},

	render: function(node) {
		if (node) {
			this.parentNode = node;
		}
		return this.inherited(arguments);
	},

	enter: function(inSender, inEvent) {
		this.controls[0].addClass("spotlight");
		return true;
	},

	leave: function(inSender, inEvent) {
		this.controls[0].removeClass("spotlight");
		return true;
	}
})<|endoftext|>


<commit_before>
// Imports the Google Cloud client library
const Logging = require('@google-cloud/logging');

// Your Google Cloud Platform project ID
const projectId = 'unity-log-to-stackdriver';

// Instantiates a client
const loggingClient = Logging({
  projectId: projectId
});

// The name of the log to write to
const logName = 'unity-log-to-stackdriver';
// Selects the log to write to
const log = loggingClient.log(logName);

function regularEntryToStackdriverEntry (entry)
{
	// The metadata associated with the entry
	const metadata = { resource: { type: 'global' } };

	// Prepares a log entry
	const stackdriverEntry = log.entry(metadata, entry['message']);

	return stackdriverEntry;
}

function regularEntriesToStackdriverEntries (entries)
{
	return entries.map(regularEntryToStackdriverEntry);
}

/**
* HTTP Cloud Function.
*
* @param {Object} req Cloud Function request context.
* @param {Object} res Cloud Function response context.
*/
exports.appendToLog = function helloHttp (req, res) {
	if (req.method == 'POST')
	{
		try
		{
			var stackdriverEntries = regularEntriesToStackdriverEntries(req.body.entries);
		}
		catch (err)
		{
			res.status(400).send({ error: 'malformed input; should be on the form of { entries: [ { message: "Entry 1 message", ... }, { message: "Entry 2 message", ... }, ... ] }'});
		}

		log.write(stackdriverEntries)
			.then(() => {
				console.log('Logged entries; ', stackdriverEntries);
				res.status(200).send();
			})
			.catch((err) => {
				console.error('ERROR:', err);
				res.status(500).send({ error: err });
			});
	}
	else
		res.status(405).send({ error: 'appendToLog only supports POST' });
};<commit_msg>Project ID taken from environment<commit_after>
// Imports the Google Cloud client library
const Logging = require('@google-cloud/logging');

// Your Google Cloud Platform project ID
const projectId = process.env.GCLOUD_PROJECT;

// Instantiates a client
const loggingClient = Logging({
  projectId: projectId
});

// The name of the log to write to
const logName = process.env.GCLOUD_PROJECT;
// Selects the log to write to
const log = loggingClient.log(logName);

function regularEntryToStackdriverEntry (entry)
{
	// The metadata associated with the entry
	const metadata = { resource: { type: 'global' } };

	// Prepares a log entry
	const stackdriverEntry = log.entry(metadata, entry['message']);

	return stackdriverEntry;
}

function regularEntriesToStackdriverEntries (entries)
{
	return entries.map(regularEntryToStackdriverEntry);
}

/**
* HTTP Cloud Function.
*
* @param {Object} req Cloud Function request context.
* @param {Object} res Cloud Function response context.
*/
exports.appendToLog = function helloHttp (req, res) {
	if (req.method == 'POST')
	{
		try
		{
			var stackdriverEntries = regularEntriesToStackdriverEntries(req.body.entries);
		}
		catch (err)
		{
			res.status(400).send({ error: 'malformed input; should be on the form of { entries: [ { message: "Entry 1 message", ... }, { message: "Entry 2 message", ... }, ... ] }'});
		}

		log.write(stackdriverEntries)
			.then(() => {
				console.log('Logged entries; ', stackdriverEntries);
				res.status(200).send();
			})
			.catch((err) => {
				console.error('ERROR:', err);
				res.status(500).send({ error: err });
			});
	}
	else
		res.status(405).send({ error: 'appendToLog only supports POST' });
};<|endoftext|>


<commit_before>'use strict';

module.exports = (function () {
  var _             = require('../lib/helper')._,
      path          = require('path'),
      spawn         = require('child_process').spawn,
      // running       = require('is-running'),
      binPath       = path.join(process.env.PWD, 'app', 'bin'),
      db            = require('./../lib/db'),
      eventEmitter_ = new (require('events').EventEmitter)(),
      proxyChilds   = {},
      mockChilds    = {};

  var Proxy = function (properties) {
    var self = this;

    this._id =
    this._port =
    this._target =
    this._status =
    this._isRecording;

    _.privateMerge(this, properties);

    // set to true if some childs are started
    this._isRunning = _.has(proxyChilds, this._id);
    this._isMocked = _.has(mockChilds, this._id);

    // enable the proxy if proxy or mock is running
    this._isEnabled = this._isRunning || this._isMocked;

    // update the disable flag in DB
    db.model('Proxy').get(this._id, function (err, Proxy) {
      if (Proxy) {
        Proxy.isEnabled = self._isEnabled;
        Proxy.save(db.log);
      }
    });
  };

  /**
   * Add a proxy in DB.
   */
  Proxy.prototype.add = function (callback) {
    db.model('Proxy').create([_.publicProperties(this)], function (err) {
      callback(err);
    });
  };

  /**
   * Remove a proxy from DB.
   */
  Proxy.prototype.remove = function (callback) {
    db.model('Proxy').find({id: this._id}).remove(function (err) {
      callback(err);
    });
  };

  /**
   * Start the proxy.
   */
  Proxy.prototype.startProxy = function () {
    proxyChilds[this._id] = spawn('node', [
      path.join(binPath, 'proxy.js'),
      '--target=' + this._target,
      '--port=' + this._port,
      '--proxyId=' + this._id
    ]);

    this.bindEvent('Proxy', proxyChilds, this._id);
  };

  /**
   * Stop the child process.
   */
  Proxy.prototype.stopProxy = function (callback) {
    if (proxyChilds[this._id]) {
      proxyChilds[this._id].kill('SIGHUP');
      if (callback) {
        proxyChilds[this._id].on('exit', callback);
      }
    }
  };

  /**
   * Start the mock
   */
  Proxy.prototype.startMock = function () {
    mockChilds[this._id] = spawn('node', [
      path.join(binPath, 'mock.js'),
      '--port=' + this._port,
      '--proxyId=' + this._id
    ]);

    this.bindEvent('Mock', mockChilds, this._id);
  };

  /**
   * Stop the child process.
   */
  Proxy.prototype.stopMock = function (callback) {
    if (mockChilds[this._id]) {
      mockChilds[this._id].kill('SIGHUP');
      if (callback) {
        mockChilds[this._id].on('exit', callback);
      }
    }
  };

  /**
   * Bind child events to websocket / logging.
   */
  Proxy.prototype.bindEvent = function (label, childs, id) {
    var self = this,
        child = childs[id];

    console.log(label + ' PID', child.pid);

    child.on('exit', function () {
      delete childs[self._id];
      self['_log' + label](label + ' has been stopped.');
    });

    child.on('error', function () {
      console.log('error', arguments);
    });

    // log stdout
    child.stdout.on('data', function (data) {
      self['_log' + label](data);
    });

    // log stderr
    child.stderr.on('data', function (data) {
      self['_log' + label](data, 'error');
    });
  };

  /**
   * Disable/enable the recording for the proxy.
   */
  Proxy.prototype.toggleRecording = function (callback) {
    var self = this;
    db.model('Proxy').get(this._id, function (err, Proxy) {
      Proxy.isRecording = self._isRecording;
      Proxy.save(function (err) {
        callback(err);
      });
    });
  };

  /**
   * Disable/enable the mock for the proxy.
   */
  Proxy.prototype.toggleMock = function () {
    var self = this;

    if (this._isMocked) {
      this.stopMock(function () {
        self.startProxy();
      });
    }

    if (this._isRunning) {
      this.stopProxy(function () {
        self.startMock();
      });
    }
  };

  /**
   * Enable/disable the proxy.
   */
  Proxy.prototype.toggleEnable = function (callback) {
    var self = this;

    db.model('Proxy').get(this._id, function (err, Proxy) {
      Proxy.isEnabled = self._isEnabled;

      // when adding a proxy, we don't run the proxy by default,
      // we run the mock => the proxy is "mocked" by default.
      if (!Proxy.isEnabled) {
        self.startMock();
      } else {
        // when disabling the Proxy, we stop all
        self.stopProxy();
        self.stopMock();
      }

      Proxy.save(function (err) {
        callback(err);
      });
    });
  };

  /**
   * Log proxy event.
   */
  Proxy.prototype._logProxy = function (message, type) {
    this._log(message, type || 'infoProxy');
  };

  /**
   * Log mock event.
   */
  Proxy.prototype._logMock = function (message, type) {
    this._log(message, type || 'infoMock');
  };

  /**
   * Emit an event for mock logging.
   * @param  {String|Buffer}  message   Message
   * @param  {String}         type      A choice between ['info', 'error']
   */
  Proxy.prototype._log = function (message, type) {
    if (message instanceof Buffer) {
      message = message.toString('utf8');
    }

    eventEmitter_.emit('log', {
      message: message,
      type: (type || 'info')
    });
  };

  /**
   * Return the event emitter for the outside communication.
   */
  Proxy.eventEmitter = function () {
    return eventEmitter_;
  };

  /**
   * List all proxies from DB.
   */
  Proxy.list = function (callback) {
    db.model('Proxy').find({}, function (err, proxies) {
      callback(err, _.map(proxies, function (properties) {
        return new Proxy(properties);
      }));
    });
  };

  return Proxy;
})();
<commit_msg>Stop all processes when removing the proxy.<commit_after>'use strict';

module.exports = (function () {
  var _             = require('../lib/helper')._,
      Q             = require('q'),
      path          = require('path'),
      spawn         = require('child_process').spawn,
      // running       = require('is-running'),
      binPath       = path.join(process.env.PWD, 'app', 'bin'),
      db            = require('./../lib/db'),
      eventEmitter_ = new (require('events').EventEmitter)(),
      proxyChilds   = {},
      mockChilds    = {};

  var Proxy = function (properties) {
    var self = this;

    this._id =
    this._port =
    this._target =
    this._status =
    this._isRecording;

    _.privateMerge(this, properties);

    // set to true if some childs are started
    this._isRunning = _.has(proxyChilds, this._id);
    this._isMocked = _.has(mockChilds, this._id);

    // enable the proxy if proxy or mock is running
    this._isEnabled = this._isRunning || this._isMocked;

    // update the disable flag in DB
    db.model('Proxy').get(this._id, function (err, Proxy) {
      if (Proxy) {
        Proxy.isEnabled = self._isEnabled;
        Proxy.save(db.log);
      }
    });
  };

  /**
   * Add a proxy in DB.
   */
  Proxy.prototype.add = function (callback) {
    db.model('Proxy').create([_.publicProperties(this)], callback);
  };

  /**
   * Stop all child processes and remove a proxy from DB.
   */
  Proxy.prototype.remove = function (callback) {
    var self = this;

    this.stopAll().then(function () {
      db.model('Proxy').find({id: self._id}).remove(function (err) {
        callback(err);
      });
    })
    .catch(function (error) {
      this._logError(error);
    });
  };

  /**
   * Start the proxy.
   */
  Proxy.prototype.startProxy = function () {
    proxyChilds[this._id] = spawn('node', [
      path.join(binPath, 'proxy.js'),
      '--target=' + this._target,
      '--port=' + this._port,
      '--proxyId=' + this._id
    ]);

    this.bindEvent('Proxy', proxyChilds, this._id);
  };

  /**
   * Stop the child process.
   */
  Proxy.prototype.stopProxy = function () {
    var deferred = Q.defer();

    if (proxyChilds[this._id]) {
      proxyChilds[this._id].kill('SIGHUP');
      proxyChilds[this._id].on('exit', function () {
        deferred.resolve();
      });
    }

    return deferred.promise;
  };

  /**
   * Start the mock
   */
  Proxy.prototype.startMock = function () {
    mockChilds[this._id] = spawn('node', [
      path.join(binPath, 'mock.js'),
      '--port=' + this._port,
      '--proxyId=' + this._id
    ]);

    this.bindEvent('Mock', mockChilds, this._id);
  };

  /**
   * Stop the child process.
   */
  Proxy.prototype.stopMock = function () {
    var deferred = Q.defer();

    if (mockChilds[this._id]) {
      mockChilds[this._id].kill('SIGHUP');
      mockChilds[this._id].on('exit', function () {
        deferred.resolve();
      });
    }

    return deferred.promise;
  };

  /**
   * Stop all processes.
   */
  Proxy.prototype.stopAll = function () {
    var promises = [];

    if (this._isMocked) {
      promises.push(this.stopMock());
    }

    if (this._isRunning) {
      promises.push(this.stopProxy());
    }

    return Q.all(promises);
  };

  /**
   * Bind child events to websocket / logging.
   */
  Proxy.prototype.bindEvent = function (label, childs, id) {
    var self = this,
        child = childs[id];

    console.log(label + ' PID', child.pid);

    child.on('exit', function () {
      delete childs[self._id];
      self['_log' + label](label + ' has been stopped.');
    });

    child.on('error', function () {
      console.log('error', arguments);
    });

    // log stdout
    child.stdout.on('data', function (data) {
      self['_log' + label](data);
    });

    // log stderr
    child.stderr.on('data', function (data) {
      self['_log' + label](data, 'error');
    });
  };

  /**
   * Disable/enable the recording for the proxy.
   */
  Proxy.prototype.toggleRecording = function (callback) {
    var self = this;
    db.model('Proxy').get(this._id, function (err, Proxy) {
      Proxy.isRecording = self._isRecording;
      Proxy.save(function (err) {
        callback(err);
      });
    });
  };

  /**
   * Disable/enable the mock for the proxy.
   */
  Proxy.prototype.toggleMock = function () {
    var self = this;

    if (this._isMocked) {
      this.stopMock().then(function () {
        self.startProxy();
      });
    }

    if (this._isRunning) {
      this.stopProxy().then(function () {
        self.startMock();
      });
    }
  };

  /**
   * Enable/disable the proxy.
   */
  Proxy.prototype.toggleEnable = function (callback) {
    var self = this;

    db.model('Proxy').get(this._id, function (err, Proxy) {
      Proxy.isEnabled = self._isEnabled;

      // when adding a proxy, we don't run the proxy by default,
      // we run the mock => the proxy is "mocked" by default.
      if (!Proxy.isEnabled) {
        self.startMock();
      } else {
        // when disabling the Proxy, we stop all
        self.stopAll();
      }

      Proxy.save(function (err) {
        callback(err);
      });
    });
  };

  /**
   * Log proxy event.
   */
  Proxy.prototype._logProxy = function (message, type) {
    this._log(message, type || 'infoProxy');
  };

  /**
   * Log mock event.
   */
  Proxy.prototype._logMock = function (message, type) {
    this._log(message, type || 'infoMock');
  };

  /**
   * Log error.
   * Prefix the message by "Error:" to pass the filter in Angular.
   * See LogsCtrl.
   */
  Proxy.prototype._logError = function (message) {
    this._log('Error: ' + message, 'error');
  };

  /**
   * Emit an event for mock logging.
   * @param  {String|Buffer}  message   Message
   * @param  {String}         type      A choice between ['info', 'error']
   */
  Proxy.prototype._log = function (message, type) {
    if (message instanceof Buffer) {
      message = message.toString('utf8');
    }

    eventEmitter_.emit('log', {
      message: message,
      type: (type || 'info')
    });
  };

  /**
   * Return the event emitter for the outside communication.
   */
  Proxy.eventEmitter = function () {
    return eventEmitter_;
  };

  /**
   * List all proxies from DB.
   */
  Proxy.list = function (callback) {
    db.model('Proxy').find({}, function (err, proxies) {
      callback(err, _.map(proxies, function (properties) {
        return new Proxy(properties);
      }));
    });
  };

  return Proxy;
})();
<|endoftext|>


<commit_before><commit_msg>Update hotkeysCommand.js<commit_after><|endoftext|>


<commit_before>// AES-CBC Web Cryptography API Example Code Snippet
// (see http://www.w3.org/TR/WebCryptoAPI/)
//
// The code demonstrates the following functionality:
// * key generation
// * key export / import
// * encryption / decryption
//
// Hint: Internet Explorer 11 supports the webcrypto-api but has a non-standard promises implementation,
// therefore you have to change the code to work in IE 11 or use a proper polyfill.
//
// This example makes also use of the JS encoding API (https://encoding.spec.whatwg.org/)
// A proper polyfill for other browsers is "text-encoding" (https://github.com/inexorabletash/text-encoding)
//
// snippet by: innoq.com, simon.koelsch

var decoder = new TextDecoder("utf-8");
var encoder = new TextEncoder("utf-8");

var cryptoSubtle = window.crypto.subtle;

// static iv for demonstration purposes only
var iv = new Uint8Array([0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
                        0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F]);
var algorithm = {name: 'AES-CBC', length: 128, iv: iv};
var extractable = true;
var usages = ["encrypt", "decrypt"];

cryptoSubtle.generateKey(algorithm, extractable, usages)
.then(function(key) {

  console.log("Key generated: ", key);

  cryptoSubtle.exportKey("raw", key)
  .then(function(exportedKey) {

    console.log("exported raw key: ", new Int8Array(exportedKey));

    // start encryption with generated key

    var text = "Encrypt me!";
    console.log("String to encrypt: ", text);

    cryptoSubtle.encrypt(algorithm, key, encoder.encode(text))
    .then(function(encryptedText) {

      var dataViewEnc = new DataView(encryptedText);
      console.log("Encrypted string: ", decoder.decode(dataViewEnc));

      // import the exported  key and use it for decryption

      cryptoSubtle.importKey("raw", exportedKey, algorithm, extractable, usages)
      .then(function(keyImport) {

        cryptoSubtle.decrypt(algorithm, keyImport, encryptedText)
        .then(function(decrypted){
          var dataView = new DataView(decrypted);
          console.log("Decrypted string: ", decoder.decode(dataView));
        });

      });
    });
  });
});
<commit_msg>use random iv values<commit_after>// AES-CBC Web Cryptography API Example Code Snippet
// (see http://www.w3.org/TR/WebCryptoAPI/)
//
// The code demonstrates the following functionality:
// * key generation
// * key export / import
// * encryption / decryption
// * use random values as iv
//
// Hint: Internet Explorer 11 supports the webcrypto-api but has a non-standard promises implementation,
// therefore you have to change the code to work in IE 11 or use a proper polyfill.
//
// This example makes also use of the JS encoding API (https://encoding.spec.whatwg.org/)
// A proper polyfill for other browsers is "text-encoding" (https://github.com/inexorabletash/text-encoding)
//
// snippet by: innoq.com, simon.koelsch

var decoder = new TextDecoder("utf-8");
var encoder = new TextEncoder("utf-8");

var cryptoSubtle = window.crypto.subtle;

// get random iv
var iv = window.crypto.getRandomValues(new Uint8Array(16));
console.log("using a random iv:", iv);

var algorithm = {name: 'AES-CBC', length: 128, iv: iv};
var extractable = true;
var usages = ["encrypt", "decrypt"];

cryptoSubtle.generateKey(algorithm, extractable, usages)
.then(function(key) {

  console.log("Key generated: ", key);

  cryptoSubtle.exportKey("raw", key)
  .then(function(exportedKey) {

    console.log("exported raw key: ", new Int8Array(exportedKey));

    // start encryption with generated key

    var text = "Encrypt me!";
    console.log("String to encrypt: ", text);

    cryptoSubtle.encrypt(algorithm, key, encoder.encode(text))
    .then(function(encryptedText) {

      var dataViewEnc = new DataView(encryptedText);
      console.log("Encrypted string: ", decoder.decode(dataViewEnc));

      // import the exported  key and use it for decryption

      cryptoSubtle.importKey("raw", exportedKey, algorithm, extractable, usages)
      .then(function(keyImport) {

        cryptoSubtle.decrypt(algorithm, keyImport, encryptedText)
        .then(function(decrypted){
          var dataView = new DataView(decrypted);
          console.log("Decrypted string: ", decoder.decode(dataView));
        });

      });
    });
  });
});
<|endoftext|>


<commit_before>import React, { PropTypes } from 'react'

// Global module dependencies
import { Loading } from '~components/await'
import {
  Sidenav,
  SidenavList,
  SidenavListItem
} from '~components/navigation/sidenav'
import * as paths from '~client/paths'
import * as BlockPaths from '~mobilizations/blocks/paths'

const Sidebar = props => {
  const { children, loading, mobilization, user, community } = props

  if (loading) return <Loading />

  return (

      <Sidenav community={community}>
        {
          !mobilization ? null : (
            <SidenavList className='bg-lighten-2'>
              {!mobilization.custom_domain ? (
                <SidenavListItem
                  text='PUBLICAR BONDE'
                  icon='rocket'
                  href={paths.mobilizationLaunch(mobilization.id)}
                  className='launch-button rounded'
                />
              ) : (
                <SidenavListItem
                  text='BONDE público'
                  icon='check'
                  className='launched-item'
                />
              )}
              <SidenavListItem
                text='Editar mobilização'
                icon='pencil'
                href={paths.editMobilization(mobilization.id)}
              />
              <SidenavListItem
                text='Adicionar conteúdo'
                icon='plus'
                href={BlockPaths.createBlock({ id: mobilization.id })}
              />
              <SidenavListItem
                text='Ver em uma nova aba'
                icon='external-link'
                linkType='anchor'
                href={paths.mobilization(mobilization)}
                target='_blank'
              />
              <SidenavListItem
                text='Configurações'
                icon='cog'
                href={paths.basicsMobilization(mobilization.id)}
              />
            </SidenavList>
          )
        }
        <SidenavList style={{ position: 'absolute', bottom: '0' }}>
          <SidenavListItem text='Minha Conta' icon='user' href={paths.editAccount()}>

{user.email}

          </SidenavListItem>
          <SidenavListItem
            icon='sign-out'
            text='Sair'
            className='caps'
            href={paths.logout()}
          />
        </SidenavList>
      </Sidenav>

        {children && React.cloneElement(children)}

  )
}

Sidebar.propTypes = {
  loading: PropTypes.bool.isRequired,
  user: PropTypes.object.isRequired,
  mobilization: PropTypes.object
}

export default Sidebar
<commit_msg>Add community settings pages links into sidebar when does not editing a mobilization; Close #489<commit_after>import React, { PropTypes } from 'react'

// Global module dependencies
import { Loading } from '~components/await'
import {
  Sidenav,
  SidenavList,
  SidenavListItem
} from '~components/navigation/sidenav'
import * as paths from '~client/paths'
import * as BlockPaths from '~mobilizations/blocks/paths'

const Sidebar = props => {
  const { children, loading, mobilization, user, community } = props

  if (loading) return <Loading />

  return (

      <Sidenav community={community}>
        {!mobilization ? (
          <SidenavList className='bg-lighten-2'>
            <SidenavListItem
              text='Informações'
              icon='info-circle'
              href={paths.communityInfo()}
            />
            <SidenavListItem
              text='Mailchimp'
              icon='envelope-o'
              href={paths.communityMailchimp()}
            />
            <SidenavListItem
              text='Recebedor'
              icon='money'
              href={paths.communityRecipient()}
            />
            <SidenavListItem
              text='Relatório'
              icon='file-excel-o'
              href={paths.communityReport()}
            />
          </SidenavList>
        ) : (
          <SidenavList className='bg-lighten-2'>
            {!mobilization.custom_domain ? (
              <SidenavListItem
                text='PUBLICAR BONDE'
                icon='rocket'
                href={paths.mobilizationLaunch(mobilization.id)}
                className='launch-button rounded'
              />
            ) : (
              <SidenavListItem
                text='BONDE público'
                icon='check'
                className='launched-item'
              />
            )}
            <SidenavListItem
              text='Editar mobilização'
              icon='pencil'
              href={paths.editMobilization(mobilization.id)}
            />
            <SidenavListItem
              text='Adicionar conteúdo'
              icon='plus'
              href={BlockPaths.createBlock({ id: mobilization.id })}
            />
            <SidenavListItem
              text='Ver em uma nova aba'
              icon='external-link'
              linkType='anchor'
              href={paths.mobilization(mobilization)}
              target='_blank'
            />
            <SidenavListItem
              text='Configurações'
              icon='cog'
              href={paths.basicsMobilization(mobilization.id)}
            />
          </SidenavList>
        )}
        <SidenavList style={{ position: 'absolute', bottom: '0' }}>
          <SidenavListItem text='Minha Conta' icon='user' href={paths.editAccount()}>

{user.email}

          </SidenavListItem>
          <SidenavListItem
            icon='sign-out'
            text='Sair'
            className='caps'
            href={paths.logout()}
          />
        </SidenavList>
      </Sidenav>

        {children && React.cloneElement(children)}

  )
}

Sidebar.propTypes = {
  loading: PropTypes.bool.isRequired,
  user: PropTypes.object.isRequired,
  mobilization: PropTypes.object
}

export default Sidebar
<|endoftext|>


<commit_before>var Decode = (function() {

  // Private
  var bencodedString
    , decodedObject
    , objectType
    , setType
    , setDecodedObject
    , dispatch
    , appendToDecodedObject
  ;

  // Constructor
  function Decode(string) {
    bencodedString = string;
    objectType = this.getType();
    return dispatch();
  }

  // Private Mutators
  setDecodedObject = function( obj ) {
    return decodedObject = obj;
  }

  appendToDecodedObject = function( obj ) { }

  // Private Methods
  dispatch = function() {
    fn = Decode.prototype
    var type = fn.getType();

    switch( type ) {
      case 'string':
        return fn.getString();
      case 'integer':
        return fn.getInteger();
      case 'list':
        return fn.getList();
      case 'dictionary':
        return fn.getDictionary();
      default:
        throw "Unexpected result in dispatch()"
    }
  }

  // Public Accessors
  Decode.prototype.getObjectType = function() {
    return objectType;
  }

  Decode.prototype.getDecodedObject = function() {
    return decodedObject;
  }

  Decode.prototype.getBencodedString = function() {
    return bencodedString;
  }

  Decode.prototype.getType = function() {
    var char = this.getBencodedString().charAt(0);

    if ( char.match(/\d/) ) {
      return "string";
    }

    switch ( char ) {
      case 'i':
        return "integer";
      case 'l':
        return "list";
      case 'd':
        return "dictionary";
      default:
        throw "String is not in any recognizable bencoding format";
    }
  }

  Decode.prototype.getString = function(str) {
    var str           = str || this.getBencodedString()
      , strArray      = str.split(':')
      , strLength     = strArray[0]
      , currentStr    = strArray[1]
      , result        = ""
    ;

    for (var i = 0; i < strLength; ++i) {
      result += currentStr[i];
    }

    if ( this.getObjectType() === 'string' ) {
      return setDecodedObject( result );
    }

    appendToDecodedObject( result );
    return dispatch();
  }

  Decode.prototype.getInteger = function(str) {
    var str        = str || this.getBencodedString()
      , integerStr = str.match(/^i(\d+)e/)[1]
    ;

    var result = parseInt(integerStr);

    if ( this.getObjectType() === 'integer' ) {
      return setDecodedObject( result );
    }

    appendToDecodedObject( result );
    return dispatch();
  }

  return Decode;
})();

window.Decode = Decode;

String.prototype.decode = function() {
  object = new Decode( this );
  return object.getDecodedObject();
}
<commit_msg>rewrote getString and getInteger methods<commit_after>var Decode = (function() {

  // Private
  var bencodedString
    , bencodedStrLength
    , decodedObject
    , currentIndex
    , objectType
    , setType
    , setDecodedObject
    , dispatch
    , appendToDecodedObject
  ;

  // Constructor
  function Decode(string) {
    currentIndex      = 0;
    bencodedString    = string;
    bencodedStrLength = bencodedString.length
    objectType        = this.getType();
    return dispatch();
  }

  // Private Mutators
  setDecodedObject = function( obj ) {
    return decodedObject = obj;
  }

  appendToDecodedObject = function( obj, lastIdx ) {
    // Increment currentIndex to its new position
    currentIndex += lastIdx + 1;

    switch( objectType ) {
      case 'string':
        return setDecodedObject( obj );
      case 'integer':
        return setDecodedObject( obj );
      case 'list':
        break;
      case 'dictionary':
        break;
    }

    if ( currentIndex >= bencodedStrLength - 1 ) return;
    return dispatch();
  }

  // Private Methods
  dispatch = function() {
    if ( currentIndex >= bencodedStrLength - 1 ) return;

    fn = Decode.prototype
    var type = fn.getType();

    switch( type ) {
      case 'string':
        return fn.getString();
      case 'integer':
        return fn.getInteger();
      case 'list':
        return fn.getList();
      case 'dictionary':
        return fn.getDictionary();
      default:
        throw "Unexpected result in dispatch()"
    }
  }

  // Public Accessors
  Decode.prototype.getObjectType = function() {
    return objectType;
  }

  Decode.prototype.getDecodedObject = function() {
    return decodedObject;
  }

  Decode.prototype.getBencodedString = function() {
    return bencodedString;
  }

  Decode.prototype.getType = function() {
    var char = this.getBencodedString().charAt( currentIndex );

    if ( char.match(/\d/) ) {
      return "string";
    }

    switch ( char ) {
      case 'i':
        return "integer";
      case 'l':
        return "list";
      case 'd':
        return "dictionary";
      default:
        throw "String is not in any recognizable bencoding format";
    }
  }

  Decode.prototype.getString = function() {

    // We use currentIndex to extract the string from where we
    // left off in our iteration over the bencoded string. We store
    // this in str.
    //
    // Then we get the index of the colon separator, and store that in
    // separatorIdx, which we'll use to get the number before the separator
    // which represents the length of the string we want. We'll then use that
    // number (stored in len) to get the desired string, and store that
    // in result.

    var str          = this.getBencodedString().substring( currentIndex )
      , separatorIdx = str.indexOf(":")
    ;

    if ( separatorIdx === -1 ) throw "Invalid String, colon separator not found";

    var len    = str.substring( 0, separatorIdx )
        endIdx = (separatorIdx + 1) + parseInt(len)
      , result = str.substring( (separatorIdx + 1), endIdx )
    ;

    return appendToDecodedObject( result, endIdx );
  }

  Decode.prototype.getInteger = function() {
    var str        = this.getBencodedString( currentIndex )
      , endIdx     = str.indexOf('e')
      , int
    ;

    str = str.slice( 0, endIdx )
    int = str.replace(/i/, '').replace(/e/, '');

    var result = parseInt( int );

    appendToDecodedObject( result );
  }

  return Decode;
})();

// Ensure compatibility with CommonJS modules or browser
var root;
root = typeof global !== "undefined" && global !== null ? global : window;

root.Decode = Decode;

String.prototype.decode = function() {
  object = new Decode( this );
  return object.getDecodedObject();
}
<|endoftext|>


<commit_before>/* global moment */
import {parseDateString, formatDate} from 'ghost/utils/date-formatting';
import SlugGenerator from 'ghost/models/slug-generator';
import boundOneWay from 'ghost/utils/bound-one-way';

var PostSettingsMenuController = Ember.ObjectController.extend({
    init: function () {
        this._super();

        // when creating a new post we want to observe the title
        // to generate the post's slug
        if (this.get('isNew')) {
            this.addObserver('titleScratch', this, 'titleObserver');
        }
    },
    //Changes in the PSM are too minor to warrant NProgress firing
    saveOptions: {disableNProgress: true},
    /**
     * The placeholder is the published date of the post,
     * or the current date if the pubdate has not been set.
     */
    publishedAtPlaceholder: function () {
        var pubDate = this.get('published_at');
        if (pubDate) {
            return formatDate(pubDate);
        }
        return formatDate(moment());
    }.property('publishedAtValue'),
    publishedAtValue: boundOneWay('published_at', formatDate),

    slugValue: boundOneWay('slug'),
    //Lazy load the slug generator for slugPlaceholder
    slugGenerator: Ember.computed(function () {
        return SlugGenerator.create({
            ghostPaths: this.get('ghostPaths')
        });
    }),
    //Requests slug from title
    generateSlugPlaceholder: function () {
        var self = this,
            title = this.get('titleScratch');

        this.get('slugGenerator').generateSlug(title).then(function (slug) {
            self.set('slugPlaceholder', slug);
        });
    },
    titleObserver: function () {
        if (this.get('isNew')) {
            Ember.run.debounce(this, 'generateSlugPlaceholder', 700);
        }
    },
    slugPlaceholder: function (key, value) {
        var slug = this.get('slug');

        //If the post has a slug, that's its placeholder.
        if (slug) {
            return slug;
        }

        //Otherwise, it's whatever value was set by the
        //  slugGenerator (below)
        if (arguments.length > 1) {
            return value;
        }
        //The title will stand in until the actual slug has been generated
        return this.get('titleScratch');
    }.property(),

    showErrors: function (errors) {
        errors = Ember.isArray(errors) ? errors : [errors];
        this.notifications.closePassive();
        this.notifications.showErrors(errors);
    },
    showSuccess: function (message) {
        this.notifications.closePassive();
        this.notifications.showSuccess(message);
    },
    actions: {
        togglePage: function () {
            var self = this;

            this.toggleProperty('page');
            // If this is a new post.  Don't save the model.  Defer the save
            // to the user pressing the save button
            if (this.get('isNew')) {
                return;
            }

            this.get('model').save(this.get('saveOptions')).catch(function (errors) {
                self.showErrors(errors);
                self.get('model').rollback();
            });
        },
        /**
         * triggered by user manually changing slug
         */
        updateSlug: function (newSlug) {
            var slug = this.get('slug'),
                self = this;

            newSlug = newSlug || slug;

            newSlug = newSlug.trim();

            // Ignore unchanged slugs or candidate slugs that are empty
            if (!newSlug || slug === newSlug) {
                return;
            }

            this.get('slugGenerator').generateSlug(newSlug).then(function (serverSlug) {
                // If after getting the sanitized and unique slug back from the API
                // we end up with a slug that matches the existing slug, abort the change
                if (serverSlug === slug) {
                    return;
                }

                // Because the server transforms the candidate slug by stripping
                // certain characters and appending a number onto the end of slugs
                // to enforce uniqueness, there are cases where we can get back a
                // candidate slug that is a duplicate of the original except for
                // the trailing incrementor (e.g., this-is-a-slug and this-is-a-slug-2)

                // get the last token out of the slug candidate and see if it's a number
                var slugTokens = serverSlug.split('-'),
                    check = Number(slugTokens.pop());

                // if the candidate slug is the same as the existing slug except
                // for the incrementor then the existing slug should be used
                if (_.isNumber(check) && check > 0) {
                    if (slug === slugTokens.join('-') && serverSlug !== newSlug) {
                        return;
                    }
                }

                self.set('slug', serverSlug);

                if (self.hasObserverFor('titleScratch')) {
                    self.removeObserver('titleScratch', self, 'titleObserver');
                }

                // If this is a new post.  Don't save the model.  Defer the save
                // to the user pressing the save button
                if (self.get('isNew')) {
                    return;
                }

                return self.get('model').save(self.get('saveOptions'));
            }).then(function () {
                self.showSuccess('Permalink successfully changed to ' +
                    self.get('slug') + '.');
            }).catch(function (errors) {
                self.showErrors(errors);
                self.get('model').rollback();
            });
        },

        /**
         * Parse user's set published date.
         * Action sent by post settings menu view.
         * (#1351)
         */
        setPublishedAt: function (userInput) {
            var errMessage = '',
                newPublishedAt = parseDateString(userInput),
                publishedAt = this.get('published_at'),
                self = this;

            if (!userInput) {
                //Clear out the published_at field for a draft
                if (this.get('isDraft')) {
                    this.set('published_at', null);
                }
                return;
            }

            // Validate new Published date
            if (!newPublishedAt.isValid()) {
                errMessage = 'Published Date must be a valid date with format: ' +
                    'DD MMM YY @ HH:mm (e.g. 6 Dec 14 @ 15:00)';
            }
            if (newPublishedAt.diff(new Date(), 'h') > 0) {
                errMessage = 'Published Date cannot currently be in the future.';
            }

            //If errors, notify and exit.
            if (errMessage) {
                this.showErrors(errMessage);
                return;
            }

            // Do nothing if the user didn't actually change the date
            if (publishedAt && publishedAt.isSame(newPublishedAt)) {
                return;
            }

            //Validation complete
            this.set('published_at', newPublishedAt);

            // If this is a new post.  Don't save the model.  Defer the save
            // to the user pressing the save button
            if (this.get('isNew')) {
                return;
            }

            this.get('model').save(this.get('saveOptions')).catch(function (errors) {
                self.showErrors(errors);
                self.get('model').rollback();
            });
        }
    }
});

export default PostSettingsMenuController;
<commit_msg>Prevent duplicate slug request on saving new post<commit_after>/* global moment */
import {parseDateString, formatDate} from 'ghost/utils/date-formatting';
import SlugGenerator from 'ghost/models/slug-generator';
import boundOneWay from 'ghost/utils/bound-one-way';

var PostSettingsMenuController = Ember.ObjectController.extend({
    init: function () {
        this._super();

        // when creating a new post we want to observe the title
        // to generate the post's slug
        if (this.get('isNew')) {
            this.addObserver('titleScratch', this, 'titleObserver');
        }
    },
    //Changes in the PSM are too minor to warrant NProgress firing
    saveOptions: {disableNProgress: true},
    /**
     * The placeholder is the published date of the post,
     * or the current date if the pubdate has not been set.
     */
    publishedAtPlaceholder: function () {
        var pubDate = this.get('published_at');
        if (pubDate) {
            return formatDate(pubDate);
        }
        return formatDate(moment());
    }.property('publishedAtValue'),
    publishedAtValue: boundOneWay('published_at', formatDate),

    slugValue: boundOneWay('slug'),
    //Lazy load the slug generator for slugPlaceholder
    slugGenerator: Ember.computed(function () {
        return SlugGenerator.create({
            ghostPaths: this.get('ghostPaths')
        });
    }),
    //Requests slug from title
    generateSlugPlaceholder: function () {
        var self = this,
            title = this.get('titleScratch');

        this.get('slugGenerator').generateSlug(title).then(function (slug) {
            self.set('slugPlaceholder', slug);
        });
    },
    titleObserver: function () {
        if (this.get('isNew') && !this.get('title')) {
            Ember.run.debounce(this, 'generateSlugPlaceholder', 700);
        }
    },
    slugPlaceholder: function (key, value) {
        var slug = this.get('slug');

        //If the post has a slug, that's its placeholder.
        if (slug) {
            return slug;
        }

        //Otherwise, it's whatever value was set by the
        //  slugGenerator (below)
        if (arguments.length > 1) {
            return value;
        }
        //The title will stand in until the actual slug has been generated
        return this.get('titleScratch');
    }.property(),

    showErrors: function (errors) {
        errors = Ember.isArray(errors) ? errors : [errors];
        this.notifications.closePassive();
        this.notifications.showErrors(errors);
    },
    showSuccess: function (message) {
        this.notifications.closePassive();
        this.notifications.showSuccess(message);
    },
    actions: {
        togglePage: function () {
            var self = this;

            this.toggleProperty('page');
            // If this is a new post.  Don't save the model.  Defer the save
            // to the user pressing the save button
            if (this.get('isNew')) {
                return;
            }

            this.get('model').save(this.get('saveOptions')).catch(function (errors) {
                self.showErrors(errors);
                self.get('model').rollback();
            });
        },
        /**
         * triggered by user manually changing slug
         */
        updateSlug: function (newSlug) {
            var slug = this.get('slug'),
                self = this;

            newSlug = newSlug || slug;

            newSlug = newSlug.trim();

            // Ignore unchanged slugs or candidate slugs that are empty
            if (!newSlug || slug === newSlug) {
                return;
            }

            this.get('slugGenerator').generateSlug(newSlug).then(function (serverSlug) {
                // If after getting the sanitized and unique slug back from the API
                // we end up with a slug that matches the existing slug, abort the change
                if (serverSlug === slug) {
                    return;
                }

                // Because the server transforms the candidate slug by stripping
                // certain characters and appending a number onto the end of slugs
                // to enforce uniqueness, there are cases where we can get back a
                // candidate slug that is a duplicate of the original except for
                // the trailing incrementor (e.g., this-is-a-slug and this-is-a-slug-2)

                // get the last token out of the slug candidate and see if it's a number
                var slugTokens = serverSlug.split('-'),
                    check = Number(slugTokens.pop());

                // if the candidate slug is the same as the existing slug except
                // for the incrementor then the existing slug should be used
                if (_.isNumber(check) && check > 0) {
                    if (slug === slugTokens.join('-') && serverSlug !== newSlug) {
                        return;
                    }
                }

                self.set('slug', serverSlug);

                if (self.hasObserverFor('titleScratch')) {
                    self.removeObserver('titleScratch', self, 'titleObserver');
                }

                // If this is a new post.  Don't save the model.  Defer the save
                // to the user pressing the save button
                if (self.get('isNew')) {
                    return;
                }

                return self.get('model').save(self.get('saveOptions'));
            }).then(function () {
                self.showSuccess('Permalink successfully changed to ' +
                    self.get('slug') + '.');
            }).catch(function (errors) {
                self.showErrors(errors);
                self.get('model').rollback();
            });
        },

        /**
         * Parse user's set published date.
         * Action sent by post settings menu view.
         * (#1351)
         */
        setPublishedAt: function (userInput) {
            var errMessage = '',
                newPublishedAt = parseDateString(userInput),
                publishedAt = this.get('published_at'),
                self = this;

            if (!userInput) {
                //Clear out the published_at field for a draft
                if (this.get('isDraft')) {
                    this.set('published_at', null);
                }
                return;
            }

            // Validate new Published date
            if (!newPublishedAt.isValid()) {
                errMessage = 'Published Date must be a valid date with format: ' +
                    'DD MMM YY @ HH:mm (e.g. 6 Dec 14 @ 15:00)';
            }
            if (newPublishedAt.diff(new Date(), 'h') > 0) {
                errMessage = 'Published Date cannot currently be in the future.';
            }

            //If errors, notify and exit.
            if (errMessage) {
                this.showErrors(errMessage);
                return;
            }

            // Do nothing if the user didn't actually change the date
            if (publishedAt && publishedAt.isSame(newPublishedAt)) {
                return;
            }

            //Validation complete
            this.set('published_at', newPublishedAt);

            // If this is a new post.  Don't save the model.  Defer the save
            // to the user pressing the save button
            if (this.get('isNew')) {
                return;
            }

            this.get('model').save(this.get('saveOptions')).catch(function (errors) {
                self.showErrors(errors);
                self.get('model').rollback();
            });
        }
    }
});

export default PostSettingsMenuController;
<|endoftext|>