<commit_before>var config = require('./config');
var manageUsers = require('./manageUsers.js');
//var mongo = require('./mongoFunctions.js');

function sendSubstitutions(senderID){
	var body = {
		'mode': 'getChanges',
		'param': 'today'
	};
	manageUsers.postCall('0000', body, function(substitutions){
		var messageData = {
			recipient: {
				id: senderID
			},
			message: {
				text: substitutions
			}
		};
		callSendAPI(messageData);
	});
}

function receivedPostback(event) {
  var senderID = event.sender.id;
  var recipientID = event.recipient.id;
  var timeOfPostback = event.timestamp;

  // The 'payload' param is a developer-defined field which is set in a postback
  // button for Structured Messages.
  var payload = event.postback.payload;

  console.log("Received postback for user %d and page %d with payload '%s' " +
    "at %d", senderID, recipientID, payload, timeOfPostback);

  // When a postback is called, we'll send a message back to the sender to
  // let them know it was successful
  //sendTextMessage(senderID, "Postback called");
}

function receivedMessage(event) {
  var senderID = event.sender.id;
  var recipientID = event.recipient.id;
  var timeOfMessage = event.timestamp;
  var message = event.message;

  console.log("Received message for user %d and page %d at %d with message:",
    senderID, recipientID, timeOfMessage);
  console.log(JSON.stringify(message));

  var messageId = message.mid;

  var messageText = message.text;
  var messageAttachments = message.attachments;

  /*if (messageText) {

    // If we receive a text message, check to see if it matches a keyword
    // and send back the example. Otherwise, just echo the text we received.
    switch (messageText) {
      case 'generic':
        sendGenericMessage(senderID);
        break;

      default:
        sendTextMessage(senderID, messageText);
    }
  } else if (messageAttachments) {
    sendTextMessage(senderID, "Message with attachment received");
  }*/
  sendSubstitutions(senderID);
  //sendTextMessage(senderID, messageText);
}

function callSendAPI(messageData) {
  request({
    uri: 'https://graph.facebook.com/v2.7/me/messages',
    qs: { access_token: config.pageToken },
    method: 'POST',
    json: messageData

  }, function (error, response, body) {
    if (!error && response.statusCode == 200) {
      var recipientId = body.recipient_id;
      var messageId = body.message_id;

      console.log("Successfully sent generic message with id %s to recipient %s",
        messageId, recipientId);
    } else {
      console.error("Unable to send message.");
      console.error(response);
      console.error(error);
    }
  });
}

/*function sendTextMessage(recipientId, messageText) {
  var messageData = {
    recipient: {
      id: recipientId
    },
    message: {
      text: messageText
    }
  };

  callSendAPI(messageData);
}*/

/*function sendGenericMessage(recipientId) {
  var messageData = {
    recipient: {
      id: recipientId
    },
    message: {
      attachment: {
        type: "template",
        payload: {
          template_type: "generic",
          elements: [{
            title: "rift",
            subtitle: "Next-generation virtual reality",
            item_url: "https://www.oculus.com/en-us/rift/",
            image_url: "http://messengerdemo.parseapp.com/img/rift.png",
            buttons: [{
              type: "web_url",
              url: "https://www.oculus.com/en-us/rift/",
              title: "Open Web URL"
            }, {
              type: "postback",
              title: "Call Postback",
              payload: "Payload for first bubble",
            }],
          }, {
            title: "touch",
            subtitle: "Your Hands, Now in VR",
            item_url: "https://www.oculus.com/en-us/touch/",
            image_url: "http://messengerdemo.parseapp.com/img/touch.png",
            buttons: [{
              type: "web_url",
              url: "https://www.oculus.com/en-us/touch/",
              title: "Open Web URL"
            }, {
              type: "postback",
              title: "Call Postback",
              payload: "Payload for second bubble",
            }]
          }]
        }
      }
    }
  };

  callSendAPI(messageData);
}*/

exports.receivedPostback=receivedPostback;
exports.receivedMessage=receivedMessage;
<commit_msg>require request<commit_after>var config = require('./config');
var manageUsers = require('./manageUsers.js');
var request = require('request');
//var mongo = require('./mongoFunctions.js');

function sendSubstitutions(senderID){
	var body = {
		'mode': 'getChanges',
		'param': 'today'
	};
	manageUsers.postCall('0000', body, function(substitutions){
		var messageData = {
			recipient: {
				id: senderID
			},
			message: {
				text: substitutions
			}
		};
		callSendAPI(messageData);
	});
}

function receivedPostback(event) {
  var senderID = event.sender.id;
  var recipientID = event.recipient.id;
  var timeOfPostback = event.timestamp;

  // The 'payload' param is a developer-defined field which is set in a postback
  // button for Structured Messages.
  var payload = event.postback.payload;

  console.log("Received postback for user %d and page %d with payload '%s' " +
    "at %d", senderID, recipientID, payload, timeOfPostback);

  // When a postback is called, we'll send a message back to the sender to
  // let them know it was successful
  //sendTextMessage(senderID, "Postback called");
}

function receivedMessage(event) {
  var senderID = event.sender.id;
  var recipientID = event.recipient.id;
  var timeOfMessage = event.timestamp;
  var message = event.message;

  console.log("Received message for user %d and page %d at %d with message:",
    senderID, recipientID, timeOfMessage);
  console.log(JSON.stringify(message));

  var messageId = message.mid;

  var messageText = message.text;
  var messageAttachments = message.attachments;

  /*if (messageText) {

    // If we receive a text message, check to see if it matches a keyword
    // and send back the example. Otherwise, just echo the text we received.
    switch (messageText) {
      case 'generic':
        sendGenericMessage(senderID);
        break;

      default:
        sendTextMessage(senderID, messageText);
    }
  } else if (messageAttachments) {
    sendTextMessage(senderID, "Message with attachment received");
  }*/
  sendSubstitutions(senderID);
  //sendTextMessage(senderID, messageText);
}

function callSendAPI(messageData) {
  request({
    uri: 'https://graph.facebook.com/v2.7/me/messages',
    qs: { access_token: config.pageToken },
    method: 'POST',
    json: messageData

  }, function (error, response, body) {
    if (!error && response.statusCode == 200) {
      var recipientId = body.recipient_id;
      var messageId = body.message_id;

      console.log("Successfully sent generic message with id %s to recipient %s",
        messageId, recipientId);
    } else {
      console.error("Unable to send message.");
      console.error(response);
      console.error(error);
    }
  });
}

/*function sendTextMessage(recipientId, messageText) {
  var messageData = {
    recipient: {
      id: recipientId
    },
    message: {
      text: messageText
    }
  };

  callSendAPI(messageData);
}*/

/*function sendGenericMessage(recipientId) {
  var messageData = {
    recipient: {
      id: recipientId
    },
    message: {
      attachment: {
        type: "template",
        payload: {
          template_type: "generic",
          elements: [{
            title: "rift",
            subtitle: "Next-generation virtual reality",
            item_url: "https://www.oculus.com/en-us/rift/",
            image_url: "http://messengerdemo.parseapp.com/img/rift.png",
            buttons: [{
              type: "web_url",
              url: "https://www.oculus.com/en-us/rift/",
              title: "Open Web URL"
            }, {
              type: "postback",
              title: "Call Postback",
              payload: "Payload for first bubble",
            }],
          }, {
            title: "touch",
            subtitle: "Your Hands, Now in VR",
            item_url: "https://www.oculus.com/en-us/touch/",
            image_url: "http://messengerdemo.parseapp.com/img/touch.png",
            buttons: [{
              type: "web_url",
              url: "https://www.oculus.com/en-us/touch/",
              title: "Open Web URL"
            }, {
              type: "postback",
              title: "Call Postback",
              payload: "Payload for second bubble",
            }]
          }]
        }
      }
    }
  };

  callSendAPI(messageData);
}*/

exports.receivedPostback=receivedPostback;
exports.receivedMessage=receivedMessage;
<|endoftext|>


<commit_before>Vue.directive('focus', {
    inserted: function (el) {
        el.focus();
    }
});

Vue.component('todo-item', {
    props: ['item', 'index', 'editmode'],
    template: '\

\
      <input type="checkbox"  v-if="!(editmode.enabled && editmode.index == index)" @click="$emit(\'strike\')" :checked="item.strikeout">\

\
      <textarea class="editor" v-focus="true" @keydown.ctrl.83="$emit(\'save\')" v-model.trim="item.text" type="text"></textarea>\

\

\
        <input type="checkbox" @keydown.ctrl.83="$emit(\'save\')" @click="$emit(\'check_remind\')" :checked="item.remind_enabled">\
        Remind\

\
      <input type="date" v-model="item.remind_date" @keydown.ctrl.83="$emit(\'save\')">\
      <input type="time" v-model="item.remind_time" @keydown.ctrl.83="$emit(\'save\')">\

\

\
        <button type="button" class="btn btn-default" @click="$emit(\'save\')" title="Ctrl+S">Save</button>\
        <button type="button" class="btn btn-default" @click="$emit(\'cancel\')" title="ESC">Cancel</button>\

\

\

\
      \
      {{item.text}}\

\

\
            <button type="button" class="btn btn-default" title="Edit item" @click="$emit(\'edit\');" v-if="!(editmode.enabled && editmode.index == index)">\
                \
            </button>\
            <button type="button" class="btn btn-default" title="Delete item" @click="$emit(\'delete\')" v-if="!(editmode.enabled && editmode.index == index)">\
                \
            </button>\

\

\
      ',
    inserted: function (el) {
        // Focus the element
        el.focus()
    }
});

