diff --git a/lib/create.js b/lib/create.js index fbbcf16a..da75631f 100755 --- a/lib/create.js +++ b/lib/create.js @@ -255,7 +255,7 @@ exports.create = function (project_path, config, options, events) { fs.ensureDirSync(activity_dir); fs.copySync(path.join(project_template_dir, 'Activity.java'), activity_path); utils.replaceFileContents(activity_path, /__ACTIVITY__/, safe_activity_name); - utils.replaceFileContents(path.join(app_path, 'res', 'values', 'strings.xml'), /__NAME__/, project_name); + utils.replaceFileContents(path.join(app_path, 'res', 'values', 'strings.xml'), /__NAME__/, utils.escape(project_name)); utils.replaceFileContents(activity_path, /__ID__/, package_name); var manifest = new AndroidManifest(path.join(project_template_dir, 'AndroidManifest.xml')); diff --git a/lib/utils.js b/lib/utils.js index 7436cac5..28f17d92 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -66,3 +66,21 @@ exports.forgivingWhichSync = (cmd) => { exports.isWindows = () => os.platform() === 'win32'; exports.isDarwin = () => os.platform() === 'darwin'; + +const UNESCAPED_REGEX = /[&<>"']/g; + +const escapes = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''' +}; + +/** + * Converts the characters "&", "<", ">", '"' and "'" in the given string to + * their corresponding escaped value + * @param {string} str the string to be escaped + * @returns the escaped string + */ +exports.escape = (str) => UNESCAPED_REGEX.test(str) ? str.replace(UNESCAPED_REGEX, (key) => escapes[key]) : str; diff --git a/spec/unit/create.spec.js b/spec/unit/create.spec.js index de05e866..33cc4bee 100644 --- a/spec/unit/create.spec.js +++ b/spec/unit/create.spec.js @@ -275,6 +275,13 @@ describe('create', function () { }); }); + it('should interpolate the escaped project name into strings.xml', () => { + config_mock.name.and.returnValue(''); + return create.create(project_path, config_mock, {}, events_mock).then(() => { + expect(utils.replaceFileContents).toHaveBeenCalledWith(path.join(app_path, 'res', 'values', 'strings.xml'), /__NAME__/, '<Incredible&App>'); + }); + }); + it('should copy template scripts into generated project', () => { return create.create(project_path, config_mock, {}, events_mock).then(() => { expect(create.copyScripts).toHaveBeenCalledWith(project_path);