You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by an...@apache.org on 2015/10/06 11:27:05 UTC

[6/6] cordova-lib git commit: Pick ConfigParser changes from apache@0c3614e

Pick ConfigParser changes from apache@0c3614e


Project: http://git-wip-us.apache.org/repos/asf/cordova-lib/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-lib/commit/ff0fd6e2
Tree: http://git-wip-us.apache.org/repos/asf/cordova-lib/tree/ff0fd6e2
Diff: http://git-wip-us.apache.org/repos/asf/cordova-lib/diff/ff0fd6e2

Branch: refs/heads/master
Commit: ff0fd6e2e54a11531be580c392c9669a0df7219d
Parents: d3821be
Author: Vladimir Kotikov <v-...@microsoft.com>
Authored: Tue Oct 6 12:02:11 2015 +0300
Committer: Vladimir Kotikov <v-...@microsoft.com>
Committed: Tue Oct 6 12:20:13 2015 +0300

----------------------------------------------------------------------
 .../spec/ConfigParser/ConfigParser.spec.js      |   8 +
 cordova-common/spec/fixtures/test-config.xml    |  65 +++
 cordova-common/src/ConfigParser/ConfigParser.js |  26 +
 cordova-lib/spec-cordova/ConfigParser.spec.js   | 232 ---------
 cordova-lib/src/configparser/ConfigParser.js    | 499 -------------------
 5 files changed, 99 insertions(+), 731 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/ff0fd6e2/cordova-common/spec/ConfigParser/ConfigParser.spec.js
----------------------------------------------------------------------
diff --git a/cordova-common/spec/ConfigParser/ConfigParser.spec.js b/cordova-common/spec/ConfigParser/ConfigParser.spec.js
index 9d4696d..f4eace7 100644
--- a/cordova-common/spec/ConfigParser/ConfigParser.spec.js
+++ b/cordova-common/spec/ConfigParser/ConfigParser.spec.js
@@ -219,6 +219,14 @@ describe('config.xml parser', function () {
                 });
                 expect(pluginNames).not.toContain('org.apache.cordova.legacyplugin');
             });
+            it('it should read <access> tag entries', function(){
+                var accesses = cfg.getAccesses();
+                expect(accesses.length).not.toEqual(0);
+            });
+            it('it should read <allow-navigation> tag entries', function(){
+                var navigations = cfg.getAllowNavigations();
+                expect(navigations.length).not.toEqual(0);
+            });
         });
     });
 });

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/ff0fd6e2/cordova-common/spec/fixtures/test-config.xml
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/test-config.xml b/cordova-common/spec/fixtures/test-config.xml
index ac22580..2f14f32 100644
--- a/cordova-common/spec/fixtures/test-config.xml
+++ b/cordova-common/spec/fixtures/test-config.xml
@@ -9,6 +9,71 @@
     </author>
     <content src="index.html" />
     <access origin="*" />