var vmTodoList = new Vue({
    el: '#todo-list',
    data: {
        newItemInput: '',
        todos: [],
        editMode: {
            enabled: false,
            index: 0
        }
    },
    methods: {
        addItem: function () {
            if (!this.newItemInput) return;
            this.todos.unshift({
                text: this.newItemInput,
                strikeout: false,
                remind_enabled: false,
                remind_date: '',
                remind_time: ''

            });
            this.newItemInput = '';
            this.save()
        },
        deleteItem: function (index) {
            if (confirm('Are you sure you want to delete this todo?')) {
                this.todos.splice(index, 1);
            }
        },
        strikeItem: function (index) {
            this.todos[index].strikeout = !this.todos[index].strikeout;
        },
        checkRemind: function (index) {
            this.todos[index].remind_enabled = !this.todos[index].remind_enabled;

        },
        editItem: function (index) {
            this.editMode.index = index;
            this.editMode.enabled = !this.editMode.enabled;
        },
        saveItem: function () {
            this.editMode.enabled = !this.editMode.enabled;
             this.save()
        },
        cancelChanges: function (index) {
            this.editMode.enabled = false;
            loadTodosFromSettings(index);
        },
        save: function () {
            loadTodosToSettings();
            updateAppSettings();
        }
    }

});

<commit_msg>point<commit_after>Vue.directive('focus', {
    inserted: function (el) {
        el.focus();
    }
});

Vue.component('todo-item', {
    props: ['item', 'index', 'editmode'],
    template: '\

\
      <input type="checkbox"  v-if="!(editmode.enabled && editmode.index == index)" @click="$emit(\'strike\')" :checked="item.strikeout">\

\
      <textarea class="editor" v-focus="true" @keydown.ctrl.83="$emit(\'save\')" v-model.trim="item.text" type="text"></textarea>\

\

\
        <input type="checkbox" @keydown.ctrl.83="$emit(\'save\')" :checked="item.remind_enabled">\
        Remind\

\
      <input type="date" v-model="item.remind_date" @keydown.ctrl.83="$emit(\'save\')">\
      <input type="time" v-model="item.remind_time" @keydown.ctrl.83="$emit(\'save\')">\

\

\
        <button type="button" class="btn btn-default" @click="$emit(\'save\')" title="Ctrl+S">Save</button>\
        <button type="button" class="btn btn-default" @click="$emit(\'cancel\')" title="ESC">Cancel</button>\

\

\

\
      \
      {{item.text}}\

\

\
            <button type="button" class="btn btn-default" title="Edit item" @click="$emit(\'edit\');" v-if="!(editmode.enabled && editmode.index == index)">\
                \
            </button>\
            <button type="button" class="btn btn-default" title="Delete item" @click="$emit(\'delete\')" v-if="!(editmode.enabled && editmode.index == index)">\
                \
            </button>\

\

\
      ',
    inserted: function (el) {
        // Focus the element
        el.focus()
    }
});

var vmTodoList = new Vue({
    el: '#todo-list',
    data: {
        newItemInput: '',
        todos: [],
        editMode: {
            enabled: false,
            index: 0
        }
    },
    methods: {
        addItem: function () {
            if (!this.newItemInput) return;
            this.todos.unshift({
                text: this.newItemInput,
                strikeout: false,
                remind_enabled: false,
                remind_date: '',
                remind_time: ''

            });
            this.newItemInput = '';
            this.save()
        },
        deleteItem: function (index) {
            if (confirm('Are you sure you want to delete this todo?')) {
                this.todos.splice(index, 1);
            }
        },
        strikeItem: function (index) {
            this.todos[index].strikeout = !this.todos[index].strikeout;
        },
        checkRemind: function (index) {
            this.todos[index].remind_enabled = !this.todos[index].remind_enabled;

        },
        editItem: function (index) {
            this.editMode.index = index;
            this.editMode.enabled = !this.editMode.enabled;
        },
        saveItem: function () {
            this.editMode.enabled = !this.editMode.enabled;
             this.save()
        },
        cancelChanges: function (index) {
            this.editMode.enabled = false;
            loadTodosFromSettings(index);
        },
        save: function () {
            loadTodosToSettings();
            updateAppSettings();
        }
    }

});

<|endoftext|>


<commit_before>//----------------------------------------------------------------------------
//  Copyright (C) 2013 The IPython Development Team
//
//  Distributed under the terms of the BSD License.  The full license is in
//  the file COPYING, distributed as part of this software.
//----------------------------------------------------------------------------

//============================================================================
// Base Widget Model and View classes
//============================================================================

/**
 * @module IPython
 * @namespace IPython
 **/

