<commit_before>var core                     = require("../level1/core").dom.level1.core,
    INVALID_STATE_ERR        = core.INVALID_STATE_ERR        = 11,
    SYNTAX_ERR               = core.SYNTAX_ERR               = 12,
    INVALID_MODIFICATION_ERR = core.INVALID_MODIFICATION_ERR = 13,
    NAMESPACE_ERR            = core.NAMESPACE_ERR            = 14,
    INVALID_ACCESS_ERR       = core.INVALID_ACCESS_ERR       = 15,
    ns = {
      validate : function(namespace, namespaceURI) {
        if (!namespace) {
          throw new core.DOMException(core.INVALID_CHARACTER_ERR, "namespace is undefined");
        }
        if(namespace.match(/[^0-9a-z\.:\-_]/i) !== null) {
          throw new core.DOMException(core.INVALID_CHARACTER_ERR, namespace);
        }
        if ((namespace === 'xmlns' && namespaceURI !== "http://www.w3.org/2000/xmlns/")        ||
            (namespace === "xml"   && namespaceURI !== "http://www.w3.org/XML/1998/namespace") ||
            namespace.indexOf('::') > -1                                                ||
            namespace[namespace.length-1] === ':'                                       ||
            namespace[0] === ':'                                                        ||
            namespace.match(/.+:.+:/))
        {
          throw new core.DOMException(NAMESPACE_ERR);
        }
      }
    };

core.DOMImplementation.prototype.createDocumentType = function(/* String */ qualifiedName,
                                                               /* String */ publicId,
                                                               /* String */ systemId)
{
  ns.validate(qualifiedName);
  var doctype = new core.DocumentType(null, qualifiedName);
  doctype._publicId = publicId ? publicId : '';
  doctype._systemId = systemId ? systemId : '';
  return doctype;
};

/**
  Creates an XML Document object of the specified type with its document element.
  HTML-only DOM implementations do not need to implement this method.
*/
core.DOMImplementation.prototype.createDocument = function(/* String */       namespaceURI,
                                                           /* String */       qualifiedName,
                                                           /* DocumentType */ doctype)
{
  ns.validate(qualifiedName, namespaceURI);

  if (doctype && doctype.ownerDocuemnt !== null) {
    throw new core.DOMException(core.WRONG_DOCUMENT_ERR);
  }

  var document = new core.Document();
  document.namespaceURI = namespaceURI;
  document.qualifiedName = qualifiedName;
  document.doctype = doctype;
  document._ownerDocument = document;
  return document;
};

core.Node.prototype.__defineGetter__("ownerDocument", function() {
  return this._ownerDocument || null;
});

core.Node.prototype.isSupported = function(/* string */ feature,
                                           /* string */ version)
{
  return this._ownerDocument.implementation.hasFeature(feature, version);
};

core.Node.prototype._namespaceURI = null;
core.Node.prototype.__defineGetter__("namespaceURI", function() {
  return this._namespaceURI || null;
});

core.Node.prototype.__defineSetter__("namespaceURI", function(value) {
  this._namespaceURI = value;
});

core.Node.prototype.__defineGetter__("prefix", function() {
  return this._prefix || null;
});

core.Node.prototype.__defineSetter__("prefix", function(value) {
  if (this._prefix === "xmlns") {
    throw new core.DOMException(core.NAMESPACE_ERR);
  }
  ns.validate(value, this._namespaceURI);

  this._prefix = value;
});

core.Node.prototype.__defineGetter__("localName", function() {
  return this._localName || null;
});

/* return boolean */
core.Node.prototype.hasAttributes = function() {
  return (this._attributes && this._attributes.length > 0);
};

core.NamedNodeMap.prototype.getNamedItemNS = function(/* string */ namespaceURI,
                                                      /* string */ localName)
{
  var defaultNode = null;
  return this._map(function(item) {

    if (namespaceURI === item.namespaceURI)
    {
      if (item.localName === localName) {
        return true;
      }
    } else if (!namespaceURI && !defaultNode) {
      defaultNode = true;
      return true;
    }
    return false;
  })[0] || null;
};

core.AttrNodeMap.prototype.setNamedItem = function(/* Node */ arg) {
  if (arg.nodeType !== this._ownerDocument.ATTRIBUTE_NODE) {
    throw new core.DOMException(core.HIERARCHY_REQUEST_ERR);
  }

  return core.NamedNodeMap.prototype.setNamedItem.call(this, arg);
};

core.NamedNodeMap.prototype.setNamedItemNS = function(/* Node */ arg)
{
  var owner = this._ownerDocument;
  if (this._parentNode &&
      this._parentNode._parentNode &&
      this._parentNode._parentNode.nodeType === owner.ENTITY_NODE)
  {
    throw new core.DOMException(core.NO_MODIFICATION_ALLOWED_ERR);
  }

  if (arg.nodeType !== owner.ATTRIBUTE_NODE) {
    throw new core.DOMException(core.HIERARCHY_REQUEST_ERR);
  }

  if (arg._parentNode) {
    throw new core.DOMException(core.INUSE_ATTRIBUTE_ERR);
  }
  return this.setNamedItem(arg);
};

core.NamedNodeMap.prototype.removeNamedItemNS = function(/*string */ namespaceURI,
                                                         /* string */ localName)
{
  if (this._parentNode &&
      this._parentNode._parentNode &&
      this._parentNode._parentNode.nodeType === this._ownerDocument.ENTITY_NODE)
  {
    throw new core.DOMException(core.NO_MODIFICATION_ALLOWED_ERR);
  }

  throw new core.DOMException(core.NOT_FOUND_ERR);
};

core.Attr.prototype.__defineGetter__("ownerElement", function() {
  return this._ownerElement || null;
});

core.Node.prototype.__defineSetter__("qualifiedName", function(qualifiedName) {
  ns.validate(qualifiedName, this._namespaceURI);
  qualifiedName       = qualifiedName || "";
  this._localName     = qualifiedName.split(":")[1] || null;
  this.prefix         = qualifiedName.split(":")[0] || null;
  this._qualifiedName = qualifiedName;
});

core.NamedNodeMap.prototype._map = function(fn) {

  if (this._attributes && this._attributes.length) {
    var ret = [], l = this._attributes.length, i = 0, attribute;
    for(i; i<l; i++) {
      attribute = this._attributes.item(i);
      if (fn && fn(attribute)) {
        ret.push(attribute);
      }
    }
    return ret;
  }
  return [];
};

core.Element.prototype.getAttributeNS = function(/* string */ namespaceURI,
                                                 /* string */ localName)
{
  var attr = this._attributes._map(function(attr) {
    if (namespaceURI === attr.namespaceURI &&
        attr.localName === localName)
    {
      return true;
    }
  })[0];

  return (attr) ? attr.nodeValue : null;
};
/*
var _setAttribute = core.Element.prototype.setAttribute;
core.Element.prototype.setAttribute = function(name, value) {
  if (name.indexOf(':') > -1) {
    var split = name.split(':');
    this._localName = split.shift();
    //name = split.pop();
  }
  _setAttribute.call(this, name, value);
}
*/
core.Element.prototype.setAttributeNS = function(/* string */ namespaceURI,
                                                 /* string */ qualifiedName,
                                                 /* string */ value)
{

  ns.validate(qualifiedName, namespaceURI);

  if (qualifiedName.split(':').shift() === "xml" &&
      namespaceURI !== "http://www.w3.org/XML/1998/namespace")
  {
    throw new core.DOMException(core.NAMESPACE_ERR);
  }

  var attr = this.setAttribute(qualifiedName, value);
  if (attr) {
    attr.namespaceURI = namespaceURI;
    var s = qualifiedName.split(':');
    attr._localName = s.pop();
    attr._prefix = (s.length > 0) ? s.pop() : null;
  }

  return attr;
};

core.Element.prototype.removeAttributeNS = function(/* string */ namespaceURI,
                                                    /* string */ localName)
{
  var qualifiedName = this._attributes._map(function(attr) {
    if (namespaceURI === attr.namespaceURI &&
        attr.localName === localName)
    {
      return true;
    }
  })[0] || null;
  return this.removeAttribute(qualifiedName);
};

core.Element.prototype.getAttributeNodeNS = function(/* string */ namespaceURI,
                                                     /* string */ localName)
{
  return this._attributes._map(function(attr) {
    if (namespaceURI === attr.namespaceURI &&
        attr.localName === localName)
    {
      return true;
    }
  })[0] || null;
};

core.Element.prototype.setAttributeNodeNS = function(/* Attr */ newAttr)
{
  if (newAttr.ownerElement) {
    throw new core.DOMException(core.INUSE_ATTRIBUTE_ERR);
  }

  newAttr._ownerElement = this;
  return this.setAttributeNode(newAttr);
};

core.Element.prototype.getElementsByTagNameNS = function(/* String */ namespaceURI,
                                                         /* String */ localName)
{
  var nsPrefixCache = {};

  function filterByTagName(child) {
    if (child.nodeType && child.nodeType === this.ENTITY_REFERENCE_NODE) {
      child = child._entity;
    }

    var localMatch = child.localName === localName,
        nsMatch    = child.namespaceURI === namespaceURI;
    if ((localMatch || localName === "*") &&
        (nsMatch || namespaceURI === "*"))
    {
      return true;
    }
    return false;
  }

  return new core.NodeList(this.ownerDocument || this, core.mapper(this, filterByTagName));
};

core.Element.prototype.hasAttribute = function(/* string */name)
{
  if (!this.attributes) {
    return false;
  }
  return this.attributes.exists(name);
};

core.Element.prototype.hasAttributeNS = function(/* string */namespaceURI,
                                                 /* string */localName)
{
  if (!this._attributes        ||
      !this._attributes.length ||
      this._attributes.length < 1)
  {
    return false;
  }
  return this.hasAttribute(localName);
};

core.DocumentType.prototype.__defineGetter__("publicId", function() {
  return this._publicId || "";
});

core.DocumentType.prototype.__defineGetter__("systemId", function() {
  return this._systemId || "";
});

core.DocumentType.prototype.__defineGetter__("internalSubset", function() {
  return this._internalSubset || null;
});

core.Document.prototype.importNode = function(/* Node */ importedNode,
                                              /* bool */ deep)
{
  if (importedNode && importedNode.nodeType) {
    if (importedNode.nodeType === this.DOCUMENT_NODE ||
        importedNode.nodeType === this.DOCUMENT_TYPE_NODE) {
      throw new core.DOMException(core.NOT_SUPPORTED_ERR);
    }
  }

  var self = this,
      newNode = importedNode.cloneNode(deep);

  function setOwnerDocument(el) {
    el._ownerDocument = self;
    if (el.id) {
      self._ids[el.id] = el;
    }
    if (el.attributes) {
      el.attributes._ownerDocument = self;
      for (var i=0,len=el.attributes.length; i < len; i++) {
        el.attributes.item(i)._ownerDocument = self;
      }
    }
  }
  if (deep) {
    core.visitTree(newNode, setOwnerDocument);
  }
  else {
    setOwnerDocument(newNode);
  }
  return newNode;
};

core.Document.prototype.createElementNS = function(/* string */ namespaceURI,
                                                   /* string */ qualifiedName)
{
  ns.validate(qualifiedName, namespaceURI);

  var element = this.createElement(qualifiedName),
      sploded = qualifiedName.split(':');

  element.namespaceURI = namespaceURI;
  element.qualifiedName = qualifiedName;

  element._localName = sploded.pop();

  if (sploded.length > 0) {
    element.prefix = sploded.pop();
  } else if (namespaceURI === "http://www.w3.org/2000/xmlns/") {
    element.prefix = "xmlns";
  } else if (namespaceURI === "http://www.w3.org/XML/1998/namespace") {
    element.prefix = "xml";
  }

  return element;
};

core.Document.prototype.createAttributeNS = function(/* string */ namespaceURI,
                                                     /* string */ qualifiedName)
{
  ns.validate(qualifiedName, namespaceURI);
  var attribute = this.createAttribute(qualifiedName);
  attribute.qualifiedName = qualifiedName;
  attribute.namespaceURI = namespaceURI;
  var s = qualifiedName.split(':');
  attribute._localName = s.pop();
  attribute._prefix = (s.length > 0) ? s.pop() : null;
  return attribute;
};

