txhttputil 1.4.8__tar.gz → 1.4.9__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.
Files changed (49) hide show
  1. {txhttputil-1.4.8 → txhttputil-1.4.9}/LICENSE +2 -1
  2. txhttputil-1.4.9/PKG-INFO +82 -0
  3. {txhttputil-1.4.8 → txhttputil-1.4.9}/README.md +5 -1
  4. txhttputil-1.4.9/pyproject.toml +97 -0
  5. txhttputil-1.4.9/txhttputil/__init__.py +9 -0
  6. {txhttputil-1.4.8 → txhttputil-1.4.9}/txhttputil/downloader/HttpFileDownloader.py +8 -9
  7. {txhttputil-1.4.8 → txhttputil-1.4.9}/txhttputil/downloader/HttpResourceProxy.py +8 -0
  8. txhttputil-1.4.9/txhttputil/downloader/__init__.py +8 -0
  9. {txhttputil-1.4.8 → txhttputil-1.4.9}/txhttputil/login_page/LoginElement.py +8 -1
  10. txhttputil-1.4.9/txhttputil/login_page/__init__.py +8 -0
  11. {txhttputil-1.4.8 → txhttputil-1.4.9}/txhttputil/site/AuthCredentials.py +8 -0
  12. {txhttputil-1.4.8 → txhttputil-1.4.9}/txhttputil/site/AuthResource.py +8 -12
  13. {txhttputil-1.4.8 → txhttputil-1.4.9}/txhttputil/site/AuthSessionWrapper.py +9 -1
  14. {txhttputil-1.4.8 → txhttputil-1.4.9}/txhttputil/site/AuthUserDetails.py +8 -8
  15. {txhttputil-1.4.8 → txhttputil-1.4.9}/txhttputil/site/BasicResource.py +8 -0
  16. {txhttputil-1.4.8 → txhttputil-1.4.9}/txhttputil/site/BasicResourceTest.py +8 -0
  17. {txhttputil-1.4.8 → txhttputil-1.4.9}/txhttputil/site/FileUnderlayResource.py +53 -6
  18. {txhttputil-1.4.8 → txhttputil-1.4.9}/txhttputil/site/FileUnderlayResourceTest.py +24 -0
  19. {txhttputil-1.4.8 → txhttputil-1.4.9}/txhttputil/site/FileUploadRequest.py +9 -11
  20. {txhttputil-1.4.8 → txhttputil-1.4.9}/txhttputil/site/RedirectToHttpsResource.py +8 -0
  21. {txhttputil-1.4.8 → txhttputil-1.4.9}/txhttputil/site/RedirectionRule.py +9 -1
  22. txhttputil-1.4.9/txhttputil/site/ResourceCreator.py +12 -0
  23. {txhttputil-1.4.8 → txhttputil-1.4.9}/txhttputil/site/RootResource.py +7 -8
  24. txhttputil-1.4.9/txhttputil/site/RootSiteTest.py +8 -0
  25. {txhttputil-1.4.8 → txhttputil-1.4.9}/txhttputil/site/SiteUtil.py +8 -10
  26. {txhttputil-1.4.8 → txhttputil-1.4.9}/txhttputil/site/StaticFileResource.py +7 -8
  27. txhttputil-1.4.9/txhttputil/site/__init__.py +8 -0
  28. {txhttputil-1.4.8 → txhttputil-1.4.9}/txhttputil/util/DeferUtil.py +8 -9
  29. {txhttputil-1.4.8 → txhttputil-1.4.9}/txhttputil/util/ModuleUtil.py +7 -9
  30. {txhttputil-1.4.8 → txhttputil-1.4.9}/txhttputil/util/PemUtil.py +9 -2
  31. {txhttputil-1.4.8 → txhttputil-1.4.9}/txhttputil/util/SslUtil.py +8 -0
  32. txhttputil-1.4.9/txhttputil/util/__init__.py +8 -0
  33. txhttputil-1.4.9/txhttputil.egg-info/PKG-INFO +82 -0
  34. {txhttputil-1.4.8 → txhttputil-1.4.9}/txhttputil.egg-info/requires.txt +6 -0
  35. txhttputil-1.4.8/PKG-INFO +0 -47
  36. txhttputil-1.4.8/pyproject.toml +0 -40
  37. txhttputil-1.4.8/txhttputil/__init__.py +0 -3
  38. txhttputil-1.4.8/txhttputil/downloader/__init__.py +0 -0
  39. txhttputil-1.4.8/txhttputil/login_page/__init__.py +0 -0
  40. txhttputil-1.4.8/txhttputil/site/ResourceCreator.py +0 -4
  41. txhttputil-1.4.8/txhttputil/site/RootSiteTest.py +0 -0
  42. txhttputil-1.4.8/txhttputil/site/__init__.py +0 -1
  43. txhttputil-1.4.8/txhttputil/util/__init__.py +0 -0
  44. txhttputil-1.4.8/txhttputil.egg-info/PKG-INFO +0 -47
  45. {txhttputil-1.4.8 → txhttputil-1.4.9}/setup.cfg +0 -0
  46. {txhttputil-1.4.8 → txhttputil-1.4.9}/txhttputil/login_page/LoginTemplate.xml +0 -0
  47. {txhttputil-1.4.8 → txhttputil-1.4.9}/txhttputil.egg-info/SOURCES.txt +0 -0
  48. {txhttputil-1.4.8 → txhttputil-1.4.9}/txhttputil.egg-info/dependency_links.txt +0 -0
  49. {txhttputil-1.4.8 → txhttputil-1.4.9}/txhttputil.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2016
3
+ Copyright (c) 2016-2026 Flying Ion Pty Ltd
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -19,3 +19,4 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
19
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
20
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
21
  SOFTWARE.
