exonware-xwsystem 0.0.1.411__py3-none-any.whl → 0.1.0.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- exonware/__init__.py +2 -1
- exonware/conf.py +2 -2
- exonware/xwsystem/__init__.py +115 -43
- exonware/xwsystem/base.py +30 -0
- exonware/xwsystem/caching/__init__.py +39 -13
- exonware/xwsystem/caching/base.py +24 -6
- exonware/xwsystem/caching/bloom_cache.py +2 -2
- exonware/xwsystem/caching/cache_manager.py +2 -1
- exonware/xwsystem/caching/conditional.py +2 -2
- exonware/xwsystem/caching/contracts.py +85 -139
- exonware/xwsystem/caching/decorators.py +6 -19
- exonware/xwsystem/caching/defs.py +2 -1
- exonware/xwsystem/caching/disk_cache.py +2 -1
- exonware/xwsystem/caching/distributed.py +2 -1
- exonware/xwsystem/caching/errors.py +2 -1
- exonware/xwsystem/caching/events.py +110 -27
- exonware/xwsystem/caching/eviction_strategies.py +2 -2
- exonware/xwsystem/caching/external_caching_python.py +701 -0
- exonware/xwsystem/caching/facade.py +253 -0
- exonware/xwsystem/caching/factory.py +300 -0
- exonware/xwsystem/caching/fluent.py +14 -12
- exonware/xwsystem/caching/integrity.py +21 -6
- exonware/xwsystem/caching/lfu_cache.py +2 -1
- exonware/xwsystem/caching/lfu_optimized.py +18 -6
- exonware/xwsystem/caching/lru_cache.py +7 -4
- exonware/xwsystem/caching/memory_bounded.py +2 -2
- exonware/xwsystem/caching/metrics_exporter.py +2 -2
- exonware/xwsystem/caching/observable_cache.py +2 -2
- exonware/xwsystem/caching/pluggable_cache.py +2 -2
- exonware/xwsystem/caching/rate_limiter.py +2 -2
- exonware/xwsystem/caching/read_through.py +2 -2
- exonware/xwsystem/caching/secure_cache.py +81 -28
- exonware/xwsystem/caching/serializable.py +9 -7
- exonware/xwsystem/caching/stats.py +2 -2
- exonware/xwsystem/caching/tagging.py +2 -2
- exonware/xwsystem/caching/ttl_cache.py +4 -3
- exonware/xwsystem/caching/two_tier_cache.py +6 -3
- exonware/xwsystem/caching/utils.py +30 -12
- exonware/xwsystem/caching/validation.py +2 -2
- exonware/xwsystem/caching/warming.py +6 -3
- exonware/xwsystem/caching/write_behind.py +15 -6
- exonware/xwsystem/config/__init__.py +11 -17
- exonware/xwsystem/config/base.py +5 -5
- exonware/xwsystem/config/contracts.py +93 -153
- exonware/xwsystem/config/defaults.py +3 -2
- exonware/xwsystem/config/defs.py +3 -2
- exonware/xwsystem/config/errors.py +2 -5
- exonware/xwsystem/config/logging.py +12 -8
- exonware/xwsystem/config/logging_setup.py +3 -2
- exonware/xwsystem/config/performance.py +73 -391
- exonware/xwsystem/config/performance_modes.py +9 -8
- exonware/xwsystem/config/version_manager.py +1 -0
- exonware/xwsystem/config.py +27 -0
- exonware/xwsystem/console/__init__.py +53 -0
- exonware/xwsystem/console/base.py +133 -0
- exonware/xwsystem/console/cli/__init__.py +61 -0
- exonware/xwsystem/{cli → console/cli}/args.py +27 -24
- exonware/xwsystem/{cli → console/cli}/base.py +18 -87
- exonware/xwsystem/{cli → console/cli}/colors.py +15 -13
- exonware/xwsystem/console/cli/console.py +98 -0
- exonware/xwsystem/{cli → console/cli}/contracts.py +51 -69
- exonware/xwsystem/console/cli/defs.py +87 -0
- exonware/xwsystem/console/cli/encoding.py +69 -0
- exonware/xwsystem/{cli → console/cli}/errors.py +8 -3
- exonware/xwsystem/console/cli/event_logger.py +166 -0
- exonware/xwsystem/{cli → console/cli}/progress.py +25 -21
- exonware/xwsystem/{cli → console/cli}/prompts.py +3 -2
- exonware/xwsystem/{cli → console/cli}/tables.py +27 -24
- exonware/xwsystem/console/contracts.py +113 -0
- exonware/xwsystem/console/defs.py +154 -0
- exonware/xwsystem/console/errors.py +34 -0
- exonware/xwsystem/console/event_logger.py +385 -0
- exonware/xwsystem/console/writer.py +132 -0
- exonware/xwsystem/contracts.py +28 -0
- exonware/xwsystem/data_structures/__init__.py +23 -0
- exonware/xwsystem/data_structures/trie.py +34 -0
- exonware/xwsystem/data_structures/union_find.py +144 -0
- exonware/xwsystem/defs.py +17 -0
- exonware/xwsystem/errors.py +23 -0
- exonware/xwsystem/facade.py +62 -0
- exonware/xwsystem/http_client/__init__.py +22 -1
- exonware/xwsystem/http_client/advanced_client.py +8 -5
- exonware/xwsystem/http_client/base.py +3 -2
- exonware/xwsystem/http_client/client.py +7 -4
- exonware/xwsystem/http_client/contracts.py +42 -56
- exonware/xwsystem/http_client/defs.py +2 -1
- exonware/xwsystem/http_client/errors.py +2 -1
- exonware/xwsystem/http_client/facade.py +156 -0
- exonware/xwsystem/io/__init__.py +22 -3
- exonware/xwsystem/io/archive/__init__.py +8 -2
- exonware/xwsystem/io/archive/archive.py +1 -1
- exonware/xwsystem/io/archive/archive_files.py +4 -7
- exonware/xwsystem/io/archive/archivers.py +120 -10
- exonware/xwsystem/io/archive/base.py +4 -5
- exonware/xwsystem/io/archive/codec_integration.py +1 -2
- exonware/xwsystem/io/archive/compression.py +1 -2
- exonware/xwsystem/io/archive/facade.py +263 -0
- exonware/xwsystem/io/archive/formats/__init__.py +2 -3
- exonware/xwsystem/io/archive/formats/brotli_format.py +20 -7
- exonware/xwsystem/io/archive/formats/lz4_format.py +20 -7
- exonware/xwsystem/io/archive/formats/rar.py +11 -5
- exonware/xwsystem/io/archive/formats/sevenzip.py +12 -6
- exonware/xwsystem/io/archive/formats/squashfs_format.py +1 -2
- exonware/xwsystem/io/archive/formats/tar.py +52 -7
- exonware/xwsystem/io/archive/formats/wim_format.py +11 -5
- exonware/xwsystem/io/archive/formats/zip.py +1 -2
- exonware/xwsystem/io/archive/formats/zpaq_format.py +1 -2
- exonware/xwsystem/io/archive/formats/zstandard.py +20 -7
- exonware/xwsystem/io/base.py +119 -115
- exonware/xwsystem/io/codec/__init__.py +4 -2
- exonware/xwsystem/io/codec/base.py +19 -13
- exonware/xwsystem/io/codec/contracts.py +59 -2
- exonware/xwsystem/io/codec/registry.py +67 -21
- exonware/xwsystem/io/common/__init__.py +1 -1
- exonware/xwsystem/io/common/atomic.py +29 -16
- exonware/xwsystem/io/common/base.py +11 -10
- exonware/xwsystem/io/common/lock.py +6 -5
- exonware/xwsystem/io/common/path_manager.py +2 -1
- exonware/xwsystem/io/common/watcher.py +1 -2
- exonware/xwsystem/io/contracts.py +301 -433
- exonware/xwsystem/io/contracts_1.py +1180 -0
- exonware/xwsystem/io/data_operations.py +279 -14
- exonware/xwsystem/io/defs.py +4 -3
- exonware/xwsystem/io/errors.py +3 -2
- exonware/xwsystem/io/facade.py +87 -61
- exonware/xwsystem/io/file/__init__.py +1 -1
- exonware/xwsystem/io/file/base.py +8 -9
- exonware/xwsystem/io/file/conversion.py +2 -3
- exonware/xwsystem/io/file/file.py +61 -18
- exonware/xwsystem/io/file/paged_source.py +8 -8
- exonware/xwsystem/io/file/paging/__init__.py +1 -2
- exonware/xwsystem/io/file/paging/byte_paging.py +4 -5
- exonware/xwsystem/io/file/paging/line_paging.py +2 -3
- exonware/xwsystem/io/file/paging/record_paging.py +2 -3
- exonware/xwsystem/io/file/paging/registry.py +1 -2
- exonware/xwsystem/io/file/source.py +13 -17
- exonware/xwsystem/io/filesystem/__init__.py +1 -1
- exonware/xwsystem/io/filesystem/base.py +1 -2
- exonware/xwsystem/io/filesystem/local.py +3 -4
- exonware/xwsystem/io/folder/__init__.py +1 -1
- exonware/xwsystem/io/folder/base.py +1 -2
- exonware/xwsystem/io/folder/folder.py +16 -7
- exonware/xwsystem/io/indexing/__init__.py +14 -0
- exonware/xwsystem/io/indexing/facade.py +443 -0
- exonware/xwsystem/io/path_parser.py +98 -0
- exonware/xwsystem/io/serialization/__init__.py +21 -3
- exonware/xwsystem/io/serialization/auto_serializer.py +146 -20
- exonware/xwsystem/io/serialization/base.py +84 -34
- exonware/xwsystem/io/serialization/contracts.py +50 -73
- exonware/xwsystem/io/serialization/defs.py +2 -1
- exonware/xwsystem/io/serialization/errors.py +2 -1
- exonware/xwsystem/io/serialization/flyweight.py +154 -7
- exonware/xwsystem/io/serialization/format_detector.py +15 -14
- exonware/xwsystem/io/serialization/formats/__init__.py +8 -5
- exonware/xwsystem/io/serialization/formats/binary/bson.py +15 -6
- exonware/xwsystem/io/serialization/formats/binary/cbor.py +5 -5
- exonware/xwsystem/io/serialization/formats/binary/marshal.py +5 -5
- exonware/xwsystem/io/serialization/formats/binary/msgpack.py +5 -5
- exonware/xwsystem/io/serialization/formats/binary/pickle.py +5 -5
- exonware/xwsystem/io/serialization/formats/binary/plistlib.py +5 -5
- exonware/xwsystem/io/serialization/formats/database/dbm.py +7 -7
- exonware/xwsystem/io/serialization/formats/database/shelve.py +7 -7
- exonware/xwsystem/io/serialization/formats/database/sqlite3.py +7 -7
- exonware/xwsystem/io/serialization/formats/tabular/__init__.py +27 -0
- exonware/xwsystem/io/serialization/formats/tabular/base.py +89 -0
- exonware/xwsystem/io/serialization/formats/tabular/csv.py +319 -0
- exonware/xwsystem/io/serialization/formats/tabular/df.py +249 -0
- exonware/xwsystem/io/serialization/formats/tabular/excel.py +291 -0
- exonware/xwsystem/io/serialization/formats/tabular/googlesheets.py +374 -0
- exonware/xwsystem/io/serialization/formats/text/__init__.py +1 -1
- exonware/xwsystem/io/serialization/formats/text/append_only_log.py +199 -0
- exonware/xwsystem/io/serialization/formats/text/configparser.py +5 -5
- exonware/xwsystem/io/serialization/formats/text/csv.py +7 -5
- exonware/xwsystem/io/serialization/formats/text/formdata.py +5 -5
- exonware/xwsystem/io/serialization/formats/text/json.py +65 -33
- exonware/xwsystem/io/serialization/formats/text/json5.py +8 -4
- exonware/xwsystem/io/serialization/formats/text/jsonlines.py +113 -25
- exonware/xwsystem/io/serialization/formats/text/multipart.py +5 -5
- exonware/xwsystem/io/serialization/formats/text/toml.py +8 -6
- exonware/xwsystem/io/serialization/formats/text/xml.py +25 -20
- exonware/xwsystem/io/serialization/formats/text/yaml.py +8 -6
- exonware/xwsystem/io/serialization/parsers/__init__.py +16 -0
- exonware/xwsystem/io/serialization/parsers/base.py +60 -0
- exonware/xwsystem/io/serialization/parsers/hybrid_parser.py +62 -0
- exonware/xwsystem/io/serialization/parsers/msgspec_parser.py +48 -0
- exonware/xwsystem/io/serialization/parsers/orjson_direct_parser.py +54 -0
- exonware/xwsystem/io/serialization/parsers/orjson_parser.py +62 -0
- exonware/xwsystem/io/serialization/parsers/pysimdjson_parser.py +55 -0
- exonware/xwsystem/io/serialization/parsers/rapidjson_parser.py +53 -0
- exonware/xwsystem/io/serialization/parsers/registry.py +91 -0
- exonware/xwsystem/io/serialization/parsers/standard.py +44 -0
- exonware/xwsystem/io/serialization/parsers/ujson_parser.py +53 -0
- exonware/xwsystem/io/serialization/registry.py +4 -4
- exonware/xwsystem/io/serialization/serializer.py +168 -79
- exonware/xwsystem/io/serialization/universal_options.py +367 -0
- exonware/xwsystem/io/serialization/utils/__init__.py +1 -2
- exonware/xwsystem/io/serialization/utils/path_ops.py +5 -6
- exonware/xwsystem/io/source_reader.py +223 -0
- exonware/xwsystem/io/stream/__init__.py +1 -1
- exonware/xwsystem/io/stream/async_operations.py +61 -14
- exonware/xwsystem/io/stream/base.py +1 -2
- exonware/xwsystem/io/stream/codec_io.py +6 -7
- exonware/xwsystem/ipc/__init__.py +1 -0
- exonware/xwsystem/ipc/async_fabric.py +4 -4
- exonware/xwsystem/ipc/base.py +6 -5
- exonware/xwsystem/ipc/contracts.py +41 -66
- exonware/xwsystem/ipc/defs.py +2 -1
- exonware/xwsystem/ipc/errors.py +2 -1
- exonware/xwsystem/ipc/message_queue.py +5 -2
- exonware/xwsystem/ipc/pipes.py +70 -34
- exonware/xwsystem/ipc/process_manager.py +7 -5
- exonware/xwsystem/ipc/process_pool.py +6 -5
- exonware/xwsystem/ipc/shared_memory.py +64 -11
- exonware/xwsystem/monitoring/__init__.py +7 -0
- exonware/xwsystem/monitoring/base.py +11 -8
- exonware/xwsystem/monitoring/contracts.py +86 -144
- exonware/xwsystem/monitoring/defs.py +2 -1
- exonware/xwsystem/monitoring/error_recovery.py +16 -3
- exonware/xwsystem/monitoring/errors.py +2 -1
- exonware/xwsystem/monitoring/facade.py +183 -0
- exonware/xwsystem/monitoring/memory_monitor.py +1 -0
- exonware/xwsystem/monitoring/metrics.py +1 -0
- exonware/xwsystem/monitoring/performance_manager_generic.py +7 -7
- exonware/xwsystem/monitoring/performance_monitor.py +1 -0
- exonware/xwsystem/monitoring/performance_validator.py +1 -0
- exonware/xwsystem/monitoring/system_monitor.py +6 -5
- exonware/xwsystem/monitoring/tracing.py +18 -16
- exonware/xwsystem/monitoring/tracker.py +2 -1
- exonware/xwsystem/operations/__init__.py +5 -50
- exonware/xwsystem/operations/base.py +3 -44
- exonware/xwsystem/operations/contracts.py +25 -15
- exonware/xwsystem/operations/defs.py +1 -1
- exonware/xwsystem/operations/diff.py +5 -4
- exonware/xwsystem/operations/errors.py +1 -1
- exonware/xwsystem/operations/merge.py +6 -4
- exonware/xwsystem/operations/patch.py +5 -4
- exonware/xwsystem/patterns/__init__.py +1 -0
- exonware/xwsystem/patterns/base.py +2 -1
- exonware/xwsystem/patterns/context_manager.py +2 -1
- exonware/xwsystem/patterns/contracts.py +215 -256
- exonware/xwsystem/patterns/defs.py +2 -1
- exonware/xwsystem/patterns/dynamic_facade.py +1 -0
- exonware/xwsystem/patterns/errors.py +2 -4
- exonware/xwsystem/patterns/handler_factory.py +2 -3
- exonware/xwsystem/patterns/import_registry.py +1 -0
- exonware/xwsystem/patterns/object_pool.py +1 -0
- exonware/xwsystem/patterns/registry.py +4 -43
- exonware/xwsystem/plugins/__init__.py +2 -1
- exonware/xwsystem/plugins/base.py +6 -5
- exonware/xwsystem/plugins/contracts.py +94 -158
- exonware/xwsystem/plugins/defs.py +2 -1
- exonware/xwsystem/plugins/errors.py +2 -1
- exonware/xwsystem/py.typed +3 -0
- exonware/xwsystem/query/__init__.py +36 -0
- exonware/xwsystem/query/contracts.py +56 -0
- exonware/xwsystem/query/errors.py +22 -0
- exonware/xwsystem/query/registry.py +128 -0
- exonware/xwsystem/runtime/__init__.py +2 -1
- exonware/xwsystem/runtime/base.py +4 -3
- exonware/xwsystem/runtime/contracts.py +39 -60
- exonware/xwsystem/runtime/defs.py +2 -1
- exonware/xwsystem/runtime/env.py +11 -9
- exonware/xwsystem/runtime/errors.py +2 -1
- exonware/xwsystem/runtime/reflection.py +3 -2
- exonware/xwsystem/security/__init__.py +68 -11
- exonware/xwsystem/security/audit.py +167 -0
- exonware/xwsystem/security/base.py +121 -24
- exonware/xwsystem/security/contracts.py +91 -146
- exonware/xwsystem/security/crypto.py +17 -16
- exonware/xwsystem/security/defs.py +2 -1
- exonware/xwsystem/security/errors.py +2 -1
- exonware/xwsystem/security/facade.py +321 -0
- exonware/xwsystem/security/file_security.py +330 -0
- exonware/xwsystem/security/hazmat.py +11 -8
- exonware/xwsystem/security/monitor.py +372 -0
- exonware/xwsystem/security/path_validator.py +140 -18
- exonware/xwsystem/security/policy.py +357 -0
- exonware/xwsystem/security/resource_limits.py +1 -0
- exonware/xwsystem/security/validator.py +455 -0
- exonware/xwsystem/shared/__init__.py +14 -1
- exonware/xwsystem/shared/base.py +285 -2
- exonware/xwsystem/shared/contracts.py +415 -126
- exonware/xwsystem/shared/defs.py +2 -1
- exonware/xwsystem/shared/errors.py +2 -2
- exonware/xwsystem/shared/xwobject.py +316 -0
- exonware/xwsystem/structures/__init__.py +1 -0
- exonware/xwsystem/structures/base.py +3 -2
- exonware/xwsystem/structures/circular_detector.py +15 -14
- exonware/xwsystem/structures/contracts.py +53 -76
- exonware/xwsystem/structures/defs.py +2 -1
- exonware/xwsystem/structures/errors.py +2 -1
- exonware/xwsystem/structures/tree_walker.py +2 -1
- exonware/xwsystem/threading/__init__.py +21 -4
- exonware/xwsystem/threading/async_primitives.py +6 -5
- exonware/xwsystem/threading/base.py +3 -2
- exonware/xwsystem/threading/contracts.py +87 -143
- exonware/xwsystem/threading/defs.py +2 -1
- exonware/xwsystem/threading/errors.py +2 -1
- exonware/xwsystem/threading/facade.py +175 -0
- exonware/xwsystem/threading/locks.py +1 -0
- exonware/xwsystem/threading/safe_factory.py +1 -0
- exonware/xwsystem/utils/__init__.py +40 -0
- exonware/xwsystem/utils/base.py +22 -21
- exonware/xwsystem/utils/contracts.py +50 -73
- exonware/xwsystem/utils/dt/__init__.py +19 -3
- exonware/xwsystem/utils/dt/base.py +5 -4
- exonware/xwsystem/utils/dt/contracts.py +22 -29
- exonware/xwsystem/utils/dt/defs.py +2 -1
- exonware/xwsystem/utils/dt/errors.py +2 -5
- exonware/xwsystem/utils/dt/formatting.py +88 -2
- exonware/xwsystem/utils/dt/humanize.py +10 -9
- exonware/xwsystem/utils/dt/parsing.py +56 -5
- exonware/xwsystem/utils/dt/timezone_utils.py +2 -24
- exonware/xwsystem/utils/errors.py +2 -4
- exonware/xwsystem/utils/paths.py +1 -0
- exonware/xwsystem/utils/string.py +49 -0
- exonware/xwsystem/utils/test_runner.py +139 -480
- exonware/xwsystem/utils/utils_contracts.py +2 -1
- exonware/xwsystem/utils/web.py +110 -0
- exonware/xwsystem/validation/__init__.py +25 -1
- exonware/xwsystem/validation/base.py +6 -5
- exonware/xwsystem/validation/contracts.py +29 -41
- exonware/xwsystem/validation/data_validator.py +1 -0
- exonware/xwsystem/validation/declarative.py +11 -8
- exonware/xwsystem/validation/defs.py +2 -1
- exonware/xwsystem/validation/errors.py +2 -1
- exonware/xwsystem/validation/facade.py +198 -0
- exonware/xwsystem/validation/fluent_validator.py +22 -19
- exonware/xwsystem/validation/schema_discovery.py +210 -0
- exonware/xwsystem/validation/type_safety.py +2 -1
- exonware/xwsystem/version.py +4 -4
- {exonware_xwsystem-0.0.1.411.dist-info → exonware_xwsystem-0.1.0.3.dist-info}/METADATA +71 -4
- exonware_xwsystem-0.1.0.3.dist-info/RECORD +337 -0
- exonware/xwsystem/caching/USAGE_GUIDE.md +0 -779
- exonware/xwsystem/cli/__init__.py +0 -43
- exonware/xwsystem/cli/console.py +0 -113
- exonware/xwsystem/cli/defs.py +0 -134
- exonware/xwsystem/conf.py +0 -44
- exonware/xwsystem/security/auth.py +0 -484
- exonware_xwsystem-0.0.1.411.dist-info/RECORD +0 -274
- {exonware_xwsystem-0.0.1.411.dist-info → exonware_xwsystem-0.1.0.3.dist-info}/WHEEL +0 -0
- {exonware_xwsystem-0.0.1.411.dist-info → exonware_xwsystem-0.1.0.3.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,455 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
#exonware/xwsystem/src/exonware/xwsystem/security/validator.py
|
|
3
|
+
"""
|
|
4
|
+
Company: eXonware.com
|
|
5
|
+
Author: Eng. Muhammad AlShehri
|
|
6
|
+
Email: connect@exonware.com
|
|
7
|
+
Version: 0.1.0.3
|
|
8
|
+
Generation Date: 07-Jan-2025
|
|
9
|
+
|
|
10
|
+
Security validator implementation for XWSystem.
|
|
11
|
+
Implements ISecurityValidator protocol for comprehensive security validation.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import re
|
|
15
|
+
import html
|
|
16
|
+
import urllib.parse
|
|
17
|
+
from typing import Any, Optional
|
|
18
|
+
from email.utils import parseaddr
|
|
19
|
+
from urllib.parse import urlparse
|
|
20
|
+
|
|
21
|
+
from .base import ASecurityValidatorBase
|
|
22
|
+
from .contracts import ISecurityValidator
|
|
23
|
+
from .defs import SecurityLevel
|
|
24
|
+
from ..config.logging_setup import get_logger
|
|
25
|
+
|
|
26
|
+
logger = get_logger("xwsystem.security.validator")
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class SecurityValidator(ASecurityValidatorBase, ISecurityValidator):
|
|
30
|
+
"""
|
|
31
|
+
Security validator implementation.
|
|
32
|
+
|
|
33
|
+
Provides comprehensive security validation including:
|
|
34
|
+
- Password strength validation
|
|
35
|
+
- Input validation and sanitization
|
|
36
|
+
- SQL injection detection
|
|
37
|
+
- XSS detection
|
|
38
|
+
- Certificate validation
|
|
39
|
+
- Security headers validation
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
def __init__(self, security_level: SecurityLevel = SecurityLevel.MEDIUM):
|
|
43
|
+
"""
|
|
44
|
+
Initialize security validator.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
security_level: Security level for validation
|
|
48
|
+
"""
|
|
49
|
+
super().__init__(security_level)
|
|
50
|
+
self._validation_errors: list[str] = []
|
|
51
|
+
|
|
52
|
+
# SQL injection patterns
|
|
53
|
+
self._sql_patterns = [
|
|
54
|
+
r"(\b(SELECT|INSERT|UPDATE|DELETE|DROP|CREATE|ALTER|EXEC|EXECUTE|UNION|SCRIPT)\b)",
|
|
55
|
+
r"(--|#|/\*|\*/|;|\||&)",
|
|
56
|
+
r"(\bOR\b.*=.*|\bAND\b.*=.*)",
|
|
57
|
+
r"('|(\\')|(;)|(--)|(\|)|(\*)|(%)|(\+)|(,)|(\\)|(\/)|(\[)|(\]))",
|
|
58
|
+
r"(\bxp_\w+|\bsp_\w+)", # SQL Server stored procedures
|
|
59
|
+
]
|
|
60
|
+
|
|
61
|
+
# XSS patterns
|
|
62
|
+
self._xss_patterns = [
|
|
63
|
+
r"<script[^>]*>.*?</script>",
|
|
64
|
+
r"<iframe[^>]*>.*?</iframe>",
|
|
65
|
+
r"javascript:",
|
|
66
|
+
r"on\w+\s*=", # Event handlers like onclick, onload, etc.
|
|
67
|
+
r"<img[^>]*src[^>]*=.*?javascript:",
|
|
68
|
+
r"<svg[^>]*onload",
|
|
69
|
+
r"<body[^>]*onload",
|
|
70
|
+
r"<input[^>]*onfocus",
|
|
71
|
+
r"eval\s*\(",
|
|
72
|
+
r"expression\s*\(",
|
|
73
|
+
]
|
|
74
|
+
|
|
75
|
+
# Security headers to check
|
|
76
|
+
self._required_headers = {
|
|
77
|
+
"X-Content-Type-Options": "nosniff",
|
|
78
|
+
"X-Frame-Options": ["DENY", "SAMEORIGIN"],
|
|
79
|
+
"X-XSS-Protection": "1; mode=block",
|
|
80
|
+
"Strict-Transport-Security": None, # Just presence required
|
|
81
|
+
"Content-Security-Policy": None, # Just presence required
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
def validate_password(self, password: str) -> tuple[bool, list[str]]:
|
|
85
|
+
"""
|
|
86
|
+
Validate password strength.
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
password: Password to validate
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
Tuple of (is_valid, error_messages)
|
|
93
|
+
"""
|
|
94
|
+
errors: list[str] = []
|
|
95
|
+
|
|
96
|
+
if not password:
|
|
97
|
+
errors.append("Password cannot be empty")
|
|
98
|
+
return False, errors
|
|
99
|
+
|
|
100
|
+
if len(password) < 8:
|
|
101
|
+
errors.append("Password must be at least 8 characters long")
|
|
102
|
+
|
|
103
|
+
if len(password) > 128:
|
|
104
|
+
errors.append("Password must be no more than 128 characters long")
|
|
105
|
+
|
|
106
|
+
if not re.search(r"[a-z]", password):
|
|
107
|
+
errors.append("Password must contain at least one lowercase letter")
|
|
108
|
+
|
|
109
|
+
if not re.search(r"[A-Z]", password):
|
|
110
|
+
errors.append("Password must contain at least one uppercase letter")
|
|
111
|
+
|
|
112
|
+
if not re.search(r"\d", password):
|
|
113
|
+
errors.append("Password must contain at least one digit")
|
|
114
|
+
|
|
115
|
+
if not re.search(r"[!@#$%^&*(),.?\":{}|<>]", password):
|
|
116
|
+
errors.append("Password must contain at least one special character")
|
|
117
|
+
|
|
118
|
+
# Check for common weak passwords
|
|
119
|
+
weak_passwords = [
|
|
120
|
+
"password", "12345678", "qwerty", "abc123", "password123",
|
|
121
|
+
"admin", "letmein", "welcome", "monkey", "1234567890"
|
|
122
|
+
]
|
|
123
|
+
if password.lower() in weak_passwords:
|
|
124
|
+
errors.append("Password is too common and easily guessable")
|
|
125
|
+
|
|
126
|
+
# Check for repeated characters
|
|
127
|
+
if re.search(r"(.)\1{3,}", password):
|
|
128
|
+
errors.append("Password contains too many repeated characters")
|
|
129
|
+
|
|
130
|
+
# Check for sequential characters
|
|
131
|
+
if re.search(r"(012|123|234|345|456|567|678|789|890|abc|bcd|cde|def|efg|fgh|ghi|hij|ijk|jkl|klm|lmn|mno|nop|opq|pqr|qrs|rst|stu|tuv|uvw|vwx|wxy|xyz)", password.lower()):
|
|
132
|
+
errors.append("Password contains sequential characters")
|
|
133
|
+
|
|
134
|
+
is_valid = len(errors) == 0
|
|
135
|
+
return is_valid, errors
|
|
136
|
+
|
|
137
|
+
def validate_input(self, input_data: str, input_type: str) -> tuple[bool, list[str]]:
|
|
138
|
+
"""
|
|
139
|
+
Validate input data based on type.
|
|
140
|
+
|
|
141
|
+
Args:
|
|
142
|
+
input_data: Input data to validate
|
|
143
|
+
input_type: Type of input (email, url, etc.)
|
|
144
|
+
|
|
145
|
+
Returns:
|
|
146
|
+
Tuple of (is_valid, error_messages)
|
|
147
|
+
"""
|
|
148
|
+
errors: list[str] = []
|
|
149
|
+
|
|
150
|
+
if not isinstance(input_data, str):
|
|
151
|
+
errors.append(f"Input must be a string, got {type(input_data).__name__}")
|
|
152
|
+
return False, errors
|
|
153
|
+
|
|
154
|
+
if input_type == "email":
|
|
155
|
+
name, addr = parseaddr(input_data)
|
|
156
|
+
if not addr or "@" not in addr:
|
|
157
|
+
errors.append("Invalid email format")
|
|
158
|
+
else:
|
|
159
|
+
# Basic email regex
|
|
160
|
+
email_pattern = r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"
|
|
161
|
+
if not re.match(email_pattern, addr):
|
|
162
|
+
errors.append("Invalid email format")
|
|
163
|
+
|
|
164
|
+
elif input_type == "url":
|
|
165
|
+
try:
|
|
166
|
+
result = urlparse(input_data)
|
|
167
|
+
if not all([result.scheme, result.netloc]):
|
|
168
|
+
errors.append("Invalid URL format")
|
|
169
|
+
except Exception as e:
|
|
170
|
+
errors.append(f"Invalid URL: {str(e)}")
|
|
171
|
+
|
|
172
|
+
elif input_type == "integer":
|
|
173
|
+
try:
|
|
174
|
+
int(input_data)
|
|
175
|
+
except ValueError:
|
|
176
|
+
errors.append("Input must be a valid integer")
|
|
177
|
+
|
|
178
|
+
elif input_type == "float":
|
|
179
|
+
try:
|
|
180
|
+
float(input_data)
|
|
181
|
+
except ValueError:
|
|
182
|
+
errors.append("Input must be a valid float")
|
|
183
|
+
|
|
184
|
+
# Check for SQL injection
|
|
185
|
+
if self.detect_sql_injection(input_data):
|
|
186
|
+
errors.append("Potential SQL injection detected")
|
|
187
|
+
|
|
188
|
+
# Check for XSS
|
|
189
|
+
if self.detect_xss(input_data):
|
|
190
|
+
errors.append("Potential XSS attack detected")
|
|
191
|
+
|
|
192
|
+
is_valid = len(errors) == 0
|
|
193
|
+
return is_valid, errors
|
|
194
|
+
|
|
195
|
+
def sanitize_input(self, input_data: str) -> str:
|
|
196
|
+
"""
|
|
197
|
+
Sanitize input data.
|
|
198
|
+
|
|
199
|
+
Args:
|
|
200
|
+
input_data: Input data to sanitize
|
|
201
|
+
|
|
202
|
+
Returns:
|
|
203
|
+
Sanitized data
|
|
204
|
+
"""
|
|
205
|
+
if not isinstance(input_data, str):
|
|
206
|
+
return str(input_data)
|
|
207
|
+
|
|
208
|
+
# HTML escape
|
|
209
|
+
sanitized = html.escape(input_data)
|
|
210
|
+
|
|
211
|
+
# Remove null bytes
|
|
212
|
+
sanitized = sanitized.replace("\x00", "")
|
|
213
|
+
|
|
214
|
+
# Remove control characters except newlines and tabs
|
|
215
|
+
sanitized = re.sub(r"[\x00-\x08\x0B-\x0C\x0E-\x1F\x7F]", "", sanitized)
|
|
216
|
+
|
|
217
|
+
# URL decode to prevent double encoding attacks
|
|
218
|
+
try:
|
|
219
|
+
sanitized = urllib.parse.unquote(sanitized)
|
|
220
|
+
sanitized = html.escape(sanitized) # Re-escape after decode
|
|
221
|
+
except Exception:
|
|
222
|
+
pass
|
|
223
|
+
|
|
224
|
+
return sanitized
|
|
225
|
+
|
|
226
|
+
def detect_sql_injection(self, input_data: str) -> bool:
|
|
227
|
+
"""
|
|
228
|
+
Detect SQL injection attempts.
|
|
229
|
+
|
|
230
|
+
Args:
|
|
231
|
+
input_data: Input data to check
|
|
232
|
+
|
|
233
|
+
Returns:
|
|
234
|
+
True if SQL injection detected
|
|
235
|
+
"""
|
|
236
|
+
if not isinstance(input_data, str):
|
|
237
|
+
input_data = str(input_data)
|
|
238
|
+
|
|
239
|
+
input_upper = input_data.upper()
|
|
240
|
+
|
|
241
|
+
for pattern in self._sql_patterns:
|
|
242
|
+
if re.search(pattern, input_upper, re.IGNORECASE):
|
|
243
|
+
logger.warning(f"SQL injection pattern detected: {pattern[:50]}")
|
|
244
|
+
return True
|
|
245
|
+
|
|
246
|
+
return False
|
|
247
|
+
|
|
248
|
+
def detect_xss(self, input_data: str) -> bool:
|
|
249
|
+
"""
|
|
250
|
+
Detect XSS attempts.
|
|
251
|
+
|
|
252
|
+
Args:
|
|
253
|
+
input_data: Input data to check
|
|
254
|
+
|
|
255
|
+
Returns:
|
|
256
|
+
True if XSS detected
|
|
257
|
+
"""
|
|
258
|
+
if not isinstance(input_data, str):
|
|
259
|
+
input_data = str(input_data)
|
|
260
|
+
|
|
261
|
+
for pattern in self._xss_patterns:
|
|
262
|
+
if re.search(pattern, input_data, re.IGNORECASE):
|
|
263
|
+
logger.warning(f"XSS pattern detected: {pattern[:50]}")
|
|
264
|
+
return True
|
|
265
|
+
|
|
266
|
+
return False
|
|
267
|
+
|
|
268
|
+
def validate_certificate(self, certificate: bytes) -> tuple[bool, str]:
|
|
269
|
+
"""
|
|
270
|
+
Validate certificate.
|
|
271
|
+
|
|
272
|
+
Args:
|
|
273
|
+
certificate: Certificate data
|
|
274
|
+
|
|
275
|
+
Returns:
|
|
276
|
+
Tuple of (is_valid, error_message)
|
|
277
|
+
"""
|
|
278
|
+
# Check if cryptography is available
|
|
279
|
+
import importlib.util
|
|
280
|
+
_cryptography_spec = importlib.util.find_spec('cryptography')
|
|
281
|
+
if _cryptography_spec is None:
|
|
282
|
+
return False, "cryptography library not available for certificate validation"
|
|
283
|
+
|
|
284
|
+
try:
|
|
285
|
+
from cryptography import x509
|
|
286
|
+
from cryptography.hazmat.backends import default_backend
|
|
287
|
+
|
|
288
|
+
# Try to parse the certificate
|
|
289
|
+
cert = x509.load_pem_x509_certificate(certificate, default_backend())
|
|
290
|
+
|
|
291
|
+
# Check if certificate is expired
|
|
292
|
+
from datetime import datetime
|
|
293
|
+
if cert.not_valid_after < datetime.now():
|
|
294
|
+
return False, "Certificate has expired"
|
|
295
|
+
|
|
296
|
+
# Check if certificate is not yet valid
|
|
297
|
+
if cert.not_valid_before > datetime.now():
|
|
298
|
+
return False, "Certificate is not yet valid"
|
|
299
|
+
|
|
300
|
+
return True, "Certificate is valid"
|
|
301
|
+
except Exception as e:
|
|
302
|
+
return False, f"Invalid certificate: {str(e)}"
|
|
303
|
+
|
|
304
|
+
def check_security_headers(self, headers: dict[str, str]) -> dict[str, bool]:
|
|
305
|
+
"""
|
|
306
|
+
Check security headers.
|
|
307
|
+
|
|
308
|
+
Args:
|
|
309
|
+
headers: HTTP headers
|
|
310
|
+
|
|
311
|
+
Returns:
|
|
312
|
+
Dictionary of header validation results
|
|
313
|
+
"""
|
|
314
|
+
results: dict[str, bool] = {}
|
|
315
|
+
headers_upper = {k.upper(): v for k, v in headers.items()}
|
|
316
|
+
|
|
317
|
+
for header_name, expected_value in self._required_headers.items():
|
|
318
|
+
header_key = header_name.upper()
|
|
319
|
+
|
|
320
|
+
if header_key not in headers_upper:
|
|
321
|
+
results[header_name] = False
|
|
322
|
+
continue
|
|
323
|
+
|
|
324
|
+
if expected_value is None:
|
|
325
|
+
# Just presence required
|
|
326
|
+
results[header_name] = True
|
|
327
|
+
elif isinstance(expected_value, list):
|
|
328
|
+
# Value is one of the allowed values
|
|
329
|
+
results[header_name] = headers_upper[header_key].upper() in [v.upper() for v in expected_value]
|
|
330
|
+
else:
|
|
331
|
+
# Value matches exactly
|
|
332
|
+
results[header_name] = headers_upper[header_key].upper() == expected_value.upper()
|
|
333
|
+
|
|
334
|
+
return results
|
|
335
|
+
|
|
336
|
+
# Implementation of ASecurityValidatorBase abstract methods
|
|
337
|
+
|
|
338
|
+
def validate_output(self, data: Any, output_type: str) -> bool:
|
|
339
|
+
"""
|
|
340
|
+
Validate output data.
|
|
341
|
+
|
|
342
|
+
Args:
|
|
343
|
+
data: Output data to validate
|
|
344
|
+
output_type: Type of output
|
|
345
|
+
|
|
346
|
+
Returns:
|
|
347
|
+
True if valid
|
|
348
|
+
"""
|
|
349
|
+
# Basic validation - can be extended
|
|
350
|
+
if output_type == "json":
|
|
351
|
+
import json
|
|
352
|
+
try:
|
|
353
|
+
json.dumps(data)
|
|
354
|
+
return True
|
|
355
|
+
except (TypeError, ValueError):
|
|
356
|
+
return False
|
|
357
|
+
|
|
358
|
+
return True
|
|
359
|
+
|
|
360
|
+
def validate_operation(self, operation: str, **kwargs) -> bool:
|
|
361
|
+
"""
|
|
362
|
+
Validate operation.
|
|
363
|
+
|
|
364
|
+
Args:
|
|
365
|
+
operation: Operation name
|
|
366
|
+
**kwargs: Operation parameters
|
|
367
|
+
|
|
368
|
+
Returns:
|
|
369
|
+
True if valid
|
|
370
|
+
"""
|
|
371
|
+
# Check if operation is in allowed list
|
|
372
|
+
allowed_operations = ["read", "write", "delete", "execute"]
|
|
373
|
+
|
|
374
|
+
if operation.lower() not in allowed_operations:
|
|
375
|
+
self._validation_errors.append(f"Operation '{operation}' is not allowed")
|
|
376
|
+
return False
|
|
377
|
+
|
|
378
|
+
# Validate parameters based on operation
|
|
379
|
+
if operation.lower() == "delete" and self.security_level == SecurityLevel.HIGH:
|
|
380
|
+
# High security: require confirmation
|
|
381
|
+
if "confirm" not in kwargs or not kwargs.get("confirm"):
|
|
382
|
+
self._validation_errors.append("Delete operation requires confirmation")
|
|
383
|
+
return False
|
|
384
|
+
|
|
385
|
+
return True
|
|
386
|
+
|
|
387
|
+
def add_validation_rule(self, rule_name: str, rule_func: callable) -> None:
|
|
388
|
+
"""
|
|
389
|
+
Add validation rule.
|
|
390
|
+
|
|
391
|
+
Args:
|
|
392
|
+
rule_name: Rule name
|
|
393
|
+
rule_func: Rule function
|
|
394
|
+
"""
|
|
395
|
+
self._validation_rules[rule_name] = rule_func
|
|
396
|
+
|
|
397
|
+
def remove_validation_rule(self, rule_name: str) -> None:
|
|
398
|
+
"""
|
|
399
|
+
Remove validation rule.
|
|
400
|
+
|
|
401
|
+
Args:
|
|
402
|
+
rule_name: Rule name
|
|
403
|
+
"""
|
|
404
|
+
if rule_name in self._validation_rules:
|
|
405
|
+
del self._validation_rules[rule_name]
|
|
406
|
+
|
|
407
|
+
def get_validation_errors(self) -> list[str]:
|
|
408
|
+
"""
|
|
409
|
+
Get validation errors.
|
|
410
|
+
|
|
411
|
+
Returns:
|
|
412
|
+
List of error messages
|
|
413
|
+
"""
|
|
414
|
+
return self._validation_errors.copy()
|
|
415
|
+
|
|
416
|
+
def clear_validation_errors(self) -> None:
|
|
417
|
+
"""Clear validation errors."""
|
|
418
|
+
self._validation_errors.clear()
|
|
419
|
+
|
|
420
|
+
def is_secure_operation(self, operation: str) -> bool:
|
|
421
|
+
"""
|
|
422
|
+
Check if operation is secure.
|
|
423
|
+
|
|
424
|
+
Args:
|
|
425
|
+
operation: Operation name
|
|
426
|
+
|
|
427
|
+
Returns:
|
|
428
|
+
True if secure
|
|
429
|
+
"""
|
|
430
|
+
# Check against known secure operations
|
|
431
|
+
secure_operations = ["read", "validate", "check"]
|
|
432
|
+
return operation.lower() in secure_operations
|
|
433
|
+
|
|
434
|
+
def get_security_score(self) -> float:
|
|
435
|
+
"""
|
|
436
|
+
Get security score.
|
|
437
|
+
|
|
438
|
+
Returns:
|
|
439
|
+
Security score (0.0 to 1.0)
|
|
440
|
+
"""
|
|
441
|
+
# Calculate score based on security level and validation rules
|
|
442
|
+
base_scores = {
|
|
443
|
+
SecurityLevel.NONE: 0.0,
|
|
444
|
+
SecurityLevel.LOW: 0.3,
|
|
445
|
+
SecurityLevel.MEDIUM: 0.6,
|
|
446
|
+
SecurityLevel.HIGH: 0.8,
|
|
447
|
+
SecurityLevel.CRITICAL: 1.0,
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
base_score = base_scores.get(self.security_level, 0.5)
|
|
451
|
+
|
|
452
|
+
# Add bonus for validation rules
|
|
453
|
+
rule_bonus = min(len(self._validation_rules) * 0.05, 0.2)
|
|
454
|
+
|
|
455
|
+
return min(base_score + rule_bonus, 1.0)
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
+
#exonware/xwsystem/src/exonware/xwsystem/shared/__init__.py
|
|
2
3
|
#exonware/xwsystem/shared/__init__.py
|
|
3
4
|
"""
|
|
4
5
|
Company: eXonware.com
|
|
5
6
|
Author: Eng. Muhammad AlShehri
|
|
6
7
|
Email: connect@exonware.com
|
|
7
|
-
Version: 0.0.
|
|
8
|
+
Version: 0.1.0.3
|
|
8
9
|
Generation Date: 10-Sep-2025
|
|
9
10
|
|
|
10
11
|
Shared types and utilities for XWSystem modules.
|
|
@@ -27,11 +28,13 @@ from .defs import (
|
|
|
27
28
|
from .base import (
|
|
28
29
|
AConfigurationBase,
|
|
29
30
|
ACoreBase,
|
|
31
|
+
AObject,
|
|
30
32
|
AOperationBase,
|
|
31
33
|
AResourceManagerBase,
|
|
32
34
|
AValidationBase,
|
|
33
35
|
BaseCore,
|
|
34
36
|
)
|
|
37
|
+
from .xwobject import XWObject
|
|
35
38
|
from .contracts import (
|
|
36
39
|
ICloneable,
|
|
37
40
|
IComparable,
|
|
@@ -41,9 +44,13 @@ from .contracts import (
|
|
|
41
44
|
IFactory,
|
|
42
45
|
IMetadata,
|
|
43
46
|
INative,
|
|
47
|
+
IObject,
|
|
44
48
|
IStringable,
|
|
45
49
|
ILifecycle,
|
|
46
50
|
IIterable,
|
|
51
|
+
# Provider interfaces (for xwauth/xwstorage decoupling)
|
|
52
|
+
IBasicProviderAuth,
|
|
53
|
+
IBasicProviderStorage,
|
|
47
54
|
)
|
|
48
55
|
from .errors import (
|
|
49
56
|
CoreConfigurationError,
|
|
@@ -79,11 +86,14 @@ __all__ = [
|
|
|
79
86
|
"AConfigurationBase",
|
|
80
87
|
"AValidationBase",
|
|
81
88
|
"AOperationBase",
|
|
89
|
+
"AObject",
|
|
82
90
|
"BaseCore",
|
|
91
|
+
"XWObject",
|
|
83
92
|
# Contracts
|
|
84
93
|
"IID",
|
|
85
94
|
"IStringable",
|
|
86
95
|
"INative",
|
|
96
|
+
"IObject",
|
|
87
97
|
"ICloneable",
|
|
88
98
|
"IComparable",
|
|
89
99
|
"IIterable",
|
|
@@ -92,6 +102,9 @@ __all__ = [
|
|
|
92
102
|
"ILifecycle",
|
|
93
103
|
"IFactory",
|
|
94
104
|
"ICore",
|
|
105
|
+
# Provider interfaces
|
|
106
|
+
"IBasicProviderAuth",
|
|
107
|
+
"IBasicProviderStorage",
|
|
95
108
|
# Errors
|
|
96
109
|
"CoreError",
|
|
97
110
|
"CoreInitializationError",
|