@@ -344,6 +344,8 @@ def _is_printable(ch):
344344__use_ini_name__ = "archivefile.ini"
345345__use_json_file__ = False
346346__use_json_name__ = "archivefile.json"
347+ if(__use_ini_file__ and __use_json_name__):
348+ __use_json_name__ = False
347349if('PYARCHIVEFILE_CONFIG_FILE' in os.environ and os.path.exists(os.environ['PYARCHIVEFILE_CONFIG_FILE']) and __use_env_file__):
348350 scriptconf = os.environ['PYARCHIVEFILE_CONFIG_FILE']
349351else:
@@ -354,6 +356,10 @@ def _is_printable(ch):
354356 scriptconf = ""
355357if os.path.exists(scriptconf):
356358 __config_file__ = scriptconf
359+ elif(__use_ini_file__ and not __use_json_file__):
360+ __config_file__ = os.path.join(os.path.dirname(os.path.realpath(__file__)), __use_ini_name__)
361+ elif(not __use_ini_file__ and __use_json_file__):
362+ __config_file__ = os.path.join(os.path.dirname(os.path.realpath(__file__)), __use_json_name__)
357363else:
358364 __config_file__ = os.path.join(os.path.dirname(os.path.realpath(__file__)), __use_ini_name__)
359365if __use_ini_file__ and os.path.exists(__config_file__):
@@ -370,19 +376,153 @@ def decode_unicode_escape(value):
370376 __use_inmemfile__ = config.getboolean('config', 'inmemfile')
371377 # Loop through all sections
372378 for section in config.sections():
379+ if section == "config":
380+ continue
381+
373382 required_keys = [
374- "len", "hex", "ver", "name",
383+ "len", "hex", "ver", "name",
375384 "magic", "delimiter", "extension",
376385 "newstyle", "advancedlist", "altinode"
377386 ]
378- if section != "config" and all(key in config[section] for key in required_keys):
379- delim = decode_unicode_escape(config.get(section, 'delimiter'))
380- if(not is_only_nonprintable(delim)):
381- delim = "\x00" * len("\x00")
382- __file_format_multi_dict__.update( { decode_unicode_escape(config.get(section, 'magic')): {'format_name': decode_unicode_escape(config.get(section, 'name')), 'format_magic': decode_unicode_escape(config.get(section, 'magic')), 'format_len': config.getint(section, 'len'), 'format_hex': config.get(section, 'hex'), 'format_delimiter': delim, 'format_ver': config.get(section, 'ver'), 'new_style': config.getboolean(section, 'newstyle'), 'use_advanced_list': config.getboolean(section, 'advancedlist'), 'use_alt_inode': config.getboolean(section, 'altinode'), 'format_extension': decode_unicode_escape(config.get(section, 'extension')) } } )
387+
388+ # Py2+Py3 compatible key presence check
389+ has_all_required = all(config.has_option(section, key) for key in required_keys)
390+ if not has_all_required:
391+ continue
392+
393+ delim = decode_unicode_escape(config.get(section, 'delimiter'))
394+ if (not is_only_nonprintable(delim)):
395+ delim = "\x00" * len("\x00")
396+
397+ __file_format_multi_dict__.update({
398+ decode_unicode_escape(config.get(section, 'magic')): {
399+ 'format_name': decode_unicode_escape(config.get(section, 'name')),
400+ 'format_magic': decode_unicode_escape(config.get(section, 'magic')),
401+ 'format_len': config.getint(section, 'len'),
402+ 'format_hex': config.get(section, 'hex'),
403+ 'format_delimiter': delim,
404+ 'format_ver': config.get(section, 'ver'),
405+ 'new_style': config.getboolean(section, 'newstyle'),
406+ 'use_advanced_list': config.getboolean(section, 'advancedlist'),
407+ 'use_alt_inode': config.getboolean(section, 'altinode'),
408+ 'format_extension': decode_unicode_escape(config.get(section, 'extension')),
409+ }
410+ })
383411 if not __file_format_multi_dict__ and not __include_defaults__:
384412 __include_defaults__ = True
413+ elif __use_json_file__ and os.path.exists(__config_file__):
414+ # Prefer ujson/simplejson if available (you already have this import block above)
415+ with open(__config_file__, 'rb') as f:
416+ raw = f.read()
417+
418+ # Ensure we get a unicode string for json.loads on both Py2 and Py3
419+ if sys.version_info[0] < 3:
420+ text = raw.decode('utf-8') # Py2 bytes -> unicode
421+ else:
422+ text = raw if isinstance(raw, str) else raw.decode('utf-8')
423+
424+ cfg = json.loads(text)
425+
426+ # --- helpers: coerce + decode like your INI path ---
427+ def decode_unicode_escape(value):
428+ if sys.version_info[0] < 3: # Python 2
429+ if isinstance(value, unicode): # noqa: F821 (Py2 only)
430+ return value.encode('utf-8').decode('unicode_escape')
431+ elif isinstance(value, str):
432+ return value.decode('unicode_escape')
433+ else:
434+ return value
435+ else: # Python 3
436+ if isinstance(value, str):
437+ return bytes(value, 'UTF-8').decode('unicode_escape')
438+ else:
439+ return value
440+
441+ def _to_bool(v):
442+ # handle true/false, 1/0, and "true"/"false"/"1"/"0"
443+ if isinstance(v, bool):
444+ return v
445+ if isinstance(v, (int, float)):
446+ return bool(v)
447+ if isinstance(v, (str,)):
448+ lv = v.strip().lower()
449+ if lv in ('true', 'yes', '1'):
450+ return True
451+ if lv in ('false', 'no', '0'):
452+ return False
453+ return bool(v)
454+
455+ def _to_int(v, default=0):
456+ try:
457+ return int(v)
458+ except Exception:
459+ return default
460+
461+ def _get(section_dict, key, default=None):
462+ return section_dict.get(key, default)
463+
464+ # --- read global config (like INI's [config]) ---
465+ cfg_config = cfg.get('config', {}) or {}
466+ __file_format_default__ = decode_unicode_escape(_get(cfg_config, 'default', ''))
467+ __program_name__ = decode_unicode_escape(_get(cfg_config, 'proname', ''))
468+ __include_defaults__ = _to_bool(_get(cfg_config, 'includedef', False))
469+ __use_inmemfile__ = _to_bool(_get(cfg_config, 'inmemfile', False))
470+
471+ # --- iterate format sections (everything except "config") ---
472+ required_keys = [
473+ "len", "hex", "ver", "name",
474+ "magic", "delimiter", "extension",
475+ "newstyle", "advancedlist", "altinode"
476+ ]
477+
478+ for section_name, section in cfg.items():
479+ if section_name == 'config' or not isinstance(section, dict):
480+ continue
481+
482+ # check required keys present
483+ if not all(k in section for k in required_keys):
484+ continue
485+
486+ # pull + coerce values
487+ magic = decode_unicode_escape(_get(section, 'magic', ''))
488+ name = decode_unicode_escape(_get(section, 'name', ''))
489+ fmt_len = _to_int(_get(section, 'len', 0))
490+ fmt_hex = decode_unicode_escape(_get(section, 'hex', ''))
491+ fmt_ver = decode_unicode_escape(_get(section, 'ver', ''))
492+ delim = decode_unicode_escape(_get(section, 'delimiter', ''))
493+ new_style = _to_bool(_get(section, 'newstyle', False))
494+ adv_list = _to_bool(_get(section, 'advancedlist', False))
495+ alt_inode = _to_bool(_get(section, 'altinode', False))
496+ extension = decode_unicode_escape(_get(section, 'extension', ''))
497+
498+ # keep your delimiter validation semantics
499+ if not is_only_nonprintable(delim):
500+ delim = "\x00" * len("\x00") # same as your INI branch
501+
502+ __file_format_multi_dict__.update({
503+ magic: {
504+ 'format_name': name,
505+ 'format_magic': magic,
506+ 'format_len': fmt_len,
507+ 'format_hex': fmt_hex,
508+ 'format_delimiter': delim,
509+ 'format_ver': fmt_ver,
510+ 'new_style': new_style,
511+ 'use_advanced_list': adv_list,
512+ 'use_alt_inode': alt_inode,
513+ 'format_extension': extension,
514+ }
515+ })
516+
517+ # mirror your INI logic
518+ if not __file_format_multi_dict__ and not __include_defaults__:
519+ __include_defaults__ = True
385520elif __use_ini_file__ and not os.path.exists(__config_file__):
521+ __use_ini_file__ = False
522+ __use_json_file__ = False
523+ __include_defaults__ = True
524+ elif __use_json_file__ and not os.path.exists(__config_file__):
525+ __use_json_file__ = False
386526 __use_ini_file__ = False
387527 __include_defaults__ = True
388528if not __use_ini_file__ and not __include_defaults__:
0 commit comments