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