xml_rpc/weapp/miniprogram_npm/xmlrpc/index.js
2025-02-13 19:23:02 +08:00

1189 lines
34 KiB
JavaScript

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