module.exports = (function() {
var __MODS__ = {};
var __DEFINE__ = function(modId, func, req) { var m = { exports: {}, _tempexports: {} }; __MODS__[modId] = { status: 0, func: func, req: req, m: m }; };
var __REQUIRE__ = function(modId, source) { if(!__MODS__[modId]) return require(source); if(!__MODS__[modId].status) { var m = __MODS__[modId].m; m._exports = m._tempexports; var desp = Object.getOwnPropertyDescriptor(m, "exports"); if (desp && desp.configurable) Object.defineProperty(m, "exports", { set: function (val) { if(typeof val === "object" && val !== m._exports) { m._exports.__proto__ = val.__proto__; Object.keys(val).forEach(function (k) { m._exports[k] = val[k]; }); } m._tempexports = val }, get: function () { return m._tempexports; } }); __MODS__[modId].status = 1; __MODS__[modId].func(__MODS__[modId].req, m, m.exports); } return __MODS__[modId].m.exports; };
var __REQUIRE_WILDCARD__ = function(obj) { if(obj && obj.__esModule) { return obj; } else { var newObj = {}; if(obj != null) { for(var k in obj) { if (Object.prototype.hasOwnProperty.call(obj, k)) newObj[k] = obj[k]; } } newObj.default = obj; return newObj; } };
var __REQUIRE_DEFAULT__ = function(obj) { return obj && obj.__esModule ? obj.default : obj; };
__DEFINE__(1738455898207, function(require, module, exports) {
var Client = require('./client')
  , Server = require('./server')
  , CustomType = require('./customtype')
  , dateFormatter = require('./date_formatter')

var xmlrpc = exports

/**
 * Creates an XML-RPC client.
 *
 * @param {Object} options - server options to make the HTTP request to
 *   - {String} host
 *   - {Number} port
 *   - {String} url
 *   - {Boolean} cookies
 * @return {Client}
 * @see Client
 */
xmlrpc.createClient = function(options) {
  return new Client(options, false)
}

/**
 * Creates an XML-RPC client that makes calls using HTTPS.
 *
 * @param {Object} options - server options to make the HTTP request to
 *   - {String} host
 *   - {Number} port
 *   - {String} url
 *   - {Boolean} cookies
 * @return {Client}
 * @see Client
 */
xmlrpc.createSecureClient = function(options) {
  return new Client(options, true)
}

/**
 * Creates an XML-RPC server.
 *
 * @param {Object}options - the HTTP server options
 *   - {String} host
 *   - {Number} port
 * @return {Server}
 * @see Server
 */
xmlrpc.createServer = function(options, callback) {
  return new Server(options, false, callback)
}

/**
 * Creates an XML-RPC server that uses HTTPS.
 *
 * @param {Object}options - the HTTP server options
 *   - {String} host
 *   - {Number} port
 * @return {Server}
 * @see Server
 */
xmlrpc.createSecureServer = function(options, callback) {
  return new Server(options, true, callback)
}

xmlrpc.CustomType = CustomType
xmlrpc.dateFormatter = dateFormatter

}, function(modId) {var map = {"./client":1738455898208,"./server":1738455898214,"./customtype":1738455898211,"./date_formatter":1738455898210}; return __REQUIRE__(map[modId], modId); })
__DEFINE__(1738455898208, function(require, module, exports) {
var http         = require('http')
  , https        = require('https')
  , url          = require('url')
  , Serializer   = require('./serializer')
  , Deserializer = require('./deserializer')
  , Cookies      = require('./cookies')

/**
 * Creates a Client object for making XML-RPC method calls.
 *
 * @constructor
 * @param {Object|String} options - Server options to make the HTTP request to.
 *                                  Either a URI string
 *                                  (e.g. 'http://localhost:9090') or an object
 *                                  with fields:
 *   - {String} host              - (optional)
 *   - {Number} port
 *   - {String} url               - (optional) - may be used instead of host/port pair
 *   - {Boolean} cookies          - (optional) - if true then cookies returned by server will be stored and sent back on the next calls.
 *                                  Also it will be possible to access/manipulate cookies via #setCookie/#getCookie methods
 * @param {Boolean} isSecure      - True if using https for making calls,
 *                                  otherwise false.
 * @return {Client}
 */
function Client(options, isSecure) {

  // Invokes with new if called without
  if (false === (this instanceof Client)) {
    return new Client(options, isSecure)
  }

  // If a string URI is passed in, converts to URI fields
  if (typeof options === 'string') {
    options = url.parse(options)
    options.host = options.hostname
    options.path = options.pathname
  }

  if (typeof options.url !== 'undefined') {
    var parsedUrl = url.parse(options.url);
    options.host = parsedUrl.hostname;
    options.path = parsedUrl.pathname;
    options.port = parsedUrl.port;
  }

  // Set the HTTP request headers
  var headers = {
    'User-Agent'     : 'NodeJS XML-RPC Client'
  , 'Content-Type'   : 'text/xml'
  , 'Accept'         : 'text/xml'
  , 'Accept-Charset' : 'UTF8'
  , 'Connection'     : 'Keep-Alive'
  }
  options.headers = options.headers || {}

  if (options.headers.Authorization == null &&
      options.basic_auth != null &&
      options.basic_auth.user != null &&
      options.basic_auth.pass != null)
  {
    var auth = options.basic_auth.user + ':' + options.basic_auth.pass
    options.headers['Authorization'] = 'Basic ' + new Buffer(auth).toString('base64')
  }

  for (var attribute in headers) {
    if (options.headers[attribute] === undefined) {
      options.headers[attribute] = headers[attribute]
    }
  }

  options.method = 'POST'
  this.options = options

  this.isSecure = isSecure
  this.headersProcessors = {
    processors: [],
    composeRequest: function(headers) {
      this.processors.forEach(function(p) {p.composeRequest(headers);})
    },
    parseResponse: function(headers) {
      this.processors.forEach(function(p) {p.parseResponse(headers);})
    }
  };
  if (options.cookies) {
    this.cookies = new Cookies();
    this.headersProcessors.processors.unshift(this.cookies);
  }
}

/**
 * Makes an XML-RPC call to the server specified by the constructor's options.
 *
 * @param {String} method     - The method name.
 * @param {Array} params      - Params to send in the call.
 * @param {Function} callback - function(error, value) { ... }
 *   - {Object|null} error    - Any errors when making the call, otherwise null.
 *   - {mixed} value          - The value returned in the method response.
 */
Client.prototype.methodCall = function methodCall(method, params, callback) {
  var options   = this.options
  var xml       = Serializer.serializeMethodCall(method, params, options.encoding)
  var transport = this.isSecure ? https : http

  options.headers['Content-Length'] = Buffer.byteLength(xml, 'utf8')
  this.headersProcessors.composeRequest(options.headers)
  var request = transport.request(options, function(response) {

    var body = []
    response.on('data', function (chunk) { body.push(chunk) })

    function __enrichError (err) {
      Object.defineProperty(err, 'req', { value: request })
      Object.defineProperty(err, 'res', { value: response })
      Object.defineProperty(err, 'body', { value: body.join('') })
      return err
    }

    if (response.statusCode == 404) {
      callback(__enrichError(new Error('Not Found')))
    }
    else {
      this.headersProcessors.parseResponse(response.headers)

      var deserializer = new Deserializer(options.responseEncoding)

      deserializer.deserializeMethodResponse(response, function(err, result) {
        if (err) {
          err = __enrichError(err)
        }
        callback(err, result)
      })
    }
  }.bind(this))

  request.on('error', callback)
  request.write(xml, 'utf8')
  request.end()
}

/**
 * Gets the cookie value by its name. The latest value received from servr with 'Set-Cookie' header is returned
 * Note that method throws an error if cookies were not turned on during client creation (see comments for constructor)
 *
 * @param {String} name name of the cookie to be obtained or changed
 * @return {*} cookie's value
 */
Client.prototype.getCookie = function getCookie(name) {
  if (!this.cookies) {
    throw 'Cookies support is not turned on for this client instance';
  }
  return this.cookies.get(name);
}

/**
 * Sets the cookie value by its name. The cookie will be sent to the server during the next xml-rpc call.
 * The method returns client itself, so it is possible to chain calls like the following:
 *
 * <code>
 *   client.cookie('login', 'alex').cookie('password', '123');
 * </code>
 *
 * Note that method throws an error if cookies were not turned on during client creation (see comments for constructor)
 *
 * @param {String} name name of the cookie to be changed
 * @param {String} value value to be set.
 * @return {*} client object itself
 */
Client.prototype.setCookie = function setCookie(name, value) {
  if (!this.cookies) {
    throw 'Cookies support is not turned on for this client instance';
  }
  this.cookies.set(name, value);
  return this;
}

module.exports = Client


}, function(modId) { var map = {"./serializer":1738455898209,"./deserializer":1738455898212,"./cookies":1738455898213}; return __REQUIRE__(map[modId], modId); })
__DEFINE__(1738455898209, function(require, module, exports) {
var xmlBuilder    = require('xmlbuilder')
  , dateFormatter = require('./date_formatter')
  , CustomType    = require('./customtype')

/**
 * Creates the XML for an XML-RPC method call.
 *
 * @param {String} method     - The method name.
 * @param {Array} params      - Params to pass in the call.
 * @param {Function} callback - function (error, xml) { ... }
 *   - {Object|null} error    - Any errors that occurred while building the XML,
 *                              otherwise null.
 *   - {String} xml           - The method call XML.
 */
exports.serializeMethodCall = function(method, params, encoding) {
  var params = params || []

  var options = { version: '1.0', allowSurrogateChars: true }

  if (encoding) {
    options.encoding = encoding
  }

  var xml = xmlBuilder.create('methodCall', options)
    .ele('methodName')
      .txt(method)
    .up()
    .ele('params')

  params.forEach(function(param) {
    serializeValue(param, xml.ele('param'))
  })

  // Includes the <?xml ...> declaration
  return xml.doc().toString()
}

/**
 * Creates the XML for an XML-RPC method response.
 *
 * @param {mixed} value       - The value to pass in the response.
 * @param {Function} callback - function (error, xml) { ... }
 *   - {Object|null} error    - Any errors that occurred while building the XML,
 *                              otherwise null.
 *   - {String} xml           - The method response XML.
 */
exports.serializeMethodResponse = function(result) {
  var xml = xmlBuilder.create('methodResponse', { version: '1.0', allowSurrogateChars: true })
    .ele('params')
      .ele('param')

  serializeValue(result, xml)

  // Includes the <?xml ...> declaration
  return xml.doc().toString()
}

exports.serializeFault = function(fault) {
  var xml = xmlBuilder.create('methodResponse', { version: '1.0', allowSurrogateChars: true })
    .ele('fault')

  serializeValue(fault, xml)

  // Includes the <?xml ...> declaration
  return xml.doc().toString()
}

function serializeValue(value, xml) {
  var stack     = [ { value: value, xml: xml } ]
    , current   = null
    , valueNode = null
    , next      = null

  while (stack.length > 0) {
    current = stack[stack.length - 1]

    if (current.index !== undefined) {
      // Iterating a compound
      next = getNextItemsFrame(current)
      if (next) {
        stack.push(next)
      }
      else {
        stack.pop()
      }
    }
    else {
      // we're about to add a new value (compound or simple)
      valueNode = current.xml.ele('value')
      switch(typeof current.value) {
        case 'boolean':
          appendBoolean(current.value, valueNode)
          stack.pop()
          break
        case 'string':
          appendString(current.value, valueNode)
          stack.pop()
          break
        case 'number':
          appendNumber(current.value, valueNode)
          stack.pop()
          break
        case 'object':
          if (current.value === null) {
            valueNode.ele('nil')
            stack.pop()
          }
          else if (current.value instanceof Date) {
            appendDatetime(current.value, valueNode)
            stack.pop()
          }
          else if (Buffer.isBuffer(current.value)) {
            appendBuffer(current.value, valueNode)
            stack.pop()
          }
          else if (current.value instanceof CustomType) {
            current.value.serialize(valueNode)
            stack.pop()
          }
          else {
            if (Array.isArray(current.value)) {
              current.xml = valueNode.ele('array').ele('data')
            }
            else {
              current.xml = valueNode.ele('struct')
              current.keys = Object.keys(current.value)
            }
            current.index = 0
            next = getNextItemsFrame(current)
            if (next) {
              stack.push(next)
            }
            else {
              stack.pop()
            }
          }
          break
        default:
          stack.pop()
          break
      }
    }
  }
}

function getNextItemsFrame(frame) {
  var nextFrame = null

  if (frame.keys) {
    if (frame.index < frame.keys.length) {
      var key    = frame.keys[frame.index++]
        , member = frame.xml.ele('member').ele('name').text(key).up()
      nextFrame = {
        value: frame.value[key]
      , xml: member
      }
    }
  }
  else if (frame.index < frame.value.length) {
    nextFrame = {
      value: frame.value[frame.index]
    , xml: frame.xml
    }
    frame.index++
  }

  return nextFrame
}

function appendBoolean(value, xml) {
  xml.ele('boolean').txt(value ? 1 : 0)
}

var illegalChars = /^(?![^<&]*]]>[^<&]*)[^<&]*$/
function appendString(value, xml) {
  if (value.length === 0) {
    xml.ele('string')
  }
  else if (!illegalChars.test(value)) {
    xml.ele('string').d(value)
  }
  else {
    xml.ele('string').txt(value)
  }
}

function appendNumber(value, xml) {
  if (value % 1 == 0) {
    xml.ele('int').txt(value)
  }
  else {
    xml.ele('double').txt(value)
  }
}

function appendDatetime(value, xml) {
  xml.ele('dateTime.iso8601').txt(dateFormatter.encodeIso8601(value))
}

function appendBuffer(value, xml) {
  xml.ele('base64').txt(value.toString('base64'))
}

}, function(modId) { var map = {"./date_formatter":1738455898210,"./customtype":1738455898211}; return __REQUIRE__(map[modId], modId); })
__DEFINE__(1738455898210, function(require, module, exports) {
/**
 * @class DateFormatter
 * The DateFormatter supports decoding from and encoding to
 * ISO8601 formatted strings. Accepts formats with and without
 * hyphen/colon separators and correctly parses zoning info.
 */
var DateFormatter = function (opts) {
  this.opts = {}
  this.setOpts(opts)
}

/**
 * Default options for DateFormatter
 * @static
 * @see DateFormatter#setOpts
 */
DateFormatter.DEFAULT_OPTIONS = {
  colons: true
, hyphens: false
, local: true
, ms: false
, offset: false
}

/**
 * Regular Expression that disects ISO 8601 formatted strings into
 * an array of parts.
 * @static
 */
DateFormatter.ISO8601 = new RegExp(
  '([0-9]{4})([-]?([0-9]{2}))([-]?([0-9]{2}))'
+ '(T([0-9]{2})(((:?([0-9]{2}))?((:?([0-9]{2}))?(\.([0-9]+))?))?)'
+ '(Z|([+-]([0-9]{2}(:?([0-9]{2}))?)))?)?'
)

/**
 * Sets options for encoding Date objects to ISO8601 strings.
 *    Omitting the 'opts' argument will reset all options to the default.
 *
 * @param {Object} opts - Options (optional)
 * @param {Boolean} opts.colons  - Enable/disable formatting the time portion
 *                                 with a colon as separator (default: true)
 * @param {Boolean} opts.hyphens - Enable/disable formatting the date portion
 *                                 with a hyphen as separator (default: false)
 * @param {Boolean} opts.local   - Encode as local time instead of UTC
 *                                 (default: true)
 * @param {Boolean} opts.ms      - Enable/Disable output of milliseconds
 *                                 (default: false)
 * @param {Boolean} opts.offset  - Enable/Disable output of UTC offset
 *                                 (default: false)
 */
DateFormatter.prototype.setOpts = function (opts) {
  if (!opts) opts = DateFormatter.DEFAULT_OPTIONS

  var ctx = this
  Object.keys(DateFormatter.DEFAULT_OPTIONS).forEach(function (k) {
    ctx.opts[k] = opts.hasOwnProperty(k) ?
      opts[k] : DateFormatter.DEFAULT_OPTIONS[k]
  })
}

/**
 * Converts a date time stamp following the ISO8601 format to a JavaScript Date
 * object.
 *
 * @param {String} time - String representation of timestamp.
 * @return {Date}       - Date object from timestamp.
 */
DateFormatter.prototype.decodeIso8601 = function(time) {
  var dateParts = time.toString().match(DateFormatter.ISO8601)
  if (!dateParts) {
    throw new Error('Expected a ISO8601 datetime but got \'' + time + '\'')
  }

  var date = [
    [dateParts[1], dateParts[3] || '01', dateParts[5] || '01'].join('-')
    , 'T'
    , [
        dateParts[7] || '00'
      , dateParts[11] || '00'
      , dateParts[14] || '00'
      ].join(':')
    , '.'
    , dateParts[16] || '000'
  ].join('')

  date += (dateParts[17] !== undefined) ?
    dateParts[17] +
      ((dateParts[19] && dateParts[20] === undefined) ? '00' : '') :
    DateFormatter.formatCurrentOffset(new Date(date))

  return new Date(date)
}

/**
 * Converts a JavaScript Date object to an ISO8601 timestamp.
 *
 * @param {Date} date - Date object.
 * @return {String}   - String representation of timestamp.
 */
DateFormatter.prototype.encodeIso8601 = function(date) {
  var parts = this.opts.local ?
    DateFormatter.getLocalDateParts(date) :
    DateFormatter.getUTCDateParts(date)

  return [
    [parts[0],parts[1],parts[2]].join(this.opts.hyphens ? '-' : '')
  , 'T'
  , [parts[3],parts[4],parts[5]].join(this.opts.colons ? ':' : '')
  , (this.opts.ms) ? '.' + parts[6] : ''
  , (this.opts.local) ? ((this.opts.offset) ?
      DateFormatter.formatCurrentOffset(date) : '') : 'Z'
  ].join('')
}

/**
 * Helper function to get an array of zero-padded date parts,
 * in UTC
 *
 * @param {Date} date - Date Object
 * @return {String[]}
 */
DateFormatter.getUTCDateParts = function (date) {
  return [
    date.getUTCFullYear()
  , DateFormatter.zeroPad(date.getUTCMonth()+1,2)
  , DateFormatter.zeroPad(date.getUTCDate(),2)
  , DateFormatter.zeroPad(date.getUTCHours(), 2)
  , DateFormatter.zeroPad(date.getUTCMinutes(), 2)
  , DateFormatter.zeroPad(date.getUTCSeconds(), 2)
  , DateFormatter.zeroPad(date.getUTCMilliseconds(), 3)]
}


/**
 * Helper function to get an array of zero-padded date parts,
 * in the local time zone
 *
 * @param {Date} date - Date Object
 * @return {String[]}
 */
DateFormatter.getLocalDateParts = function (date) {
  return [
    date.getFullYear()
  , DateFormatter.zeroPad(date.getMonth()+1,2)
  , DateFormatter.zeroPad(date.getDate(),2)
  , DateFormatter.zeroPad(date.getHours(), 2)
  , DateFormatter.zeroPad(date.getMinutes(), 2)
  , DateFormatter.zeroPad(date.getSeconds(), 2)
  , DateFormatter.zeroPad(date.getMilliseconds(), 3)]
}

/**
 * Helper function to pad the digits with 0s to meet date formatting
 * requirements.
 *
 * @param {Number} digit  - The number to pad.
 * @param {Number} length - Length of digit string, prefix with 0s if not
 *                          already length.
 * @return {String}       - String with the padded digit
 */
DateFormatter.zeroPad = function (digit, length) {
  var padded = '' + digit
  while (padded.length < length) {
    padded = '0' + padded
  }

  return padded
}

/**
 * Helper function to get the current timezone to default decoding to
 * rather than UTC. (for backward compatibility)
 *
 * @return {String} - in the format /Z|[+-]\d{2}:\d{2}/
 */
DateFormatter.formatCurrentOffset = function (d) {
  var offset = (d || new Date()).getTimezoneOffset()
  return (offset === 0) ? 'Z' : [
      (offset < 0) ? '+' : '-'
    , DateFormatter.zeroPad(Math.abs(Math.floor(offset/60)),2)
    , ':'
    , DateFormatter.zeroPad(Math.abs(offset%60),2)
  ].join('')
}

// export an instance of DateFormatter only.
module.exports = new DateFormatter()

}, function(modId) { var map = {}; return __REQUIRE__(map[modId], modId); })
__DEFINE__(1738455898211, function(require, module, exports) {
var CustomType = module.exports = function(raw) {
  this.raw = raw
}

CustomType.prototype.serialize = function(xml) {
  return xml.ele(this.tagName).txt(this.raw)
}

CustomType.prototype.tagName = 'customType'


}, function(modId) { var map = {}; return __REQUIRE__(map[modId], modId); })
__DEFINE__(1738455898212, function(require, module, exports) {
var sax           = require('sax')
  , dateFormatter = require('./date_formatter')

var Deserializer = function(encoding) {
  this.type = null
  this.responseType = null
  this.stack = []
  this.marks = []
  this.data = []
  this.methodname = null
  this.encoding = encoding || 'utf8'
  this.value = false
  this.callback = null
  this.error = null

  this.parser = sax.createStream()
  this.parser.on('opentag',  this.onOpentag.bind(this))
  this.parser.on('closetag', this.onClosetag.bind(this))
  this.parser.on('text',     this.onText.bind(this))
  this.parser.on('cdata',    this.onCDATA.bind(this))
  this.parser.on('end',      this.onDone.bind(this))
  this.parser.on('error',    this.onError.bind(this))
}

Deserializer.prototype.deserializeMethodResponse = function(stream, callback) {
  var that = this

  this.callback = function(error, result) {
    if (error) {
      callback(error)
    }
    else if (result.length > 1) {
      callback(new Error('Response has more than one param'))
    }
    else if (that.type !== 'methodresponse') {
      callback(new Error('Not a method response'))
    }
    else if (!that.responseType) {
      callback(new Error('Invalid method response'))
    }
    else {
      callback(null, result[0])
    }
  }

  stream.setEncoding(this.encoding)
  stream.on('error', this.onError.bind(this))
  stream.pipe(this.parser)
}

Deserializer.prototype.deserializeMethodCall = function(stream, callback) {
  var that = this

  this.callback = function(error, result) {
    if (error) {
      callback(error)
    }
    else if (that.type !== 'methodcall') {
      callback(new Error('Not a method call'))
    }
    else if (!that.methodname) {
      callback(new Error('Method call did not contain a method name'))
    }
    else {
      callback(null, that.methodname, result)
    }
  }

  stream.setEncoding(this.encoding)
  stream.on('error', this.onError.bind(this))
  stream.pipe(this.parser)
}

Deserializer.prototype.onDone = function() {
  var that = this

  if (!this.error) {
    if (this.type === null || this.marks.length) {
      this.callback(new Error('Invalid XML-RPC message'))
    }
    else if (this.responseType === 'fault') {
      var createFault = function(fault) {
        var error = new Error('XML-RPC fault' + (fault.faultString ? ': ' + fault.faultString : ''))
        error.code = fault.faultCode
        error.faultCode = fault.faultCode
        error.faultString = fault.faultString
        return error
      }
      this.callback(createFault(this.stack[0]))
    }
    else {
      this.callback(undefined, this.stack)
    }
  }
}

// TODO:
// Error handling needs a little thinking. There are two different kinds of
// errors: 
//   1. Low level errors like network, stream or xml errors. These don't
//      require special treatment. They only need to be forwarded. The IO
//      is already stopped in these cases. 
//   2. Protocol errors: Invalid tags, invalid values &c. These happen in
//      our code and we should tear down the IO and stop parsing.
// Currently all errors end here. Guess I'll split it up. 
Deserializer.prototype.onError = function(msg) {
  if (!this.error) {
    if (typeof msg === 'string') {
      this.error = new Error(msg)
    }
    else {
      this.error = msg
    }
    this.callback(this.error)
  }
}

Deserializer.prototype.push = function(value) {
  this.stack.push(value)
}

//==============================================================================
// SAX Handlers
//==============================================================================

Deserializer.prototype.onOpentag = function(node) {
  if (node.name === 'ARRAY' || node.name === 'STRUCT') {
    this.marks.push(this.stack.length)
  }
  this.data = []
  this.value = (node.name === 'VALUE')
}

Deserializer.prototype.onText = function(text) {
  this.data.push(text)
}

Deserializer.prototype.onCDATA = function(cdata) {
  this.data.push(cdata)
}

Deserializer.prototype.onClosetag = function(el) {
  var data = this.data.join('')
  try {
    switch(el) {
      case 'BOOLEAN':
        this.endBoolean(data)
        break
      case 'INT':
      case 'I4':
        this.endInt(data)
        break
      case 'I8':
        this.endI8(data)
        break
      case 'DOUBLE':
        this.endDouble(data)
        break
      case 'STRING':
      case 'NAME':
        this.endString(data)
        break
      case 'ARRAY':
        this.endArray(data)
        break
      case 'STRUCT':
        this.endStruct(data)
        break
      case 'BASE64':
        this.endBase64(data)
        break
      case 'DATETIME.ISO8601':
        this.endDateTime(data)
        break
      case 'VALUE':
        this.endValue(data)
        break
      case 'PARAMS':
        this.endParams(data)
        break
      case 'FAULT':
        this.endFault(data)
        break
      case 'METHODRESPONSE':
        this.endMethodResponse(data)
        break
      case 'METHODNAME':
        this.endMethodName(data)
        break
      case 'METHODCALL':
        this.endMethodCall(data)
        break
      case 'NIL':
        this.endNil(data)
        break
      case 'DATA':
      case 'PARAM':
      case 'MEMBER':
        // Ignored by design
        break
      default:
        this.onError('Unknown XML-RPC tag \'' + el + '\'')
        break
    }
  }
  catch (e) {
    this.onError(e)
  }
}

Deserializer.prototype.endNil = function(data) {
  this.push(null)
  this.value = false
}

Deserializer.prototype.endBoolean = function(data) {
  if (data === '1') {
    this.push(true)
  }
  else if (data === '0') {
    this.push(false)
  }
  else {
    throw new Error('Illegal boolean value \'' + data + '\'')
  }
  this.value = false
}

Deserializer.prototype.endInt = function(data) {
  var value = parseInt(data, 10)
  if (isNaN(value)) {
    throw new Error('Expected an integer but got \'' + data + '\'')
  }
  else {
    this.push(value)
    this.value = false
  }
}

Deserializer.prototype.endDouble = function(data) {
  var value = parseFloat(data)
  if (isNaN(value)) {
    throw new Error('Expected a double but got \'' + data + '\'')
  }
  else {
    this.push(value)
    this.value = false
  }
}

Deserializer.prototype.endString = function(data) {
  this.push(data)
  this.value = false
}

Deserializer.prototype.endArray = function(data) {
  var mark = this.marks.pop()
  this.stack.splice(mark, this.stack.length - mark, this.stack.slice(mark))
  this.value = false
}

Deserializer.prototype.endStruct = function(data) {
  var mark = this.marks.pop()
    , struct = {}
    , items = this.stack.slice(mark)
    , i = 0

  for (; i < items.length; i += 2) {
    struct[items[i]] = items[i + 1]
  }
  this.stack.splice(mark, this.stack.length - mark, struct)
  this.value = false
}

Deserializer.prototype.endBase64 = function(data) {
  var buffer = new Buffer(data, 'base64')
  this.push(buffer)
  this.value = false
}

Deserializer.prototype.endDateTime = function(data) {
  var date = dateFormatter.decodeIso8601(data)
  this.push(date)
  this.value = false
}

var isInteger = /^-?\d+$/
Deserializer.prototype.endI8 = function(data) {
  if (!isInteger.test(data)) {
    throw new Error('Expected integer (I8) value but got \'' + data + '\'')
  }
  else {
    this.endString(data)
  }
}

Deserializer.prototype.endValue = function(data) {
  if (this.value) {
    this.endString(data)
  }
}

Deserializer.prototype.endParams = function(data) {
  this.responseType = 'params'
}

Deserializer.prototype.endFault = function(data) {
  this.responseType = 'fault'
}

Deserializer.prototype.endMethodResponse = function(data) {
  this.type = 'methodresponse'
}

Deserializer.prototype.endMethodName = function(data) {
  this.methodname = data
}

Deserializer.prototype.endMethodCall = function(data) {
  this.type = 'methodcall'
}

module.exports = Deserializer


}, function(modId) { var map = {"./date_formatter":1738455898210}; return __REQUIRE__(map[modId], modId); })
__DEFINE__(1738455898213, function(require, module, exports) {
/**
 * Creates object for cookies manipulation on client side.
 * Allows to parse server's response in order to get cookies and compose http request to transfer cookies to the server
 * @constructor
 */
function Cookies() {
  this.cookies = {}
}

Cookies.prototype = {
  /**
   * Obtains value of the cookie with specified name.
   * This call checks expiration dates and does not return expired cookies.
   * @param {String} name cookie name
   * @return {String} cookie value or null
   */
  get: function(name) {
    var cookie = this.cookies[name]
    if (cookie && this.checkNotExpired(name)) {
      return this.cookies[name].value
    }
    return null
  },

  /**
   * Sets cookie's value and optional options
   * @param {String} name cookie's name
   * @param {String} value value
   * @param {Object} options with the following fields:
   *  - {Boolean} secure - is cookie secure or not (does not mean anything for now)
   *  - {Date} expires - cookie's expiration date. If specified then cookie will disappear after that date
   */
  set: function(name, value, options) {
    var cookie = typeof options == 'object'
        ? {value: value, expires: options.expires, secure: options.secure || false, new: options.new || false}
        : {value: value}
    if (this.checkNotExpired(name, cookie)) {
      this.cookies[name] = cookie
    }
  },

  // For testing purposes
  getExpirationDate: function(name) {
    return this.cookies[name] ? this.cookies[name].expires : null
  },

  // Internal function
  checkNotExpired: function(name, cookie) {
    if (typeof cookie === 'undefined') {
      cookie = this.cookies[name]
    }
    var now = new Date()
    if (cookie && cookie.expires && now > cookie.expires) {
      delete this.cookies[name]
      return false
    }
    return true
  },


  /**
   * Parses headers from server's response for 'set-cookie' header and store cookie's values.
   * Also parses expiration date
   * @param headers
   */
  parseResponse: function(headers) {
    var cookies = headers['set-cookie']
    if (cookies) {
      cookies.forEach(function(c) {
        var cookiesParams = c.split(';')
        var cookiePair = cookiesParams.shift().split('=')
        var options = {}
        cookiesParams.forEach(function(param) {
          param = param.trim()
          if (param.toLowerCase().indexOf('expires') == 0) {
            var date = param.split('=')[1].trim()
            options.expires = new Date(date)
          }
        })
        this.set(cookiePair[0].trim(), cookiePair[1].trim(), options)
      }.bind(this))
    }
  },

  /**
   * Adds cookies to the provided headers as array. Does nothing if there are no cookies stored.
   * This call checks expiration dates and does not add expired cookies.
   * @param headers
   */
  composeRequest: function(headers) {
    if (Object.keys(this.cookies).length == 0) {
      return
    }
    headers['Cookie'] = this.toString()
  },


  /**
   *
   * @return {String} cookies as 'name=value' pairs joined by semicolon
   */
  toString: function() {
    return Object.keys(this.cookies)
      .filter(this.checkNotExpired.bind(this))
      .map(function(name) {
      return name + '=' + this.cookies[name].value
    }.bind(this)).join(';')
  }
}

module.exports = Cookies

}, function(modId) { var map = {}; return __REQUIRE__(map[modId], modId); })
__DEFINE__(1738455898214, function(require, module, exports) {
var http             = require('http')
  , https            = require('https')
  , url              = require('url')
  , EventEmitter     = require('events').EventEmitter
  , Serializer       = require('./serializer')
  , Deserializer     = require('./deserializer')

/**
 * Creates a new Server object. Also creates an HTTP server to start listening
 * for XML-RPC method calls. Will emit an event with the XML-RPC call's method
 * name when receiving a method call.
 *
 * @constructor
 * @param {Object|String} options - The HTTP server options. Either a URI string
 *                                  (e.g. 'http://localhost:9090') or an object
 *                                  with fields:
 *   - {String} host              - (optional)
 *   - {Number} port
 * @param {Boolean} isSecure      - True if using https for making calls,
 *                                  otherwise false.
 * @return {Server}
 */
function Server(options, isSecure, onListening) {

  if (false === (this instanceof Server)) {
    return new Server(options, isSecure)
  }
  onListening = onListening || function() {}
  var that = this

  // If a string URI is passed in, converts to URI fields
  if (typeof options === 'string') {
    options = url.parse(options)
    options.host = options.hostname
    options.path = options.pathname
  }

  function handleMethodCall(request, response) {
    var deserializer = new Deserializer()
    deserializer.deserializeMethodCall(request, function(error, methodName, params) {
      if (Object.prototype.hasOwnProperty.call(that._events, methodName)) {
        that.emit(methodName, null, params, function(error, value) {
          var xml = null
          if (error !== null) {
            xml = Serializer.serializeFault(error)
          }
          else {
            xml = Serializer.serializeMethodResponse(value)
          }
          response.writeHead(200, {'Content-Type': 'text/xml'})
          response.end(xml)
        })
      }
      else {
        that.emit('NotFound', methodName, params)
        response.writeHead(404)
        response.end()
      }
    })
  }

  this.httpServer = isSecure ? https.createServer(options, handleMethodCall)
                            : http.createServer(handleMethodCall)

  process.nextTick(function() {
    this.httpServer.listen(options.port, options.host, onListening)
  }.bind(this))
  this.close = function(callback) {
    this.httpServer.once('close', callback)
    this.httpServer.close()
  }.bind(this)
}

// Inherit from EventEmitter to emit and listen
Server.prototype.__proto__ = EventEmitter.prototype

module.exports = Server


}, function(modId) { var map = {"./serializer":1738455898209,"./deserializer":1738455898212}; return __REQUIRE__(map[modId], modId); })
return __REQUIRE__(1738455898207);
})()
//miniprogram-npm-outsideDeps=["http","https","url","xmlbuilder","sax","events"]
//# sourceMappingURL=index.js.map