1
0
mirror of https://gitcode.com/github-mirrors/react-native-update-cli.git synced 2025-09-16 01:41:37 +08:00
Code Issues Packages Projects Releases Wiki Activity GitHub Gitee
Files
react-native-update-cli/src/utils/app-info-parser/ipa.js
波仔糕 e98bcf504f cli modular refactor (#16)
* add logic to support SENTRY_PROPERTIES parameter

* remove update.json and meta.json files in ppk

* udpapte

* refactor modles

* update

* add package-module file

* update

* update readme file

* modifu cli.json file

* fix command issues

* improve version workflow logic

* udpate

* update

* update

* update

* udpate

* udpate

* add example

* update readme file

* udpate version

* change logic to use pushy command uniformly
2025-07-24 11:46:20 +08:00

105 lines
3.2 KiB
JavaScript

const parsePlist = require('plist').parse;
const parseBplist = require('bplist-parser').parseBuffer;
const cgbiToPng = require('cgbi-to-png');
const Zip = require('./zip');
const { findIpaIconPath, getBase64FromBuffer, isBrowser } = require('./utils');
const PlistName = /payload\/[^\/]+?.app\/info.plist$/i;
const ProvisionName = /payload\/.+?\.app\/embedded.mobileprovision/;
class IpaParser extends Zip {
/**
* parser for parsing .ipa file
* @param {String | File | Blob} file // file's path in Node, instance of File or Blob in Browser
*/
constructor(file) {
super(file);
if (!(this instanceof IpaParser)) {
return new IpaParser(file);
}
}
parse() {
return new Promise((resolve, reject) => {
this.getEntries([PlistName, ProvisionName])
.then((buffers) => {
if (!buffers[PlistName]) {
throw new Error("Info.plist can't be found.");
}
const plistInfo = this._parsePlist(buffers[PlistName]);
// parse mobile provision
const provisionInfo = this._parseProvision(buffers[ProvisionName]);
plistInfo.mobileProvision = provisionInfo;
// find icon path and parse icon
const iconRegex = new RegExp(
findIpaIconPath(plistInfo).toLowerCase(),
);
this.getEntry(iconRegex)
.then((iconBuffer) => {
try {
// In general, the ipa file's icon has been specially processed, should be converted
plistInfo.icon = iconBuffer
? getBase64FromBuffer(cgbiToPng.revert(iconBuffer))
: null;
} catch (err) {
if (isBrowser()) {
// Normal conversion in other cases
plistInfo.icon = iconBuffer
? getBase64FromBuffer(
window.btoa(String.fromCharCode(...iconBuffer)),
)
: null;
} else {
plistInfo.icon = null;
console.warn('[Warning] failed to parse icon: ', err);
}
}
resolve(plistInfo);
})
.catch((e) => {
reject(e);
});
})
.catch((e) => {
reject(e);
});
});
}
/**
* Parse plist
* @param {Buffer} buffer // plist file's buffer
*/
_parsePlist(buffer) {
let result;
const bufferType = buffer[0];
if (bufferType === 60 || bufferType === '<' || bufferType === 239) {
result = parsePlist(buffer.toString());
} else if (bufferType === 98) {
result = parseBplist(buffer)[0];
} else {
throw new Error('Unknown plist buffer type.');
}
return result;
}
/**
* parse provision
* @param {Buffer} buffer // provision file's buffer
*/
_parseProvision(buffer) {
let info = {};
if (buffer) {
let content = buffer.toString('utf-8');
const firstIndex = content.indexOf('<?xml');
const endIndex = content.indexOf('</plist>');
content = content.slice(firstIndex, endIndex + 8);
if (content) {
info = parsePlist(content);
}
}
return info;
}
}
module.exports = IpaParser;