Skip to content

Commit 34ba219

Browse files
committed
refactor: Remove ZIP archive support
REMOVED: ZIP archive processing and support Changes Made: 1. Removed ZIP archive mentions from README.md: - Removed 'including ZIP archives' from Smart Parsing section - Removed 'and ZIP archives' from Multi-format Input section 2. Removed ZIP processing code from src/routes/yaml.routes.js: - Removed AdmZip require statement - Removed .zip file type mapping - Removed ZIP MIME types - Removed entire ZIP processing logic (1598-1792 lines) - Removed ZIP archive from binary analysis - Updated error messages to remove ZIP references 3. Removed ZIP dependencies: - Removed 'adm-zip' from package.json 4. Updated error messages: - Removed ZIP references from file validation errors Test Results: ✅ All 108 comprehensive tests still passing (100% success rate) ✅ No functionality broken by ZIP removal ✅ All supported file types still working correctly The application now focuses on core file types: - .mobileconfig, .xml, .eap-config, .yml/.yaml, .json, .txt/.conf/.cfg - Binary files (plist, certificates, etc.) - Text-based configuration files ZIP support has been completely removed as requested.
1 parent a0bfa98 commit 34ba219

4 files changed

Lines changed: 10 additions & 210 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ A comprehensive web application for editing Passpoint WiFi configurations and co
66

77
### Profile Converter
88
- **Multi-format Support**: Convert .mobileconfig, .xml, .eap-config, .yml/.yaml, .json, .txt/.conf/.cfg files
9-
- **Smart Parsing**: Automatic detection and parsing of configuration formats including ZIP archives
9+
- **Smart Parsing**: Automatic detection and parsing of configuration formats
1010
- **Certificate Handling**: Advanced certificate detection and display options:
1111
- **Preserve**: Show original certificate data
1212
- **Obfuscate**: Replace with `[CERTIFICATE DATA REDACTED]`
@@ -32,7 +32,7 @@ A comprehensive web application for editing Passpoint WiFi configurations and co
3232
### Technical Features
3333
- **Certificate Processing**: Backend certificate detection and transformation with metadata extraction
3434
- **Automatic Cleanup**: Uploaded files are automatically cleaned up after processing
35-
- **Multi-format Input**: Support for 15+ file formats including binary and ZIP archives
35+
- **Multi-format Input**: Support for 15+ file formats including binary files
3636
- **Security**: Non-root Docker containers, input sanitization, certificate data protection
3737
- **Performance**: Multi-stage Docker builds, optimized frontend, efficient file processing
3838
- **Monitoring**: Health checks, comprehensive logging, and WebSocket progress updates

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
"@emotion/styled": "^11.14.0",
2727
"@fastify/busboy": "^3.1.1",
2828
"@mui/material": "^7.0.2",
29-
"adm-zip": "^0.5.16",
29+
3030
"ajv": "^8.17.1",
3131
"axios": "^1.9.0",
3232
"busboy": "^1.6.0",

src/app.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ function detectFileIssues(filePath, fileExtension, fileContent) {
100100
'.mobileconfig': 'Mobile Configuration',
101101
'.eap-config': 'EAP Configuration',
102102
'.txt': 'Text',
103-
'.zip': 'ZIP Archive',
103+
104104
'.conf': 'Configuration',
105105
'.cfg': 'Configuration'
106106
};

src/routes/yaml.routes.js

