From 334c0b67d2e02d4c3216d7ecd09e9275cd44eb9a Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Mon, 28 Aug 2023 17:53:26 +0200 Subject: [PATCH 1/3] fix: Move utf7 encoding primitives to the module codebase (#689) --- lib/tools/settings-client-commands.js | 2 +- lib/tools/utf7.js | 153 ++++++++++++++++++++++++++ package.json | 3 +- 3 files changed, 155 insertions(+), 3 deletions(-) create mode 100644 lib/tools/utf7.js diff --git a/lib/tools/settings-client-commands.js b/lib/tools/settings-client-commands.js index 121bfcd8..e8fad6ea 100644 --- a/lib/tools/settings-client-commands.js +++ b/lib/tools/settings-client-commands.js @@ -3,7 +3,7 @@ import { parseJsonData } from '../helpers.js'; import _ from 'lodash'; import { util, timing } from '@appium/support'; import { waitForCondition } from 'asyncbox'; -import { imap } from 'utf7'; +import { imap } from './utf7'; import { SubProcess } from 'teen_process'; import B from 'bluebird'; diff --git a/lib/tools/utf7.js b/lib/tools/utf7.js new file mode 100644 index 00000000..178cf1e1 --- /dev/null +++ b/lib/tools/utf7.js @@ -0,0 +1,153 @@ +/* + * The code below has been adopted from https://www.npmjs.com/package/utf7 + */ + +/** + * @param {number} length + * @returns {Buffer} + */ +function allocateAsciiBuffer(length) { + return Buffer.alloc(length, 'ascii'); +} + +/** + * @param {string} str + * @returns {string} + */ +function _encode(str) { + const b = allocateAsciiBuffer(str.length * 2); + for (let i = 0, bi = 0; i < str.length; i++) { + // Note that we can't simply convert a UTF-8 string to Base64 because + // UTF-8 uses a different encoding. In modified UTF-7, all characters + // are represented by their two byte Unicode ID. + const c = str.charCodeAt(i); + // Upper 8 bits shifted into lower 8 bits so that they fit into 1 byte. + b[bi++] = c >> 8; + // Lower 8 bits. Cut off the upper 8 bits so that they fit into 1 byte. + b[bi++] = c & 0xFF; + } + // Modified Base64 uses , instead of / and omits trailing =. + return b.toString('base64').replace(/=+$/, ''); +} + +/** + * @param {string} str + * @returns {Buffer} + */ +function allocateBase64Buffer(str) { + return Buffer.from(str, 'base64'); +} + +/** + * @param {string} str + * @returns {string} + */ +function _decode(str) { + const b = allocateBase64Buffer(str); + const r = []; + for (let i = 0; i < b.length;) { + // Calculate charcode from two adjacent bytes. + r.push(String.fromCharCode(b[i++] << 8 | b[i++])); + } + return r.join(''); +} + +/** + * Escape RegEx from http://simonwillison.net/2006/Jan/20/escape/ + * + * @param {string} chars + * @returns {string} + */ +function escape(chars) { + return chars.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'); +} + +// Character classes defined by RFC 2152. +const setD = 'A-Za-z0-9' + escape(`'(),-./:?`); +const setO = escape(`!"#$%&*;<=>@[]^_'{|}`); +const setW = escape(` \r\n\t`); + +// Stores compiled regexes for various replacement pattern. +const regexes = {}; +const regexAll = new RegExp(`[^${setW}${setD}${setO}]+`, 'g'); + +export const imap = {}; + +/** + * RFC 2152 UTF-7 encoding. + * + * @param {string} str + * @param {string?} mask + * @returns {string} + */ +export const encode = function encode(str, mask = null) { + // Generate a RegExp object from the string of mask characters. + if (!mask) { + mask = ''; + } + if (!regexes[mask]) { + regexes[mask] = new RegExp(`[^${setD}${escape(mask)}]+`, 'g'); + } + + // We replace subsequent disallowed chars with their escape sequence. + return str.replace(regexes[mask], (chunk) => + // + is represented by an empty sequence +-, otherwise call encode(). + `+${chunk === '+' ? '' : _encode(chunk)}-` + ); +}; + +/** + * RFC 2152 UTF-7 encoding with all optionals. + * + * @param {string} str + * @returns {string} + */ +exports.encodeAll = function encodeAll(str) { + // We replace subsequent disallowed chars with their escape sequence. + return str.replace(regexAll, (chunk) => + // + is represented by an empty sequence +-, otherwise call encode(). + `+${chunk === '+' ? '' : _encode(chunk)}-` + ); +}; + +/** + * RFC 3501, section 5.1.3 UTF-7 encoding. + * + * @param {string} str + * @returns {string} + */ +imap.encode = function encode(str) { + // All printable ASCII chars except for & must be represented by themselves. + // We replace subsequent non-representable chars with their escape sequence. + return str.replace(/&/g, '&-').replace(/[^\x20-\x7e]+/g, (chunk) => { + // & is represented by an empty sequence &-, otherwise call encode(). + chunk = (chunk === '&' ? '' : _encode(chunk)).replace(/\//g, ','); + return `&${chunk}-`; + }); +}; + +/** + * RFC 2152 UTF-7 decoding. + * + * @param {string} str + * @returns {string} + */ +export const decode = function decode(str) { + return str.replace(/\+([A-Za-z0-9/]*)-?/gi, (_, chunk) => + // &- represents &. + chunk === '' ? '+' : _decode(chunk) + ); +}; + +/** + * RFC 3501, section 5.1.3 UTF-7 decoding. + * + * @param {string} str + * @returns {string} + */ +imap.decode = function decode(str) { + return str.replace(/&([^-]*)-/g, (_, chunk) => + // &- represents &. + chunk === '' ? '&' : _decode(chunk.replace(/,/g, '/')) + ); +}; diff --git a/package.json b/package.json index c55c1c95..7b557cbf 100644 --- a/package.json +++ b/package.json @@ -64,8 +64,7 @@ "lru-cache": "^10.0.0", "semver": "^7.0.0", "source-map-support": "^0.x", - "teen_process": "^2.0.1", - "utf7": "^1.0.2" + "teen_process": "^2.0.1" }, "devDependencies": { "@appium/eslint-config-appium": "^6.0.0", From f3b5be1ae93f2cd6cc1039d6e8f8768a7d246491 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Aug 2023 17:53:39 +0200 Subject: [PATCH 2/3] chore: Bump typescript from 5.0.4 to 5.2.2 (#688) Bumps [typescript](https://github.com/Microsoft/TypeScript) from 5.0.4 to 5.2.2. - [Release notes](https://github.com/Microsoft/TypeScript/releases) - [Commits](https://github.com/Microsoft/TypeScript/commits) --- updated-dependencies: - dependency-name: typescript dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7b557cbf..036d6ff5 100644 --- a/package.json +++ b/package.json @@ -103,7 +103,7 @@ "sinon": "^15.0.0", "temp": "^0.x", "ts-node": "^10.9.1", - "typescript": "~5.0.4" + "typescript": "~5.2.2" }, "types": "./build/index.d.ts" } From f9cbfd3d37d68aec50a24348703ef7516910709d Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 28 Aug 2023 15:54:43 +0000 Subject: [PATCH 3/3] chore(release): 9.14.9 [skip ci] ## [9.14.9](https://github.com/appium/appium-adb/compare/v9.14.8...v9.14.9) (2023-08-28) ### Bug Fixes * Move utf7 encoding primitives to the module codebase ([#689](https://github.com/appium/appium-adb/issues/689)) ([334c0b6](https://github.com/appium/appium-adb/commit/334c0b67d2e02d4c3216d7ecd09e9275cd44eb9a)) ### Miscellaneous Chores * Bump typescript from 5.0.4 to 5.2.2 ([#688](https://github.com/appium/appium-adb/issues/688)) ([f3b5be1](https://github.com/appium/appium-adb/commit/f3b5be1ae93f2cd6cc1039d6e8f8768a7d246491)) --- CHANGELOG.md | 12 ++++++++++++ package.json | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f3b631e..b2277d5a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +## [9.14.9](https://github.com/appium/appium-adb/compare/v9.14.8...v9.14.9) (2023-08-28) + + +### Bug Fixes + +* Move utf7 encoding primitives to the module codebase ([#689](https://github.com/appium/appium-adb/issues/689)) ([334c0b6](https://github.com/appium/appium-adb/commit/334c0b67d2e02d4c3216d7ecd09e9275cd44eb9a)) + + +### Miscellaneous Chores + +* Bump typescript from 5.0.4 to 5.2.2 ([#688](https://github.com/appium/appium-adb/issues/688)) ([f3b5be1](https://github.com/appium/appium-adb/commit/f3b5be1ae93f2cd6cc1039d6e8f8768a7d246491)) + ## [9.14.8](https://github.com/appium/appium-adb/compare/v9.14.7...v9.14.8) (2023-08-28) diff --git a/package.json b/package.json index 036d6ff5..4c7fd6fb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-adb", - "version": "9.14.8", + "version": "9.14.9", "description": "Android Debug Bridge interface", "main": "./build/index.js", "scripts": {