├── .env ├── LICENSE ├── README.md ├── app.js ├── logs ├── combined.log └── error.log ├── package-lock.json ├── package.json ├── uploads ├── mp │ └── .empty ├── p12 │ └── .empty ├── plist │ └── .empty ├── signed │ └── .empty └── temp │ └── .empty └── zsign-worker.js /.env: -------------------------------------------------------------------------------- 1 | # Server and Upload Config 2 | PORT=4500 3 | UPLOAD_URL=https://api.ipasign.pro/ 4 | DEFAULT_IPA_PATH=./Portal-1.9.0.ipa 5 | 6 | # Encryption Key (64 hex chars => 32 bytes) 7 | ENCRYPTION_KEY=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef 8 | 9 | # Rate Limiting 10 | RATE_LIMIT_WINDOW_MS=900000 11 | RATE_LIMIT_MAX=100 12 | 13 | # Logging 14 | LOG_LEVEL=info 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Daisuke Bauza 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # IPA Signing API (ALL CODE WAS WRITTEN USING CHATGPT O1 MINI/O1 (and O3 mini >~<) shoutout to you :3) 2 | 3 | ## Max IPA upload size is 2GB you can change that in the code if you wanna use it for your own site/locally 4 | 5 | ## HOW TO INSTALL 6 | 7 | 1. Install Zsign 8 | ```bash 9 | sudo apt-get install -y git g++ pkg-config libssl-dev libminizip-dev 10 | git clone https://github.com/zhlynn/zsign.git 11 | cd zsign/build/linux 12 | make clean && make 13 | sudo cp ../../bin/zsign /usr/local/bin/zsign 14 | ``` 15 | 16 | 2. Clone this repo 17 | ```bash 18 | git clone https://github.com/daisuke1227/DaiSign-API.git 19 | cd DaiSign-API 20 | ``` 21 | 3. Install NodeJS/NPM 22 | ```bash 23 | sudo apt install nodejs -y 24 | sudo apt install npm -y 25 | ``` 26 | 4. Update NodeJS 27 | ```bash 28 | npm install -g n 29 | n latest 30 | ``` 31 | 5. Install Node modules 32 | ```bash 33 | npm install 34 | ``` 35 | 6. rename .env and put all your configuration in there 36 | 37 | 7. Your all done yay! now run it 38 | ```bash 39 | node app.js 40 | ``` 41 | Welcome to the Signing API! This API allows you to upload an IPA file, a `.p12` certificate, and a provisioning profile, and it returns a link to install the signed app. 42 | 43 | ## Features 44 | - Upload IPA files for signing. 45 | - Use `.p12` certificates and provisioning profiles to sign the app. 46 | - Get an install link for the signed IPA. 47 | 48 | ## How It Works 49 | 1. Send a POST request to `/sign` with the required files. 50 | 2. The server processes the files and signs the IPA. 51 | 3. Receive an install link to download and install the signed app. 52 | 53 | ### Using this locally 54 | If you wanna use this for your own site then change this line of the app.js ```const UPLOAD_URL = 'https://yoursite.com/'; // Update to your actual domain``` and just follow the tutorial using your own site (this part was written by Daisuke after post) 55 | 56 | ### Changing default IPA 57 | In the app.js code if you dont upload an ipa a ipa will automatically be used you can change that in ```const DEFAULT_IPA_PATH = path.join(__dirname, 'Portal-1.9.0.ipa'); // Ensure this file exists``` this checks if the ipa is even there so if someone doesnt upload an ipa this ipa will be used in your code you can make the ipa required so you can bypass this 58 | 59 | ## API Endpoint 60 | 61 | ### POST `/sign` 62 | 63 | #### Parameters 64 | 65 | | Name | Type | Required | Description | 66 | |------------------|--------|----------|--------------------------------------------------| 67 | | `ipa` | File | No | The IPA file to be signed. Optional if default IPA is used. | 68 | | `p12` | File | Yes | The `.p12` certificate file for signing. | 69 | | `mobileprovision` | File | Yes | The provisioning profile file. | 70 | | `p12_password` | String | No | The password for the `.p12` certificate (if required). | 71 | 72 | ## Example Usage 73 | 74 | ### Curl 75 | ```bash 76 | curl -X POST https://api.ipasign.pro/sign \ 77 | -F "ipa=@/path/to/app.ipa" \ 78 | -F "p12=@/path/to/cert.p12" \ 79 | -F "mobileprovision=@/path/to/profile.mobileprovision" \ 80 | -F "p12_password=your_password" 81 | ``` 82 | ### Python 83 | ```python 84 | import requests 85 | 86 | url = "https://api.ipasign.pro/sign" 87 | files = { 88 | 'ipa': open('/path/to/app.ipa', 'rb'), 89 | 'p12': open('/path/to/cert.p12', 'rb'), 90 | 'mobileprovision': open('/path/to/profile.mobileprovision', 'rb'), 91 | } 92 | data = {'p12_password': 'your_password'} 93 | 94 | response = requests.post(url, files=files, data=data) 95 | print(response.json()) 96 | ``` 97 | ### JavaScript (Node.js) 98 | ```javascript 99 | const FormData = require('form-data'); 100 | const axios = require('axios'); 101 | const fs = require('fs'); 102 | 103 | const form = new FormData(); 104 | form.append('ipa', fs.createReadStream('/path/to/app.ipa')); 105 | form.append('p12', fs.createReadStream('/path/to/cert.p12')); 106 | form.append('mobileprovision', fs.createReadStream('/path/to/profile.mobileprovision')); 107 | form.append('p12_password', 'your_password'); 108 | 109 | axios.post('https://api.ipasign.pro/sign', form, { 110 | headers: form.getHeaders(), 111 | }) 112 | .then(response => console.log(response.data)) 113 | .catch(error => console.error(error)); 114 | ``` 115 | 116 | ### HTML/JS (use for websites and a starting base) 117 | ```html 118 | 119 | 120 | 121 | 122 | 123 | IPA Signer 124 | 125 | 126 |

IPA Signer

127 |
128 |

129 |
130 | 131 |

132 |

133 |
134 | 135 |

136 |

137 |
138 | 139 |

140 |

141 |
142 | 143 |

144 |

145 | 146 |