define(["notebook/js/widgetmanager",
        "underscore",
        "backbone"],
function(WidgetManager, _, Backbone){

    var WidgetModel = Backbone.Model.extend({
        constructor: function (widget_manager, model_id, comm) {
            // Constructor
            //
            // Creates a WidgetModel instance.
            //
            // Parameters
            // ----------
            // widget_manager : WidgetManager instance
            // model_id : string
            //      An ID unique to this model.
            // comm : Comm instance (optional)
            this.widget_manager = widget_manager;
            this._buffered_state_diff = {};
            this.pending_msgs = 0;
            this.msg_throttle = 3;
            this.msg_buffer = null;
            this.key_value_lock = null;
            this.id = model_id;
            this.views = [];

            if (comm !== undefined) {
                // Remember comm associated with the model.
                this.comm = comm;
                comm.model = this;

                // Hook comm messages up to model.
                comm.on_close($.proxy(this._handle_comm_closed, this));
                comm.on_msg($.proxy(this._handle_comm_msg, this));
            }
            return Backbone.Model.apply(this);
        },

        send: function (content, callbacks) {
            // Send a custom msg over the comm.
            if (this.comm !== undefined) {
                var data = {method: 'custom', content: content};
                this.comm.send(data, callbacks);
                this.pending_msgs++;
            }
        },

        _handle_comm_closed: function (msg) {
            // Handle when a widget is closed.
            this.trigger('comm:close');
            delete this.comm.model; // Delete ref so GC will collect widget model.
            delete this.comm;
            delete this.model_id; // Delete id from model so widget manager cleans up.
            _.each(this.views, function(view, i) {
                view.remove();
            });
        },

        _handle_comm_msg: function (msg) {
            // Handle incoming comm msg.
            var method = msg.content.data.method;
            switch (method) {
                case 'update':
                    this.apply_update(msg.content.data.state);
                    break;
                case 'custom':
                    this.trigger('msg:custom', msg.content.data.content);
                    break;
                case 'display':
                    this.widget_manager.display_view(msg, this);
                    break;
            }
        },

        apply_update: function (state) {
            // Handle when a widget is updated via the python side.
            var that = this;
            _.each(state, function(value, key) {
                that.key_value_lock = [key, value];
                try {
                    that.set(key, that._unpack_models(value));
                } finally {
                    that.key_value_lock = null;
                }
            });
        },

        _handle_status: function (msg, callbacks) {
            // Handle status msgs.

            // execution_state : ('busy', 'idle', 'starting')
            if (this.comm !== undefined) {
                if (msg.content.execution_state ==='idle') {
                    // Send buffer if this message caused another message to be
                    // throttled.
                    if (this.msg_buffer !== null &&
                        this.msg_throttle === this.pending_msgs) {
                        var data = {method: 'backbone', sync_method: 'update', sync_data: this.msg_buffer};
                        this.comm.send(data, callbacks);
                        this.msg_buffer = null;
                    } else {
                        --this.pending_msgs;
                    }
                }
            }
        },

        callbacks: function(view) {
            // Create msg callbacks for a comm msg.
            var callbacks = this.widget_manager.callbacks(view);

            if (callbacks.iopub === undefined) {
                callbacks.iopub = {};
            }

            var that = this;
            callbacks.iopub.status = function (msg) {
                that._handle_status(msg, callbacks);
            };
            return callbacks;
        },

        set: function(key, val, options) {
            // Set a value.
            var return_value = WidgetModel.__super__.set.apply(this, arguments);

            // Backbone only remembers the diff of the most recent set()
            // operation.  Calling set multiple times in a row results in a
            // loss of diff information.  Here we keep our own running diff.
            this._buffered_state_diff = $.extend(this._buffered_state_diff, this.changedAttributes() || {});
            return return_value;
        },

        sync: function (method, model, options) {
            // Handle sync to the back-end.  Called when a model.save() is called.

            // Make sure a comm exists.
            var error = options.error || function() {
                console.error('Backbone sync error:', arguments);
            };
            if (this.comm === undefined) {
                error();
                return false;
            }

            // Delete any key value pairs that the back-end already knows about.
            var attrs = (method === 'patch') ? options.attrs : model.toJSON(options);
            if (this.key_value_lock !== null) {
                var key = this.key_value_lock[0];
                var value = this.key_value_lock[1];
                if (attrs[key] === value) {
                    delete attrs[key];
                }
            }

            // Only sync if there are attributes to send to the back-end.
            attrs = this._pack_models(attrs);
            if (_.size(attrs) > 0) {

                // If this message was sent via backbone itself, it will not
                // have any callbacks.  It's important that we create callbacks
                // so we can listen for status messages, etc...
                var callbacks = options.callbacks || this.callbacks();

                // Check throttle.
                if (this.pending_msgs >= this.msg_throttle) {
                    // The throttle has been exceeded, buffer the current msg so
                    // it can be sent once the kernel has finished processing
                    // some of the existing messages.

                    // Combine updates if it is a 'patch' sync, otherwise replace updates
                    switch (method) {
                        case 'patch':
                            this.msg_buffer = $.extend(this.msg_buffer || {}, attrs);
                            break;
                        case 'update':
                        case 'create':
                            this.msg_buffer = attrs;
                            break;
                        default:
                            error();
                            return false;
                    }
                    this.msg_buffer_callbacks = callbacks;

                } else {
                    // We haven't exceeded the throttle, send the message like
                    // normal.
                    var data = {method: 'backbone', sync_data: attrs};
                    this.comm.send(data, callbacks);
                    this.pending_msgs++;
                }
            }
            // Since the comm is a one-way communication, assume the message
            // arrived.  Don't call success since we don't have a model back from the server
            // this means we miss out on the 'sync' event.
            this._buffered_state_diff = {};
        },

        save_changes: function(callbacks) {
            // Push this model's state to the back-end
            //
            // This invokes a Backbone.Sync.
            this.save(this._buffered_state_diff, {patch: true, callbacks: callbacks});
        },

        _pack_models: function(value) {
            // Replace models with model ids recursively.
            if (value instanceof Backbone.Model) {
                return value.id;

            } else if ($.isArray(value)) {
                var packed = [];
                var that = this;
                _.each(value, function(sub_value, key) {
                    packed.push(that._pack_models(sub_value));
                });
                return packed;

            } else if (value instanceof Object) {
                var packed = {};
                var that = this;
                _.each(value, function(sub_value, key) {
                    packed[key] = that._pack_models(sub_value);
                });
                return packed;

            } else {
                return value;
            }
        },

        _unpack_models: function(value) {
            // Replace model ids with models recursively.
            if ($.isArray(value)) {
                var unpacked = [];
                var that = this;
                _.each(value, function(sub_value, key) {
                    unpacked.push(that._unpack_models(sub_value));
                });
                return unpacked;

            } else if (value instanceof Object) {
                var unpacked = {};
                var that = this;
                _.each(value, function(sub_value, key) {
                    unpacked[key] = that._unpack_models(sub_value);
                });
                return unpacked;

            } else {
                var model = this.widget_manager.get_model(value);
                if (model) {
                    return model;
                } else {
                    return value;
                }
            }
        },

    });
    WidgetManager.register_widget_model('WidgetModel', WidgetModel);

    var WidgetView = Backbone.View.extend({
        initialize: function(parameters) {
            // Public constructor.
            this.model.on('change',this.update,this);
            this.options = parameters.options;
            this.child_views = [];
            this.model.views.push(this);
        },

        update: function(){
            // Triggered on model change.
            //
            // Update view to be consistent with this.model
        },

        create_child_view: function(child_model, options) {
            // Create and return a child view.
            //
            // -given a model and (optionally) a view name if the view name is
            // not given, it defaults to the model's default view attribute.

            // TODO: this is hacky, and makes the view depend on this cell attribute and widget manager behavior
            // it would be great to have the widget manager add the cell metadata
            // to the subview without having to add it here.
            var child_view = this.model.widget_manager.create_view(child_model, options || {}, this);
            this.child_views[child_model.id] = child_view;
            return child_view;
        },

        delete_child_view: function(child_model, options) {
            // Delete a child view that was previously created using create_child_view.
            var view = this.child_views[child_model.id];
            if (view !== undefined) {
                delete this.child_views[child_model.id];
                view.remove();
            }
        },

        do_diff: function(old_list, new_list, removed_callback, added_callback) {
            // Difference a changed list and call remove and add callbacks for
            // each removed and added item in the new list.
            //
            // Parameters
            // ----------
            // old_list : array
            // new_list : array
            // removed_callback : Callback(item)
            //      Callback that is called for each item removed.
            // added_callback : Callback(item)
            //      Callback that is called for each item added.

            // removed items
            _.each(_.difference(old_list, new_list), function(item, index, list) {
                removed_callback(item);
            }, this);

            // added items
            _.each(_.difference(new_list, old_list), function(item, index, list) {
                added_callback(item);
            }, this);
        },

        callbacks: function(){
            // Create msg callbacks for a comm msg.
            return this.model.callbacks(this);
        },

        render: function(){
            // Render the view.
            //
            // By default, this is only called the first time the view is created
        },

        send: function (content) {
            // Send a custom msg associated with this view.
            this.model.send(content, this.callbacks());
        },

        touch: function () {
            this.model.save_changes(this.callbacks());
        },
    });

    var DOMWidgetView = WidgetView.extend({
        initialize: function (options) {
            // Public constructor

            // In the future we may want to make changes more granular
            // (e.g., trigger on visible:change).
            this.model.on('change', this.update, this);
            this.model.on('msg:custom', this.on_msg, this);
            DOMWidgetView.__super__.initialize.apply(this, arguments);
        },

        on_msg: function(msg) {
            // Handle DOM specific msgs.
            switch(msg.msg_type) {
                case 'add_class':
                    this.add_class(msg.selector, msg.class_list);
                    break;
                case 'remove_class':
                    this.remove_class(msg.selector, msg.class_list);
                    break;
            }
        },

        add_class: function (selector, class_list) {
            // Add a DOM class to an element.
            this._get_selector_element(selector).addClass(class_list);
        },

        remove_class: function (selector, class_list) {
            // Remove a DOM class from an element.
            this._get_selector_element(selector).removeClass(class_list);
        },

        update: function () {
            // Update the contents of this view
            //
            // Called when the model is changed.  The model may have been
            // changed by another view or by a state update from the back-end.
            //      The very first update seems to happen before the element is
            // finished rendering so we use setTimeout to give the element time
            // to render
            var e = this.$el;
            var visible = this.model.get('visible');
            setTimeout(function() {e.toggle(visible);},0);

            var css = this.model.get('_css');
            if (css === undefined) {return;}
            var that = this;
            _.each(css, function(css_traits, selector){
                // Apply the css traits to all elements that match the selector.
                var elements = that._get_selector_element(selector);
                if (elements.length > 0) {
                    _.each(css_traits, function(css_value, css_key){
                        elements.css(css_key, css_value);
                    });
                }
            });
        },

        _get_selector_element: function (selector) {
            // Get the elements via the css selector.

            // If the selector is blank, apply the style to the $el_to_style
            // element.  If the $el_to_style element is not defined, use apply
            // the style to the view's element.
            var elements;
            if (!selector) {
                if (this.$el_to_style === undefined) {
                    elements = this.$el;
                } else {
                    elements = this.$el_to_style;
                }
            } else {
                elements = this.$el.find(selector);
            }
            return elements;
        },
    });

    IPython.WidgetModel = WidgetModel;
    IPython.WidgetView = WidgetView;
    IPython.DOMWidgetView = DOMWidgetView;

    // Pass through WidgetManager namespace.
    return WidgetManager;
});
<commit_msg>Fixed, set on recieve update triggering echos.<commit_after>//----------------------------------------------------------------------------
//  Copyright (C) 2013 The IPython Development Team
//
//  Distributed under the terms of the BSD License.  The full license is in
//  the file COPYING, distributed as part of this software.
//----------------------------------------------------------------------------

//============================================================================
// Base Widget Model and View classes
//============================================================================

/**
 * @module IPython
 * @namespace IPython
 **/