core.Document.prototype.getElementsByTagNameNS = function(/* String */ namespaceURI,
                                                          /* String */ localName)
{
  var nsPrefixCache = {};

  function filterByTagName(child) {
    if (child.nodeType && child.nodeType === this.ENTITY_REFERENCE_NODE) {
      child = child._entity;
    }

    var localMatch = child.localName === localName,
        nsMatch    = child.namespaceURI === namespaceURI;
    if (child.nodeType === child.ELEMENT_NODE &&
        (localMatch || localName === "*") &&
        (nsMatch || namespaceURI === "*"))
    {
      return true;
    }
    return false;
  }

  return new core.NodeList(this.ownerDocument || this, core.mapper(this, filterByTagName));
};

core.Element.prototype.__defineSetter__("id", function(id) {
  this.setAttribute("id", id);
  id = this.getAttribute("id"); //Passed validation
  if (!this._ownerDocument._ids) {
      this._ownerDocument._ids = {};
  }
  if (id === '') {
      delete this._ownerDocument._ids[id];
  } else {
      this._ownerDocument._ids[id] = this;
  }
});

core.Element.prototype.__defineGetter__("id",function() {
  return this.getAttribute("id");
});

core.Document.prototype.getElementById = function(id) {
  return this._ids[id] || null;
};

exports.dom =
{
  level2 : {
    core : core
  }
};
<commit_msg>createDocument throws when there is a prefixed qualified name and no namespaceURI<commit_after>var core                     = require("../level1/core").dom.level1.core,
    INVALID_STATE_ERR        = core.INVALID_STATE_ERR        = 11,
    SYNTAX_ERR               = core.SYNTAX_ERR               = 12,
    INVALID_MODIFICATION_ERR = core.INVALID_MODIFICATION_ERR = 13,
    NAMESPACE_ERR            = core.NAMESPACE_ERR            = 14,
    INVALID_ACCESS_ERR       = core.INVALID_ACCESS_ERR       = 15,
    ns = {
      validate : function(namespace, namespaceURI) {
        if (!namespace) {
          throw new core.DOMException(core.INVALID_CHARACTER_ERR, "namespace is undefined");
        }
        if(namespace.match(/[^0-9a-z\.:\-_]/i) !== null) {
          throw new core.DOMException(core.INVALID_CHARACTER_ERR, namespace);
        }
        if ((namespace === 'xmlns' && namespaceURI !== "http://www.w3.org/2000/xmlns/")        ||
            (namespace === "xml"   && namespaceURI !== "http://www.w3.org/XML/1998/namespace") ||
            namespace.indexOf('::') > -1                                                ||
            namespace[namespace.length-1] === ':'                                       ||
            namespace[0] === ':'                                                        ||
            namespace.match(/.+:.+:/))
        {
          throw new core.DOMException(NAMESPACE_ERR);
        }
      }
    };

core.DOMImplementation.prototype.createDocumentType = function(/* String */ qualifiedName,
                                                               /* String */ publicId,
                                                               /* String */ systemId)
{
  ns.validate(qualifiedName);
  var doctype = new core.DocumentType(null, qualifiedName);
  doctype._publicId = publicId ? publicId : '';
  doctype._systemId = systemId ? systemId : '';
  return doctype;
};

/**
  Creates an XML Document object of the specified type with its document element.
  HTML-only DOM implementations do not need to implement this method.
*/
core.DOMImplementation.prototype.createDocument = function(/* String */       namespaceURI,
                                                           /* String */       qualifiedName,
                                                           /* DocumentType */ doctype)
{
  ns.validate(qualifiedName, namespaceURI);

  if (doctype && doctype.ownerDocuemnt !== null) {
    throw new core.DOMException(core.WRONG_DOCUMENT_ERR);
  }

  if (qualifiedName.indexOf(':') > -1 && !namespaceURI) {
    throw new core.DOMException(NAMESPACE_ERR);
  }

  var document = new core.Document();
  document.namespaceURI = namespaceURI;
  document.qualifiedName = qualifiedName;
  document.doctype = doctype;
  document._ownerDocument = document;
  return document;
};

core.Node.prototype.__defineGetter__("ownerDocument", function() {
  return this._ownerDocument || null;
});

core.Node.prototype.isSupported = function(/* string */ feature,
                                           /* string */ version)
{
  return this._ownerDocument.implementation.hasFeature(feature, version);
};

core.Node.prototype._namespaceURI = null;
core.Node.prototype.__defineGetter__("namespaceURI", function() {
  return this._namespaceURI || null;
});

core.Node.prototype.__defineSetter__("namespaceURI", function(value) {
  this._namespaceURI = value;
});

core.Node.prototype.__defineGetter__("prefix", function() {
  return this._prefix || null;
});

core.Node.prototype.__defineSetter__("prefix", function(value) {
  if (this._prefix === "xmlns") {
    throw new core.DOMException(core.NAMESPACE_ERR);
  }
  ns.validate(value, this._namespaceURI);

  this._prefix = value;
});

core.Node.prototype.__defineGetter__("localName", function() {
  return this._localName || null;
});

/* return boolean */
core.Node.prototype.hasAttributes = function() {
  return (this._attributes && this._attributes.length > 0);
};

core.NamedNodeMap.prototype.getNamedItemNS = function(/* string */ namespaceURI,
                                                      /* string */ localName)
{
  var defaultNode = null;
  return this._map(function(item) {

    if (namespaceURI === item.namespaceURI)
    {
      if (item.localName === localName) {
        return true;
      }
    } else if (!namespaceURI && !defaultNode) {
      defaultNode = true;
      return true;
    }
    return false;
  })[0] || null;
};

core.AttrNodeMap.prototype.setNamedItem = function(/* Node */ arg) {
  if (arg.nodeType !== this._ownerDocument.ATTRIBUTE_NODE) {
    throw new core.DOMException(core.HIERARCHY_REQUEST_ERR);
  }

  return core.NamedNodeMap.prototype.setNamedItem.call(this, arg);
};

core.NamedNodeMap.prototype.setNamedItemNS = function(/* Node */ arg)
{
  var owner = this._ownerDocument;
  if (this._parentNode &&
      this._parentNode._parentNode &&
      this._parentNode._parentNode.nodeType === owner.ENTITY_NODE)
  {
    throw new core.DOMException(core.NO_MODIFICATION_ALLOWED_ERR);
  }

  if (arg.nodeType !== owner.ATTRIBUTE_NODE) {
    throw new core.DOMException(core.HIERARCHY_REQUEST_ERR);
  }

  if (arg._parentNode) {
    throw new core.DOMException(core.INUSE_ATTRIBUTE_ERR);
  }
  return this.setNamedItem(arg);
};

core.NamedNodeMap.prototype.removeNamedItemNS = function(/*string */ namespaceURI,
                                                         /* string */ localName)
{
  if (this._parentNode &&
      this._parentNode._parentNode &&
      this._parentNode._parentNode.nodeType === this._ownerDocument.ENTITY_NODE)
  {
    throw new core.DOMException(core.NO_MODIFICATION_ALLOWED_ERR);
  }

  throw new core.DOMException(core.NOT_FOUND_ERR);
};

core.Attr.prototype.__defineGetter__("ownerElement", function() {
  return this._ownerElement || null;
});

core.Node.prototype.__defineSetter__("qualifiedName", function(qualifiedName) {
  ns.validate(qualifiedName, this._namespaceURI);
  qualifiedName       = qualifiedName || "";
  this._localName     = qualifiedName.split(":")[1] || null;
  this.prefix         = qualifiedName.split(":")[0] || null;
  this._qualifiedName = qualifiedName;
});

core.NamedNodeMap.prototype._map = function(fn) {

  if (this._attributes && this._attributes.length) {
    var ret = [], l = this._attributes.length, i = 0, attribute;
    for(i; i<l; i++) {
      attribute = this._attributes.item(i);
      if (fn && fn(attribute)) {
        ret.push(attribute);
      }
    }
    return ret;
  }
  return [];
};

core.Element.prototype.getAttributeNS = function(/* string */ namespaceURI,
                                                 /* string */ localName)
{
  var attr = this._attributes._map(function(attr) {
    if (namespaceURI === attr.namespaceURI &&
        attr.localName === localName)
    {
      return true;
    }
  })[0];

  return (attr) ? attr.nodeValue : null;
};
/*
var _setAttribute = core.Element.prototype.setAttribute;
core.Element.prototype.setAttribute = function(name, value) {
  if (name.indexOf(':') > -1) {
    var split = name.split(':');
    this._localName = split.shift();
    //name = split.pop();
  }
  _setAttribute.call(this, name, value);
}
*/
core.Element.prototype.setAttributeNS = function(/* string */ namespaceURI,
                                                 /* string */ qualifiedName,
                                                 /* string */ value)
{

  ns.validate(qualifiedName, namespaceURI);

  if (qualifiedName.split(':').shift() === "xml" &&
      namespaceURI !== "http://www.w3.org/XML/1998/namespace")
  {
    throw new core.DOMException(core.NAMESPACE_ERR);
  }

  var attr = this.setAttribute(qualifiedName, value);
  if (attr) {
    attr.namespaceURI = namespaceURI;
    var s = qualifiedName.split(':');
    attr._localName = s.pop();
    attr._prefix = (s.length > 0) ? s.pop() : null;
  }

  return attr;
};

core.Element.prototype.removeAttributeNS = function(/* string */ namespaceURI,
                                                    /* string */ localName)
{
  var qualifiedName = this._attributes._map(function(attr) {
    if (namespaceURI === attr.namespaceURI &&
        attr.localName === localName)
    {
      return true;
    }
  })[0] || null;
  return this.removeAttribute(qualifiedName);
};

core.Element.prototype.getAttributeNodeNS = function(/* string */ namespaceURI,
                                                     /* string */ localName)
{
  return this._attributes._map(function(attr) {
    if (namespaceURI === attr.namespaceURI &&
        attr.localName === localName)
    {
      return true;
    }
  })[0] || null;
};

core.Element.prototype.setAttributeNodeNS = function(/* Attr */ newAttr)
{
  if (newAttr.ownerElement) {
    throw new core.DOMException(core.INUSE_ATTRIBUTE_ERR);
  }

  newAttr._ownerElement = this;
  return this.setAttributeNode(newAttr);
};

core.Element.prototype.getElementsByTagNameNS = function(/* String */ namespaceURI,
                                                         /* String */ localName)
{
  var nsPrefixCache = {};

  function filterByTagName(child) {
    if (child.nodeType && child.nodeType === this.ENTITY_REFERENCE_NODE) {
      child = child._entity;
    }

    var localMatch = child.localName === localName,
        nsMatch    = child.namespaceURI === namespaceURI;
    if ((localMatch || localName === "*") &&
        (nsMatch || namespaceURI === "*"))
    {
      return true;
    }
    return false;
  }

  return new core.NodeList(this.ownerDocument || this, core.mapper(this, filterByTagName));
};

core.Element.prototype.hasAttribute = function(/* string */name)
{
  if (!this.attributes) {
    return false;
  }
  return this.attributes.exists(name);
};

core.Element.prototype.hasAttributeNS = function(/* string */namespaceURI,
                                                 /* string */localName)
{
  if (!this._attributes        ||
      !this._attributes.length ||
      this._attributes.length < 1)
  {
    return false;
  }
  return this.hasAttribute(localName);
};

core.DocumentType.prototype.__defineGetter__("publicId", function() {
  return this._publicId || "";
});

core.DocumentType.prototype.__defineGetter__("systemId", function() {
  return this._systemId || "";
});

core.DocumentType.prototype.__defineGetter__("internalSubset", function() {
  return this._internalSubset || null;
});

core.Document.prototype.importNode = function(/* Node */ importedNode,
                                              /* bool */ deep)
{
  if (importedNode && importedNode.nodeType) {
    if (importedNode.nodeType === this.DOCUMENT_NODE ||
        importedNode.nodeType === this.DOCUMENT_TYPE_NODE) {
      throw new core.DOMException(core.NOT_SUPPORTED_ERR);
    }
  }

  var self = this,
      newNode = importedNode.cloneNode(deep);

  function setOwnerDocument(el) {
    el._ownerDocument = self;
    if (el.id) {
      self._ids[el.id] = el;
    }
    if (el.attributes) {
      el.attributes._ownerDocument = self;
      for (var i=0,len=el.attributes.length; i < len; i++) {
        el.attributes.item(i)._ownerDocument = self;
      }
    }
  }
  if (deep) {
    core.visitTree(newNode, setOwnerDocument);
  }
  else {
    setOwnerDocument(newNode);
  }
  return newNode;
};