22
+
@@ -0,0 +1,82 @@
1
+ Metadata-Version: 2.1
2
+ Name: txhttputil
3
+ Version: 1.4.9
4
+ Summary: Flying Ion utility classes for serving a static site with twisted.web with user permissions.
5
+ Author-email: Flying Ion Pty Ltd <contact@flyingion.com>
6
+ License: MIT License
7
+
8
+ Copyright (c) 2016-2026 Flying Ion Pty Ltd
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+
29
+ Project-URL: Homepage, https://flyingion.com
30
+ Project-URL: Repository, https://gitlab.com/flyingion/txhttputil
31
+ Project-URL: Issues, https://gitlab.com/flyingion/txhttputil/-/issues
32
+ Keywords: twisted,resource,file,download,flying-ion
33
+ Classifier: License :: OSI Approved :: MIT License
34
+ Classifier: Programming Language :: Python :: 3.9
35
+ Classifier: Programming Language :: Python :: 3.10
36
+ Classifier: Programming Language :: Python :: 3.11
37
+ Classifier: Programming Language :: Python :: 3.12
38
+ Requires-Python: >=3.9
39
+ Description-Content-Type: text/markdown
40
+ License-File: LICENSE
41
+ Requires-Dist: pytz
42
+ Requires-Dist: txwebsocket>=1.0.1
43
+ Requires-Dist: filetype
44
+ Requires-Dist: pem
45
+ Requires-Dist: pytmpdir
46
+ Requires-Dist: treelib>=1.6.4
47
+ Requires-Dist: cryptography
48
+ Requires-Dist: pyOpenSSL
49
+ Provides-Extra: dev
50
+ Requires-Dist: mypy>=1.0; extra == "dev"
51
+ Requires-Dist: ruff>=0.15; extra == "dev"
52
+ Requires-Dist: vulture>=2.14; extra == "dev"
53
+ Requires-Dist: basedpyright>=1.20; extra == "dev"
54
+
55
+ # TxHttpUtil
56
+ Flying Ion utility classes for serving a static site with twisted.web with user permissions.
57
+
58
+ Whats of interest?
59
+
60
+ * Protected resource with simple form login - Not suitable for public networks at this
61
+ stage
62
+ * A resource that underlays a multi level file system search under a standard twisted
63
+ Resource.putChild type resource tree.
64
+ * Twisted HTTP File Downloader
65
+ * Consistent request data, providing a Bytes IO like oboject and switching to a
66
+ NamedTemporaryFile if fileno, or name is called, or the data exceeds 5mb.
67
+ * Support for single page applications
68
+
69
+ # TODO
70
+
71
+ Unit tests for :
72
+ * Creating resource trees
73
+ * Getting resources from the resource tree
74
+ * Getting files from an underlay resource with two underlays
75
+ * Downloading files with the
76
+ * Logging into the test site (Using Seleneium/Chrome WebDriver)
77
+ * Test uploading data under 5mb and over 5mb to and auto switching to NamedTemporaryFile
78
+ from BytesIO
79
+
80
+ ## License
81
+
82
+ Copyright (c) 2016-2026 [Flying Ion Pty Ltd](https://flyingion.com). Released under the [MIT License](LICENSE).
@@ -1,5 +1,5 @@
1
1
  # TxHttpUtil
2
- Synerty utility classes for serving a static site with twisted.web with user permissions.
2
+ Flying Ion utility classes for serving a static site with twisted.web with user permissions.
3
3
 
4
4
  Whats of interest?
5
5
 
@@ -22,3 +22,7 @@ Unit tests for :
22
22
  * Logging into the test site (Using Seleneium/Chrome WebDriver)
23
23
  * Test uploading data under 5mb and over 5mb to and auto switching to NamedTemporaryFile
24
24
  from BytesIO
25
+
26
+ ## License
27
+
28
+ Copyright (c) 2016-2026 [Flying Ion Pty Ltd](https://flyingion.com). Released under the [MIT License](LICENSE).
@@ -0,0 +1,97 @@
1
+ [build-system]
2
+ requires = ["setuptools<70.0.0", "wheel"]
3
+ build-backend = "setuptools.build_meta:__legacy__"
4
+
5
+ [project]
6
+ name = "txhttputil"
7
+ version = "1.4.9"
8
+ description = "Flying Ion utility classes for serving a static site with twisted.web with user permissions."
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = {file = "LICENSE"}
12
+ keywords = ["twisted", "resource", "file", "download", "flying-ion"]
13
+ classifiers = [
14
+ "License :: OSI Approved :: MIT License",
15
+ "Programming Language :: Python :: 3.9",
16
+ "Programming Language :: Python :: 3.10",
17
+ "Programming Language :: Python :: 3.11",
18
+ "Programming Language :: Python :: 3.12",
19
+ ]
20
+ dependencies = [
21
+ "pytz",
22
+ "txwebsocket>=1.0.1",
23
+ "filetype",
24
+ "pem",
25
+ "pytmpdir",
26
+ "treelib>=1.6.4",
27
+ "cryptography",
28
+ "pyOpenSSL",
29
+ ]
30
+ authors = [
31
+ {name = "Flying Ion Pty Ltd", email = "contact@flyingion.com"}
32
+ ]
33
+
34
+ [project.urls]
35
+ Homepage = "https://flyingion.com"
36
+ Repository = "https://gitlab.com/flyingion/txhttputil"
37
+ Issues = "https://gitlab.com/flyingion/txhttputil/-/issues"
38
+
39
+ [project.optional-dependencies]
40
+ dev = [
41
+ "mypy>=1.0",
42
+ "ruff>=0.15",
43
+ "vulture>=2.14",
44
+ "basedpyright>=1.20",
45
+ ]
46
+
47
+ [tool.mypy]
48
+ python_version = "3.12"
49
+ explicit_package_bases = true
50
+ strict = false
51
+ warn_unused_ignores = true
52
+ warn_return_any = true
53
+ disallow_untyped_defs = false
54
+ ignore_missing_imports = true
55
+ follow_imports = "skip"
56
+
57
+ [tool.ruff]
58
+ line-length = 80
59
+ exclude = [
60
+ "build",
61
+ "txhttputil.egg-info",
62
+ ]
63
+
64
+ [tool.ruff.lint]
65
+ select = ["E", "W", "F", "B", "C4", "RET", "SIM102"]
66
+ ignore = ["E402", "E501", "SIM105", "C408"]
67
+
68
+ [tool.ruff.lint.per-file-ignores]
69
+ "txhttputil/site/RootResource.py" = ["F821"]
70
+ "txhttputil/site/SiteUtil.py" = ["B008"]
71
+ "txhttputil/site/FileUnderlayResourceTest.py" = ["RET504"]
72
+ "txhttputil/util/PemUtil.py" = ["RET503", "C405"]
73
+ "txhttputil/util/SslUtil.py" = ["C405"]
74
+
75
+ [tool.vulture]
76
+ paths = ["txhttputil"]
77
+ min_confidence = 80
78
+ exclude = [
79
+ "AuthCredentials.py",
80
+ "AuthUserDetails.py",
81
+ "PemUtil.py",
82
+ "SslUtil.py",
83
+ ]
84
+
85
+ [tool.basedpyright]
86
+ pythonVersion = "3.12"
87
+ typeCheckingMode = "basic"
88
+ reportMissingImports = true
89
+ reportMissingTypeStubs = false
90
+ exclude = ["**/*Test.py"]
91
+
92
+ [tool.setuptools.packages.find]
93
+ where = ["."]
94
+ include = ["txhttputil*"]
95
+
96
+ [tool.setuptools.package-data]
97
+ "txhttputil.login_page" = ["*.xml"]
@@ -0,0 +1,9 @@
1
+ # Copyright (c) 2016-2026 Flying Ion Pty Ltd
2
+ #
3
+ # This software is open source; the MIT license applies.
4
+ # See LICENSE for the full license text.
5
+ #
6
+ # Website : https://flyingion.com
7
+ # Support : contact@flyingion.com
8
+
9
+ __version__ = '1.4.9'
@@ -1,11 +1,10 @@
1
- """
2
- * Created by Synerty Pty Ltd
3
- *
4
- * This software is open source, the MIT license applies.
5
- *
6
- * Website : http://www.synerty.com
7
- * Support : support@synerty.com
8
- """
1
+ # Copyright (c) 2016-2026 Flying Ion Pty Ltd
2
+ #
3
+ # This software is open source; the MIT license applies.
4
+ # See LICENSE for the full license text.
5
+ #
6
+ # Website : https://flyingion.com
7
+ # Support : contact@flyingion.com
9
8
 
10
9
  import logging
11
10
  from typing import Union
@@ -35,7 +34,7 @@ class HttpFileDownloader:
35
34
  d = agent.request(
36
35
  b"GET",
37
36
  self._url,
38
- Headers({b"User-Agent": [b"Synerty File Downloader"]}),
37
+ Headers({b"User-Agent": [b"Flying Ion File Downloader"]}),
39
38
  None,
40
39
  )
41
40
 
@@ -1,3 +1,11 @@
1
+ # Copyright (c) 2016-2026 Flying Ion Pty Ltd
2
+ #
3
+ # This software is open source; the MIT license applies.
4
+ # See LICENSE for the full license text.
5
+ #
6
+ # Website : https://flyingion.com
7
+ # Support : contact@flyingion.com
8
+
1
9
  import logging
2
10
  from typing import Optional
3
11
  from urllib.parse import urlencode
@@ -0,0 +1,8 @@
1
+ # Copyright (c) 2016-2026 Flying Ion Pty Ltd
2
+ #
3
+ # This software is open source; the MIT license applies.
4
+ # See LICENSE for the full license text.
5
+ #
6
+ # Website : https://flyingion.com
7
+ # Support : contact@flyingion.com
8
+
@@ -1,3 +1,11 @@
1
+ # Copyright (c) 2016-2026 Flying Ion Pty Ltd
2
+ #
3
+ # This software is open source; the MIT license applies.
4
+ # See LICENSE for the full license text.
5
+ #
6
+ # Website : https://flyingion.com
7
+ # Support : contact@flyingion.com
8
+
1
9
  '''
2
10
  Created on 17/06/2013
3
11
 
@@ -9,7 +17,6 @@ from twisted.python.filepath import FilePath
9
17
  from twisted.web._element import renderer, Element
10
18
  from twisted.web.template import XMLFile
11
19
 
12
- import txhttputil
13
20
 
14
21
 
15
22
  class LoginElement(Element):
@@ -0,0 +1,8 @@
1
+ # Copyright (c) 2016-2026 Flying Ion Pty Ltd
2
+ #
3
+ # This software is open source; the MIT license applies.
4
+ # See LICENSE for the full license text.
5
+ #
6
+ # Website : https://flyingion.com
7
+ # Support : contact@flyingion.com
8
+
@@ -1,3 +1,11 @@
1
+ # Copyright (c) 2016-2026 Flying Ion Pty Ltd
2
+ #
3
+ # This software is open source; the MIT license applies.
4
+ # See LICENSE for the full license text.
5
+ #
6
+ # Website : https://flyingion.com
7
+ # Support : contact@flyingion.com
8
+
1
9
  from txhttputil.site.AuthUserDetails import UserDetails, everyoneGroup
2
10
  from txhttputil.util.DeferUtil import maybeDeferredWrap
3
11
 
@@ -1,15 +1,11 @@
1
- """
2
- * view.common.uiobj.Style.py
3
- *
4
- * Copyright Synerty Pty Ltd 2013
5
- *
6
- * This software is proprietary, you are not free to copy
7
- * or redistribute this code in any format.
8
- *
9
- * All rights to this software are reserved by
10
- * Synerty Pty Ltd
11
- *
12
- """
1
+ # Copyright (c) 2016-2026 Flying Ion Pty Ltd
2
+ #
3
+ # This software is open source; the MIT license applies.
4
+ # See LICENSE for the full license text.
5
+ #
6
+ # Website : https://flyingion.com
7
+ # Support : contact@flyingion.com
8
+
13
9
  from twisted.web._flatten import flattenString
14
10
  from twisted.web.resource import Resource
15
11
  from twisted.web.server import NOT_DONE_YET
@@ -1,3 +1,11 @@
1
+ # Copyright (c) 2016-2026 Flying Ion Pty Ltd
2
+ #
3
+ # This software is open source; the MIT license applies.
4
+ # See LICENSE for the full license text.
5
+ #
6
+ # Website : https://flyingion.com
7
+ # Support : contact@flyingion.com
8
+
1
9
  import logging
2
10
  from datetime import datetime
3
11
 
@@ -13,7 +21,7 @@ from .AuthResource import LoginResource, LoginSucceededResource
13
21
 
14
22
  logger = logging.getLogger(name=__name__)
15
23
 
16
- __author__ = "synerty"
24
+ __author__ = "Flying Ion Pty Ltd"
17
25
 
18
26
 
19
27
  @implementer(IResource)
@@ -1,11 +1,11 @@
1
- """
2
- * Created by Synerty Pty Ltd
3
- *
4
- * This software is open source, the MIT license applies.
5
- *
6
- * Website : http://www.synerty.com
7
- * Support : support@synerty.com
8
- """
1
+ # Copyright (c) 2016-2026 Flying Ion Pty Ltd
2
+ #
3
+ # This software is open source; the MIT license applies.
4
+ # See LICENSE for the full license text.
5
+ #
6
+ # Website : https://flyingion.com
7
+ # Support : contact@flyingion.com
8
+
9
9
  from twisted.python.components import registerAdapter
10
10
  from twisted.web.server import Session
11
11
  from zope.interface import Attribute
@@ -1,3 +1,11 @@
1
+ # Copyright (c) 2016-2026 Flying Ion Pty Ltd
2
+ #
3
+ # This software is open source; the MIT license applies.
4
+ # See LICENSE for the full license text.
5
+ #
6
+ # Website : https://flyingion.com
7
+ # Support : contact@flyingion.com
8
+
1
9
  import logging
2
10
 
3
11
  from twisted.python.compat import nativeString
@@ -1,3 +1,11 @@
1
+ # Copyright (c) 2016-2026 Flying Ion Pty Ltd
2
+ #
3
+ # This software is open source; the MIT license applies.
4
+ # See LICENSE for the full license text.
5
+ #
6
+ # Website : https://flyingion.com
7
+ # Support : contact@flyingion.com
8
+
1
9
  import logging
2
10
 
3
11
  from twisted.trial import unittest
@@ -1,6 +1,14 @@
1
+ # Copyright (c) 2016-2026 Flying Ion Pty Ltd
2
+ #
3
+ # This software is open source; the MIT license applies.
4
+ # See LICENSE for the full license text.
5
+ #
6
+ # Website : https://flyingion.com
7
+ # Support : contact@flyingion.com
8
+
1
9
  import logging
2
10
  import os
3
- from typing import Union
11
+ from typing import Optional, Union
4
12
 
5
13
  from twisted.web.resource import NoResource
6
14
  from twisted.web.util import Redirect
@@ -60,7 +68,7 @@ class FileUnderlayResource(BasicResource):
60
68
  self._singlePageAppConfig = None
61
69
  self._redirections = {}
62
70
 
63
- def addRedirectionRule(self, redirection: RedirectionRule = None):
71
+ def addRedirectionRule(self, redirection: Optional[RedirectionRule] = None):
64
72
  if redirection is not None:
65
73
  self._redirections[redirection.origin] = redirection.destination
66
74
 
@@ -73,7 +81,7 @@ class FileUnderlayResource(BasicResource):
73
81
  if filePath:
74
82
  return self._gzipIfRequired(StaticFileResource(filePath))
75
83
 
76
- if not resourcePath or not "." in os.path.basename(resourcePath):
84
+ if not resourcePath or "." not in os.path.basename(resourcePath):
77
85
  singlePageResource = self._getSinglePageAppResource()
78
86
  if singlePageResource:
79
87
  return singlePageResource
@@ -91,12 +99,45 @@ class FileUnderlayResource(BasicResource):
91
99
  indexHtmlPath=indexHtmlPath
92
100
  )
93
101
 
102
+ def _resolveFilePathUnderRoot(
103
+ self, rootDir: str, resourcePath: str
104
+ ) -> Union[str, None]:
105
+ if os.path.isabs(resourcePath):
106
+ logger.debug(
107
+ "Resource path %s is absolute and not allowed",
108
+ resourcePath,
109
+ )
110
+ return None
111
+
112
+ rootRealPath = os.path.realpath(rootDir)
113
+ candidatePath = os.path.realpath(os.path.join(rootDir, resourcePath))
114
+
115
+ try:
116
+ withinRoot = (
117
+ os.path.commonpath([rootRealPath, candidatePath])
118
+ == rootRealPath
119
+ )
120
+ except ValueError:
121
+ withinRoot = False
122
+
123
+ if not withinRoot:
124
+ logger.debug(
125
+ "Resource path %s escapes root %s",
126
+ resourcePath,
127
+ rootDir,
128
+ )
129
+ return None
130
+
131
+ return candidatePath
132
+
94
133
  def getRealFilePath(self, resourcePath: str) -> Union[str, None]:
95
134
  if not resourcePath:
96
135
  return None
97
136
 
98
137
  for rootDir in self._fileSystemRoots[::-1]:
99
- realFilePath = os.path.join(rootDir, resourcePath)
138
+ realFilePath = self._resolveFilePathUnderRoot(rootDir, resourcePath)
139
+ if realFilePath is None:
140
+ continue
100
141
 
101
142
  if os.path.isdir(realFilePath):
102
143
  logger.debug(
@@ -109,17 +150,23 @@ class FileUnderlayResource(BasicResource):
109
150
  if os.path.isfile(realFilePath):
110
151
  return realFilePath
111
152
 
153
+ return None
154
+
112
155
  def _getSinglePageAppResource(self):
113
156
  if not self._singlePageAppConfig:
114
157
  return None
115
158
 
116
159
  # Try to serve a single page app
117
- filePath = self.getRealFilePath(self._singlePageAppConfig.indexHtmlPath)
160
+ indexHtmlPath = self._singlePageAppConfig.indexHtmlPath
161
+ assert indexHtmlPath is not None, "indexHtmlPath must be set for SPA"
162
+ filePath = self.getRealFilePath(indexHtmlPath)
118
163
  if filePath:
119
164
  from txhttputil.site.StaticFileResource import StaticFileResource
120
165
 
121
166
  return self._gzipIfRequired(StaticFileResource(filePath))
122
167
 
168
+ return None
169
+
123
170
  def render_GET(self, request):
124
171
  """Render Get
125
172
 
@@ -130,7 +177,7 @@ class FileUnderlayResource(BasicResource):
130
177
 
131
178
  singlePageAppResource = self._getSinglePageAppResource()
132
179
  if singlePageAppResource:
133
- return singlePageAppResource.render_GET(request)
180
+ return singlePageAppResource.render_GET(request) # pyright: ignore[reportAttributeAccessIssue]
134
181
 
135
182
  # Else, render no resource
136
183
  return NoResource().render(request)
@@ -1,3 +1,11 @@
1
+ # Copyright (c) 2016-2026 Flying Ion Pty Ltd
2
+ #
3
+ # This software is open source; the MIT license applies.
4
+ # See LICENSE for the full license text.
5
+ #
6
+ # Website : https://flyingion.com
7
+ # Support : contact@flyingion.com
8
+
1
9
  import logging
2
10
  import os
3
11
 
@@ -73,6 +81,22 @@ class FileUnderlayResourceTest(unittest.TestCase):
73
81
  d.addCallback(self._checkDownloadedResource, fileName=realPath)
74
82
  return d
75
83
 
84
+ def testDirectoryTraversalBlocked(self):
85
+ traversalPath = "/".join([".."] * 10) + "/etc/passwd"
86
+ d = HttpFileDownloader(self.sitePath + "/" + traversalPath).run()
87
+
88
+ def assertNotSuccessful(_result):
89
+ self.fail("Directory traversal request must not succeed")
90
+
91
+ def assertNotFound(failure):
92
+ self.assertIn("404", str(failure.value))
93
+
94
+ d.addCallbacks(
95
+ callback=assertNotSuccessful,
96
+ errback=assertNotFound,
97
+ )
98
+ return d
99
+
76
100
 
77
101
  if __name__ == "__main__":
78
102
  from twisted.trial import runner, reporter
@@ -1,11 +1,10 @@
1
- """
2
- * Created by Synerty Pty Ltd
3
- *
4
- * This software is open source, the MIT license applies.
5
- *
6
- * Website : http://www.synerty.com
7
- * Support : support@synerty.com
8
- """
1
+ # Copyright (c) 2016-2026 Flying Ion Pty Ltd
2
+ #
3
+ # This software is open source; the MIT license applies.
4
+ # See LICENSE for the full license text.
5
+ #
6
+ # Website : https://flyingion.com
7
+ # Support : contact@flyingion.com
9
8
 
10
9
  import logging
11
10
  import os
@@ -120,9 +119,8 @@ class FileUploadRequest(server.Request):
120
119
  self.channel._respondToBadRequestAndDisconnect()
121
120
  if isinstance(e, (TypeError, ValueError, KeyError)):
122
121
  return
123
- else:
124
- # If it's not a userspace error from CGI, reraise
125
- raise
122
+ # If it's not a userspace error from CGI, reraise
123
+ raise
126
124
 
127
125
  self.content.seek(0, 0)
128
126
 
@@ -1,3 +1,11 @@
1
+ # Copyright (c) 2016-2026 Flying Ion Pty Ltd
2
+ #
3
+ # This software is open source; the MIT license applies.
4
+ # See LICENSE for the full license text.
5
+ #
6
+ # Website : https://flyingion.com
7
+ # Support : contact@flyingion.com
8
+
1
9
  from twisted.web import resource
2
10
  from twisted.web.server import NOT_DONE_YET
3
11
 
@@ -1,3 +1,11 @@
1
+ # Copyright (c) 2016-2026 Flying Ion Pty Ltd
2
+ #
3
+ # This software is open source; the MIT license applies.
4
+ # See LICENSE for the full license text.
5
+ #
6
+ # Website : https://flyingion.com
7
+ # Support : contact@flyingion.com
8
+
1
9
  class RedirectionRule:
2
10
  def __init__(self, origin: str = "", destination: str = ""):
3
11
  """A definition of Resource redirection rule
@@ -13,4 +21,4 @@ class RedirectionRule:
13
21
 
14
22
  @property
15
23
  def destination(self) -> bytes:
16
- return self._destination.encode()
24
+ return self._destination.encode()
@@ -0,0 +1,12 @@
1
+ # Copyright (c) 2016-2026 Flying Ion Pty Ltd
2
+ #
3
+ # This software is open source; the MIT license applies.
4
+ # See LICENSE for the full license text.
5
+ #
6
+ # Website : https://flyingion.com
7
+ # Support : contact@flyingion.com
8
+
9
+ import logging
10
+
11
+ logger = logging.getLogger(__name__)
12
+
@@ -1,11 +1,10 @@
1
- """
2
- * Created by Synerty Pty Ltd
3
- *
4
- * This software is open source, the MIT license applies.
5
- *
6
- * Website : http://www.synerty.com
7
- * Support : support@synerty.com
8
- """
1
+ # Copyright (c) 2016-2026 Flying Ion Pty Ltd
2
+ #
3
+ # This software is open source; the MIT license applies.
4
+ # See LICENSE for the full license text.
5
+ #
6
+ # Website : https://flyingion.com
7
+ # Support : contact@flyingion.com
9
8
 
10
9
  from txhttputil.site.AuthUserDetails import AuthUserDetails
11
10
  from txhttputil.site.ResourceUtil import RESOURCES
@@ -0,0 +1,8 @@
1
+ # Copyright (c) 2016-2026 Flying Ion Pty Ltd
2
+ #
3
+ # This software is open source; the MIT license applies.
4
+ # See LICENSE for the full license text.
5
+ #
6
+ # Website : https://flyingion.com
7
+ # Support : contact@flyingion.com
8
+
@@ -1,11 +1,10 @@
1
- """
2
- * Created by Synerty Pty Ltd
3
- *
4
- * This software is open source, the MIT license applies.
5
- *
6
- * Website : http://www.synerty.com
7
- * Support : support@synerty.com
8
- """
1
+ # Copyright (c) 2016-2026 Flying Ion Pty Ltd
2
+ #
3
+ # This software is open source; the MIT license applies.
4
+ # See LICENSE for the full license text.
5
+ #
6
+ # Website : https://flyingion.com
7
+ # Support : contact@flyingion.com
9
8
 
10
9
  import logging
11
10
  import platform
@@ -23,7 +22,6 @@ from txhttputil.site.AuthSessionWrapper import FormBasedAuthSessionWrapper
23
22
  from txhttputil.site.FileUploadRequest import FileUploadRequest
24
23
  from txhttputil.site.RedirectToHttpsResource import RedirectToHttpsResource
25
24
  from txhttputil.util.PemUtil import (
26
- PEM_CHECK_TYPE,
27
25
  parseTrustRootFromBundle,
28
26
  parsePemBundleForServer,
29
27
  parsePemBundleForTrustedPeers,
@@ -140,7 +138,7 @@ def setupSite(
140
138
  proto = "http"
141
139
  sitePort = reactor.listenTCP(portNum, site)
142
140
 
143
- if platform.system() is "Linux":
141
+ if platform.system() == "Linux":
144
142
  import subprocess
145
143
 
146
144
  ip = (
@@ -1,11 +1,10 @@
1
- """
2
- * Created by Synerty Pty Ltd
3
- *
4
- * This software is open source, the MIT license applies.
5
- *
6
- * Website : http://www.synerty.com
7
- * Support : support@synerty.com
8
- """
1
+ # Copyright (c) 2016-2026 Flying Ion Pty Ltd
2
+ #
3
+ # This software is open source; the MIT license applies.
4
+ # See LICENSE for the full license text.
5
+ #
6
+ # Website : https://flyingion.com
7
+ # Support : contact@flyingion.com
9
8
 
10
9
  import logging
11
10
  import mimetypes
@@ -0,0 +1,8 @@
1
+ # Copyright (c) 2016-2026 Flying Ion Pty Ltd
2
+ #
3
+ # This software is open source; the MIT license applies.
4
+ # See LICENSE for the full license text.
5
+ #
6
+ # Website : https://flyingion.com
7
+ # Support : contact@flyingion.com
8
+
@@ -1,11 +1,10 @@
1
- """
2
- * Created by Synerty Pty Ltd
3
- *
4
- * This software is open source, the MIT license applies.
5
- *
6
- * Website : http://www.synerty.com
7
- * Support : support@synerty.com
8
- """
1
+ # Copyright (c) 2016-2026 Flying Ion Pty Ltd
2
+ #
3
+ # This software is open source; the MIT license applies.
4
+ # See LICENSE for the full license text.
5
+ #
6
+ # Website : https://flyingion.com
7
+ # Support : contact@flyingion.com
9
8
 
10
9
  import logging
11
10
 
@@ -14,7 +13,7 @@ from twisted.internet.threads import deferToThread
14
13
 
15
14
  logger = logging.getLogger()
16
15
 
17
- __author__ = 'synerty'
16
+ __author__ = 'Flying Ion Pty Ltd'
18
17
 
19
18
 
20
19
  def vortexLogFailure(failure, loggerArg, consumeError=False, successValue=True):
@@ -1,12 +1,10 @@
1
- """
2
- * Created by Synerty Pty Ltd
3
- *
4
- * This software is open source, the MIT license applies.
5
- *
6
- * Website : http://www.synerty.com
7
- * Support : support@synerty.com
8
- """
9
-
1
+ # Copyright (c) 2016-2026 Flying Ion Pty Ltd
2
+ #
3
+ # This software is open source; the MIT license applies.
4
+ # See LICENSE for the full license text.
5
+ #
6
+ # Website : https://flyingion.com
7
+ # Support : contact@flyingion.com
10
8
 
11
9
  def filterModules(name_:str, file_: str) -> [str]:
12
10
  import os.path
@@ -1,3 +1,11 @@
1
+ # Copyright (c) 2016-2026 Flying Ion Pty Ltd
2
+ #
3
+ # This software is open source; the MIT license applies.
4
+ # See LICENSE for the full license text.
5
+ #
6
+ # Website : https://flyingion.com
7
+ # Support : contact@flyingion.com
8
+
1
9
  import logging
2
10
  import textwrap
3
11
  from collections import namedtuple
@@ -5,7 +13,7 @@ from datetime import datetime
5
13
  from functools import partial
6
14
  from itertools import chain
7
15
  from pathlib import Path
8
- from typing import List, Dict, NamedTuple, Union, Tuple, Literal
16
+ from typing import List, Dict, Literal
9
17
 
10
18
  import pem
11
19
  from OpenSSL.crypto import (
@@ -31,7 +39,6 @@ from cryptography.x509 import (
31
39
  BasicConstraints,
32
40
  ExtensionNotFound,
33
41
  Extension,
34
- KeyUsage,
35
42
  ExtendedKeyUsage,
36
43
  )
37
44
  from pem import AbstractPEMObject
@@ -1,3 +1,11 @@
1
+ # Copyright (c) 2016-2026 Flying Ion Pty Ltd
2
+ #
3
+ # This software is open source; the MIT license applies.
4
+ # See LICENSE for the full license text.
5
+ #
6
+ # Website : https://flyingion.com
7
+ # Support : contact@flyingion.com
8
+
1
9
  import logging
2
10
  from binascii import hexlify
3
11
  from typing import List, Set, Optional
@@ -0,0 +1,8 @@
1
+ # Copyright (c) 2016-2026 Flying Ion Pty Ltd
2
+ #
3
+ # This software is open source; the MIT license applies.
4
+ # See LICENSE for the full license text.
5
+ #
6
+ # Website : https://flyingion.com
7
+ # Support : contact@flyingion.com
8
+
@@ -0,0 +1,82 @@
1
+ Metadata-Version: 2.1
2
+ Name: txhttputil
3
+ Version: 1.4.9
4
+ Summary: Flying Ion utility classes for serving a static site with twisted.web with user permissions.
5
+ Author-email: Flying Ion Pty Ltd <contact@flyingion.com>
6
+ License: MIT License
7
+
8
+ Copyright (c) 2016-2026 Flying Ion Pty Ltd
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+
29
+ Project-URL: Homepage, https://flyingion.com
30
+ Project-URL: Repository, https://gitlab.com/flyingion/txhttputil
31
+ Project-URL: Issues, https://gitlab.com/flyingion/txhttputil/-/issues
32
+ Keywords: twisted,resource,file,download,flying-ion
33
+ Classifier: License :: OSI Approved :: MIT License
34
+ Classifier: Programming Language :: Python :: 3.9
35
+ Classifier: Programming Language :: Python :: 3.10
36
+ Classifier: Programming Language :: Python :: 3.11
37
+ Classifier: Programming Language :: Python :: 3.12
38
+ Requires-Python: >=3.9
39
+ Description-Content-Type: text/markdown
40
+ License-File: LICENSE
41
+ Requires-Dist: pytz
42
+ Requires-Dist: txwebsocket>=1.0.1
43
+ Requires-Dist: filetype
44
+ Requires-Dist: pem
45
+ Requires-Dist: pytmpdir
46
+ Requires-Dist: treelib>=1.6.4
47
+ Requires-Dist: cryptography
48
+ Requires-Dist: pyOpenSSL
49
+ Provides-Extra: dev
50
+ Requires-Dist: mypy>=1.0; extra == "dev"
51
+ Requires-Dist: ruff>=0.15; extra == "dev"
52
+ Requires-Dist: vulture>=2.14; extra == "dev"
53
+ Requires-Dist: basedpyright>=1.20; extra == "dev"
54
+
55
+ # TxHttpUtil
56
+ Flying Ion utility classes for serving a static site with twisted.web with user permissions.
57
+
58
+ Whats of interest?
59
+
60
+ * Protected resource with simple form login - Not suitable for public networks at this
61
+ stage
62
+ * A resource that underlays a multi level file system search under a standard twisted
63
+ Resource.putChild type resource tree.
64
+ * Twisted HTTP File Downloader
65
+ * Consistent request data, providing a Bytes IO like oboject and switching to a
66
+ NamedTemporaryFile if fileno, or name is called, or the data exceeds 5mb.
67
+ * Support for single page applications
68
+
69
+ # TODO
70
+
71
+ Unit tests for :
72
+ * Creating resource trees
73
+ * Getting resources from the resource tree
74
+ * Getting files from an underlay resource with two underlays
75
+ * Downloading files with the
76
+ * Logging into the test site (Using Seleneium/Chrome WebDriver)
77
+ * Test uploading data under 5mb and over 5mb to and auto switching to NamedTemporaryFile
78
+ from BytesIO
79
+
80
+ ## License
81
+
82
+ Copyright (c) 2016-2026 [Flying Ion Pty Ltd](https://flyingion.com). Released under the [MIT License](LICENSE).
@@ -6,3 +6,9 @@ pytmpdir
6
6
  treelib>=1.6.4
7
7
  cryptography
8
8
  pyOpenSSL
9
+
10
+ [dev]
11
+ mypy>=1.0
12
+ ruff>=0.15
13
+ vulture>=2.14
14
+ basedpyright>=1.20
txhttputil-1.4.8/PKG-INFO DELETED
@@ -1,47 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: txhttputil
3
- Version: 1.4.8
4
- Summary: Synerty utility classes for serving a static site with twisted.web with user permissions.
5
- Author-email: Synerty <contact@synerty.com>
6
- Project-URL: Homepage, https://gitlab.synerty.com/peek/util/txhttputil
7
- Keywords: twisted,resource,file,download,synerty
8
- Classifier: Programming Language :: Python :: 3.9
9
- Classifier: Programming Language :: Python :: 3.10
10
- Classifier: Programming Language :: Python :: 3.11
11
- Classifier: Programming Language :: Python :: 3.12
12
- Requires-Python: >=3.9
13
- Description-Content-Type: text/markdown
14
- License-File: LICENSE
15
- Requires-Dist: pytz
16
- Requires-Dist: txwebsocket>=1.0.1
17
- Requires-Dist: filetype
18
- Requires-Dist: pem
19
- Requires-Dist: pytmpdir
20
- Requires-Dist: treelib>=1.6.4
21
- Requires-Dist: cryptography
22
- Requires-Dist: pyOpenSSL
23
-
24
- # TxHttpUtil
25
- Synerty utility classes for serving a static site with twisted.web with user permissions.
26
-
27
- Whats of interest?
28
-
29
- * Protected resource with simple form login - Not suitable for public networks at this
30
- stage
31
- * A resource that underlays a multi level file system search under a standard twisted
32
- Resource.putChild type resource tree.
33
- * Twisted HTTP File Downloader
34
- * Consistent request data, providing a Bytes IO like oboject and switching to a
35
- NamedTemporaryFile if fileno, or name is called, or the data exceeds 5mb.
36
- * Support for single page applications
37
-
38
- # TODO
39
-
40
- Unit tests for :
41
- * Creating resource trees
42
- * Getting resources from the resource tree
43
- * Getting files from an underlay resource with two underlays
44
- * Downloading files with the
45
- * Logging into the test site (Using Seleneium/Chrome WebDriver)
46
- * Test uploading data under 5mb and over 5mb to and auto switching to NamedTemporaryFile
47
- from BytesIO
@@ -1,40 +0,0 @@
1
- [build-system]
2
- requires = ["setuptools<70.0.0", "wheel"]
3
- build-backend = "setuptools.build_meta:__legacy__"
4
-
5
- [project]
6
- name = "txhttputil"
7
- version = "1.4.8"
8
- description = "Synerty utility classes for serving a static site with twisted.web with user permissions."
9
- readme = "README.md"
10
- requires-python = ">=3.9"
11
- keywords = ["twisted", "resource", "file", "download", "synerty"]
12
- classifiers = [
13
- "Programming Language :: Python :: 3.9",
14
- "Programming Language :: Python :: 3.10",
15
- "Programming Language :: Python :: 3.11",
16
- "Programming Language :: Python :: 3.12"
17
- ]
18
- dependencies = [
19
- "pytz",
20
- "txwebsocket>=1.0.1",
21
- "filetype",
22
- "pem",
23
- "pytmpdir",
24
- "treelib>=1.6.4",
25
- "cryptography",
26
- "pyOpenSSL",
27
- ]
28
- authors = [
29
- {name = "Synerty", email = "contact@synerty.com"}
30
- ]
31
-
32
- [project.urls]
33
- Homepage = "https://gitlab.synerty.com/peek/util/txhttputil"
34
-
35
- [tool.setuptools.packages.find]
36
- where = ["."]
37
- include = ["txhttputil*"]
38
-
39
- [tool.setuptools.package-data]
40
- "txhttputil.login_page" = ["*.xml"]
@@ -1,3 +0,0 @@
1
-
2
-
3
- __version__ = '1.4.8'
File without changes
File without changes
@@ -1,4 +0,0 @@
1
- import logging
2
-
3
- logger = logging.getLogger(__name__)
4
-
File without changes
@@ -1 +0,0 @@
1
-
File without changes
@@ -1,47 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: txhttputil
3
- Version: 1.4.8
4
- Summary: Synerty utility classes for serving a static site with twisted.web with user permissions.
5
- Author-email: Synerty <contact@synerty.com>
6
- Project-URL: Homepage, https://gitlab.synerty.com/peek/util/txhttputil
7
- Keywords: twisted,resource,file,download,synerty
8
- Classifier: Programming Language :: Python :: 3.9
9
- Classifier: Programming Language :: Python :: 3.10
10
- Classifier: Programming Language :: Python :: 3.11
11
- Classifier: Programming Language :: Python :: 3.12
12
- Requires-Python: >=3.9
13
- Description-Content-Type: text/markdown
14
- License-File: LICENSE
15
- Requires-Dist: pytz
16
- Requires-Dist: txwebsocket>=1.0.1
17
- Requires-Dist: filetype
18
- Requires-Dist: pem
19
- Requires-Dist: pytmpdir
20
- Requires-Dist: treelib>=1.6.4
21
- Requires-Dist: cryptography
22
- Requires-Dist: pyOpenSSL
23
-
24
- # TxHttpUtil
25
- Synerty utility classes for serving a static site with twisted.web with user permissions.
26
-
27
- Whats of interest?
28
-
29
- * Protected resource with simple form login - Not suitable for public networks at this
30
- stage
31
- * A resource that underlays a multi level file system search under a standard twisted
32
- Resource.putChild type resource tree.
33
- * Twisted HTTP File Downloader
34
- * Consistent request data, providing a Bytes IO like oboject and switching to a
35
- NamedTemporaryFile if fileno, or name is called, or the data exceeds 5mb.
36
- * Support for single page applications
37
-
38
- # TODO
39
-
40
- Unit tests for :
41
- * Creating resource trees
42
- * Getting resources from the resource tree
43
- * Getting files from an underlay resource with two underlays
44
- * Downloading files with the
45
- * Logging into the test site (Using Seleneium/Chrome WebDriver)
46
- * Test uploading data under 5mb and over 5mb to and auto switching to NamedTemporaryFile
47
- from BytesIO
File without changes