基础版本
diff --git a/platforms/browser/browser.json b/platforms/browser/browser.json
new file mode 100644
index 0000000..8ae268b
--- /dev/null
+++ b/platforms/browser/browser.json
@@ -0,0 +1,449 @@
+{
+ "prepare_queue": {
+ "installed": [],
+ "uninstalled": []
+ },
+ "config_munge": {
+ "files": {
+ "config.xml": {
+ "parents": {
+ "/*": [
+ {
+ "xml": "<feature name=\"CordovaHttpPlugin\"><param name=\"browser-package\" value=\"CordovaHttpPlugin\" /></feature>",
+ "count": 1
+ },
+ {
+ "xml": "<feature name=\"QRScanner\"><param name=\"browser-package\" value=\"QRScanner\" /></feature>",
+ "count": 1
+ },
+ {
+ "xml": "<feature name=\"Camera\"><param name=\"browser-package\" value=\"Camera\" /></feature>",
+ "count": 1
+ },
+ {
+ "xml": "<feature name=\"Device\"><param name=\"browser-package\" value=\"Device\" /></feature>",
+ "count": 1
+ }
+ ]
+ }
+ },
+ "*-Info.plist": {
+ "parents": {
+ "NSCameraUsageDescription": [
+ {
+ "xml": "<string>APP需要使用您的相机权限,没有该权限将无法完成扫一扫功能</string>",
+ "count": 1,
+ "mode": "merge",
+ "id": "config.xml"
+ }
+ ]
+ }
+ }
+ }
+ },
+ "installed_plugins": {
+ "cordova-plugin-add-swift-support": {
+ "PACKAGE_NAME": "com.supwisdom.dlapp"
+ },
+ "cordova-plugin-fingerprint-aio": {
+ "PACKAGE_NAME": "com.supwisdom.dlapp"
+ },
+ "cordova-plugin-touch-id": {
+ "PACKAGE_NAME": "com.supwisdom.dlapp"
+ },
+ "cordova-plugin-whitelist": {
+ "PACKAGE_NAME": "com.supwisdom.dlapp"
+ },
+ "cordova-plugin-file": {
+ "PACKAGE_NAME": "com.supwisdom.dlapp"
+ },
+ "cordova-plugin-advanced-http": {
+ "PACKAGE_NAME": "com.supwisdom.dlapp"
+ },
+ "cordova-plugin-statusbar": {
+ "PACKAGE_NAME": "com.supwisdom.dlapp"
+ },
+ "cordova-plugin-disable-ios11-statusbar": {
+ "PACKAGE_NAME": "com.supwisdom.dlapp"
+ },
+ "cordova-plugin-qrscanner": {
+ "PACKAGE_NAME": "com.supwisdom.dlapp"
+ },
+ "cordova-plugin-camera": {
+ "PACKAGE_NAME": "com.supwisdom.dlapp"
+ },
+ "cordova-plugin-inappbrowser": {
+ "PACKAGE_NAME": "com.supwisdom.dlapp"
+ },
+ "cordova-plugin-device": {
+ "PACKAGE_NAME": "com.supwisdom.dlapp"
+ },
+ "cordova-plugin-themeablebrowser": {
+ "PACKAGE_NAME": "com.supwisdom.dlapp"
+ }
+ },
+ "dependent_plugins": {},
+ "modules": [
+ {
+ "file": "plugins/cordova-plugin-fingerprint-aio/www/Fingerprint.js",
+ "id": "cordova-plugin-fingerprint-aio.Fingerprint",
+ "pluginId": "cordova-plugin-fingerprint-aio",
+ "clobbers": [
+ "Fingerprint"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-touch-id/www/TouchID.js",
+ "id": "cordova-plugin-touch-id.TouchID",
+ "pluginId": "cordova-plugin-touch-id",
+ "clobbers": [
+ "window.plugins.touchid"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-file/www/DirectoryEntry.js",
+ "id": "cordova-plugin-file.DirectoryEntry",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.DirectoryEntry"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-file/www/DirectoryReader.js",
+ "id": "cordova-plugin-file.DirectoryReader",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.DirectoryReader"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-file/www/Entry.js",
+ "id": "cordova-plugin-file.Entry",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.Entry"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-file/www/File.js",
+ "id": "cordova-plugin-file.File",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.File"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-file/www/FileEntry.js",
+ "id": "cordova-plugin-file.FileEntry",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.FileEntry"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-file/www/FileError.js",
+ "id": "cordova-plugin-file.FileError",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.FileError"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-file/www/FileReader.js",
+ "id": "cordova-plugin-file.FileReader",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.FileReader"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-file/www/FileSystem.js",
+ "id": "cordova-plugin-file.FileSystem",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.FileSystem"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-file/www/FileUploadOptions.js",
+ "id": "cordova-plugin-file.FileUploadOptions",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.FileUploadOptions"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-file/www/FileUploadResult.js",
+ "id": "cordova-plugin-file.FileUploadResult",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.FileUploadResult"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-file/www/FileWriter.js",
+ "id": "cordova-plugin-file.FileWriter",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.FileWriter"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-file/www/Flags.js",
+ "id": "cordova-plugin-file.Flags",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.Flags"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-file/www/LocalFileSystem.js",
+ "id": "cordova-plugin-file.LocalFileSystem",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.LocalFileSystem"
+ ],
+ "merges": [
+ "window"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-file/www/Metadata.js",
+ "id": "cordova-plugin-file.Metadata",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.Metadata"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-file/www/ProgressEvent.js",
+ "id": "cordova-plugin-file.ProgressEvent",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.ProgressEvent"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-file/www/fileSystems.js",
+ "id": "cordova-plugin-file.fileSystems",
+ "pluginId": "cordova-plugin-file"
+ },
+ {
+ "file": "plugins/cordova-plugin-file/www/requestFileSystem.js",
+ "id": "cordova-plugin-file.requestFileSystem",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.requestFileSystem"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-file/www/resolveLocalFileSystemURI.js",
+ "id": "cordova-plugin-file.resolveLocalFileSystemURI",
+ "pluginId": "cordova-plugin-file",
+ "merges": [
+ "window"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-file/www/browser/isChrome.js",
+ "id": "cordova-plugin-file.isChrome",
+ "pluginId": "cordova-plugin-file",
+ "runs": true
+ },
+ {
+ "file": "plugins/cordova-plugin-file/www/browser/Preparing.js",
+ "id": "cordova-plugin-file.Preparing",
+ "pluginId": "cordova-plugin-file",
+ "runs": true
+ },
+ {
+ "file": "plugins/cordova-plugin-file/src/browser/FileProxy.js",
+ "id": "cordova-plugin-file.browserFileProxy",
+ "pluginId": "cordova-plugin-file",
+ "runs": true
+ },
+ {
+ "file": "plugins/cordova-plugin-file/www/fileSystemPaths.js",
+ "id": "cordova-plugin-file.fileSystemPaths",
+ "pluginId": "cordova-plugin-file",
+ "merges": [
+ "cordova"
+ ],
+ "runs": true
+ },
+ {
+ "file": "plugins/cordova-plugin-file/www/browser/FileSystem.js",
+ "id": "cordova-plugin-file.firefoxFileSystem",
+ "pluginId": "cordova-plugin-file",
+ "merges": [
+ "window.FileSystem"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-advanced-http/www/cookie-handler.js",
+ "id": "cordova-plugin-advanced-http.cookie-handler",
+ "pluginId": "cordova-plugin-advanced-http"
+ },
+ {
+ "file": "plugins/cordova-plugin-advanced-http/www/global-configs.js",
+ "id": "cordova-plugin-advanced-http.global-configs",
+ "pluginId": "cordova-plugin-advanced-http"
+ },
+ {
+ "file": "plugins/cordova-plugin-advanced-http/www/helpers.js",
+ "id": "cordova-plugin-advanced-http.helpers",
+ "pluginId": "cordova-plugin-advanced-http"
+ },
+ {
+ "file": "plugins/cordova-plugin-advanced-http/www/js-util.js",
+ "id": "cordova-plugin-advanced-http.js-util",
+ "pluginId": "cordova-plugin-advanced-http"
+ },
+ {
+ "file": "plugins/cordova-plugin-advanced-http/www/local-storage-store.js",
+ "id": "cordova-plugin-advanced-http.local-storage-store",
+ "pluginId": "cordova-plugin-advanced-http"
+ },
+ {
+ "file": "plugins/cordova-plugin-advanced-http/www/lodash.js",
+ "id": "cordova-plugin-advanced-http.lodash",
+ "pluginId": "cordova-plugin-advanced-http"
+ },
+ {
+ "file": "plugins/cordova-plugin-advanced-http/www/messages.js",
+ "id": "cordova-plugin-advanced-http.messages",
+ "pluginId": "cordova-plugin-advanced-http"
+ },
+ {
+ "file": "plugins/cordova-plugin-advanced-http/www/public-interface.js",
+ "id": "cordova-plugin-advanced-http.public-interface",
+ "pluginId": "cordova-plugin-advanced-http"
+ },
+ {
+ "file": "plugins/cordova-plugin-advanced-http/www/umd-tough-cookie.js",
+ "id": "cordova-plugin-advanced-http.tough-cookie",
+ "pluginId": "cordova-plugin-advanced-http"
+ },
+ {
+ "file": "plugins/cordova-plugin-advanced-http/www/url-util.js",
+ "id": "cordova-plugin-advanced-http.url-util",
+ "pluginId": "cordova-plugin-advanced-http"
+ },
+ {
+ "file": "plugins/cordova-plugin-advanced-http/www/advanced-http.js",
+ "id": "cordova-plugin-advanced-http.http",
+ "pluginId": "cordova-plugin-advanced-http",
+ "clobbers": [
+ "cordova.plugin.http"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-advanced-http/src/browser/cordova-http-plugin.js",
+ "id": "cordova-plugin-advanced-http.http-proxy",
+ "pluginId": "cordova-plugin-advanced-http",
+ "runs": true
+ },
+ {
+ "file": "plugins/cordova-plugin-statusbar/www/statusbar.js",
+ "id": "cordova-plugin-statusbar.statusbar",
+ "pluginId": "cordova-plugin-statusbar",
+ "clobbers": [
+ "window.StatusBar"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-statusbar/src/browser/StatusBarProxy.js",
+ "id": "cordova-plugin-statusbar.StatusBarProxy",
+ "pluginId": "cordova-plugin-statusbar",
+ "runs": true
+ },
+ {
+ "file": "plugins/cordova-plugin-qrscanner/www/www.min.js",
+ "id": "cordova-plugin-qrscanner.QRScanner",
+ "pluginId": "cordova-plugin-qrscanner",
+ "clobbers": [
+ "QRScanner"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-qrscanner/src/browser/plugin.min.js",
+ "id": "cordova-plugin-qrscanner.QRScannerProxy",
+ "pluginId": "cordova-plugin-qrscanner",
+ "runs": true
+ },
+ {
+ "file": "plugins/cordova-plugin-camera/www/CameraConstants.js",
+ "id": "cordova-plugin-camera.Camera",
+ "pluginId": "cordova-plugin-camera",
+ "clobbers": [
+ "Camera"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-camera/www/CameraPopoverOptions.js",
+ "id": "cordova-plugin-camera.CameraPopoverOptions",
+ "pluginId": "cordova-plugin-camera",
+ "clobbers": [
+ "CameraPopoverOptions"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-camera/www/Camera.js",
+ "id": "cordova-plugin-camera.camera",
+ "pluginId": "cordova-plugin-camera",
+ "clobbers": [
+ "navigator.camera"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-camera/src/browser/CameraProxy.js",
+ "id": "cordova-plugin-camera.CameraProxy",
+ "pluginId": "cordova-plugin-camera",
+ "runs": true
+ },
+ {
+ "file": "plugins/cordova-plugin-inappbrowser/www/inappbrowser.js",
+ "id": "cordova-plugin-inappbrowser.inappbrowser",
+ "pluginId": "cordova-plugin-inappbrowser",
+ "clobbers": [
+ "cordova.InAppBrowser.open",
+ "window.open"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-inappbrowser/src/browser/InAppBrowserProxy.js",
+ "id": "cordova-plugin-inappbrowser.InAppBrowserProxy",
+ "pluginId": "cordova-plugin-inappbrowser",
+ "runs": true
+ },
+ {
+ "file": "plugins/cordova-plugin-device/www/device.js",
+ "id": "cordova-plugin-device.device",
+ "pluginId": "cordova-plugin-device",
+ "clobbers": [
+ "device"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-device/src/browser/DeviceProxy.js",
+ "id": "cordova-plugin-device.DeviceProxy",
+ "pluginId": "cordova-plugin-device",
+ "runs": true
+ }
+ ],
+ "plugin_metadata": {
+ "cordova-plugin-add-swift-support": "2.0.2",
+ "cordova-plugin-fingerprint-aio": "1.7.0",
+ "cordova-plugin-touch-id": "3.3.1",
+ "cordova-plugin-whitelist": "1.3.3",
+ "cordova-plugin-file": "6.0.1",
+ "cordova-plugin-advanced-http": "2.1.1",
+ "cordova-plugin-statusbar": "2.4.2",
+ "cordova-plugin-disable-ios11-statusbar": "1.0.0",
+ "cordova-plugin-qrscanner": "3.0.1",
+ "cordova-plugin-camera": "4.0.3",
+ "cordova-plugin-inappbrowser": "3.0.0",
+ "cordova-plugin-device": "2.0.2",
+ "cordova-plugin-themeablebrowser": "0.2.17"
+ }
+}
diff --git a/platforms/browser/config.xml b/platforms/browser/config.xml
new file mode 100644
index 0000000..a7be4bc
--- /dev/null
+++ b/platforms/browser/config.xml
@@ -0,0 +1,33 @@
+<?xml version='1.0' encoding='utf-8'?>
+<widget id="com.supwisdom.dlapp" version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
+ <name>dlapp</name>
+ <description>
+ A sample Apache Cordova application that responds to the deviceready event.
+ </description>
+ <author email="dev@cordova.apache.org" href="http://cordova.io">
+ Apache Cordova Team
+ </author>
+ <content src="index.html" />
+ <access origin="*" />
+ <allow-intent href="http://*/*" />
+ <allow-intent href="https://*/*" />
+ <allow-intent href="tel:*" />
+ <allow-intent href="sms:*" />
+ <allow-intent href="mailto:*" />
+ <allow-intent href="geo:*" />
+ <allow-navigation href="http://*/*" />
+ <allow-navigation href="https://*/*" />
+ <allow-navigation href="data:*" />
+ <access origin="http://ip*" />
+ <edit-config file="*-Info.plist" mode="merge" target="NSCameraUsageDescription">
+ <string>APP需要使用您的相机权限,没有该权限将无法完成扫一扫功能</string>
+ </edit-config>
+ <preference name="AutoHideSplashScreen" value="true" />
+ <preference name="SplashScreenDelay" value="0" />
+ <preference name="ErrorUrl" value="error.html" />
+ <preference name="Orientation" value="portrait" />
+ <preference name="UseSwiftLanguageVersion" value="4.0" />
+ <preference name="DisallowOverscroll" value="true" />
+ <preference name="UIWebViewBounce" value="false" />
+ <preference name="BackupWebStorage" value="local" />
+</widget>
diff --git a/platforms/browser/cordova/Api.js b/platforms/browser/cordova/Api.js
new file mode 100644
index 0000000..da0ec8a
--- /dev/null
+++ b/platforms/browser/cordova/Api.js
@@ -0,0 +1,531 @@
+/**
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+'License'); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+/*
+ this file is found by cordova-lib when you attempt to
+ 'cordova platform add PATH' where path is this repo.
+*/
+
+var shell = require('shelljs');
+var path = require('path');
+var fs = require('fs');
+
+var cdvcmn = require('cordova-common');
+var CordovaLogger = cdvcmn.CordovaLogger;
+var ConfigParser = cdvcmn.ConfigParser;
+var ActionStack = cdvcmn.ActionStack;
+var selfEvents = cdvcmn.events;
+var xmlHelpers = cdvcmn.xmlHelpers;
+var PlatformJson = cdvcmn.PlatformJson;
+var PlatformMunger = cdvcmn.ConfigChanges.PlatformMunger;
+var PluginInfoProvider = cdvcmn.PluginInfoProvider;
+
+var BrowserParser = require('./browser_parser');
+var PLATFORM_NAME = 'browser';
+
+function setupEvents (externalEventEmitter) {
+ if (externalEventEmitter) {
+ // This will make the platform internal events visible outside
+ selfEvents.forwardEventsTo(externalEventEmitter);
+ return externalEventEmitter;
+ }
+
+ // There is no logger if external emitter is not present,
+ // so attach a console logger
+ CordovaLogger.get().subscribe(selfEvents);
+ return selfEvents;
+}
+
+function Api (platform, platformRootDir, events) {
+
+ this.platform = platform || PLATFORM_NAME;
+
+ // MyApp/platforms/browser
+ this.root = path.resolve(__dirname, '..');
+ this.events = setupEvents(events);
+ this.parser = new BrowserParser(this.root);
+ this._handler = require('./browser_handler');
+
+ this.locations = {
+ platformRootDir: platformRootDir,
+ root: this.root,
+ www: path.join(this.root, 'www'),
+ res: path.join(this.root, 'res'),
+ platformWww: path.join(this.root, 'platform_www'),
+ configXml: path.join(this.root, 'config.xml'),
+ defaultConfigXml: path.join(this.root, 'cordova/defaults.xml'),
+ build: path.join(this.root, 'build'),
+ // NOTE: Due to platformApi spec we need to return relative paths here
+ cordovaJs: 'bin/templates/project/assets/www/cordova.js',
+ cordovaJsSrc: 'cordova-js-src'
+ };
+
+ this._platformJson = PlatformJson.load(this.root, platform);
+ this._pluginInfoProvider = new PluginInfoProvider();
+ this._munger = new PlatformMunger(platform, this.root, this._platformJson, this._pluginInfoProvider);
+}
+
+Api.createPlatform = function (dest, config, options, events) {
+
+ var creator = require('../../lib/create');
+ events = setupEvents(events);
+
+ var name = 'HelloCordova';
+ var id = 'io.cordova.hellocordova';
+ if (config) {
+ name = config.name();
+ id = config.packageName();
+ }
+
+ var result;
+ try {
+ // we create the project using our scripts in this platform
+ result = creator.createProject(dest, id, name, options)
+ .then(function () {
+ // after platform is created we return Api instance based on new Api.js location
+ // Api.js has been copied to the new project
+ // This is required to correctly resolve paths in the future api calls
+ var PlatformApi = require(path.resolve(dest, 'cordova/Api'));
+ return new PlatformApi('browser', dest, events);
+ });
+ } catch (e) {
+ events.emit('error', 'createPlatform is not callable from the browser project API.');
+ throw (e);
+ }
+ return result;
+};
+
+Api.updatePlatform = function (dest, options, events) {
+ // console.log("test-platform:Api:updatePlatform");
+ // todo?: create projectInstance and fulfill promise with it.
+ return Promise.resolve();
+};
+
+Api.prototype.getPlatformInfo = function () {
+ // console.log("browser-platform:Api:getPlatformInfo");
+ // return PlatformInfo object
+ return {
+ 'locations': this.locations,
+ 'root': this.root,
+ 'name': this.platform,
+ 'version': { 'version': '1.0.0' }, // um, todo!
+ 'projectConfig': this.config
+ };
+};
+
+Api.prototype.prepare = function (cordovaProject, options) {
+
+ // First cleanup current config and merge project's one into own
+ var defaultConfigPath = path.join(this.locations.platformRootDir, 'cordova',
+ 'defaults.xml');
+ var ownConfigPath = this.locations.configXml;
+ var sourceCfg = cordovaProject.projectConfig;
+
+ // If defaults.xml is present, overwrite platform config.xml with it.
+ // Otherwise save whatever is there as defaults so it can be
+ // restored or copy project config into platform if none exists.
+ if (fs.existsSync(defaultConfigPath)) {
+ this.events.emit('verbose', 'Generating config.xml from defaults for platform "' + this.platform + '"');
+ shell.cp('-f', defaultConfigPath, ownConfigPath);
+ } else if (fs.existsSync(ownConfigPath)) {
+ this.events.emit('verbose', 'Generating defaults.xml from own config.xml for platform "' + this.platform + '"');
+ shell.cp('-f', ownConfigPath, defaultConfigPath);
+ } else {
+ this.events.emit('verbose', 'case 3"' + this.platform + '"');
+ shell.cp('-f', sourceCfg.path, ownConfigPath);
+ }
+
+ // merge our configs
+ this.config = new ConfigParser(ownConfigPath);
+ xmlHelpers.mergeXml(cordovaProject.projectConfig.doc.getroot(),
+ this.config.doc.getroot(),
+ this.platform, true);
+ this.config.write();
+
+ // Update own www dir with project's www assets and plugins' assets and js-files
+ this.parser.update_www(cordovaProject, options);
+
+ // Copy or Create manifest.json
+ // todo: move this to a manifest helper module
+ // output path
+ var manifestPath = path.join(this.locations.www, 'manifest.json');
+ var srcManifestPath = path.join(cordovaProject.locations.www, 'manifest.json');
+ if (fs.existsSync(srcManifestPath)) {
+ // just blindly copy it to our output/www
+ // todo: validate it? ensure all properties we expect exist?
+ this.events.emit('verbose', 'copying ' + srcManifestPath + ' => ' + manifestPath);
+ shell.cp('-f', srcManifestPath, manifestPath);
+ } else {
+ var manifestJson = {
+ 'background_color': '#FFF',
+ 'display': 'standalone'
+ };
+ if (this.config) {
+ if (this.config.name()) {
+ manifestJson.name = this.config.name();
+ }
+ if (this.config.shortName()) {
+ manifestJson.short_name = this.config.shortName();
+ }
+ if (this.config.packageName()) {
+ manifestJson.version = this.config.packageName();
+ }
+ if (this.config.description()) {
+ manifestJson.description = this.config.description();
+ }
+ if (this.config.author()) {
+ manifestJson.author = this.config.author();
+ }
+ // icons
+ var icons = this.config.getStaticResources('browser', 'icon');
+ var manifestIcons = icons.map(function (icon) {
+ // given a tag like this :
+ // <icon src="res/ios/icon.png" width="57" height="57" density="mdpi" />
+ /* configParser returns icons that look like this :
+ { src: 'res/ios/icon.png',
+ target: undefined,
+ density: 'mdpi',
+ platform: null,
+ width: 57,
+ height: 57
+ } ******/
+ /* manifest expects them to be like this :
+ { "src": "images/touch/icon-128x128.png",
+ "type": "image/png",
+ "sizes": "128x128"
+ } ******/
+ // ?Is it worth looking at file extentions?
+ return { 'src': icon.src,
+ 'type': 'image/png',
+ 'sizes': (icon.width + 'x' + icon.height) };
+ });
+ manifestJson.icons = manifestIcons;
+
+ // orientation
+ // <preference name="Orientation" value="landscape" />
+ var oriPref = this.config.getGlobalPreference('Orientation');
+ if (oriPref) {
+ // if it's a supported value, use it
+ if (['landscape', 'portrait'].indexOf(oriPref) > -1) {
+ manifestJson.orientation = oriPref;
+ } else { // anything else maps to 'any'
+ manifestJson.orientation = 'any';
+ }
+ }
+
+ // get start_url
+ var contentNode = this.config.doc.find('content') || { 'attrib': { 'src': 'index.html' } }; // sensible default
+ manifestJson.start_url = contentNode.attrib.src;
+
+ // now we get some values from start_url page ...
+ var startUrlPath = path.join(cordovaProject.locations.www, manifestJson.start_url);
+ if (fs.existsSync(startUrlPath)) {
+ var contents = fs.readFileSync(startUrlPath, 'utf-8');
+ // matches <meta name="theme-color" content="#FF0044">
+ var themeColorRegex = /<meta(?=[^>]*name="theme-color")\s[^>]*content="([^>]*)"/i;
+ var result = themeColorRegex.exec(contents);
+ var themeColor;
+ if (result && result.length >= 2) {
+ themeColor = result[1];
+ } else { // see if there is a preference in config.xml
+ // <preference name="StatusBarBackgroundColor" value="#000000" />
+ themeColor = this.config.getGlobalPreference('StatusBarBackgroundColor');
+ }
+ if (themeColor) {
+ manifestJson.theme_color = themeColor;
+ }
+ }
+ }
+ fs.writeFileSync(manifestPath, JSON.stringify(manifestJson, null, 2), 'utf8');
+ }
+
+ // update project according to config.xml changes.
+ return this.parser.update_project(this.config, options);
+};
+
+Api.prototype.addPlugin = function (pluginInfo, installOptions) {
+
+ // console.log(new Error().stack);
+ if (!pluginInfo) {
+ return Promise.reject(new Error('The parameter is incorrect. The first parameter ' +
+ 'should be valid PluginInfo instance'));
+ }
+
+ installOptions = installOptions || {};
+ installOptions.variables = installOptions.variables || {};
+ // CB-10108 platformVersion option is required for proper plugin installation
+ installOptions.platformVersion = installOptions.platformVersion ||
+ this.getPlatformInfo().version;
+
+ var self = this;
+ var actions = new ActionStack();
+ var projectFile = this._handler.parseProjectFile && this._handler.parseProjectFile(this.root);
+
+ // gather all files needs to be handled during install
+ pluginInfo.getFilesAndFrameworks(this.platform)
+ .concat(pluginInfo.getAssets(this.platform))
+ .concat(pluginInfo.getJsModules(this.platform))
+ .forEach(function (item) {
+ actions.push(actions.createAction(
+ self._getInstaller(item.itemType),
+ [item, pluginInfo.dir, pluginInfo.id, installOptions, projectFile],
+ self._getUninstaller(item.itemType),
+ [item, pluginInfo.dir, pluginInfo.id, installOptions, projectFile]));
+ });
+
+ // run through the action stack
+ return actions.process(this.platform, this.root)
+ .then(function () {
+ if (projectFile) {
+ projectFile.write();
+ }
+
+ // Add PACKAGE_NAME variable into vars
+ if (!installOptions.variables.PACKAGE_NAME) {
+ installOptions.variables.PACKAGE_NAME = self._handler.package_name(self.root);
+ }
+
+ self._munger
+ // Ignore passed `is_top_level` option since platform itself doesn't know
+ // anything about managing dependencies - it's responsibility of caller.
+ .add_plugin_changes(pluginInfo, installOptions.variables, /* is_top_level= */true, /* should_increment= */true)
+ .save_all();
+
+ var targetDir = installOptions.usePlatformWww ?
+ self.getPlatformInfo().locations.platformWww :
+ self.getPlatformInfo().locations.www;
+
+ self._addModulesInfo(pluginInfo, targetDir);
+ });
+};
+
+Api.prototype.removePlugin = function (plugin, uninstallOptions) {
+ // console.log("NotImplemented :: browser-platform:Api:removePlugin ",plugin, uninstallOptions);
+
+ uninstallOptions = uninstallOptions || {};
+ // CB-10108 platformVersion option is required for proper plugin installation
+ uninstallOptions.platformVersion = uninstallOptions.platformVersion ||
+ this.getPlatformInfo().version;
+
+ var self = this;
+ var actions = new ActionStack();
+ var projectFile = this._handler.parseProjectFile && this._handler.parseProjectFile(this.root);
+
+ // queue up plugin files
+ plugin.getFilesAndFrameworks(this.platform)
+ .concat(plugin.getAssets(this.platform))
+ .concat(plugin.getJsModules(this.platform))
+ .forEach(function (item) {
+ actions.push(actions.createAction(
+ self._getUninstaller(item.itemType), [item, plugin.dir, plugin.id, uninstallOptions, projectFile],
+ self._getInstaller(item.itemType), [item, plugin.dir, plugin.id, uninstallOptions, projectFile]));
+ });
+
+ // run through the action stack
+ return actions.process(this.platform, this.root)
+ .then(function () {
+ if (projectFile) {
+ projectFile.write();
+ }
+
+ self._munger
+ // Ignore passed `is_top_level` option since platform itself doesn't know
+ // anything about managing dependencies - it's responsibility of caller.
+ .remove_plugin_changes(plugin, /* is_top_level= */true)
+ .save_all();
+
+ var targetDir = uninstallOptions.usePlatformWww ?
+ self.getPlatformInfo().locations.platformWww :
+ self.getPlatformInfo().locations.www;
+
+ self._removeModulesInfo(plugin, targetDir);
+ // Remove stale plugin directory
+ // TODO: this should be done by plugin files uninstaller
+ shell.rm('-rf', path.resolve(self.root, 'Plugins', plugin.id));
+ });
+};
+
+Api.prototype._getInstaller = function (type) {
+ var self = this;
+ return function (item, plugin_dir, plugin_id, options, project) {
+ var installer = self._handler[type];
+
+ if (!installer) {
+ console.log('unrecognized type ' + type);
+
+ } else {
+ var wwwDest = options.usePlatformWww ?
+ self.getPlatformInfo().locations.platformWww :
+ self._handler.www_dir(self.root);
+
+ if (type === 'asset') {
+ installer.install(item, plugin_dir, wwwDest);
+ } else if (type === 'js-module') {
+ installer.install(item, plugin_dir, plugin_id, wwwDest);
+ } else {
+ installer.install(item, plugin_dir, self.root, plugin_id, options, project);
+ }
+ }
+ };
+};
+
+Api.prototype._getUninstaller = function (type) {
+ var self = this;
+ return function (item, plugin_dir, plugin_id, options, project) {
+ var installer = self._handler[type];
+
+ if (!installer) {
+ console.log('browser plugin uninstall: unrecognized type, skipping : ' + type);
+
+ } else {
+ var wwwDest = options.usePlatformWww ?
+ self.getPlatformInfo().locations.platformWww :
+ self._handler.www_dir(self.root);
+
+ if (['asset', 'js-module'].indexOf(type) > -1) {
+ return installer.uninstall(item, wwwDest, plugin_id);
+ } else {
+ return installer.uninstall(item, self.root, plugin_id, options, project);
+ }
+
+ }
+ };
+};
+
+/**
+ * Removes the specified modules from list of installed modules and updates
+ * platform_json and cordova_plugins.js on disk.
+ *
+ * @param {PluginInfo} plugin PluginInfo instance for plugin, which modules
+ * needs to be added.
+ * @param {String} targetDir The directory, where updated cordova_plugins.js
+ * should be written to.
+ */
+Api.prototype._addModulesInfo = function (plugin, targetDir) {
+ var installedModules = this._platformJson.root.modules || [];
+
+ var installedPaths = installedModules.map(function (installedModule) {
+ return installedModule.file;
+ });
+
+ var modulesToInstall = plugin.getJsModules(this.platform)
+ .filter(function (moduleToInstall) {
+ return installedPaths.indexOf(moduleToInstall.file) === -1;
+ }).map(function (moduleToInstall) {
+ var moduleName = plugin.id + '.' + (moduleToInstall.name || moduleToInstall.src.match(/([^\/]+)\.js/)[1]);
+ var obj = {
+ file: ['plugins', plugin.id, moduleToInstall.src].join('/'), /* eslint no-useless-escape : 0 */
+ id: moduleName,
+ pluginId: plugin.id
+ };
+ if (moduleToInstall.clobbers.length > 0) {
+ obj.clobbers = moduleToInstall.clobbers.map(function (o) { return o.target; });
+ }
+ if (moduleToInstall.merges.length > 0) {
+ obj.merges = moduleToInstall.merges.map(function (o) { return o.target; });
+ }
+ if (moduleToInstall.runs) {
+ obj.runs = true;
+ }
+
+ return obj;
+ });
+
+ this._platformJson.root.modules = installedModules.concat(modulesToInstall);
+ if (!this._platformJson.root.plugin_metadata) {
+ this._platformJson.root.plugin_metadata = {};
+ }
+ this._platformJson.root.plugin_metadata[plugin.id] = plugin.version;
+
+ this._writePluginModules(targetDir);
+ this._platformJson.save();
+};
+/**
+ * Fetches all installed modules, generates cordova_plugins contents and writes
+ * it to file.
+ *
+ * @param {String} targetDir Directory, where write cordova_plugins.js to.
+ * Ususally it is either <platform>/www or <platform>/platform_www
+ * directories.
+ */
+Api.prototype._writePluginModules = function (targetDir) {
+ // Write out moduleObjects as JSON wrapped in a cordova module to cordova_plugins.js
+ var final_contents = 'cordova.define(\'cordova/plugin_list\', function(require, exports, module) {\n';
+ final_contents += 'module.exports = ' + JSON.stringify(this._platformJson.root.modules, null, ' ') + ';\n';
+ final_contents += 'module.exports.metadata = \n';
+ final_contents += '// TOP OF METADATA\n';
+ final_contents += JSON.stringify(this._platformJson.root.plugin_metadata || {}, null, ' ') + '\n';
+ final_contents += '// BOTTOM OF METADATA\n';
+ final_contents += '});'; // Close cordova.define.
+
+ shell.mkdir('-p', targetDir);
+ fs.writeFileSync(path.join(targetDir, 'cordova_plugins.js'), final_contents, 'utf-8');
+};
+
+/**
+ * Removes the specified modules from list of installed modules and updates
+ * platform_json and cordova_plugins.js on disk.
+ *
+ * @param {PluginInfo} plugin PluginInfo instance for plugin, which modules
+ * needs to be removed.
+ * @param {String} targetDir The directory, where updated cordova_plugins.js
+ * should be written to.
+ */
+Api.prototype._removeModulesInfo = function (plugin, targetDir) {
+ var installedModules = this._platformJson.root.modules || [];
+ var modulesToRemove = plugin.getJsModules(this.platform)
+ .map(function (jsModule) {
+ return ['plugins', plugin.id, jsModule.src].join('/');
+ });
+
+ var updatedModules = installedModules
+ .filter(function (installedModule) {
+ return (modulesToRemove.indexOf(installedModule.file) === -1);
+ });
+
+ this._platformJson.root.modules = updatedModules;
+ if (this._platformJson.root.plugin_metadata) {
+ delete this._platformJson.root.plugin_metadata[plugin.id];
+ }
+
+ this._writePluginModules(targetDir);
+ this._platformJson.save();
+};
+
+Api.prototype.build = function (buildOptions) {
+ var self = this;
+ return require('./lib/check_reqs').run()
+ .then(function () {
+ return require('./lib/build').run.call(self, buildOptions);
+ });
+};
+
+Api.prototype.run = function (runOptions) {
+ return require('./lib/run').run(runOptions);
+};
+
+Api.prototype.clean = function (cleanOptions) {
+ return require('./lib/clean').run(cleanOptions);
+};
+
+Api.prototype.requirements = function () {
+ return require('./lib/check_reqs').run();
+};
+
+module.exports = Api;
diff --git a/platforms/browser/cordova/browser_handler.js b/platforms/browser/cordova/browser_handler.js
new file mode 100644
index 0000000..bccddb4
--- /dev/null
+++ b/platforms/browser/cordova/browser_handler.js
@@ -0,0 +1,135 @@
+/**
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+var path = require('path');
+var fs = require('fs');
+var shell = require('shelljs');
+var events = require('cordova-common').events;
+
+module.exports = {
+ www_dir: function (project_dir) {
+ return path.join(project_dir, 'www');
+ },
+ package_name: function (project_dir) {
+ // this method should the id from root config.xml => <widget id=xxx
+ // return common.package_name(project_dir, this.www_dir(project_dir));
+ // console.log('package_name called with ' + project_dir);
+ var pkgName = 'io.cordova.hellocordova';
+ var widget_id_regex = /(?:<widget\s+id=['"])(\S+)(?:['"])/;
+
+ var configPath = path.join(project_dir, 'config.xml');
+ if (fs.existsSync(configPath)) {
+ var configStr = fs.readFileSync(configPath, 'utf8');
+ var res = configStr.match(widget_id_regex);
+ if (res && res.length > 1) {
+ pkgName = res[1];
+ }
+ }
+ return pkgName;
+ },
+ 'js-module': {
+ install: function (jsModule, plugin_dir, plugin_id, www_dir) {
+ // Copy the plugin's files into the www directory.
+ var moduleSource = path.resolve(plugin_dir, jsModule.src);
+ // Get module name based on existing 'name' attribute or filename
+ // Must use path.extname/path.basename instead of path.parse due to CB-9981
+ var moduleName = plugin_id + '.' + (jsModule.name || path.basename(jsModule.src, path.extname(jsModule.src)));
+
+ // Read in the file, prepend the cordova.define, and write it back out.
+ var scriptContent = fs.readFileSync(moduleSource, 'utf-8').replace(/^\ufeff/, ''); // Window BOM
+ if (moduleSource.match(/.*\.json$/)) {
+ scriptContent = 'module.exports = ' + scriptContent;
+ }
+ scriptContent = 'cordova.define("' + moduleName + '", function(require, exports, module) { ' + scriptContent + '\n});\n';
+
+ var moduleDestination = path.resolve(www_dir, 'plugins', plugin_id, jsModule.src);
+ shell.mkdir('-p', path.dirname(moduleDestination));
+ fs.writeFileSync(moduleDestination, scriptContent, 'utf-8');
+ },
+ uninstall: function (jsModule, www_dir, plugin_id) {
+ var pluginRelativePath = path.join('plugins', plugin_id, jsModule.src);
+ // common.removeFileAndParents(www_dir, pluginRelativePath);
+ console.log('js-module uninstall called : ' + pluginRelativePath);
+ }
+ },
+ 'source-file': {
+ install: function (obj, plugin_dir, project_dir, plugin_id, options) {
+ // var dest = path.join(obj.targetDir, path.basename(obj.src));
+ // common.copyFile(plugin_dir, obj.src, project_dir, dest);
+ console.log('install called');
+ },
+ uninstall: function (obj, project_dir, plugin_id, options) {
+ // var dest = path.join(obj.targetDir, path.basename(obj.src));
+ // common.removeFile(project_dir, dest);
+ console.log('uninstall called');
+ }
+ },
+ 'header-file': {
+ install: function (obj, plugin_dir, project_dir, plugin_id, options) {
+ events.emit('verbose', 'header-fileinstall is not supported for browser');
+ },
+ uninstall: function (obj, project_dir, plugin_id, options) {
+ events.emit('verbose', 'header-file.uninstall is not supported for browser');
+ }
+ },
+ 'resource-file': {
+ install: function (obj, plugin_dir, project_dir, plugin_id, options) {
+ events.emit('verbose', 'resource-file.install is not supported for browser');
+ },
+ uninstall: function (obj, project_dir, plugin_id, options) {
+ events.emit('verbose', 'resource-file.uninstall is not supported for browser');
+ }
+ },
+ 'framework': {
+ install: function (obj, plugin_dir, project_dir, plugin_id, options) {
+ events.emit('verbose', 'framework.install is not supported for browser');
+ },
+ uninstall: function (obj, project_dir, plugin_id, options) {
+ events.emit('verbose', 'framework.uninstall is not supported for browser');
+ }
+ },
+ 'lib-file': {
+ install: function (obj, plugin_dir, project_dir, plugin_id, options) {
+ events.emit('verbose', 'lib-file.install is not supported for browser');
+ },
+ uninstall: function (obj, project_dir, plugin_id, options) {
+ events.emit('verbose', 'lib-file.uninstall is not supported for browser');
+ }
+ },
+ asset: {
+ install: function (asset, plugin_dir, wwwDest) {
+ var src = path.join(plugin_dir, asset.src);
+ var dest = path.join(wwwDest, asset.target);
+ var destDir = path.parse(dest).dir;
+ if (destDir !== '' && !fs.existsSync(destDir)) {
+ shell.mkdir('-p', destDir);
+ }
+
+ if (fs.statSync(src).isDirectory()) {
+ shell.cp('-Rf', src + '/*', dest);
+ } else {
+ shell.cp('-f', src, dest);
+ }
+ },
+ uninstall: function (asset, wwwDest, plugin_id) {
+ shell.rm('-rf', path.join(wwwDest, asset.target));
+ shell.rm('-rf', path.join(wwwDest, 'plugins', plugin_id));
+ }
+ }
+};
diff --git a/platforms/browser/cordova/browser_parser.js b/platforms/browser/cordova/browser_parser.js
new file mode 100644
index 0000000..99397c3
--- /dev/null
+++ b/platforms/browser/cordova/browser_parser.js
@@ -0,0 +1,120 @@
+/**
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+var fs = require('fs');
+var path = require('path');
+var shell = require('shelljs');
+var CordovaError = require('cordova-common').CordovaError;
+var events = require('cordova-common').events;
+var FileUpdater = require('cordova-common').FileUpdater;
+
+function dirExists (dir) {
+ return fs.existsSync(dir) && fs.statSync(dir).isDirectory();
+}
+
+function browser_parser (project) {
+ if (!dirExists(project) || !dirExists(path.join(project, 'cordova'))) {
+ throw new CordovaError('The provided path "' + project + '" is not a valid browser project.');
+ }
+ this.path = project;
+}
+
+module.exports = browser_parser;
+
+// Returns a promise.
+browser_parser.prototype.update_from_config = function () {
+ return Promise.resolve();
+};
+
+browser_parser.prototype.www_dir = function () {
+ return path.join(this.path, 'www');
+};
+
+// Used for creating platform_www in projects created by older versions.
+browser_parser.prototype.cordovajs_path = function (libDir) {
+ var jsPath = path.join(libDir, 'cordova-lib', 'cordova.js');
+ return path.resolve(jsPath);
+};
+
+browser_parser.prototype.cordovajs_src_path = function (libDir) {
+ // console.log("cordovajs_src_path");
+ var jsPath = path.join(libDir, 'cordova-js-src');
+ return path.resolve(jsPath);
+};
+
+/**
+ * Logs all file operations via the verbose event stream, indented.
+ */
+function logFileOp (message) {
+ events.emit('verbose', ' ' + message);
+}
+
+// Replace the www dir with contents of platform_www and app www.
+browser_parser.prototype.update_www = function (cordovaProject, opts) {
+ var platform_www = path.join(this.path, 'platform_www');
+ var my_www = this.www_dir();
+ // add cordova www and platform_www to sourceDirs
+ var sourceDirs = [
+ path.relative(cordovaProject.root, cordovaProject.locations.www),
+ path.relative(cordovaProject.root, platform_www)
+ ];
+
+ // If project contains 'merges' for our platform, use them as another overrides
+ var merges_path = path.join(cordovaProject.root, 'merges', 'browser');
+ if (fs.existsSync(merges_path)) {
+ events.emit('verbose', 'Found "merges/browser" folder. Copying its contents into the browser project.');
+ // add merges/browser to sourceDirs
+ sourceDirs.push(path.join('merges', 'browser'));
+ }
+
+ // targetDir points to browser/www
+ var targetDir = path.relative(cordovaProject.root, my_www);
+ events.emit('verbose', 'Merging and updating files from [' + sourceDirs.join(', ') + '] to ' + targetDir);
+ FileUpdater.mergeAndUpdateDir(sourceDirs, targetDir, { rootDir: cordovaProject.root }, logFileOp);
+};
+
+browser_parser.prototype.update_overrides = function () {
+ // console.log("update_overrides");
+
+ // TODO: ?
+ // var projectRoot = util.isCordova(this.path);
+ // var mergesPath = path.join(util.appDir(projectRoot), 'merges', 'browser');
+ // if(fs.existsSync(mergesPath)) {
+ // var overrides = path.join(mergesPath, '*');
+ // shell.cp('-rf', overrides, this.www_dir());
+ // }
+};
+
+browser_parser.prototype.config_xml = function () {
+ return path.join(this.path, 'config.xml');
+};
+
+// Returns a promise.
+browser_parser.prototype.update_project = function (cfg) {
+ // console.log("update_project ",cfg);
+ var defer = this.update_from_config();
+ var self = this;
+ var www_dir = self.www_dir();
+ defer.then(function () {
+ self.update_overrides();
+ // Copy munged config.xml to platform www dir
+ shell.cp('-rf', path.join(www_dir, '..', 'config.xml'), www_dir);
+ });
+ return defer;
+};
diff --git a/platforms/browser/cordova/build b/platforms/browser/cordova/build
new file mode 100755
index 0000000..e867ab1
--- /dev/null
+++ b/platforms/browser/cordova/build
@@ -0,0 +1,34 @@
+#!/usr/bin/env node
+
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+
+var build = require('./lib/build'),
+ args = process.argv;
+
+// provide help
+if ( args[2] == '--help' || args[2] == '/?' || args[2] == '-h' || args[2] == '/h' ||
+ args[2] == 'help' || args[2] == '-help' || args[2] == '/help') {
+ build.help();
+ process.exit(0);
+} else {
+
+ build.run();
+}
diff --git a/platforms/browser/cordova/build.bat b/platforms/browser/cordova/build.bat
new file mode 100644
index 0000000..02641bc
--- /dev/null
+++ b/platforms/browser/cordova/build.bat
@@ -0,0 +1,26 @@
+:: Licensed to the Apache Software Foundation (ASF) under one
+:: or more contributor license agreements. See the NOTICE file
+:: distributed with this work for additional information
+:: regarding copyright ownership. The ASF licenses this file
+:: to you under the Apache License, Version 2.0 (the
+:: "License"); you may not use this file except in compliance
+:: with the License. You may obtain a copy of the License at
+::
+:: http://www.apache.org/licenses/LICENSE-2.0
+::
+:: Unless required by applicable law or agreed to in writing,
+:: software distributed under the License is distributed on an
+:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+:: KIND, either express or implied. See the License for the
+:: specific language governing permissions and limitations
+:: under the License.
+
+@ECHO OFF
+SET script_path="%~dp0build"
+IF EXIST %script_path% (
+ node %script_path% %*
+) ELSE (
+ ECHO.
+ ECHO ERROR: Could not find 'build' script in 'cordova' folder, aborting...>&2
+ EXIT /B 1
+)
diff --git a/platforms/browser/cordova/clean b/platforms/browser/cordova/clean
new file mode 100644
index 0000000..1852d66
--- /dev/null
+++ b/platforms/browser/cordova/clean
@@ -0,0 +1,36 @@
+#!/usr/bin/env node
+
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+
+var path = require('path'),
+ clean = require('./lib/clean'),
+ args = process.argv;
+
+// Support basic help commands
+if ( args.length > 2
+ || args[2] == '--help' || args[2] == '/?' || args[2] == '-h' ||
+ args[2] == 'help' || args[2] == '-help' || args[2] == '/help') {
+ console.log('Usage: ' + path.relative(process.cwd(), path.join(__dirname, 'clean')) );
+ process.exit(0);
+} else {
+ clean.run();
+}
+
diff --git a/platforms/browser/cordova/clean.bat b/platforms/browser/cordova/clean.bat
new file mode 100644
index 0000000..5c572aa
--- /dev/null
+++ b/platforms/browser/cordova/clean.bat
@@ -0,0 +1,26 @@
+:: Licensed to the Apache Software Foundation (ASF) under one
+:: or more contributor license agreements. See the NOTICE file
+:: distributed with this work for additional information
+:: regarding copyright ownership. The ASF licenses this file
+:: to you under the Apache License, Version 2.0 (the
+:: "License"); you may not use this file except in compliance
+:: with the License. You may obtain a copy of the License at
+::
+:: http://www.apache.org/licenses/LICENSE-2.0
+::
+:: Unless required by applicable law or agreed to in writing,
+:: software distributed under the License is distributed on an
+:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+:: KIND, either express or implied. See the License for the
+:: specific language governing permissions and limitations
+:: under the License.
+
+@ECHO OFF
+SET script_path="%~dp0clean"
+IF EXIST %script_path% (
+ node %script_path% %*
+) ELSE (
+ ECHO.
+ ECHO ERROR: Could not find 'clean' script in 'cordova' folder, aborting...>&2
+ EXIT /B 1
+)
diff --git a/platforms/browser/cordova/defaults.xml b/platforms/browser/cordova/defaults.xml
new file mode 100644
index 0000000..a7b31c0
--- /dev/null
+++ b/platforms/browser/cordova/defaults.xml
@@ -0,0 +1,22 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<widget id="io.cordova.hellocordova" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
+
+</widget>
diff --git a/platforms/browser/cordova/lib/build.js b/platforms/browser/cordova/lib/build.js
new file mode 100644
index 0000000..01f3fb1
--- /dev/null
+++ b/platforms/browser/cordova/lib/build.js
@@ -0,0 +1,37 @@
+#!/usr/bin/env node
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+var path = require('path');
+var check_reqs = require('./check_reqs');
+
+/**
+ * run
+ * Creates a zip file int platform/build folder
+ */
+module.exports.run = function () {
+ return check_reqs.run();
+};
+
+module.exports.help = function () {
+ console.log('Usage: cordova build browser');
+ var wwwPath = path.resolve(path.join(__dirname, '../../www'));
+ console.log("Build will create the packaged app in '" + wwwPath + "'.");
+};
diff --git a/platforms/browser/cordova/lib/check_reqs.js b/platforms/browser/cordova/lib/check_reqs.js
new file mode 100644
index 0000000..c615e14
--- /dev/null
+++ b/platforms/browser/cordova/lib/check_reqs.js
@@ -0,0 +1,27 @@
+#!/usr/bin/env node
+
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+// add methods as we determine what are the requirements
+
+module.exports.run = function () {
+ // caller expects a promise resolved with an array of conditions
+ return Promise.resolve([]);
+};
diff --git a/platforms/browser/cordova/lib/clean.js b/platforms/browser/cordova/lib/clean.js
new file mode 100644
index 0000000..6ee7675
--- /dev/null
+++ b/platforms/browser/cordova/lib/clean.js
@@ -0,0 +1,51 @@
+#!/usr/bin/env node
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+var fs = require('fs');
+var shell = require('shelljs');
+var path = require('path');
+var check_reqs = require('./check_reqs');
+var platformBuildDir = path.join('platforms', 'browser', 'www');
+
+var run = function () {
+
+ // TODO: everything calls check_reqs ... why?
+ // Check that requirements are (still) met
+ if (!check_reqs.run()) {
+ console.error('Please make sure you meet the software requirements in order to clean an browser cordova project');
+ process.exit(2);
+ }
+
+ try {
+ if (fs.existsSync(platformBuildDir)) {
+ shell.rm('-r', platformBuildDir);
+ }
+ } catch (err) {
+ console.log('could not remove ' + platformBuildDir + ' : ' + err.message);
+ }
+};
+
+module.exports.run = run;
+// just on the off chance something is still calling cleanProject, we will leave this here for a while
+module.exports.cleanProject = function () {
+ console.log('lib/clean will soon only export a `run` command, please update to not call `cleanProject`.');
+ return run();
+};
diff --git a/platforms/browser/cordova/lib/run.js b/platforms/browser/cordova/lib/run.js
new file mode 100644
index 0000000..0846231
--- /dev/null
+++ b/platforms/browser/cordova/lib/run.js
@@ -0,0 +1,68 @@
+#!/usr/bin/env node
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+var fs = require('fs');
+var path = require('path');
+var url = require('url');
+var cordovaServe = require('cordova-serve');
+
+module.exports.run = function (args) {
+ // defaults
+ args.port = args.port || 8000;
+ args.target = args.target || 'default'; // make default the system browser
+ args.noLogOutput = args.silent || false;
+
+ var wwwPath = path.join(__dirname, '../../www');
+ var manifestFilePath = path.resolve(path.join(wwwPath, 'manifest.json'));
+
+ var startPage;
+
+ // get start page from manifest
+ if (fs.existsSync(manifestFilePath)) {
+ try {
+ var manifest = require(manifestFilePath);
+ startPage = manifest.start_url;
+ } catch (err) {
+ console.log('failed to require manifest ... ' + err);
+ }
+ }
+
+ var server = cordovaServe();
+ server.servePlatform('browser', { port: args.port, noServerInfo: true, noLogOutput: args.noLogOutput })
+ .then(function () {
+ if (!startPage) {
+ // failing all else, set the default
+ startPage = 'index.html';
+ }
+
+ var projectUrl = (new url.URL(`http://localhost:${server.port}/${startPage}`)).href;
+
+ console.log('startPage = ' + startPage);
+ console.log('Static file server running @ ' + projectUrl + '\nCTRL + C to shut down');
+ return server.launchBrowser({ 'target': args.target, 'url': projectUrl });
+ })
+ .catch(function (error) {
+ console.log(error.message || error.toString());
+ if (server.server) {
+ server.server.close();
+ }
+ });
+};
diff --git a/platforms/browser/cordova/log b/platforms/browser/cordova/log
new file mode 100755
index 0000000..bb6fb8c
--- /dev/null
+++ b/platforms/browser/cordova/log
@@ -0,0 +1,20 @@
+#!/usr/bin/env node
+
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+console.log("cordova/log");
\ No newline at end of file
diff --git a/platforms/browser/cordova/run b/platforms/browser/cordova/run
new file mode 100755
index 0000000..b41e299
--- /dev/null
+++ b/platforms/browser/cordova/run
@@ -0,0 +1,53 @@
+#!/usr/bin/env node
+
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+var fs = require('fs'),
+ path = require('path'),
+ nopt = require('nopt'),
+ url = require('url'),
+ runForrest = require('./lib/run'),
+ cordovaServe = require('cordova-serve');
+
+var args = process.argv;
+
+start(args);
+
+function start(argv) {
+ var args = nopt({'help': Boolean, 'target': String, 'port': Number}, {'help': ['/?', '-h', 'help', '-help', '/help']}, argv);
+ if(args.help) {
+ help();
+ }
+ else {
+ return runForrest.run(args);
+ }
+}
+
+function help() {
+ console.log("\nUsage: run [ --target=<browser> ] [ --port=<number> ]");
+ console.log(" --target=<browser> : Launches the specified browser. Chrome is default.");
+ console.log(" --port=<number> : Http server uses specified port number.");
+ console.log("Examples:");
+ console.log(" run");
+ console.log(" run -- --target=ie");
+ console.log(" run -- --target=chrome --port=8000");
+ console.log("");
+ process.exit(0);
+}
diff --git a/platforms/browser/cordova/run.bat b/platforms/browser/cordova/run.bat
new file mode 100644
index 0000000..b9c4402
--- /dev/null
+++ b/platforms/browser/cordova/run.bat
@@ -0,0 +1,26 @@
+:: Licensed to the Apache Software Foundation (ASF) under one
+:: or more contributor license agreements. See the NOTICE file
+:: distributed with this work for additional information
+:: regarding copyright ownership. The ASF licenses this file
+:: to you under the Apache License, Version 2.0 (the
+:: "License"); you may not use this file except in compliance
+:: with the License. You may obtain a copy of the License at
+::
+:: http://www.apache.org/licenses/LICENSE-2.0
+::
+:: Unless required by applicable law or agreed to in writing,
+:: software distributed under the License is distributed on an
+:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+:: KIND, either express or implied. See the License for the
+:: specific language governing permissions and limitations
+:: under the License.
+
+@ECHO OFF
+SET script_path="%~dp0run"
+IF EXIST %script_path% (
+ node %script_path% %*
+) ELSE (
+ ECHO.
+ ECHO ERROR: Could not find 'run' script in 'cordova' folder, aborting...>&2
+ EXIT /B 1
+)
diff --git a/platforms/browser/cordova/version b/platforms/browser/cordova/version
new file mode 100755
index 0000000..814b805
--- /dev/null
+++ b/platforms/browser/cordova/version
@@ -0,0 +1,25 @@
+#!/usr/bin/env node
+
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+// Coho updates this line:
+var VERSION = "6.0.0";
+
+console.log(VERSION);
diff --git a/platforms/browser/cordova/version.bat b/platforms/browser/cordova/version.bat
new file mode 100644
index 0000000..3610c17
--- /dev/null
+++ b/platforms/browser/cordova/version.bat
@@ -0,0 +1,26 @@
+:: Licensed to the Apache Software Foundation (ASF) under one
+:: or more contributor license agreements. See the NOTICE file
+:: distributed with this work for additional information
+:: regarding copyright ownership. The ASF licenses this file
+:: to you under the Apache License, Version 2.0 (the
+:: "License"); you may not use this file except in compliance
+:: with the License. You may obtain a copy of the License at
+::
+:: http://www.apache.org/licenses/LICENSE-2.0
+::
+:: Unless required by applicable law or agreed to in writing,
+:: software distributed under the License is distributed on an
+:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+:: KIND, either express or implied. See the License for the
+:: specific language governing permissions and limitations
+:: under the License.
+
+@ECHO OFF
+SET script_path="%~dp0version"
+IF EXIST %script_path% (
+ node %script_path% %*
+) ELSE (
+ ECHO.
+ ECHO ERROR: Could not find 'version' script in 'cordova' folder, aborting...>&2
+ EXIT /B 1
+)
diff --git a/platforms/browser/platform_www/cordova-js-src/confighelper.js b/platforms/browser/platform_www/cordova-js-src/confighelper.js
new file mode 100644
index 0000000..34d8b19
--- /dev/null
+++ b/platforms/browser/platform_www/cordova-js-src/confighelper.js
@@ -0,0 +1,90 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+var config;
+
+function Config(xhr) {
+ function loadPreferences(xhr) {
+ var parser = new DOMParser();
+ var doc = parser.parseFromString(xhr.responseText, "application/xml");
+
+ var preferences = doc.getElementsByTagName("preference");
+ return Array.prototype.slice.call(preferences);
+ }
+
+ this.xhr = xhr;
+ this.preferences = loadPreferences(this.xhr);
+}
+
+function readConfig(success, error) {
+ var xhr;
+
+ if(typeof config != 'undefined') {
+ success(config);
+ }
+
+ function fail(msg) {
+ console.error(msg);
+
+ if(error) {
+ error(msg);
+ }
+ }
+
+ var xhrStatusChangeHandler = function() {
+ if (xhr.readyState == 4) {
+ if (xhr.status == 200 || xhr.status == 304 || xhr.status === 0 /* file:// */) {
+ config = new Config(xhr);
+ success(config);
+ }
+ else {
+ fail('[Browser][cordova.js][xhrStatusChangeHandler] Could not XHR config.xml: ' + xhr.statusText);
+ }
+ }
+ };
+
+ xhr = new XMLHttpRequest();
+ xhr.addEventListener("load", xhrStatusChangeHandler);
+
+
+ try {
+ xhr.open("get", "config.xml", true);
+ xhr.send();
+ } catch(e) {
+ fail('[Browser][cordova.js][readConfig] Could not XHR config.xml: ' + JSON.stringify(e));
+ }
+}
+
+/**
+ * Reads a preference value from config.xml.
+ * Returns preference value or undefined if it does not exist.
+ * @param {String} preferenceName Preference name to read */
+Config.prototype.getPreferenceValue = function getPreferenceValue(preferenceName) {
+ var preferenceItem = this.preferences && this.preferences.filter(function(item) {
+ return item.attributes.name && item.attributes.name.value === preferenceName;
+ });
+
+ if(preferenceItem && preferenceItem[0] && preferenceItem[0].attributes && preferenceItem[0].attributes.value) {
+ return preferenceItem[0].attributes.value.value;
+ }
+};
+
+exports.readConfig = readConfig;
diff --git a/platforms/browser/platform_www/cordova-js-src/exec.js b/platforms/browser/platform_www/cordova-js-src/exec.js
new file mode 100644
index 0000000..97f736a
--- /dev/null
+++ b/platforms/browser/platform_www/cordova-js-src/exec.js
@@ -0,0 +1,114 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+/*jslint sloppy:true, plusplus:true*/
+/*global require, module, console */
+
+var cordova = require('cordova');
+var execProxy = require('cordova/exec/proxy');
+
+/**
+ * Execute a cordova command. It is up to the native side whether this action
+ * is synchronous or asynchronous. The native side can return:
+ * Synchronous: PluginResult object as a JSON string
+ * Asynchronous: Empty string ""
+ * If async, the native side will cordova.callbackSuccess or cordova.callbackError,
+ * depending upon the result of the action.
+ *
+ * @param {Function} success The success callback
+ * @param {Function} fail The fail callback
+ * @param {String} service The name of the service to use
+ * @param {String} action Action to be run in cordova
+ * @param {String[]} [args] Zero or more arguments to pass to the method
+ */
+module.exports = function (success, fail, service, action, args) {
+
+ var proxy = execProxy.get(service, action);
+
+ args = args || [];
+
+ if (proxy) {
+
+ var callbackId = service + cordova.callbackId++;
+
+ if (typeof success === "function" || typeof fail === "function") {
+ cordova.callbacks[callbackId] = {success: success, fail: fail};
+ }
+ try {
+
+
+
+ // callbackOptions param represents additional optional parameters command could pass back, like keepCallback or
+ // custom callbackId, for example {callbackId: id, keepCallback: true, status: cordova.callbackStatus.JSON_EXCEPTION }
+ var onSuccess = function (result, callbackOptions) {
+ callbackOptions = callbackOptions || {};
+ var callbackStatus;
+ // covering both undefined and null.
+ // strict null comparison was causing callbackStatus to be undefined
+ // and then no callback was called because of the check in cordova.callbackFromNative
+ // see CB-8996 Mobilespec app hang on windows
+ if (callbackOptions.status !== undefined && callbackOptions.status !== null) {
+ callbackStatus = callbackOptions.status;
+ }
+ else {
+ callbackStatus = cordova.callbackStatus.OK;
+ }
+ cordova.callbackSuccess(callbackOptions.callbackId || callbackId,
+ {
+ status: callbackStatus,
+ message: result,
+ keepCallback: callbackOptions.keepCallback || false
+ });
+ };
+ var onError = function (err, callbackOptions) {
+ callbackOptions = callbackOptions || {};
+ var callbackStatus;
+ // covering both undefined and null.
+ // strict null comparison was causing callbackStatus to be undefined
+ // and then no callback was called because of the check in cordova.callbackFromNative
+ // note: status can be 0
+ if (callbackOptions.status !== undefined && callbackOptions.status !== null) {
+ callbackStatus = callbackOptions.status;
+ }
+ else {
+ callbackStatus = cordova.callbackStatus.OK;
+ }
+ cordova.callbackError(callbackOptions.callbackId || callbackId,
+ {
+ status: callbackStatus,
+ message: err,
+ keepCallback: callbackOptions.keepCallback || false
+ });
+ };
+ proxy(onSuccess, onError, args);
+
+ } catch (e) {
+ console.log("Exception calling native with command :: " + service + " :: " + action + " ::exception=" + e);
+ }
+ } else {
+
+ console.log("Error: exec proxy not found for :: " + service + " :: " + action);
+
+ if(typeof fail === "function" ) {
+ fail("Missing Command Error");
+ }
+ }
+};
diff --git a/platforms/browser/platform_www/cordova-js-src/platform.js b/platforms/browser/platform_www/cordova-js-src/platform.js
new file mode 100644
index 0000000..96eb943
--- /dev/null
+++ b/platforms/browser/platform_www/cordova-js-src/platform.js
@@ -0,0 +1,46 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+module.exports = {
+ id: 'browser',
+ cordovaVersion: '4.2.0', // cordova-js
+
+ bootstrap: function() {
+
+ var modulemapper = require('cordova/modulemapper');
+ var channel = require('cordova/channel');
+
+ modulemapper.clobbers('cordova/exec/proxy', 'cordova.commandProxy');
+
+ channel.onNativeReady.fire();
+
+ document.addEventListener("visibilitychange", function(){
+ if(document.hidden) {
+ channel.onPause.fire();
+ }
+ else {
+ channel.onResume.fire();
+ }
+ });
+
+ // End of bootstrap
+ }
+};
diff --git a/platforms/browser/platform_www/cordova.js b/platforms/browser/platform_www/cordova.js
new file mode 100644
index 0000000..02de9c7
--- /dev/null
+++ b/platforms/browser/platform_www/cordova.js
@@ -0,0 +1,1594 @@
+// Platform: browser
+// d07d9d0989196f1b90fe962ca68f5ceb355c69ec
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+;(function() {
+var PLATFORM_VERSION_BUILD_LABEL = '6.0.0';
+// file: src/scripts/require.js
+
+var require;
+var define;
+
+(function () {
+ var modules = {};
+ // Stack of moduleIds currently being built.
+ var requireStack = [];
+ // Map of module ID -> index into requireStack of modules currently being built.
+ var inProgressModules = {};
+ var SEPARATOR = '.';
+
+ function build (module) {
+ var factory = module.factory;
+ var localRequire = function (id) {
+ var resultantId = id;
+ // Its a relative path, so lop off the last portion and add the id (minus "./")
+ if (id.charAt(0) === '.') {
+ resultantId = module.id.slice(0, module.id.lastIndexOf(SEPARATOR)) + SEPARATOR + id.slice(2);
+ }
+ return require(resultantId);
+ };
+ module.exports = {};
+ delete module.factory;
+ factory(localRequire, module.exports, module);
+ return module.exports;
+ }
+
+ require = function (id) {
+ if (!modules[id]) {
+ throw 'module ' + id + ' not found';
+ } else if (id in inProgressModules) {
+ var cycle = requireStack.slice(inProgressModules[id]).join('->') + '->' + id;
+ throw 'Cycle in require graph: ' + cycle;
+ }
+ if (modules[id].factory) {
+ try {
+ inProgressModules[id] = requireStack.length;
+ requireStack.push(id);
+ return build(modules[id]);
+ } finally {
+ delete inProgressModules[id];
+ requireStack.pop();
+ }
+ }
+ return modules[id].exports;
+ };
+
+ define = function (id, factory) {
+ if (modules[id]) {
+ throw 'module ' + id + ' already defined';
+ }
+
+ modules[id] = {
+ id: id,
+ factory: factory
+ };
+ };
+
+ define.remove = function (id) {
+ delete modules[id];
+ };
+
+ define.moduleMap = modules;
+})();
+
+// Export for use in node
+if (typeof module === 'object' && typeof require === 'function') {
+ module.exports.require = require;
+ module.exports.define = define;
+}
+
+// file: src/cordova.js
+define("cordova", function(require, exports, module) {
+
+// Workaround for Windows 10 in hosted environment case
+// http://www.w3.org/html/wg/drafts/html/master/browsers.html#named-access-on-the-window-object
+if (window.cordova && !(window.cordova instanceof HTMLElement)) { // eslint-disable-line no-undef
+ throw new Error('cordova already defined');
+}
+
+var channel = require('cordova/channel');
+var platform = require('cordova/platform');
+
+/**
+ * Intercept calls to addEventListener + removeEventListener and handle deviceready,
+ * resume, and pause events.
+ */
+var m_document_addEventListener = document.addEventListener;
+var m_document_removeEventListener = document.removeEventListener;
+var m_window_addEventListener = window.addEventListener;
+var m_window_removeEventListener = window.removeEventListener;
+
+/**
+ * Houses custom event handlers to intercept on document + window event listeners.
+ */
+var documentEventHandlers = {};
+var windowEventHandlers = {};
+
+document.addEventListener = function (evt, handler, capture) {
+ var e = evt.toLowerCase();
+ if (typeof documentEventHandlers[e] !== 'undefined') {
+ documentEventHandlers[e].subscribe(handler);
+ } else {
+ m_document_addEventListener.call(document, evt, handler, capture);
+ }
+};
+
+window.addEventListener = function (evt, handler, capture) {
+ var e = evt.toLowerCase();
+ if (typeof windowEventHandlers[e] !== 'undefined') {
+ windowEventHandlers[e].subscribe(handler);
+ } else {
+ m_window_addEventListener.call(window, evt, handler, capture);
+ }
+};
+
+document.removeEventListener = function (evt, handler, capture) {
+ var e = evt.toLowerCase();
+ // If unsubscribing from an event that is handled by a plugin
+ if (typeof documentEventHandlers[e] !== 'undefined') {
+ documentEventHandlers[e].unsubscribe(handler);
+ } else {
+ m_document_removeEventListener.call(document, evt, handler, capture);
+ }
+};
+
+window.removeEventListener = function (evt, handler, capture) {
+ var e = evt.toLowerCase();
+ // If unsubscribing from an event that is handled by a plugin
+ if (typeof windowEventHandlers[e] !== 'undefined') {
+ windowEventHandlers[e].unsubscribe(handler);
+ } else {
+ m_window_removeEventListener.call(window, evt, handler, capture);
+ }
+};
+
+function createEvent (type, data) {
+ var event = document.createEvent('Events');
+ event.initEvent(type, false, false);
+ if (data) {
+ for (var i in data) {
+ if (data.hasOwnProperty(i)) {
+ event[i] = data[i];
+ }
+ }
+ }
+ return event;
+}
+
+/* eslint-disable no-undef */
+var cordova = {
+ define: define,
+ require: require,
+ version: PLATFORM_VERSION_BUILD_LABEL,
+ platformVersion: PLATFORM_VERSION_BUILD_LABEL,
+ platformId: platform.id,
+
+ /* eslint-enable no-undef */
+
+ /**
+ * Methods to add/remove your own addEventListener hijacking on document + window.
+ */
+ addWindowEventHandler: function (event) {
+ return (windowEventHandlers[event] = channel.create(event));
+ },
+ addStickyDocumentEventHandler: function (event) {
+ return (documentEventHandlers[event] = channel.createSticky(event));
+ },
+ addDocumentEventHandler: function (event) {
+ return (documentEventHandlers[event] = channel.create(event));
+ },
+ removeWindowEventHandler: function (event) {
+ delete windowEventHandlers[event];
+ },
+ removeDocumentEventHandler: function (event) {
+ delete documentEventHandlers[event];
+ },
+ /**
+ * Retrieve original event handlers that were replaced by Cordova
+ *
+ * @return object
+ */
+ getOriginalHandlers: function () {
+ return {'document': {'addEventListener': m_document_addEventListener, 'removeEventListener': m_document_removeEventListener},
+ 'window': {'addEventListener': m_window_addEventListener, 'removeEventListener': m_window_removeEventListener}};
+ },
+ /**
+ * Method to fire event from native code
+ * bNoDetach is required for events which cause an exception which needs to be caught in native code
+ */
+ fireDocumentEvent: function (type, data, bNoDetach) {
+ var evt = createEvent(type, data);
+ if (typeof documentEventHandlers[type] !== 'undefined') {
+ if (bNoDetach) {
+ documentEventHandlers[type].fire(evt);
+ } else {
+ setTimeout(function () {
+ // Fire deviceready on listeners that were registered before cordova.js was loaded.
+ if (type === 'deviceready') {
+ document.dispatchEvent(evt);
+ }
+ documentEventHandlers[type].fire(evt);
+ }, 0);
+ }
+ } else {
+ document.dispatchEvent(evt);
+ }
+ },
+ fireWindowEvent: function (type, data) {
+ var evt = createEvent(type, data);
+ if (typeof windowEventHandlers[type] !== 'undefined') {
+ setTimeout(function () {
+ windowEventHandlers[type].fire(evt);
+ }, 0);
+ } else {
+ window.dispatchEvent(evt);
+ }
+ },
+
+ /**
+ * Plugin callback mechanism.
+ */
+ // Randomize the starting callbackId to avoid collisions after refreshing or navigating.
+ // This way, it's very unlikely that any new callback would get the same callbackId as an old callback.
+ callbackId: Math.floor(Math.random() * 2000000000),
+ callbacks: {},
+ callbackStatus: {
+ NO_RESULT: 0,
+ OK: 1,
+ CLASS_NOT_FOUND_EXCEPTION: 2,
+ ILLEGAL_ACCESS_EXCEPTION: 3,
+ INSTANTIATION_EXCEPTION: 4,
+ MALFORMED_URL_EXCEPTION: 5,
+ IO_EXCEPTION: 6,
+ INVALID_ACTION: 7,
+ JSON_EXCEPTION: 8,
+ ERROR: 9
+ },
+
+ /**
+ * Called by native code when returning successful result from an action.
+ */
+ callbackSuccess: function (callbackId, args) {
+ cordova.callbackFromNative(callbackId, true, args.status, [args.message], args.keepCallback);
+ },
+
+ /**
+ * Called by native code when returning error result from an action.
+ */
+ callbackError: function (callbackId, args) {
+ // TODO: Deprecate callbackSuccess and callbackError in favour of callbackFromNative.
+ // Derive success from status.
+ cordova.callbackFromNative(callbackId, false, args.status, [args.message], args.keepCallback);
+ },
+
+ /**
+ * Called by native code when returning the result from an action.
+ */
+ callbackFromNative: function (callbackId, isSuccess, status, args, keepCallback) {
+ try {
+ var callback = cordova.callbacks[callbackId];
+ if (callback) {
+ if (isSuccess && status === cordova.callbackStatus.OK) {
+ callback.success && callback.success.apply(null, args);
+ } else if (!isSuccess) {
+ callback.fail && callback.fail.apply(null, args);
+ }
+ /*
+ else
+ Note, this case is intentionally not caught.
+ this can happen if isSuccess is true, but callbackStatus is NO_RESULT
+ which is used to remove a callback from the list without calling the callbacks
+ typically keepCallback is false in this case
+ */
+ // Clear callback if not expecting any more results
+ if (!keepCallback) {
+ delete cordova.callbacks[callbackId];
+ }
+ }
+ } catch (err) {
+ var msg = 'Error in ' + (isSuccess ? 'Success' : 'Error') + ' callbackId: ' + callbackId + ' : ' + err;
+ console && console.log && console.log(msg);
+ console && console.log && err.stack && console.log(err.stack);
+ cordova.fireWindowEvent('cordovacallbackerror', { 'message': msg });
+ throw err;
+ }
+ },
+ addConstructor: function (func) {
+ channel.onCordovaReady.subscribe(function () {
+ try {
+ func();
+ } catch (e) {
+ console.log('Failed to run constructor: ' + e);
+ }
+ });
+ }
+};
+
+module.exports = cordova;
+
+});
+
+// file: src/common/argscheck.js
+define("cordova/argscheck", function(require, exports, module) {
+
+var utils = require('cordova/utils');
+
+var moduleExports = module.exports;
+
+var typeMap = {
+ 'A': 'Array',
+ 'D': 'Date',
+ 'N': 'Number',
+ 'S': 'String',
+ 'F': 'Function',
+ 'O': 'Object'
+};
+
+function extractParamName (callee, argIndex) {
+ return (/.*?\((.*?)\)/).exec(callee)[1].split(', ')[argIndex];
+}
+
+function checkArgs (spec, functionName, args, opt_callee) {
+ if (!moduleExports.enableChecks) {
+ return;
+ }
+ var errMsg = null;
+ var typeName;
+ for (var i = 0; i < spec.length; ++i) {
+ var c = spec.charAt(i);
+ var cUpper = c.toUpperCase();
+ var arg = args[i];
+ // Asterix means allow anything.
+ if (c === '*') {
+ continue;
+ }
+ typeName = utils.typeName(arg);
+ if ((arg === null || arg === undefined) && c === cUpper) {
+ continue;
+ }
+ if (typeName !== typeMap[cUpper]) {
+ errMsg = 'Expected ' + typeMap[cUpper];
+ break;
+ }
+ }
+ if (errMsg) {
+ errMsg += ', but got ' + typeName + '.';
+ errMsg = 'Wrong type for parameter "' + extractParamName(opt_callee || args.callee, i) + '" of ' + functionName + ': ' + errMsg;
+ // Don't log when running unit tests.
+ if (typeof jasmine === 'undefined') {
+ console.error(errMsg);
+ }
+ throw TypeError(errMsg);
+ }
+}
+
+function getValue (value, defaultValue) {
+ return value === undefined ? defaultValue : value;
+}
+
+moduleExports.checkArgs = checkArgs;
+moduleExports.getValue = getValue;
+moduleExports.enableChecks = true;
+
+});
+
+// file: src/common/base64.js
+define("cordova/base64", function(require, exports, module) {
+
+var base64 = exports;
+
+base64.fromArrayBuffer = function (arrayBuffer) {
+ var array = new Uint8Array(arrayBuffer);
+ return uint8ToBase64(array);
+};
+
+base64.toArrayBuffer = function (str) {
+ var decodedStr = typeof atob !== 'undefined' ? atob(str) : Buffer.from(str, 'base64').toString('binary'); // eslint-disable-line no-undef
+ var arrayBuffer = new ArrayBuffer(decodedStr.length);
+ var array = new Uint8Array(arrayBuffer);
+ for (var i = 0, len = decodedStr.length; i < len; i++) {
+ array[i] = decodedStr.charCodeAt(i);
+ }
+ return arrayBuffer;
+};
+
+// ------------------------------------------------------------------------------
+
+/* This code is based on the performance tests at http://jsperf.com/b64tests
+ * This 12-bit-at-a-time algorithm was the best performing version on all
+ * platforms tested.
+ */
+
+var b64_6bit = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
+var b64_12bit;
+
+var b64_12bitTable = function () {
+ b64_12bit = [];
+ for (var i = 0; i < 64; i++) {
+ for (var j = 0; j < 64; j++) {
+ b64_12bit[i * 64 + j] = b64_6bit[i] + b64_6bit[j];
+ }
+ }
+ b64_12bitTable = function () { return b64_12bit; };
+ return b64_12bit;
+};
+
+function uint8ToBase64 (rawData) {
+ var numBytes = rawData.byteLength;
+ var output = '';
+ var segment;
+ var table = b64_12bitTable();
+ for (var i = 0; i < numBytes - 2; i += 3) {
+ segment = (rawData[i] << 16) + (rawData[i + 1] << 8) + rawData[i + 2];
+ output += table[segment >> 12];
+ output += table[segment & 0xfff];
+ }
+ if (numBytes - i === 2) {
+ segment = (rawData[i] << 16) + (rawData[i + 1] << 8);
+ output += table[segment >> 12];
+ output += b64_6bit[(segment & 0xfff) >> 6];
+ output += '=';
+ } else if (numBytes - i === 1) {
+ segment = (rawData[i] << 16);
+ output += table[segment >> 12];
+ output += '==';
+ }
+ return output;
+}
+
+});
+
+// file: src/common/builder.js
+define("cordova/builder", function(require, exports, module) {
+
+var utils = require('cordova/utils');
+
+function each (objects, func, context) {
+ for (var prop in objects) {
+ if (objects.hasOwnProperty(prop)) {
+ func.apply(context, [objects[prop], prop]);
+ }
+ }
+}
+
+function clobber (obj, key, value) {
+ exports.replaceHookForTesting(obj, key);
+ var needsProperty = false;
+ try {
+ obj[key] = value;
+ } catch (e) {
+ needsProperty = true;
+ }
+ // Getters can only be overridden by getters.
+ if (needsProperty || obj[key] !== value) {
+ utils.defineGetter(obj, key, function () {
+ return value;
+ });
+ }
+}
+
+function assignOrWrapInDeprecateGetter (obj, key, value, message) {
+ if (message) {
+ utils.defineGetter(obj, key, function () {
+ console.log(message);
+ delete obj[key];
+ clobber(obj, key, value);
+ return value;
+ });
+ } else {
+ clobber(obj, key, value);
+ }
+}
+
+function include (parent, objects, clobber, merge) {
+ each(objects, function (obj, key) {
+ try {
+ var result = obj.path ? require(obj.path) : {};
+
+ if (clobber) {
+ // Clobber if it doesn't exist.
+ if (typeof parent[key] === 'undefined') {
+ assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
+ } else if (typeof obj.path !== 'undefined') {
+ // If merging, merge properties onto parent, otherwise, clobber.
+ if (merge) {
+ recursiveMerge(parent[key], result);
+ } else {
+ assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
+ }
+ }
+ result = parent[key];
+ } else {
+ // Overwrite if not currently defined.
+ if (typeof parent[key] === 'undefined') {
+ assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
+ } else {
+ // Set result to what already exists, so we can build children into it if they exist.
+ result = parent[key];
+ }
+ }
+
+ if (obj.children) {
+ include(result, obj.children, clobber, merge);
+ }
+ } catch (e) {
+ utils.alert('Exception building Cordova JS globals: ' + e + ' for key "' + key + '"');
+ }
+ });
+}
+
+/**
+ * Merge properties from one object onto another recursively. Properties from
+ * the src object will overwrite existing target property.
+ *
+ * @param target Object to merge properties into.
+ * @param src Object to merge properties from.
+ */
+function recursiveMerge (target, src) {
+ for (var prop in src) {
+ if (src.hasOwnProperty(prop)) {
+ if (target.prototype && target.prototype.constructor === target) {
+ // If the target object is a constructor override off prototype.
+ clobber(target.prototype, prop, src[prop]);
+ } else {
+ if (typeof src[prop] === 'object' && typeof target[prop] === 'object') {
+ recursiveMerge(target[prop], src[prop]);
+ } else {
+ clobber(target, prop, src[prop]);
+ }
+ }
+ }
+ }
+}
+
+exports.buildIntoButDoNotClobber = function (objects, target) {
+ include(target, objects, false, false);
+};
+exports.buildIntoAndClobber = function (objects, target) {
+ include(target, objects, true, false);
+};
+exports.buildIntoAndMerge = function (objects, target) {
+ include(target, objects, true, true);
+};
+exports.recursiveMerge = recursiveMerge;
+exports.assignOrWrapInDeprecateGetter = assignOrWrapInDeprecateGetter;
+exports.replaceHookForTesting = function () {};
+
+});
+
+// file: src/common/channel.js
+define("cordova/channel", function(require, exports, module) {
+
+var utils = require('cordova/utils');
+var nextGuid = 1;
+
+/**
+ * Custom pub-sub "channel" that can have functions subscribed to it
+ * This object is used to define and control firing of events for
+ * cordova initialization, as well as for custom events thereafter.
+ *
+ * The order of events during page load and Cordova startup is as follows:
+ *
+ * onDOMContentLoaded* Internal event that is received when the web page is loaded and parsed.
+ * onNativeReady* Internal event that indicates the Cordova native side is ready.
+ * onCordovaReady* Internal event fired when all Cordova JavaScript objects have been created.
+ * onDeviceReady* User event fired to indicate that Cordova is ready
+ * onResume User event fired to indicate a start/resume lifecycle event
+ * onPause User event fired to indicate a pause lifecycle event
+ *
+ * The events marked with an * are sticky. Once they have fired, they will stay in the fired state.
+ * All listeners that subscribe after the event is fired will be executed right away.
+ *
+ * The only Cordova events that user code should register for are:
+ * deviceready Cordova native code is initialized and Cordova APIs can be called from JavaScript
+ * pause App has moved to background
+ * resume App has returned to foreground
+ *
+ * Listeners can be registered as:
+ * document.addEventListener("deviceready", myDeviceReadyListener, false);
+ * document.addEventListener("resume", myResumeListener, false);
+ * document.addEventListener("pause", myPauseListener, false);
+ *
+ * The DOM lifecycle events should be used for saving and restoring state
+ * window.onload
+ * window.onunload
+ *
+ */
+
+/**
+ * Channel
+ * @constructor
+ * @param type String the channel name
+ */
+var Channel = function (type, sticky) {
+ this.type = type;
+ // Map of guid -> function.
+ this.handlers = {};
+ // 0 = Non-sticky, 1 = Sticky non-fired, 2 = Sticky fired.
+ this.state = sticky ? 1 : 0;
+ // Used in sticky mode to remember args passed to fire().
+ this.fireArgs = null;
+ // Used by onHasSubscribersChange to know if there are any listeners.
+ this.numHandlers = 0;
+ // Function that is called when the first listener is subscribed, or when
+ // the last listener is unsubscribed.
+ this.onHasSubscribersChange = null;
+};
+var channel = {
+ /**
+ * Calls the provided function only after all of the channels specified
+ * have been fired. All channels must be sticky channels.
+ */
+ join: function (h, c) {
+ var len = c.length;
+ var i = len;
+ var f = function () {
+ if (!(--i)) h();
+ };
+ for (var j = 0; j < len; j++) {
+ if (c[j].state === 0) {
+ throw Error('Can only use join with sticky channels.');
+ }
+ c[j].subscribe(f);
+ }
+ if (!len) h();
+ },
+ /* eslint-disable no-return-assign */
+ create: function (type) {
+ return channel[type] = new Channel(type, false);
+ },
+ createSticky: function (type) {
+ return channel[type] = new Channel(type, true);
+ },
+ /* eslint-enable no-return-assign */
+ /**
+ * cordova Channels that must fire before "deviceready" is fired.
+ */
+ deviceReadyChannelsArray: [],
+ deviceReadyChannelsMap: {},
+
+ /**
+ * Indicate that a feature needs to be initialized before it is ready to be used.
+ * This holds up Cordova's "deviceready" event until the feature has been initialized
+ * and Cordova.initComplete(feature) is called.
+ *
+ * @param feature {String} The unique feature name
+ */
+ waitForInitialization: function (feature) {
+ if (feature) {
+ var c = channel[feature] || this.createSticky(feature);
+ this.deviceReadyChannelsMap[feature] = c;
+ this.deviceReadyChannelsArray.push(c);
+ }
+ },
+
+ /**
+ * Indicate that initialization code has completed and the feature is ready to be used.
+ *
+ * @param feature {String} The unique feature name
+ */
+ initializationComplete: function (feature) {
+ var c = this.deviceReadyChannelsMap[feature];
+ if (c) {
+ c.fire();
+ }
+ }
+};
+
+function checkSubscriptionArgument (argument) {
+ if (typeof argument !== 'function' && typeof argument.handleEvent !== 'function') {
+ throw new Error(
+ 'Must provide a function or an EventListener object ' +
+ 'implementing the handleEvent interface.'
+ );
+ }
+}
+
+/**
+ * Subscribes the given function to the channel. Any time that
+ * Channel.fire is called so too will the function.
+ * Optionally specify an execution context for the function
+ * and a guid that can be used to stop subscribing to the channel.
+ * Returns the guid.
+ */
+Channel.prototype.subscribe = function (eventListenerOrFunction, eventListener) {
+ checkSubscriptionArgument(eventListenerOrFunction);
+ var handleEvent, guid;
+
+ if (eventListenerOrFunction && typeof eventListenerOrFunction === 'object') {
+ // Received an EventListener object implementing the handleEvent interface
+ handleEvent = eventListenerOrFunction.handleEvent;
+ eventListener = eventListenerOrFunction;
+ } else {
+ // Received a function to handle event
+ handleEvent = eventListenerOrFunction;
+ }
+
+ if (this.state === 2) {
+ handleEvent.apply(eventListener || this, this.fireArgs);
+ return;
+ }
+
+ guid = eventListenerOrFunction.observer_guid;
+ if (typeof eventListener === 'object') {
+ handleEvent = utils.close(eventListener, handleEvent);
+ }
+
+ if (!guid) {
+ // First time any channel has seen this subscriber
+ guid = '' + nextGuid++;
+ }
+ handleEvent.observer_guid = guid;
+ eventListenerOrFunction.observer_guid = guid;
+
+ // Don't add the same handler more than once.
+ if (!this.handlers[guid]) {
+ this.handlers[guid] = handleEvent;
+ this.numHandlers++;
+ if (this.numHandlers === 1) {
+ this.onHasSubscribersChange && this.onHasSubscribersChange();
+ }
+ }
+};
+
+/**
+ * Unsubscribes the function with the given guid from the channel.
+ */
+Channel.prototype.unsubscribe = function (eventListenerOrFunction) {
+ checkSubscriptionArgument(eventListenerOrFunction);
+ var handleEvent, guid, handler;
+
+ if (eventListenerOrFunction && typeof eventListenerOrFunction === 'object') {
+ // Received an EventListener object implementing the handleEvent interface
+ handleEvent = eventListenerOrFunction.handleEvent;
+ } else {
+ // Received a function to handle event
+ handleEvent = eventListenerOrFunction;
+ }
+
+ guid = handleEvent.observer_guid;
+ handler = this.handlers[guid];
+ if (handler) {
+ delete this.handlers[guid];
+ this.numHandlers--;
+ if (this.numHandlers === 0) {
+ this.onHasSubscribersChange && this.onHasSubscribersChange();
+ }
+ }
+};
+
+/**
+ * Calls all functions subscribed to this channel.
+ */
+Channel.prototype.fire = function (e) {
+ var fail = false; // eslint-disable-line no-unused-vars
+ var fireArgs = Array.prototype.slice.call(arguments);
+ // Apply stickiness.
+ if (this.state === 1) {
+ this.state = 2;
+ this.fireArgs = fireArgs;
+ }
+ if (this.numHandlers) {
+ // Copy the values first so that it is safe to modify it from within
+ // callbacks.
+ var toCall = [];
+ for (var item in this.handlers) {
+ toCall.push(this.handlers[item]);
+ }
+ for (var i = 0; i < toCall.length; ++i) {
+ toCall[i].apply(this, fireArgs);
+ }
+ if (this.state === 2 && this.numHandlers) {
+ this.numHandlers = 0;
+ this.handlers = {};
+ this.onHasSubscribersChange && this.onHasSubscribersChange();
+ }
+ }
+};
+
+// defining them here so they are ready super fast!
+// DOM event that is received when the web page is loaded and parsed.
+channel.createSticky('onDOMContentLoaded');
+
+// Event to indicate the Cordova native side is ready.
+channel.createSticky('onNativeReady');
+
+// Event to indicate that all Cordova JavaScript objects have been created
+// and it's time to run plugin constructors.
+channel.createSticky('onCordovaReady');
+
+// Event to indicate that all automatically loaded JS plugins are loaded and ready.
+// FIXME remove this
+channel.createSticky('onPluginsReady');
+
+// Event to indicate that Cordova is ready
+channel.createSticky('onDeviceReady');
+
+// Event to indicate a resume lifecycle event
+channel.create('onResume');
+
+// Event to indicate a pause lifecycle event
+channel.create('onPause');
+
+// Channels that must fire before "deviceready" is fired.
+channel.waitForInitialization('onCordovaReady');
+channel.waitForInitialization('onDOMContentLoaded');
+
+module.exports = channel;
+
+});
+
+// file: /Users/erisu/git/apache/cordova/cordova-browser/cordova-js-src/confighelper.js
+define("cordova/confighelper", function(require, exports, module) {
+
+var config;
+
+function Config(xhr) {
+ function loadPreferences(xhr) {
+ var parser = new DOMParser();
+ var doc = parser.parseFromString(xhr.responseText, "application/xml");
+
+ var preferences = doc.getElementsByTagName("preference");
+ return Array.prototype.slice.call(preferences);
+ }
+
+ this.xhr = xhr;
+ this.preferences = loadPreferences(this.xhr);
+}
+
+function readConfig(success, error) {
+ var xhr;
+
+ if(typeof config != 'undefined') {
+ success(config);
+ }
+
+ function fail(msg) {
+ console.error(msg);
+
+ if(error) {
+ error(msg);
+ }
+ }
+
+ var xhrStatusChangeHandler = function() {
+ if (xhr.readyState == 4) {
+ if (xhr.status == 200 || xhr.status == 304 || xhr.status === 0 /* file:// */) {
+ config = new Config(xhr);
+ success(config);
+ }
+ else {
+ fail('[Browser][cordova.js][xhrStatusChangeHandler] Could not XHR config.xml: ' + xhr.statusText);
+ }
+ }
+ };
+
+ xhr = new XMLHttpRequest();
+ xhr.addEventListener("load", xhrStatusChangeHandler);
+
+
+ try {
+ xhr.open("get", "config.xml", true);
+ xhr.send();
+ } catch(e) {
+ fail('[Browser][cordova.js][readConfig] Could not XHR config.xml: ' + JSON.stringify(e));
+ }
+}
+
+/**
+ * Reads a preference value from config.xml.
+ * Returns preference value or undefined if it does not exist.
+ * @param {String} preferenceName Preference name to read */
+Config.prototype.getPreferenceValue = function getPreferenceValue(preferenceName) {
+ var preferenceItem = this.preferences && this.preferences.filter(function(item) {
+ return item.attributes.name && item.attributes.name.value === preferenceName;
+ });
+
+ if(preferenceItem && preferenceItem[0] && preferenceItem[0].attributes && preferenceItem[0].attributes.value) {
+ return preferenceItem[0].attributes.value.value;
+ }
+};
+
+exports.readConfig = readConfig;
+
+});
+
+// file: /Users/erisu/git/apache/cordova/cordova-browser/cordova-js-src/exec.js
+define("cordova/exec", function(require, exports, module) {
+
+/*jslint sloppy:true, plusplus:true*/
+/*global require, module, console */
+
+var cordova = require('cordova');
+var execProxy = require('cordova/exec/proxy');
+
+/**
+ * Execute a cordova command. It is up to the native side whether this action
+ * is synchronous or asynchronous. The native side can return:
+ * Synchronous: PluginResult object as a JSON string
+ * Asynchronous: Empty string ""
+ * If async, the native side will cordova.callbackSuccess or cordova.callbackError,
+ * depending upon the result of the action.
+ *
+ * @param {Function} success The success callback
+ * @param {Function} fail The fail callback
+ * @param {String} service The name of the service to use
+ * @param {String} action Action to be run in cordova
+ * @param {String[]} [args] Zero or more arguments to pass to the method
+ */
+module.exports = function (success, fail, service, action, args) {
+
+ var proxy = execProxy.get(service, action);
+
+ args = args || [];
+
+ if (proxy) {
+
+ var callbackId = service + cordova.callbackId++;
+
+ if (typeof success === "function" || typeof fail === "function") {
+ cordova.callbacks[callbackId] = {success: success, fail: fail};
+ }
+ try {
+
+
+
+ // callbackOptions param represents additional optional parameters command could pass back, like keepCallback or
+ // custom callbackId, for example {callbackId: id, keepCallback: true, status: cordova.callbackStatus.JSON_EXCEPTION }
+ var onSuccess = function (result, callbackOptions) {
+ callbackOptions = callbackOptions || {};
+ var callbackStatus;
+ // covering both undefined and null.
+ // strict null comparison was causing callbackStatus to be undefined
+ // and then no callback was called because of the check in cordova.callbackFromNative
+ // see CB-8996 Mobilespec app hang on windows
+ if (callbackOptions.status !== undefined && callbackOptions.status !== null) {
+ callbackStatus = callbackOptions.status;
+ }
+ else {
+ callbackStatus = cordova.callbackStatus.OK;
+ }
+ cordova.callbackSuccess(callbackOptions.callbackId || callbackId,
+ {
+ status: callbackStatus,
+ message: result,
+ keepCallback: callbackOptions.keepCallback || false
+ });
+ };
+ var onError = function (err, callbackOptions) {
+ callbackOptions = callbackOptions || {};
+ var callbackStatus;
+ // covering both undefined and null.
+ // strict null comparison was causing callbackStatus to be undefined
+ // and then no callback was called because of the check in cordova.callbackFromNative
+ // note: status can be 0
+ if (callbackOptions.status !== undefined && callbackOptions.status !== null) {
+ callbackStatus = callbackOptions.status;
+ }
+ else {
+ callbackStatus = cordova.callbackStatus.OK;
+ }
+ cordova.callbackError(callbackOptions.callbackId || callbackId,
+ {
+ status: callbackStatus,
+ message: err,
+ keepCallback: callbackOptions.keepCallback || false
+ });
+ };
+ proxy(onSuccess, onError, args);
+
+ } catch (e) {
+ console.log("Exception calling native with command :: " + service + " :: " + action + " ::exception=" + e);
+ }
+ } else {
+
+ console.log("Error: exec proxy not found for :: " + service + " :: " + action);
+
+ if(typeof fail === "function" ) {
+ fail("Missing Command Error");
+ }
+ }
+};
+
+});
+
+// file: src/common/exec/proxy.js
+define("cordova/exec/proxy", function(require, exports, module) {
+
+// internal map of proxy function
+var CommandProxyMap = {};
+
+module.exports = {
+
+ // example: cordova.commandProxy.add("Accelerometer",{getCurrentAcceleration: function(successCallback, errorCallback, options) {...},...);
+ add: function (id, proxyObj) {
+ console.log('adding proxy for ' + id);
+ CommandProxyMap[id] = proxyObj;
+ return proxyObj;
+ },
+
+ // cordova.commandProxy.remove("Accelerometer");
+ remove: function (id) {
+ var proxy = CommandProxyMap[id];
+ delete CommandProxyMap[id];
+ CommandProxyMap[id] = null;
+ return proxy;
+ },
+
+ get: function (service, action) {
+ return (CommandProxyMap[service] ? CommandProxyMap[service][action] : null);
+ }
+};
+
+});
+
+// file: src/common/init.js
+define("cordova/init", function(require, exports, module) {
+
+var channel = require('cordova/channel');
+var cordova = require('cordova');
+var modulemapper = require('cordova/modulemapper');
+var platform = require('cordova/platform');
+var pluginloader = require('cordova/pluginloader');
+var utils = require('cordova/utils');
+
+var platformInitChannelsArray = [channel.onNativeReady, channel.onPluginsReady];
+
+function logUnfiredChannels (arr) {
+ for (var i = 0; i < arr.length; ++i) {
+ if (arr[i].state !== 2) {
+ console.log('Channel not fired: ' + arr[i].type);
+ }
+ }
+}
+
+window.setTimeout(function () {
+ if (channel.onDeviceReady.state !== 2) {
+ console.log('deviceready has not fired after 5 seconds.');
+ logUnfiredChannels(platformInitChannelsArray);
+ logUnfiredChannels(channel.deviceReadyChannelsArray);
+ }
+}, 5000);
+
+// Replace navigator before any modules are required(), to ensure it happens as soon as possible.
+// We replace it so that properties that can't be clobbered can instead be overridden.
+function replaceNavigator (origNavigator) {
+ var CordovaNavigator = function () {};
+ CordovaNavigator.prototype = origNavigator;
+ var newNavigator = new CordovaNavigator();
+ // This work-around really only applies to new APIs that are newer than Function.bind.
+ // Without it, APIs such as getGamepads() break.
+ if (CordovaNavigator.bind) {
+ for (var key in origNavigator) {
+ if (typeof origNavigator[key] === 'function') {
+ newNavigator[key] = origNavigator[key].bind(origNavigator);
+ } else {
+ (function (k) {
+ utils.defineGetterSetter(newNavigator, key, function () {
+ return origNavigator[k];
+ });
+ })(key);
+ }
+ }
+ }
+ return newNavigator;
+}
+
+if (window.navigator) {
+ window.navigator = replaceNavigator(window.navigator);
+}
+
+if (!window.console) {
+ window.console = {
+ log: function () {}
+ };
+}
+if (!window.console.warn) {
+ window.console.warn = function (msg) {
+ this.log('warn: ' + msg);
+ };
+}
+
+// Register pause, resume and deviceready channels as events on document.
+channel.onPause = cordova.addDocumentEventHandler('pause');
+channel.onResume = cordova.addDocumentEventHandler('resume');
+channel.onActivated = cordova.addDocumentEventHandler('activated');
+channel.onDeviceReady = cordova.addStickyDocumentEventHandler('deviceready');
+
+// Listen for DOMContentLoaded and notify our channel subscribers.
+if (document.readyState === 'complete' || document.readyState === 'interactive') {
+ channel.onDOMContentLoaded.fire();
+} else {
+ document.addEventListener('DOMContentLoaded', function () {
+ channel.onDOMContentLoaded.fire();
+ }, false);
+}
+
+// _nativeReady is global variable that the native side can set
+// to signify that the native code is ready. It is a global since
+// it may be called before any cordova JS is ready.
+if (window._nativeReady) {
+ channel.onNativeReady.fire();
+}
+
+modulemapper.clobbers('cordova', 'cordova');
+modulemapper.clobbers('cordova/exec', 'cordova.exec');
+modulemapper.clobbers('cordova/exec', 'Cordova.exec');
+
+// Call the platform-specific initialization.
+platform.bootstrap && platform.bootstrap();
+
+// Wrap in a setTimeout to support the use-case of having plugin JS appended to cordova.js.
+// The delay allows the attached modules to be defined before the plugin loader looks for them.
+setTimeout(function () {
+ pluginloader.load(function () {
+ channel.onPluginsReady.fire();
+ });
+}, 0);
+
+/**
+ * Create all cordova objects once native side is ready.
+ */
+channel.join(function () {
+ modulemapper.mapModules(window);
+
+ platform.initialize && platform.initialize();
+
+ // Fire event to notify that all objects are created
+ channel.onCordovaReady.fire();
+
+ // Fire onDeviceReady event once page has fully loaded, all
+ // constructors have run and cordova info has been received from native
+ // side.
+ channel.join(function () {
+ require('cordova').fireDocumentEvent('deviceready');
+ }, channel.deviceReadyChannelsArray);
+
+}, platformInitChannelsArray);
+
+});
+
+// file: src/common/modulemapper.js
+define("cordova/modulemapper", function(require, exports, module) {
+
+var builder = require('cordova/builder');
+var moduleMap = define.moduleMap; // eslint-disable-line no-undef
+var symbolList;
+var deprecationMap;
+
+exports.reset = function () {
+ symbolList = [];
+ deprecationMap = {};
+};
+
+function addEntry (strategy, moduleName, symbolPath, opt_deprecationMessage) {
+ if (!(moduleName in moduleMap)) {
+ throw new Error('Module ' + moduleName + ' does not exist.');
+ }
+ symbolList.push(strategy, moduleName, symbolPath);
+ if (opt_deprecationMessage) {
+ deprecationMap[symbolPath] = opt_deprecationMessage;
+ }
+}
+
+// Note: Android 2.3 does have Function.bind().
+exports.clobbers = function (moduleName, symbolPath, opt_deprecationMessage) {
+ addEntry('c', moduleName, symbolPath, opt_deprecationMessage);
+};
+
+exports.merges = function (moduleName, symbolPath, opt_deprecationMessage) {
+ addEntry('m', moduleName, symbolPath, opt_deprecationMessage);
+};
+
+exports.defaults = function (moduleName, symbolPath, opt_deprecationMessage) {
+ addEntry('d', moduleName, symbolPath, opt_deprecationMessage);
+};
+
+exports.runs = function (moduleName) {
+ addEntry('r', moduleName, null);
+};
+
+function prepareNamespace (symbolPath, context) {
+ if (!symbolPath) {
+ return context;
+ }
+ var parts = symbolPath.split('.');
+ var cur = context;
+ for (var i = 0, part; part = parts[i]; ++i) { // eslint-disable-line no-cond-assign
+ cur = cur[part] = cur[part] || {};
+ }
+ return cur;
+}
+
+exports.mapModules = function (context) {
+ var origSymbols = {};
+ context.CDV_origSymbols = origSymbols;
+ for (var i = 0, len = symbolList.length; i < len; i += 3) {
+ var strategy = symbolList[i];
+ var moduleName = symbolList[i + 1];
+ var module = require(moduleName);
+ // <runs/>
+ if (strategy === 'r') {
+ continue;
+ }
+ var symbolPath = symbolList[i + 2];
+ var lastDot = symbolPath.lastIndexOf('.');
+ var namespace = symbolPath.substr(0, lastDot);
+ var lastName = symbolPath.substr(lastDot + 1);
+
+ var deprecationMsg = symbolPath in deprecationMap ? 'Access made to deprecated symbol: ' + symbolPath + '. ' + deprecationMsg : null;
+ var parentObj = prepareNamespace(namespace, context);
+ var target = parentObj[lastName];
+
+ if (strategy === 'm' && target) {
+ builder.recursiveMerge(target, module);
+ } else if ((strategy === 'd' && !target) || (strategy !== 'd')) {
+ if (!(symbolPath in origSymbols)) {
+ origSymbols[symbolPath] = target;
+ }
+ builder.assignOrWrapInDeprecateGetter(parentObj, lastName, module, deprecationMsg);
+ }
+ }
+};
+
+exports.getOriginalSymbol = function (context, symbolPath) {
+ var origSymbols = context.CDV_origSymbols;
+ if (origSymbols && (symbolPath in origSymbols)) {
+ return origSymbols[symbolPath];
+ }
+ var parts = symbolPath.split('.');
+ var obj = context;
+ for (var i = 0; i < parts.length; ++i) {
+ obj = obj && obj[parts[i]];
+ }
+ return obj;
+};
+
+exports.reset();
+
+});
+
+// file: /Users/erisu/git/apache/cordova/cordova-browser/cordova-js-src/platform.js
+define("cordova/platform", function(require, exports, module) {
+
+module.exports = {
+ id: 'browser',
+ cordovaVersion: '4.2.0', // cordova-js
+
+ bootstrap: function() {
+
+ var modulemapper = require('cordova/modulemapper');
+ var channel = require('cordova/channel');
+
+ modulemapper.clobbers('cordova/exec/proxy', 'cordova.commandProxy');
+
+ channel.onNativeReady.fire();
+
+ document.addEventListener("visibilitychange", function(){
+ if(document.hidden) {
+ channel.onPause.fire();
+ }
+ else {
+ channel.onResume.fire();
+ }
+ });
+
+ // End of bootstrap
+ }
+};
+
+});
+
+// file: src/common/pluginloader.js
+define("cordova/pluginloader", function(require, exports, module) {
+
+var modulemapper = require('cordova/modulemapper');
+
+// Helper function to inject a <script> tag.
+// Exported for testing.
+exports.injectScript = function (url, onload, onerror) {
+ var script = document.createElement('script');
+ // onload fires even when script fails loads with an error.
+ script.onload = onload;
+ // onerror fires for malformed URLs.
+ script.onerror = onerror;
+ script.src = url;
+ document.head.appendChild(script);
+};
+
+function injectIfNecessary (id, url, onload, onerror) {
+ onerror = onerror || onload;
+ if (id in define.moduleMap) { // eslint-disable-line no-undef
+ onload();
+ } else {
+ exports.injectScript(url, function () {
+ if (id in define.moduleMap) { // eslint-disable-line no-undef
+ onload();
+ } else {
+ onerror();
+ }
+ }, onerror);
+ }
+}
+
+function onScriptLoadingComplete (moduleList, finishPluginLoading) {
+ // Loop through all the plugins and then through their clobbers and merges.
+ for (var i = 0, module; module = moduleList[i]; i++) { // eslint-disable-line no-cond-assign
+ if (module.clobbers && module.clobbers.length) {
+ for (var j = 0; j < module.clobbers.length; j++) {
+ modulemapper.clobbers(module.id, module.clobbers[j]);
+ }
+ }
+
+ if (module.merges && module.merges.length) {
+ for (var k = 0; k < module.merges.length; k++) {
+ modulemapper.merges(module.id, module.merges[k]);
+ }
+ }
+
+ // Finally, if runs is truthy we want to simply require() the module.
+ if (module.runs) {
+ modulemapper.runs(module.id);
+ }
+ }
+
+ finishPluginLoading();
+}
+
+// Handler for the cordova_plugins.js content.
+// See plugman's plugin_loader.js for the details of this object.
+// This function is only called if the really is a plugins array that isn't empty.
+// Otherwise the onerror response handler will just call finishPluginLoading().
+function handlePluginsObject (path, moduleList, finishPluginLoading) {
+ // Now inject the scripts.
+ var scriptCounter = moduleList.length;
+
+ if (!scriptCounter) {
+ finishPluginLoading();
+ return;
+ }
+ function scriptLoadedCallback () {
+ if (!--scriptCounter) {
+ onScriptLoadingComplete(moduleList, finishPluginLoading);
+ }
+ }
+
+ for (var i = 0; i < moduleList.length; i++) {
+ injectIfNecessary(moduleList[i].id, path + moduleList[i].file, scriptLoadedCallback);
+ }
+}
+
+function findCordovaPath () {
+ var path = null;
+ var scripts = document.getElementsByTagName('script');
+ var term = '/cordova.js';
+ for (var n = scripts.length - 1; n > -1; n--) {
+ var src = scripts[n].src.replace(/\?.*$/, ''); // Strip any query param (CB-6007).
+ if (src.indexOf(term) === (src.length - term.length)) {
+ path = src.substring(0, src.length - term.length) + '/';
+ break;
+ }
+ }
+ return path;
+}
+
+// Tries to load all plugins' js-modules.
+// This is an async process, but onDeviceReady is blocked on onPluginsReady.
+// onPluginsReady is fired when there are no plugins to load, or they are all done.
+exports.load = function (callback) {
+ var pathPrefix = findCordovaPath();
+ if (pathPrefix === null) {
+ console.log('Could not find cordova.js script tag. Plugin loading may fail.');
+ pathPrefix = '';
+ }
+ injectIfNecessary('cordova/plugin_list', pathPrefix + 'cordova_plugins.js', function () {
+ var moduleList = require('cordova/plugin_list');
+ handlePluginsObject(pathPrefix, moduleList, callback);
+ }, callback);
+};
+
+});
+
+// file: src/common/urlutil.js
+define("cordova/urlutil", function(require, exports, module) {
+
+/**
+ * For already absolute URLs, returns what is passed in.
+ * For relative URLs, converts them to absolute ones.
+ */
+exports.makeAbsolute = function makeAbsolute (url) {
+ var anchorEl = document.createElement('a');
+ anchorEl.href = url;
+ return anchorEl.href;
+};
+
+});
+
+// file: src/common/utils.js
+define("cordova/utils", function(require, exports, module) {
+
+var utils = exports;
+
+/**
+ * Defines a property getter / setter for obj[key].
+ */
+utils.defineGetterSetter = function (obj, key, getFunc, opt_setFunc) {
+ if (Object.defineProperty) {
+ var desc = {
+ get: getFunc,
+ configurable: true
+ };
+ if (opt_setFunc) {
+ desc.set = opt_setFunc;
+ }
+ Object.defineProperty(obj, key, desc);
+ } else {
+ obj.__defineGetter__(key, getFunc);
+ if (opt_setFunc) {
+ obj.__defineSetter__(key, opt_setFunc);
+ }
+ }
+};
+
+/**
+ * Defines a property getter for obj[key].
+ */
+utils.defineGetter = utils.defineGetterSetter;
+
+utils.arrayIndexOf = function (a, item) {
+ if (a.indexOf) {
+ return a.indexOf(item);
+ }
+ var len = a.length;
+ for (var i = 0; i < len; ++i) {
+ if (a[i] === item) {
+ return i;
+ }
+ }
+ return -1;
+};
+
+/**
+ * Returns whether the item was found in the array.
+ */
+utils.arrayRemove = function (a, item) {
+ var index = utils.arrayIndexOf(a, item);
+ if (index !== -1) {
+ a.splice(index, 1);
+ }
+ return index !== -1;
+};
+
+utils.typeName = function (val) {
+ return Object.prototype.toString.call(val).slice(8, -1);
+};
+
+/**
+ * Returns an indication of whether the argument is an array or not
+ */
+utils.isArray = Array.isArray ||
+ function (a) { return utils.typeName(a) === 'Array'; };
+
+/**
+ * Returns an indication of whether the argument is a Date or not
+ */
+utils.isDate = function (d) {
+ return (d instanceof Date);
+};
+
+/**
+ * Does a deep clone of the object.
+ */
+utils.clone = function (obj) {
+ if (!obj || typeof obj === 'function' || utils.isDate(obj) || typeof obj !== 'object') {
+ return obj;
+ }
+
+ var retVal, i;
+
+ if (utils.isArray(obj)) {
+ retVal = [];
+ for (i = 0; i < obj.length; ++i) {
+ retVal.push(utils.clone(obj[i]));
+ }
+ return retVal;
+ }
+
+ retVal = {};
+ for (i in obj) {
+ // https://issues.apache.org/jira/browse/CB-11522 'unknown' type may be returned in
+ // custom protocol activation case on Windows Phone 8.1 causing "No such interface supported" exception
+ // on cloning.
+ if ((!(i in retVal) || retVal[i] !== obj[i]) && typeof obj[i] !== 'undefined' && typeof obj[i] !== 'unknown') { // eslint-disable-line valid-typeof
+ retVal[i] = utils.clone(obj[i]);
+ }
+ }
+ return retVal;
+};
+
+/**
+ * Returns a wrapped version of the function
+ */
+utils.close = function (context, func, params) {
+ return function () {
+ var args = params || arguments;
+ return func.apply(context, args);
+ };
+};
+
+// ------------------------------------------------------------------------------
+function UUIDcreatePart (length) {
+ var uuidpart = '';
+ for (var i = 0; i < length; i++) {
+ var uuidchar = parseInt((Math.random() * 256), 10).toString(16);
+ if (uuidchar.length === 1) {
+ uuidchar = '0' + uuidchar;
+ }
+ uuidpart += uuidchar;
+ }
+ return uuidpart;
+}
+
+/**
+ * Create a UUID
+ */
+utils.createUUID = function () {
+ return UUIDcreatePart(4) + '-' +
+ UUIDcreatePart(2) + '-' +
+ UUIDcreatePart(2) + '-' +
+ UUIDcreatePart(2) + '-' +
+ UUIDcreatePart(6);
+};
+
+/**
+ * Extends a child object from a parent object using classical inheritance
+ * pattern.
+ */
+utils.extend = (function () {
+ // proxy used to establish prototype chain
+ var F = function () {};
+ // extend Child from Parent
+ return function (Child, Parent) {
+
+ F.prototype = Parent.prototype;
+ Child.prototype = new F();
+ Child.__super__ = Parent.prototype;
+ Child.prototype.constructor = Child;
+ };
+}());
+
+/**
+ * Alerts a message in any available way: alert or console.log.
+ */
+utils.alert = function (msg) {
+ if (window.alert) {
+ window.alert(msg);
+ } else if (console && console.log) {
+ console.log(msg);
+ }
+};
+
+});
+
+window.cordova = require('cordova');
+// file: src/scripts/bootstrap.js
+
+require('cordova/init');
+
+})();
\ No newline at end of file
diff --git a/platforms/browser/platform_www/cordova_plugins.js b/platforms/browser/platform_www/cordova_plugins.js
new file mode 100644
index 0000000..2b5f2ff
--- /dev/null
+++ b/platforms/browser/platform_www/cordova_plugins.js
@@ -0,0 +1,368 @@
+cordova.define('cordova/plugin_list', function(require, exports, module) {
+module.exports = [
+ {
+ "file": "plugins/cordova-plugin-fingerprint-aio/www/Fingerprint.js",
+ "id": "cordova-plugin-fingerprint-aio.Fingerprint",
+ "pluginId": "cordova-plugin-fingerprint-aio",
+ "clobbers": [
+ "Fingerprint"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-touch-id/www/TouchID.js",
+ "id": "cordova-plugin-touch-id.TouchID",
+ "pluginId": "cordova-plugin-touch-id",
+ "clobbers": [
+ "window.plugins.touchid"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-file/www/DirectoryEntry.js",
+ "id": "cordova-plugin-file.DirectoryEntry",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.DirectoryEntry"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-file/www/DirectoryReader.js",
+ "id": "cordova-plugin-file.DirectoryReader",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.DirectoryReader"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-file/www/Entry.js",
+ "id": "cordova-plugin-file.Entry",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.Entry"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-file/www/File.js",
+ "id": "cordova-plugin-file.File",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.File"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-file/www/FileEntry.js",
+ "id": "cordova-plugin-file.FileEntry",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.FileEntry"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-file/www/FileError.js",
+ "id": "cordova-plugin-file.FileError",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.FileError"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-file/www/FileReader.js",
+ "id": "cordova-plugin-file.FileReader",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.FileReader"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-file/www/FileSystem.js",
+ "id": "cordova-plugin-file.FileSystem",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.FileSystem"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-file/www/FileUploadOptions.js",
+ "id": "cordova-plugin-file.FileUploadOptions",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.FileUploadOptions"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-file/www/FileUploadResult.js",
+ "id": "cordova-plugin-file.FileUploadResult",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.FileUploadResult"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-file/www/FileWriter.js",
+ "id": "cordova-plugin-file.FileWriter",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.FileWriter"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-file/www/Flags.js",
+ "id": "cordova-plugin-file.Flags",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.Flags"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-file/www/LocalFileSystem.js",
+ "id": "cordova-plugin-file.LocalFileSystem",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.LocalFileSystem"
+ ],
+ "merges": [
+ "window"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-file/www/Metadata.js",
+ "id": "cordova-plugin-file.Metadata",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.Metadata"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-file/www/ProgressEvent.js",
+ "id": "cordova-plugin-file.ProgressEvent",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.ProgressEvent"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-file/www/fileSystems.js",
+ "id": "cordova-plugin-file.fileSystems",
+ "pluginId": "cordova-plugin-file"
+ },
+ {
+ "file": "plugins/cordova-plugin-file/www/requestFileSystem.js",
+ "id": "cordova-plugin-file.requestFileSystem",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.requestFileSystem"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-file/www/resolveLocalFileSystemURI.js",
+ "id": "cordova-plugin-file.resolveLocalFileSystemURI",
+ "pluginId": "cordova-plugin-file",
+ "merges": [
+ "window"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-file/www/browser/isChrome.js",
+ "id": "cordova-plugin-file.isChrome",
+ "pluginId": "cordova-plugin-file",
+ "runs": true
+ },
+ {
+ "file": "plugins/cordova-plugin-file/www/browser/Preparing.js",
+ "id": "cordova-plugin-file.Preparing",
+ "pluginId": "cordova-plugin-file",
+ "runs": true
+ },
+ {
+ "file": "plugins/cordova-plugin-file/src/browser/FileProxy.js",
+ "id": "cordova-plugin-file.browserFileProxy",
+ "pluginId": "cordova-plugin-file",
+ "runs": true
+ },
+ {
+ "file": "plugins/cordova-plugin-file/www/fileSystemPaths.js",
+ "id": "cordova-plugin-file.fileSystemPaths",
+ "pluginId": "cordova-plugin-file",
+ "merges": [
+ "cordova"
+ ],
+ "runs": true
+ },
+ {
+ "file": "plugins/cordova-plugin-file/www/browser/FileSystem.js",
+ "id": "cordova-plugin-file.firefoxFileSystem",
+ "pluginId": "cordova-plugin-file",
+ "merges": [
+ "window.FileSystem"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-advanced-http/www/cookie-handler.js",
+ "id": "cordova-plugin-advanced-http.cookie-handler",
+ "pluginId": "cordova-plugin-advanced-http"
+ },
+ {
+ "file": "plugins/cordova-plugin-advanced-http/www/global-configs.js",
+ "id": "cordova-plugin-advanced-http.global-configs",
+ "pluginId": "cordova-plugin-advanced-http"
+ },
+ {
+ "file": "plugins/cordova-plugin-advanced-http/www/helpers.js",
+ "id": "cordova-plugin-advanced-http.helpers",
+ "pluginId": "cordova-plugin-advanced-http"
+ },
+ {
+ "file": "plugins/cordova-plugin-advanced-http/www/js-util.js",
+ "id": "cordova-plugin-advanced-http.js-util",
+ "pluginId": "cordova-plugin-advanced-http"
+ },
+ {
+ "file": "plugins/cordova-plugin-advanced-http/www/local-storage-store.js",
+ "id": "cordova-plugin-advanced-http.local-storage-store",
+ "pluginId": "cordova-plugin-advanced-http"
+ },
+ {
+ "file": "plugins/cordova-plugin-advanced-http/www/lodash.js",
+ "id": "cordova-plugin-advanced-http.lodash",
+ "pluginId": "cordova-plugin-advanced-http"
+ },
+ {
+ "file": "plugins/cordova-plugin-advanced-http/www/messages.js",
+ "id": "cordova-plugin-advanced-http.messages",
+ "pluginId": "cordova-plugin-advanced-http"
+ },
+ {
+ "file": "plugins/cordova-plugin-advanced-http/www/public-interface.js",
+ "id": "cordova-plugin-advanced-http.public-interface",
+ "pluginId": "cordova-plugin-advanced-http"
+ },
+ {
+ "file": "plugins/cordova-plugin-advanced-http/www/umd-tough-cookie.js",
+ "id": "cordova-plugin-advanced-http.tough-cookie",
+ "pluginId": "cordova-plugin-advanced-http"
+ },
+ {
+ "file": "plugins/cordova-plugin-advanced-http/www/url-util.js",
+ "id": "cordova-plugin-advanced-http.url-util",
+ "pluginId": "cordova-plugin-advanced-http"
+ },
+ {
+ "file": "plugins/cordova-plugin-advanced-http/www/advanced-http.js",
+ "id": "cordova-plugin-advanced-http.http",
+ "pluginId": "cordova-plugin-advanced-http",
+ "clobbers": [
+ "cordova.plugin.http"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-advanced-http/src/browser/cordova-http-plugin.js",
+ "id": "cordova-plugin-advanced-http.http-proxy",
+ "pluginId": "cordova-plugin-advanced-http",
+ "runs": true
+ },
+ {
+ "file": "plugins/cordova-plugin-statusbar/www/statusbar.js",
+ "id": "cordova-plugin-statusbar.statusbar",
+ "pluginId": "cordova-plugin-statusbar",
+ "clobbers": [
+ "window.StatusBar"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-statusbar/src/browser/StatusBarProxy.js",
+ "id": "cordova-plugin-statusbar.StatusBarProxy",
+ "pluginId": "cordova-plugin-statusbar",
+ "runs": true
+ },
+ {
+ "file": "plugins/cordova-plugin-qrscanner/www/www.min.js",
+ "id": "cordova-plugin-qrscanner.QRScanner",
+ "pluginId": "cordova-plugin-qrscanner",
+ "clobbers": [
+ "QRScanner"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-qrscanner/src/browser/plugin.min.js",
+ "id": "cordova-plugin-qrscanner.QRScannerProxy",
+ "pluginId": "cordova-plugin-qrscanner",
+ "runs": true
+ },
+ {
+ "file": "plugins/cordova-plugin-camera/www/CameraConstants.js",
+ "id": "cordova-plugin-camera.Camera",
+ "pluginId": "cordova-plugin-camera",
+ "clobbers": [
+ "Camera"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-camera/www/CameraPopoverOptions.js",
+ "id": "cordova-plugin-camera.CameraPopoverOptions",
+ "pluginId": "cordova-plugin-camera",
+ "clobbers": [
+ "CameraPopoverOptions"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-camera/www/Camera.js",
+ "id": "cordova-plugin-camera.camera",
+ "pluginId": "cordova-plugin-camera",
+ "clobbers": [
+ "navigator.camera"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-camera/src/browser/CameraProxy.js",
+ "id": "cordova-plugin-camera.CameraProxy",
+ "pluginId": "cordova-plugin-camera",
+ "runs": true
+ },
+ {
+ "file": "plugins/cordova-plugin-inappbrowser/www/inappbrowser.js",
+ "id": "cordova-plugin-inappbrowser.inappbrowser",
+ "pluginId": "cordova-plugin-inappbrowser",
+ "clobbers": [
+ "cordova.InAppBrowser.open",
+ "window.open"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-inappbrowser/src/browser/InAppBrowserProxy.js",
+ "id": "cordova-plugin-inappbrowser.InAppBrowserProxy",
+ "pluginId": "cordova-plugin-inappbrowser",
+ "runs": true
+ },
+ {
+ "file": "plugins/cordova-plugin-device/www/device.js",
+ "id": "cordova-plugin-device.device",
+ "pluginId": "cordova-plugin-device",
+ "clobbers": [
+ "device"
+ ]
+ },
+ {
+ "file": "plugins/cordova-plugin-device/src/browser/DeviceProxy.js",
+ "id": "cordova-plugin-device.DeviceProxy",
+ "pluginId": "cordova-plugin-device",
+ "runs": true
+ }
+];
+module.exports.metadata =
+// TOP OF METADATA
+{
+ "cordova-plugin-add-swift-support": "2.0.2",
+ "cordova-plugin-fingerprint-aio": "1.7.0",
+ "cordova-plugin-touch-id": "3.3.1",
+ "cordova-plugin-whitelist": "1.3.3",
+ "cordova-plugin-file": "6.0.1",
+ "cordova-plugin-advanced-http": "2.1.1",
+ "cordova-plugin-statusbar": "2.4.2",
+ "cordova-plugin-disable-ios11-statusbar": "1.0.0",
+ "cordova-plugin-qrscanner": "3.0.1",
+ "cordova-plugin-camera": "4.0.3",
+ "cordova-plugin-inappbrowser": "3.0.0",
+ "cordova-plugin-device": "2.0.2",
+ "cordova-plugin-themeablebrowser": "0.2.17"
+}
+// BOTTOM OF METADATA
+});
\ No newline at end of file
diff --git a/platforms/browser/platform_www/favicon.ico b/platforms/browser/platform_www/favicon.ico
new file mode 100644
index 0000000..fa7a758
--- /dev/null
+++ b/platforms/browser/platform_www/favicon.ico
Binary files differ
diff --git a/platforms/browser/platform_www/manifest.json b/platforms/browser/platform_www/manifest.json
new file mode 100644
index 0000000..5ad3f7b
--- /dev/null
+++ b/platforms/browser/platform_www/manifest.json
@@ -0,0 +1,24 @@
+{
+ "name": "大理市民卡",
+ "short_name": "大理市民卡",
+ "description": "Description of your app from template",
+ "start_url": "index.html",
+ "scope": "index.html",
+ "icons": [
+ {
+ "src": "img/logo.png",
+ "sizes": "192x192",
+ "type": "image/png"
+ },
+ {
+ "src": "img/splash.png",
+ "sizes": "512x512",
+ "type": "image/png"
+ }
+ ],
+ "default_locale": "en",
+ "display": "standalone",
+ "background_color": "#FFF",
+ "theme_color": "#000",
+ "orientation": "landscape"
+}
\ No newline at end of file
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/src/browser/cordova-http-plugin.js b/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/src/browser/cordova-http-plugin.js
new file mode 100644
index 0000000..953386f
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/src/browser/cordova-http-plugin.js
@@ -0,0 +1,222 @@
+cordova.define("cordova-plugin-advanced-http.http-proxy", function(require, exports, module) { var pluginId = module.id.slice(0, module.id.lastIndexOf('.'));
+
+var cordovaProxy = require('cordova/exec/proxy');
+var jsUtil = require(pluginId + '.js-util');
+
+function serializeJsonData(data) {
+ try {
+ return JSON.stringify(data);
+ } catch (err) {
+ return null;
+ }
+}
+
+function serializePrimitive(key, value) {
+ if (value === null || value === undefined) {
+ return encodeURIComponent(key) + '=';
+ }
+
+ return encodeURIComponent(key) + '=' + encodeURIComponent(value);
+}
+
+function serializeArray(key, values) {
+ return values.map(function(value) {
+ return encodeURIComponent(key) + '[]=' + encodeURIComponent(value);
+ }).join('&');
+}
+
+function serializeParams(params) {
+ if (params === null) return '';
+
+ return Object.keys(params).map(function(key) {
+ if (jsUtil.getTypeOf(params[key]) === 'Array') {
+ return serializeArray(key, params[key]);
+ }
+
+ return serializePrimitive(key, params[key]);
+ }).join('&');
+}
+
+function deserializeResponseHeaders(headers) {
+ var headerMap = {};
+ var arr = headers.trim().split(/[\r\n]+/);
+
+ arr.forEach(function (line) {
+ var parts = line.split(': ');
+ var header = parts.shift().toLowerCase();
+ var value = parts.join(': ');
+
+ headerMap[header] = value;
+ });
+
+ return headerMap;
+}
+
+function getResponseData(xhr) {
+ if (xhr.responseType !== 'text' || jsUtil.getTypeOf(xhr.responseText) !== 'String') {
+ return xhr.response;
+ }
+
+ return xhr.responseText;
+}
+
+function createXhrSuccessObject(xhr) {
+ return {
+ url: xhr.responseURL,
+ status: xhr.status,
+ data: getResponseData(xhr),
+ headers: deserializeResponseHeaders(xhr.getAllResponseHeaders())
+ };
+}
+
+function createXhrFailureObject(xhr) {
+ var obj = {};
+
+ obj.headers = xhr.getAllResponseHeaders();
+ obj.error = getResponseData(xhr);
+ obj.error = obj.error || 'advanced-http: please check browser console for error messages';
+
+ if (xhr.responseURL) obj.url = xhr.responseURL;
+ if (xhr.status) obj.status = xhr.status;
+
+ return obj;
+}
+
+function getHeaderValue(headers, headerName) {
+ let result = null;
+
+ Object.keys(headers).forEach(function(key) {
+ if (key.toLowerCase() === headerName.toLowerCase()) {
+ result = headers[key];
+ }
+ });
+
+ return result;
+}
+
+function setDefaultContentType(headers, contentType) {
+ if (getHeaderValue(headers, 'Content-Type') === null) {
+ headers['Content-Type'] = contentType;
+ }
+}
+
+function setHeaders(xhr, headers) {
+ Object.keys(headers).forEach(function(key) {
+ if (key.toLowerCase() === 'cookie') return;
+
+ xhr.setRequestHeader(key, headers[key]);
+ });
+}
+
+function sendRequest(method, withData, opts, success, failure) {
+ var data, serializer, headers, timeout, followRedirect, responseType;
+ var url = opts[0];
+
+ if (withData) {
+ data = opts[1];
+ serializer = opts[2];
+ headers = opts[3];
+ timeout = opts[4];
+ followRedirect = opts[5];
+ responseType = opts[6];
+ } else {
+ headers = opts[1];
+ timeout = opts[2];
+ followRedirect = opts[3];
+ responseType = opts[4];
+
+ }
+
+ var processedData = null;
+ var xhr = new XMLHttpRequest();
+
+ xhr.open(method, url);
+
+ if (headers.Cookie && headers.Cookie.length > 0) {
+ return failure('advanced-http: custom cookies not supported on browser platform');
+ }
+
+ if (!followRedirect) {
+ return failure('advanced-http: disabling follow redirect not supported on browser platform');
+ }
+
+ switch (serializer) {
+ case 'json':
+ setDefaultContentType(headers, 'application/json; charset=utf8');
+ processedData = serializeJsonData(data);
+
+ if (processedData === null) {
+ return failure('advanced-http: failed serializing data');
+ }
+
+ break;
+
+ case 'utf8':
+ setDefaultContentType(headers, 'text/plain; charset=utf8');
+ processedData = data.text;
+ break;
+
+ case 'urlencoded':
+ setDefaultContentType(headers, 'application/x-www-form-urlencoded');
+ processedData = serializeParams(data);
+ break;
+ }
+
+ xhr.timeout = timeout * 1000;
+ xhr.responseType = responseType;
+ setHeaders(xhr, headers);
+
+ xhr.onerror = xhr.ontimeout = function () {
+ return failure(createXhrFailureObject(xhr));
+ };
+
+ xhr.onload = function () {
+ if (xhr.readyState !== xhr.DONE) return;
+
+ if (xhr.status < 200 || xhr.status > 299) {
+ return failure(createXhrFailureObject(xhr));
+ }
+
+ return success(createXhrSuccessObject(xhr));
+ };
+
+ xhr.send(processedData);
+}
+
+var browserInterface = {
+ get: function (success, failure, opts) {
+ return sendRequest('get', false, opts, success, failure);
+ },
+ head: function (success, failure, opts) {
+ return sendRequest('head', false, opts, success, failure);
+ },
+ delete: function (success, failure, opts) {
+ return sendRequest('delete', false, opts, success, failure);
+ },
+ post: function (success, failure, opts) {
+ return sendRequest('post', true, opts, success, failure);
+ },
+ put: function (success, failure, opts) {
+ return sendRequest('put', true, opts, success, failure);
+ },
+ patch: function (success, failure, opts) {
+ return sendRequest('patch', true, opts, success, failure);
+ },
+ uploadFile: function (success, failure, opts) {
+ return failure('advanced-http: function "uploadFile" not supported on browser platform');
+ },
+ downloadFile: function (success, failure, opts) {
+ return failure('advanced-http: function "downloadFile" not supported on browser platform');
+ },
+ setServerTrustMode: function (success, failure, opts) {
+ return failure('advanced-http: function "setServerTrustMode" not supported on browser platform');
+ },
+ setClientAuthMode: function (success, failure, opts) {
+ return failure('advanced-http: function "setClientAuthMode" not supported on browser platform');
+ }
+};
+
+module.exports = browserInterface;
+cordovaProxy.add('CordovaHttpPlugin', browserInterface);
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/advanced-http.js b/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/advanced-http.js
new file mode 100644
index 0000000..e41e8af
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/advanced-http.js
@@ -0,0 +1,22 @@
+cordova.define("cordova-plugin-advanced-http.http", function(require, exports, module) { /*
+ * A native HTTP Plugin for Cordova / PhoneGap.
+ */
+
+var pluginId = module.id.slice(0, module.id.lastIndexOf('.'));
+
+var exec = require('cordova/exec');
+var base64 = require('cordova/base64');
+var messages = require(pluginId + '.messages');
+var globalConfigs = require(pluginId + '.global-configs');
+var jsUtil = require(pluginId + '.js-util');
+var ToughCookie = require(pluginId + '.tough-cookie');
+var lodash = require(pluginId + '.lodash');
+var WebStorageCookieStore = require(pluginId + '.local-storage-store')(ToughCookie, lodash);
+var cookieHandler = require(pluginId + '.cookie-handler')(window.localStorage, ToughCookie, WebStorageCookieStore);
+var helpers = require(pluginId + '.helpers')(jsUtil, cookieHandler, messages, base64);
+var urlUtil = require(pluginId + '.url-util')(jsUtil);
+var publicInterface = require(pluginId + '.public-interface')(exec, cookieHandler, urlUtil, helpers, globalConfigs);
+
+module.exports = publicInterface;
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/cookie-handler.js b/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/cookie-handler.js
new file mode 100644
index 0000000..61d60b8
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/cookie-handler.js
@@ -0,0 +1,72 @@
+cordova.define("cordova-plugin-advanced-http.cookie-handler", function(require, exports, module) { module.exports = function init(storage, ToughCookie, WebStorageCookieStore) {
+ var storeKey = '__advancedHttpCookieStore__';
+
+ var store = new WebStorageCookieStore(storage, storeKey);
+ var cookieJar = new ToughCookie.CookieJar(store);
+
+ return {
+ setCookieFromString: setCookieFromString,
+ setCookie: setCookie,
+ getCookieString: getCookieString,
+ clearCookies: clearCookies,
+ removeCookies: removeCookies
+ };
+
+ function splitCookieString(cookieStr) {
+ var cookieParts = cookieStr.split(',');
+ var splitCookies = [];
+ var processedCookie = null;
+
+ for (var i = 0; i < cookieParts.length; ++i) {
+ if (cookieParts[i].substr(-11, 8).toLowerCase() === 'expires=') {
+ processedCookie = cookieParts[i] + ',' + cookieParts[i + 1];
+ i++;
+ } else {
+ processedCookie = cookieParts[i];
+ }
+
+ processedCookie = processedCookie.trim();
+ splitCookies.push(processedCookie);
+ }
+
+ return splitCookies;
+ }
+
+ function setCookieFromString(url, cookieStr) {
+ if (!cookieStr) return;
+
+ var cookies = splitCookieString(cookieStr);
+
+ for (var i = 0; i < cookies.length; ++i) {
+ cookieJar.setCookieSync(cookies[i], url, { ignoreError: true });
+ }
+ }
+
+ function setCookie(url, cookie, options) {
+ options = options || {};
+ options.ignoreError = false;
+ cookieJar.setCookieSync(cookie, url, options);
+ }
+
+ function getCookieString(url) {
+ return cookieJar.getCookieStringSync(url);
+ }
+
+ function clearCookies() {
+ window.localStorage.removeItem(storeKey);
+ }
+
+ function removeCookies(url, cb) {
+ cookieJar.getCookies(url, function (error, cookies) {
+ if (!cookies || cookies.length === 0) {
+ return cb(null, []);
+ }
+
+ var domain = cookies[0].domain;
+
+ cookieJar.store.removeCookies(domain, null, cb);
+ });
+ }
+};
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/global-configs.js b/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/global-configs.js
new file mode 100644
index 0000000..b9ff2ec
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/global-configs.js
@@ -0,0 +1,10 @@
+cordova.define("cordova-plugin-advanced-http.global-configs", function(require, exports, module) { var globalConfigs = {
+ headers: {},
+ serializer: 'urlencoded',
+ followRedirect: true,
+ timeout: 60.0,
+};
+
+module.exports = globalConfigs;
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/helpers.js b/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/helpers.js
new file mode 100644
index 0000000..e1cb118
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/helpers.js
@@ -0,0 +1,352 @@
+cordova.define("cordova-plugin-advanced-http.helpers", function(require, exports, module) { module.exports = function init(jsUtil, cookieHandler, messages, base64) {
+ var validSerializers = ['urlencoded', 'json', 'utf8'];
+ var validCertModes = ['default', 'nocheck', 'pinned', 'legacy'];
+ var validClientAuthModes = ['none', 'systemstore', 'buffer'];
+ var validHttpMethods = ['get', 'put', 'post', 'patch', 'head', 'delete', 'upload', 'download'];
+ var validResponseTypes = ['text','arraybuffer', 'blob'];
+
+ var interface = {
+ b64EncodeUnicode: b64EncodeUnicode,
+ checkSerializer: checkSerializer,
+ checkSSLCertMode: checkSSLCertMode,
+ checkClientAuthMode: checkClientAuthMode,
+ checkClientAuthOptions: checkClientAuthOptions,
+ checkForBlacklistedHeaderKey: checkForBlacklistedHeaderKey,
+ checkForInvalidHeaderValue: checkForInvalidHeaderValue,
+ checkTimeoutValue: checkTimeoutValue,
+ checkFollowRedirectValue: checkFollowRedirectValue,
+ injectCookieHandler: injectCookieHandler,
+ injectRawResponseHandler: injectRawResponseHandler,
+ injectFileEntryHandler: injectFileEntryHandler,
+ getMergedHeaders: getMergedHeaders,
+ getProcessedData: getProcessedData,
+ handleMissingCallbacks: handleMissingCallbacks,
+ handleMissingOptions: handleMissingOptions
+ };
+
+ // expose all functions for testing purposes
+ if (init.debug) {
+ interface.mergeHeaders = mergeHeaders;
+ interface.checkForValidStringValue = checkForValidStringValue;
+ interface.checkKeyValuePairObject = checkKeyValuePairObject;
+ interface.checkHttpMethod = checkHttpMethod;
+ interface.checkResponseType = checkResponseType;
+ interface.checkHeadersObject = checkHeadersObject;
+ interface.checkParamsObject = checkParamsObject;
+ interface.resolveCookieString = resolveCookieString;
+ interface.createFileEntry = createFileEntry;
+ interface.getCookieHeader = getCookieHeader;
+ interface.getMatchingHostHeaders = getMatchingHostHeaders;
+ interface.getAllowedDataTypes = getAllowedDataTypes;
+ }
+
+ return interface;
+
+ // Thanks Mozilla: https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#The_.22Unicode_Problem.22
+ function b64EncodeUnicode(str) {
+ return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) {
+ return String.fromCharCode('0x' + p1);
+ }));
+ }
+
+ function mergeHeaders(globalHeaders, localHeaders) {
+ var globalKeys = Object.keys(globalHeaders);
+ var key;
+
+ for (var i = 0; i < globalKeys.length; i++) {
+ key = globalKeys[i];
+
+ if (!localHeaders.hasOwnProperty(key)) {
+ localHeaders[key] = globalHeaders[key];
+ }
+ }
+
+ return localHeaders;
+ }
+
+ function checkForValidStringValue(list, value, onInvalidValueMessage) {
+ if (jsUtil.getTypeOf(value) !== 'String') {
+ throw new Error(onInvalidValueMessage + ' ' + list.join(', '));
+ }
+
+ value = value.trim().toLowerCase();
+
+ if (list.indexOf(value) === -1) {
+ throw new Error(onInvalidValueMessage + ' ' + list.join(', '));
+ }
+
+ return value;
+ }
+
+ function checkKeyValuePairObject(obj, allowedChildren, onInvalidValueMessage) {
+ if (jsUtil.getTypeOf(obj) !== 'Object') {
+ throw new Error(onInvalidValueMessage);
+ }
+
+ var keys = Object.keys(obj);
+
+ for (var i = 0; i < keys.length; i++) {
+ if (allowedChildren.indexOf(jsUtil.getTypeOf(obj[keys[i]])) === -1) {
+ throw new Error(onInvalidValueMessage);
+ }
+ }
+
+ return obj;
+ }
+
+ function checkHttpMethod(method) {
+ return checkForValidStringValue(validHttpMethods, method, messages.INVALID_HTTP_METHOD);
+ }
+
+ function checkResponseType(type) {
+ return checkForValidStringValue(validResponseTypes, type, messages.INVALID_RESPONSE_TYPE);
+ }
+
+ function checkSerializer(serializer) {
+ return checkForValidStringValue(validSerializers, serializer, messages.INVALID_DATA_SERIALIZER);
+ }
+
+ function checkSSLCertMode(mode) {
+ return checkForValidStringValue(validCertModes, mode, messages.INVALID_SSL_CERT_MODE);
+ }
+
+ function checkClientAuthMode(mode) {
+ return checkForValidStringValue(validClientAuthModes, mode, messages.INVALID_CLIENT_AUTH_MODE);
+ }
+
+ function checkClientAuthOptions(mode, options) {
+ options = options || {};
+
+ // none
+ if (mode === validClientAuthModes[0]) {
+ return {
+ alias: null,
+ rawPkcs: null,
+ pkcsPassword: ''
+ };
+ }
+
+ if (jsUtil.getTypeOf(options) !== 'Object') {
+ throw new Error(messages.INVALID_CLIENT_AUTH_OPTIONS);
+ }
+
+ // systemstore
+ if (mode === validClientAuthModes[1]) {
+ if (jsUtil.getTypeOf(options.alias) !== 'String'
+ && jsUtil.getTypeOf(options.alias) !== 'Undefined') {
+ throw new Error(messages.INVALID_CLIENT_AUTH_ALIAS);
+ }
+
+ return {
+ alias: jsUtil.getTypeOf(options.alias) === 'Undefined' ? null : options.alias,
+ rawPkcs: null,
+ pkcsPassword: ''
+ };
+ }
+
+ // buffer
+ if (mode === validClientAuthModes[2]) {
+ if (jsUtil.getTypeOf(options.rawPkcs) !== 'ArrayBuffer') {
+ throw new Error(messages.INVALID_CLIENT_AUTH_RAW_PKCS);
+ }
+
+ if (jsUtil.getTypeOf(options.pkcsPassword) !== 'String') {
+ throw new Error(messages.INVALID_CLIENT_AUTH_PKCS_PASSWORD);
+ }
+
+ return {
+ alias: null,
+ rawPkcs: options.rawPkcs,
+ pkcsPassword: options.pkcsPassword
+ }
+ }
+ }
+
+ function checkForBlacklistedHeaderKey(key) {
+ if (key.toLowerCase() === 'cookie') {
+ throw new Error(messages.ADDING_COOKIES_NOT_SUPPORTED);
+ }
+
+ return key;
+ }
+
+ function checkForInvalidHeaderValue(value) {
+ if (jsUtil.getTypeOf(value) !== 'String') {
+ throw new Error(messages.INVALID_HEADERS_VALUE);
+ }
+
+ return value;
+ }
+
+ function checkTimeoutValue(timeout) {
+ if (jsUtil.getTypeOf(timeout) !== 'Number' || timeout < 0) {
+ throw new Error(messages.INVALID_TIMEOUT_VALUE);
+ }
+
+ return timeout;
+ }
+
+ function checkFollowRedirectValue(follow) {
+ if (jsUtil.getTypeOf(follow) !== 'Boolean') {
+ throw new Error(messages.INVALID_FOLLOW_REDIRECT_VALUE);
+ }
+
+ return follow;
+ }
+
+ function checkHeadersObject(headers) {
+ return checkKeyValuePairObject(headers, ['String'], messages.INVALID_HEADERS_VALUE);
+ }
+
+ function checkParamsObject(params) {
+ return checkKeyValuePairObject(params, ['String', 'Array'], messages.INVALID_PARAMS_VALUE);
+ }
+
+ function resolveCookieString(headers) {
+ var keys = Object.keys(headers || {});
+
+ for (var i = 0; i < keys.length; ++i) {
+ if (keys[i].match(/^set-cookie$/i)) {
+ return headers[keys[i]];
+ }
+ }
+
+ return null;
+ }
+
+ function createFileEntry(rawEntry) {
+ var entry = new (require('cordova-plugin-file.FileEntry'))();
+
+ entry.isDirectory = rawEntry.isDirectory;
+ entry.isFile = rawEntry.isFile;
+ entry.name = rawEntry.name;
+ entry.fullPath = rawEntry.fullPath;
+ entry.filesystem = new FileSystem(rawEntry.filesystemName || (rawEntry.filesystem == window.PERSISTENT ? 'persistent' : 'temporary'));
+ entry.nativeURL = rawEntry.nativeURL;
+
+ return entry;
+ }
+
+ function injectCookieHandler(url, cb) {
+ return function (response) {
+ cookieHandler.setCookieFromString(url, resolveCookieString(response.headers));
+ cb(response);
+ }
+ }
+
+ function injectRawResponseHandler(responseType, cb) {
+ return function (response) {
+ var dataType = jsUtil.getTypeOf(response.data);
+
+ // don't need post-processing if it's already binary type (on browser platform)
+ if (dataType === 'ArrayBuffer' || dataType === 'Blob') {
+ return cb(response);
+ }
+
+ // arraybuffer
+ if (responseType === validResponseTypes[1]) {
+ var buffer = base64.toArrayBuffer(response.data);
+ response.data = buffer;
+ }
+
+ // blob
+ if (responseType === validResponseTypes[2]) {
+ var buffer = base64.toArrayBuffer(response.data);
+ var type = response.headers['content-type'] || '';
+ var blob = new Blob([ buffer ], { type: type });
+ response.data = blob;
+ }
+
+ cb(response);
+ }
+ }
+
+ function injectFileEntryHandler(cb) {
+ return function (response) {
+ cb(createFileEntry(response.file));
+ }
+ }
+
+ function getCookieHeader(url) {
+ var cookieString = cookieHandler.getCookieString(url);
+
+ if (cookieString.length) {
+ return { Cookie: cookieHandler.getCookieString(url) };
+ }
+
+ return {};
+ }
+
+ function getMatchingHostHeaders(url, headersList) {
+ var matches = url.match(/^https?\:\/\/([^\/?#]+)(?:[\/?#]|$)/i);
+ var domain = matches && matches[1];
+
+ return headersList[domain] || null;
+ }
+
+ function getMergedHeaders(url, requestHeaders, predefinedHeaders) {
+ var globalHeaders = predefinedHeaders['*'] || {};
+ var hostHeaders = getMatchingHostHeaders(url, predefinedHeaders) || {};
+ var mergedHeaders = mergeHeaders(globalHeaders, hostHeaders);
+
+ mergedHeaders = mergeHeaders(mergedHeaders, requestHeaders);
+ mergedHeaders = mergeHeaders(mergedHeaders, getCookieHeader(url));
+
+ return mergedHeaders;
+ }
+
+ function getAllowedDataTypes(dataSerializer) {
+ switch (dataSerializer) {
+ case 'utf8':
+ return ['String'];
+ case 'urlencoded':
+ return ['Object'];
+ default:
+ return ['Array', 'Object'];
+ }
+ }
+
+ function getProcessedData(data, dataSerializer) {
+ var currentDataType = jsUtil.getTypeOf(data);
+ var allowedDataTypes = getAllowedDataTypes(dataSerializer);
+
+ if (allowedDataTypes.indexOf(currentDataType) === -1) {
+ throw new Error(messages.DATA_TYPE_MISMATCH + ' ' + allowedDataTypes.join(', '));
+ }
+
+ if (dataSerializer === 'utf8') {
+ data = { text: data };
+ }
+
+ return data;
+ }
+
+ function handleMissingCallbacks(successFn, failFn) {
+ if (jsUtil.getTypeOf(successFn) !== 'Function') {
+ throw new Error(messages.MANDATORY_SUCCESS);
+ }
+
+ if (jsUtil.getTypeOf(failFn) !== 'Function') {
+ throw new Error(messages.MANDATORY_FAIL);
+ }
+ }
+
+ function handleMissingOptions(options, globals) {
+ options = options || {};
+
+ return {
+ method: checkHttpMethod(options.method || validHttpMethods[0]),
+ responseType: checkResponseType(options.responseType || validResponseTypes[0]),
+ serializer: checkSerializer(options.serializer || globals.serializer),
+ timeout: checkTimeoutValue(options.timeout || globals.timeout),
+ followRedirect: checkFollowRedirectValue(options.followRedirect || globals.followRedirect),
+ headers: checkHeadersObject(options.headers || {}),
+ params: checkParamsObject(options.params || {}),
+ data: jsUtil.getTypeOf(options.data) === 'Undefined' ? null : options.data,
+ filePath: options.filePath || '',
+ name: options.name || ''
+ };
+ }
+};
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/js-util.js b/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/js-util.js
new file mode 100644
index 0000000..ff0db76
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/js-util.js
@@ -0,0 +1,32 @@
+cordova.define("cordova-plugin-advanced-http.js-util", function(require, exports, module) { module.exports = {
+ // typeof is not working reliably in JS
+ getTypeOf: function (object) {
+ switch (Object.prototype.toString.call(object)) {
+ case '[object Array]':
+ return 'Array';
+ case '[object Blob]':
+ return 'Blob';
+ case '[object ArrayBuffer]':
+ return 'ArrayBuffer';
+ case '[object Boolean]':
+ return 'Boolean';
+ case '[object Function]':
+ return 'Function';
+ case '[object Null]':
+ return 'Null';
+ case '[object Number]':
+ return 'Number';
+ case '[object Object]':
+ return 'Object';
+ case '[object String]':
+ return 'String';
+ case '[object Undefined]':
+ return 'Undefined';
+ default:
+ return 'Unknown';
+ }
+ }
+}
+
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/local-storage-store.js b/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/local-storage-store.js
new file mode 100644
index 0000000..05cd38a
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/local-storage-store.js
@@ -0,0 +1,183 @@
+cordova.define("cordova-plugin-advanced-http.local-storage-store", function(require, exports, module) { /*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Exponent
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Based on "tough-cookie-web-storage-store" v1.0.0
+ * Thanks James Ide: https://github.com/exponentjs/tough-cookie-web-storage-store
+ *
+ * Modified by Sefa Ilkimen for cordova plugin integration
+ *
+ */
+
+'use strict';
+
+module.exports = function init(ToughCookie, _) {
+ function WebStorageCookieStore(storage, storeKey) {
+ ToughCookie.Store.call(this);
+ this._storage = storage;
+ this._storeKey = storeKey || '__cookieStore__';
+ this.synchronous = true;
+ }
+
+ WebStorageCookieStore.prototype = Object.create(ToughCookie.Store);
+
+ WebStorageCookieStore.prototype.findCookie = function (domain, path, key, callback) {
+ var store = this._readStore();
+ var cookie = _.get(store, [domain, path, key], null);
+
+ callback(null, ToughCookie.Cookie.fromJSON(cookie));
+ };
+
+ WebStorageCookieStore.prototype.findCookies = function (domain, path, callback) {
+ if (!domain) {
+ callback(null, []);
+ return;
+ }
+
+ var that = this;
+ var cookies = [];
+ var store = this._readStore();
+ var domains = ToughCookie.permuteDomain(domain) || [domain];
+
+ domains.forEach(function (domain) {
+ if (!store[domain]) {
+ return;
+ }
+
+ var matchingPaths = Object.keys(store[domain]);
+
+ if (path != null) {
+ matchingPaths = matchingPaths.filter(function (cookiePath) {
+ return that._isOnPath(cookiePath, path);
+ });
+ }
+
+ matchingPaths.forEach(function (path) {
+ Array.prototype.push.apply(cookies, _.values(store[domain][path]));
+ });
+ });
+
+ cookies = cookies.map(function (cookie) {
+ return ToughCookie.Cookie.fromJSON(cookie);
+ });
+
+ callback(null, cookies);
+ };
+
+ /**
+ * Returns whether `cookiePath` is on the given `urlPath`
+ */
+ WebStorageCookieStore.prototype._isOnPath = function (cookiePath, urlPath) {
+ if (!cookiePath) {
+ return false;
+ }
+
+ if (cookiePath === urlPath) {
+ return true;
+ }
+
+ if (urlPath.indexOf(cookiePath) !== 0) {
+ return false;
+ }
+
+ if (cookiePath[cookiePath.length - 1] !== '/' && urlPath[cookiePath.length] !== '/') {
+ return false;
+ }
+
+ return true;
+ };
+
+ WebStorageCookieStore.prototype.putCookie = function (cookie, callback) {
+ var store = this._readStore();
+
+ _.set(store, [cookie.domain, cookie.path, cookie.key], cookie);
+ this._writeStore(store);
+ callback(null);
+ };
+
+ WebStorageCookieStore.prototype.updateCookie = function (oldCookie, newCookie, callback) {
+ this.putCookie(newCookie, callback);
+ };
+
+
+ WebStorageCookieStore.prototype.removeCookie = function (domain, path, key, callback) {
+ var store = this._readStore();
+
+ _.unset(store, [domain, path, key]);
+ this._writeStore(store);
+ callback(null);
+ };
+
+ WebStorageCookieStore.prototype.removeCookies = function (domain, path, callback) {
+ var store = this._readStore();
+
+ if (path == null) {
+ _.unset(store, [domain]);
+ } else {
+ _.unset(store, [domain, path]);
+ }
+
+ this._writeStore(store);
+ callback(null);
+ };
+
+ WebStorageCookieStore.prototype.getAllCookies = function (callback) {
+ var cookies = [];
+ var store = this._readStore();
+
+ Object.keys(store).forEach(function (domain) {
+ Object.keys(store[domain]).forEach(function (path) {
+ Array.protype.push.apply(cookies, _.values(store[domain][path]));
+ });
+ });
+
+ cookies = cookies.map(function (cookie) {
+ return ToughCookie.Cookie.fromJSON(cookie);
+ });
+
+ cookies.sort(function (c1, c2) {
+ return (c1.creationIndex || 0) - (c2.creationIndex || 0);
+ });
+
+ callback(null, cookies);
+ };
+
+ WebStorageCookieStore.prototype._readStore = function () {
+ var json = this._storage.getItem(this._storeKey);
+
+ if (json !== null) {
+ try {
+ return JSON.parse(json);
+ } catch (e) { }
+ }
+
+ return {};
+ };
+
+ WebStorageCookieStore.prototype._writeStore = function (store) {
+ this._storage.setItem(this._storeKey, JSON.stringify(store));
+ };
+
+ return WebStorageCookieStore;
+};
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/lodash.js b/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/lodash.js
new file mode 100644
index 0000000..956c885
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/lodash.js
@@ -0,0 +1,21 @@
+cordova.define("cordova-plugin-advanced-http.lodash", function(require, exports, module) { /**
+ * @license
+ * Lodash (Custom Build) lodash.com/license | Underscore.js 1.8.3 underscorejs.org/LICENSE
+ * Build: `lodash include="get,set,unset,values" exports="node"`
+ */
+;(function(){function t(t,e){for(var r=-1,n=null==t?0:t.length,o=Array(n);++r<n;)o[r]=e(t[r],r,t);return o}function e(t){return function(e){return t(e)}}function r(e,r){return t(r,function(t){return e[t]})}function n(){}function o(t){var e=-1,r=null==t?0:t.length;for(this.clear();++e<r;){var n=t[e];this.set(n[0],n[1])}}function u(t){var e=-1,r=null==t?0:t.length;for(this.clear();++e<r;){var n=t[e];this.set(n[0],n[1])}}function i(t){var e=-1,r=null==t?0:t.length;for(this.clear();++e<r;){var n=t[e];this.set(n[0],n[1]);
+}}function c(t,e){for(var r=t.length;r--;)if(m(t[r][0],e))return r;return-1}function a(t,e){e=h(e,t);for(var r=0,n=e.length;null!=t&&r<n;)t=t[j(e[r++])];return r&&r==n?t:E}function l(t){if(null==t)return t===E?"[object Undefined]":"[object Null]";t=Object(t);var e;if(nt&&nt in t){var r=Q.call(t,nt),n=t[nt];try{t[nt]=E,e=true}catch(t){}var o=Y.call(t);e&&(r?t[nt]=n:delete t[nt]),e=o}else e=Y.call(t);return e}function s(t){return w(t)&&"[object Arguments]"==l(t)}function f(t){return w(t)&&z(t.length)&&!!M[l(t)];
+}function p(e){if(typeof e=="string")return e;if(ft(e))return t(e,p)+"";if(x(e))return at?at.call(e):"";var r=e+"";return"0"==r&&1/e==-T?"-0":r}function h(t,e){var r;return ft(t)?r=t:(ft(t)?r=false:(r=typeof t,r=!("number"!=r&&"symbol"!=r&&"boolean"!=r&&null!=t&&!x(t))||(B.test(t)||!I.test(t)||null!=e&&t in Object(e))),r=r?[t]:lt(F(t))),r}function y(t,e){var r=t.__data__,n=typeof e;return("string"==n||"number"==n||"symbol"==n||"boolean"==n?"__proto__"!==e:null===e)?r[typeof e=="string"?"string":"hash"]:r.map;
+}function b(t,e){var r=null==t?E:t[e];return(!S(r)||X&&X in r?0:(O(r)?Z:L).test(g(r)))?r:E}function _(t,e){return e=null==e?9007199254740991:e,!!e&&(typeof t=="number"||R.test(t))&&-1<t&&0==t%1&&t<e}function j(t){if(typeof t=="string"||x(t))return t;var e=t+"";return"0"==e&&1/t==-T?"-0":e}function g(t){if(null!=t){try{return K.call(t)}catch(t){}return t+""}return""}function v(t){var e=null==t?0:t.length;return e?t[e-1]:E}function d(t,e){function r(){var n=arguments,o=e?e.apply(this,n):n[0],u=r.cache;
+return u.has(o)?u.get(o):(n=t.apply(this,n),r.cache=u.set(o,n)||u,n)}if(typeof t!="function"||null!=e&&typeof e!="function")throw new TypeError("Expected a function");return r.cache=new(d.Cache||i),r}function m(t,e){return t===e||t!==t&&e!==e}function A(t){return null!=t&&z(t.length)&&!O(t)}function O(t){return!!S(t)&&(t=l(t),"[object Function]"==t||"[object GeneratorFunction]"==t||"[object AsyncFunction]"==t||"[object Proxy]"==t)}function z(t){return typeof t=="number"&&-1<t&&0==t%1&&9007199254740991>=t;
+}function S(t){var e=typeof t;return null!=t&&("object"==e||"function"==e)}function w(t){return null!=t&&typeof t=="object"}function x(t){return typeof t=="symbol"||w(t)&&"[object Symbol]"==l(t)}function F(t){return null==t?"":p(t)}function $(t){if(A(t)){var e=ft(t),r=!e&&st(t),n=!e&&!r&&pt(t),o=!e&&!r&&!n&&ht(t);if(e=e||r||n||o){for(var r=t.length,u=String,i=-1,c=Array(r);++i<r;)c[i]=u(i);r=c}else r=[];var a,u=r.length;for(a in t)!Q.call(t,a)||e&&("length"==a||n&&("offset"==a||"parent"==a)||o&&("buffer"==a||"byteLength"==a||"byteOffset"==a)||_(a,u))||r.push(a);
+t=r}else if(a=t&&t.constructor,t===(typeof a=="function"&&a.prototype||H)){a=[];for(n in Object(t))Q.call(t,n)&&"constructor"!=n&&a.push(n);t=a}else t=ut(t);return t}function k(){return false}var E,T=1/0,I=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,B=/^\w*$/,P=/^\./,U=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,C=/\\(\\)?/g,L=/^\[object .+?Constructor\]$/,R=/^(?:0|[1-9]\d*)$/,M={};M["[object Float32Array]"]=M["[object Float64Array]"]=M["[object Int8Array]"]=M["[object Int16Array]"]=M["[object Int32Array]"]=M["[object Uint8Array]"]=M["[object Uint8ClampedArray]"]=M["[object Uint16Array]"]=M["[object Uint32Array]"]=true,
+M["[object Arguments]"]=M["[object Array]"]=M["[object ArrayBuffer]"]=M["[object Boolean]"]=M["[object DataView]"]=M["[object Date]"]=M["[object Error]"]=M["[object Function]"]=M["[object Map]"]=M["[object Number]"]=M["[object Object]"]=M["[object RegExp]"]=M["[object Set]"]=M["[object String]"]=M["[object WeakMap]"]=false;var N,D=typeof global=="object"&&global&&global.Object===Object&&global,V=typeof self=="object"&&self&&self.Object===Object&&self,q=D||V||Function("return this")(),G=(V=typeof exports=="object"&&exports&&!exports.nodeType&&exports)&&typeof module=="object"&&module&&!module.nodeType&&module,W=G&&G.exports===V,D=W&&D.process;
+t:{try{N=D&&D.binding&&D.binding("util");break t}catch(t){}N=void 0}N=N&&N.isTypedArray;var D=Array.prototype,H=Object.prototype,J=q["__core-js_shared__"],K=Function.prototype.toString,Q=H.hasOwnProperty,X=function(){var t=/[^.]+$/.exec(J&&J.keys&&J.keys.IE_PROTO||"");return t?"Symbol(src)_1."+t:""}(),Y=H.toString,Z=RegExp("^"+K.call(Q).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),tt=W?q.Buffer:E,W=q.Symbol,et=H.propertyIsEnumerable,rt=D.splice,nt=W?W.toStringTag:E,ot=function(){
+try{var t=b(Object,"defineProperty");return t({},"",{}),t}catch(t){}}(),D=tt?tt.isBuffer:E,ut=function(t,e){return function(r){return t(e(r))}}(Object.keys,Object),it=b(q,"Map"),ct=b(Object,"create"),at=(q=W?W.prototype:E)?q.toString:E;o.prototype.clear=function(){this.__data__=ct?ct(null):{},this.size=0},o.prototype.delete=function(t){return t=this.has(t)&&delete this.__data__[t],this.size-=t?1:0,t},o.prototype.get=function(t){var e=this.__data__;return ct?(t=e[t],"__lodash_hash_undefined__"===t?E:t):Q.call(e,t)?e[t]:E;
+},o.prototype.has=function(t){var e=this.__data__;return ct?e[t]!==E:Q.call(e,t)},o.prototype.set=function(t,e){var r=this.__data__;return this.size+=this.has(t)?0:1,r[t]=ct&&e===E?"__lodash_hash_undefined__":e,this},u.prototype.clear=function(){this.__data__=[],this.size=0},u.prototype.delete=function(t){var e=this.__data__;return t=c(e,t),!(0>t)&&(t==e.length-1?e.pop():rt.call(e,t,1),--this.size,true)},u.prototype.get=function(t){var e=this.__data__;return t=c(e,t),0>t?E:e[t][1]},u.prototype.has=function(t){
+return-1<c(this.__data__,t)},u.prototype.set=function(t,e){var r=this.__data__,n=c(r,t);return 0>n?(++this.size,r.push([t,e])):r[n][1]=e,this},i.prototype.clear=function(){this.size=0,this.__data__={hash:new o,map:new(it||u),string:new o}},i.prototype.delete=function(t){return t=y(this,t).delete(t),this.size-=t?1:0,t},i.prototype.get=function(t){return y(this,t).get(t)},i.prototype.has=function(t){return y(this,t).has(t)},i.prototype.set=function(t,e){var r=y(this,t),n=r.size;return r.set(t,e),this.size+=r.size==n?0:1,
+this};var lt=function(t){t=d(t,function(t){return 500===e.size&&e.clear(),t});var e=t.cache;return t}(function(t){var e=[];return P.test(t)&&e.push(""),t.replace(U,function(t,r,n,o){e.push(n?o.replace(C,"$1"):r||t)}),e});d.Cache=i;var st=s(function(){return arguments}())?s:function(t){return w(t)&&Q.call(t,"callee")&&!et.call(t,"callee")},ft=Array.isArray,pt=D||k,ht=N?e(N):f;n.keys=$,n.memoize=d,n.set=function(t,e,r){if(null!=t&&S(t)){e=h(e,t);for(var n=-1,o=e.length,u=o-1,i=t;null!=i&&++n<o;){var c=j(e[n]),a=r;
+if(n!=u){var l=i[c],a=E;a===E&&(a=S(l)?l:_(e[n+1])?[]:{})}var s=i,l=c,f=s[l];Q.call(s,l)&&m(f,a)&&(a!==E||l in s)||("__proto__"==l&&ot?ot(s,l,{configurable:true,enumerable:true,value:a,writable:true}):s[l]=a),i=i[c]}}return t},n.unset=function(t,e){var r;if(null==t)r=true;else{var n=t,o=r=h(e,n);if(!(2>o.length)){var u=0,i=-1,c=-1,l=o.length;for(0>u&&(u=-u>l?0:l+u),i=i>l?l:i,0>i&&(i+=l),l=u>i?0:i-u>>>0,u>>>=0,i=Array(l);++c<l;)i[c]=o[c+u];n=a(n,i)}r=j(v(r)),r=!(null!=n&&Q.call(n,r))||delete n[r]}return r;
+},n.values=function(t){return null==t?[]:r(t,$(t))},n.eq=m,n.get=function(t,e,r){return t=null==t?E:a(t,e),t===E?r:t},n.isArguments=st,n.isArray=ft,n.isArrayLike=A,n.isBuffer=pt,n.isFunction=O,n.isLength=z,n.isObject=S,n.isObjectLike=w,n.isSymbol=x,n.isTypedArray=ht,n.last=v,n.stubFalse=k,n.toString=F,n.VERSION="4.17.1",G&&((G.exports=n)._=n,V._=n)}).call(this);
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/messages.js b/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/messages.js
new file mode 100644
index 0000000..0feefaf
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/messages.js
@@ -0,0 +1,21 @@
+cordova.define("cordova-plugin-advanced-http.messages", function(require, exports, module) { module.exports = {
+ ADDING_COOKIES_NOT_SUPPORTED: 'advanced-http: "setHeader" does not support adding cookies, please use "setCookie" function instead',
+ DATA_TYPE_MISMATCH: 'advanced-http: "data" argument supports only following data types:',
+ INVALID_CLIENT_AUTH_ALIAS: 'advanced-http: invalid client certificate alias, needs to be a string or undefined',
+ INVALID_CLIENT_AUTH_MODE: 'advanced-http: invalid client certificate authentication mode, supported modes are:',
+ INVALID_CLIENT_AUTH_OPTIONS: 'advanced-http: invalid client certificate authentication options, needs to be an object',
+ INVALID_CLIENT_AUTH_PKCS_PASSWORD: 'advanced-http: invalid PKCS12 container password, needs to be a string',
+ INVALID_CLIENT_AUTH_RAW_PKCS: 'advanced-http: invalid PKCS12 container, needs to be an array buffer',
+ INVALID_DATA_SERIALIZER: 'advanced-http: invalid serializer, supported serializers are:',
+ INVALID_FOLLOW_REDIRECT_VALUE: 'advanced-http: invalid follow redirect value, needs to be a boolean value',
+ INVALID_HEADERS_VALUE: 'advanced-http: header values must be strings',
+ INVALID_HTTP_METHOD: 'advanced-http: invalid HTTP method, supported methods are:',
+ INVALID_PARAMS_VALUE: 'advanced-http: invalid params object, needs to be an object with strings',
+ INVALID_RESPONSE_TYPE: 'advanced-http: invalid response type, supported types are:',
+ INVALID_SSL_CERT_MODE: 'advanced-http: invalid SSL cert mode, supported modes are:',
+ INVALID_TIMEOUT_VALUE: 'advanced-http: invalid timeout value, needs to be a positive numeric value',
+ MANDATORY_FAIL: 'advanced-http: missing mandatory "onFail" callback function',
+ MANDATORY_SUCCESS: 'advanced-http: missing mandatory "onSuccess" callback function',
+};
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/public-interface.js b/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/public-interface.js
new file mode 100644
index 0000000..a7dea53
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/public-interface.js
@@ -0,0 +1,201 @@
+cordova.define("cordova-plugin-advanced-http.public-interface", function(require, exports, module) { module.exports = function init(exec, cookieHandler, urlUtil, helpers, globalConfigs) {
+ const publicInterface = {
+ getBasicAuthHeader: getBasicAuthHeader,
+ useBasicAuth: useBasicAuth,
+ getHeaders: getHeaders,
+ setHeader: setHeader,
+ getDataSerializer: getDataSerializer,
+ setDataSerializer: setDataSerializer,
+ setCookie: setCookie,
+ clearCookies: clearCookies,
+ removeCookies: removeCookies,
+ getCookieString: getCookieString,
+ getRequestTimeout: getRequestTimeout,
+ setRequestTimeout: setRequestTimeout,
+ getFollowRedirect: getFollowRedirect,
+ setFollowRedirect: setFollowRedirect,
+ // @DEPRECATED
+ disableRedirect: disableRedirect,
+ // @DEPRECATED
+ setSSLCertMode: setServerTrustMode,
+ setServerTrustMode: setServerTrustMode,
+ setClientAuthMode: setClientAuthMode,
+ sendRequest: sendRequest,
+ post: post,
+ get: get,
+ put: put,
+ patch: patch,
+ delete: del,
+ head: head,
+ uploadFile: uploadFile,
+ downloadFile: downloadFile
+ };
+
+ function getBasicAuthHeader(username, password) {
+ return { 'Authorization': 'Basic ' + helpers.b64EncodeUnicode(username + ':' + password) };
+ }
+
+ function useBasicAuth(username, password) {
+ this.setHeader('*', 'Authorization', 'Basic ' + helpers.b64EncodeUnicode(username + ':' + password));
+ }
+
+ function getHeaders(host) {
+ return globalConfigs.headers[host || '*'] || null;
+ }
+
+ function setHeader() {
+ // this one is for being backward compatible
+ var host = '*';
+ var header = arguments[0];
+ var value = arguments[1];
+
+ if (arguments.length === 3) {
+ host = arguments[0];
+ header = arguments[1];
+ value = arguments[2];
+ }
+
+ helpers.checkForBlacklistedHeaderKey(header);
+ helpers.checkForInvalidHeaderValue(value);
+
+ globalConfigs.headers[host] = globalConfigs.headers[host] || {};
+ globalConfigs.headers[host][header] = value;
+ }
+
+ function getDataSerializer() {
+ return globalConfigs.serializer;
+ }
+
+ function setDataSerializer(serializer) {
+ globalConfigs.serializer = helpers.checkSerializer(serializer);
+ }
+
+ function setCookie(url, cookie, options) {
+ cookieHandler.setCookie(url, cookie, options);
+ }
+
+ function clearCookies() {
+ cookieHandler.clearCookies();
+ }
+
+ function removeCookies(url, callback) {
+ cookieHandler.removeCookies(url, callback);
+ }
+
+ function getCookieString(url) {
+ return cookieHandler.getCookieString(url);
+ }
+
+ function getRequestTimeout() {
+ return globalConfigs.timeout;
+ }
+
+ function setRequestTimeout(timeout) {
+ globalConfigs.timeout = helpers.checkTimeoutValue(timeout);
+ }
+
+ function getFollowRedirect() {
+ return globalConfigs.followRedirect;
+ }
+
+ function setFollowRedirect(follow) {
+ globalConfigs.followRedirect = helpers.checkFollowRedirectValue(follow);
+ }
+
+ // @DEPRECATED
+ function disableRedirect(disable, success, failure) {
+ helpers.handleMissingCallbacks(success, failure);
+
+ setFollowRedirect(!disable);
+ success();
+ }
+
+ function setServerTrustMode(mode, success, failure) {
+ helpers.handleMissingCallbacks(success, failure);
+
+ return exec(success, failure, 'CordovaHttpPlugin', 'setServerTrustMode', [helpers.checkSSLCertMode(mode)]);
+ }
+
+ function setClientAuthMode() {
+ var mode = arguments[0];
+ var options = null;
+ var success = arguments[1];
+ var failure = arguments[2];
+
+ if (arguments.length === 4) {
+ options = arguments[1];
+ success = arguments[2];
+ failure = arguments[3];
+ }
+
+ mode = helpers.checkClientAuthMode(mode);
+ options = helpers.checkClientAuthOptions(mode, options);
+
+ helpers.handleMissingCallbacks(success, failure);
+
+ return exec(success, failure, 'CordovaHttpPlugin', 'setClientAuthMode', [mode, options.alias, options.rawPkcs, options.pkcsPassword]);
+ }
+
+ function sendRequest(url, options, success, failure) {
+ helpers.handleMissingCallbacks(success, failure);
+
+ options = helpers.handleMissingOptions(options, globalConfigs);
+ url = urlUtil.appendQueryParamsString(url, urlUtil.serializeQueryParams(options.params, true));
+
+ var headers = helpers.getMergedHeaders(url, options.headers, globalConfigs.headers);
+
+ var onFail = helpers.injectCookieHandler(url, failure);
+ var onSuccess = helpers.injectCookieHandler(url, helpers.injectRawResponseHandler(options.responseType, success));
+
+ switch (options.method) {
+ case 'post':
+ case 'put':
+ case 'patch':
+ var data = helpers.getProcessedData(options.data, options.serializer);
+ return exec(onSuccess, onFail, 'CordovaHttpPlugin', options.method, [url, data, options.serializer, headers, options.timeout, options.followRedirect, options.responseType]);
+ case 'upload':
+ return exec(onSuccess, onFail, 'CordovaHttpPlugin', 'uploadFile', [url, headers, options.filePath, options.name, options.timeout, options.followRedirect, options.responseType]);
+ case 'download':
+ var onDownloadSuccess = helpers.injectCookieHandler(url, helpers.injectFileEntryHandler(success));
+ return exec(onDownloadSuccess, onFail, 'CordovaHttpPlugin', 'downloadFile', [url, headers, options.filePath, options.timeout, options.followRedirect]);
+ default:
+ return exec(onSuccess, onFail, 'CordovaHttpPlugin', options.method, [url, headers, options.timeout, options.followRedirect, options.responseType]);
+ }
+ }
+
+ function post(url, data, headers, success, failure) {
+ return publicInterface.sendRequest(url, { method: 'post', data: data, headers: headers }, success, failure);
+ };
+
+ function get(url, params, headers, success, failure) {
+ return publicInterface.sendRequest(url, { method: 'get', params: params, headers: headers }, success, failure);
+ };
+
+ function put(url, data, headers, success, failure) {
+ return publicInterface.sendRequest(url, { method: 'put', data: data, headers: headers }, success, failure);
+ }
+
+ function patch(url, data, headers, success, failure) {
+ return publicInterface.sendRequest(url, { method: 'patch', data: data, headers: headers }, success, failure);
+ }
+
+ function del(url, params, headers, success, failure) {
+ return publicInterface.sendRequest(url, { method: 'delete', params: params, headers: headers }, success, failure);
+ }
+
+ function head(url, params, headers, success, failure) {
+ return publicInterface.sendRequest(url, { method: 'head', params: params, headers: headers }, success, failure);
+ }
+
+ function uploadFile(url, params, headers, filePath, name, success, failure) {
+ return publicInterface.sendRequest(url, { method: 'upload', params: params, headers: headers, filePath: filePath, name: name }, success, failure);
+ }
+
+ function downloadFile(url, params, headers, filePath, success, failure) {
+ return publicInterface.sendRequest(url, { method: 'download', params: params, headers: headers, filePath: filePath }, success, failure);
+ }
+
+ return publicInterface;
+}
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/umd-tough-cookie.js b/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/umd-tough-cookie.js
new file mode 100644
index 0000000..47c162e
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/umd-tough-cookie.js
@@ -0,0 +1,5090 @@
+cordova.define("cordova-plugin-advanced-http.tough-cookie", function(require, exports, module) { (function webpackUniversalModuleDefinition(root, factory) {
+ if(typeof exports === 'object' && typeof module === 'object')
+ module.exports = factory();
+ else if(typeof define === 'function' && define.amd)
+ define([], factory);
+ else if(typeof exports === 'object')
+ exports["ToughCookie"] = factory();
+ else
+ root["ToughCookie"] = factory();
+})(this, function() {
+return /******/ (function(modules) { // webpackBootstrap
+/******/ // The module cache
+/******/ var installedModules = {};
+
+/******/ // The require function
+/******/ function __webpack_require__(moduleId) {
+
+/******/ // Check if module is in cache
+/******/ if(installedModules[moduleId])
+/******/ return installedModules[moduleId].exports;
+
+/******/ // Create a new module (and put it into the cache)
+/******/ var module = installedModules[moduleId] = {
+/******/ exports: {},
+/******/ id: moduleId,
+/******/ loaded: false
+/******/ };
+
+/******/ // Execute the module function
+/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+
+/******/ // Flag the module as loaded
+/******/ module.loaded = true;
+
+/******/ // Return the exports of the module
+/******/ return module.exports;
+/******/ }
+
+
+/******/ // expose the modules object (__webpack_modules__)
+/******/ __webpack_require__.m = modules;
+
+/******/ // expose the module cache
+/******/ __webpack_require__.c = installedModules;
+
+/******/ // __webpack_public_path__
+/******/ __webpack_require__.p = "";
+
+/******/ // Load entry module and return exports
+/******/ return __webpack_require__(0);
+/******/ })
+/************************************************************************/
+/******/ ([
+/* 0 */
+/***/ (function(module, exports, __webpack_require__) {
+
+ /*!
+ * Copyright (c) 2015, Salesforce.com, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of Salesforce.com nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+ 'use strict';
+ var net = __webpack_require__(1);
+ var urlParse = __webpack_require__(2).parse;
+ var util = __webpack_require__(9);
+ var pubsuffix = __webpack_require__(13);
+ var Store = __webpack_require__(17).Store;
+ var MemoryCookieStore = __webpack_require__(18).MemoryCookieStore;
+ var pathMatch = __webpack_require__(20).pathMatch;
+ var VERSION = __webpack_require__(21).version;
+
+ var punycode;
+ try {
+ punycode = __webpack_require__(15);
+ } catch(e) {
+ console.warn("tough-cookie: can't load punycode; won't use punycode for domain normalization");
+ }
+
+ // From RFC6265 S4.1.1
+ // note that it excludes \x3B ";"
+ var COOKIE_OCTETS = /^[\x21\x23-\x2B\x2D-\x3A\x3C-\x5B\x5D-\x7E]+$/;
+
+ var CONTROL_CHARS = /[\x00-\x1F]/;
+
+ // From Chromium // '\r', '\n' and '\0' should be treated as a terminator in
+ // the "relaxed" mode, see:
+ // https://github.com/ChromiumWebApps/chromium/blob/b3d3b4da8bb94c1b2e061600df106d590fda3620/net/cookies/parsed_cookie.cc#L60
+ var TERMINATORS = ['\n', '\r', '\0'];
+
+ // RFC6265 S4.1.1 defines path value as 'any CHAR except CTLs or ";"'
+ // Note ';' is \x3B
+ var PATH_VALUE = /[\x20-\x3A\x3C-\x7E]+/;
+
+ // date-time parsing constants (RFC6265 S5.1.1)
+
+ var DATE_DELIM = /[\x09\x20-\x2F\x3B-\x40\x5B-\x60\x7B-\x7E]/;
+
+ var MONTH_TO_NUM = {
+ jan:0, feb:1, mar:2, apr:3, may:4, jun:5,
+ jul:6, aug:7, sep:8, oct:9, nov:10, dec:11
+ };
+ var NUM_TO_MONTH = [
+ 'Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'
+ ];
+ var NUM_TO_DAY = [
+ 'Sun','Mon','Tue','Wed','Thu','Fri','Sat'
+ ];
+
+ var MAX_TIME = 2147483647000; // 31-bit max
+ var MIN_TIME = 0; // 31-bit min
+
+ /*
+ * Parses a Natural number (i.e., non-negative integer) with either the
+ * <min>*<max>DIGIT ( non-digit *OCTET )
+ * or
+ * <min>*<max>DIGIT
+ * grammar (RFC6265 S5.1.1).
+ *
+ * The "trailingOK" boolean controls if the grammar accepts a
+ * "( non-digit *OCTET )" trailer.
+ */
+ function parseDigits(token, minDigits, maxDigits, trailingOK) {
+ var count = 0;
+ while (count < token.length) {
+ var c = token.charCodeAt(count);
+ // "non-digit = %x00-2F / %x3A-FF"
+ if (c <= 0x2F || c >= 0x3A) {
+ break;
+ }
+ count++;
+ }
+
+ // constrain to a minimum and maximum number of digits.
+ if (count < minDigits || count > maxDigits) {
+ return null;
+ }
+
+ if (!trailingOK && count != token.length) {
+ return null;
+ }
+
+ return parseInt(token.substr(0,count), 10);
+ }
+
+ function parseTime(token) {
+ var parts = token.split(':');
+ var result = [0,0,0];
+
+ /* RF6256 S5.1.1:
+ * time = hms-time ( non-digit *OCTET )
+ * hms-time = time-field ":" time-field ":" time-field
+ * time-field = 1*2DIGIT
+ */
+
+ if (parts.length !== 3) {
+ return null;
+ }
+
+ for (var i = 0; i < 3; i++) {
+ // "time-field" must be strictly "1*2DIGIT", HOWEVER, "hms-time" can be
+ // followed by "( non-digit *OCTET )" so therefore the last time-field can
+ // have a trailer
+ var trailingOK = (i == 2);
+ var num = parseDigits(parts[i], 1, 2, trailingOK);
+ if (num === null) {
+ return null;
+ }
+ result[i] = num;
+ }
+
+ return result;
+ }
+
+ function parseMonth(token) {
+ token = String(token).substr(0,3).toLowerCase();
+ var num = MONTH_TO_NUM[token];
+ return num >= 0 ? num : null;
+ }
+
+ /*
+ * RFC6265 S5.1.1 date parser (see RFC for full grammar)
+ */
+ function parseDate(str) {
+ if (!str) {
+ return;
+ }
+
+ /* RFC6265 S5.1.1:
+ * 2. Process each date-token sequentially in the order the date-tokens
+ * appear in the cookie-date
+ */
+ var tokens = str.split(DATE_DELIM);
+ if (!tokens) {
+ return;
+ }
+
+ var hour = null;
+ var minute = null;
+ var second = null;
+ var dayOfMonth = null;
+ var month = null;
+ var year = null;
+
+ for (var i=0; i<tokens.length; i++) {
+ var token = tokens[i].trim();
+ if (!token.length) {
+ continue;
+ }
+
+ var result;
+
+ /* 2.1. If the found-time flag is not set and the token matches the time
+ * production, set the found-time flag and set the hour- value,
+ * minute-value, and second-value to the numbers denoted by the digits in
+ * the date-token, respectively. Skip the remaining sub-steps and continue
+ * to the next date-token.
+ */
+ if (second === null) {
+ result = parseTime(token);
+ if (result) {
+ hour = result[0];
+ minute = result[1];
+ second = result[2];
+ continue;
+ }
+ }
+
+ /* 2.2. If the found-day-of-month flag is not set and the date-token matches
+ * the day-of-month production, set the found-day-of- month flag and set
+ * the day-of-month-value to the number denoted by the date-token. Skip
+ * the remaining sub-steps and continue to the next date-token.
+ */
+ if (dayOfMonth === null) {
+ // "day-of-month = 1*2DIGIT ( non-digit *OCTET )"
+ result = parseDigits(token, 1, 2, true);
+ if (result !== null) {
+ dayOfMonth = result;
+ continue;
+ }
+ }
+
+ /* 2.3. If the found-month flag is not set and the date-token matches the
+ * month production, set the found-month flag and set the month-value to
+ * the month denoted by the date-token. Skip the remaining sub-steps and
+ * continue to the next date-token.
+ */
+ if (month === null) {
+ result = parseMonth(token);
+ if (result !== null) {
+ month = result;
+ continue;
+ }
+ }
+
+ /* 2.4. If the found-year flag is not set and the date-token matches the
+ * year production, set the found-year flag and set the year-value to the
+ * number denoted by the date-token. Skip the remaining sub-steps and
+ * continue to the next date-token.
+ */
+ if (year === null) {
+ // "year = 2*4DIGIT ( non-digit *OCTET )"
+ result = parseDigits(token, 2, 4, true);
+ if (result !== null) {
+ year = result;
+ /* From S5.1.1:
+ * 3. If the year-value is greater than or equal to 70 and less
+ * than or equal to 99, increment the year-value by 1900.
+ * 4. If the year-value is greater than or equal to 0 and less
+ * than or equal to 69, increment the year-value by 2000.
+ */
+ if (year >= 70 && year <= 99) {
+ year += 1900;
+ } else if (year >= 0 && year <= 69) {
+ year += 2000;
+ }
+ }
+ }
+ }
+
+ /* RFC 6265 S5.1.1
+ * "5. Abort these steps and fail to parse the cookie-date if:
+ * * at least one of the found-day-of-month, found-month, found-
+ * year, or found-time flags is not set,
+ * * the day-of-month-value is less than 1 or greater than 31,
+ * * the year-value is less than 1601,
+ * * the hour-value is greater than 23,
+ * * the minute-value is greater than 59, or
+ * * the second-value is greater than 59.
+ * (Note that leap seconds cannot be represented in this syntax.)"
+ *
+ * So, in order as above:
+ */
+ if (
+ dayOfMonth === null || month === null || year === null || second === null ||
+ dayOfMonth < 1 || dayOfMonth > 31 ||
+ year < 1601 ||
+ hour > 23 ||
+ minute > 59 ||
+ second > 59
+ ) {
+ return;
+ }
+
+ return new Date(Date.UTC(year, month, dayOfMonth, hour, minute, second));
+ }
+
+ function formatDate(date) {
+ var d = date.getUTCDate(); d = d >= 10 ? d : '0'+d;
+ var h = date.getUTCHours(); h = h >= 10 ? h : '0'+h;
+ var m = date.getUTCMinutes(); m = m >= 10 ? m : '0'+m;
+ var s = date.getUTCSeconds(); s = s >= 10 ? s : '0'+s;
+ return NUM_TO_DAY[date.getUTCDay()] + ', ' +
+ d+' '+ NUM_TO_MONTH[date.getUTCMonth()] +' '+ date.getUTCFullYear() +' '+
+ h+':'+m+':'+s+' GMT';
+ }
+
+ // S5.1.2 Canonicalized Host Names
+ function canonicalDomain(str) {
+ if (str == null) {
+ return null;
+ }
+ str = str.trim().replace(/^\./,''); // S4.1.2.3 & S5.2.3: ignore leading .
+
+ // convert to IDN if any non-ASCII characters
+ if (punycode && /[^\u0001-\u007f]/.test(str)) {
+ str = punycode.toASCII(str);
+ }
+
+ return str.toLowerCase();
+ }
+
+ // S5.1.3 Domain Matching
+ function domainMatch(str, domStr, canonicalize) {
+ if (str == null || domStr == null) {
+ return null;
+ }
+ if (canonicalize !== false) {
+ str = canonicalDomain(str);
+ domStr = canonicalDomain(domStr);
+ }
+
+ /*
+ * "The domain string and the string are identical. (Note that both the
+ * domain string and the string will have been canonicalized to lower case at
+ * this point)"
+ */
+ if (str == domStr) {
+ return true;
+ }
+
+ /* "All of the following [three] conditions hold:" (order adjusted from the RFC) */
+
+ /* "* The string is a host name (i.e., not an IP address)." */
+ if (net.isIP(str)) {
+ return false;
+ }
+
+ /* "* The domain string is a suffix of the string" */
+ var idx = str.indexOf(domStr);
+ if (idx <= 0) {
+ return false; // it's a non-match (-1) or prefix (0)
+ }
+
+ // e.g "a.b.c".indexOf("b.c") === 2
+ // 5 === 3+2
+ if (str.length !== domStr.length + idx) { // it's not a suffix
+ return false;
+ }
+
+ /* "* The last character of the string that is not included in the domain
+ * string is a %x2E (".") character." */
+ if (str.substr(idx-1,1) !== '.') {
+ return false;
+ }
+
+ return true;
+ }
+
+
+ // RFC6265 S5.1.4 Paths and Path-Match
+
+ /*
+ * "The user agent MUST use an algorithm equivalent to the following algorithm
+ * to compute the default-path of a cookie:"
+ *
+ * Assumption: the path (and not query part or absolute uri) is passed in.
+ */
+ function defaultPath(path) {
+ // "2. If the uri-path is empty or if the first character of the uri-path is not
+ // a %x2F ("/") character, output %x2F ("/") and skip the remaining steps.
+ if (!path || path.substr(0,1) !== "/") {
+ return "/";
+ }
+
+ // "3. If the uri-path contains no more than one %x2F ("/") character, output
+ // %x2F ("/") and skip the remaining step."
+ if (path === "/") {
+ return path;
+ }
+
+ var rightSlash = path.lastIndexOf("/");
+ if (rightSlash === 0) {
+ return "/";
+ }
+
+ // "4. Output the characters of the uri-path from the first character up to,
+ // but not including, the right-most %x2F ("/")."
+ return path.slice(0, rightSlash);
+ }
+
+ function trimTerminator(str) {
+ for (var t = 0; t < TERMINATORS.length; t++) {
+ var terminatorIdx = str.indexOf(TERMINATORS[t]);
+ if (terminatorIdx !== -1) {
+ str = str.substr(0,terminatorIdx);
+ }
+ }
+
+ return str;
+ }
+
+ function parseCookiePair(cookiePair, looseMode) {
+ cookiePair = trimTerminator(cookiePair);
+
+ var firstEq = cookiePair.indexOf('=');
+ if (looseMode) {
+ if (firstEq === 0) { // '=' is immediately at start
+ cookiePair = cookiePair.substr(1);
+ firstEq = cookiePair.indexOf('='); // might still need to split on '='
+ }
+ } else { // non-loose mode
+ if (firstEq <= 0) { // no '=' or is at start
+ return; // needs to have non-empty "cookie-name"
+ }
+ }
+
+ var cookieName, cookieValue;
+ if (firstEq <= 0) {
+ cookieName = "";
+ cookieValue = cookiePair.trim();
+ } else {
+ cookieName = cookiePair.substr(0, firstEq).trim();
+ cookieValue = cookiePair.substr(firstEq+1).trim();
+ }
+
+ if (CONTROL_CHARS.test(cookieName) || CONTROL_CHARS.test(cookieValue)) {
+ return;
+ }
+
+ var c = new Cookie();
+ c.key = cookieName;
+ c.value = cookieValue;
+ return c;
+ }
+
+ function parse(str, options) {
+ if (!options || typeof options !== 'object') {
+ options = {};
+ }
+ str = str.trim();
+
+ // We use a regex to parse the "name-value-pair" part of S5.2
+ var firstSemi = str.indexOf(';'); // S5.2 step 1
+ var cookiePair = (firstSemi === -1) ? str : str.substr(0, firstSemi);
+ var c = parseCookiePair(cookiePair, !!options.loose);
+ if (!c) {
+ return;
+ }
+
+ if (firstSemi === -1) {
+ return c;
+ }
+
+ // S5.2.3 "unparsed-attributes consist of the remainder of the set-cookie-string
+ // (including the %x3B (";") in question)." plus later on in the same section
+ // "discard the first ";" and trim".
+ var unparsed = str.slice(firstSemi + 1).trim();
+
+ // "If the unparsed-attributes string is empty, skip the rest of these
+ // steps."
+ if (unparsed.length === 0) {
+ return c;
+ }
+
+ /*
+ * S5.2 says that when looping over the items "[p]rocess the attribute-name
+ * and attribute-value according to the requirements in the following
+ * subsections" for every item. Plus, for many of the individual attributes
+ * in S5.3 it says to use the "attribute-value of the last attribute in the
+ * cookie-attribute-list". Therefore, in this implementation, we overwrite
+ * the previous value.
+ */
+ var cookie_avs = unparsed.split(';');
+ while (cookie_avs.length) {
+ var av = cookie_avs.shift().trim();
+ if (av.length === 0) { // happens if ";;" appears
+ continue;
+ }
+ var av_sep = av.indexOf('=');
+ var av_key, av_value;
+
+ if (av_sep === -1) {
+ av_key = av;
+ av_value = null;
+ } else {
+ av_key = av.substr(0,av_sep);
+ av_value = av.substr(av_sep+1);
+ }
+
+ av_key = av_key.trim().toLowerCase();
+
+ if (av_value) {
+ av_value = av_value.trim();
+ }
+
+ switch(av_key) {
+ case 'expires': // S5.2.1
+ if (av_value) {
+ var exp = parseDate(av_value);
+ // "If the attribute-value failed to parse as a cookie date, ignore the
+ // cookie-av."
+ if (exp) {
+ // over and underflow not realistically a concern: V8's getTime() seems to
+ // store something larger than a 32-bit time_t (even with 32-bit node)
+ c.expires = exp;
+ }
+ }
+ break;
+
+ case 'max-age': // S5.2.2
+ if (av_value) {
+ // "If the first character of the attribute-value is not a DIGIT or a "-"
+ // character ...[or]... If the remainder of attribute-value contains a
+ // non-DIGIT character, ignore the cookie-av."
+ if (/^-?[0-9]+$/.test(av_value)) {
+ var delta = parseInt(av_value, 10);
+ // "If delta-seconds is less than or equal to zero (0), let expiry-time
+ // be the earliest representable date and time."
+ c.setMaxAge(delta);
+ }
+ }
+ break;
+
+ case 'domain': // S5.2.3
+ // "If the attribute-value is empty, the behavior is undefined. However,
+ // the user agent SHOULD ignore the cookie-av entirely."
+ if (av_value) {
+ // S5.2.3 "Let cookie-domain be the attribute-value without the leading %x2E
+ // (".") character."
+ var domain = av_value.trim().replace(/^\./, '');
+ if (domain) {
+ // "Convert the cookie-domain to lower case."
+ c.domain = domain.toLowerCase();
+ }
+ }
+ break;
+
+ case 'path': // S5.2.4
+ /*
+ * "If the attribute-value is empty or if the first character of the
+ * attribute-value is not %x2F ("/"):
+ * Let cookie-path be the default-path.
+ * Otherwise:
+ * Let cookie-path be the attribute-value."
+ *
+ * We'll represent the default-path as null since it depends on the
+ * context of the parsing.
+ */
+ c.path = av_value && av_value[0] === "/" ? av_value : null;
+ break;
+
+ case 'secure': // S5.2.5
+ /*
+ * "If the attribute-name case-insensitively matches the string "Secure",
+ * the user agent MUST append an attribute to the cookie-attribute-list
+ * with an attribute-name of Secure and an empty attribute-value."
+ */
+ c.secure = true;
+ break;
+
+ case 'httponly': // S5.2.6 -- effectively the same as 'secure'
+ c.httpOnly = true;
+ break;
+
+ default:
+ c.extensions = c.extensions || [];
+ c.extensions.push(av);
+ break;
+ }
+ }
+
+ return c;
+ }
+
+ // avoid the V8 deoptimization monster!
+ function jsonParse(str) {
+ var obj;
+ try {
+ obj = JSON.parse(str);
+ } catch (e) {
+ return e;
+ }
+ return obj;
+ }
+
+ function fromJSON(str) {
+ if (!str) {
+ return null;
+ }
+
+ var obj;
+ if (typeof str === 'string') {
+ obj = jsonParse(str);
+ if (obj instanceof Error) {
+ return null;
+ }
+ } else {
+ // assume it's an Object
+ obj = str;
+ }
+
+ var c = new Cookie();
+ for (var i=0; i<Cookie.serializableProperties.length; i++) {
+ var prop = Cookie.serializableProperties[i];
+ if (obj[prop] === undefined ||
+ obj[prop] === Cookie.prototype[prop])
+ {
+ continue; // leave as prototype default
+ }
+
+ if (prop === 'expires' ||
+ prop === 'creation' ||
+ prop === 'lastAccessed')
+ {
+ if (obj[prop] === null) {
+ c[prop] = null;
+ } else {
+ c[prop] = obj[prop] == "Infinity" ?
+ "Infinity" : new Date(obj[prop]);
+ }
+ } else {
+ c[prop] = obj[prop];
+ }
+ }
+
+ return c;
+ }
+
+ /* Section 5.4 part 2:
+ * "* Cookies with longer paths are listed before cookies with
+ * shorter paths.
+ *
+ * * Among cookies that have equal-length path fields, cookies with
+ * earlier creation-times are listed before cookies with later
+ * creation-times."
+ */
+
+ function cookieCompare(a,b) {
+ var cmp = 0;
+
+ // descending for length: b CMP a
+ var aPathLen = a.path ? a.path.length : 0;
+ var bPathLen = b.path ? b.path.length : 0;
+ cmp = bPathLen - aPathLen;
+ if (cmp !== 0) {
+ return cmp;
+ }
+
+ // ascending for time: a CMP b
+ var aTime = a.creation ? a.creation.getTime() : MAX_TIME;
+ var bTime = b.creation ? b.creation.getTime() : MAX_TIME;
+ cmp = aTime - bTime;
+ if (cmp !== 0) {
+ return cmp;
+ }
+
+ // break ties for the same millisecond (precision of JavaScript's clock)
+ cmp = a.creationIndex - b.creationIndex;
+
+ return cmp;
+ }
+
+ // Gives the permutation of all possible pathMatch()es of a given path. The
+ // array is in longest-to-shortest order. Handy for indexing.
+ function permutePath(path) {
+ if (path === '/') {
+ return ['/'];
+ }
+ if (path.lastIndexOf('/') === path.length-1) {
+ path = path.substr(0,path.length-1);
+ }
+ var permutations = [path];
+ while (path.length > 1) {
+ var lindex = path.lastIndexOf('/');
+ if (lindex === 0) {
+ break;
+ }
+ path = path.substr(0,lindex);
+ permutations.push(path);
+ }
+ permutations.push('/');
+ return permutations;
+ }
+
+ function getCookieContext(url) {
+ if (url instanceof Object) {
+ return url;
+ }
+ // NOTE: decodeURI will throw on malformed URIs (see GH-32).
+ // Therefore, we will just skip decoding for such URIs.
+ try {
+ url = decodeURI(url);
+ }
+ catch(err) {
+ // Silently swallow error
+ }
+
+ return urlParse(url);
+ }
+
+ function Cookie(options) {
+ options = options || {};
+
+ Object.keys(options).forEach(function(prop) {
+ if (Cookie.prototype.hasOwnProperty(prop) &&
+ Cookie.prototype[prop] !== options[prop] &&
+ prop.substr(0,1) !== '_')
+ {
+ this[prop] = options[prop];
+ }
+ }, this);
+
+ this.creation = this.creation || new Date();
+
+ // used to break creation ties in cookieCompare():
+ Object.defineProperty(this, 'creationIndex', {
+ configurable: false,
+ enumerable: false, // important for assert.deepEqual checks
+ writable: true,
+ value: ++Cookie.cookiesCreated
+ });
+ }
+
+ Cookie.cookiesCreated = 0; // incremented each time a cookie is created
+
+ Cookie.parse = parse;
+ Cookie.fromJSON = fromJSON;
+
+ Cookie.prototype.key = "";
+ Cookie.prototype.value = "";
+
+ // the order in which the RFC has them:
+ Cookie.prototype.expires = "Infinity"; // coerces to literal Infinity
+ Cookie.prototype.maxAge = null; // takes precedence over expires for TTL
+ Cookie.prototype.domain = null;
+ Cookie.prototype.path = null;
+ Cookie.prototype.secure = false;
+ Cookie.prototype.httpOnly = false;
+ Cookie.prototype.extensions = null;
+
+ // set by the CookieJar:
+ Cookie.prototype.hostOnly = null; // boolean when set
+ Cookie.prototype.pathIsDefault = null; // boolean when set
+ Cookie.prototype.creation = null; // Date when set; defaulted by Cookie.parse
+ Cookie.prototype.lastAccessed = null; // Date when set
+ Object.defineProperty(Cookie.prototype, 'creationIndex', {
+ configurable: true,
+ enumerable: false,
+ writable: true,
+ value: 0
+ });
+
+ Cookie.serializableProperties = Object.keys(Cookie.prototype)
+ .filter(function(prop) {
+ return !(
+ Cookie.prototype[prop] instanceof Function ||
+ prop === 'creationIndex' ||
+ prop.substr(0,1) === '_'
+ );
+ });
+
+ Cookie.prototype.inspect = function inspect() {
+ var now = Date.now();
+ return 'Cookie="'+this.toString() +
+ '; hostOnly='+(this.hostOnly != null ? this.hostOnly : '?') +
+ '; aAge='+(this.lastAccessed ? (now-this.lastAccessed.getTime())+'ms' : '?') +
+ '; cAge='+(this.creation ? (now-this.creation.getTime())+'ms' : '?') +
+ '"';
+ };
+
+ // Use the new custom inspection symbol to add the custom inspect function if
+ // available.
+ if (util.inspect.custom) {
+ Cookie.prototype[util.inspect.custom] = Cookie.prototype.inspect;
+ }
+
+ Cookie.prototype.toJSON = function() {
+ var obj = {};
+
+ var props = Cookie.serializableProperties;
+ for (var i=0; i<props.length; i++) {
+ var prop = props[i];
+ if (this[prop] === Cookie.prototype[prop]) {
+ continue; // leave as prototype default
+ }
+
+ if (prop === 'expires' ||
+ prop === 'creation' ||
+ prop === 'lastAccessed')
+ {
+ if (this[prop] === null) {
+ obj[prop] = null;
+ } else {
+ obj[prop] = this[prop] == "Infinity" ? // intentionally not ===
+ "Infinity" : this[prop].toISOString();
+ }
+ } else if (prop === 'maxAge') {
+ if (this[prop] !== null) {
+ // again, intentionally not ===
+ obj[prop] = (this[prop] == Infinity || this[prop] == -Infinity) ?
+ this[prop].toString() : this[prop];
+ }
+ } else {
+ if (this[prop] !== Cookie.prototype[prop]) {
+ obj[prop] = this[prop];
+ }
+ }
+ }
+
+ return obj;
+ };
+
+ Cookie.prototype.clone = function() {
+ return fromJSON(this.toJSON());
+ };
+
+ Cookie.prototype.validate = function validate() {
+ if (!COOKIE_OCTETS.test(this.value)) {
+ return false;
+ }
+ if (this.expires != Infinity && !(this.expires instanceof Date) && !parseDate(this.expires)) {
+ return false;
+ }
+ if (this.maxAge != null && this.maxAge <= 0) {
+ return false; // "Max-Age=" non-zero-digit *DIGIT
+ }
+ if (this.path != null && !PATH_VALUE.test(this.path)) {
+ return false;
+ }
+
+ var cdomain = this.cdomain();
+ if (cdomain) {
+ if (cdomain.match(/\.$/)) {
+ return false; // S4.1.2.3 suggests that this is bad. domainMatch() tests confirm this
+ }
+ var suffix = pubsuffix.getPublicSuffix(cdomain);
+ if (suffix == null) { // it's a public suffix
+ return false;
+ }
+ }
+ return true;
+ };
+
+ Cookie.prototype.setExpires = function setExpires(exp) {
+ if (exp instanceof Date) {
+ this.expires = exp;
+ } else {
+ this.expires = parseDate(exp) || "Infinity";
+ }
+ };
+
+ Cookie.prototype.setMaxAge = function setMaxAge(age) {
+ if (age === Infinity || age === -Infinity) {
+ this.maxAge = age.toString(); // so JSON.stringify() works
+ } else {
+ this.maxAge = age;
+ }
+ };
+
+ // gives Cookie header format
+ Cookie.prototype.cookieString = function cookieString() {
+ var val = this.value;
+ if (val == null) {
+ val = '';
+ }
+ if (this.key === '') {
+ return val;
+ }
+ return this.key+'='+val;
+ };
+
+ // gives Set-Cookie header format
+ Cookie.prototype.toString = function toString() {
+ var str = this.cookieString();
+
+ if (this.expires != Infinity) {
+ if (this.expires instanceof Date) {
+ str += '; Expires='+formatDate(this.expires);
+ } else {
+ str += '; Expires='+this.expires;
+ }
+ }
+
+ if (this.maxAge != null && this.maxAge != Infinity) {
+ str += '; Max-Age='+this.maxAge;
+ }
+
+ if (this.domain && !this.hostOnly) {
+ str += '; Domain='+this.domain;
+ }
+ if (this.path) {
+ str += '; Path='+this.path;
+ }
+
+ if (this.secure) {
+ str += '; Secure';
+ }
+ if (this.httpOnly) {
+ str += '; HttpOnly';
+ }
+ if (this.extensions) {
+ this.extensions.forEach(function(ext) {
+ str += '; '+ext;
+ });
+ }
+
+ return str;
+ };
+
+ // TTL() partially replaces the "expiry-time" parts of S5.3 step 3 (setCookie()
+ // elsewhere)
+ // S5.3 says to give the "latest representable date" for which we use Infinity
+ // For "expired" we use 0
+ Cookie.prototype.TTL = function TTL(now) {
+ /* RFC6265 S4.1.2.2 If a cookie has both the Max-Age and the Expires
+ * attribute, the Max-Age attribute has precedence and controls the
+ * expiration date of the cookie.
+ * (Concurs with S5.3 step 3)
+ */
+ if (this.maxAge != null) {
+ return this.maxAge<=0 ? 0 : this.maxAge*1000;
+ }
+
+ var expires = this.expires;
+ if (expires != Infinity) {
+ if (!(expires instanceof Date)) {
+ expires = parseDate(expires) || Infinity;
+ }
+
+ if (expires == Infinity) {
+ return Infinity;
+ }
+
+ return expires.getTime() - (now || Date.now());
+ }
+
+ return Infinity;
+ };
+
+ // expiryTime() replaces the "expiry-time" parts of S5.3 step 3 (setCookie()
+ // elsewhere)
+ Cookie.prototype.expiryTime = function expiryTime(now) {
+ if (this.maxAge != null) {
+ var relativeTo = now || this.creation || new Date();
+ var age = (this.maxAge <= 0) ? -Infinity : this.maxAge*1000;
+ return relativeTo.getTime() + age;
+ }
+
+ if (this.expires == Infinity) {
+ return Infinity;
+ }
+ return this.expires.getTime();
+ };
+
+ // expiryDate() replaces the "expiry-time" parts of S5.3 step 3 (setCookie()
+ // elsewhere), except it returns a Date
+ Cookie.prototype.expiryDate = function expiryDate(now) {
+ var millisec = this.expiryTime(now);
+ if (millisec == Infinity) {
+ return new Date(MAX_TIME);
+ } else if (millisec == -Infinity) {
+ return new Date(MIN_TIME);
+ } else {
+ return new Date(millisec);
+ }
+ };
+
+ // This replaces the "persistent-flag" parts of S5.3 step 3
+ Cookie.prototype.isPersistent = function isPersistent() {
+ return (this.maxAge != null || this.expires != Infinity);
+ };
+
+ // Mostly S5.1.2 and S5.2.3:
+ Cookie.prototype.cdomain =
+ Cookie.prototype.canonicalizedDomain = function canonicalizedDomain() {
+ if (this.domain == null) {
+ return null;
+ }
+ return canonicalDomain(this.domain);
+ };
+
+ function CookieJar(store, options) {
+ if (typeof options === "boolean") {
+ options = {rejectPublicSuffixes: options};
+ } else if (options == null) {
+ options = {};
+ }
+ if (options.rejectPublicSuffixes != null) {
+ this.rejectPublicSuffixes = options.rejectPublicSuffixes;
+ }
+ if (options.looseMode != null) {
+ this.enableLooseMode = options.looseMode;
+ }
+
+ if (!store) {
+ store = new MemoryCookieStore();
+ }
+ this.store = store;
+ }
+ CookieJar.prototype.store = null;
+ CookieJar.prototype.rejectPublicSuffixes = true;
+ CookieJar.prototype.enableLooseMode = false;
+ var CAN_BE_SYNC = [];
+
+ CAN_BE_SYNC.push('setCookie');
+ CookieJar.prototype.setCookie = function(cookie, url, options, cb) {
+ var err;
+ var context = getCookieContext(url);
+ if (options instanceof Function) {
+ cb = options;
+ options = {};
+ }
+
+ var host = canonicalDomain(context.hostname);
+ var loose = this.enableLooseMode;
+ if (options.loose != null) {
+ loose = options.loose;
+ }
+
+ // S5.3 step 1
+ if (!(cookie instanceof Cookie)) {
+ cookie = Cookie.parse(cookie, { loose: loose });
+ }
+ if (!cookie) {
+ err = new Error("Cookie failed to parse");
+ return cb(options.ignoreError ? null : err);
+ }
+
+ // S5.3 step 2
+ var now = options.now || new Date(); // will assign later to save effort in the face of errors
+
+ // S5.3 step 3: NOOP; persistent-flag and expiry-time is handled by getCookie()
+
+ // S5.3 step 4: NOOP; domain is null by default
+
+ // S5.3 step 5: public suffixes
+ if (this.rejectPublicSuffixes && cookie.domain) {
+ var suffix = pubsuffix.getPublicSuffix(cookie.cdomain());
+ if (suffix == null) { // e.g. "com"
+ err = new Error("Cookie has domain set to a public suffix");
+ return cb(options.ignoreError ? null : err);
+ }
+ }
+
+ // S5.3 step 6:
+ if (cookie.domain) {
+ if (!domainMatch(host, cookie.cdomain(), false)) {
+ err = new Error("Cookie not in this host's domain. Cookie:"+cookie.cdomain()+" Request:"+host);
+ return cb(options.ignoreError ? null : err);
+ }
+
+ if (cookie.hostOnly == null) { // don't reset if already set
+ cookie.hostOnly = false;
+ }
+
+ } else {
+ cookie.hostOnly = true;
+ cookie.domain = host;
+ }
+
+ //S5.2.4 If the attribute-value is empty or if the first character of the
+ //attribute-value is not %x2F ("/"):
+ //Let cookie-path be the default-path.
+ if (!cookie.path || cookie.path[0] !== '/') {
+ cookie.path = defaultPath(context.pathname);
+ cookie.pathIsDefault = true;
+ }
+
+ // S5.3 step 8: NOOP; secure attribute
+ // S5.3 step 9: NOOP; httpOnly attribute
+
+ // S5.3 step 10
+ if (options.http === false && cookie.httpOnly) {
+ err = new Error("Cookie is HttpOnly and this isn't an HTTP API");
+ return cb(options.ignoreError ? null : err);
+ }
+
+ var store = this.store;
+
+ if (!store.updateCookie) {
+ store.updateCookie = function(oldCookie, newCookie, cb) {
+ this.putCookie(newCookie, cb);
+ };
+ }
+
+ function withCookie(err, oldCookie) {
+ if (err) {
+ return cb(err);
+ }
+
+ var next = function(err) {
+ if (err) {
+ return cb(err);
+ } else {
+ cb(null, cookie);
+ }
+ };
+
+ if (oldCookie) {
+ // S5.3 step 11 - "If the cookie store contains a cookie with the same name,
+ // domain, and path as the newly created cookie:"
+ if (options.http === false && oldCookie.httpOnly) { // step 11.2
+ err = new Error("old Cookie is HttpOnly and this isn't an HTTP API");
+ return cb(options.ignoreError ? null : err);
+ }
+ cookie.creation = oldCookie.creation; // step 11.3
+ cookie.creationIndex = oldCookie.creationIndex; // preserve tie-breaker
+ cookie.lastAccessed = now;
+ // Step 11.4 (delete cookie) is implied by just setting the new one:
+ store.updateCookie(oldCookie, cookie, next); // step 12
+
+ } else {
+ cookie.creation = cookie.lastAccessed = now;
+ store.putCookie(cookie, next); // step 12
+ }
+ }
+
+ store.findCookie(cookie.domain, cookie.path, cookie.key, withCookie);
+ };
+
+ // RFC6365 S5.4
+ CAN_BE_SYNC.push('getCookies');
+ CookieJar.prototype.getCookies = function(url, options, cb) {
+ var context = getCookieContext(url);
+ if (options instanceof Function) {
+ cb = options;
+ options = {};
+ }
+
+ var host = canonicalDomain(context.hostname);
+ var path = context.pathname || '/';
+
+ var secure = options.secure;
+ if (secure == null && context.protocol &&
+ (context.protocol == 'https:' || context.protocol == 'wss:'))
+ {
+ secure = true;
+ }
+
+ var http = options.http;
+ if (http == null) {
+ http = true;
+ }
+
+ var now = options.now || Date.now();
+ var expireCheck = options.expire !== false;
+ var allPaths = !!options.allPaths;
+ var store = this.store;
+
+ function matchingCookie(c) {
+ // "Either:
+ // The cookie's host-only-flag is true and the canonicalized
+ // request-host is identical to the cookie's domain.
+ // Or:
+ // The cookie's host-only-flag is false and the canonicalized
+ // request-host domain-matches the cookie's domain."
+ if (c.hostOnly) {
+ if (c.domain != host) {
+ return false;
+ }
+ } else {
+ if (!domainMatch(host, c.domain, false)) {
+ return false;
+ }
+ }
+
+ // "The request-uri's path path-matches the cookie's path."
+ if (!allPaths && !pathMatch(path, c.path)) {
+ return false;
+ }
+
+ // "If the cookie's secure-only-flag is true, then the request-uri's
+ // scheme must denote a "secure" protocol"
+ if (c.secure && !secure) {
+ return false;
+ }
+
+ // "If the cookie's http-only-flag is true, then exclude the cookie if the
+ // cookie-string is being generated for a "non-HTTP" API"
+ if (c.httpOnly && !http) {
+ return false;
+ }
+
+ // deferred from S5.3
+ // non-RFC: allow retention of expired cookies by choice
+ if (expireCheck && c.expiryTime() <= now) {
+ store.removeCookie(c.domain, c.path, c.key, function(){}); // result ignored
+ return false;
+ }
+
+ return true;
+ }
+
+ store.findCookies(host, allPaths ? null : path, function(err,cookies) {
+ if (err) {
+ return cb(err);
+ }
+
+ cookies = cookies.filter(matchingCookie);
+
+ // sorting of S5.4 part 2
+ if (options.sort !== false) {
+ cookies = cookies.sort(cookieCompare);
+ }
+
+ // S5.4 part 3
+ var now = new Date();
+ cookies.forEach(function(c) {
+ c.lastAccessed = now;
+ });
+ // TODO persist lastAccessed
+
+ cb(null,cookies);
+ });
+ };
+
+ CAN_BE_SYNC.push('getCookieString');
+ CookieJar.prototype.getCookieString = function(/*..., cb*/) {
+ var args = Array.prototype.slice.call(arguments,0);
+ var cb = args.pop();
+ var next = function(err,cookies) {
+ if (err) {
+ cb(err);
+ } else {
+ cb(null, cookies
+ .sort(cookieCompare)
+ .map(function(c){
+ return c.cookieString();
+ })
+ .join('; '));
+ }
+ };
+ args.push(next);
+ this.getCookies.apply(this,args);
+ };
+
+ CAN_BE_SYNC.push('getSetCookieStrings');
+ CookieJar.prototype.getSetCookieStrings = function(/*..., cb*/) {
+ var args = Array.prototype.slice.call(arguments,0);
+ var cb = args.pop();
+ var next = function(err,cookies) {
+ if (err) {
+ cb(err);
+ } else {
+ cb(null, cookies.map(function(c){
+ return c.toString();
+ }));
+ }
+ };
+ args.push(next);
+ this.getCookies.apply(this,args);
+ };
+
+ CAN_BE_SYNC.push('serialize');
+ CookieJar.prototype.serialize = function(cb) {
+ var type = this.store.constructor.name;
+ if (type === 'Object') {
+ type = null;
+ }
+
+ // update README.md "Serialization Format" if you change this, please!
+ var serialized = {
+ // The version of tough-cookie that serialized this jar. Generally a good
+ // practice since future versions can make data import decisions based on
+ // known past behavior. When/if this matters, use `semver`.
+ version: 'tough-cookie@'+VERSION,
+
+ // add the store type, to make humans happy:
+ storeType: type,
+
+ // CookieJar configuration:
+ rejectPublicSuffixes: !!this.rejectPublicSuffixes,
+
+ // this gets filled from getAllCookies:
+ cookies: []
+ };
+
+ if (!(this.store.getAllCookies &&
+ typeof this.store.getAllCookies === 'function'))
+ {
+ return cb(new Error('store does not support getAllCookies and cannot be serialized'));
+ }
+
+ this.store.getAllCookies(function(err,cookies) {
+ if (err) {
+ return cb(err);
+ }
+
+ serialized.cookies = cookies.map(function(cookie) {
+ // convert to serialized 'raw' cookies
+ cookie = (cookie instanceof Cookie) ? cookie.toJSON() : cookie;
+
+ // Remove the index so new ones get assigned during deserialization
+ delete cookie.creationIndex;
+
+ return cookie;
+ });
+
+ return cb(null, serialized);
+ });
+ };
+
+ // well-known name that JSON.stringify calls
+ CookieJar.prototype.toJSON = function() {
+ return this.serializeSync();
+ };
+
+ // use the class method CookieJar.deserialize instead of calling this directly
+ CAN_BE_SYNC.push('_importCookies');
+ CookieJar.prototype._importCookies = function(serialized, cb) {
+ var jar = this;
+ var cookies = serialized.cookies;
+ if (!cookies || !Array.isArray(cookies)) {
+ return cb(new Error('serialized jar has no cookies array'));
+ }
+ cookies = cookies.slice(); // do not modify the original
+
+ function putNext(err) {
+ if (err) {
+ return cb(err);
+ }
+
+ if (!cookies.length) {
+ return cb(err, jar);
+ }
+
+ var cookie;
+ try {
+ cookie = fromJSON(cookies.shift());
+ } catch (e) {
+ return cb(e);
+ }
+
+ if (cookie === null) {
+ return putNext(null); // skip this cookie
+ }
+
+ jar.store.putCookie(cookie, putNext);
+ }
+
+ putNext();
+ };
+
+ CookieJar.deserialize = function(strOrObj, store, cb) {
+ if (arguments.length !== 3) {
+ // store is optional
+ cb = store;
+ store = null;
+ }
+
+ var serialized;
+ if (typeof strOrObj === 'string') {
+ serialized = jsonParse(strOrObj);
+ if (serialized instanceof Error) {
+ return cb(serialized);
+ }
+ } else {
+ serialized = strOrObj;
+ }
+
+ var jar = new CookieJar(store, serialized.rejectPublicSuffixes);
+ jar._importCookies(serialized, function(err) {
+ if (err) {
+ return cb(err);
+ }
+ cb(null, jar);
+ });
+ };
+
+ CookieJar.deserializeSync = function(strOrObj, store) {
+ var serialized = typeof strOrObj === 'string' ?
+ JSON.parse(strOrObj) : strOrObj;
+ var jar = new CookieJar(store, serialized.rejectPublicSuffixes);
+
+ // catch this mistake early:
+ if (!jar.store.synchronous) {
+ throw new Error('CookieJar store is not synchronous; use async API instead.');
+ }
+
+ jar._importCookiesSync(serialized);
+ return jar;
+ };
+ CookieJar.fromJSON = CookieJar.deserializeSync;
+
+ CAN_BE_SYNC.push('clone');
+ CookieJar.prototype.clone = function(newStore, cb) {
+ if (arguments.length === 1) {
+ cb = newStore;
+ newStore = null;
+ }
+
+ this.serialize(function(err,serialized) {
+ if (err) {
+ return cb(err);
+ }
+ CookieJar.deserialize(newStore, serialized, cb);
+ });
+ };
+
+ // Use a closure to provide a true imperative API for synchronous stores.
+ function syncWrap(method) {
+ return function() {
+ if (!this.store.synchronous) {
+ throw new Error('CookieJar store is not synchronous; use async API instead.');
+ }
+
+ var args = Array.prototype.slice.call(arguments);
+ var syncErr, syncResult;
+ args.push(function syncCb(err, result) {
+ syncErr = err;
+ syncResult = result;
+ });
+ this[method].apply(this, args);
+
+ if (syncErr) {
+ throw syncErr;
+ }
+ return syncResult;
+ };
+ }
+
+ // wrap all declared CAN_BE_SYNC methods in the sync wrapper
+ CAN_BE_SYNC.forEach(function(method) {
+ CookieJar.prototype[method+'Sync'] = syncWrap(method);
+ });
+
+ exports.CookieJar = CookieJar;
+ exports.Cookie = Cookie;
+ exports.Store = Store;
+ exports.MemoryCookieStore = MemoryCookieStore;
+ exports.parseDate = parseDate;
+ exports.formatDate = formatDate;
+ exports.parse = parse;
+ exports.fromJSON = fromJSON;
+ exports.domainMatch = domainMatch;
+ exports.defaultPath = defaultPath;
+ exports.pathMatch = pathMatch;
+ exports.getPublicSuffix = pubsuffix.getPublicSuffix;
+ exports.cookieCompare = cookieCompare;
+ exports.permuteDomain = __webpack_require__(19).permuteDomain;
+ exports.permutePath = permutePath;
+ exports.canonicalDomain = canonicalDomain;
+
+
+/***/ }),
+/* 1 */
+/***/ (function(module, exports) {
+
+ /*
+ * Tests if a given ip or host string is a valid IPv4 or IPv6 address.
+ * Regex found at: https://stackoverflow.com/questions/9208814/validate-ipv4-ipv6-and-hostname
+ */
+
+ var patternIPv4 = /^\s*((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))\s*$/g;
+ var patternIPv6 = /^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/g;
+
+ function isIPv4(hostOrIp) {
+ return hostOrIp.match(patternIPv4) ? true : false;
+ }
+
+ function isIPv6(hostOrIp) {
+ return hostOrIp.match(patternIPv6) ? true : false;
+ }
+
+ function isIP(hostOrIp) {
+ if (isIPv4(hostOrIp)) {
+ return 4;
+ }
+
+ if (isIPv6(hostOrIp)) {
+ return 6;
+ }
+
+ return 0;
+ }
+
+ module.exports = {
+ isIPv4: isIPv4,
+ isIPv6: isIPv6,
+ isIP: isIP
+ };
+
+
+/***/ }),
+/* 2 */
+/***/ (function(module, exports, __webpack_require__) {
+
+ // Copyright Joyent, Inc. and other Node contributors.
+ //
+ // Permission is hereby granted, free of charge, to any person obtaining a
+ // copy of this software and associated documentation files (the
+ // "Software"), to deal in the Software without restriction, including
+ // without limitation the rights to use, copy, modify, merge, publish,
+ // distribute, sublicense, and/or sell copies of the Software, and to permit
+ // persons to whom the Software is furnished to do so, subject to the
+ // following conditions:
+ //
+ // The above copyright notice and this permission notice shall be included
+ // in all copies or substantial portions of the Software.
+ //
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+ // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ // USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ 'use strict';
+
+ var punycode = __webpack_require__(3);
+ var util = __webpack_require__(5);
+
+ exports.parse = urlParse;
+ exports.resolve = urlResolve;
+ exports.resolveObject = urlResolveObject;
+ exports.format = urlFormat;
+
+ exports.Url = Url;
+
+ function Url() {
+ this.protocol = null;
+ this.slashes = null;
+ this.auth = null;
+ this.host = null;
+ this.port = null;
+ this.hostname = null;
+ this.hash = null;
+ this.search = null;
+ this.query = null;
+ this.pathname = null;
+ this.path = null;
+ this.href = null;
+ }
+
+ // Reference: RFC 3986, RFC 1808, RFC 2396
+
+ // define these here so at least they only have to be
+ // compiled once on the first module load.
+ var protocolPattern = /^([a-z0-9.+-]+:)/i,
+ portPattern = /:[0-9]*$/,
+
+ // Special case for a simple path URL
+ simplePathPattern = /^(\/\/?(?!\/)[^\?\s]*)(\?[^\s]*)?$/,
+
+ // RFC 2396: characters reserved for delimiting URLs.
+ // We actually just auto-escape these.
+ delims = ['<', '>', '"', '`', ' ', '\r', '\n', '\t'],
+
+ // RFC 2396: characters not allowed for various reasons.
+ unwise = ['{', '}', '|', '\\', '^', '`'].concat(delims),
+
+ // Allowed by RFCs, but cause of XSS attacks. Always escape these.
+ autoEscape = ['\''].concat(unwise),
+ // Characters that are never ever allowed in a hostname.
+ // Note that any invalid chars are also handled, but these
+ // are the ones that are *expected* to be seen, so we fast-path
+ // them.
+ nonHostChars = ['%', '/', '?', ';', '#'].concat(autoEscape),
+ hostEndingChars = ['/', '?', '#'],
+ hostnameMaxLen = 255,
+ hostnamePartPattern = /^[+a-z0-9A-Z_-]{0,63}$/,
+ hostnamePartStart = /^([+a-z0-9A-Z_-]{0,63})(.*)$/,
+ // protocols that can allow "unsafe" and "unwise" chars.
+ unsafeProtocol = {
+ 'javascript': true,
+ 'javascript:': true
+ },
+ // protocols that never have a hostname.
+ hostlessProtocol = {
+ 'javascript': true,
+ 'javascript:': true
+ },
+ // protocols that always contain a // bit.
+ slashedProtocol = {
+ 'http': true,
+ 'https': true,
+ 'ftp': true,
+ 'gopher': true,
+ 'file': true,
+ 'http:': true,
+ 'https:': true,
+ 'ftp:': true,
+ 'gopher:': true,
+ 'file:': true
+ },
+ querystring = __webpack_require__(6);
+
+ function urlParse(url, parseQueryString, slashesDenoteHost) {
+ if (url && util.isObject(url) && url instanceof Url) return url;
+
+ var u = new Url;
+ u.parse(url, parseQueryString, slashesDenoteHost);
+ return u;
+ }
+
+ Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) {
+ if (!util.isString(url)) {
+ throw new TypeError("Parameter 'url' must be a string, not " + typeof url);
+ }
+
+ // Copy chrome, IE, opera backslash-handling behavior.
+ // Back slashes before the query string get converted to forward slashes
+ // See: https://code.google.com/p/chromium/issues/detail?id=25916
+ var queryIndex = url.indexOf('?'),
+ splitter =
+ (queryIndex !== -1 && queryIndex < url.indexOf('#')) ? '?' : '#',
+ uSplit = url.split(splitter),
+ slashRegex = /\\/g;
+ uSplit[0] = uSplit[0].replace(slashRegex, '/');
+ url = uSplit.join(splitter);
+
+ var rest = url;
+
+ // trim before proceeding.
+ // This is to support parse stuff like " http://foo.com \n"
+ rest = rest.trim();
+
+ if (!slashesDenoteHost && url.split('#').length === 1) {
+ // Try fast path regexp
+ var simplePath = simplePathPattern.exec(rest);
+ if (simplePath) {
+ this.path = rest;
+ this.href = rest;
+ this.pathname = simplePath[1];
+ if (simplePath[2]) {
+ this.search = simplePath[2];
+ if (parseQueryString) {
+ this.query = querystring.parse(this.search.substr(1));
+ } else {
+ this.query = this.search.substr(1);
+ }
+ } else if (parseQueryString) {
+ this.search = '';
+ this.query = {};
+ }
+ return this;
+ }
+ }
+
+ var proto = protocolPattern.exec(rest);
+ if (proto) {
+ proto = proto[0];
+ var lowerProto = proto.toLowerCase();
+ this.protocol = lowerProto;
+ rest = rest.substr(proto.length);
+ }
+
+ // figure out if it's got a host
+ // user@server is *always* interpreted as a hostname, and url
+ // resolution will treat //foo/bar as host=foo,path=bar because that's
+ // how the browser resolves relative URLs.
+ if (slashesDenoteHost || proto || rest.match(/^\/\/[^@\/]+@[^@\/]+/)) {
+ var slashes = rest.substr(0, 2) === '//';
+ if (slashes && !(proto && hostlessProtocol[proto])) {
+ rest = rest.substr(2);
+ this.slashes = true;
+ }
+ }
+
+ if (!hostlessProtocol[proto] &&
+ (slashes || (proto && !slashedProtocol[proto]))) {
+
+ // there's a hostname.
+ // the first instance of /, ?, ;, or # ends the host.
+ //
+ // If there is an @ in the hostname, then non-host chars *are* allowed
+ // to the left of the last @ sign, unless some host-ending character
+ // comes *before* the @-sign.
+ // URLs are obnoxious.
+ //
+ // ex:
+ // http://a@b@c/ => user:a@b host:c
+ // http://a@b?@c => user:a host:c path:/?@c
+
+ // v0.12 TODO(isaacs): This is not quite how Chrome does things.
+ // Review our test case against browsers more comprehensively.
+
+ // find the first instance of any hostEndingChars
+ var hostEnd = -1;
+ for (var i = 0; i < hostEndingChars.length; i++) {
+ var hec = rest.indexOf(hostEndingChars[i]);
+ if (hec !== -1 && (hostEnd === -1 || hec < hostEnd))
+ hostEnd = hec;
+ }
+
+ // at this point, either we have an explicit point where the
+ // auth portion cannot go past, or the last @ char is the decider.
+ var auth, atSign;
+ if (hostEnd === -1) {
+ // atSign can be anywhere.
+ atSign = rest.lastIndexOf('@');
+ } else {
+ // atSign must be in auth portion.
+ // http://a@b/c@d => host:b auth:a path:/c@d
+ atSign = rest.lastIndexOf('@', hostEnd);
+ }
+
+ // Now we have a portion which is definitely the auth.
+ // Pull that off.
+ if (atSign !== -1) {
+ auth = rest.slice(0, atSign);
+ rest = rest.slice(atSign + 1);
+ this.auth = decodeURIComponent(auth);
+ }
+
+ // the host is the remaining to the left of the first non-host char
+ hostEnd = -1;
+ for (var i = 0; i < nonHostChars.length; i++) {
+ var hec = rest.indexOf(nonHostChars[i]);
+ if (hec !== -1 && (hostEnd === -1 || hec < hostEnd))
+ hostEnd = hec;
+ }
+ // if we still have not hit it, then the entire thing is a host.
+ if (hostEnd === -1)
+ hostEnd = rest.length;
+
+ this.host = rest.slice(0, hostEnd);
+ rest = rest.slice(hostEnd);
+
+ // pull out port.
+ this.parseHost();
+
+ // we've indicated that there is a hostname,
+ // so even if it's empty, it has to be present.
+ this.hostname = this.hostname || '';
+
+ // if hostname begins with [ and ends with ]
+ // assume that it's an IPv6 address.
+ var ipv6Hostname = this.hostname[0] === '[' &&
+ this.hostname[this.hostname.length - 1] === ']';
+
+ // validate a little.
+ if (!ipv6Hostname) {
+ var hostparts = this.hostname.split(/\./);
+ for (var i = 0, l = hostparts.length; i < l; i++) {
+ var part = hostparts[i];
+ if (!part) continue;
+ if (!part.match(hostnamePartPattern)) {
+ var newpart = '';
+ for (var j = 0, k = part.length; j < k; j++) {
+ if (part.charCodeAt(j) > 127) {
+ // we replace non-ASCII char with a temporary placeholder
+ // we need this to make sure size of hostname is not
+ // broken by replacing non-ASCII by nothing
+ newpart += 'x';
+ } else {
+ newpart += part[j];
+ }
+ }
+ // we test again with ASCII char only
+ if (!newpart.match(hostnamePartPattern)) {
+ var validParts = hostparts.slice(0, i);
+ var notHost = hostparts.slice(i + 1);
+ var bit = part.match(hostnamePartStart);
+ if (bit) {
+ validParts.push(bit[1]);
+ notHost.unshift(bit[2]);
+ }
+ if (notHost.length) {
+ rest = '/' + notHost.join('.') + rest;
+ }
+ this.hostname = validParts.join('.');
+ break;
+ }
+ }
+ }
+ }
+
+ if (this.hostname.length > hostnameMaxLen) {
+ this.hostname = '';
+ } else {
+ // hostnames are always lower case.
+ this.hostname = this.hostname.toLowerCase();
+ }
+
+ if (!ipv6Hostname) {
+ // IDNA Support: Returns a punycoded representation of "domain".
+ // It only converts parts of the domain name that
+ // have non-ASCII characters, i.e. it doesn't matter if
+ // you call it with a domain that already is ASCII-only.
+ this.hostname = punycode.toASCII(this.hostname);
+ }
+
+ var p = this.port ? ':' + this.port : '';
+ var h = this.hostname || '';
+ this.host = h + p;
+ this.href += this.host;
+
+ // strip [ and ] from the hostname
+ // the host field still retains them, though
+ if (ipv6Hostname) {
+ this.hostname = this.hostname.substr(1, this.hostname.length - 2);
+ if (rest[0] !== '/') {
+ rest = '/' + rest;
+ }
+ }
+ }
+
+ // now rest is set to the post-host stuff.
+ // chop off any delim chars.
+ if (!unsafeProtocol[lowerProto]) {
+
+ // First, make 100% sure that any "autoEscape" chars get
+ // escaped, even if encodeURIComponent doesn't think they
+ // need to be.
+ for (var i = 0, l = autoEscape.length; i < l; i++) {
+ var ae = autoEscape[i];
+ if (rest.indexOf(ae) === -1)
+ continue;
+ var esc = encodeURIComponent(ae);
+ if (esc === ae) {
+ esc = escape(ae);
+ }
+ rest = rest.split(ae).join(esc);
+ }
+ }
+
+
+ // chop off from the tail first.
+ var hash = rest.indexOf('#');
+ if (hash !== -1) {
+ // got a fragment string.
+ this.hash = rest.substr(hash);
+ rest = rest.slice(0, hash);
+ }
+ var qm = rest.indexOf('?');
+ if (qm !== -1) {
+ this.search = rest.substr(qm);
+ this.query = rest.substr(qm + 1);
+ if (parseQueryString) {
+ this.query = querystring.parse(this.query);
+ }
+ rest = rest.slice(0, qm);
+ } else if (parseQueryString) {
+ // no query string, but parseQueryString still requested
+ this.search = '';
+ this.query = {};
+ }
+ if (rest) this.pathname = rest;
+ if (slashedProtocol[lowerProto] &&
+ this.hostname && !this.pathname) {
+ this.pathname = '/';
+ }
+
+ //to support http.request
+ if (this.pathname || this.search) {
+ var p = this.pathname || '';
+ var s = this.search || '';
+ this.path = p + s;
+ }
+
+ // finally, reconstruct the href based on what has been validated.
+ this.href = this.format();
+ return this;
+ };
+
+ // format a parsed object into a url string
+ function urlFormat(obj) {
+ // ensure it's an object, and not a string url.
+ // If it's an obj, this is a no-op.
+ // this way, you can call url_format() on strings
+ // to clean up potentially wonky urls.
+ if (util.isString(obj)) obj = urlParse(obj);
+ if (!(obj instanceof Url)) return Url.prototype.format.call(obj);
+ return obj.format();
+ }
+
+ Url.prototype.format = function() {
+ var auth = this.auth || '';
+ if (auth) {
+ auth = encodeURIComponent(auth);
+ auth = auth.replace(/%3A/i, ':');
+ auth += '@';
+ }
+
+ var protocol = this.protocol || '',
+ pathname = this.pathname || '',
+ hash = this.hash || '',
+ host = false,
+ query = '';
+
+ if (this.host) {
+ host = auth + this.host;
+ } else if (this.hostname) {
+ host = auth + (this.hostname.indexOf(':') === -1 ?
+ this.hostname :
+ '[' + this.hostname + ']');
+ if (this.port) {
+ host += ':' + this.port;
+ }
+ }
+
+ if (this.query &&
+ util.isObject(this.query) &&
+ Object.keys(this.query).length) {
+ query = querystring.stringify(this.query);
+ }
+
+ var search = this.search || (query && ('?' + query)) || '';
+
+ if (protocol && protocol.substr(-1) !== ':') protocol += ':';
+
+ // only the slashedProtocols get the //. Not mailto:, xmpp:, etc.
+ // unless they had them to begin with.
+ if (this.slashes ||
+ (!protocol || slashedProtocol[protocol]) && host !== false) {
+ host = '//' + (host || '');
+ if (pathname && pathname.charAt(0) !== '/') pathname = '/' + pathname;
+ } else if (!host) {
+ host = '';
+ }
+
+ if (hash && hash.charAt(0) !== '#') hash = '#' + hash;
+ if (search && search.charAt(0) !== '?') search = '?' + search;
+
+ pathname = pathname.replace(/[?#]/g, function(match) {
+ return encodeURIComponent(match);
+ });
+ search = search.replace('#', '%23');
+
+ return protocol + host + pathname + search + hash;
+ };
+
+ function urlResolve(source, relative) {
+ return urlParse(source, false, true).resolve(relative);
+ }
+
+ Url.prototype.resolve = function(relative) {
+ return this.resolveObject(urlParse(relative, false, true)).format();
+ };
+
+ function urlResolveObject(source, relative) {
+ if (!source) return relative;
+ return urlParse(source, false, true).resolveObject(relative);
+ }
+
+ Url.prototype.resolveObject = function(relative) {
+ if (util.isString(relative)) {
+ var rel = new Url();
+ rel.parse(relative, false, true);
+ relative = rel;
+ }
+
+ var result = new Url();
+ var tkeys = Object.keys(this);
+ for (var tk = 0; tk < tkeys.length; tk++) {
+ var tkey = tkeys[tk];
+ result[tkey] = this[tkey];
+ }
+
+ // hash is always overridden, no matter what.
+ // even href="" will remove it.
+ result.hash = relative.hash;
+
+ // if the relative url is empty, then there's nothing left to do here.
+ if (relative.href === '') {
+ result.href = result.format();
+ return result;
+ }
+
+ // hrefs like //foo/bar always cut to the protocol.
+ if (relative.slashes && !relative.protocol) {
+ // take everything except the protocol from relative
+ var rkeys = Object.keys(relative);
+ for (var rk = 0; rk < rkeys.length; rk++) {
+ var rkey = rkeys[rk];
+ if (rkey !== 'protocol')
+ result[rkey] = relative[rkey];
+ }
+
+ //urlParse appends trailing / to urls like http://www.example.com
+ if (slashedProtocol[result.protocol] &&
+ result.hostname && !result.pathname) {
+ result.path = result.pathname = '/';
+ }
+
+ result.href = result.format();
+ return result;
+ }
+
+ if (relative.protocol && relative.protocol !== result.protocol) {
+ // if it's a known url protocol, then changing
+ // the protocol does weird things
+ // first, if it's not file:, then we MUST have a host,
+ // and if there was a path
+ // to begin with, then we MUST have a path.
+ // if it is file:, then the host is dropped,
+ // because that's known to be hostless.
+ // anything else is assumed to be absolute.
+ if (!slashedProtocol[relative.protocol]) {
+ var keys = Object.keys(relative);
+ for (var v = 0; v < keys.length; v++) {
+ var k = keys[v];
+ result[k] = relative[k];
+ }
+ result.href = result.format();
+ return result;
+ }
+
+ result.protocol = relative.protocol;
+ if (!relative.host && !hostlessProtocol[relative.protocol]) {
+ var relPath = (relative.pathname || '').split('/');
+ while (relPath.length && !(relative.host = relPath.shift()));
+ if (!relative.host) relative.host = '';
+ if (!relative.hostname) relative.hostname = '';
+ if (relPath[0] !== '') relPath.unshift('');
+ if (relPath.length < 2) relPath.unshift('');
+ result.pathname = relPath.join('/');
+ } else {
+ result.pathname = relative.pathname;
+ }
+ result.search = relative.search;
+ result.query = relative.query;
+ result.host = relative.host || '';
+ result.auth = relative.auth;
+ result.hostname = relative.hostname || relative.host;
+ result.port = relative.port;
+ // to support http.request
+ if (result.pathname || result.search) {
+ var p = result.pathname || '';
+ var s = result.search || '';
+ result.path = p + s;
+ }
+ result.slashes = result.slashes || relative.slashes;
+ result.href = result.format();
+ return result;
+ }
+
+ var isSourceAbs = (result.pathname && result.pathname.charAt(0) === '/'),
+ isRelAbs = (
+ relative.host ||
+ relative.pathname && relative.pathname.charAt(0) === '/'
+ ),
+ mustEndAbs = (isRelAbs || isSourceAbs ||
+ (result.host && relative.pathname)),
+ removeAllDots = mustEndAbs,
+ srcPath = result.pathname && result.pathname.split('/') || [],
+ relPath = relative.pathname && relative.pathname.split('/') || [],
+ psychotic = result.protocol && !slashedProtocol[result.protocol];
+
+ // if the url is a non-slashed url, then relative
+ // links like ../.. should be able
+ // to crawl up to the hostname, as well. This is strange.
+ // result.protocol has already been set by now.
+ // Later on, put the first path part into the host field.
+ if (psychotic) {
+ result.hostname = '';
+ result.port = null;
+ if (result.host) {
+ if (srcPath[0] === '') srcPath[0] = result.host;
+ else srcPath.unshift(result.host);
+ }
+ result.host = '';
+ if (relative.protocol) {
+ relative.hostname = null;
+ relative.port = null;
+ if (relative.host) {
+ if (relPath[0] === '') relPath[0] = relative.host;
+ else relPath.unshift(relative.host);
+ }
+ relative.host = null;
+ }
+ mustEndAbs = mustEndAbs && (relPath[0] === '' || srcPath[0] === '');
+ }
+
+ if (isRelAbs) {
+ // it's absolute.
+ result.host = (relative.host || relative.host === '') ?
+ relative.host : result.host;
+ result.hostname = (relative.hostname || relative.hostname === '') ?
+ relative.hostname : result.hostname;
+ result.search = relative.search;
+ result.query = relative.query;
+ srcPath = relPath;
+ // fall through to the dot-handling below.
+ } else if (relPath.length) {
+ // it's relative
+ // throw away the existing file, and take the new path instead.
+ if (!srcPath) srcPath = [];
+ srcPath.pop();
+ srcPath = srcPath.concat(relPath);
+ result.search = relative.search;
+ result.query = relative.query;
+ } else if (!util.isNullOrUndefined(relative.search)) {
+ // just pull out the search.
+ // like href='?foo'.
+ // Put this after the other two cases because it simplifies the booleans
+ if (psychotic) {
+ result.hostname = result.host = srcPath.shift();
+ //occationaly the auth can get stuck only in host
+ //this especially happens in cases like
+ //url.resolveObject('mailto:local1@domain1', 'local2@domain2')
+ var authInHost = result.host && result.host.indexOf('@') > 0 ?
+ result.host.split('@') : false;
+ if (authInHost) {
+ result.auth = authInHost.shift();
+ result.host = result.hostname = authInHost.shift();
+ }
+ }
+ result.search = relative.search;
+ result.query = relative.query;
+ //to support http.request
+ if (!util.isNull(result.pathname) || !util.isNull(result.search)) {
+ result.path = (result.pathname ? result.pathname : '') +
+ (result.search ? result.search : '');
+ }
+ result.href = result.format();
+ return result;
+ }
+
+ if (!srcPath.length) {
+ // no path at all. easy.
+ // we've already handled the other stuff above.
+ result.pathname = null;
+ //to support http.request
+ if (result.search) {
+ result.path = '/' + result.search;
+ } else {
+ result.path = null;
+ }
+ result.href = result.format();
+ return result;
+ }
+
+ // if a url ENDs in . or .., then it must get a trailing slash.
+ // however, if it ends in anything else non-slashy,
+ // then it must NOT get a trailing slash.
+ var last = srcPath.slice(-1)[0];
+ var hasTrailingSlash = (
+ (result.host || relative.host || srcPath.length > 1) &&
+ (last === '.' || last === '..') || last === '');
+
+ // strip single dots, resolve double dots to parent dir
+ // if the path tries to go above the root, `up` ends up > 0
+ var up = 0;
+ for (var i = srcPath.length; i >= 0; i--) {
+ last = srcPath[i];
+ if (last === '.') {
+ srcPath.splice(i, 1);
+ } else if (last === '..') {
+ srcPath.splice(i, 1);
+ up++;
+ } else if (up) {
+ srcPath.splice(i, 1);
+ up--;
+ }
+ }
+
+ // if the path is allowed to go above the root, restore leading ..s
+ if (!mustEndAbs && !removeAllDots) {
+ for (; up--; up) {
+ srcPath.unshift('..');
+ }
+ }
+
+ if (mustEndAbs && srcPath[0] !== '' &&
+ (!srcPath[0] || srcPath[0].charAt(0) !== '/')) {
+ srcPath.unshift('');
+ }
+
+ if (hasTrailingSlash && (srcPath.join('/').substr(-1) !== '/')) {
+ srcPath.push('');
+ }
+
+ var isAbsolute = srcPath[0] === '' ||
+ (srcPath[0] && srcPath[0].charAt(0) === '/');
+
+ // put the host back
+ if (psychotic) {
+ result.hostname = result.host = isAbsolute ? '' :
+ srcPath.length ? srcPath.shift() : '';
+ //occationaly the auth can get stuck only in host
+ //this especially happens in cases like
+ //url.resolveObject('mailto:local1@domain1', 'local2@domain2')
+ var authInHost = result.host && result.host.indexOf('@') > 0 ?
+ result.host.split('@') : false;
+ if (authInHost) {
+ result.auth = authInHost.shift();
+ result.host = result.hostname = authInHost.shift();
+ }
+ }
+
+ mustEndAbs = mustEndAbs || (result.host && srcPath.length);
+
+ if (mustEndAbs && !isAbsolute) {
+ srcPath.unshift('');
+ }
+
+ if (!srcPath.length) {
+ result.pathname = null;
+ result.path = null;
+ } else {
+ result.pathname = srcPath.join('/');
+ }
+
+ //to support request.http
+ if (!util.isNull(result.pathname) || !util.isNull(result.search)) {
+ result.path = (result.pathname ? result.pathname : '') +
+ (result.search ? result.search : '');
+ }
+ result.auth = relative.auth || result.auth;
+ result.slashes = result.slashes || relative.slashes;
+ result.href = result.format();
+ return result;
+ };
+
+ Url.prototype.parseHost = function() {
+ var host = this.host;
+ var port = portPattern.exec(host);
+ if (port) {
+ port = port[0];
+ if (port !== ':') {
+ this.port = port.substr(1);
+ }
+ host = host.substr(0, host.length - port.length);
+ }
+ if (host) this.hostname = host;
+ };
+
+
+/***/ }),
+/* 3 */
+/***/ (function(module, exports, __webpack_require__) {
+
+ var __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(module, global) {/*! https://mths.be/punycode v1.3.2 by @mathias */
+ ;(function(root) {
+
+ /** Detect free variables */
+ var freeExports = typeof exports == 'object' && exports &&
+ !exports.nodeType && exports;
+ var freeModule = typeof module == 'object' && module &&
+ !module.nodeType && module;
+ var freeGlobal = typeof global == 'object' && global;
+ if (
+ freeGlobal.global === freeGlobal ||
+ freeGlobal.window === freeGlobal ||
+ freeGlobal.self === freeGlobal
+ ) {
+ root = freeGlobal;
+ }
+
+ /**
+ * The `punycode` object.
+ * @name punycode
+ * @type Object
+ */
+ var punycode,
+
+ /** Highest positive signed 32-bit float value */
+ maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1
+
+ /** Bootstring parameters */
+ base = 36,
+ tMin = 1,
+ tMax = 26,
+ skew = 38,
+ damp = 700,
+ initialBias = 72,
+ initialN = 128, // 0x80
+ delimiter = '-', // '\x2D'
+
+ /** Regular expressions */
+ regexPunycode = /^xn--/,
+ regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars
+ regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators
+
+ /** Error messages */
+ errors = {
+ 'overflow': 'Overflow: input needs wider integers to process',
+ 'not-basic': 'Illegal input >= 0x80 (not a basic code point)',
+ 'invalid-input': 'Invalid input'
+ },
+
+ /** Convenience shortcuts */
+ baseMinusTMin = base - tMin,
+ floor = Math.floor,
+ stringFromCharCode = String.fromCharCode,
+
+ /** Temporary variable */
+ key;
+
+ /*--------------------------------------------------------------------------*/
+
+ /**
+ * A generic error utility function.
+ * @private
+ * @param {String} type The error type.
+ * @returns {Error} Throws a `RangeError` with the applicable error message.
+ */
+ function error(type) {
+ throw RangeError(errors[type]);
+ }
+
+ /**
+ * A generic `Array#map` utility function.
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} callback The function that gets called for every array
+ * item.
+ * @returns {Array} A new array of values returned by the callback function.
+ */
+ function map(array, fn) {
+ var length = array.length;
+ var result = [];
+ while (length--) {
+ result[length] = fn(array[length]);
+ }
+ return result;
+ }
+
+ /**
+ * A simple `Array#map`-like wrapper to work with domain name strings or email
+ * addresses.
+ * @private
+ * @param {String} domain The domain name or email address.
+ * @param {Function} callback The function that gets called for every
+ * character.
+ * @returns {Array} A new string of characters returned by the callback
+ * function.
+ */
+ function mapDomain(string, fn) {
+ var parts = string.split('@');
+ var result = '';
+ if (parts.length > 1) {
+ // In email addresses, only the domain name should be punycoded. Leave
+ // the local part (i.e. everything up to `@`) intact.
+ result = parts[0] + '@';
+ string = parts[1];
+ }
+ // Avoid `split(regex)` for IE8 compatibility. See #17.
+ string = string.replace(regexSeparators, '\x2E');
+ var labels = string.split('.');
+ var encoded = map(labels, fn).join('.');
+ return result + encoded;
+ }
+
+ /**
+ * Creates an array containing the numeric code points of each Unicode
+ * character in the string. While JavaScript uses UCS-2 internally,
+ * this function will convert a pair of surrogate halves (each of which
+ * UCS-2 exposes as separate characters) into a single code point,
+ * matching UTF-16.
+ * @see `punycode.ucs2.encode`
+ * @see <https://mathiasbynens.be/notes/javascript-encoding>
+ * @memberOf punycode.ucs2
+ * @name decode
+ * @param {String} string The Unicode input string (UCS-2).
+ * @returns {Array} The new array of code points.
+ */
+ function ucs2decode(string) {
+ var output = [],
+ counter = 0,
+ length = string.length,
+ value,
+ extra;
+ while (counter < length) {
+ value = string.charCodeAt(counter++);
+ if (value >= 0xD800 && value <= 0xDBFF && counter < length) {
+ // high surrogate, and there is a next character
+ extra = string.charCodeAt(counter++);
+ if ((extra & 0xFC00) == 0xDC00) { // low surrogate
+ output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);
+ } else {
+ // unmatched surrogate; only append this code unit, in case the next
+ // code unit is the high surrogate of a surrogate pair
+ output.push(value);
+ counter--;
+ }
+ } else {
+ output.push(value);
+ }
+ }
+ return output;
+ }
+
+ /**
+ * Creates a string based on an array of numeric code points.
+ * @see `punycode.ucs2.decode`
+ * @memberOf punycode.ucs2
+ * @name encode
+ * @param {Array} codePoints The array of numeric code points.
+ * @returns {String} The new Unicode string (UCS-2).
+ */
+ function ucs2encode(array) {
+ return map(array, function(value) {
+ var output = '';
+ if (value > 0xFFFF) {
+ value -= 0x10000;
+ output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
+ value = 0xDC00 | value & 0x3FF;
+ }
+ output += stringFromCharCode(value);
+ return output;
+ }).join('');
+ }
+
+ /**
+ * Converts a basic code point into a digit/integer.
+ * @see `digitToBasic()`
+ * @private
+ * @param {Number} codePoint The basic numeric code point value.
+ * @returns {Number} The numeric value of a basic code point (for use in
+ * representing integers) in the range `0` to `base - 1`, or `base` if
+ * the code point does not represent a value.
+ */
+ function basicToDigit(codePoint) {
+ if (codePoint - 48 < 10) {
+ return codePoint - 22;
+ }
+ if (codePoint - 65 < 26) {
+ return codePoint - 65;
+ }
+ if (codePoint - 97 < 26) {
+ return codePoint - 97;
+ }
+ return base;
+ }
+
+ /**
+ * Converts a digit/integer into a basic code point.
+ * @see `basicToDigit()`
+ * @private
+ * @param {Number} digit The numeric value of a basic code point.
+ * @returns {Number} The basic code point whose value (when used for
+ * representing integers) is `digit`, which needs to be in the range
+ * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is
+ * used; else, the lowercase form is used. The behavior is undefined
+ * if `flag` is non-zero and `digit` has no uppercase form.
+ */
+ function digitToBasic(digit, flag) {
+ // 0..25 map to ASCII a..z or A..Z
+ // 26..35 map to ASCII 0..9
+ return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);
+ }
+
+ /**
+ * Bias adaptation function as per section 3.4 of RFC 3492.
+ * http://tools.ietf.org/html/rfc3492#section-3.4
+ * @private
+ */
+ function adapt(delta, numPoints, firstTime) {
+ var k = 0;
+ delta = firstTime ? floor(delta / damp) : delta >> 1;
+ delta += floor(delta / numPoints);
+ for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) {
+ delta = floor(delta / baseMinusTMin);
+ }
+ return floor(k + (baseMinusTMin + 1) * delta / (delta + skew));
+ }
+
+ /**
+ * Converts a Punycode string of ASCII-only symbols to a string of Unicode
+ * symbols.
+ * @memberOf punycode
+ * @param {String} input The Punycode string of ASCII-only symbols.
+ * @returns {String} The resulting string of Unicode symbols.
+ */
+ function decode(input) {
+ // Don't use UCS-2
+ var output = [],
+ inputLength = input.length,
+ out,
+ i = 0,
+ n = initialN,
+ bias = initialBias,
+ basic,
+ j,
+ index,
+ oldi,
+ w,
+ k,
+ digit,
+ t,
+ /** Cached calculation results */
+ baseMinusT;
+
+ // Handle the basic code points: let `basic` be the number of input code
+ // points before the last delimiter, or `0` if there is none, then copy
+ // the first basic code points to the output.
+
+ basic = input.lastIndexOf(delimiter);
+ if (basic < 0) {
+ basic = 0;
+ }
+
+ for (j = 0; j < basic; ++j) {
+ // if it's not a basic code point
+ if (input.charCodeAt(j) >= 0x80) {
+ error('not-basic');
+ }
+ output.push(input.charCodeAt(j));
+ }
+
+ // Main decoding loop: start just after the last delimiter if any basic code
+ // points were copied; start at the beginning otherwise.
+
+ for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) {
+
+ // `index` is the index of the next character to be consumed.
+ // Decode a generalized variable-length integer into `delta`,
+ // which gets added to `i`. The overflow checking is easier
+ // if we increase `i` as we go, then subtract off its starting
+ // value at the end to obtain `delta`.
+ for (oldi = i, w = 1, k = base; /* no condition */; k += base) {
+
+ if (index >= inputLength) {
+ error('invalid-input');
+ }
+
+ digit = basicToDigit(input.charCodeAt(index++));
+
+ if (digit >= base || digit > floor((maxInt - i) / w)) {
+ error('overflow');
+ }
+
+ i += digit * w;
+ t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
+
+ if (digit < t) {
+ break;
+ }
+
+ baseMinusT = base - t;
+ if (w > floor(maxInt / baseMinusT)) {
+ error('overflow');
+ }
+
+ w *= baseMinusT;
+
+ }
+
+ out = output.length + 1;
+ bias = adapt(i - oldi, out, oldi == 0);
+
+ // `i` was supposed to wrap around from `out` to `0`,
+ // incrementing `n` each time, so we'll fix that now:
+ if (floor(i / out) > maxInt - n) {
+ error('overflow');
+ }
+
+ n += floor(i / out);
+ i %= out;
+
+ // Insert `n` at position `i` of the output
+ output.splice(i++, 0, n);
+
+ }
+
+ return ucs2encode(output);
+ }
+
+ /**
+ * Converts a string of Unicode symbols (e.g. a domain name label) to a
+ * Punycode string of ASCII-only symbols.
+ * @memberOf punycode
+ * @param {String} input The string of Unicode symbols.
+ * @returns {String} The resulting Punycode string of ASCII-only symbols.
+ */
+ function encode(input) {
+ var n,
+ delta,
+ handledCPCount,
+ basicLength,
+ bias,
+ j,
+ m,
+ q,
+ k,
+ t,
+ currentValue,
+ output = [],
+ /** `inputLength` will hold the number of code points in `input`. */
+ inputLength,
+ /** Cached calculation results */
+ handledCPCountPlusOne,
+ baseMinusT,
+ qMinusT;
+
+ // Convert the input in UCS-2 to Unicode
+ input = ucs2decode(input);
+
+ // Cache the length
+ inputLength = input.length;
+
+ // Initialize the state
+ n = initialN;
+ delta = 0;
+ bias = initialBias;
+
+ // Handle the basic code points
+ for (j = 0; j < inputLength; ++j) {
+ currentValue = input[j];
+ if (currentValue < 0x80) {
+ output.push(stringFromCharCode(currentValue));
+ }
+ }
+
+ handledCPCount = basicLength = output.length;
+
+ // `handledCPCount` is the number of code points that have been handled;
+ // `basicLength` is the number of basic code points.
+
+ // Finish the basic string - if it is not empty - with a delimiter
+ if (basicLength) {
+ output.push(delimiter);
+ }
+
+ // Main encoding loop:
+ while (handledCPCount < inputLength) {
+
+ // All non-basic code points < n have been handled already. Find the next
+ // larger one:
+ for (m = maxInt, j = 0; j < inputLength; ++j) {
+ currentValue = input[j];
+ if (currentValue >= n && currentValue < m) {
+ m = currentValue;
+ }
+ }
+
+ // Increase `delta` enough to advance the decoder's <n,i> state to <m,0>,
+ // but guard against overflow
+ handledCPCountPlusOne = handledCPCount + 1;
+ if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {
+ error('overflow');
+ }
+
+ delta += (m - n) * handledCPCountPlusOne;
+ n = m;
+
+ for (j = 0; j < inputLength; ++j) {
+ currentValue = input[j];
+
+ if (currentValue < n && ++delta > maxInt) {
+ error('overflow');
+ }
+
+ if (currentValue == n) {
+ // Represent delta as a generalized variable-length integer
+ for (q = delta, k = base; /* no condition */; k += base) {
+ t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
+ if (q < t) {
+ break;
+ }
+ qMinusT = q - t;
+ baseMinusT = base - t;
+ output.push(
+ stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0))
+ );
+ q = floor(qMinusT / baseMinusT);
+ }
+
+ output.push(stringFromCharCode(digitToBasic(q, 0)));
+ bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);
+ delta = 0;
+ ++handledCPCount;
+ }
+ }
+
+ ++delta;
+ ++n;
+
+ }
+ return output.join('');
+ }
+
+ /**
+ * Converts a Punycode string representing a domain name or an email address
+ * to Unicode. Only the Punycoded parts of the input will be converted, i.e.
+ * it doesn't matter if you call it on a string that has already been
+ * converted to Unicode.
+ * @memberOf punycode
+ * @param {String} input The Punycoded domain name or email address to
+ * convert to Unicode.
+ * @returns {String} The Unicode representation of the given Punycode
+ * string.
+ */
+ function toUnicode(input) {
+ return mapDomain(input, function(string) {
+ return regexPunycode.test(string)
+ ? decode(string.slice(4).toLowerCase())
+ : string;
+ });
+ }
+
+ /**
+ * Converts a Unicode string representing a domain name or an email address to
+ * Punycode. Only the non-ASCII parts of the domain name will be converted,
+ * i.e. it doesn't matter if you call it with a domain that's already in
+ * ASCII.
+ * @memberOf punycode
+ * @param {String} input The domain name or email address to convert, as a
+ * Unicode string.
+ * @returns {String} The Punycode representation of the given domain name or
+ * email address.
+ */
+ function toASCII(input) {
+ return mapDomain(input, function(string) {
+ return regexNonASCII.test(string)
+ ? 'xn--' + encode(string)
+ : string;
+ });
+ }
+
+ /*--------------------------------------------------------------------------*/
+
+ /** Define the public API */
+ punycode = {
+ /**
+ * A string representing the current Punycode.js version number.
+ * @memberOf punycode
+ * @type String
+ */
+ 'version': '1.3.2',
+ /**
+ * An object of methods to convert from JavaScript's internal character
+ * representation (UCS-2) to Unicode code points, and back.
+ * @see <https://mathiasbynens.be/notes/javascript-encoding>
+ * @memberOf punycode
+ * @type Object
+ */
+ 'ucs2': {
+ 'decode': ucs2decode,
+ 'encode': ucs2encode
+ },
+ 'decode': decode,
+ 'encode': encode,
+ 'toASCII': toASCII,
+ 'toUnicode': toUnicode
+ };
+
+ /** Expose `punycode` */
+ // Some AMD build optimizers, like r.js, check for specific condition patterns
+ // like the following:
+ if (
+ true
+ ) {
+ !(__WEBPACK_AMD_DEFINE_RESULT__ = function() {
+ return punycode;
+ }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
+ } else if (freeExports && freeModule) {
+ if (module.exports == freeExports) { // in Node.js or RingoJS v0.8.0+
+ freeModule.exports = punycode;
+ } else { // in Narwhal or RingoJS v0.7.0-
+ for (key in punycode) {
+ punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]);
+ }
+ }
+ } else { // in Rhino or a web browser
+ root.punycode = punycode;
+ }
+
+ }(this));
+
+ /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(4)(module), (function() { return this; }())))
+
+/***/ }),
+/* 4 */
+/***/ (function(module, exports) {
+
+ module.exports = function(module) {
+ if(!module.webpackPolyfill) {
+ module.deprecate = function() {};
+ module.paths = [];
+ // module.parent = undefined by default
+ module.children = [];
+ module.webpackPolyfill = 1;
+ }
+ return module;
+ }
+
+
+/***/ }),
+/* 5 */
+/***/ (function(module, exports) {
+
+ 'use strict';
+
+ module.exports = {
+ isString: function(arg) {
+ return typeof(arg) === 'string';
+ },
+ isObject: function(arg) {
+ return typeof(arg) === 'object' && arg !== null;
+ },
+ isNull: function(arg) {
+ return arg === null;
+ },
+ isNullOrUndefined: function(arg) {
+ return arg == null;
+ }
+ };
+
+
+/***/ }),
+/* 6 */
+/***/ (function(module, exports, __webpack_require__) {
+
+ 'use strict';
+
+ exports.decode = exports.parse = __webpack_require__(7);
+ exports.encode = exports.stringify = __webpack_require__(8);
+
+
+/***/ }),
+/* 7 */
+/***/ (function(module, exports) {
+
+ // Copyright Joyent, Inc. and other Node contributors.
+ //
+ // Permission is hereby granted, free of charge, to any person obtaining a
+ // copy of this software and associated documentation files (the
+ // "Software"), to deal in the Software without restriction, including
+ // without limitation the rights to use, copy, modify, merge, publish,
+ // distribute, sublicense, and/or sell copies of the Software, and to permit
+ // persons to whom the Software is furnished to do so, subject to the
+ // following conditions:
+ //
+ // The above copyright notice and this permission notice shall be included
+ // in all copies or substantial portions of the Software.
+ //
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+ // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ // USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ 'use strict';
+
+ // If obj.hasOwnProperty has been overridden, then calling
+ // obj.hasOwnProperty(prop) will break.
+ // See: https://github.com/joyent/node/issues/1707
+ function hasOwnProperty(obj, prop) {
+ return Object.prototype.hasOwnProperty.call(obj, prop);
+ }
+
+ module.exports = function(qs, sep, eq, options) {
+ sep = sep || '&';
+ eq = eq || '=';
+ var obj = {};
+
+ if (typeof qs !== 'string' || qs.length === 0) {
+ return obj;
+ }
+
+ var regexp = /\+/g;
+ qs = qs.split(sep);
+
+ var maxKeys = 1000;
+ if (options && typeof options.maxKeys === 'number') {
+ maxKeys = options.maxKeys;
+ }
+
+ var len = qs.length;
+ // maxKeys <= 0 means that we should not limit keys count
+ if (maxKeys > 0 && len > maxKeys) {
+ len = maxKeys;
+ }
+
+ for (var i = 0; i < len; ++i) {
+ var x = qs[i].replace(regexp, '%20'),
+ idx = x.indexOf(eq),
+ kstr, vstr, k, v;
+
+ if (idx >= 0) {
+ kstr = x.substr(0, idx);
+ vstr = x.substr(idx + 1);
+ } else {
+ kstr = x;
+ vstr = '';
+ }
+
+ k = decodeURIComponent(kstr);
+ v = decodeURIComponent(vstr);
+
+ if (!hasOwnProperty(obj, k)) {
+ obj[k] = v;
+ } else if (Array.isArray(obj[k])) {
+ obj[k].push(v);
+ } else {
+ obj[k] = [obj[k], v];
+ }
+ }
+
+ return obj;
+ };
+
+
+/***/ }),
+/* 8 */
+/***/ (function(module, exports) {
+
+ // Copyright Joyent, Inc. and other Node contributors.
+ //
+ // Permission is hereby granted, free of charge, to any person obtaining a
+ // copy of this software and associated documentation files (the
+ // "Software"), to deal in the Software without restriction, including
+ // without limitation the rights to use, copy, modify, merge, publish,
+ // distribute, sublicense, and/or sell copies of the Software, and to permit
+ // persons to whom the Software is furnished to do so, subject to the
+ // following conditions:
+ //
+ // The above copyright notice and this permission notice shall be included
+ // in all copies or substantial portions of the Software.
+ //
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+ // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ // USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ 'use strict';
+
+ var stringifyPrimitive = function(v) {
+ switch (typeof v) {
+ case 'string':
+ return v;
+
+ case 'boolean':
+ return v ? 'true' : 'false';
+
+ case 'number':
+ return isFinite(v) ? v : '';
+
+ default:
+ return '';
+ }
+ };
+
+ module.exports = function(obj, sep, eq, name) {
+ sep = sep || '&';
+ eq = eq || '=';
+ if (obj === null) {
+ obj = undefined;
+ }
+
+ if (typeof obj === 'object') {
+ return Object.keys(obj).map(function(k) {
+ var ks = encodeURIComponent(stringifyPrimitive(k)) + eq;
+ if (Array.isArray(obj[k])) {
+ return obj[k].map(function(v) {
+ return ks + encodeURIComponent(stringifyPrimitive(v));
+ }).join(sep);
+ } else {
+ return ks + encodeURIComponent(stringifyPrimitive(obj[k]));
+ }
+ }).join(sep);
+
+ }
+
+ if (!name) return '';
+ return encodeURIComponent(stringifyPrimitive(name)) + eq +
+ encodeURIComponent(stringifyPrimitive(obj));
+ };
+
+
+/***/ }),
+/* 9 */
+/***/ (function(module, exports, __webpack_require__) {
+
+ /* WEBPACK VAR INJECTION */(function(global, process) {// Copyright Joyent, Inc. and other Node contributors.
+ //
+ // Permission is hereby granted, free of charge, to any person obtaining a
+ // copy of this software and associated documentation files (the
+ // "Software"), to deal in the Software without restriction, including
+ // without limitation the rights to use, copy, modify, merge, publish,
+ // distribute, sublicense, and/or sell copies of the Software, and to permit
+ // persons to whom the Software is furnished to do so, subject to the
+ // following conditions:
+ //
+ // The above copyright notice and this permission notice shall be included
+ // in all copies or substantial portions of the Software.
+ //
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+ // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ // USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ var formatRegExp = /%[sdj%]/g;
+ exports.format = function(f) {
+ if (!isString(f)) {
+ var objects = [];
+ for (var i = 0; i < arguments.length; i++) {
+ objects.push(inspect(arguments[i]));
+ }
+ return objects.join(' ');
+ }
+
+ var i = 1;
+ var args = arguments;
+ var len = args.length;
+ var str = String(f).replace(formatRegExp, function(x) {
+ if (x === '%%') return '%';
+ if (i >= len) return x;
+ switch (x) {
+ case '%s': return String(args[i++]);
+ case '%d': return Number(args[i++]);
+ case '%j':
+ try {
+ return JSON.stringify(args[i++]);
+ } catch (_) {
+ return '[Circular]';
+ }
+ default:
+ return x;
+ }
+ });
+ for (var x = args[i]; i < len; x = args[++i]) {
+ if (isNull(x) || !isObject(x)) {
+ str += ' ' + x;
+ } else {
+ str += ' ' + inspect(x);
+ }
+ }
+ return str;
+ };
+
+
+ // Mark that a method should not be used.
+ // Returns a modified function which warns once by default.
+ // If --no-deprecation is set, then it is a no-op.
+ exports.deprecate = function(fn, msg) {
+ // Allow for deprecating things in the process of starting up.
+ if (isUndefined(global.process)) {
+ return function() {
+ return exports.deprecate(fn, msg).apply(this, arguments);
+ };
+ }
+
+ if (process.noDeprecation === true) {
+ return fn;
+ }
+
+ var warned = false;
+ function deprecated() {
+ if (!warned) {
+ if (process.throwDeprecation) {
+ throw new Error(msg);
+ } else if (process.traceDeprecation) {
+ console.trace(msg);
+ } else {
+ console.error(msg);
+ }
+ warned = true;
+ }
+ return fn.apply(this, arguments);
+ }
+
+ return deprecated;
+ };
+
+
+ var debugs = {};
+ var debugEnviron;
+ exports.debuglog = function(set) {
+ if (isUndefined(debugEnviron))
+ debugEnviron = process.env.NODE_DEBUG || '';
+ set = set.toUpperCase();
+ if (!debugs[set]) {
+ if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) {
+ var pid = process.pid;
+ debugs[set] = function() {
+ var msg = exports.format.apply(exports, arguments);
+ console.error('%s %d: %s', set, pid, msg);
+ };
+ } else {
+ debugs[set] = function() {};
+ }
+ }
+ return debugs[set];
+ };
+
+
+ /**
+ * Echos the value of a value. Trys to print the value out
+ * in the best way possible given the different types.
+ *
+ * @param {Object} obj The object to print out.
+ * @param {Object} opts Optional options object that alters the output.
+ */
+ /* legacy: obj, showHidden, depth, colors*/
+ function inspect(obj, opts) {
+ // default options
+ var ctx = {
+ seen: [],
+ stylize: stylizeNoColor
+ };
+ // legacy...
+ if (arguments.length >= 3) ctx.depth = arguments[2];
+ if (arguments.length >= 4) ctx.colors = arguments[3];
+ if (isBoolean(opts)) {
+ // legacy...
+ ctx.showHidden = opts;
+ } else if (opts) {
+ // got an "options" object
+ exports._extend(ctx, opts);
+ }
+ // set default options
+ if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
+ if (isUndefined(ctx.depth)) ctx.depth = 2;
+ if (isUndefined(ctx.colors)) ctx.colors = false;
+ if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
+ if (ctx.colors) ctx.stylize = stylizeWithColor;
+ return formatValue(ctx, obj, ctx.depth);
+ }
+ exports.inspect = inspect;
+
+
+ // http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
+ inspect.colors = {
+ 'bold' : [1, 22],
+ 'italic' : [3, 23],
+ 'underline' : [4, 24],
+ 'inverse' : [7, 27],
+ 'white' : [37, 39],
+ 'grey' : [90, 39],
+ 'black' : [30, 39],
+ 'blue' : [34, 39],
+ 'cyan' : [36, 39],
+ 'green' : [32, 39],
+ 'magenta' : [35, 39],
+ 'red' : [31, 39],
+ 'yellow' : [33, 39]
+ };
+
+ // Don't use 'blue' not visible on cmd.exe
+ inspect.styles = {
+ 'special': 'cyan',
+ 'number': 'yellow',
+ 'boolean': 'yellow',
+ 'undefined': 'grey',
+ 'null': 'bold',
+ 'string': 'green',
+ 'date': 'magenta',
+ // "name": intentionally not styling
+ 'regexp': 'red'
+ };
+
+
+ function stylizeWithColor(str, styleType) {
+ var style = inspect.styles[styleType];
+
+ if (style) {
+ return '\u001b[' + inspect.colors[style][0] + 'm' + str +
+ '\u001b[' + inspect.colors[style][1] + 'm';
+ } else {
+ return str;
+ }
+ }
+
+
+ function stylizeNoColor(str, styleType) {
+ return str;
+ }
+
+
+ function arrayToHash(array) {
+ var hash = {};
+
+ array.forEach(function(val, idx) {
+ hash[val] = true;
+ });
+
+ return hash;
+ }
+
+
+ function formatValue(ctx, value, recurseTimes) {
+ // Provide a hook for user-specified inspect functions.
+ // Check that value is an object with an inspect function on it
+ if (ctx.customInspect &&
+ value &&
+ isFunction(value.inspect) &&
+ // Filter out the util module, it's inspect function is special
+ value.inspect !== exports.inspect &&
+ // Also filter out any prototype objects using the circular check.
+ !(value.constructor && value.constructor.prototype === value)) {
+ var ret = value.inspect(recurseTimes, ctx);
+ if (!isString(ret)) {
+ ret = formatValue(ctx, ret, recurseTimes);
+ }
+ return ret;
+ }
+
+ // Primitive types cannot have properties
+ var primitive = formatPrimitive(ctx, value);
+ if (primitive) {
+ return primitive;
+ }
+
+ // Look up the keys of the object.
+ var keys = Object.keys(value);
+ var visibleKeys = arrayToHash(keys);
+
+ if (ctx.showHidden) {
+ keys = Object.getOwnPropertyNames(value);
+ }
+
+ // IE doesn't make error fields non-enumerable
+ // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx
+ if (isError(value)
+ && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) {
+ return formatError(value);
+ }
+
+ // Some type of object without properties can be shortcutted.
+ if (keys.length === 0) {
+ if (isFunction(value)) {
+ var name = value.name ? ': ' + value.name : '';
+ return ctx.stylize('[Function' + name + ']', 'special');
+ }
+ if (isRegExp(value)) {
+ return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
+ }
+ if (isDate(value)) {
+ return ctx.stylize(Date.prototype.toString.call(value), 'date');
+ }
+ if (isError(value)) {
+ return formatError(value);
+ }
+ }
+
+ var base = '', array = false, braces = ['{', '}'];
+
+ // Make Array say that they are Array
+ if (isArray(value)) {
+ array = true;
+ braces = ['[', ']'];
+ }
+
+ // Make functions say that they are functions
+ if (isFunction(value)) {
+ var n = value.name ? ': ' + value.name : '';
+ base = ' [Function' + n + ']';
+ }
+
+ // Make RegExps say that they are RegExps
+ if (isRegExp(value)) {
+ base = ' ' + RegExp.prototype.toString.call(value);
+ }
+
+ // Make dates with properties first say the date
+ if (isDate(value)) {
+ base = ' ' + Date.prototype.toUTCString.call(value);
+ }
+
+ // Make error with message first say the error
+ if (isError(value)) {
+ base = ' ' + formatError(value);
+ }
+
+ if (keys.length === 0 && (!array || value.length == 0)) {
+ return braces[0] + base + braces[1];
+ }
+
+ if (recurseTimes < 0) {
+ if (isRegExp(value)) {
+ return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
+ } else {
+ return ctx.stylize('[Object]', 'special');
+ }
+ }
+
+ ctx.seen.push(value);
+
+ var output;
+ if (array) {
+ output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
+ } else {
+ output = keys.map(function(key) {
+ return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
+ });
+ }
+
+ ctx.seen.pop();
+
+ return reduceToSingleString(output, base, braces);
+ }
+
+
+ function formatPrimitive(ctx, value) {
+ if (isUndefined(value))
+ return ctx.stylize('undefined', 'undefined');
+ if (isString(value)) {
+ var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
+ .replace(/'/g, "\\'")
+ .replace(/\\"/g, '"') + '\'';
+ return ctx.stylize(simple, 'string');
+ }
+ if (isNumber(value))
+ return ctx.stylize('' + value, 'number');
+ if (isBoolean(value))
+ return ctx.stylize('' + value, 'boolean');
+ // For some reason typeof null is "object", so special case here.
+ if (isNull(value))
+ return ctx.stylize('null', 'null');
+ }
+
+
+ function formatError(value) {
+ return '[' + Error.prototype.toString.call(value) + ']';
+ }
+
+
+ function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
+ var output = [];
+ for (var i = 0, l = value.length; i < l; ++i) {
+ if (hasOwnProperty(value, String(i))) {
+ output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
+ String(i), true));
+ } else {
+ output.push('');
+ }
+ }
+ keys.forEach(function(key) {
+ if (!key.match(/^\d+$/)) {
+ output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
+ key, true));
+ }
+ });
+ return output;
+ }
+
+
+ function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
+ var name, str, desc;
+ desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] };
+ if (desc.get) {
+ if (desc.set) {
+ str = ctx.stylize('[Getter/Setter]', 'special');
+ } else {
+ str = ctx.stylize('[Getter]', 'special');
+ }
+ } else {
+ if (desc.set) {
+ str = ctx.stylize('[Setter]', 'special');
+ }
+ }
+ if (!hasOwnProperty(visibleKeys, key)) {
+ name = '[' + key + ']';
+ }
+ if (!str) {
+ if (ctx.seen.indexOf(desc.value) < 0) {
+ if (isNull(recurseTimes)) {
+ str = formatValue(ctx, desc.value, null);
+ } else {
+ str = formatValue(ctx, desc.value, recurseTimes - 1);
+ }
+ if (str.indexOf('\n') > -1) {
+ if (array) {
+ str = str.split('\n').map(function(line) {
+ return ' ' + line;
+ }).join('\n').substr(2);
+ } else {
+ str = '\n' + str.split('\n').map(function(line) {
+ return ' ' + line;
+ }).join('\n');
+ }
+ }
+ } else {
+ str = ctx.stylize('[Circular]', 'special');
+ }
+ }
+ if (isUndefined(name)) {
+ if (array && key.match(/^\d+$/)) {
+ return str;
+ }
+ name = JSON.stringify('' + key);
+ if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
+ name = name.substr(1, name.length - 2);
+ name = ctx.stylize(name, 'name');
+ } else {
+ name = name.replace(/'/g, "\\'")
+ .replace(/\\"/g, '"')
+ .replace(/(^"|"$)/g, "'");
+ name = ctx.stylize(name, 'string');
+ }
+ }
+
+ return name + ': ' + str;
+ }
+
+
+ function reduceToSingleString(output, base, braces) {
+ var numLinesEst = 0;
+ var length = output.reduce(function(prev, cur) {
+ numLinesEst++;
+ if (cur.indexOf('\n') >= 0) numLinesEst++;
+ return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1;
+ }, 0);
+
+ if (length > 60) {
+ return braces[0] +
+ (base === '' ? '' : base + '\n ') +
+ ' ' +
+ output.join(',\n ') +
+ ' ' +
+ braces[1];
+ }
+
+ return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
+ }
+
+
+ // NOTE: These type checking functions intentionally don't use `instanceof`
+ // because it is fragile and can be easily faked with `Object.create()`.
+ function isArray(ar) {
+ return Array.isArray(ar);
+ }
+ exports.isArray = isArray;
+
+ function isBoolean(arg) {
+ return typeof arg === 'boolean';
+ }
+ exports.isBoolean = isBoolean;
+
+ function isNull(arg) {
+ return arg === null;
+ }
+ exports.isNull = isNull;
+
+ function isNullOrUndefined(arg) {
+ return arg == null;
+ }
+ exports.isNullOrUndefined = isNullOrUndefined;
+
+ function isNumber(arg) {
+ return typeof arg === 'number';
+ }
+ exports.isNumber = isNumber;
+
+ function isString(arg) {
+ return typeof arg === 'string';
+ }
+ exports.isString = isString;
+
+ function isSymbol(arg) {
+ return typeof arg === 'symbol';
+ }
+ exports.isSymbol = isSymbol;
+
+ function isUndefined(arg) {
+ return arg === void 0;
+ }
+ exports.isUndefined = isUndefined;
+
+ function isRegExp(re) {
+ return isObject(re) && objectToString(re) === '[object RegExp]';
+ }
+ exports.isRegExp = isRegExp;
+
+ function isObject(arg) {
+ return typeof arg === 'object' && arg !== null;
+ }
+ exports.isObject = isObject;
+
+ function isDate(d) {
+ return isObject(d) && objectToString(d) === '[object Date]';
+ }
+ exports.isDate = isDate;
+
+ function isError(e) {
+ return isObject(e) &&
+ (objectToString(e) === '[object Error]' || e instanceof Error);
+ }
+ exports.isError = isError;
+
+ function isFunction(arg) {
+ return typeof arg === 'function';
+ }
+ exports.isFunction = isFunction;
+
+ function isPrimitive(arg) {
+ return arg === null ||
+ typeof arg === 'boolean' ||
+ typeof arg === 'number' ||
+ typeof arg === 'string' ||
+ typeof arg === 'symbol' || // ES6 symbol
+ typeof arg === 'undefined';
+ }
+ exports.isPrimitive = isPrimitive;
+
+ exports.isBuffer = __webpack_require__(11);
+
+ function objectToString(o) {
+ return Object.prototype.toString.call(o);
+ }
+
+
+ function pad(n) {
+ return n < 10 ? '0' + n.toString(10) : n.toString(10);
+ }
+
+
+ var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
+ 'Oct', 'Nov', 'Dec'];
+
+ // 26 Feb 16:19:34
+ function timestamp() {
+ var d = new Date();
+ var time = [pad(d.getHours()),
+ pad(d.getMinutes()),
+ pad(d.getSeconds())].join(':');
+ return [d.getDate(), months[d.getMonth()], time].join(' ');
+ }
+
+
+ // log is just a thin wrapper to console.log that prepends a timestamp
+ exports.log = function() {
+ console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));
+ };
+
+
+ /**
+ * Inherit the prototype methods from one constructor into another.
+ *
+ * The Function.prototype.inherits from lang.js rewritten as a standalone
+ * function (not on Function.prototype). NOTE: If this file is to be loaded
+ * during bootstrapping this function needs to be rewritten using some native
+ * functions as prototype setup using normal JavaScript does not work as
+ * expected during bootstrapping (see mirror.js in r114903).
+ *
+ * @param {function} ctor Constructor function which needs to inherit the
+ * prototype.
+ * @param {function} superCtor Constructor function to inherit prototype from.
+ */
+ exports.inherits = __webpack_require__(12);
+
+ exports._extend = function(origin, add) {
+ // Don't do anything if add isn't an object
+ if (!add || !isObject(add)) return origin;
+
+ var keys = Object.keys(add);
+ var i = keys.length;
+ while (i--) {
+ origin[keys[i]] = add[keys[i]];
+ }
+ return origin;
+ };
+
+ function hasOwnProperty(obj, prop) {
+ return Object.prototype.hasOwnProperty.call(obj, prop);
+ }
+
+ /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()), __webpack_require__(10)))
+
+/***/ }),
+/* 10 */
+/***/ (function(module, exports) {
+
+ // shim for using process in browser
+ var process = module.exports = {};
+
+ // cached from whatever global is present so that test runners that stub it
+ // don't break things. But we need to wrap it in a try catch in case it is
+ // wrapped in strict mode code which doesn't define any globals. It's inside a
+ // function because try/catches deoptimize in certain engines.
+
+ var cachedSetTimeout;
+ var cachedClearTimeout;
+
+ function defaultSetTimout() {
+ throw new Error('setTimeout has not been defined');
+ }
+ function defaultClearTimeout () {
+ throw new Error('clearTimeout has not been defined');
+ }
+ (function () {
+ try {
+ if (typeof setTimeout === 'function') {
+ cachedSetTimeout = setTimeout;
+ } else {
+ cachedSetTimeout = defaultSetTimout;
+ }
+ } catch (e) {
+ cachedSetTimeout = defaultSetTimout;
+ }
+ try {
+ if (typeof clearTimeout === 'function') {
+ cachedClearTimeout = clearTimeout;
+ } else {
+ cachedClearTimeout = defaultClearTimeout;
+ }
+ } catch (e) {
+ cachedClearTimeout = defaultClearTimeout;
+ }
+ } ())
+ function runTimeout(fun) {
+ if (cachedSetTimeout === setTimeout) {
+ //normal enviroments in sane situations
+ return setTimeout(fun, 0);
+ }
+ // if setTimeout wasn't available but was latter defined
+ if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
+ cachedSetTimeout = setTimeout;
+ return setTimeout(fun, 0);
+ }
+ try {
+ // when when somebody has screwed with setTimeout but no I.E. maddness
+ return cachedSetTimeout(fun, 0);
+ } catch(e){
+ try {
+ // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
+ return cachedSetTimeout.call(null, fun, 0);
+ } catch(e){
+ // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
+ return cachedSetTimeout.call(this, fun, 0);
+ }
+ }
+
+
+ }
+ function runClearTimeout(marker) {
+ if (cachedClearTimeout === clearTimeout) {
+ //normal enviroments in sane situations
+ return clearTimeout(marker);
+ }
+ // if clearTimeout wasn't available but was latter defined
+ if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
+ cachedClearTimeout = clearTimeout;
+ return clearTimeout(marker);
+ }
+ try {
+ // when when somebody has screwed with setTimeout but no I.E. maddness
+ return cachedClearTimeout(marker);
+ } catch (e){
+ try {
+ // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
+ return cachedClearTimeout.call(null, marker);
+ } catch (e){
+ // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
+ // Some versions of I.E. have different rules for clearTimeout vs setTimeout
+ return cachedClearTimeout.call(this, marker);
+ }
+ }
+
+
+
+ }
+ var queue = [];
+ var draining = false;
+ var currentQueue;
+ var queueIndex = -1;
+
+ function cleanUpNextTick() {
+ if (!draining || !currentQueue) {
+ return;
+ }
+ draining = false;
+ if (currentQueue.length) {
+ queue = currentQueue.concat(queue);
+ } else {
+ queueIndex = -1;
+ }
+ if (queue.length) {
+ drainQueue();
+ }
+ }
+
+ function drainQueue() {
+ if (draining) {
+ return;
+ }
+ var timeout = runTimeout(cleanUpNextTick);
+ draining = true;
+
+ var len = queue.length;
+ while(len) {
+ currentQueue = queue;
+ queue = [];
+ while (++queueIndex < len) {
+ if (currentQueue) {
+ currentQueue[queueIndex].run();
+ }
+ }
+ queueIndex = -1;
+ len = queue.length;
+ }
+ currentQueue = null;
+ draining = false;
+ runClearTimeout(timeout);
+ }
+
+ process.nextTick = function (fun) {
+ var args = new Array(arguments.length - 1);
+ if (arguments.length > 1) {
+ for (var i = 1; i < arguments.length; i++) {
+ args[i - 1] = arguments[i];
+ }
+ }
+ queue.push(new Item(fun, args));
+ if (queue.length === 1 && !draining) {
+ runTimeout(drainQueue);
+ }
+ };
+
+ // v8 likes predictible objects
+ function Item(fun, array) {
+ this.fun = fun;
+ this.array = array;
+ }
+ Item.prototype.run = function () {
+ this.fun.apply(null, this.array);
+ };
+ process.title = 'browser';
+ process.browser = true;
+ process.env = {};
+ process.argv = [];
+ process.version = ''; // empty string to avoid regexp issues
+ process.versions = {};
+
+ function noop() {}
+
+ process.on = noop;
+ process.addListener = noop;
+ process.once = noop;
+ process.off = noop;
+ process.removeListener = noop;
+ process.removeAllListeners = noop;
+ process.emit = noop;
+ process.prependListener = noop;
+ process.prependOnceListener = noop;
+
+ process.listeners = function (name) { return [] }
+
+ process.binding = function (name) {
+ throw new Error('process.binding is not supported');
+ };
+
+ process.cwd = function () { return '/' };
+ process.chdir = function (dir) {
+ throw new Error('process.chdir is not supported');
+ };
+ process.umask = function() { return 0; };
+
+
+/***/ }),
+/* 11 */
+/***/ (function(module, exports) {
+
+ module.exports = function isBuffer(arg) {
+ return arg && typeof arg === 'object'
+ && typeof arg.copy === 'function'
+ && typeof arg.fill === 'function'
+ && typeof arg.readUInt8 === 'function';
+ }
+
+/***/ }),
+/* 12 */
+/***/ (function(module, exports) {
+
+ if (typeof Object.create === 'function') {
+ // implementation from standard node.js 'util' module
+ module.exports = function inherits(ctor, superCtor) {
+ ctor.super_ = superCtor
+ ctor.prototype = Object.create(superCtor.prototype, {
+ constructor: {
+ value: ctor,
+ enumerable: false,
+ writable: true,
+ configurable: true
+ }
+ });
+ };
+ } else {
+ // old school shim for old browsers
+ module.exports = function inherits(ctor, superCtor) {
+ ctor.super_ = superCtor
+ var TempCtor = function () {}
+ TempCtor.prototype = superCtor.prototype
+ ctor.prototype = new TempCtor()
+ ctor.prototype.constructor = ctor
+ }
+ }
+
+
+/***/ }),
+/* 13 */
+/***/ (function(module, exports, __webpack_require__) {
+
+ /*!
+ * Copyright (c) 2018, Salesforce.com, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of Salesforce.com nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+ 'use strict';
+ var psl = __webpack_require__(14);
+
+ function getPublicSuffix(domain) {
+ return psl.get(domain);
+ }
+
+ exports.getPublicSuffix = getPublicSuffix;
+
+
+/***/ }),
+/* 14 */
+/***/ (function(module, exports, __webpack_require__) {
+
+ /*eslint no-var:0, prefer-arrow-callback: 0, object-shorthand: 0 */
+ 'use strict';
+
+
+ var Punycode = __webpack_require__(15);
+
+
+ var internals = {};
+
+
+ //
+ // Read rules from file.
+ //
+ internals.rules = __webpack_require__(16).map(function (rule) {
+
+ return {
+ rule: rule,
+ suffix: rule.replace(/^(\*\.|\!)/, ''),
+ punySuffix: -1,
+ wildcard: rule.charAt(0) === '*',
+ exception: rule.charAt(0) === '!'
+ };
+ });
+
+
+ //
+ // Check is given string ends with `suffix`.
+ //
+ internals.endsWith = function (str, suffix) {
+
+ return str.indexOf(suffix, str.length - suffix.length) !== -1;
+ };
+
+
+ //
+ // Find rule for a given domain.
+ //
+ internals.findRule = function (domain) {
+
+ var punyDomain = Punycode.toASCII(domain);
+ return internals.rules.reduce(function (memo, rule) {
+
+ if (rule.punySuffix === -1){
+ rule.punySuffix = Punycode.toASCII(rule.suffix);
+ }
+ if (!internals.endsWith(punyDomain, '.' + rule.punySuffix) && punyDomain !== rule.punySuffix) {
+ return memo;
+ }
+ // This has been commented out as it never seems to run. This is because
+ // sub tlds always appear after their parents and we never find a shorter
+ // match.
+ //if (memo) {
+ // var memoSuffix = Punycode.toASCII(memo.suffix);
+ // if (memoSuffix.length >= punySuffix.length) {
+ // return memo;
+ // }
+ //}
+ return rule;
+ }, null);
+ };
+
+
+ //
+ // Error codes and messages.
+ //
+ exports.errorCodes = {
+ DOMAIN_TOO_SHORT: 'Domain name too short.',
+ DOMAIN_TOO_LONG: 'Domain name too long. It should be no more than 255 chars.',
+ LABEL_STARTS_WITH_DASH: 'Domain name label can not start with a dash.',
+ LABEL_ENDS_WITH_DASH: 'Domain name label can not end with a dash.',
+ LABEL_TOO_LONG: 'Domain name label should be at most 63 chars long.',
+ LABEL_TOO_SHORT: 'Domain name label should be at least 1 character long.',
+ LABEL_INVALID_CHARS: 'Domain name label can only contain alphanumeric characters or dashes.'
+ };
+
+
+ //
+ // Validate domain name and throw if not valid.
+ //
+ // From wikipedia:
+ //
+ // Hostnames are composed of series of labels concatenated with dots, as are all
+ // domain names. Each label must be between 1 and 63 characters long, and the
+ // entire hostname (including the delimiting dots) has a maximum of 255 chars.
+ //
+ // Allowed chars:
+ //
+ // * `a-z`
+ // * `0-9`
+ // * `-` but not as a starting or ending character
+ // * `.` as a separator for the textual portions of a domain name
+ //
+ // * http://en.wikipedia.org/wiki/Domain_name
+ // * http://en.wikipedia.org/wiki/Hostname
+ //
+ internals.validate = function (input) {
+
+ // Before we can validate we need to take care of IDNs with unicode chars.
+ var ascii = Punycode.toASCII(input);
+
+ if (ascii.length < 1) {
+ return 'DOMAIN_TOO_SHORT';
+ }
+ if (ascii.length > 255) {
+ return 'DOMAIN_TOO_LONG';
+ }
+
+ // Check each part's length and allowed chars.
+ var labels = ascii.split('.');
+ var label;
+
+ for (var i = 0; i < labels.length; ++i) {
+ label = labels[i];
+ if (!label.length) {
+ return 'LABEL_TOO_SHORT';
+ }
+ if (label.length > 63) {
+ return 'LABEL_TOO_LONG';
+ }
+ if (label.charAt(0) === '-') {
+ return 'LABEL_STARTS_WITH_DASH';
+ }
+ if (label.charAt(label.length - 1) === '-') {
+ return 'LABEL_ENDS_WITH_DASH';
+ }
+ if (!/^[a-z0-9\-]+$/.test(label)) {
+ return 'LABEL_INVALID_CHARS';
+ }
+ }
+ };
+
+
+ //
+ // Public API
+ //
+
+
+ //
+ // Parse domain.
+ //
+ exports.parse = function (input) {
+
+ if (typeof input !== 'string') {
+ throw new TypeError('Domain name must be a string.');
+ }
+
+ // Force domain to lowercase.
+ var domain = input.slice(0).toLowerCase();
+
+ // Handle FQDN.
+ // TODO: Simply remove trailing dot?
+ if (domain.charAt(domain.length - 1) === '.') {
+ domain = domain.slice(0, domain.length - 1);
+ }
+
+ // Validate and sanitise input.
+ var error = internals.validate(domain);
+ if (error) {
+ return {
+ input: input,
+ error: {
+ message: exports.errorCodes[error],
+ code: error
+ }
+ };
+ }
+
+ var parsed = {
+ input: input,
+ tld: null,
+ sld: null,
+ domain: null,
+ subdomain: null,
+ listed: false
+ };
+
+ var domainParts = domain.split('.');
+
+ // Non-Internet TLD
+ if (domainParts[domainParts.length - 1] === 'local') {
+ return parsed;
+ }
+
+ var handlePunycode = function () {
+
+ if (!/xn--/.test(domain)) {
+ return parsed;
+ }
+ if (parsed.domain) {
+ parsed.domain = Punycode.toASCII(parsed.domain);
+ }
+ if (parsed.subdomain) {
+ parsed.subdomain = Punycode.toASCII(parsed.subdomain);
+ }
+ return parsed;
+ };
+
+ var rule = internals.findRule(domain);
+
+ // Unlisted tld.
+ if (!rule) {
+ if (domainParts.length < 2) {
+ return parsed;
+ }
+ parsed.tld = domainParts.pop();
+ parsed.sld = domainParts.pop();
+ parsed.domain = [parsed.sld, parsed.tld].join('.');
+ if (domainParts.length) {
+ parsed.subdomain = domainParts.pop();
+ }
+ return handlePunycode();
+ }
+
+ // At this point we know the public suffix is listed.
+ parsed.listed = true;
+
+ var tldParts = rule.suffix.split('.');
+ var privateParts = domainParts.slice(0, domainParts.length - tldParts.length);
+
+ if (rule.exception) {
+ privateParts.push(tldParts.shift());
+ }
+
+ parsed.tld = tldParts.join('.');
+
+ if (!privateParts.length) {
+ return handlePunycode();
+ }
+
+ if (rule.wildcard) {
+ tldParts.unshift(privateParts.pop());
+ parsed.tld = tldParts.join('.');
+ }
+
+ if (!privateParts.length) {
+ return handlePunycode();
+ }
+
+ parsed.sld = privateParts.pop();
+ parsed.domain = [parsed.sld, parsed.tld].join('.');
+
+ if (privateParts.length) {
+ parsed.subdomain = privateParts.join('.');
+ }
+
+ return handlePunycode();
+ };
+
+
+ //
+ // Get domain.
+ //
+ exports.get = function (domain) {
+
+ if (!domain) {
+ return null;
+ }
+ return exports.parse(domain).domain || null;
+ };
+
+
+ //
+ // Check whether domain belongs to a known public suffix.
+ //
+ exports.isValid = function (domain) {
+
+ var parsed = exports.parse(domain);
+ return Boolean(parsed.domain && parsed.listed);
+ };
+
+
+/***/ }),
+/* 15 */
+/***/ (function(module, exports, __webpack_require__) {
+
+ var __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(module, global) {/*! https://mths.be/punycode v1.4.1 by @mathias */
+ ;(function(root) {
+
+ /** Detect free variables */
+ var freeExports = typeof exports == 'object' && exports &&
+ !exports.nodeType && exports;
+ var freeModule = typeof module == 'object' && module &&
+ !module.nodeType && module;
+ var freeGlobal = typeof global == 'object' && global;
+ if (
+ freeGlobal.global === freeGlobal ||
+ freeGlobal.window === freeGlobal ||
+ freeGlobal.self === freeGlobal
+ ) {
+ root = freeGlobal;
+ }
+
+ /**
+ * The `punycode` object.
+ * @name punycode
+ * @type Object
+ */
+ var punycode,
+
+ /** Highest positive signed 32-bit float value */
+ maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1
+
+ /** Bootstring parameters */
+ base = 36,
+ tMin = 1,
+ tMax = 26,
+ skew = 38,
+ damp = 700,
+ initialBias = 72,
+ initialN = 128, // 0x80
+ delimiter = '-', // '\x2D'
+
+ /** Regular expressions */
+ regexPunycode = /^xn--/,
+ regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars
+ regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators
+
+ /** Error messages */
+ errors = {
+ 'overflow': 'Overflow: input needs wider integers to process',
+ 'not-basic': 'Illegal input >= 0x80 (not a basic code point)',
+ 'invalid-input': 'Invalid input'
+ },
+
+ /** Convenience shortcuts */
+ baseMinusTMin = base - tMin,
+ floor = Math.floor,
+ stringFromCharCode = String.fromCharCode,
+
+ /** Temporary variable */
+ key;
+
+ /*--------------------------------------------------------------------------*/
+
+ /**
+ * A generic error utility function.
+ * @private
+ * @param {String} type The error type.
+ * @returns {Error} Throws a `RangeError` with the applicable error message.
+ */
+ function error(type) {
+ throw new RangeError(errors[type]);
+ }
+
+ /**
+ * A generic `Array#map` utility function.
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} callback The function that gets called for every array
+ * item.
+ * @returns {Array} A new array of values returned by the callback function.
+ */
+ function map(array, fn) {
+ var length = array.length;
+ var result = [];
+ while (length--) {
+ result[length] = fn(array[length]);
+ }
+ return result;
+ }
+
+ /**
+ * A simple `Array#map`-like wrapper to work with domain name strings or email
+ * addresses.
+ * @private
+ * @param {String} domain The domain name or email address.
+ * @param {Function} callback The function that gets called for every
+ * character.
+ * @returns {Array} A new string of characters returned by the callback
+ * function.
+ */
+ function mapDomain(string, fn) {
+ var parts = string.split('@');
+ var result = '';
+ if (parts.length > 1) {
+ // In email addresses, only the domain name should be punycoded. Leave
+ // the local part (i.e. everything up to `@`) intact.
+ result = parts[0] + '@';
+ string = parts[1];
+ }
+ // Avoid `split(regex)` for IE8 compatibility. See #17.
+ string = string.replace(regexSeparators, '\x2E');
+ var labels = string.split('.');
+ var encoded = map(labels, fn).join('.');
+ return result + encoded;
+ }
+
+ /**
+ * Creates an array containing the numeric code points of each Unicode
+ * character in the string. While JavaScript uses UCS-2 internally,
+ * this function will convert a pair of surrogate halves (each of which
+ * UCS-2 exposes as separate characters) into a single code point,
+ * matching UTF-16.
+ * @see `punycode.ucs2.encode`
+ * @see <https://mathiasbynens.be/notes/javascript-encoding>
+ * @memberOf punycode.ucs2
+ * @name decode
+ * @param {String} string The Unicode input string (UCS-2).
+ * @returns {Array} The new array of code points.
+ */
+ function ucs2decode(string) {
+ var output = [],
+ counter = 0,
+ length = string.length,
+ value,
+ extra;
+ while (counter < length) {
+ value = string.charCodeAt(counter++);
+ if (value >= 0xD800 && value <= 0xDBFF && counter < length) {
+ // high surrogate, and there is a next character
+ extra = string.charCodeAt(counter++);
+ if ((extra & 0xFC00) == 0xDC00) { // low surrogate
+ output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);
+ } else {
+ // unmatched surrogate; only append this code unit, in case the next
+ // code unit is the high surrogate of a surrogate pair
+ output.push(value);
+ counter--;
+ }
+ } else {
+ output.push(value);
+ }
+ }
+ return output;
+ }
+
+ /**
+ * Creates a string based on an array of numeric code points.
+ * @see `punycode.ucs2.decode`
+ * @memberOf punycode.ucs2
+ * @name encode
+ * @param {Array} codePoints The array of numeric code points.
+ * @returns {String} The new Unicode string (UCS-2).
+ */
+ function ucs2encode(array) {
+ return map(array, function(value) {
+ var output = '';
+ if (value > 0xFFFF) {
+ value -= 0x10000;
+ output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
+ value = 0xDC00 | value & 0x3FF;
+ }
+ output += stringFromCharCode(value);
+ return output;
+ }).join('');
+ }
+
+ /**
+ * Converts a basic code point into a digit/integer.
+ * @see `digitToBasic()`
+ * @private
+ * @param {Number} codePoint The basic numeric code point value.
+ * @returns {Number} The numeric value of a basic code point (for use in
+ * representing integers) in the range `0` to `base - 1`, or `base` if
+ * the code point does not represent a value.
+ */
+ function basicToDigit(codePoint) {
+ if (codePoint - 48 < 10) {
+ return codePoint - 22;
+ }
+ if (codePoint - 65 < 26) {
+ return codePoint - 65;
+ }
+ if (codePoint - 97 < 26) {
+ return codePoint - 97;
+ }
+ return base;
+ }
+
+ /**
+ * Converts a digit/integer into a basic code point.
+ * @see `basicToDigit()`
+ * @private
+ * @param {Number} digit The numeric value of a basic code point.
+ * @returns {Number} The basic code point whose value (when used for
+ * representing integers) is `digit`, which needs to be in the range
+ * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is
+ * used; else, the lowercase form is used. The behavior is undefined
+ * if `flag` is non-zero and `digit` has no uppercase form.
+ */
+ function digitToBasic(digit, flag) {
+ // 0..25 map to ASCII a..z or A..Z
+ // 26..35 map to ASCII 0..9
+ return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);
+ }
+
+ /**
+ * Bias adaptation function as per section 3.4 of RFC 3492.
+ * https://tools.ietf.org/html/rfc3492#section-3.4
+ * @private
+ */
+ function adapt(delta, numPoints, firstTime) {
+ var k = 0;
+ delta = firstTime ? floor(delta / damp) : delta >> 1;
+ delta += floor(delta / numPoints);
+ for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) {
+ delta = floor(delta / baseMinusTMin);
+ }
+ return floor(k + (baseMinusTMin + 1) * delta / (delta + skew));
+ }
+
+ /**
+ * Converts a Punycode string of ASCII-only symbols to a string of Unicode
+ * symbols.
+ * @memberOf punycode
+ * @param {String} input The Punycode string of ASCII-only symbols.
+ * @returns {String} The resulting string of Unicode symbols.
+ */
+ function decode(input) {
+ // Don't use UCS-2
+ var output = [],
+ inputLength = input.length,
+ out,
+ i = 0,
+ n = initialN,
+ bias = initialBias,
+ basic,
+ j,
+ index,
+ oldi,
+ w,
+ k,
+ digit,
+ t,
+ /** Cached calculation results */
+ baseMinusT;
+
+ // Handle the basic code points: let `basic` be the number of input code
+ // points before the last delimiter, or `0` if there is none, then copy
+ // the first basic code points to the output.
+
+ basic = input.lastIndexOf(delimiter);
+ if (basic < 0) {
+ basic = 0;
+ }
+
+ for (j = 0; j < basic; ++j) {
+ // if it's not a basic code point
+ if (input.charCodeAt(j) >= 0x80) {
+ error('not-basic');
+ }
+ output.push(input.charCodeAt(j));
+ }
+
+ // Main decoding loop: start just after the last delimiter if any basic code
+ // points were copied; start at the beginning otherwise.
+
+ for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) {
+
+ // `index` is the index of the next character to be consumed.
+ // Decode a generalized variable-length integer into `delta`,
+ // which gets added to `i`. The overflow checking is easier
+ // if we increase `i` as we go, then subtract off its starting
+ // value at the end to obtain `delta`.
+ for (oldi = i, w = 1, k = base; /* no condition */; k += base) {
+
+ if (index >= inputLength) {
+ error('invalid-input');
+ }
+
+ digit = basicToDigit(input.charCodeAt(index++));
+
+ if (digit >= base || digit > floor((maxInt - i) / w)) {
+ error('overflow');
+ }
+
+ i += digit * w;
+ t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
+
+ if (digit < t) {
+ break;
+ }
+
+ baseMinusT = base - t;
+ if (w > floor(maxInt / baseMinusT)) {
+ error('overflow');
+ }
+
+ w *= baseMinusT;
+
+ }
+
+ out = output.length + 1;
+ bias = adapt(i - oldi, out, oldi == 0);
+
+ // `i` was supposed to wrap around from `out` to `0`,
+ // incrementing `n` each time, so we'll fix that now:
+ if (floor(i / out) > maxInt - n) {
+ error('overflow');
+ }
+
+ n += floor(i / out);
+ i %= out;
+
+ // Insert `n` at position `i` of the output
+ output.splice(i++, 0, n);
+
+ }
+
+ return ucs2encode(output);
+ }
+
+ /**
+ * Converts a string of Unicode symbols (e.g. a domain name label) to a
+ * Punycode string of ASCII-only symbols.
+ * @memberOf punycode
+ * @param {String} input The string of Unicode symbols.
+ * @returns {String} The resulting Punycode string of ASCII-only symbols.
+ */
+ function encode(input) {
+ var n,
+ delta,
+ handledCPCount,
+ basicLength,
+ bias,
+ j,
+ m,
+ q,
+ k,
+ t,
+ currentValue,
+ output = [],
+ /** `inputLength` will hold the number of code points in `input`. */
+ inputLength,
+ /** Cached calculation results */
+ handledCPCountPlusOne,
+ baseMinusT,
+ qMinusT;
+
+ // Convert the input in UCS-2 to Unicode
+ input = ucs2decode(input);
+
+ // Cache the length
+ inputLength = input.length;
+
+ // Initialize the state
+ n = initialN;
+ delta = 0;
+ bias = initialBias;
+
+ // Handle the basic code points
+ for (j = 0; j < inputLength; ++j) {
+ currentValue = input[j];
+ if (currentValue < 0x80) {
+ output.push(stringFromCharCode(currentValue));
+ }
+ }
+
+ handledCPCount = basicLength = output.length;
+
+ // `handledCPCount` is the number of code points that have been handled;
+ // `basicLength` is the number of basic code points.
+
+ // Finish the basic string - if it is not empty - with a delimiter
+ if (basicLength) {
+ output.push(delimiter);
+ }
+
+ // Main encoding loop:
+ while (handledCPCount < inputLength) {
+
+ // All non-basic code points < n have been handled already. Find the next
+ // larger one:
+ for (m = maxInt, j = 0; j < inputLength; ++j) {
+ currentValue = input[j];
+ if (currentValue >= n && currentValue < m) {
+ m = currentValue;
+ }
+ }
+
+ // Increase `delta` enough to advance the decoder's <n,i> state to <m,0>,
+ // but guard against overflow
+ handledCPCountPlusOne = handledCPCount + 1;
+ if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {
+ error('overflow');
+ }
+
+ delta += (m - n) * handledCPCountPlusOne;
+ n = m;
+
+ for (j = 0; j < inputLength; ++j) {
+ currentValue = input[j];
+
+ if (currentValue < n && ++delta > maxInt) {
+ error('overflow');
+ }
+
+ if (currentValue == n) {
+ // Represent delta as a generalized variable-length integer
+ for (q = delta, k = base; /* no condition */; k += base) {
+ t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
+ if (q < t) {
+ break;
+ }
+ qMinusT = q - t;
+ baseMinusT = base - t;
+ output.push(
+ stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0))
+ );
+ q = floor(qMinusT / baseMinusT);
+ }
+
+ output.push(stringFromCharCode(digitToBasic(q, 0)));
+ bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);
+ delta = 0;
+ ++handledCPCount;
+ }
+ }
+
+ ++delta;
+ ++n;
+
+ }
+ return output.join('');
+ }
+
+ /**
+ * Converts a Punycode string representing a domain name or an email address
+ * to Unicode. Only the Punycoded parts of the input will be converted, i.e.
+ * it doesn't matter if you call it on a string that has already been
+ * converted to Unicode.
+ * @memberOf punycode
+ * @param {String} input The Punycoded domain name or email address to
+ * convert to Unicode.
+ * @returns {String} The Unicode representation of the given Punycode
+ * string.
+ */
+ function toUnicode(input) {
+ return mapDomain(input, function(string) {
+ return regexPunycode.test(string)
+ ? decode(string.slice(4).toLowerCase())
+ : string;
+ });
+ }
+
+ /**
+ * Converts a Unicode string representing a domain name or an email address to
+ * Punycode. Only the non-ASCII parts of the domain name will be converted,
+ * i.e. it doesn't matter if you call it with a domain that's already in
+ * ASCII.
+ * @memberOf punycode
+ * @param {String} input The domain name or email address to convert, as a
+ * Unicode string.
+ * @returns {String} The Punycode representation of the given domain name or
+ * email address.
+ */
+ function toASCII(input) {
+ return mapDomain(input, function(string) {
+ return regexNonASCII.test(string)
+ ? 'xn--' + encode(string)
+ : string;
+ });
+ }
+
+ /*--------------------------------------------------------------------------*/
+
+ /** Define the public API */
+ punycode = {
+ /**
+ * A string representing the current Punycode.js version number.
+ * @memberOf punycode
+ * @type String
+ */
+ 'version': '1.4.1',
+ /**
+ * An object of methods to convert from JavaScript's internal character
+ * representation (UCS-2) to Unicode code points, and back.
+ * @see <https://mathiasbynens.be/notes/javascript-encoding>
+ * @memberOf punycode
+ * @type Object
+ */
+ 'ucs2': {
+ 'decode': ucs2decode,
+ 'encode': ucs2encode
+ },
+ 'decode': decode,
+ 'encode': encode,
+ 'toASCII': toASCII,
+ 'toUnicode': toUnicode
+ };
+
+ /** Expose `punycode` */
+ // Some AMD build optimizers, like r.js, check for specific condition patterns
+ // like the following:
+ if (
+ true
+ ) {
+ !(__WEBPACK_AMD_DEFINE_RESULT__ = function() {
+ return punycode;
+ }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
+ } else if (freeExports && freeModule) {
+ if (module.exports == freeExports) {
+ // in Node.js, io.js, or RingoJS v0.8.0+
+ freeModule.exports = punycode;
+ } else {
+ // in Narwhal or RingoJS v0.7.0-
+ for (key in punycode) {
+ punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]);
+ }
+ }
+ } else {
+ // in Rhino or a web browser
+ root.punycode = punycode;
+ }
+
+ }(this));
+
+ /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(4)(module), (function() { return this; }())))
+
+/***/ }),
+/* 16 */
+/***/ (function(module, exports) {
+
+ module.exports = ["ac","com.ac","edu.ac","gov.ac","net.ac","mil.ac","org.ac","ad","nom.ad","ae","co.ae","net.ae","org.ae","sch.ae","ac.ae","gov.ae","mil.ae","aero","accident-investigation.aero","accident-prevention.aero","aerobatic.aero","aeroclub.aero","aerodrome.aero","agents.aero","aircraft.aero","airline.aero","airport.aero","air-surveillance.aero","airtraffic.aero","air-traffic-control.aero","ambulance.aero","amusement.aero","association.aero","author.aero","ballooning.aero","broker.aero","caa.aero","cargo.aero","catering.aero","certification.aero","championship.aero","charter.aero","civilaviation.aero","club.aero","conference.aero","consultant.aero","consulting.aero","control.aero","council.aero","crew.aero","design.aero","dgca.aero","educator.aero","emergency.aero","engine.aero","engineer.aero","entertainment.aero","equipment.aero","exchange.aero","express.aero","federation.aero","flight.aero","freight.aero","fuel.aero","gliding.aero","government.aero","groundhandling.aero","group.aero","hanggliding.aero","homebuilt.aero","insurance.aero","journal.aero","journalist.aero","leasing.aero","logistics.aero","magazine.aero","maintenance.aero","media.aero","microlight.aero","modelling.aero","navigation.aero","parachuting.aero","paragliding.aero","passenger-association.aero","pilot.aero","press.aero","production.aero","recreation.aero","repbody.aero","res.aero","research.aero","rotorcraft.aero","safety.aero","scientist.aero","services.aero","show.aero","skydiving.aero","software.aero","student.aero","trader.aero","trading.aero","trainer.aero","union.aero","workinggroup.aero","works.aero","af","gov.af","com.af","org.af","net.af","edu.af","ag","com.ag","org.ag","net.ag","co.ag","nom.ag","ai","off.ai","com.ai","net.ai","org.ai","al","com.al","edu.al","gov.al","mil.al","net.al","org.al","am","ao","ed.ao","gv.ao","og.ao","co.ao","pb.ao","it.ao","aq","ar","com.ar","edu.ar","gob.ar","gov.ar","int.ar","mil.ar","musica.ar","net.ar","org.ar","tur.ar","arpa","e164.arpa","in-addr.arpa","ip6.arpa","iris.arpa","uri.arpa","urn.arpa","as","gov.as","asia","at","ac.at","co.at","gv.at","or.at","au","com.au","net.au","org.au","edu.au","gov.au","asn.au","id.au","info.au","conf.au","oz.au","act.au","nsw.au","nt.au","qld.au","sa.au","tas.au","vic.au","wa.au","act.edu.au","nsw.edu.au","nt.edu.au","qld.edu.au","sa.edu.au","tas.edu.au","vic.edu.au","wa.edu.au","qld.gov.au","sa.gov.au","tas.gov.au","vic.gov.au","wa.gov.au","aw","com.aw","ax","az","com.az","net.az","int.az","gov.az","org.az","edu.az","info.az","pp.az","mil.az","name.az","pro.az","biz.az","ba","com.ba","edu.ba","gov.ba","mil.ba","net.ba","org.ba","bb","biz.bb","co.bb","com.bb","edu.bb","gov.bb","info.bb","net.bb","org.bb","store.bb","tv.bb","*.bd","be","ac.be","bf","gov.bf","bg","a.bg","b.bg","c.bg","d.bg","e.bg","f.bg","g.bg","h.bg","i.bg","j.bg","k.bg","l.bg","m.bg","n.bg","o.bg","p.bg","q.bg","r.bg","s.bg","t.bg","u.bg","v.bg","w.bg","x.bg","y.bg","z.bg","0.bg","1.bg","2.bg","3.bg","4.bg","5.bg","6.bg","7.bg","8.bg","9.bg","bh","com.bh","edu.bh","net.bh","org.bh","gov.bh","bi","co.bi","com.bi","edu.bi","or.bi","org.bi","biz","bj","asso.bj","barreau.bj","gouv.bj","bm","com.bm","edu.bm","gov.bm","net.bm","org.bm","*.bn","bo","com.bo","edu.bo","gob.bo","int.bo","org.bo","net.bo","mil.bo","tv.bo","web.bo","academia.bo","agro.bo","arte.bo","blog.bo","bolivia.bo","ciencia.bo","cooperativa.bo","democracia.bo","deporte.bo","ecologia.bo","economia.bo","empresa.bo","indigena.bo","industria.bo","info.bo","medicina.bo","movimiento.bo","musica.bo","natural.bo","nombre.bo","noticias.bo","patria.bo","politica.bo","profesional.bo","plurinacional.bo","pueblo.bo","revista.bo","salud.bo","tecnologia.bo","tksat.bo","transporte.bo","wiki.bo","br","9guacu.br","abc.br","adm.br","adv.br","agr.br","aju.br","am.br","anani.br","aparecida.br","arq.br","art.br","ato.br","b.br","barueri.br","belem.br","bhz.br","bio.br","blog.br","bmd.br","boavista.br","bsb.br","campinagrande.br","campinas.br","caxias.br","cim.br","cng.br","cnt.br","com.br","contagem.br","coop.br","cri.br","cuiaba.br","curitiba.br","def.br","ecn.br","eco.br","edu.br","emp.br","eng.br","esp.br","etc.br","eti.br","far.br","feira.br","flog.br","floripa.br","fm.br","fnd.br","fortal.br","fot.br","foz.br","fst.br","g12.br","ggf.br","goiania.br","gov.br","ac.gov.br","al.gov.br","am.gov.br","ap.gov.br","ba.gov.br","ce.gov.br","df.gov.br","es.gov.br","go.gov.br","ma.gov.br","mg.gov.br","ms.gov.br","mt.gov.br","pa.gov.br","pb.gov.br","pe.gov.br","pi.gov.br","pr.gov.br","rj.gov.br","rn.gov.br","ro.gov.br","rr.gov.br","rs.gov.br","sc.gov.br","se.gov.br","sp.gov.br","to.gov.br","gru.br","imb.br","ind.br","inf.br","jab.br","jampa.br","jdf.br","joinville.br","jor.br","jus.br","leg.br","lel.br","londrina.br","macapa.br","maceio.br","manaus.br","maringa.br","mat.br","med.br","mil.br","morena.br","mp.br","mus.br","natal.br","net.br","niteroi.br","*.nom.br","not.br","ntr.br","odo.br","org.br","osasco.br","palmas.br","poa.br","ppg.br","pro.br","psc.br","psi.br","pvh.br","qsl.br","radio.br","rec.br","recife.br","ribeirao.br","rio.br","riobranco.br","riopreto.br","salvador.br","sampa.br","santamaria.br","santoandre.br","saobernardo.br","saogonca.br","sjc.br","slg.br","slz.br","sorocaba.br","srv.br","taxi.br","teo.br","the.br","tmp.br","trd.br","tur.br","tv.br","udi.br","vet.br","vix.br","vlog.br","wiki.br","zlg.br","bs","com.bs","net.bs","org.bs","edu.bs","gov.bs","bt","com.bt","edu.bt","gov.bt","net.bt","org.bt","bv","bw","co.bw","org.bw","by","gov.by","mil.by","com.by","of.by","bz","com.bz","net.bz","org.bz","edu.bz","gov.bz","ca","ab.ca","bc.ca","mb.ca","nb.ca","nf.ca","nl.ca","ns.ca","nt.ca","nu.ca","on.ca","pe.ca","qc.ca","sk.ca","yk.ca","gc.ca","cat","cc","cd","gov.cd","cf","cg","ch","ci","org.ci","or.ci","com.ci","co.ci","edu.ci","ed.ci","ac.ci","net.ci","go.ci","asso.ci","aéroport.ci","int.ci","presse.ci","md.ci","gouv.ci","*.ck","!www.ck","cl","gov.cl","gob.cl","co.cl","mil.cl","cm","co.cm","com.cm","gov.cm","net.cm","cn","ac.cn","com.cn","edu.cn","gov.cn","net.cn","org.cn","mil.cn","公司.cn","网络.cn","網絡.cn","ah.cn","bj.cn","cq.cn","fj.cn","gd.cn","gs.cn","gz.cn","gx.cn","ha.cn","hb.cn","he.cn","hi.cn","hl.cn","hn.cn","jl.cn","js.cn","jx.cn","ln.cn","nm.cn","nx.cn","qh.cn","sc.cn","sd.cn","sh.cn","sn.cn","sx.cn","tj.cn","xj.cn","xz.cn","yn.cn","zj.cn","hk.cn","mo.cn","tw.cn","co","arts.co","com.co","edu.co","firm.co","gov.co","info.co","int.co","mil.co","net.co","nom.co","org.co","rec.co","web.co","com","coop","cr","ac.cr","co.cr","ed.cr","fi.cr","go.cr","or.cr","sa.cr","cu","com.cu","edu.cu","org.cu","net.cu","gov.cu","inf.cu","cv","cw","com.cw","edu.cw","net.cw","org.cw","cx","gov.cx","cy","ac.cy","biz.cy","com.cy","ekloges.cy","gov.cy","ltd.cy","name.cy","net.cy","org.cy","parliament.cy","press.cy","pro.cy","tm.cy","cz","de","dj","dk","dm","com.dm","net.dm","org.dm","edu.dm","gov.dm","do","art.do","com.do","edu.do","gob.do","gov.do","mil.do","net.do","org.do","sld.do","web.do","dz","com.dz","org.dz","net.dz","gov.dz","edu.dz","asso.dz","pol.dz","art.dz","ec","com.ec","info.ec","net.ec","fin.ec","k12.ec","med.ec","pro.ec","org.ec","edu.ec","gov.ec","gob.ec","mil.ec","edu","ee","edu.ee","gov.ee","riik.ee","lib.ee","med.ee","com.ee","pri.ee","aip.ee","org.ee","fie.ee","eg","com.eg","edu.eg","eun.eg","gov.eg","mil.eg","name.eg","net.eg","org.eg","sci.eg","*.er","es","com.es","nom.es","org.es","gob.es","edu.es","et","com.et","gov.et","org.et","edu.et","biz.et","name.et","info.et","net.et","eu","fi","aland.fi","*.fj","*.fk","fm","fo","fr","com.fr","asso.fr","nom.fr","prd.fr","presse.fr","tm.fr","aeroport.fr","assedic.fr","avocat.fr","avoues.fr","cci.fr","chambagri.fr","chirurgiens-dentistes.fr","experts-comptables.fr","geometre-expert.fr","gouv.fr","greta.fr","huissier-justice.fr","medecin.fr","notaires.fr","pharmacien.fr","port.fr","veterinaire.fr","ga","gb","gd","ge","com.ge","edu.ge","gov.ge","org.ge","mil.ge","net.ge","pvt.ge","gf","gg","co.gg","net.gg","org.gg","gh","com.gh","edu.gh","gov.gh","org.gh","mil.gh","gi","com.gi","ltd.gi","gov.gi","mod.gi","edu.gi","org.gi","gl","co.gl","com.gl","edu.gl","net.gl","org.gl","gm","gn","ac.gn","com.gn","edu.gn","gov.gn","org.gn","net.gn","gov","gp","com.gp","net.gp","mobi.gp","edu.gp","org.gp","asso.gp","gq","gr","com.gr","edu.gr","net.gr","org.gr","gov.gr","gs","gt","com.gt","edu.gt","gob.gt","ind.gt","mil.gt","net.gt","org.gt","gu","com.gu","edu.gu","gov.gu","guam.gu","info.gu","net.gu","org.gu","web.gu","gw","gy","co.gy","com.gy","edu.gy","gov.gy","net.gy","org.gy","hk","com.hk","edu.hk","gov.hk","idv.hk","net.hk","org.hk","公司.hk","教育.hk","敎育.hk","政府.hk","個人.hk","个人.hk","箇人.hk","網络.hk","网络.hk","组織.hk","網絡.hk","网絡.hk","组织.hk","組織.hk","組织.hk","hm","hn","com.hn","edu.hn","org.hn","net.hn","mil.hn","gob.hn","hr","iz.hr","from.hr","name.hr","com.hr","ht","com.ht","shop.ht","firm.ht","info.ht","adult.ht","net.ht","pro.ht","org.ht","med.ht","art.ht","coop.ht","pol.ht","asso.ht","edu.ht","rel.ht","gouv.ht","perso.ht","hu","co.hu","info.hu","org.hu","priv.hu","sport.hu","tm.hu","2000.hu","agrar.hu","bolt.hu","casino.hu","city.hu","erotica.hu","erotika.hu","film.hu","forum.hu","games.hu","hotel.hu","ingatlan.hu","jogasz.hu","konyvelo.hu","lakas.hu","media.hu","news.hu","reklam.hu","sex.hu","shop.hu","suli.hu","szex.hu","tozsde.hu","utazas.hu","video.hu","id","ac.id","biz.id","co.id","desa.id","go.id","mil.id","my.id","net.id","or.id","sch.id","web.id","ie","gov.ie","il","ac.il","co.il","gov.il","idf.il","k12.il","muni.il","net.il","org.il","im","ac.im","co.im","com.im","ltd.co.im","net.im","org.im","plc.co.im","tt.im","tv.im","in","co.in","firm.in","net.in","org.in","gen.in","ind.in","nic.in","ac.in","edu.in","res.in","gov.in","mil.in","info","int","eu.int","io","com.io","iq","gov.iq","edu.iq","mil.iq","com.iq","org.iq","net.iq","ir","ac.ir","co.ir","gov.ir","id.ir","net.ir","org.ir","sch.ir","ایران.ir","ايران.ir","is","net.is","com.is","edu.is","gov.is","org.is","int.is","it","gov.it","edu.it","abr.it","abruzzo.it","aosta-valley.it","aostavalley.it","bas.it","basilicata.it","cal.it","calabria.it","cam.it","campania.it","emilia-romagna.it","emiliaromagna.it","emr.it","friuli-v-giulia.it","friuli-ve-giulia.it","friuli-vegiulia.it","friuli-venezia-giulia.it","friuli-veneziagiulia.it","friuli-vgiulia.it","friuliv-giulia.it","friulive-giulia.it","friulivegiulia.it","friulivenezia-giulia.it","friuliveneziagiulia.it","friulivgiulia.it","fvg.it","laz.it","lazio.it","lig.it","liguria.it","lom.it","lombardia.it","lombardy.it","lucania.it","mar.it","marche.it","mol.it","molise.it","piedmont.it","piemonte.it","pmn.it","pug.it","puglia.it","sar.it","sardegna.it","sardinia.it","sic.it","sicilia.it","sicily.it","taa.it","tos.it","toscana.it","trentin-sud-tirol.it","trentin-süd-tirol.it","trentin-sudtirol.it","trentin-südtirol.it","trentin-sued-tirol.it","trentin-suedtirol.it","trentino-a-adige.it","trentino-aadige.it","trentino-alto-adige.it","trentino-altoadige.it","trentino-s-tirol.it","trentino-stirol.it","trentino-sud-tirol.it","trentino-süd-tirol.it","trentino-sudtirol.it","trentino-südtirol.it","trentino-sued-tirol.it","trentino-suedtirol.it","trentino.it","trentinoa-adige.it","trentinoaadige.it","trentinoalto-adige.it","trentinoaltoadige.it","trentinos-tirol.it","trentinostirol.it","trentinosud-tirol.it","trentinosüd-tirol.it","trentinosudtirol.it","trentinosüdtirol.it","trentinosued-tirol.it","trentinosuedtirol.it","trentinsud-tirol.it","trentinsüd-tirol.it","trentinsudtirol.it","trentinsüdtirol.it","trentinsued-tirol.it","trentinsuedtirol.it","tuscany.it","umb.it","umbria.it","val-d-aosta.it","val-daosta.it","vald-aosta.it","valdaosta.it","valle-aosta.it","valle-d-aosta.it","valle-daosta.it","valleaosta.it","valled-aosta.it","valledaosta.it","vallee-aoste.it","vallée-aoste.it","vallee-d-aoste.it","vallée-d-aoste.it","valleeaoste.it","valléeaoste.it","valleedaoste.it","valléedaoste.it","vao.it","vda.it","ven.it","veneto.it","ag.it","agrigento.it","al.it","alessandria.it","alto-adige.it","altoadige.it","an.it","ancona.it","andria-barletta-trani.it","andria-trani-barletta.it","andriabarlettatrani.it","andriatranibarletta.it","ao.it","aosta.it","aoste.it","ap.it","aq.it","aquila.it","ar.it","arezzo.it","ascoli-piceno.it","ascolipiceno.it","asti.it","at.it","av.it","avellino.it","ba.it","balsan-sudtirol.it","balsan-südtirol.it","balsan-suedtirol.it","balsan.it","bari.it","barletta-trani-andria.it","barlettatraniandria.it","belluno.it","benevento.it","bergamo.it","bg.it","bi.it","biella.it","bl.it","bn.it","bo.it","bologna.it","bolzano-altoadige.it","bolzano.it","bozen-sudtirol.it","bozen-südtirol.it","bozen-suedtirol.it","bozen.it","br.it","brescia.it","brindisi.it","bs.it","bt.it","bulsan-sudtirol.it","bulsan-südtirol.it","bulsan-suedtirol.it","bulsan.it","bz.it","ca.it","cagliari.it","caltanissetta.it","campidano-medio.it","campidanomedio.it","campobasso.it","carbonia-iglesias.it","carboniaiglesias.it","carrara-massa.it","carraramassa.it","caserta.it","catania.it","catanzaro.it","cb.it","ce.it","cesena-forli.it","cesena-forlì.it","cesenaforli.it","cesenaforlì.it","ch.it","chieti.it","ci.it","cl.it","cn.it","co.it","como.it","cosenza.it","cr.it","cremona.it","crotone.it","cs.it","ct.it","cuneo.it","cz.it","dell-ogliastra.it","dellogliastra.it","en.it","enna.it","fc.it","fe.it","fermo.it","ferrara.it","fg.it","fi.it","firenze.it","florence.it","fm.it","foggia.it","forli-cesena.it","forlì-cesena.it","forlicesena.it","forlìcesena.it","fr.it","frosinone.it","ge.it","genoa.it","genova.it","go.it","gorizia.it","gr.it","grosseto.it","iglesias-carbonia.it","iglesiascarbonia.it","im.it","imperia.it","is.it","isernia.it","kr.it","la-spezia.it","laquila.it","laspezia.it","latina.it","lc.it","le.it","lecce.it","lecco.it","li.it","livorno.it","lo.it","lodi.it","lt.it","lu.it","lucca.it","macerata.it","mantova.it","massa-carrara.it","massacarrara.it","matera.it","mb.it","mc.it","me.it","medio-campidano.it","mediocampidano.it","messina.it","mi.it","milan.it","milano.it","mn.it","mo.it","modena.it","monza-brianza.it","monza-e-della-brianza.it","monza.it","monzabrianza.it","monzaebrianza.it","monzaedellabrianza.it","ms.it","mt.it","na.it","naples.it","napoli.it","no.it","novara.it","nu.it","nuoro.it","og.it","ogliastra.it","olbia-tempio.it","olbiatempio.it","or.it","oristano.it","ot.it","pa.it","padova.it","padua.it","palermo.it","parma.it","pavia.it","pc.it","pd.it","pe.it","perugia.it","pesaro-urbino.it","pesarourbino.it","pescara.it","pg.it","pi.it","piacenza.it","pisa.it","pistoia.it","pn.it","po.it","pordenone.it","potenza.it","pr.it","prato.it","pt.it","pu.it","pv.it","pz.it","ra.it","ragusa.it","ravenna.it","rc.it","re.it","reggio-calabria.it","reggio-emilia.it","reggiocalabria.it","reggioemilia.it","rg.it","ri.it","rieti.it","rimini.it","rm.it","rn.it","ro.it","roma.it","rome.it","rovigo.it","sa.it","salerno.it","sassari.it","savona.it","si.it","siena.it","siracusa.it","so.it","sondrio.it","sp.it","sr.it","ss.it","suedtirol.it","südtirol.it","sv.it","ta.it","taranto.it","te.it","tempio-olbia.it","tempioolbia.it","teramo.it","terni.it","tn.it","to.it","torino.it","tp.it","tr.it","trani-andria-barletta.it","trani-barletta-andria.it","traniandriabarletta.it","tranibarlettaandria.it","trapani.it","trento.it","treviso.it","trieste.it","ts.it","turin.it","tv.it","ud.it","udine.it","urbino-pesaro.it","urbinopesaro.it","va.it","varese.it","vb.it","vc.it","ve.it","venezia.it","venice.it","verbania.it","vercelli.it","verona.it","vi.it","vibo-valentia.it","vibovalentia.it","vicenza.it","viterbo.it","vr.it","vs.it","vt.it","vv.it","je","co.je","net.je","org.je","*.jm","jo","com.jo","org.jo","net.jo","edu.jo","sch.jo","gov.jo","mil.jo","name.jo","jobs","jp","ac.jp","ad.jp","co.jp","ed.jp","go.jp","gr.jp","lg.jp","ne.jp","or.jp","aichi.jp","akita.jp","aomori.jp","chiba.jp","ehime.jp","fukui.jp","fukuoka.jp","fukushima.jp","gifu.jp","gunma.jp","hiroshima.jp","hokkaido.jp","hyogo.jp","ibaraki.jp","ishikawa.jp","iwate.jp","kagawa.jp","kagoshima.jp","kanagawa.jp","kochi.jp","kumamoto.jp","kyoto.jp","mie.jp","miyagi.jp","miyazaki.jp","nagano.jp","nagasaki.jp","nara.jp","niigata.jp","oita.jp","okayama.jp","okinawa.jp","osaka.jp","saga.jp","saitama.jp","shiga.jp","shimane.jp","shizuoka.jp","tochigi.jp","tokushima.jp","tokyo.jp","tottori.jp","toyama.jp","wakayama.jp","yamagata.jp","yamaguchi.jp","yamanashi.jp","栃木.jp","愛知.jp","愛媛.jp","兵庫.jp","熊本.jp","茨城.jp","北海道.jp","千葉.jp","和歌山.jp","長崎.jp","長野.jp","新潟.jp","青森.jp","静岡.jp","東京.jp","石川.jp","埼玉.jp","三重.jp","京都.jp","佐賀.jp","大分.jp","大阪.jp","奈良.jp","宮城.jp","宮崎.jp","富山.jp","山口.jp","山形.jp","山梨.jp","岩手.jp","岐阜.jp","岡山.jp","島根.jp","広島.jp","徳島.jp","沖縄.jp","滋賀.jp","神奈川.jp","福井.jp","福岡.jp","福島.jp","秋田.jp","群馬.jp","香川.jp","高知.jp","鳥取.jp","鹿児島.jp","*.kawasaki.jp","*.kitakyushu.jp","*.kobe.jp","*.nagoya.jp","*.sapporo.jp","*.sendai.jp","*.yokohama.jp","!city.kawasaki.jp","!city.kitakyushu.jp","!city.kobe.jp","!city.nagoya.jp","!city.sapporo.jp","!city.sendai.jp","!city.yokohama.jp","aisai.aichi.jp","ama.aichi.jp","anjo.aichi.jp","asuke.aichi.jp","chiryu.aichi.jp","chita.aichi.jp","fuso.aichi.jp","gamagori.aichi.jp","handa.aichi.jp","hazu.aichi.jp","hekinan.aichi.jp","higashiura.aichi.jp","ichinomiya.aichi.jp","inazawa.aichi.jp","inuyama.aichi.jp","isshiki.aichi.jp","iwakura.aichi.jp","kanie.aichi.jp","kariya.aichi.jp","kasugai.aichi.jp","kira.aichi.jp","kiyosu.aichi.jp","komaki.aichi.jp","konan.aichi.jp","kota.aichi.jp","mihama.aichi.jp","miyoshi.aichi.jp","nishio.aichi.jp","nisshin.aichi.jp","obu.aichi.jp","oguchi.aichi.jp","oharu.aichi.jp","okazaki.aichi.jp","owariasahi.aichi.jp","seto.aichi.jp","shikatsu.aichi.jp","shinshiro.aichi.jp","shitara.aichi.jp","tahara.aichi.jp","takahama.aichi.jp","tobishima.aichi.jp","toei.aichi.jp","togo.aichi.jp","tokai.aichi.jp","tokoname.aichi.jp","toyoake.aichi.jp","toyohashi.aichi.jp","toyokawa.aichi.jp","toyone.aichi.jp","toyota.aichi.jp","tsushima.aichi.jp","yatomi.aichi.jp","akita.akita.jp","daisen.akita.jp","fujisato.akita.jp","gojome.akita.jp","hachirogata.akita.jp","happou.akita.jp","higashinaruse.akita.jp","honjo.akita.jp","honjyo.akita.jp","ikawa.akita.jp","kamikoani.akita.jp","kamioka.akita.jp","katagami.akita.jp","kazuno.akita.jp","kitaakita.akita.jp","kosaka.akita.jp","kyowa.akita.jp","misato.akita.jp","mitane.akita.jp","moriyoshi.akita.jp","nikaho.akita.jp","noshiro.akita.jp","odate.akita.jp","oga.akita.jp","ogata.akita.jp","semboku.akita.jp","yokote.akita.jp","yurihonjo.akita.jp","aomori.aomori.jp","gonohe.aomori.jp","hachinohe.aomori.jp","hashikami.aomori.jp","hiranai.aomori.jp","hirosaki.aomori.jp","itayanagi.aomori.jp","kuroishi.aomori.jp","misawa.aomori.jp","mutsu.aomori.jp","nakadomari.aomori.jp","noheji.aomori.jp","oirase.aomori.jp","owani.aomori.jp","rokunohe.aomori.jp","sannohe.aomori.jp","shichinohe.aomori.jp","shingo.aomori.jp","takko.aomori.jp","towada.aomori.jp","tsugaru.aomori.jp","tsuruta.aomori.jp","abiko.chiba.jp","asahi.chiba.jp","chonan.chiba.jp","chosei.chiba.jp","choshi.chiba.jp","chuo.chiba.jp","funabashi.chiba.jp","futtsu.chiba.jp","hanamigawa.chiba.jp","ichihara.chiba.jp","ichikawa.chiba.jp","ichinomiya.chiba.jp","inzai.chiba.jp","isumi.chiba.jp","kamagaya.chiba.jp","kamogawa.chiba.jp","kashiwa.chiba.jp","katori.chiba.jp","katsuura.chiba.jp","kimitsu.chiba.jp","kisarazu.chiba.jp","kozaki.chiba.jp","kujukuri.chiba.jp","kyonan.chiba.jp","matsudo.chiba.jp","midori.chiba.jp","mihama.chiba.jp","minamiboso.chiba.jp","mobara.chiba.jp","mutsuzawa.chiba.jp","nagara.chiba.jp","nagareyama.chiba.jp","narashino.chiba.jp","narita.chiba.jp","noda.chiba.jp","oamishirasato.chiba.jp","omigawa.chiba.jp","onjuku.chiba.jp","otaki.chiba.jp","sakae.chiba.jp","sakura.chiba.jp","shimofusa.chiba.jp","shirako.chiba.jp","shiroi.chiba.jp","shisui.chiba.jp","sodegaura.chiba.jp","sosa.chiba.jp","tako.chiba.jp","tateyama.chiba.jp","togane.chiba.jp","tohnosho.chiba.jp","tomisato.chiba.jp","urayasu.chiba.jp","yachimata.chiba.jp","yachiyo.chiba.jp","yokaichiba.chiba.jp","yokoshibahikari.chiba.jp","yotsukaido.chiba.jp","ainan.ehime.jp","honai.ehime.jp","ikata.ehime.jp","imabari.ehime.jp","iyo.ehime.jp","kamijima.ehime.jp","kihoku.ehime.jp","kumakogen.ehime.jp","masaki.ehime.jp","matsuno.ehime.jp","matsuyama.ehime.jp","namikata.ehime.jp","niihama.ehime.jp","ozu.ehime.jp","saijo.ehime.jp","seiyo.ehime.jp","shikokuchuo.ehime.jp","tobe.ehime.jp","toon.ehime.jp","uchiko.ehime.jp","uwajima.ehime.jp","yawatahama.ehime.jp","echizen.fukui.jp","eiheiji.fukui.jp","fukui.fukui.jp","ikeda.fukui.jp","katsuyama.fukui.jp","mihama.fukui.jp","minamiechizen.fukui.jp","obama.fukui.jp","ohi.fukui.jp","ono.fukui.jp","sabae.fukui.jp","sakai.fukui.jp","takahama.fukui.jp","tsuruga.fukui.jp","wakasa.fukui.jp","ashiya.fukuoka.jp","buzen.fukuoka.jp","chikugo.fukuoka.jp","chikuho.fukuoka.jp","chikujo.fukuoka.jp","chikushino.fukuoka.jp","chikuzen.fukuoka.jp","chuo.fukuoka.jp","dazaifu.fukuoka.jp","fukuchi.fukuoka.jp","hakata.fukuoka.jp","higashi.fukuoka.jp","hirokawa.fukuoka.jp","hisayama.fukuoka.jp","iizuka.fukuoka.jp","inatsuki.fukuoka.jp","kaho.fukuoka.jp","kasuga.fukuoka.jp","kasuya.fukuoka.jp","kawara.fukuoka.jp","keisen.fukuoka.jp","koga.fukuoka.jp","kurate.fukuoka.jp","kurogi.fukuoka.jp","kurume.fukuoka.jp","minami.fukuoka.jp","miyako.fukuoka.jp","miyama.fukuoka.jp","miyawaka.fukuoka.jp","mizumaki.fukuoka.jp","munakata.fukuoka.jp","nakagawa.fukuoka.jp","nakama.fukuoka.jp","nishi.fukuoka.jp","nogata.fukuoka.jp","ogori.fukuoka.jp","okagaki.fukuoka.jp","okawa.fukuoka.jp","oki.fukuoka.jp","omuta.fukuoka.jp","onga.fukuoka.jp","onojo.fukuoka.jp","oto.fukuoka.jp","saigawa.fukuoka.jp","sasaguri.fukuoka.jp","shingu.fukuoka.jp","shinyoshitomi.fukuoka.jp","shonai.fukuoka.jp","soeda.fukuoka.jp","sue.fukuoka.jp","tachiarai.fukuoka.jp","tagawa.fukuoka.jp","takata.fukuoka.jp","toho.fukuoka.jp","toyotsu.fukuoka.jp","tsuiki.fukuoka.jp","ukiha.fukuoka.jp","umi.fukuoka.jp","usui.fukuoka.jp","yamada.fukuoka.jp","yame.fukuoka.jp","yanagawa.fukuoka.jp","yukuhashi.fukuoka.jp","aizubange.fukushima.jp","aizumisato.fukushima.jp","aizuwakamatsu.fukushima.jp","asakawa.fukushima.jp","bandai.fukushima.jp","date.fukushima.jp","fukushima.fukushima.jp","furudono.fukushima.jp","futaba.fukushima.jp","hanawa.fukushima.jp","higashi.fukushima.jp","hirata.fukushima.jp","hirono.fukushima.jp","iitate.fukushima.jp","inawashiro.fukushima.jp","ishikawa.fukushima.jp","iwaki.fukushima.jp","izumizaki.fukushima.jp","kagamiishi.fukushima.jp","kaneyama.fukushima.jp","kawamata.fukushima.jp","kitakata.fukushima.jp","kitashiobara.fukushima.jp","koori.fukushima.jp","koriyama.fukushima.jp","kunimi.fukushima.jp","miharu.fukushima.jp","mishima.fukushima.jp","namie.fukushima.jp","nango.fukushima.jp","nishiaizu.fukushima.jp","nishigo.fukushima.jp","okuma.fukushima.jp","omotego.fukushima.jp","ono.fukushima.jp","otama.fukushima.jp","samegawa.fukushima.jp","shimogo.fukushima.jp","shirakawa.fukushima.jp","showa.fukushima.jp","soma.fukushima.jp","sukagawa.fukushima.jp","taishin.fukushima.jp","tamakawa.fukushima.jp","tanagura.fukushima.jp","tenei.fukushima.jp","yabuki.fukushima.jp","yamato.fukushima.jp","yamatsuri.fukushima.jp","yanaizu.fukushima.jp","yugawa.fukushima.jp","anpachi.gifu.jp","ena.gifu.jp","gifu.gifu.jp","ginan.gifu.jp","godo.gifu.jp","gujo.gifu.jp","hashima.gifu.jp","hichiso.gifu.jp","hida.gifu.jp","higashishirakawa.gifu.jp","ibigawa.gifu.jp","ikeda.gifu.jp","kakamigahara.gifu.jp","kani.gifu.jp","kasahara.gifu.jp","kasamatsu.gifu.jp","kawaue.gifu.jp","kitagata.gifu.jp","mino.gifu.jp","minokamo.gifu.jp","mitake.gifu.jp","mizunami.gifu.jp","motosu.gifu.jp","nakatsugawa.gifu.jp","ogaki.gifu.jp","sakahogi.gifu.jp","seki.gifu.jp","sekigahara.gifu.jp","shirakawa.gifu.jp","tajimi.gifu.jp","takayama.gifu.jp","tarui.gifu.jp","toki.gifu.jp","tomika.gifu.jp","wanouchi.gifu.jp","yamagata.gifu.jp","yaotsu.gifu.jp","yoro.gifu.jp","annaka.gunma.jp","chiyoda.gunma.jp","fujioka.gunma.jp","higashiagatsuma.gunma.jp","isesaki.gunma.jp","itakura.gunma.jp","kanna.gunma.jp","kanra.gunma.jp","katashina.gunma.jp","kawaba.gunma.jp","kiryu.gunma.jp","kusatsu.gunma.jp","maebashi.gunma.jp","meiwa.gunma.jp","midori.gunma.jp","minakami.gunma.jp","naganohara.gunma.jp","nakanojo.gunma.jp","nanmoku.gunma.jp","numata.gunma.jp","oizumi.gunma.jp","ora.gunma.jp","ota.gunma.jp","shibukawa.gunma.jp","shimonita.gunma.jp","shinto.gunma.jp","showa.gunma.jp","takasaki.gunma.jp","takayama.gunma.jp","tamamura.gunma.jp","tatebayashi.gunma.jp","tomioka.gunma.jp","tsukiyono.gunma.jp","tsumagoi.gunma.jp","ueno.gunma.jp","yoshioka.gunma.jp","asaminami.hiroshima.jp","daiwa.hiroshima.jp","etajima.hiroshima.jp","fuchu.hiroshima.jp","fukuyama.hiroshima.jp","hatsukaichi.hiroshima.jp","higashihiroshima.hiroshima.jp","hongo.hiroshima.jp","jinsekikogen.hiroshima.jp","kaita.hiroshima.jp","kui.hiroshima.jp","kumano.hiroshima.jp","kure.hiroshima.jp","mihara.hiroshima.jp","miyoshi.hiroshima.jp","naka.hiroshima.jp","onomichi.hiroshima.jp","osakikamijima.hiroshima.jp","otake.hiroshima.jp","saka.hiroshima.jp","sera.hiroshima.jp","seranishi.hiroshima.jp","shinichi.hiroshima.jp","shobara.hiroshima.jp","takehara.hiroshima.jp","abashiri.hokkaido.jp","abira.hokkaido.jp","aibetsu.hokkaido.jp","akabira.hokkaido.jp","akkeshi.hokkaido.jp","asahikawa.hokkaido.jp","ashibetsu.hokkaido.jp","ashoro.hokkaido.jp","assabu.hokkaido.jp","atsuma.hokkaido.jp","bibai.hokkaido.jp","biei.hokkaido.jp","bifuka.hokkaido.jp","bihoro.hokkaido.jp","biratori.hokkaido.jp","chippubetsu.hokkaido.jp","chitose.hokkaido.jp","date.hokkaido.jp","ebetsu.hokkaido.jp","embetsu.hokkaido.jp","eniwa.hokkaido.jp","erimo.hokkaido.jp","esan.hokkaido.jp","esashi.hokkaido.jp","fukagawa.hokkaido.jp","fukushima.hokkaido.jp","furano.hokkaido.jp","furubira.hokkaido.jp","haboro.hokkaido.jp","hakodate.hokkaido.jp","hamatonbetsu.hokkaido.jp","hidaka.hokkaido.jp","higashikagura.hokkaido.jp","higashikawa.hokkaido.jp","hiroo.hokkaido.jp","hokuryu.hokkaido.jp","hokuto.hokkaido.jp","honbetsu.hokkaido.jp","horokanai.hokkaido.jp","horonobe.hokkaido.jp","ikeda.hokkaido.jp","imakane.hokkaido.jp","ishikari.hokkaido.jp","iwamizawa.hokkaido.jp","iwanai.hokkaido.jp","kamifurano.hokkaido.jp","kamikawa.hokkaido.jp","kamishihoro.hokkaido.jp","kamisunagawa.hokkaido.jp","kamoenai.hokkaido.jp","kayabe.hokkaido.jp","kembuchi.hokkaido.jp","kikonai.hokkaido.jp","kimobetsu.hokkaido.jp","kitahiroshima.hokkaido.jp","kitami.hokkaido.jp","kiyosato.hokkaido.jp","koshimizu.hokkaido.jp","kunneppu.hokkaido.jp","kuriyama.hokkaido.jp","kuromatsunai.hokkaido.jp","kushiro.hokkaido.jp","kutchan.hokkaido.jp","kyowa.hokkaido.jp","mashike.hokkaido.jp","matsumae.hokkaido.jp","mikasa.hokkaido.jp","minamifurano.hokkaido.jp","mombetsu.hokkaido.jp","moseushi.hokkaido.jp","mukawa.hokkaido.jp","muroran.hokkaido.jp","naie.hokkaido.jp","nakagawa.hokkaido.jp","nakasatsunai.hokkaido.jp","nakatombetsu.hokkaido.jp","nanae.hokkaido.jp","nanporo.hokkaido.jp","nayoro.hokkaido.jp","nemuro.hokkaido.jp","niikappu.hokkaido.jp","niki.hokkaido.jp","nishiokoppe.hokkaido.jp","noboribetsu.hokkaido.jp","numata.hokkaido.jp","obihiro.hokkaido.jp","obira.hokkaido.jp","oketo.hokkaido.jp","okoppe.hokkaido.jp","otaru.hokkaido.jp","otobe.hokkaido.jp","otofuke.hokkaido.jp","otoineppu.hokkaido.jp","oumu.hokkaido.jp","ozora.hokkaido.jp","pippu.hokkaido.jp","rankoshi.hokkaido.jp","rebun.hokkaido.jp","rikubetsu.hokkaido.jp","rishiri.hokkaido.jp","rishirifuji.hokkaido.jp","saroma.hokkaido.jp","sarufutsu.hokkaido.jp","shakotan.hokkaido.jp","shari.hokkaido.jp","shibecha.hokkaido.jp","shibetsu.hokkaido.jp","shikabe.hokkaido.jp","shikaoi.hokkaido.jp","shimamaki.hokkaido.jp","shimizu.hokkaido.jp","shimokawa.hokkaido.jp","shinshinotsu.hokkaido.jp","shintoku.hokkaido.jp","shiranuka.hokkaido.jp","shiraoi.hokkaido.jp","shiriuchi.hokkaido.jp","sobetsu.hokkaido.jp","sunagawa.hokkaido.jp","taiki.hokkaido.jp","takasu.hokkaido.jp","takikawa.hokkaido.jp","takinoue.hokkaido.jp","teshikaga.hokkaido.jp","tobetsu.hokkaido.jp","tohma.hokkaido.jp","tomakomai.hokkaido.jp","tomari.hokkaido.jp","toya.hokkaido.jp","toyako.hokkaido.jp","toyotomi.hokkaido.jp","toyoura.hokkaido.jp","tsubetsu.hokkaido.jp","tsukigata.hokkaido.jp","urakawa.hokkaido.jp","urausu.hokkaido.jp","uryu.hokkaido.jp","utashinai.hokkaido.jp","wakkanai.hokkaido.jp","wassamu.hokkaido.jp","yakumo.hokkaido.jp","yoichi.hokkaido.jp","aioi.hyogo.jp","akashi.hyogo.jp","ako.hyogo.jp","amagasaki.hyogo.jp","aogaki.hyogo.jp","asago.hyogo.jp","ashiya.hyogo.jp","awaji.hyogo.jp","fukusaki.hyogo.jp","goshiki.hyogo.jp","harima.hyogo.jp","himeji.hyogo.jp","ichikawa.hyogo.jp","inagawa.hyogo.jp","itami.hyogo.jp","kakogawa.hyogo.jp","kamigori.hyogo.jp","kamikawa.hyogo.jp","kasai.hyogo.jp","kasuga.hyogo.jp","kawanishi.hyogo.jp","miki.hyogo.jp","minamiawaji.hyogo.jp","nishinomiya.hyogo.jp","nishiwaki.hyogo.jp","ono.hyogo.jp","sanda.hyogo.jp","sannan.hyogo.jp","sasayama.hyogo.jp","sayo.hyogo.jp","shingu.hyogo.jp","shinonsen.hyogo.jp","shiso.hyogo.jp","sumoto.hyogo.jp","taishi.hyogo.jp","taka.hyogo.jp","takarazuka.hyogo.jp","takasago.hyogo.jp","takino.hyogo.jp","tamba.hyogo.jp","tatsuno.hyogo.jp","toyooka.hyogo.jp","yabu.hyogo.jp","yashiro.hyogo.jp","yoka.hyogo.jp","yokawa.hyogo.jp","ami.ibaraki.jp","asahi.ibaraki.jp","bando.ibaraki.jp","chikusei.ibaraki.jp","daigo.ibaraki.jp","fujishiro.ibaraki.jp","hitachi.ibaraki.jp","hitachinaka.ibaraki.jp","hitachiomiya.ibaraki.jp","hitachiota.ibaraki.jp","ibaraki.ibaraki.jp","ina.ibaraki.jp","inashiki.ibaraki.jp","itako.ibaraki.jp","iwama.ibaraki.jp","joso.ibaraki.jp","kamisu.ibaraki.jp","kasama.ibaraki.jp","kashima.ibaraki.jp","kasumigaura.ibaraki.jp","koga.ibaraki.jp","miho.ibaraki.jp","mito.ibaraki.jp","moriya.ibaraki.jp","naka.ibaraki.jp","namegata.ibaraki.jp","oarai.ibaraki.jp","ogawa.ibaraki.jp","omitama.ibaraki.jp","ryugasaki.ibaraki.jp","sakai.ibaraki.jp","sakuragawa.ibaraki.jp","shimodate.ibaraki.jp","shimotsuma.ibaraki.jp","shirosato.ibaraki.jp","sowa.ibaraki.jp","suifu.ibaraki.jp","takahagi.ibaraki.jp","tamatsukuri.ibaraki.jp","tokai.ibaraki.jp","tomobe.ibaraki.jp","tone.ibaraki.jp","toride.ibaraki.jp","tsuchiura.ibaraki.jp","tsukuba.ibaraki.jp","uchihara.ibaraki.jp","ushiku.ibaraki.jp","yachiyo.ibaraki.jp","yamagata.ibaraki.jp","yawara.ibaraki.jp","yuki.ibaraki.jp","anamizu.ishikawa.jp","hakui.ishikawa.jp","hakusan.ishikawa.jp","kaga.ishikawa.jp","kahoku.ishikawa.jp","kanazawa.ishikawa.jp","kawakita.ishikawa.jp","komatsu.ishikawa.jp","nakanoto.ishikawa.jp","nanao.ishikawa.jp","nomi.ishikawa.jp","nonoichi.ishikawa.jp","noto.ishikawa.jp","shika.ishikawa.jp","suzu.ishikawa.jp","tsubata.ishikawa.jp","tsurugi.ishikawa.jp","uchinada.ishikawa.jp","wajima.ishikawa.jp","fudai.iwate.jp","fujisawa.iwate.jp","hanamaki.iwate.jp","hiraizumi.iwate.jp","hirono.iwate.jp","ichinohe.iwate.jp","ichinoseki.iwate.jp","iwaizumi.iwate.jp","iwate.iwate.jp","joboji.iwate.jp","kamaishi.iwate.jp","kanegasaki.iwate.jp","karumai.iwate.jp","kawai.iwate.jp","kitakami.iwate.jp","kuji.iwate.jp","kunohe.iwate.jp","kuzumaki.iwate.jp","miyako.iwate.jp","mizusawa.iwate.jp","morioka.iwate.jp","ninohe.iwate.jp","noda.iwate.jp","ofunato.iwate.jp","oshu.iwate.jp","otsuchi.iwate.jp","rikuzentakata.iwate.jp","shiwa.iwate.jp","shizukuishi.iwate.jp","sumita.iwate.jp","tanohata.iwate.jp","tono.iwate.jp","yahaba.iwate.jp","yamada.iwate.jp","ayagawa.kagawa.jp","higashikagawa.kagawa.jp","kanonji.kagawa.jp","kotohira.kagawa.jp","manno.kagawa.jp","marugame.kagawa.jp","mitoyo.kagawa.jp","naoshima.kagawa.jp","sanuki.kagawa.jp","tadotsu.kagawa.jp","takamatsu.kagawa.jp","tonosho.kagawa.jp","uchinomi.kagawa.jp","utazu.kagawa.jp","zentsuji.kagawa.jp","akune.kagoshima.jp","amami.kagoshima.jp","hioki.kagoshima.jp","isa.kagoshima.jp","isen.kagoshima.jp","izumi.kagoshima.jp","kagoshima.kagoshima.jp","kanoya.kagoshima.jp","kawanabe.kagoshima.jp","kinko.kagoshima.jp","kouyama.kagoshima.jp","makurazaki.kagoshima.jp","matsumoto.kagoshima.jp","minamitane.kagoshima.jp","nakatane.kagoshima.jp","nishinoomote.kagoshima.jp","satsumasendai.kagoshima.jp","soo.kagoshima.jp","tarumizu.kagoshima.jp","yusui.kagoshima.jp","aikawa.kanagawa.jp","atsugi.kanagawa.jp","ayase.kanagawa.jp","chigasaki.kanagawa.jp","ebina.kanagawa.jp","fujisawa.kanagawa.jp","hadano.kanagawa.jp","hakone.kanagawa.jp","hiratsuka.kanagawa.jp","isehara.kanagawa.jp","kaisei.kanagawa.jp","kamakura.kanagawa.jp","kiyokawa.kanagawa.jp","matsuda.kanagawa.jp","minamiashigara.kanagawa.jp","miura.kanagawa.jp","nakai.kanagawa.jp","ninomiya.kanagawa.jp","odawara.kanagawa.jp","oi.kanagawa.jp","oiso.kanagawa.jp","sagamihara.kanagawa.jp","samukawa.kanagawa.jp","tsukui.kanagawa.jp","yamakita.kanagawa.jp","yamato.kanagawa.jp","yokosuka.kanagawa.jp","yugawara.kanagawa.jp","zama.kanagawa.jp","zushi.kanagawa.jp","aki.kochi.jp","geisei.kochi.jp","hidaka.kochi.jp","higashitsuno.kochi.jp","ino.kochi.jp","kagami.kochi.jp","kami.kochi.jp","kitagawa.kochi.jp","kochi.kochi.jp","mihara.kochi.jp","motoyama.kochi.jp","muroto.kochi.jp","nahari.kochi.jp","nakamura.kochi.jp","nankoku.kochi.jp","nishitosa.kochi.jp","niyodogawa.kochi.jp","ochi.kochi.jp","okawa.kochi.jp","otoyo.kochi.jp","otsuki.kochi.jp","sakawa.kochi.jp","sukumo.kochi.jp","susaki.kochi.jp","tosa.kochi.jp","tosashimizu.kochi.jp","toyo.kochi.jp","tsuno.kochi.jp","umaji.kochi.jp","yasuda.kochi.jp","yusuhara.kochi.jp","amakusa.kumamoto.jp","arao.kumamoto.jp","aso.kumamoto.jp","choyo.kumamoto.jp","gyokuto.kumamoto.jp","kamiamakusa.kumamoto.jp","kikuchi.kumamoto.jp","kumamoto.kumamoto.jp","mashiki.kumamoto.jp","mifune.kumamoto.jp","minamata.kumamoto.jp","minamioguni.kumamoto.jp","nagasu.kumamoto.jp","nishihara.kumamoto.jp","oguni.kumamoto.jp","ozu.kumamoto.jp","sumoto.kumamoto.jp","takamori.kumamoto.jp","uki.kumamoto.jp","uto.kumamoto.jp","yamaga.kumamoto.jp","yamato.kumamoto.jp","yatsushiro.kumamoto.jp","ayabe.kyoto.jp","fukuchiyama.kyoto.jp","higashiyama.kyoto.jp","ide.kyoto.jp","ine.kyoto.jp","joyo.kyoto.jp","kameoka.kyoto.jp","kamo.kyoto.jp","kita.kyoto.jp","kizu.kyoto.jp","kumiyama.kyoto.jp","kyotamba.kyoto.jp","kyotanabe.kyoto.jp","kyotango.kyoto.jp","maizuru.kyoto.jp","minami.kyoto.jp","minamiyamashiro.kyoto.jp","miyazu.kyoto.jp","muko.kyoto.jp","nagaokakyo.kyoto.jp","nakagyo.kyoto.jp","nantan.kyoto.jp","oyamazaki.kyoto.jp","sakyo.kyoto.jp","seika.kyoto.jp","tanabe.kyoto.jp","uji.kyoto.jp","ujitawara.kyoto.jp","wazuka.kyoto.jp","yamashina.kyoto.jp","yawata.kyoto.jp","asahi.mie.jp","inabe.mie.jp","ise.mie.jp","kameyama.mie.jp","kawagoe.mie.jp","kiho.mie.jp","kisosaki.mie.jp","kiwa.mie.jp","komono.mie.jp","kumano.mie.jp","kuwana.mie.jp","matsusaka.mie.jp","meiwa.mie.jp","mihama.mie.jp","minamiise.mie.jp","misugi.mie.jp","miyama.mie.jp","nabari.mie.jp","shima.mie.jp","suzuka.mie.jp","tado.mie.jp","taiki.mie.jp","taki.mie.jp","tamaki.mie.jp","toba.mie.jp","tsu.mie.jp","udono.mie.jp","ureshino.mie.jp","watarai.mie.jp","yokkaichi.mie.jp","furukawa.miyagi.jp","higashimatsushima.miyagi.jp","ishinomaki.miyagi.jp","iwanuma.miyagi.jp","kakuda.miyagi.jp","kami.miyagi.jp","kawasaki.miyagi.jp","marumori.miyagi.jp","matsushima.miyagi.jp","minamisanriku.miyagi.jp","misato.miyagi.jp","murata.miyagi.jp","natori.miyagi.jp","ogawara.miyagi.jp","ohira.miyagi.jp","onagawa.miyagi.jp","osaki.miyagi.jp","rifu.miyagi.jp","semine.miyagi.jp","shibata.miyagi.jp","shichikashuku.miyagi.jp","shikama.miyagi.jp","shiogama.miyagi.jp","shiroishi.miyagi.jp","tagajo.miyagi.jp","taiwa.miyagi.jp","tome.miyagi.jp","tomiya.miyagi.jp","wakuya.miyagi.jp","watari.miyagi.jp","yamamoto.miyagi.jp","zao.miyagi.jp","aya.miyazaki.jp","ebino.miyazaki.jp","gokase.miyazaki.jp","hyuga.miyazaki.jp","kadogawa.miyazaki.jp","kawaminami.miyazaki.jp","kijo.miyazaki.jp","kitagawa.miyazaki.jp","kitakata.miyazaki.jp","kitaura.miyazaki.jp","kobayashi.miyazaki.jp","kunitomi.miyazaki.jp","kushima.miyazaki.jp","mimata.miyazaki.jp","miyakonojo.miyazaki.jp","miyazaki.miyazaki.jp","morotsuka.miyazaki.jp","nichinan.miyazaki.jp","nishimera.miyazaki.jp","nobeoka.miyazaki.jp","saito.miyazaki.jp","shiiba.miyazaki.jp","shintomi.miyazaki.jp","takaharu.miyazaki.jp","takanabe.miyazaki.jp","takazaki.miyazaki.jp","tsuno.miyazaki.jp","achi.nagano.jp","agematsu.nagano.jp","anan.nagano.jp","aoki.nagano.jp","asahi.nagano.jp","azumino.nagano.jp","chikuhoku.nagano.jp","chikuma.nagano.jp","chino.nagano.jp","fujimi.nagano.jp","hakuba.nagano.jp","hara.nagano.jp","hiraya.nagano.jp","iida.nagano.jp","iijima.nagano.jp","iiyama.nagano.jp","iizuna.nagano.jp","ikeda.nagano.jp","ikusaka.nagano.jp","ina.nagano.jp","karuizawa.nagano.jp","kawakami.nagano.jp","kiso.nagano.jp","kisofukushima.nagano.jp","kitaaiki.nagano.jp","komagane.nagano.jp","komoro.nagano.jp","matsukawa.nagano.jp","matsumoto.nagano.jp","miasa.nagano.jp","minamiaiki.nagano.jp","minamimaki.nagano.jp","minamiminowa.nagano.jp","minowa.nagano.jp","miyada.nagano.jp","miyota.nagano.jp","mochizuki.nagano.jp","nagano.nagano.jp","nagawa.nagano.jp","nagiso.nagano.jp","nakagawa.nagano.jp","nakano.nagano.jp","nozawaonsen.nagano.jp","obuse.nagano.jp","ogawa.nagano.jp","okaya.nagano.jp","omachi.nagano.jp","omi.nagano.jp","ookuwa.nagano.jp","ooshika.nagano.jp","otaki.nagano.jp","otari.nagano.jp","sakae.nagano.jp","sakaki.nagano.jp","saku.nagano.jp","sakuho.nagano.jp","shimosuwa.nagano.jp","shinanomachi.nagano.jp","shiojiri.nagano.jp","suwa.nagano.jp","suzaka.nagano.jp","takagi.nagano.jp","takamori.nagano.jp","takayama.nagano.jp","tateshina.nagano.jp","tatsuno.nagano.jp","togakushi.nagano.jp","togura.nagano.jp","tomi.nagano.jp","ueda.nagano.jp","wada.nagano.jp","yamagata.nagano.jp","yamanouchi.nagano.jp","yasaka.nagano.jp","yasuoka.nagano.jp","chijiwa.nagasaki.jp","futsu.nagasaki.jp","goto.nagasaki.jp","hasami.nagasaki.jp","hirado.nagasaki.jp","iki.nagasaki.jp","isahaya.nagasaki.jp","kawatana.nagasaki.jp","kuchinotsu.nagasaki.jp","matsuura.nagasaki.jp","nagasaki.nagasaki.jp","obama.nagasaki.jp","omura.nagasaki.jp","oseto.nagasaki.jp","saikai.nagasaki.jp","sasebo.nagasaki.jp","seihi.nagasaki.jp","shimabara.nagasaki.jp","shinkamigoto.nagasaki.jp","togitsu.nagasaki.jp","tsushima.nagasaki.jp","unzen.nagasaki.jp","ando.nara.jp","gose.nara.jp","heguri.nara.jp","higashiyoshino.nara.jp","ikaruga.nara.jp","ikoma.nara.jp","kamikitayama.nara.jp","kanmaki.nara.jp","kashiba.nara.jp","kashihara.nara.jp","katsuragi.nara.jp","kawai.nara.jp","kawakami.nara.jp","kawanishi.nara.jp","koryo.nara.jp","kurotaki.nara.jp","mitsue.nara.jp","miyake.nara.jp","nara.nara.jp","nosegawa.nara.jp","oji.nara.jp","ouda.nara.jp","oyodo.nara.jp","sakurai.nara.jp","sango.nara.jp","shimoichi.nara.jp","shimokitayama.nara.jp","shinjo.nara.jp","soni.nara.jp","takatori.nara.jp","tawaramoto.nara.jp","tenkawa.nara.jp","tenri.nara.jp","uda.nara.jp","yamatokoriyama.nara.jp","yamatotakada.nara.jp","yamazoe.nara.jp","yoshino.nara.jp","aga.niigata.jp","agano.niigata.jp","gosen.niigata.jp","itoigawa.niigata.jp","izumozaki.niigata.jp","joetsu.niigata.jp","kamo.niigata.jp","kariwa.niigata.jp","kashiwazaki.niigata.jp","minamiuonuma.niigata.jp","mitsuke.niigata.jp","muika.niigata.jp","murakami.niigata.jp","myoko.niigata.jp","nagaoka.niigata.jp","niigata.niigata.jp","ojiya.niigata.jp","omi.niigata.jp","sado.niigata.jp","sanjo.niigata.jp","seiro.niigata.jp","seirou.niigata.jp","sekikawa.niigata.jp","shibata.niigata.jp","tagami.niigata.jp","tainai.niigata.jp","tochio.niigata.jp","tokamachi.niigata.jp","tsubame.niigata.jp","tsunan.niigata.jp","uonuma.niigata.jp","yahiko.niigata.jp","yoita.niigata.jp","yuzawa.niigata.jp","beppu.oita.jp","bungoono.oita.jp","bungotakada.oita.jp","hasama.oita.jp","hiji.oita.jp","himeshima.oita.jp","hita.oita.jp","kamitsue.oita.jp","kokonoe.oita.jp","kuju.oita.jp","kunisaki.oita.jp","kusu.oita.jp","oita.oita.jp","saiki.oita.jp","taketa.oita.jp","tsukumi.oita.jp","usa.oita.jp","usuki.oita.jp","yufu.oita.jp","akaiwa.okayama.jp","asakuchi.okayama.jp","bizen.okayama.jp","hayashima.okayama.jp","ibara.okayama.jp","kagamino.okayama.jp","kasaoka.okayama.jp","kibichuo.okayama.jp","kumenan.okayama.jp","kurashiki.okayama.jp","maniwa.okayama.jp","misaki.okayama.jp","nagi.okayama.jp","niimi.okayama.jp","nishiawakura.okayama.jp","okayama.okayama.jp","satosho.okayama.jp","setouchi.okayama.jp","shinjo.okayama.jp","shoo.okayama.jp","soja.okayama.jp","takahashi.okayama.jp","tamano.okayama.jp","tsuyama.okayama.jp","wake.okayama.jp","yakage.okayama.jp","aguni.okinawa.jp","ginowan.okinawa.jp","ginoza.okinawa.jp","gushikami.okinawa.jp","haebaru.okinawa.jp","higashi.okinawa.jp","hirara.okinawa.jp","iheya.okinawa.jp","ishigaki.okinawa.jp","ishikawa.okinawa.jp","itoman.okinawa.jp","izena.okinawa.jp","kadena.okinawa.jp","kin.okinawa.jp","kitadaito.okinawa.jp","kitanakagusuku.okinawa.jp","kumejima.okinawa.jp","kunigami.okinawa.jp","minamidaito.okinawa.jp","motobu.okinawa.jp","nago.okinawa.jp","naha.okinawa.jp","nakagusuku.okinawa.jp","nakijin.okinawa.jp","nanjo.okinawa.jp","nishihara.okinawa.jp","ogimi.okinawa.jp","okinawa.okinawa.jp","onna.okinawa.jp","shimoji.okinawa.jp","taketomi.okinawa.jp","tarama.okinawa.jp","tokashiki.okinawa.jp","tomigusuku.okinawa.jp","tonaki.okinawa.jp","urasoe.okinawa.jp","uruma.okinawa.jp","yaese.okinawa.jp","yomitan.okinawa.jp","yonabaru.okinawa.jp","yonaguni.okinawa.jp","zamami.okinawa.jp","abeno.osaka.jp","chihayaakasaka.osaka.jp","chuo.osaka.jp","daito.osaka.jp","fujiidera.osaka.jp","habikino.osaka.jp","hannan.osaka.jp","higashiosaka.osaka.jp","higashisumiyoshi.osaka.jp","higashiyodogawa.osaka.jp","hirakata.osaka.jp","ibaraki.osaka.jp","ikeda.osaka.jp","izumi.osaka.jp","izumiotsu.osaka.jp","izumisano.osaka.jp","kadoma.osaka.jp","kaizuka.osaka.jp","kanan.osaka.jp","kashiwara.osaka.jp","katano.osaka.jp","kawachinagano.osaka.jp","kishiwada.osaka.jp","kita.osaka.jp","kumatori.osaka.jp","matsubara.osaka.jp","minato.osaka.jp","minoh.osaka.jp","misaki.osaka.jp","moriguchi.osaka.jp","neyagawa.osaka.jp","nishi.osaka.jp","nose.osaka.jp","osakasayama.osaka.jp","sakai.osaka.jp","sayama.osaka.jp","sennan.osaka.jp","settsu.osaka.jp","shijonawate.osaka.jp","shimamoto.osaka.jp","suita.osaka.jp","tadaoka.osaka.jp","taishi.osaka.jp","tajiri.osaka.jp","takaishi.osaka.jp","takatsuki.osaka.jp","tondabayashi.osaka.jp","toyonaka.osaka.jp","toyono.osaka.jp","yao.osaka.jp","ariake.saga.jp","arita.saga.jp","fukudomi.saga.jp","genkai.saga.jp","hamatama.saga.jp","hizen.saga.jp","imari.saga.jp","kamimine.saga.jp","kanzaki.saga.jp","karatsu.saga.jp","kashima.saga.jp","kitagata.saga.jp","kitahata.saga.jp","kiyama.saga.jp","kouhoku.saga.jp","kyuragi.saga.jp","nishiarita.saga.jp","ogi.saga.jp","omachi.saga.jp","ouchi.saga.jp","saga.saga.jp","shiroishi.saga.jp","taku.saga.jp","tara.saga.jp","tosu.saga.jp","yoshinogari.saga.jp","arakawa.saitama.jp","asaka.saitama.jp","chichibu.saitama.jp","fujimi.saitama.jp","fujimino.saitama.jp","fukaya.saitama.jp","hanno.saitama.jp","hanyu.saitama.jp","hasuda.saitama.jp","hatogaya.saitama.jp","hatoyama.saitama.jp","hidaka.saitama.jp","higashichichibu.saitama.jp","higashimatsuyama.saitama.jp","honjo.saitama.jp","ina.saitama.jp","iruma.saitama.jp","iwatsuki.saitama.jp","kamiizumi.saitama.jp","kamikawa.saitama.jp","kamisato.saitama.jp","kasukabe.saitama.jp","kawagoe.saitama.jp","kawaguchi.saitama.jp","kawajima.saitama.jp","kazo.saitama.jp","kitamoto.saitama.jp","koshigaya.saitama.jp","kounosu.saitama.jp","kuki.saitama.jp","kumagaya.saitama.jp","matsubushi.saitama.jp","minano.saitama.jp","misato.saitama.jp","miyashiro.saitama.jp","miyoshi.saitama.jp","moroyama.saitama.jp","nagatoro.saitama.jp","namegawa.saitama.jp","niiza.saitama.jp","ogano.saitama.jp","ogawa.saitama.jp","ogose.saitama.jp","okegawa.saitama.jp","omiya.saitama.jp","otaki.saitama.jp","ranzan.saitama.jp","ryokami.saitama.jp","saitama.saitama.jp","sakado.saitama.jp","satte.saitama.jp","sayama.saitama.jp","shiki.saitama.jp","shiraoka.saitama.jp","soka.saitama.jp","sugito.saitama.jp","toda.saitama.jp","tokigawa.saitama.jp","tokorozawa.saitama.jp","tsurugashima.saitama.jp","urawa.saitama.jp","warabi.saitama.jp","yashio.saitama.jp","yokoze.saitama.jp","yono.saitama.jp","yorii.saitama.jp","yoshida.saitama.jp","yoshikawa.saitama.jp","yoshimi.saitama.jp","aisho.shiga.jp","gamo.shiga.jp","higashiomi.shiga.jp","hikone.shiga.jp","koka.shiga.jp","konan.shiga.jp","kosei.shiga.jp","koto.shiga.jp","kusatsu.shiga.jp","maibara.shiga.jp","moriyama.shiga.jp","nagahama.shiga.jp","nishiazai.shiga.jp","notogawa.shiga.jp","omihachiman.shiga.jp","otsu.shiga.jp","ritto.shiga.jp","ryuoh.shiga.jp","takashima.shiga.jp","takatsuki.shiga.jp","torahime.shiga.jp","toyosato.shiga.jp","yasu.shiga.jp","akagi.shimane.jp","ama.shimane.jp","gotsu.shimane.jp","hamada.shimane.jp","higashiizumo.shimane.jp","hikawa.shimane.jp","hikimi.shimane.jp","izumo.shimane.jp","kakinoki.shimane.jp","masuda.shimane.jp","matsue.shimane.jp","misato.shimane.jp","nishinoshima.shimane.jp","ohda.shimane.jp","okinoshima.shimane.jp","okuizumo.shimane.jp","shimane.shimane.jp","tamayu.shimane.jp","tsuwano.shimane.jp","unnan.shimane.jp","yakumo.shimane.jp","yasugi.shimane.jp","yatsuka.shimane.jp","arai.shizuoka.jp","atami.shizuoka.jp","fuji.shizuoka.jp","fujieda.shizuoka.jp","fujikawa.shizuoka.jp","fujinomiya.shizuoka.jp","fukuroi.shizuoka.jp","gotemba.shizuoka.jp","haibara.shizuoka.jp","hamamatsu.shizuoka.jp","higashiizu.shizuoka.jp","ito.shizuoka.jp","iwata.shizuoka.jp","izu.shizuoka.jp","izunokuni.shizuoka.jp","kakegawa.shizuoka.jp","kannami.shizuoka.jp","kawanehon.shizuoka.jp","kawazu.shizuoka.jp","kikugawa.shizuoka.jp","kosai.shizuoka.jp","makinohara.shizuoka.jp","matsuzaki.shizuoka.jp","minamiizu.shizuoka.jp","mishima.shizuoka.jp","morimachi.shizuoka.jp","nishiizu.shizuoka.jp","numazu.shizuoka.jp","omaezaki.shizuoka.jp","shimada.shizuoka.jp","shimizu.shizuoka.jp","shimoda.shizuoka.jp","shizuoka.shizuoka.jp","susono.shizuoka.jp","yaizu.shizuoka.jp","yoshida.shizuoka.jp","ashikaga.tochigi.jp","bato.tochigi.jp","haga.tochigi.jp","ichikai.tochigi.jp","iwafune.tochigi.jp","kaminokawa.tochigi.jp","kanuma.tochigi.jp","karasuyama.tochigi.jp","kuroiso.tochigi.jp","mashiko.tochigi.jp","mibu.tochigi.jp","moka.tochigi.jp","motegi.tochigi.jp","nasu.tochigi.jp","nasushiobara.tochigi.jp","nikko.tochigi.jp","nishikata.tochigi.jp","nogi.tochigi.jp","ohira.tochigi.jp","ohtawara.tochigi.jp","oyama.tochigi.jp","sakura.tochigi.jp","sano.tochigi.jp","shimotsuke.tochigi.jp","shioya.tochigi.jp","takanezawa.tochigi.jp","tochigi.tochigi.jp","tsuga.tochigi.jp","ujiie.tochigi.jp","utsunomiya.tochigi.jp","yaita.tochigi.jp","aizumi.tokushima.jp","anan.tokushima.jp","ichiba.tokushima.jp","itano.tokushima.jp","kainan.tokushima.jp","komatsushima.tokushima.jp","matsushige.tokushima.jp","mima.tokushima.jp","minami.tokushima.jp","miyoshi.tokushima.jp","mugi.tokushima.jp","nakagawa.tokushima.jp","naruto.tokushima.jp","sanagochi.tokushima.jp","shishikui.tokushima.jp","tokushima.tokushima.jp","wajiki.tokushima.jp","adachi.tokyo.jp","akiruno.tokyo.jp","akishima.tokyo.jp","aogashima.tokyo.jp","arakawa.tokyo.jp","bunkyo.tokyo.jp","chiyoda.tokyo.jp","chofu.tokyo.jp","chuo.tokyo.jp","edogawa.tokyo.jp","fuchu.tokyo.jp","fussa.tokyo.jp","hachijo.tokyo.jp","hachioji.tokyo.jp","hamura.tokyo.jp","higashikurume.tokyo.jp","higashimurayama.tokyo.jp","higashiyamato.tokyo.jp","hino.tokyo.jp","hinode.tokyo.jp","hinohara.tokyo.jp","inagi.tokyo.jp","itabashi.tokyo.jp","katsushika.tokyo.jp","kita.tokyo.jp","kiyose.tokyo.jp","kodaira.tokyo.jp","koganei.tokyo.jp","kokubunji.tokyo.jp","komae.tokyo.jp","koto.tokyo.jp","kouzushima.tokyo.jp","kunitachi.tokyo.jp","machida.tokyo.jp","meguro.tokyo.jp","minato.tokyo.jp","mitaka.tokyo.jp","mizuho.tokyo.jp","musashimurayama.tokyo.jp","musashino.tokyo.jp","nakano.tokyo.jp","nerima.tokyo.jp","ogasawara.tokyo.jp","okutama.tokyo.jp","ome.tokyo.jp","oshima.tokyo.jp","ota.tokyo.jp","setagaya.tokyo.jp","shibuya.tokyo.jp","shinagawa.tokyo.jp","shinjuku.tokyo.jp","suginami.tokyo.jp","sumida.tokyo.jp","tachikawa.tokyo.jp","taito.tokyo.jp","tama.tokyo.jp","toshima.tokyo.jp","chizu.tottori.jp","hino.tottori.jp","kawahara.tottori.jp","koge.tottori.jp","kotoura.tottori.jp","misasa.tottori.jp","nanbu.tottori.jp","nichinan.tottori.jp","sakaiminato.tottori.jp","tottori.tottori.jp","wakasa.tottori.jp","yazu.tottori.jp","yonago.tottori.jp","asahi.toyama.jp","fuchu.toyama.jp","fukumitsu.toyama.jp","funahashi.toyama.jp","himi.toyama.jp","imizu.toyama.jp","inami.toyama.jp","johana.toyama.jp","kamiichi.toyama.jp","kurobe.toyama.jp","nakaniikawa.toyama.jp","namerikawa.toyama.jp","nanto.toyama.jp","nyuzen.toyama.jp","oyabe.toyama.jp","taira.toyama.jp","takaoka.toyama.jp","tateyama.toyama.jp","toga.toyama.jp","tonami.toyama.jp","toyama.toyama.jp","unazuki.toyama.jp","uozu.toyama.jp","yamada.toyama.jp","arida.wakayama.jp","aridagawa.wakayama.jp","gobo.wakayama.jp","hashimoto.wakayama.jp","hidaka.wakayama.jp","hirogawa.wakayama.jp","inami.wakayama.jp","iwade.wakayama.jp","kainan.wakayama.jp","kamitonda.wakayama.jp","katsuragi.wakayama.jp","kimino.wakayama.jp","kinokawa.wakayama.jp","kitayama.wakayama.jp","koya.wakayama.jp","koza.wakayama.jp","kozagawa.wakayama.jp","kudoyama.wakayama.jp","kushimoto.wakayama.jp","mihama.wakayama.jp","misato.wakayama.jp","nachikatsuura.wakayama.jp","shingu.wakayama.jp","shirahama.wakayama.jp","taiji.wakayama.jp","tanabe.wakayama.jp","wakayama.wakayama.jp","yuasa.wakayama.jp","yura.wakayama.jp","asahi.yamagata.jp","funagata.yamagata.jp","higashine.yamagata.jp","iide.yamagata.jp","kahoku.yamagata.jp","kaminoyama.yamagata.jp","kaneyama.yamagata.jp","kawanishi.yamagata.jp","mamurogawa.yamagata.jp","mikawa.yamagata.jp","murayama.yamagata.jp","nagai.yamagata.jp","nakayama.yamagata.jp","nanyo.yamagata.jp","nishikawa.yamagata.jp","obanazawa.yamagata.jp","oe.yamagata.jp","oguni.yamagata.jp","ohkura.yamagata.jp","oishida.yamagata.jp","sagae.yamagata.jp","sakata.yamagata.jp","sakegawa.yamagata.jp","shinjo.yamagata.jp","shirataka.yamagata.jp","shonai.yamagata.jp","takahata.yamagata.jp","tendo.yamagata.jp","tozawa.yamagata.jp","tsuruoka.yamagata.jp","yamagata.yamagata.jp","yamanobe.yamagata.jp","yonezawa.yamagata.jp","yuza.yamagata.jp","abu.yamaguchi.jp","hagi.yamaguchi.jp","hikari.yamaguchi.jp","hofu.yamaguchi.jp","iwakuni.yamaguchi.jp","kudamatsu.yamaguchi.jp","mitou.yamaguchi.jp","nagato.yamaguchi.jp","oshima.yamaguchi.jp","shimonoseki.yamaguchi.jp","shunan.yamaguchi.jp","tabuse.yamaguchi.jp","tokuyama.yamaguchi.jp","toyota.yamaguchi.jp","ube.yamaguchi.jp","yuu.yamaguchi.jp","chuo.yamanashi.jp","doshi.yamanashi.jp","fuefuki.yamanashi.jp","fujikawa.yamanashi.jp","fujikawaguchiko.yamanashi.jp","fujiyoshida.yamanashi.jp","hayakawa.yamanashi.jp","hokuto.yamanashi.jp","ichikawamisato.yamanashi.jp","kai.yamanashi.jp","kofu.yamanashi.jp","koshu.yamanashi.jp","kosuge.yamanashi.jp","minami-alps.yamanashi.jp","minobu.yamanashi.jp","nakamichi.yamanashi.jp","nanbu.yamanashi.jp","narusawa.yamanashi.jp","nirasaki.yamanashi.jp","nishikatsura.yamanashi.jp","oshino.yamanashi.jp","otsuki.yamanashi.jp","showa.yamanashi.jp","tabayama.yamanashi.jp","tsuru.yamanashi.jp","uenohara.yamanashi.jp","yamanakako.yamanashi.jp","yamanashi.yamanashi.jp","ke","ac.ke","co.ke","go.ke","info.ke","me.ke","mobi.ke","ne.ke","or.ke","sc.ke","kg","org.kg","net.kg","com.kg","edu.kg","gov.kg","mil.kg","*.kh","ki","edu.ki","biz.ki","net.ki","org.ki","gov.ki","info.ki","com.ki","km","org.km","nom.km","gov.km","prd.km","tm.km","edu.km","mil.km","ass.km","com.km","coop.km","asso.km","presse.km","medecin.km","notaires.km","pharmaciens.km","veterinaire.km","gouv.km","kn","net.kn","org.kn","edu.kn","gov.kn","kp","com.kp","edu.kp","gov.kp","org.kp","rep.kp","tra.kp","kr","ac.kr","co.kr","es.kr","go.kr","hs.kr","kg.kr","mil.kr","ms.kr","ne.kr","or.kr","pe.kr","re.kr","sc.kr","busan.kr","chungbuk.kr","chungnam.kr","daegu.kr","daejeon.kr","gangwon.kr","gwangju.kr","gyeongbuk.kr","gyeonggi.kr","gyeongnam.kr","incheon.kr","jeju.kr","jeonbuk.kr","jeonnam.kr","seoul.kr","ulsan.kr","kw","com.kw","edu.kw","emb.kw","gov.kw","ind.kw","net.kw","org.kw","ky","edu.ky","gov.ky","com.ky","org.ky","net.ky","kz","org.kz","edu.kz","net.kz","gov.kz","mil.kz","com.kz","la","int.la","net.la","info.la","edu.la","gov.la","per.la","com.la","org.la","lb","com.lb","edu.lb","gov.lb","net.lb","org.lb","lc","com.lc","net.lc","co.lc","org.lc","edu.lc","gov.lc","li","lk","gov.lk","sch.lk","net.lk","int.lk","com.lk","org.lk","edu.lk","ngo.lk","soc.lk","web.lk","ltd.lk","assn.lk","grp.lk","hotel.lk","ac.lk","lr","com.lr","edu.lr","gov.lr","org.lr","net.lr","ls","co.ls","org.ls","lt","gov.lt","lu","lv","com.lv","edu.lv","gov.lv","org.lv","mil.lv","id.lv","net.lv","asn.lv","conf.lv","ly","com.ly","net.ly","gov.ly","plc.ly","edu.ly","sch.ly","med.ly","org.ly","id.ly","ma","co.ma","net.ma","gov.ma","org.ma","ac.ma","press.ma","mc","tm.mc","asso.mc","md","me","co.me","net.me","org.me","edu.me","ac.me","gov.me","its.me","priv.me","mg","org.mg","nom.mg","gov.mg","prd.mg","tm.mg","edu.mg","mil.mg","com.mg","co.mg","mh","mil","mk","com.mk","org.mk","net.mk","edu.mk","gov.mk","inf.mk","name.mk","ml","com.ml","edu.ml","gouv.ml","gov.ml","net.ml","org.ml","presse.ml","*.mm","mn","gov.mn","edu.mn","org.mn","mo","com.mo","net.mo","org.mo","edu.mo","gov.mo","mobi","mp","mq","mr","gov.mr","ms","com.ms","edu.ms","gov.ms","net.ms","org.ms","mt","com.mt","edu.mt","net.mt","org.mt","mu","com.mu","net.mu","org.mu","gov.mu","ac.mu","co.mu","or.mu","museum","academy.museum","agriculture.museum","air.museum","airguard.museum","alabama.museum","alaska.museum","amber.museum","ambulance.museum","american.museum","americana.museum","americanantiques.museum","americanart.museum","amsterdam.museum","and.museum","annefrank.museum","anthro.museum","anthropology.museum","antiques.museum","aquarium.museum","arboretum.museum","archaeological.museum","archaeology.museum","architecture.museum","art.museum","artanddesign.museum","artcenter.museum","artdeco.museum","arteducation.museum","artgallery.museum","arts.museum","artsandcrafts.museum","asmatart.museum","assassination.museum","assisi.museum","association.museum","astronomy.museum","atlanta.museum","austin.museum","australia.museum","automotive.museum","aviation.museum","axis.museum","badajoz.museum","baghdad.museum","bahn.museum","bale.museum","baltimore.museum","barcelona.museum","baseball.museum","basel.museum","baths.museum","bauern.museum","beauxarts.museum","beeldengeluid.museum","bellevue.museum","bergbau.museum","berkeley.museum","berlin.museum","bern.museum","bible.museum","bilbao.museum","bill.museum","birdart.museum","birthplace.museum","bonn.museum","boston.museum","botanical.museum","botanicalgarden.museum","botanicgarden.museum","botany.museum","brandywinevalley.museum","brasil.museum","bristol.museum","british.museum","britishcolumbia.museum","broadcast.museum","brunel.museum","brussel.museum","brussels.museum","bruxelles.museum","building.museum","burghof.museum","bus.museum","bushey.museum","cadaques.museum","california.museum","cambridge.museum","can.museum","canada.museum","capebreton.museum","carrier.museum","cartoonart.museum","casadelamoneda.museum","castle.museum","castres.museum","celtic.museum","center.museum","chattanooga.museum","cheltenham.museum","chesapeakebay.museum","chicago.museum","children.museum","childrens.museum","childrensgarden.museum","chiropractic.museum","chocolate.museum","christiansburg.museum","cincinnati.museum","cinema.museum","circus.museum","civilisation.museum","civilization.museum","civilwar.museum","clinton.museum","clock.museum","coal.museum","coastaldefence.museum","cody.museum","coldwar.museum","collection.museum","colonialwilliamsburg.museum","coloradoplateau.museum","columbia.museum","columbus.museum","communication.museum","communications.museum","community.museum","computer.museum","computerhistory.museum","comunicações.museum","contemporary.museum","contemporaryart.museum","convent.museum","copenhagen.museum","corporation.museum","correios-e-telecomunicações.museum","corvette.museum","costume.museum","countryestate.museum","county.museum","crafts.museum","cranbrook.museum","creation.museum","cultural.museum","culturalcenter.museum","culture.museum","cyber.museum","cymru.museum","dali.museum","dallas.museum","database.museum","ddr.museum","decorativearts.museum","delaware.museum","delmenhorst.museum","denmark.museum","depot.museum","design.museum","detroit.museum","dinosaur.museum","discovery.museum","dolls.museum","donostia.museum","durham.museum","eastafrica.museum","eastcoast.museum","education.museum","educational.museum","egyptian.museum","eisenbahn.museum","elburg.museum","elvendrell.museum","embroidery.museum","encyclopedic.museum","england.museum","entomology.museum","environment.museum","environmentalconservation.museum","epilepsy.museum","essex.museum","estate.museum","ethnology.museum","exeter.museum","exhibition.museum","family.museum","farm.museum","farmequipment.museum","farmers.museum","farmstead.museum","field.museum","figueres.museum","filatelia.museum","film.museum","fineart.museum","finearts.museum","finland.museum","flanders.museum","florida.museum","force.museum","fortmissoula.museum","fortworth.museum","foundation.museum","francaise.museum","frankfurt.museum","franziskaner.museum","freemasonry.museum","freiburg.museum","fribourg.museum","frog.museum","fundacio.museum","furniture.museum","gallery.museum","garden.museum","gateway.museum","geelvinck.museum","gemological.museum","geology.museum","georgia.museum","giessen.museum","glas.museum","glass.museum","gorge.museum","grandrapids.museum","graz.museum","guernsey.museum","halloffame.museum","hamburg.museum","handson.museum","harvestcelebration.museum","hawaii.museum","health.museum","heimatunduhren.museum","hellas.museum","helsinki.museum","hembygdsforbund.museum","heritage.museum","histoire.museum","historical.museum","historicalsociety.museum","historichouses.museum","historisch.museum","historisches.museum","history.museum","historyofscience.museum","horology.museum","house.museum","humanities.museum","illustration.museum","imageandsound.museum","indian.museum","indiana.museum","indianapolis.museum","indianmarket.museum","intelligence.museum","interactive.museum","iraq.museum","iron.museum","isleofman.museum","jamison.museum","jefferson.museum","jerusalem.museum","jewelry.museum","jewish.museum","jewishart.museum","jfk.museum","journalism.museum","judaica.museum","judygarland.museum","juedisches.museum","juif.museum","karate.museum","karikatur.museum","kids.museum","koebenhavn.museum","koeln.museum","kunst.museum","kunstsammlung.museum","kunstunddesign.museum","labor.museum","labour.museum","lajolla.museum","lancashire.museum","landes.museum","lans.museum","läns.museum","larsson.museum","lewismiller.museum","lincoln.museum","linz.museum","living.museum","livinghistory.museum","localhistory.museum","london.museum","losangeles.museum","louvre.museum","loyalist.museum","lucerne.museum","luxembourg.museum","luzern.museum","mad.museum","madrid.museum","mallorca.museum","manchester.museum","mansion.museum","mansions.museum","manx.museum","marburg.museum","maritime.museum","maritimo.museum","maryland.museum","marylhurst.museum","media.museum","medical.museum","medizinhistorisches.museum","meeres.museum","memorial.museum","mesaverde.museum","michigan.museum","midatlantic.museum","military.museum","mill.museum","miners.museum","mining.museum","minnesota.museum","missile.museum","missoula.museum","modern.museum","moma.museum","money.museum","monmouth.museum","monticello.museum","montreal.museum","moscow.museum","motorcycle.museum","muenchen.museum","muenster.museum","mulhouse.museum","muncie.museum","museet.museum","museumcenter.museum","museumvereniging.museum","music.museum","national.museum","nationalfirearms.museum","nationalheritage.museum","nativeamerican.museum","naturalhistory.museum","naturalhistorymuseum.museum","naturalsciences.museum","nature.museum","naturhistorisches.museum","natuurwetenschappen.museum","naumburg.museum","naval.museum","nebraska.museum","neues.museum","newhampshire.museum","newjersey.museum","newmexico.museum","newport.museum","newspaper.museum","newyork.museum","niepce.museum","norfolk.museum","north.museum","nrw.museum","nuernberg.museum","nuremberg.museum","nyc.museum","nyny.museum","oceanographic.museum","oceanographique.museum","omaha.museum","online.museum","ontario.museum","openair.museum","oregon.museum","oregontrail.museum","otago.museum","oxford.museum","pacific.museum","paderborn.museum","palace.museum","paleo.museum","palmsprings.museum","panama.museum","paris.museum","pasadena.museum","pharmacy.museum","philadelphia.museum","philadelphiaarea.museum","philately.museum","phoenix.museum","photography.museum","pilots.museum","pittsburgh.museum","planetarium.museum","plantation.museum","plants.museum","plaza.museum","portal.museum","portland.museum","portlligat.museum","posts-and-telecommunications.museum","preservation.museum","presidio.museum","press.museum","project.museum","public.museum","pubol.museum","quebec.museum","railroad.museum","railway.museum","research.museum","resistance.museum","riodejaneiro.museum","rochester.museum","rockart.museum","roma.museum","russia.museum","saintlouis.museum","salem.museum","salvadordali.museum","salzburg.museum","sandiego.museum","sanfrancisco.museum","santabarbara.museum","santacruz.museum","santafe.museum","saskatchewan.museum","satx.museum","savannahga.museum","schlesisches.museum","schoenbrunn.museum","schokoladen.museum","school.museum","schweiz.museum","science.museum","scienceandhistory.museum","scienceandindustry.museum","sciencecenter.museum","sciencecenters.museum","science-fiction.museum","sciencehistory.museum","sciences.museum","sciencesnaturelles.museum","scotland.museum","seaport.museum","settlement.museum","settlers.museum","shell.museum","sherbrooke.museum","sibenik.museum","silk.museum","ski.museum","skole.museum","society.museum","sologne.museum","soundandvision.museum","southcarolina.museum","southwest.museum","space.museum","spy.museum","square.museum","stadt.museum","stalbans.museum","starnberg.museum","state.museum","stateofdelaware.museum","station.museum","steam.museum","steiermark.museum","stjohn.museum","stockholm.museum","stpetersburg.museum","stuttgart.museum","suisse.museum","surgeonshall.museum","surrey.museum","svizzera.museum","sweden.museum","sydney.museum","tank.museum","tcm.museum","technology.museum","telekommunikation.museum","television.museum","texas.museum","textile.museum","theater.museum","time.museum","timekeeping.museum","topology.museum","torino.museum","touch.museum","town.museum","transport.museum","tree.museum","trolley.museum","trust.museum","trustee.museum","uhren.museum","ulm.museum","undersea.museum","university.museum","usa.museum","usantiques.museum","usarts.museum","uscountryestate.museum","usculture.museum","usdecorativearts.museum","usgarden.museum","ushistory.museum","ushuaia.museum","uslivinghistory.museum","utah.museum","uvic.museum","valley.museum","vantaa.museum","versailles.museum","viking.museum","village.museum","virginia.museum","virtual.museum","virtuel.museum","vlaanderen.museum","volkenkunde.museum","wales.museum","wallonie.museum","war.museum","washingtondc.museum","watchandclock.museum","watch-and-clock.museum","western.museum","westfalen.museum","whaling.museum","wildlife.museum","williamsburg.museum","windmill.museum","workshop.museum","york.museum","yorkshire.museum","yosemite.museum","youth.museum","zoological.museum","zoology.museum","ירושלים.museum","иком.museum","mv","aero.mv","biz.mv","com.mv","coop.mv","edu.mv","gov.mv","info.mv","int.mv","mil.mv","museum.mv","name.mv","net.mv","org.mv","pro.mv","mw","ac.mw","biz.mw","co.mw","com.mw","coop.mw","edu.mw","gov.mw","int.mw","museum.mw","net.mw","org.mw","mx","com.mx","org.mx","gob.mx","edu.mx","net.mx","my","com.my","net.my","org.my","gov.my","edu.my","mil.my","name.my","mz","ac.mz","adv.mz","co.mz","edu.mz","gov.mz","mil.mz","net.mz","org.mz","na","info.na","pro.na","name.na","school.na","or.na","dr.na","us.na","mx.na","ca.na","in.na","cc.na","tv.na","ws.na","mobi.na","co.na","com.na","org.na","name","nc","asso.nc","nom.nc","ne","net","nf","com.nf","net.nf","per.nf","rec.nf","web.nf","arts.nf","firm.nf","info.nf","other.nf","store.nf","ng","com.ng","edu.ng","gov.ng","i.ng","mil.ng","mobi.ng","name.ng","net.ng","org.ng","sch.ng","ni","ac.ni","biz.ni","co.ni","com.ni","edu.ni","gob.ni","in.ni","info.ni","int.ni","mil.ni","net.ni","nom.ni","org.ni","web.ni","nl","bv.nl","no","fhs.no","vgs.no","fylkesbibl.no","folkebibl.no","museum.no","idrett.no","priv.no","mil.no","stat.no","dep.no","kommune.no","herad.no","aa.no","ah.no","bu.no","fm.no","hl.no","hm.no","jan-mayen.no","mr.no","nl.no","nt.no","of.no","ol.no","oslo.no","rl.no","sf.no","st.no","svalbard.no","tm.no","tr.no","va.no","vf.no","gs.aa.no","gs.ah.no","gs.bu.no","gs.fm.no","gs.hl.no","gs.hm.no","gs.jan-mayen.no","gs.mr.no","gs.nl.no","gs.nt.no","gs.of.no","gs.ol.no","gs.oslo.no","gs.rl.no","gs.sf.no","gs.st.no","gs.svalbard.no","gs.tm.no","gs.tr.no","gs.va.no","gs.vf.no","akrehamn.no","åkrehamn.no","algard.no","ålgård.no","arna.no","brumunddal.no","bryne.no","bronnoysund.no","brønnøysund.no","drobak.no","drøbak.no","egersund.no","fetsund.no","floro.no","florø.no","fredrikstad.no","hokksund.no","honefoss.no","hønefoss.no","jessheim.no","jorpeland.no","jørpeland.no","kirkenes.no","kopervik.no","krokstadelva.no","langevag.no","langevåg.no","leirvik.no","mjondalen.no","mjøndalen.no","mo-i-rana.no","mosjoen.no","mosjøen.no","nesoddtangen.no","orkanger.no","osoyro.no","osøyro.no","raholt.no","råholt.no","sandnessjoen.no","sandnessjøen.no","skedsmokorset.no","slattum.no","spjelkavik.no","stathelle.no","stavern.no","stjordalshalsen.no","stjørdalshalsen.no","tananger.no","tranby.no","vossevangen.no","afjord.no","åfjord.no","agdenes.no","al.no","ål.no","alesund.no","ålesund.no","alstahaug.no","alta.no","áltá.no","alaheadju.no","álaheadju.no","alvdal.no","amli.no","åmli.no","amot.no","åmot.no","andebu.no","andoy.no","andøy.no","andasuolo.no","ardal.no","årdal.no","aremark.no","arendal.no","ås.no","aseral.no","åseral.no","asker.no","askim.no","askvoll.no","askoy.no","askøy.no","asnes.no","åsnes.no","audnedaln.no","aukra.no","aure.no","aurland.no","aurskog-holand.no","aurskog-høland.no","austevoll.no","austrheim.no","averoy.no","averøy.no","balestrand.no","ballangen.no","balat.no","bálát.no","balsfjord.no","bahccavuotna.no","báhccavuotna.no","bamble.no","bardu.no","beardu.no","beiarn.no","bajddar.no","bájddar.no","baidar.no","báidár.no","berg.no","bergen.no","berlevag.no","berlevåg.no","bearalvahki.no","bearalváhki.no","bindal.no","birkenes.no","bjarkoy.no","bjarkøy.no","bjerkreim.no","bjugn.no","bodo.no","bodø.no","badaddja.no","bådåddjå.no","budejju.no","bokn.no","bremanger.no","bronnoy.no","brønnøy.no","bygland.no","bykle.no","barum.no","bærum.no","bo.telemark.no","bø.telemark.no","bo.nordland.no","bø.nordland.no","bievat.no","bievát.no","bomlo.no","bømlo.no","batsfjord.no","båtsfjord.no","bahcavuotna.no","báhcavuotna.no","dovre.no","drammen.no","drangedal.no","dyroy.no","dyrøy.no","donna.no","dønna.no","eid.no","eidfjord.no","eidsberg.no","eidskog.no","eidsvoll.no","eigersund.no","elverum.no","enebakk.no","engerdal.no","etne.no","etnedal.no","evenes.no","evenassi.no","evenášši.no","evje-og-hornnes.no","farsund.no","fauske.no","fuossko.no","fuoisku.no","fedje.no","fet.no","finnoy.no","finnøy.no","fitjar.no","fjaler.no","fjell.no","flakstad.no","flatanger.no","flekkefjord.no","flesberg.no","flora.no","fla.no","flå.no","folldal.no","forsand.no","fosnes.no","frei.no","frogn.no","froland.no","frosta.no","frana.no","fræna.no","froya.no","frøya.no","fusa.no","fyresdal.no","forde.no","førde.no","gamvik.no","gangaviika.no","gáŋgaviika.no","gaular.no","gausdal.no","gildeskal.no","gildeskål.no","giske.no","gjemnes.no","gjerdrum.no","gjerstad.no","gjesdal.no","gjovik.no","gjøvik.no","gloppen.no","gol.no","gran.no","grane.no","granvin.no","gratangen.no","grimstad.no","grong.no","kraanghke.no","kråanghke.no","grue.no","gulen.no","hadsel.no","halden.no","halsa.no","hamar.no","hamaroy.no","habmer.no","hábmer.no","hapmir.no","hápmir.no","hammerfest.no","hammarfeasta.no","hámmárfeasta.no","haram.no","hareid.no","harstad.no","hasvik.no","aknoluokta.no","ákŋoluokta.no","hattfjelldal.no","aarborte.no","haugesund.no","hemne.no","hemnes.no","hemsedal.no","heroy.more-og-romsdal.no","herøy.møre-og-romsdal.no","heroy.nordland.no","herøy.nordland.no","hitra.no","hjartdal.no","hjelmeland.no","hobol.no","hobøl.no","hof.no","hol.no","hole.no","holmestrand.no","holtalen.no","holtålen.no","hornindal.no","horten.no","hurdal.no","hurum.no","hvaler.no","hyllestad.no","hagebostad.no","hægebostad.no","hoyanger.no","høyanger.no","hoylandet.no","høylandet.no","ha.no","hå.no","ibestad.no","inderoy.no","inderøy.no","iveland.no","jevnaker.no","jondal.no","jolster.no","jølster.no","karasjok.no","karasjohka.no","kárášjohka.no","karlsoy.no","galsa.no","gálsá.no","karmoy.no","karmøy.no","kautokeino.no","guovdageaidnu.no","klepp.no","klabu.no","klæbu.no","kongsberg.no","kongsvinger.no","kragero.no","kragerø.no","kristiansand.no","kristiansund.no","krodsherad.no","krødsherad.no","kvalsund.no","rahkkeravju.no","ráhkkerávju.no","kvam.no","kvinesdal.no","kvinnherad.no","kviteseid.no","kvitsoy.no","kvitsøy.no","kvafjord.no","kvæfjord.no","giehtavuoatna.no","kvanangen.no","kvænangen.no","navuotna.no","návuotna.no","kafjord.no","kåfjord.no","gaivuotna.no","gáivuotna.no","larvik.no","lavangen.no","lavagis.no","loabat.no","loabát.no","lebesby.no","davvesiida.no","leikanger.no","leirfjord.no","leka.no","leksvik.no","lenvik.no","leangaviika.no","leaŋgaviika.no","lesja.no","levanger.no","lier.no","lierne.no","lillehammer.no","lillesand.no","lindesnes.no","lindas.no","lindås.no","lom.no","loppa.no","lahppi.no","láhppi.no","lund.no","lunner.no","luroy.no","lurøy.no","luster.no","lyngdal.no","lyngen.no","ivgu.no","lardal.no","lerdal.no","lærdal.no","lodingen.no","lødingen.no","lorenskog.no","lørenskog.no","loten.no","løten.no","malvik.no","masoy.no","måsøy.no","muosat.no","muosát.no","mandal.no","marker.no","marnardal.no","masfjorden.no","meland.no","meldal.no","melhus.no","meloy.no","meløy.no","meraker.no","meråker.no","moareke.no","moåreke.no","midsund.no","midtre-gauldal.no","modalen.no","modum.no","molde.no","moskenes.no","moss.no","mosvik.no","malselv.no","målselv.no","malatvuopmi.no","málatvuopmi.no","namdalseid.no","aejrie.no","namsos.no","namsskogan.no","naamesjevuemie.no","nååmesjevuemie.no","laakesvuemie.no","nannestad.no","narvik.no","narviika.no","naustdal.no","nedre-eiker.no","nes.akershus.no","nes.buskerud.no","nesna.no","nesodden.no","nesseby.no","unjarga.no","unjárga.no","nesset.no","nissedal.no","nittedal.no","nord-aurdal.no","nord-fron.no","nord-odal.no","norddal.no","nordkapp.no","davvenjarga.no","davvenjárga.no","nordre-land.no","nordreisa.no","raisa.no","ráisa.no","nore-og-uvdal.no","notodden.no","naroy.no","nærøy.no","notteroy.no","nøtterøy.no","odda.no","oksnes.no","øksnes.no","oppdal.no","oppegard.no","oppegård.no","orkdal.no","orland.no","ørland.no","orskog.no","ørskog.no","orsta.no","ørsta.no","os.hedmark.no","os.hordaland.no","osen.no","osteroy.no","osterøy.no","ostre-toten.no","østre-toten.no","overhalla.no","ovre-eiker.no","øvre-eiker.no","oyer.no","øyer.no","oygarden.no","øygarden.no","oystre-slidre.no","øystre-slidre.no","porsanger.no","porsangu.no","porsáŋgu.no","porsgrunn.no","radoy.no","radøy.no","rakkestad.no","rana.no","ruovat.no","randaberg.no","rauma.no","rendalen.no","rennebu.no","rennesoy.no","rennesøy.no","rindal.no","ringebu.no","ringerike.no","ringsaker.no","rissa.no","risor.no","risør.no","roan.no","rollag.no","rygge.no","ralingen.no","rælingen.no","rodoy.no","rødøy.no","romskog.no","rømskog.no","roros.no","røros.no","rost.no","røst.no","royken.no","røyken.no","royrvik.no","røyrvik.no","rade.no","råde.no","salangen.no","siellak.no","saltdal.no","salat.no","sálát.no","sálat.no","samnanger.no","sande.more-og-romsdal.no","sande.møre-og-romsdal.no","sande.vestfold.no","sandefjord.no","sandnes.no","sandoy.no","sandøy.no","sarpsborg.no","sauda.no","sauherad.no","sel.no","selbu.no","selje.no","seljord.no","sigdal.no","siljan.no","sirdal.no","skaun.no","skedsmo.no","ski.no","skien.no","skiptvet.no","skjervoy.no","skjervøy.no","skierva.no","skiervá.no","skjak.no","skjåk.no","skodje.no","skanland.no","skånland.no","skanit.no","skánit.no","smola.no","smøla.no","snillfjord.no","snasa.no","snåsa.no","snoasa.no","snaase.no","snåase.no","sogndal.no","sokndal.no","sola.no","solund.no","songdalen.no","sortland.no","spydeberg.no","stange.no","stavanger.no","steigen.no","steinkjer.no","stjordal.no","stjørdal.no","stokke.no","stor-elvdal.no","stord.no","stordal.no","storfjord.no","omasvuotna.no","strand.no","stranda.no","stryn.no","sula.no","suldal.no","sund.no","sunndal.no","surnadal.no","sveio.no","svelvik.no","sykkylven.no","sogne.no","søgne.no","somna.no","sømna.no","sondre-land.no","søndre-land.no","sor-aurdal.no","sør-aurdal.no","sor-fron.no","sør-fron.no","sor-odal.no","sør-odal.no","sor-varanger.no","sør-varanger.no","matta-varjjat.no","mátta-várjjat.no","sorfold.no","sørfold.no","sorreisa.no","sørreisa.no","sorum.no","sørum.no","tana.no","deatnu.no","time.no","tingvoll.no","tinn.no","tjeldsund.no","dielddanuorri.no","tjome.no","tjøme.no","tokke.no","tolga.no","torsken.no","tranoy.no","tranøy.no","tromso.no","tromsø.no","tromsa.no","romsa.no","trondheim.no","troandin.no","trysil.no","trana.no","træna.no","trogstad.no","trøgstad.no","tvedestrand.no","tydal.no","tynset.no","tysfjord.no","divtasvuodna.no","divttasvuotna.no","tysnes.no","tysvar.no","tysvær.no","tonsberg.no","tønsberg.no","ullensaker.no","ullensvang.no","ulvik.no","utsira.no","vadso.no","vadsø.no","cahcesuolo.no","čáhcesuolo.no","vaksdal.no","valle.no","vang.no","vanylven.no","vardo.no","vardø.no","varggat.no","várggát.no","vefsn.no","vaapste.no","vega.no","vegarshei.no","vegårshei.no","vennesla.no","verdal.no","verran.no","vestby.no","vestnes.no","vestre-slidre.no","vestre-toten.no","vestvagoy.no","vestvågøy.no","vevelstad.no","vik.no","vikna.no","vindafjord.no","volda.no","voss.no","varoy.no","værøy.no","vagan.no","vågan.no","voagat.no","vagsoy.no","vågsøy.no","vaga.no","vågå.no","valer.ostfold.no","våler.østfold.no","valer.hedmark.no","våler.hedmark.no","*.np","nr","biz.nr","info.nr","gov.nr","edu.nr","org.nr","net.nr","com.nr","nu","nz","ac.nz","co.nz","cri.nz","geek.nz","gen.nz","govt.nz","health.nz","iwi.nz","kiwi.nz","maori.nz","mil.nz","māori.nz","net.nz","org.nz","parliament.nz","school.nz","om","co.om","com.om","edu.om","gov.om","med.om","museum.om","net.om","org.om","pro.om","onion","org","pa","ac.pa","gob.pa","com.pa","org.pa","sld.pa","edu.pa","net.pa","ing.pa","abo.pa","med.pa","nom.pa","pe","edu.pe","gob.pe","nom.pe","mil.pe","org.pe","com.pe","net.pe","pf","com.pf","org.pf","edu.pf","*.pg","ph","com.ph","net.ph","org.ph","gov.ph","edu.ph","ngo.ph","mil.ph","i.ph","pk","com.pk","net.pk","edu.pk","org.pk","fam.pk","biz.pk","web.pk","gov.pk","gob.pk","gok.pk","gon.pk","gop.pk","gos.pk","info.pk","pl","com.pl","net.pl","org.pl","aid.pl","agro.pl","atm.pl","auto.pl","biz.pl","edu.pl","gmina.pl","gsm.pl","info.pl","mail.pl","miasta.pl","media.pl","mil.pl","nieruchomosci.pl","nom.pl","pc.pl","powiat.pl","priv.pl","realestate.pl","rel.pl","sex.pl","shop.pl","sklep.pl","sos.pl","szkola.pl","targi.pl","tm.pl","tourism.pl","travel.pl","turystyka.pl","gov.pl","ap.gov.pl","ic.gov.pl","is.gov.pl","us.gov.pl","kmpsp.gov.pl","kppsp.gov.pl","kwpsp.gov.pl","psp.gov.pl","wskr.gov.pl","kwp.gov.pl","mw.gov.pl","ug.gov.pl","um.gov.pl","umig.gov.pl","ugim.gov.pl","upow.gov.pl","uw.gov.pl","starostwo.gov.pl","pa.gov.pl","po.gov.pl","psse.gov.pl","pup.gov.pl","rzgw.gov.pl","sa.gov.pl","so.gov.pl","sr.gov.pl","wsa.gov.pl","sko.gov.pl","uzs.gov.pl","wiih.gov.pl","winb.gov.pl","pinb.gov.pl","wios.gov.pl","witd.gov.pl","wzmiuw.gov.pl","piw.gov.pl","wiw.gov.pl","griw.gov.pl","wif.gov.pl","oum.gov.pl","sdn.gov.pl","zp.gov.pl","uppo.gov.pl","mup.gov.pl","wuoz.gov.pl","konsulat.gov.pl","oirm.gov.pl","augustow.pl","babia-gora.pl","bedzin.pl","beskidy.pl","bialowieza.pl","bialystok.pl","bielawa.pl","bieszczady.pl","boleslawiec.pl","bydgoszcz.pl","bytom.pl","cieszyn.pl","czeladz.pl","czest.pl","dlugoleka.pl","elblag.pl","elk.pl","glogow.pl","gniezno.pl","gorlice.pl","grajewo.pl","ilawa.pl","jaworzno.pl","jelenia-gora.pl","jgora.pl","kalisz.pl","kazimierz-dolny.pl","karpacz.pl","kartuzy.pl","kaszuby.pl","katowice.pl","kepno.pl","ketrzyn.pl","klodzko.pl","kobierzyce.pl","kolobrzeg.pl","konin.pl","konskowola.pl","kutno.pl","lapy.pl","lebork.pl","legnica.pl","lezajsk.pl","limanowa.pl","lomza.pl","lowicz.pl","lubin.pl","lukow.pl","malbork.pl","malopolska.pl","mazowsze.pl","mazury.pl","mielec.pl","mielno.pl","mragowo.pl","naklo.pl","nowaruda.pl","nysa.pl","olawa.pl","olecko.pl","olkusz.pl","olsztyn.pl","opoczno.pl","opole.pl","ostroda.pl","ostroleka.pl","ostrowiec.pl","ostrowwlkp.pl","pila.pl","pisz.pl","podhale.pl","podlasie.pl","polkowice.pl","pomorze.pl","pomorskie.pl","prochowice.pl","pruszkow.pl","przeworsk.pl","pulawy.pl","radom.pl","rawa-maz.pl","rybnik.pl","rzeszow.pl","sanok.pl","sejny.pl","slask.pl","slupsk.pl","sosnowiec.pl","stalowa-wola.pl","skoczow.pl","starachowice.pl","stargard.pl","suwalki.pl","swidnica.pl","swiebodzin.pl","swinoujscie.pl","szczecin.pl","szczytno.pl","tarnobrzeg.pl","tgory.pl","turek.pl","tychy.pl","ustka.pl","walbrzych.pl","warmia.pl","warszawa.pl","waw.pl","wegrow.pl","wielun.pl","wlocl.pl","wloclawek.pl","wodzislaw.pl","wolomin.pl","wroclaw.pl","zachpomor.pl","zagan.pl","zarow.pl","zgora.pl","zgorzelec.pl","pm","pn","gov.pn","co.pn","org.pn","edu.pn","net.pn","post","pr","com.pr","net.pr","org.pr","gov.pr","edu.pr","isla.pr","pro.pr","biz.pr","info.pr","name.pr","est.pr","prof.pr","ac.pr","pro","aaa.pro","aca.pro","acct.pro","avocat.pro","bar.pro","cpa.pro","eng.pro","jur.pro","law.pro","med.pro","recht.pro","ps","edu.ps","gov.ps","sec.ps","plo.ps","com.ps","org.ps","net.ps","pt","net.pt","gov.pt","org.pt","edu.pt","int.pt","publ.pt","com.pt","nome.pt","pw","co.pw","ne.pw","or.pw","ed.pw","go.pw","belau.pw","py","com.py","coop.py","edu.py","gov.py","mil.py","net.py","org.py","qa","com.qa","edu.qa","gov.qa","mil.qa","name.qa","net.qa","org.qa","sch.qa","re","asso.re","com.re","nom.re","ro","arts.ro","com.ro","firm.ro","info.ro","nom.ro","nt.ro","org.ro","rec.ro","store.ro","tm.ro","www.ro","rs","ac.rs","co.rs","edu.rs","gov.rs","in.rs","org.rs","ru","ac.ru","edu.ru","gov.ru","int.ru","mil.ru","test.ru","rw","gov.rw","net.rw","edu.rw","ac.rw","com.rw","co.rw","int.rw","mil.rw","gouv.rw","sa","com.sa","net.sa","org.sa","gov.sa","med.sa","pub.sa","edu.sa","sch.sa","sb","com.sb","edu.sb","gov.sb","net.sb","org.sb","sc","com.sc","gov.sc","net.sc","org.sc","edu.sc","sd","com.sd","net.sd","org.sd","edu.sd","med.sd","tv.sd","gov.sd","info.sd","se","a.se","ac.se","b.se","bd.se","brand.se","c.se","d.se","e.se","f.se","fh.se","fhsk.se","fhv.se","g.se","h.se","i.se","k.se","komforb.se","kommunalforbund.se","komvux.se","l.se","lanbib.se","m.se","n.se","naturbruksgymn.se","o.se","org.se","p.se","parti.se","pp.se","press.se","r.se","s.se","t.se","tm.se","u.se","w.se","x.se","y.se","z.se","sg","com.sg","net.sg","org.sg","gov.sg","edu.sg","per.sg","sh","com.sh","net.sh","gov.sh","org.sh","mil.sh","si","sj","sk","sl","com.sl","net.sl","edu.sl","gov.sl","org.sl","sm","sn","art.sn","com.sn","edu.sn","gouv.sn","org.sn","perso.sn","univ.sn","so","com.so","net.so","org.so","sr","st","co.st","com.st","consulado.st","edu.st","embaixada.st","gov.st","mil.st","net.st","org.st","principe.st","saotome.st","store.st","su","sv","com.sv","edu.sv","gob.sv","org.sv","red.sv","sx","gov.sx","sy","edu.sy","gov.sy","net.sy","mil.sy","com.sy","org.sy","sz","co.sz","ac.sz","org.sz","tc","td","tel","tf","tg","th","ac.th","co.th","go.th","in.th","mi.th","net.th","or.th","tj","ac.tj","biz.tj","co.tj","com.tj","edu.tj","go.tj","gov.tj","int.tj","mil.tj","name.tj","net.tj","nic.tj","org.tj","test.tj","web.tj","tk","tl","gov.tl","tm","com.tm","co.tm","org.tm","net.tm","nom.tm","gov.tm","mil.tm","edu.tm","tn","com.tn","ens.tn","fin.tn","gov.tn","ind.tn","intl.tn","nat.tn","net.tn","org.tn","info.tn","perso.tn","tourism.tn","edunet.tn","rnrt.tn","rns.tn","rnu.tn","mincom.tn","agrinet.tn","defense.tn","turen.tn","to","com.to","gov.to","net.to","org.to","edu.to","mil.to","tr","com.tr","info.tr","biz.tr","net.tr","org.tr","web.tr","gen.tr","tv.tr","av.tr","dr.tr","bbs.tr","name.tr","tel.tr","gov.tr","bel.tr","pol.tr","mil.tr","k12.tr","edu.tr","kep.tr","nc.tr","gov.nc.tr","tt","co.tt","com.tt","org.tt","net.tt","biz.tt","info.tt","pro.tt","int.tt","coop.tt","jobs.tt","mobi.tt","travel.tt","museum.tt","aero.tt","name.tt","gov.tt","edu.tt","tv","tw","edu.tw","gov.tw","mil.tw","com.tw","net.tw","org.tw","idv.tw","game.tw","ebiz.tw","club.tw","網路.tw","組織.tw","商業.tw","tz","ac.tz","co.tz","go.tz","hotel.tz","info.tz","me.tz","mil.tz","mobi.tz","ne.tz","or.tz","sc.tz","tv.tz","ua","com.ua","edu.ua","gov.ua","in.ua","net.ua","org.ua","cherkassy.ua","cherkasy.ua","chernigov.ua","chernihiv.ua","chernivtsi.ua","chernovtsy.ua","ck.ua","cn.ua","cr.ua","crimea.ua","cv.ua","dn.ua","dnepropetrovsk.ua","dnipropetrovsk.ua","dominic.ua","donetsk.ua","dp.ua","if.ua","ivano-frankivsk.ua","kh.ua","kharkiv.ua","kharkov.ua","kherson.ua","khmelnitskiy.ua","khmelnytskyi.ua","kiev.ua","kirovograd.ua","km.ua","kr.ua","krym.ua","ks.ua","kv.ua","kyiv.ua","lg.ua","lt.ua","lugansk.ua","lutsk.ua","lv.ua","lviv.ua","mk.ua","mykolaiv.ua","nikolaev.ua","od.ua","odesa.ua","odessa.ua","pl.ua","poltava.ua","rivne.ua","rovno.ua","rv.ua","sb.ua","sebastopol.ua","sevastopol.ua","sm.ua","sumy.ua","te.ua","ternopil.ua","uz.ua","uzhgorod.ua","vinnica.ua","vinnytsia.ua","vn.ua","volyn.ua","yalta.ua","zaporizhzhe.ua","zaporizhzhia.ua","zhitomir.ua","zhytomyr.ua","zp.ua","zt.ua","ug","co.ug","or.ug","ac.ug","sc.ug","go.ug","ne.ug","com.ug","org.ug","uk","ac.uk","co.uk","gov.uk","ltd.uk","me.uk","net.uk","nhs.uk","org.uk","plc.uk","police.uk","*.sch.uk","us","dni.us","fed.us","isa.us","kids.us","nsn.us","ak.us","al.us","ar.us","as.us","az.us","ca.us","co.us","ct.us","dc.us","de.us","fl.us","ga.us","gu.us","hi.us","ia.us","id.us","il.us","in.us","ks.us","ky.us","la.us","ma.us","md.us","me.us","mi.us","mn.us","mo.us","ms.us","mt.us","nc.us","nd.us","ne.us","nh.us","nj.us","nm.us","nv.us","ny.us","oh.us","ok.us","or.us","pa.us","pr.us","ri.us","sc.us","sd.us","tn.us","tx.us","ut.us","vi.us","vt.us","va.us","wa.us","wi.us","wv.us","wy.us","k12.ak.us","k12.al.us","k12.ar.us","k12.as.us","k12.az.us","k12.ca.us","k12.co.us","k12.ct.us","k12.dc.us","k12.de.us","k12.fl.us","k12.ga.us","k12.gu.us","k12.ia.us","k12.id.us","k12.il.us","k12.in.us","k12.ks.us","k12.ky.us","k12.la.us","k12.ma.us","k12.md.us","k12.me.us","k12.mi.us","k12.mn.us","k12.mo.us","k12.ms.us","k12.mt.us","k12.nc.us","k12.ne.us","k12.nh.us","k12.nj.us","k12.nm.us","k12.nv.us","k12.ny.us","k12.oh.us","k12.ok.us","k12.or.us","k12.pa.us","k12.pr.us","k12.ri.us","k12.sc.us","k12.tn.us","k12.tx.us","k12.ut.us","k12.vi.us","k12.vt.us","k12.va.us","k12.wa.us","k12.wi.us","k12.wy.us","cc.ak.us","cc.al.us","cc.ar.us","cc.as.us","cc.az.us","cc.ca.us","cc.co.us","cc.ct.us","cc.dc.us","cc.de.us","cc.fl.us","cc.ga.us","cc.gu.us","cc.hi.us","cc.ia.us","cc.id.us","cc.il.us","cc.in.us","cc.ks.us","cc.ky.us","cc.la.us","cc.ma.us","cc.md.us","cc.me.us","cc.mi.us","cc.mn.us","cc.mo.us","cc.ms.us","cc.mt.us","cc.nc.us","cc.nd.us","cc.ne.us","cc.nh.us","cc.nj.us","cc.nm.us","cc.nv.us","cc.ny.us","cc.oh.us","cc.ok.us","cc.or.us","cc.pa.us","cc.pr.us","cc.ri.us","cc.sc.us","cc.sd.us","cc.tn.us","cc.tx.us","cc.ut.us","cc.vi.us","cc.vt.us","cc.va.us","cc.wa.us","cc.wi.us","cc.wv.us","cc.wy.us","lib.ak.us","lib.al.us","lib.ar.us","lib.as.us","lib.az.us","lib.ca.us","lib.co.us","lib.ct.us","lib.dc.us","lib.fl.us","lib.ga.us","lib.gu.us","lib.hi.us","lib.ia.us","lib.id.us","lib.il.us","lib.in.us","lib.ks.us","lib.ky.us","lib.la.us","lib.ma.us","lib.md.us","lib.me.us","lib.mi.us","lib.mn.us","lib.mo.us","lib.ms.us","lib.mt.us","lib.nc.us","lib.nd.us","lib.ne.us","lib.nh.us","lib.nj.us","lib.nm.us","lib.nv.us","lib.ny.us","lib.oh.us","lib.ok.us","lib.or.us","lib.pa.us","lib.pr.us","lib.ri.us","lib.sc.us","lib.sd.us","lib.tn.us","lib.tx.us","lib.ut.us","lib.vi.us","lib.vt.us","lib.va.us","lib.wa.us","lib.wi.us","lib.wy.us","pvt.k12.ma.us","chtr.k12.ma.us","paroch.k12.ma.us","ann-arbor.mi.us","cog.mi.us","dst.mi.us","eaton.mi.us","gen.mi.us","mus.mi.us","tec.mi.us","washtenaw.mi.us","uy","com.uy","edu.uy","gub.uy","mil.uy","net.uy","org.uy","uz","co.uz","com.uz","net.uz","org.uz","va","vc","com.vc","net.vc","org.vc","gov.vc","mil.vc","edu.vc","ve","arts.ve","co.ve","com.ve","e12.ve","edu.ve","firm.ve","gob.ve","gov.ve","info.ve","int.ve","mil.ve","net.ve","org.ve","rec.ve","store.ve","tec.ve","web.ve","vg","vi","co.vi","com.vi","k12.vi","net.vi","org.vi","vn","com.vn","net.vn","org.vn","edu.vn","gov.vn","int.vn","ac.vn","biz.vn","info.vn","name.vn","pro.vn","health.vn","vu","com.vu","edu.vu","net.vu","org.vu","wf","ws","com.ws","net.ws","org.ws","gov.ws","edu.ws","yt","امارات","հայ","বাংলা","бг","бел","中国","中國","الجزائر","مصر","ею","გე","ελ","香港","公司.香港","教育.香港","政府.香港","個人.香港","網絡.香港","組織.香港","ಭಾರತ","ଭାରତ","ভাৰত","भारतम्","भारोत","ڀارت","ഭാരതം","भारत","بارت","بھارت","భారత్","ભારત","ਭਾਰਤ","ভারত","இந்தியா","ایران","ايران","عراق","الاردن","한국","қаз","ලංකා","இலங்கை","المغرب","мкд","мон","澳門","澳门","مليسيا","عمان","پاکستان","پاكستان","فلسطين","срб","пр.срб","орг.срб","обр.срб","од.срб","упр.срб","ак.срб","рф","قطر","السعودية","السعودیة","السعودیۃ","السعوديه","سودان","新加坡","சிங்கப்பூர்","سورية","سوريا","ไทย","ศึกษา.ไทย","ธุรกิจ.ไทย","รัฐบาล.ไทย","ทหาร.ไทย","เน็ต.ไทย","องค์กร.ไทย","تونس","台灣","台湾","臺灣","укр","اليمن","xxx","*.ye","ac.za","agric.za","alt.za","co.za","edu.za","gov.za","grondar.za","law.za","mil.za","net.za","ngo.za","nis.za","nom.za","org.za","school.za","tm.za","web.za","zm","ac.zm","biz.zm","co.zm","com.zm","edu.zm","gov.zm","info.zm","mil.zm","net.zm","org.zm","sch.zm","zw","ac.zw","co.zw","gov.zw","mil.zw","org.zw","aaa","aarp","abarth","abb","abbott","abbvie","abc","able","abogado","abudhabi","academy","accenture","accountant","accountants","aco","active","actor","adac","ads","adult","aeg","aetna","afamilycompany","afl","africa","agakhan","agency","aig","aigo","airbus","airforce","airtel","akdn","alfaromeo","alibaba","alipay","allfinanz","allstate","ally","alsace","alstom","americanexpress","americanfamily","amex","amfam","amica","amsterdam","analytics","android","anquan","anz","aol","apartments","app","apple","aquarelle","arab","aramco","archi","army","art","arte","asda","associates","athleta","attorney","auction","audi","audible","audio","auspost","author","auto","autos","avianca","aws","axa","azure","baby","baidu","banamex","bananarepublic","band","bank","bar","barcelona","barclaycard","barclays","barefoot","bargains","baseball","basketball","bauhaus","bayern","bbc","bbt","bbva","bcg","bcn","beats","beauty","beer","bentley","berlin","best","bestbuy","bet","bharti","bible","bid","bike","bing","bingo","bio","black","blackfriday","blanco","blockbuster","blog","bloomberg","blue","bms","bmw","bnl","bnpparibas","boats","boehringer","bofa","bom","bond","boo","book","booking","bosch","bostik","boston","bot","boutique","box","bradesco","bridgestone","broadway","broker","brother","brussels","budapest","bugatti","build","builders","business","buy","buzz","bzh","cab","cafe","cal","call","calvinklein","cam","camera","camp","cancerresearch","canon","capetown","capital","capitalone","car","caravan","cards","care","career","careers","cars","cartier","casa","case","caseih","cash","casino","catering","catholic","cba","cbn","cbre","cbs","ceb","center","ceo","cern","cfa","cfd","chanel","channel","charity","chase","chat","cheap","chintai","christmas","chrome","chrysler","church","cipriani","circle","cisco","citadel","citi","citic","city","cityeats","claims","cleaning","click","clinic","clinique","clothing","cloud","club","clubmed","coach","codes","coffee","college","cologne","comcast","commbank","community","company","compare","computer","comsec","condos","construction","consulting","contact","contractors","cooking","cookingchannel","cool","corsica","country","coupon","coupons","courses","credit","creditcard","creditunion","cricket","crown","crs","cruise","cruises","csc","cuisinella","cymru","cyou","dabur","dad","dance","data","date","dating","datsun","day","dclk","dds","deal","dealer","deals","degree","delivery","dell","deloitte","delta","democrat","dental","dentist","desi","design","dev","dhl","diamonds","diet","digital","direct","directory","discount","discover","dish","diy","dnp","docs","doctor","dodge","dog","doha","domains","dot","download","drive","dtv","dubai","duck","dunlop","duns","dupont","durban","dvag","dvr","earth","eat","eco","edeka","education","email","emerck","energy","engineer","engineering","enterprises","epost","epson","equipment","ericsson","erni","esq","estate","esurance","etisalat","eurovision","eus","events","everbank","exchange","expert","exposed","express","extraspace","fage","fail","fairwinds","faith","family","fan","fans","farm","farmers","fashion","fast","fedex","feedback","ferrari","ferrero","fiat","fidelity","fido","film","final","finance","financial","fire","firestone","firmdale","fish","fishing","fit","fitness","flickr","flights","flir","florist","flowers","fly","foo","food","foodnetwork","football","ford","forex","forsale","forum","foundation","fox","free","fresenius","frl","frogans","frontdoor","frontier","ftr","fujitsu","fujixerox","fun","fund","furniture","futbol","fyi","gal","gallery","gallo","gallup","game","games","gap","garden","gbiz","gdn","gea","gent","genting","george","ggee","gift","gifts","gives","giving","glade","glass","gle","global","globo","gmail","gmbh","gmo","gmx","godaddy","gold","goldpoint","golf","goo","goodhands","goodyear","goog","google","gop","got","grainger","graphics","gratis","green","gripe","grocery","group","guardian","gucci","guge","guide","guitars","guru","hair","hamburg","hangout","haus","hbo","hdfc","hdfcbank","health","healthcare","help","helsinki","here","hermes","hgtv","hiphop","hisamitsu","hitachi","hiv","hkt","hockey","holdings","holiday","homedepot","homegoods","homes","homesense","honda","honeywell","horse","hospital","host","hosting","hot","hoteles","hotels","hotmail","house","how","hsbc","hughes","hyatt","hyundai","ibm","icbc","ice","icu","ieee","ifm","ikano","imamat","imdb","immo","immobilien","inc","industries","infiniti","ing","ink","institute","insurance","insure","intel","international","intuit","investments","ipiranga","irish","iselect","ismaili","ist","istanbul","itau","itv","iveco","jaguar","java","jcb","jcp","jeep","jetzt","jewelry","jio","jlc","jll","jmp","jnj","joburg","jot","joy","jpmorgan","jprs","juegos","juniper","kaufen","kddi","kerryhotels","kerrylogistics","kerryproperties","kfh","kia","kim","kinder","kindle","kitchen","kiwi","koeln","komatsu","kosher","kpmg","kpn","krd","kred","kuokgroup","kyoto","lacaixa","ladbrokes","lamborghini","lamer","lancaster","lancia","lancome","land","landrover","lanxess","lasalle","lat","latino","latrobe","law","lawyer","lds","lease","leclerc","lefrak","legal","lego","lexus","lgbt","liaison","lidl","life","lifeinsurance","lifestyle","lighting","like","lilly","limited","limo","lincoln","linde","link","lipsy","live","living","lixil","llc","loan","loans","locker","locus","loft","lol","london","lotte","lotto","love","lpl","lplfinancial","ltd","ltda","lundbeck","lupin","luxe","luxury","macys","madrid","maif","maison","makeup","man","management","mango","map","market","marketing","markets","marriott","marshalls","maserati","mattel","mba","mckinsey","med","media","meet","melbourne","meme","memorial","men","menu","merckmsd","metlife","miami","microsoft","mini","mint","mit","mitsubishi","mlb","mls","mma","mobile","mobily","moda","moe","moi","mom","monash","money","monster","mopar","mormon","mortgage","moscow","moto","motorcycles","mov","movie","movistar","msd","mtn","mtr","mutual","nab","nadex","nagoya","nationwide","natura","navy","nba","nec","netbank","netflix","network","neustar","new","newholland","news","next","nextdirect","nexus","nfl","ngo","nhk","nico","nike","nikon","ninja","nissan","nissay","nokia","northwesternmutual","norton","now","nowruz","nowtv","nra","nrw","ntt","nyc","obi","observer","off","office","okinawa","olayan","olayangroup","oldnavy","ollo","omega","one","ong","onl","online","onyourside","ooo","open","oracle","orange","organic","origins","osaka","otsuka","ott","ovh","page","panasonic","panerai","paris","pars","partners","parts","party","passagens","pay","pccw","pet","pfizer","pharmacy","phd","philips","phone","photo","photography","photos","physio","piaget","pics","pictet","pictures","pid","pin","ping","pink","pioneer","pizza","place","play","playstation","plumbing","plus","pnc","pohl","poker","politie","porn","pramerica","praxi","press","prime","prod","productions","prof","progressive","promo","properties","property","protection","pru","prudential","pub","pwc","qpon","quebec","quest","qvc","racing","radio","raid","read","realestate","realtor","realty","recipes","red","redstone","redumbrella","rehab","reise","reisen","reit","reliance","ren","rent","rentals","repair","report","republican","rest","restaurant","review","reviews","rexroth","rich","richardli","ricoh","rightathome","ril","rio","rip","rmit","rocher","rocks","rodeo","rogers","room","rsvp","rugby","ruhr","run","rwe","ryukyu","saarland","safe","safety","sakura","sale","salon","samsclub","samsung","sandvik","sandvikcoromant","sanofi","sap","sarl","sas","save","saxo","sbi","sbs","sca","scb","schaeffler","schmidt","scholarships","school","schule","schwarz","science","scjohnson","scor","scot","search","seat","secure","security","seek","select","sener","services","ses","seven","sew","sex","sexy","sfr","shangrila","sharp","shaw","shell","shia","shiksha","shoes","shop","shopping","shouji","show","showtime","shriram","silk","sina","singles","site","ski","skin","sky","skype","sling","smart","smile","sncf","soccer","social","softbank","software","sohu","solar","solutions","song","sony","soy","space","spiegel","sport","spot","spreadbetting","srl","srt","stada","staples","star","starhub","statebank","statefarm","statoil","stc","stcgroup","stockholm","storage","store","stream","studio","study","style","sucks","supplies","supply","support","surf","surgery","suzuki","swatch","swiftcover","swiss","sydney","symantec","systems","tab","taipei","talk","taobao","target","tatamotors","tatar","tattoo","tax","taxi","tci","tdk","team","tech","technology","telecity","telefonica","temasek","tennis","teva","thd","theater","theatre","tiaa","tickets","tienda","tiffany","tips","tires","tirol","tjmaxx","tjx","tkmaxx","tmall","today","tokyo","tools","top","toray","toshiba","total","tours","town","toyota","toys","trade","trading","training","travel","travelchannel","travelers","travelersinsurance","trust","trv","tube","tui","tunes","tushu","tvs","ubank","ubs","uconnect","unicom","university","uno","uol","ups","vacations","vana","vanguard","vegas","ventures","verisign","versicherung","vet","viajes","video","vig","viking","villas","vin","vip","virgin","visa","vision","vista","vistaprint","viva","vivo","vlaanderen","vodka","volkswagen","volvo","vote","voting","voto","voyage","vuelos","wales","walmart","walter","wang","wanggou","warman","watch","watches","weather","weatherchannel","webcam","weber","website","wed","wedding","weibo","weir","whoswho","wien","wiki","williamhill","win","windows","wine","winners","wme","wolterskluwer","woodside","work","works","world","wow","wtc","wtf","xbox","xerox","xfinity","xihuan","xin","कॉम","セール","佛山","慈善","集团","在线","大众汽车","点看","คอม","八卦","موقع","公益","公司","香格里拉","网站","移动","我爱你","москва","католик","онлайн","сайт","联通","קום","时尚","微博","淡马锡","ファッション","орг","नेट","ストア","삼성","商标","商店","商城","дети","ポイント","新闻","工行","家電","كوم","中文网","中信","娱乐","谷歌","電訊盈科","购物","クラウド","通販","网店","संगठन","餐厅","网络","ком","诺基亚","食品","飞利浦","手表","手机","ارامكو","العليان","اتصالات","بازار","موبايلي","ابوظبي","كاثوليك","همراه","닷컴","政府","شبكة","بيتك","عرب","机构","组织机构","健康","招聘","рус","珠宝","大拿","みんな","グーグル","世界","書籍","网址","닷넷","コム","天主教","游戏","vermögensberater","vermögensberatung","企业","信息","嘉里大酒店","嘉里","广东","政务","xyz","yachts","yahoo","yamaxun","yandex","yodobashi","yoga","yokohama","you","youtube","yun","zappos","zara","zero","zip","zippo","zone","zuerich","cc.ua","inf.ua","ltd.ua","beep.pl","*.compute.estate","*.alces.network","alwaysdata.net","cloudfront.net","*.compute.amazonaws.com","*.compute-1.amazonaws.com","*.compute.amazonaws.com.cn","us-east-1.amazonaws.com","cn-north-1.eb.amazonaws.com.cn","elasticbeanstalk.com","ap-northeast-1.elasticbeanstalk.com","ap-northeast-2.elasticbeanstalk.com","ap-northeast-3.elasticbeanstalk.com","ap-south-1.elasticbeanstalk.com","ap-southeast-1.elasticbeanstalk.com","ap-southeast-2.elasticbeanstalk.com","ca-central-1.elasticbeanstalk.com","eu-central-1.elasticbeanstalk.com","eu-west-1.elasticbeanstalk.com","eu-west-2.elasticbeanstalk.com","eu-west-3.elasticbeanstalk.com","sa-east-1.elasticbeanstalk.com","us-east-1.elasticbeanstalk.com","us-east-2.elasticbeanstalk.com","us-gov-west-1.elasticbeanstalk.com","us-west-1.elasticbeanstalk.com","us-west-2.elasticbeanstalk.com","*.elb.amazonaws.com","*.elb.amazonaws.com.cn","s3.amazonaws.com","s3-ap-northeast-1.amazonaws.com","s3-ap-northeast-2.amazonaws.com","s3-ap-south-1.amazonaws.com","s3-ap-southeast-1.amazonaws.com","s3-ap-southeast-2.amazonaws.com","s3-ca-central-1.amazonaws.com","s3-eu-central-1.amazonaws.com","s3-eu-west-1.amazonaws.com","s3-eu-west-2.amazonaws.com","s3-eu-west-3.amazonaws.com","s3-external-1.amazonaws.com","s3-fips-us-gov-west-1.amazonaws.com","s3-sa-east-1.amazonaws.com","s3-us-gov-west-1.amazonaws.com","s3-us-east-2.amazonaws.com","s3-us-west-1.amazonaws.com","s3-us-west-2.amazonaws.com","s3.ap-northeast-2.amazonaws.com","s3.ap-south-1.amazonaws.com","s3.cn-north-1.amazonaws.com.cn","s3.ca-central-1.amazonaws.com","s3.eu-central-1.amazonaws.com","s3.eu-west-2.amazonaws.com","s3.eu-west-3.amazonaws.com","s3.us-east-2.amazonaws.com","s3.dualstack.ap-northeast-1.amazonaws.com","s3.dualstack.ap-northeast-2.amazonaws.com","s3.dualstack.ap-south-1.amazonaws.com","s3.dualstack.ap-southeast-1.amazonaws.com","s3.dualstack.ap-southeast-2.amazonaws.com","s3.dualstack.ca-central-1.amazonaws.com","s3.dualstack.eu-central-1.amazonaws.com","s3.dualstack.eu-west-1.amazonaws.com","s3.dualstack.eu-west-2.amazonaws.com","s3.dualstack.eu-west-3.amazonaws.com","s3.dualstack.sa-east-1.amazonaws.com","s3.dualstack.us-east-1.amazonaws.com","s3.dualstack.us-east-2.amazonaws.com","s3-website-us-east-1.amazonaws.com","s3-website-us-west-1.amazonaws.com","s3-website-us-west-2.amazonaws.com","s3-website-ap-northeast-1.amazonaws.com","s3-website-ap-southeast-1.amazonaws.com","s3-website-ap-southeast-2.amazonaws.com","s3-website-eu-west-1.amazonaws.com","s3-website-sa-east-1.amazonaws.com","s3-website.ap-northeast-2.amazonaws.com","s3-website.ap-south-1.amazonaws.com","s3-website.ca-central-1.amazonaws.com","s3-website.eu-central-1.amazonaws.com","s3-website.eu-west-2.amazonaws.com","s3-website.eu-west-3.amazonaws.com","s3-website.us-east-2.amazonaws.com","t3l3p0rt.net","tele.amune.org","on-aptible.com","user.party.eus","pimienta.org","poivron.org","potager.org","sweetpepper.org","myasustor.com","myfritz.net","*.awdev.ca","*.advisor.ws","backplaneapp.io","betainabox.com","bnr.la","blackbaudcdn.net","boomla.net","boxfuse.io","square7.ch","bplaced.com","bplaced.de","square7.de","bplaced.net","square7.net","browsersafetymark.io","mycd.eu","ae.org","ar.com","br.com","cn.com","com.de","com.se","de.com","eu.com","gb.com","gb.net","hu.com","hu.net","jp.net","jpn.com","kr.com","mex.com","no.com","qc.com","ru.com","sa.com","se.net","uk.com","uk.net","us.com","uy.com","za.bz","za.com","africa.com","gr.com","in.net","us.org","co.com","c.la","certmgr.org","xenapponazure.com","virtueeldomein.nl","cleverapps.io","c66.me","cloud66.ws","jdevcloud.com","wpdevcloud.com","cloudaccess.host","freesite.host","cloudaccess.net","cloudcontrolled.com","cloudcontrolapp.com","co.ca","*.otap.co","co.cz","c.cdn77.org","cdn77-ssl.net","r.cdn77.net","rsc.cdn77.org","ssl.origin.cdn77-secure.org","cloudns.asia","cloudns.biz","cloudns.club","cloudns.cc","cloudns.eu","cloudns.in","cloudns.info","cloudns.org","cloudns.pro","cloudns.pw","cloudns.us","cloudeity.net","cnpy.gdn","co.nl","co.no","webhosting.be","hosting-cluster.nl","dyn.cosidns.de","dynamisches-dns.de","dnsupdater.de","internet-dns.de","l-o-g-i-n.de","dynamic-dns.info","feste-ip.net","knx-server.net","static-access.net","realm.cz","*.cryptonomic.net","cupcake.is","cyon.link","cyon.site","daplie.me","localhost.daplie.me","dattolocal.com","dattorelay.com","dattoweb.com","mydatto.com","dattolocal.net","mydatto.net","biz.dk","co.dk","firm.dk","reg.dk","store.dk","debian.net","dedyn.io","dnshome.de","drayddns.com","dreamhosters.com","mydrobo.com","drud.io","drud.us","duckdns.org","dy.fi","tunk.org","dyndns-at-home.com","dyndns-at-work.com","dyndns-blog.com","dyndns-free.com","dyndns-home.com","dyndns-ip.com","dyndns-mail.com","dyndns-office.com","dyndns-pics.com","dyndns-remote.com","dyndns-server.com","dyndns-web.com","dyndns-wiki.com","dyndns-work.com","dyndns.biz","dyndns.info","dyndns.org","dyndns.tv","at-band-camp.net","ath.cx","barrel-of-knowledge.info","barrell-of-knowledge.info","better-than.tv","blogdns.com","blogdns.net","blogdns.org","blogsite.org","boldlygoingnowhere.org","broke-it.net","buyshouses.net","cechire.com","dnsalias.com","dnsalias.net","dnsalias.org","dnsdojo.com","dnsdojo.net","dnsdojo.org","does-it.net","doesntexist.com","doesntexist.org","dontexist.com","dontexist.net","dontexist.org","doomdns.com","doomdns.org","dvrdns.org","dyn-o-saur.com","dynalias.com","dynalias.net","dynalias.org","dynathome.net","dyndns.ws","endofinternet.net","endofinternet.org","endoftheinternet.org","est-a-la-maison.com","est-a-la-masion.com","est-le-patron.com","est-mon-blogueur.com","for-better.biz","for-more.biz","for-our.info","for-some.biz","for-the.biz","forgot.her.name","forgot.his.name","from-ak.com","from-al.com","from-ar.com","from-az.net","from-ca.com","from-co.net","from-ct.com","from-dc.com","from-de.com","from-fl.com","from-ga.com","from-hi.com","from-ia.com","from-id.com","from-il.com","from-in.com","from-ks.com","from-ky.com","from-la.net","from-ma.com","from-md.com","from-me.org","from-mi.com","from-mn.com","from-mo.com","from-ms.com","from-mt.com","from-nc.com","from-nd.com","from-ne.com","from-nh.com","from-nj.com","from-nm.com","from-nv.com","from-ny.net","from-oh.com","from-ok.com","from-or.com","from-pa.com","from-pr.com","from-ri.com","from-sc.com","from-sd.com","from-tn.com","from-tx.com","from-ut.com","from-va.com","from-vt.com","from-wa.com","from-wi.com","from-wv.com","from-wy.com","ftpaccess.cc","fuettertdasnetz.de","game-host.org","game-server.cc","getmyip.com","gets-it.net","go.dyndns.org","gotdns.com","gotdns.org","groks-the.info","groks-this.info","ham-radio-op.net","here-for-more.info","hobby-site.com","hobby-site.org","home.dyndns.org","homedns.org","homeftp.net","homeftp.org","homeip.net","homelinux.com","homelinux.net","homelinux.org","homeunix.com","homeunix.net","homeunix.org","iamallama.com","in-the-band.net","is-a-anarchist.com","is-a-blogger.com","is-a-bookkeeper.com","is-a-bruinsfan.org","is-a-bulls-fan.com","is-a-candidate.org","is-a-caterer.com","is-a-celticsfan.org","is-a-chef.com","is-a-chef.net","is-a-chef.org","is-a-conservative.com","is-a-cpa.com","is-a-cubicle-slave.com","is-a-democrat.com","is-a-designer.com","is-a-doctor.com","is-a-financialadvisor.com","is-a-geek.com","is-a-geek.net","is-a-geek.org","is-a-green.com","is-a-guru.com","is-a-hard-worker.com","is-a-hunter.com","is-a-knight.org","is-a-landscaper.com","is-a-lawyer.com","is-a-liberal.com","is-a-libertarian.com","is-a-linux-user.org","is-a-llama.com","is-a-musician.com","is-a-nascarfan.com","is-a-nurse.com","is-a-painter.com","is-a-patsfan.org","is-a-personaltrainer.com","is-a-photographer.com","is-a-player.com","is-a-republican.com","is-a-rockstar.com","is-a-socialist.com","is-a-soxfan.org","is-a-student.com","is-a-teacher.com","is-a-techie.com","is-a-therapist.com","is-an-accountant.com","is-an-actor.com","is-an-actress.com","is-an-anarchist.com","is-an-artist.com","is-an-engineer.com","is-an-entertainer.com","is-by.us","is-certified.com","is-found.org","is-gone.com","is-into-anime.com","is-into-cars.com","is-into-cartoons.com","is-into-games.com","is-leet.com","is-lost.org","is-not-certified.com","is-saved.org","is-slick.com","is-uberleet.com","is-very-bad.org","is-very-evil.org","is-very-good.org","is-very-nice.org","is-very-sweet.org","is-with-theband.com","isa-geek.com","isa-geek.net","isa-geek.org","isa-hockeynut.com","issmarterthanyou.com","isteingeek.de","istmein.de","kicks-ass.net","kicks-ass.org","knowsitall.info","land-4-sale.us","lebtimnetz.de","leitungsen.de","likes-pie.com","likescandy.com","merseine.nu","mine.nu","misconfused.org","mypets.ws","myphotos.cc","neat-url.com","office-on-the.net","on-the-web.tv","podzone.net","podzone.org","readmyblog.org","saves-the-whales.com","scrapper-site.net","scrapping.cc","selfip.biz","selfip.com","selfip.info","selfip.net","selfip.org","sells-for-less.com","sells-for-u.com","sells-it.net","sellsyourhome.org","servebbs.com","servebbs.net","servebbs.org","serveftp.net","serveftp.org","servegame.org","shacknet.nu","simple-url.com","space-to-rent.com","stuff-4-sale.org","stuff-4-sale.us","teaches-yoga.com","thruhere.net","traeumtgerade.de","webhop.biz","webhop.info","webhop.net","webhop.org","worse-than.tv","writesthisblog.com","ddnss.de","dyn.ddnss.de","dyndns.ddnss.de","dyndns1.de","dyn-ip24.de","home-webserver.de","dyn.home-webserver.de","myhome-server.de","ddnss.org","definima.net","definima.io","bci.dnstrace.pro","ddnsfree.com","ddnsgeek.com","giize.com","gleeze.com","kozow.com","loseyourip.com","ooguy.com","theworkpc.com","casacam.net","dynu.net","accesscam.org","camdvr.org","freeddns.org","mywire.org","webredirect.org","myddns.rocks","blogsite.xyz","dynv6.net","e4.cz","mytuleap.com","enonic.io","customer.enonic.io","eu.org","al.eu.org","asso.eu.org","at.eu.org","au.eu.org","be.eu.org","bg.eu.org","ca.eu.org","cd.eu.org","ch.eu.org","cn.eu.org","cy.eu.org","cz.eu.org","de.eu.org","dk.eu.org","edu.eu.org","ee.eu.org","es.eu.org","fi.eu.org","fr.eu.org","gr.eu.org","hr.eu.org","hu.eu.org","ie.eu.org","il.eu.org","in.eu.org","int.eu.org","is.eu.org","it.eu.org","jp.eu.org","kr.eu.org","lt.eu.org","lu.eu.org","lv.eu.org","mc.eu.org","me.eu.org","mk.eu.org","mt.eu.org","my.eu.org","net.eu.org","ng.eu.org","nl.eu.org","no.eu.org","nz.eu.org","paris.eu.org","pl.eu.org","pt.eu.org","q-a.eu.org","ro.eu.org","ru.eu.org","se.eu.org","si.eu.org","sk.eu.org","tr.eu.org","uk.eu.org","us.eu.org","eu-1.evennode.com","eu-2.evennode.com","eu-3.evennode.com","eu-4.evennode.com","us-1.evennode.com","us-2.evennode.com","us-3.evennode.com","us-4.evennode.com","twmail.cc","twmail.net","twmail.org","mymailer.com.tw","url.tw","apps.fbsbx.com","ru.net","adygeya.ru","bashkiria.ru","bir.ru","cbg.ru","com.ru","dagestan.ru","grozny.ru","kalmykia.ru","kustanai.ru","marine.ru","mordovia.ru","msk.ru","mytis.ru","nalchik.ru","nov.ru","pyatigorsk.ru","spb.ru","vladikavkaz.ru","vladimir.ru","abkhazia.su","adygeya.su","aktyubinsk.su","arkhangelsk.su","armenia.su","ashgabad.su","azerbaijan.su","balashov.su","bashkiria.su","bryansk.su","bukhara.su","chimkent.su","dagestan.su","east-kazakhstan.su","exnet.su","georgia.su","grozny.su","ivanovo.su","jambyl.su","kalmykia.su","kaluga.su","karacol.su","karaganda.su","karelia.su","khakassia.su","krasnodar.su","kurgan.su","kustanai.su","lenug.su","mangyshlak.su","mordovia.su","msk.su","murmansk.su","nalchik.su","navoi.su","north-kazakhstan.su","nov.su","obninsk.su","penza.su","pokrovsk.su","sochi.su","spb.su","tashkent.su","termez.su","togliatti.su","troitsk.su","tselinograd.su","tula.su","tuva.su","vladikavkaz.su","vladimir.su","vologda.su","channelsdvr.net","fastlylb.net","map.fastlylb.net","freetls.fastly.net","map.fastly.net","a.prod.fastly.net","global.prod.fastly.net","a.ssl.fastly.net","b.ssl.fastly.net","global.ssl.fastly.net","fastpanel.direct","fastvps-server.com","fhapp.xyz","fedorainfracloud.org","fedorapeople.org","cloud.fedoraproject.org","app.os.fedoraproject.org","app.os.stg.fedoraproject.org","filegear.me","firebaseapp.com","flynnhub.com","flynnhosting.net","freebox-os.com","freeboxos.com","fbx-os.fr","fbxos.fr","freebox-os.fr","freeboxos.fr","freedesktop.org","*.futurecms.at","*.ex.futurecms.at","*.in.futurecms.at","futurehosting.at","futuremailing.at","*.ex.ortsinfo.at","*.kunden.ortsinfo.at","*.statics.cloud","service.gov.uk","github.io","githubusercontent.com","gitlab.io","homeoffice.gov.uk","ro.im","shop.ro","goip.de","*.0emm.com","appspot.com","blogspot.ae","blogspot.al","blogspot.am","blogspot.ba","blogspot.be","blogspot.bg","blogspot.bj","blogspot.ca","blogspot.cf","blogspot.ch","blogspot.cl","blogspot.co.at","blogspot.co.id","blogspot.co.il","blogspot.co.ke","blogspot.co.nz","blogspot.co.uk","blogspot.co.za","blogspot.com","blogspot.com.ar","blogspot.com.au","blogspot.com.br","blogspot.com.by","blogspot.com.co","blogspot.com.cy","blogspot.com.ee","blogspot.com.eg","blogspot.com.es","blogspot.com.mt","blogspot.com.ng","blogspot.com.tr","blogspot.com.uy","blogspot.cv","blogspot.cz","blogspot.de","blogspot.dk","blogspot.fi","blogspot.fr","blogspot.gr","blogspot.hk","blogspot.hr","blogspot.hu","blogspot.ie","blogspot.in","blogspot.is","blogspot.it","blogspot.jp","blogspot.kr","blogspot.li","blogspot.lt","blogspot.lu","blogspot.md","blogspot.mk","blogspot.mr","blogspot.mx","blogspot.my","blogspot.nl","blogspot.no","blogspot.pe","blogspot.pt","blogspot.qa","blogspot.re","blogspot.ro","blogspot.rs","blogspot.ru","blogspot.se","blogspot.sg","blogspot.si","blogspot.sk","blogspot.sn","blogspot.td","blogspot.tw","blogspot.ug","blogspot.vn","cloudfunctions.net","cloud.goog","codespot.com","googleapis.com","googlecode.com","pagespeedmobilizer.com","publishproxy.com","withgoogle.com","withyoutube.com","hashbang.sh","hasura.app","hasura-app.io","hepforge.org","herokuapp.com","herokussl.com","myravendb.com","ravendb.community","ravendb.me","development.run","ravendb.run","moonscale.net","iki.fi","biz.at","info.at","info.cx","ac.leg.br","al.leg.br","am.leg.br","ap.leg.br","ba.leg.br","ce.leg.br","df.leg.br","es.leg.br","go.leg.br","ma.leg.br","mg.leg.br","ms.leg.br","mt.leg.br","pa.leg.br","pb.leg.br","pe.leg.br","pi.leg.br","pr.leg.br","rj.leg.br","rn.leg.br","ro.leg.br","rr.leg.br","rs.leg.br","sc.leg.br","se.leg.br","sp.leg.br","to.leg.br","pixolino.com","ipifony.net","mein-iserv.de","test-iserv.de","myjino.ru","*.hosting.myjino.ru","*.landing.myjino.ru","*.spectrum.myjino.ru","*.vps.myjino.ru","*.triton.zone","*.cns.joyent.com","js.org","keymachine.de","knightpoint.systems","co.krd","edu.krd","git-repos.de","lcube-server.de","svn-repos.de","app.lmpm.com","linkitools.space","linkyard.cloud","linkyard-cloud.ch","we.bs","uklugs.org","glug.org.uk","lug.org.uk","lugs.org.uk","barsy.bg","barsy.co.uk","barsyonline.co.uk","barsycenter.com","barsyonline.com","barsy.club","barsy.de","barsy.eu","barsy.in","barsy.info","barsy.io","barsy.me","barsy.menu","barsy.mobi","barsy.net","barsy.online","barsy.org","barsy.pro","barsy.pub","barsy.shop","barsy.site","barsy.support","barsy.uk","*.magentosite.cloud","mayfirst.info","mayfirst.org","hb.cldmail.ru","miniserver.com","memset.net","cloud.metacentrum.cz","custom.metacentrum.cz","flt.cloud.muni.cz","usr.cloud.muni.cz","meteorapp.com","eu.meteorapp.com","co.pl","azurecontainer.io","azurewebsites.net","azure-mobile.net","cloudapp.net","mozilla-iot.org","bmoattachments.org","net.ru","org.ru","pp.ru","bitballoon.com","netlify.com","4u.com","ngrok.io","nh-serv.co.uk","nfshost.com","dnsking.ch","mypi.co","n4t.co","001www.com","ddnslive.com","myiphost.com","forumz.info","16-b.it","32-b.it","64-b.it","soundcast.me","tcp4.me","dnsup.net","hicam.net","now-dns.net","ownip.net","vpndns.net","dynserv.org","now-dns.org","x443.pw","now-dns.top","ntdll.top","freeddns.us","crafting.xyz","zapto.xyz","nsupdate.info","nerdpol.ovh","blogsyte.com","brasilia.me","cable-modem.org","ciscofreak.com","collegefan.org","couchpotatofries.org","damnserver.com","ddns.me","ditchyourip.com","dnsfor.me","dnsiskinky.com","dvrcam.info","dynns.com","eating-organic.net","fantasyleague.cc","geekgalaxy.com","golffan.us","health-carereform.com","homesecuritymac.com","homesecuritypc.com","hopto.me","ilovecollege.info","loginto.me","mlbfan.org","mmafan.biz","myactivedirectory.com","mydissent.net","myeffect.net","mymediapc.net","mypsx.net","mysecuritycamera.com","mysecuritycamera.net","mysecuritycamera.org","net-freaks.com","nflfan.org","nhlfan.net","no-ip.ca","no-ip.co.uk","no-ip.net","noip.us","onthewifi.com","pgafan.net","point2this.com","pointto.us","privatizehealthinsurance.net","quicksytes.com","read-books.org","securitytactics.com","serveexchange.com","servehumour.com","servep2p.com","servesarcasm.com","stufftoread.com","ufcfan.org","unusualperson.com","workisboring.com","3utilities.com","bounceme.net","ddns.net","ddnsking.com","gotdns.ch","hopto.org","myftp.biz","myftp.org","myvnc.com","no-ip.biz","no-ip.info","no-ip.org","noip.me","redirectme.net","servebeer.com","serveblog.net","servecounterstrike.com","serveftp.com","servegame.com","servehalflife.com","servehttp.com","serveirc.com","serveminecraft.net","servemp3.com","servepics.com","servequake.com","sytes.net","webhop.me","zapto.org","stage.nodeart.io","nodum.co","nodum.io","pcloud.host","nyc.mn","nom.ae","nom.af","nom.ai","nom.al","nym.by","nym.bz","nom.cl","nom.gd","nom.ge","nom.gl","nym.gr","nom.gt","nym.gy","nom.hn","nym.ie","nom.im","nom.ke","nym.kz","nym.la","nym.lc","nom.li","nym.li","nym.lt","nym.lu","nym.me","nom.mk","nym.mn","nym.mx","nom.nu","nym.nz","nym.pe","nym.pt","nom.pw","nom.qa","nym.ro","nom.rs","nom.si","nym.sk","nom.st","nym.su","nym.sx","nom.tj","nym.tw","nom.ug","nom.uy","nom.vc","nom.vg","cya.gg","cloudycluster.net","nid.io","opencraft.hosting","operaunite.com","outsystemscloud.com","ownprovider.com","own.pm","ox.rs","oy.lc","pgfog.com","pagefrontapp.com","art.pl","gliwice.pl","krakow.pl","poznan.pl","wroc.pl","zakopane.pl","pantheonsite.io","gotpantheon.com","mypep.link","on-web.fr","*.platform.sh","*.platformsh.site","xen.prgmr.com","priv.at","protonet.io","chirurgiens-dentistes-en-france.fr","byen.site","ras.ru","qa2.com","dev-myqnapcloud.com","alpha-myqnapcloud.com","myqnapcloud.com","*.quipelements.com","vapor.cloud","vaporcloud.io","rackmaze.com","rackmaze.net","rhcloud.com","resindevice.io","devices.resinstaging.io","hzc.io","wellbeingzone.eu","ptplus.fit","wellbeingzone.co.uk","sandcats.io","logoip.de","logoip.com","schokokeks.net","scrysec.com","firewall-gateway.com","firewall-gateway.de","my-gateway.de","my-router.de","spdns.de","spdns.eu","firewall-gateway.net","my-firewall.org","myfirewall.org","spdns.org","*.s5y.io","*.sensiosite.cloud","biz.ua","co.ua","pp.ua","shiftedit.io","myshopblocks.com","1kapp.com","appchizi.com","applinzi.com","sinaapp.com","vipsinaapp.com","bounty-full.com","alpha.bounty-full.com","beta.bounty-full.com","static.land","dev.static.land","sites.static.land","apps.lair.io","*.stolos.io","spacekit.io","customer.speedpartner.de","storj.farm","utwente.io","temp-dns.com","diskstation.me","dscloud.biz","dscloud.me","dscloud.mobi","dsmynas.com","dsmynas.net","dsmynas.org","familyds.com","familyds.net","familyds.org","i234.me","myds.me","synology.me","vpnplus.to","taifun-dns.de","gda.pl","gdansk.pl","gdynia.pl","med.pl","sopot.pl","gwiddle.co.uk","cust.dev.thingdust.io","cust.disrec.thingdust.io","cust.prod.thingdust.io","cust.testing.thingdust.io","bloxcms.com","townnews-staging.com","12hp.at","2ix.at","4lima.at","lima-city.at","12hp.ch","2ix.ch","4lima.ch","lima-city.ch","trafficplex.cloud","de.cool","12hp.de","2ix.de","4lima.de","lima-city.de","1337.pictures","clan.rip","lima-city.rocks","webspace.rocks","lima.zone","*.transurl.be","*.transurl.eu","*.transurl.nl","tuxfamily.org","dd-dns.de","diskstation.eu","diskstation.org","dray-dns.de","draydns.de","dyn-vpn.de","dynvpn.de","mein-vigor.de","my-vigor.de","my-wan.de","syno-ds.de","synology-diskstation.de","synology-ds.de","uber.space","*.uberspace.de","hk.com","hk.org","ltd.hk","inc.hk","virtualuser.de","virtual-user.de","lib.de.us","2038.io","router.management","v-info.info","wedeploy.io","wedeploy.me","wedeploy.sh","remotewd.com","wmflabs.org","half.host","xnbay.com","u2.xnbay.com","u2-local.xnbay.com","cistron.nl","demon.nl","xs4all.space","official.academy","yolasite.com","ybo.faith","yombo.me","homelink.one","ybo.party","ybo.review","ybo.science","ybo.trade","nohost.me","noho.st","za.net","za.org","now.sh","zone.id"]
+
+/***/ }),
+/* 17 */
+/***/ (function(module, exports) {
+
+ /*!
+ * Copyright (c) 2015, Salesforce.com, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of Salesforce.com nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+ 'use strict';
+ /*jshint unused:false */
+
+ function Store() {
+ }
+ exports.Store = Store;
+
+ // Stores may be synchronous, but are still required to use a
+ // Continuation-Passing Style API. The CookieJar itself will expose a "*Sync"
+ // API that converts from synchronous-callbacks to imperative style.
+ Store.prototype.synchronous = false;
+
+ Store.prototype.findCookie = function(domain, path, key, cb) {
+ throw new Error('findCookie is not implemented');
+ };
+
+ Store.prototype.findCookies = function(domain, path, cb) {
+ throw new Error('findCookies is not implemented');
+ };
+
+ Store.prototype.putCookie = function(cookie, cb) {
+ throw new Error('putCookie is not implemented');
+ };
+
+ Store.prototype.updateCookie = function(oldCookie, newCookie, cb) {
+ // recommended default implementation:
+ // return this.putCookie(newCookie, cb);
+ throw new Error('updateCookie is not implemented');
+ };
+
+ Store.prototype.removeCookie = function(domain, path, key, cb) {
+ throw new Error('removeCookie is not implemented');
+ };
+
+ Store.prototype.removeCookies = function(domain, path, cb) {
+ throw new Error('removeCookies is not implemented');
+ };
+
+ Store.prototype.getAllCookies = function(cb) {
+ throw new Error('getAllCookies is not implemented (therefore jar cannot be serialized)');
+ };
+
+
+/***/ }),
+/* 18 */
+/***/ (function(module, exports, __webpack_require__) {
+
+ /*!
+ * Copyright (c) 2015, Salesforce.com, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of Salesforce.com nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+ 'use strict';
+ var Store = __webpack_require__(17).Store;
+ var permuteDomain = __webpack_require__(19).permuteDomain;
+ var pathMatch = __webpack_require__(20).pathMatch;
+ var util = __webpack_require__(9);
+
+ function MemoryCookieStore() {
+ Store.call(this);
+ this.idx = {};
+ }
+ util.inherits(MemoryCookieStore, Store);
+ exports.MemoryCookieStore = MemoryCookieStore;
+ MemoryCookieStore.prototype.idx = null;
+
+ // Since it's just a struct in RAM, this Store is synchronous
+ MemoryCookieStore.prototype.synchronous = true;
+
+ // force a default depth:
+ MemoryCookieStore.prototype.inspect = function() {
+ return "{ idx: "+util.inspect(this.idx, false, 2)+' }';
+ };
+
+ // Use the new custom inspection symbol to add the custom inspect function if
+ // available.
+ if (util.inspect.custom) {
+ MemoryCookieStore.prototype[util.inspect.custom] = MemoryCookieStore.prototype.inspect;
+ }
+
+ MemoryCookieStore.prototype.findCookie = function(domain, path, key, cb) {
+ if (!this.idx[domain]) {
+ return cb(null,undefined);
+ }
+ if (!this.idx[domain][path]) {
+ return cb(null,undefined);
+ }
+ return cb(null,this.idx[domain][path][key]||null);
+ };
+
+ MemoryCookieStore.prototype.findCookies = function(domain, path, cb) {
+ var results = [];
+ if (!domain) {
+ return cb(null,[]);
+ }
+
+ var pathMatcher;
+ if (!path) {
+ // null means "all paths"
+ pathMatcher = function matchAll(domainIndex) {
+ for (var curPath in domainIndex) {
+ var pathIndex = domainIndex[curPath];
+ for (var key in pathIndex) {
+ results.push(pathIndex[key]);
+ }
+ }
+ };
+
+ } else {
+ pathMatcher = function matchRFC(domainIndex) {
+ //NOTE: we should use path-match algorithm from S5.1.4 here
+ //(see : https://github.com/ChromiumWebApps/chromium/blob/b3d3b4da8bb94c1b2e061600df106d590fda3620/net/cookies/canonical_cookie.cc#L299)
+ Object.keys(domainIndex).forEach(function (cookiePath) {
+ if (pathMatch(path, cookiePath)) {
+ var pathIndex = domainIndex[cookiePath];
+
+ for (var key in pathIndex) {
+ results.push(pathIndex[key]);
+ }
+ }
+ });
+ };
+ }
+
+ var domains = permuteDomain(domain) || [domain];
+ var idx = this.idx;
+ domains.forEach(function(curDomain) {
+ var domainIndex = idx[curDomain];
+ if (!domainIndex) {
+ return;
+ }
+ pathMatcher(domainIndex);
+ });
+
+ cb(null,results);
+ };
+
+ MemoryCookieStore.prototype.putCookie = function(cookie, cb) {
+ if (!this.idx[cookie.domain]) {
+ this.idx[cookie.domain] = {};
+ }
+ if (!this.idx[cookie.domain][cookie.path]) {
+ this.idx[cookie.domain][cookie.path] = {};
+ }
+ this.idx[cookie.domain][cookie.path][cookie.key] = cookie;
+ cb(null);
+ };
+
+ MemoryCookieStore.prototype.updateCookie = function(oldCookie, newCookie, cb) {
+ // updateCookie() may avoid updating cookies that are identical. For example,
+ // lastAccessed may not be important to some stores and an equality
+ // comparison could exclude that field.
+ this.putCookie(newCookie,cb);
+ };
+
+ MemoryCookieStore.prototype.removeCookie = function(domain, path, key, cb) {
+ if (this.idx[domain] && this.idx[domain][path] && this.idx[domain][path][key]) {
+ delete this.idx[domain][path][key];
+ }
+ cb(null);
+ };
+
+ MemoryCookieStore.prototype.removeCookies = function(domain, path, cb) {
+ if (this.idx[domain]) {
+ if (path) {
+ delete this.idx[domain][path];
+ } else {
+ delete this.idx[domain];
+ }
+ }
+ return cb(null);
+ };
+
+ MemoryCookieStore.prototype.getAllCookies = function(cb) {
+ var cookies = [];
+ var idx = this.idx;
+
+ var domains = Object.keys(idx);
+ domains.forEach(function(domain) {
+ var paths = Object.keys(idx[domain]);
+ paths.forEach(function(path) {
+ var keys = Object.keys(idx[domain][path]);
+ keys.forEach(function(key) {
+ if (key !== null) {
+ cookies.push(idx[domain][path][key]);
+ }
+ });
+ });
+ });
+
+ // Sort by creationIndex so deserializing retains the creation order.
+ // When implementing your own store, this SHOULD retain the order too
+ cookies.sort(function(a,b) {
+ return (a.creationIndex||0) - (b.creationIndex||0);
+ });
+
+ cb(null, cookies);
+ };
+
+
+/***/ }),
+/* 19 */
+/***/ (function(module, exports, __webpack_require__) {
+
+ /*!
+ * Copyright (c) 2015, Salesforce.com, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of Salesforce.com nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+ "use strict";
+ var pubsuffix = __webpack_require__(13);
+
+ // Gives the permutation of all possible domainMatch()es of a given domain. The
+ // array is in shortest-to-longest order. Handy for indexing.
+ function permuteDomain (domain) {
+ var pubSuf = pubsuffix.getPublicSuffix(domain);
+ if (!pubSuf) {
+ return null;
+ }
+ if (pubSuf == domain) {
+ return [domain];
+ }
+
+ var prefix = domain.slice(0, -(pubSuf.length + 1)); // ".example.com"
+ var parts = prefix.split('.').reverse();
+ var cur = pubSuf;
+ var permutations = [cur];
+ while (parts.length) {
+ cur = parts.shift() + '.' + cur;
+ permutations.push(cur);
+ }
+ return permutations;
+ }
+
+ exports.permuteDomain = permuteDomain;
+
+
+/***/ }),
+/* 20 */
+/***/ (function(module, exports) {
+
+ /*!
+ * Copyright (c) 2015, Salesforce.com, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of Salesforce.com nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+ "use strict";
+ /*
+ * "A request-path path-matches a given cookie-path if at least one of the
+ * following conditions holds:"
+ */
+ function pathMatch (reqPath, cookiePath) {
+ // "o The cookie-path and the request-path are identical."
+ if (cookiePath === reqPath) {
+ return true;
+ }
+
+ var idx = reqPath.indexOf(cookiePath);
+ if (idx === 0) {
+ // "o The cookie-path is a prefix of the request-path, and the last
+ // character of the cookie-path is %x2F ("/")."
+ if (cookiePath.substr(-1) === "/") {
+ return true;
+ }
+
+ // " o The cookie-path is a prefix of the request-path, and the first
+ // character of the request-path that is not included in the cookie- path
+ // is a %x2F ("/") character."
+ if (reqPath.substr(cookiePath.length, 1) === "/") {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ exports.pathMatch = pathMatch;
+
+
+/***/ }),
+/* 21 */
+/***/ (function(module, exports) {
+
+ module.exports = {"_from":"tough-cookie@2.4.3","_id":"tough-cookie@2.4.3","_inBundle":false,"_integrity":"sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==","_location":"/tough-cookie","_phantomChildren":{},"_requested":{"type":"version","registry":true,"raw":"tough-cookie@2.4.3","name":"tough-cookie","escapedName":"tough-cookie","rawSpec":"2.4.3","saveSpec":null,"fetchSpec":"2.4.3"},"_requiredBy":["#DEV:/"],"_resolved":"https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz","_shasum":"53f36da3f47783b0925afa06ff9f3b165280f781","_spec":"tough-cookie@2.4.3","_where":"/Users/sefa/Entwicklung/umd-tough-cookie","author":{"name":"Jeremy Stashewsky","email":"jstash@gmail.com"},"bugs":{"url":"https://github.com/salesforce/tough-cookie/issues"},"bundleDependencies":false,"contributors":[{"name":"Alexander Savin"},{"name":"Ian Livingstone"},{"name":"Ivan Nikulin"},{"name":"Lalit Kapoor"},{"name":"Sam Thompson"},{"name":"Sebastian Mayr"}],"dependencies":{"psl":"^1.1.24","punycode":"^1.4.1"},"deprecated":false,"description":"RFC6265 Cookies and Cookie Jar for node.js","devDependencies":{"async":"^1.4.2","nyc":"^11.6.0","string.prototype.repeat":"^0.2.0","vows":"^0.8.1"},"engines":{"node":">=0.8"},"files":["lib"],"homepage":"https://github.com/salesforce/tough-cookie","keywords":["HTTP","cookie","cookies","set-cookie","cookiejar","jar","RFC6265","RFC2965"],"license":"BSD-3-Clause","main":"./lib/cookie","name":"tough-cookie","repository":{"type":"git","url":"git://github.com/salesforce/tough-cookie.git"},"scripts":{"cover":"nyc --reporter=lcov --reporter=html vows test/*_test.js","test":"vows test/*_test.js"},"version":"2.4.3"}
+
+/***/ })
+/******/ ])
+});
+;
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/url-util.js b/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/url-util.js
new file mode 100644
index 0000000..2e92be6
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/url-util.js
@@ -0,0 +1,105 @@
+cordova.define("cordova-plugin-advanced-http.url-util", function(require, exports, module) { module.exports = function init(jsUtil) {
+ return {
+ parseUrl: parseUrl,
+ appendQueryParamsString: appendQueryParamsString,
+ serializeQueryParams: serializeQueryParams
+ }
+
+ function parseUrl(url) {
+ var match = url.match(/^(https?\:)\/\/(([^:\/?#]*)(?:\:([0-9]+))?)([\/]{0,1}[^?#]*)(\?[^#]*|)(#.*|)$/);
+
+ return match && {
+ protocol: match[1],
+ host: match[2],
+ hostname: match[3],
+ port: match[4] || '',
+ pathname: match[5],
+ search: match[6],
+ hash: match[7]
+ }
+ }
+
+ function appendQueryParamsString(url, params) {
+ if (!url.length || !params.length) {
+ return url;
+ }
+
+ var parsed = parseUrl(url);
+
+ return parsed.protocol
+ + '//'
+ + parsed.host
+ + parsed.pathname
+ + (parsed.search.length ? parsed.search + '&' + params : '?' + params)
+ + parsed.hash;
+ }
+
+ function serializeQueryParams(params, encode) {
+ return serializeObject('', params, encode);
+ }
+
+ function serializeObject(parentKey, object, encode) {
+ var parts = [];
+
+ for (var key in object) {
+ if (!object.hasOwnProperty(key)) {
+ continue;
+ }
+
+ var identifier = parentKey.length ? parentKey + '[' + key + ']' : key;
+
+ if (jsUtil.getTypeOf(object[key]) === 'Array') {
+ parts.push(serializeArray(identifier, object[key], encode));
+ continue;
+ } else if (jsUtil.getTypeOf(object[key]) === 'Object') {
+ parts.push(serializeObject(identifier, object[key], encode));
+ continue;
+ }
+
+ parts.push(serializeIdentifier(parentKey, key, encode) + '=' + serializeValue(object[key], encode));
+ }
+
+ return parts.join('&');
+ }
+
+ function serializeArray(parentKey, array, encode) {
+ var parts = [];
+
+ for (var i = 0; i < array.length; ++i) {
+ if (jsUtil.getTypeOf(array[i]) === 'Array') {
+ parts.push(serializeArray(parentKey + '[]', array[i], encode));
+ continue;
+ } else if (jsUtil.getTypeOf(array[i]) === 'Object') {
+ parts.push(serializeObject(parentKey + '[]' + array[i], encode));
+ continue;
+ }
+
+ parts.push(serializeIdentifier(parentKey, '', encode) + '=' + serializeValue(array[i], encode));
+ }
+
+ return parts.join('&');
+ }
+
+ function serializeIdentifier(parentKey, key, encode) {
+ if (!parentKey.length) {
+ return encode ? encodeURIComponent(key) : key;
+ }
+
+ if (encode) {
+ return encodeURIComponent(parentKey) + '[' + encodeURIComponent(key) + ']';
+ } else {
+ return parentKey + '[' + key + ']';
+ }
+ }
+
+ function serializeValue(value, encode) {
+ if (encode) {
+ return encodeURIComponent(value);
+ } else {
+ return value;
+ }
+ }
+};
+
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-camera/src/browser/CameraProxy.js b/platforms/browser/platform_www/plugins/cordova-plugin-camera/src/browser/CameraProxy.js
new file mode 100644
index 0000000..50d8bff
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-camera/src/browser/CameraProxy.js
@@ -0,0 +1,125 @@
+cordova.define("cordova-plugin-camera.CameraProxy", function(require, exports, module) { /*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+var HIGHEST_POSSIBLE_Z_INDEX = 2147483647;
+
+function takePicture (success, error, opts) {
+ if (opts && opts[2] === 1) {
+ capture(success, error, opts);
+ } else {
+ var input = document.createElement('input');
+ input.style.position = 'relative';
+ input.style.zIndex = HIGHEST_POSSIBLE_Z_INDEX;
+ input.className = 'cordova-camera-select';
+ input.type = 'file';
+ input.name = 'files[]';
+
+ input.onchange = function (inputEvent) {
+ var reader = new FileReader(); /* eslint no-undef : 0 */
+ reader.onload = function (readerEvent) {
+ input.parentNode.removeChild(input);
+
+ var imageData = readerEvent.target.result;
+
+ return success(imageData.substr(imageData.indexOf(',') + 1));
+ };
+
+ reader.readAsDataURL(inputEvent.target.files[0]);
+ };
+
+ document.body.appendChild(input);
+ }
+}
+
+function capture (success, errorCallback, opts) {
+ var localMediaStream;
+ var targetWidth = opts[3];
+ var targetHeight = opts[4];
+
+ targetWidth = targetWidth === -1 ? 320 : targetWidth;
+ targetHeight = targetHeight === -1 ? 240 : targetHeight;
+
+ var video = document.createElement('video');
+ var button = document.createElement('button');
+ var parent = document.createElement('div');
+ parent.style.position = 'relative';
+ parent.style.zIndex = HIGHEST_POSSIBLE_Z_INDEX;
+ parent.className = 'cordova-camera-capture';
+ parent.appendChild(video);
+ parent.appendChild(button);
+
+ video.width = targetWidth;
+ video.height = targetHeight;
+ button.innerHTML = 'Capture!';
+
+ button.onclick = function () {
+ // create a canvas and capture a frame from video stream
+ var canvas = document.createElement('canvas');
+ canvas.width = targetWidth;
+ canvas.height = targetHeight;
+ canvas.getContext('2d').drawImage(video, 0, 0, targetWidth, targetHeight);
+
+ // convert image stored in canvas to base64 encoded image
+ var imageData = canvas.toDataURL('image/png');
+ imageData = imageData.replace('data:image/png;base64,', '');
+
+ // stop video stream, remove video and button.
+ // Note that MediaStream.stop() is deprecated as of Chrome 47.
+ if (localMediaStream.stop) {
+ localMediaStream.stop();
+ } else {
+ localMediaStream.getTracks().forEach(function (track) {
+ track.stop();
+ });
+ }
+ parent.parentNode.removeChild(parent);
+
+ return success(imageData);
+ };
+
+ navigator.getUserMedia = navigator.getUserMedia ||
+ navigator.webkitGetUserMedia ||
+ navigator.mozGetUserMedia ||
+ navigator.msGetUserMedia;
+
+ var successCallback = function (stream) {
+ localMediaStream = stream;
+ video.src = window.URL.createObjectURL(localMediaStream);
+ video.play();
+
+ document.body.appendChild(parent);
+ };
+
+ if (navigator.getUserMedia) {
+ navigator.getUserMedia({video: true, audio: true}, successCallback, errorCallback);
+ } else {
+ alert('Browser does not support camera :(');
+ }
+}
+
+module.exports = {
+ takePicture: takePicture,
+ cleanup: function () {}
+};
+
+require('cordova/exec/proxy').add('Camera', module.exports);
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-camera/www/Camera.js b/platforms/browser/platform_www/plugins/cordova-plugin-camera/www/Camera.js
new file mode 100644
index 0000000..3959553
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-camera/www/Camera.js
@@ -0,0 +1,187 @@
+cordova.define("cordova-plugin-camera.camera", function(require, exports, module) { /*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+var argscheck = require('cordova/argscheck');
+var exec = require('cordova/exec');
+var Camera = require('./Camera');
+// XXX: commented out
+// CameraPopoverHandle = require('./CameraPopoverHandle');
+
+/**
+ * @namespace navigator
+ */
+
+/**
+ * @exports camera
+ */
+var cameraExport = {};
+
+// Tack on the Camera Constants to the base camera plugin.
+for (var key in Camera) {
+ cameraExport[key] = Camera[key];
+}
+
+/**
+ * Callback function that provides an error message.
+ * @callback module:camera.onError
+ * @param {string} message - The message is provided by the device's native code.
+ */
+
+/**
+ * Callback function that provides the image data.
+ * @callback module:camera.onSuccess
+ * @param {string} imageData - Base64 encoding of the image data, _or_ the image file URI, depending on [`cameraOptions`]{@link module:camera.CameraOptions} in effect.
+ * @example
+ * // Show image
+ * //
+ * function cameraCallback(imageData) {
+ * var image = document.getElementById('myImage');
+ * image.src = "data:image/jpeg;base64," + imageData;
+ * }
+ */
+
+/**
+ * Optional parameters to customize the camera settings.
+ * * [Quirks](#CameraOptions-quirks)
+ * @typedef module:camera.CameraOptions
+ * @type {Object}
+ * @property {number} [quality=50] - Quality of the saved image, expressed as a range of 0-100, where 100 is typically full resolution with no loss from file compression. (Note that information about the camera's resolution is unavailable.)
+ * @property {module:Camera.DestinationType} [destinationType=FILE_URI] - Choose the format of the return value.
+ * @property {module:Camera.PictureSourceType} [sourceType=CAMERA] - Set the source of the picture.
+ * @property {Boolean} [allowEdit=false] - Allow simple editing of image before selection.
+ * @property {module:Camera.EncodingType} [encodingType=JPEG] - Choose the returned image file's encoding.
+ * @property {number} [targetWidth] - Width in pixels to scale image. Must be used with `targetHeight`. Aspect ratio remains constant.
+ * @property {number} [targetHeight] - Height in pixels to scale image. Must be used with `targetWidth`. Aspect ratio remains constant.
+ * @property {module:Camera.MediaType} [mediaType=PICTURE] - Set the type of media to select from. Only works when `PictureSourceType` is `PHOTOLIBRARY` or `SAVEDPHOTOALBUM`.
+ * @property {Boolean} [correctOrientation] - Rotate the image to correct for the orientation of the device during capture.
+ * @property {Boolean} [saveToPhotoAlbum] - Save the image to the photo album on the device after capture.
+ * @property {module:CameraPopoverOptions} [popoverOptions] - iOS-only options that specify popover location in iPad.
+ * @property {module:Camera.Direction} [cameraDirection=BACK] - Choose the camera to use (front- or back-facing).
+ */
+
+/**
+ * @description Takes a photo using the camera, or retrieves a photo from the device's
+ * image gallery. The image is passed to the success callback as a
+ * Base64-encoded `String`, or as the URI for the image file.
+ *
+ * The `camera.getPicture` function opens the device's default camera
+ * application that allows users to snap pictures by default - this behavior occurs,
+ * when `Camera.sourceType` equals [`Camera.PictureSourceType.CAMERA`]{@link module:Camera.PictureSourceType}.
+ * Once the user snaps the photo, the camera application closes and the application is restored.
+ *
+ * If `Camera.sourceType` is `Camera.PictureSourceType.PHOTOLIBRARY` or
+ * `Camera.PictureSourceType.SAVEDPHOTOALBUM`, then a dialog displays
+ * that allows users to select an existing image.
+ *
+ * The return value is sent to the [`cameraSuccess`]{@link module:camera.onSuccess} callback function, in
+ * one of the following formats, depending on the specified
+ * `cameraOptions`:
+ *
+ * - A `String` containing the Base64-encoded photo image.
+ * - A `String` representing the image file location on local storage (default).
+ *
+ * You can do whatever you want with the encoded image or URI, for
+ * example:
+ *
+ * - Render the image in an `<img>` tag, as in the example below
+ * - Save the data locally (`LocalStorage`, [Lawnchair](http://brianleroux.github.com/lawnchair/), etc.)
+ * - Post the data to a remote server
+ *
+ * __NOTE__: Photo resolution on newer devices is quite good. Photos
+ * selected from the device's gallery are not downscaled to a lower
+ * quality, even if a `quality` parameter is specified. To avoid common
+ * memory problems, set `Camera.destinationType` to `FILE_URI` rather
+ * than `DATA_URL`.
+ *
+ * __Supported Platforms__
+ *
+ * - Android
+ * - BlackBerry
+ * - Browser
+ * - Firefox
+ * - FireOS
+ * - iOS
+ * - Windows
+ * - WP8
+ * - Ubuntu
+ *
+ * More examples [here](#camera-getPicture-examples). Quirks [here](#camera-getPicture-quirks).
+ *
+ * @example
+ * navigator.camera.getPicture(cameraSuccess, cameraError, cameraOptions);
+ * @param {module:camera.onSuccess} successCallback
+ * @param {module:camera.onError} errorCallback
+ * @param {module:camera.CameraOptions} options CameraOptions
+ */
+cameraExport.getPicture = function (successCallback, errorCallback, options) {
+ argscheck.checkArgs('fFO', 'Camera.getPicture', arguments);
+ options = options || {};
+ var getValue = argscheck.getValue;
+
+ var quality = getValue(options.quality, 50);
+ var destinationType = getValue(options.destinationType, Camera.DestinationType.FILE_URI);
+ var sourceType = getValue(options.sourceType, Camera.PictureSourceType.CAMERA);
+ var targetWidth = getValue(options.targetWidth, -1);
+ var targetHeight = getValue(options.targetHeight, -1);
+ var encodingType = getValue(options.encodingType, Camera.EncodingType.JPEG);
+ var mediaType = getValue(options.mediaType, Camera.MediaType.PICTURE);
+ var allowEdit = !!options.allowEdit;
+ var correctOrientation = !!options.correctOrientation;
+ var saveToPhotoAlbum = !!options.saveToPhotoAlbum;
+ var popoverOptions = getValue(options.popoverOptions, null);
+ var cameraDirection = getValue(options.cameraDirection, Camera.Direction.BACK);
+
+ var args = [quality, destinationType, sourceType, targetWidth, targetHeight, encodingType,
+ mediaType, allowEdit, correctOrientation, saveToPhotoAlbum, popoverOptions, cameraDirection];
+
+ exec(successCallback, errorCallback, 'Camera', 'takePicture', args);
+ // XXX: commented out
+ // return new CameraPopoverHandle();
+};
+
+/**
+ * Removes intermediate image files that are kept in temporary storage
+ * after calling [`camera.getPicture`]{@link module:camera.getPicture}. Applies only when the value of
+ * `Camera.sourceType` equals `Camera.PictureSourceType.CAMERA` and the
+ * `Camera.destinationType` equals `Camera.DestinationType.FILE_URI`.
+ *
+ * __Supported Platforms__
+ *
+ * - iOS
+ *
+ * @example
+ * navigator.camera.cleanup(onSuccess, onFail);
+ *
+ * function onSuccess() {
+ * console.log("Camera cleanup success.")
+ * }
+ *
+ * function onFail(message) {
+ * alert('Failed because: ' + message);
+ * }
+ */
+cameraExport.cleanup = function (successCallback, errorCallback) {
+ exec(successCallback, errorCallback, 'Camera', 'cleanup', []);
+};
+
+module.exports = cameraExport;
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-camera/www/CameraConstants.js b/platforms/browser/platform_www/plugins/cordova-plugin-camera/www/CameraConstants.js
new file mode 100644
index 0000000..c271df6
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-camera/www/CameraConstants.js
@@ -0,0 +1,103 @@
+cordova.define("cordova-plugin-camera.Camera", function(require, exports, module) { /*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+/**
+ * @module Camera
+ */
+module.exports = {
+ /**
+ * @description
+ * Defines the output format of `Camera.getPicture` call.
+ * _Note:_ On iOS passing `DestinationType.NATIVE_URI` along with
+ * `PictureSourceType.PHOTOLIBRARY` or `PictureSourceType.SAVEDPHOTOALBUM` will
+ * disable any image modifications (resize, quality change, cropping, etc.) due
+ * to implementation specific.
+ *
+ * @enum {number}
+ */
+ DestinationType: {
+ /** Return base64 encoded string. DATA_URL can be very memory intensive and cause app crashes or out of memory errors. Use FILE_URI or NATIVE_URI if possible */
+ DATA_URL: 0,
+ /** Return file uri (content://media/external/images/media/2 for Android) */
+ FILE_URI: 1,
+ /** Return native uri (eg. asset-library://... for iOS) */
+ NATIVE_URI: 2
+ },
+ /**
+ * @enum {number}
+ */
+ EncodingType: {
+ /** Return JPEG encoded image */
+ JPEG: 0,
+ /** Return PNG encoded image */
+ PNG: 1
+ },
+ /**
+ * @enum {number}
+ */
+ MediaType: {
+ /** Allow selection of still pictures only. DEFAULT. Will return format specified via DestinationType */
+ PICTURE: 0,
+ /** Allow selection of video only, ONLY RETURNS URL */
+ VIDEO: 1,
+ /** Allow selection from all media types */
+ ALLMEDIA: 2
+ },
+ /**
+ * @description
+ * Defines the output format of `Camera.getPicture` call.
+ * _Note:_ On iOS passing `PictureSourceType.PHOTOLIBRARY` or `PictureSourceType.SAVEDPHOTOALBUM`
+ * along with `DestinationType.NATIVE_URI` will disable any image modifications (resize, quality
+ * change, cropping, etc.) due to implementation specific.
+ *
+ * @enum {number}
+ */
+ PictureSourceType: {
+ /** Choose image from the device's photo library (same as SAVEDPHOTOALBUM for Android) */
+ PHOTOLIBRARY: 0,
+ /** Take picture from camera */
+ CAMERA: 1,
+ /** Choose image only from the device's Camera Roll album (same as PHOTOLIBRARY for Android) */
+ SAVEDPHOTOALBUM: 2
+ },
+ /**
+ * Matches iOS UIPopoverArrowDirection constants to specify arrow location on popover.
+ * @enum {number}
+ */
+ PopoverArrowDirection: {
+ ARROW_UP: 1,
+ ARROW_DOWN: 2,
+ ARROW_LEFT: 4,
+ ARROW_RIGHT: 8,
+ ARROW_ANY: 15
+ },
+ /**
+ * @enum {number}
+ */
+ Direction: {
+ /** Use the back-facing camera */
+ BACK: 0,
+ /** Use the front-facing camera */
+ FRONT: 1
+ }
+};
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-camera/www/CameraPopoverOptions.js b/platforms/browser/platform_www/plugins/cordova-plugin-camera/www/CameraPopoverOptions.js
new file mode 100644
index 0000000..9b42e8b
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-camera/www/CameraPopoverOptions.js
@@ -0,0 +1,54 @@
+cordova.define("cordova-plugin-camera.CameraPopoverOptions", function(require, exports, module) { /*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+var Camera = require('./Camera');
+
+/**
+ * @namespace navigator
+ */
+
+/**
+ * iOS-only parameters that specify the anchor element location and arrow
+ * direction of the popover when selecting images from an iPad's library
+ * or album.
+ * Note that the size of the popover may change to adjust to the
+ * direction of the arrow and orientation of the screen. Make sure to
+ * account for orientation changes when specifying the anchor element
+ * location.
+ * @module CameraPopoverOptions
+ * @param {Number} [x=0] - x pixel coordinate of screen element onto which to anchor the popover.
+ * @param {Number} [y=32] - y pixel coordinate of screen element onto which to anchor the popover.
+ * @param {Number} [width=320] - width, in pixels, of the screen element onto which to anchor the popover.
+ * @param {Number} [height=480] - height, in pixels, of the screen element onto which to anchor the popover.
+ * @param {module:Camera.PopoverArrowDirection} [arrowDir=ARROW_ANY] - Direction the arrow on the popover should point.
+ */
+var CameraPopoverOptions = function (x, y, width, height, arrowDir) {
+ // information of rectangle that popover should be anchored to
+ this.x = x || 0;
+ this.y = y || 32;
+ this.width = width || 320;
+ this.height = height || 480;
+ this.arrowDir = arrowDir || Camera.PopoverArrowDirection.ARROW_ANY;
+};
+
+module.exports = CameraPopoverOptions;
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-device/src/browser/DeviceProxy.js b/platforms/browser/platform_www/plugins/cordova-plugin-device/src/browser/DeviceProxy.js
new file mode 100644
index 0000000..a4998fe
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-device/src/browser/DeviceProxy.js
@@ -0,0 +1,86 @@
+cordova.define("cordova-plugin-device.DeviceProxy", function(require, exports, module) { /*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+var browser = require('cordova/platform');
+
+function getPlatform () {
+ return 'browser';
+}
+
+function getModel () {
+ return getBrowserInfo(true);
+}
+
+function getVersion () {
+ return getBrowserInfo(false);
+}
+
+function getBrowserInfo (getModel) {
+ var userAgent = navigator.userAgent;
+ var returnVal = '';
+ var offset;
+
+ if ((offset = userAgent.indexOf('Edge')) !== -1) {
+ returnVal = (getModel) ? 'Edge' : userAgent.substring(offset + 5);
+ } else if ((offset = userAgent.indexOf('Chrome')) !== -1) {
+ returnVal = (getModel) ? 'Chrome' : userAgent.substring(offset + 7);
+ } else if ((offset = userAgent.indexOf('Safari')) !== -1) {
+ if (getModel) {
+ returnVal = 'Safari';
+ } else {
+ returnVal = userAgent.substring(offset + 7);
+
+ if ((offset = userAgent.indexOf('Version')) !== -1) {
+ returnVal = userAgent.substring(offset + 8);
+ }
+ }
+ } else if ((offset = userAgent.indexOf('Firefox')) !== -1) {
+ returnVal = (getModel) ? 'Firefox' : userAgent.substring(offset + 8);
+ } else if ((offset = userAgent.indexOf('MSIE')) !== -1) {
+ returnVal = (getModel) ? 'MSIE' : userAgent.substring(offset + 5);
+ } else if ((offset = userAgent.indexOf('Trident')) !== -1) {
+ returnVal = (getModel) ? 'MSIE' : '11';
+ }
+
+ if ((offset = returnVal.indexOf(';')) !== -1 || (offset = returnVal.indexOf(' ')) !== -1) {
+ returnVal = returnVal.substring(0, offset);
+ }
+
+ return returnVal;
+}
+
+module.exports = {
+ getDeviceInfo: function (success, error) {
+ setTimeout(function () {
+ success({
+ cordova: browser.cordovaVersion,
+ platform: getPlatform(),
+ model: getModel(),
+ version: getVersion(),
+ uuid: null,
+ isVirtual: false
+ });
+ }, 0);
+ }
+};
+
+require('cordova/exec/proxy').add('Device', module.exports);
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-device/www/device.js b/platforms/browser/platform_www/plugins/cordova-plugin-device/www/device.js
new file mode 100644
index 0000000..059351d
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-device/www/device.js
@@ -0,0 +1,85 @@
+cordova.define("cordova-plugin-device.device", function(require, exports, module) { /*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+var argscheck = require('cordova/argscheck');
+var channel = require('cordova/channel');
+var utils = require('cordova/utils');
+var exec = require('cordova/exec');
+var cordova = require('cordova');
+
+channel.createSticky('onCordovaInfoReady');
+// Tell cordova channel to wait on the CordovaInfoReady event
+channel.waitForInitialization('onCordovaInfoReady');
+
+/**
+ * This represents the mobile device, and provides properties for inspecting the model, version, UUID of the
+ * phone, etc.
+ * @constructor
+ */
+function Device () {
+ this.available = false;
+ this.platform = null;
+ this.version = null;
+ this.uuid = null;
+ this.cordova = null;
+ this.model = null;
+ this.manufacturer = null;
+ this.isVirtual = null;
+ this.serial = null;
+
+ var me = this;
+
+ channel.onCordovaReady.subscribe(function () {
+ me.getInfo(function (info) {
+ // ignoring info.cordova returning from native, we should use value from cordova.version defined in cordova.js
+ // TODO: CB-5105 native implementations should not return info.cordova
+ var buildLabel = cordova.version;
+ me.available = true;
+ me.platform = info.platform;
+ me.version = info.version;
+ me.uuid = info.uuid;
+ me.cordova = buildLabel;
+ me.model = info.model;
+ me.isVirtual = info.isVirtual;
+ me.manufacturer = info.manufacturer || 'unknown';
+ me.serial = info.serial || 'unknown';
+ channel.onCordovaInfoReady.fire();
+ }, function (e) {
+ me.available = false;
+ utils.alert('[ERROR] Error initializing Cordova: ' + e);
+ });
+ });
+}
+
+/**
+ * Get device info
+ *
+ * @param {Function} successCallback The function to call when the heading data is available
+ * @param {Function} errorCallback The function to call when there is an error getting the heading data. (OPTIONAL)
+ */
+Device.prototype.getInfo = function (successCallback, errorCallback) {
+ argscheck.checkArgs('fF', 'Device.getInfo', arguments);
+ exec(successCallback, errorCallback, 'Device', 'getDeviceInfo', []);
+};
+
+module.exports = new Device();
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-file/src/browser/FileProxy.js b/platforms/browser/platform_www/plugins/cordova-plugin-file/src/browser/FileProxy.js
new file mode 100644
index 0000000..d7b0541
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-file/src/browser/FileProxy.js
@@ -0,0 +1,986 @@
+cordova.define("cordova-plugin-file.browserFileProxy", function(require, exports, module) { /*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+(function () {
+ /* global require, exports, module */
+ /* global FILESYSTEM_PREFIX */
+ /* global IDBKeyRange */
+
+ /* Heavily based on https://github.com/ebidel/idb.filesystem.js */
+
+ // For chrome we don't need to implement proxy methods
+ // All functionality can be accessed natively.
+ if (require('./isChrome')()) {
+ var pathsPrefix = {
+ // Read-only directory where the application is installed.
+ applicationDirectory: location.origin + '/', // eslint-disable-line no-undef
+ // Where to put app-specific data files.
+ dataDirectory: 'filesystem:file:///persistent/',
+ // Cached files that should survive app restarts.
+ // Apps should not rely on the OS to delete files in here.
+ cacheDirectory: 'filesystem:file:///temporary/'
+ };
+
+ exports.requestAllPaths = function (successCallback) {
+ successCallback(pathsPrefix);
+ };
+
+ require('cordova/exec/proxy').add('File', module.exports);
+ return;
+ }
+
+ var LocalFileSystem = require('./LocalFileSystem');
+ var FileSystem = require('./FileSystem');
+ var FileEntry = require('./FileEntry');
+ var FileError = require('./FileError');
+ var DirectoryEntry = require('./DirectoryEntry');
+ var File = require('./File');
+
+ (function (exports, global) {
+ var indexedDB = global.indexedDB || global.mozIndexedDB;
+ if (!indexedDB) {
+ throw 'Firefox OS File plugin: indexedDB not supported';
+ }
+
+ var fs_ = null;
+
+ var idb_ = {};
+ idb_.db = null;
+ var FILE_STORE_ = 'entries';
+
+ var DIR_SEPARATOR = '/';
+
+ var pathsPrefix = {
+ // Read-only directory where the application is installed.
+ applicationDirectory: location.origin + '/', // eslint-disable-line no-undef
+ // Where to put app-specific data files.
+ dataDirectory: 'file:///persistent/',
+ // Cached files that should survive app restarts.
+ // Apps should not rely on the OS to delete files in here.
+ cacheDirectory: 'file:///temporary/'
+ };
+
+ var unicodeLastChar = 65535;
+
+ /** * Exported functionality ***/
+
+ exports.requestFileSystem = function (successCallback, errorCallback, args) {
+ var type = args[0];
+ // Size is ignored since IDB filesystem size depends
+ // on browser implementation and can't be set up by user
+ var size = args[1]; // eslint-disable-line no-unused-vars
+
+ if (type !== LocalFileSystem.TEMPORARY && type !== LocalFileSystem.PERSISTENT) {
+ if (errorCallback) {
+ errorCallback(FileError.INVALID_MODIFICATION_ERR);
+ }
+ return;
+ }
+
+ var name = type === LocalFileSystem.TEMPORARY ? 'temporary' : 'persistent';
+ var storageName = (location.protocol + location.host).replace(/:/g, '_'); // eslint-disable-line no-undef
+
+ var root = new DirectoryEntry('', DIR_SEPARATOR);
+ fs_ = new FileSystem(name, root);
+
+ idb_.open(storageName, function () {
+ successCallback(fs_);
+ }, errorCallback);
+ };
+
+ // Overridden by Android, BlackBerry 10 and iOS to populate fsMap
+ require('./fileSystems').getFs = function (name, callback) {
+ callback(new FileSystem(name, fs_.root));
+ };
+
+ // list a directory's contents (files and folders).
+ exports.readEntries = function (successCallback, errorCallback, args) {
+ var fullPath = args[0];
+
+ if (typeof successCallback !== 'function') {
+ throw Error('Expected successCallback argument.');
+ }
+
+ var path = resolveToFullPath_(fullPath);
+
+ exports.getDirectory(function () {
+ idb_.getAllEntries(path.fullPath + DIR_SEPARATOR, path.storagePath, function (entries) {
+ successCallback(entries);
+ }, errorCallback);
+ }, function () {
+ if (errorCallback) {
+ errorCallback(FileError.NOT_FOUND_ERR);
+ }
+ }, [path.storagePath, path.fullPath, {create: false}]);
+ };
+
+ exports.getFile = function (successCallback, errorCallback, args) {
+ var fullPath = args[0];
+ var path = args[1];
+ var options = args[2] || {};
+
+ // Create an absolute path if we were handed a relative one.
+ path = resolveToFullPath_(fullPath, path);
+
+ idb_.get(path.storagePath, function (fileEntry) {
+ if (options.create === true && options.exclusive === true && fileEntry) {
+ // If create and exclusive are both true, and the path already exists,
+ // getFile must fail.
+
+ if (errorCallback) {
+ errorCallback(FileError.PATH_EXISTS_ERR);
+ }
+ } else if (options.create === true && !fileEntry) {
+ // If create is true, the path doesn't exist, and no other error occurs,
+ // getFile must create it as a zero-length file and return a corresponding
+ // FileEntry.
+ var newFileEntry = new FileEntry(path.fileName, path.fullPath, new FileSystem(path.fsName, fs_.root));
+
+ newFileEntry.file_ = new MyFile({
+ size: 0,
+ name: newFileEntry.name,
+ lastModifiedDate: new Date(),
+ storagePath: path.storagePath
+ });
+
+ idb_.put(newFileEntry, path.storagePath, successCallback, errorCallback);
+ } else if (options.create === true && fileEntry) {
+ if (fileEntry.isFile) {
+ // Overwrite file, delete then create new.
+ idb_['delete'](path.storagePath, function () {
+ var newFileEntry = new FileEntry(path.fileName, path.fullPath, new FileSystem(path.fsName, fs_.root));
+
+ newFileEntry.file_ = new MyFile({
+ size: 0,
+ name: newFileEntry.name,
+ lastModifiedDate: new Date(),
+ storagePath: path.storagePath
+ });
+
+ idb_.put(newFileEntry, path.storagePath, successCallback, errorCallback);
+ }, errorCallback);
+ } else {
+ if (errorCallback) {
+ errorCallback(FileError.INVALID_MODIFICATION_ERR);
+ }
+ }
+ } else if ((!options.create || options.create === false) && !fileEntry) {
+ // If create is not true and the path doesn't exist, getFile must fail.
+ if (errorCallback) {
+ errorCallback(FileError.NOT_FOUND_ERR);
+ }
+ } else if ((!options.create || options.create === false) && fileEntry &&
+ fileEntry.isDirectory) {
+ // If create is not true and the path exists, but is a directory, getFile
+ // must fail.
+ if (errorCallback) {
+ errorCallback(FileError.TYPE_MISMATCH_ERR);
+ }
+ } else {
+ // Otherwise, if no other error occurs, getFile must return a FileEntry
+ // corresponding to path.
+
+ successCallback(fileEntryFromIdbEntry(fileEntry));
+ }
+ }, errorCallback);
+ };
+
+ exports.getFileMetadata = function (successCallback, errorCallback, args) {
+ var fullPath = args[0];
+
+ exports.getFile(function (fileEntry) {
+ successCallback(new File(fileEntry.file_.name, fileEntry.fullPath, '', fileEntry.file_.lastModifiedDate,
+ fileEntry.file_.size));
+ }, errorCallback, [fullPath, null]);
+ };
+
+ exports.getMetadata = function (successCallback, errorCallback, args) {
+ exports.getFile(function (fileEntry) {
+ successCallback(
+ {
+ modificationTime: fileEntry.file_.lastModifiedDate,
+ size: fileEntry.file_.lastModifiedDate
+ });
+ }, errorCallback, args);
+ };
+
+ exports.setMetadata = function (successCallback, errorCallback, args) {
+ var fullPath = args[0];
+ var metadataObject = args[1];
+
+ exports.getFile(function (fileEntry) {
+ fileEntry.file_.lastModifiedDate = metadataObject.modificationTime;
+ idb_.put(fileEntry, fileEntry.file_.storagePath, successCallback, errorCallback);
+ }, errorCallback, [fullPath, null]);
+ };
+
+ exports.write = function (successCallback, errorCallback, args) {
+ var fileName = args[0];
+ var data = args[1];
+ var position = args[2];
+ var isBinary = args[3]; // eslint-disable-line no-unused-vars
+
+ if (!data) {
+ if (errorCallback) {
+ errorCallback(FileError.INVALID_MODIFICATION_ERR);
+ }
+ return;
+ }
+
+ if (typeof data === 'string' || data instanceof String) {
+ data = new Blob([data]); // eslint-disable-line no-undef
+ }
+
+ exports.getFile(function (fileEntry) {
+ var blob_ = fileEntry.file_.blob_;
+
+ if (!blob_) {
+ blob_ = new Blob([data], {type: data.type}); // eslint-disable-line no-undef
+ } else {
+ // Calc the head and tail fragments
+ var head = blob_.slice(0, position);
+ var tail = blob_.slice(position + (data.size || data.byteLength));
+
+ // Calc the padding
+ var padding = position - head.size;
+ if (padding < 0) {
+ padding = 0;
+ }
+
+ // Do the "write". In fact, a full overwrite of the Blob.
+ blob_ = new Blob([head, new Uint8Array(padding), data, tail], // eslint-disable-line no-undef
+ {type: data.type});
+ }
+
+ // Set the blob we're writing on this file entry so we can recall it later.
+ fileEntry.file_.blob_ = blob_;
+ fileEntry.file_.lastModifiedDate = new Date() || null;
+ fileEntry.file_.size = blob_.size;
+ fileEntry.file_.name = blob_.name;
+ fileEntry.file_.type = blob_.type;
+
+ idb_.put(fileEntry, fileEntry.file_.storagePath, function () {
+ successCallback(data.size || data.byteLength);
+ }, errorCallback);
+ }, errorCallback, [fileName, null]);
+ };
+
+ exports.readAsText = function (successCallback, errorCallback, args) {
+ var fileName = args[0];
+ var enc = args[1];
+ var startPos = args[2];
+ var endPos = args[3];
+
+ readAs('text', fileName, enc, startPos, endPos, successCallback, errorCallback);
+ };
+
+ exports.readAsDataURL = function (successCallback, errorCallback, args) {
+ var fileName = args[0];
+ var startPos = args[1];
+ var endPos = args[2];
+
+ readAs('dataURL', fileName, null, startPos, endPos, successCallback, errorCallback);
+ };
+
+ exports.readAsBinaryString = function (successCallback, errorCallback, args) {
+ var fileName = args[0];
+ var startPos = args[1];
+ var endPos = args[2];
+
+ readAs('binaryString', fileName, null, startPos, endPos, successCallback, errorCallback);
+ };
+
+ exports.readAsArrayBuffer = function (successCallback, errorCallback, args) {
+ var fileName = args[0];
+ var startPos = args[1];
+ var endPos = args[2];
+
+ readAs('arrayBuffer', fileName, null, startPos, endPos, successCallback, errorCallback);
+ };
+
+ exports.removeRecursively = exports.remove = function (successCallback, errorCallback, args) {
+ if (typeof successCallback !== 'function') {
+ throw Error('Expected successCallback argument.');
+ }
+
+ var fullPath = resolveToFullPath_(args[0]).storagePath;
+ if (fullPath === pathsPrefix.cacheDirectory || fullPath === pathsPrefix.dataDirectory) {
+ errorCallback(FileError.NO_MODIFICATION_ALLOWED_ERR);
+ return;
+ }
+
+ function deleteEntry (isDirectory) {
+ // TODO: This doesn't protect against directories that have content in it.
+ // Should throw an error instead if the dirEntry is not empty.
+ idb_['delete'](fullPath, function () {
+ successCallback();
+ }, function () {
+ if (errorCallback) { errorCallback(); }
+ }, isDirectory);
+ }
+
+ // We need to to understand what we are deleting:
+ exports.getDirectory(function (entry) {
+ deleteEntry(entry.isDirectory);
+ }, function () {
+ // DirectoryEntry was already deleted or entry is FileEntry
+ deleteEntry(false);
+ }, [fullPath, null, {create: false}]);
+ };
+
+ exports.getDirectory = function (successCallback, errorCallback, args) {
+ var fullPath = args[0];
+ var path = args[1];
+ var options = args[2];
+
+ // Create an absolute path if we were handed a relative one.
+ path = resolveToFullPath_(fullPath, path);
+
+ idb_.get(path.storagePath, function (folderEntry) {
+ if (!options) {
+ options = {};
+ }
+
+ if (options.create === true && options.exclusive === true && folderEntry) {
+ // If create and exclusive are both true, and the path already exists,
+ // getDirectory must fail.
+ if (errorCallback) {
+ errorCallback(FileError.PATH_EXISTS_ERR);
+ }
+ // There is a strange bug in mobilespec + FF, which results in coming to multiple else-if's
+ // so we are shielding from it with returns.
+ return;
+ }
+
+ if (options.create === true && !folderEntry) {
+ // If create is true, the path doesn't exist, and no other error occurs,
+ // getDirectory must create it as a zero-length file and return a corresponding
+ // MyDirectoryEntry.
+ var dirEntry = new DirectoryEntry(path.fileName, path.fullPath, new FileSystem(path.fsName, fs_.root));
+
+ idb_.put(dirEntry, path.storagePath, successCallback, errorCallback);
+ return;
+ }
+
+ if (options.create === true && folderEntry) {
+
+ if (folderEntry.isDirectory) {
+ // IDB won't save methods, so we need re-create the MyDirectoryEntry.
+ successCallback(new DirectoryEntry(folderEntry.name, folderEntry.fullPath, folderEntry.filesystem));
+ } else {
+ if (errorCallback) {
+ errorCallback(FileError.INVALID_MODIFICATION_ERR);
+ }
+ }
+ return;
+ }
+
+ if ((!options.create || options.create === false) && !folderEntry) {
+ // Handle root special. It should always exist.
+ if (path.fullPath === DIR_SEPARATOR) {
+ successCallback(fs_.root);
+ return;
+ }
+
+ // If create is not true and the path doesn't exist, getDirectory must fail.
+ if (errorCallback) {
+ errorCallback(FileError.NOT_FOUND_ERR);
+ }
+
+ return;
+ }
+ if ((!options.create || options.create === false) && folderEntry && folderEntry.isFile) {
+ // If create is not true and the path exists, but is a file, getDirectory
+ // must fail.
+ if (errorCallback) {
+ errorCallback(FileError.TYPE_MISMATCH_ERR);
+ }
+ return;
+ }
+
+ // Otherwise, if no other error occurs, getDirectory must return a
+ // MyDirectoryEntry corresponding to path.
+
+ // IDB won't' save methods, so we need re-create MyDirectoryEntry.
+ successCallback(new DirectoryEntry(folderEntry.name, folderEntry.fullPath, folderEntry.filesystem));
+ }, errorCallback);
+ };
+
+ exports.getParent = function (successCallback, errorCallback, args) {
+ if (typeof successCallback !== 'function') {
+ throw Error('Expected successCallback argument.');
+ }
+
+ var fullPath = args[0];
+ // fullPath is like this:
+ // file:///persistent/path/to/file or
+ // file:///persistent/path/to/directory/
+
+ if (fullPath === DIR_SEPARATOR || fullPath === pathsPrefix.cacheDirectory ||
+ fullPath === pathsPrefix.dataDirectory) {
+ successCallback(fs_.root);
+ return;
+ }
+
+ // To delete all slashes at the end
+ while (fullPath[fullPath.length - 1] === '/') {
+ fullPath = fullPath.substr(0, fullPath.length - 1);
+ }
+
+ var pathArr = fullPath.split(DIR_SEPARATOR);
+ pathArr.pop();
+ var parentName = pathArr.pop();
+ var path = pathArr.join(DIR_SEPARATOR) + DIR_SEPARATOR;
+
+ // To get parent of root files
+ var joined = path + parentName + DIR_SEPARATOR;// is like this: file:///persistent/
+ if (joined === pathsPrefix.cacheDirectory || joined === pathsPrefix.dataDirectory) {
+ exports.getDirectory(successCallback, errorCallback, [joined, DIR_SEPARATOR, {create: false}]);
+ return;
+ }
+
+ exports.getDirectory(successCallback, errorCallback, [path, parentName, {create: false}]);
+ };
+
+ exports.copyTo = function (successCallback, errorCallback, args) {
+ var srcPath = args[0];
+ var parentFullPath = args[1];
+ var name = args[2];
+
+ if (name.indexOf('/') !== -1 || srcPath === parentFullPath + name) {
+ if (errorCallback) {
+ errorCallback(FileError.INVALID_MODIFICATION_ERR);
+ }
+
+ return;
+ }
+
+ // Read src file
+ exports.getFile(function (srcFileEntry) {
+
+ var path = resolveToFullPath_(parentFullPath);
+ // Check directory
+ exports.getDirectory(function () {
+
+ // Create dest file
+ exports.getFile(function (dstFileEntry) {
+
+ exports.write(function () {
+ successCallback(dstFileEntry);
+ }, errorCallback, [dstFileEntry.file_.storagePath, srcFileEntry.file_.blob_, 0]);
+
+ }, errorCallback, [parentFullPath, name, {create: true}]);
+
+ }, function () { if (errorCallback) { errorCallback(FileError.NOT_FOUND_ERR); } },
+ [path.storagePath, null, {create: false}]);
+
+ }, errorCallback, [srcPath, null]);
+ };
+
+ exports.moveTo = function (successCallback, errorCallback, args) {
+ var srcPath = args[0];
+ // parentFullPath and name parameters is ignored because
+ // args is being passed downstream to exports.copyTo method
+ var parentFullPath = args[1]; // eslint-disable-line
+ var name = args[2]; // eslint-disable-line
+
+ exports.copyTo(function (fileEntry) {
+
+ exports.remove(function () {
+ successCallback(fileEntry);
+ }, errorCallback, [srcPath]);
+
+ }, errorCallback, args);
+ };
+
+ exports.resolveLocalFileSystemURI = function (successCallback, errorCallback, args) {
+ var path = args[0];
+
+ // Ignore parameters
+ if (path.indexOf('?') !== -1) {
+ path = String(path).split('?')[0];
+ }
+
+ // support for encodeURI
+ if (/\%5/g.test(path) || /\%20/g.test(path)) { // eslint-disable-line no-useless-escape
+ path = decodeURI(path);
+ }
+
+ if (path.trim()[0] === '/') {
+ if (errorCallback) {
+ errorCallback(FileError.ENCODING_ERR);
+ }
+ return;
+ }
+
+ // support for cdvfile
+ if (path.trim().substr(0, 7) === 'cdvfile') {
+ if (path.indexOf('cdvfile://localhost') === -1) {
+ if (errorCallback) {
+ errorCallback(FileError.ENCODING_ERR);
+ }
+ return;
+ }
+
+ var indexPersistent = path.indexOf('persistent');
+ var indexTemporary = path.indexOf('temporary');
+
+ // cdvfile://localhost/persistent/path/to/file
+ if (indexPersistent !== -1) {
+ path = 'file:///persistent' + path.substr(indexPersistent + 10);
+ } else if (indexTemporary !== -1) {
+ path = 'file:///temporary' + path.substr(indexTemporary + 9);
+ } else {
+ if (errorCallback) {
+ errorCallback(FileError.ENCODING_ERR);
+ }
+ return;
+ }
+ }
+
+ // to avoid path form of '///path/to/file'
+ function handlePathSlashes (path) {
+ var cutIndex = 0;
+ for (var i = 0; i < path.length - 1; i++) {
+ if (path[i] === DIR_SEPARATOR && path[i + 1] === DIR_SEPARATOR) {
+ cutIndex = i + 1;
+ } else break;
+ }
+
+ return path.substr(cutIndex);
+ }
+
+ // Handle localhost containing paths (see specs )
+ if (path.indexOf('file://localhost/') === 0) {
+ path = path.replace('file://localhost/', 'file:///');
+ }
+
+ if (path.indexOf(pathsPrefix.dataDirectory) === 0) {
+ path = path.substring(pathsPrefix.dataDirectory.length - 1);
+ path = handlePathSlashes(path);
+
+ exports.requestFileSystem(function () {
+ exports.getFile(successCallback, function () {
+ exports.getDirectory(successCallback, errorCallback, [pathsPrefix.dataDirectory, path,
+ {create: false}]);
+ }, [pathsPrefix.dataDirectory, path, {create: false}]);
+ }, errorCallback, [LocalFileSystem.PERSISTENT]);
+ } else if (path.indexOf(pathsPrefix.cacheDirectory) === 0) {
+ path = path.substring(pathsPrefix.cacheDirectory.length - 1);
+ path = handlePathSlashes(path);
+
+ exports.requestFileSystem(function () {
+ exports.getFile(successCallback, function () {
+ exports.getDirectory(successCallback, errorCallback, [pathsPrefix.cacheDirectory, path,
+ {create: false}]);
+ }, [pathsPrefix.cacheDirectory, path, {create: false}]);
+ }, errorCallback, [LocalFileSystem.TEMPORARY]);
+ } else if (path.indexOf(pathsPrefix.applicationDirectory) === 0) {
+ path = path.substring(pathsPrefix.applicationDirectory.length);
+ // TODO: need to cut out redundant slashes?
+
+ var xhr = new XMLHttpRequest(); // eslint-disable-line no-undef
+ xhr.open('GET', path, true);
+ xhr.onreadystatechange = function () {
+ if (xhr.status === 200 && xhr.readyState === 4) {
+ exports.requestFileSystem(function (fs) {
+ fs.name = location.hostname; // eslint-disable-line no-undef
+
+ // TODO: need to call exports.getFile(...) to handle errors correct
+ fs.root.getFile(path, {create: true}, writeFile, errorCallback);
+ }, errorCallback, [LocalFileSystem.PERSISTENT]);
+ }
+ };
+
+ xhr.onerror = function () {
+ if (errorCallback) {
+ errorCallback(FileError.NOT_READABLE_ERR);
+ }
+ };
+
+ xhr.send();
+ } else {
+ if (errorCallback) {
+ errorCallback(FileError.NOT_FOUND_ERR);
+ }
+ }
+
+ function writeFile (entry) {
+ entry.createWriter(function (fileWriter) {
+ fileWriter.onwriteend = function (evt) {
+ if (!evt.target.error) {
+ entry.filesystemName = location.hostname; // eslint-disable-line no-undef
+ successCallback(entry);
+ }
+ };
+ fileWriter.onerror = function () {
+ if (errorCallback) {
+ errorCallback(FileError.NOT_READABLE_ERR);
+ }
+ };
+ fileWriter.write(new Blob([xhr.response])); // eslint-disable-line no-undef
+ }, errorCallback); // eslint-disable-line no-undef
+ }
+ };
+
+ exports.requestAllPaths = function (successCallback) {
+ successCallback(pathsPrefix);
+ };
+
+ /** * Helpers ***/
+
+ /**
+ * Interface to wrap the native File interface.
+ *
+ * This interface is necessary for creating zero-length (empty) files,
+ * something the Filesystem API allows you to do. Unfortunately, File's
+ * constructor cannot be called directly, making it impossible to instantiate
+ * an empty File in JS.
+ *
+ * @param {Object} opts Initial values.
+ * @constructor
+ */
+ function MyFile (opts) {
+ var blob_ = new Blob(); // eslint-disable-line no-undef
+
+ this.size = opts.size || 0;
+ this.name = opts.name || '';
+ this.type = opts.type || '';
+ this.lastModifiedDate = opts.lastModifiedDate || null;
+ this.storagePath = opts.storagePath || '';
+
+ // Need some black magic to correct the object's size/name/type based on the
+ // blob that is saved.
+ Object.defineProperty(this, 'blob_', {
+ enumerable: true,
+ get: function () {
+ return blob_;
+ },
+ set: function (val) {
+ blob_ = val;
+ this.size = blob_.size;
+ this.name = blob_.name;
+ this.type = blob_.type;
+ this.lastModifiedDate = blob_.lastModifiedDate;
+ }.bind(this)
+ });
+ }
+
+ MyFile.prototype.constructor = MyFile;
+
+ // When saving an entry, the fullPath should always lead with a slash and never
+ // end with one (e.g. a directory). Also, resolve '.' and '..' to an absolute
+ // one. This method ensures path is legit!
+ function resolveToFullPath_ (cwdFullPath, path) {
+ path = path || '';
+ var fullPath = path;
+ var prefix = '';
+
+ cwdFullPath = cwdFullPath || DIR_SEPARATOR;
+ if (cwdFullPath.indexOf(FILESYSTEM_PREFIX) === 0) {
+ prefix = cwdFullPath.substring(0, cwdFullPath.indexOf(DIR_SEPARATOR, FILESYSTEM_PREFIX.length));
+ cwdFullPath = cwdFullPath.substring(cwdFullPath.indexOf(DIR_SEPARATOR, FILESYSTEM_PREFIX.length));
+ }
+
+ var relativePath = path[0] !== DIR_SEPARATOR;
+ if (relativePath) {
+ fullPath = cwdFullPath;
+ if (cwdFullPath !== DIR_SEPARATOR) {
+ fullPath += DIR_SEPARATOR + path;
+ } else {
+ fullPath += path;
+ }
+ }
+
+ // Remove doubled separator substrings
+ var re = new RegExp(DIR_SEPARATOR + DIR_SEPARATOR, 'g');
+ fullPath = fullPath.replace(re, DIR_SEPARATOR);
+
+ // Adjust '..'s by removing parent directories when '..' flows in path.
+ var parts = fullPath.split(DIR_SEPARATOR);
+ for (var i = 0; i < parts.length; ++i) {
+ var part = parts[i];
+ if (part === '..') {
+ parts[i - 1] = '';
+ parts[i] = '';
+ }
+ }
+ fullPath = parts.filter(function (el) {
+ return el;
+ }).join(DIR_SEPARATOR);
+
+ // Add back in leading slash.
+ if (fullPath[0] !== DIR_SEPARATOR) {
+ fullPath = DIR_SEPARATOR + fullPath;
+ }
+
+ // Replace './' by current dir. ('./one/./two' -> one/two)
+ fullPath = fullPath.replace(/\.\//g, DIR_SEPARATOR);
+
+ // Replace '//' with '/'.
+ fullPath = fullPath.replace(/\/\//g, DIR_SEPARATOR);
+
+ // Replace '/.' with '/'.
+ fullPath = fullPath.replace(/\/\./g, DIR_SEPARATOR);
+
+ // Remove '/' if it appears on the end.
+ if (fullPath[fullPath.length - 1] === DIR_SEPARATOR &&
+ fullPath !== DIR_SEPARATOR) {
+ fullPath = fullPath.substring(0, fullPath.length - 1);
+ }
+
+ var storagePath = prefix + fullPath;
+ storagePath = decodeURI(storagePath);
+ fullPath = decodeURI(fullPath);
+
+ return {
+ storagePath: storagePath,
+ fullPath: fullPath,
+ fileName: fullPath.split(DIR_SEPARATOR).pop(),
+ fsName: prefix.split(DIR_SEPARATOR).pop()
+ };
+ }
+
+ function fileEntryFromIdbEntry (fileEntry) {
+ // IDB won't save methods, so we need re-create the FileEntry.
+ var clonedFileEntry = new FileEntry(fileEntry.name, fileEntry.fullPath, fileEntry.filesystem);
+ clonedFileEntry.file_ = fileEntry.file_;
+
+ return clonedFileEntry;
+ }
+
+ function readAs (what, fullPath, encoding, startPos, endPos, successCallback, errorCallback) {
+ exports.getFile(function (fileEntry) {
+ var fileReader = new FileReader(); // eslint-disable-line no-undef
+ var blob = fileEntry.file_.blob_.slice(startPos, endPos);
+
+ fileReader.onload = function (e) {
+ successCallback(e.target.result);
+ };
+
+ fileReader.onerror = errorCallback;
+
+ switch (what) {
+ case 'text':
+ fileReader.readAsText(blob, encoding);
+ break;
+ case 'dataURL':
+ fileReader.readAsDataURL(blob);
+ break;
+ case 'arrayBuffer':
+ fileReader.readAsArrayBuffer(blob);
+ break;
+ case 'binaryString':
+ fileReader.readAsBinaryString(blob);
+ break;
+ }
+
+ }, errorCallback, [fullPath, null]);
+ }
+
+ /** * Core logic to handle IDB operations ***/
+
+ idb_.open = function (dbName, successCallback, errorCallback) {
+ var self = this;
+
+ // TODO: FF 12.0a1 isn't liking a db name with : in it.
+ var request = indexedDB.open(dbName.replace(':', '_')/*, 1 /*version */);
+
+ request.onerror = errorCallback || onError;
+
+ request.onupgradeneeded = function (e) {
+ // First open was called or higher db version was used.
+
+ // console.log('onupgradeneeded: oldVersion:' + e.oldVersion,
+ // 'newVersion:' + e.newVersion);
+
+ self.db = e.target.result;
+ self.db.onerror = onError;
+
+ if (!self.db.objectStoreNames.contains(FILE_STORE_)) {
+ self.db.createObjectStore(FILE_STORE_/*, {keyPath: 'id', autoIncrement: true} */);
+ }
+ };
+
+ request.onsuccess = function (e) {
+ self.db = e.target.result;
+ self.db.onerror = onError;
+ successCallback(e);
+ };
+
+ request.onblocked = errorCallback || onError;
+ };
+
+ idb_.close = function () {
+ this.db.close();
+ this.db = null;
+ };
+
+ idb_.get = function (fullPath, successCallback, errorCallback) {
+ if (!this.db) {
+ if (errorCallback) {
+ errorCallback(FileError.INVALID_MODIFICATION_ERR);
+ }
+ return;
+ }
+
+ var tx = this.db.transaction([FILE_STORE_], 'readonly');
+
+ var request = tx.objectStore(FILE_STORE_).get(fullPath);
+
+ tx.onabort = errorCallback || onError;
+ tx.oncomplete = function () {
+ successCallback(request.result);
+ };
+ };
+
+ idb_.getAllEntries = function (fullPath, storagePath, successCallback, errorCallback) {
+ if (!this.db) {
+ if (errorCallback) {
+ errorCallback(FileError.INVALID_MODIFICATION_ERR);
+ }
+ return;
+ }
+
+ var results = [];
+
+ if (storagePath[storagePath.length - 1] === DIR_SEPARATOR) {
+ storagePath = storagePath.substring(0, storagePath.length - 1);
+ }
+
+ var range = IDBKeyRange.bound(storagePath + DIR_SEPARATOR + ' ',
+ storagePath + DIR_SEPARATOR + String.fromCharCode(unicodeLastChar));
+
+ var tx = this.db.transaction([FILE_STORE_], 'readonly');
+ tx.onabort = errorCallback || onError;
+ tx.oncomplete = function () {
+ results = results.filter(function (val) {
+ var pathWithoutSlash = val.fullPath;
+
+ if (val.fullPath[val.fullPath.length - 1] === DIR_SEPARATOR) {
+ pathWithoutSlash = pathWithoutSlash.substr(0, pathWithoutSlash.length - 1);
+ }
+
+ var valPartsLen = pathWithoutSlash.split(DIR_SEPARATOR).length;
+ var fullPathPartsLen = fullPath.split(DIR_SEPARATOR).length;
+
+ /* Input fullPath parameter equals '//' for root folder */
+ /* Entries in root folder has valPartsLen equals 2 (see below) */
+ if (fullPath[fullPath.length - 1] === DIR_SEPARATOR && fullPath.trim().length === 2) {
+ fullPathPartsLen = 1;
+ } else if (fullPath[fullPath.length - 1] === DIR_SEPARATOR) {
+ fullPathPartsLen = fullPath.substr(0, fullPath.length - 1).split(DIR_SEPARATOR).length;
+ } else {
+ fullPathPartsLen = fullPath.split(DIR_SEPARATOR).length;
+ }
+
+ if (valPartsLen === fullPathPartsLen + 1) {
+ // If this a subfolder and entry is a direct child, include it in
+ // the results. Otherwise, it's not an entry of this folder.
+ return val;
+ } else return false;
+ });
+
+ successCallback(results);
+ };
+
+ var request = tx.objectStore(FILE_STORE_).openCursor(range);
+
+ request.onsuccess = function (e) {
+ var cursor = e.target.result;
+ if (cursor) {
+ var val = cursor.value;
+
+ results.push(val.isFile ? fileEntryFromIdbEntry(val) : new DirectoryEntry(val.name, val.fullPath, val.filesystem));
+ cursor['continue']();
+ }
+ };
+ };
+
+ idb_['delete'] = function (fullPath, successCallback, errorCallback, isDirectory) {
+ if (!idb_.db) {
+ if (errorCallback) {
+ errorCallback(FileError.INVALID_MODIFICATION_ERR);
+ }
+ return;
+ }
+
+ var tx = this.db.transaction([FILE_STORE_], 'readwrite');
+ tx.oncomplete = successCallback;
+ tx.onabort = errorCallback || onError;
+ tx.oncomplete = function () {
+ if (isDirectory) {
+ // We delete nested files and folders after deleting parent folder
+ // We use ranges: https://developer.mozilla.org/en-US/docs/Web/API/IDBKeyRange
+ fullPath = fullPath + DIR_SEPARATOR;
+
+ // Range contains all entries in the form fullPath<symbol> where
+ // symbol in the range from ' ' to symbol which has code `unicodeLastChar`
+ var range = IDBKeyRange.bound(fullPath + ' ', fullPath + String.fromCharCode(unicodeLastChar));
+
+ var newTx = this.db.transaction([FILE_STORE_], 'readwrite');
+ newTx.oncomplete = successCallback;
+ newTx.onabort = errorCallback || onError;
+ newTx.objectStore(FILE_STORE_)['delete'](range);
+ } else {
+ successCallback();
+ }
+ };
+ tx.objectStore(FILE_STORE_)['delete'](fullPath);
+ };
+
+ idb_.put = function (entry, storagePath, successCallback, errorCallback) {
+ if (!this.db) {
+ if (errorCallback) {
+ errorCallback(FileError.INVALID_MODIFICATION_ERR);
+ }
+ return;
+ }
+
+ var tx = this.db.transaction([FILE_STORE_], 'readwrite');
+ tx.onabort = errorCallback || onError;
+ tx.oncomplete = function () {
+ // TODO: Error is thrown if we pass the request event back instead.
+ successCallback(entry);
+ };
+
+ tx.objectStore(FILE_STORE_).put(entry, storagePath);
+ };
+
+ // Global error handler. Errors bubble from request, to transaction, to db.
+ function onError (e) {
+ switch (e.target.errorCode) {
+ case 12:
+ console.log('Error - Attempt to open db with a lower version than the ' +
+ 'current one.');
+ break;
+ default:
+ console.log('errorCode: ' + e.target.errorCode);
+ }
+
+ console.log(e, e.code, e.message);
+ }
+
+ })(module.exports, window);
+
+ require('cordova/exec/proxy').add('File', module.exports);
+})();
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-file/www/DirectoryEntry.js b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/DirectoryEntry.js
new file mode 100644
index 0000000..7e1d3f7
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/DirectoryEntry.js
@@ -0,0 +1,119 @@
+cordova.define("cordova-plugin-file.DirectoryEntry", function(require, exports, module) { /*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+var argscheck = require('cordova/argscheck');
+var utils = require('cordova/utils');
+var exec = require('cordova/exec');
+var Entry = require('./Entry');
+var FileError = require('./FileError');
+var DirectoryReader = require('./DirectoryReader');
+
+/**
+ * An interface representing a directory on the file system.
+ *
+ * {boolean} isFile always false (readonly)
+ * {boolean} isDirectory always true (readonly)
+ * {DOMString} name of the directory, excluding the path leading to it (readonly)
+ * {DOMString} fullPath the absolute full path to the directory (readonly)
+ * {FileSystem} filesystem on which the directory resides (readonly)
+ */
+var DirectoryEntry = function (name, fullPath, fileSystem, nativeURL) {
+
+ // add trailing slash if it is missing
+ if ((fullPath) && !/\/$/.test(fullPath)) {
+ fullPath += '/';
+ }
+ // add trailing slash if it is missing
+ if (nativeURL && !/\/$/.test(nativeURL)) {
+ nativeURL += '/';
+ }
+ DirectoryEntry.__super__.constructor.call(this, false, true, name, fullPath, fileSystem, nativeURL);
+};
+
+utils.extend(DirectoryEntry, Entry);
+
+/**
+ * Creates a new DirectoryReader to read entries from this directory
+ */
+DirectoryEntry.prototype.createReader = function () {
+ return new DirectoryReader(this.toInternalURL());
+};
+
+/**
+ * Creates or looks up a directory
+ *
+ * @param {DOMString} path either a relative or absolute path from this directory in which to look up or create a directory
+ * @param {Flags} options to create or exclusively create the directory
+ * @param {Function} successCallback is called with the new entry
+ * @param {Function} errorCallback is called with a FileError
+ */
+DirectoryEntry.prototype.getDirectory = function (path, options, successCallback, errorCallback) {
+ argscheck.checkArgs('sOFF', 'DirectoryEntry.getDirectory', arguments);
+ var fs = this.filesystem;
+ var win = successCallback && function (result) {
+ var entry = new DirectoryEntry(result.name, result.fullPath, fs, result.nativeURL);
+ successCallback(entry);
+ };
+ var fail = errorCallback && function (code) {
+ errorCallback(new FileError(code));
+ };
+ exec(win, fail, 'File', 'getDirectory', [this.toInternalURL(), path, options]);
+};
+
+/**
+ * Deletes a directory and all of it's contents
+ *
+ * @param {Function} successCallback is called with no parameters
+ * @param {Function} errorCallback is called with a FileError
+ */
+DirectoryEntry.prototype.removeRecursively = function (successCallback, errorCallback) {
+ argscheck.checkArgs('FF', 'DirectoryEntry.removeRecursively', arguments);
+ var fail = errorCallback && function (code) {
+ errorCallback(new FileError(code));
+ };
+ exec(successCallback, fail, 'File', 'removeRecursively', [this.toInternalURL()]);
+};
+
+/**
+ * Creates or looks up a file
+ *
+ * @param {DOMString} path either a relative or absolute path from this directory in which to look up or create a file
+ * @param {Flags} options to create or exclusively create the file
+ * @param {Function} successCallback is called with the new entry
+ * @param {Function} errorCallback is called with a FileError
+ */
+DirectoryEntry.prototype.getFile = function (path, options, successCallback, errorCallback) {
+ argscheck.checkArgs('sOFF', 'DirectoryEntry.getFile', arguments);
+ var fs = this.filesystem;
+ var win = successCallback && function (result) {
+ var FileEntry = require('./FileEntry');
+ var entry = new FileEntry(result.name, result.fullPath, fs, result.nativeURL);
+ successCallback(entry);
+ };
+ var fail = errorCallback && function (code) {
+ errorCallback(new FileError(code));
+ };
+ exec(win, fail, 'File', 'getFile', [this.toInternalURL(), path, options]);
+};
+
+module.exports = DirectoryEntry;
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-file/www/DirectoryReader.js b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/DirectoryReader.js
new file mode 100644
index 0000000..ce74ade
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/DirectoryReader.js
@@ -0,0 +1,74 @@
+cordova.define("cordova-plugin-file.DirectoryReader", function(require, exports, module) { /*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+var exec = require('cordova/exec');
+var FileError = require('./FileError');
+
+/**
+ * An interface that lists the files and directories in a directory.
+ */
+function DirectoryReader (localURL) {
+ this.localURL = localURL || null;
+ this.hasReadEntries = false;
+}
+
+/**
+ * Returns a list of entries from a directory.
+ *
+ * @param {Function} successCallback is called with a list of entries
+ * @param {Function} errorCallback is called with a FileError
+ */
+DirectoryReader.prototype.readEntries = function (successCallback, errorCallback) {
+ // If we've already read and passed on this directory's entries, return an empty list.
+ if (this.hasReadEntries) {
+ successCallback([]);
+ return;
+ }
+ var reader = this;
+ var win = typeof successCallback !== 'function' ? null : function (result) {
+ var retVal = [];
+ for (var i = 0; i < result.length; i++) {
+ var entry = null;
+ if (result[i].isDirectory) {
+ entry = new (require('./DirectoryEntry'))();
+ } else if (result[i].isFile) {
+ entry = new (require('./FileEntry'))();
+ }
+ entry.isDirectory = result[i].isDirectory;
+ entry.isFile = result[i].isFile;
+ entry.name = result[i].name;
+ entry.fullPath = result[i].fullPath;
+ entry.filesystem = new (require('./FileSystem'))(result[i].filesystemName);
+ entry.nativeURL = result[i].nativeURL;
+ retVal.push(entry);
+ }
+ reader.hasReadEntries = true;
+ successCallback(retVal);
+ };
+ var fail = typeof errorCallback !== 'function' ? null : function (code) {
+ errorCallback(new FileError(code));
+ };
+ exec(win, fail, 'File', 'readEntries', [this.localURL]);
+};
+
+module.exports = DirectoryReader;
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-file/www/Entry.js b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/Entry.js
new file mode 100644
index 0000000..973cf14
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/Entry.js
@@ -0,0 +1,262 @@
+cordova.define("cordova-plugin-file.Entry", function(require, exports, module) { /*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+var argscheck = require('cordova/argscheck');
+var exec = require('cordova/exec');
+var FileError = require('./FileError');
+var Metadata = require('./Metadata');
+
+/**
+ * Represents a file or directory on the local file system.
+ *
+ * @param isFile
+ * {boolean} true if Entry is a file (readonly)
+ * @param isDirectory
+ * {boolean} true if Entry is a directory (readonly)
+ * @param name
+ * {DOMString} name of the file or directory, excluding the path
+ * leading to it (readonly)
+ * @param fullPath
+ * {DOMString} the absolute full path to the file or directory
+ * (readonly)
+ * @param fileSystem
+ * {FileSystem} the filesystem on which this entry resides
+ * (readonly)
+ * @param nativeURL
+ * {DOMString} an alternate URL which can be used by native
+ * webview controls, for example media players.
+ * (optional, readonly)
+ */
+function Entry (isFile, isDirectory, name, fullPath, fileSystem, nativeURL) {
+ this.isFile = !!isFile;
+ this.isDirectory = !!isDirectory;
+ this.name = name || '';
+ this.fullPath = fullPath || '';
+ this.filesystem = fileSystem || null;
+ this.nativeURL = nativeURL || null;
+}
+
+/**
+ * Look up the metadata of the entry.
+ *
+ * @param successCallback
+ * {Function} is called with a Metadata object
+ * @param errorCallback
+ * {Function} is called with a FileError
+ */
+Entry.prototype.getMetadata = function (successCallback, errorCallback) {
+ argscheck.checkArgs('FF', 'Entry.getMetadata', arguments);
+ var success = successCallback && function (entryMetadata) {
+ var metadata = new Metadata({
+ size: entryMetadata.size,
+ modificationTime: entryMetadata.lastModifiedDate
+ });
+ successCallback(metadata);
+ };
+ var fail = errorCallback && function (code) {
+ errorCallback(new FileError(code));
+ };
+ exec(success, fail, 'File', 'getFileMetadata', [this.toInternalURL()]);
+};
+
+/**
+ * Set the metadata of the entry.
+ *
+ * @param successCallback
+ * {Function} is called with a Metadata object
+ * @param errorCallback
+ * {Function} is called with a FileError
+ * @param metadataObject
+ * {Object} keys and values to set
+ */
+Entry.prototype.setMetadata = function (successCallback, errorCallback, metadataObject) {
+ argscheck.checkArgs('FFO', 'Entry.setMetadata', arguments);
+ exec(successCallback, errorCallback, 'File', 'setMetadata', [this.toInternalURL(), metadataObject]);
+};
+
+/**
+ * Move a file or directory to a new location.
+ *
+ * @param parent
+ * {DirectoryEntry} the directory to which to move this entry
+ * @param newName
+ * {DOMString} new name of the entry, defaults to the current name
+ * @param successCallback
+ * {Function} called with the new DirectoryEntry object
+ * @param errorCallback
+ * {Function} called with a FileError
+ */
+Entry.prototype.moveTo = function (parent, newName, successCallback, errorCallback) {
+ argscheck.checkArgs('oSFF', 'Entry.moveTo', arguments);
+ var fail = errorCallback && function (code) {
+ errorCallback(new FileError(code));
+ };
+ var srcURL = this.toInternalURL();
+ // entry name
+ var name = newName || this.name;
+ var success = function (entry) {
+ if (entry) {
+ if (successCallback) {
+ // create appropriate Entry object
+ var newFSName = entry.filesystemName || (entry.filesystem && entry.filesystem.name);
+ var fs = newFSName ? new FileSystem(newFSName, { name: '', fullPath: '/' }) : new FileSystem(parent.filesystem.name, { name: '', fullPath: '/' }); // eslint-disable-line no-undef
+ var result = (entry.isDirectory) ? new (require('./DirectoryEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL) : new (require('cordova-plugin-file.FileEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL);
+ successCallback(result);
+ }
+ } else {
+ // no Entry object returned
+ if (fail) {
+ fail(FileError.NOT_FOUND_ERR);
+ }
+ }
+ };
+
+ // copy
+ exec(success, fail, 'File', 'moveTo', [srcURL, parent.toInternalURL(), name]);
+};
+
+/**
+ * Copy a directory to a different location.
+ *
+ * @param parent
+ * {DirectoryEntry} the directory to which to copy the entry
+ * @param newName
+ * {DOMString} new name of the entry, defaults to the current name
+ * @param successCallback
+ * {Function} called with the new Entry object
+ * @param errorCallback
+ * {Function} called with a FileError
+ */
+Entry.prototype.copyTo = function (parent, newName, successCallback, errorCallback) {
+ argscheck.checkArgs('oSFF', 'Entry.copyTo', arguments);
+ var fail = errorCallback && function (code) {
+ errorCallback(new FileError(code));
+ };
+ var srcURL = this.toInternalURL();
+ // entry name
+ var name = newName || this.name;
+ // success callback
+ var success = function (entry) {
+ if (entry) {
+ if (successCallback) {
+ // create appropriate Entry object
+ var newFSName = entry.filesystemName || (entry.filesystem && entry.filesystem.name);
+ var fs = newFSName ? new FileSystem(newFSName, { name: '', fullPath: '/' }) : new FileSystem(parent.filesystem.name, { name: '', fullPath: '/' }); // eslint-disable-line no-undef
+ var result = (entry.isDirectory) ? new (require('./DirectoryEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL) : new (require('cordova-plugin-file.FileEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL);
+ successCallback(result);
+ }
+ } else {
+ // no Entry object returned
+ if (fail) {
+ fail(FileError.NOT_FOUND_ERR);
+ }
+ }
+ };
+
+ // copy
+ exec(success, fail, 'File', 'copyTo', [srcURL, parent.toInternalURL(), name]);
+};
+
+/**
+ * Return a URL that can be passed across the bridge to identify this entry.
+ */
+Entry.prototype.toInternalURL = function () {
+ if (this.filesystem && this.filesystem.__format__) {
+ return this.filesystem.__format__(this.fullPath, this.nativeURL);
+ }
+};
+
+/**
+ * Return a URL that can be used to identify this entry.
+ * Use a URL that can be used to as the src attribute of a <video> or
+ * <audio> tag. If that is not possible, construct a cdvfile:// URL.
+ */
+Entry.prototype.toURL = function () {
+ if (this.nativeURL) {
+ return this.nativeURL;
+ }
+ // fullPath attribute may contain the full URL in the case that
+ // toInternalURL fails.
+ return this.toInternalURL() || 'file://localhost' + this.fullPath;
+};
+
+/**
+ * Backwards-compatibility: In v1.0.0 - 1.0.2, .toURL would only return a
+ * cdvfile:// URL, and this method was necessary to obtain URLs usable by the
+ * webview.
+ * See CB-6051, CB-6106, CB-6117, CB-6152, CB-6199, CB-6201, CB-6243, CB-6249,
+ * and CB-6300.
+ */
+Entry.prototype.toNativeURL = function () {
+ console.log("DEPRECATED: Update your code to use 'toURL'");
+ return this.toURL();
+};
+
+/**
+ * Returns a URI that can be used to identify this entry.
+ *
+ * @param {DOMString} mimeType for a FileEntry, the mime type to be used to interpret the file, when loaded through this URI.
+ * @return uri
+ */
+Entry.prototype.toURI = function (mimeType) {
+ console.log("DEPRECATED: Update your code to use 'toURL'");
+ return this.toURL();
+};
+
+/**
+ * Remove a file or directory. It is an error to attempt to delete a
+ * directory that is not empty. It is an error to attempt to delete a
+ * root directory of a file system.
+ *
+ * @param successCallback {Function} called with no parameters
+ * @param errorCallback {Function} called with a FileError
+ */
+Entry.prototype.remove = function (successCallback, errorCallback) {
+ argscheck.checkArgs('FF', 'Entry.remove', arguments);
+ var fail = errorCallback && function (code) {
+ errorCallback(new FileError(code));
+ };
+ exec(successCallback, fail, 'File', 'remove', [this.toInternalURL()]);
+};
+
+/**
+ * Look up the parent DirectoryEntry of this entry.
+ *
+ * @param successCallback {Function} called with the parent DirectoryEntry object
+ * @param errorCallback {Function} called with a FileError
+ */
+Entry.prototype.getParent = function (successCallback, errorCallback) {
+ argscheck.checkArgs('FF', 'Entry.getParent', arguments);
+ var fs = this.filesystem;
+ var win = successCallback && function (result) {
+ var DirectoryEntry = require('./DirectoryEntry');
+ var entry = new DirectoryEntry(result.name, result.fullPath, fs, result.nativeURL);
+ successCallback(entry);
+ };
+ var fail = errorCallback && function (code) {
+ errorCallback(new FileError(code));
+ };
+ exec(win, fail, 'File', 'getParent', [this.toInternalURL()]);
+};
+
+module.exports = Entry;
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-file/www/File.js b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/File.js
new file mode 100644
index 0000000..974b09f
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/File.js
@@ -0,0 +1,80 @@
+cordova.define("cordova-plugin-file.File", function(require, exports, module) { /*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+/**
+ * Constructor.
+ * name {DOMString} name of the file, without path information
+ * fullPath {DOMString} the full path of the file, including the name
+ * type {DOMString} mime type
+ * lastModifiedDate {Date} last modified date
+ * size {Number} size of the file in bytes
+ */
+
+var File = function (name, localURL, type, lastModifiedDate, size) {
+ this.name = name || '';
+ this.localURL = localURL || null;
+ this.type = type || null;
+ this.lastModified = lastModifiedDate || null;
+ // For backwards compatibility, store the timestamp in lastModifiedDate as well
+ this.lastModifiedDate = lastModifiedDate || null;
+ this.size = size || 0;
+
+ // These store the absolute start and end for slicing the file.
+ this.start = 0;
+ this.end = this.size;
+};
+
+/**
+ * Returns a "slice" of the file. Since Cordova Files don't contain the actual
+ * content, this really returns a File with adjusted start and end.
+ * Slices of slices are supported.
+ * start {Number} The index at which to start the slice (inclusive).
+ * end {Number} The index at which to end the slice (exclusive).
+ */
+File.prototype.slice = function (start, end) {
+ var size = this.end - this.start;
+ var newStart = 0;
+ var newEnd = size;
+ if (arguments.length) {
+ if (start < 0) {
+ newStart = Math.max(size + start, 0);
+ } else {
+ newStart = Math.min(size, start);
+ }
+ }
+
+ if (arguments.length >= 2) {
+ if (end < 0) {
+ newEnd = Math.max(size + end, 0);
+ } else {
+ newEnd = Math.min(end, size);
+ }
+ }
+
+ var newFile = new File(this.name, this.localURL, this.type, this.lastModified, this.size);
+ newFile.start = this.start + newStart;
+ newFile.end = this.start + newEnd;
+ return newFile;
+};
+
+module.exports = File;
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-file/www/FileEntry.js b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/FileEntry.js
new file mode 100644
index 0000000..b16c851
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/FileEntry.js
@@ -0,0 +1,94 @@
+cordova.define("cordova-plugin-file.FileEntry", function(require, exports, module) { /*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+var utils = require('cordova/utils');
+var exec = require('cordova/exec');
+var Entry = require('./Entry');
+var FileWriter = require('./FileWriter');
+var File = require('./File');
+var FileError = require('./FileError');
+
+/**
+ * An interface representing a file on the file system.
+ *
+ * {boolean} isFile always true (readonly)
+ * {boolean} isDirectory always false (readonly)
+ * {DOMString} name of the file, excluding the path leading to it (readonly)
+ * {DOMString} fullPath the absolute full path to the file (readonly)
+ * {FileSystem} filesystem on which the file resides (readonly)
+ */
+var FileEntry = function (name, fullPath, fileSystem, nativeURL) {
+ // remove trailing slash if it is present
+ if (fullPath && /\/$/.test(fullPath)) {
+ fullPath = fullPath.substring(0, fullPath.length - 1);
+ }
+ if (nativeURL && /\/$/.test(nativeURL)) {
+ nativeURL = nativeURL.substring(0, nativeURL.length - 1);
+ }
+
+ FileEntry.__super__.constructor.apply(this, [true, false, name, fullPath, fileSystem, nativeURL]);
+};
+
+utils.extend(FileEntry, Entry);
+
+/**
+ * Creates a new FileWriter associated with the file that this FileEntry represents.
+ *
+ * @param {Function} successCallback is called with the new FileWriter
+ * @param {Function} errorCallback is called with a FileError
+ */
+FileEntry.prototype.createWriter = function (successCallback, errorCallback) {
+ this.file(function (filePointer) {
+ var writer = new FileWriter(filePointer);
+
+ if (writer.localURL === null || writer.localURL === '') {
+ if (errorCallback) {
+ errorCallback(new FileError(FileError.INVALID_STATE_ERR));
+ }
+ } else {
+ if (successCallback) {
+ successCallback(writer);
+ }
+ }
+ }, errorCallback);
+};
+
+/**
+ * Returns a File that represents the current state of the file that this FileEntry represents.
+ *
+ * @param {Function} successCallback is called with the new File object
+ * @param {Function} errorCallback is called with a FileError
+ */
+FileEntry.prototype.file = function (successCallback, errorCallback) {
+ var localURL = this.toInternalURL();
+ var win = successCallback && function (f) {
+ var file = new File(f.name, localURL, f.type, f.lastModifiedDate, f.size);
+ successCallback(file);
+ };
+ var fail = errorCallback && function (code) {
+ errorCallback(new FileError(code));
+ };
+ exec(win, fail, 'File', 'getFileMetadata', [localURL]);
+};
+
+module.exports = FileEntry;
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-file/www/FileError.js b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/FileError.js
new file mode 100644
index 0000000..7a0a66e
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/FileError.js
@@ -0,0 +1,48 @@
+cordova.define("cordova-plugin-file.FileError", function(require, exports, module) { /*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+/**
+ * FileError
+ */
+function FileError (error) {
+ this.code = error || null;
+}
+
+// File error codes
+// Found in DOMException
+FileError.NOT_FOUND_ERR = 1;
+FileError.SECURITY_ERR = 2;
+FileError.ABORT_ERR = 3;
+
+// Added by File API specification
+FileError.NOT_READABLE_ERR = 4;
+FileError.ENCODING_ERR = 5;
+FileError.NO_MODIFICATION_ALLOWED_ERR = 6;
+FileError.INVALID_STATE_ERR = 7;
+FileError.SYNTAX_ERR = 8;
+FileError.INVALID_MODIFICATION_ERR = 9;
+FileError.QUOTA_EXCEEDED_ERR = 10;
+FileError.TYPE_MISMATCH_ERR = 11;
+FileError.PATH_EXISTS_ERR = 12;
+
+module.exports = FileError;
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-file/www/FileReader.js b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/FileReader.js
new file mode 100644
index 0000000..1227dd8
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/FileReader.js
@@ -0,0 +1,300 @@
+cordova.define("cordova-plugin-file.FileReader", function(require, exports, module) { /*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+var exec = require('cordova/exec');
+var modulemapper = require('cordova/modulemapper');
+var utils = require('cordova/utils');
+var FileError = require('./FileError');
+var ProgressEvent = require('./ProgressEvent');
+var origFileReader = modulemapper.getOriginalSymbol(window, 'FileReader');
+
+/**
+ * This class reads the mobile device file system.
+ *
+ * For Android:
+ * The root directory is the root of the file system.
+ * To read from the SD card, the file name is "sdcard/my_file.txt"
+ * @constructor
+ */
+var FileReader = function () {
+ this._readyState = 0;
+ this._error = null;
+ this._result = null;
+ this._progress = null;
+ this._localURL = '';
+ this._realReader = origFileReader ? new origFileReader() : {}; // eslint-disable-line new-cap
+};
+
+/**
+ * Defines the maximum size to read at a time via the native API. The default value is a compromise between
+ * minimizing the overhead of many exec() calls while still reporting progress frequently enough for large files.
+ * (Note attempts to allocate more than a few MB of contiguous memory on the native side are likely to cause
+ * OOM exceptions, while the JS engine seems to have fewer problems managing large strings or ArrayBuffers.)
+ */
+FileReader.READ_CHUNK_SIZE = 256 * 1024;
+
+// States
+FileReader.EMPTY = 0;
+FileReader.LOADING = 1;
+FileReader.DONE = 2;
+
+utils.defineGetter(FileReader.prototype, 'readyState', function () {
+ return this._localURL ? this._readyState : this._realReader.readyState;
+});
+
+utils.defineGetter(FileReader.prototype, 'error', function () {
+ return this._localURL ? this._error : this._realReader.error;
+});
+
+utils.defineGetter(FileReader.prototype, 'result', function () {
+ return this._localURL ? this._result : this._realReader.result;
+});
+
+function defineEvent (eventName) {
+ utils.defineGetterSetter(FileReader.prototype, eventName, function () {
+ return this._realReader[eventName] || null;
+ }, function (value) {
+ this._realReader[eventName] = value;
+ });
+}
+defineEvent('onloadstart'); // When the read starts.
+defineEvent('onprogress'); // While reading (and decoding) file or fileBlob data, and reporting partial file data (progress.loaded/progress.total)
+defineEvent('onload'); // When the read has successfully completed.
+defineEvent('onerror'); // When the read has failed (see errors).
+defineEvent('onloadend'); // When the request has completed (either in success or failure).
+defineEvent('onabort'); // When the read has been aborted. For instance, by invoking the abort() method.
+
+function initRead (reader, file) {
+ // Already loading something
+ if (reader.readyState === FileReader.LOADING) {
+ throw new FileError(FileError.INVALID_STATE_ERR);
+ }
+
+ reader._result = null;
+ reader._error = null;
+ reader._progress = 0;
+ reader._readyState = FileReader.LOADING;
+
+ if (typeof file.localURL === 'string') {
+ reader._localURL = file.localURL;
+ } else {
+ reader._localURL = '';
+ return true;
+ }
+
+ if (reader.onloadstart) {
+ reader.onloadstart(new ProgressEvent('loadstart', {target: reader}));
+ }
+}
+
+/**
+ * Callback used by the following read* functions to handle incremental or final success.
+ * Must be bound to the FileReader's this along with all but the last parameter,
+ * e.g. readSuccessCallback.bind(this, "readAsText", "UTF-8", offset, totalSize, accumulate)
+ * @param readType The name of the read function to call.
+ * @param encoding Text encoding, or null if this is not a text type read.
+ * @param offset Starting offset of the read.
+ * @param totalSize Total number of bytes or chars to read.
+ * @param accumulate A function that takes the callback result and accumulates it in this._result.
+ * @param r Callback result returned by the last read exec() call, or null to begin reading.
+ */
+function readSuccessCallback (readType, encoding, offset, totalSize, accumulate, r) {
+ if (this._readyState === FileReader.DONE) {
+ return;
+ }
+
+ var CHUNK_SIZE = FileReader.READ_CHUNK_SIZE;
+ if (readType === 'readAsDataURL') {
+ // Windows proxy does not support reading file slices as Data URLs
+ // so read the whole file at once.
+ CHUNK_SIZE = cordova.platformId === 'windows' ? totalSize : // eslint-disable-line no-undef
+ // Calculate new chunk size for data URLs to be multiply of 3
+ // Otherwise concatenated base64 chunks won't be valid base64 data
+ FileReader.READ_CHUNK_SIZE - (FileReader.READ_CHUNK_SIZE % 3) + 3;
+ }
+
+ if (typeof r !== 'undefined') {
+ accumulate(r);
+ this._progress = Math.min(this._progress + CHUNK_SIZE, totalSize);
+
+ if (typeof this.onprogress === 'function') {
+ this.onprogress(new ProgressEvent('progress', {loaded: this._progress, total: totalSize}));
+ }
+ }
+
+ if (typeof r === 'undefined' || this._progress < totalSize) {
+ var execArgs = [
+ this._localURL,
+ offset + this._progress,
+ offset + this._progress + Math.min(totalSize - this._progress, CHUNK_SIZE)];
+ if (encoding) {
+ execArgs.splice(1, 0, encoding);
+ }
+ exec(
+ readSuccessCallback.bind(this, readType, encoding, offset, totalSize, accumulate),
+ readFailureCallback.bind(this),
+ 'File', readType, execArgs);
+ } else {
+ this._readyState = FileReader.DONE;
+
+ if (typeof this.onload === 'function') {
+ this.onload(new ProgressEvent('load', {target: this}));
+ }
+
+ if (typeof this.onloadend === 'function') {
+ this.onloadend(new ProgressEvent('loadend', {target: this}));
+ }
+ }
+}
+
+/**
+ * Callback used by the following read* functions to handle errors.
+ * Must be bound to the FileReader's this, e.g. readFailureCallback.bind(this)
+ */
+function readFailureCallback (e) {
+ if (this._readyState === FileReader.DONE) {
+ return;
+ }
+
+ this._readyState = FileReader.DONE;
+ this._result = null;
+ this._error = new FileError(e);
+
+ if (typeof this.onerror === 'function') {
+ this.onerror(new ProgressEvent('error', {target: this}));
+ }
+
+ if (typeof this.onloadend === 'function') {
+ this.onloadend(new ProgressEvent('loadend', {target: this}));
+ }
+}
+
+/**
+ * Abort reading file.
+ */
+FileReader.prototype.abort = function () {
+ if (origFileReader && !this._localURL) {
+ return this._realReader.abort();
+ }
+ this._result = null;
+
+ if (this._readyState === FileReader.DONE || this._readyState === FileReader.EMPTY) {
+ return;
+ }
+
+ this._readyState = FileReader.DONE;
+
+ // If abort callback
+ if (typeof this.onabort === 'function') {
+ this.onabort(new ProgressEvent('abort', {target: this}));
+ }
+ // If load end callback
+ if (typeof this.onloadend === 'function') {
+ this.onloadend(new ProgressEvent('loadend', {target: this}));
+ }
+};
+
+/**
+ * Read text file.
+ *
+ * @param file {File} File object containing file properties
+ * @param encoding [Optional] (see http://www.iana.org/assignments/character-sets)
+ */
+FileReader.prototype.readAsText = function (file, encoding) {
+ if (initRead(this, file)) {
+ return this._realReader.readAsText(file, encoding);
+ }
+
+ // Default encoding is UTF-8
+ var enc = encoding || 'UTF-8';
+
+ var totalSize = file.end - file.start;
+ readSuccessCallback.bind(this)('readAsText', enc, file.start, totalSize, function (r) {
+ if (this._progress === 0) {
+ this._result = '';
+ }
+ this._result += r;
+ }.bind(this));
+};
+
+/**
+ * Read file and return data as a base64 encoded data url.
+ * A data url is of the form:
+ * data:[<mediatype>][;base64],<data>
+ *
+ * @param file {File} File object containing file properties
+ */
+FileReader.prototype.readAsDataURL = function (file) {
+ if (initRead(this, file)) {
+ return this._realReader.readAsDataURL(file);
+ }
+
+ var totalSize = file.end - file.start;
+ readSuccessCallback.bind(this)('readAsDataURL', null, file.start, totalSize, function (r) {
+ var commaIndex = r.indexOf(',');
+ if (this._progress === 0) {
+ this._result = r;
+ } else {
+ this._result += r.substring(commaIndex + 1);
+ }
+ }.bind(this));
+};
+
+/**
+ * Read file and return data as a binary data.
+ *
+ * @param file {File} File object containing file properties
+ */
+FileReader.prototype.readAsBinaryString = function (file) {
+ if (initRead(this, file)) {
+ return this._realReader.readAsBinaryString(file);
+ }
+
+ var totalSize = file.end - file.start;
+ readSuccessCallback.bind(this)('readAsBinaryString', null, file.start, totalSize, function (r) {
+ if (this._progress === 0) {
+ this._result = '';
+ }
+ this._result += r;
+ }.bind(this));
+};
+
+/**
+ * Read file and return data as a binary data.
+ *
+ * @param file {File} File object containing file properties
+ */
+FileReader.prototype.readAsArrayBuffer = function (file) {
+ if (initRead(this, file)) {
+ return this._realReader.readAsArrayBuffer(file);
+ }
+
+ var totalSize = file.end - file.start;
+ readSuccessCallback.bind(this)('readAsArrayBuffer', null, file.start, totalSize, function (r) {
+ var resultArray = (this._progress === 0 ? new Uint8Array(totalSize) : new Uint8Array(this._result));
+ resultArray.set(new Uint8Array(r), this._progress);
+ this._result = resultArray.buffer;
+ }.bind(this));
+};
+
+module.exports = FileReader;
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-file/www/FileSystem.js b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/FileSystem.js
new file mode 100644
index 0000000..f7e751e
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/FileSystem.js
@@ -0,0 +1,57 @@
+cordova.define("cordova-plugin-file.FileSystem", function(require, exports, module) { /*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+var DirectoryEntry = require('./DirectoryEntry');
+
+/**
+ * An interface representing a file system
+ *
+ * @constructor
+ * {DOMString} name the unique name of the file system (readonly)
+ * {DirectoryEntry} root directory of the file system (readonly)
+ */
+var FileSystem = function (name, root) {
+ this.name = name;
+ if (root) {
+ this.root = new DirectoryEntry(root.name, root.fullPath, this, root.nativeURL);
+ } else {
+ this.root = new DirectoryEntry(this.name, '/', this);
+ }
+};
+
+FileSystem.prototype.__format__ = function (fullPath, nativeUrl) {
+ return fullPath;
+};
+
+FileSystem.prototype.toJSON = function () {
+ return '<FileSystem: ' + this.name + '>';
+};
+
+// Use instead of encodeURI() when encoding just the path part of a URI rather than an entire URI.
+FileSystem.encodeURIPath = function (path) {
+ // Because # is a valid filename character, it must be encoded to prevent part of the
+ // path from being parsed as a URI fragment.
+ return encodeURI(path).replace(/#/g, '%23');
+};
+
+module.exports = FileSystem;
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-file/www/FileUploadOptions.js b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/FileUploadOptions.js
new file mode 100644
index 0000000..908091b
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/FileUploadOptions.js
@@ -0,0 +1,43 @@
+cordova.define("cordova-plugin-file.FileUploadOptions", function(require, exports, module) { /*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+/**
+ * Options to customize the HTTP request used to upload files.
+ * @constructor
+ * @param fileKey {String} Name of file request parameter.
+ * @param fileName {String} Filename to be used by the server. Defaults to image.jpg.
+ * @param mimeType {String} Mimetype of the uploaded file. Defaults to image/jpeg.
+ * @param params {Object} Object with key: value params to send to the server.
+ * @param headers {Object} Keys are header names, values are header values. Multiple
+ * headers of the same name are not supported.
+ */
+var FileUploadOptions = function (fileKey, fileName, mimeType, params, headers, httpMethod) {
+ this.fileKey = fileKey || null;
+ this.fileName = fileName || null;
+ this.mimeType = mimeType || null;
+ this.params = params || null;
+ this.headers = headers || null;
+ this.httpMethod = httpMethod || null;
+};
+
+module.exports = FileUploadOptions;
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-file/www/FileUploadResult.js b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/FileUploadResult.js
new file mode 100644
index 0000000..a94cb9a
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/FileUploadResult.js
@@ -0,0 +1,32 @@
+cordova.define("cordova-plugin-file.FileUploadResult", function(require, exports, module) { /*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+/**
+ * FileUploadResult
+ * @constructor
+ */
+module.exports = function FileUploadResult (size, code, content) {
+ this.bytesSent = size;
+ this.responseCode = code;
+ this.response = content;
+};
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-file/www/FileWriter.js b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/FileWriter.js
new file mode 100644
index 0000000..1f978bb
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/FileWriter.js
@@ -0,0 +1,326 @@
+cordova.define("cordova-plugin-file.FileWriter", function(require, exports, module) { /*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+var exec = require('cordova/exec');
+var FileError = require('./FileError');
+var ProgressEvent = require('./ProgressEvent');
+
+/**
+ * This class writes to the mobile device file system.
+ *
+ * For Android:
+ * The root directory is the root of the file system.
+ * To write to the SD card, the file name is "sdcard/my_file.txt"
+ *
+ * @constructor
+ * @param file {File} File object containing file properties
+ * @param append if true write to the end of the file, otherwise overwrite the file
+ */
+var FileWriter = function (file) {
+ this.fileName = '';
+ this.length = 0;
+ if (file) {
+ this.localURL = file.localURL || file;
+ this.length = file.size || 0;
+ }
+ // default is to write at the beginning of the file
+ this.position = 0;
+
+ this.readyState = 0; // EMPTY
+
+ this.result = null;
+
+ // Error
+ this.error = null;
+
+ // Event handlers
+ this.onwritestart = null; // When writing starts
+ this.onprogress = null; // While writing the file, and reporting partial file data
+ this.onwrite = null; // When the write has successfully completed.
+ this.onwriteend = null; // When the request has completed (either in success or failure).
+ this.onabort = null; // When the write has been aborted. For instance, by invoking the abort() method.
+ this.onerror = null; // When the write has failed (see errors).
+};
+
+// States
+FileWriter.INIT = 0;
+FileWriter.WRITING = 1;
+FileWriter.DONE = 2;
+
+/**
+ * Abort writing file.
+ */
+FileWriter.prototype.abort = function () {
+ // check for invalid state
+ if (this.readyState === FileWriter.DONE || this.readyState === FileWriter.INIT) {
+ throw new FileError(FileError.INVALID_STATE_ERR);
+ }
+
+ // set error
+ this.error = new FileError(FileError.ABORT_ERR);
+
+ this.readyState = FileWriter.DONE;
+
+ // If abort callback
+ if (typeof this.onabort === 'function') {
+ this.onabort(new ProgressEvent('abort', {'target': this}));
+ }
+
+ // If write end callback
+ if (typeof this.onwriteend === 'function') {
+ this.onwriteend(new ProgressEvent('writeend', {'target': this}));
+ }
+};
+
+/**
+ * Writes data to the file
+ *
+ * @param data text or blob to be written
+ * @param isPendingBlobReadResult {Boolean} true if the data is the pending blob read operation result
+ */
+FileWriter.prototype.write = function (data, isPendingBlobReadResult) {
+
+ var that = this;
+ var supportsBinary = (typeof window.Blob !== 'undefined' && typeof window.ArrayBuffer !== 'undefined');
+ /* eslint-disable no-undef */
+ var isProxySupportBlobNatively = (cordova.platformId === 'windows8' || cordova.platformId === 'windows');
+ var isBinary;
+
+ // Check to see if the incoming data is a blob
+ if (data instanceof File || (!isProxySupportBlobNatively && supportsBinary && data instanceof Blob)) {
+ var fileReader = new FileReader();
+ /* eslint-enable no-undef */
+ fileReader.onload = function () {
+ // Call this method again, with the arraybuffer as argument
+ FileWriter.prototype.write.call(that, this.result, true /* isPendingBlobReadResult */);
+ };
+ fileReader.onerror = function () {
+ // DONE state
+ that.readyState = FileWriter.DONE;
+
+ // Save error
+ that.error = this.error;
+
+ // If onerror callback
+ if (typeof that.onerror === 'function') {
+ that.onerror(new ProgressEvent('error', {'target': that}));
+ }
+
+ // If onwriteend callback
+ if (typeof that.onwriteend === 'function') {
+ that.onwriteend(new ProgressEvent('writeend', {'target': that}));
+ }
+ };
+
+ // WRITING state
+ this.readyState = FileWriter.WRITING;
+
+ if (supportsBinary) {
+ fileReader.readAsArrayBuffer(data);
+ } else {
+ fileReader.readAsText(data);
+ }
+ return;
+ }
+
+ // Mark data type for safer transport over the binary bridge
+ isBinary = supportsBinary && (data instanceof ArrayBuffer);
+ if (isBinary && cordova.platformId === 'windowsphone') { // eslint-disable-line no-undef
+ // create a plain array, using the keys from the Uint8Array view so that we can serialize it
+ data = Array.apply(null, new Uint8Array(data));
+ }
+
+ // Throw an exception if we are already writing a file
+ if (this.readyState === FileWriter.WRITING && !isPendingBlobReadResult) {
+ throw new FileError(FileError.INVALID_STATE_ERR);
+ }
+
+ // WRITING state
+ this.readyState = FileWriter.WRITING;
+
+ var me = this;
+
+ // If onwritestart callback
+ if (typeof me.onwritestart === 'function') {
+ me.onwritestart(new ProgressEvent('writestart', {'target': me}));
+ }
+
+ // Write file
+ exec(
+ // Success callback
+ function (r) {
+ // If DONE (cancelled), then don't do anything
+ if (me.readyState === FileWriter.DONE) {
+ return;
+ }
+
+ // position always increases by bytes written because file would be extended
+ me.position += r;
+ // The length of the file is now where we are done writing.
+
+ me.length = me.position;
+
+ // DONE state
+ me.readyState = FileWriter.DONE;
+
+ // If onwrite callback
+ if (typeof me.onwrite === 'function') {
+ me.onwrite(new ProgressEvent('write', {'target': me}));
+ }
+
+ // If onwriteend callback
+ if (typeof me.onwriteend === 'function') {
+ me.onwriteend(new ProgressEvent('writeend', {'target': me}));
+ }
+ },
+ // Error callback
+ function (e) {
+ // If DONE (cancelled), then don't do anything
+ if (me.readyState === FileWriter.DONE) {
+ return;
+ }
+
+ // DONE state
+ me.readyState = FileWriter.DONE;
+
+ // Save error
+ me.error = new FileError(e);
+
+ // If onerror callback
+ if (typeof me.onerror === 'function') {
+ me.onerror(new ProgressEvent('error', {'target': me}));
+ }
+
+ // If onwriteend callback
+ if (typeof me.onwriteend === 'function') {
+ me.onwriteend(new ProgressEvent('writeend', {'target': me}));
+ }
+ }, 'File', 'write', [this.localURL, data, this.position, isBinary]);
+};
+
+/**
+ * Moves the file pointer to the location specified.
+ *
+ * If the offset is a negative number the position of the file
+ * pointer is rewound. If the offset is greater than the file
+ * size the position is set to the end of the file.
+ *
+ * @param offset is the location to move the file pointer to.
+ */
+FileWriter.prototype.seek = function (offset) {
+ // Throw an exception if we are already writing a file
+ if (this.readyState === FileWriter.WRITING) {
+ throw new FileError(FileError.INVALID_STATE_ERR);
+ }
+
+ if (!offset && offset !== 0) {
+ return;
+ }
+
+ // See back from end of file.
+ if (offset < 0) {
+ this.position = Math.max(offset + this.length, 0);
+ // Offset is bigger than file size so set position
+ // to the end of the file.
+ } else if (offset > this.length) {
+ this.position = this.length;
+ // Offset is between 0 and file size so set the position
+ // to start writing.
+ } else {
+ this.position = offset;
+ }
+};
+
+/**
+ * Truncates the file to the size specified.
+ *
+ * @param size to chop the file at.
+ */
+FileWriter.prototype.truncate = function (size) {
+ // Throw an exception if we are already writing a file
+ if (this.readyState === FileWriter.WRITING) {
+ throw new FileError(FileError.INVALID_STATE_ERR);
+ }
+
+ // WRITING state
+ this.readyState = FileWriter.WRITING;
+
+ var me = this;
+
+ // If onwritestart callback
+ if (typeof me.onwritestart === 'function') {
+ me.onwritestart(new ProgressEvent('writestart', {'target': this}));
+ }
+
+ // Write file
+ exec(
+ // Success callback
+ function (r) {
+ // If DONE (cancelled), then don't do anything
+ if (me.readyState === FileWriter.DONE) {
+ return;
+ }
+
+ // DONE state
+ me.readyState = FileWriter.DONE;
+
+ // Update the length of the file
+ me.length = r;
+ me.position = Math.min(me.position, r);
+
+ // If onwrite callback
+ if (typeof me.onwrite === 'function') {
+ me.onwrite(new ProgressEvent('write', {'target': me}));
+ }
+
+ // If onwriteend callback
+ if (typeof me.onwriteend === 'function') {
+ me.onwriteend(new ProgressEvent('writeend', {'target': me}));
+ }
+ },
+ // Error callback
+ function (e) {
+ // If DONE (cancelled), then don't do anything
+ if (me.readyState === FileWriter.DONE) {
+ return;
+ }
+
+ // DONE state
+ me.readyState = FileWriter.DONE;
+
+ // Save error
+ me.error = new FileError(e);
+
+ // If onerror callback
+ if (typeof me.onerror === 'function') {
+ me.onerror(new ProgressEvent('error', {'target': me}));
+ }
+
+ // If onwriteend callback
+ if (typeof me.onwriteend === 'function') {
+ me.onwriteend(new ProgressEvent('writeend', {'target': me}));
+ }
+ }, 'File', 'truncate', [this.localURL, size]);
+};
+
+module.exports = FileWriter;
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-file/www/Flags.js b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/Flags.js
new file mode 100644
index 0000000..f51db30
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/Flags.js
@@ -0,0 +1,38 @@
+cordova.define("cordova-plugin-file.Flags", function(require, exports, module) { /*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+/**
+ * Supplies arguments to methods that lookup or create files and directories.
+ *
+ * @param create
+ * {boolean} file or directory if it doesn't exist
+ * @param exclusive
+ * {boolean} used with create; if true the command will fail if
+ * target path exists
+ */
+function Flags (create, exclusive) {
+ this.create = create || false;
+ this.exclusive = exclusive || false;
+}
+
+module.exports = Flags;
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-file/www/LocalFileSystem.js b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/LocalFileSystem.js
new file mode 100644
index 0000000..e424c10
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/LocalFileSystem.js
@@ -0,0 +1,25 @@
+cordova.define("cordova-plugin-file.LocalFileSystem", function(require, exports, module) { /*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+exports.TEMPORARY = 0;
+exports.PERSISTENT = 1;
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-file/www/Metadata.js b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/Metadata.js
new file mode 100644
index 0000000..5550f8a
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/Metadata.js
@@ -0,0 +1,42 @@
+cordova.define("cordova-plugin-file.Metadata", function(require, exports, module) { /*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+/**
+ * Information about the state of the file or directory
+ *
+ * {Date} modificationTime (readonly)
+ */
+var Metadata = function (metadata) {
+ if (typeof metadata === 'object') {
+ this.modificationTime = new Date(metadata.modificationTime);
+ this.size = metadata.size || 0;
+ } else if (typeof metadata === 'undefined') {
+ this.modificationTime = null;
+ this.size = 0;
+ } else {
+ /* Backwards compatiblity with platforms that only return a timestamp */
+ this.modificationTime = new Date(metadata);
+ }
+};
+
+module.exports = Metadata;
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-file/www/ProgressEvent.js b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/ProgressEvent.js
new file mode 100644
index 0000000..0315adf
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/ProgressEvent.js
@@ -0,0 +1,69 @@
+cordova.define("cordova-plugin-file.ProgressEvent", function(require, exports, module) { /*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+// If ProgressEvent exists in global context, use it already, otherwise use our own polyfill
+// Feature test: See if we can instantiate a native ProgressEvent;
+// if so, use that approach,
+// otherwise fill-in with our own implementation.
+//
+// NOTE: right now we always fill in with our own. Down the road would be nice if we can use whatever is native in the webview.
+var ProgressEvent = (function () {
+ /*
+ var createEvent = function(data) {
+ var event = document.createEvent('Events');
+ event.initEvent('ProgressEvent', false, false);
+ if (data) {
+ for (var i in data) {
+ if (data.hasOwnProperty(i)) {
+ event[i] = data[i];
+ }
+ }
+ if (data.target) {
+ // TODO: cannot call <some_custom_object>.dispatchEvent
+ // need to first figure out how to implement EventTarget
+ }
+ }
+ return event;
+ };
+ try {
+ var ev = createEvent({type:"abort",target:document});
+ return function ProgressEvent(type, data) {
+ data.type = type;
+ return createEvent(data);
+ };
+ } catch(e){
+ */
+ return function ProgressEvent (type, dict) {
+ this.type = type;
+ this.bubbles = false;
+ this.cancelBubble = false;
+ this.cancelable = false;
+ this.lengthComputable = false;
+ this.loaded = dict && dict.loaded ? dict.loaded : 0;
+ this.total = dict && dict.total ? dict.total : 0;
+ this.target = dict && dict.target ? dict.target : null;
+ };
+ // }
+})();
+
+module.exports = ProgressEvent;
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-file/www/browser/FileSystem.js b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/browser/FileSystem.js
new file mode 100644
index 0000000..0f49c2c
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/browser/FileSystem.js
@@ -0,0 +1,32 @@
+cordova.define("cordova-plugin-file.firefoxFileSystem", function(require, exports, module) { /*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+/* global FILESYSTEM_PREFIX: true, module */
+
+FILESYSTEM_PREFIX = 'file:///';
+
+module.exports = {
+ __format__: function (fullPath) {
+ return (FILESYSTEM_PREFIX + this.name + (fullPath[0] === '/' ? '' : '/') + FileSystem.encodeURIPath(fullPath)); // eslint-disable-line no-undef
+ }
+};
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-file/www/browser/Preparing.js b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/browser/Preparing.js
new file mode 100644
index 0000000..24ea404
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/browser/Preparing.js
@@ -0,0 +1,194 @@
+cordova.define("cordova-plugin-file.Preparing", function(require, exports, module) { /*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+(function () {
+ /* global require */
+
+ // Only Chrome uses this file.
+ if (!require('./isChrome')()) {
+ return;
+ }
+
+ var channel = require('cordova/channel');
+ var FileError = require('./FileError');
+ var PERSISTENT_FS_QUOTA = 5 * 1024 * 1024;
+ var filePluginIsReadyEvent = new Event('filePluginIsReady'); // eslint-disable-line no-undef
+
+ var entryFunctionsCreated = false;
+ var quotaWasRequested = false;
+ var eventWasThrown = false;
+
+ if (!window.requestFileSystem) {
+ window.requestFileSystem = function (type, size, win, fail) {
+ if (fail) {
+ fail('Not supported');
+ }
+ };
+ } else {
+ window.requestFileSystem(window.TEMPORARY, 1, createFileEntryFunctions, function () {});
+ }
+
+ if (!window.resolveLocalFileSystemURL) {
+ window.resolveLocalFileSystemURL = function (url, win, fail) {
+ if (fail) {
+ fail('Not supported');
+ }
+ };
+ }
+
+ // Resolves a filesystem entry by its path - which is passed either in standard (filesystem:file://) or
+ // Cordova-specific (cdvfile://) universal way.
+ // Aligns with specification: http://www.w3.org/TR/2011/WD-file-system-api-20110419/#widl-LocalFileSystem-resolveLocalFileSystemURL
+ var nativeResolveLocalFileSystemURL = window.resolveLocalFileSystemURL || window.webkitResolveLocalFileSystemURL;
+ window.resolveLocalFileSystemURL = function (url, win, fail) {
+ /* If url starts with `cdvfile` then we need convert it to Chrome real url first:
+ cdvfile://localhost/persistent/path/to/file -> filesystem:file://persistent/path/to/file */
+ if (url.trim().substr(0, 7) === 'cdvfile') {
+ /* Quirk:
+ Plugin supports cdvfile://localhost (local resources) only.
+ I.e. external resources are not supported via cdvfile. */
+ if (url.indexOf('cdvfile://localhost') !== -1) {
+ // Browser supports temporary and persistent only
+ var indexPersistent = url.indexOf('persistent');
+ var indexTemporary = url.indexOf('temporary');
+
+ /* Chrome urls start with 'filesystem:' prefix. See quirk:
+ toURL function in Chrome returns filesystem:-prefixed path depending on application host.
+ For example, filesystem:file:///persistent/somefile.txt,
+ filesystem:http://localhost:8080/persistent/somefile.txt. */
+ var prefix = 'filesystem:file:///';
+ if (location.protocol !== 'file:') { // eslint-disable-line no-undef
+ prefix = 'filesystem:' + location.origin + '/'; // eslint-disable-line no-undef
+ }
+
+ var result;
+ if (indexPersistent !== -1) {
+ // cdvfile://localhost/persistent/path/to/file -> filesystem:file://persistent/path/to/file
+ // or filesystem:http://localhost:8080/persistent/path/to/file
+ result = prefix + 'persistent' + url.substr(indexPersistent + 10);
+ nativeResolveLocalFileSystemURL(result, win, fail);
+ return;
+ }
+
+ if (indexTemporary !== -1) {
+ // cdvfile://localhost/temporary/path/to/file -> filesystem:file://temporary/path/to/file
+ // or filesystem:http://localhost:8080/temporary/path/to/file
+ result = prefix + 'temporary' + url.substr(indexTemporary + 9);
+ nativeResolveLocalFileSystemURL(result, win, fail);
+ return;
+ }
+ }
+
+ // cdvfile other than local file resource is not supported
+ if (fail) {
+ fail(new FileError(FileError.ENCODING_ERR));
+ }
+ } else {
+ nativeResolveLocalFileSystemURL(url, win, fail);
+ }
+ };
+
+ function createFileEntryFunctions (fs) {
+ fs.root.getFile('todelete_658674_833_4_cdv', {create: true}, function (fileEntry) {
+ var fileEntryType = Object.getPrototypeOf(fileEntry);
+ var entryType = Object.getPrototypeOf(fileEntryType);
+
+ // Save the original method
+ var origToURL = entryType.toURL;
+ entryType.toURL = function () {
+ var origURL = origToURL.call(this);
+ if (this.isDirectory && origURL.substr(-1) !== '/') {
+ return origURL + '/';
+ }
+ return origURL;
+ };
+
+ entryType.toNativeURL = function () {
+ console.warn("DEPRECATED: Update your code to use 'toURL'");
+ return this.toURL();
+ };
+
+ entryType.toInternalURL = function () {
+ if (this.toURL().indexOf('persistent') > -1) {
+ return 'cdvfile://localhost/persistent' + this.fullPath;
+ }
+
+ if (this.toURL().indexOf('temporary') > -1) {
+ return 'cdvfile://localhost/temporary' + this.fullPath;
+ }
+ };
+
+ entryType.setMetadata = function (win, fail /*, metadata */) {
+ if (fail) {
+ fail('Not supported');
+ }
+ };
+
+ fileEntry.createWriter(function (writer) {
+ var originalWrite = writer.write;
+ var writerProto = Object.getPrototypeOf(writer);
+ writerProto.write = function (blob) {
+ if (blob instanceof Blob) { // eslint-disable-line no-undef
+ originalWrite.apply(this, [blob]);
+ } else {
+ var realBlob = new Blob([blob]); // eslint-disable-line no-undef
+ originalWrite.apply(this, [realBlob]);
+ }
+ };
+
+ fileEntry.remove(function () { entryFunctionsCreated = true; }, function () { /* empty callback */ });
+ });
+ });
+ }
+
+ window.initPersistentFileSystem = function (size, win, fail) {
+ if (navigator.webkitPersistentStorage) {
+ navigator.webkitPersistentStorage.requestQuota(size, win, fail);
+ return;
+ }
+
+ fail('This browser does not support this function');
+ };
+
+ window.isFilePluginReadyRaised = function () { return eventWasThrown; };
+
+ window.initPersistentFileSystem(PERSISTENT_FS_QUOTA, function () {
+ console.log('Persistent fs quota granted');
+ quotaWasRequested = true;
+ }, function (e) {
+ console.log('Error occured while trying to request Persistent fs quota: ' + JSON.stringify(e));
+ });
+
+ channel.onCordovaReady.subscribe(function () {
+ function dispatchEventIfReady () {
+ if (entryFunctionsCreated && quotaWasRequested) {
+ window.dispatchEvent(filePluginIsReadyEvent);
+ eventWasThrown = true;
+ } else {
+ setTimeout(dispatchEventIfReady, 100);
+ }
+ }
+
+ dispatchEventIfReady();
+ }, false);
+})();
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-file/www/browser/isChrome.js b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/browser/isChrome.js
new file mode 100644
index 0000000..1421b21
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/browser/isChrome.js
@@ -0,0 +1,28 @@
+cordova.define("cordova-plugin-file.isChrome", function(require, exports, module) { /*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+module.exports = function () {
+ // window.webkitRequestFileSystem and window.webkitResolveLocalFileSystemURL are available only in Chrome and
+ // possibly a good flag to indicate that we're running in Chrome
+ return window.webkitRequestFileSystem && window.webkitResolveLocalFileSystemURL;
+};
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-file/www/fileSystemPaths.js b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/fileSystemPaths.js
new file mode 100644
index 0000000..be7278f
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/fileSystemPaths.js
@@ -0,0 +1,64 @@
+cordova.define("cordova-plugin-file.fileSystemPaths", function(require, exports, module) { /*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+var exec = require('cordova/exec');
+var channel = require('cordova/channel');
+
+exports.file = {
+ // Read-only directory where the application is installed.
+ applicationDirectory: null,
+ // Root of app's private writable storage
+ applicationStorageDirectory: null,
+ // Where to put app-specific data files.
+ dataDirectory: null,
+ // Cached files that should survive app restarts.
+ // Apps should not rely on the OS to delete files in here.
+ cacheDirectory: null,
+ // Android: the application space on external storage.
+ externalApplicationStorageDirectory: null,
+ // Android: Where to put app-specific data files on external storage.
+ externalDataDirectory: null,
+ // Android: the application cache on external storage.
+ externalCacheDirectory: null,
+ // Android: the external storage (SD card) root.
+ externalRootDirectory: null,
+ // iOS: Temp directory that the OS can clear at will.
+ tempDirectory: null,
+ // iOS: Holds app-specific files that should be synced (e.g. to iCloud).
+ syncedDataDirectory: null,
+ // iOS: Files private to the app, but that are meaningful to other applications (e.g. Office files)
+ documentsDirectory: null,
+ // BlackBerry10: Files globally available to all apps
+ sharedDirectory: null
+};
+
+channel.waitForInitialization('onFileSystemPathsReady');
+channel.onCordovaReady.subscribe(function () {
+ function after (paths) {
+ for (var k in paths) {
+ exports.file[k] = paths[k];
+ }
+ channel.initializationComplete('onFileSystemPathsReady');
+ }
+ exec(after, null, 'File', 'requestAllPaths', []);
+});
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-file/www/fileSystems.js b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/fileSystems.js
new file mode 100644
index 0000000..99b38f6
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/fileSystems.js
@@ -0,0 +1,27 @@
+cordova.define("cordova-plugin-file.fileSystems", function(require, exports, module) { /*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+// Overridden by Android, BlackBerry 10 and iOS to populate fsMap.
+module.exports.getFs = function (name, callback) {
+ callback(null);
+};
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-file/www/requestFileSystem.js b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/requestFileSystem.js
new file mode 100644
index 0000000..e182354
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/requestFileSystem.js
@@ -0,0 +1,83 @@
+cordova.define("cordova-plugin-file.requestFileSystem", function(require, exports, module) { /*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+(function () {
+ // For browser platform: not all browsers use this file.
+ function checkBrowser () {
+ if (cordova.platformId === 'browser' && require('./isChrome')()) { // eslint-disable-line no-undef
+ module.exports = window.requestFileSystem || window.webkitRequestFileSystem;
+ return true;
+ }
+ return false;
+ }
+ if (checkBrowser()) {
+ return;
+ }
+
+ var argscheck = require('cordova/argscheck');
+ var FileError = require('./FileError');
+ var FileSystem = require('./FileSystem');
+ var exec = require('cordova/exec');
+ var fileSystems = require('./fileSystems');
+
+ /**
+ * Request a file system in which to store application data.
+ * @param type local file system type
+ * @param size indicates how much storage space, in bytes, the application expects to need
+ * @param successCallback invoked with a FileSystem object
+ * @param errorCallback invoked if error occurs retrieving file system
+ */
+ var requestFileSystem = function (type, size, successCallback, errorCallback) {
+ argscheck.checkArgs('nnFF', 'requestFileSystem', arguments);
+ var fail = function (code) {
+ if (errorCallback) {
+ errorCallback(new FileError(code));
+ }
+ };
+
+ if (type < 0) {
+ fail(FileError.SYNTAX_ERR);
+ } else {
+ // if successful, return a FileSystem object
+ var success = function (file_system) {
+ if (file_system) {
+ if (successCallback) {
+ fileSystems.getFs(file_system.name, function (fs) {
+ // This should happen only on platforms that haven't implemented requestAllFileSystems (windows)
+ if (!fs) {
+ fs = new FileSystem(file_system.name, file_system.root);
+ }
+ successCallback(fs);
+ });
+ }
+ } else {
+ // no FileSystem object returned
+ fail(FileError.NOT_FOUND_ERR);
+ }
+ };
+ exec(success, fail, 'File', 'requestFileSystem', [type, size]);
+ }
+ };
+
+ module.exports = requestFileSystem;
+})();
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-file/www/resolveLocalFileSystemURI.js b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/resolveLocalFileSystemURI.js
new file mode 100644
index 0000000..659d417
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/resolveLocalFileSystemURI.js
@@ -0,0 +1,93 @@
+cordova.define("cordova-plugin-file.resolveLocalFileSystemURI", function(require, exports, module) { /*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+(function () {
+ // For browser platform: not all browsers use overrided `resolveLocalFileSystemURL`.
+ function checkBrowser () {
+ if (cordova.platformId === 'browser' && require('./isChrome')()) { // eslint-disable-line no-undef
+ module.exports.resolveLocalFileSystemURL = window.resolveLocalFileSystemURL || window.webkitResolveLocalFileSystemURL;
+ return true;
+ }
+ return false;
+ }
+ if (checkBrowser()) {
+ return;
+ }
+
+ var argscheck = require('cordova/argscheck');
+ var DirectoryEntry = require('./DirectoryEntry');
+ var FileEntry = require('./FileEntry');
+ var FileError = require('./FileError');
+ var exec = require('cordova/exec');
+ var fileSystems = require('./fileSystems');
+
+ /**
+ * Look up file system Entry referred to by local URI.
+ * @param {DOMString} uri URI referring to a local file or directory
+ * @param successCallback invoked with Entry object corresponding to URI
+ * @param errorCallback invoked if error occurs retrieving file system entry
+ */
+ module.exports.resolveLocalFileSystemURL = module.exports.resolveLocalFileSystemURL || function (uri, successCallback, errorCallback) {
+ argscheck.checkArgs('sFF', 'resolveLocalFileSystemURI', arguments);
+ // error callback
+ var fail = function (error) {
+ if (errorCallback) {
+ errorCallback(new FileError(error));
+ }
+ };
+ // sanity check for 'not:valid:filename' or '/not:valid:filename'
+ // file.spec.12 window.resolveLocalFileSystemURI should error (ENCODING_ERR) when resolving invalid URI with leading /.
+ if (!uri || uri.split(':').length > 2) {
+ setTimeout(function () {
+ fail(FileError.ENCODING_ERR);
+ }, 0);
+ return;
+ }
+ // if successful, return either a file or directory entry
+ var success = function (entry) {
+ if (entry) {
+ if (successCallback) {
+ // create appropriate Entry object
+ var fsName = entry.filesystemName || (entry.filesystem && entry.filesystem.name) || (entry.filesystem === window.PERSISTENT ? 'persistent' : 'temporary'); // eslint-disable-line no-undef
+ fileSystems.getFs(fsName, function (fs) {
+ // This should happen only on platforms that haven't implemented requestAllFileSystems (windows)
+ if (!fs) {
+ fs = new FileSystem(fsName, {name: '', fullPath: '/'}); // eslint-disable-line no-undef
+ }
+ var result = (entry.isDirectory) ? new DirectoryEntry(entry.name, entry.fullPath, fs, entry.nativeURL) : new FileEntry(entry.name, entry.fullPath, fs, entry.nativeURL);
+ successCallback(result);
+ });
+ }
+ } else {
+ // no Entry object returned
+ fail(FileError.NOT_FOUND_ERR);
+ }
+ };
+
+ exec(success, fail, 'File', 'resolveLocalFileSystemURI', [uri]);
+ };
+
+ module.exports.resolveLocalFileSystemURI = function () {
+ console.log('resolveLocalFileSystemURI is deprecated. Please call resolveLocalFileSystemURL instead.');
+ module.exports.resolveLocalFileSystemURL.apply(this, arguments);
+ };
+})();
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-fingerprint-aio/www/Fingerprint.js b/platforms/browser/platform_www/plugins/cordova-plugin-fingerprint-aio/www/Fingerprint.js
new file mode 100644
index 0000000..6c8203d
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-fingerprint-aio/www/Fingerprint.js
@@ -0,0 +1,28 @@
+cordova.define("cordova-plugin-fingerprint-aio.Fingerprint", function(require, exports, module) { /*global cordova */
+
+function Fingerprint() {
+}
+
+Fingerprint.prototype.show = function (params, successCallback, errorCallback) {
+ cordova.exec(
+ successCallback,
+ errorCallback,
+ "Fingerprint",
+ "authenticate",
+ [params]
+ );
+};
+
+Fingerprint.prototype.isAvailable = function (successCallback, errorCallback) {
+ cordova.exec(
+ successCallback,
+ errorCallback,
+ "Fingerprint",
+ "isAvailable",
+ [{}]
+ );
+};
+
+module.exports = new Fingerprint();
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-inappbrowser/src/browser/InAppBrowserProxy.js b/platforms/browser/platform_www/plugins/cordova-plugin-inappbrowser/src/browser/InAppBrowserProxy.js
new file mode 100644
index 0000000..86e120f
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-inappbrowser/src/browser/InAppBrowserProxy.js
@@ -0,0 +1,249 @@
+cordova.define("cordova-plugin-inappbrowser.InAppBrowserProxy", function(require, exports, module) { /*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+var modulemapper = require('cordova/modulemapper');
+
+var browserWrap,
+ popup,
+ navigationButtonsDiv,
+ navigationButtonsDivInner,
+ backButton,
+ forwardButton,
+ closeButton;
+
+function attachNavigationEvents (element, callback) {
+ var onError = function () {
+ try {
+ callback({ type: 'loaderror', url: this.contentWindow.location.href }, {keepCallback: true}); // eslint-disable-line standard/no-callback-literal
+ } catch (err) {
+ // blocked by CORS :\
+ callback({ type: 'loaderror', url: null }, {keepCallback: true}); // eslint-disable-line standard/no-callback-literal
+ }
+ };
+
+ element.addEventListener('pageshow', function () {
+ try {
+ callback({ type: 'loadstart', url: this.contentWindow.location.href }, {keepCallback: true}); // eslint-disable-line standard/no-callback-literal
+ } catch (err) {
+ // blocked by CORS :\
+ callback({ type: 'loadstart', url: null }, {keepCallback: true}); // eslint-disable-line standard/no-callback-literal
+ }
+ });
+
+ element.addEventListener('load', function () {
+ try {
+ callback({ type: 'loadstop', url: this.contentWindow.location.href }, {keepCallback: true}); // eslint-disable-line standard/no-callback-literal
+ } catch (err) {
+ // blocked by CORS :\
+ callback({ type: 'loadstop', url: null }, {keepCallback: true}); // eslint-disable-line standard/no-callback-literal
+ }
+ });
+
+ element.addEventListener('error', onError);
+ element.addEventListener('abort', onError);
+}
+
+var IAB = {
+ close: function (win, lose) {
+ if (browserWrap) {
+ // use the "open" function callback so that the exit event is fired properly
+ if (IAB._win) IAB._win({ type: 'exit' });
+
+ browserWrap.parentNode.removeChild(browserWrap);
+ browserWrap = null;
+ popup = null;
+ }
+ },
+
+ show: function (win, lose) {
+ if (browserWrap) {
+ browserWrap.style.display = 'block';
+ }
+ },
+
+ open: function (win, lose, args) {
+ var strUrl = args[0];
+ var target = args[1];
+ var features = args[2];
+
+ IAB._win = win;
+
+ if (target === '_self' || !target) {
+ window.location = strUrl;
+ } else if (target === '_system') {
+ modulemapper.getOriginalSymbol(window, 'window.open').call(window, strUrl, '_blank');
+ } else {
+ // "_blank" or anything else
+ if (!browserWrap) {
+ browserWrap = document.createElement('div');
+ browserWrap.style.position = 'absolute';
+ browserWrap.style.top = '0';
+ browserWrap.style.left = '0';
+ browserWrap.style.boxSizing = 'border-box';
+ browserWrap.style.borderWidth = '40px';
+ browserWrap.style.width = '100vw';
+ browserWrap.style.height = '100vh';
+ browserWrap.style.borderStyle = 'solid';
+ browserWrap.style.borderColor = 'rgba(0,0,0,0.25)';
+
+ browserWrap.onclick = function () {
+ setTimeout(function () {
+ IAB.close();
+ }, 0);
+ };
+
+ document.body.appendChild(browserWrap);
+ }
+
+ if (features.indexOf('hidden=yes') !== -1) {
+ browserWrap.style.display = 'none';
+ }
+
+ popup = document.createElement('iframe');
+ popup.style.borderWidth = '0px';
+ popup.style.width = '100%';
+
+ browserWrap.appendChild(popup);
+
+ if (features.indexOf('location=yes') !== -1 || features.indexOf('location') === -1) {
+ popup.style.height = 'calc(100% - 60px)';
+ popup.style.marginBottom = '-4px';
+
+ navigationButtonsDiv = document.createElement('div');
+ navigationButtonsDiv.style.height = '60px';
+ navigationButtonsDiv.style.backgroundColor = '#404040';
+ navigationButtonsDiv.style.zIndex = '999';
+ navigationButtonsDiv.onclick = function (e) {
+ e.cancelBubble = true;
+ };
+
+ navigationButtonsDivInner = document.createElement('div');
+ navigationButtonsDivInner.style.paddingTop = '10px';
+ navigationButtonsDivInner.style.height = '50px';
+ navigationButtonsDivInner.style.width = '160px';
+ navigationButtonsDivInner.style.margin = '0 auto';
+ navigationButtonsDivInner.style.backgroundColor = '#404040';
+ navigationButtonsDivInner.style.zIndex = '999';
+ navigationButtonsDivInner.onclick = function (e) {
+ e.cancelBubble = true;
+ };
+
+ backButton = document.createElement('button');
+ backButton.style.width = '40px';
+ backButton.style.height = '40px';
+ backButton.style.borderRadius = '40px';
+
+ backButton.innerHTML = '←';
+ backButton.addEventListener('click', function (e) {
+ if (popup.canGoBack) { popup.goBack(); }
+ });
+
+ forwardButton = document.createElement('button');
+ forwardButton.style.marginLeft = '20px';
+ forwardButton.style.width = '40px';
+ forwardButton.style.height = '40px';
+ forwardButton.style.borderRadius = '40px';
+
+ forwardButton.innerHTML = '→';
+ forwardButton.addEventListener('click', function (e) {
+ if (popup.canGoForward) { popup.goForward(); }
+ });
+
+ closeButton = document.createElement('button');
+ closeButton.style.marginLeft = '20px';
+ closeButton.style.width = '40px';
+ closeButton.style.height = '40px';
+ closeButton.style.borderRadius = '40px';
+
+ closeButton.innerHTML = '✖';
+ closeButton.addEventListener('click', function (e) {
+ setTimeout(function () {
+ IAB.close();
+ }, 0);
+ });
+
+ // iframe navigation is not yet supported
+ backButton.disabled = true;
+ forwardButton.disabled = true;
+
+ navigationButtonsDivInner.appendChild(backButton);
+ navigationButtonsDivInner.appendChild(forwardButton);
+ navigationButtonsDivInner.appendChild(closeButton);
+ navigationButtonsDiv.appendChild(navigationButtonsDivInner);
+
+ browserWrap.appendChild(navigationButtonsDiv);
+ } else {
+ popup.style.height = '100%';
+ }
+
+ // start listening for navigation events
+ attachNavigationEvents(popup, win);
+
+ popup.src = strUrl;
+ }
+ },
+
+ injectScriptCode: function (win, fail, args) {
+ var code = args[0];
+ var hasCallback = args[1];
+
+ if (browserWrap && popup) {
+ try {
+ popup.contentWindow.eval(code);
+ if (hasCallback) {
+ win([]);
+ }
+ } catch (e) {
+ console.error('Error occured while trying to injectScriptCode: ' + JSON.stringify(e));
+ }
+ }
+ },
+
+ injectScriptFile: function (win, fail, args) {
+ var msg = 'Browser cordova-plugin-inappbrowser injectScriptFile is not yet implemented';
+ console.warn(msg);
+ if (fail) {
+ fail(msg);
+ }
+ },
+
+ injectStyleCode: function (win, fail, args) {
+ var msg = 'Browser cordova-plugin-inappbrowser injectStyleCode is not yet implemented';
+ console.warn(msg);
+ if (fail) {
+ fail(msg);
+ }
+ },
+
+ injectStyleFile: function (win, fail, args) {
+ var msg = 'Browser cordova-plugin-inappbrowser injectStyleFile is not yet implemented';
+ console.warn(msg);
+ if (fail) {
+ fail(msg);
+ }
+ }
+};
+
+module.exports = IAB;
+
+require('cordova/exec/proxy').add('InAppBrowser', module.exports);
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-inappbrowser/www/inappbrowser.js b/platforms/browser/platform_www/plugins/cordova-plugin-inappbrowser/www/inappbrowser.js
new file mode 100644
index 0000000..759dacf
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-inappbrowser/www/inappbrowser.js
@@ -0,0 +1,117 @@
+cordova.define("cordova-plugin-inappbrowser.inappbrowser", function(require, exports, module) { /*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+(function () {
+ // special patch to correctly work on Ripple emulator (CB-9760)
+ if (window.parent && !!window.parent.ripple) { // https://gist.github.com/triceam/4658021
+ module.exports = window.open.bind(window); // fallback to default window.open behaviour
+ return;
+ }
+
+ var exec = require('cordova/exec');
+ var channel = require('cordova/channel');
+ var modulemapper = require('cordova/modulemapper');
+ var urlutil = require('cordova/urlutil');
+
+ function InAppBrowser () {
+ this.channels = {
+ 'loadstart': channel.create('loadstart'),
+ 'loadstop': channel.create('loadstop'),
+ 'loaderror': channel.create('loaderror'),
+ 'exit': channel.create('exit'),
+ 'customscheme': channel.create('customscheme')
+ };
+ }
+
+ InAppBrowser.prototype = {
+ _eventHandler: function (event) {
+ if (event && (event.type in this.channels)) {
+ this.channels[event.type].fire(event);
+ }
+ },
+ close: function (eventname) {
+ exec(null, null, 'InAppBrowser', 'close', []);
+ },
+ show: function (eventname) {
+ exec(null, null, 'InAppBrowser', 'show', []);
+ },
+ hide: function (eventname) {
+ exec(null, null, 'InAppBrowser', 'hide', []);
+ },
+ addEventListener: function (eventname, f) {
+ if (eventname in this.channels) {
+ this.channels[eventname].subscribe(f);
+ }
+ },
+ removeEventListener: function (eventname, f) {
+ if (eventname in this.channels) {
+ this.channels[eventname].unsubscribe(f);
+ }
+ },
+
+ executeScript: function (injectDetails, cb) {
+ if (injectDetails.code) {
+ exec(cb, null, 'InAppBrowser', 'injectScriptCode', [injectDetails.code, !!cb]);
+ } else if (injectDetails.file) {
+ exec(cb, null, 'InAppBrowser', 'injectScriptFile', [injectDetails.file, !!cb]);
+ } else {
+ throw new Error('executeScript requires exactly one of code or file to be specified');
+ }
+ },
+
+ insertCSS: function (injectDetails, cb) {
+ if (injectDetails.code) {
+ exec(cb, null, 'InAppBrowser', 'injectStyleCode', [injectDetails.code, !!cb]);
+ } else if (injectDetails.file) {
+ exec(cb, null, 'InAppBrowser', 'injectStyleFile', [injectDetails.file, !!cb]);
+ } else {
+ throw new Error('insertCSS requires exactly one of code or file to be specified');
+ }
+ }
+ };
+
+ module.exports = function (strUrl, strWindowName, strWindowFeatures, callbacks) {
+ // Don't catch calls that write to existing frames (e.g. named iframes).
+ if (window.frames && window.frames[strWindowName]) {
+ var origOpenFunc = modulemapper.getOriginalSymbol(window, 'open');
+ return origOpenFunc.apply(window, arguments);
+ }
+
+ strUrl = urlutil.makeAbsolute(strUrl);
+ var iab = new InAppBrowser();
+
+ callbacks = callbacks || {};
+ for (var callbackName in callbacks) {
+ iab.addEventListener(callbackName, callbacks[callbackName]);
+ }
+
+ var cb = function (eventname) {
+ iab._eventHandler(eventname);
+ };
+
+ strWindowFeatures = strWindowFeatures || '';
+
+ exec(cb, cb, 'InAppBrowser', 'open', [strUrl, strWindowName, strWindowFeatures]);
+ return iab;
+ };
+})();
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-qrscanner/src/browser/plugin.min.js b/platforms/browser/platform_www/plugins/cordova-plugin-qrscanner/src/browser/plugin.min.js
new file mode 100644
index 0000000..44888a7
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-qrscanner/src/browser/plugin.min.js
@@ -0,0 +1,4243 @@
+cordova.define("cordova-plugin-qrscanner.QRScannerProxy", function(require, exports, module) { // This file is generated by `npm run build`.
+
+/*global exports:false*/
+/*jshint unused:false */
+// remap parameter names from cordova.define
+// see `externals` in webpack.cordova.config.js
+var cordovaRequire = require;
+var cordovaExports = exports;
+var cordovaModule = module;
+/******/ (function(modules) { // webpackBootstrap
+/******/ // The module cache
+/******/ var installedModules = {};
+/******/
+/******/ // The require function
+/******/ function __webpack_require__(moduleId) {
+/******/
+/******/ // Check if module is in cache
+/******/ if(installedModules[moduleId]) {
+/******/ return installedModules[moduleId].exports;
+/******/ }
+/******/ // Create a new module (and put it into the cache)
+/******/ var module = installedModules[moduleId] = {
+/******/ i: moduleId,
+/******/ l: false,
+/******/ exports: {}
+/******/ };
+/******/
+/******/ // Execute the module function
+/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/
+/******/ // Flag the module as loaded
+/******/ module.l = true;
+/******/
+/******/ // Return the exports of the module
+/******/ return module.exports;
+/******/ }
+/******/
+/******/
+/******/ // expose the modules object (__webpack_modules__)
+/******/ __webpack_require__.m = modules;
+/******/
+/******/ // expose the module cache
+/******/ __webpack_require__.c = installedModules;
+/******/
+/******/ // identity function for calling harmony imports with the correct context
+/******/ __webpack_require__.i = function(value) { return value; };
+/******/
+/******/ // define getter function for harmony exports
+/******/ __webpack_require__.d = function(exports, name, getter) {
+/******/ if(!__webpack_require__.o(exports, name)) {
+/******/ Object.defineProperty(exports, name, {
+/******/ configurable: false,
+/******/ enumerable: true,
+/******/ get: getter
+/******/ });
+/******/ }
+/******/ };
+/******/
+/******/ // getDefaultExport function for compatibility with non-harmony modules
+/******/ __webpack_require__.n = function(module) {
+/******/ var getter = module && module.__esModule ?
+/******/ function getDefault() { return module['default']; } :
+/******/ function getModuleExports() { return module; };
+/******/ __webpack_require__.d(getter, 'a', getter);
+/******/ return getter;
+/******/ };
+/******/
+/******/ // Object.prototype.hasOwnProperty.call
+/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
+/******/
+/******/ // __webpack_public_path__
+/******/ __webpack_require__.p = "";
+/******/
+/******/ // Load entry module and return exports
+/******/ return __webpack_require__(__webpack_require__.s = 17);
+/******/ })
+/************************************************************************/
+/******/ ([
+/* 0 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+/*
+ * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree.
+ */
+ /* eslint-env node */
+
+
+var logDisabled_ = true;
+
+// Utility methods.
+var utils = {
+ disableLog: function(bool) {
+ if (typeof bool !== 'boolean') {
+ return new Error('Argument type: ' + typeof bool +
+ '. Please use a boolean.');
+ }
+ logDisabled_ = bool;
+ return (bool) ? 'adapter.js logging disabled' :
+ 'adapter.js logging enabled';
+ },
+
+ log: function() {
+ if (typeof window === 'object') {
+ if (logDisabled_) {
+ return;
+ }
+ if (typeof console !== 'undefined' && typeof console.log === 'function') {
+ console.log.apply(console, arguments);
+ }
+ }
+ },
+
+ /**
+ * Extract browser version out of the provided user agent string.
+ *
+ * @param {!string} uastring userAgent string.
+ * @param {!string} expr Regular expression used as match criteria.
+ * @param {!number} pos position in the version string to be returned.
+ * @return {!number} browser version.
+ */
+ extractVersion: function(uastring, expr, pos) {
+ var match = uastring.match(expr);
+ return match && match.length >= pos && parseInt(match[pos], 10);
+ },
+
+ /**
+ * Browser detector.
+ *
+ * @return {object} result containing browser and version
+ * properties.
+ */
+ detectBrowser: function() {
+ // Returned result object.
+ var result = {};
+ result.browser = null;
+ result.version = null;
+
+ // Fail early if it's not a browser
+ if (typeof window === 'undefined' || !window.navigator) {
+ result.browser = 'Not a browser.';
+ return result;
+ }
+
+ // Firefox.
+ if (navigator.mozGetUserMedia) {
+ result.browser = 'firefox';
+ result.version = this.extractVersion(navigator.userAgent,
+ /Firefox\/(\d+)\./, 1);
+ } else if (navigator.webkitGetUserMedia) {
+ // Chrome, Chromium, Webview, Opera, all use the chrome shim for now
+ if (window.webkitRTCPeerConnection) {
+ result.browser = 'chrome';
+ result.version = this.extractVersion(navigator.userAgent,
+ /Chrom(e|ium)\/(\d+)\./, 2);
+ } else { // Safari (in an unpublished version) or unknown webkit-based.
+ if (navigator.userAgent.match(/Version\/(\d+).(\d+)/)) {
+ result.browser = 'safari';
+ result.version = this.extractVersion(navigator.userAgent,
+ /AppleWebKit\/(\d+)\./, 1);
+ } else { // unknown webkit-based browser.
+ result.browser = 'Unsupported webkit-based browser ' +
+ 'with GUM support but no WebRTC support.';
+ return result;
+ }
+ }
+ } else if (navigator.mediaDevices &&
+ navigator.userAgent.match(/Edge\/(\d+).(\d+)$/)) { // Edge.
+ result.browser = 'edge';
+ result.version = this.extractVersion(navigator.userAgent,
+ /Edge\/(\d+).(\d+)$/, 2);
+ } else if (navigator.mediaDevices &&
+ navigator.userAgent.match(/AppleWebKit\/(\d+)\./)) {
+ // Safari, with webkitGetUserMedia removed.
+ result.browser = 'safari';
+ result.version = this.extractVersion(navigator.userAgent,
+ /AppleWebKit\/(\d+)\./, 1);
+ } else { // Default fallthrough: not supported.
+ result.browser = 'Not a supported browser.';
+ return result;
+ }
+
+ return result;
+ },
+
+ // shimCreateObjectURL must be called before shimSourceObject to avoid loop.
+
+ shimCreateObjectURL: function() {
+ if (!(typeof window === 'object' && window.HTMLMediaElement &&
+ 'srcObject' in window.HTMLMediaElement.prototype)) {
+ // Only shim CreateObjectURL using srcObject if srcObject exists.
+ return undefined;
+ }
+
+ var nativeCreateObjectURL = URL.createObjectURL.bind(URL);
+ var nativeRevokeObjectURL = URL.revokeObjectURL.bind(URL);
+ var streams = new Map(), newId = 0;
+
+ URL.createObjectURL = function(stream) {
+ if ('getTracks' in stream) {
+ var url = 'polyblob:' + (++newId);
+ streams.set(url, stream);
+ console.log('URL.createObjectURL(stream) is deprecated! ' +
+ 'Use elem.srcObject = stream instead!');
+ return url;
+ }
+ return nativeCreateObjectURL(stream);
+ };
+ URL.revokeObjectURL = function(url) {
+ nativeRevokeObjectURL(url);
+ streams.delete(url);
+ };
+
+ var dsc = Object.getOwnPropertyDescriptor(window.HTMLMediaElement.prototype,
+ 'src');
+ Object.defineProperty(window.HTMLMediaElement.prototype, 'src', {
+ get: function() {
+ return dsc.get.apply(this);
+ },
+ set: function(url) {
+ this.srcObject = streams.get(url) || null;
+ return dsc.set.apply(this, [url]);
+ }
+ });
+
+ var nativeSetAttribute = HTMLMediaElement.prototype.setAttribute;
+ HTMLMediaElement.prototype.setAttribute = function() {
+ if (arguments.length === 2 &&
+ ('' + arguments[0]).toLowerCase() === 'src') {
+ this.srcObject = streams.get(arguments[1]) || null;
+ }
+ return nativeSetAttribute.apply(this, arguments);
+ };
+ }
+};
+
+// Export.
+module.exports = {
+ log: utils.log,
+ disableLog: utils.disableLog,
+ browserDetails: utils.detectBrowser(),
+ extractVersion: utils.extractVersion,
+ shimCreateObjectURL: utils.shimCreateObjectURL,
+ detectBrowser: utils.detectBrowser.bind(utils)
+};
+
+
+/***/ }),
+/* 1 */
+/***/ (function(module, exports) {
+
+module.exports = cordovaModule;
+
+/***/ }),
+/* 2 */
+/***/ (function(module, exports, __webpack_require__) {
+
+__webpack_require__(8);
+var workerScript = __webpack_require__(6);
+
+module.exports = function(){
+
+ var ELEMENTS = {
+ preview: 'cordova-plugin-qrscanner-video-preview',
+ still: 'cordova-plugin-qrscanner-still'
+ };
+ var ZINDEXES = {
+ preview: -100,
+ still: -99
+ };
+ var backCamera = null;
+ var frontCamera = null;
+ var currentCamera = 0;
+ var activeMediaStream = null;
+ var scanning = false;
+ var previewing = false;
+ var scanWorker = null;
+ var thisScanCycle = null;
+ var nextScan = null;
+ var cancelNextScan = null;
+
+ // standard screen widths/heights, from 4k down to 320x240
+ // widths and heights are each tested separately to account for screen rotation
+ var standardWidthsAndHeights = [
+ 5120, 4096, 3840, 3440, 3200, 3072, 3000, 2880, 2800, 2736, 2732, 2560,
+ 2538, 2400, 2304, 2160, 2100, 2048, 2000, 1920, 1856, 1824, 1800, 1792,
+ 1776, 1728, 1700, 1680, 1600, 1536, 1440, 1400, 1392, 1366, 1344, 1334,
+ 1280, 1200, 1152, 1136, 1120, 1080, 1050, 1024, 1000, 960, 900, 854, 848,
+ 832, 800, 768, 750, 720, 640, 624, 600, 576, 544, 540, 512, 480, 320, 240
+ ];
+
+ var facingModes = [
+ 'environment',
+ 'user'
+ ];
+
+ //utils
+ function killStream(mediaStream){
+ mediaStream.getTracks().forEach(function(track){
+ track.stop();
+ });
+ }
+
+ // For performance, we test best-to-worst constraints. Once we find a match,
+ // we move to the next test. Since `ConstraintNotSatisfiedError`s are thrown
+ // much faster than streams can be started and stopped, the scan is much
+ // faster, even though it may iterate through more constraint objects.
+ function getCameraSpecsById(deviceId){
+
+ // return a getUserMedia Constraints
+ function getConstraintObj(deviceId, facingMode, width, height){
+ var obj = { audio: false, video: {} };
+ obj.video.deviceId = {exact: deviceId};
+ if(facingMode) {
+ obj.video.facingMode = {exact: facingMode};
+ }
+ if(width) {
+ obj.video.width = {exact: width};
+ }
+ if(height) {
+ obj.video.height = {exact: height};
+ }
+ return obj;
+ }
+
+ var facingModeConstraints = facingModes.map(function(mode){
+ return getConstraintObj(deviceId, mode);
+ });
+ var widthConstraints = standardWidthsAndHeights.map(function(width){
+ return getConstraintObj(deviceId, null, width);
+ });
+ var heightConstraints = standardWidthsAndHeights.map(function(height){
+ return getConstraintObj(deviceId, null, null, height);
+ });
+
+ // create a promise which tries to resolve the best constraints for this deviceId
+ // rather than reject, failures return a value of `null`
+ function getFirstResolvingConstraint(constraintsBestToWorst){
+ return new Promise(function(resolveBestConstraints){
+ // build a chain of promises which either resolves or continues searching
+ return constraintsBestToWorst.reduce(function(chain, next){
+ return chain.then(function(searchState){
+ if(searchState.found){
+ // The best working constraint was found. Skip further tests.
+ return searchState;
+ } else {
+ searchState.nextConstraint = next;
+ return window.navigator.mediaDevices.getUserMedia(searchState.nextConstraint).then(function(mediaStream){
+ // We found the first working constraint object, now we can stop
+ // the stream and short-circuit the search.
+ killStream(mediaStream);
+ searchState.found = true;
+ return searchState;
+ }, function(){
+ // didn't get a media stream. The search continues:
+ return searchState;
+ });
+ }
+ });
+ }, Promise.resolve({
+ // kick off the search:
+ found: false,
+ nextConstraint: {}
+ })).then(function(searchState){
+ if(searchState.found){
+ resolveBestConstraints(searchState.nextConstraint);
+ } else {
+ resolveBestConstraints(null);
+ }
+ });
+ });
+ }
+
+ return getFirstResolvingConstraint(facingModeConstraints).then(function(facingModeSpecs){
+ return getFirstResolvingConstraint(widthConstraints).then(function(widthSpecs){
+ return getFirstResolvingConstraint(heightConstraints).then(function(heightSpecs){
+ return {
+ deviceId: deviceId,
+ facingMode: facingModeSpecs === null ? null : facingModeSpecs.video.facingMode.exact,
+ width: widthSpecs === null ? null : widthSpecs.video.width.exact,
+ height: heightSpecs === null ? null : heightSpecs.video.height.exact
+ };
+ });
+ });
+ });
+ }
+
+ function chooseCameras(){
+ var devices = window.navigator.mediaDevices.enumerateDevices();
+ return devices.then(function(mediaDeviceInfoList){
+ var videoDeviceIds = mediaDeviceInfoList.filter(function(elem){
+ return elem.kind === 'videoinput';
+ }).map(function(elem){
+ return elem.deviceId;
+ });
+ return videoDeviceIds;
+ }).then(function(videoDeviceIds){
+ // there is no standardized way for us to get the specs of each camera
+ // (due to concerns over user fingerprinting), so we're forced to
+ // iteratively test each camera for it's capabilities
+ var searches = [];
+ videoDeviceIds.forEach(function(id){
+ searches.push(getCameraSpecsById(id));
+ });
+ return Promise.all(searches);
+ }).then(function(cameraSpecsArray){
+ return cameraSpecsArray.filter(function(camera){
+ // filter out any cameras where width and height could not be captured
+ if(camera !== null && camera.width !== null && camera.height !== null){
+ return true;
+ }
+ }).sort(function(a, b){
+ // sort cameras from highest resolution (by width) to lowest
+ return b.width - a.width;
+ });
+ }).then(function(bestToWorstCameras){
+ var backCamera = null,
+ frontCamera = null;
+ // choose backCamera
+ for(var i = 0; i < bestToWorstCameras.length; i++){
+ if (bestToWorstCameras[i].facingMode === 'environment'){
+ backCamera = bestToWorstCameras[i];
+ // (shouldn't be used for frontCamera)
+ bestToWorstCameras.splice(i, 1);
+ break;
+ }
+ }
+ // if no back-facing cameras were found, choose the highest resolution
+ if(backCamera === null){
+ if(bestToWorstCameras.length > 0){
+ backCamera = bestToWorstCameras[0];
+ // (shouldn't be used for frontCamera)
+ bestToWorstCameras.splice(0, 1);
+ } else {
+ // user doesn't have any available cameras
+ backCamera = false;
+ }
+ }
+ if(bestToWorstCameras.length > 0){
+ // frontCamera should simply be the next-best resolution camera
+ frontCamera = bestToWorstCameras[0];
+ } else {
+ // user doesn't have any more cameras
+ frontCamera = false;
+ }
+ return {
+ backCamera: backCamera,
+ frontCamera: frontCamera
+ };
+ });
+ }
+
+ function mediaStreamIsActive(){
+ return activeMediaStream !== null;
+ }
+
+ function killActiveMediaStream(){
+ killStream(activeMediaStream);
+ activeMediaStream = null;
+ }
+
+ function getVideoPreview(){
+ return document.getElementById(ELEMENTS.preview);
+ }
+
+ function getImg(){
+ return document.getElementById(ELEMENTS.still);
+ }
+
+ function getCurrentCameraIndex(){
+ return currentCamera;
+ }
+
+ function getCurrentCamera(){
+ return currentCamera === 1 ? frontCamera : backCamera;
+ }
+
+ function bringStillToFront(){
+ var img = getImg();
+ if(img){
+ img.style.visibility = 'visible';
+ previewing = false;
+ }
+ }
+
+ function bringPreviewToFront(){
+ var img = getImg();
+ if(img){
+ img.style.visibility = 'hidden';
+ previewing = true;
+ }
+ }
+
+ function isInitialized(){
+ return backCamera !== null;
+ }
+
+ function canChangeCamera(){
+ return !!backCamera && !!frontCamera;
+ }
+
+ function calcStatus(){
+ return {
+ // !authorized means the user either has no camera or has denied access.
+ // This would leave a value of `null` before prepare(), and `false` after.
+ authorized: (backCamera !== null && backCamera !== false)? '1': '0',
+ // No applicable API
+ denied: '0',
+ // No applicable API
+ restricted: '0',
+ prepared: isInitialized() ? '1' : '0',
+ scanning: scanning? '1' : '0',
+ previewing: previewing? '1' : '0',
+ // We leave this true after prepare() to match the mobile experience as
+ // closely as possible. (Without additional covering, the preview will
+ // always be visible to the user).
+ showing: getVideoPreview()? '1' : '0',
+ // No applicable API
+ lightEnabled: '0',
+ // No applicable API
+ canOpenSettings: '0',
+ // No applicable API
+ canEnableLight: '0',
+ canChangeCamera: canChangeCamera() ? '1' : '0',
+ currentCamera: currentCamera.toString()
+ };
+ }
+
+ function startCamera(success, error){
+ var currentCameraIndex = getCurrentCameraIndex();
+ var currentCamera = getCurrentCamera();
+ window.navigator.mediaDevices.getUserMedia({
+ audio: false,
+ video: {
+ deviceId: {exact: currentCamera.deviceId},
+ width: {ideal: currentCamera.width},
+ height: {ideal: currentCamera.height}
+ }
+ }).then(function(mediaStream){
+ activeMediaStream = mediaStream;
+ var video = getVideoPreview();
+ video.src = URL.createObjectURL(mediaStream);
+ success(calcStatus());
+ }, function(err){
+ // something bad happened
+ err = null;
+ var code = currentCameraIndex? 4 : 3;
+ error(code); // FRONT_CAMERA_UNAVAILABLE : BACK_CAMERA_UNAVAILABLE
+ });
+ }
+
+ function getTempCanvasAndContext(videoElement){
+ var tempCanvas = document.createElement('canvas');
+ var camera = getCurrentCamera();
+ tempCanvas.height = camera.height;
+ tempCanvas.width = camera.width;
+ var tempCanvasContext = tempCanvas.getContext('2d');
+ tempCanvasContext.drawImage(videoElement, 0, 0, camera.width, camera.height);
+ return {
+ canvas: tempCanvas,
+ context: tempCanvasContext
+ };
+ }
+
+ function getCurrentImageData(videoElement){
+ var snapshot = getTempCanvasAndContext(videoElement);
+ return snapshot.context.getImageData(0, 0, snapshot.canvas.width, snapshot.canvas.height);
+ }
+
+ // take a screenshot of the video preview with a temp canvas
+ function captureCurrentFrame(videoElement){
+ return getTempCanvasAndContext(videoElement).canvas.toDataURL('image/png');
+ }
+
+ function initialize(success, error){
+ if(scanWorker === null){
+ var workerBlob = new Blob([workerScript],{type: "text/javascript"});
+ scanWorker = new Worker(URL.createObjectURL(workerBlob));
+ }
+ if(!getVideoPreview()){
+ // prepare DOM (sync)
+ var videoPreview = document.createElement('video');
+ videoPreview.setAttribute('autoplay', 'autoplay');
+ videoPreview.setAttribute('id', ELEMENTS.preview);
+ videoPreview.setAttribute('style', 'display:block;position:fixed;top:50%;left:50%;' +
+ 'width:auto;height:auto;min-width:100%;min-height:100%;z-index:' + ZINDEXES.preview +
+ ';-moz-transform: translateX(-50%) translateY(-50%);-webkit-transform: ' +
+ 'translateX(-50%) translateY(-50%);transform:translateX(-50%) translateY(-50%);' +
+ 'background-size:cover;background-position:50% 50%;background-color:#FFF;');
+ videoPreview.addEventListener('loadeddata', function(){
+ bringPreviewToFront();
+ });
+
+ var stillImg = document.createElement('div');
+ stillImg.setAttribute('id', ELEMENTS.still);
+ stillImg.setAttribute('style', 'display:block;position:fixed;top:50%;left:50%;visibility: hidden;' +
+ 'width:auto;height:auto;min-width:100%;min-height:100%;z-index:' + ZINDEXES.still +
+ ';-moz-transform: translateX(-50%) translateY(-50%);-webkit-transform: ' +
+ 'translateX(-50%) translateY(-50%);transform:translateX(-50%) translateY(-50%);' +
+ 'background-size:cover;background-position:50% 50%;background-color:#FFF;');
+
+ document.body.appendChild(videoPreview);
+ document.body.appendChild(stillImg);
+ }
+ if(backCamera === null){
+ // set instance cameras
+ chooseCameras().then(function(cameras){
+ backCamera = cameras.backCamera;
+ frontCamera = cameras.frontCamera;
+ if(backCamera !== false){
+ success();
+ } else {
+ error(5); // CAMERA_UNAVAILABLE
+ }
+ }, function(err){
+ // something bad happened
+ err = null;
+ error(0); // UNEXPECTED_ERROR
+ });
+ } else if (backCamera === false){
+ error(5); // CAMERA_UNAVAILABLE
+ } else {
+ success();
+ }
+ }
+
+ /*
+ * --- Begin Public API ---
+ */
+
+ function prepare(success, error){
+ initialize(function(){
+ // return status on success
+ success(calcStatus());
+ },
+ // pass errors through
+ error);
+ }
+
+ function show(success, error){
+ function showCamera(){
+ if(!mediaStreamIsActive()){
+ startCamera(success, error);
+ } else {
+ success(calcStatus());
+ }
+ }
+ if(!isInitialized()){
+ initialize(function(){
+ // on successful initialization, attempt to showCamera
+ showCamera();
+ },
+ // pass errors through
+ error);
+ } else {
+ showCamera();
+ }
+ }
+
+ function hide(success, error){
+ error = null; // should never error
+ if(mediaStreamIsActive()){
+ killActiveMediaStream();
+ }
+ var video = getVideoPreview();
+ if(video){
+ video.src = '';
+ }
+ success(calcStatus());
+ }
+
+ function scan(success, error) {
+ // initialize and start video preview if not already active
+ show(function(ignore){
+ // ignore success output – `scan` method callback should be passed the decoded data
+ ignore = null;
+ var video = getVideoPreview();
+ var returned = false;
+ scanning = true;
+ scanWorker.onmessage = function(event){
+ var obj = event.data;
+ if(obj.result && !returned){
+ returned = true;
+ thisScanCycle = null;
+ success(obj.result);
+ }
+ };
+ thisScanCycle = function(){
+ scanWorker.postMessage(getCurrentImageData(video));
+ if(cancelNextScan !== null){
+ // avoid race conditions, always clear before starting a cycle
+ cancelNextScan();
+ }
+ // interval in milliseconds at which to try decoding the QR code
+ var SCAN_INTERVAL = window.QRScanner_SCAN_INTERVAL || 130;
+ // this value can be adjusted on-the-fly (while a scan is active) to
+ // balance scan speed vs. CPU/power usage
+ nextScan = window.setTimeout(thisScanCycle, SCAN_INTERVAL);
+ cancelNextScan = function(sendError){
+ window.clearTimeout(nextScan);
+ nextScan = null;
+ cancelNextScan = null;
+ if(sendError){
+ error(6); // SCAN_CANCELED
+ }
+ };
+ };
+ thisScanCycle();
+ }, error);
+ }
+
+ function cancelScan(success, error){
+ error = null; // should never error
+ if(cancelNextScan !== null){
+ cancelNextScan(true);
+ }
+ scanning = false;
+ if(typeof success === "function"){
+ success(calcStatus());
+ }
+ }
+
+ function pausePreview(success, error){
+ error = null; // should never error
+ if(mediaStreamIsActive()){
+ // pause scanning too
+ if(cancelNextScan !== null){
+ cancelNextScan();
+ }
+ var video = getVideoPreview();
+ video.pause();
+ var img = new Image();
+ img.src = captureCurrentFrame(video);
+ getImg().style.backgroundImage = 'url(' + img.src + ')';
+ bringStillToFront();
+ // kill the active stream to turn off the privacy light (the screenshot
+ // in the stillImg will remain visible)
+ killActiveMediaStream();
+ success(calcStatus());
+ } else {
+ success(calcStatus());
+ }
+ }
+
+ function resumePreview(success, error){
+ // if a scan was happening, resume it
+ if(thisScanCycle !== null){
+ thisScanCycle();
+ }
+ show(success, error);
+ }
+
+ function enableLight(success, error){
+ error(7); //LIGHT_UNAVAILABLE
+ }
+
+ function disableLight(success, error){
+ error(7); //LIGHT_UNAVAILABLE
+ }
+
+ function useCamera(success, error, array){
+ var requestedCamera = array[0];
+ var initialized = isInitialized();
+ if(requestedCamera !== currentCamera){
+ if(initialized && requestedCamera === 1 && !canChangeCamera()){
+ error(4); //FRONT_CAMERA_UNAVAILABLE
+ } else {
+ currentCamera = requestedCamera;
+ if(initialized){
+ hide(function(status){
+ // Don't need this one
+ status = null;
+ });
+ show(success, error);
+ } else {
+ success(calcStatus());
+ }
+ }
+ } else {
+ success(calcStatus());
+ }
+ }
+
+ function openSettings(success, error){
+ error(8); //OPEN_SETTINGS_UNAVAILABLE
+ }
+
+ function getStatus(success, error){
+ error = null; // should never error
+ success(calcStatus());
+ }
+
+ // Reset all instance variables to their original state.
+ // This method might be useful in cases where a new camera is available, and
+ // the application needs to force the plugin to chooseCameras() again.
+ function destroy(success, error){
+ error = null; // should never error
+ cancelScan();
+ if(mediaStreamIsActive()){
+ killActiveMediaStream();
+ }
+ backCamera = null;
+ frontCamera = null;
+ var preview = getVideoPreview();
+ var still = getImg();
+ if(preview){
+ preview.remove();
+ }
+ if(still){
+ still.remove();
+ }
+ success(calcStatus());
+ }
+
+ return {
+ prepare: prepare,
+ show: show,
+ hide: hide,
+ scan: scan,
+ cancelScan: cancelScan,
+ pausePreview: pausePreview,
+ resumePreview: resumePreview,
+ enableLight: enableLight,
+ disableLight: disableLight,
+ useCamera: useCamera,
+ openSettings: openSettings,
+ getStatus: getStatus,
+ destroy: destroy
+ };
+};
+
+
+/***/ }),
+/* 3 */,
+/* 4 */,
+/* 5 */
+/***/ (function(module, exports) {
+
+module.exports = cordovaRequire;
+
+/***/ }),
+/* 6 */
+/***/ (function(module, exports) {
+
+module.exports = "!function(t){function e(i){if(n[i])return n[i].exports;var r=n[i]={i:i,l:!1,exports:{}};return t[i].call(r.exports,r,r.exports,e),r.l=!0,r.exports}var n={};e.m=t,e.c=n,e.i=function(t){return t},e.d=function(t,n,i){e.o(t,n)||Object.defineProperty(t,n,{configurable:!1,enumerable:!0,get:i})},e.n=function(t){var n=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(n,\"a\",n),n},e.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},e.p=\"\",e(e.s=19)}([function(t,e,n){\"use strict\";function i(){this.imagedata=null,this.width=0,this.height=0,this.qrCodeSymbol=null,this.debug=!1,this.callback=null}function r(t,e){return t>=0?t>>e:(t>>e)+(2<<~e)}n.d(e,\"b\",function(){return s}),e.a=i,e.c=r;var o=n(14),a=n(13),s={};s.sizeOfDataLengthInfo=[[10,9,8,8],[12,11,16,10],[14,13,16,12]],i.prototype.decode=function(t,e){var n=function(){try{this.error=void 0,this.result=this.process(this.imagedata)}catch(t){this.error=t,this.result=void 0}return null!=this.callback&&this.callback(this.error,this.result),this.result}.bind(this);if(void 0!=t&&void 0!=t.width)this.width=t.width,this.height=t.height,this.imagedata={data:e||t.data},this.imagedata.width=t.width,this.imagedata.height=t.height,n();else{if(\"undefined\"==typeof Image)throw new Error(\"This source format is not supported in your environment, you need to pass an image buffer with width and height (see https://github.com/edi9999/jsqrcode/blob/master/test/qrcode.js)\");var i=new Image;i.crossOrigin=\"Anonymous\",i.onload=function(){var t=document.createElement(\"canvas\"),e=t.getContext(\"2d\"),r=document.getElementById(\"out-canvas\");if(null!=r){var o=r.getContext(\"2d\");o.clearRect(0,0,320,240),o.drawImage(i,0,0,320,240)}t.width=i.width,t.height=i.height,e.drawImage(i,0,0),this.width=i.width,this.height=i.height;try{this.imagedata=e.getImageData(0,0,i.width,i.height)}catch(t){if(this.result=\"Cross domain image reading not supported in your browser! Save it to your computer then drag and drop the file!\",null!=this.callback)return this.callback(null,this.result)}n()}.bind(this),i.src=t}},i.prototype.decode_utf8=function(t){return decodeURIComponent(escape(t))},i.prototype.process=function(t){for(var e=(new Date).getTime(),n=this.grayScaleToBitmap(this.grayscale(t)),i=new o.a(n),r=i.detect(),s=a.a.decode(r.bits),h=s.DataByte,f=\"\",w=0;w<h.length;w++)for(var u=0;u<h[w].length;u++)f+=String.fromCharCode(h[w][u]);var l=(new Date).getTime(),c=l-e;return this.debug&&console.log(\"QR Code processing time (ms): \"+c),{result:this.decode_utf8(f),points:r.points}},i.prototype.getPixel=function(t,e,n){if(t.width<e)throw\"point error\";if(t.height<n)throw\"point error\";var i=4*e+n*t.width*4;return(33*t.data[i]+34*t.data[i+1]+33*t.data[i+2])/100},i.prototype.binarize=function(t){for(var e=new Array(this.width*this.height),n=0;n<this.height;n++)for(var i=0;i<this.width;i++){var r=this.getPixel(i,n);e[i+n*this.width]=r<=t}return e},i.prototype.getMiddleBrightnessPerArea=function(t){for(var e=Math.floor(t.width/4),n=Math.floor(t.height/4),i=new Array(4),r=0;r<4;r++){i[r]=new Array(4);for(var o=0;o<4;o++)i[r][o]=[0,0]}for(var a=0;a<4;a++)for(var s=0;s<4;s++){i[s][a][0]=255;for(var h=0;h<n;h++)for(var f=0;f<e;f++){var w=t.data[e*s+f+(n*a+h)*t.width];w<i[s][a][0]&&(i[s][a][0]=w),w>i[s][a][1]&&(i[s][a][1]=w)}}for(var u=new Array(4),l=0;l<4;l++)u[l]=new Array(4);for(var a=0;a<4;a++)for(var s=0;s<4;s++)u[s][a]=Math.floor((i[s][a][0]+i[s][a][1])/2);return u},i.prototype.grayScaleToBitmap=function(t){for(var e=this.getMiddleBrightnessPerArea(t),n=e.length,i=Math.floor(t.width/n),r=Math.floor(t.height/n),o=0;o<n;o++)for(var a=0;a<n;a++)for(var s=0;s<r;s++)for(var h=0;h<i;h++)t.data[i*a+h+(r*o+s)*t.width]=t.data[i*a+h+(r*o+s)*t.width]<e[a][o];return t},i.prototype.grayscale=function(t){for(var e=new Array(t.width*t.height),n=0;n<t.height;n++)for(var i=0;i<t.width;i++){var r=this.getPixel(t,i,n);e[i+n*t.width]=r}return{height:t.height,width:t.width,data:e}}},function(t,e,n){\"use strict\";function i(t,e){if(e||(e=t),t<1||e<1)throw\"Both dimensions must be greater than 0\";this.width=t,this.height=e;var n=t>>5;0!=(31&t)&&n++,this.rowSize=n,this.bits=new Array(n*e);for(var i=0;i<this.bits.length;i++)this.bits[i]=0}e.a=i;var r=n(0);Object.defineProperty(i.prototype,\"Dimension\",{get:function(){if(this.width!=this.height)throw\"Can't call getDimension() on a non-square matrix\";return this.width}}),i.prototype.get_Renamed=function(t,e){var i=e*this.rowSize+(t>>5);return 0!=(1&n.i(r.c)(this.bits[i],31&t))},i.prototype.set_Renamed=function(t,e){var n=e*this.rowSize+(t>>5);this.bits[n]|=1<<(31&t)},i.prototype.flip=function(t,e){var n=e*this.rowSize+(t>>5);this.bits[n]^=1<<(31&t)},i.prototype.clear=function(){for(var t=this.bits.length,e=0;e<t;e++)this.bits[e]=0},i.prototype.setRegion=function(t,e,n,i){if(e<0||t<0)throw\"Left and top must be nonnegative\";if(i<1||n<1)throw\"Height and width must be at least 1\";var r=t+n,o=e+i;if(o>this.height||r>this.width)throw\"The region must fit inside the matrix\";for(var a=e;a<o;a++)for(var s=a*this.rowSize,h=t;h<r;h++)this.bits[s+(h>>5)]|=1<<(31&h)}},function(t,e,n){\"use strict\";function i(t){this.errorCorrectionLevel=o.a.forBits(t>>3&3),this.dataMask=7&t}e.a=i;var r=n(0),o=n(15),a=[[21522,0],[20773,1],[24188,2],[23371,3],[17913,4],[16590,5],[20375,6],[19104,7],[30660,8],[29427,9],[32170,10],[30877,11],[26159,12],[25368,13],[27713,14],[26998,15],[5769,16],[5054,17],[7399,18],[6608,19],[1890,20],[597,21],[3340,22],[2107,23],[13663,24],[12392,25],[16177,26],[14854,27],[9396,28],[8579,29],[11994,30],[11245,31]],s=[0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4];i.prototype.GetHashCode=function(){return this.errorCorrectionLevel.ordinal()<<3|this.dataMask},i.prototype.Equals=function(t){var e=t;return this.errorCorrectionLevel==e.errorCorrectionLevel&&this.dataMask==e.dataMask},i.numBitsDiffering=function(t,e){return t^=e,s[15&t]+s[15&n.i(r.c)(t,4)]+s[15&n.i(r.c)(t,8)]+s[15&n.i(r.c)(t,12)]+s[15&n.i(r.c)(t,16)]+s[15&n.i(r.c)(t,20)]+s[15&n.i(r.c)(t,24)]+s[15&n.i(r.c)(t,28)]},i.decodeFormatInformation=function(t){var e=i.doDecodeFormatInformation(t);return null!=e?e:i.doDecodeFormatInformation(21522^t)},i.doDecodeFormatInformation=function(t){for(var e=4294967295,n=0,r=0;r<a.length;r++){var o=a[r],s=o[0];if(s==t)return new i(o[1]);var h=this.numBitsDiffering(t,s);h<e&&(n=o[1],e=h)}return e<=3?new i(n):null}},function(t,e,n){\"use strict\";function i(t){this.expTable=new Array(256),this.logTable=new Array(256);for(var e=1,n=0;n<256;n++)this.expTable[n]=e,(e<<=1)>=256&&(e^=t);for(var n=0;n<255;n++)this.logTable[this.expTable[n]]=n;var i=new Array(1);i[0]=0,this.zero=new r.a(this,new Array(i));var o=new Array(1);o[0]=1,this.one=new r.a(this,new Array(o))}e.a=i;var r=n(4);Object.defineProperty(i.prototype,\"Zero\",{get:function(){return this.zero}}),Object.defineProperty(i.prototype,\"One\",{get:function(){return this.one}}),i.prototype.buildMonomial=function(t,e){if(t<0)throw\"System.ArgumentException\";if(0==e)return this.zero;for(var n=new Array(t+1),i=0;i<n.length;i++)n[i]=0;return n[0]=e,new r.a(this,n)},i.prototype.exp=function(t){return this.expTable[t]},i.prototype.log=function(t){if(0==t)throw\"System.ArgumentException\";return this.logTable[t]},i.prototype.inverse=function(t){if(0==t)throw\"System.ArithmeticException\";return this.expTable[255-this.logTable[t]]},i.prototype.addOrSubtract=function(t,e){return t^e},i.prototype.multiply=function(t,e){return 0==t||0==e?0:1==t?e:1==e?t:this.expTable[(this.logTable[t]+this.logTable[e])%255]},i.QR_CODE_FIELD=new i(285),i.DATA_MATRIX_FIELD=new i(301)},function(t,e,n){\"use strict\";function i(t,e){if(null==e||0==e.length)throw\"System.ArgumentException\";this.field=t;var n=e.length;if(n>1&&0==e[0]){for(var i=1;i<n&&0==e[i];)i++;if(i==n)this.coefficients=t.Zero.coefficients;else{this.coefficients=new Array(n-i);for(var r=0;r<this.coefficients.length;r++)this.coefficients[r]=0;for(var o=0;o<this.coefficients.length;o++)this.coefficients[o]=e[i+o]}}else this.coefficients=e}e.a=i,Object.defineProperty(i.prototype,\"Zero\",{get:function(){return 0==this.coefficients[0]}}),Object.defineProperty(i.prototype,\"Degree\",{get:function(){return this.coefficients.length-1}}),i.prototype.getCoefficient=function(t){return this.coefficients[this.coefficients.length-1-t]},i.prototype.evaluateAt=function(t){if(0==t)return this.getCoefficient(0);var e=this.coefficients.length;if(1==t){for(var n=0,i=0;i<e;i++)n=this.field.addOrSubtract(n,this.coefficients[i]);return n}for(var r=this.coefficients[0],i=1;i<e;i++)r=this.field.addOrSubtract(this.field.multiply(t,r),this.coefficients[i]);return r},i.prototype.addOrSubtract=function(t){if(this.field!=t.field)throw\"GF256Polys do not have same GF256 field\";if(this.Zero)return t;if(t.Zero)return this;var e=this.coefficients,n=t.coefficients;if(e.length>n.length){var r=e;e=n,n=r}for(var o=new Array(n.length),a=n.length-e.length,s=0;s<a;s++)o[s]=n[s];for(var h=a;h<n.length;h++)o[h]=this.field.addOrSubtract(e[h-a],n[h]);return new i(this.field,o)},i.prototype.multiply1=function(t){if(this.field!=t.field)throw\"GF256Polys do not have same GF256 field\";if(this.Zero||t.Zero)return this.field.Zero;for(var e=this.coefficients,n=e.length,r=t.coefficients,o=r.length,a=new Array(n+o-1),s=0;s<n;s++)for(var h=e[s],f=0;f<o;f++)a[s+f]=this.field.addOrSubtract(a[s+f],this.field.multiply(h,r[f]));return new i(this.field,a)},i.prototype.multiply2=function(t){if(0==t)return this.field.Zero;if(1==t)return this;for(var e=this.coefficients.length,n=new Array(e),r=0;r<e;r++)n[r]=this.field.multiply(this.coefficients[r],t);return new i(this.field,n)},i.prototype.multiplyByMonomial=function(t,e){if(t<0)throw\"System.ArgumentException\";if(0==e)return this.field.Zero;for(var n=this.coefficients.length,r=new Array(n+t),o=0;o<r.length;o++)r[o]=0;for(var o=0;o<n;o++)r[o]=this.field.multiply(this.coefficients[o],e);return new i(this.field,r)},i.prototype.divide=function(t){if(this.field!=t.field)throw\"GF256Polys do not have same GF256 field\";if(t.Zero)throw\"Divide by 0\";for(var e=this.field.Zero,n=this,i=t.getCoefficient(t.Degree),r=this.field.inverse(i);n.Degree>=t.Degree&&!n.Zero;){var o=n.Degree-t.Degree,a=this.field.multiply(n.getCoefficient(n.Degree),r),s=t.multiplyByMonomial(o,a),h=this.field.buildMonomial(o,a);e=e.addOrSubtract(h),n=n.addOrSubtract(s)}return[e,n]}},function(t,e,n){\"use strict\";function i(t,e){this.count=t,this.dataCodewords=e}function r(t,e,n){this.ecCodewordsPerBlock=t,this.ecBlocks=n?[e,n]:[e]}function o(t,e,n,i,r,o){this.versionNumber=t,this.alignmentPatternCenters=e,this.ecBlocks=[n,i,r,o];for(var a=0,s=n.ecCodewordsPerBlock,h=n.getECBlocks(),f=0;f<h.length;f++){var w=h[f];a+=w.count*(w.dataCodewords+s)}this.totalCodewords=a}e.a=o;var a=n(2),s=n(1);Object.defineProperty(r.prototype,\"TotalECCodewords\",{get:function(){return this.ecCodewordsPerBlock*this.NumBlocks}}),Object.defineProperty(r.prototype,\"NumBlocks\",{get:function(){for(var t=0,e=0;e<this.ecBlocks.length;e++)t+=this.ecBlocks[e].length;return t}}),r.prototype.getECBlocks=function(){return this.ecBlocks},Object.defineProperty(o.prototype,\"DimensionForVersion\",{get:function(){return 17+4*this.versionNumber}}),o.prototype.buildFunctionPattern=function(){var t=this.DimensionForVersion,e=new s.a(t);e.setRegion(0,0,9,9),e.setRegion(t-8,0,8,9),e.setRegion(0,t-8,9,8);for(var n=this.alignmentPatternCenters.length,i=0;i<n;i++)for(var r=this.alignmentPatternCenters[i]-2,o=0;o<n;o++)0==i&&(0==o||o==n-1)||i==n-1&&0==o||e.setRegion(this.alignmentPatternCenters[o]-2,r,5,5);return e.setRegion(6,9,1,t-17),e.setRegion(9,6,t-17,1),this.versionNumber>6&&(e.setRegion(t-11,0,3,6),e.setRegion(0,t-11,6,3)),e},o.prototype.getECBlocksForLevel=function(t){return this.ecBlocks[t.ordinal()]},o.VERSION_DECODE_INFO=[31892,34236,39577,42195,48118,51042,55367,58893,63784,68472,70749,76311,79154,84390,87683,92361,96236,102084,102881,110507,110734,117786,119615,126325,127568,133589,136944,141498,145311,150283,152622,158308,161089,167017],o.VERSIONS=function(){return[new o(1,[],new r(7,new i(1,19)),new r(10,new i(1,16)),new r(13,new i(1,13)),new r(17,new i(1,9))),new o(2,[6,18],new r(10,new i(1,34)),new r(16,new i(1,28)),new r(22,new i(1,22)),new r(28,new i(1,16))),new o(3,[6,22],new r(15,new i(1,55)),new r(26,new i(1,44)),new r(18,new i(2,17)),new r(22,new i(2,13))),new o(4,[6,26],new r(20,new i(1,80)),new r(18,new i(2,32)),new r(26,new i(2,24)),new r(16,new i(4,9))),new o(5,[6,30],new r(26,new i(1,108)),new r(24,new i(2,43)),new r(18,new i(2,15),new i(2,16)),new r(22,new i(2,11),new i(2,12))),new o(6,[6,34],new r(18,new i(2,68)),new r(16,new i(4,27)),new r(24,new i(4,19)),new r(28,new i(4,15))),new o(7,[6,22,38],new r(20,new i(2,78)),new r(18,new i(4,31)),new r(18,new i(2,14),new i(4,15)),new r(26,new i(4,13),new i(1,14))),new o(8,[6,24,42],new r(24,new i(2,97)),new r(22,new i(2,38),new i(2,39)),new r(22,new i(4,18),new i(2,19)),new r(26,new i(4,14),new i(2,15))),new o(9,[6,26,46],new r(30,new i(2,116)),new r(22,new i(3,36),new i(2,37)),new r(20,new i(4,16),new i(4,17)),new r(24,new i(4,12),new i(4,13))),new o(10,[6,28,50],new r(18,new i(2,68),new i(2,69)),new r(26,new i(4,43),new i(1,44)),new r(24,new i(6,19),new i(2,20)),new r(28,new i(6,15),new i(2,16))),new o(11,[6,30,54],new r(20,new i(4,81)),new r(30,new i(1,50),new i(4,51)),new r(28,new i(4,22),new i(4,23)),new r(24,new i(3,12),new i(8,13))),new o(12,[6,32,58],new r(24,new i(2,92),new i(2,93)),new r(22,new i(6,36),new i(2,37)),new r(26,new i(4,20),new i(6,21)),new r(28,new i(7,14),new i(4,15))),new o(13,[6,34,62],new r(26,new i(4,107)),new r(22,new i(8,37),new i(1,38)),new r(24,new i(8,20),new i(4,21)),new r(22,new i(12,11),new i(4,12))),new o(14,[6,26,46,66],new r(30,new i(3,115),new i(1,116)),new r(24,new i(4,40),new i(5,41)),new r(20,new i(11,16),new i(5,17)),new r(24,new i(11,12),new i(5,13))),new o(15,[6,26,48,70],new r(22,new i(5,87),new i(1,88)),new r(24,new i(5,41),new i(5,42)),new r(30,new i(5,24),new i(7,25)),new r(24,new i(11,12),new i(7,13))),new o(16,[6,26,50,74],new r(24,new i(5,98),new i(1,99)),new r(28,new i(7,45),new i(3,46)),new r(24,new i(15,19),new i(2,20)),new r(30,new i(3,15),new i(13,16))),new o(17,[6,30,54,78],new r(28,new i(1,107),new i(5,108)),new r(28,new i(10,46),new i(1,47)),new r(28,new i(1,22),new i(15,23)),new r(28,new i(2,14),new i(17,15))),new o(18,[6,30,56,82],new r(30,new i(5,120),new i(1,121)),new r(26,new i(9,43),new i(4,44)),new r(28,new i(17,22),new i(1,23)),new r(28,new i(2,14),new i(19,15))),new o(19,[6,30,58,86],new r(28,new i(3,113),new i(4,114)),new r(26,new i(3,44),new i(11,45)),new r(26,new i(17,21),new i(4,22)),new r(26,new i(9,13),new i(16,14))),new o(20,[6,34,62,90],new r(28,new i(3,107),new i(5,108)),new r(26,new i(3,41),new i(13,42)),new r(30,new i(15,24),new i(5,25)),new r(28,new i(15,15),new i(10,16))),new o(21,[6,28,50,72,94],new r(28,new i(4,116),new i(4,117)),new r(26,new i(17,42)),new r(28,new i(17,22),new i(6,23)),new r(30,new i(19,16),new i(6,17))),new o(22,[6,26,50,74,98],new r(28,new i(2,111),new i(7,112)),new r(28,new i(17,46)),new r(30,new i(7,24),new i(16,25)),new r(24,new i(34,13))),new o(23,[6,30,54,74,102],new r(30,new i(4,121),new i(5,122)),new r(28,new i(4,47),new i(14,48)),new r(30,new i(11,24),new i(14,25)),new r(30,new i(16,15),new i(14,16))),new o(24,[6,28,54,80,106],new r(30,new i(6,117),new i(4,118)),new r(28,new i(6,45),new i(14,46)),new r(30,new i(11,24),new i(16,25)),new r(30,new i(30,16),new i(2,17))),new o(25,[6,32,58,84,110],new r(26,new i(8,106),new i(4,107)),new r(28,new i(8,47),new i(13,48)),new r(30,new i(7,24),new i(22,25)),new r(30,new i(22,15),new i(13,16))),new o(26,[6,30,58,86,114],new r(28,new i(10,114),new i(2,115)),new r(28,new i(19,46),new i(4,47)),new r(28,new i(28,22),new i(6,23)),new r(30,new i(33,16),new i(4,17))),new o(27,[6,34,62,90,118],new r(30,new i(8,122),new i(4,123)),new r(28,new i(22,45),new i(3,46)),new r(30,new i(8,23),new i(26,24)),new r(30,new i(12,15),new i(28,16))),new o(28,[6,26,50,74,98,122],new r(30,new i(3,117),new i(10,118)),new r(28,new i(3,45),new i(23,46)),new r(30,new i(4,24),new i(31,25)),new r(30,new i(11,15),new i(31,16))),new o(29,[6,30,54,78,102,126],new r(30,new i(7,116),new i(7,117)),new r(28,new i(21,45),new i(7,46)),new r(30,new i(1,23),new i(37,24)),new r(30,new i(19,15),new i(26,16))),new o(30,[6,26,52,78,104,130],new r(30,new i(5,115),new i(10,116)),new r(28,new i(19,47),new i(10,48)),new r(30,new i(15,24),new i(25,25)),new r(30,new i(23,15),new i(25,16))),new o(31,[6,30,56,82,108,134],new r(30,new i(13,115),new i(3,116)),new r(28,new i(2,46),new i(29,47)),new r(30,new i(42,24),new i(1,25)),new r(30,new i(23,15),new i(28,16))),new o(32,[6,34,60,86,112,138],new r(30,new i(17,115)),new r(28,new i(10,46),new i(23,47)),new r(30,new i(10,24),new i(35,25)),new r(30,new i(19,15),new i(35,16))),new o(33,[6,30,58,86,114,142],new r(30,new i(17,115),new i(1,116)),new r(28,new i(14,46),new i(21,47)),new r(30,new i(29,24),new i(19,25)),new r(30,new i(11,15),new i(46,16))),new o(34,[6,34,62,90,118,146],new r(30,new i(13,115),new i(6,116)),new r(28,new i(14,46),new i(23,47)),new r(30,new i(44,24),new i(7,25)),new r(30,new i(59,16),new i(1,17))),new o(35,[6,30,54,78,102,126,150],new r(30,new i(12,121),new i(7,122)),new r(28,new i(12,47),new i(26,48)),new r(30,new i(39,24),new i(14,25)),new r(30,new i(22,15),new i(41,16))),new o(36,[6,24,50,76,102,128,154],new r(30,new i(6,121),new i(14,122)),new r(28,new i(6,47),new i(34,48)),new r(30,new i(46,24),new i(10,25)),new r(30,new i(2,15),new i(64,16))),new o(37,[6,28,54,80,106,132,158],new r(30,new i(17,122),new i(4,123)),new r(28,new i(29,46),new i(14,47)),new r(30,new i(49,24),new i(10,25)),new r(30,new i(24,15),new i(46,16))),new o(38,[6,32,58,84,110,136,162],new r(30,new i(4,122),new i(18,123)),new r(28,new i(13,46),new i(32,47)),new r(30,new i(48,24),new i(14,25)),new r(30,new i(42,15),new i(32,16))),new o(39,[6,26,54,82,110,138,166],new r(30,new i(20,117),new i(4,118)),new r(28,new i(40,47),new i(7,48)),new r(30,new i(43,24),new i(22,25)),new r(30,new i(10,15),new i(67,16))),new o(40,[6,30,58,86,114,142,170],new r(30,new i(19,118),new i(6,119)),new r(28,new i(18,47),new i(31,48)),new r(30,new i(34,24),new i(34,25)),new r(30,new i(20,15),new i(61,16)))]}(),o.getVersionForNumber=function(t){if(t<1||t>40)throw\"ArgumentException\";return o.VERSIONS[t-1]},o.getProvisionalVersionForDimension=function(t){if(t%4!=1)throw\"Error getProvisionalVersionForDimension\";try{return o.getVersionForNumber(t-17>>2)}catch(t){throw\"Error getVersionForNumber\"}},o.decodeVersionInformation=function(t){for(var e=4294967295,n=0,i=0;i<o.VERSION_DECODE_INFO.length;i++){var r=o.VERSION_DECODE_INFO[i];if(r==t)return this.getVersionForNumber(i+7);var s=a.a.numBitsDiffering(t,r);s<e&&(n=i+7,e=s)}return e<=3?this.getVersionForNumber(n):null}},function(t,e,n){\"use strict\";Object.defineProperty(e,\"__esModule\",{value:!0});var i=n(0);e.default=i.a},function(t,e){t.exports=function(t){return t.webpackPolyfill||(t.deprecate=function(){},t.paths=[],t.children||(t.children=[]),Object.defineProperty(t,\"loaded\",{enumerable:!0,get:function(){return t.l}}),Object.defineProperty(t,\"id\",{enumerable:!0,get:function(){return t.i}}),t.webpackPolyfill=1),t}},function(t,e,n){\"use strict\";function i(t,e,n){this.x=t,this.y=e,this.count=1,this.estimatedModuleSize=n}function r(t,e,n,i,r,o,a){this.image=t,this.possibleCenters=[],this.startX=e,this.startY=n,this.width=i,this.height=r,this.moduleSize=o,this.crossCheckStateCount=[0,0,0],this.resultPointCallback=a}e.a=r,Object.defineProperty(i.prototype,\"X\",{get:function(){return Math.floor(this.x)}}),Object.defineProperty(i.prototype,\"Y\",{get:function(){return Math.floor(this.y)}}),i.prototype.incrementCount=function(){this.count++},i.prototype.aboutEquals=function(t,e,n){if(Math.abs(e-this.y)<=t&&Math.abs(n-this.x)<=t){var i=Math.abs(t-this.estimatedModuleSize);return i<=1||i/this.estimatedModuleSize<=1}return!1},r.prototype.centerFromEnd=function(t,e){return e-t[2]-t[1]/2},r.prototype.foundPatternCross=function(t){for(var e=this.moduleSize,n=e/2,i=0;i<3;i++)if(Math.abs(e-t[i])>=n)return!1;return!0},r.prototype.crossCheckVertical=function(t,e,n,i){var r=this.image,o=r.height,a=this.crossCheckStateCount;a[0]=0,a[1]=0,a[2]=0;for(var s=t;s>=0&&r.data[e+s*r.width]&&a[1]<=n;)a[1]++,s--;if(s<0||a[1]>n)return NaN;for(;s>=0&&!r.data[e+s*r.width]&&a[0]<=n;)a[0]++,s--;if(a[0]>n)return NaN;for(s=t+1;s<o&&r.data[e+s*r.width]&&a[1]<=n;)a[1]++,s++;if(s==o||a[1]>n)return NaN;for(;s<o&&!r.data[e+s*r.width]&&a[2]<=n;)a[2]++,s++;if(a[2]>n)return NaN;var h=a[0]+a[1]+a[2];return 5*Math.abs(h-i)>=2*i?NaN:this.foundPatternCross(a)?this.centerFromEnd(a,s):NaN},r.prototype.handlePossibleCenter=function(t,e,n){var r=t[0]+t[1]+t[2],o=this.centerFromEnd(t,n),a=this.crossCheckVertical(e,Math.floor(o),2*t[1],r);if(!isNaN(a)){for(var s=(t[0]+t[1]+t[2])/3,h=this.possibleCenters.length,f=0;f<h;f++){if(this.possibleCenters[f].aboutEquals(s,a,o))return new i(o,a,s)}var w=new i(o,a,s);this.possibleCenters.push(w),null!=this.resultPointCallback&&this.resultPointCallback.foundPossibleResultPoint(w)}return null},r.prototype.find=function(){for(var t=this.image,e=this.startX,n=this.height,i=e+this.width,r=this.startY+(n>>1),o=[0,0,0],a=0;a<n;a++){var s=r+(0==(1&a)?a+1>>1:-(a+1>>1));o[0]=0,o[1]=0,o[2]=0;for(var h=e;h<i&&!t.data[h+t.width*s];)h++;for(var f=0;h<i;){if(t.data[h+s*t.width])if(1==f)o[f]++;else if(2==f){if(this.foundPatternCross(o)){var w=this.handlePossibleCenter(o,s,h);if(null!=w)return w}o[0]=o[2],o[1]=1,o[2]=0,f=1}else o[++f]++;else 1==f&&f++,o[f]++;h++}if(this.foundPatternCross(o)){var w=this.handlePossibleCenter(o,s,i);if(null!=w)return w}}if(0!=this.possibleCenters.length)return this.possibleCenters[0];throw\"Couldn't find enough alignment patterns\"}},function(t,e,n){\"use strict\";function i(t){var e=t.Dimension;if(e<21||1!=(3&e))throw\"Error BitMatrixParser\";this.bitMatrix=t,this.parsedVersion=null,this.parsedFormatInfo=null}e.a=i;var r=n(2),o=n(5),a=n(12);i.prototype.copyBit=function(t,e,n){return this.bitMatrix.get_Renamed(t,e)?n<<1|1:n<<1},i.prototype.readFormatInformation=function(){if(null!=this.parsedFormatInfo)return this.parsedFormatInfo;for(var t=0,e=0;e<6;e++)t=this.copyBit(e,8,t);t=this.copyBit(7,8,t),t=this.copyBit(8,8,t),t=this.copyBit(8,7,t);for(var n=5;n>=0;n--)t=this.copyBit(8,n,t);if(this.parsedFormatInfo=r.a.decodeFormatInformation(t),null!=this.parsedFormatInfo)return this.parsedFormatInfo;var i=this.bitMatrix.Dimension;t=0;for(var o=i-8,e=i-1;e>=o;e--)t=this.copyBit(e,8,t);for(var n=i-7;n<i;n++)t=this.copyBit(8,n,t);if(this.parsedFormatInfo=r.a.decodeFormatInformation(t),null!=this.parsedFormatInfo)return this.parsedFormatInfo;throw\"Error readFormatInformation\"},i.prototype.readVersion=function(){if(null!=this.parsedVersion)return this.parsedVersion;var t=this.bitMatrix.Dimension,e=t-17>>2;if(e<=6)return o.a.getVersionForNumber(e);for(var n=0,i=t-11,r=5;r>=0;r--)for(var a=t-9;a>=i;a--)n=this.copyBit(a,r,n);if(this.parsedVersion=o.a.decodeVersionInformation(n),null!=this.parsedVersion&&this.parsedVersion.DimensionForVersion==t)return this.parsedVersion;n=0;for(var a=5;a>=0;a--)for(var r=t-9;r>=i;r--)n=this.copyBit(a,r,n);if(this.parsedVersion=o.a.decodeVersionInformation(n),null!=this.parsedVersion&&this.parsedVersion.DimensionForVersion==t)return this.parsedVersion;throw\"Error readVersion\"},i.prototype.readCodewords=function(){var t=this.readFormatInformation(),e=this.readVersion(),n=a.a.forReference(t.dataMask),i=this.bitMatrix.Dimension;n.unmaskBitMatrix(this.bitMatrix,i);for(var r=e.buildFunctionPattern(),o=!0,s=new Array(e.totalCodewords),h=0,f=0,w=0,u=i-1;u>0;u-=2){6==u&&u--;for(var l=0;l<i;l++)for(var c=o?i-1-l:l,d=0;d<2;d++)r.get_Renamed(u-d,c)||(w++,f<<=1,this.bitMatrix.get_Renamed(u-d,c)&&(f|=1),8==w&&(s[h++]=f,w=0,f=0));o^=!0}if(h!=e.totalCodewords)throw\"Error readCodewords\";return s}},function(t,e,n){\"use strict\";function i(t,e){this.numDataCodewords=t,this.codewords=e}e.a=i,i.getDataBlocks=function(t,e,n){if(t.length!=e.totalCodewords)throw\"ArgumentException\";for(var r=e.getECBlocksForLevel(n),o=0,a=r.getECBlocks(),s=0;s<a.length;s++)o+=a[s].count;for(var h=new Array(o),f=0,w=0;w<a.length;w++)for(var u=a[w],s=0;s<u.count;s++){var l=u.dataCodewords,c=r.ecCodewordsPerBlock+l;h[f++]=new i(l,new Array(c))}for(var d=h[0].codewords.length,p=h.length-1;p>=0;){if(h[p].codewords.length==d)break;p--}p++;for(var g=d-r.ecCodewordsPerBlock,v=0,s=0;s<g;s++)for(var w=0;w<f;w++)h[w].codewords[s]=t[v++];for(var w=p;w<f;w++)h[w].codewords[g]=t[v++];for(var m=h[0].codewords.length,s=g;s<m;s++)for(var w=0;w<f;w++){var b=w<p?s:s+1;h[w].codewords[b]=t[v++]}return h}},function(t,e,n){\"use strict\";function i(t,e,n){this.blockPointer=0,this.bitPointer=7,this.dataLength=0,this.blocks=t,this.numErrorCorrectionCode=n,e<=9?this.dataLengthMode=0:e>=10&&e<=26?this.dataLengthMode=1:e>=27&&e<=40&&(this.dataLengthMode=2)}e.a=i;var r=n(0);i.prototype.getNextBits=function(t){var e=0;if(t<this.bitPointer+1){for(var n=0,i=0;i<t;i++)n+=1<<i;return n<<=this.bitPointer-t+1,e=(this.blocks[this.blockPointer]&n)>>this.bitPointer-t+1,this.bitPointer-=t,e}if(t<this.bitPointer+1+8){for(var r=0,i=0;i<this.bitPointer+1;i++)r+=1<<i;return e=(this.blocks[this.blockPointer]&r)<<t-(this.bitPointer+1),this.blockPointer++,e+=this.blocks[this.blockPointer]>>8-(t-(this.bitPointer+1)),this.bitPointer=this.bitPointer-t%8,this.bitPointer<0&&(this.bitPointer=8+this.bitPointer),e}if(t<this.bitPointer+1+16){for(var r=0,o=0,i=0;i<this.bitPointer+1;i++)r+=1<<i;var a=(this.blocks[this.blockPointer]&r)<<t-(this.bitPointer+1);this.blockPointer++;var s=this.blocks[this.blockPointer]<<t-(this.bitPointer+1+8);this.blockPointer++;for(var i=0;i<t-(this.bitPointer+1+8);i++)o+=1<<i;o<<=8-(t-(this.bitPointer+1+8));return e=a+s+((this.blocks[this.blockPointer]&o)>>8-(t-(this.bitPointer+1+8))),this.bitPointer=this.bitPointer-(t-8)%8,this.bitPointer<0&&(this.bitPointer=8+this.bitPointer),e}return 0},i.prototype.NextMode=function(){return this.blockPointer>this.blocks.length-this.numErrorCorrectionCode-2?0:this.getNextBits(4)},i.prototype.getDataLength=function(t){for(var e=0;;){if(t>>e==1)break;e++}return this.getNextBits(r.b.sizeOfDataLengthInfo[this.dataLengthMode][e])},i.prototype.getRomanAndFigureString=function(t){var e=t,n=0,i=\"\",r=[\"0\",\"1\",\"2\",\"3\",\"4\",\"5\",\"6\",\"7\",\"8\",\"9\",\"A\",\"B\",\"C\",\"D\",\"E\",\"F\",\"G\",\"H\",\"I\",\"J\",\"K\",\"L\",\"M\",\"N\",\"O\",\"P\",\"Q\",\"R\",\"S\",\"T\",\"U\",\"V\",\"W\",\"X\",\"Y\",\"Z\",\" \",\"$\",\"%\",\"*\",\"+\",\"-\",\".\",\"/\",\":\"];do{if(e>1){n=this.getNextBits(11);var o=Math.floor(n/45),a=n%45;i+=r[o],i+=r[a],e-=2}else 1==e&&(n=this.getNextBits(6),i+=r[n],e-=1)}while(e>0);return i},i.prototype.getFigureString=function(t){var e=t,n=0,i=\"\";do{e>=3?(n=this.getNextBits(10),n<100&&(i+=\"0\"),n<10&&(i+=\"0\"),e-=3):2==e?(n=this.getNextBits(7),n<10&&(i+=\"0\"),e-=2):1==e&&(n=this.getNextBits(4),e-=1),i+=n}while(e>0);return i},i.prototype.get8bitByteArray=function(t){var e=t,n=0,i=[];do{n=this.getNextBits(8),i.push(n),e--}while(e>0);return i},i.prototype.getKanjiString=function(t){var e=t,n=0,i=\"\";do{n=this.getNextBits(13);var r=n%192,o=n/192,a=(o<<8)+r,s=0;s=a+33088<=40956?a+33088:a+49472,i+=String.fromCharCode(s),e--}while(e>0);return i},Object.defineProperty(i.prototype,\"DataByte\",{get:function(){for(var t=[];;){var e=this.NextMode();if(0==e){if(t.length>0)break;throw\"Empty data block\"}if(1!=e&&2!=e&&4!=e&&8!=e&&7!=e)throw\"Invalid mode: \"+e+\" in (block:\"+this.blockPointer+\" bit:\"+this.bitPointer+\")\";var n=this.getDataLength(e);if(n<1)throw\"Invalid data length: \"+n;switch(e){case 1:for(var i=this.getFigureString(n),r=new Array(i.length),o=0;o<i.length;o++)r[o]=i.charCodeAt(o);t.push(r);break;case 2:for(var i=this.getRomanAndFigureString(n),r=new Array(i.length),o=0;o<i.length;o++)r[o]=i.charCodeAt(o);t.push(r);break;case 4:var a=this.get8bitByteArray(n);t.push(a);break;case 8:var i=this.getKanjiString(n);t.push(i)}}return t}})},function(t,e,n){\"use strict\";function i(){this.unmaskBitMatrix=function(t,e){for(var n=0;n<e;n++)for(var i=0;i<e;i++)this.isMasked(n,i)&&t.flip(i,n)},this.isMasked=function(t,e){return 0==(t+e&1)}}function r(){this.unmaskBitMatrix=function(t,e){for(var n=0;n<e;n++)for(var i=0;i<e;i++)this.isMasked(n,i)&&t.flip(i,n)},this.isMasked=function(t,e){return 0==(1&t)}}function o(){this.unmaskBitMatrix=function(t,e){for(var n=0;n<e;n++)for(var i=0;i<e;i++)this.isMasked(n,i)&&t.flip(i,n)},this.isMasked=function(t,e){return e%3==0}}function a(){this.unmaskBitMatrix=function(t,e){for(var n=0;n<e;n++)for(var i=0;i<e;i++)this.isMasked(n,i)&&t.flip(i,n)},this.isMasked=function(t,e){return(t+e)%3==0}}function s(){this.unmaskBitMatrix=function(t,e){for(var n=0;n<e;n++)for(var i=0;i<e;i++)this.isMasked(n,i)&&t.flip(i,n)},this.isMasked=function(t,e){return 0==(n.i(u.c)(t,1)+e/3&1)}}function h(){this.unmaskBitMatrix=function(t,e){for(var n=0;n<e;n++)for(var i=0;i<e;i++)this.isMasked(n,i)&&t.flip(i,n)},this.isMasked=function(t,e){var n=t*e;return(1&n)+n%3==0}}function f(){this.unmaskBitMatrix=function(t,e){for(var n=0;n<e;n++)for(var i=0;i<e;i++)this.isMasked(n,i)&&t.flip(i,n)},this.isMasked=function(t,e){var n=t*e;return 0==((1&n)+n%3&1)}}function w(){this.unmaskBitMatrix=function(t,e){for(var n=0;n<e;n++)for(var i=0;i<e;i++)this.isMasked(n,i)&&t.flip(i,n)},this.isMasked=function(t,e){return 0==((t+e&1)+t*e%3&1)}}var u=n(0),l={};l.forReference=function(t){if(t<0||t>7)throw\"System.ArgumentException\";return l.DATA_MASKS[t]},l.DATA_MASKS=[new i,new r,new o,new a,new s,new h,new f,new w],e.a=l},function(t,e,n){\"use strict\";var i=n(18),r=n(3),o=n(9),a=n(10),s=n(11),h={};h.rsDecoder=new i.a(r.a.QR_CODE_FIELD),h.correctErrors=function(t,e){for(var n=t.length,i=new Array(n),r=0;r<n;r++)i[r]=255&t[r];var o=t.length-e;try{h.rsDecoder.decode(i,o)}catch(t){throw t}for(var r=0;r<e;r++)t[r]=i[r]},h.decode=function(t){for(var e=new o.a(t),n=e.readVersion(),i=e.readFormatInformation().errorCorrectionLevel,r=e.readCodewords(),f=a.a.getDataBlocks(r,n,i),w=0,u=0;u<f.length;u++)w+=f[u].numDataCodewords;for(var l=new Array(w),c=0,d=0;d<f.length;d++){var p=f[d],g=p.codewords,v=p.numDataCodewords;h.correctErrors(g,v);for(var u=0;u<v;u++)l[c++]=g[u]}return new s.a(l,n.versionNumber,i.bits)},e.a=h},function(t,e,n){\"use strict\";function i(t,e,n,i,r,o,a,s,h){this.a11=t,this.a12=i,this.a13=a,this.a21=e,this.a22=r,this.a23=s,this.a31=n,this.a32=o,this.a33=h}function r(t,e){this.bits=t,this.points=e}function o(t){this.image=t,this.resultPointCallback=null}e.a=o;var a=n(5),s=n(8),h=n(17),f=n(16);i.prototype.transformPoints1=function(t){for(var e=t.length,n=this.a11,i=this.a12,r=this.a13,o=this.a21,a=this.a22,s=this.a23,h=this.a31,f=this.a32,w=this.a33,u=0;u<e;u+=2){var l=t[u],c=t[u+1],d=r*l+s*c+w;t[u]=(n*l+o*c+h)/d,t[u+1]=(i*l+a*c+f)/d}},i.prototype.transformPoints2=function(t,e){for(var n=t.length,i=0;i<n;i++){var r=t[i],o=e[i],a=this.a13*r+this.a23*o+this.a33;t[i]=(this.a11*r+this.a21*o+this.a31)/a,e[i]=(this.a12*r+this.a22*o+this.a32)/a}},i.prototype.buildAdjoint=function(){return new i(this.a22*this.a33-this.a23*this.a32,this.a23*this.a31-this.a21*this.a33,this.a21*this.a32-this.a22*this.a31,this.a13*this.a32-this.a12*this.a33,this.a11*this.a33-this.a13*this.a31,this.a12*this.a31-this.a11*this.a32,this.a12*this.a23-this.a13*this.a22,this.a13*this.a21-this.a11*this.a23,this.a11*this.a22-this.a12*this.a21)},i.prototype.times=function(t){return new i(this.a11*t.a11+this.a21*t.a12+this.a31*t.a13,this.a11*t.a21+this.a21*t.a22+this.a31*t.a23,this.a11*t.a31+this.a21*t.a32+this.a31*t.a33,this.a12*t.a11+this.a22*t.a12+this.a32*t.a13,this.a12*t.a21+this.a22*t.a22+this.a32*t.a23,this.a12*t.a31+this.a22*t.a32+this.a32*t.a33,this.a13*t.a11+this.a23*t.a12+this.a33*t.a13,this.a13*t.a21+this.a23*t.a22+this.a33*t.a23,this.a13*t.a31+this.a23*t.a32+this.a33*t.a33)},i.quadrilateralToQuadrilateral=function(t,e,n,i,r,o,a,s,h,f,w,u,l,c,d,p){var g=this.quadrilateralToSquare(t,e,n,i,r,o,a,s);return this.squareToQuadrilateral(h,f,w,u,l,c,d,p).times(g)},i.squareToQuadrilateral=function(t,e,n,r,o,a,s,h){var f=h-a,w=e-r+a-h;if(0==f&&0==w)return new i(n-t,o-n,t,r-e,a-r,e,0,0,1);var u=n-o,l=s-o,c=t-n+o-s,d=r-a,p=u*f-l*d,g=(c*f-l*w)/p,v=(u*w-c*d)/p;return new i(n-t+g*n,s-t+v*s,t,r-e+g*r,h-e+v*h,e,g,v,1)},i.quadrilateralToSquare=function(t,e,n,i,r,o,a,s){return this.squareToQuadrilateral(t,e,n,i,r,o,a,s).buildAdjoint()},o.prototype.sizeOfBlackWhiteBlackRun=function(t,e,n,i){var r=Math.abs(i-e)>Math.abs(n-t);if(r){var o=t;t=e,e=o,o=n,n=i,i=o}for(var a=Math.abs(n-t),s=Math.abs(i-e),h=-a>>1,f=e<i?1:-1,w=t<n?1:-1,u=0,l=t,c=e;l!=n;l+=w){var d=r?c:l,p=r?l:c;if(1==u?this.image.data[d+p*this.image.width]&&u++:this.image.data[d+p*this.image.width]||u++,3==u){var g=l-t,v=c-e;return Math.sqrt(g*g+v*v)}if((h+=s)>0){if(c==i)break;c+=f,h-=a}}var m=n-t,b=i-e;return Math.sqrt(m*m+b*b)},o.prototype.sizeOfBlackWhiteBlackRunBothWays=function(t,e,n,i){var r=this.sizeOfBlackWhiteBlackRun(t,e,n,i),o=1,a=t-(n-t);a<0?(o=t/(t-a),a=0):a>=this.image.width&&(o=(this.image.width-1-t)/(a-t),a=this.image.width-1);var s=Math.floor(e-(i-e)*o);return o=1,s<0?(o=e/(e-s),s=0):s>=this.image.height&&(o=(this.image.height-1-e)/(s-e),s=this.image.height-1),a=Math.floor(t+(a-t)*o),(r+=this.sizeOfBlackWhiteBlackRun(t,e,a,s))-1},o.prototype.calculateModuleSizeOneWay=function(t,e){var n=this.sizeOfBlackWhiteBlackRunBothWays(Math.floor(t.X),Math.floor(t.Y),Math.floor(e.X),Math.floor(e.Y)),i=this.sizeOfBlackWhiteBlackRunBothWays(Math.floor(e.X),Math.floor(e.Y),Math.floor(t.X),Math.floor(t.Y));return isNaN(n)?i/7:isNaN(i)?n/7:(n+i)/14},o.prototype.calculateModuleSize=function(t,e,n){return(this.calculateModuleSizeOneWay(t,e)+this.calculateModuleSizeOneWay(t,n))/2},o.prototype.distance=function(t,e){var n=t.X-e.X,i=t.Y-e.Y;return Math.sqrt(n*n+i*i)},o.prototype.computeDimension=function(t,e,n,i){var r=Math.round(this.distance(t,e)/i),o=Math.round(this.distance(t,n)/i),a=7+(r+o>>1);switch(3&a){case 0:a++;break;case 2:a--;break;case 3:throw\"Error\"}return a},o.prototype.findAlignmentInRegion=function(t,e,n,i){var r=Math.floor(i*t),o=Math.max(0,e-r),a=Math.min(this.image.width-1,e+r);if(a-o<3*t)throw\"Error\";var h=Math.max(0,n-r),f=Math.min(this.image.height-1,n+r);return new s.a(this.image,o,h,a-o,f-h,t,this.resultPointCallback).find()},o.prototype.createTransform=function(t,e,n,r,o){var a,s,h,f,w=o-3.5;return null!=r?(a=r.X,s=r.Y,h=f=w-3):(a=e.X-t.X+n.X,s=e.Y-t.Y+n.Y,h=f=w),i.quadrilateralToQuadrilateral(3.5,3.5,w,3.5,h,f,3.5,w,t.X,t.Y,e.X,e.Y,a,s,n.X,n.Y)},o.prototype.sampleGrid=function(t,e,n){return h.a.sampleGrid3(t,n,e)},o.prototype.processFinderPatternInfo=function(t){var e=t.topLeft,n=t.topRight,i=t.bottomLeft,o=this.calculateModuleSize(e,n,i);if(o<1)throw\"Error\";var s=this.computeDimension(e,n,i,o),h=a.a.getProvisionalVersionForDimension(s),f=h.DimensionForVersion-7,w=null;if(h.alignmentPatternCenters.length>0)for(var u=n.X-e.X+i.X,l=n.Y-e.Y+i.Y,c=1-3/f,d=Math.floor(e.X+c*(u-e.X)),p=Math.floor(e.Y+c*(l-e.Y)),g=4;g<=16;g<<=1){w=this.findAlignmentInRegion(o,d,p,g);break}var v,m=this.createTransform(e,n,i,w,s),b=this.sampleGrid(this.image,m,s);return v=null==w?[i,e,n]:[i,e,n,w],new r(b,v)},o.prototype.detect=function(){var t=(new f.a).findFinderPattern(this.image);return this.processFinderPatternInfo(t)}},function(t,e,n){\"use strict\";function i(t,e,n){this.ordinal_Renamed_Field=t,this.bits=e,this.name=n}e.a=i,i.prototype.ordinal=function(){return this.ordinal_Renamed_Field},i.forBits=function(t){if(t<0||t>=r.length)throw\"ArgumentException\";return r[t]};var r=[new i(1,0,\"M\"),new i(0,1,\"L\"),new i(3,2,\"H\"),new i(2,3,\"Q\")]},function(t,e,n){\"use strict\";function i(t){function e(t,e){var n=t.X-e.X,i=t.Y-e.Y;return Math.sqrt(n*n+i*i)}var n,i,r,o=e(t[0],t[1]),a=e(t[1],t[2]),s=e(t[0],t[2]);if(a>=o&&a>=s?(i=t[0],n=t[1],r=t[2]):s>=a&&s>=o?(i=t[1],n=t[0],r=t[2]):(i=t[2],n=t[0],r=t[1]),function(t,e,n){var i=e.x,r=e.y;return(n.x-i)*(t.y-r)-(n.y-r)*(t.x-i)}(n,i,r)<0){var h=n;n=r,r=h}t[0]=n,t[1]=i,t[2]=r}function r(t,e,n){this.x=t,this.y=e,this.count=1,this.estimatedModuleSize=n}function o(t){this.bottomLeft=t[0],this.topLeft=t[1],this.topRight=t[2]}function a(){this.image=null,this.possibleCenters=[],this.hasSkipped=!1,this.crossCheckStateCount=[0,0,0,0,0],this.resultPointCallback=null}e.a=a;Object.defineProperty(r.prototype,\"X\",{get:function(){return this.x}}),Object.defineProperty(r.prototype,\"Y\",{get:function(){return this.y}}),r.prototype.incrementCount=function(){this.count++},r.prototype.aboutEquals=function(t,e,n){if(Math.abs(e-this.y)<=t&&Math.abs(n-this.x)<=t){var i=Math.abs(t-this.estimatedModuleSize);return i<=1||i/this.estimatedModuleSize<=1}return!1},Object.defineProperty(a.prototype,\"CrossCheckStateCount\",{get:function(){return this.crossCheckStateCount[0]=0,this.crossCheckStateCount[1]=0,this.crossCheckStateCount[2]=0,this.crossCheckStateCount[3]=0,this.crossCheckStateCount[4]=0,this.crossCheckStateCount}}),a.prototype.foundPatternCross=function(t){for(var e=0,n=0;n<5;n++){var i=t[n];if(0==i)return!1;e+=i}if(e<7)return!1;var r=Math.floor((e<<8)/7),o=Math.floor(r/2);return Math.abs(r-(t[0]<<8))<o&&Math.abs(r-(t[1]<<8))<o&&Math.abs(3*r-(t[2]<<8))<3*o&&Math.abs(r-(t[3]<<8))<o&&Math.abs(r-(t[4]<<8))<o},a.prototype.centerFromEnd=function(t,e){return e-t[4]-t[3]-t[2]/2},a.prototype.crossCheckVertical=function(t,e,n,i){for(var r=this.image,o=r.height,a=this.CrossCheckStateCount,s=t;s>=0&&r.data[e+s*r.width];)a[2]++,s--;if(s<0)return NaN;for(;s>=0&&!r.data[e+s*r.width]&&a[1]<=n;)a[1]++,s--;if(s<0||a[1]>n)return NaN;for(;s>=0&&r.data[e+s*r.width]&&a[0]<=n;)a[0]++,s--;if(a[0]>n)return NaN;for(s=t+1;s<o&&r.data[e+s*r.width];)a[2]++,s++;if(s==o)return NaN;for(;s<o&&!r.data[e+s*r.width]&&a[3]<n;)a[3]++,s++;if(s==o||a[3]>=n)return NaN;for(;s<o&&r.data[e+s*r.width]&&a[4]<n;)a[4]++,s++;if(a[4]>=n)return NaN;var h=a[0]+a[1]+a[2]+a[3]+a[4];return 5*Math.abs(h-i)>=2*i?NaN:this.foundPatternCross(a)?this.centerFromEnd(a,s):NaN},a.prototype.crossCheckHorizontal=function(t,e,n,i){for(var r=this.image,o=r.width,a=this.CrossCheckStateCount,s=t;s>=0&&r.data[s+e*r.width];)a[2]++,s--;if(s<0)return NaN;for(;s>=0&&!r.data[s+e*r.width]&&a[1]<=n;)a[1]++,s--;if(s<0||a[1]>n)return NaN;for(;s>=0&&r.data[s+e*r.width]&&a[0]<=n;)a[0]++,s--;if(a[0]>n)return NaN;for(s=t+1;s<o&&r.data[s+e*r.width];)a[2]++,s++;if(s==o)return NaN;for(;s<o&&!r.data[s+e*r.width]&&a[3]<n;)a[3]++,s++;if(s==o||a[3]>=n)return NaN;for(;s<o&&r.data[s+e*r.width]&&a[4]<n;)a[4]++,s++;if(a[4]>=n)return NaN;var h=a[0]+a[1]+a[2]+a[3]+a[4];return 5*Math.abs(h-i)>=i?NaN:this.foundPatternCross(a)?this.centerFromEnd(a,s):NaN},a.prototype.handlePossibleCenter=function(t,e,n){var i=t[0]+t[1]+t[2]+t[3]+t[4],o=this.centerFromEnd(t,n),a=this.crossCheckVertical(e,Math.floor(o),t[2],i);if(!isNaN(a)&&(o=this.crossCheckHorizontal(Math.floor(o),Math.floor(a),t[2],i),!isNaN(o))){for(var s=i/7,h=!1,f=this.possibleCenters.length,w=0;w<f;w++){var u=this.possibleCenters[w];if(u.aboutEquals(s,a,o)){u.incrementCount(),h=!0;break}}if(!h){var l=new r(o,a,s);this.possibleCenters.push(l),null!=this.resultPointCallback&&this.resultPointCallback.foundPossibleResultPoint(l)}return!0}return!1},a.prototype.selectBestPatterns=function(){var t=this.possibleCenters.length;if(t<3)throw\"Couldn't find enough finder patterns:\"+t+\" patterns found\";if(t>3){for(var e=0,n=0,i=0;i<t;i++){var r=this.possibleCenters[i].estimatedModuleSize;e+=r,n+=r*r}var o=e/t;this.possibleCenters.sort(function(t,e){var n=Math.abs(e.estimatedModuleSize-o),i=Math.abs(t.estimatedModuleSize-o);return n<i?-1:n==i?0:1});for(var a=Math.sqrt(n/t-o*o),s=Math.max(.2*o,a),i=this.possibleCenters-1;i>=0;i--){var h=this.possibleCenters[i];Math.abs(h.estimatedModuleSize-o)>s&&this.possibleCenters.splice(i,1)}}return this.possibleCenters.length>3&&this.possibleCenters.sort(function(t,e){return t.count>e.count?-1:t.count<e.count?1:0}),[this.possibleCenters[0],this.possibleCenters[1],this.possibleCenters[2]]},a.prototype.findRowSkip=function(){var t=this.possibleCenters.length;if(t<=1)return 0;for(var e=null,n=0;n<t;n++){var i=this.possibleCenters[n];if(i.count>=2){if(null!=e)return this.hasSkipped=!0,Math.floor((Math.abs(e.X-i.X)-Math.abs(e.Y-i.Y))/2);e=i}}return 0},a.prototype.haveMultiplyConfirmedCenters=function(){for(var t=0,e=0,n=this.possibleCenters.length,i=0;i<n;i++){var r=this.possibleCenters[i];r.count>=2&&(t++,e+=r.estimatedModuleSize)}if(t<3)return!1;for(var o=e/n,a=0,i=0;i<n;i++)r=this.possibleCenters[i],a+=Math.abs(r.estimatedModuleSize-o);return a<=.05*e},a.prototype.findFinderPattern=function(t){this.image=t;var e=t.height,n=t.width,r=Math.floor(3*e/228);r<3&&(r=3);for(var a=!1,s=new Array(5),h=r-1;h<e&&!a;h+=r){s[0]=0,s[1]=0,s[2]=0,s[3]=0,s[4]=0;for(var f=0,w=0;w<n;w++)if(t.data[w+h*t.width])1==(1&f)&&f++,s[f]++;else if(0==(1&f))if(4==f)if(this.foundPatternCross(s)){var u=this.handlePossibleCenter(s,h,w);if(u)if(r=2,this.hasSkipped)a=this.haveMultiplyConfirmedCenters();else{var l=this.findRowSkip();l>s[2]&&(h+=l-s[2]-r,w=n-1)}else{do{w++}while(w<n&&!t.data[w+h*t.width]);w--}f=0,s[0]=0,s[1]=0,s[2]=0,s[3]=0,s[4]=0}else s[0]=s[2],s[1]=s[3],s[2]=s[4],s[3]=1,s[4]=0,f=3;else s[++f]++;else s[f]++;if(this.foundPatternCross(s)){var u=this.handlePossibleCenter(s,h,n);u&&(r=s[0],this.hasSkipped&&(a=this.haveMultiplyConfirmedCenters()))}}var c=this.selectBestPatterns();return i(c),new o(c)}},function(t,e,n){\"use strict\";var i=n(1),r={};r.checkAndNudgePoints=function(t,e){for(var n=t.width,i=t.height,r=!0,o=0;o<e.length&&r;o+=2){var a=Math.floor(e[o]),s=Math.floor(e[o+1]);if(a<-1||a>n||s<-1||s>i)throw\"Error.checkAndNudgePoints \";r=!1,-1==a?(e[o]=0,r=!0):a==n&&(e[o]=n-1,r=!0),-1==s?(e[o+1]=0,r=!0):s==i&&(e[o+1]=i-1,r=!0)}r=!0;for(var o=e.length-2;o>=0&&r;o-=2){var a=Math.floor(e[o]),s=Math.floor(e[o+1]);if(a<-1||a>n||s<-1||s>i)throw\"Error.checkAndNudgePoints \";r=!1,-1==a?(e[o]=0,r=!0):a==n&&(e[o]=n-1,r=!0),-1==s?(e[o+1]=0,r=!0):s==i&&(e[o+1]=i-1,r=!0)}},r.sampleGrid3=function(t,e,n){for(var o=new i.a(e),a=new Array(e<<1),s=0;s<e;s++){for(var h=a.length,f=s+.5,w=0;w<h;w+=2)a[w]=.5+(w>>1),a[w+1]=f;n.transformPoints1(a),r.checkAndNudgePoints(t,a);try{for(var w=0;w<h;w+=2){t.data[Math.floor(a[w])+t.width*Math.floor(a[w+1])]&&o.set_Renamed(w>>1,s)}}catch(t){throw\"Error.checkAndNudgePoints\"}}return o},e.a=r},function(t,e,n){\"use strict\";function i(t){this.field=t}e.a=i;var r=n(3),o=n(4);i.prototype.decode=function(t,e){for(var n=new o.a(this.field,t),i=new Array(e),a=0;a<i.length;a++)i[a]=0;for(var s=!0,a=0;a<e;a++){var h=n.evaluateAt(this.field.exp(a));i[i.length-1-a]=h,0!=h&&(s=!1)}if(!s)for(var f=new o.a(this.field,i),w=this.runEuclideanAlgorithm(this.field.buildMonomial(e,1),f,e),u=w[0],l=w[1],c=this.findErrorLocations(u),d=this.findErrorMagnitudes(l,c,!1),a=0;a<c.length;a++){var p=t.length-1-this.field.log(c[a]);if(p<0)throw\"ReedSolomonException Bad error location\";t[p]=r.a.prototype.addOrSubtract(t[p],d[a])}},i.prototype.runEuclideanAlgorithm=function(t,e,n){if(t.Degree<e.Degree){var i=t;t=e,e=i}for(var r=t,o=e,a=this.field.One,s=this.field.Zero,h=this.field.Zero,f=this.field.One;o.Degree>=Math.floor(n/2);){var w=r,u=a,l=h;if(r=o,a=s,h=f,r.Zero)throw\"r_{i-1} was zero\";o=w;for(var c=this.field.Zero,d=r.getCoefficient(r.Degree),p=this.field.inverse(d);o.Degree>=r.Degree&&!o.Zero;){var g=o.Degree-r.Degree,v=this.field.multiply(o.getCoefficient(o.Degree),p);c=c.addOrSubtract(this.field.buildMonomial(g,v)),o=o.addOrSubtract(r.multiplyByMonomial(g,v))}s=c.multiply1(a).addOrSubtract(u),f=c.multiply1(h).addOrSubtract(l)}var m=f.getCoefficient(0);if(0==m)throw\"ReedSolomonException sigmaTilde(0) was zero\";var b=this.field.inverse(m);return[f.multiply2(b),o.multiply2(b)]},i.prototype.findErrorLocations=function(t){var e=t.Degree;if(1==e)return new Array(t.getCoefficient(1));for(var n=new Array(e),i=0,r=1;r<256&&i<e;r++)0==t.evaluateAt(r)&&(n[i]=this.field.inverse(r),i++);if(i!=e)throw\"Error locator degree does not match number of roots\";return n},i.prototype.findErrorMagnitudes=function(t,e,n){for(var i=e.length,o=new Array(i),a=0;a<i;a++){for(var s=this.field.inverse(e[a]),h=1,f=0;f<i;f++)a!=f&&(h=this.field.multiply(h,r.a.prototype.addOrSubtract(1,this.field.multiply(e[f],s))));o[a]=this.field.multiply(t.evaluateAt(s),this.field.inverse(h)),n&&(o[a]=this.field.multiply(o[a],s))}return o}},function(t,e,n){(function(t){var e=n(6).default,i=new e;i.callback=function(t,e){postMessage({result:e,err:t})},onmessage=function(t){var e=t.data;i.decode(e)}}).call(e,n(7)(t))}]);"
+
+/***/ }),
+/* 7 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+ /* eslint-env node */
+
+
+// SDP helpers.
+var SDPUtils = {};
+
+// Generate an alphanumeric identifier for cname or mids.
+// TODO: use UUIDs instead? https://gist.github.com/jed/982883
+SDPUtils.generateIdentifier = function() {
+ return Math.random().toString(36).substr(2, 10);
+};
+
+// The RTCP CNAME used by all peerconnections from the same JS.
+SDPUtils.localCName = SDPUtils.generateIdentifier();
+
+// Splits SDP into lines, dealing with both CRLF and LF.
+SDPUtils.splitLines = function(blob) {
+ return blob.trim().split('\n').map(function(line) {
+ return line.trim();
+ });
+};
+// Splits SDP into sessionpart and mediasections. Ensures CRLF.
+SDPUtils.splitSections = function(blob) {
+ var parts = blob.split('\nm=');
+ return parts.map(function(part, index) {
+ return (index > 0 ? 'm=' + part : part).trim() + '\r\n';
+ });
+};
+
+// Returns lines that start with a certain prefix.
+SDPUtils.matchPrefix = function(blob, prefix) {
+ return SDPUtils.splitLines(blob).filter(function(line) {
+ return line.indexOf(prefix) === 0;
+ });
+};
+
+// Parses an ICE candidate line. Sample input:
+// candidate:702786350 2 udp 41819902 8.8.8.8 60769 typ relay raddr 8.8.8.8
+// rport 55996"
+SDPUtils.parseCandidate = function(line) {
+ var parts;
+ // Parse both variants.
+ if (line.indexOf('a=candidate:') === 0) {
+ parts = line.substring(12).split(' ');
+ } else {
+ parts = line.substring(10).split(' ');
+ }
+
+ var candidate = {
+ foundation: parts[0],
+ component: parts[1],
+ protocol: parts[2].toLowerCase(),
+ priority: parseInt(parts[3], 10),
+ ip: parts[4],
+ port: parseInt(parts[5], 10),
+ // skip parts[6] == 'typ'
+ type: parts[7]
+ };
+
+ for (var i = 8; i < parts.length; i += 2) {
+ switch (parts[i]) {
+ case 'raddr':
+ candidate.relatedAddress = parts[i + 1];
+ break;
+ case 'rport':
+ candidate.relatedPort = parseInt(parts[i + 1], 10);
+ break;
+ case 'tcptype':
+ candidate.tcpType = parts[i + 1];
+ break;
+ default: // extension handling, in particular ufrag
+ candidate[parts[i]] = parts[i + 1];
+ break;
+ }
+ }
+ return candidate;
+};
+
+// Translates a candidate object into SDP candidate attribute.
+SDPUtils.writeCandidate = function(candidate) {
+ var sdp = [];
+ sdp.push(candidate.foundation);
+ sdp.push(candidate.component);
+ sdp.push(candidate.protocol.toUpperCase());
+ sdp.push(candidate.priority);
+ sdp.push(candidate.ip);
+ sdp.push(candidate.port);
+
+ var type = candidate.type;
+ sdp.push('typ');
+ sdp.push(type);
+ if (type !== 'host' && candidate.relatedAddress &&
+ candidate.relatedPort) {
+ sdp.push('raddr');
+ sdp.push(candidate.relatedAddress); // was: relAddr
+ sdp.push('rport');
+ sdp.push(candidate.relatedPort); // was: relPort
+ }
+ if (candidate.tcpType && candidate.protocol.toLowerCase() === 'tcp') {
+ sdp.push('tcptype');
+ sdp.push(candidate.tcpType);
+ }
+ return 'candidate:' + sdp.join(' ');
+};
+
+// Parses an ice-options line, returns an array of option tags.
+// a=ice-options:foo bar
+SDPUtils.parseIceOptions = function(line) {
+ return line.substr(14).split(' ');
+}
+
+// Parses an rtpmap line, returns RTCRtpCoddecParameters. Sample input:
+// a=rtpmap:111 opus/48000/2
+SDPUtils.parseRtpMap = function(line) {
+ var parts = line.substr(9).split(' ');
+ var parsed = {
+ payloadType: parseInt(parts.shift(), 10) // was: id
+ };
+
+ parts = parts[0].split('/');
+
+ parsed.name = parts[0];
+ parsed.clockRate = parseInt(parts[1], 10); // was: clockrate
+ // was: channels
+ parsed.numChannels = parts.length === 3 ? parseInt(parts[2], 10) : 1;
+ return parsed;
+};
+
+// Generate an a=rtpmap line from RTCRtpCodecCapability or
+// RTCRtpCodecParameters.
+SDPUtils.writeRtpMap = function(codec) {
+ var pt = codec.payloadType;
+ if (codec.preferredPayloadType !== undefined) {
+ pt = codec.preferredPayloadType;
+ }
+ return 'a=rtpmap:' + pt + ' ' + codec.name + '/' + codec.clockRate +
+ (codec.numChannels !== 1 ? '/' + codec.numChannels : '') + '\r\n';
+};
+
+// Parses an a=extmap line (headerextension from RFC 5285). Sample input:
+// a=extmap:2 urn:ietf:params:rtp-hdrext:toffset
+// a=extmap:2/sendonly urn:ietf:params:rtp-hdrext:toffset
+SDPUtils.parseExtmap = function(line) {
+ var parts = line.substr(9).split(' ');
+ return {
+ id: parseInt(parts[0], 10),
+ direction: parts[0].indexOf('/') > 0 ? parts[0].split('/')[1] : 'sendrecv',
+ uri: parts[1]
+ };
+};
+
+// Generates a=extmap line from RTCRtpHeaderExtensionParameters or
+// RTCRtpHeaderExtension.
+SDPUtils.writeExtmap = function(headerExtension) {
+ return 'a=extmap:' + (headerExtension.id || headerExtension.preferredId) +
+ (headerExtension.direction && headerExtension.direction !== 'sendrecv'
+ ? '/' + headerExtension.direction
+ : '') +
+ ' ' + headerExtension.uri + '\r\n';
+};
+
+// Parses an ftmp line, returns dictionary. Sample input:
+// a=fmtp:96 vbr=on;cng=on
+// Also deals with vbr=on; cng=on
+SDPUtils.parseFmtp = function(line) {
+ var parsed = {};
+ var kv;
+ var parts = line.substr(line.indexOf(' ') + 1).split(';');
+ for (var j = 0; j < parts.length; j++) {
+ kv = parts[j].trim().split('=');
+ parsed[kv[0].trim()] = kv[1];
+ }
+ return parsed;
+};
+
+// Generates an a=ftmp line from RTCRtpCodecCapability or RTCRtpCodecParameters.
+SDPUtils.writeFmtp = function(codec) {
+ var line = '';
+ var pt = codec.payloadType;
+ if (codec.preferredPayloadType !== undefined) {
+ pt = codec.preferredPayloadType;
+ }
+ if (codec.parameters && Object.keys(codec.parameters).length) {
+ var params = [];
+ Object.keys(codec.parameters).forEach(function(param) {
+ params.push(param + '=' + codec.parameters[param]);
+ });
+ line += 'a=fmtp:' + pt + ' ' + params.join(';') + '\r\n';
+ }
+ return line;
+};
+
+// Parses an rtcp-fb line, returns RTCPRtcpFeedback object. Sample input:
+// a=rtcp-fb:98 nack rpsi
+SDPUtils.parseRtcpFb = function(line) {
+ var parts = line.substr(line.indexOf(' ') + 1).split(' ');
+ return {
+ type: parts.shift(),
+ parameter: parts.join(' ')
+ };
+};
+// Generate a=rtcp-fb lines from RTCRtpCodecCapability or RTCRtpCodecParameters.
+SDPUtils.writeRtcpFb = function(codec) {
+ var lines = '';
+ var pt = codec.payloadType;
+ if (codec.preferredPayloadType !== undefined) {
+ pt = codec.preferredPayloadType;
+ }
+ if (codec.rtcpFeedback && codec.rtcpFeedback.length) {
+ // FIXME: special handling for trr-int?
+ codec.rtcpFeedback.forEach(function(fb) {
+ lines += 'a=rtcp-fb:' + pt + ' ' + fb.type +
+ (fb.parameter && fb.parameter.length ? ' ' + fb.parameter : '') +
+ '\r\n';
+ });
+ }
+ return lines;
+};
+
+// Parses an RFC 5576 ssrc media attribute. Sample input:
+// a=ssrc:3735928559 cname:something
+SDPUtils.parseSsrcMedia = function(line) {
+ var sp = line.indexOf(' ');
+ var parts = {
+ ssrc: parseInt(line.substr(7, sp - 7), 10)
+ };
+ var colon = line.indexOf(':', sp);
+ if (colon > -1) {
+ parts.attribute = line.substr(sp + 1, colon - sp - 1);
+ parts.value = line.substr(colon + 1);
+ } else {
+ parts.attribute = line.substr(sp + 1);
+ }
+ return parts;
+};
+
+// Extracts the MID (RFC 5888) from a media section.
+// returns the MID or undefined if no mid line was found.
+SDPUtils.getMid = function(mediaSection) {
+ var mid = SDPUtils.matchPrefix(mediaSection, 'a=mid:')[0];
+ if (mid) {
+ return mid.substr(6);
+ }
+}
+
+SDPUtils.parseFingerprint = function(line) {
+ var parts = line.substr(14).split(' ');
+ return {
+ algorithm: parts[0].toLowerCase(), // algorithm is case-sensitive in Edge.
+ value: parts[1]
+ };
+};
+
+// Extracts DTLS parameters from SDP media section or sessionpart.
+// FIXME: for consistency with other functions this should only
+// get the fingerprint line as input. See also getIceParameters.
+SDPUtils.getDtlsParameters = function(mediaSection, sessionpart) {
+ var lines = SDPUtils.matchPrefix(mediaSection + sessionpart,
+ 'a=fingerprint:');
+ // Note: a=setup line is ignored since we use the 'auto' role.
+ // Note2: 'algorithm' is not case sensitive except in Edge.
+ return {
+ role: 'auto',
+ fingerprints: lines.map(SDPUtils.parseFingerprint)
+ };
+};
+
+// Serializes DTLS parameters to SDP.
+SDPUtils.writeDtlsParameters = function(params, setupType) {
+ var sdp = 'a=setup:' + setupType + '\r\n';
+ params.fingerprints.forEach(function(fp) {
+ sdp += 'a=fingerprint:' + fp.algorithm + ' ' + fp.value + '\r\n';
+ });
+ return sdp;
+};
+// Parses ICE information from SDP media section or sessionpart.
+// FIXME: for consistency with other functions this should only
+// get the ice-ufrag and ice-pwd lines as input.
+SDPUtils.getIceParameters = function(mediaSection, sessionpart) {
+ var lines = SDPUtils.splitLines(mediaSection);
+ // Search in session part, too.
+ lines = lines.concat(SDPUtils.splitLines(sessionpart));
+ var iceParameters = {
+ usernameFragment: lines.filter(function(line) {
+ return line.indexOf('a=ice-ufrag:') === 0;
+ })[0].substr(12),
+ password: lines.filter(function(line) {
+ return line.indexOf('a=ice-pwd:') === 0;
+ })[0].substr(10)
+ };
+ return iceParameters;
+};
+
+// Serializes ICE parameters to SDP.
+SDPUtils.writeIceParameters = function(params) {
+ return 'a=ice-ufrag:' + params.usernameFragment + '\r\n' +
+ 'a=ice-pwd:' + params.password + '\r\n';
+};
+
+// Parses the SDP media section and returns RTCRtpParameters.
+SDPUtils.parseRtpParameters = function(mediaSection) {
+ var description = {
+ codecs: [],
+ headerExtensions: [],
+ fecMechanisms: [],
+ rtcp: []
+ };
+ var lines = SDPUtils.splitLines(mediaSection);
+ var mline = lines[0].split(' ');
+ for (var i = 3; i < mline.length; i++) { // find all codecs from mline[3..]
+ var pt = mline[i];
+ var rtpmapline = SDPUtils.matchPrefix(
+ mediaSection, 'a=rtpmap:' + pt + ' ')[0];
+ if (rtpmapline) {
+ var codec = SDPUtils.parseRtpMap(rtpmapline);
+ var fmtps = SDPUtils.matchPrefix(
+ mediaSection, 'a=fmtp:' + pt + ' ');
+ // Only the first a=fmtp:<pt> is considered.
+ codec.parameters = fmtps.length ? SDPUtils.parseFmtp(fmtps[0]) : {};
+ codec.rtcpFeedback = SDPUtils.matchPrefix(
+ mediaSection, 'a=rtcp-fb:' + pt + ' ')
+ .map(SDPUtils.parseRtcpFb);
+ description.codecs.push(codec);
+ // parse FEC mechanisms from rtpmap lines.
+ switch (codec.name.toUpperCase()) {
+ case 'RED':
+ case 'ULPFEC':
+ description.fecMechanisms.push(codec.name.toUpperCase());
+ break;
+ default: // only RED and ULPFEC are recognized as FEC mechanisms.
+ break;
+ }
+ }
+ }
+ SDPUtils.matchPrefix(mediaSection, 'a=extmap:').forEach(function(line) {
+ description.headerExtensions.push(SDPUtils.parseExtmap(line));
+ });
+ // FIXME: parse rtcp.
+ return description;
+};
+
+// Generates parts of the SDP media section describing the capabilities /
+// parameters.
+SDPUtils.writeRtpDescription = function(kind, caps) {
+ var sdp = '';
+
+ // Build the mline.
+ sdp += 'm=' + kind + ' ';
+ sdp += caps.codecs.length > 0 ? '9' : '0'; // reject if no codecs.
+ sdp += ' UDP/TLS/RTP/SAVPF ';
+ sdp += caps.codecs.map(function(codec) {
+ if (codec.preferredPayloadType !== undefined) {
+ return codec.preferredPayloadType;
+ }
+ return codec.payloadType;
+ }).join(' ') + '\r\n';
+
+ sdp += 'c=IN IP4 0.0.0.0\r\n';
+ sdp += 'a=rtcp:9 IN IP4 0.0.0.0\r\n';
+
+ // Add a=rtpmap lines for each codec. Also fmtp and rtcp-fb.
+ caps.codecs.forEach(function(codec) {
+ sdp += SDPUtils.writeRtpMap(codec);
+ sdp += SDPUtils.writeFmtp(codec);
+ sdp += SDPUtils.writeRtcpFb(codec);
+ });
+ var maxptime = 0;
+ caps.codecs.forEach(function(codec) {
+ if (codec.maxptime > maxptime) {
+ maxptime = codec.maxptime;
+ }
+ });
+ if (maxptime > 0) {
+ sdp += 'a=maxptime:' + maxptime + '\r\n';
+ }
+ sdp += 'a=rtcp-mux\r\n';
+
+ caps.headerExtensions.forEach(function(extension) {
+ sdp += SDPUtils.writeExtmap(extension);
+ });
+ // FIXME: write fecMechanisms.
+ return sdp;
+};
+
+// Parses the SDP media section and returns an array of
+// RTCRtpEncodingParameters.
+SDPUtils.parseRtpEncodingParameters = function(mediaSection) {
+ var encodingParameters = [];
+ var description = SDPUtils.parseRtpParameters(mediaSection);
+ var hasRed = description.fecMechanisms.indexOf('RED') !== -1;
+ var hasUlpfec = description.fecMechanisms.indexOf('ULPFEC') !== -1;
+
+ // filter a=ssrc:... cname:, ignore PlanB-msid
+ var ssrcs = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:')
+ .map(function(line) {
+ return SDPUtils.parseSsrcMedia(line);
+ })
+ .filter(function(parts) {
+ return parts.attribute === 'cname';
+ });
+ var primarySsrc = ssrcs.length > 0 && ssrcs[0].ssrc;
+ var secondarySsrc;
+
+ var flows = SDPUtils.matchPrefix(mediaSection, 'a=ssrc-group:FID')
+ .map(function(line) {
+ var parts = line.split(' ');
+ parts.shift();
+ return parts.map(function(part) {
+ return parseInt(part, 10);
+ });
+ });
+ if (flows.length > 0 && flows[0].length > 1 && flows[0][0] === primarySsrc) {
+ secondarySsrc = flows[0][1];
+ }
+
+ description.codecs.forEach(function(codec) {
+ if (codec.name.toUpperCase() === 'RTX' && codec.parameters.apt) {
+ var encParam = {
+ ssrc: primarySsrc,
+ codecPayloadType: parseInt(codec.parameters.apt, 10),
+ rtx: {
+ ssrc: secondarySsrc
+ }
+ };
+ encodingParameters.push(encParam);
+ if (hasRed) {
+ encParam = JSON.parse(JSON.stringify(encParam));
+ encParam.fec = {
+ ssrc: secondarySsrc,
+ mechanism: hasUlpfec ? 'red+ulpfec' : 'red'
+ };
+ encodingParameters.push(encParam);
+ }
+ }
+ });
+ if (encodingParameters.length === 0 && primarySsrc) {
+ encodingParameters.push({
+ ssrc: primarySsrc
+ });
+ }
+
+ // we support both b=AS and b=TIAS but interpret AS as TIAS.
+ var bandwidth = SDPUtils.matchPrefix(mediaSection, 'b=');
+ if (bandwidth.length) {
+ if (bandwidth[0].indexOf('b=TIAS:') === 0) {
+ bandwidth = parseInt(bandwidth[0].substr(7), 10);
+ } else if (bandwidth[0].indexOf('b=AS:') === 0) {
+ bandwidth = parseInt(bandwidth[0].substr(5), 10);
+ }
+ encodingParameters.forEach(function(params) {
+ params.maxBitrate = bandwidth;
+ });
+ }
+ return encodingParameters;
+};
+
+// parses http://draft.ortc.org/#rtcrtcpparameters*
+SDPUtils.parseRtcpParameters = function(mediaSection) {
+ var rtcpParameters = {};
+
+ var cname;
+ // Gets the first SSRC. Note that with RTX there might be multiple
+ // SSRCs.
+ var remoteSsrc = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:')
+ .map(function(line) {
+ return SDPUtils.parseSsrcMedia(line);
+ })
+ .filter(function(obj) {
+ return obj.attribute === 'cname';
+ })[0];
+ if (remoteSsrc) {
+ rtcpParameters.cname = remoteSsrc.value;
+ rtcpParameters.ssrc = remoteSsrc.ssrc;
+ }
+
+ // Edge uses the compound attribute instead of reducedSize
+ // compound is !reducedSize
+ var rsize = SDPUtils.matchPrefix(mediaSection, 'a=rtcp-rsize');
+ rtcpParameters.reducedSize = rsize.length > 0;
+ rtcpParameters.compound = rsize.length === 0;
+
+ // parses the rtcp-mux attrіbute.
+ // Note that Edge does not support unmuxed RTCP.
+ var mux = SDPUtils.matchPrefix(mediaSection, 'a=rtcp-mux');
+ rtcpParameters.mux = mux.length > 0;
+
+ return rtcpParameters;
+};
+
+// parses either a=msid: or a=ssrc:... msid lines and returns
+// the id of the MediaStream and MediaStreamTrack.
+SDPUtils.parseMsid = function(mediaSection) {
+ var parts;
+ var spec = SDPUtils.matchPrefix(mediaSection, 'a=msid:');
+ if (spec.length === 1) {
+ parts = spec[0].substr(7).split(' ');
+ return {stream: parts[0], track: parts[1]};
+ }
+ var planB = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:')
+ .map(function(line) {
+ return SDPUtils.parseSsrcMedia(line);
+ })
+ .filter(function(parts) {
+ return parts.attribute === 'msid';
+ });
+ if (planB.length > 0) {
+ parts = planB[0].value.split(' ');
+ return {stream: parts[0], track: parts[1]};
+ }
+};
+
+SDPUtils.writeSessionBoilerplate = function() {
+ // FIXME: sess-id should be an NTP timestamp.
+ return 'v=0\r\n' +
+ 'o=thisisadapterortc 8169639915646943137 2 IN IP4 127.0.0.1\r\n' +
+ 's=-\r\n' +
+ 't=0 0\r\n';
+};
+
+SDPUtils.writeMediaSection = function(transceiver, caps, type, stream) {
+ var sdp = SDPUtils.writeRtpDescription(transceiver.kind, caps);
+
+ // Map ICE parameters (ufrag, pwd) to SDP.
+ sdp += SDPUtils.writeIceParameters(
+ transceiver.iceGatherer.getLocalParameters());
+
+ // Map DTLS parameters to SDP.
+ sdp += SDPUtils.writeDtlsParameters(
+ transceiver.dtlsTransport.getLocalParameters(),
+ type === 'offer' ? 'actpass' : 'active');
+
+ sdp += 'a=mid:' + transceiver.mid + '\r\n';
+
+ if (transceiver.direction) {
+ sdp += 'a=' + transceiver.direction + '\r\n';
+ } else if (transceiver.rtpSender && transceiver.rtpReceiver) {
+ sdp += 'a=sendrecv\r\n';
+ } else if (transceiver.rtpSender) {
+ sdp += 'a=sendonly\r\n';
+ } else if (transceiver.rtpReceiver) {
+ sdp += 'a=recvonly\r\n';
+ } else {
+ sdp += 'a=inactive\r\n';
+ }
+
+ if (transceiver.rtpSender) {
+ // spec.
+ var msid = 'msid:' + stream.id + ' ' +
+ transceiver.rtpSender.track.id + '\r\n';
+ sdp += 'a=' + msid;
+
+ // for Chrome.
+ sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].ssrc +
+ ' ' + msid;
+ if (transceiver.sendEncodingParameters[0].rtx) {
+ sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].rtx.ssrc +
+ ' ' + msid;
+ sdp += 'a=ssrc-group:FID ' +
+ transceiver.sendEncodingParameters[0].ssrc + ' ' +
+ transceiver.sendEncodingParameters[0].rtx.ssrc +
+ '\r\n';
+ }
+ }
+ // FIXME: this should be written by writeRtpDescription.
+ sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].ssrc +
+ ' cname:' + SDPUtils.localCName + '\r\n';
+ if (transceiver.rtpSender && transceiver.sendEncodingParameters[0].rtx) {
+ sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].rtx.ssrc +
+ ' cname:' + SDPUtils.localCName + '\r\n';
+ }
+ return sdp;
+};
+
+// Gets the direction from the mediaSection or the sessionpart.
+SDPUtils.getDirection = function(mediaSection, sessionpart) {
+ // Look for sendrecv, sendonly, recvonly, inactive, default to sendrecv.
+ var lines = SDPUtils.splitLines(mediaSection);
+ for (var i = 0; i < lines.length; i++) {
+ switch (lines[i]) {
+ case 'a=sendrecv':
+ case 'a=sendonly':
+ case 'a=recvonly':
+ case 'a=inactive':
+ return lines[i].substr(2);
+ default:
+ // FIXME: What should happen here?
+ }
+ }
+ if (sessionpart) {
+ return SDPUtils.getDirection(sessionpart);
+ }
+ return 'sendrecv';
+};
+
+SDPUtils.getKind = function(mediaSection) {
+ var lines = SDPUtils.splitLines(mediaSection);
+ var mline = lines[0].split(' ');
+ return mline[0].substr(2);
+};
+
+SDPUtils.isRejected = function(mediaSection) {
+ return mediaSection.split(' ', 2)[1] === '0';
+};
+
+// Expose public methods.
+module.exports = SDPUtils;
+
+
+/***/ }),
+/* 8 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+/*
+ * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree.
+ */
+ /* eslint-env node */
+
+
+
+// Shimming starts here.
+(function() {
+ // Utils.
+ var utils = __webpack_require__(0);
+ var logging = utils.log;
+ var browserDetails = utils.browserDetails;
+ // Export to the adapter global object visible in the browser.
+ module.exports.browserDetails = browserDetails;
+ module.exports.extractVersion = utils.extractVersion;
+ module.exports.disableLog = utils.disableLog;
+
+ // Uncomment the line below if you want logging to occur, including logging
+ // for the switch statement below. Can also be turned on in the browser via
+ // adapter.disableLog(false), but then logging from the switch statement below
+ // will not appear.
+ // require('./utils').disableLog(false);
+
+ // Browser shims.
+ var chromeShim = __webpack_require__(9) || null;
+ var edgeShim = __webpack_require__(11) || null;
+ var firefoxShim = __webpack_require__(14) || null;
+ var safariShim = __webpack_require__(16) || null;
+
+ // Shim browser if found.
+ switch (browserDetails.browser) {
+ case 'chrome':
+ if (!chromeShim || !chromeShim.shimPeerConnection) {
+ logging('Chrome shim is not included in this adapter release.');
+ return;
+ }
+ logging('adapter.js shimming chrome.');
+ // Export to the adapter global object visible in the browser.
+ module.exports.browserShim = chromeShim;
+
+ chromeShim.shimGetUserMedia();
+ chromeShim.shimMediaStream();
+ utils.shimCreateObjectURL();
+ chromeShim.shimSourceObject();
+ chromeShim.shimPeerConnection();
+ chromeShim.shimOnTrack();
+ chromeShim.shimGetSendersWithDtmf();
+ break;
+ case 'firefox':
+ if (!firefoxShim || !firefoxShim.shimPeerConnection) {
+ logging('Firefox shim is not included in this adapter release.');
+ return;
+ }
+ logging('adapter.js shimming firefox.');
+ // Export to the adapter global object visible in the browser.
+ module.exports.browserShim = firefoxShim;
+
+ firefoxShim.shimGetUserMedia();
+ utils.shimCreateObjectURL();
+ firefoxShim.shimSourceObject();
+ firefoxShim.shimPeerConnection();
+ firefoxShim.shimOnTrack();
+ break;
+ case 'edge':
+ if (!edgeShim || !edgeShim.shimPeerConnection) {
+ logging('MS edge shim is not included in this adapter release.');
+ return;
+ }
+ logging('adapter.js shimming edge.');
+ // Export to the adapter global object visible in the browser.
+ module.exports.browserShim = edgeShim;
+
+ edgeShim.shimGetUserMedia();
+ utils.shimCreateObjectURL();
+ edgeShim.shimPeerConnection();
+ edgeShim.shimReplaceTrack();
+ break;
+ case 'safari':
+ if (!safariShim) {
+ logging('Safari shim is not included in this adapter release.');
+ return;
+ }
+ logging('adapter.js shimming safari.');
+ // Export to the adapter global object visible in the browser.
+ module.exports.browserShim = safariShim;
+
+ safariShim.shimCallbacksAPI();
+ safariShim.shimAddStream();
+ safariShim.shimOnAddStream();
+ safariShim.shimGetUserMedia();
+ break;
+ default:
+ logging('Unsupported browser!');
+ }
+})();
+
+
+/***/ }),
+/* 9 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+/*
+ * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree.
+ */
+ /* eslint-env node */
+
+var logging = __webpack_require__(0).log;
+var browserDetails = __webpack_require__(0).browserDetails;
+
+var chromeShim = {
+ shimMediaStream: function() {
+ window.MediaStream = window.MediaStream || window.webkitMediaStream;
+ },
+
+ shimOnTrack: function() {
+ if (typeof window === 'object' && window.RTCPeerConnection && !('ontrack' in
+ window.RTCPeerConnection.prototype)) {
+ Object.defineProperty(window.RTCPeerConnection.prototype, 'ontrack', {
+ get: function() {
+ return this._ontrack;
+ },
+ set: function(f) {
+ var self = this;
+ if (this._ontrack) {
+ this.removeEventListener('track', this._ontrack);
+ this.removeEventListener('addstream', this._ontrackpoly);
+ }
+ this.addEventListener('track', this._ontrack = f);
+ this.addEventListener('addstream', this._ontrackpoly = function(e) {
+ // onaddstream does not fire when a track is added to an existing
+ // stream. But stream.onaddtrack is implemented so we use that.
+ e.stream.addEventListener('addtrack', function(te) {
+ var receiver;
+ if (RTCPeerConnection.prototype.getReceivers) {
+ receiver = self.getReceivers().find(function(r) {
+ return r.track.id === te.track.id;
+ });
+ } else {
+ receiver = {track: te.track};
+ }
+
+ var event = new Event('track');
+ event.track = te.track;
+ event.receiver = receiver;
+ event.streams = [e.stream];
+ self.dispatchEvent(event);
+ });
+ e.stream.getTracks().forEach(function(track) {
+ var receiver;
+ if (RTCPeerConnection.prototype.getReceivers) {
+ receiver = self.getReceivers().find(function(r) {
+ return r.track.id === track.id;
+ });
+ } else {
+ receiver = {track: track};
+ }
+ var event = new Event('track');
+ event.track = track;
+ event.receiver = receiver;
+ event.streams = [e.stream];
+ this.dispatchEvent(event);
+ }.bind(this));
+ }.bind(this));
+ }
+ });
+ }
+ },
+
+ shimGetSendersWithDtmf: function() {
+ if (typeof window === 'object' && window.RTCPeerConnection &&
+ !('getSenders' in RTCPeerConnection.prototype) &&
+ 'createDTMFSender' in RTCPeerConnection.prototype) {
+ RTCPeerConnection.prototype.getSenders = function() {
+ return this._senders || [];
+ };
+ var origAddStream = RTCPeerConnection.prototype.addStream;
+ var origRemoveStream = RTCPeerConnection.prototype.removeStream;
+
+ if (!RTCPeerConnection.prototype.addTrack) {
+ RTCPeerConnection.prototype.addTrack = function(track, stream) {
+ var pc = this;
+ if (pc.signalingState === 'closed') {
+ throw new DOMException(
+ 'The RTCPeerConnection\'s signalingState is \'closed\'.',
+ 'InvalidStateError');
+ }
+ var streams = [].slice.call(arguments, 1);
+ if (streams.length !== 1 ||
+ !streams[0].getTracks().find(function(t) {
+ return t === track;
+ })) {
+ // this is not fully correct but all we can manage without
+ // [[associated MediaStreams]] internal slot.
+ throw new DOMException(
+ 'The adapter.js addTrack polyfill only supports a single ' +
+ ' stream which is associated with the specified track.',
+ 'NotSupportedError');
+ }
+
+ pc._senders = pc._senders || [];
+ var alreadyExists = pc._senders.find(function(t) {
+ return t.track === track;
+ });
+ if (alreadyExists) {
+ throw new DOMException('Track already exists.',
+ 'InvalidAccessError');
+ }
+
+ pc._streams = pc._streams || {};
+ var oldStream = pc._streams[stream.id];
+ if (oldStream) {
+ oldStream.addTrack(track);
+ pc.removeStream(oldStream);
+ pc.addStream(oldStream);
+ } else {
+ var newStream = new MediaStream([track]);
+ pc._streams[stream.id] = newStream;
+ pc.addStream(newStream);
+ }
+
+ var sender = {
+ track: track,
+ get dtmf() {
+ if (this._dtmf === undefined) {
+ if (track.kind === 'audio') {
+ this._dtmf = pc.createDTMFSender(track);
+ } else {
+ this._dtmf = null;
+ }
+ }
+ return this._dtmf;
+ }
+ };
+ pc._senders.push(sender);
+ return sender;
+ };
+ }
+ RTCPeerConnection.prototype.addStream = function(stream) {
+ var pc = this;
+ pc._senders = pc._senders || [];
+ origAddStream.apply(pc, [stream]);
+ stream.getTracks().forEach(function(track) {
+ pc._senders.push({
+ track: track,
+ get dtmf() {
+ if (this._dtmf === undefined) {
+ if (track.kind === 'audio') {
+ this._dtmf = pc.createDTMFSender(track);
+ } else {
+ this._dtmf = null;
+ }
+ }
+ return this._dtmf;
+ }
+ });
+ });
+ };
+
+ RTCPeerConnection.prototype.removeStream = function(stream) {
+ var pc = this;
+ pc._senders = pc._senders || [];
+ origRemoveStream.apply(pc, [stream]);
+ stream.getTracks().forEach(function(track) {
+ var sender = pc._senders.find(function(s) {
+ return s.track === track;
+ });
+ if (sender) {
+ pc._senders.splice(pc._senders.indexOf(sender), 1); // remove sender
+ }
+ });
+ };
+ }
+ },
+
+ shimSourceObject: function() {
+ if (typeof window === 'object') {
+ if (window.HTMLMediaElement &&
+ !('srcObject' in window.HTMLMediaElement.prototype)) {
+ // Shim the srcObject property, once, when HTMLMediaElement is found.
+ Object.defineProperty(window.HTMLMediaElement.prototype, 'srcObject', {
+ get: function() {
+ return this._srcObject;
+ },
+ set: function(stream) {
+ var self = this;
+ // Use _srcObject as a private property for this shim
+ this._srcObject = stream;
+ if (this.src) {
+ URL.revokeObjectURL(this.src);
+ }
+
+ if (!stream) {
+ this.src = '';
+ return undefined;
+ }
+ this.src = URL.createObjectURL(stream);
+ // We need to recreate the blob url when a track is added or
+ // removed. Doing it manually since we want to avoid a recursion.
+ stream.addEventListener('addtrack', function() {
+ if (self.src) {
+ URL.revokeObjectURL(self.src);
+ }
+ self.src = URL.createObjectURL(stream);
+ });
+ stream.addEventListener('removetrack', function() {
+ if (self.src) {
+ URL.revokeObjectURL(self.src);
+ }
+ self.src = URL.createObjectURL(stream);
+ });
+ }
+ });
+ }
+ }
+ },
+
+ shimPeerConnection: function() {
+ // The RTCPeerConnection object.
+ if (!window.RTCPeerConnection) {
+ window.RTCPeerConnection = function(pcConfig, pcConstraints) {
+ // Translate iceTransportPolicy to iceTransports,
+ // see https://code.google.com/p/webrtc/issues/detail?id=4869
+ // this was fixed in M56 along with unprefixing RTCPeerConnection.
+ logging('PeerConnection');
+ if (pcConfig && pcConfig.iceTransportPolicy) {
+ pcConfig.iceTransports = pcConfig.iceTransportPolicy;
+ }
+
+ return new webkitRTCPeerConnection(pcConfig, pcConstraints);
+ };
+ window.RTCPeerConnection.prototype = webkitRTCPeerConnection.prototype;
+ // wrap static methods. Currently just generateCertificate.
+ if (webkitRTCPeerConnection.generateCertificate) {
+ Object.defineProperty(window.RTCPeerConnection, 'generateCertificate', {
+ get: function() {
+ return webkitRTCPeerConnection.generateCertificate;
+ }
+ });
+ }
+ } else {
+ // migrate from non-spec RTCIceServer.url to RTCIceServer.urls
+ var OrigPeerConnection = RTCPeerConnection;
+ window.RTCPeerConnection = function(pcConfig, pcConstraints) {
+ if (pcConfig && pcConfig.iceServers) {
+ var newIceServers = [];
+ for (var i = 0; i < pcConfig.iceServers.length; i++) {
+ var server = pcConfig.iceServers[i];
+ if (!server.hasOwnProperty('urls') &&
+ server.hasOwnProperty('url')) {
+ console.warn('RTCIceServer.url is deprecated! Use urls instead.');
+ server = JSON.parse(JSON.stringify(server));
+ server.urls = server.url;
+ newIceServers.push(server);
+ } else {
+ newIceServers.push(pcConfig.iceServers[i]);
+ }
+ }
+ pcConfig.iceServers = newIceServers;
+ }
+ return new OrigPeerConnection(pcConfig, pcConstraints);
+ };
+ window.RTCPeerConnection.prototype = OrigPeerConnection.prototype;
+ // wrap static methods. Currently just generateCertificate.
+ Object.defineProperty(window.RTCPeerConnection, 'generateCertificate', {
+ get: function() {
+ return OrigPeerConnection.generateCertificate;
+ }
+ });
+ }
+
+ var origGetStats = RTCPeerConnection.prototype.getStats;
+ RTCPeerConnection.prototype.getStats = function(selector,
+ successCallback, errorCallback) {
+ var self = this;
+ var args = arguments;
+
+ // If selector is a function then we are in the old style stats so just
+ // pass back the original getStats format to avoid breaking old users.
+ if (arguments.length > 0 && typeof selector === 'function') {
+ return origGetStats.apply(this, arguments);
+ }
+
+ // When spec-style getStats is supported, return those when called with
+ // either no arguments or the selector argument is null.
+ if (origGetStats.length === 0 && (arguments.length === 0 ||
+ typeof arguments[0] !== 'function')) {
+ return origGetStats.apply(this, []);
+ }
+
+ var fixChromeStats_ = function(response) {
+ var standardReport = {};
+ var reports = response.result();
+ reports.forEach(function(report) {
+ var standardStats = {
+ id: report.id,
+ timestamp: report.timestamp,
+ type: {
+ localcandidate: 'local-candidate',
+ remotecandidate: 'remote-candidate'
+ }[report.type] || report.type
+ };
+ report.names().forEach(function(name) {
+ standardStats[name] = report.stat(name);
+ });
+ standardReport[standardStats.id] = standardStats;
+ });
+
+ return standardReport;
+ };
+
+ // shim getStats with maplike support
+ var makeMapStats = function(stats) {
+ return new Map(Object.keys(stats).map(function(key) {
+ return [key, stats[key]];
+ }));
+ };
+
+ if (arguments.length >= 2) {
+ var successCallbackWrapper_ = function(response) {
+ args[1](makeMapStats(fixChromeStats_(response)));
+ };
+
+ return origGetStats.apply(this, [successCallbackWrapper_,
+ arguments[0]]);
+ }
+
+ // promise-support
+ return new Promise(function(resolve, reject) {
+ origGetStats.apply(self, [
+ function(response) {
+ resolve(makeMapStats(fixChromeStats_(response)));
+ }, reject]);
+ }).then(successCallback, errorCallback);
+ };
+
+ // add promise support -- natively available in Chrome 51
+ if (browserDetails.version < 51) {
+ ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate']
+ .forEach(function(method) {
+ var nativeMethod = RTCPeerConnection.prototype[method];
+ RTCPeerConnection.prototype[method] = function() {
+ var args = arguments;
+ var self = this;
+ var promise = new Promise(function(resolve, reject) {
+ nativeMethod.apply(self, [args[0], resolve, reject]);
+ });
+ if (args.length < 2) {
+ return promise;
+ }
+ return promise.then(function() {
+ args[1].apply(null, []);
+ },
+ function(err) {
+ if (args.length >= 3) {
+ args[2].apply(null, [err]);
+ }
+ });
+ };
+ });
+ }
+
+ // promise support for createOffer and createAnswer. Available (without
+ // bugs) since M52: crbug/619289
+ if (browserDetails.version < 52) {
+ ['createOffer', 'createAnswer'].forEach(function(method) {
+ var nativeMethod = RTCPeerConnection.prototype[method];
+ RTCPeerConnection.prototype[method] = function() {
+ var self = this;
+ if (arguments.length < 1 || (arguments.length === 1 &&
+ typeof arguments[0] === 'object')) {
+ var opts = arguments.length === 1 ? arguments[0] : undefined;
+ return new Promise(function(resolve, reject) {
+ nativeMethod.apply(self, [resolve, reject, opts]);
+ });
+ }
+ return nativeMethod.apply(this, arguments);
+ };
+ });
+ }
+
+ // shim implicit creation of RTCSessionDescription/RTCIceCandidate
+ ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate']
+ .forEach(function(method) {
+ var nativeMethod = RTCPeerConnection.prototype[method];
+ RTCPeerConnection.prototype[method] = function() {
+ arguments[0] = new ((method === 'addIceCandidate') ?
+ RTCIceCandidate : RTCSessionDescription)(arguments[0]);
+ return nativeMethod.apply(this, arguments);
+ };
+ });
+
+ // support for addIceCandidate(null or undefined)
+ var nativeAddIceCandidate =
+ RTCPeerConnection.prototype.addIceCandidate;
+ RTCPeerConnection.prototype.addIceCandidate = function() {
+ if (!arguments[0]) {
+ if (arguments[1]) {
+ arguments[1].apply(null);
+ }
+ return Promise.resolve();
+ }
+ return nativeAddIceCandidate.apply(this, arguments);
+ };
+ }
+};
+
+
+// Expose public methods.
+module.exports = {
+ shimMediaStream: chromeShim.shimMediaStream,
+ shimOnTrack: chromeShim.shimOnTrack,
+ shimGetSendersWithDtmf: chromeShim.shimGetSendersWithDtmf,
+ shimSourceObject: chromeShim.shimSourceObject,
+ shimPeerConnection: chromeShim.shimPeerConnection,
+ shimGetUserMedia: __webpack_require__(10)
+};
+
+
+/***/ }),
+/* 10 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+/*
+ * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree.
+ */
+ /* eslint-env node */
+
+var logging = __webpack_require__(0).log;
+var browserDetails = __webpack_require__(0).browserDetails;
+
+// Expose public methods.
+module.exports = function() {
+ var constraintsToChrome_ = function(c) {
+ if (typeof c !== 'object' || c.mandatory || c.optional) {
+ return c;
+ }
+ var cc = {};
+ Object.keys(c).forEach(function(key) {
+ if (key === 'require' || key === 'advanced' || key === 'mediaSource') {
+ return;
+ }
+ var r = (typeof c[key] === 'object') ? c[key] : {ideal: c[key]};
+ if (r.exact !== undefined && typeof r.exact === 'number') {
+ r.min = r.max = r.exact;
+ }
+ var oldname_ = function(prefix, name) {
+ if (prefix) {
+ return prefix + name.charAt(0).toUpperCase() + name.slice(1);
+ }
+ return (name === 'deviceId') ? 'sourceId' : name;
+ };
+ if (r.ideal !== undefined) {
+ cc.optional = cc.optional || [];
+ var oc = {};
+ if (typeof r.ideal === 'number') {
+ oc[oldname_('min', key)] = r.ideal;
+ cc.optional.push(oc);
+ oc = {};
+ oc[oldname_('max', key)] = r.ideal;
+ cc.optional.push(oc);
+ } else {
+ oc[oldname_('', key)] = r.ideal;
+ cc.optional.push(oc);
+ }
+ }
+ if (r.exact !== undefined && typeof r.exact !== 'number') {
+ cc.mandatory = cc.mandatory || {};
+ cc.mandatory[oldname_('', key)] = r.exact;
+ } else {
+ ['min', 'max'].forEach(function(mix) {
+ if (r[mix] !== undefined) {
+ cc.mandatory = cc.mandatory || {};
+ cc.mandatory[oldname_(mix, key)] = r[mix];
+ }
+ });
+ }
+ });
+ if (c.advanced) {
+ cc.optional = (cc.optional || []).concat(c.advanced);
+ }
+ return cc;
+ };
+
+ var shimConstraints_ = function(constraints, func) {
+ constraints = JSON.parse(JSON.stringify(constraints));
+ if (constraints && constraints.audio) {
+ constraints.audio = constraintsToChrome_(constraints.audio);
+ }
+ if (constraints && typeof constraints.video === 'object') {
+ // Shim facingMode for mobile & surface pro.
+ var face = constraints.video.facingMode;
+ face = face && ((typeof face === 'object') ? face : {ideal: face});
+ var getSupportedFacingModeLies = browserDetails.version < 61;
+
+ if ((face && (face.exact === 'user' || face.exact === 'environment' ||
+ face.ideal === 'user' || face.ideal === 'environment')) &&
+ !(navigator.mediaDevices.getSupportedConstraints &&
+ navigator.mediaDevices.getSupportedConstraints().facingMode &&
+ !getSupportedFacingModeLies)) {
+ delete constraints.video.facingMode;
+ var matches;
+ if (face.exact === 'environment' || face.ideal === 'environment') {
+ matches = ['back', 'rear'];
+ } else if (face.exact === 'user' || face.ideal === 'user') {
+ matches = ['front'];
+ }
+ if (matches) {
+ // Look for matches in label, or use last cam for back (typical).
+ return navigator.mediaDevices.enumerateDevices()
+ .then(function(devices) {
+ devices = devices.filter(function(d) {
+ return d.kind === 'videoinput';
+ });
+ var dev = devices.find(function(d) {
+ return matches.some(function(match) {
+ return d.label.toLowerCase().indexOf(match) !== -1;
+ });
+ });
+ if (!dev && devices.length && matches.indexOf('back') !== -1) {
+ dev = devices[devices.length - 1]; // more likely the back cam
+ }
+ if (dev) {
+ constraints.video.deviceId = face.exact ? {exact: dev.deviceId} :
+ {ideal: dev.deviceId};
+ }
+ constraints.video = constraintsToChrome_(constraints.video);
+ logging('chrome: ' + JSON.stringify(constraints));
+ return func(constraints);
+ });
+ }
+ }
+ constraints.video = constraintsToChrome_(constraints.video);
+ }
+ logging('chrome: ' + JSON.stringify(constraints));
+ return func(constraints);
+ };
+
+ var shimError_ = function(e) {
+ return {
+ name: {
+ ConstraintNotSatisfiedError: 'OverconstrainedError',
+ PermissionDeniedError: 'NotAllowedError',
+ TrackStartError: 'NotReadableError'
+ }[e.name] || e.name,
+ message: e.message,
+ constraint: e.constraintName,
+ toString: function() {
+ return this.name + (this.message && ': ') + this.message;
+ }
+ };
+ };
+
+ var getUserMedia_ = function(constraints, onSuccess, onError) {
+ shimConstraints_(constraints, function(c) {
+ navigator.webkitGetUserMedia(c, onSuccess, function(e) {
+ onError(shimError_(e));
+ });
+ });
+ };
+
+ navigator.getUserMedia = getUserMedia_;
+
+ // Returns the result of getUserMedia as a Promise.
+ var getUserMediaPromise_ = function(constraints) {
+ return new Promise(function(resolve, reject) {
+ navigator.getUserMedia(constraints, resolve, reject);
+ });
+ };
+
+ if (!navigator.mediaDevices) {
+ navigator.mediaDevices = {
+ getUserMedia: getUserMediaPromise_,
+ enumerateDevices: function() {
+ return new Promise(function(resolve) {
+ var kinds = {audio: 'audioinput', video: 'videoinput'};
+ return MediaStreamTrack.getSources(function(devices) {
+ resolve(devices.map(function(device) {
+ return {label: device.label,
+ kind: kinds[device.kind],
+ deviceId: device.id,
+ groupId: ''};
+ }));
+ });
+ });
+ },
+ getSupportedConstraints: function() {
+ return {
+ deviceId: true, echoCancellation: true, facingMode: true,
+ frameRate: true, height: true, width: true
+ };
+ }
+ };
+ }
+
+ // A shim for getUserMedia method on the mediaDevices object.
+ // TODO(KaptenJansson) remove once implemented in Chrome stable.
+ if (!navigator.mediaDevices.getUserMedia) {
+ navigator.mediaDevices.getUserMedia = function(constraints) {
+ return getUserMediaPromise_(constraints);
+ };
+ } else {
+ // Even though Chrome 45 has navigator.mediaDevices and a getUserMedia
+ // function which returns a Promise, it does not accept spec-style
+ // constraints.
+ var origGetUserMedia = navigator.mediaDevices.getUserMedia.
+ bind(navigator.mediaDevices);
+ navigator.mediaDevices.getUserMedia = function(cs) {
+ return shimConstraints_(cs, function(c) {
+ return origGetUserMedia(c).then(function(stream) {
+ if (c.audio && !stream.getAudioTracks().length ||
+ c.video && !stream.getVideoTracks().length) {
+ stream.getTracks().forEach(function(track) {
+ track.stop();
+ });
+ throw new DOMException('', 'NotFoundError');
+ }
+ return stream;
+ }, function(e) {
+ return Promise.reject(shimError_(e));
+ });
+ });
+ };
+ }
+
+ // Dummy devicechange event methods.
+ // TODO(KaptenJansson) remove once implemented in Chrome stable.
+ if (typeof navigator.mediaDevices.addEventListener === 'undefined') {
+ navigator.mediaDevices.addEventListener = function() {
+ logging('Dummy mediaDevices.addEventListener called.');
+ };
+ }
+ if (typeof navigator.mediaDevices.removeEventListener === 'undefined') {
+ navigator.mediaDevices.removeEventListener = function() {
+ logging('Dummy mediaDevices.removeEventListener called.');
+ };
+ }
+};
+
+
+/***/ }),
+/* 11 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+/*
+ * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree.
+ */
+ /* eslint-env node */
+
+
+var browserDetails = __webpack_require__(0).browserDetails;
+var shimRTCPeerConnection = __webpack_require__(13);
+
+module.exports = {
+ shimGetUserMedia: __webpack_require__(12),
+ shimPeerConnection: function() {
+ if (window.RTCIceGatherer) {
+ // ORTC defines an RTCIceCandidate object but no constructor.
+ // Not implemented in Edge.
+ if (!window.RTCIceCandidate) {
+ window.RTCIceCandidate = function(args) {
+ return args;
+ };
+ }
+ // ORTC does not have a session description object but
+ // other browsers (i.e. Chrome) that will support both PC and ORTC
+ // in the future might have this defined already.
+ if (!window.RTCSessionDescription) {
+ window.RTCSessionDescription = function(args) {
+ return args;
+ };
+ }
+ // this adds an additional event listener to MediaStrackTrack that signals
+ // when a tracks enabled property was changed. Workaround for a bug in
+ // addStream, see below. No longer required in 15025+
+ if (browserDetails.version < 15025) {
+ var origMSTEnabled = Object.getOwnPropertyDescriptor(
+ MediaStreamTrack.prototype, 'enabled');
+ Object.defineProperty(MediaStreamTrack.prototype, 'enabled', {
+ set: function(value) {
+ origMSTEnabled.set.call(this, value);
+ var ev = new Event('enabled');
+ ev.enabled = value;
+ this.dispatchEvent(ev);
+ }
+ });
+ }
+ }
+ window.RTCPeerConnection = shimRTCPeerConnection(browserDetails.version);
+ },
+ shimReplaceTrack: function() {
+ // ORTC has replaceTrack -- https://github.com/w3c/ortc/issues/614
+ if (window.RTCRtpSender && !('replaceTrack' in RTCRtpSender.prototype)) {
+ RTCRtpSender.prototype.replaceTrack = RTCRtpSender.prototype.setTrack;
+ }
+ }
+};
+
+
+/***/ }),
+/* 12 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+/*
+ * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree.
+ */
+ /* eslint-env node */
+
+
+// Expose public methods.
+module.exports = function() {
+ var shimError_ = function(e) {
+ return {
+ name: {PermissionDeniedError: 'NotAllowedError'}[e.name] || e.name,
+ message: e.message,
+ constraint: e.constraint,
+ toString: function() {
+ return this.name;
+ }
+ };
+ };
+
+ // getUserMedia error shim.
+ var origGetUserMedia = navigator.mediaDevices.getUserMedia.
+ bind(navigator.mediaDevices);
+ navigator.mediaDevices.getUserMedia = function(c) {
+ return origGetUserMedia(c).catch(function(e) {
+ return Promise.reject(shimError_(e));
+ });
+ };
+};
+
+
+/***/ }),
+/* 13 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+/*
+ * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree.
+ */
+ /* eslint-env node */
+
+
+var SDPUtils = __webpack_require__(7);
+
+// sort tracks such that they follow an a-v-a-v...
+// pattern.
+function sortTracks(tracks) {
+ var audioTracks = tracks.filter(function(track) {
+ return track.kind === 'audio';
+ });
+ var videoTracks = tracks.filter(function(track) {
+ return track.kind === 'video';
+ });
+ tracks = [];
+ while (audioTracks.length || videoTracks.length) {
+ if (audioTracks.length) {
+ tracks.push(audioTracks.shift());
+ }
+ if (videoTracks.length) {
+ tracks.push(videoTracks.shift());
+ }
+ }
+ return tracks;
+}
+
+// Edge does not like
+// 1) stun:
+// 2) turn: that does not have all of turn:host:port?transport=udp
+// 3) turn: with ipv6 addresses
+// 4) turn: occurring muliple times
+function filterIceServers(iceServers, edgeVersion) {
+ var hasTurn = false;
+ iceServers = JSON.parse(JSON.stringify(iceServers));
+ return iceServers.filter(function(server) {
+ if (server && (server.urls || server.url)) {
+ var urls = server.urls || server.url;
+ if (server.url && !server.urls) {
+ console.warn('RTCIceServer.url is deprecated! Use urls instead.');
+ }
+ var isString = typeof urls === 'string';
+ if (isString) {
+ urls = [urls];
+ }
+ urls = urls.filter(function(url) {
+ var validTurn = url.indexOf('turn:') === 0 &&
+ url.indexOf('transport=udp') !== -1 &&
+ url.indexOf('turn:[') === -1 &&
+ !hasTurn;
+
+ if (validTurn) {
+ hasTurn = true;
+ return true;
+ }
+ return url.indexOf('stun:') === 0 && edgeVersion >= 14393;
+ });
+
+ delete server.url;
+ server.urls = isString ? urls[0] : urls;
+ return !!urls.length;
+ }
+ return false;
+ });
+}
+
+// Determines the intersection of local and remote capabilities.
+function getCommonCapabilities(localCapabilities, remoteCapabilities) {
+ var commonCapabilities = {
+ codecs: [],
+ headerExtensions: [],
+ fecMechanisms: []
+ };
+
+ var findCodecByPayloadType = function(pt, codecs) {
+ pt = parseInt(pt, 10);
+ for (var i = 0; i < codecs.length; i++) {
+ if (codecs[i].payloadType === pt ||
+ codecs[i].preferredPayloadType === pt) {
+ return codecs[i];
+ }
+ }
+ };
+
+ var rtxCapabilityMatches = function(lRtx, rRtx, lCodecs, rCodecs) {
+ var lCodec = findCodecByPayloadType(lRtx.parameters.apt, lCodecs);
+ var rCodec = findCodecByPayloadType(rRtx.parameters.apt, rCodecs);
+ return lCodec && rCodec &&
+ lCodec.name.toLowerCase() === rCodec.name.toLowerCase();
+ };
+
+ localCapabilities.codecs.forEach(function(lCodec) {
+ for (var i = 0; i < remoteCapabilities.codecs.length; i++) {
+ var rCodec = remoteCapabilities.codecs[i];
+ if (lCodec.name.toLowerCase() === rCodec.name.toLowerCase() &&
+ lCodec.clockRate === rCodec.clockRate) {
+ if (lCodec.name.toLowerCase() === 'rtx' &&
+ lCodec.parameters && rCodec.parameters.apt) {
+ // for RTX we need to find the local rtx that has a apt
+ // which points to the same local codec as the remote one.
+ if (!rtxCapabilityMatches(lCodec, rCodec,
+ localCapabilities.codecs, remoteCapabilities.codecs)) {
+ continue;
+ }
+ }
+ rCodec = JSON.parse(JSON.stringify(rCodec)); // deepcopy
+ // number of channels is the highest common number of channels
+ rCodec.numChannels = Math.min(lCodec.numChannels,
+ rCodec.numChannels);
+ // push rCodec so we reply with offerer payload type
+ commonCapabilities.codecs.push(rCodec);
+
+ // determine common feedback mechanisms
+ rCodec.rtcpFeedback = rCodec.rtcpFeedback.filter(function(fb) {
+ for (var j = 0; j < lCodec.rtcpFeedback.length; j++) {
+ if (lCodec.rtcpFeedback[j].type === fb.type &&
+ lCodec.rtcpFeedback[j].parameter === fb.parameter) {
+ return true;
+ }
+ }
+ return false;
+ });
+ // FIXME: also need to determine .parameters
+ // see https://github.com/openpeer/ortc/issues/569
+ break;
+ }
+ }
+ });
+
+ localCapabilities.headerExtensions.forEach(function(lHeaderExtension) {
+ for (var i = 0; i < remoteCapabilities.headerExtensions.length;
+ i++) {
+ var rHeaderExtension = remoteCapabilities.headerExtensions[i];
+ if (lHeaderExtension.uri === rHeaderExtension.uri) {
+ commonCapabilities.headerExtensions.push(rHeaderExtension);
+ break;
+ }
+ }
+ });
+
+ // FIXME: fecMechanisms
+ return commonCapabilities;
+}
+
+// is action=setLocalDescription with type allowed in signalingState
+function isActionAllowedInSignalingState(action, type, signalingState) {
+ return {
+ offer: {
+ setLocalDescription: ['stable', 'have-local-offer'],
+ setRemoteDescription: ['stable', 'have-remote-offer']
+ },
+ answer: {
+ setLocalDescription: ['have-remote-offer', 'have-local-pranswer'],
+ setRemoteDescription: ['have-local-offer', 'have-remote-pranswer']
+ }
+ }[type][action].indexOf(signalingState) !== -1;
+}
+
+module.exports = function(edgeVersion) {
+ var RTCPeerConnection = function(config) {
+ var self = this;
+
+ var _eventTarget = document.createDocumentFragment();
+ ['addEventListener', 'removeEventListener', 'dispatchEvent']
+ .forEach(function(method) {
+ self[method] = _eventTarget[method].bind(_eventTarget);
+ });
+
+ this.needNegotiation = false;
+
+ this.onicecandidate = null;
+ this.onaddstream = null;
+ this.ontrack = null;
+ this.onremovestream = null;
+ this.onsignalingstatechange = null;
+ this.oniceconnectionstatechange = null;
+ this.onicegatheringstatechange = null;
+ this.onnegotiationneeded = null;
+ this.ondatachannel = null;
+ this.canTrickleIceCandidates = null;
+
+ this.localStreams = [];
+ this.remoteStreams = [];
+ this.getLocalStreams = function() {
+ return self.localStreams;
+ };
+ this.getRemoteStreams = function() {
+ return self.remoteStreams;
+ };
+
+ this.localDescription = new RTCSessionDescription({
+ type: '',
+ sdp: ''
+ });
+ this.remoteDescription = new RTCSessionDescription({
+ type: '',
+ sdp: ''
+ });
+ this.signalingState = 'stable';
+ this.iceConnectionState = 'new';
+ this.iceGatheringState = 'new';
+
+ this.iceOptions = {
+ gatherPolicy: 'all',
+ iceServers: []
+ };
+ if (config && config.iceTransportPolicy) {
+ switch (config.iceTransportPolicy) {
+ case 'all':
+ case 'relay':
+ this.iceOptions.gatherPolicy = config.iceTransportPolicy;
+ break;
+ default:
+ // don't set iceTransportPolicy.
+ break;
+ }
+ }
+ this.usingBundle = config && config.bundlePolicy === 'max-bundle';
+
+ if (config && config.iceServers) {
+ this.iceOptions.iceServers = filterIceServers(config.iceServers,
+ edgeVersion);
+ }
+ this._config = config || {};
+
+ // per-track iceGathers, iceTransports, dtlsTransports, rtpSenders, ...
+ // everything that is needed to describe a SDP m-line.
+ this.transceivers = [];
+
+ // since the iceGatherer is currently created in createOffer but we
+ // must not emit candidates until after setLocalDescription we buffer
+ // them in this array.
+ this._localIceCandidatesBuffer = [];
+ };
+
+ RTCPeerConnection.prototype._emitGatheringStateChange = function() {
+ var event = new Event('icegatheringstatechange');
+ this.dispatchEvent(event);
+ if (this.onicegatheringstatechange !== null) {
+ this.onicegatheringstatechange(event);
+ }
+ };
+
+ RTCPeerConnection.prototype._emitBufferedCandidates = function() {
+ var self = this;
+ var sections = SDPUtils.splitSections(self.localDescription.sdp);
+ // FIXME: need to apply ice candidates in a way which is async but
+ // in-order
+ this._localIceCandidatesBuffer.forEach(function(event) {
+ var end = !event.candidate || Object.keys(event.candidate).length === 0;
+ if (end) {
+ for (var j = 1; j < sections.length; j++) {
+ if (sections[j].indexOf('\r\na=end-of-candidates\r\n') === -1) {
+ sections[j] += 'a=end-of-candidates\r\n';
+ }
+ }
+ } else {
+ sections[event.candidate.sdpMLineIndex + 1] +=
+ 'a=' + event.candidate.candidate + '\r\n';
+ }
+ self.localDescription.sdp = sections.join('');
+ self.dispatchEvent(event);
+ if (self.onicecandidate !== null) {
+ self.onicecandidate(event);
+ }
+ if (!event.candidate && self.iceGatheringState !== 'complete') {
+ var complete = self.transceivers.every(function(transceiver) {
+ return transceiver.iceGatherer &&
+ transceiver.iceGatherer.state === 'completed';
+ });
+ if (complete && self.iceGatheringStateChange !== 'complete') {
+ self.iceGatheringState = 'complete';
+ self._emitGatheringStateChange();
+ }
+ }
+ });
+ this._localIceCandidatesBuffer = [];
+ };
+
+ RTCPeerConnection.prototype.getConfiguration = function() {
+ return this._config;
+ };
+
+ // internal helper to create a transceiver object.
+ // (whih is not yet the same as the WebRTC 1.0 transceiver)
+ RTCPeerConnection.prototype._createTransceiver = function(kind) {
+ var hasBundleTransport = this.transceivers.length > 0;
+ var transceiver = {
+ track: null,
+ iceGatherer: null,
+ iceTransport: null,
+ dtlsTransport: null,
+ localCapabilities: null,
+ remoteCapabilities: null,
+ rtpSender: null,
+ rtpReceiver: null,
+ kind: kind,
+ mid: null,
+ sendEncodingParameters: null,
+ recvEncodingParameters: null,
+ stream: null,
+ wantReceive: true
+ };
+ if (this.usingBundle && hasBundleTransport) {
+ transceiver.iceTransport = this.transceivers[0].iceTransport;
+ transceiver.dtlsTransport = this.transceivers[0].dtlsTransport;
+ } else {
+ var transports = this._createIceAndDtlsTransports();
+ transceiver.iceTransport = transports.iceTransport;
+ transceiver.dtlsTransport = transports.dtlsTransport;
+ }
+ this.transceivers.push(transceiver);
+ return transceiver;
+ };
+
+ RTCPeerConnection.prototype.addTrack = function(track, stream) {
+ var transceiver;
+ for (var i = 0; i < this.transceivers.length; i++) {
+ if (!this.transceivers[i].track &&
+ this.transceivers[i].kind === track.kind) {
+ transceiver = this.transceivers[i];
+ }
+ }
+ if (!transceiver) {
+ transceiver = this._createTransceiver(track.kind);
+ }
+
+ transceiver.track = track;
+ transceiver.stream = stream;
+ transceiver.rtpSender = new RTCRtpSender(track,
+ transceiver.dtlsTransport);
+
+ this._maybeFireNegotiationNeeded();
+ return transceiver.rtpSender;
+ };
+
+ RTCPeerConnection.prototype.addStream = function(stream) {
+ var self = this;
+ if (edgeVersion >= 15025) {
+ this.localStreams.push(stream);
+ stream.getTracks().forEach(function(track) {
+ self.addTrack(track, stream);
+ });
+ } else {
+ // Clone is necessary for local demos mostly, attaching directly
+ // to two different senders does not work (build 10547).
+ // Fixed in 15025 (or earlier)
+ var clonedStream = stream.clone();
+ stream.getTracks().forEach(function(track, idx) {
+ var clonedTrack = clonedStream.getTracks()[idx];
+ track.addEventListener('enabled', function(event) {
+ clonedTrack.enabled = event.enabled;
+ });
+ });
+ clonedStream.getTracks().forEach(function(track) {
+ self.addTrack(track, clonedStream);
+ });
+ this.localStreams.push(clonedStream);
+ }
+ this._maybeFireNegotiationNeeded();
+ };
+
+ RTCPeerConnection.prototype.removeStream = function(stream) {
+ var idx = this.localStreams.indexOf(stream);
+ if (idx > -1) {
+ this.localStreams.splice(idx, 1);
+ this._maybeFireNegotiationNeeded();
+ }
+ };
+
+ RTCPeerConnection.prototype.getSenders = function() {
+ return this.transceivers.filter(function(transceiver) {
+ return !!transceiver.rtpSender;
+ })
+ .map(function(transceiver) {
+ return transceiver.rtpSender;
+ });
+ };
+
+ RTCPeerConnection.prototype.getReceivers = function() {
+ return this.transceivers.filter(function(transceiver) {
+ return !!transceiver.rtpReceiver;
+ })
+ .map(function(transceiver) {
+ return transceiver.rtpReceiver;
+ });
+ };
+
+ // Create ICE gatherer and hook it up.
+ RTCPeerConnection.prototype._createIceGatherer = function(mid,
+ sdpMLineIndex) {
+ var self = this;
+ var iceGatherer = new RTCIceGatherer(self.iceOptions);
+ iceGatherer.onlocalcandidate = function(evt) {
+ var event = new Event('icecandidate');
+ event.candidate = {sdpMid: mid, sdpMLineIndex: sdpMLineIndex};
+
+ var cand = evt.candidate;
+ var end = !cand || Object.keys(cand).length === 0;
+ // Edge emits an empty object for RTCIceCandidateComplete‥
+ if (end) {
+ // polyfill since RTCIceGatherer.state is not implemented in
+ // Edge 10547 yet.
+ if (iceGatherer.state === undefined) {
+ iceGatherer.state = 'completed';
+ }
+ } else {
+ // RTCIceCandidate doesn't have a component, needs to be added
+ cand.component = 1;
+ event.candidate.candidate = SDPUtils.writeCandidate(cand);
+ }
+
+ // update local description.
+ var sections = SDPUtils.splitSections(self.localDescription.sdp);
+ if (!end) {
+ sections[event.candidate.sdpMLineIndex + 1] +=
+ 'a=' + event.candidate.candidate + '\r\n';
+ } else {
+ sections[event.candidate.sdpMLineIndex + 1] +=
+ 'a=end-of-candidates\r\n';
+ }
+ self.localDescription.sdp = sections.join('');
+ var transceivers = self._pendingOffer ? self._pendingOffer :
+ self.transceivers;
+ var complete = transceivers.every(function(transceiver) {
+ return transceiver.iceGatherer &&
+ transceiver.iceGatherer.state === 'completed';
+ });
+
+ // Emit candidate if localDescription is set.
+ // Also emits null candidate when all gatherers are complete.
+ switch (self.iceGatheringState) {
+ case 'new':
+ if (!end) {
+ self._localIceCandidatesBuffer.push(event);
+ }
+ if (end && complete) {
+ self._localIceCandidatesBuffer.push(
+ new Event('icecandidate'));
+ }
+ break;
+ case 'gathering':
+ self._emitBufferedCandidates();
+ if (!end) {
+ self.dispatchEvent(event);
+ if (self.onicecandidate !== null) {
+ self.onicecandidate(event);
+ }
+ }
+ if (complete) {
+ self.dispatchEvent(new Event('icecandidate'));
+ if (self.onicecandidate !== null) {
+ self.onicecandidate(new Event('icecandidate'));
+ }
+ self.iceGatheringState = 'complete';
+ self._emitGatheringStateChange();
+ }
+ break;
+ case 'complete':
+ // should not happen... currently!
+ break;
+ default: // no-op.
+ break;
+ }
+ };
+ return iceGatherer;
+ };
+
+ // Create ICE transport and DTLS transport.
+ RTCPeerConnection.prototype._createIceAndDtlsTransports = function() {
+ var self = this;
+ var iceTransport = new RTCIceTransport(null);
+ iceTransport.onicestatechange = function() {
+ self._updateConnectionState();
+ };
+
+ var dtlsTransport = new RTCDtlsTransport(iceTransport);
+ dtlsTransport.ondtlsstatechange = function() {
+ self._updateConnectionState();
+ };
+ dtlsTransport.onerror = function() {
+ // onerror does not set state to failed by itself.
+ Object.defineProperty(dtlsTransport, 'state',
+ {value: 'failed', writable: true});
+ self._updateConnectionState();
+ };
+
+ return {
+ iceTransport: iceTransport,
+ dtlsTransport: dtlsTransport
+ };
+ };
+
+ // Destroy ICE gatherer, ICE transport and DTLS transport.
+ // Without triggering the callbacks.
+ RTCPeerConnection.prototype._disposeIceAndDtlsTransports = function(
+ sdpMLineIndex) {
+ var iceGatherer = this.transceivers[sdpMLineIndex].iceGatherer;
+ if (iceGatherer) {
+ delete iceGatherer.onlocalcandidate;
+ delete this.transceivers[sdpMLineIndex].iceGatherer;
+ }
+ var iceTransport = this.transceivers[sdpMLineIndex].iceTransport;
+ if (iceTransport) {
+ delete iceTransport.onicestatechange;
+ delete this.transceivers[sdpMLineIndex].iceTransport;
+ }
+ var dtlsTransport = this.transceivers[sdpMLineIndex].dtlsTransport;
+ if (dtlsTransport) {
+ delete dtlsTransport.ondtlssttatechange;
+ delete dtlsTransport.onerror;
+ delete this.transceivers[sdpMLineIndex].dtlsTransport;
+ }
+ };
+
+ // Start the RTP Sender and Receiver for a transceiver.
+ RTCPeerConnection.prototype._transceive = function(transceiver,
+ send, recv) {
+ var params = getCommonCapabilities(transceiver.localCapabilities,
+ transceiver.remoteCapabilities);
+ if (send && transceiver.rtpSender) {
+ params.encodings = transceiver.sendEncodingParameters;
+ params.rtcp = {
+ cname: SDPUtils.localCName,
+ compound: transceiver.rtcpParameters.compound
+ };
+ if (transceiver.recvEncodingParameters.length) {
+ params.rtcp.ssrc = transceiver.recvEncodingParameters[0].ssrc;
+ }
+ transceiver.rtpSender.send(params);
+ }
+ if (recv && transceiver.rtpReceiver) {
+ // remove RTX field in Edge 14942
+ if (transceiver.kind === 'video'
+ && transceiver.recvEncodingParameters
+ && edgeVersion < 15019) {
+ transceiver.recvEncodingParameters.forEach(function(p) {
+ delete p.rtx;
+ });
+ }
+ params.encodings = transceiver.recvEncodingParameters;
+ params.rtcp = {
+ cname: transceiver.rtcpParameters.cname,
+ compound: transceiver.rtcpParameters.compound
+ };
+ if (transceiver.sendEncodingParameters.length) {
+ params.rtcp.ssrc = transceiver.sendEncodingParameters[0].ssrc;
+ }
+ transceiver.rtpReceiver.receive(params);
+ }
+ };
+
+ RTCPeerConnection.prototype.setLocalDescription = function(description) {
+ var self = this;
+
+ if (!isActionAllowedInSignalingState('setLocalDescription',
+ description.type, this.signalingState)) {
+ var e = new Error('Can not set local ' + description.type +
+ ' in state ' + this.signalingState);
+ e.name = 'InvalidStateError';
+ if (arguments.length > 2 && typeof arguments[2] === 'function') {
+ window.setTimeout(arguments[2], 0, e);
+ }
+ return Promise.reject(e);
+ }
+
+ var sections;
+ var sessionpart;
+ if (description.type === 'offer') {
+ // FIXME: What was the purpose of this empty if statement?
+ // if (!this._pendingOffer) {
+ // } else {
+ if (this._pendingOffer) {
+ // VERY limited support for SDP munging. Limited to:
+ // * changing the order of codecs
+ sections = SDPUtils.splitSections(description.sdp);
+ sessionpart = sections.shift();
+ sections.forEach(function(mediaSection, sdpMLineIndex) {
+ var caps = SDPUtils.parseRtpParameters(mediaSection);
+ self._pendingOffer[sdpMLineIndex].localCapabilities = caps;
+ });
+ this.transceivers = this._pendingOffer;
+ delete this._pendingOffer;
+ }
+ } else if (description.type === 'answer') {
+ sections = SDPUtils.splitSections(self.remoteDescription.sdp);
+ sessionpart = sections.shift();
+ var isIceLite = SDPUtils.matchPrefix(sessionpart,
+ 'a=ice-lite').length > 0;
+ sections.forEach(function(mediaSection, sdpMLineIndex) {
+ var transceiver = self.transceivers[sdpMLineIndex];
+ var iceGatherer = transceiver.iceGatherer;
+ var iceTransport = transceiver.iceTransport;
+ var dtlsTransport = transceiver.dtlsTransport;
+ var localCapabilities = transceiver.localCapabilities;
+ var remoteCapabilities = transceiver.remoteCapabilities;
+
+ var rejected = SDPUtils.isRejected(mediaSection);
+
+ if (!rejected && !transceiver.isDatachannel) {
+ var remoteIceParameters = SDPUtils.getIceParameters(
+ mediaSection, sessionpart);
+ var remoteDtlsParameters = SDPUtils.getDtlsParameters(
+ mediaSection, sessionpart);
+ if (isIceLite) {
+ remoteDtlsParameters.role = 'server';
+ }
+
+ if (!self.usingBundle || sdpMLineIndex === 0) {
+ iceTransport.start(iceGatherer, remoteIceParameters,
+ isIceLite ? 'controlling' : 'controlled');
+ dtlsTransport.start(remoteDtlsParameters);
+ }
+
+ // Calculate intersection of capabilities.
+ var params = getCommonCapabilities(localCapabilities,
+ remoteCapabilities);
+
+ // Start the RTCRtpSender. The RTCRtpReceiver for this
+ // transceiver has already been started in setRemoteDescription.
+ self._transceive(transceiver,
+ params.codecs.length > 0,
+ false);
+ }
+ });
+ }
+
+ this.localDescription = {
+ type: description.type,
+ sdp: description.sdp
+ };
+ switch (description.type) {
+ case 'offer':
+ this._updateSignalingState('have-local-offer');
+ break;
+ case 'answer':
+ this._updateSignalingState('stable');
+ break;
+ default:
+ throw new TypeError('unsupported type "' + description.type +
+ '"');
+ }
+
+ // If a success callback was provided, emit ICE candidates after it
+ // has been executed. Otherwise, emit callback after the Promise is
+ // resolved.
+ var hasCallback = arguments.length > 1 &&
+ typeof arguments[1] === 'function';
+ if (hasCallback) {
+ var cb = arguments[1];
+ window.setTimeout(function() {
+ cb();
+ if (self.iceGatheringState === 'new') {
+ self.iceGatheringState = 'gathering';
+ self._emitGatheringStateChange();
+ }
+ self._emitBufferedCandidates();
+ }, 0);
+ }
+ var p = Promise.resolve();
+ p.then(function() {
+ if (!hasCallback) {
+ if (self.iceGatheringState === 'new') {
+ self.iceGatheringState = 'gathering';
+ self._emitGatheringStateChange();
+ }
+ // Usually candidates will be emitted earlier.
+ window.setTimeout(self._emitBufferedCandidates.bind(self), 500);
+ }
+ });
+ return p;
+ };
+
+ RTCPeerConnection.prototype.setRemoteDescription = function(description) {
+ var self = this;
+
+ if (!isActionAllowedInSignalingState('setRemoteDescription',
+ description.type, this.signalingState)) {
+ var e = new Error('Can not set remote ' + description.type +
+ ' in state ' + this.signalingState);
+ e.name = 'InvalidStateError';
+ if (arguments.length > 2 && typeof arguments[2] === 'function') {
+ window.setTimeout(arguments[2], 0, e);
+ }
+ return Promise.reject(e);
+ }
+
+ var streams = {};
+ var receiverList = [];
+ var sections = SDPUtils.splitSections(description.sdp);
+ var sessionpart = sections.shift();
+ var isIceLite = SDPUtils.matchPrefix(sessionpart,
+ 'a=ice-lite').length > 0;
+ var usingBundle = SDPUtils.matchPrefix(sessionpart,
+ 'a=group:BUNDLE ').length > 0;
+ this.usingBundle = usingBundle;
+ var iceOptions = SDPUtils.matchPrefix(sessionpart,
+ 'a=ice-options:')[0];
+ if (iceOptions) {
+ this.canTrickleIceCandidates = iceOptions.substr(14).split(' ')
+ .indexOf('trickle') >= 0;
+ } else {
+ this.canTrickleIceCandidates = false;
+ }
+
+ sections.forEach(function(mediaSection, sdpMLineIndex) {
+ var lines = SDPUtils.splitLines(mediaSection);
+ var kind = SDPUtils.getKind(mediaSection);
+ var rejected = SDPUtils.isRejected(mediaSection);
+ var protocol = lines[0].substr(2).split(' ')[2];
+
+ var direction = SDPUtils.getDirection(mediaSection, sessionpart);
+ var remoteMsid = SDPUtils.parseMsid(mediaSection);
+
+ var mid = SDPUtils.getMid(mediaSection) || SDPUtils.generateIdentifier();
+
+ // Reject datachannels which are not implemented yet.
+ if (kind === 'application' && protocol === 'DTLS/SCTP') {
+ self.transceivers[sdpMLineIndex] = {
+ mid: mid,
+ isDatachannel: true
+ };
+ return;
+ }
+
+ var transceiver;
+ var iceGatherer;
+ var iceTransport;
+ var dtlsTransport;
+ var rtpReceiver;
+ var sendEncodingParameters;
+ var recvEncodingParameters;
+ var localCapabilities;
+
+ var track;
+ // FIXME: ensure the mediaSection has rtcp-mux set.
+ var remoteCapabilities = SDPUtils.parseRtpParameters(mediaSection);
+ var remoteIceParameters;
+ var remoteDtlsParameters;
+ if (!rejected) {
+ remoteIceParameters = SDPUtils.getIceParameters(mediaSection,
+ sessionpart);
+ remoteDtlsParameters = SDPUtils.getDtlsParameters(mediaSection,
+ sessionpart);
+ remoteDtlsParameters.role = 'client';
+ }
+ recvEncodingParameters =
+ SDPUtils.parseRtpEncodingParameters(mediaSection);
+
+ var rtcpParameters = SDPUtils.parseRtcpParameters(mediaSection);
+
+ var isComplete = SDPUtils.matchPrefix(mediaSection,
+ 'a=end-of-candidates', sessionpart).length > 0;
+ var cands = SDPUtils.matchPrefix(mediaSection, 'a=candidate:')
+ .map(function(cand) {
+ return SDPUtils.parseCandidate(cand);
+ })
+ .filter(function(cand) {
+ return cand.component === '1' || cand.component === 1;
+ });
+ if (description.type === 'offer' && !rejected) {
+ transceiver = self.transceivers[sdpMLineIndex] ||
+ self._createTransceiver(kind);
+ transceiver.mid = mid;
+
+ if (!transceiver.iceGatherer) {
+ transceiver.iceGatherer = usingBundle && sdpMLineIndex > 0 ?
+ self.transceivers[0].iceGatherer :
+ self._createIceGatherer(mid, sdpMLineIndex);
+ }
+
+ if (isComplete && (!usingBundle || sdpMLineIndex === 0)) {
+ transceiver.iceTransport.setRemoteCandidates(cands);
+ }
+
+ localCapabilities = RTCRtpReceiver.getCapabilities(kind);
+
+ // filter RTX until additional stuff needed for RTX is implemented
+ // in adapter.js
+ if (edgeVersion < 15019) {
+ localCapabilities.codecs = localCapabilities.codecs.filter(
+ function(codec) {
+ return codec.name !== 'rtx';
+ });
+ }
+
+ sendEncodingParameters = [{
+ ssrc: (2 * sdpMLineIndex + 2) * 1001
+ }];
+
+ if (direction === 'sendrecv' || direction === 'sendonly') {
+ rtpReceiver = new RTCRtpReceiver(transceiver.dtlsTransport,
+ kind);
+
+ track = rtpReceiver.track;
+ // FIXME: does not work with Plan B.
+ if (remoteMsid) {
+ if (!streams[remoteMsid.stream]) {
+ streams[remoteMsid.stream] = new MediaStream();
+ Object.defineProperty(streams[remoteMsid.stream], 'id', {
+ get: function() {
+ return remoteMsid.stream;
+ }
+ });
+ }
+ Object.defineProperty(track, 'id', {
+ get: function() {
+ return remoteMsid.track;
+ }
+ });
+ streams[remoteMsid.stream].addTrack(track);
+ receiverList.push([track, rtpReceiver,
+ streams[remoteMsid.stream]]);
+ } else {
+ if (!streams.default) {
+ streams.default = new MediaStream();
+ }
+ streams.default.addTrack(track);
+ receiverList.push([track, rtpReceiver, streams.default]);
+ }
+ }
+
+ transceiver.localCapabilities = localCapabilities;
+ transceiver.remoteCapabilities = remoteCapabilities;
+ transceiver.rtpReceiver = rtpReceiver;
+ transceiver.rtcpParameters = rtcpParameters;
+ transceiver.sendEncodingParameters = sendEncodingParameters;
+ transceiver.recvEncodingParameters = recvEncodingParameters;
+
+ // Start the RTCRtpReceiver now. The RTPSender is started in
+ // setLocalDescription.
+ self._transceive(self.transceivers[sdpMLineIndex],
+ false,
+ direction === 'sendrecv' || direction === 'sendonly');
+ } else if (description.type === 'answer' && !rejected) {
+ if (usingBundle && sdpMLineIndex > 0) {
+ self._disposeIceAndDtlsTransports(sdpMLineIndex);
+ self.transceivers[sdpMLineIndex].iceGatherer =
+ self.transceivers[0].iceGatherer;
+ self.transceivers[sdpMLineIndex].iceTransport =
+ self.transceivers[0].iceTransport;
+ self.transceivers[sdpMLineIndex].dtlsTransport =
+ self.transceivers[0].dtlsTransport;
+ if (self.transceivers[sdpMLineIndex].rtpSender) {
+ self.transceivers[sdpMLineIndex].rtpSender.setTransport(
+ self.transceivers[0].dtlsTransport);
+ }
+ if (self.transceivers[sdpMLineIndex].rtpReceiver) {
+ self.transceivers[sdpMLineIndex].rtpReceiver.setTransport(
+ self.transceivers[0].dtlsTransport);
+ }
+ }
+ transceiver = self.transceivers[sdpMLineIndex];
+ iceGatherer = transceiver.iceGatherer;
+ iceTransport = transceiver.iceTransport;
+ dtlsTransport = transceiver.dtlsTransport;
+ rtpReceiver = transceiver.rtpReceiver;
+ sendEncodingParameters = transceiver.sendEncodingParameters;
+ localCapabilities = transceiver.localCapabilities;
+
+ self.transceivers[sdpMLineIndex].recvEncodingParameters =
+ recvEncodingParameters;
+ self.transceivers[sdpMLineIndex].remoteCapabilities =
+ remoteCapabilities;
+ self.transceivers[sdpMLineIndex].rtcpParameters = rtcpParameters;
+
+ if ((isIceLite || isComplete) && cands.length) {
+ iceTransport.setRemoteCandidates(cands);
+ }
+ if (!usingBundle || sdpMLineIndex === 0) {
+ iceTransport.start(iceGatherer, remoteIceParameters,
+ 'controlling');
+ dtlsTransport.start(remoteDtlsParameters);
+ }
+
+ self._transceive(transceiver,
+ direction === 'sendrecv' || direction === 'recvonly',
+ direction === 'sendrecv' || direction === 'sendonly');
+
+ if (rtpReceiver &&
+ (direction === 'sendrecv' || direction === 'sendonly')) {
+ track = rtpReceiver.track;
+ if (remoteMsid) {
+ if (!streams[remoteMsid.stream]) {
+ streams[remoteMsid.stream] = new MediaStream();
+ }
+ streams[remoteMsid.stream].addTrack(track);
+ receiverList.push([track, rtpReceiver, streams[remoteMsid.stream]]);
+ } else {
+ if (!streams.default) {
+ streams.default = new MediaStream();
+ }
+ streams.default.addTrack(track);
+ receiverList.push([track, rtpReceiver, streams.default]);
+ }
+ } else {
+ // FIXME: actually the receiver should be created later.
+ delete transceiver.rtpReceiver;
+ }
+ }
+ });
+
+ this.remoteDescription = {
+ type: description.type,
+ sdp: description.sdp
+ };
+ switch (description.type) {
+ case 'offer':
+ this._updateSignalingState('have-remote-offer');
+ break;
+ case 'answer':
+ this._updateSignalingState('stable');
+ break;
+ default:
+ throw new TypeError('unsupported type "' + description.type +
+ '"');
+ }
+ Object.keys(streams).forEach(function(sid) {
+ var stream = streams[sid];
+ if (stream.getTracks().length) {
+ self.remoteStreams.push(stream);
+ var event = new Event('addstream');
+ event.stream = stream;
+ self.dispatchEvent(event);
+ if (self.onaddstream !== null) {
+ window.setTimeout(function() {
+ self.onaddstream(event);
+ }, 0);
+ }
+
+ receiverList.forEach(function(item) {
+ var track = item[0];
+ var receiver = item[1];
+ if (stream.id !== item[2].id) {
+ return;
+ }
+ var trackEvent = new Event('track');
+ trackEvent.track = track;
+ trackEvent.receiver = receiver;
+ trackEvent.streams = [stream];
+ self.dispatchEvent(trackEvent);
+ if (self.ontrack !== null) {
+ window.setTimeout(function() {
+ self.ontrack(trackEvent);
+ }, 0);
+ }
+ });
+ }
+ });
+
+ // check whether addIceCandidate({}) was called within four seconds after
+ // setRemoteDescription.
+ window.setTimeout(function() {
+ if (!(self && self.transceivers)) {
+ return;
+ }
+ self.transceivers.forEach(function(transceiver) {
+ if (transceiver.iceTransport &&
+ transceiver.iceTransport.state === 'new' &&
+ transceiver.iceTransport.getRemoteCandidates().length > 0) {
+ console.warn('Timeout for addRemoteCandidate. Consider sending ' +
+ 'an end-of-candidates notification');
+ transceiver.iceTransport.addRemoteCandidate({});
+ }
+ });
+ }, 4000);
+
+ if (arguments.length > 1 && typeof arguments[1] === 'function') {
+ window.setTimeout(arguments[1], 0);
+ }
+ return Promise.resolve();
+ };
+
+ RTCPeerConnection.prototype.close = function() {
+ this.transceivers.forEach(function(transceiver) {
+ /* not yet
+ if (transceiver.iceGatherer) {
+ transceiver.iceGatherer.close();
+ }
+ */
+ if (transceiver.iceTransport) {
+ transceiver.iceTransport.stop();
+ }
+ if (transceiver.dtlsTransport) {
+ transceiver.dtlsTransport.stop();
+ }
+ if (transceiver.rtpSender) {
+ transceiver.rtpSender.stop();
+ }
+ if (transceiver.rtpReceiver) {
+ transceiver.rtpReceiver.stop();
+ }
+ });
+ // FIXME: clean up tracks, local streams, remote streams, etc
+ this._updateSignalingState('closed');
+ };
+
+ // Update the signaling state.
+ RTCPeerConnection.prototype._updateSignalingState = function(newState) {
+ this.signalingState = newState;
+ var event = new Event('signalingstatechange');
+ this.dispatchEvent(event);
+ if (this.onsignalingstatechange !== null) {
+ this.onsignalingstatechange(event);
+ }
+ };
+
+ // Determine whether to fire the negotiationneeded event.
+ RTCPeerConnection.prototype._maybeFireNegotiationNeeded = function() {
+ var self = this;
+ if (this.signalingState !== 'stable' || this.needNegotiation === true) {
+ return;
+ }
+ this.needNegotiation = true;
+ window.setTimeout(function() {
+ if (self.needNegotiation === false) {
+ return;
+ }
+ self.needNegotiation = false;
+ var event = new Event('negotiationneeded');
+ self.dispatchEvent(event);
+ if (self.onnegotiationneeded !== null) {
+ self.onnegotiationneeded(event);
+ }
+ }, 0);
+ };
+
+ // Update the connection state.
+ RTCPeerConnection.prototype._updateConnectionState = function() {
+ var self = this;
+ var newState;
+ var states = {
+ 'new': 0,
+ closed: 0,
+ connecting: 0,
+ checking: 0,
+ connected: 0,
+ completed: 0,
+ failed: 0
+ };
+ this.transceivers.forEach(function(transceiver) {
+ states[transceiver.iceTransport.state]++;
+ states[transceiver.dtlsTransport.state]++;
+ });
+ // ICETransport.completed and connected are the same for this purpose.
+ states.connected += states.completed;
+
+ newState = 'new';
+ if (states.failed > 0) {
+ newState = 'failed';
+ } else if (states.connecting > 0 || states.checking > 0) {
+ newState = 'connecting';
+ } else if (states.disconnected > 0) {
+ newState = 'disconnected';
+ } else if (states.new > 0) {
+ newState = 'new';
+ } else if (states.connected > 0 || states.completed > 0) {
+ newState = 'connected';
+ }
+
+ if (newState !== self.iceConnectionState) {
+ self.iceConnectionState = newState;
+ var event = new Event('iceconnectionstatechange');
+ this.dispatchEvent(event);
+ if (this.oniceconnectionstatechange !== null) {
+ this.oniceconnectionstatechange(event);
+ }
+ }
+ };
+
+ RTCPeerConnection.prototype.createOffer = function() {
+ var self = this;
+ if (this._pendingOffer) {
+ throw new Error('createOffer called while there is a pending offer.');
+ }
+ var offerOptions;
+ if (arguments.length === 1 && typeof arguments[0] !== 'function') {
+ offerOptions = arguments[0];
+ } else if (arguments.length === 3) {
+ offerOptions = arguments[2];
+ }
+
+ var numAudioTracks = this.transceivers.filter(function(t) {
+ return t.kind === 'audio';
+ }).length;
+ var numVideoTracks = this.transceivers.filter(function(t) {
+ return t.kind === 'video';
+ }).length;
+
+ // Determine number of audio and video tracks we need to send/recv.
+ if (offerOptions) {
+ // Reject Chrome legacy constraints.
+ if (offerOptions.mandatory || offerOptions.optional) {
+ throw new TypeError(
+ 'Legacy mandatory/optional constraints not supported.');
+ }
+ if (offerOptions.offerToReceiveAudio !== undefined) {
+ if (offerOptions.offerToReceiveAudio === true) {
+ numAudioTracks = 1;
+ } else if (offerOptions.offerToReceiveAudio === false) {
+ numAudioTracks = 0;
+ } else {
+ numAudioTracks = offerOptions.offerToReceiveAudio;
+ }
+ }
+ if (offerOptions.offerToReceiveVideo !== undefined) {
+ if (offerOptions.offerToReceiveVideo === true) {
+ numVideoTracks = 1;
+ } else if (offerOptions.offerToReceiveVideo === false) {
+ numVideoTracks = 0;
+ } else {
+ numVideoTracks = offerOptions.offerToReceiveVideo;
+ }
+ }
+ }
+
+ this.transceivers.forEach(function(transceiver) {
+ if (transceiver.kind === 'audio') {
+ numAudioTracks--;
+ if (numAudioTracks < 0) {
+ transceiver.wantReceive = false;
+ }
+ } else if (transceiver.kind === 'video') {
+ numVideoTracks--;
+ if (numVideoTracks < 0) {
+ transceiver.wantReceive = false;
+ }
+ }
+ });
+
+ // Create M-lines for recvonly streams.
+ while (numAudioTracks > 0 || numVideoTracks > 0) {
+ if (numAudioTracks > 0) {
+ this._createTransceiver('audio');
+ numAudioTracks--;
+ }
+ if (numVideoTracks > 0) {
+ this._createTransceiver('video');
+ numVideoTracks--;
+ }
+ }
+ // reorder tracks
+ var transceivers = sortTracks(this.transceivers);
+
+ var sdp = SDPUtils.writeSessionBoilerplate();
+ transceivers.forEach(function(transceiver, sdpMLineIndex) {
+ // For each track, create an ice gatherer, ice transport,
+ // dtls transport, potentially rtpsender and rtpreceiver.
+ var track = transceiver.track;
+ var kind = transceiver.kind;
+ var mid = SDPUtils.generateIdentifier();
+ transceiver.mid = mid;
+
+ if (!transceiver.iceGatherer) {
+ transceiver.iceGatherer = self.usingBundle && sdpMLineIndex > 0 ?
+ transceivers[0].iceGatherer :
+ self._createIceGatherer(mid, sdpMLineIndex);
+ }
+
+ var localCapabilities = RTCRtpSender.getCapabilities(kind);
+ // filter RTX until additional stuff needed for RTX is implemented
+ // in adapter.js
+ if (edgeVersion < 15019) {
+ localCapabilities.codecs = localCapabilities.codecs.filter(
+ function(codec) {
+ return codec.name !== 'rtx';
+ });
+ }
+ localCapabilities.codecs.forEach(function(codec) {
+ // work around https://bugs.chromium.org/p/webrtc/issues/detail?id=6552
+ // by adding level-asymmetry-allowed=1
+ if (codec.name === 'H264' &&
+ codec.parameters['level-asymmetry-allowed'] === undefined) {
+ codec.parameters['level-asymmetry-allowed'] = '1';
+ }
+ });
+
+ // generate an ssrc now, to be used later in rtpSender.send
+ var sendEncodingParameters = [{
+ ssrc: (2 * sdpMLineIndex + 1) * 1001
+ }];
+ if (track) {
+ // add RTX
+ if (edgeVersion >= 15019 && kind === 'video') {
+ sendEncodingParameters[0].rtx = {
+ ssrc: (2 * sdpMLineIndex + 1) * 1001 + 1
+ };
+ }
+ }
+
+ if (transceiver.wantReceive) {
+ transceiver.rtpReceiver = new RTCRtpReceiver(transceiver.dtlsTransport,
+ kind);
+ }
+
+ transceiver.localCapabilities = localCapabilities;
+ transceiver.sendEncodingParameters = sendEncodingParameters;
+ });
+
+ // always offer BUNDLE and dispose on return if not supported.
+ if (this._config.bundlePolicy !== 'max-compat') {
+ sdp += 'a=group:BUNDLE ' + transceivers.map(function(t) {
+ return t.mid;
+ }).join(' ') + '\r\n';
+ }
+ sdp += 'a=ice-options:trickle\r\n';
+
+ transceivers.forEach(function(transceiver, sdpMLineIndex) {
+ sdp += SDPUtils.writeMediaSection(transceiver,
+ transceiver.localCapabilities, 'offer', transceiver.stream);
+ sdp += 'a=rtcp-rsize\r\n';
+ });
+
+ this._pendingOffer = transceivers;
+ var desc = new RTCSessionDescription({
+ type: 'offer',
+ sdp: sdp
+ });
+ if (arguments.length && typeof arguments[0] === 'function') {
+ window.setTimeout(arguments[0], 0, desc);
+ }
+ return Promise.resolve(desc);
+ };
+
+ RTCPeerConnection.prototype.createAnswer = function() {
+ var sdp = SDPUtils.writeSessionBoilerplate();
+ if (this.usingBundle) {
+ sdp += 'a=group:BUNDLE ' + this.transceivers.map(function(t) {
+ return t.mid;
+ }).join(' ') + '\r\n';
+ }
+ this.transceivers.forEach(function(transceiver, sdpMLineIndex) {
+ if (transceiver.isDatachannel) {
+ sdp += 'm=application 0 DTLS/SCTP 5000\r\n' +
+ 'c=IN IP4 0.0.0.0\r\n' +
+ 'a=mid:' + transceiver.mid + '\r\n';
+ return;
+ }
+
+ // FIXME: look at direction.
+ if (transceiver.stream) {
+ var localTrack;
+ if (transceiver.kind === 'audio') {
+ localTrack = transceiver.stream.getAudioTracks()[0];
+ } else if (transceiver.kind === 'video') {
+ localTrack = transceiver.stream.getVideoTracks()[0];
+ }
+ if (localTrack) {
+ // add RTX
+ if (edgeVersion >= 15019 && transceiver.kind === 'video') {
+ transceiver.sendEncodingParameters[0].rtx = {
+ ssrc: (2 * sdpMLineIndex + 2) * 1001 + 1
+ };
+ }
+ }
+ }
+
+ // Calculate intersection of capabilities.
+ var commonCapabilities = getCommonCapabilities(
+ transceiver.localCapabilities,
+ transceiver.remoteCapabilities);
+
+ var hasRtx = commonCapabilities.codecs.filter(function(c) {
+ return c.name.toLowerCase() === 'rtx';
+ }).length;
+ if (!hasRtx && transceiver.sendEncodingParameters[0].rtx) {
+ delete transceiver.sendEncodingParameters[0].rtx;
+ }
+
+ sdp += SDPUtils.writeMediaSection(transceiver, commonCapabilities,
+ 'answer', transceiver.stream);
+ if (transceiver.rtcpParameters &&
+ transceiver.rtcpParameters.reducedSize) {
+ sdp += 'a=rtcp-rsize\r\n';
+ }
+ });
+
+ var desc = new RTCSessionDescription({
+ type: 'answer',
+ sdp: sdp
+ });
+ if (arguments.length && typeof arguments[0] === 'function') {
+ window.setTimeout(arguments[0], 0, desc);
+ }
+ return Promise.resolve(desc);
+ };
+
+ RTCPeerConnection.prototype.addIceCandidate = function(candidate) {
+ if (!candidate) {
+ for (var j = 0; j < this.transceivers.length; j++) {
+ this.transceivers[j].iceTransport.addRemoteCandidate({});
+ if (this.usingBundle) {
+ return Promise.resolve();
+ }
+ }
+ } else {
+ var mLineIndex = candidate.sdpMLineIndex;
+ if (candidate.sdpMid) {
+ for (var i = 0; i < this.transceivers.length; i++) {
+ if (this.transceivers[i].mid === candidate.sdpMid) {
+ mLineIndex = i;
+ break;
+ }
+ }
+ }
+ var transceiver = this.transceivers[mLineIndex];
+ if (transceiver) {
+ var cand = Object.keys(candidate.candidate).length > 0 ?
+ SDPUtils.parseCandidate(candidate.candidate) : {};
+ // Ignore Chrome's invalid candidates since Edge does not like them.
+ if (cand.protocol === 'tcp' && (cand.port === 0 || cand.port === 9)) {
+ return Promise.resolve();
+ }
+ // Ignore RTCP candidates, we assume RTCP-MUX.
+ if (cand.component &&
+ !(cand.component === '1' || cand.component === 1)) {
+ return Promise.resolve();
+ }
+ transceiver.iceTransport.addRemoteCandidate(cand);
+
+ // update the remoteDescription.
+ var sections = SDPUtils.splitSections(this.remoteDescription.sdp);
+ sections[mLineIndex + 1] += (cand.type ? candidate.candidate.trim()
+ : 'a=end-of-candidates') + '\r\n';
+ this.remoteDescription.sdp = sections.join('');
+ }
+ }
+ if (arguments.length > 1 && typeof arguments[1] === 'function') {
+ window.setTimeout(arguments[1], 0);
+ }
+ return Promise.resolve();
+ };
+
+ RTCPeerConnection.prototype.getStats = function() {
+ var promises = [];
+ this.transceivers.forEach(function(transceiver) {
+ ['rtpSender', 'rtpReceiver', 'iceGatherer', 'iceTransport',
+ 'dtlsTransport'].forEach(function(method) {
+ if (transceiver[method]) {
+ promises.push(transceiver[method].getStats());
+ }
+ });
+ });
+ var cb = arguments.length > 1 && typeof arguments[1] === 'function' &&
+ arguments[1];
+ var fixStatsType = function(stat) {
+ return {
+ inboundrtp: 'inbound-rtp',
+ outboundrtp: 'outbound-rtp',
+ candidatepair: 'candidate-pair',
+ localcandidate: 'local-candidate',
+ remotecandidate: 'remote-candidate'
+ }[stat.type] || stat.type;
+ };
+ return new Promise(function(resolve) {
+ // shim getStats with maplike support
+ var results = new Map();
+ Promise.all(promises).then(function(res) {
+ res.forEach(function(result) {
+ Object.keys(result).forEach(function(id) {
+ result[id].type = fixStatsType(result[id]);
+ results.set(id, result[id]);
+ });
+ });
+ if (cb) {
+ window.setTimeout(cb, 0, results);
+ }
+ resolve(results);
+ });
+ });
+ };
+ return RTCPeerConnection;
+};
+
+
+/***/ }),
+/* 14 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+/*
+ * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree.
+ */
+ /* eslint-env node */
+
+
+var browserDetails = __webpack_require__(0).browserDetails;
+
+var firefoxShim = {
+ shimOnTrack: function() {
+ if (typeof window === 'object' && window.RTCPeerConnection && !('ontrack' in
+ window.RTCPeerConnection.prototype)) {
+ Object.defineProperty(window.RTCPeerConnection.prototype, 'ontrack', {
+ get: function() {
+ return this._ontrack;
+ },
+ set: function(f) {
+ if (this._ontrack) {
+ this.removeEventListener('track', this._ontrack);
+ this.removeEventListener('addstream', this._ontrackpoly);
+ }
+ this.addEventListener('track', this._ontrack = f);
+ this.addEventListener('addstream', this._ontrackpoly = function(e) {
+ e.stream.getTracks().forEach(function(track) {
+ var event = new Event('track');
+ event.track = track;
+ event.receiver = {track: track};
+ event.streams = [e.stream];
+ this.dispatchEvent(event);
+ }.bind(this));
+ }.bind(this));
+ }
+ });
+ }
+ },
+
+ shimSourceObject: function() {
+ // Firefox has supported mozSrcObject since FF22, unprefixed in 42.
+ if (typeof window === 'object') {
+ if (window.HTMLMediaElement &&
+ !('srcObject' in window.HTMLMediaElement.prototype)) {
+ // Shim the srcObject property, once, when HTMLMediaElement is found.
+ Object.defineProperty(window.HTMLMediaElement.prototype, 'srcObject', {
+ get: function() {
+ return this.mozSrcObject;
+ },
+ set: function(stream) {
+ this.mozSrcObject = stream;
+ }
+ });
+ }
+ }
+ },
+
+ shimPeerConnection: function() {
+ if (typeof window !== 'object' || !(window.RTCPeerConnection ||
+ window.mozRTCPeerConnection)) {
+ return; // probably media.peerconnection.enabled=false in about:config
+ }
+ // The RTCPeerConnection object.
+ if (!window.RTCPeerConnection) {
+ window.RTCPeerConnection = function(pcConfig, pcConstraints) {
+ if (browserDetails.version < 38) {
+ // .urls is not supported in FF < 38.
+ // create RTCIceServers with a single url.
+ if (pcConfig && pcConfig.iceServers) {
+ var newIceServers = [];
+ for (var i = 0; i < pcConfig.iceServers.length; i++) {
+ var server = pcConfig.iceServers[i];
+ if (server.hasOwnProperty('urls')) {
+ for (var j = 0; j < server.urls.length; j++) {
+ var newServer = {
+ url: server.urls[j]
+ };
+ if (server.urls[j].indexOf('turn') === 0) {
+ newServer.username = server.username;
+ newServer.credential = server.credential;
+ }
+ newIceServers.push(newServer);
+ }
+ } else {
+ newIceServers.push(pcConfig.iceServers[i]);
+ }
+ }
+ pcConfig.iceServers = newIceServers;
+ }
+ }
+ return new mozRTCPeerConnection(pcConfig, pcConstraints);
+ };
+ window.RTCPeerConnection.prototype = mozRTCPeerConnection.prototype;
+
+ // wrap static methods. Currently just generateCertificate.
+ if (mozRTCPeerConnection.generateCertificate) {
+ Object.defineProperty(window.RTCPeerConnection, 'generateCertificate', {
+ get: function() {
+ return mozRTCPeerConnection.generateCertificate;
+ }
+ });
+ }
+
+ window.RTCSessionDescription = mozRTCSessionDescription;
+ window.RTCIceCandidate = mozRTCIceCandidate;
+ }
+
+ // shim away need for obsolete RTCIceCandidate/RTCSessionDescription.
+ ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate']
+ .forEach(function(method) {
+ var nativeMethod = RTCPeerConnection.prototype[method];
+ RTCPeerConnection.prototype[method] = function() {
+ arguments[0] = new ((method === 'addIceCandidate') ?
+ RTCIceCandidate : RTCSessionDescription)(arguments[0]);
+ return nativeMethod.apply(this, arguments);
+ };
+ });
+
+ // support for addIceCandidate(null or undefined)
+ var nativeAddIceCandidate =
+ RTCPeerConnection.prototype.addIceCandidate;
+ RTCPeerConnection.prototype.addIceCandidate = function() {
+ if (!arguments[0]) {
+ if (arguments[1]) {
+ arguments[1].apply(null);
+ }
+ return Promise.resolve();
+ }
+ return nativeAddIceCandidate.apply(this, arguments);
+ };
+
+ // shim getStats with maplike support
+ var makeMapStats = function(stats) {
+ var map = new Map();
+ Object.keys(stats).forEach(function(key) {
+ map.set(key, stats[key]);
+ map[key] = stats[key];
+ });
+ return map;
+ };
+
+ var modernStatsTypes = {
+ inboundrtp: 'inbound-rtp',
+ outboundrtp: 'outbound-rtp',
+ candidatepair: 'candidate-pair',
+ localcandidate: 'local-candidate',
+ remotecandidate: 'remote-candidate'
+ };
+
+ var nativeGetStats = RTCPeerConnection.prototype.getStats;
+ RTCPeerConnection.prototype.getStats = function(selector, onSucc, onErr) {
+ return nativeGetStats.apply(this, [selector || null])
+ .then(function(stats) {
+ if (browserDetails.version < 48) {
+ stats = makeMapStats(stats);
+ }
+ if (browserDetails.version < 53 && !onSucc) {
+ // Shim only promise getStats with spec-hyphens in type names
+ // Leave callback version alone; misc old uses of forEach before Map
+ try {
+ stats.forEach(function(stat) {
+ stat.type = modernStatsTypes[stat.type] || stat.type;
+ });
+ } catch (e) {
+ if (e.name !== 'TypeError') {
+ throw e;
+ }
+ // Avoid TypeError: "type" is read-only, in old versions. 34-43ish
+ stats.forEach(function(stat, i) {
+ stats.set(i, Object.assign({}, stat, {
+ type: modernStatsTypes[stat.type] || stat.type
+ }));
+ });
+ }
+ }
+ return stats;
+ })
+ .then(onSucc, onErr);
+ };
+ }
+};
+
+// Expose public methods.
+module.exports = {
+ shimOnTrack: firefoxShim.shimOnTrack,
+ shimSourceObject: firefoxShim.shimSourceObject,
+ shimPeerConnection: firefoxShim.shimPeerConnection,
+ shimGetUserMedia: __webpack_require__(15)
+};
+
+
+/***/ }),
+/* 15 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+/*
+ * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree.
+ */
+ /* eslint-env node */
+
+
+var logging = __webpack_require__(0).log;
+var browserDetails = __webpack_require__(0).browserDetails;
+
+// Expose public methods.
+module.exports = function() {
+ var shimError_ = function(e) {
+ return {
+ name: {
+ InternalError: 'NotReadableError',
+ NotSupportedError: 'TypeError',
+ PermissionDeniedError: 'NotAllowedError',
+ SecurityError: 'NotAllowedError'
+ }[e.name] || e.name,
+ message: {
+ 'The operation is insecure.': 'The request is not allowed by the ' +
+ 'user agent or the platform in the current context.'
+ }[e.message] || e.message,
+ constraint: e.constraint,
+ toString: function() {
+ return this.name + (this.message && ': ') + this.message;
+ }
+ };
+ };
+
+ // getUserMedia constraints shim.
+ var getUserMedia_ = function(constraints, onSuccess, onError) {
+ var constraintsToFF37_ = function(c) {
+ if (typeof c !== 'object' || c.require) {
+ return c;
+ }
+ var require = [];
+ Object.keys(c).forEach(function(key) {
+ if (key === 'require' || key === 'advanced' || key === 'mediaSource') {
+ return;
+ }
+ var r = c[key] = (typeof c[key] === 'object') ?
+ c[key] : {ideal: c[key]};
+ if (r.min !== undefined ||
+ r.max !== undefined || r.exact !== undefined) {
+ require.push(key);
+ }
+ if (r.exact !== undefined) {
+ if (typeof r.exact === 'number') {
+ r. min = r.max = r.exact;
+ } else {
+ c[key] = r.exact;
+ }
+ delete r.exact;
+ }
+ if (r.ideal !== undefined) {
+ c.advanced = c.advanced || [];
+ var oc = {};
+ if (typeof r.ideal === 'number') {
+ oc[key] = {min: r.ideal, max: r.ideal};
+ } else {
+ oc[key] = r.ideal;
+ }
+ c.advanced.push(oc);
+ delete r.ideal;
+ if (!Object.keys(r).length) {
+ delete c[key];
+ }
+ }
+ });
+ if (require.length) {
+ c.require = require;
+ }
+ return c;
+ };
+ constraints = JSON.parse(JSON.stringify(constraints));
+ if (browserDetails.version < 38) {
+ logging('spec: ' + JSON.stringify(constraints));
+ if (constraints.audio) {
+ constraints.audio = constraintsToFF37_(constraints.audio);
+ }
+ if (constraints.video) {
+ constraints.video = constraintsToFF37_(constraints.video);
+ }
+ logging('ff37: ' + JSON.stringify(constraints));
+ }
+ return navigator.mozGetUserMedia(constraints, onSuccess, function(e) {
+ onError(shimError_(e));
+ });
+ };
+
+ // Returns the result of getUserMedia as a Promise.
+ var getUserMediaPromise_ = function(constraints) {
+ return new Promise(function(resolve, reject) {
+ getUserMedia_(constraints, resolve, reject);
+ });
+ };
+
+ // Shim for mediaDevices on older versions.
+ if (!navigator.mediaDevices) {
+ navigator.mediaDevices = {getUserMedia: getUserMediaPromise_,
+ addEventListener: function() { },
+ removeEventListener: function() { }
+ };
+ }
+ navigator.mediaDevices.enumerateDevices =
+ navigator.mediaDevices.enumerateDevices || function() {
+ return new Promise(function(resolve) {
+ var infos = [
+ {kind: 'audioinput', deviceId: 'default', label: '', groupId: ''},
+ {kind: 'videoinput', deviceId: 'default', label: '', groupId: ''}
+ ];
+ resolve(infos);
+ });
+ };
+
+ if (browserDetails.version < 41) {
+ // Work around http://bugzil.la/1169665
+ var orgEnumerateDevices =
+ navigator.mediaDevices.enumerateDevices.bind(navigator.mediaDevices);
+ navigator.mediaDevices.enumerateDevices = function() {
+ return orgEnumerateDevices().then(undefined, function(e) {
+ if (e.name === 'NotFoundError') {
+ return [];
+ }
+ throw e;
+ });
+ };
+ }
+ if (browserDetails.version < 49) {
+ var origGetUserMedia = navigator.mediaDevices.getUserMedia.
+ bind(navigator.mediaDevices);
+ navigator.mediaDevices.getUserMedia = function(c) {
+ return origGetUserMedia(c).then(function(stream) {
+ // Work around https://bugzil.la/802326
+ if (c.audio && !stream.getAudioTracks().length ||
+ c.video && !stream.getVideoTracks().length) {
+ stream.getTracks().forEach(function(track) {
+ track.stop();
+ });
+ throw new DOMException('The object can not be found here.',
+ 'NotFoundError');
+ }
+ return stream;
+ }, function(e) {
+ return Promise.reject(shimError_(e));
+ });
+ };
+ }
+ navigator.getUserMedia = function(constraints, onSuccess, onError) {
+ if (browserDetails.version < 44) {
+ return getUserMedia_(constraints, onSuccess, onError);
+ }
+ // Replace Firefox 44+'s deprecation warning with unprefixed version.
+ console.warn('navigator.getUserMedia has been replaced by ' +
+ 'navigator.mediaDevices.getUserMedia');
+ navigator.mediaDevices.getUserMedia(constraints).then(onSuccess, onError);
+ };
+};
+
+
+/***/ }),
+/* 16 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+/*
+ * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree.
+ */
+
+var safariShim = {
+ // TODO: DrAlex, should be here, double check against LayoutTests
+
+ // TODO: once the back-end for the mac port is done, add.
+ // TODO: check for webkitGTK+
+ // shimPeerConnection: function() { },
+
+ shimAddStream: function() {
+ if (typeof window === 'object' && window.RTCPeerConnection &&
+ !('addStream' in window.RTCPeerConnection.prototype)) {
+ RTCPeerConnection.prototype.addStream = function(stream) {
+ var self = this;
+ stream.getTracks().forEach(function(track) {
+ self.addTrack(track, stream);
+ });
+ };
+ }
+ },
+ shimOnAddStream: function() {
+ if (typeof window === 'object' && window.RTCPeerConnection &&
+ !('onaddstream' in window.RTCPeerConnection.prototype)) {
+ Object.defineProperty(window.RTCPeerConnection.prototype, 'onaddstream', {
+ get: function() {
+ return this._onaddstream;
+ },
+ set: function(f) {
+ if (this._onaddstream) {
+ this.removeEventListener('addstream', this._onaddstream);
+ this.removeEventListener('track', this._onaddstreampoly);
+ }
+ this.addEventListener('addstream', this._onaddstream = f);
+ this.addEventListener('track', this._onaddstreampoly = function(e) {
+ var stream = e.streams[0];
+ if (!this._streams) {
+ this._streams = [];
+ }
+ if (this._streams.indexOf(stream) >= 0) {
+ return;
+ }
+ this._streams.push(stream);
+ var event = new Event('addstream');
+ event.stream = e.streams[0];
+ this.dispatchEvent(event);
+ }.bind(this));
+ }
+ });
+ }
+ },
+ shimCallbacksAPI: function() {
+ if (typeof window !== 'object' || !window.RTCPeerConnection) {
+ return;
+ }
+ var prototype = RTCPeerConnection.prototype;
+ var createOffer = prototype.createOffer;
+ var createAnswer = prototype.createAnswer;
+ var setLocalDescription = prototype.setLocalDescription;
+ var setRemoteDescription = prototype.setRemoteDescription;
+ var addIceCandidate = prototype.addIceCandidate;
+
+ prototype.createOffer = function(successCallback, failureCallback) {
+ var options = (arguments.length >= 2) ? arguments[2] : arguments[0];
+ var promise = createOffer.apply(this, [options]);
+ if (!failureCallback) {
+ return promise;
+ }
+ promise.then(successCallback, failureCallback);
+ return Promise.resolve();
+ };
+
+ prototype.createAnswer = function(successCallback, failureCallback) {
+ var options = (arguments.length >= 2) ? arguments[2] : arguments[0];
+ var promise = createAnswer.apply(this, [options]);
+ if (!failureCallback) {
+ return promise;
+ }
+ promise.then(successCallback, failureCallback);
+ return Promise.resolve();
+ };
+
+ var withCallback = function(description, successCallback, failureCallback) {
+ var promise = setLocalDescription.apply(this, [description]);
+ if (!failureCallback) {
+ return promise;
+ }
+ promise.then(successCallback, failureCallback);
+ return Promise.resolve();
+ };
+ prototype.setLocalDescription = withCallback;
+
+ withCallback = function(description, successCallback, failureCallback) {
+ var promise = setRemoteDescription.apply(this, [description]);
+ if (!failureCallback) {
+ return promise;
+ }
+ promise.then(successCallback, failureCallback);
+ return Promise.resolve();
+ };
+ prototype.setRemoteDescription = withCallback;
+
+ withCallback = function(candidate, successCallback, failureCallback) {
+ var promise = addIceCandidate.apply(this, [candidate]);
+ if (!failureCallback) {
+ return promise;
+ }
+ promise.then(successCallback, failureCallback);
+ return Promise.resolve();
+ };
+ prototype.addIceCandidate = withCallback;
+ },
+ shimGetUserMedia: function() {
+ if (!navigator.getUserMedia) {
+ if (navigator.webkitGetUserMedia) {
+ navigator.getUserMedia = navigator.webkitGetUserMedia.bind(navigator);
+ } else if (navigator.mediaDevices &&
+ navigator.mediaDevices.getUserMedia) {
+ navigator.getUserMedia = function(constraints, cb, errcb) {
+ navigator.mediaDevices.getUserMedia(constraints)
+ .then(cb, errcb);
+ }.bind(navigator);
+ }
+ }
+ }
+};
+
+// Expose public methods.
+module.exports = {
+ shimCallbacksAPI: safariShim.shimCallbacksAPI,
+ shimAddStream: safariShim.shimAddStream,
+ shimOnAddStream: safariShim.shimOnAddStream,
+ shimGetUserMedia: safariShim.shimGetUserMedia
+ // TODO
+ // shimPeerConnection: safariShim.shimPeerConnection
+};
+
+
+/***/ }),
+/* 17 */
+/***/ (function(module, exports, __webpack_require__) {
+
+var cordovaRequire = __webpack_require__(5);
+var cordovaModule = __webpack_require__(1);
+
+var createQRScannerInternal = __webpack_require__(2);
+
+cordovaModule.exports = createQRScannerInternal();
+cordovaRequire('cordova/exec/proxy').add('QRScanner', cordovaModule.exports);
+
+
+/***/ })
+/******/ ]);
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-qrscanner/www/www.min.js b/platforms/browser/platform_www/plugins/cordova-plugin-qrscanner/www/www.min.js
new file mode 100644
index 0000000..5d95c0a
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-qrscanner/www/www.min.js
@@ -0,0 +1,343 @@
+cordova.define("cordova-plugin-qrscanner.QRScanner", function(require, exports, module) { // This file is generated by `npm run build`.
+
+/*global exports:false*/
+/*jshint unused:false */
+// remap parameter names from cordova.define
+// see `externals` in webpack.cordova.config.js
+var cordovaRequire = require;
+var cordovaExports = exports;
+var cordovaModule = module;
+/******/ (function(modules) { // webpackBootstrap
+/******/ // The module cache
+/******/ var installedModules = {};
+/******/
+/******/ // The require function
+/******/ function __webpack_require__(moduleId) {
+/******/
+/******/ // Check if module is in cache
+/******/ if(installedModules[moduleId]) {
+/******/ return installedModules[moduleId].exports;
+/******/ }
+/******/ // Create a new module (and put it into the cache)
+/******/ var module = installedModules[moduleId] = {
+/******/ i: moduleId,
+/******/ l: false,
+/******/ exports: {}
+/******/ };
+/******/
+/******/ // Execute the module function
+/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/
+/******/ // Flag the module as loaded
+/******/ module.l = true;
+/******/
+/******/ // Return the exports of the module
+/******/ return module.exports;
+/******/ }
+/******/
+/******/
+/******/ // expose the modules object (__webpack_modules__)
+/******/ __webpack_require__.m = modules;
+/******/
+/******/ // expose the module cache
+/******/ __webpack_require__.c = installedModules;
+/******/
+/******/ // identity function for calling harmony imports with the correct context
+/******/ __webpack_require__.i = function(value) { return value; };
+/******/
+/******/ // define getter function for harmony exports
+/******/ __webpack_require__.d = function(exports, name, getter) {
+/******/ if(!__webpack_require__.o(exports, name)) {
+/******/ Object.defineProperty(exports, name, {
+/******/ configurable: false,
+/******/ enumerable: true,
+/******/ get: getter
+/******/ });
+/******/ }
+/******/ };
+/******/
+/******/ // getDefaultExport function for compatibility with non-harmony modules
+/******/ __webpack_require__.n = function(module) {
+/******/ var getter = module && module.__esModule ?
+/******/ function getDefault() { return module['default']; } :
+/******/ function getModuleExports() { return module; };
+/******/ __webpack_require__.d(getter, 'a', getter);
+/******/ return getter;
+/******/ };
+/******/
+/******/ // Object.prototype.hasOwnProperty.call
+/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
+/******/
+/******/ // __webpack_public_path__
+/******/ __webpack_require__.p = "";
+/******/
+/******/ // Load entry module and return exports
+/******/ return __webpack_require__(__webpack_require__.s = 18);
+/******/ })
+/************************************************************************/
+/******/ ({
+
+/***/ 1:
+/***/ (function(module, exports) {
+
+module.exports = cordovaModule;
+
+/***/ }),
+
+/***/ 18:
+/***/ (function(module, exports, __webpack_require__) {
+
+var globalCordova = __webpack_require__(4);
+var cordovaModule = __webpack_require__(1);
+
+var createQRScannerAdapter = __webpack_require__(3);
+
+// pass in global cordova object to expose cordova.exec
+var QRScannerAdapter = createQRScannerAdapter(globalCordova);
+cordovaModule.exports = QRScannerAdapter;
+
+
+/***/ }),
+
+/***/ 3:
+/***/ (function(module, exports) {
+
+module.exports = function createQRScanner(cordova){
+// The native implementations should return their status as ['string':'string']
+// dictionaries. Boolean values are encoded to '0' and '1', respectively.
+function stringToBool(string) {
+ switch (string) {
+ case '1':
+ return true;
+ case '0':
+ return false;
+ default:
+ throw new Error('QRScanner plugin returned an invalid boolean number-string: ' + string);
+ }
+}
+
+// Converts the returned ['string':'string'] dictionary to a status object.
+function convertStatus(statusDictionary) {
+ return {
+ authorized: stringToBool(statusDictionary.authorized),
+ denied: stringToBool(statusDictionary.denied),
+ restricted: stringToBool(statusDictionary.restricted),
+ prepared: stringToBool(statusDictionary.prepared),
+ scanning: stringToBool(statusDictionary.scanning),
+ previewing: stringToBool(statusDictionary.previewing),
+ showing: stringToBool(statusDictionary.showing),
+ lightEnabled: stringToBool(statusDictionary.lightEnabled),
+ canOpenSettings: stringToBool(statusDictionary.canOpenSettings),
+ canEnableLight: stringToBool(statusDictionary.canEnableLight),
+ canChangeCamera: stringToBool(statusDictionary.canChangeCamera),
+ currentCamera: parseInt(statusDictionary.currentCamera)
+ };
+}
+
+// Simple utility method to ensure the background is transparent. Used by the
+// plugin to force re-rendering immediately after the native webview background
+// is made transparent.
+function clearBackground() {
+ var body = document.body;
+ if (body.style) {
+ body.style.backgroundColor = 'rgba(0,0,0,0.01)';
+ body.style.backgroundImage = '';
+ setTimeout(function() {
+ body.style.backgroundColor = 'transparent';
+ }, 1);
+ if (body.parentNode && body.parentNode.style) {
+ body.parentNode.style.backgroundColor = 'transparent';
+ body.parentNode.style.backgroundImage = '';
+ }
+ }
+}
+
+function errorCallback(callback) {
+ if (!callback) {
+ return null;
+ }
+ return function(error) {
+ var errorCode = parseInt(error);
+ var QRScannerError = {};
+ switch (errorCode) {
+ case 0:
+ QRScannerError = {
+ name: 'UNEXPECTED_ERROR',
+ code: 0,
+ _message: 'QRScanner experienced an unexpected error.'
+ };
+ break;
+ case 1:
+ QRScannerError = {
+ name: 'CAMERA_ACCESS_DENIED',
+ code: 1,
+ _message: 'The user denied camera access.'
+ };
+ break;
+ case 2:
+ QRScannerError = {
+ name: 'CAMERA_ACCESS_RESTRICTED',
+ code: 2,
+ _message: 'Camera access is restricted.'
+ };
+ break;
+ case 3:
+ QRScannerError = {
+ name: 'BACK_CAMERA_UNAVAILABLE',
+ code: 3,
+ _message: 'The back camera is unavailable.'
+ };
+ break;
+ case 4:
+ QRScannerError = {
+ name: 'FRONT_CAMERA_UNAVAILABLE',
+ code: 4,
+ _message: 'The front camera is unavailable.'
+ };
+ break;
+ case 5:
+ QRScannerError = {
+ name: 'CAMERA_UNAVAILABLE',
+ code: 5,
+ _message: 'The camera is unavailable.'
+ };
+ break;
+ case 6:
+ QRScannerError = {
+ name: 'SCAN_CANCELED',
+ code: 6,
+ _message: 'Scan was canceled.'
+ };
+ break;
+ case 7:
+ QRScannerError = {
+ name: 'LIGHT_UNAVAILABLE',
+ code: 7,
+ _message: 'The device light is unavailable.'
+ };
+ break;
+ case 8:
+ // Open settings is only available on iOS 8.0+.
+ QRScannerError = {
+ name: 'OPEN_SETTINGS_UNAVAILABLE',
+ code: 8,
+ _message: 'The device is unable to open settings.'
+ };
+ break;
+ default:
+ QRScannerError = {
+ name: 'UNEXPECTED_ERROR',
+ code: 0,
+ _message: 'QRScanner returned an invalid error code.'
+ };
+ break;
+ }
+ callback(QRScannerError);
+ };
+}
+
+function successCallback(callback) {
+ if (!callback) {
+ return null;
+ }
+ return function(statusDict) {
+ callback(null, convertStatus(statusDict));
+ };
+}
+
+function doneCallback(callback, clear) {
+ if (!callback) {
+ return null;
+ }
+ return function(statusDict) {
+ if (clear) {
+ clearBackground();
+ }
+ callback(convertStatus(statusDict));
+ };
+}
+
+return {
+ prepare: function(callback) {
+ cordova.exec(successCallback(callback), errorCallback(callback), 'QRScanner', 'prepare', []);
+ },
+ destroy: function(callback) {
+ cordova.exec(doneCallback(callback, true), null, 'QRScanner', 'destroy', []);
+ },
+ scan: function(callback) {
+ if (!callback) {
+ throw new Error('No callback provided to scan method.');
+ }
+ var success = function(result) {
+ callback(null, result);
+ };
+ cordova.exec(success, errorCallback(callback), 'QRScanner', 'scan', []);
+ },
+ cancelScan: function(callback) {
+ cordova.exec(doneCallback(callback), null, 'QRScanner', 'cancelScan', []);
+ },
+ show: function(callback) {
+ cordova.exec(doneCallback(callback, true), null, 'QRScanner', 'show', []);
+ },
+ hide: function(callback) {
+ cordova.exec(doneCallback(callback, true), null, 'QRScanner', 'hide', []);
+ },
+ pausePreview: function(callback) {
+ cordova.exec(doneCallback(callback), null, 'QRScanner', 'pausePreview', []);
+ },
+ resumePreview: function(callback) {
+ cordova.exec(doneCallback(callback), null, 'QRScanner', 'resumePreview', []);
+ },
+ enableLight: function(callback) {
+ cordova.exec(successCallback(callback), errorCallback(callback), 'QRScanner', 'enableLight', []);
+ },
+ disableLight: function(callback) {
+ cordova.exec(successCallback(callback), errorCallback(callback), 'QRScanner', 'disableLight', []);
+ },
+ useCamera: function(index, callback) {
+ cordova.exec(successCallback(callback), errorCallback(callback), 'QRScanner', 'useCamera', [index]);
+ },
+ useFrontCamera: function(callback) {
+ var frontCamera = 1;
+ if (callback) {
+ this.useCamera(frontCamera, callback);
+ } else {
+ cordova.exec(null, null, 'QRScanner', 'useCamera', [frontCamera]);
+ }
+ },
+ useBackCamera: function(callback) {
+ var backCamera = 0;
+ if (callback) {
+ this.useCamera(backCamera, callback);
+ } else {
+ cordova.exec(null, null, 'QRScanner', 'useCamera', [backCamera]);
+ }
+ },
+ openSettings: function(callback) {
+ if (callback) {
+ cordova.exec(successCallback(callback), errorCallback(callback), 'QRScanner', 'openSettings', []);
+ } else {
+ cordova.exec(null, null, 'QRScanner', 'openSettings', []);
+ }
+ },
+ getStatus: function(callback) {
+ if (!callback) {
+ throw new Error('No callback provided to getStatus method.');
+ }
+ cordova.exec(doneCallback(callback), null, 'QRScanner', 'getStatus', []);
+ }
+};
+};
+
+
+/***/ }),
+
+/***/ 4:
+/***/ (function(module, exports) {
+
+module.exports = cordova;
+
+/***/ })
+
+/******/ });
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-splashscreen/src/browser/SplashScreenProxy.js b/platforms/browser/platform_www/plugins/cordova-plugin-splashscreen/src/browser/SplashScreenProxy.js
new file mode 100644
index 0000000..6f04cf5
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-splashscreen/src/browser/SplashScreenProxy.js
@@ -0,0 +1,172 @@
+cordova.define("cordova-plugin-splashscreen.SplashScreenProxy", function(require, exports, module) { /*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+// Default parameter values including image size can be changed in `config.xml`
+var splashImageWidth = 170;
+var splashImageHeight = 200;
+var position = { x: 0, y: 0, width: splashImageWidth, height: splashImageHeight };
+var localSplash; // the image to display
+var localSplashImage;
+var bgColor = "#464646";
+var imageSrc = '/img/logo.png';
+var splashScreenDelay = 3000; // in milliseconds
+var showSplashScreen = true; // show splashcreen by default
+var cordova = require('cordova');
+var configHelper = cordova.require('cordova/confighelper');
+var autoHideSplashScreen = true;
+
+function updateImageLocation() {
+ position.width = Math.min(splashImageWidth, window.innerWidth);
+ position.height = position.width * (splashImageHeight / splashImageWidth);
+
+ localSplash.style.width = window.innerWidth + "px";
+ localSplash.style.height = window.innerHeight + "px";
+ localSplash.style.top = "0px";
+ localSplash.style.left = "0px";
+
+ localSplashImage.style.top = "50%";
+ localSplashImage.style.left = "50%";
+ localSplashImage.style.height = position.height + "px";
+ localSplashImage.style.width = position.width + "px";
+ localSplashImage.style.marginTop = (-position.height / 2) + "px";
+ localSplashImage.style.marginLeft = (-position.width / 2) + "px";
+}
+
+function onResize() {
+ updateImageLocation();
+}
+
+var SplashScreen = {
+ setBGColor: function (cssBGColor) {
+ bgColor = cssBGColor;
+ if (localSplash) {
+ localSplash.style.backgroundColor = bgColor;
+ }
+ },
+ show: function () {
+ if(!localSplash) {
+ window.addEventListener("resize", onResize, false);
+ localSplash = document.createElement("div");
+ localSplash.style.backgroundColor = bgColor;
+ localSplash.style.position = "absolute";
+ localSplash.style["z-index"] = "99999";
+
+ localSplashImage = document.createElement("img");
+ localSplashImage.src = imageSrc;
+ localSplashImage.style.position = "absolute";
+
+ updateImageLocation();
+
+ localSplash.appendChild(localSplashImage);
+ document.body.appendChild(localSplash);
+
+ // deviceready fires earlier than the plugin init on cold-start
+ if (SplashScreen.shouldHideImmediately) {
+ SplashScreen.shouldHideImmediately = false;
+ window.setTimeout(function () {
+ SplashScreen.hide();
+ }, 1000);
+ }
+ }
+ },
+ hide: function () {
+ if(localSplash) {
+ var innerLocalSplash = localSplash;
+ localSplash = null;
+ window.removeEventListener("resize", onResize, false);
+
+ innerLocalSplash.style.opacity = '0';
+ innerLocalSplash.style["-webkit-transition"] = "opacity 1s ease-in-out";
+ innerLocalSplash.style["-moz-transition"] = "opacity 1s ease-in-out";
+ innerLocalSplash.style["-ms-transition"] = "opacity 1s ease-in-out";
+ innerLocalSplash.style["-o-transition"] = "opacity 1s ease-in-out";
+
+ window.setTimeout(function () {
+ document.body.removeChild(innerLocalSplash);
+ innerLocalSplash = null;
+ }, 1000);
+ } else {
+ SplashScreen.shouldHideImmediately = true;
+ }
+ }
+};
+
+/**
+ * Reads preferences via ConfigHelper and substitutes default parameters.
+ */
+function readPreferencesFromCfg(cfg) {
+ try {
+ var value = cfg.getPreferenceValue('ShowSplashScreen');
+ if(typeof value != 'undefined') {
+ showSplashScreen = value === 'true';
+ }
+
+ splashScreenDelay = cfg.getPreferenceValue('SplashScreenDelay') || splashScreenDelay;
+ splashScreenDelay = parseInt(splashScreenDelay, 10);
+
+ imageSrc = cfg.getPreferenceValue('SplashScreen') || imageSrc;
+ bgColor = cfg.getPreferenceValue('SplashScreenBackgroundColor') || bgColor;
+ splashImageWidth = cfg.getPreferenceValue('SplashScreenWidth') || splashImageWidth;
+ splashImageHeight = cfg.getPreferenceValue('SplashScreenHeight') || splashImageHeight;
+ autoHideSplashScreen = cfg.getPreferenceValue('AutoHideSplashScreen') || autoHideSplashScreen;
+ autoHideSplashScreen = (autoHideSplashScreen === true || autoHideSplashScreen.toLowerCase() === 'true');
+ } catch(e) {
+ var msg = '[Browser][SplashScreen] Error occurred on loading preferences from config.xml: ' + JSON.stringify(e);
+ console.error(msg);
+ }
+}
+
+/**
+ * Shows and hides splashscreen if it is enabled, with a delay according the current preferences.
+ */
+function showAndHide() {
+ if(showSplashScreen) {
+ SplashScreen.show();
+
+ window.setTimeout(function() {
+ SplashScreen.hide();
+ }, splashScreenDelay);
+ }
+}
+
+/**
+ * Tries to read config.xml and override default properties and then shows and hides splashscreen if it is enabled.
+ */
+(function initAndShow() {
+ configHelper.readConfig(function(config) {
+ readPreferencesFromCfg(config);
+ if (autoHideSplashScreen) {
+ showAndHide();
+ } else {
+ SplashScreen.show();
+ }
+
+ }, function(err) {
+ console.error(err);
+ });
+})();
+
+module.exports = SplashScreen;
+
+require("cordova/exec/proxy").add("SplashScreen", SplashScreen);
+
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-splashscreen/www/splashscreen.js b/platforms/browser/platform_www/plugins/cordova-plugin-splashscreen/www/splashscreen.js
new file mode 100644
index 0000000..5b42e17
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-splashscreen/www/splashscreen.js
@@ -0,0 +1,35 @@
+cordova.define("cordova-plugin-splashscreen.SplashScreen", function(require, exports, module) { /*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+var exec = require('cordova/exec');
+
+var splashscreen = {
+ show:function() {
+ exec(null, null, "SplashScreen", "show", []);
+ },
+ hide:function() {
+ exec(null, null, "SplashScreen", "hide", []);
+ }
+};
+
+module.exports = splashscreen;
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-statusbar/src/browser/StatusBarProxy.js b/platforms/browser/platform_www/plugins/cordova-plugin-statusbar/src/browser/StatusBarProxy.js
new file mode 100644
index 0000000..e6e41ec
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-statusbar/src/browser/StatusBarProxy.js
@@ -0,0 +1,52 @@
+cordova.define("cordova-plugin-statusbar.StatusBarProxy", function(require, exports, module) { /*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+function notSupported(win,fail) {
+ //
+ console.log('StatusBar is not supported');
+ setTimeout(function(){
+ if (win) {
+ win();
+ }
+ // note that while it is not explicitly supported, it does not fail
+ // this is really just here to allow developers to test their code in the browser
+ // and if we fail, then their app might as well. -jm
+ },0);
+}
+
+module.exports = {
+ isVisible: false,
+ styleBlackTranslucent:notSupported,
+ styleDefault:notSupported,
+ styleLightContent:notSupported,
+ styleBlackOpaque:notSupported,
+ overlaysWebView:notSupported,
+ styleLightContect: notSupported,
+ backgroundColorByName: notSupported,
+ backgroundColorByHexString: notSupported,
+ hide: notSupported,
+ show: notSupported,
+ _ready:notSupported
+};
+
+require("cordova/exec/proxy").add("StatusBar", module.exports);
+
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-statusbar/www/statusbar.js b/platforms/browser/platform_www/plugins/cordova-plugin-statusbar/www/statusbar.js
new file mode 100644
index 0000000..9684d23
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-statusbar/www/statusbar.js
@@ -0,0 +1,115 @@
+cordova.define("cordova-plugin-statusbar.statusbar", function(require, exports, module) { /*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+/* global cordova */
+
+var exec = require('cordova/exec');
+
+var namedColors = {
+ "black": "#000000",
+ "darkGray": "#A9A9A9",
+ "lightGray": "#D3D3D3",
+ "white": "#FFFFFF",
+ "gray": "#808080",
+ "red": "#FF0000",
+ "green": "#00FF00",
+ "blue": "#0000FF",
+ "cyan": "#00FFFF",
+ "yellow": "#FFFF00",
+ "magenta": "#FF00FF",
+ "orange": "#FFA500",
+ "purple": "#800080",
+ "brown": "#A52A2A"
+};
+
+var StatusBar = {
+
+ isVisible: true,
+
+ overlaysWebView: function (doOverlay) {
+ exec(null, null, "StatusBar", "overlaysWebView", [doOverlay]);
+ },
+
+ styleDefault: function () {
+ // dark text ( to be used on a light background )
+ exec(null, null, "StatusBar", "styleDefault", []);
+ },
+
+ styleLightContent: function () {
+ // light text ( to be used on a dark background )
+ exec(null, null, "StatusBar", "styleLightContent", []);
+ },
+
+ styleBlackTranslucent: function () {
+ // #88000000 ? Apple says to use lightContent instead
+ exec(null, null, "StatusBar", "styleBlackTranslucent", []);
+ },
+
+ styleBlackOpaque: function () {
+ // #FF000000 ? Apple says to use lightContent instead
+ exec(null, null, "StatusBar", "styleBlackOpaque", []);
+ },
+
+ backgroundColorByName: function (colorname) {
+ return StatusBar.backgroundColorByHexString(namedColors[colorname]);
+ },
+
+ backgroundColorByHexString: function (hexString) {
+ if (hexString.charAt(0) !== "#") {
+ hexString = "#" + hexString;
+ }
+
+ if (hexString.length === 4) {
+ var split = hexString.split("");
+ hexString = "#" + split[1] + split[1] + split[2] + split[2] + split[3] + split[3];
+ }
+
+ exec(null, null, "StatusBar", "backgroundColorByHexString", [hexString]);
+ },
+
+ hide: function () {
+ exec(null, null, "StatusBar", "hide", []);
+ StatusBar.isVisible = false;
+ },
+
+ show: function () {
+ exec(null, null, "StatusBar", "show", []);
+ StatusBar.isVisible = true;
+ }
+
+};
+
+// prime it. setTimeout so that proxy gets time to init
+window.setTimeout(function () {
+ exec(function (res) {
+ if (typeof res == 'object') {
+ if (res.type == 'tap') {
+ cordova.fireWindowEvent('statusTap');
+ }
+ } else {
+ StatusBar.isVisible = res;
+ }
+ }, null, "StatusBar", "_ready", []);
+}, 0);
+
+module.exports = StatusBar;
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-touch-id/www/TouchID.js b/platforms/browser/platform_www/plugins/cordova-plugin-touch-id/www/TouchID.js
new file mode 100644
index 0000000..6e4b765
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-touch-id/www/TouchID.js
@@ -0,0 +1,35 @@
+cordova.define("cordova-plugin-touch-id.TouchID", function(require, exports, module) { function TouchID() {
+}
+
+TouchID.prototype.isAvailable = function (successCallback, errorCallback) {
+ cordova.exec(successCallback, errorCallback, "TouchID", "isAvailable", []);
+};
+
+TouchID.prototype.didFingerprintDatabaseChange = function (successCallback, errorCallback) {
+ cordova.exec(successCallback, errorCallback, "TouchID", "didFingerprintDatabaseChange", []);
+};
+
+TouchID.prototype.verifyFingerprint = function (message, successCallback, errorCallback) {
+ cordova.exec(successCallback, errorCallback, "TouchID", "verifyFingerprint", [message]);
+};
+
+TouchID.prototype.verifyFingerprintWithCustomPasswordFallback = function (message, successCallback, errorCallback) {
+ cordova.exec(successCallback, errorCallback, "TouchID", "verifyFingerprintWithCustomPasswordFallback", [message]);
+};
+
+TouchID.prototype.verifyFingerprintWithCustomPasswordFallbackAndEnterPasswordLabel = function (message, enterPasswordLabel, successCallback, errorCallback) {
+ cordova.exec(successCallback, errorCallback, "TouchID", "verifyFingerprintWithCustomPasswordFallbackAndEnterPasswordLabel", [message, enterPasswordLabel]);
+};
+
+TouchID.install = function () {
+ if (!window.plugins) {
+ window.plugins = {};
+ }
+
+ window.plugins.touchid = new TouchID();
+ return window.plugins.touchid;
+};
+
+cordova.addConstructor(TouchID.install);
+
+});