define(["notebook/js/widgetmanager",
        "underscore",
        "backbone"],
function(WidgetManager, _, Backbone){

    var WidgetModel = Backbone.Model.extend({
        constructor: function (widget_manager, model_id, comm) {
            // Constructor
            //
            // Creates a WidgetModel instance.
            //
            // Parameters
            // ----------
            // widget_manager : WidgetManager instance
            // model_id : string
            //      An ID unique to this model.
            // comm : Comm instance (optional)
            this.widget_manager = widget_manager;
            this._buffered_state_diff = {};
            this.pending_msgs = 0;
            this.msg_throttle = 3;
            this.msg_buffer = null;
            this.key_value_lock = null;
            this.id = model_id;
            this.views = [];

            if (comm !== undefined) {
                // Remember comm associated with the model.
                this.comm = comm;
                comm.model = this;

                // Hook comm messages up to model.
                comm.on_close($.proxy(this._handle_comm_closed, this));
                comm.on_msg($.proxy(this._handle_comm_msg, this));
            }
            return Backbone.Model.apply(this);
        },

        send: function (content, callbacks) {
            // Send a custom msg over the comm.
            if (this.comm !== undefined) {
                var data = {method: 'custom', content: content};
                this.comm.send(data, callbacks);
                this.pending_msgs++;
            }
        },

        _handle_comm_closed: function (msg) {
            // Handle when a widget is closed.
            this.trigger('comm:close');
            delete this.comm.model; // Delete ref so GC will collect widget model.
            delete this.comm;
            delete this.model_id; // Delete id from model so widget manager cleans up.
            _.each(this.views, function(view, i) {
                view.remove();
            });
        },

        _handle_comm_msg: function (msg) {
            // Handle incoming comm msg.
            var method = msg.content.data.method;
            switch (method) {
                case 'update':
                    this.apply_update(msg.content.data.state);
                    break;
                case 'custom':
                    this.trigger('msg:custom', msg.content.data.content);
                    break;
                case 'display':
                    this.widget_manager.display_view(msg, this);
                    break;
            }
        },

        apply_update: function (state) {
            // Handle when a widget is updated via the python side.
            var that = this;
            _.each(state, function(value, key) {
                that.key_value_lock = [key, value];
                try {
                    WidgetModel.__super__.set.apply(that, [key, that._unpack_models(value)]);
                } finally {
                    that.key_value_lock = null;
                }
            });
        },

        _handle_status: function (msg, callbacks) {
            // Handle status msgs.

            // execution_state : ('busy', 'idle', 'starting')
            if (this.comm !== undefined) {
                if (msg.content.execution_state ==='idle') {
                    // Send buffer if this message caused another message to be
                    // throttled.
                    if (this.msg_buffer !== null &&
                        this.msg_throttle === this.pending_msgs) {
                        var data = {method: 'backbone', sync_method: 'update', sync_data: this.msg_buffer};
                        this.comm.send(data, callbacks);
                        this.msg_buffer = null;
                    } else {
                        --this.pending_msgs;
                    }
                }
            }
        },

        callbacks: function(view) {
            // Create msg callbacks for a comm msg.
            var callbacks = this.widget_manager.callbacks(view);

            if (callbacks.iopub === undefined) {
                callbacks.iopub = {};
            }

            var that = this;
            callbacks.iopub.status = function (msg) {
                that._handle_status(msg, callbacks);
            };
            return callbacks;
        },

        set: function(key, val, options) {
            // Set a value.
            var return_value = WidgetModel.__super__.set.apply(this, arguments);

            // Backbone only remembers the diff of the most recent set()
            // operation.  Calling set multiple times in a row results in a
            // loss of diff information.  Here we keep our own running diff.
            this._buffered_state_diff = $.extend(this._buffered_state_diff, this.changedAttributes() || {});
            return return_value;
        },

        sync: function (method, model, options) {
            // Handle sync to the back-end.  Called when a model.save() is called.

            // Make sure a comm exists.
            var error = options.error || function() {
                console.error('Backbone sync error:', arguments);
            };
            if (this.comm === undefined) {
                error();
                return false;
            }

            // Delete any key value pairs that the back-end already knows about.
            var attrs = (method === 'patch') ? options.attrs : model.toJSON(options);
            if (this.key_value_lock !== null) {
                var key = this.key_value_lock[0];
                var value = this.key_value_lock[1];
                if (attrs[key] === value) {
                    delete attrs[key];
                }
            }

            // Only sync if there are attributes to send to the back-end.
            attrs = this._pack_models(attrs);
            if (_.size(attrs) > 0) {

                // If this message was sent via backbone itself, it will not
                // have any callbacks.  It's important that we create callbacks
                // so we can listen for status messages, etc...
                var callbacks = options.callbacks || this.callbacks();

                // Check throttle.
                if (this.pending_msgs >= this.msg_throttle) {
                    // The throttle has been exceeded, buffer the current msg so
                    // it can be sent once the kernel has finished processing
                    // some of the existing messages.

                    // Combine updates if it is a 'patch' sync, otherwise replace updates
                    switch (method) {
                        case 'patch':
                            this.msg_buffer = $.extend(this.msg_buffer || {}, attrs);
                            break;
                        case 'update':
                        case 'create':
                            this.msg_buffer = attrs;
                            break;
                        default:
                            error();
                            return false;
                    }
                    this.msg_buffer_callbacks = callbacks;

                } else {
                    // We haven't exceeded the throttle, send the message like
                    // normal.
                    var data = {method: 'backbone', sync_data: attrs};
                    this.comm.send(data, callbacks);
                    this.pending_msgs++;
                }
            }
            // Since the comm is a one-way communication, assume the message
            // arrived.  Don't call success since we don't have a model back from the server
            // this means we miss out on the 'sync' event.
            this._buffered_state_diff = {};
        },

        save_changes: function(callbacks) {
            // Push this model's state to the back-end
            //
            // This invokes a Backbone.Sync.
            this.save(this._buffered_state_diff, {patch: true, callbacks: callbacks});
        },

        _pack_models: function(value) {
            // Replace models with model ids recursively.
            if (value instanceof Backbone.Model) {
                return value.id;

            } else if ($.isArray(value)) {
                var packed = [];
                var that = this;
                _.each(value, function(sub_value, key) {
                    packed.push(that._pack_models(sub_value));
                });
                return packed;

            } else if (value instanceof Object) {
                var packed = {};
                var that = this;
                _.each(value, function(sub_value, key) {
                    packed[key] = that._pack_models(sub_value);
                });
                return packed;

            } else {
                return value;
            }
        },

        _unpack_models: function(value) {
            // Replace model ids with models recursively.
            if ($.isArray(value)) {
                var unpacked = [];
                var that = this;
                _.each(value, function(sub_value, key) {
                    unpacked.push(that._unpack_models(sub_value));
                });
                return unpacked;

            } else if (value instanceof Object) {
                var unpacked = {};
                var that = this;
                _.each(value, function(sub_value, key) {
                    unpacked[key] = that._unpack_models(sub_value);
                });
                return unpacked;

            } else {
                var model = this.widget_manager.get_model(value);
                if (model) {
                    return model;
                } else {
                    return value;
                }
            }
        },

    });
    WidgetManager.register_widget_model('WidgetModel', WidgetModel);

    var WidgetView = Backbone.View.extend({
        initialize: function(parameters) {
            // Public constructor.
            this.model.on('change',this.update,this);
            this.options = parameters.options;
            this.child_views = [];
            this.model.views.push(this);
        },

        update: function(){
            // Triggered on model change.
            //
            // Update view to be consistent with this.model
        },

        create_child_view: function(child_model, options) {
            // Create and return a child view.
            //
            // -given a model and (optionally) a view name if the view name is
            // not given, it defaults to the model's default view attribute.

            // TODO: this is hacky, and makes the view depend on this cell attribute and widget manager behavior
            // it would be great to have the widget manager add the cell metadata
            // to the subview without having to add it here.
            var child_view = this.model.widget_manager.create_view(child_model, options || {}, this);
            this.child_views[child_model.id] = child_view;
            return child_view;
        },

        delete_child_view: function(child_model, options) {
            // Delete a child view that was previously created using create_child_view.
            var view = this.child_views[child_model.id];
            if (view !== undefined) {
                delete this.child_views[child_model.id];
                view.remove();
            }
        },

        do_diff: function(old_list, new_list, removed_callback, added_callback) {
            // Difference a changed list and call remove and add callbacks for
            // each removed and added item in the new list.
            //
            // Parameters
            // ----------
            // old_list : array
            // new_list : array
            // removed_callback : Callback(item)
            //      Callback that is called for each item removed.
            // added_callback : Callback(item)
            //      Callback that is called for each item added.

            // removed items
            _.each(_.difference(old_list, new_list), function(item, index, list) {
                removed_callback(item);
            }, this);

            // added items
            _.each(_.difference(new_list, old_list), function(item, index, list) {
                added_callback(item);
            }, this);
        },

        callbacks: function(){
            // Create msg callbacks for a comm msg.
            return this.model.callbacks(this);
        },

        render: function(){
            // Render the view.
            //
            // By default, this is only called the first time the view is created
        },

        send: function (content) {
            // Send a custom msg associated with this view.
            this.model.send(content, this.callbacks());
        },

        touch: function () {
            this.model.save_changes(this.callbacks());
        },
    });

    var DOMWidgetView = WidgetView.extend({
        initialize: function (options) {
            // Public constructor

            // In the future we may want to make changes more granular
            // (e.g., trigger on visible:change).
            this.model.on('change', this.update, this);
            this.model.on('msg:custom', this.on_msg, this);
            DOMWidgetView.__super__.initialize.apply(this, arguments);
        },

        on_msg: function(msg) {
            // Handle DOM specific msgs.
            switch(msg.msg_type) {
                case 'add_class':
                    this.add_class(msg.selector, msg.class_list);
                    break;
                case 'remove_class':
                    this.remove_class(msg.selector, msg.class_list);
                    break;
            }
        },

        add_class: function (selector, class_list) {
            // Add a DOM class to an element.
            this._get_selector_element(selector).addClass(class_list);
        },

        remove_class: function (selector, class_list) {
            // Remove a DOM class from an element.
            this._get_selector_element(selector).removeClass(class_list);
        },

        update: function () {
            // Update the contents of this view
            //
            // Called when the model is changed.  The model may have been
            // changed by another view or by a state update from the back-end.
            //      The very first update seems to happen before the element is
            // finished rendering so we use setTimeout to give the element time
            // to render
            var e = this.$el;
            var visible = this.model.get('visible');
            setTimeout(function() {e.toggle(visible);},0);

            var css = this.model.get('_css');
            if (css === undefined) {return;}
            var that = this;
            _.each(css, function(css_traits, selector){
                // Apply the css traits to all elements that match the selector.
                var elements = that._get_selector_element(selector);
                if (elements.length > 0) {
                    _.each(css_traits, function(css_value, css_key){
                        elements.css(css_key, css_value);
                    });
                }
            });
        },

        _get_selector_element: function (selector) {
            // Get the elements via the css selector.

            // If the selector is blank, apply the style to the $el_to_style
            // element.  If the $el_to_style element is not defined, use apply
            // the style to the view's element.
            var elements;
            if (!selector) {
                if (this.$el_to_style === undefined) {
                    elements = this.$el;
                } else {
                    elements = this.$el_to_style;
                }
            } else {
                elements = this.$el.find(selector);
            }
            return elements;
        },
    });

    IPython.WidgetModel = WidgetModel;
    IPython.WidgetView = WidgetView;
    IPython.DOMWidgetView = DOMWidgetView;

    // Pass through WidgetManager namespace.
    return WidgetManager;
});
<|endoftext|>