core.Document.prototype.createElementNS = function(/* string */ namespaceURI,
                                                   /* string */ qualifiedName)
{
  ns.validate(qualifiedName, namespaceURI);

  var element = this.createElement(qualifiedName),
      sploded = qualifiedName.split(':');

  element.namespaceURI = namespaceURI;
  element.qualifiedName = qualifiedName;

  element._localName = sploded.pop();

  if (sploded.length > 0) {
    element.prefix = sploded.pop();
  } else if (namespaceURI === "http://www.w3.org/2000/xmlns/") {
    element.prefix = "xmlns";
  } else if (namespaceURI === "http://www.w3.org/XML/1998/namespace") {
    element.prefix = "xml";
  }

  return element;
};

core.Document.prototype.createAttributeNS = function(/* string */ namespaceURI,
                                                     /* string */ qualifiedName)
{
  ns.validate(qualifiedName, namespaceURI);
  var attribute = this.createAttribute(qualifiedName);
  attribute.qualifiedName = qualifiedName;
  attribute.namespaceURI = namespaceURI;
  var s = qualifiedName.split(':');
  attribute._localName = s.pop();
  attribute._prefix = (s.length > 0) ? s.pop() : null;
  return attribute;
};

core.Document.prototype.getElementsByTagNameNS = function(/* String */ namespaceURI,
                                                          /* String */ localName)
{
  var nsPrefixCache = {};

  function filterByTagName(child) {
    if (child.nodeType && child.nodeType === this.ENTITY_REFERENCE_NODE) {
      child = child._entity;
    }

    var localMatch = child.localName === localName,
        nsMatch    = child.namespaceURI === namespaceURI;
    if (child.nodeType === child.ELEMENT_NODE &&
        (localMatch || localName === "*") &&
        (nsMatch || namespaceURI === "*"))
    {
      return true;
    }
    return false;
  }

  return new core.NodeList(this.ownerDocument || this, core.mapper(this, filterByTagName));
};

core.Element.prototype.__defineSetter__("id", function(id) {
  this.setAttribute("id", id);
  id = this.getAttribute("id"); //Passed validation
  if (!this._ownerDocument._ids) {
      this._ownerDocument._ids = {};
  }
  if (id === '') {
      delete this._ownerDocument._ids[id];
  } else {
      this._ownerDocument._ids[id] = this;
  }
});

core.Element.prototype.__defineGetter__("id",function() {
  return this.getAttribute("id");
});

core.Document.prototype.getElementById = function(id) {
  return this._ids[id] || null;
};

exports.dom =
{
  level2 : {
    core : core
  }
};
<|endoftext|>


<commit_before>'use strict';

var path = require('path');
var errors = require('./errors');
var router = require('./router');
var root = null;
var responseRenderer = null;

/**
 * @param {String} _root
 */
function setRoot(_root) {
	root = _root;
}

/**
 * @param {Function} _responseRenderer
 */
function setResponseRenderer(_responseRenderer) {
	return responseRenderer = _responseRenderer;
}

/**
 * @param {ExpressServerRequest} req
 * @param {ExpressServerResponse} res
 */
function renderer(req, res) {

	/**
	 * @param {Error|null} error
	 * @param {Object} data
	 * @param {String|Array} messages
	 */
	function render(error, data, messages) {

		messages = messages || [];
		var statusCode = 200,
			responseData = data || {};

		responseData.messages = Object.prototype.toString.call(messages) === '[object Array]' ? messages : [messages];
		if (res.exception) {
			responseData.messages.unshift(res.exception);
		}

		if (error) {

			if (error instanceof errors.ActionNotFoundError ||
				error instanceof errors.ControllerNotFoundError) {
				statusCode = 501;
			} else if (error  instanceof errors.NotFoundError) {
				statusCode = 404;
			} else {
				statusCode = 500;
			}
		}
		res.status(statusCode);

		if (responseRenderer === null) {
			return res.json(responseData);
		} else {
			try {
				return responseRenderer(res, error, responseData);
			} catch (error) {
				if (res.exception) {
					return res.json(responseData);
				}
				res.exception = error;
				return exception(req, renderer(req, res));
			}

		}
	}

	return render;
}

function exception(req, next) {
	next(new errors.DispatcherError('Application Error'));
}

function rootNotSet(req, next) {
	next(new errors.DispatcherError('Root not set'));
}

function noAction(req, next) {
	next(new errors.ActionNotFoundError(['Action not found:', req.actionName].join(' ')));
}

function noController(req, next) {
	next(new errors.ControllerNotFoundError(['Controller not found:', req.controllerName].join(' ')));
}

function route(controllerName, actionName) {

	/**
	 * @param {ExpressServerRequest} req
	 * @param {ExpressServerResponse} res
	 */
	function dispatch(req, res) {
		req.actionName = actionName;
		req.controllerName = controllerName;
		var action, controllerPath = path.join(root, controllerName);

		if (root === null) {
			action = rootNotSet;
		} else {
			try {
				action = require(controllerPath)[actionName] || noAction;
			} catch (error) {
				res.exception = error;
				action = noController;
			}
		}

		try {
			return action(req, renderer(req, res));
		} catch (error) {
			res.exception = error;
			return exception(req, renderer(req, res));
		}
	}

	return dispatch;
}

function defaultRoute(defaultControllerName, defaultActionName) {

	// Defaults
	defaultControllerName = defaultControllerName || 'index';
	defaultActionName = defaultActionName || 'index';

	/**
	 * @param {ExpressServerRequest} req
	 * @param {ExpressServerResponse} res
	 */
	function dispatch(req, res) {

		return router.match(req, function routeMatched(error, controllerName, actionName) {
			if (error) {
				res.exception = error;
				return exception(req, renderer(req, res));
			}
			return route(controllerName || defaultControllerName, actionName || defaultActionName)(req, res);
		});
	}

	return dispatch;
}

exports.setRoot = setRoot;
exports.setResponseRenderer = setResponseRenderer;
exports.errors = errors;
exports.route = route;
exports.defaultRoute = defaultRoute;
exports.http = require('./http');<commit_msg>Code reorganized to keep Node app completely in the separate folder<commit_after>'use strict';

var path = require('path');
var errors = require('./errors');
var router = require('./router');
var root = null;
var responseRenderer = null;

/**
 * @param {String} _root
 */
function setRoot(_root) {
	root = _root;
}

/**
 * @param {Function} _responseRenderer
 */
function setResponseRenderer(_responseRenderer) {
	responseRenderer = _responseRenderer;
}

/**
 * @param {ExpressServerRequest} req
 * @param {ExpressServerResponse} res
 */
function renderer(req, res) {

	/**
	 * @param {Error|null} error
	 * @param {Object} data
	 * @param {String|Array} messages
	 */
	function render(error, data, messages) {

		messages = messages || [];
		var statusCode = 200,
			responseData = data || {};

		responseData.messages = Object.prototype.toString.call(messages) === '[object Array]' ? messages : [messages];
		if (res.exception) {
			responseData.messages.unshift(res.exception);
		}

		if (error) {

			if (error instanceof errors.ActionNotFoundError ||
				error instanceof errors.ControllerNotFoundError) {
				statusCode = 501;
			} else if (error  instanceof errors.NotFoundError) {
				statusCode = 404;
			} else {
				statusCode = 500;
			}
		}
		res.status(statusCode);

		if (responseRenderer === null) {
			return res.json(responseData);
		} else {
			try {
				return responseRenderer(res, error, responseData);
			} catch (error) {
				if (res.exception) {
					return res.json(responseData);
				}
				res.exception = error;
				return exception(req, renderer(req, res));
			}

		}
	}

	return render;
}

function exception(req, next) {
	next(new errors.DispatcherError('Application Error'));
}

function rootNotSet(req, next) {
	next(new errors.DispatcherError('Root not set'));
}

function noAction(req, next) {
	next(new errors.ActionNotFoundError(['Action not found:', req.actionName].join(' ')));
}

function noController(req, next) {
	next(new errors.ControllerNotFoundError(['Controller not found:', req.controllerName].join(' ')));
}

function route(controllerName, actionName) {

	/**
	 * @param {ExpressServerRequest} req
	 * @param {ExpressServerResponse} res
	 */
	function dispatch(req, res) {
		req.actionName = actionName;
		req.controllerName = controllerName;
		var action, controllerPath = path.join(root, controllerName);

		if (root === null) {
			action = rootNotSet;
		} else {
			try {
				action = require(controllerPath)[actionName] || noAction;
			} catch (error) {
				res.exception = error;
				action = noController;
			}
		}

		try {
			return action(req, renderer(req, res));
		} catch (error) {
			res.exception = error;
			return exception(req, renderer(req, res));
		}
	}

	return dispatch;
}

function defaultRoute(defaultControllerName, defaultActionName) {

	// Defaults
	defaultControllerName = defaultControllerName || 'index';
	defaultActionName = defaultActionName || 'index';

	/**
	 * @param {ExpressServerRequest} req
	 * @param {ExpressServerResponse} res
	 */
	function dispatch(req, res) {

		return router.match(req, function routeMatched(error, controllerName, actionName) {
			if (error) {
				res.exception = error;
				return exception(req, renderer(req, res));
			}
			return route(controllerName || defaultControllerName, actionName || defaultActionName)(req, res);
		});
	}

	return dispatch;
}

exports.setRoot = setRoot;
exports.setResponseRenderer = setResponseRenderer;
exports.errors = errors;
exports.route = route;
exports.defaultRoute = defaultRoute;
exports.http = require('./http');<|endoftext|>


<commit_before>/* global django, CKEDITOR */
(function($) {
    // Activate and deactivate the CKEDITOR because it does not like
    // getting dragged or its underlying ID changed.
    // The 'data-processed' attribute is set for compatibility with
    // django-ckeditor.
    $(document).on(
        'content-editor:activate',
        function(event, $row, formsetName) {
            $row.find('textarea[data-type=ckeditortype]').each(function() {
                if (this.getAttribute('data-processed') != '1') {
                    this.setAttribute('data-processed', '1')
                    $($(this).data('external-plugin-resources')).each(function(){
                        CKEDITOR.plugins.addExternal(this[0], this[1], this[2]);
                    });
                    CKEDITOR.replace(this.id, $(this).data('config'));
                }
            });
        }
    ).on(
        'content-editor:deactivate',
        function(event, $row, formsetName) {
            $row.find('textarea[data-type=ckeditortype]').each(function() {
                try {
                    CKEDITOR.instances[this.id] && CKEDITOR.instances[this.id].destroy();
                    this.setAttribute('data-processed', '0')
                } catch(err) {}
            });
        }
    );

    // Move CKEditor up a bit to hide the text label.
    // var style = document.createElement('style');
    // style.textContent = '.order-machine .django-ckeditor-widget { margin: -30px 0 0 -1px; }';
    // document.head.appendChild(style);
})(django.jQuery);
<commit_msg>Responsive CKEditor sizing<commit_after>/* global django, CKEDITOR */
(function($) {
    // Activate and deactivate the CKEDITOR because it does not like
    // getting dragged or its underlying ID changed.
    // The 'data-processed' attribute is set for compatibility with
    // django-ckeditor.
    $(document).on(
        'content-editor:activate',
        function(event, $row, formsetName) {
            $row.find('textarea[data-type=ckeditortype]').each(function() {
                if (this.getAttribute('data-processed') != '1') {
                    this.setAttribute('data-processed', '1')
                    $($(this).data('external-plugin-resources')).each(function(){
                        CKEDITOR.plugins.addExternal(this[0], this[1], this[2]);
                    });
                    CKEDITOR.replace(this.id, $(this).data('config'));
                }
            });
        }
    ).on(
        'content-editor:deactivate',
        function(event, $row, formsetName) {
            $row.find('textarea[data-type=ckeditortype]').each(function() {
                try {
                    CKEDITOR.instances[this.id] && CKEDITOR.instances[this.id].destroy();
                    this.setAttribute('data-processed', '0')
                } catch(err) {}
            });
        }
    );

    // Move CKEditor up a bit to hide the text label.
    var style = document.createElement('style');
    style.textContent = '.order-machine .django-ckeditor-widget { width: calc(100% - 170px); }';
    style.textContent += '@media (max-width: 767px) { .order-machine .django-ckeditor-widget { width: calc(100%); }';
    document.head.appendChild(style);
})(django.jQuery);
<|endoftext|>


