From 7428ca85742b2b17c6649d4ec33ec038f43d944a Mon Sep 17 00:00:00 2001 From: loganhz Date: Wed, 9 May 2018 21:47:01 +0800 Subject: [PATCH] Update Aliyun ECS node driver --- .eslintrc.js | 1 + ember-cli-build.js | 1 + lib/.eslintrc.js | 1 + .../node-driver/driver-aliyunecs/component.js | 320 +- .../node-driver/driver-aliyunecs/template.hbs | 500 +- translations/en-us.yaml | 69 +- vendor/aliyun-sdk.js | 24784 ++++++++++++++++ 7 files changed, 25394 insertions(+), 282 deletions(-) create mode 100644 vendor/aliyun-sdk.js diff --git a/.eslintrc.js b/.eslintrc.js index 94acbff63..c97b1372e 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -22,6 +22,7 @@ module.exports = { "Ui": true, "async": true, "AWS": true, + "ALY": true, "Identicon": true, "md5": true, "_": true, diff --git a/ember-cli-build.js b/ember-cli-build.js index 9bdeeb4e6..b65de5796 100644 --- a/ember-cli-build.js +++ b/ember-cli-build.js @@ -105,6 +105,7 @@ module.exports = function(defaults) { app.import('vendor/prompt/prompt-v1-latin-600.woff', { destDir: 'assets/fonts/'}); app.import('vendor/prompt/prompt-v1-latin-600.woff2',{ destDir: 'assets/fonts/'}); app.import('vendor/aws-sdk-ec2.js'); + app.import('vendor/aliyun-sdk.js'); app.import('vendor/file-saver/fileSaver.mini.js'); app.import('vendor/json-sanitizer/json-sanitizer.js'); diff --git a/lib/.eslintrc.js b/lib/.eslintrc.js index c4d7cbb4d..caec012eb 100644 --- a/lib/.eslintrc.js +++ b/lib/.eslintrc.js @@ -21,6 +21,7 @@ module.exports = { "Ui": true, "async": true, "AWS": true, + "ALY": true, "Identicon": true, "md5": true, "_": true, diff --git a/lib/shared/addon/components/node-driver/driver-aliyunecs/component.js b/lib/shared/addon/components/node-driver/driver-aliyunecs/component.js index 26f5cadb1..c75d21f3b 100644 --- a/lib/shared/addon/components/node-driver/driver-aliyunecs/component.js +++ b/lib/shared/addon/components/node-driver/driver-aliyunecs/component.js @@ -1,41 +1,331 @@ import { alias } from '@ember/object/computed'; +import { set, get, observer, setProperties, computed } from '@ember/object'; import Component from '@ember/component'; import NodeDriver from 'shared/mixins/node-driver'; import layout from './template'; +import { inject as service } from '@ember/service'; +import { Promise as EmberPromise } from 'rsvp'; -let ioOptimized=[ - { - value : "none", +const ENDPOINT = 'https://ecs.aliyuncs.com'; +const PAGE_SIZE = 50; +const NONE_OPT_DISK = [{ + value: 'cloud' +}]; + +const OPT_DISK = [{ + value: 'cloud_efficiency' }, { - value: "optimized", - }, + value: 'cloud_ssd' + } ]; export default Component.extend(NodeDriver, { layout, - driverName: 'aliyunecs', + + intl: service(), + settings: service(), + + driverName: 'aliyunecs', config: alias('model.aliyunecsConfig'), - ioOptimized: ioOptimized, + zones: null, + regions: null, + securityGroups: null, + images: null, + instanceTypes: null, - bootstrap: function() { - let config = this.get('globalStore').createRecord({ + ecsClient: null, + step: 1, + + bootstrap: function () { + const config = get(this, 'globalStore').createRecord({ type: 'aliyunecsConfig', - accessKeySecret: '' + accessKeySecret: '', + ioOptimized: 'optimized', }); - this.set('model.aliyunecsConfig', config); + set(this, 'model.aliyunecsConfig', config); + set(this, 'model.engineRegistryMirror', ['https://s06nkgus.mirror.aliyuncs.com']); + set(this, 'model.engineInstallURL', 'http://dev-tool.oss-cn-shenzhen.aliyuncs.com/docker-install/1.13.1.sh'); }, - validate() { - let errors = []; - if ( !this.get('model.name') ) { + actions: { + alyLogin: function (cb) { + setProperties(this, { + 'errors': null, + 'config.accessKeyId': (get(this, 'config.accessKeyId') || '').trim(), + 'config.accessKeySecret': (get(this, 'config.accessKeySecret') || '').trim(), + }); + + const errors = get(this, 'errors') || []; + const intl = get(this, 'intl'); + + const accessKey = get(this, 'config.accessKeyId'); + const accessSecret = get(this, 'config.accessKeySecret'); + + if (!accessKey) { + errors.push(intl.t('nodeDriver.aliyunecs.errors.accessKeyRequired')); + } + + if (!accessSecret) { + errors.push(intl.t('nodeDriver.aliyunecs.errors.accessSecretRequired')); + } + + if (errors.length > 0) { + set(this, 'errors', errors); + cb(); + return; + } + + let ecs; + + try { + const location = window.location; + let endpoint = get(this, 'config.apiEndpoint') ? get(this, 'config.apiEndpoint') : ENDPOINT; + endpoint = get(this,'app.proxyEndpoint') + '/' + endpoint.replace('//', '/'); + endpoint = `${location.protocol}//${window.location.host}${endpoint}`; + + ecs = new ALY.ECS({ + accessKeyId: get(this, 'config.accessKeyId'), + secretAccessKey: get(this, 'config.accessKeySecret'), + apiVersion: '2014-05-26', + endpoint, + }); + + ecs.describeRegions({}, (err, res) => { + if (err) { + let errors = get(this, 'errors') || []; + errors.pushObject(err.message || err); + set(this, 'errors', errors); + cb(); + return; + } + + set(this, 'ecsClient', ecs); + set(this, 'regions', res.Regions.Region.map((region) => { + return { + value: region.RegionId, + label: region.LocalName, + }; + })); + this.regionDidChange(); + set(this, 'step', 2); + cb(); + }); + } catch (err) { + const errors = get(this, 'errors') || []; + errors.pushObject(err.message || err); + set(this, 'errors', errors); + cb(); + return; + } + }, + + loadStorageTypes: function (cb) { + if (!get(this, 'config.securityGroup')) { + set(this, 'config.securityGroup', 'docker-machine') + } + set(this, 'step', 3); + this.diskCategoryChoicesDidChange(); + cb(); + }, + + loadInstanceTypes: function (cb) { + this.fetch('Image', 'Images') + .then((images) => { + set(this, 'images', images.filter((image) => image.raw.OSType === 'linux')); + set(this, 'config.imageId', get(this, 'images.firstObject.value')); + this.fetch('InstanceType', 'InstanceTypes') + .then((instanceTypes) => { + set(this, 'instanceTypes', instanceTypes.map((instanceType) => { + return { + group: instanceType.raw.InstanceTypeFamily, + value: instanceType.value, + label: `${instanceType.raw.InstanceTypeId} ( ${instanceType.raw.CpuCoreCount} ${instanceType.raw.CpuCoreCount > 1 ? 'Cores': 'Core'} ${instanceType.raw.MemorySize}GB RAM )`, + } + })); + set(this, 'config.instanceType', get(this, 'instanceTypes.firstObject.value')) + set(this, 'step', 4); + cb(); + }) + .catch((err) => { + const errors = get(this, 'errors') || []; + errors.pushObject(err.message || err); + set(this, 'errors', errors); + cb(); + return; + }); + }) + .catch((err) => { + const errors = get(this, 'errors') || []; + errors.pushObject(err.message || err); + set(this, 'errors', errors); + cb(); + return; + }); + }, + }, + + vpcDidChange: observer('config.vpcId', function () { + const vpcId = get(this, 'config.vpcId'); + if (vpcId) { + this.fetch('VSwitch', 'VSwitches').then((vswitches) => { + set(this, 'vswitches', vswitches); + const selectedVSwitch = get(this, 'config.vswitchId'); + if (selectedVSwitch) { + const found = vswitches.findBy('VSwitchId', selectedVSwitch); + if (!found) { + set(this, 'config.vswitchId', null); + } + } + }); + + this.fetch('SecurityGroup', 'SecurityGroups').then((securityGroups) => { + set(this, 'securityGroups', securityGroups); + const selectedSecurityGroup = get(this, 'config.securityGroup'); + if (selectedSecurityGroup) { + const found = securityGroups.findBy('SecurityGroupId', selectedSecurityGroup); + if (!found) { + set(this, 'config.securityGroup', 'docker-machine'); + } + } + }); + } else { + set(this, 'config.vswitchId', null); + set(this, 'config.securityGroup', 'docker-machine'); + } + }), + + regionDidChange: observer('config.region', function () { + const region = get(this, 'config.region'); + if (region) { + this.fetch('Vpc', 'Vpcs').then((vpcs) => { + set(this, 'vpcs', vpcs); + const selectedVPC = get(this, 'config.vpcId'); + if (selectedVPC) { + const found = vpcs.findBy('VpcId', selectedVPC); + if (!found) { + set(this, 'config.vpcId', null); + } + } + }); + + this.fetch('Zone', 'Zones').then((zones) => { + set(this, 'zones', zones); + const selectedZone = get(this, 'config.zone'); + if (selectedZone) { + const found = zones.findBy('ZoneId', selectedZone); + if (!found) { + set(this, 'config.zone', null); + } + } + }); + } + }), + + diskCategoryChoices: computed('config.ioOptimized', function () { + return get(this, 'config.ioOptimized') === 'none' ? NONE_OPT_DISK : OPT_DISK; + }), + + diskCategoryChoicesDidChange: observer('diskCategoryChoices.@each.value', function () { + set(this, 'config.systemDiskCategory', get(this, 'diskCategoryChoices.firstObject.value')); + set(this, 'config.diskCategory', get(this, 'diskCategoryChoices.firstObject.value')); + }), + + validate: function () { + this._super(); + const errors = get(this, 'model').validationErrors(); + + const intl = get(this, 'intl'); + + const name = get(this, 'model.name'); + + const sshPassword = get(this, 'config.sshPassword'); + + const lower = /[a-z]/.test(sshPassword) ? 1 : 0; + const upper = /[A-Z]/.test(sshPassword) ? 1 : 0; + const number = /[0-9]/.test(sshPassword) ? 1 : 0; + const special = /[?+*$^().|<>';:\-=\[\]\{\},&%#@!~`\\]/.test(sshPassword) ? 1 : 0; + + if (!name) { errors.push('Name is required'); } - this.set('errors', errors); + if (sshPassword && (sshPassword.length < 8) || sshPassword.length > 30) { + errors.push(intl.t('nodeDriver.aliyunecs.errors.sshPasswordLengthNotValid')); + } + + if (sshPassword && !/[?+*$^().|<>';:\-=\[\]\{\},&%#@!~`\\a-zA-Z0-9]+/.test(sshPassword)) { + errors.push(intl.t('nodeDriver.aliyunecs.errors.sshPasswordInvalidCharacter')); + } + + if (sshPassword && (lower + upper + number + special < 3)) { + errors.push(get(this, 'intl').t('nodeDriver.aliyunecs.errors.sshPasswordFormatError')); + } + + set(this, 'errors', errors); return errors.length === 0; }, + fetch: function (resource, plural, page = 1) { + const ecs = get(this, 'ecsClient'); + const region = get(this, 'config.region'); + const results = []; + let params = { + PageSize: PAGE_SIZE, + PageNumber: page, + }; + + switch (resource) { + case 'InstanceType': + params = {}; + break; + case 'VSwitch': + params.VpcId = get(this, 'config.vpcId'); + break; + case 'SecurityGroup': + params.VpcId = get(this, 'config.vpcId'); + params.RegionId = region; + break; + case 'Zone': + params = { + RegionId: region, + }; + break; + default: + params.RegionId = region; + } + + return new EmberPromise((resolve, reject) => { + ecs[`describe${plural}`](params, (err, res) => { + if (err) { + reject(err); + return; + } + + const current = res[`${plural}`][resource]; + results.pushObjects(current.map((item) => { + return { + label: item[`${resource}Id`], + value: item[`${resource}Id`], + raw: item, + }; + })); + + if (res.TotalCount > ((PAGE_SIZE * (page - 1)) + current.length)) { + return this.fetch(resource, plural, page + 1) + .then((array) => { + results.pushObjects(array); + resolve(results); + }) + .catch((err) => { + reject(err); + }); + } else { + resolve(results); + } + }); + }); + }, }); diff --git a/lib/shared/addon/components/node-driver/driver-aliyunecs/template.hbs b/lib/shared/addon/components/node-driver/driver-aliyunecs/template.hbs index b3cdf190e..b60344cf7 100644 --- a/lib/shared/addon/components/node-driver/driver-aliyunecs/template.hbs +++ b/lib/shared/addon/components/node-driver/driver-aliyunecs/template.hbs @@ -1,260 +1,270 @@ -
-
- {{#if showNameScale}} -
-

{{t 'nodeDriver.aliyunecs.instanceSection'}}

-
-
-
- {{form-name-description - name=prefix - nameRequired=true - namePlaceholder="hostsPage.new.name.placeholder" - nameHelpText=nameCountLabel - descriptionShown=true - }} -
-
- {{form-count - min=0 - initialScale=1 - setScale=(action (mut count)) - }} -
-
-
-
- {{/if}} +{{#accordion-list showExpandAll=false as | al expandFn |}} +
{{driverOptionsTitle}}
-
-

{{t 'nodeDriver.aliyunecs.accountSection'}}

- -
-
- -
-
+ {{#accordion-list-item + title=(t 'nodeDriver.aliyunecs.accountSection.label') + detail=(t 'nodeDriver.aliyunecs.accountSection.detail') + expandAll=expandAll + expand=(action expandFn) + expandOnInit=true + }} +
+
+ + {{#input-or-display editable=(eq step 1) value=config.accessKeyId}} {{input type="text" class="form-control" value=config.accessKeyId placeholder=(t 'nodeDriver.aliyunecs.accessKey.placeholder')}} -
- -
- -
-
+ {{/input-or-display}} +
+
+ + {{#if (eq step 1)}} {{input type="password" class="form-control" value=config.accessKeySecret placeholder=(t 'nodeDriver.aliyunecs.accessKeySecret.placeholder')}} -
+ {{else}} +
{{t 'nodeDriver.aliyunecs.accessKeySecret.provided'}}
+ {{/if}}
- -
-
- -
-
- {{input type="text" class="form-control" value=config.apiEndpoint placeholder=(t 'nodeDriver.aliyunecs.apiEndpoint.placeholder')}} -
-
- -
- - -
-

{{t 'nodeDriver.aliyunecs.instanceOptionsSection'}}

- -
-
- -
-
- {{input type="text" class="form-control" value=config.description placeholder=(t 'nodeDriver.aliyunecs.instanceDescription.placeholder')}} -
- -
- -
-
- {{input type="text" class="form-control" value=config.instanceType placeholder=(t 'nodeDriver.aliyunecs.instanceType.placeholder')}} -
-
- -
-
- -
-
- {{input type="text" class="form-control" value=config.imageId placeholder=(t 'nodeDriver.aliyunecs.systemImage.placeholder')}} -
- -
- -
-
- {{input type="text" class="form-control" value=config.tag placeholder=(t 'nodeDriver.aliyunecs.instanceTag.placeholder')}} -
-
- -
-
- -
-
-
- {{input type="text" class="form-control" value=config.internetMaxBandwidth placeholder=(t 'nodeDriver.aliyunecs.internetMaxBandwidth.placeholder')}} -
Mbps
-
-
-
- -
-
- {{input type="text" class="form-control" value=config.slbId placeholder=(t 'nodeDriver.aliyunecs.aliyunSLB.placeholder')}} -
- -
-
- -
-

{{t 'nodeDriver.aliyunecs.storageSection'}}

- -
-
- -
-
- {{!--{{input type="text" class="form-control" value=config.ioOptimized placeholder=(t 'nodeDriver.aliyunecs.ioOptimized.placeholder')}}--}} - {{new-select - classNames="form-control" - content=ioOptimized - optionLabelPath='value' - value=config.ioOptimized - }} -
- -
- -
-
- {{input type="text" class="form-control" value=config.systemDiskCategory placeholder=(t 'nodeDriver.aliyunecs.systemDiskCategory.placeholder')}} -
-
- -
-
- -
-
- {{input type="text" class="form-control" value=config.diskCategory placeholder=(t 'nodeDriver.aliyunecs.dataDiskCategory.placeholder')}} -
- -
- -
-
-
- {{input type="text" class="form-control" value=config.diskSize placeholder=(t 'nodeDriver.aliyunecs.dataDiskSize.placeholder')}} -
GB
-
-
-
- -
-
- -
-
- {{input type="text" class="form-control" value=config.region placeholder=(t 'nodeDriver.aliyunecs.region.placeholder')}} -
- -
- -
-
- {{input type="text" class="form-control" value=config.zone placeholder=(t 'nodeDriver.aliyunecs.zone.placeholder')}} -
-
-
- - -
-

{{t 'nodeDriver.aliyunecs.networkSection'}}

-
-
- -
-
- {{input type="text" class="form-control" value=config.routeCidr placeholder=(t 'nodeDriver.aliyunecs.routeCIDR.placeholder')}} -
- -
- -
-
- {{input type="text" class="form-control" value=config.vpcId placeholder=(t 'nodeDriver.aliyunecs.vpcId.placeholder')}} -
-
- -
-
- -
-
- {{input type="text" class="form-control" value=config.vswitchId placeholder=(t 'nodeDriver.aliyunecs.vswitchId.placeholder')}} -
- -
- -
-
- {{input type="text" class="form-control" value=config.privateIp placeholder=(t 'nodeDriver.aliyunecs.privateIp.placeholder')}} -
-
- -
-
- -
-
- {{input type="checkbox" class="form-control" checked=config.privateAddressOnly}} -
-
-
- -
-

{{t 'nodeDriver.aliyunecs.securitySection'}}

-
-
- -
-
- {{input type="text" class="form-control" value=config.securityGroup placeholder=(t 'nodeDriver.aliyunecs.securityGroup.placeholder')}} -
- -
- -
-
- {{input type="text" class="form-control" value=config.sshPassword placeholder=(t 'nodeDriver.aliyunecs.sshPassword.placeholder')}} -
-
-
- -
- {{settings.appName}}
-
- {{form-user-labels initialLabels=labelResource.labels setLabels=(action 'setLabels') expandAll=null}} +
+ + {{#input-or-display editable=(eq step 1) value=config.apiEndpoint}} + {{input type="text" class="form-control" value=config.apiEndpoint placeholder=(t 'nodeDriver.aliyunecs.apiEndpoint.placeholder')}} + {{/input-or-display}}
+ {{/accordion-list-item}} - {{#advanced-section}} - {{form-engine-opts machine=model showEngineUrl=showEngineUrl}} - {{/advanced-section}} + {{#if (eq step 1)}} + {{top-errors errors=errors}} + {{save-cancel + save="alyLogin" + cancel="cancel" + createLabel="nodeDriver.aliyunecs.accountSection.next" + savingLabel="nodeDriver.aliyunecs.accountSection.loading" + }} + {{/if}} + +
+ {{#accordion-list-item + title=(t 'nodeDriver.aliyunecs.networkSection.label') + detail=(t 'nodeDriver.aliyunecs.networkSection.detail') + expandAll=expandAll + expand=(action expandFn) + expandOnInit=true + }} +
+
+ + {{#input-or-display editable=(eq step 2) value=config.region}} + {{new-select classNames="form-control" content=regions value=config.region}} + {{/input-or-display}} +
+
+ + {{#input-or-display editable=(eq step 2) value=config.vpcId}} + {{new-select classNames="form-control" content=vpcs value=config.vpcId prompt="nodeDriver.aliyunecs.vpcId.prompt" localizedPrompt=true}} + {{/input-or-display}} +
+
+ +
+
+ + {{#input-or-display editable=(eq step 2) value=config.securityGroup}} + {{new-select classNames="form-control" content=securityGroups value=config.securityGroup prompt="nodeDriver.aliyunecs.securityGroup.prompt" localizedPrompt=true}} + {{/input-or-display}} +
+
+ + {{#input-or-display editable=(eq step 2) value=config.vswitchId}} + {{new-select classNames="form-control" content=vswitches value=config.vswitchId prompt="nodeDriver.aliyunecs.vswitchId.prompt" localizedPrompt=true}} + {{/input-or-display}} +
+
+ +
+
+ + {{#input-or-display editable=(eq step 2) value=config.zone}} + {{new-select classNames="form-control" content=zones value=config.zone prompt="nodeDriver.aliyunecs.zone.prompt" localizedPrompt=true}} + {{/input-or-display}} +
+
+ + {{#input-or-display editable=(eq step 2) value=config.routeCidr}} + {{input type="text" class="form-control" value=config.routeCidr placeholder=(t 'nodeDriver.aliyunecs.routeCIDR.placeholder')}} + {{/input-or-display}} +
+
+ +
+
+ + {{#input-or-display editable=(eq step 2) value=config.privateIp}} + {{input type="text" class="form-control" value=config.privateIp placeholder=(t 'nodeDriver.aliyunecs.privateIp.placeholder')}} + {{/input-or-display}} +
+
+ + {{#input-or-display editable=(eq step 2) value=config.privateAddressOnly}} +
+ {{input type="checkbox" class="form-control" checked=config.privateAddressOnly}} +
+ {{/input-or-display}} +
+
+ {{/accordion-list-item}} + + {{#if (eq step 2)}} + {{top-errors errors=errors}} + {{save-cancel + save="loadStorageTypes" + cancel="cancel" + createLabel="nodeDriver.aliyunecs.networkSection.next" + savingLabel="nodeDriver.aliyunecs.networkSection.loading" + }} + {{/if}}
+
+ {{#accordion-list-item + title=(t 'nodeDriver.aliyunecs.storageSection.label') + detail=(t 'nodeDriver.aliyunecs.storageSection.detail') + expandAll=expandAll + expand=(action expandFn) + expandOnInit=true + }} +
+
+ + {{#input-or-display editable=(eq step 3) value=config.ioOptimized}} +
+ + +
+ {{/input-or-display}} +
+
+ + {{#input-or-display editable=(eq step 3) value=config.systemDiskCategory}} + {{new-select classNames="form-control" content=diskCategoryChoices optionLabelPath='value' value=config.systemDiskCategory}} + {{/input-or-display}} +
+
- {{top-errors errors=errors}} +
+
+ + {{#input-or-display editable=(eq step 3) value=config.diskCategory}} + {{new-select classNames="form-control" content=diskCategoryChoices optionLabelPath='value' value=config.diskCategory}} + {{/input-or-display}} +
+
+ + {{#input-or-display editable=(eq step 3) value=config.diskSize}} +
+ {{input type="text" class="form-control" value=config.diskSize placeholder=(t 'nodeDriver.aliyunecs.dataDiskSize.placeholder')}} +
GB
+
+ {{/input-or-display}} +
+
+ {{/accordion-list-item}} + {{#if (eq step 3)}} + {{top-errors errors=errors}} + {{save-cancel + save="loadInstanceTypes" + cancel="cancel" + createLabel="nodeDriver.aliyunecs.storageSection.next" + savingLabel="nodeDriver.aliyunecs.storageSection.loading" + }} + {{/if}} +
- {{save-cancel save="save" cancel="cancel" editing=editing}} -
+
+ {{#accordion-list-item + title=(t 'nodeDriver.aliyunecs.instanceOptionsSection.label') + detail=(t 'nodeDriver.aliyunecs.instanceOptionsSection.detail') + expandAll=expandAll + expand=(action expandFn) + expandOnInit=true + }} +
+
+ + {{input type="text" class="form-control" value=config.description placeholder=(t 'nodeDriver.aliyunecs.instanceDescription.placeholder')}} +
+
+ + {{new-select classNames="form-control" content=instanceTypes value=config.instanceType}} +
+
+ +
+
+ + {{new-select classNames="form-control" content=images optionLabelPath='raw.OSName' optionValuePath='value' value=config.imageId}} +
+
+ +
+ {{input-integer min=1 max=100 class="form-control" value=config.internetMaxBandwidth placeholder=(t 'nodeDriver.aliyunecs.internetMaxBandwidth.placeholder')}} +
Mbps
+
+
+
+ +
+
+ + {{input type="text" class="form-control" value=config.slbId placeholder=(t 'nodeDriver.aliyunecs.aliyunSLB.placeholder')}} +
+ +
+ + {{input type="password" class="form-control" value=config.sshPassword placeholder=(t 'nodeDriver.aliyunecs.sshPassword.placeholder')}} +
+
+ +
+
+ {{form-value-array + initialValues=config.tag + addActionLabel='nodeDriver.aliyunecs.tags.addActionLabel' + valueLabel='nodeDriver.aliyunecs.tags.valueLabel' + valuePlaceholder='nodeDriver.aliyunecs.tags.placeholder' + changed=(action (mut config.tag)) + }} +
+
+ {{/accordion-list-item}} + +
{{templateOptionsTitle}}
+ + {{form-name-description + model=model + nameRequired=true + }} + + {{form-user-labels + initialLabels=labelResource.labels + setLabels=(action 'setLabels') + expandAll=expandAll + expand=(action expandFn) + }} + + {{form-engine-opts + machine=model + showEngineUrl=showEngineUrl + }} + + {{top-errors errors=errors}} + {{save-cancel save="save" cancel="cancel" editing=editing}} +
+{{/accordion-list}} \ No newline at end of file diff --git a/translations/en-us.yaml b/translations/en-us.yaml index 8d1433d75..2811e7319 100644 --- a/translations/en-us.yaml +++ b/translations/en-us.yaml @@ -4724,18 +4724,24 @@ nodeDriver: region: label: Region aliyunecs: - accountSection: Account Access Section + accountSection: + label: 1. Account Access + detail: API Keys will be used to launch Aliyun ECS Instances. + next: "Next: Authenticate & Config network options" + loading: Loading Regions from Aliyun ECS... accessKey: - label: Access Key* + label: Access Key placeholder: Your Aliyun Account Access Key accessKeySecret: - label: Access Key Secret* - placeholder: Your Key's secret + label: Access Key Secret + placeholder: Your Aliyun Account Access Key Secret + provided: Provided apiEndpoint: - label: Api Endpoint - placeholder: Private Aliyun Api Server Endpoint - instanceSection: Instance Section - instanceOptionsSection: Instance Options Section + label: API Endpoint + placeholder: Private Aliyun API Server Endpoint + instanceOptionsSection: + label: Instance + detail: Customize the Aliyun ECS Instance that will be created. instanceDescription: label: Instance Description placeholder: Instance Description @@ -4745,25 +4751,25 @@ nodeDriver: systemImage: label: System image placeholder: System image - instanceTag: - label: Instance Tag - placeholder: Your Instance Tag in Aliyun internetMaxBandwidth: label: Internet Max Bandwidth placeholder: 1 to 100 aliyunSLB: label: Aliyun SLB ID placeholder: Aliyun SLB ID - storageSection: Storage Info + storageSection: + label: Storage + detail: Configure the storage for the instances that will be created by this template. + next: "Next: Config Aliyun ECS Instance options" + loading: Loading Instance Types and Images from Aliyun ECS... ioOptimized: label: Instance Storage I/O Optimized - placeholder: none or optimized + optimized: Optimized + none: None systemDiskCategory: label: System Disk Category - placeholder: When Storage is optimized, you can input cloud_efficiency, cloud_ssd or ephemeral_ssd. dataDiskCategory: label: Data Disk Category - placeholder: When Storage is optimized, you can input cloud_efficiency, cloud_ssd or ephemeral_ssd. dataDiskSize: label: Data Disk Size placeholder: Disk Size @@ -4772,29 +4778,48 @@ nodeDriver: placeholder: Region zone: label: Available Zone - placeholder: Blank for auto select - networkSection: Network Section + prompt: Choose a Available Zone... + networkSection: + label: Network + detail: Configure the network for the instances that will be created by this template. + next: "Next: Config Storage Options" + loading: Loading Storage Types from Aliyun ECS... routeCIDR: label: Route CIDR placeholder: e.g. 192.168.1.0/24 vpcId: - label: Aliyun VPC ID - placeholder: Aliyun VPC ID + label: VPC + prompt: Choose a VPC... vswitchId: - label: Aliyun Vswitch ID - placeholder: Aliyun Vswitch ID + label: VSwitch + prompt: Choose a VSwitch... privateIp: label: Private IP placeholder: Private IP in Private Network privateAddressOnly: label: Private Address Only - securitySection: Security Section + securitySection: + label: Security + detail: Choose the security groups that will be applied to Instances securityGroup: label: Security Group placeholder: Security Group + prompt: Choose a Security Group... sshPassword: label: SSH Password placeholder: Set Instance SSH Password, Blank for Auto set + provided: Provided + tags: + addActionLabel: Add Instance Tag + valueLabel: Tags + placeholder: e.g. dev + errors: + accessKeyRequired: Access Key is required. + accessSecretRequired: Access Secret Key is required. + sshPasswordLengthNotValid: The length of SSH password must between eight and thirty. + sshPasswordInvalidCharacter: SSH password contains invalid characters. + sshPasswordFormatError: "SSH password must contain at least three out of four kinds of following characters: uppercase letter, lowercase letters, numbers, and special characters." + nameNotValidForApp: The name is invalid according to the {appName} hostname rule. zstack: access: title: 1. Account Access diff --git a/vendor/aliyun-sdk.js b/vendor/aliyun-sdk.js new file mode 100644 index 000000000..21dc68f99 --- /dev/null +++ b/vendor/aliyun-sdk.js @@ -0,0 +1,24784 @@ +// This SDK is distributed under the Apache License, Version 2.0. +// License at https://github.com/aliyun-UED/aliyun-sdk-js#license +require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;ox)throw Error("numRounds must a integer >= 1");if("SHA-1"===c)m=512,u=K,r=U,h=160;else if(u=function(a,d){return L(a,d,c)},r=function(a,d,b,f){var k,e;if("SHA-224"===c||"SHA-256"===c)k=(d+65>>>9<<4)+15,e=16;else if("SHA-384"===c||"SHA-512"===c)k=(d+129>>>10<<5)+31,e=32;else throw Error("Unexpected error in SHA-2 implementation"); + for(;a.length<=k;)a.push(0);a[d>>>5]|=128<<24-d%32;a[k]=d+b;b=a.length;for(d=0;d>>3;f=k/4-1;if(k< + a/8){for(d=r(d,a,0,z(c));d.length<=f;)d.push(0);d[f]&=4294967040}else if(k>a/8){for(;d.length<=f;)d.push(0);d[f]&=4294967040}for(a=0;a<=f;a+=1)t[a]=d[a]^909522486,v[a]=d[a]^1549556828;e=u(t,e);b=m;q=!0};this.update=function(a){var c,d,g,h=0,p=m>>>5;c=n(a,f,k);a=c.binLen;d=c.value;c=a>>>5;for(g=0;g>>5);k=a%m;w=!0};this.getHash=function(a,d){var g,m,n;if(!0===q)throw Error("Cannot call getHash after setting HMAC key");n=M(d);switch(a){case "HEX":g= + function(a){return N(a,n)};break;case "B64":g=function(a){return O(a,n)};break;case "BYTES":g=P;break;default:throw Error("format must be HEX, B64, or BYTES");}if(!1===p)for(e=r(f,k,b,e),m=1;m>>3;if(0!==b%2)throw Error("String of HEX type must be in byte increments");for(f=0;f>>1)+n;for(e=l>>>2;a.length<=e;)a.push(0);a[e]|=k<<8*(3-l%4)}return{value:a,binLen:4*b+d}}function W(c,a,d){var b=[],f,k,e,l,b=a||[0];d= + d||0;k=d>>>3;for(f=0;f>>2,b.length<=e&&b.push(0),b[e]|=a<<8*(3-l%4);return{value:b,binLen:8*c.length+d}}function X(c,a,d){var b=[],f=0,e,g,l,n,h,m,b=a||[0];d=d||0;a=d>>>3;if(-1===c.search(/^[a-zA-Z0-9=+\/]+$/))throw Error("Invalid character in base-64 string");g=c.indexOf("=");c=c.replace(/\=/g,"");if(-1!==g&&g>> (32 - s)), b); + } + + function ff(a, b, c, d, x, s, t) { + return cmn((b & c) | ((~b) & d), a, b, x, s, t); + } + + function gg(a, b, c, d, x, s, t) { + return cmn((b & d) | (c & (~d)), a, b, x, s, t); + } + + function hh(a, b, c, d, x, s, t) { + return cmn(b ^ c ^ d, a, b, x, s, t); + } + + function ii(a, b, c, d, x, s, t) { + return cmn(c ^ (b | (~d)), a, b, x, s, t); + } + + function md5cycle(x, k) { + var a = x[0], + b = x[1], + c = x[2], + d = x[3]; + + a = ff(a, b, c, d, k[0], 7, -680876936); + d = ff(d, a, b, c, k[1], 12, -389564586); + c = ff(c, d, a, b, k[2], 17, 606105819); + b = ff(b, c, d, a, k[3], 22, -1044525330); + a = ff(a, b, c, d, k[4], 7, -176418897); + d = ff(d, a, b, c, k[5], 12, 1200080426); + c = ff(c, d, a, b, k[6], 17, -1473231341); + b = ff(b, c, d, a, k[7], 22, -45705983); + a = ff(a, b, c, d, k[8], 7, 1770035416); + d = ff(d, a, b, c, k[9], 12, -1958414417); + c = ff(c, d, a, b, k[10], 17, -42063); + b = ff(b, c, d, a, k[11], 22, -1990404162); + a = ff(a, b, c, d, k[12], 7, 1804603682); + d = ff(d, a, b, c, k[13], 12, -40341101); + c = ff(c, d, a, b, k[14], 17, -1502002290); + b = ff(b, c, d, a, k[15], 22, 1236535329); + + a = gg(a, b, c, d, k[1], 5, -165796510); + d = gg(d, a, b, c, k[6], 9, -1069501632); + c = gg(c, d, a, b, k[11], 14, 643717713); + b = gg(b, c, d, a, k[0], 20, -373897302); + a = gg(a, b, c, d, k[5], 5, -701558691); + d = gg(d, a, b, c, k[10], 9, 38016083); + c = gg(c, d, a, b, k[15], 14, -660478335); + b = gg(b, c, d, a, k[4], 20, -405537848); + a = gg(a, b, c, d, k[9], 5, 568446438); + d = gg(d, a, b, c, k[14], 9, -1019803690); + c = gg(c, d, a, b, k[3], 14, -187363961); + b = gg(b, c, d, a, k[8], 20, 1163531501); + a = gg(a, b, c, d, k[13], 5, -1444681467); + d = gg(d, a, b, c, k[2], 9, -51403784); + c = gg(c, d, a, b, k[7], 14, 1735328473); + b = gg(b, c, d, a, k[12], 20, -1926607734); + + a = hh(a, b, c, d, k[5], 4, -378558); + d = hh(d, a, b, c, k[8], 11, -2022574463); + c = hh(c, d, a, b, k[11], 16, 1839030562); + b = hh(b, c, d, a, k[14], 23, -35309556); + a = hh(a, b, c, d, k[1], 4, -1530992060); + d = hh(d, a, b, c, k[4], 11, 1272893353); + c = hh(c, d, a, b, k[7], 16, -155497632); + b = hh(b, c, d, a, k[10], 23, -1094730640); + a = hh(a, b, c, d, k[13], 4, 681279174); + d = hh(d, a, b, c, k[0], 11, -358537222); + c = hh(c, d, a, b, k[3], 16, -722521979); + b = hh(b, c, d, a, k[6], 23, 76029189); + a = hh(a, b, c, d, k[9], 4, -640364487); + d = hh(d, a, b, c, k[12], 11, -421815835); + c = hh(c, d, a, b, k[15], 16, 530742520); + b = hh(b, c, d, a, k[2], 23, -995338651); + + a = ii(a, b, c, d, k[0], 6, -198630844); + d = ii(d, a, b, c, k[7], 10, 1126891415); + c = ii(c, d, a, b, k[14], 15, -1416354905); + b = ii(b, c, d, a, k[5], 21, -57434055); + a = ii(a, b, c, d, k[12], 6, 1700485571); + d = ii(d, a, b, c, k[3], 10, -1894986606); + c = ii(c, d, a, b, k[10], 15, -1051523); + b = ii(b, c, d, a, k[1], 21, -2054922799); + a = ii(a, b, c, d, k[8], 6, 1873313359); + d = ii(d, a, b, c, k[15], 10, -30611744); + c = ii(c, d, a, b, k[6], 15, -1560198380); + b = ii(b, c, d, a, k[13], 21, 1309151649); + a = ii(a, b, c, d, k[4], 6, -145523070); + d = ii(d, a, b, c, k[11], 10, -1120210379); + c = ii(c, d, a, b, k[2], 15, 718787259); + b = ii(b, c, d, a, k[9], 21, -343485551); + + x[0] = add32(a, x[0]); + x[1] = add32(b, x[1]); + x[2] = add32(c, x[2]); + x[3] = add32(d, x[3]); + } + + function md5blk(s) { + var md5blks = [], + i; /* Andy King said do it this way. */ + + for (i = 0; i < 64; i += 4) { + md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24); + } + return md5blks; + } + + function md5blk_array(a) { + var md5blks = [], + i; /* Andy King said do it this way. */ + + for (i = 0; i < 64; i += 4) { + md5blks[i >> 2] = a[i] + (a[i + 1] << 8) + (a[i + 2] << 16) + (a[i + 3] << 24); + } + return md5blks; + } + + function md51(s) { + var n = s.length, + state = [1732584193, -271733879, -1732584194, 271733878], + i, + length, + tail, + tmp, + lo, + hi; + + for (i = 64; i <= n; i += 64) { + md5cycle(state, md5blk(s.substring(i - 64, i))); + } + s = s.substring(i - 64); + length = s.length; + tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + for (i = 0; i < length; i += 1) { + tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3); + } + tail[i >> 2] |= 0x80 << ((i % 4) << 3); + if (i > 55) { + md5cycle(state, tail); + for (i = 0; i < 16; i += 1) { + tail[i] = 0; + } + } + + // Beware that the final length might not fit in 32 bits so we take care of that + tmp = n * 8; + tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/); + lo = parseInt(tmp[2], 16); + hi = parseInt(tmp[1], 16) || 0; + + tail[14] = lo; + tail[15] = hi; + + md5cycle(state, tail); + return state; + } + + function md51_array(a) { + var n = a.length, + state = [1732584193, -271733879, -1732584194, 271733878], + i, + length, + tail, + tmp, + lo, + hi; + + for (i = 64; i <= n; i += 64) { + md5cycle(state, md5blk_array(a.subarray(i - 64, i))); + } + + // Not sure if it is a bug, however IE10 will always produce a sub array of length 1 + // containing the last element of the parent array if the sub array specified starts + // beyond the length of the parent array - weird. + // https://connect.microsoft.com/IE/feedback/details/771452/typed-array-subarray-issue + a = (i - 64) < n ? a.subarray(i - 64) : new Uint8Array(0); + + length = a.length; + tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + for (i = 0; i < length; i += 1) { + tail[i >> 2] |= a[i] << ((i % 4) << 3); + } + + tail[i >> 2] |= 0x80 << ((i % 4) << 3); + if (i > 55) { + md5cycle(state, tail); + for (i = 0; i < 16; i += 1) { + tail[i] = 0; + } + } + + // Beware that the final length might not fit in 32 bits so we take care of that + tmp = n * 8; + tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/); + lo = parseInt(tmp[2], 16); + hi = parseInt(tmp[1], 16) || 0; + + tail[14] = lo; + tail[15] = hi; + + md5cycle(state, tail); + + return state; + } + + function rhex(n) { + var s = '', + j; + for (j = 0; j < 4; j += 1) { + s += hex_chr[(n >> (j * 8 + 4)) & 0x0F] + hex_chr[(n >> (j * 8)) & 0x0F]; + } + return s; + } + + function hex(x) { + var i; + for (i = 0; i < x.length; i += 1) { + x[i] = rhex(x[i]); + } + return x.join(''); + } + + // In some cases the fast add32 function cannot be used.. + if (hex(md51('hello')) !== '5d41402abc4b2a76b9719d911017c592') { + add32 = function (x, y) { + var lsw = (x & 0xFFFF) + (y & 0xFFFF), + msw = (x >> 16) + (y >> 16) + (lsw >> 16); + return (msw << 16) | (lsw & 0xFFFF); + }; + } + + // --------------------------------------------------- + + function toUtf8(str) { + if (/[\u0080-\uFFFF]/.test(str)) { + str = unescape(encodeURIComponent(str)); + } + + return str; + } + + function utf8Str2ArrayBuffer(str, returnUInt8Array) { + var length = str.length, + buff = new ArrayBuffer(length), + arr = new Uint8Array(buff), + i; + + for (i = 0; i < length; i++) { + arr[i] = str.charCodeAt(i); + } + + return returnUInt8Array ? arr : buff; + } + + function arrayBuffer2Utf8Str(buff) { + return String.fromCharCode.apply(null, new Uint8Array(buff)); + } + + function concatenateArrayBuffers(first, second, returnUInt8Array) { + var result = new Uint8Array(first.byteLength + second.byteLength); + + result.set(new Uint8Array(first)); + result.set(new Uint8Array(second), first.byteLength); + + return returnUInt8Array ? result : result.buffer; + } + + // --------------------------------------------------- + + /** + * SparkMD5 OOP implementation. + * + * Use this class to perform an incremental md5, otherwise use the + * static methods instead. + */ + function SparkMD5() { + // call reset to init the instance + this.reset(); + } + + /** + * Appends a string. + * A conversion will be applied if an utf8 string is detected. + * + * @param {String} str The string to be appended + * + * @return {SparkMD5} The instance itself + */ + SparkMD5.prototype.append = function (str) { + // Converts the string to utf8 bytes if necessary + // Then append as binary + this.appendBinary(toUtf8(str)); + + return this; + }; + + /** + * Appends a binary string. + * + * @param {String} contents The binary string to be appended + * + * @return {SparkMD5} The instance itself + */ + SparkMD5.prototype.appendBinary = function (contents) { + this._buff += contents; + this._length += contents.length; + + var length = this._buff.length, + i; + + for (i = 64; i <= length; i += 64) { + md5cycle(this._hash, md5blk(this._buff.substring(i - 64, i))); + } + + this._buff = this._buff.substring(i - 64); + + return this; + }; + + /** + * Finishes the incremental computation, reseting the internal state and + * returning the result. + * Use the raw parameter to obtain the raw result instead of the hex one. + * + * @param {Boolean} raw True to get the raw result, false to get the hex result + * + * @return {String|Array} The result + */ + SparkMD5.prototype.end = function (raw) { + var buff = this._buff, + length = buff.length, + i, + tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + ret; + + for (i = 0; i < length; i += 1) { + tail[i >> 2] |= buff.charCodeAt(i) << ((i % 4) << 3); + } + + this._finish(tail, length); + ret = !!raw ? this._hash : hex(this._hash); + + this.reset(); + + return ret; + }; + + /** + * Resets the internal state of the computation. + * + * @return {SparkMD5} The instance itself + */ + SparkMD5.prototype.reset = function () { + this._buff = ''; + this._length = 0; + this._hash = [1732584193, -271733879, -1732584194, 271733878]; + + return this; + }; + + /** + * Gets the internal state of the computation. + * + * @return {Object} The state + */ + SparkMD5.prototype.getState = function () { + return { + buff: this._buff, + length: this._length, + hash: this._hash + }; + }; + + /** + * Gets the internal state of the computation. + * + * @param {Object} state The state + * + * @return {SparkMD5} The instance itself + */ + SparkMD5.prototype.setState = function (state) { + this._buff = state.buff; + this._length = state.length; + this._hash = state.hash; + + return this; + }; + + /** + * Releases memory used by the incremental buffer and other additional + * resources. If you plan to use the instance again, use reset instead. + */ + SparkMD5.prototype.destroy = function () { + delete this._hash; + delete this._buff; + delete this._length; + }; + + /** + * Finish the final calculation based on the tail. + * + * @param {Array} tail The tail (will be modified) + * @param {Number} length The length of the remaining buffer + */ + SparkMD5.prototype._finish = function (tail, length) { + var i = length, + tmp, + lo, + hi; + + tail[i >> 2] |= 0x80 << ((i % 4) << 3); + if (i > 55) { + md5cycle(this._hash, tail); + for (i = 0; i < 16; i += 1) { + tail[i] = 0; + } + } + + // Do the final computation based on the tail and length + // Beware that the final length may not fit in 32 bits so we take care of that + tmp = this._length * 8; + tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/); + lo = parseInt(tmp[2], 16); + hi = parseInt(tmp[1], 16) || 0; + + tail[14] = lo; + tail[15] = hi; + md5cycle(this._hash, tail); + }; + + /** + * Performs the md5 hash on a string. + * A conversion will be applied if utf8 string is detected. + * + * @param {String} str The string + * @param {Boolean} raw True to get the raw result, false to get the hex result + * + * @return {String|Array} The result + */ + SparkMD5.hash = function (str, raw) { + // Converts the string to utf8 bytes if necessary + // Then compute it using the binary function + return SparkMD5.hashBinary(toUtf8(str), raw); + }; + + /** + * Performs the md5 hash on a binary string. + * + * @param {String} content The binary string + * @param {Boolean} raw True to get the raw result, false to get the hex result + * + * @return {String|Array} The result + */ + SparkMD5.hashBinary = function (content, raw) { + var hash = md51(content); + + return !!raw ? hash : hex(hash); + }; + + // --------------------------------------------------- + + /** + * SparkMD5 OOP implementation for array buffers. + * + * Use this class to perform an incremental md5 ONLY for array buffers. + */ + SparkMD5.ArrayBuffer = function () { + // call reset to init the instance + this.reset(); + }; + + /** + * Appends an array buffer. + * + * @param {ArrayBuffer} arr The array to be appended + * + * @return {SparkMD5.ArrayBuffer} The instance itself + */ + SparkMD5.ArrayBuffer.prototype.append = function (arr) { + var buff = concatenateArrayBuffers(this._buff.buffer, arr, true), + length = buff.length, + i; + + this._length += arr.byteLength; + + for (i = 64; i <= length; i += 64) { + md5cycle(this._hash, md5blk_array(buff.subarray(i - 64, i))); + } + + // Avoids IE10 weirdness (documented above) + this._buff = (i - 64) < length ? buff.subarray(i - 64) : new Uint8Array(0); + + return this; + }; + + /** + * Finishes the incremental computation, reseting the internal state and + * returning the result. + * Use the raw parameter to obtain the raw result instead of the hex one. + * + * @param {Boolean} raw True to get the raw result, false to get the hex result + * + * @return {String|Array} The result + */ + SparkMD5.ArrayBuffer.prototype.end = function (raw) { + var buff = this._buff, + length = buff.length, + tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + i, + ret; + + for (i = 0; i < length; i += 1) { + tail[i >> 2] |= buff[i] << ((i % 4) << 3); + } + + this._finish(tail, length); + ret = !!raw ? this._hash : hex(this._hash); + + this.reset(); + + return ret; + }; + + /** + * Resets the internal state of the computation. + * + * @return {SparkMD5.ArrayBuffer} The instance itself + */ + SparkMD5.ArrayBuffer.prototype.reset = function () { + this._buff = new Uint8Array(0); + this._length = 0; + this._hash = [1732584193, -271733879, -1732584194, 271733878]; + + return this; + }; + + /** + * Gets the internal state of the computation. + * + * @return {Object} The state + */ + SparkMD5.ArrayBuffer.prototype.getState = function () { + var state = SparkMD5.prototype.getState.call(this); + + // Convert buffer to a string + state.buff = arrayBuffer2Utf8Str(state.buff); + + return state; + }; + + /** + * Gets the internal state of the computation. + * + * @param {Object} state The state + * + * @return {SparkMD5.ArrayBuffer} The instance itself + */ + SparkMD5.ArrayBuffer.prototype.setState = function (state) { + // Convert string to buffer + state.buff = utf8Str2ArrayBuffer(state.buff, true); + + return SparkMD5.prototype.setState.call(this, state); + }; + + SparkMD5.ArrayBuffer.prototype.destroy = SparkMD5.prototype.destroy; + + SparkMD5.ArrayBuffer.prototype._finish = SparkMD5.prototype._finish; + + /** + * Performs the md5 hash on an array buffer. + * + * @param {ArrayBuffer} arr The array buffer + * @param {Boolean} raw True to get the raw result, false to get the hex result + * + * @return {String|Array} The result + */ + SparkMD5.ArrayBuffer.hash = function (arr, raw) { + var hash = md51_array(new Uint8Array(arr)); + + return !!raw ? hash : hex(hash); + }; + + return SparkMD5; + })); + + },{}],3:[function(require,module,exports){ + window.ALY = module.exports = require('./lib/core'); + require('./lib/http/xhr'); + + require('./lib/services/oss'); + require('./lib/services/opensearch'); + require('./lib/services/batchcompute'); + + ALY.ECS = ALY.Service.defineService('ecs', ['2014-05-26']); + ALY.RDS = ALY.Service.defineService('rds', ['2014-08-15']); + ALY.SLB = ALY.Service.defineService('slb', ['2014-05-15']); + ALY.CDN = ALY.Service.defineService('cdn', ['2014-11-11']); + ALY.STS = ALY.Service.defineService('sts', ['2015-04-01']); + ALY.ESS = ALY.Service.defineService('ess', ['2014-08-28']); + + },{"./lib/core":5,"./lib/http/xhr":8,"./lib/services/batchcompute":21,"./lib/services/opensearch":22,"./lib/services/oss":23}],4:[function(require,module,exports){ + var ALY = require('./core'); + + ALY.Config = ALY.util.inherit({ + + constructor: function Config(options) { + if (options === undefined) options = {}; + + ALY.util.each.call(this, this.keys, function (key, value) { + this.set(key, options[key], value); + }); + }, + + clear: function clear() { + /*jshint forin:false */ + ALY.util.each.call(this, this.keys, function (key) { + delete this[key]; + }); + + // reset credential provider + this.set('credentials', undefined); + this.set('credentialProvider', undefined); + }, + + getCredentials: function getCredentials() { + return { + accessKeyId: this.accessKeyId, + secretAccessKey: this.secretAccessKey, + securityToken: this.securityToken + }; + }, + + /** + * Sets a property on the configuration object, allowing for a + * default value + * @api private + */ + set: function set(property, value, defaultValue) { + if (value === undefined) { + if (defaultValue === undefined) { + defaultValue = this.keys[property]; + } + if (typeof defaultValue === 'function') { + this[property] = defaultValue.call(this); + } else { + this[property] = defaultValue; + } + } else { + this[property] = value; + } + }, + + keys: { + accessKeyId: null, + secretAccessKey: null, + region: null, + logger: null, + apiVersions: {}, + apiVersion: null, + endpoint: undefined, + endpointFixed: undefined, // 目前仅对 ots 有效 + httpOptions: {}, + maxRetries: undefined, + maxRedirects: 10, + paramValidation: true, + sslEnabled: true, + computeChecksums: true, + securityToken: '' + } + }); + + },{"./core":5}],5:[function(require,module,exports){ + /** + * The main ALY namespace + * + * @!macro [new] nobrowser + * @note This feature is not supported in the browser environment of the SDK. + */ + var ALY = {}; + module.exports = ALY; + require('./util'); + + ALY.util.update(ALY, { + + VERSION: '1.0.0', + + ServiceInterface: {}, + + Signers: {}, + + XML: {} + + }); + + require('./service'); + + require('./config'); + require('./http'); + require('./sequential_executor'); + require('./event_listeners'); + require('./request'); + require('./signers/request_signer'); + require('./param_validator'); + + ALY.events = new ALY.SequentialExecutor(); + + },{"./config":4,"./event_listeners":6,"./http":7,"./param_validator":10,"./request":11,"./sequential_executor":12,"./service":13,"./signers/request_signer":31,"./util":34}],6:[function(require,module,exports){ + var ALY = require('./core'); + require('./sequential_executor'); + require('./service_interface/json'); + require('./service_interface/query'); + require('./service_interface/rest'); + require('./service_interface/rest_json'); + require('./service_interface/rest_xml'); + require('./service_interface/pop'); + require('./service_interface/top'); + + ALY.EventListeners = { + Core: {} + }; + + ALY.EventListeners = { + Core: new ALY.SequentialExecutor().addNamedListeners(function(add, addAsync) { + + add('VALIDATE_PARAMETERS', 'validate', function VALIDATE_PARAMETERS(req) { + var rules = req.service.api.operations[req.operation].input; + new ALY.ParamValidator().validate(rules, req.params); + }); + + add('SET_CONTENT_LENGTH', 'afterBuild', function SET_CONTENT_LENGTH(req) { + if (req.httpRequest.headers['Content-Length'] === undefined) { + var length = ALY.util.string.byteLength(req.httpRequest.body); + req.httpRequest.headers['Content-Length'] = length; + } + }); + + add('SET_HTTP_HOST', 'afterBuild', function SET_HTTP_HOST(req) { + req.httpRequest.headers['Host'] = req.httpRequest.endpoint.host; + }); + + addAsync('SIGN', 'sign', function SIGN(req, done) { + if (!req.service.api.signatureVersion) return done(); // none + + var credentials = req.service.config.getCredentials(); + + try { + var date = ALY.util.date.getDate(); + var SignerClass = req.service.getSignerClass(req); + var signer = new SignerClass(req.httpRequest, req.service.api.signingName); + + // add new authorization + signer.addAuthorization(credentials, date); + } catch (e) { + req.response.error = e; + } + done(); + }); + + add('VALIDATE_RESPONSE', 'validateResponse', function VALIDATE_RESPONSE(resp) { + if (this.service.successfulResponse(resp, this)) { + resp.data = {}; + resp.error = null; + } else { + resp.data = null; + resp.error = ALY.util.error(new Error(), + {code: 'UnknownError', message: 'An unknown error occurred.'}); + } + }); + + addAsync('SEND', 'send', function SEND(resp, done) { + function callback(httpResp) { + resp.httpResponse.stream = httpResp; + resp.httpResponse._abortCallback = done; + + httpResp.on('headers', function onHeaders(statusCode, headers) { + resp.request.emit('httpHeaders', [statusCode, headers, resp]); + + if (!resp.request.httpRequest._streaming) { + if (ALY.HttpClient.streamsApiVersion === 2) { // streams2 API check + httpResp.on('readable', function onReadable() { + var data = httpResp.read(); + if (data !== null) { + resp.request.emit('httpData', [data, resp]); + } + }); + } else { // legacy streams API + httpResp.on('data', function onData(data) { + resp.request.emit('httpData', [data, resp]); + }); + } + } + }); + + httpResp.on('end', function onEnd() { + resp.request.emit('httpDone'); + done(); + }); + } + + function progress(httpResp) { + httpResp.on('sendProgress', function onSendProgress(progress) { + resp.request.emit('httpUploadProgress', [progress, resp]); + }); + + httpResp.on('receiveProgress', function onReceiveProgress(progress) { + resp.request.emit('httpDownloadProgress', [progress, resp]); + }); + } + + function error(err) { + resp.error = ALY.util.error(err, { + code: 'NetworkingError', + region: resp.request.httpRequest.region, + hostname: resp.request.httpRequest.endpoint.hostname, + retryable: true + }); + resp.request.emit('httpError', [resp.error, resp], function() { + done(); + }); + } + + resp.error = null; + resp.data = null; + + var http = ALY.HttpClient.getInstance(); + var httpOptions = resp.request.service.config.httpOptions || {}; + this.httpRequest.debug(); + var s = http.handleRequest(this.httpRequest, httpOptions, callback, error); + progress(s); + }); + + add('HTTP_HEADERS', 'httpHeaders', + function HTTP_HEADERS(statusCode, headers, resp) { + resp.httpResponse.statusCode = statusCode; + resp.httpResponse.headers = headers; + resp.httpResponse.body = new ALY.util.Buffer(''); + resp.httpResponse.buffers = []; + resp.httpResponse.numBytes = 0; + }); + + add('HTTP_DATA', 'httpData', function HTTP_DATA(chunk, resp) { + if (chunk) { + if (ALY.util.isNode()) { + resp.httpResponse.numBytes += chunk.length; + + var total = resp.httpResponse.headers['content-length']; + var progress = { loaded: resp.httpResponse.numBytes, total: total }; + resp.request.emit('httpDownloadProgress', [progress, resp]); + } + + resp.httpResponse.buffers.push(new ALY.util.Buffer(chunk)); + } + }); + + add('HTTP_DONE', 'httpDone', function HTTP_DONE(resp) { + // convert buffers array into single buffer + if (resp.httpResponse.buffers && resp.httpResponse.buffers.length > 0) { + var body = ALY.util.buffer.concat(resp.httpResponse.buffers); + resp.httpResponse.body = body; + } + delete resp.httpResponse.numBytes; + delete resp.httpResponse.buffers; + }); + + add('FINALIZE_ERROR', 'retry', function FINALIZE_ERROR(resp) { + if (resp.httpResponse.statusCode) { + resp.error.statusCode = resp.httpResponse.statusCode; + if (resp.error.retryable === undefined) { + resp.error.retryable = this.service.retryableError(resp.error, this); + } + } + }); + + }), + + Logger: new ALY.SequentialExecutor().addNamedListeners(function(add) { + add('LOG_REQUEST', 'complete', function LOG_REQUEST(resp) { + var req = resp.request; + var logger = req.service.config.logger; + if (!logger) return; + + function buildMessage() { + var time = ALY.util.date.getDate().getTime(); + var delta = (time - req.startTime.getTime()) / 1000; + var ansi = logger.isTTY ? true : false; + var status = resp.httpResponse.statusCode; + var params = require('util').inspect(req.params, true, true); + + var message = ''; + if (ansi) message += '\x1B[33m'; + message += '[ALY ' + req.service.serviceIdentifier + ' ' + status; + message += ' ' + delta.toString() + 's ' + resp.retryCount + ' retries]'; + if (ansi) message += '\x1B[0;1m'; + message += ' ' + req.operation + '(' + params + ')'; + if (ansi) message += '\x1B[0m'; + return message; + } + + var message = buildMessage(); + if (typeof logger.log === 'function') { + logger.log(message); + } else if (typeof logger.write === 'function') { + logger.write(message + '\n'); + } + }); + }), + + Json: new ALY.SequentialExecutor().addNamedListeners(function(add) { + var svc = ALY.ServiceInterface.Json; + add('BUILD', 'build', svc.buildRequest); + add('EXTRACT_DATA', 'extractData', svc.extractData); + add('EXTRACT_ERROR', 'extractError', svc.extractError); + }), + + Rest: new ALY.SequentialExecutor().addNamedListeners(function(add) { + var svc = ALY.ServiceInterface.Rest; + add('BUILD', 'build', svc.buildRequest); + add('EXTRACT_DATA', 'extractData', svc.extractData); + add('EXTRACT_ERROR', 'extractError', svc.extractError); + }), + + RestJson: new ALY.SequentialExecutor().addNamedListeners(function(add) { + var svc = ALY.ServiceInterface.RestJson; + add('BUILD', 'build', svc.buildRequest); + add('EXTRACT_DATA', 'extractData', svc.extractData); + add('EXTRACT_ERROR', 'extractError', svc.extractError); + }), + + Pop: new ALY.SequentialExecutor().addNamedListeners(function(add) { + var svc = ALY.ServiceInterface.Pop; + add('BUILD', 'build', svc.buildRequest); + add('EXTRACT_DATA', 'extractData', svc.extractData); + add('EXTRACT_ERROR', 'extractError', svc.extractError); + }), + + Top: new ALY.SequentialExecutor().addNamedListeners(function(add) { + var svc = ALY.ServiceInterface.Top; + add('BUILD', 'build', svc.buildRequest); + add('EXTRACT_DATA', 'extractData', svc.extractData); + add('EXTRACT_ERROR', 'extractError', svc.extractError); + }), + + RestXml: new ALY.SequentialExecutor().addNamedListeners(function(add) { + var svc = ALY.ServiceInterface.RestXml; + add('BUILD', 'build', svc.buildRequest); + add('EXTRACT_DATA', 'extractData', svc.extractData); + add('EXTRACT_ERROR', 'extractError', svc.extractError); + }), + + Query: new ALY.SequentialExecutor().addNamedListeners(function(add) { + var svc = ALY.ServiceInterface.Query; + add('BUILD', 'build', svc.buildRequest); + add('EXTRACT_DATA', 'extractData', svc.extractData); + add('EXTRACT_ERROR', 'extractError', svc.extractError); + }) + }; + + },{"./core":5,"./sequential_executor":12,"./service_interface/json":14,"./service_interface/pop":15,"./service_interface/query":16,"./service_interface/rest":17,"./service_interface/rest_json":18,"./service_interface/rest_xml":19,"./service_interface/top":20,"util":111}],7:[function(require,module,exports){ + (function (process){ + var ALY = require('./core'); + var inherit = ALY.util.inherit; + + ALY.Endpoint = inherit({ + + constructor: function Endpoint(endpoint) { + ALY.util.hideProperties(this, ['slashes', 'auth', 'hash', 'search', 'query']); + + if (typeof endpoint === 'undefined' || endpoint === null) { + throw new Error('Invalid endpoint: ' + endpoint); + } + + if (!endpoint.match(/^http/)) { + throw new Error('错误的 endpoint 格式, 需要以 http 或者 https 开头'); + } + + ALY.util.update(this, ALY.util.urlParse(endpoint)); + + // Ensure the port property is set as an integer + if (this.port) { + this.port = parseInt(this.port, 10); + } else { + this.port = this.protocol === 'https:' ? 443 : 80; + } + } + + }); + + ALY.HttpRequest = inherit({ + + constructor: function HttpRequest(endpoint, region) { + this.method = 'POST'; + this.path = endpoint.path || '/'; + this.headers = {}; + this.body = ''; + this.endpoint = endpoint; + this.region = region; + this.setUserAgent(); + }, + + setUserAgent: function setUserAgent() { + //var prefix = ALY.util.isBrowser() ? 'X-Aly-' : ''; + //this.headers[prefix + 'User-Agent'] = ALY.util.userAgent(); + //this.headers['x-sdk-client'] = this.headers['User-Agent'] = ALY.util.userAgent(); + // pop 现在不支持 x-sdk-client 在浏览器设置 + this.headers['User-Agent'] = ALY.util.userAgent(); + }, + + pathname: function pathname() { + return this.path.split('?', 1)[0]; + }, + + search: function search() { + return this.path.split('?', 2)[1] || ''; + }, + + debug: function () { + if(process.env.DEBUG == 'aliyun') { + console.log('-------- HttpRequest Start: --------'); + console.log('method:', this.method); + console.log('path:', this.path); + console.log('headers:'); + for(var i in this.headers) { + if (i == 'constructor') + continue; + console.log(i, ':', this.headers[i]); + }; + } + } + }); + + ALY.HttpResponse = inherit({ + + constructor: function HttpResponse() { + this.statusCode = undefined; + this.headers = {}; + this.body = undefined; + } + }); + + + ALY.HttpClient = inherit({}); + + ALY.HttpClient.getInstance = function getInstance() { + /*jshint newcap:false */ + if (this.singleton === undefined) { + this.singleton = new this(); + } + return this.singleton; + }; + + }).call(this,require('_process')) + },{"./core":5,"_process":89}],8:[function(require,module,exports){ + var ALY = require('../core'); + var EventEmitter = require('events').EventEmitter; + require('../http'); + + /** + * @api private + */ + ALY.XHRClient = ALY.util.inherit({ + handleRequest: function handleRequest(httpRequest, httpOptions, callback, errCallback) { + var self = this; + var endpoint = httpRequest.endpoint; + var emitter = new EventEmitter(); + var href = endpoint.protocol + '//' + endpoint.hostname; + if (endpoint.port != 80 && endpoint.port != 443) { + href += ':' + endpoint.port; + } + href += httpRequest.path; + + href = endpoint.href; + + var xhr = new XMLHttpRequest(); + httpRequest.stream = xhr; + + if (httpOptions.timeout) { + xhr.timeout = httpOptions.timeout; + } + + xhr.addEventListener('readystatechange', function() { + try { + if (xhr.status === 0) return; // 0 code is invalid + } + catch (e) { return; } + + if (this.readyState === this.HEADERS_RECEIVED) { + try { xhr.responseType = 'arraybuffer'; } catch (e) {} + emitter.statusCode = xhr.status; + emitter.headers = self.parseHeaders(xhr.getAllResponseHeaders()); + emitter.emit('headers', emitter.statusCode, emitter.headers); + } else if (this.readyState === this.DONE) { + self.finishRequest(xhr, emitter); + } + }, false); + xhr.upload.addEventListener('progress', function (evt) { + emitter.emit('sendProgress', evt); + }); + xhr.addEventListener('progress', function (evt) { + emitter.emit('receiveProgress', evt); + }, false); + xhr.addEventListener('timeout', function () { + errCallback(ALY.util.error(new Error('Timeout'), {code: 'TimeoutError'})); + }, false); + xhr.addEventListener('error', function () { + errCallback(ALY.util.error(new Error('Network Failure'), { + code: 'NetworkingError' + })); + }, false); + + callback(emitter); + xhr.open(httpRequest.method, href, true); + ALY.util.each(httpRequest.headers, function (key, value) { + if (key !== 'Content-Length' && key !== 'User-Agent' && key !== 'Host' && key !== 'Date') { + xhr.setRequestHeader(key, value); + } + }); + + if (httpRequest.body && typeof httpRequest.body.buffer === 'object') { + xhr.send(httpRequest.body.buffer); // typed arrays sent as ArrayBuffer + } else { + xhr.send(httpRequest.body); + } + + return emitter; + }, + + parseHeaders: function parseHeaders(rawHeaders) { + var headers = {}; + ALY.util.arrayEach(rawHeaders.split(/\r?\n/), function (line) { + var key = line.split(':', 1)[0]; + var value = line.substring(key.length + 2); + if (key.length > 0) headers[key] = value; + }); + return headers; + }, + + finishRequest: function finishRequest(xhr, emitter) { + var buffer; + if (xhr.responseType === 'arraybuffer' && xhr.response) { + var ab = xhr.response; + buffer = new ALY.util.Buffer(ab.byteLength); + var view = new Uint8Array(ab); + for (var i = 0; i < buffer.length; ++i) { + buffer[i] = view[i]; + } + } + + try { + if (!buffer && typeof xhr.responseText === 'string') { + buffer = new ALY.util.Buffer(xhr.responseText); + } + } catch (e) {} + + if (buffer) emitter.emit('data', buffer); + emitter.emit('end'); + } + }); + + /** + * @api private + */ + ALY.HttpClient.prototype = ALY.XHRClient.prototype; + + /** + * @api private + */ + ALY.HttpClient.streamsApiVersion = 1; + + },{"../core":5,"../http":7,"events":86}],9:[function(require,module,exports){ + var ALY = require('../core'); + var inherit = ALY.util.inherit; + + /** + * @api private + */ + ALY.JSON = {}; + + /** + * @api private + */ + ALY.JSON.Builder = inherit({ + + constructor: function JSONBuilder(rules, options) { + this.rules = rules; + this.timestampFormat = options.timestampFormat; + }, + + build: function build(params) { + return JSON.stringify(this.translate(this.rules, params)); + }, + + translate: function translate(rules, value) { + if (value === null || value === undefined) return undefined; + + if (rules.type == 'structure') { + + // translate structures (hashes with pre-defined keys) + var struct = {}; + ALY.util.each.call(this, value, function (memberName, memberValue) { + var memberRules = rules.members[memberName] || {}; + var result = this.translate(memberRules, memberValue); + if (result !== undefined) struct[memberName] = result; + }); + return struct; + + } else if (rules.type == 'list') { + + // translate each member of the list + var list = []; + ALY.util.arrayEach.call(this, value, function (memberValue) { + var memberRules = rules.members || {}; + var result = this.translate(memberRules, memberValue); + if (result !== undefined) list.push(result); + }); + return list; + + } else if (rules.type == 'map') { + + // translate maps (hashes with user supplied keys) + var map = {}; + ALY.util.each.call(this, value, function (memberName, memberValue) { + var memberRules = rules.members || {}; + var result = this.translate(memberRules, memberValue); + if (result !== undefined) map[memberName] = result; + }); + return map; + + } else if (rules.type == 'timestamp') { + + var timestampFormat = rules.format || this.timestampFormat; + return ALY.util.date.format(value, timestampFormat); + + } else if (rules.type == 'integer') { + return parseInt(value, 10); + } else if (rules.type == 'float') { + return parseFloat(value); + } else { + + // all other shapes + return value; + + } + } + + }); + + },{"../core":5}],10:[function(require,module,exports){ + var ALY = require('./core'); + + /** + * @api private + */ + ALY.ParamValidator = ALY.util.inherit({ + validate: function validate(rules, params, context) { + var cRules = (rules || {}).members || {}; + var payload = rules ? rules.xml : null; + if (payload) { + cRules = ALY.util.merge(cRules, (cRules[payload] || {}).members || {}); + delete cRules[payload]; + } + + return this.validateStructure(cRules, params || {}, context || 'params'); + }, + + validateStructure: function validateStructure(rules, params, context) { + /*jshint maxcomplexity:12*/ + this.validateType(context, params, ['object'], 'structure'); + + /*jshint forin:false*/ + for (var paramName in rules) { + if (!rules.hasOwnProperty(paramName)) continue; + var value = params[paramName]; + var notSet = value === undefined || value === null; + if (notSet) { + if (rules[paramName].default) { + params[paramName] = rules[paramName].default; + } + else if (rules[paramName].required) { + this.fail('MissingRequiredParameter', + 'Missing required key \'' + paramName + '\' in ' + context); + } + } + //if (rules[paramName].location == 'uri' && value) { + // if (typeof value == 'string' && value.indexOf('/') == 0) { + // this.fail('UnexpectedParameter', + // 'the value of ' + paramName + ' can not start with /'); + // } + //} + } + + // validate hash members + for (paramName in params) { + if (!params.hasOwnProperty(paramName)) continue; + + var paramValue = params[paramName], + paramRules = rules[paramName]; + + if (paramRules !== undefined) { + var memberContext = [context, paramName].join('.'); + this.validateMember(paramRules, paramValue, memberContext); + } else { + this.fail('UnexpectedParameter', + 'Unexpected key \'' + paramName + '\' found in ' + context); + } + } + + return true; + }, + + validateMember: function validateMember(rules, param, context) { + var memberRules = rules.members || {}; + switch(rules.type) { + case 'structure': + return this.validateStructure(memberRules, param, context); + case 'list': + return this.validateList(memberRules, param, context); + case 'map': + return this.validateMap(memberRules, param, context); + default: + return this.validateScalar(rules, param, context); + } + }, + + validateList: function validateList(rules, params, context) { + this.validateType(context, params, [Array]); + + // validate array members + for (var i = 0; i < params.length; i++) { + this.validateMember(rules, params[i], context + '[' + i + ']'); + } + }, + + validateMap: function validateMap(rules, params, context) { + this.validateType(context, params, ['object'], 'map'); + + /*jshint forin:false*/ + for (var param in params) { + if (!params.hasOwnProperty(param)) continue; + this.validateMember(rules, params[param], + context + '[\'' + param + '\']'); + } + }, + + validateScalar: function validateScalar(rules, value, context) { + /*jshint maxcomplexity:12*/ + switch (rules.type) { + case null: + case undefined: + case 'string': + return this.validateType(context, value, ['string']); + case 'base64': + case 'binary': + return this.validatePayload(context, value); + case 'integer': + case 'float': + return this.validateNumber(context, value); + case 'boolean': + return this.validateType(context, value, ['boolean']); + case 'timestamp': + return this.validateType(context, value, [Date, + /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?Z$/, 'number'], + 'Date object, ISO-8601 string, or a UNIX timestamp'); + default: + return this.fail('UnkownType', 'Unhandled type ' + + rules.type + ' for ' + context); + } + }, + + fail: function fail(code, message) { + throw ALY.util.error(new Error(message), {code: code}); + }, + + validateType: function validateType(context, value, acceptedTypes, type) { + /*jshint maxcomplexity:14*/ + if (value === null || value === undefined) return; + + var foundInvalidType = false; + for (var i = 0; i < acceptedTypes.length; i++) { + if (typeof acceptedTypes[i] === 'string') { + if (typeof value === acceptedTypes[i]) return; + } else if (acceptedTypes[i] instanceof RegExp) { + if ((value || '').toString().match(acceptedTypes[i])) return; + } else { + if (value instanceof acceptedTypes[i]) return; + if (ALY.util.isType(value, acceptedTypes[i])) return; + if (!type && !foundInvalidType) acceptedTypes = acceptedTypes.slice(); + acceptedTypes[i] = ALY.util.typeName(acceptedTypes[i]); + } + foundInvalidType = true; + } + + var acceptedType = type; + if (!acceptedType) { + /*jshint regexp:false*/ + acceptedType = acceptedTypes.join(', ').replace(/,([^,]+)$/, ', or$1'); + } + + var vowel = acceptedType.match(/^[aeiou]/i) ? 'n' : ''; + this.fail('InvalidParameterType', 'Expected ' + context + ' to be a' + + vowel + ' ' + acceptedType); + }, + + validateNumber: function validateNumber(context, value) { + if (value === null || value === undefined) return; + if (typeof value === 'string') { + var castedValue = parseFloat(value); + if (castedValue.toString() === value) value = castedValue; + } + return this.validateType(context, value, ['number']); + }, + + validatePayload: function validatePayload(context, value) { + /*jshint maxcomplexity:14*/ + if (value === null || value === undefined) return; + if (typeof value === 'string') return; + if (value && typeof value.byteLength === 'number') return; // typed arrays + if (ALY.util.isNode()) { // special check for buffer/stream in Node.js + var Stream = require('stream').Stream; + if (ALY.util.Buffer.isBuffer(value) || value instanceof Stream) return; + } + + var types = ['Buffer', 'Stream', 'File', 'Blob', 'ArrayBuffer', 'DataView']; + if (value) { + for (var i = 0; i < types.length; i++) { + if (ALY.util.isType(value, types[i])) return; + if (ALY.util.typeName(value.constructor) === types[i]) return; + } + } + + this.fail('InvalidParameterType', 'Expected ' + context + ' to be a ' + + 'string, Buffer, Stream, Blob, or typed array object'); + } + }); + + },{"./core":5,"stream":107}],11:[function(require,module,exports){ + (function (process){ + var ALY = require('./core'); + var inherit = ALY.util.inherit; + + function AcceptorStateMachine(states, state) { + this.currentState = state || null; + this.states = states || {}; + } + + AcceptorStateMachine.prototype.runTo = function runTo(finalState, done, bindObject, inputError) { + if (typeof finalState === 'function') { + inputError = bindObject; bindObject = done; + done = finalState; finalState = null; + } + + var self = this; + var state = self.states[self.currentState]; + state.fn.call(bindObject || self, inputError, function(err) { + if (err) { + if (bindObject.logger) bindObject.logger.log(self.currentState, '->', state.fail, err); + if (state.fail) self.currentState = state.fail; + else return done ? done(err) : null; + } else { + if (bindObject.logger) bindObject.logger.log(self.currentState, '->', state.accept); + if (state.accept) self.currentState = state.accept; + else return done ? done() : null; + } + if (self.currentState === finalState) return done ? done(err) : null; + + self.runTo(finalState, done, bindObject, err); + }); + }; + + AcceptorStateMachine.prototype.addState = function addState(name, acceptState, failState, fn) { + if (typeof acceptState === 'function') { + fn = acceptState; acceptState = null; failState = null; + } else if (typeof failState === 'function') { + fn = failState; failState = null; + } + + if (!this.currentState) this.currentState = name; + this.states[name] = { accept: acceptState, fail: failState, fn: fn }; + return this; + }; + + var fsm = new AcceptorStateMachine(); + fsm.setupStates = function() { + var hardErrorStates = ['success', 'error', 'complete']; + var transition = function transition(err, done) { + try { + var self = this; + var origError = self.response.error; + self.emit(self._asm.currentState, function() { + if (self.response.error && origError != self.response.error) { + if (hardErrorStates.indexOf(this._asm.currentState) >= 0) { + this._hardError = true; + } + } + done(self.response.error); + }); + + } catch (e) { + this.response.error = e; + if (hardErrorStates.indexOf(this._asm.currentState) >= 0) { + this._hardError = true; + } + done(e); + } + }; + + this.addState('validate', 'build', 'error', transition); + this.addState('restart', 'build', 'error', function(err, done) { + err = this.response.error; + if (!err) return done(); + if (!err.retryable) return done(err); + + if (this.response.retryCount < this.service.config.maxRetries) { + this.response.retryCount++; + done(); + } else { + done(err); + } + }); + this.addState('build', 'afterBuild', 'restart', transition); + this.addState('afterBuild', 'sign', 'restart', transition); + this.addState('sign', 'send', 'retry', transition); + this.addState('retry', 'afterRetry', 'afterRetry', transition); + this.addState('afterRetry', 'sign', 'error', transition); + this.addState('send', 'validateResponse', 'retry', transition); + this.addState('validateResponse', 'extractData', 'extractError', transition); + this.addState('extractError', 'extractData', 'retry', transition); + this.addState('extractData', 'success', 'retry', transition); + this.addState('success', 'complete', 'complete', transition); + this.addState('error', 'complete', 'complete', transition); + this.addState('complete', null, 'uncaughtException', transition); + this.addState('uncaughtException', function(err, done) { + try { + ALY.SequentialExecutor.prototype.unhandledErrorCallback.call(this, err); + } catch (e) { + if (this._hardError) throw err; + } + done(err); + }); + }; + fsm.setupStates(); + + ALY.Request = inherit({ + + /** + * Creates a request for an operation on a given service with + * a set of input parameters. + * + * @param service [ALY.Service] the service to perform the operation on + * @param operation [String] the operation to perform on the service + * @param params [Object] parameters to send to the operation. + * See the operation's documentation for the format of the + * parameters. + */ + constructor: function Request(service, operation, params) { + var endpoint = new ALY.Endpoint(service.config.endpoint); + var region = service.config.region; + + this.service = service; + this.operation = operation; + this.params = params || {}; + this.httpRequest = new ALY.HttpRequest(endpoint, region); + this.startTime = ALY.util.date.getDate(); + + this.response = new ALY.Response(this); + this.restartCount = 0; + this._asm = new AcceptorStateMachine(fsm.states, 'validate'); + + ALY.SequentialExecutor.call(this); + this.emit = this.emitEvent; + }, + + /** + * @!group Sending a Request + */ + + /** + * @overload send(callback = null) + * Sends the request object. + * + * @callback callback function(err, data) + * If a callback is supplied, it is called when a response is returned + * from the service. + * @param err [Error] the error object returned from the request. + * Set to `null` if the request is successful. + * @param data [Object] the de-serialized data returned from + * the request. Set to `null` if a request error occurs. + * @example Sending a request with a callback + * request = s3.putObject({Bucket: 'bucket', Key: 'key'}); + * request.send(function(err, data) { console.log(err, data); }); + * @example Sending a request with no callback (using event handlers) + * request = s3.putObject({Bucket: 'bucket', Key: 'key'}); + * request.on('complete', function(response) { ... }); // register a callback + * request.send(); + */ + send: function send(callback) { + if (callback) { + this.on('complete', function (resp) { + try { + callback.call(resp, resp.error, resp.data); + } catch (e) { + resp.request._hardError = true; + throw e; + } + }); + } + this.runTo(); + + return this.response; + }, + + build: function build(callback) { + this._hardError = callback ? false : true; + return this.runTo('send', callback); + }, + + runTo: function runTo(state, done) { + this._asm.runTo(state, done, this); + return this; + }, + + /** + * Aborts a request, emitting the error and complete events. + * + * @!macro nobrowser + * @example Aborting a request after sending + * var params = { + * Bucket: 'bucket', Key: 'key', + * Body: new Buffer(1024 * 1024 * 5) // 5MB payload + * }; + * var request = s3.putObject(params); + * request.send(function (err, data) { + * if (err) console.log("Error:", err.code, err.message); + * else console.log(data); + * }); + * + * // abort request in 1 second + * setTimeout(request.abort.bind(request), 1000); + * + * // prints "Error: RequestAbortedError Request aborted by user" + * @return [ALY.Request] the same request object, for chaining. + * @since v1.4.0 + */ + abort: function abort() { + this.removeAllListeners('validateResponse'); + this.removeAllListeners('extractError'); + this.on('validateResponse', function addAbortedError(resp) { + resp.error = ALY.util.error(new Error('Request aborted by user'), { + code: 'RequestAbortedError', retryable: false + }); + }); + + if (this.httpRequest.stream) { // abort HTTP stream + this.httpRequest.stream.abort(); + this.httpRequest._abortCallback(); + } + + return this; + }, + + /** + * Iterates over each page of results given a pageable request, calling + * the provided callback with each page of data. After all pages have been + * retrieved, the callback is called with `null` data. + * + * @note This operation can generate multiple requests to a service. + * @example Iterating over multiple pages of objects in an S3 bucket + * var pages = 1; + * s3.listObjects().eachPage(function(err, data) { + * if (err) return; + * console.log("Page", pages++); + * console.log(data); + * }); + * @callback callback function(err, data) + * Called with each page of resulting data from the request. + * + * @param err [Error] an error object, if an error occurred. + * @param data [Object] a single page of response data. If there is no + * more data, this object will be `null`. + * @return [Boolean] if the callback returns `false`, pagination will + * stop. + * + * @api experimental + * @see ALY.Request.eachItem + * @see ALY.Response.nextPage + * @since v1.4.0 + */ + eachPage: function eachPage(callback) { + function wrappedCallback(response) { + var result = callback.call(response, response.error, response.data); + if (result === false) return; + + if (response.hasNextPage()) { + response.nextPage().on('complete', wrappedCallback).send(); + } else { + callback.call(response, null, null); + } + } + + this.on('complete', wrappedCallback).send(); + }, + + /** + * Enumerates over individual items of a request, paging the responses if + * necessary. + * + * @api experimental + * @since v1.4.0 + */ + eachItem: function eachItem(callback) { + function wrappedCallback(err, data) { + if (err) return callback(err, null); + if (data === null) return callback(null, null); + + var config = this.request.service.paginationConfig(this.request.operation); + var resultKey = config.resultKey; + if (Array.isArray(resultKey)) resultKey = resultKey[0]; + var results = ALY.util.jamespath.query(resultKey, data); + ALY.util.arrayEach(results, function(result) { + ALY.util.arrayEach(result, function(item) { callback(null, item); }); + }); + } + + this.eachPage(wrappedCallback); + }, + + /** + * @return [Boolean] whether the operation can return multiple pages of + * response data. + * @api experimental + * @see ALY.Response.eachPage + * @since v1.4.0 + */ + isPageable: function isPageable() { + return this.service.paginationConfig(this.operation) ? true : false; + }, + + /** + * Converts the request object into a readable stream that + * can be read from or piped into a writable stream. + * + * @note The data read from a readable stream contains only + * the raw HTTP body contents. + * @example Manually reading from a stream + * request.createReadStream().on('data', function(data) { + * console.log("Got data:", data.toString()); + * }); + * @example Piping a request body into a file + * var out = fs.createWriteStream('/path/to/outfile.jpg'); + * s3.service.getObject(params).createReadStream().pipe(out); + * @return [Stream] the readable stream object that can be piped + * or read from (by registering 'data' event listeners). + */ + createReadStream: function createReadStream() { + var streams = require('stream'); + var req = this; + var stream = null; + var legacyStreams = false; + + if (ALY.HttpClient.streamsApiVersion === 2) { + stream = new streams.Readable(); + stream._read = function() { stream.push(''); }; + } else { + stream = new streams.Stream(); + stream.readable = true; + } + + stream.sent = false; + stream.on('newListener', function(event) { + if (!stream.sent && (event === 'data' || event === 'readable')) { + if (event === 'data') legacyStreams = true; + stream.sent = true; + process.nextTick(function() { req.send(function() { }); }); + } + }); + + this.on('httpHeaders', function streamHeaders(statusCode, headers, resp) { + if (statusCode < 300) { + this.httpRequest._streaming = true; + + req.removeListener('httpData', ALY.EventListeners.Core.HTTP_DATA); + req.removeListener('httpError', ALY.EventListeners.Core.HTTP_ERROR); + req.on('httpError', function streamHttpError(error, resp) { + resp.error = error; + resp.error.retryable = false; + }); + + var httpStream = resp.httpResponse.stream; + stream.response = resp; + stream._read = function() { + var data; + /*jshint boss:true*/ + while (data = httpStream.read()) { + stream.push(data); + } + stream.push(''); + }; + + var events = ['end', 'error', (legacyStreams ? 'data' : 'readable')]; + ALY.util.arrayEach(events, function(event) { + httpStream.on(event, function(arg) { + stream.emit(event, arg); + }); + }); + } + }); + + this.on('error', function(err) { + stream.emit('error', err); + }); + + return stream; + }, + + /** + * @param [Array,Response] args This should be the response object, + * or an array of args to send to the event. + * @api private + */ + emitEvent: function emit(eventName, args, done) { + if (typeof args === 'function') { done = args; args = null; } + if (!done) done = this.unhandledErrorCallback; + if (!args) args = this.eventParameters(eventName, this.response); + + var origEmit = ALY.SequentialExecutor.prototype.emit; + origEmit.call(this, eventName, args, function (err) { + if (err) this.response.error = err; + done.call(this, err); + }); + }, + + /** + * @api private + */ + eventParameters: function eventParameters(eventName) { + switch (eventName) { + case 'validate': + case 'sign': + case 'build': + case 'afterBuild': + return [this]; + case 'error': + return [this.response.error, this.response]; + default: + return [this.response]; + } + } + }); + + ALY.util.mixin(ALY.Request, ALY.SequentialExecutor); + + ALY.Response = inherit({ + + /** + * @api private + */ + constructor: function Response(request) { + this.request = request; + this.data = null; + this.error = null; + this.retryCount = 0; + this.redirectCount = 0; + this.httpResponse = new ALY.HttpResponse(); + }, + + nextPage: function nextPage(callback) { + var config; + var service = this.request.service; + var operation = this.request.operation; + try { + config = service.paginationConfig(operation, true); + } catch (e) { this.error = e; } + + if (!this.hasNextPage()) { + if (callback) callback(this.error, null); + else if (this.error) throw this.error; + return null; + } + + var params = ALY.util.copy(this.request.params); + if (!this.nextPageTokens) { + return callback ? callback(null, null) : null; + } else { + var inputTokens = config.inputToken; + if (typeof inputTokens === 'string') inputTokens = [inputTokens]; + for (var i = 0; i < inputTokens.length; i++) { + params[inputTokens[i]] = this.nextPageTokens[i]; + } + return service.makeRequest(this.request.operation, params, callback); + } + }, + + /** + * @return [Boolean] whether more pages of data can be returned by further + * requests + * @api experimental + * @since v1.4.0 + */ + hasNextPage: function hasNextPage() { + this.cacheNextPageTokens(); + if (this.nextPageTokens) return true; + if (this.nextPageTokens === undefined) return undefined; + else return false; + }, + + /** + * @api private + */ + cacheNextPageTokens: function cacheNextPageTokens() { + if (this.hasOwnProperty('nextPageTokens')) return this.nextPageTokens; + this.nextPageTokens = undefined; + + var config = this.request.service.paginationConfig(this.request.operation); + if (!config) return this.nextPageTokens; + + this.nextPageTokens = null; + if (config.moreResults) { + if (!ALY.util.jamespath.find(config.moreResults, this.data)) { + return this.nextPageTokens; + } + } + + var exprs = config.outputToken; + if (typeof exprs === 'string') exprs = [exprs]; + ALY.util.arrayEach.call(this, exprs, function (expr) { + var output = ALY.util.jamespath.find(expr, this.data); + if (output) { + this.nextPageTokens = this.nextPageTokens || []; + this.nextPageTokens.push(output); + } + }); + + return this.nextPageTokens; + } + + }); + + }).call(this,require('_process')) + },{"./core":5,"_process":89,"stream":107}],12:[function(require,module,exports){ + (function (process){ + var ALY = require('./core'); + var domain = ALY.util.nodeRequire('domain'); + + /** + * @!method on(eventName, callback) + * Registers an event listener callback for the event given by `eventName`. + * Parameters passed to the callback function depend on the individual event + * being triggered. See the event documentation for those parameters. + * + * @param eventName [String] the event name to register the listener for + * @param callback [Function] the listener callback function + * @return [ALY.SequentialExecutor] the same object for chaining + */ + ALY.SequentialExecutor = ALY.util.inherit({ + + constructor: function SequentialExecutor() { + this.domain = domain && domain.active; + this._events = {}; + }, + + /** + * @api private + */ + listeners: function listeners(eventName) { + return this._events[eventName] ? this._events[eventName].slice(0) : []; + }, + + on: function on(eventName, listener) { + if (this._events[eventName]) { + this._events[eventName].push(listener); + } else { + this._events[eventName] = [listener]; + } + return this; + }, + + onAsync: function onAsync(eventName, listener) { + listener._isAsync = true; + return this.on(eventName, listener); + }, + + removeListener: function removeListener(eventName, listener) { + var listeners = this._events[eventName]; + if (listeners) { + var length = listeners.length; + var position = -1; + for (var i = 0; i < length; ++i) { + if (listeners[i] === listener) { + position = i; + } + } + if (position > -1) { + listeners.splice(position, 1); + } + } + return this; + }, + + removeAllListeners: function removeAllListeners(eventName) { + if (eventName) { + delete this._events[eventName]; + } else { + this._events = {}; + } + return this; + }, + + /** + * @api private + */ + emit: function emit(eventName, eventArgs, doneCallback) { + if (!doneCallback) doneCallback = this.unhandledErrorCallback; + if (domain && this.domain instanceof domain.Domain) + this.domain.enter(); + + if(process.env.DEBUG == 'aliyun') { + console.log('emit', eventName); + } + var listeners = this.listeners(eventName); + var count = listeners.length; + this.callListeners(listeners, eventArgs, doneCallback); + return count > 0; + }, + + /** + * @api private + */ + callListeners: function callListeners(listeners, args, doneCallback) { + if (listeners.length === 0) { + doneCallback.call(this); + if (domain && this.domain instanceof domain.Domain) + this.domain.exit(); + } else { + var listener = listeners.shift(); + if (listener._isAsync) { + + // asynchronous listener + var callNextListener = function(err) { + if (err) { + doneCallback.call(this, err); + if (domain && this.domain instanceof domain.Domain) + this.domain.exit(); + } else { + this.callListeners(listeners, args, doneCallback); + } + }.bind(this); + listener.apply(this, args.concat([callNextListener])); + + } else { + + // synchronous listener + try { + listener.apply(this, args); + this.callListeners(listeners, args, doneCallback); + } catch (err) { + doneCallback.call(this, err); + if (domain && this.domain instanceof domain.Domain) + this.domain.exit(); + } + + } + } + }, + + /** + * Adds or copies a set of listeners from another list of + * listeners or SequentialExecutor object. + * + * @param listeners [map>, ALY.SequentialExecutor] + * a list of events and callbacks, or an event emitter object + * containing listeners to add to this emitter object. + * @return [ALY.SequentialExecutor] the emitter object, for chaining. + * @example Adding listeners from a map of listeners + * emitter.addListeners({ + * event1: [function() { ... }, function() { ... }], + * event2: [function() { ... }] + * }); + * emitter.emit('event1'); // emitter has event1 + * emitter.emit('event2'); // emitter has event2 + * @example Adding listeners from another emitter object + * var emitter1 = new ALY.SequentialExecutor(); + * emitter1.on('event1', function() { ... }); + * emitter1.on('event2', function() { ... }); + * var emitter2 = new ALY.SequentialExecutor(); + * emitter2.addListeners(emitter1); + * emitter2.emit('event1'); // emitter2 has event1 + * emitter2.emit('event2'); // emitter2 has event2 + */ + addListeners: function addListeners(listeners) { + var self = this; + + // extract listeners if parameter is an SequentialExecutor object + if (listeners._events) listeners = listeners._events; + + ALY.util.each(listeners, function(event, callbacks) { + if (typeof callbacks === 'function') callbacks = [callbacks]; + ALY.util.arrayEach(callbacks, function(callback) { + self.on(event, callback); + }); + }); + + return self; + }, + + /** + * Registers an event with {on} and saves the callback handle function + * as a property on the emitter object using a given `name`. + * + * @param name [String] the property name to set on this object containing + * the callback function handle so that the listener can be removed in + * the future. + * @param (see on) + * @return (see on) + * @example Adding a named listener DATA_CALLBACK + * var listener = function() { doSomething(); }; + * emitter.addNamedListener('DATA_CALLBACK', 'data', listener); + * + * // the following prints: true + * console.log(emitter.DATA_CALLBACK == listener); + */ + addNamedListener: function addNamedListener(name, eventName, callback) { + this[name] = callback; + this.addListener(eventName, callback); + return this; + }, + + /** + * @api private + */ + addNamedAsyncListener: function addNamedAsyncListener(name, eventName, callback) { + callback._isAsync = true; + return this.addNamedListener(name, eventName, callback); + }, + + /** + * Helper method to add a set of named listeners using + * {addNamedListener}. The callback contains a parameter + * with a handle to the `addNamedListener` method. + * + * @callback callback function(add) + * The callback function is called immediately in order to provide + * the `add` function to the block. This simplifies the addition of + * a large group of named listeners. + * @param add [Function] the {addNamedListener} function to call + * when registering listeners. + * @example Adding a set of named listeners + * emitter.addNamedListeners(function(add) { + * add('DATA_CALLBACK', 'data', function() { ... }); + * add('OTHER', 'otherEvent', function() { ... }); + * add('LAST', 'lastEvent', function() { ... }); + * }); + * + * // these properties are now set: + * emitter.DATA_CALLBACK; + * emitter.OTHER; + * emitter.LAST; + */ + addNamedListeners: function addNamedListeners(callback) { + var self = this; + callback( + function() { + self.addNamedListener.apply(self, arguments); + }, + function() { + self.addNamedAsyncListener.apply(self, arguments); + } + ); + return this; + }, + + /** + * @api private + */ + unhandledErrorCallback: function unhandledErrorCallback(err) { + if (err) { + if (domain && this.domain instanceof domain.Domain) { + err.domainEmitter = this; + err.domain = this.domain; + err.domainThrown = false; + this.domain.emit('error', err); + } else { + throw err; + } + } + } + }); + + /** + * {on} is the prefered method. + * @api private + */ + ALY.SequentialExecutor.prototype.addListener = ALY.SequentialExecutor.prototype.on; + ALY.SequentialExecutor.prototype.addAsyncListener = ALY.SequentialExecutor.prototype.onAsync; + + }).call(this,require('_process')) + },{"./core":5,"_process":89}],13:[function(require,module,exports){ + (function (__dirname){ + var ALY = require('./core'); + var inherit = ALY.util.inherit; + + const ecsApiVersion = { + "format": "pop", + "apiVersion": "2014-05-26", + "checksumFormat": "md5", + "endpointPrefix": "ecs", + "serviceAbbreviation": "ECS", + "serviceFullName": "Aliyun ECS", + "signatureVersion": "pop", + "timestampFormat": "top", + "xmlnamespace": "", + "operations": { + "allocateEipAddress": { + "name": "AllocateEipAddress", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "AllocateEipAddress" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "RegionId": { + "required": true, + "type": "string" + }, + "Bandwidth": { + "type": "string" + }, + "InternetChargeType": { + "type": "string" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "allocatePublicIpAddress": { + "name": "AllocatePublicIpAddress", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "AllocatePublicIpAddress" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "InstanceId": { + "required": true, + "type": "string" + }, + "IpAddress": { + "type": "string" + }, + "VlanId": { + "type": "string" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "associateEipAddress": { + "name": "AssociateEipAddress", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "AssociateEipAddress" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "AllocationId": { + "required": true, + "type": "string" + }, + "InstanceId": { + "required": true, + "type": "string" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "attachDisk": { + "name": "AttachDisk", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "AttachDisk" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "InstanceId": { + "required": true, + "type": "string" + }, + "DiskId": { + "required": true, + "type": "string" + }, + "Device": { + "type": "string" + }, + "DeleteWithInstance": { + "type": "boolean" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "authorizeSecurityGroup": { + "name": "AuthorizeSecurityGroup", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "AuthorizeSecurityGroup" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "SecurityGroupId": { + "required": true, + "type": "string" + }, + "RegionId": { + "required": true, + "type": "string" + }, + "IpProtocol": { + "required": true, + "type": "string" + }, + "PortRange": { + "required": true, + "type": "string" + }, + "SourceGroupId": { + "type": "string" + }, + "SourceGroupOwnerAccount": { + "type": "string" + }, + "SourceCidrIp": { + "type": "string" + }, + "Policy": { + "type": "string" + }, + "Priority": { + "type": "string" + }, + "NicType": { + "type": "string" + }, + "ClientToken": { + "type": "string" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "authorizeSecurityGroupEgress": { + "name": "AuthorizeSecurityGroupEgress", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "AuthorizeSecurityGroupEgress" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "SecurityGroupId": { + "required": true, + "type": "string" + }, + "RegionId": { + "required": true, + "type": "string" + }, + "IpProtocol": { + "required": true, + "type": "string" + }, + "PortRange": { + "required": true, + "type": "string" + }, + "DestGroupId": { + "type": "string" + }, + "DestGroupOwnerAccount": { + "type": "string" + }, + "DestCidrIp": { + "type": "string" + }, + "Policy": { + "type": "string" + }, + "Priority": { + "type": "string" + }, + "NicType": { + "type": "string" + }, + "ClientToken": { + "type": "string" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "bindIpRange": { + "name": "BindIpRange", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "BindIpRange" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "InstanceId": { + "required": true, + "type": "string" + }, + "IpAddress": { + "required": true, + "type": "string" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "cancelCopyImage": { + "name": "CancelCopyImage", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "CancelCopyImage" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "RegionId": { + "required": true, + "type": "string" + }, + "ImageId": { + "required": true, + "type": "string" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "checkAutoSnapshotPolicy": { + "name": "CheckAutoSnapshotPolicy", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "CheckAutoSnapshotPolicy" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "OwnerAccount": { + "type": "string" + }, + "SystemDiskPolicyEnabled": { + "type": "boolean" + }, + "SystemDiskPolicyTimePeriod": { + "type": "integer" + }, + "SystemDiskPolicyRetentionDays": { + "type": "integer" + }, + "SystemDiskPolicyRetentionLastWeek": { + "type": "boolean" + }, + "DataDiskPolicyEnabled": { + "type": "boolean" + }, + "DataDiskPolicyTimePeriod": { + "type": "integer" + }, + "DataDiskPolicyRetentionDays": { + "type": "integer" + }, + "DataDiskPolicyRetentionLastWeek": { + "type": "boolean" + } + } + } + }, + "checkDiskEnableAutoSnapshotValidation": { + "name": "CheckDiskEnableAutoSnapshotValidation", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "CheckDiskEnableAutoSnapshotValidation" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "OwnerAccount": { + "type": "string" + }, + "DiskIds": { + "required": true, + "type": "string" + } + } + } + }, + "copyImage": { + "name": "CopyImage", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "CopyImage" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "DestinationImageName": { + "required": true, + "type": "string" + }, + "DestinationDescription": { + "required": true, + "type": "string" + }, + "ImageId": { + "required": true, + "type": "string" + }, + "RegionId": { + "required": true, + "type": "string" + }, + "DestinationRegionId": { + "required": true, + "type": "string" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "createDisk": { + "name": "CreateDisk", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "CreateDisk" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "RegionId": { + "required": true, + "type": "string" + }, + "ZoneId": { + "required": true, + "type": "string" + }, + "SnapshotId": { + "type": "string" + }, + "DiskName": { + "type": "string" + }, + "Size": { + "type": "integer" + }, + "DiskCategory": { + "type": "string" + }, + "Description": { + "type": "string" + }, + "ClientToken": { + "type": "string" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "createImage": { + "name": "CreateImage", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "CreateImage" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "RegionId": { + "required": true, + "type": "string" + }, + "SnapshotId": { + "required": true, + "type": "string" + }, + "ImageName": { + "type": "string" + }, + "ImageVersion": { + "type": "string" + }, + "Description": { + "type": "string" + }, + "ClientToken": { + "type": "string" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "createInstance": { + "name": "CreateInstance", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "CreateInstance" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "RegionId": { + "required": true, + "type": "string" + }, + "ImageId": { + "required": true, + "type": "string" + }, + "InstanceType": { + "required": true, + "type": "string" + }, + "SecurityGroupId": { + "required": true, + "type": "string" + }, + "InstanceName": { + "type": "string" + }, + "InternetChargeType": { + "type": "string" + }, + "InternetMaxBandwidthIn": { + "type": "integer" + }, + "InternetMaxBandwidthOut": { + "type": "integer" + }, + "HostName": { + "type": "string" + }, + "Password": { + "type": "string" + }, + "ZoneId": { + "type": "string" + }, + "ClusterId": { + "type": "string" + }, + "ClientToken": { + "type": "string" + }, + "VlanId": { + "type": "string" + }, + "InnerIpAddress": { + "type": "string" + }, + "SystemDisk.Category": { + "type": "string" + }, + "SystemDisk.DiskName": { + "type": "string" + }, + "SystemDisk.Description": { + "type": "string" + }, + "DataDisk.1.Size": { + "type": "integer" + }, + "DataDisk.1.Category": { + "type": "string" + }, + "DataDisk.1.SnapshotId": { + "type": "string" + }, + "DataDisk.1.DiskName": { + "type": "string" + }, + "DataDisk.1.Description": { + "type": "string" + }, + "DataDisk.1.Device": { + "type": "string" + }, + "DataDisk.1.DeleteWithInstance": { + "type": "boolean" + }, + "DataDisk.2.Size": { + "type": "integer" + }, + "DataDisk.2.Category": { + "type": "string" + }, + "DataDisk.2.SnapshotId": { + "type": "string" + }, + "DataDisk.2.DiskName": { + "type": "string" + }, + "DataDisk.2.Description": { + "type": "string" + }, + "DataDisk.2.Device": { + "type": "string" + }, + "DataDisk.2.DeleteWithInstance": { + "type": "boolean" + }, + "DataDisk.3.Size": { + "type": "integer" + }, + "DataDisk.3.Category": { + "type": "string" + }, + "DataDisk.3.SnapshotId": { + "type": "string" + }, + "DataDisk.3.DiskName": { + "type": "string" + }, + "DataDisk.3.Description": { + "type": "string" + }, + "DataDisk.3.Device": { + "type": "string" + }, + "DataDisk.3.DeleteWithInstance": { + "type": "boolean" + }, + "DataDisk.4.Size": { + "type": "integer" + }, + "DataDisk.4.Category": { + "type": "string" + }, + "DataDisk.4.SnapshotId": { + "type": "string" + }, + "DataDisk.4.DiskName": { + "type": "string" + }, + "DataDisk.4.Description": { + "type": "string" + }, + "DataDisk.4.Device": { + "type": "string" + }, + "DataDisk.4.DeleteWithInstance": { + "type": "boolean" + }, + "NodeControllerId": { + "type": "string" + }, + "Description": { + "type": "string" + }, + "VSwitchId": { + "type": "string" + }, + "PrivateIpAddress": { + "type": "string" + }, + "IoOptimized": { + "type": "string" + }, + "OwnerAccount": { + "type": "string" + }, + "UseAdditionalService": { + "type": "boolean" + }, + "InstanceChargeType": { + "type": "string" + }, + "Period": { + "type": "integer" + } + } + } + }, + "createRouteEntry": { + "name": "CreateRouteEntry", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "CreateRouteEntry" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "RouteTableId": { + "required": true, + "type": "string" + }, + "DestinationCidrBlock": { + "required": true, + "type": "string" + }, + "NextHopId": { + "required": true, + "type": "string" + }, + "ClientToken": { + "type": "string" + }, + "NextHopType": { + "type": "string" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "createSecurityGroup": { + "name": "CreateSecurityGroup", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "CreateSecurityGroup" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "RegionId": { + "required": true, + "type": "string" + }, + "Description": { + "type": "string" + }, + "ClientToken": { + "type": "string" + }, + "SecurityGroupName": { + "type": "string" + }, + "VpcId": { + "type": "string" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "createSnapshot": { + "name": "CreateSnapshot", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "CreateSnapshot" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "DiskId": { + "required": true, + "type": "string" + }, + "SnapshotName": { + "type": "string" + }, + "Description": { + "type": "string" + }, + "ClientToken": { + "type": "string" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "createVpc": { + "name": "CreateVpc", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "CreateVpc" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "RegionId": { + "required": true, + "type": "string" + }, + "CidrBlock": { + "type": "string" + }, + "VpcName": { + "type": "string" + }, + "Description": { + "type": "string" + }, + "ClientToken": { + "type": "string" + }, + "OwnerAccount": { + "type": "string" + }, + "UserCidr": { + "type": "string" + } + } + } + }, + "createVSwitch": { + "name": "CreateVSwitch", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "CreateVSwitch" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "ZoneId": { + "required": true, + "type": "string" + }, + "CidrBlock": { + "required": true, + "type": "string" + }, + "VpcId": { + "required": true, + "type": "string" + }, + "VSwitchName": { + "type": "string" + }, + "Description": { + "type": "string" + }, + "ClientToken": { + "type": "string" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "deleteDisk": { + "name": "DeleteDisk", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "DeleteDisk" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "DiskId": { + "required": true, + "type": "string" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "deleteImage": { + "name": "DeleteImage", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "DeleteImage" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "RegionId": { + "required": true, + "type": "string" + }, + "ImageId": { + "required": true, + "type": "string" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "deleteInstance": { + "name": "DeleteInstance", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "DeleteInstance" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "InstanceId": { + "required": true, + "type": "string" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "deleteRouteEntry": { + "name": "DeleteRouteEntry", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "DeleteRouteEntry" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "RouteTableId": { + "required": true, + "type": "string" + }, + "DestinationCidrBlock": { + "required": true, + "type": "string" + }, + "NextHopId": { + "required": true, + "type": "string" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "deleteSecurityGroup": { + "name": "DeleteSecurityGroup", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "DeleteSecurityGroup" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "RegionId": { + "required": true, + "type": "string" + }, + "SecurityGroupId": { + "required": true, + "type": "string" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "deleteSnapshot": { + "name": "DeleteSnapshot", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "DeleteSnapshot" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "SnapshotId": { + "required": true, + "type": "string" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "deleteVpc": { + "name": "DeleteVpc", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "DeleteVpc" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "VpcId": { + "required": true, + "type": "string" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "deleteVSwitch": { + "name": "DeleteVSwitch", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "DeleteVSwitch" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "VSwitchId": { + "required": true, + "type": "string" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "describeAutoSnapshotPolicy": { + "name": "DescribeAutoSnapshotPolicy", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "DescribeAutoSnapshotPolicy" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "describeClusters": { + "name": "DescribeClusters", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "DescribeClusters" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "RegionId": { + "required": true, + "type": "string" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "describeDiskMonitorData": { + "name": "DescribeDiskMonitorData", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "DescribeDiskMonitorData" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "DiskId": { + "required": true, + "type": "string" + }, + "StartTime": { + "required": true, + "type": "string" + }, + "EndTime": { + "required": true, + "type": "string" + }, + "Period": { + "type": "integer" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "describeDisks": { + "name": "DescribeDisks", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "DescribeDisks" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "RegionId": { + "required": true, + "type": "string" + }, + "ZoneId": { + "type": "string" + }, + "DiskIds": { + "type": "string" + }, + "InstanceId": { + "type": "string" + }, + "DiskType": { + "type": "string" + }, + "Category": { + "type": "string" + }, + "Status": { + "type": "string" + }, + "SnapshotId": { + "type": "string" + }, + "Portable": { + "type": "boolean" + }, + "DeleteWithInstance": { + "type": "boolean" + }, + "DeleteAutoSnapshot": { + "type": "boolean" + }, + "PageNumber": { + "type": "integer" + }, + "PageSize": { + "type": "integer" + }, + "OwnerAccount": { + "type": "string" + }, + "DiskName": { + "type": "string" + }, + "EnableAutoSnapshot": { + "type": "boolean" + }, + "DiskChargeType": { + "type": "string" + }, + "LockReason": { + "type": "string" + }, + "Filter.1.Key": { + "type": "string" + }, + "Filter.2.Key": { + "type": "string" + }, + "Filter.1.Value": { + "type": "string" + }, + "Filter.2.Value": { + "type": "string" + }, + "Tag.1.Key": { + "type": "string" + }, + "Tag.2.Key": { + "type": "string" + }, + "Tag.3.Key": { + "type": "string" + }, + "Tag.4.Key": { + "type": "string" + }, + "Tag.5.Key": { + "type": "string" + }, + "Tag.1.Value": { + "type": "string" + }, + "Tag.2.Value": { + "type": "string" + }, + "Tag.3.Value": { + "type": "string" + }, + "Tag.4.Value": { + "type": "string" + }, + "Tag.5.Value": { + "type": "string" + } + } + } + }, + "describeEipAddresses": { + "name": "DescribeEipAddresses", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "DescribeEipAddresses" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "RegionId": { + "required": true, + "type": "string" + }, + "Status": { + "type": "string" + }, + "EipAddress": { + "type": "string" + }, + "AllocationId": { + "type": "string" + }, + "PageNumber": { + "type": "integer" + }, + "PageSize": { + "type": "integer" + }, + "OwnerAccount": { + "type": "string" + }, + "Filter.1.Key": { + "type": "string" + }, + "Filter.2.Key": { + "type": "string" + }, + "Filter.1.Value": { + "type": "string" + }, + "Filter.2.Value": { + "type": "string" + }, + "LockReason": { + "type": "string" + } + } + } + }, + "describeEipMonitorData": { + "name": "DescribeEipMonitorData", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "DescribeEipMonitorData" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "AllocationId": { + "required": true, + "type": "string" + }, + "StartTime": { + "required": true, + "type": "string" + }, + "EndTime": { + "required": true, + "type": "string" + }, + "Period": { + "type": "integer" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "describeImages": { + "name": "DescribeImages", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "DescribeImages" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "RegionId": { + "required": true, + "type": "string" + }, + "Status": { + "type": "string" + }, + "ImageId": { + "type": "string" + }, + "ShowExpired": { + "type": "boolean" + }, + "SnapshotId": { + "type": "string" + }, + "ImageName": { + "type": "string" + }, + "ImageOwnerAlias": { + "type": "string" + }, + "PageNumber": { + "type": "integer" + }, + "PageSize": { + "type": "integer" + }, + "OwnerAccount": { + "type": "string" + }, + "Filter.1.Key": { + "type": "string" + }, + "Filter.2.Key": { + "type": "string" + }, + "Filter.1.Value": { + "type": "string" + }, + "Filter.2.Value": { + "type": "string" + }, + "Usage": { + "type": "string" + }, + "Tag.1.Key": { + "type": "string" + }, + "Tag.2.Key": { + "type": "string" + }, + "Tag.3.Key": { + "type": "string" + }, + "Tag.4.Key": { + "type": "string" + }, + "Tag.5.Key": { + "type": "string" + }, + "Tag.1.Value": { + "type": "string" + }, + "Tag.2.Value": { + "type": "string" + }, + "Tag.3.Value": { + "type": "string" + }, + "Tag.4.Value": { + "type": "string" + }, + "Tag.5.Value": { + "type": "string" + } + } + } + }, + "describeImageSharePermission": { + "name": "DescribeImageSharePermission", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "DescribeImageSharePermission" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "RegionId": { + "required": true, + "type": "string" + }, + "ImageId": { + "required": true, + "type": "string" + }, + "PageNumber": { + "type": "integer" + }, + "PageSize": { + "type": "integer" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "describeInstanceAttribute": { + "name": "DescribeInstanceAttribute", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "DescribeInstanceAttribute" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "InstanceId": { + "required": true, + "type": "string" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "describeInstanceMonitorData": { + "name": "DescribeInstanceMonitorData", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "DescribeInstanceMonitorData" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "InstanceId": { + "required": true, + "type": "string" + }, + "StartTime": { + "required": true, + "type": "string" + }, + "EndTime": { + "required": true, + "type": "string" + }, + "Period": { + "type": "integer" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "describeInstancePhysicalAttribute": { + "name": "DescribeInstancePhysicalAttribute", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "DescribeInstancePhysicalAttribute" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "InstanceId": { + "required": true, + "type": "string" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "describeInstances": { + "name": "DescribeInstances", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "DescribeInstances" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "RegionId": { + "required": true, + "type": "string" + }, + "VpcId": { + "type": "string" + }, + "VSwitchId": { + "type": "string" + }, + "ZoneId": { + "type": "string" + }, + "InstanceNetworkType": { + "type": "string" + }, + "SecurityGroupId": { + "type": "string" + }, + "InstanceIds": { + "type": "string" + }, + "PageNumber": { + "type": "integer" + }, + "PageSize": { + "type": "integer" + }, + "InnerIpAddresses": { + "type": "string" + }, + "PrivateIpAddresses": { + "type": "string" + }, + "PublicIpAddresses": { + "type": "string" + }, + "OwnerAccount": { + "type": "string" + }, + "InstanceChargeType": { + "type": "string" + }, + "InternetChargeType": { + "type": "string" + }, + "InstanceName": { + "type": "string" + }, + "ImageId": { + "type": "string" + }, + "Status": { + "type": "string" + }, + "LockReason": { + "type": "string" + }, + "Filter.1.Key": { + "type": "string" + }, + "Filter.2.Key": { + "type": "string" + }, + "Filter.3.Key": { + "type": "string" + }, + "Filter.4.Key": { + "type": "string" + }, + "Filter.1.Value": { + "type": "string" + }, + "Filter.2.Value": { + "type": "string" + }, + "Filter.3.Value": { + "type": "string" + }, + "Filter.4.Value": { + "type": "string" + }, + "DeviceAvailable": { + "type": "boolean" + }, + "IoOptimized": { + "type": "boolean" + }, + "Tag.1.Key": { + "type": "string" + }, + "Tag.2.Key": { + "type": "string" + }, + "Tag.3.Key": { + "type": "string" + }, + "Tag.4.Key": { + "type": "string" + }, + "Tag.5.Key": { + "type": "string" + }, + "Tag.1.Value": { + "type": "string" + }, + "Tag.2.Value": { + "type": "string" + }, + "Tag.3.Value": { + "type": "string" + }, + "Tag.4.Value": { + "type": "string" + }, + "Tag.5.Value": { + "type": "string" + } + } + } + }, + "describeInstanceStatus": { + "name": "DescribeInstanceStatus", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "DescribeInstanceStatus" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "RegionId": { + "required": true, + "type": "string" + }, + "ZoneId": { + "type": "string" + }, + "ClusterId": { + "type": "string" + }, + "PageNumber": { + "type": "integer" + }, + "PageSize": { + "type": "integer" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "describeInstanceTypes": { + "name": "DescribeInstanceTypes", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "DescribeInstanceTypes" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "describeInstanceVncPasswd": { + "name": "DescribeInstanceVncPasswd", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "DescribeInstanceVncPasswd" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "RegionId": { + "required": true, + "type": "string" + }, + "InstanceId": { + "required": true, + "type": "string" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "describeInstanceVncUrl": { + "name": "DescribeInstanceVncUrl", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "DescribeInstanceVncUrl" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "RegionId": { + "required": true, + "type": "string" + }, + "InstanceId": { + "required": true, + "type": "string" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "describeIntranetAttributeKb": { + "name": "DescribeIntranetAttributeKb", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "DescribeIntranetAttributeKb" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "InstanceId": { + "required": true, + "type": "string" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "describeIpRanges": { + "name": "DescribeIpRanges", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "DescribeIpRanges" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "RegionId": { + "required": true, + "type": "string" + }, + "ClusterId": { + "required": true, + "type": "string" + }, + "NicType": { + "required": true, + "type": "string" + }, + "PageNumber": { + "type": "integer" + }, + "PageSize": { + "type": "integer" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "describeLimitation": { + "name": "DescribeLimitation", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "DescribeLimitation" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "OwnerAccount": { + "type": "string" + }, + "Limitation": { + "required": true, + "type": "string" + } + } + } + }, + "describeRegions": { + "name": "DescribeRegions", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "DescribeRegions" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "describeRouteTables": { + "name": "DescribeRouteTables", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "DescribeRouteTables" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "VRouterId": { + "required": true, + "type": "string" + }, + "RouteTableId": { + "type": "string" + }, + "PageNumber": { + "type": "integer" + }, + "PageSize": { + "type": "integer" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "describeSecurityGroupAttribute": { + "name": "DescribeSecurityGroupAttribute", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "DescribeSecurityGroupAttribute" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "SecurityGroupId": { + "required": true, + "type": "string" + }, + "RegionId": { + "required": true, + "type": "string" + }, + "NicType": { + "type": "string" + }, + "OwnerAccount": { + "type": "string" + }, + "Direction": { + "type": "string" + } + } + } + }, + "describeSecurityGroups": { + "name": "DescribeSecurityGroups", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "DescribeSecurityGroups" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "RegionId": { + "required": true, + "type": "string" + }, + "VpcId": { + "type": "string" + }, + "PageNumber": { + "type": "integer" + }, + "PageSize": { + "type": "integer" + }, + "OwnerAccount": { + "type": "string" + }, + "SecurityGroupIds": { + "type": "string" + } + } + } + }, + "describeSnapshots": { + "name": "DescribeSnapshots", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "DescribeSnapshots" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "InstanceId": { + "type": "string" + }, + "DiskId": { + "type": "string" + }, + "RegionId": { + "required": true, + "type": "string" + }, + "SnapshotIds": { + "type": "string" + }, + "PageNumber": { + "type": "integer" + }, + "PageSize": { + "type": "integer" + }, + "OwnerAccount": { + "type": "string" + }, + "SnapshotName": { + "type": "string" + }, + "Status": { + "type": "string" + }, + "SnapshotType": { + "type": "string" + }, + "Filter.1.Key": { + "type": "string" + }, + "Filter.2.Key": { + "type": "string" + }, + "Filter.1.Value": { + "type": "string" + }, + "Filter.2.Value": { + "type": "string" + }, + "Usage": { + "type": "string" + }, + "SourceDiskType": { + "type": "string" + }, + "Tag.1.Key": { + "type": "string" + }, + "Tag.2.Key": { + "type": "string" + }, + "Tag.3.Key": { + "type": "string" + }, + "Tag.4.Key": { + "type": "string" + }, + "Tag.5.Key": { + "type": "string" + }, + "Tag.1.Value": { + "type": "string" + }, + "Tag.2.Value": { + "type": "string" + }, + "Tag.3.Value": { + "type": "string" + }, + "Tag.4.Value": { + "type": "string" + }, + "Tag.5.Value": { + "type": "string" + } + } + } + }, + "describeVpcs": { + "name": "DescribeVpcs", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "DescribeVpcs" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "VpcId": { + "type": "string" + }, + "RegionId": { + "required": true, + "type": "string" + }, + "PageNumber": { + "type": "integer" + }, + "PageSize": { + "type": "integer" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "describeVRouters": { + "name": "DescribeVRouters", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "DescribeVRouters" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "VRouterId": { + "type": "string" + }, + "RegionId": { + "required": true, + "type": "string" + }, + "PageNumber": { + "type": "integer" + }, + "PageSize": { + "type": "integer" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "describeVSwitches": { + "name": "DescribeVSwitches", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "DescribeVSwitches" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "VpcId": { + "required": true, + "type": "string" + }, + "VSwitchId": { + "type": "string" + }, + "ZoneId": { + "type": "string" + }, + "PageNumber": { + "type": "integer" + }, + "PageSize": { + "type": "integer" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "describeZones": { + "name": "DescribeZones", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "DescribeZones" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "RegionId": { + "required": true, + "type": "string" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "detachDisk": { + "name": "DetachDisk", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "DetachDisk" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "InstanceId": { + "required": true, + "type": "string" + }, + "DiskId": { + "required": true, + "type": "string" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "joinSecurityGroup": { + "name": "JoinSecurityGroup", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "JoinSecurityGroup" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "SecurityGroupId": { + "required": true, + "type": "string" + }, + "InstanceId": { + "required": true, + "type": "string" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "leaveSecurityGroup": { + "name": "LeaveSecurityGroup", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "LeaveSecurityGroup" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "SecurityGroupId": { + "required": true, + "type": "string" + }, + "InstanceId": { + "required": true, + "type": "string" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "modifyAutoSnapshotPolicy": { + "name": "ModifyAutoSnapshotPolicy", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "ModifyAutoSnapshotPolicy" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "SystemDiskPolicyEnabled": { + "type": "boolean" + }, + "SystemDiskPolicyTimePeriod": { + "type": "integer" + }, + "SystemDiskPolicyRetentionDays": { + "type": "integer" + }, + "SystemDiskPolicyRetentionLastWeek": { + "type": "boolean" + }, + "DataDiskPolicyEnabled": { + "type": "boolean" + }, + "DataDiskPolicyTimePeriod": { + "type": "integer" + }, + "DataDiskPolicyRetentionDays": { + "type": "integer" + }, + "DataDiskPolicyRetentionLastWeek": { + "type": "boolean" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "modifyDiskAttribute": { + "name": "ModifyDiskAttribute", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "ModifyDiskAttribute" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "DiskId": { + "required": true, + "type": "string" + }, + "DiskName": { + "type": "string" + }, + "Description": { + "type": "string" + }, + "DeleteWithInstance": { + "type": "boolean" + }, + "DeleteAutoSnapshot": { + "type": "boolean" + }, + "EnableAutoSnapshot": { + "type": "boolean" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "modifyEipAddressAttribute": { + "name": "ModifyEipAddressAttribute", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "ModifyEipAddressAttribute" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "AllocationId": { + "required": true, + "type": "string" + }, + "Bandwidth": { + "required": true, + "type": "string" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "modifyImageAttribute": { + "name": "ModifyImageAttribute", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "ModifyImageAttribute" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "RegionId": { + "required": true, + "type": "string" + }, + "ImageId": { + "required": true, + "type": "string" + }, + "ImageName": { + "type": "string" + }, + "Description": { + "type": "string" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "modifyImageShareGroupPermission": { + "name": "ModifyImageShareGroupPermission", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "ModifyImageShareGroupPermission" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "RegionId": { + "required": true, + "type": "string" + }, + "ImageId": { + "required": true, + "type": "string" + }, + "AddGroup.1": { + "type": "string" + }, + "RemoveGroup.1": { + "type": "string" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "modifyImageSharePermission": { + "name": "ModifyImageSharePermission", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "ModifyImageSharePermission" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "RegionId": { + "required": true, + "type": "string" + }, + "ImageId": { + "required": true, + "type": "string" + }, + "AddAccount.1": { + "type": "string" + }, + "AddAccount.2": { + "type": "string" + }, + "AddAccount.3": { + "type": "string" + }, + "AddAccount.4": { + "type": "string" + }, + "AddAccount.5": { + "type": "string" + }, + "AddAccount.6": { + "type": "string" + }, + "AddAccount.7": { + "type": "string" + }, + "AddAccount.8": { + "type": "string" + }, + "AddAccount.9": { + "type": "string" + }, + "AddAccount.10": { + "type": "string" + }, + "RemoveAccount.1": { + "type": "string" + }, + "RemoveAccount.2": { + "type": "string" + }, + "RemoveAccount.3": { + "type": "string" + }, + "RemoveAccount.4": { + "type": "string" + }, + "RemoveAccount.5": { + "type": "string" + }, + "RemoveAccount.6": { + "type": "string" + }, + "RemoveAccount.7": { + "type": "string" + }, + "RemoveAccount.8": { + "type": "string" + }, + "RemoveAccount.9": { + "type": "string" + }, + "RemoveAccount.10": { + "type": "string" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "modifyInstanceAttribute": { + "name": "ModifyInstanceAttribute", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "ModifyInstanceAttribute" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "InstanceId": { + "required": true, + "type": "string" + }, + "Password": { + "type": "string" + }, + "HostName": { + "type": "string" + }, + "InstanceName": { + "type": "string" + }, + "Description": { + "type": "string" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "modifyInstanceNetworkSpec": { + "name": "ModifyInstanceNetworkSpec", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "ModifyInstanceNetworkSpec" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "InstanceId": { + "required": true, + "type": "string" + }, + "InternetMaxBandwidthOut": { + "type": "integer" + }, + "InternetMaxBandwidthIn": { + "type": "integer" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "modifyInstanceSpec": { + "name": "ModifyInstanceSpec", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "ModifyInstanceSpec" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "InstanceId": { + "required": true, + "type": "string" + }, + "InstanceType": { + "type": "string" + }, + "InternetMaxBandwidthOut": { + "type": "integer" + }, + "InternetMaxBandwidthIn": { + "type": "integer" + }, + "OwnerAccount": { + "type": "string" + }, + "Temporary.StartTime": { + "type": "string" + }, + "Temporary.EndTime": { + "type": "string" + }, + "Temporary.InternetMaxBandwidthOut": { + "type": "integer" + } + } + } + }, + "modifyInstanceVncPasswd": { + "name": "ModifyInstanceVncPasswd", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "ModifyInstanceVncPasswd" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "InstanceId": { + "required": true, + "type": "string" + }, + "RegionId": { + "required": true, + "type": "string" + }, + "VncPassword": { + "required": true, + "type": "string" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "modifyInstanceVpcAttribute": { + "name": "ModifyInstanceVpcAttribute", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "ModifyInstanceVpcAttribute" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "InstanceId": { + "required": true, + "type": "string" + }, + "VSwitchId": { + "required": true, + "type": "string" + }, + "PrivateIpAddress": { + "type": "string" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "modifyIntranetBandwidthKb": { + "name": "ModifyIntranetBandwidthKb", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "ModifyIntranetBandwidthKb" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "InstanceId": { + "required": true, + "type": "string" + }, + "IntranetMaxBandwidthIn": { + "type": "integer" + }, + "IntranetMaxBandwidthOut": { + "type": "integer" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "modifySecurityGroupAttribute": { + "name": "ModifySecurityGroupAttribute", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "ModifySecurityGroupAttribute" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "SecurityGroupId": { + "required": true, + "type": "string" + }, + "Description": { + "type": "string" + }, + "SecurityGroupName": { + "type": "string" + }, + "RegionId": { + "required": true, + "type": "string" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "modifySnapshotAttribute": { + "name": "ModifySnapshotAttribute", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "ModifySnapshotAttribute" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "OwnerAccount": { + "type": "string" + }, + "SnapshotId": { + "required": true, + "type": "string" + }, + "SnapshotName": { + "type": "string" + }, + "Description": { + "type": "string" + } + } + } + }, + "modifyVpcAttribute": { + "name": "ModifyVpcAttribute", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "ModifyVpcAttribute" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "VpcId": { + "required": true, + "type": "string" + }, + "Description": { + "type": "string" + }, + "VpcName": { + "type": "string" + }, + "OwnerAccount": { + "type": "string" + }, + "UserCidr": { + "type": "string" + } + } + } + }, + "modifyVRouterAttribute": { + "name": "ModifyVRouterAttribute", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "ModifyVRouterAttribute" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "VRouterId": { + "required": true, + "type": "string" + }, + "VRouterName": { + "type": "string" + }, + "Description": { + "type": "string" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "modifyVSwitchAttribute": { + "name": "ModifyVSwitchAttribute", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "ModifyVSwitchAttribute" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "VSwitchId": { + "required": true, + "type": "string" + }, + "VSwitchName": { + "type": "string" + }, + "Description": { + "type": "string" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "rebootInstance": { + "name": "RebootInstance", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "RebootInstance" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "InstanceId": { + "required": true, + "type": "string" + }, + "ForceStop": { + "type": "boolean" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "reInitDisk": { + "name": "ReInitDisk", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "ReInitDisk" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "DiskId": { + "required": true, + "type": "string" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "releaseEipAddress": { + "name": "ReleaseEipAddress", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "ReleaseEipAddress" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "AllocationId": { + "required": true, + "type": "string" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "releasePublicIpAddress": { + "name": "ReleasePublicIpAddress", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "ReleasePublicIpAddress" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "InstanceId": { + "type": "string" + }, + "PublicIpAddress": { + "required": true, + "type": "string" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "replaceSystemDisk": { + "name": "ReplaceSystemDisk", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "ReplaceSystemDisk" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "InstanceId": { + "required": true, + "type": "string" + }, + "ImageId": { + "required": true, + "type": "string" + }, + "ClientToken": { + "type": "string" + }, + "OwnerAccount": { + "type": "string" + }, + "UseAdditionalService": { + "type": "boolean" + } + } + } + }, + "resetDisk": { + "name": "ResetDisk", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "ResetDisk" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "DiskId": { + "required": true, + "type": "string" + }, + "SnapshotId": { + "required": true, + "type": "string" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "resizeDisk": { + "name": "ResizeDisk", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "ResizeDisk" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "DiskId": { + "required": true, + "type": "string" + }, + "NewSize": { + "required": true, + "type": "integer" + }, + "ClientToken": { + "type": "string" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "revokeSecurityGroup": { + "name": "RevokeSecurityGroup", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "RevokeSecurityGroup" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "SecurityGroupId": { + "required": true, + "type": "string" + }, + "RegionId": { + "required": true, + "type": "string" + }, + "IpProtocol": { + "required": true, + "type": "string" + }, + "PortRange": { + "required": true, + "type": "string" + }, + "SourceGroupId": { + "type": "string" + }, + "SourceGroupOwnerAccount": { + "type": "string" + }, + "SourceCidrIp": { + "type": "string" + }, + "Policy": { + "type": "string" + }, + "NicType": { + "type": "string" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "revokeSecurityGroupEgress": { + "name": "RevokeSecurityGroupEgress", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "RevokeSecurityGroupEgress" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "SecurityGroupId": { + "required": true, + "type": "string" + }, + "RegionId": { + "required": true, + "type": "string" + }, + "IpProtocol": { + "required": true, + "type": "string" + }, + "PortRange": { + "required": true, + "type": "string" + }, + "DestGroupId": { + "type": "string" + }, + "DestGroupOwnerAccount": { + "type": "string" + }, + "DestCidrIp": { + "type": "string" + }, + "Policy": { + "type": "string" + }, + "NicType": { + "type": "string" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "startInstance": { + "name": "StartInstance", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "StartInstance" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "InstanceId": { + "required": true, + "type": "string" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "stopInstance": { + "name": "StopInstance", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "StopInstance" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "InstanceId": { + "required": true, + "type": "string" + }, + "ForceStop": { + "type": "boolean" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "unassociateEipAddress": { + "name": "UnassociateEipAddress", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "UnassociateEipAddress" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "AllocationId": { + "required": true, + "type": "string" + }, + "InstanceId": { + "required": true, + "type": "string" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "unbindIpRange": { + "name": "UnbindIpRange", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "UnbindIpRange" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "InstanceId": { + "required": true, + "type": "string" + }, + "IpAddress": { + "required": true, + "type": "string" + }, + "OwnerAccount": { + "type": "string" + } + } + } + }, + "addTags": { + "name": "AddTags", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "AddTags" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "RegionId": { + "required": true, + "type": "string" + }, + "ResourceType": { + "required": true, + "type": "string" + }, + "ResourceId": { + "required": true, + "type": "string" + }, + "Tag.1.Key": { + "required": true, + "type": "string" + }, + "Tag.2.Key": { + "type": "string" + }, + "Tag.3.Key": { + "type": "string" + }, + "Tag.4.Key": { + "type": "string" + }, + "Tag.5.Key": { + "type": "string" + }, + "Tag.1.Value": { + "required": true, + "type": "string" + }, + "Tag.2.Value": { + "type": "string" + }, + "Tag.3.Value": { + "type": "string" + }, + "Tag.4.Value": { + "type": "string" + }, + "Tag.5.Value": { + "type": "string" + } + } + } + }, + "describeResourceByTags": { + "name": "DescribeResourceByTags", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "DescribeResourceByTags" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "PageSize": { + "type": "integer" + }, + "PageNumber": { + "type": "integer" + }, + "ResourceType": { + "type": "string" + }, + "RegionId": { + "required": true, + "type": "string" + }, + "Tag.1.Key": { + "type": "string" + }, + "Tag.2.Key": { + "type": "string" + }, + "Tag.3.Key": { + "type": "string" + }, + "Tag.4.Key": { + "type": "string" + }, + "Tag.5.Key": { + "type": "string" + }, + "Tag.1.Value": { + "type": "string" + }, + "Tag.2.Value": { + "type": "string" + }, + "Tag.3.Value": { + "type": "string" + }, + "Tag.4.Value": { + "type": "string" + }, + "Tag.5.Value": { + "type": "string" + } + } + } + }, + "describeTags": { + "name": "DescribeTags", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "DescribeTags" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "PageSize": { + "type": "integer" + }, + "PageNumber": { + "type": "integer" + }, + "ResourceType": { + "type": "string" + }, + "ResourceId": { + "type": "string" + }, + "RegionId": { + "required": true, + "type": "string" + }, + "Tag.1.Key": { + "type": "string" + }, + "Tag.2.Key": { + "type": "string" + }, + "Tag.3.Key": { + "type": "string" + }, + "Tag.4.Key": { + "type": "string" + }, + "Tag.5.Key": { + "type": "string" + }, + "Tag.1.Value": { + "type": "string" + }, + "Tag.2.Value": { + "type": "string" + }, + "Tag.3.Value": { + "type": "string" + }, + "Tag.4.Value": { + "type": "string" + }, + "Tag.5.Value": { + "type": "string" + } + } + } + }, + "removeTags": { + "name": "RemoveTags", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "RemoveTags" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "RegionId": { + "required": true, + "type": "string" + }, + "ResourceType": { + "type": "string" + }, + "ResourceId": { + "type": "string" + }, + "Tag.1.Key": { + "type": "string" + }, + "Tag.2.Key": { + "type": "string" + }, + "Tag.3.Key": { + "type": "string" + }, + "Tag.4.Key": { + "type": "string" + }, + "Tag.5.Key": { + "type": "string" + }, + "Tag.1.Value": { + "type": "string" + }, + "Tag.2.Value": { + "type": "string" + }, + "Tag.3.Value": { + "type": "string" + }, + "Tag.4.Value": { + "type": "string" + }, + "Tag.5.Value": { + "type": "string" + } + } + } + }, + "describeTagKeys": { + "name": "DescribeTagKeys", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "DescribeTagKeys" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "PageSize": { + "type": "integer" + }, + "PageNumber": { + "type": "integer" + }, + "ResourceType": { + "type": "string" + }, + "ResourceId": { + "type": "string" + }, + "RegionId": { + "required": true, + "type": "string" + } + } + } + }, + "renewInstance": { + "name": "RenewInstance", + "http": { + "method": "POST", + "uri": "/" + }, + "input": { + "type": "structure", + "members": { + "Action": { + "required": true, + "default": "RenewInstance" + }, + "OwnerId": { + "type": "integer" + }, + "ResourceOwnerAccount": { + "type": "string" + }, + "ResourceOwnerId": { + "type": "integer" + }, + "OwnerAccount": { + "type": "string" + }, + "InstanceId": { + "required": true, + "type": "string" + }, + "InstanceType": { + "type": "string" + }, + "InternetMaxBandwidthOut": { + "type": "integer" + }, + "InternetChargeType": { + "type": "string" + }, + "Period": { + "required": true, + "type": "integer" + }, + "RebootTime": { + "type": "string" + }, + "CovertDiskPortable.1.DiskId": { + "type": "string" + }, + "CovertDiskPortable.2.DiskId": { + "type": "string" + }, + "CovertDiskPortable.3.DiskId": { + "type": "string" + }, + "CovertDiskPortable.4.DiskId": { + "type": "string" + } + } + } + } + } + } + + /** + * The service class representing an ALY service. + * + * @abstract + * + * @!attribute apiVersions + * @return [Array] the list of API versions supported by this service. + * @readonly + */ + ALY.Service = inherit({ + /** + * Create a new service object with a configuration object + * + * @param config [map] a map of configuration options + */ + constructor: function Service(config) { + if (!this.loadServiceClass) { + throw ALY.util.error(new Error(), + 'Service must be constructed with `new\' operator'); + } + var ServiceClass = this.loadServiceClass(config || {}); + if (ServiceClass) return new ServiceClass(config); + this.initialize(config); + }, + + /** + * @api private + */ + initialize: function initialize(config) { + this.config = new ALY.Config(config); + }, + + /** + * @api private + */ + loadServiceClass: function loadServiceClass(serviceConfig) { + if (!ALY.util.isEmpty(this.api)) { + return; + } else if (!this.constructor.services) { + return; + } else { + return this.getLatestServiceClass(serviceConfig.apiVersion); + } + }, + + /** + * @api private + */ + getLatestServiceClass: function getLatestServiceClass(version) { + if (this.constructor.services[version] === null) { + ALY.Service.defineServiceApi(this.constructor, version); + } + + return this.constructor.services[version]; + }, + + /** + * @api private + */ + api: {}, + + /** + * @api private + */ + defaultRetryCount: 3, + + /** + * Calls an operation on a service with the given input parameters. + * + * @param operation [String] the name of the operation to call on the service. + * @param params [map] a map of input options for the operation + * @callback callback function(err, data) + * If a callback is supplied, it is called when a response is returned + * from the service. + * @param err [Error] the error object returned from the request. + * Set to `null` if the request is successful. + * @param data [Object] the de-serialized data returned from + * the request. Set to `null` if a request error occurs. + */ + makeRequest: function makeRequest(operation, params, callback) { + if (typeof params === 'function') { + callback = params; + params = null; + } + + params = params || {}; + if (this.config.params) { // copy only toplevel bound params + var rules = this.api.operations[operation]; + if (rules) { + params = ALY.util.copy(params); + ALY.util.each(this.config.params, function(key, value) { + if (rules.input.members[key]) { + if (params[key] === undefined || params[key] === null) { + params[key] = value; + } + } + }); + } + } + + var request = new ALY.Request(this, operation, params); + this.addAllRequestListeners(request); + + if (callback) request.send(callback); + return request; + }, + + /** + * Calls an operation on a service with the given input parameters, without + * any authentication data. This method is useful for "public" API operations. + * + * @param operation [String] the name of the operation to call on the service. + * @param params [map] a map of input options for the operation + * @callback callback function(err, data) + * If a callback is supplied, it is called when a response is returned + * from the service. + * @param err [Error] the error object returned from the request. + * Set to `null` if the request is successful. + * @param data [Object] the de-serialized data returned from + * the request. Set to `null` if a request error occurs. + */ + makeUnauthenticatedRequest: function makeUnauthenticatedRequest(operation, params, callback) { + if (typeof params === 'function') { + callback = params; + params = {}; + } + + var request = this.makeRequest(operation, params); + request.removeListener('sign', ALY.EventListeners.Core.SIGN); + if (this.api.format === 'query') { // query services turn into GET requests + request.addListener('build', function convertToGET(request) { + request.httpRequest.method = 'GET'; + request.httpRequest.path = '/?' + request.httpRequest.body; + request.httpRequest.body = ''; + + // don't need these headers on a GET request + delete request.httpRequest.headers['Content-Length']; + delete request.httpRequest.headers['Content-Type']; + }); + } + + return callback ? request.send(callback) : request; + }, + + /** + * @api private + */ + addAllRequestListeners: function addAllRequestListeners(request) { + var list = [ALY.events, ALY.EventListeners.Core, + this.serviceInterface()]; + for (var i = 0; i < list.length; i++) { + if (list[i]) request.addListeners(list[i]); + } + + // disable parameter validation + if (!this.config.paramValidation) { + request.removeListener('validate', + ALY.EventListeners.Core.VALIDATE_PARAMETERS); + } + + if (this.config.logger) { // add logging events + request.addListeners(ALY.EventListeners.Logger); + } + + this.setupRequestListeners(request); + }, + + /** + * Override this method to setup any custom request listeners for each + * new request to the service. + * + * @abstract + */ + setupRequestListeners: function setupRequestListeners() { + }, + + /** + * Gets the signer class for a given request + * @api private + */ + getSignerClass: function getSignerClass() { + var version = this.api.signatureVersion; + return ALY.Signers.RequestSigner.getVersion(version); + }, + + /** + * @api private + */ + serviceInterface: function serviceInterface() { + switch (this.api.format) { + case 'query': return ALY.EventListeners.Query; + case 'json': return ALY.EventListeners.Json; + case 'rest': return ALY.EventListeners.Rest; + case 'rest-json': return ALY.EventListeners.RestJson; + case 'pop': return ALY.EventListeners.Pop; + case 'top': return ALY.EventListeners.Top; + case 'rest-xml': return ALY.EventListeners.RestXml; + } + if (this.api.format) { + throw new Error('Invalid service `format\' ' + + this.api.format + ' in API config'); + } + }, + + /** + * @api private + */ + successfulResponse: function successfulResponse(resp) { + return resp.httpResponse.statusCode < 300; + }, + + /** + * How many times a failed request should be retried before giving up. + * the defaultRetryCount can be overriden by service classes. + * + * @api private + */ + numRetries: function numRetries() { + if (this.config.maxRetries !== undefined) { + return this.config.maxRetries; + } else { + return this.defaultRetryCount; + } + }, + + /** + * @api private + */ + retryDelays: function retryDelays() { + var retryCount = this.numRetries(); + var delays = []; + for (var i = 0; i < retryCount; ++i) { + delays[i] = Math.pow(2, i) * 30; + } + return delays; + }, + + /** + * @api private + */ + retryableError: function retryableError(error) { + if (this.networkingError(error)) return true; + if (this.throttledError(error)) return true; + if (error.statusCode >= 500) return true; + return false; + }, + + /** + * @api private + */ + networkingError: function networkingError(error) { + return error.code == 'NetworkingError'; + }, + + /** + * @api private + */ + throttledError: function throttledError(error) { + // this logic varies between services + return (error.code == 'ProvisionedThroughputExceededException'); + }, + + /** + * @api private + */ + isRegionCN: function isRegionCN() { + if (!this.config.region) return false; + return this.config.region.match(/^cn-/) ? true : false; + }, + + /** + * @api private + */ + isRegionV4: function isRegionV4() { + return this.isRegionCN(); + }, + + /** + * @api private + */ + paginationConfig: function paginationConfig(operation, throwException) { + function fail(name) { + if (throwException) { + var e = new Error(); + throw ALY.util.error(e, 'No pagination configuration for ' + name); + } + return null; + } + + if (!this.api.pagination) return fail('service'); + if (!this.api.pagination[operation]) return fail(operation); + return this.api.pagination[operation]; + } + }); + + ALY.util.update(ALY.Service, { + + /** + * Adds one method for each operation described in the api configuration + * + * @api private + */ + defineMethods: function defineMethods(svc) { + ALY.util.each(svc.prototype.api.operations, function iterator(method) { + if (svc.prototype[method]) return; + svc.prototype[method] = function (params, callback) { + return this.makeRequest(method, params, callback); + }; + }); + }, + + defineService: function defineService(serviceIdentifier, versions, features) { + if (!Array.isArray(versions)) { + features = versions; + versions = []; + } + + var svc = inherit(ALY.Service, features || {}); + + if (typeof serviceIdentifier === 'string') { + // create versions hash + var services = {}; + for (var i = 0; i < versions.length; i++) { + services[versions[i]] = null; + } + + svc.services = svc.services || services; + svc.apiVersions = Object.keys(svc.services).sort(); + svc.serviceIdentifier = svc.serviceIdentifier || serviceIdentifier; + } else { // defineService called with an API + svc.prototype.api = serviceIdentifier; + ALY.Service.defineMethods(svc); + } + + return svc; + }, + + /** + * @api private + */ + defineServiceApi: function defineServiceApi(superclass, version) { + var svc = inherit(superclass, { + serviceIdentifier: superclass.serviceIdentifier + }); + + if (typeof version === 'string') { + var file = superclass.serviceIdentifier + '-' + version; + var path = __dirname + '/../apis/' + file + '.json'; + try { + if(ALY.util.isBrowser()) { + svc.prototype.api = ecsApiVersion; + } + else { + var fs = require('fs'); + svc.prototype.api = JSON.parse(fs.readFileSync(path)); + } + } catch (err) { + throw ALY.util.error(err, { + message: 'Could not find API configuration ' + file + }); + } + + if (!superclass.services.hasOwnProperty(version)) { + superclass.apiVersions.push(version); + } + superclass.services[version] = svc; + } else { + setApi(version); + } + + ALY.Service.defineMethods(svc); + return svc; + } + }); + + }).call(this,"/lib") + },{"./core":5,"fs":80}],14:[function(require,module,exports){ + var ALY = require('../core'); + require('../json/builder'); + + /** + * @api private + */ + ALY.ServiceInterface.Json = { + buildRequest: function buildRequest(req) { + var httpRequest = req.httpRequest; + var api = req.service.api; + var target = api.targetPrefix + '.' + api.operations[req.operation].name; + var version = api.jsonVersion || '1.0'; + + var rules = api.operations[req.operation].input; + var builder = new ALY.JSON.Builder(rules, api); + + httpRequest.path = '/'; + httpRequest.body = builder.build(req.params || {}); + }, + + extractError: function extractError(resp) { + var error = {}; + var httpResponse = resp.httpResponse; + + if (httpResponse.body.length > 0) { + var e = JSON.parse(httpResponse.body.toString()); + if (e.__type || e.code || e.Code) { + error.code = (e.__type || e.code || e.Code).split('#').pop(); + } else { + error.code = 'UnknownError'; + } + if (error.code === 'RequestEntityTooLarge') { + error.message = 'Request body must be less than 1 MB'; + } else { + error.message = (e.message || e.Message || null); + } + } else { + error.code = httpResponse.statusCode; + error.message = null; + } + + resp.error = ALY.util.error(new Error(), error); + }, + + extractData: function extractData(resp) { + resp.data = JSON.parse(resp.httpResponse.body.toString() || '{}'); + } + + }; + + },{"../core":5,"../json/builder":9}],15:[function(require,module,exports){ + var ALY = require('../core'); + require('./rest'); + require('./json'); + + function randomNumbers(count) { + var num = ''; + for (var i = 0; i < count; i++) { + num += Math.floor(Math.random() * 10); + } + return num; + } + + /** + * @api private + */ + ALY.ServiceInterface.Pop = { + buildRequest: function buildRequest(req) { + ALY.ServiceInterface.Rest.buildRequest(req); + ALY.ServiceInterface.Pop.populateBody(req); + }, + + extractError: function extractError(resp) { + ALY.ServiceInterface.Json.extractError(resp); + }, + + extractData: function extractData(resp) { + resp.data = JSON.parse(resp.httpResponse.body.toString()); + }, + + populateBody: function populateBody(req) { + req.httpRequest.headers['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8'; + + var body = req.params; + var date = ALY.util.date.getDate(); + + body.Format = "JSON"; + body.Version = req.service.api.apiVersion; + body.AccessKeyId = req.service.config.accessKeyId; + body.SignatureVersion = "1.0"; + body.SignatureMethod = "HMAC-SHA1"; + body.SignatureNonce = String(date.getTime()) + randomNumbers(4); + body.Timestamp = ALY.util.date.iso8601(date); + + // sign + var headers = []; + + ALY.util.each(body, function (name) { + headers.push(name); + }); + + headers.sort(function (a, b) { + return a < b ? -1 : 1; + }); + + var canonicalizedQueryString = ""; + ALY.util.arrayEach.call(this, headers, function (name) { + canonicalizedQueryString += "&" + name + "=" + ALY.util.popEscape(body[name]); + }); + + var stringToSign = 'POST&%2F&' + ALY.util.popEscape(canonicalizedQueryString.substr(1)); + body.Signature = ALY.util.crypto.hmac(req.service.config.secretAccessKey + '&', stringToSign, 'base64', 'sha1'); + + // body + var bodyString = ALY.util.queryParamsToString(body); + + req.httpRequest.body = bodyString; + }, + + buildJSON: function buildJSON(params, rules, api) { + var builder = new ALY.JSON.Builder(rules, api); + return builder.build(params); + } + + }; + + },{"../core":5,"./json":14,"./rest":17}],16:[function(require,module,exports){ + var ALY = require('../core'); + var inherit = ALY.util.inherit; + + // 目前 query 是针对 top 调用的 + ALY.ServiceInterface.Query = { + buildRequest: function buildRequest(req) { + var operation = req.service.api.operations[req.operation]; + var httpRequest = req.httpRequest; + httpRequest.method = 'GET'; + httpRequest.headers['Content-Type'] = + 'application/x-www-form-urlencoded; charset=utf-8'; + httpRequest.params = { + Action: operation.name, + Version: req.service.api.apiVersion, + Timestamp: ALY.util.date.iso8601(ALY.util.date.getDate()), + Format: 'json', + AccessKeyId: req.service.config.accessKeyId, + SignatureVersion: '1.0', + SignatureMethod: 'HMAC-SHA1', + SignatureNonce: ALY.util.uuid() + }; + + // convert the request parameters into a list of query params, + // e.g. Deeply.NestedParam.0.Name=value + var rules = operation.input; + if (rules) rules = rules.members; + var builder = new ALY.QueryParamSerializer(rules, req.service.api); + builder.serialize(req.params, function(name, value) { + httpRequest.params[name] = value; + }); + httpRequest.path = '/?' + ALY.util.queryParamsToString(httpRequest.params); + }, + + extractError: function extractError(resp) { + var data = JSON.parse(resp.httpResponse.body.toString()); + + if (data.Code) { + resp.error = ALY.util.error(new Error(), { + code: data.Code, + message: data.Message, + RequestId: data.RequestId + }); + } else { + resp.error = ALY.util.error(new Error(), { + code: resp.httpResponse.statusCode, + message: null, + RequestId: data.RequestId + }); + } + }, + + extractData: function extractData(resp) { + resp.data = resp.httpResponse.body.toString(); + } + }; + + /** + * @api private + */ + ALY.QueryParamSerializer = inherit({ + + constructor: function QueryParamSerializer(rules, options) { + this.rules = rules; + this.timestampFormat = options ? options.timestampFormat : 'iso8601'; + }, + + serialize: function serialize(params, fn) { + this.serializeStructure('', params, this.rules, fn); + }, + + serializeStructure: function serializeStructure(prefix, struct, rules, fn) { + var that = this; + ALY.util.each(struct, function (name, member) { + var n = rules[name].name || name; + var memberName = prefix ? prefix + '.' + n : n; + that.serializeMember(memberName, member, rules[name], fn); + }); + }, + + serializeMap: function serialzeMap(name, map, rules, fn) { + var i = 1; + var that = this; + ALY.util.each(map, function (key, value) { + var prefix = rules.flattened ? '.' : '.entry.'; + var position = prefix + (i++) + '.'; + var keyName = position + (rules.keys.name || 'key'); + var valueName = position + (rules.members.name || 'value'); + that.serializeMember(name + keyName, key, rules.keys, fn); + that.serializeMember(name + valueName, value, rules.members, fn); + }); + }, + + serializeList: function serializeList(name, list, rules, fn) { + var that = this; + var memberRules = rules.members || {}; + ALY.util.arrayEach(list, function (v, n) { + var suffix = '.' + (n + 1); + if (rules.flattened) { + if (memberRules.name) { + var parts = name.split('.'); + parts.pop(); + parts.push(memberRules.name); + name = parts.join('.'); + } + } else { + suffix = '.member' + suffix; + } + that.serializeMember(name + suffix, v, memberRules, fn); + }); + }, + + serializeMember: function serializeMember(name, value, rules, fn) { + if (value === null || value === undefined) return; + if (rules.type === 'structure') { + this.serializeStructure(name, value, rules.members, fn); + } else if (rules.type === 'list') { + this.serializeList(name, value, rules, fn); + } else if (rules.type === 'map') { + this.serializeMap(name, value, rules, fn); + } else if (rules.type === 'timestamp') { + var timestampFormat = rules.format || this.timestampFormat; + fn.call(this, name, ALY.util.date.format(value, timestampFormat)); + } else { + fn.call(this, name, String(value)); + } + } + + }); + + },{"../core":5}],17:[function(require,module,exports){ + var ALY = require('../core'); + + /** + * @api private + */ + ALY.ServiceInterface.Rest = { + buildRequest: function buildRequest(req) { + ALY.ServiceInterface.Rest.populateMethod(req); + ALY.ServiceInterface.Rest.populateURI(req); + ALY.ServiceInterface.Rest.populateHeaders(req); + }, + + extractError: function extractError() { + }, + + extractData: function extractData(resp) { + var req = resp.request; + var data = {}; + var r = resp.httpResponse; + var operation = req.service.api.operations[req.operation]; + var rules = (operation.output || {}).members || {}; + + // normalize headers names to lower-cased keys for matching + var headers = {}; + ALY.util.each(r.headers, function (k, v) { + headers[k.toLowerCase()] = v; + }); + + ALY.util.each(rules, function (name, rule) { + if (rule.location === 'header') { + var header = (rule.name || name).toLowerCase(); + if (rule.type == 'map') { + data[name] = {}; + ALY.util.each(r.headers, function (k, v) { + var result = k.match(new RegExp('^' + rule.name + '(.+)', 'i')); + if (result !== null) { + data[name][result[1]] = v; + } + }); + } + if (headers[header] !== undefined) { + data[name] = headers[header]; + } + } + if (rule.location === 'status') { + data[name] = parseInt(r.statusCode, 10); + } + }); + + resp.data = data; + }, + + populateMethod: function populateMethod(req) { + req.httpRequest.method = req.service.api.operations[req.operation].http.method; + }, + + populateURI: function populateURI(req) { + var operation = req.service.api.operations[req.operation]; + var uri = operation.http.uri; + var pathPattern = uri.split(/\?/)[0]; + var rules = (operation.input || {}).members || {}; + + var escapePathParam = req.service.escapePathParam || + ALY.ServiceInterface.Rest.escapePathParam; + var escapeQuerystringParam = req.service.escapeQuerystringParam || + ALY.ServiceInterface.Rest.escapeQuerystringParam; + + ALY.util.each.call(this, rules, function (name, rule) { + if (rule.location == 'uri' && req.params[name] != null) { + // if the value is being inserted into the path portion of the + // URI, then we need to use a different (potentially) escaping + // pattern, this is especially true for S3 path params like Key. + var value = pathPattern.match('{' + name + '}') ? + escapePathParam(req.params[name]) : + escapeQuerystringParam(req.params[name]); + + uri = uri.replace('{' + name + '}', value); + } + }); + + var path = uri.split('?')[0]; + var querystring = uri.split('?')[1]; + + if (querystring) { + var parts = []; + ALY.util.arrayEach(querystring.split('&'), function (part) { + if (!part.match('{\\w+}')) parts.push(part); + }); + uri = (parts.length > 0 ? path + '?' + parts.join('&') : path); + } else { + uri = path; + } + + req.httpRequest.path = uri; + }, + + escapePathParam: function escapePathParam(value) { + return ALY.util.uriEscape(String(value)); + }, + + escapeQuerystringParam: function escapeQuerystringParam(value) { + return ALY.util.uriEscape(String(value)); + }, + + populateHeaders: function populateHeaders(req) { + var operation = req.service.api.operations[req.operation]; + var rules = (operation.input || {}).members || {}; + + ALY.util.each.call(this, rules, function (name, rule) { + if (rule.location === 'header' && req.params[name]) { + if (rule.type === 'map') { + ALY.util.each(req.params[name], function (key, value) { + req.httpRequest.headers[rule.name + key] = value; + }); + } else { + var value = req.params[name]; + if (rule.type === 'timestamp') { + var timestampFormat = rule.format || req.service.api.timestampFormat; + value = ALY.util.date.format(value, timestampFormat); + } + req.httpRequest.headers[rule.name || name] = value; + } + } + }); + + if(req.service.config.securityToken) { + req.httpRequest.headers["x-oss-security-token"] = req.service.config.securityToken; + } + + } + }; + + },{"../core":5}],18:[function(require,module,exports){ + var ALY = require('../core'); + require('./rest'); + require('./json'); + + /** + * @api private + */ + ALY.ServiceInterface.RestJson = { + buildRequest: function buildRequest(req) { + ALY.ServiceInterface.Rest.buildRequest(req); + ALY.ServiceInterface.RestJson.populateBody(req); + }, + + extractError: function extractError(resp) { + ALY.ServiceInterface.Json.extractError(resp); + }, + + extractData: function extractData(resp) { + var req = resp.request; + var rules = req.service.api.operations[req.operation].output || {}; + if (rules.payload && rules.members[rules.payload]) { + if (rules.members[rules.payload].streaming) { + resp.data[rules.payload] = resp.httpResponse.body; + } else { + resp.data[rules.payload] = resp.httpResponse.body.toString(); + } + } else { + var data = resp.data; + ALY.ServiceInterface.Json.extractData(resp); + resp.data = ALY.util.merge(data, resp.data); + } + }, + + populateBody: function populateBody(req) { + var input = req.service.api.operations[req.operation].input; + var payload = input.payload; + var params = {}; + + if (typeof payload === 'string') { + + var rules = input.members[payload]; + params = req.params[payload]; + + if (params === undefined) return; + + if (rules.type === 'structure') { + req.httpRequest.body = this.buildJSON(params, input, req.service.api); + } else { + // non-xml paylaod + req.httpRequest.body = params; + } + + } else if (payload) { + + ALY.util.arrayEach(payload, function (param) { + if (req.params[param] !== undefined) { + params[param] = req.params[param]; + } + }); + req.httpRequest.body = this.buildJSON(params, input, req.service.api); + + } + }, + + buildJSON: function buildJSON(params, rules, api) { + var builder = new ALY.JSON.Builder(rules, api); + return builder.build(params); + } + + }; + + },{"../core":5,"./json":14,"./rest":17}],19:[function(require,module,exports){ + var ALY = require('../core'); + require('../xml/builder'); + require('../xml/parser'); + require('./rest'); + + /** + * @api private + */ + ALY.ServiceInterface.RestXml = { + buildRequest: function buildRequest(req) { + ALY.ServiceInterface.Rest.buildRequest(req); + ALY.ServiceInterface.RestXml.populateBody(req); + }, + + extractError: function extractError(resp) { + try { + var data = new ALY.XML.Parser({}).parse(resp.httpResponse.body.toString()); + if (data.Errors) data = data.Errors; + if (data.Error) data = data.Error; + if (data.Code) { + resp.error = ALY.util.error(new Error(), { + code: data.Code, + message: data.Message + }); + } else { + resp.error = ALY.util.error(new Error(), { + code: resp.httpResponse.statusCode, + message: null + }); + } + } + catch(err) { + resp.error = ALY.util.error(new Error(), { + code: resp.httpResponse.statusCode, + message: resp.httpResponse.body.toString() + }); + } + }, + + extractData: function extractData(resp) { + ALY.ServiceInterface.Rest.extractData(resp); + + var req = resp.request; + var httpResponse = resp.httpResponse; + var operation = req.service.api.operations[req.operation]; + var rules = operation.output.members; + + var output = operation.output; + var payload = output.payload; + + if (payload) { + if (rules[payload].streaming) { + resp.data[payload] = httpResponse.body; + } else { + resp.data[payload] = httpResponse.body.toString(); + } + } else if (httpResponse.body.length > 0) { + try { + var parser = new ALY.XML.Parser(operation.output || {}); + ALY.util.update(resp.data, parser.parse(httpResponse.body.toString())); + } + catch(err) { + // ignore parse error + } + } + + // extract request id + resp.data.RequestId = httpResponse.headers['x-oss-request-id'] || + httpResponse.headers['x-oss-requestid']; + }, + + populateBody: function populateBody(req) { + var input = req.service.api.operations[req.operation].input; + var payload = input.payload; + var rules = {}; + var builder = null; + var params = req.params; + + if (typeof payload === 'string') { + + rules = input.members[payload]; + params = params[payload]; + + if (params === undefined) return; + + if (rules.type === 'structure') { + builder = new ALY.XML.Builder(payload, rules.members, req.service.api); + req.httpRequest.body = builder.toXML(params); + } else { + // non-xml paylaod + req.httpRequest.body = params; + } + + } else if (payload) { + + ALY.util.arrayEach(payload, function (member) { + rules[member] = input.members[member]; + }); + + builder = new ALY.XML.Builder(input.wrapper, rules, req.service.api); + req.httpRequest.body = builder.toXML(params); + + } + + } + }; + + },{"../core":5,"../xml/builder":35,"../xml/parser":36,"./rest":17}],20:[function(require,module,exports){ + var ALY = require('../core'); + require('./rest'); + require('./json'); + + /** + * @api private + */ + ALY.ServiceInterface.Top = { + buildRequest: function buildRequest(req) { + ALY.ServiceInterface.Top.populateMethod(req); + ALY.ServiceInterface.Top.populateBodyAndURI(req); + }, + + extractError: function extractError(resp) { + ALY.ServiceInterface.Json.extractError(resp); + }, + + extractData: function extractData(resp) { + resp.data = JSON.parse(resp.httpResponse.body.toString()); + }, + + populateMethod: function populateBodyAndURI(req) { + req.httpRequest.method = req.service.api.operations[req.operation].http.method; + }, + + populateBodyAndURI: function populateBody(req) { + req.httpRequest.headers['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8'; + req.httpRequest.headers['Cache-Control'] = "no-cache"; + req.httpRequest.headers['Connection'] = "Keep-Alive"; + + var application_parameter = req.params; + + // convert json object to json string + ALY.util.each(application_parameter, function (name) { + var value = application_parameter[name]; + if(value !== null && typeof value === 'object') { + application_parameter[name] = JSON.stringify(value); + } + }); + + var sys_parameters = { + format: "json", + app_key: req.service.config.accessKeyId, + sign_method: "md5", + v: "2.0", + timestamp: ALY.util.date.unixMilliseconds(ALY.util.date.getDate()), + partner_id: "taobao-sdk-python-20151223", + method: application_parameter.method + }; + + delete application_parameter.method; + + // sign + var sign_parameter = []; + + ALY.util.each(sys_parameters, function (name) { + sign_parameter.push(name); + }); + + ALY.util.each(application_parameter, function (name) { + sign_parameter.push(name); + }); + + sign_parameter.sort(function (a, b) { + return a.toLowerCase() < b.toLowerCase() ? -1 : 1; + }); + + var canonicalizedQueryString = ""; + ALY.util.arrayEach.call(this, sign_parameter, function (name) { + canonicalizedQueryString += name + (sys_parameters[name] || application_parameter[name]); + }); + + var stringToSign = req.service.config.secretAccessKey + canonicalizedQueryString + req.service.config.secretAccessKey; + + sys_parameters.sign = ALY.util.crypto.md5(stringToSign, 'hex').toUpperCase(); + + req.httpRequest.body = ALY.util.queryParamsToString(application_parameter); + + req.httpRequest.path = "/router/rest?" + ALY.util.queryParamsToString(sys_parameters); + }, + + buildJSON: function buildJSON(params, rules, api) { + var builder = new ALY.JSON.Builder(rules, api); + return builder.build(params); + } + + }; + + },{"../core":5,"./json":14,"./rest":17}],21:[function(require,module,exports){ + var ALY = require('../core'); + var parseURL = require('url').parse; + + ALY.BatchCompute = ALY.Service.defineService('batchcompute', ['2015-06-30','2015-11-11'], { + /** + * @api private + */ + initialize: function initialize(options) { + ALY.Service.prototype.initialize.call(this, options); + }, + setupRequestListeners: function setupRequestListeners(request) { + + var that = this; + var svc = ALY.ServiceInterface.RestJson; + + request.addListener('build', this.addContentType); + + request.removeListener('extractData', svc.extractData); + + request.addListener('extractError', this.extractError); + request.addListener('extractData', function (response) { + that.extractData(response, request['operation']); + }); + }, + + + addContentType: function(req){ + var httpRequest = req.httpRequest; + var headers = httpRequest.headers; + + headers['x-acs-version'] = req.service.config.apiVersion; + + if(req.operation==='updateJobPriority'){ + httpRequest.body = JSON.parse(httpRequest.body).priority+''; + headers['Content-Type'] = 'application/octet-stream'; + //headers['Content-Length']= httpRequest.body.length; + } + }, + + + extractData: function extractData(resp, operation) { + + resp.data = JSON.parse(resp.httpResponse.body.toString().trim() || '{}'); + + var result = resp.data; + delete result['RequestId']; + + + var headers = resp.httpResponse.headers; + var reqId = headers['x-acs-request-id'] || headers['request-id']; + + + resp.data = { + code: resp.httpResponse.statusCode, + message: headers.status, + headers: headers, + requestId: reqId || '' + }; + + if(headers['x-acs-version']==='2015-06-30') { + + switch (operation) { + case 'listJobs': + resp.data.data = this.getFormatters().formatJobList(result); + break; + case 'getJob': + resp.data.data = this.getFormatters().formatJob(result); + break; + case 'getJobDescription': + resp.data.data = this.getFormatters().formatJobDescription(result); + break; + case 'listTasks': + resp.data.data = this.getFormatters().formatTaskList(result); + break; + case 'listImages': + resp.data.data = this.getFormatters().formatImageList(result); + break; + case 'createJob': + resp.data.data = this.getFormatters().formatJob(result); + break; + } + } + else{ + resp.data.data = result; + } + + }, + getFormatters: function () { + + function getState(state) { + switch (state) { + case 0: + return 'Init'; + case 1: + return 'Waiting'; + case 2: + return 'Running'; + case 3: + return 'Finished'; + case 4: + return 'Failed'; + case 5: + return 'Stopped'; + default: + return 'Unkowned'; + } + } + + return { + formatJob: function (v) { + + v['JobId'] = v['ResourceId']; + v['JobName'] = v['Name']; + v['CreationTime'] = v['CreateTime']; + + delete v['Name']; + delete v['ResourceId']; + delete v['CreateTime']; + + if (v['State'] == 'Terminated') v['State'] = 'Finished'; + + return v; + }, + formatJobList: function (data) { + var that = this; + var t = []; + Object.keys(data).forEach(function (k) { + t.push(that.formatJob(data[k])); + }); + + t.sort(function (a, b) { + return a['JobId'] > b['JobId'] ? 1 : -1; + }); + return t; + }, + formatTaskList: function (data) { + /*{ CountTask: + { EndTime: 1435520792, + InstanceStatusVector: [Object], + StartTime: 1435519721, + State: 5, + UnfinishedInstances: [Object] } }, + */ + var t = []; + Object.keys(data).forEach(function (k) { + var v = data[k]; + v['TaskName'] = k; + v['State'] = getState(v['State']); + v['InstanceList'] = v['InstanceStatusVector']; + + delete v['InstanceStatusVector']; + delete v['UnfinishedInstances']; + + if (v['InstanceList']) { + v['InstanceList'].forEach(function (n) { + n.State = getState(n.State); + delete n['WorkerStartTime']; + delete n['WorkerEndTime']; + }); + } + t.push(data[k]); + }); + + //sort by StartTime, TaskName + t.sort(function (a, b) { + if (a['StartTime'] == 0) { + if (b['StartTime'] == 0) { + return a['TaskName'] > b['TaskName'] ? 1 : -1; + } else { + return -1; + } + } else { + if (b['StartTime'] == 0) { + return -1; + } else { + return a['StartTime'] > b['StartTime'] ? 1 : -1; + } + } + }); + return t; + }, + formatImageList: function (data) { + var t = []; + + Object.keys(data).forEach(function (k) { + var v = data[k]; + v['ImageId'] = k; + v['ImageName'] = v['Name']; + + delete v['Name']; + + t.push(data[k]); + }); + + t.sort(function (a, b) { + return a['ImageId'] > b['ImageId'] ? 1 : -1; + }); + return t; + }, + formatJobDescription: function (data) { + var taskMap = data.TaskDag.TaskDescMap; + Object.keys(taskMap).forEach(function (k) { + var v = taskMap[k]; + delete v['BlockDeviceMapping']; + delete v['CreateSnapshotAfterTerminated']; + delete v['LoadImage']; + delete v['SaveImage']; + delete v['LoadPreparedData']; + delete v['MaxReplica']; + delete v['MinReplica']; + }); + return data; + } + + }; + }, + + + extractError: function extractError(resp) { + + var headers = resp.httpResponse.headers; + + var body = resp.httpResponse.body; + var error = body.toString(); + + try { + error = JSON.parse(error); + } catch (e) { + error = {}; + } + + resp.error = ALY.util.error(new Error(error.Message), { + code: error.Code || error.ErrorCode, + headers: headers, + requestId: headers['x-acs-request-id'] || headers['request-id'] + }); + } + }); + + module.exports = ALY.BatchCompute; + + },{"../core":5,"url":109}],22:[function(require,module,exports){ + var ALY = require('../core'); + var parseURL = require('url').parse; + + ALY.OpenSearch = ALY.Service.defineService('opensearch', ['2015-01-01'], { + /** + * @api private + */ + initialize: function initialize(options) { + ALY.Service.prototype.initialize.call(this, options); + }, + + setupRequestListeners: function setupRequestListeners(request) { + request.addListener('build', this.addContentType); + request.addListener('build', this.buildContent); + //request.addListener('build', this.populateURI); + // + //request.addListener('build', this.computeContentMd5); + //request.addListener('build', this.computeSha256); + + request.removeListener('validate', + ALY.EventListeners.Core.VALIDATE_REGION); + + request.addListener('extractError', this.extractError); + request.addListener('extractData', this.extractData); + + //request.addListener('afterBuild', function (req) { + // //Host in request.header + // console.log(req.httpRequest.headers['projectName'], req.params['projectName']); + // + // req.httpRequest.headers['Host'] = req.params['projectName'] + // +'.'+req.httpRequest.endpoint.hostname; + // //头中的 projectName 不需要 + // delete req.httpRequest.headers['projectName']; + //}); + }, + + populateURI: function populateURI(req) { + var hostname = req.httpRequest.endpoint.hostname; + + var projectName = req.params['projectName']; + var host = projectName + '.' + hostname; + + if (!/^[0-9.]+$/.test(hostname)) { + //不是ip, 是域名, 则需要拼接project名 + var protocol = req.httpRequest.endpoint.protocol; + var port = req.httpRequest.endpoint.port; + + //real endpoint + var endpointObj = parseURL(protocol + '//' + host + ':' + port); + + ALY.util.update(req.httpRequest, {endpoint: endpointObj}); + // ALY.util.update(req.service, {endpoint: endpointObj }); + } + + //final host, 不管是ip还是域名,都要拼接project名 + req.httpRequest.headers['Host'] = host; + + //头中的 projectName 不需要 + delete req.httpRequest.headers['projectName']; + }, + + addContentType: function addContentType(req) { + var httpRequest = req.httpRequest; + + httpRequest.headers['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8'; + }, + + buildContent: function buildContent(req) { + var input = req.service.api.operations[req.operation].input; + var payload = input.payload; + var params = {}; + + // todo: payload 是否有可能为 string + if (typeof payload === 'string') { + + var rules = input.members[payload]; + params = req.params[payload]; + + if (params === undefined) return; + + if (rules.type === 'structure') { + req.httpRequest.body = this.buildJSON(params, input, req.service.api); + } else { + // non-xml paylaod + req.httpRequest.body = params; + } + + } else if (payload) { + var arr = []; + + ALY.util.arrayEach(payload, function (param) { + if (req.params[param] !== undefined) { + params[param] = req.params[param]; + if(param == 'items') { + arr.push(param + '=' + encodeURIComponent(JSON.stringify(req.params[param]))); + } + else { + arr.push(param + '=' + req.params[param]); + } + } + }); + + req.httpRequest.body = arr.join('&'); + } + + }, + + willComputeChecksums: function willComputeChecksums(req) { + + // // TODO: compute checksums for Stream objects + // if (!ALY.util.Buffer.isBuffer(req.httpRequest.body) && + // typeof req.httpRequest.body !== 'string') { + // return false; + // } + + var rules = req.service.api.operations[req.operation].input; + + // // V4 signer uses SHA256 signatures so only compute MD5 if it is required + // if (req.service.getSignerClass(req) === ALY.Signers.V4) { + // if (rules.ContentMD5 && !rules.ContentMD5.required) return false; + // } + + if (rules.ContentMD5) return true; + }, + + computeContentMd5: function computeContentMd5(req) { + if (req.service.willComputeChecksums(req)) { + var md5 = ALY.util.crypto.md5(req.httpRequest.body, 'hex').toUpperCase(); + req.httpRequest.headers['Content-MD5'] = md5; + } + }, + + computeSha256: function computeSha256(req) { + if (req.service.getSignerClass(req) === ALY.Signers.V4) { + req.httpRequest.headers['X-Amz-Content-Sha256'] = + ALY.util.crypto.sha256(req.httpRequest.body || '', 'hex'); + } + }, + + escapePathParam: function escapePathParam(value) { + return ALY.util.uriEscapePath(String(value)); + }, + + + successfulResponse: function successfulResponse(resp) { + //var req = resp.request; + var httpResponse = resp.httpResponse; + return httpResponse.statusCode < 300; + }, + + retryableError: function retryableError(error, request) { + + var _super = ALY.Service.prototype.retryableError; + return _super.call(this, error, request); + + }, + + extractData: function extractData(resp) { + ALY.ServiceInterface.Rest.extractData(resp); + + var req = resp.request; + var rules = req.service.api.operations[req.operation].output || {}; + if (rules.payload && rules.members[rules.payload]) { + if (rules.members[rules.payload].streaming) { + resp.data[rules.payload] = resp.httpResponse.body; + } else { + resp.data[rules.payload] = resp.httpResponse.body.toString(); + } + } else { + var data = resp.data; + ALY.ServiceInterface.Json.extractData(resp); + resp.data = ALY.util.merge(data, resp.data); + } + }, + + extractError: function extractError(resp) { + var error = {}; + var httpResponse = resp.httpResponse; + + if (httpResponse.body.length > 0) { + var e = JSON.parse(httpResponse.body.toString()); + if (e.__type || e.code) { + error.code = (e.__type || e.code).split('#').pop(); + } else { + error.code = 'UnknownError'; + } + if (error.code === 'RequestEntityTooLarge') { + error.message = 'Request body must be less than 1 MB'; + } else { + error.message = (e.message || e.Message || null); + } + } else { + error.code = httpResponse.statusCode; + error.message = null; + } + + resp.error = ALY.util.error(new Error(), error); + } + + }); + + module.exports = ALY.OpenSearch; + + },{"../core":5,"url":109}],23:[function(require,module,exports){ + var ALY = require('../core'); + + ALY.OSS = ALY.Service.defineService('oss', ['2013-10-15'], { + /** + * @api private + */ + initialize: function initialize(options) { + ALY.Service.prototype.initialize.call(this, options); + }, + + setupRequestListeners: function setupRequestListeners(request) { + request.addListener('build', this.addContentType); + request.addListener('build', this.populateURI); + request.addListener('build', this.computeContentMd5); + request.addListener('extractError', this.extractError); + request.addListener('extractData', this.extractData); + }, + + populateURI: function populateURI(req) { + var httpRequest = req.httpRequest; + var b = req.params.Bucket; + + if (b) { + // 确保 host 只被 set 一次,因为 endpoint 只在 service 唯一 + httpRequest.endpoint.host = httpRequest.endpoint.hostname = b + '.' + httpRequest.endpoint.hostname; + + httpRequest.virtualHostedBucket = b; + httpRequest.path = httpRequest.path.replace(new RegExp('^/' + b), ''); + if (httpRequest.path[0] !== '/') { + httpRequest.path = '/' + httpRequest.path; + } + } + }, + + addContentType: function addContentType(req) { + var httpRequest = req.httpRequest; + if (!httpRequest.headers['Content-Type']) { // always have a Content-Type + httpRequest.headers['Content-Type'] = 'application/octet-stream'; + } + if (ALY.util.isBrowser() && window.navigator.userAgent.match(/Firefox/)) { + if (!httpRequest.headers['Content-Type'].match(/;/)) { + var charset = '; charset=UTF-8'; + httpRequest.headers['Content-Type'] += charset; + } + } + }, + + willComputeChecksums: function willComputeChecksums(req) { + // TODO: compute checksums for Stream objects + //if (!ALY.util.Buffer.isBuffer(req.httpRequest.body) && + // typeof req.httpRequest.body !== 'string') { + // return false; + //} + + var rules = req.service.api.operations[req.operation].input.members; + + if (rules.ContentMD5 && !req.params.ContentMD5) return true; + }, + + computeContentMd5: function computeContentMd5(req) { + if (req.service.willComputeChecksums(req)) { + var md5 = ALY.util.crypto.md5(req.httpRequest.body, 'base64'); + req.httpRequest.headers['Content-MD5'] = md5; + } + }, + + /** + * OSS requires that path params not escape forward slashes. + * + * @api private + */ + escapePathParam: function escapePathParam(value) { + return ALY.util.uriEscapePath(String(value)); + }, + + /** + * @return [Boolean] whether response contains an error + * @api private + */ + successfulResponse: function successfulResponse(resp) { + var req = resp.request; + var httpResponse = resp.httpResponse; + if (req.operation === 'completeMultipartUpload' && + httpResponse.body.toString().match('')) + return false; + else + return httpResponse.statusCode < 300; + }, + + /** + * @return [Boolean] whether the error can be retried + * @api private + */ + retryableError: function retryableError(error, request) { + if (request.operation == 'completeMultipartUpload' && + error.statusCode === 200) { + return true; + } else { + var _super = ALY.Service.prototype.retryableError; + return _super.call(this, error, request); + } + }, + + /** + * Provides a specialized parser for getBucketLocation -- all other + * operations are parsed by the super class. + * + * @api private + */ + extractData: function extractData(resp) { + var req = resp.request; + if (req.operation === 'getBucketLocation') { + /*jshint regexp:false*/ + var match = resp.httpResponse.body.toString().match(/>(.+)<\/Location/); + if (match) { + delete resp.data['_']; + resp.data.LocationConstraint = match[1]; + } + } + + for(var k in resp.httpResponse.headers){ + if(k.indexOf('x-oss-')==0){ + var arr = k.substring('x-oss-'.length).split('-'); + for(var i=0;i 604800) { // one week expiry is invalid + // var message = 'getSignedUrl() does not support expiry time greater ' + + // 'than a week with SigV4 signing.'; + // throw ALY.util.error(new Error(), { + // code: 'InvalidExpiryTime', message: message, retryable: false + // }); + //} + request.httpRequest.headers[expiresHeader] = expires; + } else { + request.httpRequest.headers[expiresHeader] = parseInt( + ALY.util.date.unixSeconds() + expires, 10).toString(); + } + } + + function signedUrlSigner() { + var queryParams = {}; + + ALY.util.each(request.httpRequest.headers, function (key, value) { + if (key === expiresHeader) key = 'Expires'; + queryParams[key] = value; + }); + delete request.httpRequest.headers[expiresHeader]; + + var auth = queryParams['Authorization'].split(' '); + if (auth[0] === 'OSS') { + auth = auth[1].split(':'); + queryParams['OSSAccessKeyId'] = auth[0]; + queryParams['Signature'] = auth[1]; + } + delete queryParams['Authorization']; + delete queryParams['Host']; + + // build URL + var endpoint = request.httpRequest.endpoint; + var parsedUrl = ALY.util.urlParse(request.httpRequest.path); + var querystring = ALY.util.queryParamsToString(queryParams); + endpoint.pathname = parsedUrl.pathname; + endpoint.search = !parsedUrl.search ? querystring : + parsedUrl.search + '&' + querystring; + } + + request.on('build', signedUrlBuilder); + request.on('sign', signedUrlSigner); + request.removeListener('build', this.addContentType); + request.removeAllListeners('afterBuild'); + if (!params.Body) { // no Content-MD5/SHA-256 if body is not provided + request.removeListener('build', this.computeContentMd5); + } + + if (callback) { + request.build(function() { + if (request.response.error) callback(request.response.error, null); + else callback(null, ALY.util.urlFormat(request.httpRequest.endpoint)); + }); + } else { + request.build(); + return ALY.util.urlFormat(request.httpRequest.endpoint); + } + } + }); + + module.exports = ALY.OSS; + + },{"../core":5}],24:[function(require,module,exports){ + (function (process){ + var ALY = require('../core'); + var inherit = ALY.util.inherit; + //var API_VERSION = '2015-11-11'; + //var API_VERSION = '2015-06-30'; + + /** + * @api private + */ + ALY.Signers.BatchCompute = inherit(ALY.Signers.RequestSigner, { + + //entry + addAuthorization: function addAuthorization(credentials, date) { + var headers = this.request.headers; + + //headers['Date'] = ALY.util.date.rfc822(date); + headers['x-acs-date'] = ALY.util.date.rfc822(date); + //headers['Date'] = new Date().toGMTString(); + + + //var bodyStr; + //var body = this.request.body; + //if(body){ + // bodyStr = typeof(body)=='object'? JSON.stringify(body):body; + // headers['Content-MD5'] = ALY.util.crypto.md5(bodyStr,'hex').toUpperCase(); + //} + + headers['x-acs-signature-method'] = 'HMAC-SHA1'; + headers['x-acs-signature-version'] = '1.0'; + //headers['x-acs-version'] = API_VERSION; + headers['x-sdk-client'] = 'node.js/1.0.0'; + headers['Accept'] = 'application/json'; + + var signature = this.sign(credentials.secretAccessKey, this.stringToSign()); + var auth = 'acs ' + credentials.accessKeyId + ':' + signature; + + headers['Authorization'] = auth; + }, + + stringToSign: function stringToSign() { + var r = this.request; + + //fix signature not match in browser + if (r.method !== 'GET' && r.method !== 'HEAD') { + r.headers['Content-Type'] = r.headers['Content-Type'] || 'text/plain;charset=UTF-8'; + } + + var parts = []; + parts.push(r.method); + parts.push(r.headers['Accept'] || ''); + parts.push(r.headers['Content-MD5'] || ''); + parts.push(r.headers['Content-Type'] || ''); + parts.push(r.headers['x-acs-date'] || r.headers['Date'] || ''); + + var headers = this.canonicalizedAmzHeaders(); + if (headers) parts.push(headers); + parts.push(this.canonicalizedResource()); + + return parts.join('\n'); + }, + + canonicalizedAmzHeaders: function canonicalizedAmzHeaders() { + + var acsHeaders = []; + + ALY.util.each(this.request.headers, function (name) { + if (name.match(/^x-acs-/i)) + acsHeaders.push(name); + }); + + acsHeaders.sort(function (a, b) { + return a.toLowerCase() < b.toLowerCase() ? -1 : 1; + }); + + var parts = []; + ALY.util.arrayEach.call(this, acsHeaders, function (name) { + parts.push(name.toLowerCase() + ':' + String(this.request.headers[name])); + }); + + return parts.join('\n'); + + }, + + canonicalizedResource: function canonicalizedResource() { + + var r = this.request; + + var parts = r.path.split('?'); + var path = parts[0]; + var querystring = parts[1]; + + var resource = ''; + + + resource += decodeURIComponent(path); + + + if (querystring) { + + // collect a list of sub resources and query params that need to be signed + var resources = []; + + var arr = querystring.replace(/(^&*)|(&*$)/g, '').split('&'); + + + ALY.util.arrayEach.call(this, arr, function (param) { + var kv = param.split('='); + + var name = kv[0]; + + var value = (kv.length > 1) ? decodeURIComponent(kv[1]) : ''; + /*jshint undef:false */ + + var resource = {name: name}; + if (value !== undefined) { + resource.value = value; + } + resources.push(resource); + + }); + + resources.sort(function (a, b) { + return a.name < b.name ? -1 : 1; + }); + + if (resources.length) { + + querystring = []; + ALY.util.arrayEach(resources, function (resource) { + if (resource.value === undefined) + querystring.push(resource.name); + else { + + if (resource.value != null && resource.value != '') { + querystring.push(resource.name + '=' + resource.value); + } else { + querystring.push(resource.name); + } + } + }); + + resource += '?' + querystring.join('&'); + } + + } + + return resource; + + }, + + sign: function sign(secret, string) { + if (process.env.DEBUG == 'aliyun') { + console.log('----------- sign string start -----------'); + console.log(string); + console.log('----------- sign string end -----------'); + } + return ALY.util.crypto.hmac(secret, string, 'base64', 'sha1'); + } + }); + + module.exports = ALY.Signers.BatchCompute; + + }).call(this,require('_process')) + },{"../core":5,"_process":89}],25:[function(require,module,exports){ + (function (process){ + var ALY = require('../core'); + var inherit = ALY.util.inherit; + + function randomNumbers(count) { + var num = ''; + for (var i = 0; i < count; i++) { + num += Math.floor(Math.random() * 10); + } + return num; + } + + /** + * @api private + */ + ALY.Signers.CMS = inherit(ALY.Signers.RequestSigner, { + + addAuthorization: function addAuthorization(credentials, date) { + // if (!this.request.headers['presigned-expires']) { + // this.request.headers['Date'] = ALY.util.date.rfc822(date); + // } + + // if (credentials.sessionToken) { + // // presigned URLs require this header to be lowercased + // this.request.headers['x-amz-security-token'] = credentials.sessionToken; + // } + var date = new Date(); + + var globalQuery = { + 'Format': 'JSON', + 'Version': '2015-10-20', + 'AccessKeyId': credentials.accessKeyId, + 'SignatureMethod': 'HMAC-SHA1', + 'SignatureVersion': '1.0', + 'SignatureNonce': String(date.getTime()) + randomNumbers(4), + 'Timestamp': date.toISOString().replace(/\.\d{3}/, '') + }; + + var parts = []; + Object.keys(globalQuery).forEach(function(key) { + parts.push(key + '=' + encodeURIComponent(globalQuery[key])); + }); + this.request.path += (this.request.path.indexOf('?') == -1? '?' : '&') + parts.join('&'); + + var signature = this.sign(credentials.secretAccessKey, this.stringToSign()); + this.request.path += '&Signature=' + encodeURIComponent(signature); + // var auth = 'OSS ' + credentials.accessKeyId + ':' + signature; + + // this.request.headers['Authorization'] = auth; + }, + + stringToSign: function stringToSign() { + var r = this.request; + + var s = r.method + '&%2F&' + encodeURIComponent(this.canonicalizedQueryString()); + + return s; + }, + + canonicalizedQueryString: function canonicalizedQueryString() { + var that = this; + var r = this.request; + var querystring = r.path.split('?')[1]; + var resource = ''; + if (r.body) { + querystring += '&' + r.body; + } + + if (querystring) { + + // collect a list of sub resources and query params that need to be signed + var resources = []; + + ALY.util.arrayEach.call(this, querystring.split('&'), function (param) { + var pos = param.indexOf('='); + var name = param.slice(0, pos); + var value = param.slice(pos + 1); + + var resource = { name: name }; + if (value !== undefined) { + resource.value = decodeURIComponent(value); + } + + resources.push(resource); + }); + + resources.sort(function (a, b) { return a.name < b.name ? -1 : 1; }); + + if (resources.length) { + + querystring = []; + ALY.util.arrayEach(resources, function (resource) { + if (resource.value === undefined) + querystring.push(that.cmsEscape(resource.name)); + else + querystring.push(that.cmsEscape(resource.name) + '=' + that.cmsEscape(resource.value)); + }); + + resource += querystring.join('&'); + } + } + + return resource; + }, + + cmsEscape: function(clearString) { + // http://v8.googlecode.com/svn/trunk/src/uri.js + return encodeURIComponent(clearString) + .replace(/\!/gi, '%21') + .replace(/\'/gi, '%27') + .replace(/\(/gi, '%28') + .replace(/\)/gi, '%29') + .replace(/\*/gi, '%2A') + }, + + sign: function sign(secret, string) { + if(process.env.DEBUG == 'aliyun') { + console.log('----------- sign string start -----------'); + console.log(string); + console.log('----------- sign string end -----------'); + } + return ALY.util.crypto.hmac(secret + '&', string, 'base64', 'sha1'); + } + }); + + module.exports = ALY.Signers.CMS; + }).call(this,require('_process')) + },{"../core":5,"_process":89}],26:[function(require,module,exports){ + (function (process){ + var ALY = require('../core'); + var inherit = ALY.util.inherit; + + function randomNumbers(count) { + var num = ''; + for (var i = 0; i < count; i++) { + num += Math.floor(Math.random() * 10); + } + return num; + } + + /** + * @api private + */ + ALY.Signers.OpenSearch = inherit(ALY.Signers.RequestSigner, { + + addAuthorization: function addAuthorization(credentials, date) { + // if (!this.request.headers['presigned-expires']) { + // this.request.headers['Date'] = ALY.util.date.rfc822(date); + // } + + // if (credentials.sessionToken) { + // // presigned URLs require this header to be lowercased + // this.request.headers['x-amz-security-token'] = credentials.sessionToken; + // } + var date = new Date(); + + var globalQuery = { + 'Version': 'v2', + 'AccessKeyId': credentials.accessKeyId, + 'SignatureMethod': 'HMAC-SHA1', + 'SignatureVersion': '1.0', + 'SignatureNonce': String(date.getTime()) + randomNumbers(4), + 'Timestamp': date.toISOString().replace(/\.\d{3}/, '') + }; + + var parts = []; + Object.keys(globalQuery).forEach(function(key) { + parts.push(key + '=' + encodeURIComponent(globalQuery[key])); + }); + this.request.path += (this.request.path.indexOf('?') == -1? '?' : '&') + parts.join('&'); + + var signature = this.sign(credentials.secretAccessKey, this.stringToSign()); + this.request.path += '&Signature=' + encodeURIComponent(signature); + // var auth = 'OSS ' + credentials.accessKeyId + ':' + signature; + + // this.request.headers['Authorization'] = auth; + }, + + stringToSign: function stringToSign() { + var r = this.request; + + var s = r.method + '&%2F&' + encodeURIComponent(this.canonicalizedQueryString()); + + return s; + }, + + canonicalizedQueryString: function canonicalizedQueryString() { + + var r = this.request; + var querystring = r.path.split('?')[1]; + var resource = ''; + if (r.body) { + querystring += '&' + r.body; + } + + if (querystring) { + + // collect a list of sub resources and query params that need to be signed + var resources = []; + + ALY.util.arrayEach.call(this, querystring.split('&'), function (param) { + var pos = param.indexOf('='); + var name = param.slice(0, pos); + var value = param.slice(pos + 1); + + var resource = { name: name }; + if (value !== undefined) { + resource.value = decodeURIComponent(value); + } + + resources.push(resource); + }); + + resources.sort(function (a, b) { return a.name < b.name ? -1 : 1; }); + + if (resources.length) { + + querystring = []; + ALY.util.arrayEach(resources, function (resource) { + if (resource.value === undefined) + querystring.push(ALY.util.opensearchEscape(resource.name)); + else + querystring.push(ALY.util.opensearchEscape(resource.name) + '=' + ALY.util.opensearchEscape(resource.value)); + }); + + resource += querystring.join('&'); + } + } + + return resource; + }, + + sign: function sign(secret, string) { + if(process.env.DEBUG == 'aliyun') { + console.log('----------- sign string start -----------'); + console.log(string); + console.log('----------- sign string end -----------'); + } + return ALY.util.crypto.hmac(secret + '&', string, 'base64', 'sha1'); + } + }); + + module.exports = ALY.Signers.OpenSearch; + }).call(this,require('_process')) + },{"../core":5,"_process":89}],27:[function(require,module,exports){ + (function (process){ + var ALY = require('../core'); + var inherit = ALY.util.inherit; + + /** + * @api private + */ + ALY.Signers.OSS = inherit(ALY.Signers.RequestSigner, { + + subResources: { + "acl": 1, + "uploads": 1, + "location": 1, + "cors": 1, + "logging": 1, + "website": 1, + "referer": 1, + "lifecycle": 1, + "delete": 1, + "append": 1, + "tagging": 1, + "objectMeta": 1, + "uploadId": 1, + "partNumber": 1, + "security-token": 1, + "position": 1, + "img": 1, + "style": 1, + "styleName": 1, + "replication": 1, + "replicationProgress": 1, + "replicationLocation": 1, + 'restore': 1, + "cname": 1, + "bucketInfo": 1, + "comp": 1, + "qos": 1, + "live": 1, + "status": 1, + "vod": 1, + "startTime": 1, + "endTime": 1, + "symlink": 1, + "x-oss-process": 1, + "response-content-type": 1, + "response-content-language": 1, + "response-expires": 1, + "response-cache-control": 1, + "response-content-disposition": 1, + "response-content-encoding": 1 + }, + + // when building the stringToSign, these querystring params should be + // part of the canonical resource string with their NON-encoded values + responseHeaders: { + 'response-content-type': 1, + 'response-content-language': 1, + 'response-expires': 1, + 'response-cache-control': 1, + 'response-content-disposition': 1, + 'response-content-encoding': 1 + }, + + addAuthorization: function addAuthorization(credentials, date) { + if (!this.request.headers['presigned-expires']) { + // 在浏览器中不能设置 date header + if (ALY.util.isBrowser()) { + this.request.headers['x-oss-date'] = ALY.util.date.rfc822(date); + } + else { + this.request.headers['Date'] = ALY.util.date.rfc822(date); + } + } + + var signature = this.sign(credentials.secretAccessKey, this.stringToSign()); + var auth = 'OSS ' + credentials.accessKeyId + ':' + signature; + + this.request.headers['Authorization'] = auth; + }, + + stringToSign: function stringToSign() { + var r = this.request; + + var parts = []; + parts.push(r.method); + parts.push(r.headers['Content-MD5'] || ''); + parts.push(r.headers['Content-Type'] || ''); + + // This is the "Date" header, but we use X-Amz-Date. + // The S3 signing mechanism requires us to pass an empty + // string for this Date header regardless. + // this works: + // getSignedUrl use 'presigned-expires' + // other request use 'Date' + parts.push(r.headers['presigned-expires'] || r.headers['x-oss-date'] || r.headers['Date'] || ''); + + var headers = this.canonicalizedHeaders(); + if (headers) parts.push(headers); + parts.push(this.canonicalizedResource()); + + return parts.join('\n'); + + }, + + canonicalizedHeaders: function canonicalizedHeaders() { + + var headers = []; + + ALY.util.each(this.request.headers, function (name) { + if (name.match(/^x-oss-/i)) + headers.push(name); + }); + + headers.sort(function (a, b) { + return a.toLowerCase() < b.toLowerCase() ? -1 : 1; + }); + + var parts = []; + ALY.util.arrayEach.call(this, headers, function (name) { + parts.push(name.toLowerCase() + ':' + String(this.request.headers[name])); + }); + + return parts.join('\n'); + + }, + + canonicalizedResource: function canonicalizedResource() { + + var r = this.request; + + var parts = r.path.split('?'); + var path = parts[0]; + var querystring = parts[1]; + + var resource = ''; + + if (r.virtualHostedBucket) + resource += '/' + r.virtualHostedBucket; + + // OSS 遗留问题,header 中的 Key 不能 url encode + resource += decodeURIComponent(path); + + if (querystring) { + + // collect a list of sub resources and query params that need to be signed + var resources = []; + + ALY.util.arrayEach.call(this, querystring.split('&'), function (param) { + var name = param.split('=')[0]; + var value = param.split('=')[1]; + if (this.subResources[name] || this.responseHeaders[name]) { + var subresource = {name: name}; + if (value !== undefined) { + if (this.subResources[name]) { + subresource.value = value; + } else { + subresource.value = decodeURIComponent(value); + } + } + resources.push(subresource); + } + }); + + resources.sort(function (a, b) { + return a.name < b.name ? -1 : 1; + }); + + if (resources.length) { + + querystring = []; + ALY.util.arrayEach(resources, function (res) { + if (res.value === undefined) + querystring.push(res.name); + else + querystring.push(res.name + '=' + res.value); + }); + + resource += '?' + querystring.join('&'); + } + + } + + return resource; + }, + + sign: function sign(secret, string) { + if (process.env.DEBUG == 'aliyun') { + console.log('----------- sign string start -----------'); + console.log(string); + console.log('----------- sign string end -----------'); + } + return ALY.util.crypto.hmac(secret, string, 'base64', 'sha1'); + } + }); + + module.exports = ALY.Signers.OSS; + + }).call(this,require('_process')) + },{"../core":5,"_process":89}],28:[function(require,module,exports){ + (function (process){ + var ALY = require('../core'); + var inherit = ALY.util.inherit; + + /** + * @api private + */ + ALY.Signers.OTS = inherit(ALY.Signers.RequestSigner, { + + subResources: { + 'acl': 1, + 'cors': 1, + 'lifecycle': 1, + 'delete': 1, + 'location': 1, + 'logging': 1, + 'notification': 1, + 'partNumber': 1, + 'policy': 1, + 'requestPayment': 1, + 'restore': 1, + 'tagging': 1, + 'torrent': 1, + 'uploadId': 1, + 'uploads': 1, + 'versionId': 1, + 'versioning': 1, + 'versions': 1, + 'website': 1 + }, + + // when building the stringToSign, these querystring params should be + // part of the canonical resource string with their NON-encoded values + responseHeaders: { + 'response-content-type': 1, + 'response-content-language': 1, + 'response-expires': 1, + 'response-cache-control': 1, + 'response-content-disposition': 1, + 'response-content-encoding': 1 + }, + + addAuthorization: function addAuthorization(credentials, date) { + this.request.headers['x-ots-date'] = ALY.util.date.rfc822(date); + this.request.headers['x-ots-accesskeyid'] = credentials.accessKeyId; + + var signature = this.sign(credentials.secretAccessKey, this.stringToSign()); + + this.request.headers['x-ots-signature'] = signature; + }, + + stringToSign: function stringToSign() { + var r = this.request; + + var parts = []; + + parts.push(r.path); + + parts.push(r.method + '\n'); + + var headers = this.canonicalizedHeaders(); + if (headers) parts.push(headers); + //parts.push(this.canonicalizedResource()); + + return parts.join('\n') + '\n'; + }, + + canonicalizedHeaders: function canonicalizedHeaders() { + + var headers = []; + + ALY.util.each(this.request.headers, function (name) { + if (name.match(/^x-ots-/i)) + headers.push(name); + }); + + headers.sort(function (a, b) { + return a.toLowerCase() < b.toLowerCase() ? -1 : 1; + }); + + var parts = []; + ALY.util.arrayEach.call(this, headers, function (name) { + parts.push(name.toLowerCase() + ':' + String(this.request.headers[name])); + }); + + return parts.join('\n'); + + }, + + canonicalizedResource: function canonicalizedResource() { + + var r = this.request; + + var parts = r.path.split('?'); + var path = parts[0]; + var querystring = parts[1]; + + var resource = ''; + + if (r.virtualHostedBucket) + resource += '/' + r.virtualHostedBucket; + + // OSS 遗留问题,header 中的 Key 不能 url encode + resource += decodeURIComponent(path); + + if (querystring) { + + // collect a list of sub resources and query params that need to be signed + var resources = []; + + ALY.util.arrayEach.call(this, querystring.split('&'), function (param) { + var name = param.split('=')[0]; + var value = param.split('=')[1]; + if (this.subResources[name] || this.responseHeaders[name]) { + var subresource = { name: name }; + if (value !== undefined) { + if (this.subResources[name]) { + subresource.value = value; + } else { + subresource.value = decodeURIComponent(value); + } + } + resources.push(subresource); + } + }); + + resources.sort(function (a, b) { return a.name < b.name ? -1 : 1; }); + + if (resources.length) { + + querystring = []; + ALY.util.arrayEach(resources, function (res) { + if (res.value === undefined) + querystring.push(res.name); + else + querystring.push(res.name + '=' + res.value); + }); + + resource += '?' + querystring.join('&'); + } + + } + + return resource; + + }, + + sign: function sign(secret, string) { + if(process.env.DEBUG == 'aliyun') { + console.log('----------- sign string start -----------'); + console.log(string); + console.log('----------- sign string end -----------'); + } + return ALY.util.crypto.hmac(secret, string, 'base64', 'sha1'); + } + }); + + module.exports = ALY.Signers.OSS; + + }).call(this,require('_process')) + },{"../core":5,"_process":89}],29:[function(require,module,exports){ + var ALY = require('../core'); + var inherit = ALY.util.inherit; + + ALY.Signers.POP = inherit(ALY.Signers.RequestSigner, { + + addAuthorization: function addAuthorization(credentials, date) { + }, + + }); + + module.exports = ALY.Signers.POP; + + },{"../core":5}],30:[function(require,module,exports){ + (function (process){ + var ALY = require('../core'); + var inherit = ALY.util.inherit; + + /** + * @api private + */ + ALY.Signers.PopJson = inherit(ALY.Signers.RequestSigner, { + + //entry + addAuthorization: function addAuthorization(credentials, date) { + var headers = this.request.headers; + + headers['x-acs-date'] = ALY.util.date.rfc822(date); + + headers['x-acs-signature-method'] = 'HMAC-SHA1'; + headers['x-acs-signature-version'] = '1.0'; + //headers['x-acs-version'] = API_VERSION; + headers['x-sdk-client'] = 'node.js/1.0.0'; + headers['Accept'] = 'application/json'; + + var signature = this.sign(credentials.secretAccessKey, this.stringToSign()); + + headers['Authorization'] = 'acs ' + credentials.accessKeyId + ':' + signature; + }, + + stringToSign: function stringToSign() { + var r = this.request; + + //fix signature not match in browser + if (r.method !== 'GET' && r.method !== 'HEAD') { + r.headers['Content-Type'] = 'application/json;charset=utf-8'; + } + + var parts = []; + parts.push(r.method); + parts.push(r.headers['Accept'] || ''); + parts.push(r.headers['Content-MD5'] || ''); + parts.push(r.headers['Content-Type'] || ''); + parts.push(r.headers['x-acs-date'] || r.headers['Date'] || ''); + + var headers = this.canonicalizedAcsHeaders(); + if (headers) parts.push(headers); + parts.push(this.canonicalizedResource()); + + return parts.join('\n'); + }, + + canonicalizedAcsHeaders: function canonicalizedAcsHeaders() { + + var acsHeaders = []; + + ALY.util.each(this.request.headers, function (name) { + if (name.match(/^x-acs-/i)) + acsHeaders.push(name); + }); + + acsHeaders.sort(function (a, b) { + return a.toLowerCase() < b.toLowerCase() ? -1 : 1; + }); + + var parts = []; + ALY.util.arrayEach.call(this, acsHeaders, function (name) { + parts.push(name.toLowerCase() + ':' + String(this.request.headers[name])); + }); + + return parts.join('\n'); + + }, + + canonicalizedResource: function canonicalizedResource() { + + var r = this.request; + + var parts = r.path.split('?'); + var path = parts[0]; + var querystring = parts[1]; + + var resource = ''; + + resource += decodeURIComponent(path); + + if (querystring) { + + // collect a list of sub resources and query params that need to be signed + var resources = []; + + var arr = querystring.replace(/(^&*)|(&*$)/g, '').split('&'); + + ALY.util.arrayEach.call(this, arr, function (param) { + var kv = param.split('='); + + var name = kv[0]; + + var value = (kv.length > 1) ? decodeURIComponent(kv[1]) : ''; + /*jshint undef:false */ + + var resource = {name: name}; + if (value !== undefined) { + resource.value = value; + } + resources.push(resource); + + }); + + resources.sort(function (a, b) { + return a.name < b.name ? -1 : 1; + }); + + if (resources.length) { + + querystring = []; + ALY.util.arrayEach(resources, function (resource) { + if (resource.value === undefined) + querystring.push(resource.name); + else { + + if (resource.value !== null && resource.value !== '') { + querystring.push(resource.name + '=' + resource.value); + } else { + querystring.push(resource.name); + } + } + }); + + resource += '?' + querystring.join('&'); + } + + } + + return resource; + + }, + + sign: function sign(secret, string) { + if (process.env.DEBUG === 'aliyun') { + console.log('----------- sign string start -----------'); + console.log(string); + console.log('----------- sign string end -----------'); + } + return ALY.util.crypto.hmac(secret, string, 'base64', 'sha1'); + } + }); + + module.exports = ALY.Signers.PopJson; + }).call(this,require('_process')) + },{"../core":5,"_process":89}],31:[function(require,module,exports){ + var ALY = require('../core'); + var inherit = ALY.util.inherit; + + /** + * @api private + */ + ALY.Signers.RequestSigner = inherit({ + constructor: function RequestSigner(request) { + this.request = request; + } + }); + + ALY.Signers.RequestSigner.getVersion = function getVersion(version) { + switch (version) { + case 'oss': return ALY.Signers.OSS; + case 'ots': return ALY.Signers.OTS; + case 'sls': return ALY.Signers.SLS; + case 'top': return ALY.Signers.TOP; + case 'pop': return ALY.Signers.POP; + case 'pop-json': return ALY.Signers.PopJson; + case 'opensearch': return ALY.Signers.OpenSearch; + case 'batchcompute': return ALY.Signers.BatchCompute; + case 'cms': return ALY.Signers.CMS; + } + throw new Error('Unknown signing version ' + version); + }; + + require('./oss'); + require('./ots'); + require('./sls'); + require('./opensearch'); + require('./top'); + require('./pop'); + require('./pop_json'); + require('./batchcompute'); + require('./cms'); + },{"../core":5,"./batchcompute":24,"./cms":25,"./opensearch":26,"./oss":27,"./ots":28,"./pop":29,"./pop_json":30,"./sls":32,"./top":33}],32:[function(require,module,exports){ + (function (process){ + var ALY = require('../core'); + var inherit = ALY.util.inherit; + /** + * @api private + */ + ALY.Signers.SLS = inherit(ALY.Signers.RequestSigner, { + + + // when building the stringToSign, these querystring params should be + // part of the canonical resource string with their NON-encoded values + responseHeaders: { + 'response-content-type': 1, + 'response-content-language': 1, + 'response-expires': 1, + 'response-cache-control': 1, + 'response-content-disposition': 1, + 'response-content-encoding': 1 + }, + + addAuthorization: function addAuthorization(credentials, date) { + this.request.headers['Date'] = ALY.util.date.rfc822(date); + if(credentials.securityToken) + this.request.headers['x-acs-security-token'] = credentials.securityToken; + + var signature = this.sign(credentials.secretAccessKey, this.stringToSign()); + var auth = 'LOG ' + credentials.accessKeyId + ':' + signature; + + this.request.headers['Authorization'] = auth; + }, + + stringToSign: function stringToSign() { + var r = this.request; + + var parts = []; + parts.push(r.method); + parts.push(r.headers['Content-MD5'] || ''); + parts.push(r.headers['Content-Type'] || ''); + + // This is the "Date" header, but we use X-Amz-Date. + // The S3 signing mechanism requires us to pass an empty + // string for this Date header regardless. + // this works: + // getSignedUrl use 'presigned-expires' + // other request use 'Date' + parts.push(r.headers['Date'] || ''); + + var headers = this.canonicalizedAmzHeaders(); + if (headers) parts.push(headers); + parts.push(this.canonicalizedResource()); + + return parts.join('\n'); + + }, + + canonicalizedAmzHeaders: function canonicalizedAmzHeaders() { + + var amzHeaders = []; + + ALY.util.each(this.request.headers, function (name) { + if (name.match(/^x-log-/i) || name=='x-acs-security-token') + amzHeaders.push(name); + }); + + amzHeaders.sort(function (a, b) { + return a.toLowerCase() < b.toLowerCase() ? -1 : 1; + }); + + var parts = []; + ALY.util.arrayEach.call(this, amzHeaders, function (name) { + parts.push(name.toLowerCase() + ':' + String(this.request.headers[name])); + }); + + return parts.join('\n'); + + }, + + canonicalizedResource: function canonicalizedResource() { + + var r = this.request; + + var parts = r.path.split('?'); + var path = parts[0]; + var querystring = parts[1]; + + var resource = ''; + + + resource += decodeURIComponent(path); + + + if (querystring) { + + // collect a list of sub resources and query params that need to be signed + var resources = []; + + var arr = querystring.replace(/(^&*)|(&*$)/g,'').split('&'); + + + ALY.util.arrayEach.call(this, arr, function (param) { + var kv = param.split('='); + + var name = kv[0]; + //修复topic中带有 / 等字符,签名报错 + var value = (kv.length>1)? decodeURIComponent(kv[1]):''; + /*jshint undef:false */ + + var resource = { name: name }; + if (value !== undefined) { + resource.value = value; + } + resources.push(resource); + + }); + + resources.sort(function (a, b) { return a.name < b.name ? -1 : 1; }); + + if (resources.length) { + + querystring = []; + ALY.util.arrayEach(resources, function (resource) { + if (resource.value === undefined) + querystring.push(resource.name); + else + querystring.push(resource.name + '=' + resource.value); + }); + + resource += '?' + querystring.join('&'); + } + + } + + return resource; + + }, + + sign: function sign(secret, string) { + if(process.env.DEBUG == 'aliyun') { + console.log('----------- sign string start -----------'); + console.log(string); + console.log('----------- sign string end -----------'); + } + return ALY.util.crypto.hmac(secret, string, 'base64', 'sha1'); + } + }); + + module.exports = ALY.Signers.SLS; + + }).call(this,require('_process')) + },{"../core":5,"_process":89}],33:[function(require,module,exports){ + var ALY = require('../core'); + var inherit = ALY.util.inherit; + + ALY.Signers.TOP = inherit(ALY.Signers.RequestSigner, { + + // sign 已经在 service_interface/top 中实现了 + addAuthorization: function addAuthorization(credentials, date) { + + } + + }); + + module.exports = ALY.Signers.TOP; + + },{"../core":5}],34:[function(require,module,exports){ + (function (process){ + /*global escape:true */ + + var ALY = require('./core'); + //var cryptoLib = require('crypto'); + var jsSHA = require('../bower_components/jsSHA/src/sha.js'); + var SparkMD5 = require('../bower_components/spark-md5/spark-md5.js'); + + /* jshint -W079 */ + var Buffer = require('buffer').Buffer; + /* jshint +W079 */ + + /** + * A set of utility methods for use with the ALY SDK. + * + * @!attribute abort + * Return this value from an iterator function {each} or {arrayEach} + * to break out of the iteration. + * @example Breaking out of an iterator function + * ALY.util.each({a: 1, b: 2, c: 3}, function(key, value) { + * if (key == 'b') return ALY.util.abort; + * }); + * @see each + * @see arrayEach + * @api private + */ + ALY.util = { + engine: function engine() { + if (ALY.util.isBrowser() && typeof navigator !== 'undefined') { + return navigator.userAgent; + } else { + return process.platform + '/' + process.version; + } + }, + + userAgent: function userAgent() { + // 在 浏览器中不能设置 ua + return ""; + }, + + isBrowser: function isBrowser() { return typeof window !== 'undefined'; }, + isNode: function isNode() { return !ALY.util.isBrowser(); }, + nodeRequire: function nodeRequire(module) { + if (ALY.util.isNode()) return require(module); + }, + + // todo: atob, btoa + hexToBase64: function (str) { + return btoa(String.fromCharCode.apply(null, + str.replace(/\r|\n/g, "").replace(/([\da-fA-F]{2}) ?/g, "0x$1 ").replace(/ +$/, "").split(" ")) + ); + }, + + topEscape: function(clearString) { + var output = ''; + var x = 0; + clearString = clearString.toString(); + var regex = /(^[a-zA-Z0-9-_.~]*)/; + while (x < clearString.length) { + var match = regex.exec(clearString.substr(x)); + if (match != null && match.length > 1 && match[1] != '') { + output += match[1]; + x += match[1].length; + } else { + if (clearString[x] == ' ') + output += '%20'; + else { + var charCode = clearString.charCodeAt(x); + var hexVal = charCode.toString(16); + output += '%' + ( hexVal.length < 2 ? '0' : '' ) + hexVal.toUpperCase(); + } + x++; + } + } + return output; + }, + + popEscape: function(clearString) { + clearString = clearString.toString(); + clearString = encodeURIComponent(clearString) + .replace(/\!/gi, '%21') + .replace(/\'/gi, '%27') + .replace(/\(/gi, '%28') + .replace(/\)/gi, '%29') + .replace(/\*/gi, '%2A') + return clearString; + }, + + opensearchEscape: function(clearString) { + // http://v8.googlecode.com/svn/trunk/src/uri.js + return encodeURIComponent(clearString) + .replace(/\!/gi, '%21') + .replace(/\'/gi, '%27') + .replace(/\(/gi, '%28') + .replace(/\)/gi, '%29') + .replace(/\*/gi, '%2A') + }, + + uriEscape: function uriEscape(string) { + /*jshint undef:false */ + var output = encodeURIComponent(string); + output = output.replace(/[^A-Za-z0-9_.~\-%]+/g, escape); + + // percent-encodes some extra non-standard characters in a URI + output = output.replace(/[*]/g, function(ch) { + return '%' + ch.charCodeAt(0).toString(16).toUpperCase(); + }); + + return output; + }, + + uriEscapePath: function uriEscapePath(string) { + var parts = []; + ALY.util.arrayEach(string.split('/'), function (part) { + parts.push(ALY.util.uriEscape(part)); + }); + return parts.join('/'); + }, + + urlParse: function urlParse(url) { + return require('url').parse(url); + }, + + urlFormat: function urlFormat(url) { + return require('url').format(url); + }, + + uuid: function generateUUID(){ + var d = new Date().getTime(); + if(window.performance && typeof window.performance.now === "function"){ + d += performance.now(); //use high-precision timer if available + } + var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { + var r = (d + Math.random()*16)%16 | 0; + d = Math.floor(d/16); + return (c=='x' ? r : (r&0x3|0x8)).toString(16); + }); + return uuid; + }, + + queryParamsToString: function queryParamsToString(params) { + var items = []; + var escape = ALY.util.uriEscape; + var sortedKeys = Object.keys(params).sort(); + + ALY.util.arrayEach(sortedKeys, function(name) { + var value = params[name]; + var ename = escape(name); + var result = ename; + if (Array.isArray(value)) { + var vals = []; + ALY.util.arrayEach(value, function(item) { vals.push(escape(item)); }); + result = ename + '=' + vals.sort().join('&' + ename + '='); + } else if (value !== undefined && value !== null) { + result = ename + '=' + escape(value); + } + items.push(result); + }); + + return items.join('&'); + }, + + readFileSync: function readFileSync(path) { + if (typeof window !== 'undefined') return null; + return require('fs').readFileSync(path, 'utf-8'); + }, + + base64: { + + encode: function encode64(string) { + return new Buffer(string).toString('base64'); + }, + + decode: function decode64(string) { + return new Buffer(string, 'base64').toString(); + } + + }, + + Buffer: Buffer, + + buffer: { + /** + * Concatenates a list of Buffer objects. + */ + concat: function(buffers) { + var length = 0, + offset = 0, + buffer = null, i; + + for (i = 0; i < buffers.length; i++) { + length += buffers[i].length; + } + + buffer = new Buffer(length); + + for (i = 0; i < buffers.length; i++) { + buffers[i].copy(buffer, offset); + offset += buffers[i].length; + } + + return buffer; + } + }, + + string: { + byteLength: function byteLength(string) { + if (string === null || string === undefined) return 0; + if (typeof string === 'string') string = new Buffer(string); + + if (typeof string.byteLength === 'number') { + return string.byteLength; + } else if (typeof string.length === 'number') { + return string.length; + } else if (typeof string.size === 'number') { + return string.size; + } else if (typeof string.path === 'string') { + return require('fs').lstatSync(string.path).size; + } else { + throw ALY.util.error(new Error('Cannot determine length of ' + string), + { object: string }); + } + } + }, + + jamespath: { + query: function query(expression, data) { + if (!data) return []; + + var results = []; + var expressions = expression.split(/\s+or\s+/); + ALY.util.arrayEach.call(this, expressions, function (expr) { + var objects = [data]; + var tokens = expr.split('.'); + ALY.util.arrayEach.call(this, tokens, function (token) { + var match = token.match('^(.+?)(?:\\[(-?\\d+|\\*)\\])?$'); + var newObjects = []; + ALY.util.arrayEach.call(this, objects, function (obj) { + if (match[1] === '*') { + ALY.util.arrayEach.call(this, obj, function (value) { + newObjects.push(value); + }); + } else if (obj.hasOwnProperty(match[1])) { + newObjects.push(obj[match[1]]); + } + }); + objects = newObjects; + + // handle indexing (token[0], token[-1]) + if (match[2]) { + newObjects = []; + ALY.util.arrayEach.call(this, objects, function (obj) { + if (Array.isArray(obj)) { + if (match[2] === '*') { + newObjects = newObjects.concat(obj); + } else { + var idx = parseInt(match[2], 10); + if (idx < 0) idx = obj.length + idx; // negative indexing + newObjects.push(obj[idx]); + } + } + }); + objects = newObjects; + } + + if (objects.length === 0) return ALY.util.abort; + }); + + if (objects.length > 0) { + results = objects; + return ALY.util.abort; + } + }); + + return results; + }, + + find: function find(expression, data) { + return ALY.util.jamespath.query(expression, data)[0]; + } + }, + + /** + * Date and time utility functions. + */ + date: { + + /** + * @return [Date] the current JavaScript date object. Since all + * ALY services rely on this date object, you can override + * this function to provide a special time value to ALY service + * requests. + */ + getDate: function getDate() { return new Date(); }, + + // for taobao open platform + top: function top(date, fmt) { + fmt = fmt || '%Y-%M-%dT%H:%m:%sZ'; + + function pad(value) { + return (value.toString().length < 2) ? '0' + value : value; + }; + + return fmt.replace(/%([a-zA-Z])/g, function (_, fmtCode) { + switch (fmtCode) { + case 'Y': + return date.getUTCFullYear(); + case 'M': + return pad(date.getUTCMonth() + 1); + case 'd': + return pad(date.getUTCDate()); + case 'H': + return pad(date.getUTCHours()); + case 'm': + return pad(date.getUTCMinutes()); + case 's': + return pad(date.getUTCSeconds()); + default: + throw new Error('Unsupported format code: ' + fmtCode); + } + }); + }, + + /** + * @return [String] the date in ISO-8601 format + */ + iso8601: function iso8601(date) { + if (date === undefined) { date = ALY.util.date.getDate(); } + return date.toISOString(); + }, + + /** + * @return [String] the date in RFC 822 format + */ + rfc822: function rfc822(date) { + if (date === undefined) { date = ALY.util.date.getDate(); } + return date.toUTCString(); + }, + + unixSeconds: function unixSeconds(date) { + if (date === undefined) { date = ALY.util.date.getDate(); } + return Math.floor(date.getTime() / 1000); + }, + + unixMilliseconds: function unixMilliseconds(date) { + if (date === undefined) { date = ALY.util.date.getDate(); } + return date.getTime(); + }, + + /** + * @param [String,number,Date] date + * @return [Date] + */ + from: function format(date) { + if (typeof date === 'number') { + if(date.toString().length == 10) { + return new Date(date * 1000); // unix timestamp in seconds + } + return new Date(date); // unix timestamp in mill seconds + } + else if(Object.prototype.toString.call(date) === '[object Date]') { + return date; + } + else { + return new Date(date); + } + }, + + /** + * Given a Date or date-like value, this function formats the + * date into a string of the requested value. + * @param [String,number,Date] date + * @param [String] formatter Valid formats are: + # * 'iso8601' + # * 'rfc822' + # * 'unixSeconds' + # * 'unixMilliseconds' + * @return [String] + */ + format: function format(date, formatter) { + if (!formatter) formatter = 'unixSeconds'; + return ALY.util.date[formatter](ALY.util.date.from(date)); + } + + }, + + crypto: { + crc32Table: [ + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, + 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, + 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, + 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, + 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, + 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, + 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, + 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, + 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, + 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, + 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, + 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, + 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, + 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, + 0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, + 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, + 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, + 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, + 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, + 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, + 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, + 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, + 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, + 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, + 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, + 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, + 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, + 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, + 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, + 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, + 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, + 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, + 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, + 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, + 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, + 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, + 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, + 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, + 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, + 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, + 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, + 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, + 0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, + 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, + 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, + 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, + 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, + 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, + 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, + 0x2D02EF8D], + + crc32: function crc32(data) { + /*jshint bitwise:false*/ + var tbl = ALY.util.crypto.crc32Table; + var crc = 0 ^ -1; + + if (typeof data === 'string') { + data = new Buffer(data); + } + + for (var i = 0; i < data.length; i++) { + var code = data.readUInt8(i); + crc = (crc>>>8) ^ tbl[(crc^code)&0xFF]; + } + return (crc ^ -1) >>> 0; + }, + + hmac: function hmac(key, string, digest, fn) { + if (!digest) digest = 'binary'; + + if (digest === 'buffer') { + digest = undefined; + // todo: 不支持 buffer 类型的 hash + return ""; + } + + if (!fn) fn = 'sha256'; + + if (typeof string != 'string') { + //string = new Buffer(string); + // todo: 目前只支持 string + return ""; + } + + var shaObj; + switch (fn) { + case "md5": + // todo: 不支持 md5 + return ""; + case "sha1": + shaObj = new jsSHA("SHA-1", "TEXT"); + break; + case "sha256": + shaObj = new jsSHA("SHA-256", "TEXT"); + break; + case "sha512": + shaObj = new jsSHA("SHA-512", "TEXT"); + break; + default: + return ""; + } + + shaObj.setHMACKey(key, "TEXT"); + + shaObj.update(string); + + switch(digest) { + case "binary": + return shaObj.getHMAC("BYTES"); + case "hex": + return shaObj.getHMAC("HEX"); + case "base64": + return shaObj.getHMAC("B64"); + default: + return ""; + } + }, + + // https://nodejs.org/api/crypto.html#crypto_hash_digest_encoding + md5: function md5(data, digest) { + var hash = ""; + + if (!digest) { digest = 'binary'; } + + if (digest === 'buffer') { + digest = undefined; + // todo: 不支持 buffer 类型的 hash + return ""; + } + + if (typeof data === 'string') { + switch(digest) { + case "binary": + return SparkMD5.hash(data, true); + case "hex": + return SparkMD5.hash(data); + case "base64": + return ALY.util.hexToBase64(SparkMD5.hash(data)); + default: + return ""; + } + } + else { // array buffer + switch(digest) { + case "binary": + return SparkMD5.ArrayBuffer.hash(data, true); + case "hex": + return SparkMD5.ArrayBuffer.hash(data); + case "base64": + return ALY.util.hexToBase64(SparkMD5.ArrayBuffer.hash(data)); + default: + return ""; + } + } + }, + + // 目前不支持 sha256 hash + sha256: function sha256(string, digest) { + //if (!digest) { digest = 'binary'; } + //if (digest === 'buffer') { digest = undefined; } + //if (typeof string === 'string') string = new Buffer(string); + //return ALY.util.crypto.createHash('sha256').update(string).digest(digest); + return ""; + }, + + toHex: function toHex(data) { + var out = []; + for (var i = 0; i < data.length; i++) { + out.push(('0' + data.charCodeAt(i).toString(16)).substr(-2, 2)); + } + return out.join(''); + } + + }, + + /** @!ignore */ + + /* Abort constant */ + abort: {}, + + each: function each(object, iterFunction) { + for (var key in object) { + if (object.hasOwnProperty(key)) { + var ret = iterFunction.call(this, key, object[key]); + if (ret === ALY.util.abort) break; + } + } + }, + + arrayEach: function arrayEach(array, iterFunction) { + for (var idx in array) { + if (array.hasOwnProperty(idx)) { + var ret = iterFunction.call(this, array[idx], parseInt(idx, 10)); + if (ret === ALY.util.abort) break; + } + } + }, + + update: function update(obj1, obj2) { + ALY.util.each(obj2, function iterator(key, item) { + obj1[key] = item; + }); + return obj1; + }, + + merge: function merge(obj1, obj2) { + return ALY.util.update(ALY.util.copy(obj1), obj2); + }, + + copy: function copy(object) { + if (object === null || object === undefined) return object; + var dupe = {}; + /*jshint forin:false */ + for (var key in object) { + dupe[key] = object[key]; + } + return dupe; + }, + + isEmpty: function isEmpty(obj) { + for (var prop in obj) { + if (obj.hasOwnProperty(prop)) { + return false; + } + } + return true; + }, + + isType: function isType(obj, type) { + // handle cross-"frame" objects + if (typeof type === 'function') type = ALY.util.typeName(type); + return Object.prototype.toString.call(obj) === '[object ' + type + ']'; + }, + + typeName: function typeName(type) { + if (type.hasOwnProperty('name')) return type.name; + var str = type.toString(); + var match = str.match(/^\s*function (.+)\(/); + return match ? match[1] : str; + }, + + error: function error(err, options) { + var originalError = null; + if (typeof err.message === 'string' && err.message !== '') { + if (typeof options === 'string' || (options && options.message)) { + originalError = ALY.util.copy(err); + originalError.message = err.message; + } + } + err.message = err.message || null; + + if (typeof options === 'string') { + err.message = options; + } else { + ALY.util.update(err, options); + } + + if (typeof Object.defineProperty === 'function') { + Object.defineProperty(err, 'name', {writable: true, enumerable: false}); + Object.defineProperty(err, 'message', {enumerable: true}); + } + + err.name = err.name || err.code || 'Error'; + err.time = new Date(); + + if (originalError) err.originalError = originalError; + + return err; + }, + + /** + * @api private + */ + inherit: function inherit(klass, features) { + var newObject = null; + if (features === undefined) { + features = klass; + klass = Object; + newObject = {}; + } else { + /*jshint newcap:false */ + /*jshint camelcase:false */ + var ctor = function __ctor_wrapper__() {}; + ctor.prototype = klass.prototype; + newObject = new ctor(); + } + + // constructor not supplied, create pass-through ctor + if (features.constructor === Object) { + features.constructor = function() { + if (klass !== Object) { + return klass.apply(this, arguments); + } + }; + } + + features.constructor.prototype = newObject; + ALY.util.update(features.constructor.prototype, features); + features.constructor.__super__ = klass; + return features.constructor; + }, + + /** + * @api private + */ + mixin: function mixin() { + var klass = arguments[0]; + for (var i = 1; i < arguments.length; i++) { + /*jshint forin:false*/ + for (var prop in arguments[i].prototype) { + var fn = arguments[i].prototype[prop]; + if (prop != 'constructor') { + klass.prototype[prop] = fn; + } + } + } + return klass; + }, + + /** + * @api private + */ + hideProperties: function hideProperties(obj, props) { + if (typeof Object.defineProperty !== 'function') return; + + ALY.util.arrayEach(props, function (key) { + Object.defineProperty(obj, key, { + enumerable: false, writable: true, configurable: true }); + }); + } + }; + + module.exports = ALY.util; + + }).call(this,require('_process')) + },{"../bower_components/jsSHA/src/sha.js":1,"../bower_components/spark-md5/spark-md5.js":2,"./core":5,"_process":89,"buffer":82,"fs":80,"url":109}],35:[function(require,module,exports){ + var ALY = require('../core'); + var builder = require('xmlbuilder'); + var inherit = ALY.util.inherit; + + /** + * @api private + */ + ALY.XML.Builder = inherit({ + + constructor: function XMLBuilder(root, rules, options) { + this.root = root; + this.rules = rules; + this.xmlns = options.xmlnamespace; + this.timestampFormat = options.timestampFormat; + }, + + toXML: function toXML(params) { + var xml = builder.create(this.root); + if (this.xmlns) xml.att('xmlns', this.xmlns); + this.serializeStructure(this.rules, params, xml); + return xml.root().toString(); + }, + + serializeStructure: function serializeStructure(rules, params, xml) { + ALY.util.each.call(this, rules || {}, function (memberName, memberRules) { + var value = params[memberName]; + if (value !== undefined) { + if (memberRules.attribute) { + xml.att(memberRules.name, value); + } else { + this.serializeMember(memberName, memberRules, value, xml); + } + } + }); + }, + + serializeList: function serializeList(name, rules, list, xml) { + if (rules.flattened) { + ALY.util.arrayEach.call(this, list, function (value) { + this.serializeMember(rules.name || name, rules.members, value, xml); + }); + } else { + xml = xml.ele(rules.name || name); + ALY.util.arrayEach.call(this, list, function (value) { + var memberName = rules.members.name || 'member'; + this.serializeMember(memberName, rules.members, value, xml); + }); + } + }, + + serializeMember: function serializeMember(memberName, rules, params, xml) { + if (params === null || params === undefined) return; + + var name = memberName; + if (rules.type === 'structure') { + xml = xml.ele(name); + this.serializeStructure(rules.members, params, xml); + } else if (rules.type === 'list') { + this.serializeList(name, rules, params, xml); + } else if (rules.type === 'timestamp') { + var timestampFormat = rules.format || this.timestampFormat; + var date = ALY.util.date.format(params, timestampFormat); + xml = xml.ele(name, String(date)); + } else { + xml = xml.ele(name, String(params)); + } + this.applyNamespaces(xml, rules); + }, + + applyNamespaces: function applyNamespaces(xml, rules) { + if (rules.xmlns) { + var attr = 'xmlns'; + if (rules.xmlns.prefix) attr += ':' + rules.xmlns.prefix; + xml.att(attr, rules.xmlns.uri); + } + } + + + }); + + },{"../core":5,"xmlbuilder":57}],36:[function(require,module,exports){ + var ALY = require('../core'); + var inherit = ALY.util.inherit; + var xml2js = require('xml2js'); + + /** + * @api private + */ + ALY.XML.Parser = inherit({ + + constructor: function XMLParser(rules) { + this.rules = (rules || {}).members || {}; + }, + + // options passed to xml2js parser + options: { + explicitCharkey: false, // undocumented + trim: false, // trim the leading/trailing whitespace from text nodes + normalize: false, // trim interior whitespace inside text nodes + explicitRoot: false, // return the root node in the resulting object? + emptyTag: null, // the default value for empty nodes + explicitArray: true, // always put child nodes in an array + ignoreAttrs: false, // ignore attributes, only create text nodes + mergeAttrs: false, // merge attributes and child elements + validator: null // a callable validator + }, + + parse: function parse(xml) { + + var result = null; + var error = null; + var parser = new xml2js.Parser(this.options); + parser.parseString(xml, function (e, r) { + error = e; + result = r; + }); + + if (result) { + delete result.xmlns; + return this.parseStructure(result, this.rules); + } else if (error) { + throw ALY.util.error(error, {code: 'XMLParserError'}); + } else { // empty xml document + return this.parseStructure({}, this.rules); + } + + }, + + parseStructure: function parseStructure(structure, rules) { + var data = {}; + + // force array members to always be present + ALY.util.each.call(this, rules, function(memberName, memberRules) { + if (memberRules.type == 'list') { + data[memberRules.name || memberName] = []; + } + }); + + ALY.util.each.call(this, structure, function (xmlName, value) { + if (xmlName == '$') { + ALY.util.each.call(this, value, function (attrName, attrValue) { + if (rules[attrName]) { + var rule = rules[attrName]; + data[rule.name || xmlName] = this.parseMember([attrValue], rule); + } + }); + } else { + var rule = rules[xmlName] || {}; + data[rule.name || xmlName] = this.parseMember(value, rule); + } + }); + + return data; + }, + + parseMap: function parseMap(map, rules) { + var data = {}; + var keyRules = rules.keys || {}; + var valueRules = rules.members || {}; + var keyName = keyRules.name || 'key'; + var valueName = valueRules.name || 'value'; + if (!rules.flattened) { + map = map[0].entry; + } + ALY.util.arrayEach.call(this, map, function (entry) { + var value = this.parseMember(entry[valueName], valueRules); + data[entry[keyName][0]] = value; + }); + return data; + }, + + parseList: function parseList(list, rules) { + var data = []; + var memberRules = rules.members || {}; + var memberName = memberRules.name || 'member'; + if (rules.flattened) { + ALY.util.arrayEach.call(this, list, function (value) { + data.push(this.parseMember([value], memberRules)); + }); + } else { + ALY.util.arrayEach.call(this, list, function (member) { + ALY.util.arrayEach.call(this, member[memberName], function (value) { + data.push(this.parseMember([value], memberRules)); + }); + }); + } + return data; + }, + + parseMember: function parseMember(values, rules) { + /*jshint maxcomplexity:20*/ + + if (values[0] === null) { + if (rules.type === 'structure') return {}; + if (rules.type === 'list') return []; + if (rules.type === 'map') return {}; + return null; + } + + if (values[0]['$'] && values[0]['$'].encoding == 'base64') { + return ALY.util.base64.decode(values[0]['_']); + } + + if (!rules.type) { + if (typeof values[0] === 'string') { + rules.type = 'string'; + } else if (values[0]['_']) { + rules.type = 'string'; + values = [values[0]['_']]; + } else { + rules.type = 'structure'; + } + } + + if (rules.type === 'string') { + + return values[0]; + + } else if (rules.type === 'structure') { + + return this.parseStructure(values[0], rules.members || {}); + + } else if (rules.type === 'list') { + + return this.parseList(values, rules); + + } else if (rules.type === 'map') { + + return this.parseMap(values, rules); + + } else if (rules.type === 'integer') { + + return parseInt(values[0], 10); + + } else if (rules.type === 'float') { + + return parseFloat(values[0]); + + } else if (rules.type === 'timestamp') { + + return this.parseTimestamp(values[0]); + + } else if (rules.type === 'boolean') { + + return values[0] === 'true'; + + } else { + + var msg = 'unhandled type: ' + rules.type; + throw ALY.util.error(new Error(msg), {code: 'XMLParserError'}); + + } + + }, + + parseTimestamp: function parseTimestamp(value) { + + if (value.match(/^\d+$/)) { // unix timestamp + + return new Date(value * 1000); + + } else if (value.match(/^\d{4}/)) { // iso8601 + + return new Date(value); + + } else if (value.match(/^\w{3},/)) { // rfc822 + + return new Date(value); + + } else { + + throw ALY.util.error( + new Error('unhandled timestamp format: ' + value), + {code: 'TimestampParserError'}); + + } + + } + + }); + + },{"../core":5,"xml2js":39}],37:[function(require,module,exports){ + // Generated by CoffeeScript 1.7.1 + (function() { + var xml2js; + + xml2js = require('../lib/xml2js'); + + exports.stripBOM = function(str) { + if (str[0] === '\uFEFF') { + return str.substring(1); + } else { + return str; + } + }; + + }).call(this); + + },{"../lib/xml2js":39}],38:[function(require,module,exports){ + // Generated by CoffeeScript 1.7.1 + (function() { + var prefixMatch; + + prefixMatch = new RegExp(/(?!xmlns)^.*:/); + + exports.normalize = function(str) { + return str.toLowerCase(); + }; + + exports.firstCharLowerCase = function(str) { + return str.charAt(0).toLowerCase() + str.slice(1); + }; + + exports.stripPrefix = function(str) { + return str.replace(prefixMatch, ''); + }; + + }).call(this); + + },{}],39:[function(require,module,exports){ + (function (process){ + // Generated by CoffeeScript 1.7.1 + (function() { + var bom, builder, events, isEmpty, processName, processors, sax, + __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, + __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; + + sax = require('sax'); + + events = require('events'); + + builder = require('xmlbuilder'); + + bom = require('./bom'); + + processors = require('./processors'); + + isEmpty = function(thing) { + return typeof thing === "object" && (thing != null) && Object.keys(thing).length === 0; + }; + + processName = function(processors, processedName) { + var process, _i, _len; + for (_i = 0, _len = processors.length; _i < _len; _i++) { + process = processors[_i]; + processedName = process(processedName); + } + return processedName; + }; + + exports.processors = processors; + + exports.defaults = { + "0.1": { + explicitCharkey: false, + trim: true, + normalize: true, + normalizeTags: false, + attrkey: "@", + charkey: "#", + explicitArray: false, + ignoreAttrs: false, + mergeAttrs: false, + explicitRoot: false, + validator: null, + xmlns: false, + explicitChildren: false, + childkey: '@@', + charsAsChildren: false, + async: false, + strict: true, + attrNameProcessors: null, + tagNameProcessors: null + }, + "0.2": { + explicitCharkey: false, + trim: false, + normalize: false, + normalizeTags: false, + attrkey: "$", + charkey: "_", + explicitArray: true, + ignoreAttrs: false, + mergeAttrs: false, + explicitRoot: true, + validator: null, + xmlns: false, + explicitChildren: false, + childkey: '$$', + charsAsChildren: false, + async: false, + strict: true, + attrNameProcessors: null, + tagNameProcessors: null, + rootName: 'root', + xmldec: { + 'version': '1.0', + 'encoding': 'UTF-8', + 'standalone': true + }, + doctype: null, + renderOpts: { + 'pretty': true, + 'indent': ' ', + 'newline': '\n' + }, + headless: false + } + }; + + exports.ValidationError = (function(_super) { + __extends(ValidationError, _super); + + function ValidationError(message) { + this.message = message; + } + + return ValidationError; + + })(Error); + + exports.Builder = (function() { + function Builder(opts) { + var key, value, _ref; + this.options = {}; + _ref = exports.defaults["0.2"]; + for (key in _ref) { + if (!__hasProp.call(_ref, key)) continue; + value = _ref[key]; + this.options[key] = value; + } + for (key in opts) { + if (!__hasProp.call(opts, key)) continue; + value = opts[key]; + this.options[key] = value; + } + } + + Builder.prototype.buildObject = function(rootObj) { + var attrkey, charkey, render, rootElement, rootName; + attrkey = this.options.attrkey; + charkey = this.options.charkey; + if ((Object.keys(rootObj).length === 1) && (this.options.rootName === exports.defaults['0.2'].rootName)) { + rootName = Object.keys(rootObj)[0]; + rootObj = rootObj[rootName]; + } else { + rootName = this.options.rootName; + } + render = function(element, obj) { + var attr, child, entry, index, key, value, _ref, _ref1; + if (typeof obj !== 'object') { + element.txt(obj); + } else { + for (key in obj) { + if (!__hasProp.call(obj, key)) continue; + child = obj[key]; + if (key === attrkey) { + if (typeof child === "object") { + for (attr in child) { + value = child[attr]; + element = element.att(attr, value); + } + } + } else if (key === charkey) { + element = element.txt(child); + } else if (typeof child === 'object' && ((child != null ? child.constructor : void 0) != null) && ((child != null ? (_ref = child.constructor) != null ? _ref.name : void 0 : void 0) != null) && (child != null ? (_ref1 = child.constructor) != null ? _ref1.name : void 0 : void 0) === 'Array') { + for (index in child) { + if (!__hasProp.call(child, index)) continue; + entry = child[index]; + if (typeof entry === 'string') { + element = element.ele(key, entry).up(); + } else { + element = arguments.callee(element.ele(key), entry).up(); + } + } + } else if (typeof child === "object") { + element = arguments.callee(element.ele(key), child).up(); + } else { + element = element.ele(key, child.toString()).up(); + } + } + } + return element; + }; + rootElement = builder.create(rootName, this.options.xmldec, this.options.doctype, { + headless: this.options.headless + }); + return render(rootElement, rootObj).end(this.options.renderOpts); + }; + + return Builder; + + })(); + + exports.Parser = (function(_super) { + __extends(Parser, _super); + + function Parser(opts) { + this.parseString = __bind(this.parseString, this); + this.reset = __bind(this.reset, this); + this.assignOrPush = __bind(this.assignOrPush, this); + var key, value, _ref; + if (!(this instanceof exports.Parser)) { + return new exports.Parser(opts); + } + this.options = {}; + _ref = exports.defaults["0.2"]; + for (key in _ref) { + if (!__hasProp.call(_ref, key)) continue; + value = _ref[key]; + this.options[key] = value; + } + for (key in opts) { + if (!__hasProp.call(opts, key)) continue; + value = opts[key]; + this.options[key] = value; + } + if (this.options.xmlns) { + this.options.xmlnskey = this.options.attrkey + "ns"; + } + if (this.options.normalizeTags) { + if (!this.options.tagNameProcessors) { + this.options.tagNameProcessors = []; + } + this.options.tagNameProcessors.unshift(processors.normalize); + } + this.reset(); + } + + Parser.prototype.assignOrPush = function(obj, key, newValue) { + if (!(key in obj)) { + if (!this.options.explicitArray) { + return obj[key] = newValue; + } else { + return obj[key] = [newValue]; + } + } else { + if (!(obj[key] instanceof Array)) { + obj[key] = [obj[key]]; + } + return obj[key].push(newValue); + } + }; + + Parser.prototype.reset = function() { + var attrkey, charkey, ontext, stack; + this.removeAllListeners(); + this.saxParser = sax.parser(this.options.strict, { + trim: false, + normalize: false, + xmlns: this.options.xmlns + }); + this.saxParser.errThrown = false; + this.saxParser.onerror = (function(_this) { + return function(error) { + _this.saxParser.resume(); + if (!_this.saxParser.errThrown) { + _this.saxParser.errThrown = true; + return _this.emit("error", error); + } + }; + })(this); + this.saxParser.ended = false; + this.EXPLICIT_CHARKEY = this.options.explicitCharkey; + this.resultObject = null; + stack = []; + attrkey = this.options.attrkey; + charkey = this.options.charkey; + this.saxParser.onopentag = (function(_this) { + return function(node) { + var key, newValue, obj, processedKey, _ref; + obj = {}; + obj[charkey] = ""; + if (!_this.options.ignoreAttrs) { + _ref = node.attributes; + for (key in _ref) { + if (!__hasProp.call(_ref, key)) continue; + if (!(attrkey in obj) && !_this.options.mergeAttrs) { + obj[attrkey] = {}; + } + newValue = node.attributes[key]; + processedKey = _this.options.attrNameProcessors ? processName(_this.options.attrNameProcessors, key) : key; + if (_this.options.mergeAttrs) { + _this.assignOrPush(obj, processedKey, newValue); + } else { + obj[attrkey][processedKey] = newValue; + } + } + } + obj["#name"] = _this.options.tagNameProcessors ? processName(_this.options.tagNameProcessors, node.name) : node.name; + if (_this.options.xmlns) { + obj[_this.options.xmlnskey] = { + uri: node.uri, + local: node.local + }; + } + return stack.push(obj); + }; + })(this); + this.saxParser.onclosetag = (function(_this) { + return function() { + var cdata, emptyStr, err, node, nodeName, obj, old, s, xpath; + obj = stack.pop(); + nodeName = obj["#name"]; + delete obj["#name"]; + cdata = obj.cdata; + delete obj.cdata; + s = stack[stack.length - 1]; + if (obj[charkey].match(/^\s*$/) && !cdata) { + emptyStr = obj[charkey]; + delete obj[charkey]; + } else { + if (_this.options.trim) { + obj[charkey] = obj[charkey].trim(); + } + if (_this.options.normalize) { + obj[charkey] = obj[charkey].replace(/\s{2,}/g, " ").trim(); + } + if (Object.keys(obj).length === 1 && charkey in obj && !_this.EXPLICIT_CHARKEY) { + obj = obj[charkey]; + } + } + if (isEmpty(obj)) { + obj = _this.options.emptyTag !== void 0 ? _this.options.emptyTag : emptyStr; + } + if (_this.options.validator != null) { + xpath = "/" + ((function() { + var _i, _len, _results; + _results = []; + for (_i = 0, _len = stack.length; _i < _len; _i++) { + node = stack[_i]; + _results.push(node["#name"]); + } + return _results; + })()).concat(nodeName).join("/"); + try { + obj = _this.options.validator(xpath, s && s[nodeName], obj); + } catch (_error) { + err = _error; + _this.emit("error", err); + } + } + if (_this.options.explicitChildren && !_this.options.mergeAttrs && typeof obj === 'object') { + node = {}; + if (_this.options.attrkey in obj) { + node[_this.options.attrkey] = obj[_this.options.attrkey]; + delete obj[_this.options.attrkey]; + } + if (!_this.options.charsAsChildren && _this.options.charkey in obj) { + node[_this.options.charkey] = obj[_this.options.charkey]; + delete obj[_this.options.charkey]; + } + if (Object.getOwnPropertyNames(obj).length > 0) { + node[_this.options.childkey] = obj; + } + obj = node; + } + if (stack.length > 0) { + return _this.assignOrPush(s, nodeName, obj); + } else { + if (_this.options.explicitRoot) { + old = obj; + obj = {}; + obj[nodeName] = old; + } + _this.resultObject = obj; + _this.saxParser.ended = true; + return _this.emit("end", _this.resultObject); + } + }; + })(this); + ontext = (function(_this) { + return function(text) { + var s; + s = stack[stack.length - 1]; + if (s) { + s[charkey] += text; + return s; + } + }; + })(this); + this.saxParser.ontext = ontext; + return this.saxParser.oncdata = (function(_this) { + return function(text) { + var s; + s = ontext(text); + if (s) { + return s.cdata = true; + } + }; + })(this); + }; + + Parser.prototype.parseString = function(str, cb) { + var err; + if ((cb != null) && typeof cb === "function") { + this.on("end", function(result) { + this.reset(); + if (this.options.async) { + return process.nextTick(function() { + return cb(null, result); + }); + } else { + return cb(null, result); + } + }); + this.on("error", function(err) { + this.reset(); + if (this.options.async) { + return process.nextTick(function() { + return cb(err); + }); + } else { + return cb(err); + } + }); + } + if (str.toString().trim() === '') { + this.emit("end", null); + return true; + } + try { + return this.saxParser.write(bom.stripBOM(str.toString())).close(); + } catch (_error) { + err = _error; + if (!(this.saxParser.errThrown || this.saxParser.ended)) { + this.emit('error', err); + return this.saxParser.errThrown = true; + } + } + }; + + return Parser; + + })(events.EventEmitter); + + exports.parseString = function(str, a, b) { + var cb, options, parser; + if (b != null) { + if (typeof b === 'function') { + cb = b; + } + if (typeof a === 'object') { + options = a; + } + } else { + if (typeof a === 'function') { + cb = a; + } + options = {}; + } + parser = new exports.Parser(options); + return parser.parseString(str, cb); + }; + + }).call(this); + + }).call(this,require('_process')) + },{"./bom":37,"./processors":38,"_process":89,"events":86,"sax":40,"xmlbuilder":57}],40:[function(require,module,exports){ + (function (Buffer){ + // wrapper for non-node envs + ;(function (sax) { + + sax.parser = function (strict, opt) { return new SAXParser(strict, opt) } + sax.SAXParser = SAXParser + sax.SAXStream = SAXStream + sax.createStream = createStream + + // When we pass the MAX_BUFFER_LENGTH position, start checking for buffer overruns. + // When we check, schedule the next check for MAX_BUFFER_LENGTH - (max(buffer lengths)), + // since that's the earliest that a buffer overrun could occur. This way, checks are + // as rare as required, but as often as necessary to ensure never crossing this bound. + // Furthermore, buffers are only tested at most once per write(), so passing a very + // large string into write() might have undesirable effects, but this is manageable by + // the caller, so it is assumed to be safe. Thus, a call to write() may, in the extreme + // edge case, result in creating at most one complete copy of the string passed in. + // Set to Infinity to have unlimited buffers. + sax.MAX_BUFFER_LENGTH = 64 * 1024 + + var buffers = [ + "comment", "sgmlDecl", "textNode", "tagName", "doctype", + "procInstName", "procInstBody", "entity", "attribName", + "attribValue", "cdata", "script" + ] + + sax.EVENTS = // for discoverability. + [ "text" + , "processinginstruction" + , "sgmldeclaration" + , "doctype" + , "comment" + , "attribute" + , "opentag" + , "closetag" + , "opencdata" + , "cdata" + , "closecdata" + , "error" + , "end" + , "ready" + , "script" + , "opennamespace" + , "closenamespace" + ] + + function SAXParser (strict, opt) { + if (!(this instanceof SAXParser)) return new SAXParser(strict, opt) + + var parser = this + clearBuffers(parser) + parser.q = parser.c = "" + parser.bufferCheckPosition = sax.MAX_BUFFER_LENGTH + parser.opt = opt || {} + parser.opt.lowercase = parser.opt.lowercase || parser.opt.lowercasetags + parser.looseCase = parser.opt.lowercase ? "toLowerCase" : "toUpperCase" + parser.tags = [] + parser.closed = parser.closedRoot = parser.sawRoot = false + parser.tag = parser.error = null + parser.strict = !!strict + parser.noscript = !!(strict || parser.opt.noscript) + parser.state = S.BEGIN + parser.ENTITIES = Object.create(sax.ENTITIES) + parser.attribList = [] + + // namespaces form a prototype chain. + // it always points at the current tag, + // which protos to its parent tag. + if (parser.opt.xmlns) parser.ns = Object.create(rootNS) + + // mostly just for error reporting + parser.trackPosition = parser.opt.position !== false + if (parser.trackPosition) { + parser.position = parser.line = parser.column = 0 + } + emit(parser, "onready") + } + + if (!Object.create) Object.create = function (o) { + function f () { this.__proto__ = o } + f.prototype = o + return new f + } + + if (!Object.getPrototypeOf) Object.getPrototypeOf = function (o) { + return o.__proto__ + } + + if (!Object.keys) Object.keys = function (o) { + var a = [] + for (var i in o) if (o.hasOwnProperty(i)) a.push(i) + return a + } + + function checkBufferLength (parser) { + var maxAllowed = Math.max(sax.MAX_BUFFER_LENGTH, 10) + , maxActual = 0 + for (var i = 0, l = buffers.length; i < l; i ++) { + var len = parser[buffers[i]].length + if (len > maxAllowed) { + // Text/cdata nodes can get big, and since they're buffered, + // we can get here under normal conditions. + // Avoid issues by emitting the text node now, + // so at least it won't get any bigger. + switch (buffers[i]) { + case "textNode": + closeText(parser) + break + + case "cdata": + emitNode(parser, "oncdata", parser.cdata) + parser.cdata = "" + break + + case "script": + emitNode(parser, "onscript", parser.script) + parser.script = "" + break + + default: + error(parser, "Max buffer length exceeded: "+buffers[i]) + } + } + maxActual = Math.max(maxActual, len) + } + // schedule the next check for the earliest possible buffer overrun. + parser.bufferCheckPosition = (sax.MAX_BUFFER_LENGTH - maxActual) + + parser.position + } + + function clearBuffers (parser) { + for (var i = 0, l = buffers.length; i < l; i ++) { + parser[buffers[i]] = "" + } + } + + function flushBuffers (parser) { + closeText(parser) + if (parser.cdata !== "") { + emitNode(parser, "oncdata", parser.cdata) + parser.cdata = "" + } + if (parser.script !== "") { + emitNode(parser, "onscript", parser.script) + parser.script = "" + } + } + + SAXParser.prototype = + { end: function () { end(this) } + , write: write + , resume: function () { this.error = null; return this } + , close: function () { return this.write(null) } + , flush: function () { flushBuffers(this) } + } + + try { + var Stream = require("stream").Stream + } catch (ex) { + var Stream = function () {} + } + + + var streamWraps = sax.EVENTS.filter(function (ev) { + return ev !== "error" && ev !== "end" + }) + + function createStream (strict, opt) { + return new SAXStream(strict, opt) + } + + function SAXStream (strict, opt) { + if (!(this instanceof SAXStream)) return new SAXStream(strict, opt) + + Stream.apply(this) + + this._parser = new SAXParser(strict, opt) + this.writable = true + this.readable = true + + + var me = this + + this._parser.onend = function () { + me.emit("end") + } + + this._parser.onerror = function (er) { + me.emit("error", er) + + // if didn't throw, then means error was handled. + // go ahead and clear error, so we can write again. + me._parser.error = null + } + + this._decoder = null; + + streamWraps.forEach(function (ev) { + Object.defineProperty(me, "on" + ev, { + get: function () { return me._parser["on" + ev] }, + set: function (h) { + if (!h) { + me.removeAllListeners(ev) + return me._parser["on"+ev] = h + } + me.on(ev, h) + }, + enumerable: true, + configurable: false + }) + }) + } + + SAXStream.prototype = Object.create(Stream.prototype, + { constructor: { value: SAXStream } }) + + SAXStream.prototype.write = function (data) { + if (typeof Buffer === 'function' && + typeof Buffer.isBuffer === 'function' && + Buffer.isBuffer(data)) { + if (!this._decoder) { + var SD = require('string_decoder').StringDecoder + this._decoder = new SD('utf8') + } + data = this._decoder.write(data); + } + + this._parser.write(data.toString()) + this.emit("data", data) + return true + } + + SAXStream.prototype.end = function (chunk) { + if (chunk && chunk.length) this.write(chunk) + this._parser.end() + return true + } + + SAXStream.prototype.on = function (ev, handler) { + var me = this + if (!me._parser["on"+ev] && streamWraps.indexOf(ev) !== -1) { + me._parser["on"+ev] = function () { + var args = arguments.length === 1 ? [arguments[0]] + : Array.apply(null, arguments) + args.splice(0, 0, ev) + me.emit.apply(me, args) + } + } + + return Stream.prototype.on.call(me, ev, handler) + } + + + + // character classes and tokens + var whitespace = "\r\n\t " + // this really needs to be replaced with character classes. + // XML allows all manner of ridiculous numbers and digits. + , number = "0124356789" + , letter = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + // (Letter | "_" | ":") + , quote = "'\"" + , entity = number+letter+"#" + , attribEnd = whitespace + ">" + , CDATA = "[CDATA[" + , DOCTYPE = "DOCTYPE" + , XML_NAMESPACE = "http://www.w3.org/XML/1998/namespace" + , XMLNS_NAMESPACE = "http://www.w3.org/2000/xmlns/" + , rootNS = { xml: XML_NAMESPACE, xmlns: XMLNS_NAMESPACE } + + // turn all the string character sets into character class objects. + whitespace = charClass(whitespace) + number = charClass(number) + letter = charClass(letter) + + // http://www.w3.org/TR/REC-xml/#NT-NameStartChar + // This implementation works on strings, a single character at a time + // as such, it cannot ever support astral-plane characters (10000-EFFFF) + // without a significant breaking change to either this parser, or the + // JavaScript language. Implementation of an emoji-capable xml parser + // is left as an exercise for the reader. + var nameStart = /[:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]/ + + var nameBody = /[:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\u00B7\u0300-\u036F\u203F-\u2040\.\d-]/ + + quote = charClass(quote) + entity = charClass(entity) + attribEnd = charClass(attribEnd) + + function charClass (str) { + return str.split("").reduce(function (s, c) { + s[c] = true + return s + }, {}) + } + + function isRegExp (c) { + return Object.prototype.toString.call(c) === '[object RegExp]' + } + + function is (charclass, c) { + return isRegExp(charclass) ? !!c.match(charclass) : charclass[c] + } + + function not (charclass, c) { + return !is(charclass, c) + } + + var S = 0 + sax.STATE = + { BEGIN : S++ + , TEXT : S++ // general stuff + , TEXT_ENTITY : S++ // & and such. + , OPEN_WAKA : S++ // < + , SGML_DECL : S++ // + , SCRIPT : S++ //