<commit_before>var dns       = require('dns'),
    net       = require('net'),
    utils     = require('./utils'),
    net_utils = require('./net_utils');

exports.register = function () {
    var plugin = this;
    plugin.load_fcrdns_ini();
};

exports.load_fcrdns_ini = function () {
    var plugin = this;
    plugin.cfg = plugin.config.get('connect.fcrdns.ini', {
        booleans: [
            '-reject.no_rdns',
            '-reject.no_fcrdns',
            '-reject.invalid_tld',
            '-reject.generic_rdns',
        ]
    }, function () {
        plugin.load_fcrdns_ini();
    });
};

exports.hook_lookup_rdns = function (next, connection) {
    var plugin = this;

    // always init, so results.get is deterministic
    connection.results.add(plugin, {
        fcrdns: [],               // PTR host names that resolve to this IP
        invalid_tlds: [],         // rDNS names with invalid TLDs
        other_ips: [],            // IPs from names that didn't match
        ptr_names: [],            // Array of host names from PTR query
        ptr_multidomain: false,   // Multiple host names in different domains
        has_rdns: false,          // does IP have PTR records?
        ptr_name_has_ips: false,  // PTR host has IP address(es)
        ptr_name_to_ip: {},       // host names and their IP addresses
    });

    var rip = connection.remote_ip;
    if (net_utils.is_private_ip(rip)) {
        connection.results.add(plugin, {skip: "private_ip"});
        return next();
    }

    plugin.refresh_config(connection);

    var called_next = 0;
    var timer;
    var do_next = function (code, msg) {
        if (called_next) return;
        called_next++;
        clearTimeout(timer);
        return next(code, msg);
    };

    // Set-up timer
    timer = setTimeout(function () {
        connection.results.add(plugin, {err: 'timeout', emit: true});
        if (plugin.cfg.reject.no_rdns) {
            return do_next(DENYSOFT, 'client [' + rip + '] rDNS lookup timeout');
        }
        return do_next();
    }, (plugin.cfg.main.timeout || 30) * 1000);

    dns.reverse(rip, function (err, ptr_names) {
        connection.logdebug(plugin, 'rdns lookup: ' + rip);
        if (err) return plugin.handle_ptr_error(connection, err, do_next);

        connection.results.add(plugin, {ptr_names: ptr_names});
        connection.results.add(plugin, {has_rdns: true});

        // Fetch A records for each PTR host name
        var pending_queries = 0;
        var queries_run = false;
        var results = {};
        for (var i=0; i<ptr_names.length; i++) {
            var ptr_domain = ptr_names[i].toLowerCase();
            results[ptr_domain] = [];

            // Make sure TLD is valid
            if (!net_utils.get_organizational_domain(ptr_domain)) {
                connection.results.add(plugin, {fail: 'valid_tld(' + ptr_domain +')'});
                if (!plugin.cfg.reject.invalid_tld) continue;
                if (net_utils.is_private_ip(rip)) continue;
                return do_next(DENY, 'client [' + rip +
                        '] rejected; invalid TLD in rDNS (' + ptr_domain + ')');
            }

            queries_run = true;
            connection.logdebug(plugin, 'domain: ' + ptr_domain);
            pending_queries++;
            (function (ptr_domain) {  /* BEGIN BLOCK SCOPE */
            dns.resolve(ptr_domain, function(err, ips_from_fwd) {
                pending_queries--;
                if (err) {
                    plugin.handle_a_error(connection, err, ptr_domain);
                }
                else {
                    connection.logdebug(plugin, ptr_domain + ' => ' + ips_from_fwd);
                    results[ptr_domain] = ips_from_fwd;
                }
                if (pending_queries > 0) return;

                // Got all DNS results
                connection.results.add(plugin, {ptr_name_to_ip: results});
                return plugin.check_fcrdns(connection, results, do_next);
            });
            })(ptr_domain); /* END BLOCK SCOPE */
        }

        // No valid PTR
        if (!queries_run || (queries_run && pending_queries === 0)) {
            return do_next();
        }
    });
};

exports.hook_data_post = function (next, connection) {
    var plugin = this;
    var txn = connection.transaction;
    txn.remove_header('X-Haraka-rDNS');
    txn.remove_header('X-Haraka-FCrDNS');
    txn.remove_header('X-Haraka-rDNS-OtherIPs');
    txn.remove_header('X-Haraka-HostID');

    var fcrdns = connection.results.get('connect.fcrdns');
    if (!fcrdns) {
        connection.results.add(plugin, {err: "no fcrdns results!?"});
        return next();
    }

    if (fcrdns.name && fcrdns.name.length) {
        txn.add_header('X-Haraka-rDNS', fcrdns.name.join(' '));
    }
    if (fcrdns.fcrdns && fcrdns.fcrdns.length) {
        txn.add_header('X-Haraka-FCrDNS', fcrdns.fcrdns.join(' '));
    }
    if (fcrdns.other_ips && fcrdns.other_ips.length) {
        txn.add_header('X-Haraka-rDNS-OtherIPs', fcrdns.other_ips.join(' '));
    }
    return next();
};

exports.handle_a_error = function(connection, err, domain) {
    var plugin = this;

    switch (err.code) {
        case 'ENOTFOUND':
        case dns.NOTFOUND:
        case dns.NXDOMAIN:
            connection.results.add(plugin, {fail: 'ptr_valid('+domain+')' });
            break;
        default:
            connection.results.add(plugin, {err: err});
    }
};

exports.handle_ptr_error = function(connection, err, do_next) {
    var plugin = this;
    var rip = connection.remote_ip;

    switch (err.code) {
        case 'ENOTFOUND':
        case dns.NOTFOUND:
        case dns.NXDOMAIN:
            connection.results.add(plugin, {fail: 'has_rdns', emit: true});
            if (plugin.cfg.reject.no_rdns) {
                return do_next(DENY, 'client [' + rip + '] rejected; no rDNS');
            }
            return do_next();
        default:
            connection.results.add(plugin, {err: err.code});
            if (plugin.cfg.reject.no_rdns) {
                return do_next(DENYSOFT, 'client [' + rip + '] rDNS lookup error (' + err + ')');
            }
            return do_next();
    }
};

exports.check_fcrdns = function(connection, results, do_next) {
    var plugin = this;

    for (var fdom in results) {    // mail.example.com
        if (!fdom) continue;
        var org_domain = net_utils.get_organizational_domain(fdom); // example.com

        // Multiple domains?
        if (last_domain && last_domain !== org_domain) {
            connection.results.add(plugin, {ptr_multidomain: true});
        }
        else {
            var last_domain = org_domain;
        }

        // FCrDNS? PTR -> (A | AAAA) 3. PTR comparison
        plugin.ptr_compare(results[fdom], connection, fdom);

        connection.results.add(plugin, {ptr_name_has_ips: true});

        if (plugin.is_generic_rdns(connection, fdom) &&
            plugin.cfg.reject.generic_rdns) {
            return do_next(DENY, 'client ' + fdom + ' [' + connection.remote_ip +
                '] rejected; generic rDNS, please use your ISPs SMTP relay');
        }
    }

    plugin.log_summary(connection);
    plugin.save_auth_results(connection);

    var r = connection.results.get('connect.fcrdns');
    if (!r.fcrdns.length && plugin.cfg.reject.no_fcrdns) {
        return do_next(DENY, 'Sorry, no FCrDNS match found');
    }
    return do_next();
};

exports.ptr_compare = function (ip_list, connection, domain) {
    var plugin = this;
    if (!ip_list) return false;
    if (!ip_list.length) return false;

    if (ip_list.indexOf(connection.remote_ip) !== -1) {
        connection.results.add(plugin, {pass: 'fcrdns' });
        connection.results.push(plugin, {fcrdns: domain});
        return true;
    }
    if (net_utils.same_ipv4_network(connection.remote_ip, ip_list)) {
        connection.results.add(plugin, {pass: 'fcrdns(net)' });
        connection.results.push(plugin, {fcrdns: domain});
        return true;
    }
    for (var j=0; j<ip_list.length; j++) {
        connection.results.push(plugin, {other_ips: ip_list[j]});
    }
    return false;
};

exports.save_auth_results = function (connection) {
    var r = connection.results.get('connect.fcrdns');
    if (!r) return;
    if (r.fcrdns && r.fcrdns.length) {
        connection.auth_results('iprev=pass');
        return true;
    }
    if (!r.has_rdns) {
        connection.auth_results('iprev=permerror');
        return false;
    }
    if (r.err.length) {
        connection.auth_results('iprev=temperror');
        return false;
    }
    connection.auth_results('iprev=fail');
    return false;
};