<commit_before>'use strict';

/**
 * @ngdoc service
 * @name flowsimUiApp.datapath
 * @description
 * # datapath
 * Service in the flowsimUiApp.
 */
angular.module('flowsimUiApp')
  .factory('Datapath', function(fgConstraints) {

var defaultFragHandling = 'normal';
var defaultMissSendLen  = 100;

var fragOptions = [
  'normal',
  'drop',
  'reassemble'
];

function Capabilities(datapath) {
  if(datapath) {
    _.extend(this, datapath);
  } else {
    // default constructor
    this.datapath_id   = '01:23:45:67:89:ab'; // FIXME: bad default
    this.n_buffers     = 1024;
    this.ip_reassembly = true;
    // Descriptions
    this.mfr_description = '';
    this.hw_description  = '';
    this.sw_description  = '';
    this.serial_num      = '';
    this.dp_description  = '';
  }
}

Capabilities.prototype.openflow_1_0 = function() {
  this.ip_reassembly   = true;
  this.mfr_description = 'Flowgrammable';
  this.hw_description  = 'Generic OpenFlow 1.0 Switch';
  this.sw_description  = 'Generic OpenFlow 1.0 Software';
  this.dp_description  = 'Generic OpenFlow 1.0 Pipeline';
};

Capabilities.prototype.openflow_1_1 = function() {
  this.ip_reassembly   = true;
  this.mfr_description = 'Flowgrammable';
  this.hw_description  = 'Generic OpenFlow 1.1 Switch';
  this.sw_description  = 'Generic OpenFlow 1.1 Software';
  this.dp_description  = 'Generic OpenFlow 1.1 Pipeline';
};

Capabilities.prototype.openflow_1_2 = function() {
  this.ip_reassembly   = true;
  this.mfr_description = 'Flowgrammable';
  this.hw_description  = 'Generic OpenFlow 1.2 Switch';
  this.sw_description  = 'Generic OpenFlow 1.2 Software';
  this.dp_description  = 'Generic OpenFlow 1.2 Pipeline';
};

Capabilities.prototype.openflow_1_3 = function() {
  this.ip_reassembly   = true;
  this.mfr_description = 'Flowgrammable';
  this.hw_description  = 'Generic OpenFlow 1.3 Switch';
  this.sw_description  = 'Generic OpenFlow 1.3 Software';
  this.dp_description  = 'Generic OpenFlow 1.3 Pipeline';
};

Capabilities.prototype.openflow_1_4 = function() {
  this.ip_reassembly   = true;
  this.mfr_description = 'Flowgrammable';
  this.hw_description  = 'Generic OpenFlow 1.4 Switch';
  this.sw_description  = 'Generic OpenFlow 1.4 Software';
  this.dp_description  = 'Generic OpenFlow 1.4 Pipeline';
};

function Datapath(datapath, profile) {
  if(datapath instanceof Datapath || typeof datapath === 'object') {
    _.extend(this, datapath);
  } else {
      this.datapath_id   = profile.datapath_id;
      this.n_buffers     = profile.n_buffers;
      this.miss_send_len = defaultMissSendLen;

      // optional bit necessary for UI display
      this.ip_reassebly = profile.ip_reassembly;
      this.fragHandling = defaultFragHandling;

      this.mfr_description = profile.mfr_description;
      this.hw_description  = profile.hw_description;
      this.sw_description  = profile.sw_description;
      this.serial_num      = profile.serial_num;
      this.dp_description  = profile.dp_description;
  }
}

var TIPS = {
  datapath_id: 'Unique id of the datapath',
  ip_reassembly: 'Datapath can reassemble IP fragments',
  n_buffers: 'Number of packets that can be buffered for controller',
  mfr_description: '',
  hw_description: '',
  sw_description: '',
  serial_num: '',
  dp_description: ''
};

var TESTS = {
  datapath_id:     function() { return true; },
  n_buffers:       fgConstraints.isUInt(0, 0xffff),
  mfr_description: function(v) { return !v || v.length <= 256 ; },
  hw_description:  function(v) { return !v || v.length <= 256; },
  sw_description:  function(v) { return !v || v.length <= 256; },
  serial_num:      function(v) { return !v || v.length <= 32; },
  dp_description:  function(v) { return !v || v.length <= 256; }
};

return {
  Capabilities: Capabilities,
  Configuration: Datapath,
  TIPS: TIPS,
  TESTS: TESTS
};

});
<commit_msg>latest<commit_after>'use strict';

/**
 * @ngdoc service
 * @name flowsimUiApp.datapath
 * @description
 * # datapath
 * Service in the flowsimUiApp.
 */
angular.module('flowsimUiApp')
  .factory('Datapath', function(fgConstraints) {

var defaultFragHandling = 'normal';
var defaultMissSendLen  = 100;

var fragOptions = [
  'normal',
  'drop',
  'reassemble'
];

function Capabilities(datapath) {
  if(datapath) {
    _.extend(this, datapath);
  } else {
    // default constructor
    this.datapath_id   = '01:23:45:67:89:ab'; // FIXME: bad default
    this.n_buffers     = 1024;
    this.ip_reassembly = true;
    // Descriptions
    this.mfr_description = '';
    this.hw_description  = '';
    this.sw_description  = '';
    this.serial_num      = '';
    this.dp_description  = '';
  }
}

Capabilities.prototype.openflow_1_0 = function() {
  this.ip_reassembly   = true;
  this.mfr_description = 'Flowgrammable';
  this.hw_description  = 'Generic OpenFlow 1.0 Switch';
  this.sw_description  = 'Generic OpenFlow 1.0 Software';
  this.dp_description  = 'Generic OpenFlow 1.0 Pipeline';
};

Capabilities.prototype.openflow_1_1 = function() {
  this.ip_reassembly   = true;
  this.mfr_description = 'Flowgrammable';
  this.hw_description  = 'Generic OpenFlow 1.1 Switch';
  this.sw_description  = 'Generic OpenFlow 1.1 Software';
  this.dp_description  = 'Generic OpenFlow 1.1 Pipeline';
};

Capabilities.prototype.openflow_1_2 = function() {
  this.ip_reassembly   = true;
  this.mfr_description = 'Flowgrammable';
  this.hw_description  = 'Generic OpenFlow 1.2 Switch';
  this.sw_description  = 'Generic OpenFlow 1.2 Software';
  this.dp_description  = 'Generic OpenFlow 1.2 Pipeline';
};

Capabilities.prototype.openflow_1_3 = function() {
  this.ip_reassembly   = true;
  this.mfr_description = 'Flowgrammable';
  this.hw_description  = 'Generic OpenFlow 1.3 Switch';
  this.sw_description  = 'Generic OpenFlow 1.3 Software';
  this.dp_description  = 'Generic OpenFlow 1.3 Pipeline';
};

Capabilities.prototype.openflow_1_4 = function() {
  this.ip_reassembly   = true;
  this.mfr_description = 'Flowgrammable';
  this.hw_description  = 'Generic OpenFlow 1.4 Switch';
  this.sw_description  = 'Generic OpenFlow 1.4 Software';
  this.dp_description  = 'Generic OpenFlow 1.4 Pipeline';
};

function Datapath(datapath, profile) {
  if(datapath instanceof Datapath || typeof datapath === 'object') {
    _.extend(this, datapath);
  } else {
      this.datapath_id   = profile.datapath_id;
      this.n_buffers     = profile.n_buffers;
      this.miss_send_len = defaultMissSendLen;

      // optional bit necessary for UI display
      this.ip_reassembly = profile.ip_reassembly;
      // or this
      this.capabilities = {
        ip_reassembly: profile.ip_reassebmly
      };
      this.fragHandling = defaultFragHandling;

      this.mfr_description = profile.mfr_description;
      this.hw_description  = profile.hw_description;
      this.sw_description  = profile.sw_description;
      this.serial_num      = profile.serial_num;
      this.dp_description  = profile.dp_description;
  }
}

var TIPS = {
  datapath_id: 'Unique id of the datapath',
  ip_reassembly: 'Datapath can reassemble IP fragments',
  n_buffers: 'Number of packets that can be buffered for controller',
  mfr_description: '',
  hw_description: '',
  sw_description: '',
  serial_num: '',
  dp_description: ''
};

var TESTS = {
  datapath_id:     function() { return true; },
  n_buffers:       fgConstraints.isUInt(0, 0xffff),
  mfr_description: function(v) { return !v || v.length <= 256 ; },
  hw_description:  function(v) { return !v || v.length <= 256; },
  sw_description:  function(v) { return !v || v.length <= 256; },
  serial_num:      function(v) { return !v || v.length <= 32; },
  dp_description:  function(v) { return !v || v.length <= 256; }
};

return {
  Capabilities: Capabilities,
  Configuration: Datapath,
  TIPS: TIPS,
  TESTS: TESTS
};

});
<|endoftext|>


<commit_before>import {map, flatten} from '../utils/helpers';
import CSSPropertyOperations from '../vendor/react/lib/CSSPropertyOperations';
import animations from '../style/animations';

let styleElement;
const styleStorage = {};

/**
 * Injects the provided style into the styleStore.
 */
function injectStyleTag() {
  if (!styleElement) {
    styleElement = document.createElement('style');
    document.body.appendChild(styleElement);
    styleElement.setAttribute('class', 'belle-style');
  }
}

/**
 * Injects the provided style into the styleStore.
 */
function updateStore(styleId, style, pseudoClass, disabled) {
  styleStorage[styleId] = styleStorage[styleId] || {};
  if (disabled) {
    styleStorage[styleId].disabledPseudoClasses = styleStorage[styleId].disabledPseudoClasses || {};
    styleStorage[styleId].disabledPseudoClasses[pseudoClass] = style;
  } else {
    styleStorage[styleId].pseudoClasses = styleStorage[styleId].pseudoClasses || {};
    styleStorage[styleId].pseudoClasses[pseudoClass] = style;
  }
}

/**
 * Constructs all the stored styles & injects them to the DOM.
 */
function createMarkupOnPseudoClass(pseudoClasses, id, disabled) {
  return map(pseudoClasses, (style, pseudoClass) => {
    const styleString = CSSPropertyOperations.createMarkupForStyles(style);
    const styleWithImportant = styleString.replace(/;/g, ' !important;');

    return disabled ?
        `.${id}[disabled]:${pseudoClass} {${styleWithImportant}}` :
        `.${id}:${pseudoClass} {${styleWithImportant}}`;
  });
}

function updateStyling() {
  const styles = map(styleStorage, (storageEntry, id) => {
    const pseudoClassesArray = [];

    if (storageEntry.pseudoClasses) {
      pseudoClassesArray.push(createMarkupOnPseudoClass(storageEntry.pseudoClasses, id, false));
    }
    if (storageEntry.disabledPseudoClasses) {
      pseudoClassesArray.push(createMarkupOnPseudoClass(storageEntry.disabledPseudoClasses, id, true));
    }

    return pseudoClassesArray;
  });
  styleElement.innerHTML = flatten([animations, styles]).join(' ');
}

/**
 * Injects a style tag and adds multiple passed styles.
 *
 * By using this function someone can make sure the DOM is updated only once.
 *
 * @example
 * ```
 * const styles = [
 *   {
 *     id: 'style-0.0.2',
 *     style: { color: '#F00' },
 *     pseudoClass: 'hover'
 *   }
 * ];
 * injectStyles(styles);
 * ```
 */
export function injectStyles(styles) {
  injectStyleTag();
  styles.forEach((style) => {
    updateStore(style.id, style.style, style.pseudoClass, style.disabled);
  });
  updateStyling();
}

/**
 * Removes all pseudoClass styles based on the provided styleId.
 */
export function removeStyle(styleId) {
  delete styleStorage[styleId];
  updateStyling();
}

/**
 * Removes all pseudoClass styles based on all provided styleIds.
 */
