# GeViSet Configuration File Parser A portable Python parser and generator for Geutebruck GeViSet `.set` configuration files. ## Features - **Parse** `.set` binary configuration files to JSON format - **Generate** `.set` files from JSON configuration - **Cross-platform**: Works on Windows, Linux, and macOS - **Pure Python**: No external dependencies except Python 3.6+ ## Binary Format Specification The GeViSet `.set` file format is a proprietary binary format with the following structure: ### Type Markers - `0x00` - Section/Container - `0x01` - Boolean (1 byte: 0x00 or 0x01) - `0x02` - 64-bit integer (8 bytes, little-endian) - `0x04` - 32-bit integer (4 bytes, little-endian) - `0x07` - Property name (1-byte length prefix) - `0x08` - String value (2-byte length prefix) ### File Structure ``` [Section] 0x00 - Section marker [1-byte length] - Name length [name bytes] - Section name (UTF-8) [4-byte int32] - Metadata value [1-byte] - Metadata flags [Properties/Subsections...] 0x00 0x00 0x00... - End marker [Property] 0x07 - Property name marker [1-byte length] - Name length [name bytes] - Property name (UTF-8) [type marker] - Value type (0x01, 0x02, 0x04, or 0x08) [value bytes] - Value data ``` ## Installation No installation required! Just copy `geviset_parser.py` to your system. ```bash # Download or copy the file cp geviset_parser.py /usr/local/bin/ chmod +x /usr/local/bin/geviset_parser.py ``` ## Usage ### Command Line #### Parse .set file to JSON ```bash python3 geviset_parser.py config.set output.json ``` #### Generate .set file from JSON ```bash python3 geviset_parser.py config.json output.set ``` ### Python API #### Parse a configuration file ```python from geviset_parser import GeViSetParser parser = GeViSetParser() config = parser.parse_file("GeViSoft.set") # Access configuration print(config.keys()) # Top-level sections print(config['Users']['SysAdmin']['Password']) ``` #### Modify and save configuration ```python from geviset_parser import GeViSetParser, GeViSetGenerator from collections import OrderedDict # Load existing configuration parser = GeViSetParser() config = parser.parse_file("GeViSoft.set") # Modify user password (example - you'd need to hash it properly) if 'Users' in config and 'aa' in config['Users']: config['Users']['aa']['Password'] = 'new_hashed_password' # Save modified configuration generator = GeViSetGenerator() generator.generate_file(config, "GeViSoft_modified.set") ``` #### Create new configuration from scratch ```python from geviset_parser import GeViSetGenerator from collections import OrderedDict config = OrderedDict() config['MySection'] = OrderedDict() config['MySection']['_metadata'] = {'value': 0, 'flags': 0} config['MySection']['Enabled'] = True config['MySection']['Port'] = 8080 config['MySection']['ServerName'] = 'localhost' generator = GeViSetGenerator() generator.generate_file(config, "custom_config.set") ``` ## JSON Format When exported to JSON, the configuration maintains an OrderedDict structure: ```json { "GeViSoft Parameters": { "_metadata": { "value": 20, "flags": 0 }, "Alarms": { "_metadata": { "value": 0, "flags": 0 } }, "Users": { "_metadata": { "value": 0, "flags": 0 } } }, "Users": { "_metadata": { "value": 6, "flags": 7 }, "SysAdmin": { "_metadata": { "value": 0, "flags": 7 }, "Checksum": "340e1f3d767e056d5e9502c56fc9d73b", "Configured": true, "Description": "System Administrator", "Password": "abe6db4c9f5484fae8d79f2e868a673c" } } } ``` ### Metadata Each section includes a `_metadata` dictionary with: - `value`: 32-bit integer (purpose varies by section) - `flags`: 8-bit flags byte ## Common Tasks ### Extract User Passwords ```python parser = GeViSetParser() config = parser.parse_file("GeViSoft.set") if 'Users' in config: for user_name, user_data in config['Users'].items(): if user_name != '_metadata' and isinstance(user_data, dict): password_hash = user_data.get('Password', '') print(f"User: {user_name}, Password Hash: {password_hash}") ``` ### Change Server Settings ```python parser = GeViSetParser() config = parser.parse_file("GeViSoft.set") # Modify GETAS TCP settings if 'GeViSoft Parameters' in config: getas = config['GeViSoft Parameters'].get('GETAS', {}) getas['TCPEnabled'] = True getas['TCPPort'] = 7777 getas['MaxTCPConnections'] = 10 # Save generator = GeViSetGenerator() generator.generate_file(config, "GeViSoft_modified.set") ``` ### Export Configuration for Backup ```bash # Convert to JSON for version control python3 geviset_parser.py GeViSoft.set backup.json # Edit in text editor vi backup.json # Convert back to .set python3 geviset_parser.py backup.json GeViSoft_restored.set ``` ## Security Considerations ### Password Hashing The GeViSet format stores password hashes, not plaintext passwords. The exact hashing algorithm used by GeViSet is proprietary. When modifying user passwords: 1. **Do NOT** store plaintext passwords 2. Use the same hashing algorithm as GeViSet (may require reverse engineering) 3. Consider using the official GeViSet tool for password changes ### Checksums Some sections include checksum fields (32-character hex strings that appear to be MD5 hashes). These may be used for integrity verification. When modifying configuration: 1. Preserve checksums if possible 2. Or recalculate them based on the section content (algorithm TBD) 3. Test modified configurations thoroughly before deployment ## Limitations - Checksum/hash algorithms are not yet fully reverse-engineered - Some metadata field meanings are unknown - Binary format may vary between GeViSet versions ## Troubleshooting ### Parse Errors If you encounter parse errors: 1. **Check file integrity**: Ensure the .set file isn't corrupted 2. **Verify format version**: This parser was developed for GeViSet 7.x 3. **Enable debug output**: Check warnings during parsing ### Generated Files Don't Work If generated .set files don't load in GeViSet: 1. **Preserve metadata**: Ensure `_metadata` fields are maintained 2. **Check checksums**: Some checksums may need recalculation 3. **Verify structure**: Compare with original file structure ### Stack Overflow / Recursion Errors If you hit recursion limits with very deeply nested configurations: ```python import sys sys.setrecursionlimit(5000) # Increase from default 1000 ``` ## Development ### Running Tests ```bash # Parse a sample file python3 geviset_parser.py sample.set sample.json # Generate it back python3 geviset_parser.py sample.json sample_regenerated.set # Compare diff <(xxd sample.set) <(xxd sample_regenerated.set) ``` ### Contributing To contribute improvements: 1. Document any new type markers or structures discovered 2. Add test cases for edge cases 3. Update this README with new findings ## License This parser was reverse-engineered for interoperability purposes. Use responsibly and in accordance with your GeViSet license agreement. ## Related Projects - **geutebruck-api**: RESTful API for GeViScope/GeViSoft surveillance systems - See `C:\DEV\COPILOT\CLAUDE.md` for SDK documentation ## Author Created during analysis of Geutebruck GeViSet configuration format. For questions or issues, refer to the main project documentation.