exports.is_generic_rdns = function (connection, domain) {
    var plugin = this;
    // IP in rDNS? (Generic rDNS)
    if (!domain) return false;

    if (!net_utils.is_ip_in_str(connection.remote_ip, domain)) {
        connection.results.add(plugin, {pass: 'is_generic_rdns'});
        return false;
    }

    connection.results.add(plugin, {fail: 'is_generic_rdns'});

    var orgDom = net_utils.get_organizational_domain(domain);
    if (!orgDom) {
        connection.loginfo(this, 'no org domain for: ' + domain);
        return false;
    }

    var host_part = domain.split('.').slice(0,orgDom.split('.').length+1);
    if (/(?:static|business)/.test(host_part)) {
        // Allow some obvious generic but static ranges
        // EHLO/HELO checks will still catch out hosts that use generic rDNS there
        connection.loginfo(this, 'allowing generic static rDNS');
        return false;
    }

    return true;
};

exports.log_summary = function (connection) {
    if (!connection) return;   // connection went away
    var note = connection.results.get('connect.fcrdns');
    if (!note) return;

    connection.loginfo(this,
        ['ip=' + connection.remote_ip,
        'rdns="' + ((note.ptr_names.length > 2) ? note.ptr_names.slice(0,2).join(',') + '...' : note.ptr_names.join(',')) + '"',
        'rdns_len=' + note.ptr_names.length,
        'fcrdns="' + ((note.fcrdns.length > 2) ? note.fcrdns.slice(0,2).join(',') + '...' : note.fcrdns.join(',')) + '"',
        'fcrdns_len=' + note.fcrdns.length,
        'other_ips_len=' + note.other_ips.length,
        'invalid_tlds=' + note.invalid_tlds.length,
        'generic_rdns=' + ((note.ptr_name_has_ips) ? 'true' : 'false'),
        ].join(' '));
};

exports.refresh_config = function (connection) {
    var plugin = this;
    // allow rdns_acccess whitelist to override
    if (connection.notes.rdns_access && connection.notes.rdns_access === 'white') {
        plugin.cfg.reject.no_rdns = 0;
        plugin.cfg.reject.invalid_tld = 0;
        plugin.cfg.reject.generic_rdns = 0;
    }

    return plugin.cfg;
};
<commit_msg>fcrdns: better error message to results<commit_after>var dns       = require('dns'),
    net       = require('net'),
    utils     = require('./utils'),
    net_utils = require('./net_utils');

exports.register = function () {
    var plugin = this;
    plugin.load_fcrdns_ini();
};

exports.load_fcrdns_ini = function () {
    var plugin = this;
    plugin.cfg = plugin.config.get('connect.fcrdns.ini', {
        booleans: [
            '-reject.no_rdns',
            '-reject.no_fcrdns',
            '-reject.invalid_tld',
            '-reject.generic_rdns',
        ]
    }, function () {
        plugin.load_fcrdns_ini();
    });
};

exports.hook_lookup_rdns = function (next, connection) {
    var plugin = this;

    // always init, so results.get is deterministic
    connection.results.add(plugin, {
        fcrdns: [],               // PTR host names that resolve to this IP
        invalid_tlds: [],         // rDNS names with invalid TLDs
        other_ips: [],            // IPs from names that didn't match
        ptr_names: [],            // Array of host names from PTR query
        ptr_multidomain: false,   // Multiple host names in different domains
        has_rdns: false,          // does IP have PTR records?
        ptr_name_has_ips: false,  // PTR host has IP address(es)
        ptr_name_to_ip: {},       // host names and their IP addresses
    });

    var rip = connection.remote_ip;
    if (net_utils.is_private_ip(rip)) {
        connection.results.add(plugin, {skip: "private_ip"});
        return next();
    }

    plugin.refresh_config(connection);

    var called_next = 0;
    var timer;
    var do_next = function (code, msg) {
        if (called_next) return;
        called_next++;
        clearTimeout(timer);
        return next(code, msg);
    };

    // Set-up timer
    timer = setTimeout(function () {
        connection.results.add(plugin, {err: 'timeout', emit: true});
        if (plugin.cfg.reject.no_rdns) {
            return do_next(DENYSOFT, 'client [' + rip + '] rDNS lookup timeout');
        }
        return do_next();
    }, (plugin.cfg.main.timeout || 30) * 1000);

    dns.reverse(rip, function (err, ptr_names) {
        connection.logdebug(plugin, 'rdns lookup: ' + rip);
        if (err) return plugin.handle_ptr_error(connection, err, do_next);

        connection.results.add(plugin, {ptr_names: ptr_names});
        connection.results.add(plugin, {has_rdns: true});

        // Fetch A records for each PTR host name
        var pending_queries = 0;
        var queries_run = false;
        var results = {};
        for (var i=0; i<ptr_names.length; i++) {
            var ptr_domain = ptr_names[i].toLowerCase();
            results[ptr_domain] = [];

            // Make sure TLD is valid
            if (!net_utils.get_organizational_domain(ptr_domain)) {
                connection.results.add(plugin, {fail: 'valid_tld(' + ptr_domain +')'});
                if (!plugin.cfg.reject.invalid_tld) continue;
                if (net_utils.is_private_ip(rip)) continue;
                return do_next(DENY, 'client [' + rip +
                        '] rejected; invalid TLD in rDNS (' + ptr_domain + ')');
            }

            queries_run = true;
            connection.logdebug(plugin, 'domain: ' + ptr_domain);
            pending_queries++;
            (function (ptr_domain) {  /* BEGIN BLOCK SCOPE */
            dns.resolve(ptr_domain, function(err, ips_from_fwd) {
                pending_queries--;
                if (err) {
                    plugin.handle_a_error(connection, err, ptr_domain);
                }
                else {
                    connection.logdebug(plugin, ptr_domain + ' => ' + ips_from_fwd);
                    results[ptr_domain] = ips_from_fwd;
                }
                if (pending_queries > 0) return;

                // Got all DNS results
                connection.results.add(plugin, {ptr_name_to_ip: results});
                return plugin.check_fcrdns(connection, results, do_next);
            });
            })(ptr_domain); /* END BLOCK SCOPE */
        }

        // No valid PTR
        if (!queries_run || (queries_run && pending_queries === 0)) {
            return do_next();
        }
    });
};

exports.hook_data_post = function (next, connection) {
    var plugin = this;
    var txn = connection.transaction;
    txn.remove_header('X-Haraka-rDNS');
    txn.remove_header('X-Haraka-FCrDNS');
    txn.remove_header('X-Haraka-rDNS-OtherIPs');
    txn.remove_header('X-Haraka-HostID');

    var fcrdns = connection.results.get('connect.fcrdns');
    if (!fcrdns) {
        connection.results.add(plugin, {err: "no fcrdns results!?"});
        return next();
    }

    if (fcrdns.name && fcrdns.name.length) {
        txn.add_header('X-Haraka-rDNS', fcrdns.name.join(' '));
    }
    if (fcrdns.fcrdns && fcrdns.fcrdns.length) {
        txn.add_header('X-Haraka-FCrDNS', fcrdns.fcrdns.join(' '));
    }
    if (fcrdns.other_ips && fcrdns.other_ips.length) {
        txn.add_header('X-Haraka-rDNS-OtherIPs', fcrdns.other_ips.join(' '));
    }
    return next();
};

exports.handle_a_error = function(connection, err, domain) {
    var plugin = this;

    switch (err.code) {
        case 'ENOTFOUND':
        case 'NXDOMAIN':
        case dns.NOTFOUND:
        case dns.NXDOMAIN:
            connection.results.add(plugin, {fail: 'ptr_valid('+domain+')' });
            break;
        default:
            connection.results.add(plugin, {err: err.message});
    }
};

exports.handle_ptr_error = function(connection, err, do_next) {
    var plugin = this;
    var rip = connection.remote_ip;

    switch (err.code) {
        case 'ENOTFOUND':
        case dns.NOTFOUND:
        case dns.NXDOMAIN:
            connection.results.add(plugin, {fail: 'has_rdns', emit: true});
            if (plugin.cfg.reject.no_rdns) {
                return do_next(DENY, 'client [' + rip + '] rejected; no rDNS');
            }
            return do_next();
        default:
            connection.results.add(plugin, {err: err.code});
            if (plugin.cfg.reject.no_rdns) {
                return do_next(DENYSOFT, 'client [' + rip + '] rDNS lookup error (' + err + ')');
            }
            return do_next();
    }
};

exports.check_fcrdns = function(connection, results, do_next) {
    var plugin = this;

    for (var fdom in results) {    // mail.example.com
        if (!fdom) continue;
        var org_domain = net_utils.get_organizational_domain(fdom); // example.com

        // Multiple domains?
        if (last_domain && last_domain !== org_domain) {
            connection.results.add(plugin, {ptr_multidomain: true});
        }
        else {
            var last_domain = org_domain;
        }

        // FCrDNS? PTR -> (A | AAAA) 3. PTR comparison
        plugin.ptr_compare(results[fdom], connection, fdom);

        connection.results.add(plugin, {ptr_name_has_ips: true});

        if (plugin.is_generic_rdns(connection, fdom) &&
            plugin.cfg.reject.generic_rdns) {
            return do_next(DENY, 'client ' + fdom + ' [' + connection.remote_ip +
                '] rejected; generic rDNS, please use your ISPs SMTP relay');
        }
    }

    plugin.log_summary(connection);
    plugin.save_auth_results(connection);

    var r = connection.results.get('connect.fcrdns');
    if (!r.fcrdns.length && plugin.cfg.reject.no_fcrdns) {
        return do_next(DENY, 'Sorry, no FCrDNS match found');
    }
    return do_next();
};