+
+    <!--
+        <access> tests
+
+        Test wildcard allow all. Note in ATS you can open up all, and have restrictions for certain domains.
+        This is to allow for example, an in-app-browser (*) but your own server communications must be https, for example.
+     -->
+    <access origin="*" />
+    <!-- https, with subdomain wildcard, with attribute differences -->
+    <access origin="https://*.server01.com" /> <!-- equivalent to the next line -->
+    <access origin="https://*.server01.com" minimum-tls-version="TLSv1.2" requires-forward-secrecy="true" />
+    <access origin="https://*.server02.com" minimum-tls-version="TLSv1.2" requires-forward-secrecy="false" />
+    <access origin="https://*.server03.com" minimum-tls-version="TLSv1.1" requires-forward-secrecy="true" />
+    <access origin="https://*.server04.com" minimum-tls-version="TLSv1.1" requires-forward-secrecy="false" />
+    <!-- http, no subdomain wildcard, with attribute differences -->
+    <access origin="http://server05.com" /> <!-- equivalent to the next line -->
+    <access origin="http://server05.com" minimum-tls-version="TLSv1.2" requires-forward-secrecy="true" />
+    <access origin="http://server06.com" minimum-tls-version="TLSv1.2" requires-forward-secrecy="false" />
+    <access origin="http://server07.com" minimum-tls-version="TLSv1.1" requires-forward-secrecy="true" />
+    <access origin="http://server08.com" minimum-tls-version="TLSv1.1" requires-forward-secrecy="false" />
+    <!-- https, no subdomain wildcard, with attribute differences -->
+    <access origin="https://server09.com" /> <!-- equivalent to the next line -->
+    <access origin="https://server09.com" minimum-tls-version="TLSv1.2" requires-forward-secrecy="true" />
+    <access origin="https://server10.com" minimum-tls-version="TLSv1.2" requires-forward-secrecy="false" />
+    <access origin="https://server11.com" minimum-tls-version="TLSv1.1" requires-forward-secrecy="true" />
+    <access origin="https://server12.com" minimum-tls-version="TLSv1.1" requires-forward-secrecy="false" />
+
+    <!--
+        <allow-navigation> tests
+
+        Test wildcard allow all. Note in ATS you can open up all, and have restrictions for certain domains.
+        This is to allow for example, an in-app-browser (*) but your own server communications must be https, for example.
+     -->
+    <allow-navigation href="*" />
+    <!-- https, with subdomain wildcard, attribute differences -->
+    <allow-navigation href="https://*.server21.com" /> <!-- equivalent to the next line -->
+    <allow-navigation href="https://*.server21.com" minimum-tls-version="TLSv1.2" requires-forward-secrecy="true" />
+    <allow-navigation href="https://*.server22.com" minimum-tls-version="TLSv1.2" requires-forward-secrecy="false" />
+    <allow-navigation href="https://*.server23.com" minimum-tls-version="TLSv1.1" requires-forward-secrecy="true" />
+    <allow-navigation href="https://*.server24.com" minimum-tls-version="TLSv1.1" requires-forward-secrecy="false" />
+    <!-- http, no subdomain, with attribute differences -->
+    <allow-navigation href="http://server25.com" /> <!-- equivalent to the next line -->
+    <allow-navigation href="http://server25.com" minimum-tls-version="TLSv1.2" requires-forward-secrecy="true" />
+    <allow-navigation href="http://server26.com" minimum-tls-version="TLSv1.2" requires-forward-secrecy="false" />
+    <allow-navigation href="http://server27.com" minimum-tls-version="TLSv1.1" requires-forward-secrecy="true" />
+    <allow-navigation href="http://server28.com" minimum-tls-version="TLSv1.1" requires-forward-secrecy="false" />
+    <!-- https, no subdomain, with attribute differences -->
+    <allow-navigation href="https://server29.com" /> <!-- equivalent to the next line -->
+    <allow-navigation href="https://server29.com" minimum-tls-version="TLSv1.2" requires-forward-secrecy="true" />
+    <allow-navigation href="https://server30.com" minimum-tls-version="TLSv1.2" requires-forward-secrecy="false" />
+    <allow-navigation href="https://server31.com" minimum-tls-version="TLSv1.1" requires-forward-secrecy="true" />
+    <allow-navigation href="https://server32.com" minimum-tls-version="TLSv1.1" requires-forward-secrecy="false" />
+    <!-- wildcard scheme, with subdomain wildcard, with attribute differences -->
+    <allow-navigation href="*://*.server33.com" /> <!-- equivalent to the next line -->
+    <allow-navigation href="*://*.server33.com" minimum-tls-version="TLSv1.2" requires-forward-secrecy="true" />
+    <allow-navigation href="*://*.server34.com" minimum-tls-version="TLSv1.2" requires-forward-secrecy="false" />
+    <allow-navigation href="*://*.server35.com" minimum-tls-version="TLSv1.1" requires-forward-secrecy="true" />
+    <allow-navigation href="*://*.server36.com" minimum-tls-version="TLSv1.1" requires-forward-secrecy="false" />
+    <!-- wildcard scheme, no subdomain, with attribute differences -->
+    <allow-navigation href="*://server37.com" /> <!-- equivalent to the next line -->
+    <allow-navigation href="*://server37.com" minimum-tls-version="TLSv1.2" requires-forward-secrecy="true" />
+    <allow-navigation href="*://server38.com" minimum-tls-version="TLSv1.2" requires-forward-secrecy="false" />
+    <allow-navigation href="*://server39.com" minimum-tls-version="TLSv1.1" requires-forward-secrecy="true" />
+    <allow-navigation href="*://server40.com" minimum-tls-version="TLSv1.1" requires-forward-secrecy="false" />
+
     <preference name="fullscreen" value="true" />
     <preference name="webviewbounce" value="true" />
     <preference name="orientation" value="portrait" />

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/ff0fd6e2/cordova-common/src/ConfigParser/ConfigParser.js
----------------------------------------------------------------------
diff --git a/cordova-common/src/ConfigParser/ConfigParser.js b/cordova-common/src/ConfigParser/ConfigParser.js
index 0529651..7abddf6 100644
--- a/cordova-common/src/ConfigParser/ConfigParser.js
+++ b/cordova-common/src/ConfigParser/ConfigParser.js
@@ -437,6 +437,32 @@ ConfigParser.prototype = {
             };
         });
     },