147 |
148 | 149 | 150 |
151 | 152 | 216 | 217 | 218 | ``` 219 | ### Example Response 220 | ``` 221 | { 222 | "installLink": "itms-services://?action=download-manifest&url=https://api.ipasign.pro/plist/example.plist" 223 | } 224 | ``` 225 | Field Description 226 | installLink The link to download and install the signed app. 227 | 228 | Common Errors 229 | 230 | Missing Required Files 231 | 232 | { 233 | "error": "P12 and MobileProvision files are required." 234 | } 235 | 236 | • Cause: You did not upload the .p12 or .mobileprovision file. 237 | • Fix: Ensure both files are included in your request. 238 | 239 | Notes 240 | • The ipa file is optional. If not provided, the default IPA will be used. 241 | • The p12_password is only required if your certificate has a password. 242 | 243 | Credits 244 | • API Developed By: Daisuke 245 | • Documentation Assistance: ChatGPT 246 | 247 | Questions or Issues? 248 | 249 | If you have any questions or run into issues, feel free to reach out to me on [Discord](https://discord.com/users/630151942135480370) or [Telegram](https://t.me/dai1228) 250 | 251 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config(); 2 | const express = require('express'); 3 | const multer = require('multer'); 4 | const fs = require('fs'); 5 | const fsp = fs.promises; 6 | const path = require('path'); 7 | const { exec } = require('child_process'); 8 | const { Worker } = require('worker_threads'); 9 | const AdmZip = require('adm-zip'); 10 | const plist = require('plist'); 11 | const bplistParser = require('bplist-parser'); 12 | const cors = require('cors'); 13 | const crypto = require('crypto'); 14 | const rateLimit = require('express-rate-limit'); 15 | const winston = require('winston'); 16 | const forge = require('node-forge'); 17 | 18 | const { 19 | PORT = 4500, 20 | UPLOAD_URL = 'https://yoursite.com/', 21 | DEFAULT_IPA_PATH, 22 | ENCRYPTION_KEY, 23 | RATE_LIMIT_WINDOW_MS = 900000, 24 | RATE_LIMIT_MAX = 100, 25 | LOG_LEVEL = 'info', 26 | } = process.env; 27 | 28 | if (!ENCRYPTION_KEY || Buffer.from(ENCRYPTION_KEY, 'hex').length !== 32) { 29 | console.error('Error: ENCRYPTION_KEY must be set in .env and be 64 hex chars (32 bytes).'); 30 | process.exit(1); 31 | } 32 | 33 | if (DEFAULT_IPA_PATH && fs.existsSync(DEFAULT_IPA_PATH)) { 34 | console.log(`Default IPA found at: ${DEFAULT_IPA_PATH}`); 35 | } else if (DEFAULT_IPA_PATH) { 36 | console.warn(`Warning: DEFAULT_IPA_PATH is set to "${DEFAULT_IPA_PATH}" but file not found.`); 37 | } 38 | 39 | const WORK_DIR = path.join(__dirname, 'uploads'); 40 | const REQUIRED_DIRS = ['p12', 'mp', 'temp', 'signed', 'plist']; 41 | const logDir = path.join(__dirname, 'logs'); 42 | 43 | if (!fs.existsSync(logDir)) fs.mkdirSync(logDir); 44 | 45 | const logger = winston.createLogger({ 46 | level: LOG_LEVEL, 47 | format: winston.format.combine( 48 | winston.format.timestamp(), 49 | winston.format.printf(({ level, message, timestamp }) => `[${timestamp}] ${level.toUpperCase()}: ${message}`) 50 | ), 51 | transports: [ 52 | new winston.transports.File({ filename: path.join(logDir, 'error.log'), level: 'error' }), 53 | new winston.transports.File({ filename: path.join(logDir, 'combined.log') }), 54 | ], 55 | }); 56 | 57 | logger.add(new winston.transports.Console({ format: winston.format.simple() })); 58 | 59 | const app = express(); 60 | app.use(express.urlencoded({ extended: true })); 61 | app.use(cors()); 62 | 63 | const limiter = rateLimit({ 64 | windowMs: parseInt(RATE_LIMIT_WINDOW_MS, 10), 65 | max: parseInt(RATE_LIMIT_MAX, 10), 66 | standardHeaders: true, 67 | legacyHeaders: false, 68 | }); 69 | app.use(limiter); 70 | 71 | for (const dir of REQUIRED_DIRS) { 72 | const dirPath = path.join(WORK_DIR, dir); 73 | if (!fs.existsSync(dirPath)) { 74 | fs.mkdirSync(dirPath, { recursive: true }); 75 | logger.info(`Created directory: ${dirPath}`); 76 | } 77 | } 78 | 79 | app.use(express.static(path.join(__dirname, 'public'))); 80 | app.use('/signed', express.static(path.join(WORK_DIR, 'signed'))); 81 | app.use('/plist', express.static(path.join(WORK_DIR, 'plist'))); 82 | 83 | const upload = multer({ 84 | dest: path.join(WORK_DIR, 'temp'), 85 | limits: { fileSize: 2 * 1024 * 1024 * 1024 }, 86 | fileFilter: (req, file, cb) => { 87 | const allowedTypes = ['.ipa', '.p12', '.mobileprovision']; 88 | const ext = path.extname(file.originalname).toLowerCase(); 89 | if (allowedTypes.includes(ext)) cb(null, true); 90 | else cb(new Error('Invalid file type. Only .ipa, .p12, and .mobileprovision are allowed.')); 91 | }, 92 | }); 93 | 94 | function generateRandomSuffix() { 95 | const randomStr = Math.random().toString(36).substring(2, 8); 96 | return `${Date.now()}_${randomStr}`; 97 | } 98 | 99 | function sanitizeFilename(name) { 100 | return name.replace(/[^a-zA-Z0-9_-]/g, ''); 101 | } 102 | 103 | const algorithm = 'aes-256-cbc'; 104 | const key = Buffer.from(ENCRYPTION_KEY, 'hex'); 105 | const ivLength = 16; 106 | 107 | function encrypt(text) { 108 | const iv = crypto.randomBytes(ivLength); 109 | const cipher = crypto.createCipheriv(algorithm, key, iv); 110 | let encrypted = cipher.update(text, 'utf8', 'hex'); 111 | encrypted += cipher.final('hex'); 112 | return `${iv.toString('hex')}:${encrypted}`; 113 | } 114 | 115 | function decrypt(encryptedText) { 116 | const [ivStr, encrypted] = encryptedText.split(':'); 117 | if (!ivStr || !encrypted) throw new Error('Invalid encrypted text format'); 118 | const iv = Buffer.from(ivStr, 'hex'); 119 | const decipher = crypto.createDecipheriv(algorithm, key, iv); 120 | let decrypted = decipher.update(encrypted, 'hex', 'utf8'); 121 | decrypted += decipher.final('utf8'); 122 | return decrypted; 123 | } 124 | 125 | function generateManifestPlist(ipaUrl, bundleId, bundleVersion, displayName) { 126 | const defaultBundleId = 'com.example.default'; 127 | return ` 128 | 130 | 131 | 132 | items 133 | 134 | 135 | assets 136 | 137 | 138 | kind 139 | software-package 140 | url 141 | ${ipaUrl} 142 | 143 | 144 | kind 145 | display-image 146 | needs-shine 147 | 148 | url 149 | https://raw.githubusercontent.com/daisuke1227/RevengeUpdates/refs/heads/main/IMG_0651.png 150 | 151 | 152 | kind 153 | full-size-image 154 | needs-shine 155 | 156 | url 157 | https://raw.githubusercontent.com/daisuke1227/RevengeUpdates/refs/heads/main/IMG_0651.png 158 | 159 | 160 | metadata 161 | 162 | bundle-identifier 163 | ${bundleId || defaultBundleId} 164 | bundle-version 165 | ${bundleVersion} 166 | kind 167 | software 168 | title 169 | ${displayName} 170 | 171 | 172 | 173 | 174 | `; 175 | } 176 | 177 | function execPromise(cmd) { 178 | return new Promise((resolve, reject) => { 179 | exec(cmd, (error, stdout, stderr) => { 180 | if (error) { 181 | logger.error(`Command failed: ${cmd}`); 182 | logger.error(`stderr: ${stderr}`); 183 | return reject(new Error(stderr || error.message)); 184 | } 185 | logger.info(`Command output: ${stdout}`); 186 | resolve(stdout.trim()); 187 | }); 188 | }); 189 | } 190 | 191 | async function checkCertificateValidityAndCompatibility(p12Path, password = '', mpPath) { 192 | try { 193 | const p12Buffer = await fsp.readFile(p12Path); 194 | const p12Der = p12Buffer.toString('binary'); 195 | const p12Asn1 = forge.asn1.fromDer(p12Der); 196 | const p12 = forge.pkcs12.pkcs12FromAsn1(p12Asn1, password); 197 | const certBags = p12.getBags({ bagType: forge.pki.oids.certBag })[forge.pki.oids.certBag]; 198 | if (!certBags || certBags.length === 0) throw new Error('No certificate found in the p12 file.'); 199 | const cert = certBags[0].cert; 200 | const certAsn1 = forge.pki.certificateToAsn1(cert); 201 | const derCert = forge.asn1.toDer(certAsn1).getBytes(); 202 | const p12Fingerprint = forge.md.sha1.create().update(derCert).digest().toHex(); 203 | const mpContent = await fsp.readFile(mpPath, 'utf8'); 204 | const plistStart = mpContent.indexOf(''); 206 | if (plistStart === -1 || plistEnd === -1) throw new Error('Invalid mobileprovision file; unable to extract plist data.'); 207 | const plistStr = mpContent.substring(plistStart, plistEnd + 8); 208 | const mpPlist = plist.parse(plistStr); 209 | if (!mpPlist.DeveloperCertificates || !Array.isArray(mpPlist.DeveloperCertificates)) throw new Error('DeveloperCertificates not found in mobileprovision file.'); 210 | let matchFound = false; 211 | for (const devCertData of mpPlist.DeveloperCertificates) { 212 | let devCertBytes; 213 | if (Buffer.isBuffer(devCertData)) devCertBytes = devCertData.toString('binary'); 214 | else if (typeof devCertData === 'string') devCertBytes = Buffer.from(devCertData, 'base64').toString('binary'); 215 | else continue; 216 | try { 217 | const devCertAsn1 = forge.asn1.fromDer(devCertBytes); 218 | const devCert = forge.pki.certificateFromAsn1(devCertAsn1); 219 | const devDer = forge.asn1.toDer(forge.pki.certificateToAsn1(devCert)).getBytes(); 220 | const devFingerprint = forge.md.sha1.create().update(devDer).digest().toHex(); 221 | if (devFingerprint === p12Fingerprint) { 222 | matchFound = true; 223 | break; 224 | } 225 | } catch (err) { 226 | continue; 227 | } 228 | } 229 | if (!matchFound) throw new Error('The certificate in the p12 file does not match any certificate in the mobileprovision file.'); 230 | } catch (err) { 231 | throw new Error('Invalid certificate or password, or incompatible mobileprovision: ' + err.message); 232 | } 233 | } 234 | 235 | function signIpaInWorker({ p12Path, p12Password, mpPath, ipaPath, signedIpaPath }) { 236 | return new Promise((resolve, reject) => { 237 | const workerData = { p12Path, p12Password, mpPath, ipaPath, signedIpaPath }; 238 | const worker = new Worker(path.join(__dirname, 'zsign-worker.js'), { workerData }); 239 | worker.on('message', (message) => { 240 | if (message.status === 'ok') resolve(message); 241 | else reject(new Error(message.error)); 242 | }); 243 | worker.on('error', (err) => reject(err)); 244 | worker.on('exit', (code) => { 245 | if (code !== 0) reject(new Error(`Worker stopped with exit code ${code}`)); 246 | }); 247 | }); 248 | } 249 | 250 | app.post( 251 | '/sign', 252 | upload.fields([ 253 | { name: 'ipa', maxCount: 1 }, 254 | { name: 'p12', maxCount: 1 }, 255 | { name: 'mobileprovision', maxCount: 1 }, 256 | ]), 257 | async (req, res) => { 258 | logger.info('Sign Request Received'); 259 | let uniqueSuffix; 260 | let ipaPath; 261 | let p12Path; 262 | let mpPath; 263 | let signedIpaPath; 264 | try { 265 | if (!req.files?.p12 || !req.files?.mobileprovision) { 266 | return res.status(400).json({ error: 'P12 and MobileProvision files are required.' }); 267 | } 268 | if (req.files.ipa) { 269 | uniqueSuffix = generateRandomSuffix(); 270 | ipaPath = path.join(WORK_DIR, 'temp', `input_${uniqueSuffix}.ipa`); 271 | await fsp.rename(req.files.ipa[0].path, ipaPath); 272 | logger.info(`Received IPA: ${req.files.ipa[0].originalname}`); 273 | } else if (DEFAULT_IPA_PATH && fs.existsSync(DEFAULT_IPA_PATH)) { 274 | uniqueSuffix = generateRandomSuffix(); 275 | ipaPath = DEFAULT_IPA_PATH; 276 | logger.info(`No IPA uploaded. Using default IPA: ${ipaPath}`); 277 | } else { 278 | return res.status(400).json({ error: 'An IPA file is required. No IPA was uploaded, and no valid default IPA is available.' }); 279 | } 280 | const p12Password = (req.body.p12_password || '').trim(); 281 | const saveCert = req.body.save_cert === 'on'; 282 | if (!uniqueSuffix) uniqueSuffix = generateRandomSuffix(); 283 | p12Path = path.join(WORK_DIR, 'p12', `cert_${uniqueSuffix}.p12`); 284 | mpPath = path.join(WORK_DIR, 'mp', `app_${uniqueSuffix}.mobileprovision`); 285 | await fsp.rename(req.files.p12[0].path, p12Path); 286 | await fsp.rename(req.files.mobileprovision[0].path, mpPath); 287 | logger.info(saveCert ? `Saved certs permanently: p12 -> ${p12Path}, mp -> ${mpPath}` : `Using temporary certs: p12 -> ${p12Path}, mp -> ${mpPath}`); 288 | try { 289 | await checkCertificateValidityAndCompatibility(p12Path, p12Password, mpPath); 290 | } catch (certErr) { 291 | return res.status(400).json({ error: certErr.message || 'Invalid certificate or password.' }); 292 | } 293 | if (saveCert && p12Password) { 294 | const encryptedPwd = encrypt(p12Password); 295 | const pwdPath = path.join(WORK_DIR, 'p12', `password_${uniqueSuffix}.enc`); 296 | await fsp.writeFile(pwdPath, encryptedPwd, 'utf8'); 297 | logger.info(`Saved encrypted password at: ${pwdPath}`); 298 | } 299 | signedIpaPath = path.join(WORK_DIR, 'signed', `signed_${uniqueSuffix}.ipa`); 300 | try { 301 | await signIpaInWorker({ p12Path, p12Password, mpPath, ipaPath, signedIpaPath }); 302 | } catch (zsignErr) { 303 | const errorMsg = zsignErr.message.toLowerCase(); 304 | if (errorMsg.includes('pkcs12') || errorMsg.includes('password') || errorMsg.includes('mac verify error')) { 305 | return res.status(400).json({ error: 'Wrong P12 password or invalid certificate. Check your .p12.' }); 306 | } 307 | if (errorMsg.includes('ipa') || errorMsg.includes('error parsing')) { 308 | return res.status(400).json({ error: 'Failed to sign. The IPA might be corrupted or invalid.' }); 309 | } 310 | logger.error(`zsign failed: ${zsignErr}`); 311 | return res.status(500).json({ error: 'Signing process failed. Check server logs.', details: zsignErr.message }); 312 | } 313 | logger.info(`Signed IPA successfully created at: ${signedIpaPath}`); 314 | const zipSigned = new AdmZip(signedIpaPath); 315 | const zipEntries = zipSigned.getEntries(); 316 | let appFolderName = ''; 317 | for (const entry of zipEntries) { 318 | const parts = entry.entryName.split('/'); 319 | if (parts.length > 1 && parts[1].endsWith('.app')) { 320 | appFolderName = parts[1]; 321 | break; 322 | } 323 | } 324 | if (!appFolderName) return res.status(500).json({ error: "Couldn't find .app directory in the signed IPA." }); 325 | const plistEntryPath = `Payload/${appFolderName}/Info.plist`; 326 | const plistEntry = zipSigned.getEntry(plistEntryPath); 327 | if (!plistEntry) return res.status(500).json({ error: 'Info.plist not found in the signed IPA.' }); 328 | let plistData; 329 | const plistBuffer = plistEntry.getData(); 330 | try { 331 | plistData = plist.parse(plistBuffer.toString('utf8')); 332 | } catch (xmlErr) { 333 | try { 334 | const parsed = await bplistParser.parseBuffer(plistBuffer); 335 | if (parsed && parsed.length > 0) plistData = parsed[0]; 336 | else throw new Error('Parsed binary plist is empty.'); 337 | } catch (binErr) { 338 | logger.error('Both XML and binary plist parsing failed.'); 339 | return res.status(500).json({ error: 'Failed to parse Info.plist from signed IPA.' }); 340 | } 341 | } 342 | const bundleId = plistData.CFBundleIdentifier || 'com.example.unknown'; 343 | const bundleVersion = plistData.CFBundleVersion || '1.0.0'; 344 | const displayName = plistData.CFBundleDisplayName || plistData.CFBundleName || 'App'; 345 | const ipaUrl = new URL(`signed/${path.basename(signedIpaPath)}`, UPLOAD_URL).toString(); 346 | const manifest = generateManifestPlist(ipaUrl, bundleId, bundleVersion, displayName); 347 | const filename = `${sanitizeFilename(displayName)}_${uniqueSuffix}.plist`; 348 | const plistSavePath = path.join(WORK_DIR, 'plist', filename); 349 | await fsp.writeFile(plistSavePath, manifest, 'utf8'); 350 | const manifestUrl = new URL(`plist/${filename}`, UPLOAD_URL).toString(); 351 | const installLink = `itms-services://?action=download-manifest&url=${manifestUrl}`; 352 | res.json({ installLink }); 353 | } catch (err) { 354 | logger.error(`Error during signing process: ${err}`); 355 | return res.status(500).json({ error: 'Unexpected error during signing. Check server logs.', details: err.message }); 356 | } finally { 357 | try { 358 | if (uniqueSuffix) { 359 | if (req.files?.ipa && ipaPath !== DEFAULT_IPA_PATH && fs.existsSync(ipaPath)) { 360 | await fsp.unlink(ipaPath); 361 | logger.info(`Removed uploaded IPA: ${ipaPath}`); 362 | } 363 | if (req.files?.p12 && req.files?.mobileprovision) { 364 | const notSaving = req.body.save_cert !== 'on'; 365 | if (notSaving && fs.existsSync(p12Path)) { 366 | await fsp.unlink(p12Path); 367 | logger.info(`Removed temporary p12: ${p12Path}`); 368 | } 369 | if (notSaving && fs.existsSync(mpPath)) { 370 | await fsp.unlink(mpPath); 371 | logger.info(`Removed temporary mobileprovision: ${mpPath}`); 372 | } 373 | } 374 | if (signedIpaPath && fs.existsSync(signedIpaPath)) { 375 | await fsp.unlink(signedIpaPath); 376 | logger.info(`Removed signed IPA file: ${signedIpaPath}`); 377 | } 378 | } 379 | } catch (cleanupErr) { 380 | logger.error(`Error during cleanup: ${cleanupErr}`); 381 | } 382 | } 383 | } 384 | ); 385 | 386 | function multerErrorHandler(err, req, res, next) { 387 | if (err instanceof multer.MulterError) { 388 | if (err.code === 'LIMIT_FILE_SIZE') return res.status(413).json({ error: 'File too large. Maximum allowed size is 2GB.' }); 389 | return res.status(400).json({ error: err.message }); 390 | } 391 | if (err) return res.status(500).json({ error: 'An unexpected error occurred.' }); 392 | return next(); 393 | } 394 | app.use(multerErrorHandler); 395 | 396 | app.listen(PORT, () => { 397 | logger.info(`Server running on port ${PORT}.`); 398 | }); 399 | 400 | setInterval(async () => { 401 | try { 402 | const subdirs = await fsp.readdir(WORK_DIR); 403 | for (const subdir of subdirs) { 404 | const subdirPath = path.join(WORK_DIR, subdir); 405 | const stats = await fsp.stat(subdirPath); 406 | if (!stats.isDirectory()) continue; 407 | const files = await fsp.readdir(subdirPath); 408 | for (const file of files) { 409 | const filePath = path.join(subdirPath, file); 410 | const fileStats = await fsp.stat(filePath); 411 | if (fileStats.isFile()) await fsp.unlink(filePath); 412 | } 413 | } 414 | logger.info('Uploads directory cleanup completed.'); 415 | } catch (err) { 416 | logger.error('Error during scheduled cleanup: ' + err.message); 417 | } 418 | }, 60 * 60 * 1000); 419 | -------------------------------------------------------------------------------- /logs/combined.log: -------------------------------------------------------------------------------- 1 | [2025-04-13T19:49:17.111Z] INFO: Server running on port 4600. 2 | [2025-04-13T19:56:08.829Z] INFO: Server running on port 4500. 3 | [2025-04-13T19:56:24.186Z] INFO: Server running on port 4500. 4 | [2025-04-13T19:57:16.585Z] INFO: Sign Request Received 5 | [2025-04-13T19:57:16.601Z] INFO: Received IPA: com.kdt.livecontainer.ipa 6 | [2025-04-13T19:57:16.608Z] INFO: Using temporary certs: p12 -> /home/dai1228/why/DaiSign-API/uploads/p12/cert_1744574236597_y2vy7m.p12, mp -> /home/dai1228/why/DaiSign-API/uploads/mp/app_1744574236597_y2vy7m.mobileprovision 7 | [2025-04-13T19:57:17.612Z] INFO: Signed IPA successfully created at: /home/dai1228/why/DaiSign-API/uploads/signed/signed_1744574236597_y2vy7m.ipa 8 | [2025-04-13T19:57:17.843Z] INFO: Removed uploaded IPA: /home/dai1228/why/DaiSign-API/uploads/temp/input_1744574236597_y2vy7m.ipa 9 | [2025-04-13T19:57:17.897Z] INFO: Removed temporary p12: /home/dai1228/why/DaiSign-API/uploads/p12/cert_1744574236597_y2vy7m.p12 10 | [2025-04-13T19:57:17.903Z] INFO: Removed temporary mobileprovision: /home/dai1228/why/DaiSign-API/uploads/mp/app_1744574236597_y2vy7m.mobileprovision 11 | -------------------------------------------------------------------------------- /logs/error.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daisuke1227/DaiSign-API/6239d4aa089680d882c315285d493daf865e179f/logs/error.log -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "daisign-api", 3 | "version": "1.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "daisign-api", 9 | "version": "1.0.0", 10 | "license": "ISC", 11 | "dependencies": { 12 | "adm-zip": "^0.5.16", 13 | "bplist-parser": "^0.3.2", 14 | "cors": "^2.8.5", 15 | "dotenv": "^16.4.7", 16 | "express": "^4.21.2", 17 | "express-rate-limit": "^7.5.0", 18 | "multer": "^1.4.5-lts.1", 19 | "node-forge": "^1.3.1", 20 | "plist": "^3.1.0", 21 | "winston": "^3.17.0" 22 | }, 23 | "devDependencies": {} 24 | }, 25 | "node_modules/@colors/colors": { 26 | "version": "1.6.0", 27 | "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", 28 | "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==", 29 | "license": "MIT", 30 | "engines": { 31 | "node": ">=0.1.90" 32 | } 33 | }, 34 | "node_modules/@dabh/diagnostics": { 35 | "version": "2.0.3", 36 | "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz", 37 | "integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==", 38 | "license": "MIT", 39 | "dependencies": { 40 | "colorspace": "1.1.x", 41 | "enabled": "2.0.x", 42 | "kuler": "^2.0.0" 43 | } 44 | }, 45 | "node_modules/@types/triple-beam": { 46 | "version": "1.3.5", 47 | "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz", 48 | "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==", 49 | "license": "MIT" 50 | }, 51 | "node_modules/@xmldom/xmldom": { 52 | "version": "0.8.10", 53 | "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz", 54 | "integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==", 55 | "license": "MIT", 56 | "engines": { 57 | "node": ">=10.0.0" 58 | } 59 | }, 60 | "node_modules/accepts": { 61 | "version": "1.3.8", 62 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", 63 | "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", 64 | "license": "MIT", 65 | "dependencies": { 66 | "mime-types": "~2.1.34", 67 | "negotiator": "0.6.3" 68 | }, 69 | "engines": { 70 | "node": ">= 0.6" 71 | } 72 | }, 73 | "node_modules/adm-zip": { 74 | "version": "0.5.16", 75 | "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.16.tgz", 76 | "integrity": "sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ==", 77 | "license": "MIT", 78 | "engines": { 79 | "node": ">=12.0" 80 | } 81 | }, 82 | "node_modules/append-field": { 83 | "version": "1.0.0", 84 | "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", 85 | "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==", 86 | "license": "MIT" 87 | }, 88 | "node_modules/array-flatten": { 89 | "version": "1.1.1", 90 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 91 | "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", 92 | "license": "MIT" 93 | }, 94 | "node_modules/async": { 95 | "version": "3.2.6", 96 | "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", 97 | "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", 98 | "license": "MIT" 99 | }, 100 | "node_modules/base64-js": { 101 | "version": "1.5.1", 102 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", 103 | "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", 104 | "funding": [ 105 | { 106 | "type": "github", 107 | "url": "https://github.com/sponsors/feross" 108 | }, 109 | { 110 | "type": "patreon", 111 | "url": "https://www.patreon.com/feross" 112 | }, 113 | { 114 | "type": "consulting", 115 | "url": "https://feross.org/support" 116 | } 117 | ], 118 | "license": "MIT" 119 | }, 120 | "node_modules/big-integer": { 121 | "version": "1.6.52", 122 | "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", 123 | "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", 124 | "license": "Unlicense", 125 | "engines": { 126 | "node": ">=0.6" 127 | } 128 | }, 129 | "node_modules/body-parser": { 130 | "version": "1.20.3", 131 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", 132 | "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", 133 | "license": "MIT", 134 | "dependencies": { 135 | "bytes": "3.1.2", 136 | "content-type": "~1.0.5", 137 | "debug": "2.6.9", 138 | "depd": "2.0.0", 139 | "destroy": "1.2.0", 140 | "http-errors": "2.0.0", 141 | "iconv-lite": "0.4.24", 142 | "on-finished": "2.4.1", 143 | "qs": "6.13.0", 144 | "raw-body": "2.5.2", 145 | "type-is": "~1.6.18", 146 | "unpipe": "1.0.0" 147 | }, 148 | "engines": { 149 | "node": ">= 0.8", 150 | "npm": "1.2.8000 || >= 1.4.16" 151 | } 152 | }, 153 | "node_modules/bplist-parser": { 154 | "version": "0.3.2", 155 | "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.3.2.tgz", 156 | "integrity": "sha512-apC2+fspHGI3mMKj+dGevkGo/tCqVB8jMb6i+OX+E29p0Iposz07fABkRIfVUPNd5A5VbuOz1bZbnmkKLYF+wQ==", 157 | "license": "MIT", 158 | "dependencies": { 159 | "big-integer": "1.6.x" 160 | }, 161 | "engines": { 162 | "node": ">= 5.10.0" 163 | } 164 | }, 165 | "node_modules/buffer-from": { 166 | "version": "1.1.2", 167 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", 168 | "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", 169 | "license": "MIT" 170 | }, 171 | "node_modules/busboy": { 172 | "version": "1.6.0", 173 | "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", 174 | "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", 175 | "dependencies": { 176 | "streamsearch": "^1.1.0" 177 | }, 178 | "engines": { 179 | "node": ">=10.16.0" 180 | } 181 | }, 182 | "node_modules/bytes": { 183 | "version": "3.1.2", 184 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 185 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", 186 | "license": "MIT", 187 | "engines": { 188 | "node": ">= 0.8" 189 | } 190 | }, 191 | "node_modules/call-bind-apply-helpers": { 192 | "version": "1.0.1", 193 | "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz", 194 | "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==", 195 | "license": "MIT", 196 | "dependencies": { 197 | "es-errors": "^1.3.0", 198 | "function-bind": "^1.1.2" 199 | }, 200 | "engines": { 201 | "node": ">= 0.4" 202 | } 203 | }, 204 | "node_modules/call-bound": { 205 | "version": "1.0.3", 206 | "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz", 207 | "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==", 208 | "license": "MIT", 209 | "dependencies": { 210 | "call-bind-apply-helpers": "^1.0.1", 211 | "get-intrinsic": "^1.2.6" 212 | }, 213 | "engines": { 214 | "node": ">= 0.4" 215 | }, 216 | "funding": { 217 | "url": "https://github.com/sponsors/ljharb" 218 | } 219 | }, 220 | "node_modules/color": { 221 | "version": "3.2.1", 222 | "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", 223 | "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", 224 | "license": "MIT", 225 | "dependencies": { 226 | "color-convert": "^1.9.3", 227 | "color-string": "^1.6.0" 228 | } 229 | }, 230 | "node_modules/color-convert": { 231 | "version": "1.9.3", 232 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 233 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 234 | "license": "MIT", 235 | "dependencies": { 236 | "color-name": "1.1.3" 237 | } 238 | }, 239 | "node_modules/color-name": { 240 | "version": "1.1.3", 241 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 242 | "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", 243 | "license": "MIT" 244 | }, 245 | "node_modules/color-string": { 246 | "version": "1.9.1", 247 | "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", 248 | "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", 249 | "license": "MIT", 250 | "dependencies": { 251 | "color-name": "^1.0.0", 252 | "simple-swizzle": "^0.2.2" 253 | } 254 | }, 255 | "node_modules/colorspace": { 256 | "version": "1.1.4", 257 | "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz", 258 | "integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==", 259 | "license": "MIT", 260 | "dependencies": { 261 | "color": "^3.1.3", 262 | "text-hex": "1.0.x" 263 | } 264 | }, 265 | "node_modules/concat-stream": { 266 | "version": "1.6.2", 267 | "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", 268 | "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", 269 | "engines": [ 270 | "node >= 0.8" 271 | ], 272 | "license": "MIT", 273 | "dependencies": { 274 | "buffer-from": "^1.0.0", 275 | "inherits": "^2.0.3", 276 | "readable-stream": "^2.2.2", 277 | "typedarray": "^0.0.6" 278 | } 279 | }, 280 | "node_modules/content-disposition": { 281 | "version": "0.5.4", 282 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", 283 | "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", 284 | "license": "MIT", 285 | "dependencies": { 286 | "safe-buffer": "5.2.1" 287 | }, 288 | "engines": { 289 | "node": ">= 0.6" 290 | } 291 | }, 292 | "node_modules/content-type": { 293 | "version": "1.0.5", 294 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", 295 | "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", 296 | "license": "MIT", 297 | "engines": { 298 | "node": ">= 0.6" 299 | } 300 | }, 301 | "node_modules/cookie": { 302 | "version": "0.7.1", 303 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", 304 | "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", 305 | "license": "MIT", 306 | "engines": { 307 | "node": ">= 0.6" 308 | } 309 | }, 310 | "node_modules/cookie-signature": { 311 | "version": "1.0.6", 312 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 313 | "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", 314 | "license": "MIT" 315 | }, 316 | "node_modules/core-util-is": { 317 | "version": "1.0.3", 318 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", 319 | "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", 320 | "license": "MIT" 321 | }, 322 | "node_modules/cors": { 323 | "version": "2.8.5", 324 | "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", 325 | "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", 326 | "license": "MIT", 327 | "dependencies": { 328 | "object-assign": "^4", 329 | "vary": "^1" 330 | }, 331 | "engines": { 332 | "node": ">= 0.10" 333 | } 334 | }, 335 | "node_modules/debug": { 336 | "version": "2.6.9", 337 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 338 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 339 | "license": "MIT", 340 | "dependencies": { 341 | "ms": "2.0.0" 342 | } 343 | }, 344 | "node_modules/depd": { 345 | "version": "2.0.0", 346 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 347 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", 348 | "license": "MIT", 349 | "engines": { 350 | "node": ">= 0.8" 351 | } 352 | }, 353 | "node_modules/destroy": { 354 | "version": "1.2.0", 355 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", 356 | "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", 357 | "license": "MIT", 358 | "engines": { 359 | "node": ">= 0.8", 360 | "npm": "1.2.8000 || >= 1.4.16" 361 | } 362 | }, 363 | "node_modules/dotenv": { 364 | "version": "16.4.7", 365 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", 366 | "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==", 367 | "license": "BSD-2-Clause", 368 | "engines": { 369 | "node": ">=12" 370 | }, 371 | "funding": { 372 | "url": "https://dotenvx.com" 373 | } 374 | }, 375 | "node_modules/dunder-proto": { 376 | "version": "1.0.1", 377 | "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", 378 | "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", 379 | "license": "MIT", 380 | "dependencies": { 381 | "call-bind-apply-helpers": "^1.0.1", 382 | "es-errors": "^1.3.0", 383 | "gopd": "^1.2.0" 384 | }, 385 | "engines": { 386 | "node": ">= 0.4" 387 | } 388 | }, 389 | "node_modules/ee-first": { 390 | "version": "1.1.1", 391 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 392 | "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", 393 | "license": "MIT" 394 | }, 395 | "node_modules/enabled": { 396 | "version": "2.0.0", 397 | "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", 398 | "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==", 399 | "license": "MIT" 400 | }, 401 | "node_modules/encodeurl": { 402 | "version": "2.0.0", 403 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", 404 | "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", 405 | "license": "MIT", 406 | "engines": { 407 | "node": ">= 0.8" 408 | } 409 | }, 410 | "node_modules/es-define-property": { 411 | "version": "1.0.1", 412 | "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", 413 | "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", 414 | "license": "MIT", 415 | "engines": { 416 | "node": ">= 0.4" 417 | } 418 | }, 419 | "node_modules/es-errors": { 420 | "version": "1.3.0", 421 | "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", 422 | "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", 423 | "license": "MIT", 424 | "engines": { 425 | "node": ">= 0.4" 426 | } 427 | }, 428 | "node_modules/es-object-atoms": { 429 | "version": "1.0.0", 430 | "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", 431 | "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", 432 | "license": "MIT", 433 | "dependencies": { 434 | "es-errors": "^1.3.0" 435 | }, 436 | "engines": { 437 | "node": ">= 0.4" 438 | } 439 | }, 440 | "node_modules/escape-html": { 441 | "version": "1.0.3", 442 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 443 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", 444 | "license": "MIT" 445 | }, 446 | "node_modules/etag": { 447 | "version": "1.8.1", 448 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 449 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", 450 | "license": "MIT", 451 | "engines": { 452 | "node": ">= 0.6" 453 | } 454 | }, 455 | "node_modules/express": { 456 | "version": "4.21.2", 457 | "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", 458 | "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", 459 | "license": "MIT", 460 | "dependencies": { 461 | "accepts": "~1.3.8", 462 | "array-flatten": "1.1.1", 463 | "body-parser": "1.20.3", 464 | "content-disposition": "0.5.4", 465 | "content-type": "~1.0.4", 466 | "cookie": "0.7.1", 467 | "cookie-signature": "1.0.6", 468 | "debug": "2.6.9", 469 | "depd": "2.0.0", 470 | "encodeurl": "~2.0.0", 471 | "escape-html": "~1.0.3", 472 | "etag": "~1.8.1", 473 | "finalhandler": "1.3.1", 474 | "fresh": "0.5.2", 475 | "http-errors": "2.0.0", 476 | "merge-descriptors": "1.0.3", 477 | "methods": "~1.1.2", 478 | "on-finished": "2.4.1", 479 | "parseurl": "~1.3.3", 480 | "path-to-regexp": "0.1.12", 481 | "proxy-addr": "~2.0.7", 482 | "qs": "6.13.0", 483 | "range-parser": "~1.2.1", 484 | "safe-buffer": "5.2.1", 485 | "send": "0.19.0", 486 | "serve-static": "1.16.2", 487 | "setprototypeof": "1.2.0", 488 | "statuses": "2.0.1", 489 | "type-is": "~1.6.18", 490 | "utils-merge": "1.0.1", 491 | "vary": "~1.1.2" 492 | }, 493 | "engines": { 494 | "node": ">= 0.10.0" 495 | }, 496 | "funding": { 497 | "type": "opencollective", 498 | "url": "https://opencollective.com/express" 499 | } 500 | }, 501 | "node_modules/express-rate-limit": { 502 | "version": "7.5.0", 503 | "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.5.0.tgz", 504 | "integrity": "sha512-eB5zbQh5h+VenMPM3fh+nw1YExi5nMr6HUCR62ELSP11huvxm/Uir1H1QEyTkk5QX6A58pX6NmaTMceKZ0Eodg==", 505 | "license": "MIT", 506 | "engines": { 507 | "node": ">= 16" 508 | }, 509 | "funding": { 510 | "url": "https://github.com/sponsors/express-rate-limit" 511 | }, 512 | "peerDependencies": { 513 | "express": "^4.11 || 5 || ^5.0.0-beta.1" 514 | } 515 | }, 516 | "node_modules/fecha": { 517 | "version": "4.2.3", 518 | "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", 519 | "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==", 520 | "license": "MIT" 521 | }, 522 | "node_modules/finalhandler": { 523 | "version": "1.3.1", 524 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", 525 | "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", 526 | "license": "MIT", 527 | "dependencies": { 528 | "debug": "2.6.9", 529 | "encodeurl": "~2.0.0", 530 | "escape-html": "~1.0.3", 531 | "on-finished": "2.4.1", 532 | "parseurl": "~1.3.3", 533 | "statuses": "2.0.1", 534 | "unpipe": "~1.0.0" 535 | }, 536 | "engines": { 537 | "node": ">= 0.8" 538 | } 539 | }, 540 | "node_modules/fn.name": { 541 | "version": "1.1.0", 542 | "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", 543 | "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==", 544 | "license": "MIT" 545 | }, 546 | "node_modules/forwarded": { 547 | "version": "0.2.0", 548 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 549 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", 550 | "license": "MIT", 551 | "engines": { 552 | "node": ">= 0.6" 553 | } 554 | }, 555 | "node_modules/fresh": { 556 | "version": "0.5.2", 557 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 558 | "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", 559 | "license": "MIT", 560 | "engines": { 561 | "node": ">= 0.6" 562 | } 563 | }, 564 | "node_modules/function-bind": { 565 | "version": "1.1.2", 566 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", 567 | "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", 568 | "license": "MIT", 569 | "funding": { 570 | "url": "https://github.com/sponsors/ljharb" 571 | } 572 | }, 573 | "node_modules/get-intrinsic": { 574 | "version": "1.2.6", 575 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.6.tgz", 576 | "integrity": "sha512-qxsEs+9A+u85HhllWJJFicJfPDhRmjzoYdl64aMWW9yRIJmSyxdn8IEkuIM530/7T+lv0TIHd8L6Q/ra0tEoeA==", 577 | "license": "MIT", 578 | "dependencies": { 579 | "call-bind-apply-helpers": "^1.0.1", 580 | "dunder-proto": "^1.0.0", 581 | "es-define-property": "^1.0.1", 582 | "es-errors": "^1.3.0", 583 | "es-object-atoms": "^1.0.0", 584 | "function-bind": "^1.1.2", 585 | "gopd": "^1.2.0", 586 | "has-symbols": "^1.1.0", 587 | "hasown": "^2.0.2", 588 | "math-intrinsics": "^1.0.0" 589 | }, 590 | "engines": { 591 | "node": ">= 0.4" 592 | }, 593 | "funding": { 594 | "url": "https://github.com/sponsors/ljharb" 595 | } 596 | }, 597 | "node_modules/gopd": { 598 | "version": "1.2.0", 599 | "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", 600 | "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", 601 | "license": "MIT", 602 | "engines": { 603 | "node": ">= 0.4" 604 | }, 605 | "funding": { 606 | "url": "https://github.com/sponsors/ljharb" 607 | } 608 | }, 609 | "node_modules/has-symbols": { 610 | "version": "1.1.0", 611 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", 612 | "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", 613 | "license": "MIT", 614 | "engines": { 615 | "node": ">= 0.4" 616 | }, 617 | "funding": { 618 | "url": "https://github.com/sponsors/ljharb" 619 | } 620 | }, 621 | "node_modules/hasown": { 622 | "version": "2.0.2", 623 | "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", 624 | "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", 625 | "license": "MIT", 626 | "dependencies": { 627 | "function-bind": "^1.1.2" 628 | }, 629 | "engines": { 630 | "node": ">= 0.4" 631 | } 632 | }, 633 | "node_modules/http-errors": { 634 | "version": "2.0.0", 635 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", 636 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", 637 | "license": "MIT", 638 | "dependencies": { 639 | "depd": "2.0.0", 640 | "inherits": "2.0.4", 641 | "setprototypeof": "1.2.0", 642 | "statuses": "2.0.1", 643 | "toidentifier": "1.0.1" 644 | }, 645 | "engines": { 646 | "node": ">= 0.8" 647 | } 648 | }, 649 | "node_modules/iconv-lite": { 650 | "version": "0.4.24", 651 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 652 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 653 | "license": "MIT", 654 | "dependencies": { 655 | "safer-buffer": ">= 2.1.2 < 3" 656 | }, 657 | "engines": { 658 | "node": ">=0.10.0" 659 | } 660 | }, 661 | "node_modules/inherits": { 662 | "version": "2.0.4", 663 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 664 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 665 | "license": "ISC" 666 | }, 667 | "node_modules/ipaddr.js": { 668 | "version": "1.9.1", 669 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 670 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", 671 | "license": "MIT", 672 | "engines": { 673 | "node": ">= 0.10" 674 | } 675 | }, 676 | "node_modules/is-arrayish": { 677 | "version": "0.3.2", 678 | "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", 679 | "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", 680 | "license": "MIT" 681 | }, 682 | "node_modules/is-stream": { 683 | "version": "2.0.1", 684 | "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", 685 | "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", 686 | "license": "MIT", 687 | "engines": { 688 | "node": ">=8" 689 | }, 690 | "funding": { 691 | "url": "https://github.com/sponsors/sindresorhus" 692 | } 693 | }, 694 | "node_modules/isarray": { 695 | "version": "1.0.0", 696 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 697 | "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", 698 | "license": "MIT" 699 | }, 700 | "node_modules/kuler": { 701 | "version": "2.0.0", 702 | "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", 703 | "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==", 704 | "license": "MIT" 705 | }, 706 | "node_modules/logform": { 707 | "version": "2.7.0", 708 | "resolved": "https://registry.npmjs.org/logform/-/logform-2.7.0.tgz", 709 | "integrity": "sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ==", 710 | "license": "MIT", 711 | "dependencies": { 712 | "@colors/colors": "1.6.0", 713 | "@types/triple-beam": "^1.3.2", 714 | "fecha": "^4.2.0", 715 | "ms": "^2.1.1", 716 | "safe-stable-stringify": "^2.3.1", 717 | "triple-beam": "^1.3.0" 718 | }, 719 | "engines": { 720 | "node": ">= 12.0.0" 721 | } 722 | }, 723 | "node_modules/logform/node_modules/ms": { 724 | "version": "2.1.3", 725 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 726 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 727 | "license": "MIT" 728 | }, 729 | "node_modules/math-intrinsics": { 730 | "version": "1.1.0", 731 | "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", 732 | "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", 733 | "license": "MIT", 734 | "engines": { 735 | "node": ">= 0.4" 736 | } 737 | }, 738 | "node_modules/media-typer": { 739 | "version": "0.3.0", 740 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 741 | "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", 742 | "license": "MIT", 743 | "engines": { 744 | "node": ">= 0.6" 745 | } 746 | }, 747 | "node_modules/merge-descriptors": { 748 | "version": "1.0.3", 749 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", 750 | "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", 751 | "license": "MIT", 752 | "funding": { 753 | "url": "https://github.com/sponsors/sindresorhus" 754 | } 755 | }, 756 | "node_modules/methods": { 757 | "version": "1.1.2", 758 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 759 | "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", 760 | "license": "MIT", 761 | "engines": { 762 | "node": ">= 0.6" 763 | } 764 | }, 765 | "node_modules/mime": { 766 | "version": "1.6.0", 767 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 768 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", 769 | "license": "MIT", 770 | "bin": { 771 | "mime": "cli.js" 772 | }, 773 | "engines": { 774 | "node": ">=4" 775 | } 776 | }, 777 | "node_modules/mime-db": { 778 | "version": "1.52.0", 779 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 780 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", 781 | "license": "MIT", 782 | "engines": { 783 | "node": ">= 0.6" 784 | } 785 | }, 786 | "node_modules/mime-types": { 787 | "version": "2.1.35", 788 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 789 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 790 | "license": "MIT", 791 | "dependencies": { 792 | "mime-db": "1.52.0" 793 | }, 794 | "engines": { 795 | "node": ">= 0.6" 796 | } 797 | }, 798 | "node_modules/minimist": { 799 | "version": "1.2.8", 800 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", 801 | "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", 802 | "license": "MIT", 803 | "funding": { 804 | "url": "https://github.com/sponsors/ljharb" 805 | } 806 | }, 807 | "node_modules/mkdirp": { 808 | "version": "0.5.6", 809 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", 810 | "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", 811 | "license": "MIT", 812 | "dependencies": { 813 | "minimist": "^1.2.6" 814 | }, 815 | "bin": { 816 | "mkdirp": "bin/cmd.js" 817 | } 818 | }, 819 | "node_modules/ms": { 820 | "version": "2.0.0", 821 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 822 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", 823 | "license": "MIT" 824 | }, 825 | "node_modules/multer": { 826 | "version": "1.4.5-lts.1", 827 | "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz", 828 | "integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==", 829 | "license": "MIT", 830 | "dependencies": { 831 | "append-field": "^1.0.0", 832 | "busboy": "^1.0.0", 833 | "concat-stream": "^1.5.2", 834 | "mkdirp": "^0.5.4", 835 | "object-assign": "^4.1.1", 836 | "type-is": "^1.6.4", 837 | "xtend": "^4.0.0" 838 | }, 839 | "engines": { 840 | "node": ">= 6.0.0" 841 | } 842 | }, 843 | "node_modules/negotiator": { 844 | "version": "0.6.3", 845 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", 846 | "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", 847 | "license": "MIT", 848 | "engines": { 849 | "node": ">= 0.6" 850 | } 851 | }, 852 | "node_modules/node-forge": { 853 | "version": "1.3.1", 854 | "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", 855 | "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", 856 | "license": "(BSD-3-Clause OR GPL-2.0)", 857 | "engines": { 858 | "node": ">= 6.13.0" 859 | } 860 | }, 861 | "node_modules/object-assign": { 862 | "version": "4.1.1", 863 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 864 | "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", 865 | "license": "MIT", 866 | "engines": { 867 | "node": ">=0.10.0" 868 | } 869 | }, 870 | "node_modules/object-inspect": { 871 | "version": "1.13.3", 872 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", 873 | "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", 874 | "license": "MIT", 875 | "engines": { 876 | "node": ">= 0.4" 877 | }, 878 | "funding": { 879 | "url": "https://github.com/sponsors/ljharb" 880 | } 881 | }, 882 | "node_modules/on-finished": { 883 | "version": "2.4.1", 884 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", 885 | "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", 886 | "license": "MIT", 887 | "dependencies": { 888 | "ee-first": "1.1.1" 889 | }, 890 | "engines": { 891 | "node": ">= 0.8" 892 | } 893 | }, 894 | "node_modules/one-time": { 895 | "version": "1.0.0", 896 | "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", 897 | "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", 898 | "license": "MIT", 899 | "dependencies": { 900 | "fn.name": "1.x.x" 901 | } 902 | }, 903 | "node_modules/parseurl": { 904 | "version": "1.3.3", 905 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 906 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", 907 | "license": "MIT", 908 | "engines": { 909 | "node": ">= 0.8" 910 | } 911 | }, 912 | "node_modules/path-to-regexp": { 913 | "version": "0.1.12", 914 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", 915 | "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", 916 | "license": "MIT" 917 | }, 918 | "node_modules/plist": { 919 | "version": "3.1.0", 920 | "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz", 921 | "integrity": "sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==", 922 | "license": "MIT", 923 | "dependencies": { 924 | "@xmldom/xmldom": "^0.8.8", 925 | "base64-js": "^1.5.1", 926 | "xmlbuilder": "^15.1.1" 927 | }, 928 | "engines": { 929 | "node": ">=10.4.0" 930 | } 931 | }, 932 | "node_modules/process-nextick-args": { 933 | "version": "2.0.1", 934 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", 935 | "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", 936 | "license": "MIT" 937 | }, 938 | "node_modules/proxy-addr": { 939 | "version": "2.0.7", 940 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 941 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 942 | "license": "MIT", 943 | "dependencies": { 944 | "forwarded": "0.2.0", 945 | "ipaddr.js": "1.9.1" 946 | }, 947 | "engines": { 948 | "node": ">= 0.10" 949 | } 950 | }, 951 | "node_modules/qs": { 952 | "version": "6.13.0", 953 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", 954 | "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", 955 | "license": "BSD-3-Clause", 956 | "dependencies": { 957 | "side-channel": "^1.0.6" 958 | }, 959 | "engines": { 960 | "node": ">=0.6" 961 | }, 962 | "funding": { 963 | "url": "https://github.com/sponsors/ljharb" 964 | } 965 | }, 966 | "node_modules/range-parser": { 967 | "version": "1.2.1", 968 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 969 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", 970 | "license": "MIT", 971 | "engines": { 972 | "node": ">= 0.6" 973 | } 974 | }, 975 | "node_modules/raw-body": { 976 | "version": "2.5.2", 977 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", 978 | "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", 979 | "license": "MIT", 980 | "dependencies": { 981 | "bytes": "3.1.2", 982 | "http-errors": "2.0.0", 983 | "iconv-lite": "0.4.24", 984 | "unpipe": "1.0.0" 985 | }, 986 | "engines": { 987 | "node": ">= 0.8" 988 | } 989 | }, 990 | "node_modules/readable-stream": { 991 | "version": "2.3.8", 992 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", 993 | "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", 994 | "license": "MIT", 995 | "dependencies": { 996 | "core-util-is": "~1.0.0", 997 | "inherits": "~2.0.3", 998 | "isarray": "~1.0.0", 999 | "process-nextick-args": "~2.0.0", 1000 | "safe-buffer": "~5.1.1", 1001 | "string_decoder": "~1.1.1", 1002 | "util-deprecate": "~1.0.1" 1003 | } 1004 | }, 1005 | "node_modules/readable-stream/node_modules/safe-buffer": { 1006 | "version": "5.1.2", 1007 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 1008 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", 1009 | "license": "MIT" 1010 | }, 1011 | "node_modules/safe-buffer": { 1012 | "version": "5.2.1", 1013 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 1014 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 1015 | "funding": [ 1016 | { 1017 | "type": "github", 1018 | "url": "https://github.com/sponsors/feross" 1019 | }, 1020 | { 1021 | "type": "patreon", 1022 | "url": "https://www.patreon.com/feross" 1023 | }, 1024 | { 1025 | "type": "consulting", 1026 | "url": "https://feross.org/support" 1027 | } 1028 | ], 1029 | "license": "MIT" 1030 | }, 1031 | "node_modules/safe-stable-stringify": { 1032 | "version": "2.5.0", 1033 | "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", 1034 | "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", 1035 | "license": "MIT", 1036 | "engines": { 1037 | "node": ">=10" 1038 | } 1039 | }, 1040 | "node_modules/safer-buffer": { 1041 | "version": "2.1.2", 1042 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1043 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", 1044 | "license": "MIT" 1045 | }, 1046 | "node_modules/send": { 1047 | "version": "0.19.0", 1048 | "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", 1049 | "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", 1050 | "license": "MIT", 1051 | "dependencies": { 1052 | "debug": "2.6.9", 1053 | "depd": "2.0.0", 1054 | "destroy": "1.2.0", 1055 | "encodeurl": "~1.0.2", 1056 | "escape-html": "~1.0.3", 1057 | "etag": "~1.8.1", 1058 | "fresh": "0.5.2", 1059 | "http-errors": "2.0.0", 1060 | "mime": "1.6.0", 1061 | "ms": "2.1.3", 1062 | "on-finished": "2.4.1", 1063 | "range-parser": "~1.2.1", 1064 | "statuses": "2.0.1" 1065 | }, 1066 | "engines": { 1067 | "node": ">= 0.8.0" 1068 | } 1069 | }, 1070 | "node_modules/send/node_modules/encodeurl": { 1071 | "version": "1.0.2", 1072 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 1073 | "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", 1074 | "license": "MIT", 1075 | "engines": { 1076 | "node": ">= 0.8" 1077 | } 1078 | }, 1079 | "node_modules/send/node_modules/ms": { 1080 | "version": "2.1.3", 1081 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 1082 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 1083 | "license": "MIT" 1084 | }, 1085 | "node_modules/serve-static": { 1086 | "version": "1.16.2", 1087 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", 1088 | "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", 1089 | "license": "MIT", 1090 | "dependencies": { 1091 | "encodeurl": "~2.0.0", 1092 | "escape-html": "~1.0.3", 1093 | "parseurl": "~1.3.3", 1094 | "send": "0.19.0" 1095 | }, 1096 | "engines": { 1097 | "node": ">= 0.8.0" 1098 | } 1099 | }, 1100 | "node_modules/setprototypeof": { 1101 | "version": "1.2.0", 1102 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 1103 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", 1104 | "license": "ISC" 1105 | }, 1106 | "node_modules/side-channel": { 1107 | "version": "1.1.0", 1108 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", 1109 | "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", 1110 | "license": "MIT", 1111 | "dependencies": { 1112 | "es-errors": "^1.3.0", 1113 | "object-inspect": "^1.13.3", 1114 | "side-channel-list": "^1.0.0", 1115 | "side-channel-map": "^1.0.1", 1116 | "side-channel-weakmap": "^1.0.2" 1117 | }, 1118 | "engines": { 1119 | "node": ">= 0.4" 1120 | }, 1121 | "funding": { 1122 | "url": "https://github.com/sponsors/ljharb" 1123 | } 1124 | }, 1125 | "node_modules/side-channel-list": { 1126 | "version": "1.0.0", 1127 | "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", 1128 | "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", 1129 | "license": "MIT", 1130 | "dependencies": { 1131 | "es-errors": "^1.3.0", 1132 | "object-inspect": "^1.13.3" 1133 | }, 1134 | "engines": { 1135 | "node": ">= 0.4" 1136 | }, 1137 | "funding": { 1138 | "url": "https://github.com/sponsors/ljharb" 1139 | } 1140 | }, 1141 | "node_modules/side-channel-map": { 1142 | "version": "1.0.1", 1143 | "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", 1144 | "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", 1145 | "license": "MIT", 1146 | "dependencies": { 1147 | "call-bound": "^1.0.2", 1148 | "es-errors": "^1.3.0", 1149 | "get-intrinsic": "^1.2.5", 1150 | "object-inspect": "^1.13.3" 1151 | }, 1152 | "engines": { 1153 | "node": ">= 0.4" 1154 | }, 1155 | "funding": { 1156 | "url": "https://github.com/sponsors/ljharb" 1157 | } 1158 | }, 1159 | "node_modules/side-channel-weakmap": { 1160 | "version": "1.0.2", 1161 | "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", 1162 | "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", 1163 | "license": "MIT", 1164 | "dependencies": { 1165 | "call-bound": "^1.0.2", 1166 | "es-errors": "^1.3.0", 1167 | "get-intrinsic": "^1.2.5", 1168 | "object-inspect": "^1.13.3", 1169 | "side-channel-map": "^1.0.1" 1170 | }, 1171 | "engines": { 1172 | "node": ">= 0.4" 1173 | }, 1174 | "funding": { 1175 | "url": "https://github.com/sponsors/ljharb" 1176 | } 1177 | }, 1178 | "node_modules/simple-swizzle": { 1179 | "version": "0.2.2", 1180 | "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", 1181 | "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", 1182 | "license": "MIT", 1183 | "dependencies": { 1184 | "is-arrayish": "^0.3.1" 1185 | } 1186 | }, 1187 | "node_modules/stack-trace": { 1188 | "version": "0.0.10", 1189 | "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", 1190 | "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==", 1191 | "license": "MIT", 1192 | "engines": { 1193 | "node": "*" 1194 | } 1195 | }, 1196 | "node_modules/statuses": { 1197 | "version": "2.0.1", 1198 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", 1199 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", 1200 | "license": "MIT", 1201 | "engines": { 1202 | "node": ">= 0.8" 1203 | } 1204 | }, 1205 | "node_modules/streamsearch": { 1206 | "version": "1.1.0", 1207 | "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", 1208 | "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", 1209 | "engines": { 1210 | "node": ">=10.0.0" 1211 | } 1212 | }, 1213 | "node_modules/string_decoder": { 1214 | "version": "1.1.1", 1215 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", 1216 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", 1217 | "license": "MIT", 1218 | "dependencies": { 1219 | "safe-buffer": "~5.1.0" 1220 | } 1221 | }, 1222 | "node_modules/string_decoder/node_modules/safe-buffer": { 1223 | "version": "5.1.2", 1224 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 1225 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", 1226 | "license": "MIT" 1227 | }, 1228 | "node_modules/text-hex": { 1229 | "version": "1.0.0", 1230 | "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", 1231 | "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==", 1232 | "license": "MIT" 1233 | }, 1234 | "node_modules/toidentifier": { 1235 | "version": "1.0.1", 1236 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 1237 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", 1238 | "license": "MIT", 1239 | "engines": { 1240 | "node": ">=0.6" 1241 | } 1242 | }, 1243 | "node_modules/triple-beam": { 1244 | "version": "1.4.1", 1245 | "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz", 1246 | "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==", 1247 | "license": "MIT", 1248 | "engines": { 1249 | "node": ">= 14.0.0" 1250 | } 1251 | }, 1252 | "node_modules/type-is": { 1253 | "version": "1.6.18", 1254 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 1255 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 1256 | "license": "MIT", 1257 | "dependencies": { 1258 | "media-typer": "0.3.0", 1259 | "mime-types": "~2.1.24" 1260 | }, 1261 | "engines": { 1262 | "node": ">= 0.6" 1263 | } 1264 | }, 1265 | "node_modules/typedarray": { 1266 | "version": "0.0.6", 1267 | "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", 1268 | "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", 1269 | "license": "MIT" 1270 | }, 1271 | "node_modules/unpipe": { 1272 | "version": "1.0.0", 1273 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 1274 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", 1275 | "license": "MIT", 1276 | "engines": { 1277 | "node": ">= 0.8" 1278 | } 1279 | }, 1280 | "node_modules/util-deprecate": { 1281 | "version": "1.0.2", 1282 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 1283 | "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", 1284 | "license": "MIT" 1285 | }, 1286 | "node_modules/utils-merge": { 1287 | "version": "1.0.1", 1288 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 1289 | "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", 1290 | "license": "MIT", 1291 | "engines": { 1292 | "node": ">= 0.4.0" 1293 | } 1294 | }, 1295 | "node_modules/vary": { 1296 | "version": "1.1.2", 1297 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 1298 | "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", 1299 | "license": "MIT", 1300 | "engines": { 1301 | "node": ">= 0.8" 1302 | } 1303 | }, 1304 | "node_modules/winston": { 1305 | "version": "3.17.0", 1306 | "resolved": "https://registry.npmjs.org/winston/-/winston-3.17.0.tgz", 1307 | "integrity": "sha512-DLiFIXYC5fMPxaRg832S6F5mJYvePtmO5G9v9IgUFPhXm9/GkXarH/TUrBAVzhTCzAj9anE/+GjrgXp/54nOgw==", 1308 | "license": "MIT", 1309 | "dependencies": { 1310 | "@colors/colors": "^1.6.0", 1311 | "@dabh/diagnostics": "^2.0.2", 1312 | "async": "^3.2.3", 1313 | "is-stream": "^2.0.0", 1314 | "logform": "^2.7.0", 1315 | "one-time": "^1.0.0", 1316 | "readable-stream": "^3.4.0", 1317 | "safe-stable-stringify": "^2.3.1", 1318 | "stack-trace": "0.0.x", 1319 | "triple-beam": "^1.3.0", 1320 | "winston-transport": "^4.9.0" 1321 | }, 1322 | "engines": { 1323 | "node": ">= 12.0.0" 1324 | } 1325 | }, 1326 | "node_modules/winston-transport": { 1327 | "version": "4.9.0", 1328 | "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.9.0.tgz", 1329 | "integrity": "sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A==", 1330 | "license": "MIT", 1331 | "dependencies": { 1332 | "logform": "^2.7.0", 1333 | "readable-stream": "^3.6.2", 1334 | "triple-beam": "^1.3.0" 1335 | }, 1336 | "engines": { 1337 | "node": ">= 12.0.0" 1338 | } 1339 | }, 1340 | "node_modules/winston-transport/node_modules/readable-stream": { 1341 | "version": "3.6.2", 1342 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", 1343 | "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", 1344 | "license": "MIT", 1345 | "dependencies": { 1346 | "inherits": "^2.0.3", 1347 | "string_decoder": "^1.1.1", 1348 | "util-deprecate": "^1.0.1" 1349 | }, 1350 | "engines": { 1351 | "node": ">= 6" 1352 | } 1353 | }, 1354 | "node_modules/winston/node_modules/readable-stream": { 1355 | "version": "3.6.2", 1356 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", 1357 | "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", 1358 | "license": "MIT", 1359 | "dependencies": { 1360 | "inherits": "^2.0.3", 1361 | "string_decoder": "^1.1.1", 1362 | "util-deprecate": "^1.0.1" 1363 | }, 1364 | "engines": { 1365 | "node": ">= 6" 1366 | } 1367 | }, 1368 | "node_modules/xmlbuilder": { 1369 | "version": "15.1.1", 1370 | "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", 1371 | "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", 1372 | "license": "MIT", 1373 | "engines": { 1374 | "node": ">=8.0" 1375 | } 1376 | }, 1377 | "node_modules/xtend": { 1378 | "version": "4.0.2", 1379 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", 1380 | "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", 1381 | "license": "MIT", 1382 | "engines": { 1383 | "node": ">=0.4" 1384 | } 1385 | } 1386 | } 1387 | } 1388 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "daisign-api", 3 | "version": "1.0.0", 4 | "main": "app.js", 5 | "scripts": { 6 | "test": "echo \"Error: no test specified\" && exit 1" 7 | }, 8 | "keywords": [], 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "adm-zip": "^0.5.16", 13 | "bplist-parser": "^0.3.2", 14 | "cors": "^2.8.5", 15 | "dotenv": "^16.4.7", 16 | "express": "^4.21.2", 17 | "express-rate-limit": "^7.5.0", 18 | "multer": "^1.4.5-lts.1", 19 | "node-forge": "^1.3.1", 20 | "plist": "^3.1.0", 21 | "winston": "^3.17.0" 22 | }, 23 | "description": "## Max IPA upload size is 2GB you can change that in the code if you wanna use it for your own site/locally", 24 | "repository": { 25 | "type": "git", 26 | "url": "git+https://github.com/daisuke1227/DaiSign-API.git" 27 | }, 28 | "type": "commonjs", 29 | "bugs": { 30 | "url": "https://github.com/daisuke1227/DaiSign-API/issues" 31 | }, 32 | "homepage": "https://github.com/daisuke1227/DaiSign-API#readme" 33 | } 34 | -------------------------------------------------------------------------------- /uploads/mp/.empty: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daisuke1227/DaiSign-API/6239d4aa089680d882c315285d493daf865e179f/uploads/mp/.empty -------------------------------------------------------------------------------- /uploads/p12/.empty: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daisuke1227/DaiSign-API/6239d4aa089680d882c315285d493daf865e179f/uploads/p12/.empty -------------------------------------------------------------------------------- /uploads/plist/.empty: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daisuke1227/DaiSign-API/6239d4aa089680d882c315285d493daf865e179f/uploads/plist/.empty -------------------------------------------------------------------------------- /uploads/signed/.empty: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daisuke1227/DaiSign-API/6239d4aa089680d882c315285d493daf865e179f/uploads/signed/.empty -------------------------------------------------------------------------------- /uploads/temp/.empty: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daisuke1227/DaiSign-API/6239d4aa089680d882c315285d493daf865e179f/uploads/temp/.empty -------------------------------------------------------------------------------- /zsign-worker.js: -------------------------------------------------------------------------------- 1 | const { parentPort, workerData } = require('worker_threads'); 2 | const { exec } = require('child_process'); 3 | const util = require('util'); 4 | 5 | const execAsync = util.promisify(exec); 6 | 7 | (async () => { 8 | const { p12Path, p12Password, mpPath, ipaPath, signedIpaPath } = workerData; 9 | try { 10 | let zsignCmd = `zsign -z 5 -k "${p12Path}" `; 11 | if (p12Password) zsignCmd += `-p "${p12Password}" `; 12 | zsignCmd += `-m "${mpPath}" -o "${signedIpaPath}" "${ipaPath}"`; 13 | const { stdout, stderr } = await execAsync(zsignCmd); 14 | parentPort.postMessage({ status: 'ok', stdout, stderr }); 15 | } catch (error) { 16 | parentPort.postMessage({ status: 'error', error: error.message }); 17 | } 18 | })(); 19 | --------------------------------------------------------------------------------