export function removeAllStyles(styleIds) {
  styleIds.forEach((styleId) => {
    delete styleStorage[styleId];
  });
  updateStyling();
}

/**
 * Injects a style tag and adds the passed style for the provided pseudoClass.
 */
export default function(styleId, style, pseudoClass, disabled) {
  injectStyleTag();
  updateStore(styleId, style, pseudoClass, disabled);
  updateStyling();
}
<commit_msg>fix(inject-style): avoid accessing document in case DOM is not available e.g. server side rendering<commit_after>import {map, flatten} from '../utils/helpers';
import CSSPropertyOperations from '../vendor/react/lib/CSSPropertyOperations';
import { canUseDOM } from 'react/lib/ExecutionEnvironment';
import animations from '../style/animations';

let styleElement;
const styleStorage = {};

/**
 * Injects the provided style into the styleStore.
 */
function injectStyleTag() {
  if (!styleElement && canUseDOM) {
    styleElement = document.createElement('style');
    document.body.appendChild(styleElement);
    styleElement.setAttribute('class', 'belle-style');
  }
}

/**
 * Injects the provided style into the styleStore.
 */
function updateStore(styleId, style, pseudoClass, disabled) {
  styleStorage[styleId] = styleStorage[styleId] || {};
  if (disabled) {
    styleStorage[styleId].disabledPseudoClasses = styleStorage[styleId].disabledPseudoClasses || {};
    styleStorage[styleId].disabledPseudoClasses[pseudoClass] = style;
  } else {
    styleStorage[styleId].pseudoClasses = styleStorage[styleId].pseudoClasses || {};
    styleStorage[styleId].pseudoClasses[pseudoClass] = style;
  }
}

/**
 * Constructs all the stored styles & injects them to the DOM.
 */
function createMarkupOnPseudoClass(pseudoClasses, id, disabled) {
  return map(pseudoClasses, (style, pseudoClass) => {
    const styleString = CSSPropertyOperations.createMarkupForStyles(style);
    const styleWithImportant = styleString.replace(/;/g, ' !important;');

    return disabled ?
        `.${id}[disabled]:${pseudoClass} {${styleWithImportant}}` :
        `.${id}:${pseudoClass} {${styleWithImportant}}`;
  });
}

function updateStyling() {
  const styles = map(styleStorage, (storageEntry, id) => {
    const pseudoClassesArray = [];

    if (storageEntry.pseudoClasses) {
      pseudoClassesArray.push(createMarkupOnPseudoClass(storageEntry.pseudoClasses, id, false));
    }
    if (storageEntry.disabledPseudoClasses) {
      pseudoClassesArray.push(createMarkupOnPseudoClass(storageEntry.disabledPseudoClasses, id, true));
    }

    return pseudoClassesArray;
  });
  if (styleElement) {
    styleElement.innerHTML = flatten([animations, styles]).join(' ');
  }
}

/**
 * Injects a style tag and adds multiple passed styles.
 *
 * By using this function someone can make sure the DOM is updated only once.
 *
 * @example
 * ```
 * const styles = [
 *   {
 *     id: 'style-0.0.2',
 *     style: { color: '#F00' },
 *     pseudoClass: 'hover'
 *   }
 * ];
 * injectStyles(styles);
 * ```
 */
export function injectStyles(styles) {
  injectStyleTag();
  styles.forEach((style) => {
    updateStore(style.id, style.style, style.pseudoClass, style.disabled);
  });
  updateStyling();
}

/**
 * Removes all pseudoClass styles based on the provided styleId.
 */
export function removeStyle(styleId) {
  delete styleStorage[styleId];
  updateStyling();
}

/**
 * Removes all pseudoClass styles based on all provided styleIds.
 */
export function removeAllStyles(styleIds) {
  styleIds.forEach((styleId) => {
    delete styleStorage[styleId];
  });
  updateStyling();
}

/**
 * Injects a style tag and adds the passed style for the provided pseudoClass.
 */
export default function(styleId, style, pseudoClass, disabled) {
  injectStyleTag();
  updateStore(styleId, style, pseudoClass, disabled);
  updateStyling();
}
<|endoftext|>


<commit_before>var fse = require('fs-extra')
var repo = require('./repo')
var gather = require('./gather')
var Doclet = require('./models/doclet')
var Bull = require('bull')
var mongoose = require('mongoose')
var services = require('./services')

var init = function (gitRoot) {
  fse.mkdirsSync(gitRoot)

  mongoose.connect('mongodb://' + services.mongodb.host + services.mongodb.db)

  var inbox = new Bull('inbox', services.redis.port, services.redis.host)
  var failed = new Bull('failed', services.redis.port, services.redis.host)

  var updateDoc = function (repository, branch, eventData, done) {
    console.log('checking out', repository.html_url, branch)
    var gitDir = repo.checkout(repository.html_url, branch, gitRoot)
    console.log('creating doc', repository.html_url, branch)
    var data = gather.gatherDocletsAndMeta(gitDir)
    console.log('finished doc', repository.html_url, branch)
    Doclet.createFromGitHubEvent(eventData, data, done)
  }

  inbox.process(function (job, jobDone) {
    try {
      var data = job.data
      var done = function (err, result) {
        if (err) {
          console.error('doc failed', err, data.repository.full_name, data.ref)
          failed.add(job.data)
          jobDone(err)
        } else {
          console.log('doc created', data.repository.full_name, data.ref)
          jobDone()
        }
      }
      var refParts = data.ref.split('refs/heads/')
      if (data.ref_type === 'tag') {
        console.log('new release of', data.repository.full_name, data.ref)
        updateDoc(data.repository, data.ref, data, done)
      } else if (refParts) {
        console.log('new release of', data.repository.full_name, refParts[1])
        updateDoc(data.repository, refParts[1], data, done)
      } else {
        jobDone()
      }
    } catch (err) {
      console.log('failed with exception', err)
      jobDone(err)
    }
  })
}

module.exports = {
  init: init
}
<commit_msg>improve error handling<commit_after>var fse = require('fs-extra')
var repo = require('./repo')
var gather = require('./gather')
var Doclet = require('./models/doclet')
var Bull = require('bull')
var mongoose = require('mongoose')
var services = require('./services')

var init = function (gitRoot) {
  fse.mkdirsSync(gitRoot)

  mongoose.connect('mongodb://' + services.mongodb.host + services.mongodb.db)

  var inbox = new Bull('inbox', services.redis.port, services.redis.host)
  var failed = new Bull('failed', services.redis.port, services.redis.host)

  var updateDoc = function (repository, branch, eventData, done) {
    console.log('checking out', repository.html_url, branch)
    var gitDir = repo.checkout(repository.html_url, branch, gitRoot)
    console.log('creating doc', repository.html_url, branch)
    var data = gather.gatherDocletsAndMeta(gitDir)
    console.log('finished doc', repository.html_url, branch)
    Doclet.createFromGitHubEvent(eventData, data, done)
  }

  inbox.process(function (job, jobDone) {
    try {
      var data = job.data
      var done = function (err, result) {
        if (err) {
          console.error('doc failed', err, data.repository && data.repository.full_name, data.ref)
          failed.add(job.data)
          jobDone(err)
        } else {
          console.log('doc created', data.repository.full_name, data.ref)
          jobDone()
        }
      }
      var refParts = data.ref.split('refs/heads/')
      var branch = refParts && refParts[1]
      if (data.ref_type === 'tag') {
        console.log('new release of', data.repository.full_name, data.ref)
        updateDoc(data.repository, data.ref, data, done)
      } else if (branch) {
        console.log('new release of', data.repository.full_name, branch)
        updateDoc(data.repository, branch, data, done)
      } else {
        console.log('skipping', data.repository.full_name, data.ref)
        jobDone()
      }
    } catch (err) {
      console.log('failed with exception', err)
      failed.add(job.data)
      jobDone(err)
    }
  })
}

module.exports = {
  init: init
}
<|endoftext|>


<commit_before>/* eslint-disable no-param-reassign */
const sanitizeHtml = require('sanitize-html');

const maxDeep = 12;
// enable html for all current editors
const keys = ['content', 'text', 'comment', 'gradeComment', 'description'];
const paths = ['lessons', 'news', 'newsModel', 'homework', 'submissions'];
const saveKeys = ['password', 'secret'];
const allowedTags = ['h1', 'h2', 'h3', 'blockquote', 'p', 'a', 'ul', 'ol', 's', 'u', 'span', 'del',
	'li', 'b', 'i', 'img', 'strong', 'em', 'strike', 'code', 'hr', 'br', 'div',
	'table', 'thead', 'caption', 'tbody', 'tr', 'th', 'td', 'pre', 'audio', 'video', 'sub', 'sup'];
const allowedSchemes = ['http', 'https', 'ftp', 'mailto'];

// const allowedSchemesByTag = {
// 	// allow base64 image data
// 	img: ['data'],
// };

const allowedAttributes = {
	a: ['href', 'name', 'target'],
	img: ['src', 'width', 'height'],
};