+    /* Get all the access tags */
+    getAccesses: function() {
+        var accesses = this.doc.findall('./access');
+        return accesses.map(function(access){
+            var minimum_tls_version = access.attrib['minimum-tls-version']; /* String */
+            var requires_forward_secrecy = access.attrib['requires-forward-secrecy']; /* Boolean */
+            return {
+                'origin': access.attrib.origin,
+                'minimum_tls_version': minimum_tls_version,
+                'requires_forward_secrecy' : requires_forward_secrecy
+            };
+        });
+    },
+    /* Get all the allow-navigation tags */
+    getAllowNavigations: function() {
+        var allow_navigations = this.doc.findall('./allow-navigation');
+        return allow_navigations.map(function(allow_navigation){
+            var minimum_tls_version = allow_navigation.attrib['minimum-tls-version']; /* String */
+            var requires_forward_secrecy = allow_navigation.attrib['requires-forward-secrecy']; /* Boolean */
+            return {
+                'href': allow_navigation.attrib.href,
+                'minimum_tls_version': minimum_tls_version,
+                'requires_forward_secrecy' : requires_forward_secrecy
+            };
+        });
+    },
     write:function() {
         fs.writeFileSync(this.path, this.doc.write({indent: 4}), 'utf-8');
     }

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/ff0fd6e2/cordova-lib/spec-cordova/ConfigParser.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/ConfigParser.spec.js b/cordova-lib/spec-cordova/ConfigParser.spec.js
deleted file mode 100644
index 4d41488..0000000
--- a/cordova-lib/spec-cordova/ConfigParser.spec.js
+++ /dev/null
@@ -1,232 +0,0 @@
-/**
-    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'),
-    fs = require('fs'),
-    ConfigParser = require('../src/configparser/ConfigParser'),
-    xml = path.join(__dirname, 'test-config.xml'),
-    xml_contents = fs.readFileSync(xml, 'utf-8');
-
-describe('config.xml parser', function () {
-    var readFile;
-    beforeEach(function() {
-        readFile = spyOn(fs, 'readFileSync').andReturn(xml_contents);
-    });
-
-    it('should create an instance based on an xml file', function() {
-        var cfg;
-        expect(function () {
-            cfg = new ConfigParser(xml);
-        }).not.toThrow();
-        expect(cfg).toBeDefined();
-        expect(cfg.doc).toBeDefined();
-    });
-
-    describe('methods', function() {
-        var cfg;
-        beforeEach(function() {
-            cfg = new ConfigParser(xml);
-        });
-
-        describe('package name / id', function() {
-            it('should get the (default) packagename', function() {
-                expect(cfg.packageName()).toEqual('io.cordova.hellocordova');
-            });
-            it('should allow setting the packagename', function() {
-                cfg.setPackageName('this.is.bat.country');
-                expect(cfg.packageName()).toEqual('this.is.bat.country');
-            });
-        });
-
-        describe('package name / android-packageName', function() {
-            it('should get the android packagename', function() {
-                expect(cfg.android_packageName()).toEqual('io.cordova.hellocordova.android');
-            });
-        });
-
-        describe('package name / ios-CFBundleIdentifier', function() {
-            it('should get the ios packagename', function() {
-                expect(cfg.ios_CFBundleIdentifier()).toEqual('io.cordova.hellocordova.ios');
-            });
-        });
-
-        describe('version', function() {
-            it('should get the version', function() {
-                expect(cfg.version()).toEqual('0.0.1');
-            });
-            it('should allow setting the version', function() {
-                cfg.setVersion('2.0.1');
-                expect(cfg.version()).toEqual('2.0.1');
-            });
-        });
-
-        describe('app name', function() {
-            it('should get the (default) app name', function() {
-                expect(cfg.name()).toEqual('Hello Cordova');
-            });
-            it('should allow setting the app name', function() {
-                cfg.setName('this.is.bat.country');
-                expect(cfg.name()).toEqual('this.is.bat.country');
-            });
-        });
-        describe('preference', function() {
-            it('should return the value of a global preference', function() {
-                expect(cfg.getPreference('fullscreen')).toEqual('true');
-            });
-            it('should return the value of a platform-specific preference', function() {
-                expect(cfg.getPreference('android-minSdkVersion', 'android')).toEqual('10');
-            });
-            it('should return an empty string for a non-existing preference', function() {
-                expect(cfg.getPreference('zimzooo!')).toEqual('');
-            });
-        });
-        describe('global preference', function() {
-            it('should return the value of a global preference', function() {
-                expect(cfg.getGlobalPreference('orientation')).toEqual('portrait');
-            });
-            it('should return an empty string for a non-existing preference', function() {
-                expect(cfg.getGlobalPreference('foobar')).toEqual('');
-            });
-        });
-        describe('platform-specific preference', function() {
-            it('should return the value of a platform specific preference', function() {
-                expect(cfg.getPlatformPreference('orientation', 'android')).toEqual('landscape');
-            });
-            it('should return an empty string when querying for a non-existing preference', function() {
-                expect(cfg.getPlatformPreference('foobar', 'android')).toEqual('');
-            });
-            it('should return an empty string when querying with unsupported platform', function() {
-                expect(cfg.getPlatformPreference('orientation', 'foobar')).toEqual('');
-            });
-        });
-        describe('plugin',function(){
-            it('should read plugin id list', function() {
-               var expectedList = [
-                   'org.apache.cordova.pluginwithvars',
-                   'org.apache.cordova.pluginwithurl',
-                   'org.apache.cordova.pluginwithversion',
-                   'org.apache.cordova.pluginwithurlandversion',
-                   'org.apache.cordova.justaplugin',
-                   'org.apache.cordova.legacyfeatureversion',
-                   'org.apache.cordova.legacyfeatureurl',
-                   'org.apache.cordova.legacyfeatureversionandurl'
-               ];
-               var list = cfg.getPluginIdList();
-               expect(list.length).toEqual(expectedList.length);
-               expectedList.forEach(function(plugin){
-                   expect(list).toContain(plugin);
-               });
-            });
-            it('should read plugin given id', function(){
-                var plugin = cfg.getPlugin('org.apache.cordova.justaplugin');
-                expect(plugin).toBeDefined();
-                expect(plugin.name).toEqual('org.apache.cordova.justaplugin');
-                expect(plugin.variables).toBeDefined();
-            });
-            it('should not read plugin given undefined id', function(){
-                var plugin = cfg.getPlugin('org.apache.cordova.undefinedplugin');
-                expect(plugin).not.toBeDefined();
-            });
-            it('should read plugin with src and store it in spec field', function(){
-                var plugin = cfg.getPlugin('org.apache.cordova.pluginwithurl');
-                expect(plugin.spec).toEqual('http://cordova.apache.org/pluginwithurl');
-            });
-            it('should read plugin with version and store it in spec field', function(){
-                var plugin = cfg.getPlugin('org.apache.cordova.pluginwithversion');
-                expect(plugin.spec).toEqual('1.1.1');
-            });
-            it('should read plugin with source and version and store source in spec field', function(){
-                var plugin = cfg.getPlugin('org.apache.cordova.pluginwithurlandversion');
-                expect(plugin.spec).toEqual('http://cordova.apache.org/pluginwithurlandversion');
-            });
-            it('should read plugin variables', function () {
-                var plugin = cfg.getPlugin('org.apache.cordova.pluginwithvars');
-                expect(plugin.variables).toBeDefined();
-                expect(plugin.variables.var).toBeDefined();
-                expect(plugin.variables.var).toEqual('varvalue');
-            });
-            it('should allow adding a new plugin', function(){
-                cfg.addPlugin({name:'myplugin'});
-                var plugins = cfg.doc.findall('plugin');
-                var pluginNames = plugins.map(function(plugin){
-                    return plugin.attrib.name;
-                });
-                expect(pluginNames).toContain('myplugin');
-            });
-            it('should allow adding features with params', function(){
-                cfg.addPlugin({name:'aplugin'}, [{name:'paraname',value:'paravalue'}]);
-                // Additional check for new parameters syntax
-                cfg.addPlugin({name:'bplugin'}, {paraname: 'paravalue'});
-                var plugins = cfg.doc.findall('plugin')
-                .filter(function (plugin) {
-                    return plugin.attrib.name === 'aplugin' || plugin.attrib.name === 'bplugin';
-                });
-                expect(plugins.length).toBe(2);
-                plugins.forEach(function (plugin) {
-                    var variables = plugin.findall('variable');
-                    expect(variables[0].attrib.name).toEqual('paraname');
-                    expect(variables[0].attrib.value).toEqual('paravalue');
-                });
-            });
-            it('should be able to read legacy feature entries with a version', function(){
-                var plugin = cfg.getPlugin('org.apache.cordova.legacyfeatureversion');
-                expect(plugin).toBeDefined();
-                expect(plugin.name).toEqual('org.apache.cordova.legacyfeatureversion');
-                expect(plugin.spec).toEqual('1.2.3');
-                expect(plugin.variables).toBeDefined();
-                expect(plugin.variables.aVar).toEqual('aValue');
-            });
-            it('should be able to read legacy feature entries with a url', function(){
-                var plugin = cfg.getPlugin('org.apache.cordova.legacyfeatureurl');
-                expect(plugin).toBeDefined();
-                expect(plugin.name).toEqual('org.apache.cordova.legacyfeatureurl');
-                expect(plugin.spec).toEqual('http://cordova.apache.org/legacyfeatureurl');
-            });
-            it('should be able to read legacy feature entries with a version and a url', function(){
-                var plugin = cfg.getPlugin('org.apache.cordova.legacyfeatureversionandurl');
-                expect(plugin).toBeDefined();
-                expect(plugin.name).toEqual('org.apache.cordova.legacyfeatureversionandurl');
-                expect(plugin.spec).toEqual('http://cordova.apache.org/legacyfeatureversionandurl');
-            });
-            it('it should remove given plugin', function(){
-                cfg.removePlugin('org.apache.cordova.justaplugin');
-                var plugins = cfg.doc.findall('plugin');
-                var pluginNames = plugins.map(function(plugin){
-                    return plugin.attrib.name;
-                });
-                expect(pluginNames).not.toContain('org.apache.cordova.justaplugin');
-            });
-            it('it should remove given legacy feature id', function(){
-                cfg.removePlugin('org.apache.cordova.legacyplugin');
-                var plugins = cfg.doc.findall('feature');
-                var pluginNames = plugins.map(function(plugin){
-                    return plugin.attrib.name;
-                });
-                expect(pluginNames).not.toContain('org.apache.cordova.legacyplugin');
-            });
-            it('it should read <access> tag entries', function(){
-                var accesses = cfg.getAccesses();
-                expect(accesses.length).not.toEqual(0);
-            });
-            it('it should read <allow-navigation> tag entries', function(){
-                var navigations = cfg.getAllowNavigations();
-                expect(navigations.length).not.toEqual(0);
-            });
-        });
-    });
-});

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/ff0fd6e2/cordova-lib/src/configparser/ConfigParser.js
----------------------------------------------------------------------
diff --git a/cordova-lib/src/configparser/ConfigParser.js b/cordova-lib/src/configparser/ConfigParser.js
deleted file mode 100644
index 448b50a..0000000
--- a/cordova-lib/src/configparser/ConfigParser.js
+++ /dev/null
@@ -1,499 +0,0 @@
-/**
-    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.
-*/
-
-/* jshint sub:true */
-
-var et = require('elementtree'),
-    xml= require('../util/xml-helpers'),
-    CordovaError = require('../CordovaError'),
-    fs = require('fs'),
-    events = require('../events');
-
-
-/** Wraps a config.xml file */
-function ConfigParser(path) {
-    this.path = path;
-    try {
-        this.doc = xml.parseElementtreeSync(path);
-        this.cdvNamespacePrefix = getCordovaNamespacePrefix(this.doc);
-        et.register_namespace(this.cdvNamespacePrefix, 'http://cordova.apache.org/ns/1.0');
-    } catch (e) {
-        console.error('Parsing '+path+' failed');
-        throw e;
-    }
-    var r = this.doc.getroot();
-    if (r.tag !== 'widget') {
-        throw new CordovaError(path + ' has incorrect root node name (expected "widget", was "' + r.tag + '")');
-    }
-}
-
-function getNodeTextSafe(el) {
-    return el && el.text && el.text.trim();
-}
-
-function findOrCreate(doc, name) {
-    var ret = doc.find(name);
-    if (!ret) {
-        ret = new et.Element(name);
-        doc.getroot().append(ret);
-    }
-    return ret;
-}
-
-function getCordovaNamespacePrefix(doc){
-    var rootAtribs = Object.getOwnPropertyNames(doc.getroot().attrib);
-    var prefix = 'cdv';
-    for (var j = 0; j < rootAtribs.length; j++ ) {
-        if(rootAtribs[j].indexOf('xmlns:') === 0 &&
-            doc.getroot().attrib[rootAtribs[j]] === 'http://cordova.apache.org/ns/1.0'){
-            var strings = rootAtribs[j].split(':');
-            prefix = strings[1];
-            break;
-        }
-    }
-    return prefix;
-}
-
-/**
- * Finds the value of an element's attribute
- * @param  {String} attributeName Name of the attribute to search for
- * @param  {Array}  elems         An array of ElementTree nodes
- * @return {String}
- */
-function findElementAttributeValue(attributeName, elems) {
-
-    elems = Array.isArray(elems) ? elems : [ elems ];
-
-    var value = elems.filter(function (elem) {
-        return elem.attrib.name.toLowerCase() === attributeName.toLowerCase();
-    }).map(function (filteredElems) {
-        return filteredElems.attrib.value;
-    }).pop();
-
-    return value ? value : '';
-}
-
-ConfigParser.prototype = {
-    packageName: function(id) {
-        return this.doc.getroot().attrib['id'];
-    },
-    setPackageName: function(id) {
-        this.doc.getroot().attrib['id'] = id;
-    },
-    android_packageName: function() {
-        return this.doc.getroot().attrib['android-packageName'];
-    },
-    android_activityName: function() {
-	return this.doc.getroot().attrib['android-activityName'];
-    },
-    ios_CFBundleIdentifier: function() {
-        return this.doc.getroot().attrib['ios-CFBundleIdentifier'];
-    },
-    name: function() {
-        return getNodeTextSafe(this.doc.find('name'));
-    },
-    setName: function(name) {
-        var el = findOrCreate(this.doc, 'name');
-        el.text = name;
-    },
-    description: function() {
-        return getNodeTextSafe(this.doc.find('description'));
-    },
-    setDescription: function(text) {
-        var el = findOrCreate(this.doc, 'description');
-        el.text = text;
-    },
-    version: function() {
-        return this.doc.getroot().attrib['version'];
-    },
-    windows_packageVersion: function() {
-        return this.doc.getroot().attrib('windows-packageVersion');
-    },
-    android_versionCode: function() {
-        return this.doc.getroot().attrib['android-versionCode'];
-    },
-    ios_CFBundleVersion: function() {
-        return this.doc.getroot().attrib['ios-CFBundleVersion'];
-    },
-    setVersion: function(value) {
-        this.doc.getroot().attrib['version'] = value;
-    },
-    author: function() {
-        return getNodeTextSafe(this.doc.find('author'));
-    },
-    getGlobalPreference: function (name) {
-        return findElementAttributeValue(name, this.doc.findall('preference'));
-    },
-    setGlobalPreference: function (name, value) {
-        var pref = this.doc.find('preference[@name="' + name + '"]');
-        if (!pref) {
-            pref = new et.Element('preference');
-            pref.attrib.name = name;
-            this.doc.getroot().append(pref);
-        }
-        pref.attrib.value = value;
-    },
-    getPlatformPreference: function (name, platform) {
-        return findElementAttributeValue(name, this.doc.findall('platform[@name=\'' + platform + '\']/preference'));
-    },
-    getPreference: function(name, platform) {
-
-        var platformPreference = '';
-
-        if (platform) {
-            platformPreference = this.getPlatformPreference(name, platform);
-        }
-
-        return platformPreference ? platformPreference : this.getGlobalPreference(name);
-
-    },
-    /**
-     * Returns all resources for the platform specified.
-     * @param  {String} platform     The platform.
-     * @param {string}  resourceName Type of static resources to return.
-     *                               "icon" and "splash" currently supported.
-     * @return {Array}               Resources for the platform specified.
-     */
-    getStaticResources: function(platform, resourceName) {
-        var ret = [],
-            staticResources = [];
-        if (platform) { // platform specific icons
-            this.doc.findall('platform[@name=\'' + platform + '\']/' + resourceName).forEach(function(elt){
-                elt.platform = platform; // mark as platform specific resource
-                staticResources.push(elt);
-            });
-        }
-        // root level resources
-        staticResources = staticResources.concat(this.doc.findall(resourceName));
-        // parse resource elements
-        var that = this;
-        staticResources.forEach(function (elt) {
-            var res = {};
-            res.src = elt.attrib.src;
-            res.density = elt.attrib['density'] || elt.attrib[that.cdvNamespacePrefix+':density'] || elt.attrib['gap:density'];
-            res.platform = elt.platform || null; // null means icon represents default icon (shared between platforms)
-            res.width = +elt.attrib.width || undefined;
-            res.height = +elt.attrib.height || undefined;
-
-            // default icon
-            if (!res.width && !res.height && !res.density) {
-                ret.defaultResource = res;
-            }
-            ret.push(res);
-        });
-
-        /**
-         * Returns resource with specified width and/or height.
-         * @param  {number} width Width of resource.
-         * @param  {number} height Height of resource.
-         * @return {Resource} Resource object or null if not found.
-         */
-        ret.getBySize = function(width, height) {
-            return ret.filter(function(res) {
-                if (!res.width && !res.height) {
-                    return false;
-                }
-                return ((!res.width || (width == res.width)) &&
-                    (!res.height || (height == res.height)));
-            })[0] || null;
-        };
-
-        /**
-         * Returns resource with specified density.
-         * @param  {string} density Density of resource.
-         * @return {Resource}       Resource object or null if not found.
-         */
-        ret.getByDensity = function(density) {
-            return ret.filter(function(res) {
-                return res.density == density;
-            })[0] || null;
-        };
-
-        /** Returns default icons */
-        ret.getDefault = function() {
-            return ret.defaultResource;
-        };
-
-        return ret;
-    },
-
-    /**
-     * Returns all icons for specific platform.
-     * @param  {string} platform Platform name
-     * @return {Resource[]}      Array of icon objects.
-     */
-    getIcons: function(platform) {
-        return this.getStaticResources(platform, 'icon');
-    },
-
-    /**
-     * Returns all splash images for specific platform.
-     * @param  {string} platform Platform name
-     * @return {Resource[]}      Array of Splash objects.
-     */
-    getSplashScreens: function(platform) {
-        return this.getStaticResources(platform, 'splash');
-    },
-
-    /**
-     * Returns all hook scripts for the hook type specified.
-     * @param  {String} hook     The hook type.
-     * @param {Array}  platforms Platforms to look for scripts into (root scripts will be included as well).
-     * @return {Array}               Script elements.
-     */
-    getHookScripts: function(hook, platforms) {
-        var self = this;
-        var scriptElements = self.doc.findall('./hook');
-
-        if(platforms) {
-            platforms.forEach(function (platform) {
-                scriptElements = scriptElements.concat(self.doc.findall('./platform[@name="' + platform + '"]/hook'));
-            });
-        }
-
-        function filterScriptByHookType(el) {
-            return el.attrib.src && el.attrib.type && el.attrib.type.toLowerCase() === hook;
-        }
-
-        return scriptElements.filter(filterScriptByHookType);
-    },
-   /**
-    * Returns a list of plugin (IDs).
-    *
-    * This function also returns any plugin's that
-    * were defined using the legacy <feature> tags.
-    * @return {string[]} Array of plugin IDs
-    */
-    getPluginIdList: function () {
-        var plugins = this.doc.findall('plugin');
-        var result = plugins.map(function(plugin){
-            return plugin.attrib.name;
-        });
-        var features = this.doc.findall('feature');
-        features.forEach(function(element ){
-            var idTag = element.find('./param[@name="id"]');
-            if(idTag){
-                result.push(idTag.attrib.value);
-            }
-        });
-        return result;
-    },
-    getPlugins: function () {
-        return this.getPluginIdList().map(function (pluginId) {
-            return this.getPlugin(pluginId);
-        }, this);
-    },
-    /**
-     * Adds a plugin element. Does not check for duplicates.
-     * @name addPlugin
-     * @function
-     * @param {object} attributes name and spec are supported
-     * @param {Array|object} variables name, value or arbitary object
-     */
-    addPlugin: function (attributes, variables) {
-        if (!attributes && !attributes.name) return;
-        var el = new et.Element('plugin');
-        el.attrib.name = attributes.name;
-        if (attributes.spec) {
-            el.attrib.spec = attributes.spec;
-        }
-
-        // support arbitrary object as variables source
-        if (variables && typeof variables === 'object' && !Array.isArray(variables)) {
-            variables = Object.keys(variables)
-            .map(function (variableName) {
-                return {name: variableName, value: variables[variableName]};
-            });
-        }
-
-        if (variables) {
-            variables.forEach(function (variable) {
-                el.append(new et.Element('variable', { name: variable.name, value: variable.value }));
-            });
-        }
-        this.doc.getroot().append(el);
-    },
-    /**
-     * Retrives the plugin with the given id or null if not found.
-     *
-     * This function also returns any plugin's that
-     * were defined using the legacy <feature> tags.
-     * @name getPlugin
-     * @function
-     * @param {String} id
-     * @returns {object} plugin including any variables
-     */
-    getPlugin: function(id){
-        if(!id){
-            return undefined;
-        }
-        var pluginElement = this.doc.find('./plugin/[@name="' + id + '"]');
-        if (null === pluginElement) {
-            var legacyFeature =  this.doc.find('./feature/param[@name="id"][@value="' + id + '"]/..');
-            if(legacyFeature){
-                 events.emit('log', 'Found deprecated feature entry for ' + id +' in config.xml.');
-                return featureToPlugin(legacyFeature);
-            }
-            return undefined;
-        }
-        var plugin = {};
-
-        plugin.name = pluginElement.attrib.name;
-        plugin.spec = pluginElement.attrib.spec || pluginElement.attrib.src || pluginElement.attrib.version;
-        plugin.variables = {};
-        var variableElements = pluginElement.findall('variable');
-        variableElements.forEach(function(varElement){
-            var name = varElement.attrib.name;
-            var value = varElement.attrib.value;
-            if(name){
-                plugin.variables[name] = value;
-            }
-        });
-        return plugin;
-    },
-    /**
-     * Remove the plugin entry with give name (id).
-     *
-     * This function also operates on any plugin's that
-     * were defined using the legacy <feature> tags.
-     * @name removePlugin
-     * @function
-     * @param id name of the plugin
-     */
-    removePlugin: function(id){
-        if(id){
-            var plugins = this.doc.findall('./plugin/[@name="' + id + '"]')
-                .concat(this.doc.findall('./feature/param[@name="id"][@value="' + id + '"]/..'));
-            var children = this.doc.getroot().getchildren();
-            plugins.forEach(function (plugin) {
-                var idx = children.indexOf(plugin);
-                if (idx > -1) {
-                    children.splice(idx, 1);
-                }
-            });
-        }
-    },
-
-    // Add any element to the root
-    addElement: function(name, attributes) {
-        var el = et.Element(name);
-        for (var a in attributes) {
-            el.attrib[a] = attributes[a];
-        }
-        this.doc.getroot().append(el);
-    },
-
-    /**
-     * Adds an engine. Does not check for duplicates.
-     * @param  {String} name the engine name
-     * @param  {String} spec engine source location or version (optional)
-     */
-    addEngine: function(name, spec){
-        if(!name) return;
-        var el = et.Element('engine');
-        el.attrib.name = name;
-        if(spec){
-            el.attrib.spec = spec;
-        }
-        this.doc.getroot().append(el);
-    },
-    /**
-     * Removes all the engines with given name
-     * @param  {String} name the engine name.
-     */
-    removeEngine: function(name){
-        var engines = this.doc.findall('./engine/[@name="' +name+'"]');
-        for(var i=0; i < engines.length; i++){
-            var children = this.doc.getroot().getchildren();
-            var idx = children.indexOf(engines[i]);
-            if(idx > -1){
-                children.splice(idx,1);
-            }
-        }
-    },
-    getEngines: function(){
-        var engines = this.doc.findall('./engine');
-        return engines.map(function(engine){
-            var spec = engine.attrib.spec || engine.attrib.version;
-            return {
-                'name': engine.attrib.name,
-                'spec': spec ? spec : null
-            };
-        });
-    },
-    /* Get all the access tags */
-    getAccesses: function() {
-        var accesses = this.doc.findall('./access');
-        return accesses.map(function(access){
-            var minimum_tls_version = access.attrib['minimum-tls-version']; /* String */
-            var requires_forward_secrecy = access.attrib['requires-forward-secrecy']; /* Boolean */
-            return {
-                'origin': access.attrib.origin,
-                'minimum_tls_version': minimum_tls_version,
-                'requires_forward_secrecy' : requires_forward_secrecy 
-            };
-        });
-    },
-    /* Get all the allow-navigation tags */
-    getAllowNavigations: function() {
-        var allow_navigations = this.doc.findall('./allow-navigation');
-        return allow_navigations.map(function(allow_navigation){
-            var minimum_tls_version = allow_navigation.attrib['minimum-tls-version']; /* String */
-            var requires_forward_secrecy = allow_navigation.attrib['requires-forward-secrecy']; /* Boolean */
-            return {
-                'href': allow_navigation.attrib.href,
-                'minimum_tls_version': minimum_tls_version,
-                'requires_forward_secrecy' : requires_forward_secrecy 
-            };
-        });
-    },
-    write:function() {
-        fs.writeFileSync(this.path, this.doc.write({indent: 4}), 'utf-8');
-    }
-};
-
-function featureToPlugin(featureElement) {
-    var plugin = {};
-    plugin.variables = [];
-    var pluginVersion,
-        pluginSrc;
-
-    var nodes = featureElement.findall('param');
-    nodes.forEach(function (element) {
-        var n = element.attrib.name;
-        var v = element.attrib.value;
-        if (n === 'id') {
-            plugin.name = v;
-        } else if (n === 'version') {
-            pluginVersion = v;
-        } else if (n === 'url' || n === 'installPath') {
-            pluginSrc = v;
-        } else {
-            plugin.variables[n] = v;
-        }
-    });
-
-    var spec = pluginSrc || pluginVersion;
-    if (spec) {
-        plugin.spec = spec;
-    }
-
-    return plugin;
-}
-module.exports = ConfigParser;


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org