aird 0.4.23.dev18__tar.gz → 0.4.23.dev20__tar.gz
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.
- {aird-0.4.23.dev18/aird.egg-info → aird-0.4.23.dev20}/PKG-INFO +1 -1
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/constants/__init__.py +1 -1
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/handlers/file_op_handlers.py +1 -1
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/js/browse/app.js +5 -5
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/js/download-manager.js +6 -11
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/js/file-transfer-ws.js +48 -7
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/js/transfer-tracker.js +7 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/browse.html +0 -2
- {aird-0.4.23.dev18 → aird-0.4.23.dev20/aird.egg-info}/PKG-INFO +1 -1
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird.egg-info/SOURCES.txt +0 -2
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/setup.py +1 -1
- aird-0.4.23.dev18/aird/static/js/file-transfer-http.js +0 -98
- aird-0.4.23.dev18/aird/static/js/file-transfer.js +0 -55
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/LICENSE +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/MANIFEST.in +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/README.md +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/__init__.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/__main__.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/app_context.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/cli/__init__.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/cli/__main__.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/cli/authelia.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/cli/config.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/cli/main.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/cli/session.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/cloud/__init__.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/config.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/constants/admin.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/constants/file_ops.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/constants/input_limits.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/constants/media.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/core/__init__.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/core/events.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/core/file_operations.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/core/filter_expression.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/core/folder_size.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/core/input_validation.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/core/mmap_handler.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/core/security.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/core/share_root.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/core/websocket_manager.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/core/zip_download.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/database/__init__.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/database/db.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/database/feature_flags.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/database/ldap.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/db/__init__.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/db/audit.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/db/config.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/db/favorites.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/db/network_shares.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/db/policies.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/db/policy_decisions.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/db/policy_seeds.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/db/quota.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/db/resource_tags.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/db/schema.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/db/shares.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/db/user_attributes.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/db/users.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/domain/__init__.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/domain/contracts.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/domain/models.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/email/__init__.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/email/brevo.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/email/resolve.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/event_loop.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/handlers/__init__.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/handlers/abac_handlers.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/handlers/admin_handlers.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/handlers/api_handlers.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/handlers/auth_handlers.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/handlers/base_handler.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/handlers/constants.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/handlers/health_handler.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/handlers/p2p_handlers.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/handlers/share_handlers.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/handlers/transfer_ws_handlers.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/handlers/view_handlers.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/main.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/network_share_manager.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/server_runtime.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/services/__init__.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/services/audit_service.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/services/config_service.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/services/email_service.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/services/email_subscriber.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/services/event_subscribers.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/services/favorites_service.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/services/network_share_service.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/services/p2p_service.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/services/policy_service.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/services/quota_service.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/services/share_service.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/services/tag_service.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/services/user_service.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/sql_identifiers.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/css/app.css +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/favicon.png +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/favicon.svg +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/img/logo-icon.png +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/img/logo-mark.svg +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/img/logo-text.png +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/img/logo.png +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/js/aird-core.js +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/js/bg-canvas.js +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/js/common/command-palette.js +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/js/components/folder-picker.js +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/js/feature-flags-live.js +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/js/folder-size-scan.js +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/js/login-ui.js +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/js/media-view.js +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/js/p2p/app.js +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/js/p2p/mediator.js +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/js/p2p/qr-adapter.js +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/js/p2p/signaling-service.js +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/js/p2p/state-machine.js +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/js/p2p/transfer-service.js +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/js/pages/p2p-page.js +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/js/pages/super-search.js +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/js/share/app.js +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/js/theme.js +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/js/vendor/pdf.min.js +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/js/vendor/pdf.worker.min.js +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/js/vendor/qrcode-browser.js +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/_admin_tabs.html +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/_app_nav_header.html +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/_bg_canvas.html +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/_theme_early.html +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/_theme_login_corner.html +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/admin.html +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/admin_audit.html +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/admin_ldap.html +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/admin_login.html +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/admin_network_shares.html +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/admin_policies.html +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/admin_tags.html +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/admin_user_attributes.html +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/admin_users.html +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/directory.html +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/edit.html +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/error.html +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/file.html +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/ldap_config_create.html +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/ldap_config_edit.html +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/login.html +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/media_view.html +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/p2p_transfer.html +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/profile.html +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/share.html +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/shared_list.html +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/super_search.html +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/tagged_files.html +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/token_verification.html +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/user_create.html +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/user_edit.html +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/utils/__init__.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/utils/util.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird.egg-info/dependency_links.txt +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird.egg-info/entry_points.txt +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird.egg-info/requires.txt +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird.egg-info/top_level.txt +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/setup.cfg +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/__init__.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/conftest.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/handler_helpers.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_admin_handlers.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_api_handlers.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_architecture_conformance.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_auth_handlers.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_auth_handlers_extended.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_base_handler.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_base_handler_pep.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_cli.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_cloud.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_config.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_core_file_operations.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_database_db.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_database_feature_flags.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_database_ldap.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_database_shares.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_database_users.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_database_users_hashing.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_db.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_email_service.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_file_op_handlers.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_filter_expression.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_folder_size.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_main.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_mmap_handler.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_multi_user.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_network_shares.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_p2p_handlers.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_password_hashing.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_policy_service.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_rate_limit.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_security.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_security_comprehensive.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_server_runtime.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_share_handlers.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_share_ownership.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_super_search_handler.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_tag_service.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_transfer_ws_handlers.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_util.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_view_handlers.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_websocket_manager.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_wheel_static_assets.py +0 -0
- {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_zip_download.py +0 -0
|
@@ -63,7 +63,7 @@ UPLOAD_CONFIG = {
|
|
|
63
63
|
|
|
64
64
|
# File operation constants (derived from UPLOAD_CONFIG at startup)
|
|
65
65
|
MAX_FILE_SIZE = UPLOAD_CONFIG["max_file_size_mb"] * 1024 * 1024
|
|
66
|
-
# HTTP /upload body limit (browser uploads
|
|
66
|
+
# HTTP /upload body limit (browser uploads use WebSocket; CLI may POST whole file)
|
|
67
67
|
UPLOAD_REQUEST_MAX_BODY_SIZE = MAX_FILE_SIZE + (1024 * 1024)
|
|
68
68
|
MAX_READABLE_FILE_SIZE = 50 * 1024 * 1024 # 50 MB
|
|
69
69
|
|
|
@@ -349,7 +349,7 @@ def _process_bulk_action(
|
|
|
349
349
|
|
|
350
350
|
@tornado.web.stream_request_body
|
|
351
351
|
class UploadHandler(BaseHandler):
|
|
352
|
-
"""
|
|
352
|
+
"""Single-request HTTP upload (CLI / direct origin). Browser uses WebSocket."""
|
|
353
353
|
|
|
354
354
|
def check_xsrf_cookie(self) -> None:
|
|
355
355
|
"""Streamed uploads send raw body; accept X-XSRFToken header or ?_xsrf= query param."""
|
|
@@ -258,7 +258,7 @@
|
|
|
258
258
|
const raw = (err && err.message) ? String(err.message).trim() : "";
|
|
259
259
|
if (!raw || raw === "cancelled") return raw;
|
|
260
260
|
const lower = raw.toLowerCase();
|
|
261
|
-
if (lower.includes("network") || lower.includes("websocket")
|
|
261
|
+
if (lower.includes("network") || lower.includes("websocket")) {
|
|
262
262
|
return "Upload interrupted. Check your connection and try again.";
|
|
263
263
|
}
|
|
264
264
|
if (lower.includes("403") || lower.includes("access denied")) {
|
|
@@ -271,15 +271,15 @@
|
|
|
271
271
|
}
|
|
272
272
|
|
|
273
273
|
async function uploadFile(item) {
|
|
274
|
-
const
|
|
275
|
-
if (!
|
|
276
|
-
throw new Error("
|
|
274
|
+
const FTW = globalThis.AirdFileTransferWs;
|
|
275
|
+
if (!FTW?.uploadFile) {
|
|
276
|
+
throw new Error("WebSocket upload unavailable. Hard-refresh the page.");
|
|
277
277
|
}
|
|
278
278
|
const dir = item.uploadDir ?? document.getElementById('currentPath')?.value ?? '';
|
|
279
279
|
const fname = item.uploadName ?? item.file.name;
|
|
280
280
|
item.uploadSignal = { aborted: false };
|
|
281
281
|
const cancelFn = () => abortActiveUploads(item);
|
|
282
|
-
await
|
|
282
|
+
await FTW.uploadFile(item.file, {
|
|
283
283
|
uploadDir: dir,
|
|
284
284
|
filename: fname,
|
|
285
285
|
signal: item.uploadSignal,
|
|
@@ -59,19 +59,9 @@
|
|
|
59
59
|
|
|
60
60
|
cancelOne(item) {
|
|
61
61
|
if (!item) return;
|
|
62
|
-
if (item.status === 'downloading'
|
|
62
|
+
if (item.status === 'downloading' || item.status === 'queued') {
|
|
63
63
|
item.cancelSignal.aborted = true;
|
|
64
64
|
item.status = 'cancelled';
|
|
65
|
-
if (item.ttId != null) {
|
|
66
|
-
global.AirdTransferTracker?.failTransfer(item.ttId, 'Cancelled');
|
|
67
|
-
}
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
if (item.status !== 'queued') return;
|
|
71
|
-
item.status = 'cancelled';
|
|
72
|
-
item.cancelSignal.aborted = true;
|
|
73
|
-
if (item.ttId != null) {
|
|
74
|
-
global.AirdTransferTracker?.failTransfer(item.ttId, 'Cancelled');
|
|
75
65
|
}
|
|
76
66
|
}
|
|
77
67
|
|
|
@@ -103,9 +93,14 @@
|
|
|
103
93
|
if (item.ws && FTW?.downloadFile) {
|
|
104
94
|
item.status = 'downloading';
|
|
105
95
|
item.downloadStart = Date.now();
|
|
96
|
+
const onCancel = () => {
|
|
97
|
+
item.cancelSignal.aborted = true;
|
|
98
|
+
item.status = 'cancelled';
|
|
99
|
+
};
|
|
106
100
|
try {
|
|
107
101
|
const result = await FTW.downloadFile(item.path, {
|
|
108
102
|
signal: item.cancelSignal,
|
|
103
|
+
onCancel: onCancel,
|
|
109
104
|
});
|
|
110
105
|
if (item.cancelSignal?.aborted || this.cancelled) {
|
|
111
106
|
item.status = 'cancelled';
|
|
@@ -155,22 +155,30 @@
|
|
|
155
155
|
|
|
156
156
|
/**
|
|
157
157
|
* @param {string} path relative file path
|
|
158
|
-
* @param {{ onProgress?: (loaded: number, total: number) => void, signal?: { aborted: boolean } }} options
|
|
158
|
+
* @param {{ onProgress?: (loaded: number, total: number) => void, signal?: { aborted: boolean }, onCancel?: Function }} options
|
|
159
159
|
*/
|
|
160
160
|
async function downloadFile(path, options) {
|
|
161
161
|
options = options || {};
|
|
162
162
|
const onProgress = options.onProgress || function () {};
|
|
163
|
-
const signal = options.signal;
|
|
163
|
+
const signal = options.signal || { aborted: false };
|
|
164
164
|
const ws = await openSocket();
|
|
165
165
|
const chunks = [];
|
|
166
166
|
let meta = null;
|
|
167
|
+
let settled = false;
|
|
168
|
+
let abortPoll = null;
|
|
167
169
|
|
|
168
170
|
const TT = global.AirdTransferTracker;
|
|
169
171
|
const fname = path.split('/').pop() || path;
|
|
170
|
-
const ttId = TT
|
|
172
|
+
const ttId = TT
|
|
173
|
+
? TT.addTransfer(fname, 0, 'download', { onCancel: options.onCancel })
|
|
174
|
+
: null;
|
|
171
175
|
|
|
172
176
|
return new Promise((resolve, reject) => {
|
|
173
177
|
function cleanup() {
|
|
178
|
+
if (abortPoll !== null) {
|
|
179
|
+
clearInterval(abortPoll);
|
|
180
|
+
abortPoll = null;
|
|
181
|
+
}
|
|
174
182
|
ws.removeEventListener('message', onMessage);
|
|
175
183
|
try {
|
|
176
184
|
ws.close();
|
|
@@ -179,11 +187,38 @@
|
|
|
179
187
|
}
|
|
180
188
|
}
|
|
181
189
|
|
|
190
|
+
function finishCancel() {
|
|
191
|
+
if (settled) return;
|
|
192
|
+
settled = true;
|
|
193
|
+
signal.aborted = true;
|
|
194
|
+
try {
|
|
195
|
+
ws.send(JSON.stringify({ action: 'cancel' }));
|
|
196
|
+
} catch {
|
|
197
|
+
/* ignore */
|
|
198
|
+
}
|
|
199
|
+
cleanup();
|
|
200
|
+
if (TT && ttId) TT.failTransfer(ttId, 'Cancelled');
|
|
201
|
+
reject(new Error('cancelled'));
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
if (TT && ttId) {
|
|
205
|
+
TT.setCancelHandler(ttId, function () {
|
|
206
|
+
if (typeof options.onCancel === 'function') {
|
|
207
|
+
options.onCancel();
|
|
208
|
+
}
|
|
209
|
+
finishCancel();
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (signal) {
|
|
214
|
+
abortPoll = setInterval(() => {
|
|
215
|
+
if (signal.aborted) finishCancel();
|
|
216
|
+
}, 100);
|
|
217
|
+
}
|
|
218
|
+
|
|
182
219
|
function onMessage(ev) {
|
|
183
|
-
if (signal
|
|
184
|
-
|
|
185
|
-
if (TT && ttId) TT.failTransfer(ttId, 'Cancelled');
|
|
186
|
-
reject(new Error('cancelled'));
|
|
220
|
+
if (signal.aborted) {
|
|
221
|
+
finishCancel();
|
|
187
222
|
return;
|
|
188
223
|
}
|
|
189
224
|
if (typeof ev.data === 'string') {
|
|
@@ -194,6 +229,8 @@
|
|
|
194
229
|
return;
|
|
195
230
|
}
|
|
196
231
|
if (msg.type === 'error') {
|
|
232
|
+
if (settled) return;
|
|
233
|
+
settled = true;
|
|
197
234
|
cleanup();
|
|
198
235
|
if (TT && ttId) TT.failTransfer(ttId, msg.message);
|
|
199
236
|
reject(new Error(msg.message || 'download failed'));
|
|
@@ -205,6 +242,8 @@
|
|
|
205
242
|
return;
|
|
206
243
|
}
|
|
207
244
|
if (msg.type === 'download_end') {
|
|
245
|
+
if (settled) return;
|
|
246
|
+
settled = true;
|
|
208
247
|
cleanup();
|
|
209
248
|
if (TT && ttId) TT.completeTransfer(ttId);
|
|
210
249
|
const blob = new Blob(chunks, {
|
|
@@ -229,6 +268,8 @@
|
|
|
229
268
|
|
|
230
269
|
ws.addEventListener('message', onMessage);
|
|
231
270
|
ws.addEventListener('error', () => {
|
|
271
|
+
if (settled) return;
|
|
272
|
+
settled = true;
|
|
232
273
|
cleanup();
|
|
233
274
|
if (TT && ttId) TT.failTransfer(ttId, 'WebSocket error');
|
|
234
275
|
reject(new Error('WebSocket error'));
|
|
@@ -278,6 +278,12 @@
|
|
|
278
278
|
}, 8000);
|
|
279
279
|
}
|
|
280
280
|
|
|
281
|
+
function removeTransfer(id) {
|
|
282
|
+
if (_items.delete(id)) {
|
|
283
|
+
_render();
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
281
287
|
function completeByExternalId(externalId) {
|
|
282
288
|
var id = _findByExternalId(externalId);
|
|
283
289
|
if (id != null) completeTransfer(id);
|
|
@@ -305,6 +311,7 @@
|
|
|
305
311
|
setCancelHandler: setCancelHandler,
|
|
306
312
|
completeTransfer: completeTransfer,
|
|
307
313
|
failTransfer: failTransfer,
|
|
314
|
+
removeTransfer: removeTransfer,
|
|
308
315
|
completeByExternalId: completeByExternalId,
|
|
309
316
|
failByExternalId: failByExternalId,
|
|
310
317
|
updateProgressByExternalId: updateProgressByExternalId,
|
|
@@ -342,8 +342,6 @@
|
|
|
342
342
|
<input type="hidden" id="currentPath" value="{{ current_path or '' }}" />
|
|
343
343
|
<script src="/static/js/aird-core.js?v={{ static_version }}"></script>
|
|
344
344
|
<script src="/static/js/file-transfer-ws.js?v={{ static_version }}"></script>
|
|
345
|
-
<script src="/static/js/file-transfer-http.js?v={{ static_version }}"></script>
|
|
346
|
-
<script src="/static/js/file-transfer.js?v={{ static_version }}"></script>
|
|
347
345
|
<script src="/static/js/download-manager.js?v={{ static_version }}"></script>
|
|
348
346
|
<script src="/static/js/components/folder-picker.js?v={{ static_version }}"></script>
|
|
349
347
|
<script nonce="{{ csp_nonce }}">
|
|
@@ -102,9 +102,7 @@ aird/static/js/aird-core.js
|
|
|
102
102
|
aird/static/js/bg-canvas.js
|
|
103
103
|
aird/static/js/download-manager.js
|
|
104
104
|
aird/static/js/feature-flags-live.js
|
|
105
|
-
aird/static/js/file-transfer-http.js
|
|
106
105
|
aird/static/js/file-transfer-ws.js
|
|
107
|
-
aird/static/js/file-transfer.js
|
|
108
106
|
aird/static/js/folder-size-scan.js
|
|
109
107
|
aird/static/js/login-ui.js
|
|
110
108
|
aird/static/js/media-view.js
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* HTTP streaming upload (POST /upload). Works via Cloudflare HTTP/3 or direct to origin.
|
|
3
|
-
*/
|
|
4
|
-
(function (global) {
|
|
5
|
-
'use strict';
|
|
6
|
-
|
|
7
|
-
function getXSRFToken() {
|
|
8
|
-
if (global.AirdCore?.getXSRFToken) {
|
|
9
|
-
return global.AirdCore.getXSRFToken();
|
|
10
|
-
}
|
|
11
|
-
const match = document.cookie.match(/\b_xsrf=([^;]*)/);
|
|
12
|
-
return match ? decodeURIComponent(match[1]) : '';
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* @param {File|Blob} file
|
|
17
|
-
* @param {{ uploadDir?: string, filename?: string, onProgress?: Function, signal?: { aborted: boolean }, onCancel?: Function }} options
|
|
18
|
-
*/
|
|
19
|
-
function uploadFile(file, options) {
|
|
20
|
-
options = options || {};
|
|
21
|
-
const uploadDir = options.uploadDir ?? '';
|
|
22
|
-
const filename = options.filename ?? (file.name || 'upload');
|
|
23
|
-
const onProgress = options.onProgress || function () {};
|
|
24
|
-
const signal = options.signal;
|
|
25
|
-
const totalSize = file.size;
|
|
26
|
-
|
|
27
|
-
const TT = global.AirdTransferTracker;
|
|
28
|
-
const ttId = TT
|
|
29
|
-
? TT.addTransfer(filename, totalSize, 'upload', { onCancel: options.onCancel })
|
|
30
|
-
: null;
|
|
31
|
-
if (TT && ttId && options.onCancel) {
|
|
32
|
-
TT.setCancelHandler(ttId, options.onCancel);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
return new Promise((resolve, reject) => {
|
|
36
|
-
const xhr = new XMLHttpRequest();
|
|
37
|
-
let abortPoll = null;
|
|
38
|
-
|
|
39
|
-
function cleanup() {
|
|
40
|
-
if (abortPoll !== null) {
|
|
41
|
-
clearInterval(abortPoll);
|
|
42
|
-
abortPoll = null;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function fail(err, httpStatus) {
|
|
47
|
-
cleanup();
|
|
48
|
-
const msg = err?.message || String(err);
|
|
49
|
-
const error = err instanceof Error ? err : new Error(msg);
|
|
50
|
-
error.httpStatus = httpStatus ?? 0;
|
|
51
|
-
if (TT && ttId) TT.failTransfer(ttId, msg);
|
|
52
|
-
reject(error);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
xhr.upload.addEventListener('progress', (ev) => {
|
|
56
|
-
if (!ev.lengthComputable) return;
|
|
57
|
-
const loaded = ev.loaded;
|
|
58
|
-
const pct = totalSize > 0 ? Math.round((loaded / totalSize) * 100) : 0;
|
|
59
|
-
onProgress(pct, loaded, totalSize);
|
|
60
|
-
if (TT && ttId) TT.updateProgress(ttId, loaded, totalSize);
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
xhr.addEventListener('load', () => {
|
|
64
|
-
cleanup();
|
|
65
|
-
if (xhr.status >= 200 && xhr.status < 300) {
|
|
66
|
-
onProgress(100, totalSize, totalSize);
|
|
67
|
-
if (TT && ttId) TT.completeTransfer(ttId);
|
|
68
|
-
resolve({ message: xhr.responseText || 'Upload successful' });
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
const body = (xhr.responseText || '').trim();
|
|
72
|
-
fail(new Error(body || `Upload failed (HTTP ${xhr.status})`), xhr.status);
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
xhr.addEventListener('error', () => fail(new Error('Network error during upload'), 0));
|
|
76
|
-
xhr.addEventListener('abort', () => fail(new Error('cancelled'), 0));
|
|
77
|
-
|
|
78
|
-
if (signal) {
|
|
79
|
-
abortPoll = setInterval(() => {
|
|
80
|
-
if (signal.aborted) {
|
|
81
|
-
xhr.abort();
|
|
82
|
-
}
|
|
83
|
-
}, 100);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
xhr.open('POST', '/upload');
|
|
87
|
-
xhr.setRequestHeader('X-Upload-Dir', uploadDir);
|
|
88
|
-
xhr.setRequestHeader('X-Upload-Filename', filename);
|
|
89
|
-
xhr.setRequestHeader('X-XSRFToken', getXSRFToken());
|
|
90
|
-
xhr.setRequestHeader('Content-Type', 'application/octet-stream');
|
|
91
|
-
xhr.send(file);
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
global.AirdFileTransferHttp = {
|
|
96
|
-
uploadFile: uploadFile,
|
|
97
|
-
};
|
|
98
|
-
})(typeof globalThis !== 'undefined' ? globalThis : window);
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Upload facade: HTTP first (CF or direct origin), WebSocket fallback when needed.
|
|
3
|
-
*/
|
|
4
|
-
(function (global) {
|
|
5
|
-
'use strict';
|
|
6
|
-
|
|
7
|
-
function isCancelled(err) {
|
|
8
|
-
const msg = (err && err.message) ? String(err.message).toLowerCase() : '';
|
|
9
|
-
return msg === 'cancelled';
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
/** Use WS when HTTP is blocked, proxied limits apply, or the connection failed. */
|
|
13
|
-
function shouldFallbackToWs(err) {
|
|
14
|
-
if (!err || isCancelled(err)) return false;
|
|
15
|
-
const status = err.httpStatus ?? 0;
|
|
16
|
-
if (status === 401 || status === 403 || status === 400) return false;
|
|
17
|
-
if (status === 413 || status === 0 || status === 502 || status === 503 || status === 504) {
|
|
18
|
-
return true;
|
|
19
|
-
}
|
|
20
|
-
const msg = String(err.message || '').toLowerCase();
|
|
21
|
-
return msg.includes('network error');
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* @param {File|Blob} file
|
|
26
|
-
* @param {object} options passed to HTTP/WS upload helpers
|
|
27
|
-
*/
|
|
28
|
-
async function uploadFile(file, options) {
|
|
29
|
-
options = options || {};
|
|
30
|
-
const http = global.AirdFileTransferHttp;
|
|
31
|
-
const ws = global.AirdFileTransferWs;
|
|
32
|
-
|
|
33
|
-
if (http?.uploadFile) {
|
|
34
|
-
try {
|
|
35
|
-
return await http.uploadFile(file, options);
|
|
36
|
-
} catch (err) {
|
|
37
|
-
if (ws?.uploadFile && shouldFallbackToWs(err)) {
|
|
38
|
-
return ws.uploadFile(file, options);
|
|
39
|
-
}
|
|
40
|
-
throw err;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
if (ws?.uploadFile) {
|
|
45
|
-
return ws.uploadFile(file, options);
|
|
46
|
-
}
|
|
47
|
-
throw new Error('No upload transport available. Hard-refresh the page.');
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
global.AirdFileTransfer = {
|
|
51
|
-
uploadFile: uploadFile,
|
|
52
|
-
saveBlob: global.AirdFileTransferWs?.saveBlob,
|
|
53
|
-
downloadFile: global.AirdFileTransferWs?.downloadFile,
|
|
54
|
-
};
|
|
55
|
-
})(typeof globalThis !== 'undefined' ? globalThis : window);
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|