const htmlTrueOptions = {
	allowedTags,
	allowedAttributes, // allow all attributes of allowed tags
	allowedSchemes,
	// allowedSchemesByTag, // TODO enable this?
	parser: {
		decodeEntities: true,
	},
	allowedStyles: {
		'*': {
			// Match HEX and RGB
			color: [/^#(0x)?[0-9a-f]+$/i, /^rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/],
			'text-align': [/^left$/, /^right$/, /^center$/],
			// Match any number with px, em, or %
			'font-size': [/^\d+(?:px|em|%)$/],
			'font-style': [/^\w+$/],
		},
	},
};

const htmlFalseOptions = {
	allowedTags: [], // disallow all tags
	allowedAttributes: [], // disallow all attributes
	allowedSchemes: [], // disallow url schemes
	parser: {
		decodeEntities: true,
	},
};

/**
 * sanitizes data
 * @param {*} data
 * @param {*} param
 */
const sanitize = (data, { html = false }) => {
	// https://www.npmjs.com/package/sanitize-html
	if (html === true) {
		// editor-content data
		data = sanitizeHtml(data, htmlTrueOptions);
		data = data.replace(/(<script>).*?(<\/script>)/gim, ''); // force remove script tags
		data = data.replace(/(<script>).*?(<\/script>)/gim, ''); // force remove script tags
	} else {
		// non editor-content data
		data = sanitizeHtml(data, htmlFalseOptions);
	}
	return data;
};

/**
 * disables sanitization for defined keys if a path is matching
 * @param {*} path
 * @param {*} key
 */
const allowedHtmlByPathAndKeys = (path, key) => paths.includes(path) && keys.includes(key);

/**
 * Strips JS/HTML Code from data and returns clean version of it
 * @param data {object/array/string}
 * @param path {string}
 * @param depth {number} -
 * @param safeAttributes {array} - attributes over which sanitization won't be performed
 * @returns data - clean without JS
 */
const sanitizeDeep = (data, path, depth = 0, safeAttributes = []) => {
	if (depth >= maxDeep) {
		throw new Error('Data level is to deep. (sanitizeDeep)', { path, data });
	}
	if (typeof data === 'object' && data !== null) {
		// we have an object, can match strings or recurse child objects
		// eslint-disable-next-line consistent-return
		Object.entries(data).forEach(([key, value]) => {
			if (typeof value === 'string') {
				// ignore values completely
				if (saveKeys.includes(key) || safeAttributes.includes(key)) {
					return data; // TODO:  why not over keys in allowedHtmlByPathAndKeys
				}
				data[key] = sanitize(value, { html: allowedHtmlByPathAndKeys(path, key) });
			} else {
				sanitizeDeep(value, path, depth + 1, safeAttributes);
			}
		});
	} else if (typeof data === 'string') {
		// here we can sanitize the input
		data = sanitize(data, { html: false });
	} else if (Array.isArray(data)) {
		// here we have to check all array elements and sanitize strings or do recursion
		for (let i = 0; i < data.length; i += 1) {
			if (typeof data[i] === 'string') {
				data[i] = sanitize(data[i], { html: false });
			} else {
				sanitizeDeep(data[i], path, depth + 1, safeAttributes);
			}
		}
	}
	return data;
};

module.exports = {
	sanitizeDeep,
	sanitizeConsts: {
		keys,
		paths,
		saveKeys,
		allowedTags,
		allowedSchemes,
		maxDeep,
	},
};
<commit_msg>allow image alt tag<commit_after>/* eslint-disable no-param-reassign */
const sanitizeHtml = require('sanitize-html');

const maxDeep = 12;
// enable html for all current editors
const keys = ['content', 'text', 'comment', 'gradeComment', 'description'];
const paths = ['lessons', 'news', 'newsModel', 'homework', 'submissions'];
const saveKeys = ['password', 'secret'];
const allowedTags = ['h1', 'h2', 'h3', 'blockquote', 'p', 'a', 'ul', 'ol', 's', 'u', 'span', 'del',
	'li', 'b', 'i', 'img', 'strong', 'em', 'strike', 'code', 'hr', 'br', 'div',
	'table', 'thead', 'caption', 'tbody', 'tr', 'th', 'td', 'pre', 'audio', 'video', 'sub', 'sup'];
const allowedSchemes = ['http', 'https', 'ftp', 'mailto'];

// const allowedSchemesByTag = {
// 	// allow base64 image data
// 	img: ['data'],
// };

const allowedAttributes = {
	a: ['href', 'name', 'target'],
	img: ['src', 'width', 'height', 'alt'],
};

const htmlTrueOptions = {
	allowedTags,
	allowedAttributes, // allow all attributes of allowed tags
	allowedSchemes,
	// allowedSchemesByTag, // TODO enable this?
	parser: {
		decodeEntities: true,
	},
	allowedStyles: {
		'*': {
			// Match HEX and RGB
			color: [/^#(0x)?[0-9a-f]+$/i, /^rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/],
			'text-align': [/^left$/, /^right$/, /^center$/],
			// Match any number with px, em, or %
			'font-size': [/^\d+(?:px|em|%)$/],
			'font-style': [/^\w+$/],
		},
	},
};

const htmlFalseOptions = {
	allowedTags: [], // disallow all tags
	allowedAttributes: [], // disallow all attributes
	allowedSchemes: [], // disallow url schemes
	parser: {
		decodeEntities: true,
	},
};

/**
 * sanitizes data
 * @param {*} data
 * @param {*} param
 */
const sanitize = (data, { html = false }) => {
	// https://www.npmjs.com/package/sanitize-html
	if (html === true) {
		// editor-content data
		data = sanitizeHtml(data, htmlTrueOptions);
		data = data.replace(/(<script>).*?(<\/script>)/gim, ''); // force remove script tags
		data = data.replace(/(<script>).*?(<\/script>)/gim, ''); // force remove script tags
	} else {
		// non editor-content data
		data = sanitizeHtml(data, htmlFalseOptions);
	}
	return data;
};

/**
 * disables sanitization for defined keys if a path is matching
 * @param {*} path
 * @param {*} key
 */
const allowedHtmlByPathAndKeys = (path, key) => paths.includes(path) && keys.includes(key);

/**
 * Strips JS/HTML Code from data and returns clean version of it
 * @param data {object/array/string}
 * @param path {string}
 * @param depth {number} -
 * @param safeAttributes {array} - attributes over which sanitization won't be performed
 * @returns data - clean without JS
 */
const sanitizeDeep = (data, path, depth = 0, safeAttributes = []) => {
	if (depth >= maxDeep) {
		throw new Error('Data level is to deep. (sanitizeDeep)', { path, data });
	}
	if (typeof data === 'object' && data !== null) {
		// we have an object, can match strings or recurse child objects
		// eslint-disable-next-line consistent-return
		Object.entries(data).forEach(([key, value]) => {
			if (typeof value === 'string') {
				// ignore values completely
				if (saveKeys.includes(key) || safeAttributes.includes(key)) {
					return data; // TODO:  why not over keys in allowedHtmlByPathAndKeys
				}
				data[key] = sanitize(value, { html: allowedHtmlByPathAndKeys(path, key) });
			} else {
				sanitizeDeep(value, path, depth + 1, safeAttributes);
			}
		});
	} else if (typeof data === 'string') {
		// here we can sanitize the input
		data = sanitize(data, { html: false });
	} else if (Array.isArray(data)) {
		// here we have to check all array elements and sanitize strings or do recursion
		for (let i = 0; i < data.length; i += 1) {
			if (typeof data[i] === 'string') {
				data[i] = sanitize(data[i], { html: false });
			} else {
				sanitizeDeep(data[i], path, depth + 1, safeAttributes);
			}
		}
	}
	return data;
};

module.exports = {
	sanitizeDeep,
	sanitizeConsts: {
		keys,
		paths,
		saveKeys,
		allowedTags,
		allowedSchemes,
		maxDeep,
	},
};
<|endoftext|>


<commit_before>plan(20);

Type("Integer", {
    where: /^-*\d+$/
})

ok(TYPE, "We have a TYPE Module");

ok(TYPE.Integer, "The new type is there");

ok(TYPE.Integer.validate(123), "It matches valid input")

fail(function () {TYPE.Integer.validate("hallo")}, "The passed value ", "It fails on invalid input")

Module("MyTypes", function () {
    Type("PositiveInteger", {
        isa: TYPE.Integer,
        where: function (value) {
            return value > 0
        }
    })
})

ok(MyTypes.PositiveInteger, "Type in custom module is here")
ok(MyTypes.PositiveInteger.validate(10), "It validates valid input")

fail(function () {MyTypes.PositiveInteger.validate(-10)}, "The passed value ", "It fails on invalid input (subtype)")
fail(function () {MyTypes.PositiveInteger.validate("hallo")}, "The passed value ", "It fails on invalid input (supertype)")

ok(MyTypes.PositiveInteger.validate("1325135"), "It validates valid input")
fail(function () {MyTypes.PositiveInteger.validate("123.12")}, "The passed value ", "It fails on invalid input ")

diag("Type Coercion")

Module("MyTypes", function () {
    Type("PositiveIntegerWithCoercion", {
        isa: TYPE.Integer,
        where: function (value) {
            return value > 0
        },
        coerce: [{
            from: TYPE.Integer,
            via:  function (value) {
                return Math.abs(value)
            }
        }]
    })
})

ok(MyTypes.PositiveIntegerWithCoercion, "Type with Coercion is here");
canOk(MyTypes.PositiveIntegerWithCoercion, "coerce")
var value = MyTypes.PositiveIntegerWithCoercion.coerce(-10);
isEq(value, 10, "Coercion works")
var value = MyTypes.PositiveIntegerWithCoercion.coerce("one")
ok(value == null, "Does not coerce wrong values")
var value = MyTypes.PositiveIntegerWithCoercion.coerce(100)
isEq(value, 100, "Leaves correct values alone")

// now just test plain vanilla type constraints in class attributes
diag('type constrained vanilla class attributes');

Type('BooleanTest', {
    where: function(value) {
        if (typeof value == 'boolean') {
            return true;
        }
        return false;
    },
    coerce: [{
            from: TYPE.Integer,
             via:  function (value) {
                if ( value == 0 )
                    return false;
                return true;
            }
        }]
    }
);

Class("BooleanTypeConstrained", {
    has: {
        attr1: {
            is: 'rw',
            isa: TYPE.BooleanTest,
            coerce: true
        }
    }
})

var constrained = new BooleanTypeConstrained({attr1: false});
ok(constrained.getAttr1() == false, "setting boolean constrained to false in constructor succeeds")

ok(constrained.setAttr1(true), 'setting boolean constrained to true succeeds');
fail(function () { constrained.setAttr1('foo')},
    'The passed value [foo] is not a BooleanTest',
    'setting boolean constrained to foo fails');

fail(function () { new BooleanTypeConstrained({attr1: 'foo'})},
    'The passed value [foo] is not a BooleanTest',
    'setting boolean constrained to foo in constructor fails');

fail(function () { new BooleanTypeConstrained({attr1: "one"}) },
    'The passed value [one] is not a BooleanTest',
    'newing up a boolean constrained with non boolean value fails');

ok(constrained.setAttr1(1), 'setting boolean to 1 succeeds');
ok(constrained.getAttr1() !== 1, '...but value was not actually set to 1');
ok(constrained.getAttr1() === true, '1 coerces to boolean true');

ok(constrained.setAttr1(0), 'setting boolean to 0 succeeds');
ok(constrained.getAttr1() !== 0, '...but value was not actually set to 0');
ok(constrained.getAttr1() === false, '0 coerces to boolean false');

ok(new BooleanTypeConstrained({attr1: 1}).getAttr1() == true, "setting boolean to 1 coerces to true in constructor")

//TODO(jwall): attribute coercion tests

endTests()
<commit_msg>Correct number of tests<commit_after>plan(27);

Type("Integer", {
    where: /^-*\d+$/
})

ok(TYPE, "We have a TYPE Module");

ok(TYPE.Integer, "The new type is there");

ok(TYPE.Integer.validate(123), "It matches valid input")

fail(function () {TYPE.Integer.validate("hallo")}, "The passed value ", "It fails on invalid input")

Module("MyTypes", function () {
    Type("PositiveInteger", {
        isa: TYPE.Integer,
        where: function (value) {
            return value > 0
        }
    })
})

ok(MyTypes.PositiveInteger, "Type in custom module is here")
ok(MyTypes.PositiveInteger.validate(10), "It validates valid input")

fail(function () {MyTypes.PositiveInteger.validate(-10)}, "The passed value ", "It fails on invalid input (subtype)")
fail(function () {MyTypes.PositiveInteger.validate("hallo")}, "The passed value ", "It fails on invalid input (supertype)")

ok(MyTypes.PositiveInteger.validate("1325135"), "It validates valid input")
fail(function () {MyTypes.PositiveInteger.validate("123.12")}, "The passed value ", "It fails on invalid input ")

diag("Type Coercion")

Module("MyTypes", function () {
    Type("PositiveIntegerWithCoercion", {
        isa: TYPE.Integer,
        where: function (value) {
            return value > 0
        },
        coerce: [{
            from: TYPE.Integer,
            via:  function (value) {
                return Math.abs(value)
            }
        }]
    })
})

ok(MyTypes.PositiveIntegerWithCoercion, "Type with Coercion is here");
canOk(MyTypes.PositiveIntegerWithCoercion, "coerce")
var value = MyTypes.PositiveIntegerWithCoercion.coerce(-10);
isEq(value, 10, "Coercion works")
var value = MyTypes.PositiveIntegerWithCoercion.coerce("one")
ok(value == null, "Does not coerce wrong values")
var value = MyTypes.PositiveIntegerWithCoercion.coerce(100)
isEq(value, 100, "Leaves correct values alone")

// now just test plain vanilla type constraints in class attributes
diag('type constrained vanilla class attributes');

Type('BooleanTest', {
    where: function(value) {
        if (typeof value == 'boolean') {
            return true;
        }
        return false;
    },
    coerce: [{
            from: TYPE.Integer,
             via:  function (value) {
                if ( value == 0 )
                    return false;
                return true;
            }
        }]
    }
);

Class("BooleanTypeConstrained", {
    has: {
        attr1: {
            is: 'rw',
            isa: TYPE.BooleanTest,
            coerce: true
        }
    }
})

var constrained = new BooleanTypeConstrained({attr1: false});
ok(constrained.getAttr1() == false, "setting boolean constrained to false in constructor succeeds")

ok(constrained.setAttr1(true), 'setting boolean constrained to true succeeds');
fail(function () { constrained.setAttr1('foo')},
    'The passed value [foo] is not a BooleanTest',
    'setting boolean constrained to foo fails');

fail(function () { new BooleanTypeConstrained({attr1: 'foo'})},
    'The passed value [foo] is not a BooleanTest',
    'setting boolean constrained to foo in constructor fails');

fail(function () { new BooleanTypeConstrained({attr1: "one"}) },
    'The passed value [one] is not a BooleanTest',
    'newing up a boolean constrained with non boolean value fails');

ok(constrained.setAttr1(1), 'setting boolean to 1 succeeds');
ok(constrained.getAttr1() !== 1, '...but value was not actually set to 1');
ok(constrained.getAttr1() === true, '1 coerces to boolean true');

ok(constrained.setAttr1(0), 'setting boolean to 0 succeeds');
ok(constrained.getAttr1() !== 0, '...but value was not actually set to 0');
ok(constrained.getAttr1() === false, '0 coerces to boolean false');

ok(new BooleanTypeConstrained({attr1: 1}).getAttr1() == true, "setting boolean to 1 coerces to true in constructor")

//TODO(jwall): attribute coercion tests

endTests()
<|endoftext|>


<commit_before>/*
 * This file is part of Adblock Plus <http://adblockplus.org/>,
 * Copyright (C) 2006-2013 Eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * @fileOverview Downloads a set of URLs in regular time intervals.
 */

let {Utils} = require("utils");

let MILLIS_IN_SECOND = exports.MILLIS_IN_SECOND = 1000;
let MILLIS_IN_MINUTE = exports.MILLIS_IN_MINUTE = 60 * MILLIS_IN_SECOND;
let MILLIS_IN_HOUR = exports.MILLIS_IN_HOUR = 60 * MILLIS_IN_MINUTE;
let MILLIS_IN_DAY = exports.MILLIS_IN_DAY = 24 * MILLIS_IN_HOUR;

/**
 * Creates a new downloader instance.
 * @param {Function} dataSource  Function that will yield downloadable objects on each check
 * @param {Integer} initialDelay  Number of milliseconds to wait before the first check
 * @param {Integer} checkInterval  Interval between the checks
 * @constructor
 */
let Downloader = exports.Downloader = function Downloader(dataSource, initialDelay, checkInterval)
{
  this.dataSource = dataSource;
  this._timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
  this._timer.initWithCallback(function()
  {
    this._timer.delay = checkInterval;
    this._doCheck();
  }.bind(this), initialDelay, Ci.nsITimer.TYPE_REPEATING_SLACK);
  this._downloading = Object.create(null);
}
Downloader.prototype =
{
  /**
   * Timer triggering the downloads.
   * @type nsITimer
   */
  _timer: null,

  /**
   * Map containing the URLs of objects currently being downloaded as its keys.
   */
  _downloading: null,

  /**
   * Function that will yield downloadable objects on each check.
   * @type Function
   */
  dataSource: null,

  /**
   * Maximal time interval that the checks can be left out until the soft
   * expiration interval increases.
   * @type Integer
   */
  maxAbsenseInterval: 1 * MILLIS_IN_DAY,

  /**
   * Minimal time interval before retrying a download after an error.
   * @type Integer
   */
  minRetryInterval: 1 * MILLIS_IN_DAY,

  /**
   * Maximal allowed expiration interval, larger expiration intervals will be
   * corrected.
   * @type Integer
   */
  maxExpirationInterval: 14 * MILLIS_IN_DAY,

  /**
   * Maximal number of redirects before the download is considered as failed.
   * @type Integer
   */
  maxRedirects: 5,

  /**
   * Called whenever expiration intervals for an object need to be adapted.
   * @type Function
   */
  onExpirationChange: null,

  /**
   * Callback to be triggered whenever a download starts.
   * @type Function
   */
  onDownloadStarted: null,

  /**
   * Callback to be triggered whenever a download finishes successfully. The
   * callback can return an error code to indicate that the data is wrong.
   * @type Function
   */
  onDownloadSuccess: null,

  /**
   * Callback to be triggered whenever a download fails.
   * @type Function
   */
  onDownloadError: null,

  /**
   * Checks whether anything needs downloading.
   */
  _doCheck: function()
  {
    let now = Date.now();
    for each (let downloadable in this.dataSource())
    {
      if (downloadable.lastCheck && now - downloadable.lastCheck > this.maxAbsenseInterval)
      {
        // No checks for a long time interval - user must have been offline, e.g.
        // during a weekend. Increase soft expiration to prevent load peaks on the
        // server.
        downloadable.softExpiration += now - downloadable.lastCheck;
      }
      downloadable.lastCheck = now;

      // Sanity check: do expiration times make sense? Make sure people changing
      // system clock don't get stuck with outdated subscriptions.
      if (downloadable.hardExpiration - now > this.maxExpirationInterval)
        downloadable.hardExpiration = now + this.maxExpirationInterval;
      if (downloadable.softExpiration - now > this.maxExpirationInterval)
        downloadable.softExpiration = now + this.maxExpirationInterval;

      // Notify the caller about changes to expiration parameters
      if (this.onExpirationChange)
        this.onExpirationChange(downloadable);

      // Does that object need downloading?
      if (downloadable.softExpiration > now && downloadable.hardExpiration > now)
        continue;

      // Do not retry downloads too often
      if (downloadable.lastError && now - downloadable.lastError < this.minRetryInterval)
        continue;

      this._download(downloadable, 0);
    }
  },

  /**
   * Stops the periodic checks.
   */
  cancel: function()
  {
    this._timer.cancel();
  },

  /**
   * Checks whether an address is currently being downloaded.
   */
  isDownloading: function(/**String*/ url) /**Boolean*/
  {
    return url in this._downloading;
  },

  /**
   * Starts a download.
   * @param {Downloadable} url  the object to be downloaded
   */
  download: function(downloadable)
  {
    // Make sure to detach download from the current execution context
    Utils.runAsync(this._download.bind(this, downloadable, 0));
  },

  /**
   * Generates the real download URL for an object by appending various
   * parameters.
   */
  getDownloadUrl: function(/**Downloadable*/ downloadable)  /** String*/
  {
    let {addonName, addonVersion, application} = require("info");
    let url = downloadable.redirectURL || downloadable.url;
    if (url.indexOf("?") >= 0)
      url += "&";
    else
      url += "?";
    url += "addonName=" + encodeURIComponent(addonName) +
        "&addonVersion=" + encodeURIComponent(addonVersion) +
        "&application=" + encodeURIComponent(application) +
        "&lastVersion=" + encodeURIComponent(downloadable.lastVersion);
    return url;
  },

  _download: function(downloadable, redirects)
  {
    if (downloadable.url in this._downloading)
      return;

    let downloadURL = this.getDownloadUrl(downloadable);
    let request = null;

    let errorCallback = function errorCallback(error)
    {
      let channelStatus = -1;
      try
      {
        channelStatus = request.channel.status;
      } catch (e) {}

      let responseStatus = "";
      try
      {
        responseStatus = request.channel.QueryInterface(Ci.nsIHttpChannel).responseStatus;
      } catch (e) {}

      Cu.reportError("Adblock Plus: Downloading URL " + downloadable.url + " failed (" + error + ")\n" +
                     "Download address: " + downloadURL + "\n" +
                     "Channel status: " + channelStatus + "\n" +
                     "Server response: " + responseStatus);

      if (this.onDownloadError)
      {
        // Allow one extra redirect if the error handler gives us a redirect URL
        let redirectCallback = null;
        if (redirects <= this.maxRedirects)
        {
          redirectCallback = function redirectCallback(url)
          {
            downloadable.redirectURL = url;
            this._download(downloadable, redirects + 1);
          }.bind(this);
        }

        this.onDownloadError(downloadable, downloadURL, error, channelStatus, responseStatus, redirectCallback);
      }
    }.bind(this);

    try
    {
      request = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest);
      request.mozBackgroundRequest = true;
      request.open("GET", downloadURL);
    }
    catch (e)
    {
      errorCallback("synchronize_invalid_url");
      return;
    }

    try {
      request.overrideMimeType("text/plain");
      request.channel.loadFlags = request.channel.loadFlags |
                                  request.channel.INHIBIT_CACHING |
                                  request.channel.VALIDATE_ALWAYS;

      // Override redirect limit from preferences, user might have set it to 1
      if (request.channel instanceof Ci.nsIHttpChannel)
        request.channel.redirectionLimit = this.maxRedirects;
    }
    catch (e)
    {
      Cu.reportError(e)
    }

    request.addEventListener("error", function(event)
    {
      if (onShutdown.done)
        return;

      delete this._downloading[downloadable.url];
      errorCallback("synchronize_connection_error");
    }.bind(this), false);

    request.addEventListener("load", function(event)
    {
      if (onShutdown.done)
        return;

      delete this._downloading[downloadable.url];

      // Status will be 0 for non-HTTP requests
      if (request.status && request.status != 200)
      {
        errorCallback("synchronize_connection_error");
        return;
      }

      this.onDownloadSuccess(downloadable, request.responseText, errorCallback, function redirectCallback(url)
      {
        if (redirects >= this.maxRedirects)
          errorCallback("synchronize_connection_error");
        else
        {
          downloadable.redirectURL = url;
          this._download(downloadable, redirects + 1);
        }
      }.bind(this));
    }.bind(this), false);

    this._downloading[downloadable.url] = true;
    if (this.onDownloadStarted)
      this.onDownloadStarted(downloadable);
    request.send(null);
  },

  /**
   * Produces a soft and a hard expiration interval for a given supplied
   * expiration interval.
   * @return {Array} soft and hard expiration interval
   */
  processExpirationInterval: function(/**Integer*/ interval)
  {
    interval = Math.min(Math.max(interval, 0), this.maxExpirationInterval);
    let soft = Math.round(interval * (Math.random() * 0.4 + 0.8));
    let hard = interval * 2;
    let now = Date.now();
    return [now + soft, now + hard];
  }
};

/**
 * An object that can be downloaded by the downloadable
 * @param {String} url  URL that has to be requested for the object
 * @constructor
 */
let Downloadable = exports.Downloadable = function Downloadable(url)
{
  this.url = url;
}
Downloadable.prototype =
{
  /**
   * URL that has to be requested for the object.
   * @type String
   */
  url: null,

  /**
   * URL that the download was redirected to if any.
   * @type String
   */
  redirectURL: null,

  /**
   * Time of last download error or 0 if the last download was successful.
   * @type Integer
   */
  lastError: 0,

  /**
   * Time of last check whether the object needs downloading.
   * @type Integer
   */
  lastCheck: 0,

  /**
   * Object version corresponding to the last successful download.
   * @type Integer
   */
  lastVersion: 0,

  /**
   * Soft expiration interval, will increase if no checks are performed for a
   * while.
   * @type Integer
   */
  softExpiration: 0,

  /**
   * Hard expiration interval, this is fixed.
   * @type Integer
   */
  hardExpiration: 0,
};
<commit_msg>Added more parameters to the requests made by downloader https://hg.adblockplus.org/adblockplus/rev/2eeca9ca0b7a Author: Wladimir Palant<commit_after>/*
 * This file is part of Adblock Plus <http://adblockplus.org/>,
 * Copyright (C) 2006-2013 Eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * @fileOverview Downloads a set of URLs in regular time intervals.
 */

let {Utils} = require("utils");

let MILLIS_IN_SECOND = exports.MILLIS_IN_SECOND = 1000;
let MILLIS_IN_MINUTE = exports.MILLIS_IN_MINUTE = 60 * MILLIS_IN_SECOND;
let MILLIS_IN_HOUR = exports.MILLIS_IN_HOUR = 60 * MILLIS_IN_MINUTE;
let MILLIS_IN_DAY = exports.MILLIS_IN_DAY = 24 * MILLIS_IN_HOUR;

/**
 * Creates a new downloader instance.
 * @param {Function} dataSource  Function that will yield downloadable objects on each check
 * @param {Integer} initialDelay  Number of milliseconds to wait before the first check
 * @param {Integer} checkInterval  Interval between the checks
 * @constructor
 */
let Downloader = exports.Downloader = function Downloader(dataSource, initialDelay, checkInterval)
{
  this.dataSource = dataSource;
  this._timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
  this._timer.initWithCallback(function()
  {
    this._timer.delay = checkInterval;
    this._doCheck();
  }.bind(this), initialDelay, Ci.nsITimer.TYPE_REPEATING_SLACK);
  this._downloading = Object.create(null);
}
Downloader.prototype =
{
  /**
   * Timer triggering the downloads.
   * @type nsITimer
   */
  _timer: null,

  /**
   * Map containing the URLs of objects currently being downloaded as its keys.
   */
  _downloading: null,

  /**
   * Function that will yield downloadable objects on each check.
   * @type Function
   */
  dataSource: null,

  /**
   * Maximal time interval that the checks can be left out until the soft
   * expiration interval increases.
   * @type Integer
   */
  maxAbsenseInterval: 1 * MILLIS_IN_DAY,

  /**
   * Minimal time interval before retrying a download after an error.
   * @type Integer
   */
  minRetryInterval: 1 * MILLIS_IN_DAY,

  /**
   * Maximal allowed expiration interval, larger expiration intervals will be
   * corrected.
   * @type Integer
   */
  maxExpirationInterval: 14 * MILLIS_IN_DAY,

  /**
   * Maximal number of redirects before the download is considered as failed.
   * @type Integer
   */
  maxRedirects: 5,

  /**
   * Called whenever expiration intervals for an object need to be adapted.
   * @type Function
   */
  onExpirationChange: null,

  /**
   * Callback to be triggered whenever a download starts.
   * @type Function
   */
  onDownloadStarted: null,

  /**
   * Callback to be triggered whenever a download finishes successfully. The
   * callback can return an error code to indicate that the data is wrong.
   * @type Function
   */
  onDownloadSuccess: null,

  /**
   * Callback to be triggered whenever a download fails.
   * @type Function
   */
  onDownloadError: null,

  /**
   * Checks whether anything needs downloading.
   */
  _doCheck: function()
  {
    let now = Date.now();
    for each (let downloadable in this.dataSource())
    {
      if (downloadable.lastCheck && now - downloadable.lastCheck > this.maxAbsenseInterval)
      {
        // No checks for a long time interval - user must have been offline, e.g.
        // during a weekend. Increase soft expiration to prevent load peaks on the
        // server.
        downloadable.softExpiration += now - downloadable.lastCheck;
      }
      downloadable.lastCheck = now;

      // Sanity check: do expiration times make sense? Make sure people changing
      // system clock don't get stuck with outdated subscriptions.
      if (downloadable.hardExpiration - now > this.maxExpirationInterval)
        downloadable.hardExpiration = now + this.maxExpirationInterval;
      if (downloadable.softExpiration - now > this.maxExpirationInterval)
        downloadable.softExpiration = now + this.maxExpirationInterval;

      // Notify the caller about changes to expiration parameters
      if (this.onExpirationChange)
        this.onExpirationChange(downloadable);

      // Does that object need downloading?
      if (downloadable.softExpiration > now && downloadable.hardExpiration > now)
        continue;

      // Do not retry downloads too often
      if (downloadable.lastError && now - downloadable.lastError < this.minRetryInterval)
        continue;

      this._download(downloadable, 0);
    }
  },

  /**
   * Stops the periodic checks.
   */
  cancel: function()
  {
    this._timer.cancel();
  },

  /**
   * Checks whether an address is currently being downloaded.
   */
  isDownloading: function(/**String*/ url) /**Boolean*/
  {
    return url in this._downloading;
  },

  /**
   * Starts a download.
   * @param {Downloadable} url  the object to be downloaded
   */
  download: function(downloadable)
  {
    // Make sure to detach download from the current execution context
    Utils.runAsync(this._download.bind(this, downloadable, 0));
  },

  /**
   * Generates the real download URL for an object by appending various
   * parameters.
   */
  getDownloadUrl: function(/**Downloadable*/ downloadable)  /** String*/
  {
    let {addonName, addonVersion, application, applicationVersion, platform, platformVersion} = require("info");
    let url = downloadable.redirectURL || downloadable.url;
    if (url.indexOf("?") >= 0)
      url += "&";
    else
      url += "?";
    url += "addonName=" + encodeURIComponent(addonName) +
        "&addonVersion=" + encodeURIComponent(addonVersion) +
        "&application=" + encodeURIComponent(application) +
        "&applicationVersion=" + encodeURIComponent(applicationVersion) +
        "&platform=" + encodeURIComponent(platform) +
        "&platformVersion=" + encodeURIComponent(platformVersion) +
        "&lastVersion=" + encodeURIComponent(downloadable.lastVersion);
    return url;
  },

  _download: function(downloadable, redirects)
  {
    if (downloadable.url in this._downloading)
      return;

    let downloadURL = this.getDownloadUrl(downloadable);
    let request = null;

    let errorCallback = function errorCallback(error)
    {
      let channelStatus = -1;
      try
      {
        channelStatus = request.channel.status;
      } catch (e) {}

      let responseStatus = "";
      try
      {
        responseStatus = request.channel.QueryInterface(Ci.nsIHttpChannel).responseStatus;
      } catch (e) {}

      Cu.reportError("Adblock Plus: Downloading URL " + downloadable.url + " failed (" + error + ")\n" +
                     "Download address: " + downloadURL + "\n" +
                     "Channel status: " + channelStatus + "\n" +
                     "Server response: " + responseStatus);

      if (this.onDownloadError)
      {
        // Allow one extra redirect if the error handler gives us a redirect URL
        let redirectCallback = null;
        if (redirects <= this.maxRedirects)
        {
          redirectCallback = function redirectCallback(url)
          {
            downloadable.redirectURL = url;
            this._download(downloadable, redirects + 1);
          }.bind(this);
        }

        this.onDownloadError(downloadable, downloadURL, error, channelStatus, responseStatus, redirectCallback);
      }
    }.bind(this);

    try
    {
      request = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest);
      request.mozBackgroundRequest = true;
      request.open("GET", downloadURL);
    }
    catch (e)
    {
      errorCallback("synchronize_invalid_url");
      return;
    }

    try {
      request.overrideMimeType("text/plain");
      request.channel.loadFlags = request.channel.loadFlags |
                                  request.channel.INHIBIT_CACHING |
                                  request.channel.VALIDATE_ALWAYS;

      // Override redirect limit from preferences, user might have set it to 1
      if (request.channel instanceof Ci.nsIHttpChannel)
        request.channel.redirectionLimit = this.maxRedirects;
    }
    catch (e)
    {
      Cu.reportError(e)
    }

    request.addEventListener("error", function(event)
    {
      if (onShutdown.done)
        return;

      delete this._downloading[downloadable.url];
      errorCallback("synchronize_connection_error");
    }.bind(this), false);

    request.addEventListener("load", function(event)
    {
      if (onShutdown.done)
        return;

      delete this._downloading[downloadable.url];

      // Status will be 0 for non-HTTP requests
      if (request.status && request.status != 200)
      {
        errorCallback("synchronize_connection_error");
        return;
      }

      this.onDownloadSuccess(downloadable, request.responseText, errorCallback, function redirectCallback(url)
      {
        if (redirects >= this.maxRedirects)
          errorCallback("synchronize_connection_error");
        else
        {
          downloadable.redirectURL = url;
          this._download(downloadable, redirects + 1);
        }
      }.bind(this));
    }.bind(this), false);

    this._downloading[downloadable.url] = true;
    if (this.onDownloadStarted)
      this.onDownloadStarted(downloadable);
    request.send(null);
  },

  /**
   * Produces a soft and a hard expiration interval for a given supplied
   * expiration interval.
   * @return {Array} soft and hard expiration interval
   */
  processExpirationInterval: function(/**Integer*/ interval)
  {
    interval = Math.min(Math.max(interval, 0), this.maxExpirationInterval);
    let soft = Math.round(interval * (Math.random() * 0.4 + 0.8));
    let hard = interval * 2;
    let now = Date.now();
    return [now + soft, now + hard];
  }
};