exports.ptr_compare = function (ip_list, connection, domain) {
    var plugin = this;
    if (!ip_list) return false;
    if (!ip_list.length) return false;

    if (ip_list.indexOf(connection.remote_ip) !== -1) {
        connection.results.add(plugin, {pass: 'fcrdns' });
        connection.results.push(plugin, {fcrdns: domain});
        return true;
    }
    if (net_utils.same_ipv4_network(connection.remote_ip, ip_list)) {
        connection.results.add(plugin, {pass: 'fcrdns(net)' });
        connection.results.push(plugin, {fcrdns: domain});
        return true;
    }
    for (var j=0; j<ip_list.length; j++) {
        connection.results.push(plugin, {other_ips: ip_list[j]});
    }
    return false;
};

exports.save_auth_results = function (connection) {
    var r = connection.results.get('connect.fcrdns');
    if (!r) return;
    if (r.fcrdns && r.fcrdns.length) {
        connection.auth_results('iprev=pass');
        return true;
    }
    if (!r.has_rdns) {
        connection.auth_results('iprev=permerror');
        return false;
    }
    if (r.err.length) {
        connection.auth_results('iprev=temperror');
        return false;
    }
    connection.auth_results('iprev=fail');
    return false;
};

exports.is_generic_rdns = function (connection, domain) {
    var plugin = this;
    // IP in rDNS? (Generic rDNS)
    if (!domain) return false;

    if (!net_utils.is_ip_in_str(connection.remote_ip, domain)) {
        connection.results.add(plugin, {pass: 'is_generic_rdns'});
        return false;
    }

    connection.results.add(plugin, {fail: 'is_generic_rdns'});

    var orgDom = net_utils.get_organizational_domain(domain);
    if (!orgDom) {
        connection.loginfo(this, 'no org domain for: ' + domain);
        return false;
    }

    var host_part = domain.split('.').slice(0,orgDom.split('.').length+1);
    if (/(?:static|business)/.test(host_part)) {
        // Allow some obvious generic but static ranges
        // EHLO/HELO checks will still catch out hosts that use generic rDNS there
        connection.loginfo(this, 'allowing generic static rDNS');
        return false;
    }

    return true;
};

exports.log_summary = function (connection) {
    if (!connection) return;   // connection went away
    var note = connection.results.get('connect.fcrdns');
    if (!note) return;

    connection.loginfo(this,
        ['ip=' + connection.remote_ip,
        'rdns="' + ((note.ptr_names.length > 2) ? note.ptr_names.slice(0,2).join(',') + '...' : note.ptr_names.join(',')) + '"',
        'rdns_len=' + note.ptr_names.length,
        'fcrdns="' + ((note.fcrdns.length > 2) ? note.fcrdns.slice(0,2).join(',') + '...' : note.fcrdns.join(',')) + '"',
        'fcrdns_len=' + note.fcrdns.length,
        'other_ips_len=' + note.other_ips.length,
        'invalid_tlds=' + note.invalid_tlds.length,
        'generic_rdns=' + ((note.ptr_name_has_ips) ? 'true' : 'false'),
        ].join(' '));
};

exports.refresh_config = function (connection) {
    var plugin = this;
    // allow rdns_acccess whitelist to override
    if (connection.notes.rdns_access && connection.notes.rdns_access === 'white') {
        plugin.cfg.reject.no_rdns = 0;
        plugin.cfg.reject.invalid_tld = 0;
        plugin.cfg.reject.generic_rdns = 0;
    }

    return plugin.cfg;
};
<|endoftext|>


<commit_before>"use strict";

class HomeController {
  constructor() {}
}

const HOME_CTRL = angular
  .module("home.controller", [])
  .controller("HomeController", HomeController);

export { HOME_CTRL };
<commit_msg>Rename module home.controller -> home.module. Refactoring. Added component<commit_after>"use strict";

class HomeController {
  constructor() {}
}

const homeComponent = {
  template: require("../views/home.html"),
  controller: HomeController
};

const HOME_MODULE = angular
  .module("home.module", [])
  .component("homeComponent", homeComponent);

export { HOME_MODULE };
<|endoftext|>


<commit_before>exports.config = {
    baseUrl: 'http://localhost:8000/',
    framework: 'jasmine',
    specs: 'e2e/**/*.test.js',
    capabilities: {
        browserName: 'phantomjs',
        shardTestFiles: true,
        maxInstances: 4,
        'phantomjs.binary.path': './node_modules/phantomjs-prebuilt/bin/phantomjs'
    },
    seleniumServerJar: 'node_modules/protractor/node_modules/webdriver-manager/selenium/selenium-server-standalone-3.4.0.jar',
    chromeDriver: './node_modules/protractor/node_modules/webdriver-manager/selenium/chromedriver_2.29',
    onPrepare: function () {
        browser.driver.manage().window().setSize(1024, 768);

        global.dp = require('./e2e/helpers/datapunt');

        // dp.navigate requires that other helpers are already loaded, just making sure the others are initialized first
        global.dp.navigate = require('./e2e/helpers/navigate');
    }
};
<commit_msg>Disable E2E tests temporarily<commit_after>exports.config = {
    baseUrl: 'http://localhost:8000/',
    framework: 'jasmine',
    specs: 'e2e/**/*.disabled.js',
    capabilities: {
        browserName: 'phantomjs',
        shardTestFiles: true,
        maxInstances: 4,
        'phantomjs.binary.path': './node_modules/phantomjs-prebuilt/bin/phantomjs'
    },
    seleniumServerJar: 'node_modules/protractor/node_modules/webdriver-manager/selenium/selenium-server-standalone-3.4.0.jar',
    chromeDriver: './node_modules/protractor/node_modules/webdriver-manager/selenium/chromedriver_2.29',
    onPrepare: function () {
        browser.driver.manage().window().setSize(1024, 768);

        global.dp = require('./e2e/helpers/datapunt');

        // dp.navigate requires that other helpers are already loaded, just making sure the others are initialized first
        global.dp.navigate = require('./e2e/helpers/navigate');
    }
};
<|endoftext|>


<commit_before>/**
@ngdoc directive
@name umbraco.directives.directive:umbGenerateAlias
@restrict E
@scope

@description
Use this directive to generate a camelCased umbraco alias.
When the aliasFrom value is changed the directive will get a formatted alias from the server and update the alias model. If "enableLock" is set to true
the directive will use {@link umbraco.directives.directive:umbLockedField umbLockedField} to lock and unlock the alias.

Markup example

        <input type="text" ng-model="vm.name" />

        <umb-generate-alias
            enable-lock="true"
            alias-from="vm.name"
            alias="vm.alias">
        </umb-generate-alias>

Controller example

    (function () {
        "use strict";

        function Controller() {

            var vm = this;

            vm.name = "";
            vm.alias = "";

        }

        angular.module("umbraco").controller("My.Controller", Controller);
    })();

@param {string} alias (binding): The model where the alias is bound.
@param {string} aliasFrom (binding): The model to generate the alias from.
@param {boolean=} enableLock (binding): Set to true to add a lock next to the alias from where it can be unlocked and changed.
**/

angular.module("umbraco.directives")
    .directive('umbGenerateAlias', function ($timeout, entityResource, localizationService) {
        return {
            restrict: 'E',
            templateUrl: 'views/components/umb-generate-alias.html',
            replace: true,
            scope: {
                alias: '=',
                aliasFrom: '=',
                enableLock: '=?',
                serverValidationField: '@'
            },
            link: function (scope, element, attrs, ctrl) {

                var eventBindings = [];
                var bindWatcher = true;
                var generateAliasTimeout = "";
                var updateAlias = false;

                scope.locked = true;

                scope.labels = {
                    idle: "Enter alias...",
                    busy: "Generating alias..."
                };

                scope.placeholderText = scope.labels.idle;

                localizationService.localize('placeholders_enterAlias').then(function (value) {
                    scope.labels.idle = scope.placeholderText = value;
                });

                localizationService.localize('placeholders_generatingAlias').then(function (value) {
                    scope.labels.busy = value;
                });

                function generateAlias(value) {

                  if (generateAliasTimeout) {
                    $timeout.cancel(generateAliasTimeout);
                  }

                  if( value !== undefined && value !== "" && value !== null) {

                      scope.alias = "";
                    scope.placeholderText = scope.labels.busy;

                    generateAliasTimeout = $timeout(function () {
                       updateAlias = true;
                        entityResource.getSafeAlias(value, true).then(function (safeAlias) {
                            if (updateAlias) {
                              scope.alias = safeAlias.alias;
                           }
                      });
                    }, 500);

                  } else {
                    updateAlias = true;
                    scope.alias = "";
                    scope.placeholderText = scope.labels.idle;
                  }

                }

                // if alias gets unlocked - stop watching alias
                eventBindings.push(scope.$watch('locked', function(newValue, oldValue){
                    if(newValue === false) {
                       bindWatcher = false;
                    }
                }));

                // validate custom entered alias
                eventBindings.push(scope.$watch('alias', function(newValue, oldValue){

                  if(scope.alias === "" && bindWatcher === true || scope.alias === null && bindWatcher === true) {
                    // add watcher
                    eventBindings.push(scope.$watch('aliasFrom', function(newValue, oldValue) {
                       if(bindWatcher) {
                          generateAlias(newValue);
                       }
                    }));
                  }

               }));

               // clean up
               scope.$on('$destroy', function(){
                 // unbind watchers
                 for(var e in eventBindings) {
                   eventBindings[e]();
                  }
               });

            }
        };
    });