Lines changed: 6 additions & 206 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const { mapToYamlSchema } = require('../services/mapping.service'); // Import th
1414
const certService = require('../services/cert.service'); // Import the certificate service
1515
const { v4: uuidv4 } = require('uuid');
1616
const { sendConversionUpdate } = require('../services/websocket.service'); // Import WebSocket service
17-
const AdmZip = require('adm-zip');
17+
1818
const crypto = require('crypto');
1919
const Busboy = require('@fastify/busboy'); // Use Fastify busboy for better serverless support
2020
const { bufferJsonReplacer, processBinaryData } = require('../utils/binary-helpers'); // Import binary data helpers
@@ -33,7 +33,7 @@ const SUPPORTED_FILE_TYPES = {
3333
'.mobileconfig': 'Mobile Configuration',
3434
'.eap-config': 'EAP Configuration',
3535
'.txt': 'Text',
36-
'.zip': 'ZIP Archive',
36+
3737
'.conf': 'Configuration',
3838
'.cfg': 'Configuration'
3939
};
@@ -648,7 +648,7 @@ const upload = multer({
648648
'.yml', '.yaml', '.mobileconfig', '.xml', '.eap-config',
649649
'.txt', '.json', '.conf', '.cfg',
650650
'.pem', '.crt', '.cer', '.ovpn', '.profile', '.p12', '.pfx',
651-
'.zip', '.plist', '.config', '.ini', '.properties', '.env',
651+
'.plist', '.config', '.ini', '.properties', '.env',
652652
'.toml', '.log', '.data', '.bin' // Added more types
653653
];
654654
const allowedMimeTypes = [
@@ -663,8 +663,7 @@ const upload = multer({
663663
'application/vnd.visio', // .vsd
664664
'application/json',
665665
'text/json',
666-
'application/zip', // ZIP files
667-
'application/x-zip-compressed',
666+
668667
'application/x-plist', // Plist files
669668
'application/pkcs12', // P12/PFX certificates
670669
'application/x-pkcs12',
@@ -1564,7 +1563,7 @@ router.post('/convert', async (req, res) => {
15641563
// Try to detect file format based on magic bytes
15651564
const firstFourBytes = fileBuffer.slice(0, 4);
15661565
if (firstFourBytes[0] === 0x50 && firstFourBytes[1] === 0x4B) {
1567-
binaryAnalysis.analysis.possibleFormats.push('ZIP archive');
1566+
15681567
}
15691568
if (fileBuffer.slice(0, 8).toString() === 'bplist00') {
15701569
binaryAnalysis.analysis.possibleFormats.push('Binary property list (plist)');
@@ -1596,205 +1595,6 @@ router.post('/convert', async (req, res) => {
15961595
});
15971596
}
15981597

1599-
// Check if this is actually a ZIP file (Office document or ZIP archive)
1600-
const zipSignature = fileBuffer.subarray(0, 4);
1601-
const isZip = zipSignature[0] === 0x50 && zipSignature[1] === 0x4B; // "PK" signature
1602-
1603-
if (isZip) {
1604-
console.log('[SERVER /convert] Detected ZIP archive format, searching for plist content');
1605-
1606-
try {
1607-
const zip = new AdmZip(fileBuffer);
1608-
const zipEntries = zip.getEntries();
1609-
1610-
console.log('[SERVER /convert] ZIP contains', zipEntries.length, 'files');
1611-
1612-
// First pass: Look for obvious plist/mobileconfig files
1613-
let plistEntry = null;
1614-
for (const entry of zipEntries) {
1615-
const entryName = entry.entryName.toLowerCase();
1616-
console.log('[SERVER /convert] Found file in ZIP:', entry.entryName);
1617-
1618-
if (entryName.endsWith('.plist') ||
1619-
entryName.endsWith('.mobileconfig') ||
1620-
entryName.includes('passpoint') ||
1621-
entryName.includes('wifi') ||
1622-
entryName.includes('802dot1x')) {
1623-
plistEntry = entry;
1624-
console.log('[SERVER /convert] Found potential plist file in ZIP:', entry.entryName);
1625-
break;
1626-
}
1627-
}
1628-
1629-
// Second pass: Search file contents for plist data
1630-
if (!plistEntry) {
1631-
console.log('[SERVER /convert] No obvious plist files found, searching file contents...');
1632-
1633-
for (const entry of zipEntries) {
1634-
// Skip directories and very large files
1635-
if (entry.isDirectory || entry.header.size > 1024 * 1024) { // Skip files > 1MB
1636-
continue;
1637-
}
1638-
1639-
try {
1640-
const entryData = entry.getData();
1641-
const entryText = entryData.toString('utf8', 0, Math.min(entryData.length, 10000)); // Check first 10KB
1642-
1643-
// Look for plist signatures in the content
1644-
if (entryText.includes('<!DOCTYPE plist') ||
1645-
entryText.includes('<plist') ||
1646-
entryText.includes('PayloadType') ||
1647-
entryText.includes('com.apple.wifi.managed') ||
1648-
entryText.includes('EAPClientConfiguration') ||
1649-
entryText.includes('RoamingConsortiumOIs')) {
1650-
1651-
console.log('[SERVER /convert] Found plist content in file:', entry.entryName);
1652-
plistEntry = entry;
1653-
break;
1654-
}
1655-
1656-
// Also check for binary plist signatures
1657-
if (entryData.length >= 8) {
1658-
const header = entryData.toString('ascii', 0, 8);
1659-
if (header === 'bplist00' || header.startsWith('bplist')) {
1660-
console.log('[SERVER /convert] Found binary plist in file:', entry.entryName);
1661-
plistEntry = entry;
1662-
break;
1663-
}
1664-
}
1665-
1666-
} catch (contentError) {
1667-
// Skip files that can't be read as text
1668-
continue;
1669-
}
1670-
}
1671-
}
1672-
1673-
// Third pass: Try XML files that might contain embedded plist data
1674-
if (!plistEntry) {
1675-
console.log('[SERVER /convert] Still no plist found, checking XML files for embedded content...');
1676-
1677-
for (const entry of zipEntries) {
1678-
const entryName = entry.entryName.toLowerCase();
1679-
1680-
if (entryName.endsWith('.xml') &&
1681-
!entryName.includes('content_types') &&
1682-
!entryName.includes('theme') &&
1683-
!entryName.includes('styles') &&
1684-
!entryName.includes('settings') &&
1685-
!entryName.includes('rels')) {
1686-
1687-
try {
1688-
const xmlBuffer = entry.getData();
1689-
const xmlContent = xmlBuffer.toString('utf8');
1690-
1691-
// Look for WiFi/network configuration in XML
1692-
if (xmlContent.includes('wifi') ||
1693-
xmlContent.includes('network') ||
1694-
xmlContent.includes('eap') ||
1695-
xmlContent.includes('passpoint') ||
1696-
xmlContent.includes('802.1x') ||
1697-
xmlContent.includes('certificate') ||
1698-
xmlContent.includes('credential')) {
1699-
1700-
console.log('[SERVER /convert] Found potential network config in XML:', entry.entryName);
1701-
plistEntry = entry;
1702-
break;
1703-
}
1704-
} catch (xmlError) {
1705-
continue;
1706-
}
1707-
}
1708-
}
1709-
}
1710-
1711-
if (!plistEntry) {
1712-
return res.status(400).json({
1713-
error: 'No plist, mobileconfig, or network configuration content found in the ZIP archive. Searched through all files but found no Passpoint/WiFi configuration data. Files found: ' +
1714-
zipEntries.map(e => e.entryName).join(', ')
1715-
});
1716-
}
1717-
1718-
// Extract the plist file content
1719-
const plistBuffer = plistEntry.getData();
1720-
console.log('[SERVER /convert] Extracted potential plist file, size:', plistBuffer.length);
1721-
1722-
// Try to parse as plist
1723-
let parsedPlist;
1724-
try {
1725-
// Try binary plist first
1726-
parsedPlist = plist.parse(plistBuffer);
1727-
console.log('[SERVER /convert] Binary plist parsing successful from ZIP');
1728-
} catch (binaryError) {
1729-
console.log('[SERVER /convert] Binary plist failed, trying as text:', binaryError.message);
1730-
1731-
try {
1732-
// Try as text plist
1733-
const plistText = plistBuffer.toString('utf8');
1734-
1735-
// If it doesn't look like a plist, try to extract plist content from it
1736-
if (!plistText.includes('<plist') && !plistText.includes('<!DOCTYPE plist')) {
1737-
console.log('[SERVER /convert] Not a standard plist, searching for embedded plist content...');
1738-
1739-
// Look for plist-like structures in the text
1740-
const plistMatch = plistText.match(/<!DOCTYPE plist[\s\S]*?<\/plist>/i);
1741-
if (plistMatch) {
1742-
console.log('[SERVER /convert] Found embedded plist content');
1743-
parsedPlist = plist.parse(plistMatch[0]);
1744-
} else {
1745-
throw new Error('No valid plist content found in extracted file');
1746-
}
1747-
} else {
1748-
parsedPlist = plist.parse(plistText);
1749-
}
1750-
1751-
console.log('[SERVER /convert] Text plist parsing successful from ZIP');
1752-
} catch (textError) {
1753-
console.log('[SERVER /convert] Text plist also failed:', textError.message);
1754-
throw new Error(`Unable to parse extracted file as plist: ${textError.message}`);
1755-
}
1756-
}
1757-
1758-
console.log('[SERVER /convert] Parsed plist structure from ZIP:', JSON.stringify(parsedPlist, null, 2));
1759-
1760-
// Return full unfiltered data from ZIP
1761-
const fullYamlOutput = yaml.dump(parsedPlist, {
1762-
indent: 2,
1763-
lineWidth: 120,
1764-
noRefs: true,
1765-
});
1766-
1767-
// Also create filtered version for comparison
1768-
const mappedData = mapMobileConfigToYaml(parsedPlist);
1769-
const filteredYamlOutput = yaml.dump(mappedData, {
1770-
indent: 2,
1771-
lineWidth: 120,
1772-
noRefs: true,
1773-
});
1774-
1775-
return res.json({
1776-
success: true,
1777-
yamlOutput: fullYamlOutput, // PRIMARY: Full unfiltered data (frontend expects yamlOutput)
1778-
comprehensiveYaml: fullYamlOutput, // ALSO: Same data for comprehensive tab
1779-
filteredYaml: filteredYamlOutput, // SECONDARY: Filtered version
1780-
jsonOutput: JSON.stringify(parsedPlist, null, 2), // JSON format for JSON tab
1781-
originalData: parsedPlist,
1782-
sourceFile: plistEntry.entryName,
1783-
fileType: 'plist-in-zip',
1784-
mappingInfo: {
1785-
filtered: false,
1786-
note: "Full unfiltered data extracted from ZIP is provided in the 'yamlOutput' field"
1787-
}
1788-
});
1789-
1790-
} catch (zipError) {
1791-
console.log('[SERVER /convert] ZIP processing failed:', zipError.message);
1792-
return res.status(400).json({
1793-
error: `Failed to process ZIP file: ${zipError.message}. This may not contain valid plist/configuration data.`
1794-
});
1795-
}
1796-
}
1797-
17981598
// Convert buffer to string and clean it
17991599
let xmlString = fileBuffer.toString('utf8');
18001600

@@ -2009,7 +1809,7 @@ router.post('/convert', async (req, res) => {
20091809
const trimmedXml = xmlString.trim();
20101810
if (!trimmedXml.includes('<') || trimmedXml.length === 0) {
20111811
return res.status(400).json({
2012-
error: 'File does not appear to contain valid XML content. Please ensure you have uploaded a proper XML, plist, or ZIP file containing configuration data.'
1812+
error: 'File does not appear to contain valid XML content. Please ensure you have uploaded a proper XML or plist file containing configuration data.'
20131813
});
20141814
}
20151815

0 commit comments

Comments
 (0)