1- const parsePlist = require ( 'plist' ) . parse ;
21const parseBplist = require ( 'bplist-parser' ) . parseBuffer ;
32const cgbiToPng = require ( 'cgbi-to-png' ) ;
43
@@ -8,57 +7,77 @@ import { Zip } from './zip';
87const PlistName = / p a y l o a d \/ [ ^ / ] + ?.a p p \/ i n f o .p l i s t $ / i;
98const ProvisionName = / p a y l o a d \/ .+ ?\. a p p \/ e m b e d d e d .m o b i l e p r o v i s i o n / ;
109
11- export class IpaParser extends Zip {
12- parse ( ) : Promise < any > {
13- return new Promise ( ( resolve , reject ) => {
14- this . getEntries ( [ PlistName , ProvisionName ] )
15- . then ( ( buffers : any ) => {
16- if ( ! buffers [ PlistName as any ] ) {
17- throw new Error ( "Info.plist can't be found." ) ;
18- }
19- const plistInfo = this . _parsePlist ( buffers [ PlistName as any ] ) ;
20- const provisionInfo = this . _parseProvision (
21- buffers [ ProvisionName as any ] ,
22- ) ;
23- plistInfo . mobileProvision = provisionInfo ;
10+ type ParsePlist = ( content : string ) => Record < string , any > ;
11+
12+ let parsePlistPromise : Promise < ParsePlist > | undefined ;
2413
25- const iconRegex = new RegExp (
26- findIpaIconPath ( plistInfo ) . toLowerCase ( ) ,
27- ) ;
28- this . getEntry ( iconRegex )
29- . then ( ( iconBuffer : any ) => {
30- try {
31- plistInfo . icon = iconBuffer
32- ? getBase64FromBuffer ( cgbiToPng . revert ( iconBuffer ) )
33- : null ;
34- } catch ( err ) {
35- if ( isBrowser ( ) ) {
36- plistInfo . icon = iconBuffer
37- ? getBase64FromBuffer (
38- window . btoa ( String . fromCharCode ( ...iconBuffer ) ) ,
39- )
40- : null ;
41- } else {
42- plistInfo . icon = null ;
43- console . warn ( '[Warning] failed to parse icon: ' , err ) ;
44- }
45- }
46- resolve ( plistInfo ) ;
47- } )
48- . catch ( ( e : any ) => {
49- reject ( e ) ;
50- } ) ;
51- } )
52- . catch ( ( e : any ) => {
53- reject ( e ) ;
54- } ) ;
14+ function loadParsePlist ( ) : Promise < ParsePlist > {
15+ if ( ! parsePlistPromise ) {
16+ parsePlistPromise = Promise . resolve ( ) . then ( async ( ) => {
17+ try {
18+ return require ( 'plist' ) . parse as ParsePlist ;
19+ } catch ( requireError ) {
20+ const importModule = new Function (
21+ 'specifier' ,
22+ 'return import(specifier)' ,
23+ ) as ( specifier : string ) => Promise < {
24+ parse ?: ParsePlist ;
25+ default ?: { parse ?: ParsePlist } ;
26+ } > ;
27+ const plistModule = await importModule ( 'plist' ) ;
28+ const parsePlist = plistModule . parse ?? plistModule . default ?. parse ;
29+ if ( ! parsePlist ) {
30+ throw requireError ;
31+ }
32+ return parsePlist ;
33+ }
5534 } ) ;
5635 }
36+ return parsePlistPromise ;
37+ }
38+
39+ export class IpaParser extends Zip {
40+ async parse ( ) : Promise < any > {
41+ const parsePlist = await loadParsePlist ( ) ;
42+ const buffers = await this . getEntries ( [ PlistName , ProvisionName ] ) ;
43+ if ( ! buffers [ PlistName as any ] ) {
44+ throw new Error ( "Info.plist can't be found." ) ;
45+ }
46+ const plistInfo = this . _parsePlist (
47+ buffers [ PlistName as any ] as Buffer ,
48+ parsePlist ,
49+ ) ;
50+ const provisionInfo = this . _parseProvision (
51+ buffers [ ProvisionName as any ] as Buffer | undefined ,
52+ parsePlist ,
53+ ) ;
54+ plistInfo . mobileProvision = provisionInfo ;
55+
56+ const iconRegex = new RegExp ( findIpaIconPath ( plistInfo ) . toLowerCase ( ) ) ;
57+ const iconBuffer = await this . getEntry ( iconRegex ) ;
58+ try {
59+ plistInfo . icon = iconBuffer
60+ ? getBase64FromBuffer ( cgbiToPng . revert ( iconBuffer ) )
61+ : null ;
62+ } catch ( err ) {
63+ if ( isBrowser ( ) ) {
64+ plistInfo . icon = iconBuffer
65+ ? getBase64FromBuffer (
66+ window . btoa ( String . fromCharCode ( ...( iconBuffer as Buffer ) ) ) ,
67+ )
68+ : null ;
69+ } else {
70+ plistInfo . icon = null ;
71+ console . warn ( '[Warning] failed to parse icon: ' , err ) ;
72+ }
73+ }
74+ return plistInfo ;
75+ }
5776 /**
5877 * Parse plist
5978 * @param {Buffer } buffer // plist file's buffer
6079 */
61- private _parsePlist ( buffer : Buffer ) {
80+ private _parsePlist ( buffer : Buffer , parsePlist : ParsePlist ) {
6281 let result : any ;
6382 const bufferType = buffer [ 0 ] ;
6483 if ( bufferType === 60 || bufferType === 239 ) {
@@ -74,7 +93,7 @@ export class IpaParser extends Zip {
7493 * parse provision
7594 * @param {Buffer } buffer // provision file's buffer
7695 */
77- private _parseProvision ( buffer : Buffer | undefined ) {
96+ private _parseProvision ( buffer : Buffer | undefined , parsePlist : ParsePlist ) {
7897 let info : Record < string , any > = { } ;
7998 if ( buffer ) {
8099 let content = buffer . toString ( 'utf-8' ) ;
0 commit comments