<commit_msg>Fix placeholder text when empty alias input after generating alias (#4032)<commit_after>/**
@ngdoc directive
@name umbraco.directives.directive:umbGenerateAlias
@restrict E
@scope

@description
Use this directive to generate a camelCased umbraco alias.
When the aliasFrom value is changed the directive will get a formatted alias from the server and update the alias model. If "enableLock" is set to true
the directive will use {@link umbraco.directives.directive:umbLockedField umbLockedField} to lock and unlock the alias.

Markup example

        <input type="text" ng-model="vm.name" />

        <umb-generate-alias
            enable-lock="true"
            alias-from="vm.name"
            alias="vm.alias">
        </umb-generate-alias>

Controller example

    (function () {
        "use strict";

        function Controller() {

            var vm = this;

            vm.name = "";
            vm.alias = "";

        }

        angular.module("umbraco").controller("My.Controller", Controller);
    })();

@param {string} alias (binding): The model where the alias is bound.
@param {string} aliasFrom (binding): The model to generate the alias from.
@param {boolean=} enableLock (binding): Set to true to add a lock next to the alias from where it can be unlocked and changed.
**/

angular.module("umbraco.directives")
    .directive('umbGenerateAlias', function ($timeout, entityResource, localizationService) {
        return {
            restrict: 'E',
            templateUrl: 'views/components/umb-generate-alias.html',
            replace: true,
            scope: {
                alias: '=',
                aliasFrom: '=',
                enableLock: '=?',
                serverValidationField: '@'
            },
            link: function (scope, element, attrs, ctrl) {

                var eventBindings = [];
                var bindWatcher = true;
                var generateAliasTimeout = "";
                var updateAlias = false;

                scope.locked = true;

                scope.labels = {
                    idle: "Enter alias...",
                    busy: "Generating alias..."
                };

                scope.placeholderText = scope.labels.idle;

                localizationService.localize('placeholders_enterAlias').then(function (value) {
                    scope.labels.idle = scope.placeholderText = value;
                });

                localizationService.localize('placeholders_generatingAlias').then(function (value) {
                    scope.labels.busy = value;
                });

                function generateAlias(value) {

                  if (generateAliasTimeout) {
                     $timeout.cancel(generateAliasTimeout);
                  }

                  if (value !== undefined && value !== "" && value !== null) {

                    scope.alias = "";
                    scope.placeholderText = scope.labels.busy;

                    generateAliasTimeout = $timeout(function () {
                       updateAlias = true;
                        entityResource.getSafeAlias(value, true).then(function (safeAlias) {
                            if (updateAlias) {
                                scope.alias = safeAlias.alias;
                            }
                            scope.placeholderText = scope.labels.idle;
                      });
                    }, 500);

                  } else {
                    updateAlias = true;
                    scope.alias = "";
                    scope.placeholderText = scope.labels.idle;
                  }
                }

                // if alias gets unlocked - stop watching alias
                eventBindings.push(scope.$watch('locked', function(newValue, oldValue){
                    if(newValue === false) {
                       bindWatcher = false;
                    }
                }));

                // validate custom entered alias
                eventBindings.push(scope.$watch('alias', function (newValue, oldValue) {
                    if (scope.alias === "" || scope.alias === null || scope.alias === undefined) {
                        if (bindWatcher === true) {
                            // add watcher
                            eventBindings.push(scope.$watch('aliasFrom', function (newValue, oldValue) {
                                if (bindWatcher) {
                                    generateAlias(newValue);
                                }
                            }));
                        }
                    }
               }));

               // clean up
               scope.$on('$destroy', function(){
                 // unbind watchers
                 for(var e in eventBindings) {
                   eventBindings[e]();
                  }
               });

            }
        };
    });
<|endoftext|>


<commit_before>var AdminData = AdminData || {};

AdminData.advanceSearch = {

	buildFirstRow: function() {

		var img = $('<img />', {
			src: 'https://github.com/neerajdotname/admin_data/raw/rails3_gem/public/images/add.png'
		});

		$('#advance_search_table').append(this.buildRow()).find('tr td:last a').removeClass('remove_row').addClass('add_row_link').html('').append(img);
	},

	buildCol1: function() {
		var i, col = $('<select />', {
			className: 'col1'
		}).append($('<option />')),
		tableStructure = $('#advance_search_table').data('table_structure');

		for (i in tableStructure) {
			$('<option />', {
				text: i,
				value: i
			}).appendTo(col);
		}
		return $('<td />').append(col);
	},

	buildCol2: function() {
		var select = $('<select />', {
			className: 'col2'
		});
		return $('<td />').append(select);
	},

	buildCol3: function() {
		return $('<td />').append($('<input />', {
			className: 'col3'
		}));
	},

	buildCol4: function() {
		var img = $('<img />', {
			src: 'https://github.com/neerajdotname/admin_data/raw/rails3_gem/public/images/no.png'
		});

		return $('<td />').append($('<a />', {
			text: '',
			href: '#',
			className: 'remove_row'
		}).append(img));
	},

	buildRow: function() {

		var $tr = $('<tr />'),
		currentRowNumber = $(document).data('currentRowNumber'),
		that = this,
		build_array = ['buildCol1', 'buildCol2', 'buildCol3', 'buildCol4'];

		if (currentRowNumber === undefined) {
			currentRowNumber = 1;
			$(document).data('currentRowNumber', currentRowNumber)
		} else {
			currentRowNumber = parseInt(currentRowNumber) + 1;
			$(document).data('currentRowNumber', currentRowNumber)
		}

		$.each(build_array, function(index, value) {
			$tr.append(that[value]());
		});

		$tr.find('select.col1').attr({
			name: 'adv_search[' + currentRowNumber + '_row][col1]'
		});
		$tr.find('select.col2').attr({
			name: 'adv_search[' + currentRowNumber + '_row][col2]'
		});
		$tr.find('input.col3').attr({
			name: 'adv_search[' + currentRowNumber + '_row][col3]'
		});

		return $tr;
	}

};

<commit_msg>add id to add link; add id to remove link<commit_after>var AdminData = AdminData || {};

AdminData.advanceSearch = {

	buildFirstRow: function() {

		var img = $('<img />', {
			src: 'https://github.com/neerajdotname/admin_data/raw/rails3_gem/public/images/add.png'
		});

		$('#advance_search_table').append(this.buildRow()).find('tr td:last a').attr('id','add_row_link_1').removeClass('remove_row').addClass('add_row_link').html('').append(img);
	},

	buildCol1: function() {
		var i, col = $('<select />', {
			className: 'col1'
		}).append($('<option />')),
		tableStructure = $('#advance_search_table').data('table_structure');

		for (i in tableStructure) {
			$('<option />', {
				text: i,
				value: i
			}).appendTo(col);
		}
		return $('<td />').append(col);
	},

	buildCol2: function() {
		var select = $('<select />', {
			className: 'col2'
		});
		return $('<td />').append(select);
	},

	buildCol3: function() {
		return $('<td />').append($('<input />', {
			className: 'col3'
		}));
	},

	buildCol4: function() {
		var img = $('<img />', {
			src: 'https://github.com/neerajdotname/admin_data/raw/rails3_gem/public/images/no.png'
		});

		return $('<td />').append($('<a />', {
			text: '',
			href: '#',
			className: 'remove_row'
		}).append(img));
	},

	buildRow: function() {

		var $tr = $('<tr />'),
		currentRowNumber = $(document).data('currentRowNumber'),
		that = this,
		build_array = ['buildCol1', 'buildCol2', 'buildCol3', 'buildCol4'];

		if (currentRowNumber === undefined) {
			currentRowNumber = 1;
			$(document).data('currentRowNumber', currentRowNumber)
		} else {
			currentRowNumber = parseInt(currentRowNumber) + 1;
			$(document).data('currentRowNumber', currentRowNumber)
		}

		$.each(build_array, function(index, value) {
			$tr.append(that[value]());
		});

		$tr.find('select.col1').attr({
			name: 'adv_search[' + currentRowNumber + '_row][col1]'
		});
		$tr.find('select.col2').attr({
			name: 'adv_search[' + currentRowNumber + '_row][col2]'
		});
		$tr.find('input.col3').attr({
			name: 'adv_search[' + currentRowNumber + '_row][col3]'
		});

    $tr.find('.remove_row').attr('id', 'remove_row_'+currentRowNumber);

		return $tr;
	}

};

<|endoftext|>


<commit_before>document.write('Everything is ok');
<commit_msg>Required react and reactDOM<commit_after>var React = require('react');
var ReactDOM = require('react-dom');
<|endoftext|>