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: * * * client.cookie('login', 'alex').cookie('password', '123'); * * * 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 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 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 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