/**
 * An object that can be downloaded by the downloadable
 * @param {String} url  URL that has to be requested for the object
 * @constructor
 */
let Downloadable = exports.Downloadable = function Downloadable(url)
{
  this.url = url;
}
Downloadable.prototype =
{
  /**
   * URL that has to be requested for the object.
   * @type String
   */
  url: null,

  /**
   * URL that the download was redirected to if any.
   * @type String
   */
  redirectURL: null,

  /**
   * Time of last download error or 0 if the last download was successful.
   * @type Integer
   */
  lastError: 0,

  /**
   * Time of last check whether the object needs downloading.
   * @type Integer
   */
  lastCheck: 0,

  /**
   * Object version corresponding to the last successful download.
   * @type Integer
   */
  lastVersion: 0,

  /**
   * Soft expiration interval, will increase if no checks are performed for a
   * while.
   * @type Integer
   */
  softExpiration: 0,

  /**
   * Hard expiration interval, this is fixed.
   * @type Integer
   */
  hardExpiration: 0,
};
<|endoftext|>


<commit_before>var fs = require('fs');
var addon = require('../build/Release/avro');

var Buffer = require('buffer').Buffer;

var avro = new addon.Avro();

avro.onerror = function(error){
  console.log(error);
};

var buildingSchema = '{\
    "name": "com.gensler.models.organizations.Organization",\
    "type": "record",\
    "fields": [\
      { "name": "id", "type": \
        {\
          "name": "com.gensler.models.common.GUID",\
          "type": "record",\
          "fields": [\
            { "name": "bytes", "type": "bytes"}\
          ]\
        }\
      },\
      { "name": "name", "type": "string" },\
      { "name": "organizationType", "type": "string" }\
    ]\
  }';

var complexSchema = '{\
  "name": "com.gensler.organizations.GetOrganization",\
  "type": "record",\
  "fields": [\
    { "name": "id", "type": \
      {\
        "name": "com.gensler.models.common.GUID",\
        "type": "record",\
        "fields": [\
          { "name": "bytes", "type": "bytes"}\
        ]\
      }\
    }\
  ]\
}';

var map = '{"type": "map","values": "bytes"}';
// Some of the types supported
// TODO finish off examples.
var mapResult = avro.decodeDatum(map, new Buffer(avro.encodeDatum(map, {sequence: new Buffer(avro.encodeDatum('"long"', 12345))})));
var booleanResult = avro.decodeDatum('"boolean"', new Buffer(avro.encodeDatum('"boolean"', true )));
var stringResult = avro.decodeDatum('"string"', new Buffer(avro.encodeDatum('"string"', "A string to parse" )));
var complexResult = avro.decodeDatum(complexSchema, new Buffer(avro.encodeDatum(complexSchema, { id: { bytes: new Buffer([8,-85,-51,18,52]) }})));
var longResult = avro.decodeDatum('"long"', new Buffer(avro.encodeDatum('"long"', 12345)));

console.log("boolean result: ", booleanResult);
console.log("map result: ", mapResult);
console.log("long result: ", longResult);
console.log("string result: ", stringResult);
console.log("complex result: ", complexResult);

//Since avro starts another thread in the background for reading data to stop node
// we need to send a kill to the process.
process.kill();<commit_msg>removing local only websocket examples. Generic == win<commit_after>var fs = require('fs');
var addon = require('../build/Release/avro');

var Buffer = require('buffer').Buffer;

var avro = new addon.Avro();

avro.onerror = function(error){
  console.log(error);
};

var buildingSchema = '{\
    "name": "Organization",\
    "type": "record",\
    "fields": [\
      { "name": "id", "type": \
        {\
          "name": "GUID",\
          "type": "record",\
          "fields": [\
            { "name": "bytes", "type": "bytes"}\
          ]\
        }\
      },\
      { "name": "name", "type": "string" },\
      { "name": "organizationType", "type": "string" }\
    ]\
  }';

var complexSchema = '{\
  "name": "GetOrganization",\
  "type": "record",\
  "fields": [\
    { "name": "id", "type": \
      {\
        "name": "common.GUID",\
        "type": "record",\
        "fields": [\
          { "name": "bytes", "type": "bytes"}\
        ]\
      }\
    }\
  ]\
}';

var map = '{"type": "map","values": "bytes"}';
// Some of the types supported
// TODO finish off examples.
var mapResult = avro.decodeDatum(map, new Buffer(avro.encodeDatum(map, {sequence: new Buffer(avro.encodeDatum('"long"', 12345))})));
var booleanResult = avro.decodeDatum('"boolean"', new Buffer(avro.encodeDatum('"boolean"', true )));
var stringResult = avro.decodeDatum('"string"', new Buffer(avro.encodeDatum('"string"', "A string to parse" )));
var complexResult = avro.decodeDatum(complexSchema, new Buffer(avro.encodeDatum(complexSchema, { id: { bytes: new Buffer([8,-85,-51,18,52]) }})));
var longResult = avro.decodeDatum('"long"', new Buffer(avro.encodeDatum('"long"', 12345)));

console.log("boolean result: ", booleanResult);
console.log("map result: ", mapResult);
console.log("long result: ", longResult);
console.log("string result: ", stringResult);
console.log("complex result: ", complexResult);

//Since avro starts another thread in the background for reading data to stop node
// we need to send a kill to the process.
process.kill();<|endoftext|>