modulitiz-micro 2.45.1__py311-none-any.whl → 2.46.0__py311-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.
Files changed (64) hide show
  1. modulitiz_micro/ModuloSeriale.py +70 -70
  2. modulitiz_micro/ModuloTarghe.py +47 -47
  3. modulitiz_micro/database/AbstractDatabaseService.py +13 -13
  4. modulitiz_micro/database/AbstractSql.py +69 -69
  5. modulitiz_micro/database/ModuloSqlOracle.py +19 -19
  6. modulitiz_micro/database/ModuloSqlServer.py +43 -43
  7. modulitiz_micro/database/eccezioni/EccezioneDbNoData.py +6 -6
  8. modulitiz_micro/database/mysql/AbstractBasicMysql.py +114 -114
  9. modulitiz_micro/database/mysql/ModuloMysql.py +163 -163
  10. modulitiz_micro/database/mysql/MysqlCommonConverter.py +47 -47
  11. modulitiz_micro/database/mysql/eccezioni/EccezioneMysqlOffline.py +6 -6
  12. modulitiz_micro/database/sqlite/AbstractBasicSQLite.py +114 -114
  13. modulitiz_micro/database/sqlite/ModuloSQLite.py +82 -82
  14. modulitiz_micro/eccezioni/EccezioneCtrlC.py +7 -7
  15. modulitiz_micro/eccezioni/EccezioneScheduler.py +7 -7
  16. modulitiz_micro/eccezioni/http/EccezioneHttp.py +8 -8
  17. modulitiz_micro/eccezioni/http/EccezioneHttp404.py +7 -7
  18. modulitiz_micro/eccezioni/http/EccezioneHttpGeneric.py +7 -7
  19. modulitiz_micro/files/cache/DatabaseCache.py +91 -91
  20. modulitiz_micro/files/cache/decorators/cacheRam.py +26 -26
  21. modulitiz_micro/files/git/ModuloGit.py +28 -28
  22. modulitiz_micro/files/git/decorators/catchAndRaiseGitExceptions.py +19 -19
  23. modulitiz_micro/files/git/exceptions/EccezioneGit.py +7 -7
  24. modulitiz_micro/gestionedom/GestioneDom.py +44 -44
  25. modulitiz_micro/iot/ModuleIotDevice.py +62 -62
  26. modulitiz_micro/keylogger/EccezioneKeyLogger.py +7 -7
  27. modulitiz_micro/keylogger/ModuloKeylogger.py +73 -73
  28. modulitiz_micro/rete/ModuleAndroidTVRemote.py +107 -0
  29. modulitiz_micro/rete/ModuloNetworking.py +67 -72
  30. modulitiz_micro/rete/ModuloOpenVpn.py +15 -15
  31. modulitiz_micro/rete/email/EmailBean.py +5 -5
  32. modulitiz_micro/rete/email/ModuloEmail.py +90 -90
  33. modulitiz_micro/rete/http/ModuloHttp.py +119 -119
  34. modulitiz_micro/rete/http/ModuloHttpConnectionSafe.py +91 -91
  35. modulitiz_micro/rete/http/ModuloHttpUtils.py +69 -69
  36. modulitiz_micro/rete/http/beans/HttpResponseBean.py +5 -5
  37. modulitiz_micro/rete/http/decorators/catchAndRaiseHttpExceptions.py +22 -22
  38. modulitiz_micro/rete/http/huawei/fusionsolar/ModuleHuaweiFusionSolar.py +84 -84
  39. modulitiz_micro/rete/http/huawei/fusionsolar/beans/TokenBean.py +28 -28
  40. modulitiz_micro/rete/http/huawei/fusionsolar/beans/device/DeviceBean.py +6 -6
  41. modulitiz_micro/rete/http/huawei/fusionsolar/beans/device/DeviceDataBattery.py +22 -22
  42. modulitiz_micro/rete/http/huawei/fusionsolar/beans/device/DeviceDataPowerSensor.py +49 -49
  43. modulitiz_micro/rete/http/huawei/fusionsolar/enums/DevTypeIdEnum.py +21 -21
  44. modulitiz_micro/rete/http/huawei/fusionsolar/exceptions/ExceptionTooManyLogins.py +7 -7
  45. modulitiz_micro/rete/http/huawei/fusionsolar/service/AbstractHuaweiFusionSolar.py +72 -72
  46. modulitiz_micro/rete/ntp/AbstractModuloNtp.py +73 -73
  47. modulitiz_micro/rete/ntp/ModuloNtpIt.py +8 -8
  48. modulitiz_micro/rete/socketserver/AbstractBasicGetSocketServer.py +35 -35
  49. modulitiz_micro/rete/socketserver/AbstractSocketServer.py +267 -267
  50. modulitiz_micro/rete/ssl/ModuloSsl.py +56 -56
  51. modulitiz_micro/sistema/ModuloEnvVars.py +34 -34
  52. modulitiz_micro/sistema/ModuloSystemPipe.py +67 -67
  53. modulitiz_micro/social/telegram/AbstractModuloTelegram.py +53 -53
  54. modulitiz_micro/social/telegram/ModuloTelegramSimple.py +26 -26
  55. modulitiz_micro/util/beans/globalvar/AbstractBasicGlobalVarBean.py +15 -15
  56. modulitiz_micro/util/scheduler/ModuleScheduler.py +26 -26
  57. modulitiz_micro/weather/AbstractModuleWeather.py +31 -31
  58. modulitiz_micro/weather/ModuleWeather.py +62 -62
  59. {modulitiz_micro-2.45.1.dist-info → modulitiz_micro-2.46.0.dist-info}/METADATA +59 -59
  60. modulitiz_micro-2.46.0.dist-info/RECORD +67 -0
  61. {modulitiz_micro-2.45.1.dist-info → modulitiz_micro-2.46.0.dist-info}/licenses/LICENSE +21 -21
  62. modulitiz_micro-2.45.1.dist-info/RECORD +0 -66
  63. {modulitiz_micro-2.45.1.dist-info → modulitiz_micro-2.46.0.dist-info}/WHEEL +0 -0
  64. {modulitiz_micro-2.45.1.dist-info → modulitiz_micro-2.46.0.dist-info}/top_level.txt +0 -0
@@ -1,267 +1,267 @@
1
- import errno
2
- import os
3
- import socket
4
- import ssl
5
- import time
6
- from _io import BufferedReader
7
- from abc import ABC
8
- from abc import abstractmethod
9
-
10
- from modulitiz_nano.ModuloListe import ModuloListe
11
- from modulitiz_nano.ModuloStringhe import ModuloStringhe
12
- from modulitiz_nano.eccezioni.EccezioneRuntime import EccezioneRuntime
13
- from modulitiz_nano.files.ModuloFiles import ModuloFiles
14
- from modulitiz_nano.files.ModuloLogging import ModuloLogging
15
- from modulitiz_nano.multithread.ModuloThread import ModuloThread
16
- from modulitiz_micro.rete.ModuloNetworking import ModuloNetworking
17
- from modulitiz_micro.rete.http.ModuloHttp import ModuloHttp
18
- from modulitiz_micro.rete.http.ModuloHttpUtils import ModuloHttpUtils
19
- from modulitiz_micro.rete.ssl.ModuloSsl import ModuloSsl
20
-
21
-
22
- class AbstractSocketServer(ABC):
23
- HTTP_CODES={
24
- ModuloHttp.STATUS_OK:"OK",
25
- 404:"Not Found",
26
- 500:"Internal Server Error",
27
- 501:"Not Implemented",
28
- }
29
-
30
- MAX_CONNECTIONS=10
31
- TIMEOUT_SERVER=30
32
- TIMEOUT_CLIENT=60
33
-
34
- TIPO_RESPONSE__PLAIN_TEXT=1
35
- TIPO_RESPONSE__STREAM=2
36
-
37
- def __init__(self,logger:ModuloLogging,porta:int,percorsoFileCertSsl:str):
38
- self._logger=logger
39
- self.__porta=porta
40
- self.__percorsoFileCertSsl=percorsoFileCertSsl
41
-
42
- self.isRequestedExit=False
43
- self.countActiveConnections=0
44
- self.contextSsl=None
45
- self.serverSocket=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
46
-
47
- def populate(self):
48
- # controllo che la porta non sia gia' occupata
49
- if self.isOpen():
50
- raise EccezioneRuntime(f"La porta {self.__porta} e' gia' aperta")
51
- # ssl
52
- if self.__percorsoFileCertSsl is not None:
53
- # se il certificato non esiste lo creo
54
- if ModuloFiles.getFileSize(self.__percorsoFileCertSsl)==-1:
55
- self._logger.info("Generazione certificato...")
56
- moduloSsl=ModuloSsl()
57
- moduloSsl.createSelfSignedCertAnonymous()
58
- with ModuloFiles.open(self.__percorsoFileCertSsl,"w+t") as fp:
59
- fp.write(moduloSsl.certStr)
60
- contextSsl=ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
61
- contextSsl.load_cert_chain(certfile=self.__percorsoFileCertSsl)
62
- self.contextSsl=contextSsl
63
- # creo la socket
64
- self.serverSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
65
- self.serverSocket.bind(('0.0.0.0', self.__porta))
66
- self.serverSocket.listen(self.MAX_CONNECTIONS)
67
- self.serverSocket.settimeout(self.TIMEOUT_SERVER)
68
-
69
- @abstractmethod
70
- def callbackError(self,ex: Exception):
71
- """
72
- Cosa fare in caso di errore della socket
73
- """
74
-
75
- @abstractmethod
76
- def handleRequest(self,method:str,url:str,path:str,params:dict,httpType:str,clientIp:str,clientPort:int)->tuple:
77
- """
78
- Cosa fare se un client contatta il server.
79
- Deve ritornare una tupla: (httpCode,header,body)
80
- """
81
-
82
- def isOpen(self)->bool:
83
- return ModuloNetworking.isHttpPortOpen(None, self.__porta)
84
-
85
- def avvia(self):
86
- protocolSuffix="S" if self.contextSsl is not None else ""
87
- self._logger.info("Server in ascolto sulla porta HTTP%s %d",protocolSuffix,self.__porta)
88
- ModuloThread.startDaemonWithCallbackError(self.callbackError,self.__avviaLoopNoThreaded,())
89
-
90
- def chiudi(self):
91
- if not self.isOpen():
92
- return
93
- self.isRequestedExit=True
94
- while self.countActiveConnections>0:
95
- time.sleep(0.5)
96
- # qui socket.shutdown() non ci vuole perche' deve essere usato solo lato client
97
- self.serverSocket.close()
98
-
99
- def __avviaLoopNoThreaded(self):
100
- while not self.isRequestedExit:
101
- self.__avviaNoThreaded()
102
- self.countActiveConnections=0
103
- def __avviaNoThreaded(self):
104
- # aspetto una richiesta
105
- try:
106
- clientConnection,(clientIp,clientPort)=self.serverSocket.accept()
107
- except TimeoutError:
108
- clientConnection=None
109
- clientIp=None
110
- clientPort=None
111
- except OSError as osError:
112
- if osError.errno not in(errno.ENOTSOCK,errno.EBADF):
113
- self.callbackError(osError)
114
- clientConnection=None
115
- clientIp=None
116
- clientPort=None
117
- if clientConnection is None:
118
- return
119
- self.countActiveConnections+=1
120
- # richiedo i dati
121
- request=None
122
- try:
123
- clientConnection.settimeout(self.TIMEOUT_CLIENT)
124
- if self.contextSsl is not None:
125
- clientConnection=self.contextSsl.wrap_socket(clientConnection,server_side=True)
126
- request=clientConnection.recv(1024)
127
- except (ssl.SSLEOFError,ssl.SSLZeroReturnError,TimeoutError):
128
- self.countActiveConnections-=1
129
- except ssl.SSLError as ex:
130
- if ex.reason not in(
131
- "NO_SHARED_CIPHER",
132
- "TLSV1_ALERT_UNKNOWN_CA",
133
- "SSLV3_ALERT_BAD_CERTIFICATE","SSLV3_ALERT_CERTIFICATE_UNKNOWN",
134
- "HTTP_REQUEST","HTTPS_PROXY_REQUEST",
135
- "UNKNOWN_PROTOCOL","WRONG_VERSION_NUMBER","WRONG_SSL_VERSION"):
136
- self.callbackError(ex)
137
- self.countActiveConnections-=1
138
- except OSError as ex:
139
- self.__handleOsError(ex)
140
- self.countActiveConnections-=1
141
- if request is None:
142
- clientConnection.close()
143
- return
144
- # decodifico la richiesta
145
- try:
146
- request=request.decode(ModuloStringhe.CODIFICA_UTF8)
147
- except UnicodeDecodeError:
148
- request = None
149
- self.countActiveConnections -= 1
150
- if request is None:
151
- clientConnection.close()
152
- return
153
- ModuloThread.startDaemonWithCallbackError(self.callbackError,self.__handleRequestNoThreaded,(request,clientConnection,clientIp,clientPort))
154
-
155
- def __handleRequestNoThreaded(self,request:str|None,clientConnection,clientIp:str,clientPort:int):
156
- valori=self.__parseRequest(request)
157
- if valori is not None:
158
- httpCode,responseHeader,responseBody=self.handleRequest(*valori,clientIp,clientPort)
159
- response,tipo=self.__parseResponse(httpCode,responseHeader,responseBody)
160
- else:
161
- responseBody=None
162
- response,tipo=self.__parseResponse(500,None,None)
163
-
164
- if tipo==self.TIPO_RESPONSE__PLAIN_TEXT:
165
- self.__sendResponse(clientConnection,response)
166
- elif tipo==self.TIPO_RESPONSE__STREAM and responseBody is not None:
167
- self.__sendResponse(clientConnection,response)
168
- # se e' un file pointer leggo e invio un po' alla volta
169
- fp=responseBody
170
- chunk=fp.read(1024)
171
- while chunk:
172
- clientConnection.send(chunk)
173
- chunk=fp.read(1024)
174
- fp.close()
175
- else:
176
- response,tipo=self.__parseResponse(500,None,None)
177
- self.__sendResponse(clientConnection,response)
178
- try:
179
- clientConnection.shutdown(socket.SHUT_RDWR)
180
- except OSError as e:
181
- if e.errno!=errno.ENOTCONN:
182
- raise e
183
- clientConnection.close()
184
- self.countActiveConnections-=1
185
-
186
- @staticmethod
187
- def __parseRequest(request:str)->tuple|None:
188
- request=ModuloStringhe.normalizzaEol(request)
189
- index=request.find('\n\n')
190
- if index==-1:
191
- return None
192
- headers=request[0:index]
193
- headers=headers.split("\n")
194
- # la prima riga dell'header deve contenere 3 info
195
- header=headers[0]
196
- if ModuloStringhe.isEmpty(header):
197
- return None
198
- arr=header.split()
199
- method=ModuloListe.collectionSafeGet(arr,0)
200
- url=ModuloListe.collectionSafeGet(arr,1)
201
- httpType=ModuloListe.collectionSafeGet(arr,2)
202
- if method is None or url is None or httpType is None:
203
- return None
204
-
205
- url=ModuloHttpUtils.decodeUrl(url)
206
- if not ModuloStringhe.contains(url,"?"):
207
- return method,url,url,{},httpType
208
- # controllo url
209
- path,params=url.split("?",1)
210
- path=path[1:]
211
- params=params.split("&")
212
- params=[x.split('=') for x in params]
213
- params=dict(zip([x[0] for x in params],[x[1] if len(x)>=2 else None for x in params]))
214
- return method,url,path,params,httpType
215
-
216
- def __parseResponse(self,httpCode:int,responseHeader:str|None,responseBody)->tuple:
217
- if responseHeader is None:
218
- responseHeader=""
219
- if responseBody is None:
220
- responseBody=""
221
-
222
- lunghezza=None
223
- tipo=None
224
- filename=None
225
- if isinstance(responseBody,str):
226
- contentType="text/plain; charset=UTF-8"#TODO: se cors usare contentType dell'origine
227
- tipo=self.TIPO_RESPONSE__PLAIN_TEXT
228
- responseBody=ModuloStringhe.normalizzaEol(responseBody.rstrip())
229
- lunghezza=len(responseBody.encode(ModuloStringhe.CODIFICA_UTF8))
230
- elif isinstance(responseBody,BufferedReader):
231
- contentType="application/octet-stream"
232
- tipo=self.TIPO_RESPONSE__STREAM
233
- filename=os.path.basename(responseBody.name)
234
- else:
235
- contentType="text/plain; charset=UTF-8"
236
- httpCode=501
237
-
238
- responseHeader+=("HTTP/1.1 %d %s"%(httpCode,self.HTTP_CODES.get(httpCode,"")))
239
- if httpCode==ModuloHttp.STATUS_OK:
240
- if lunghezza is not None:
241
- responseHeader+="\nContent-Length: "+str(lunghezza)
242
- if filename is not None:
243
- responseHeader+='\nContent-Disposition: attachment; filename="'+filename+'"'
244
- responseHeader+=f"""
245
- Access-Control-Allow-Origin: *
246
- Content-Type: {contentType}
247
- Connection: close
248
- X-Robots-Tag: noindex, nofollow"""
249
- #compongo response
250
- response=responseHeader+"\n\n"
251
- if tipo==self.TIPO_RESPONSE__PLAIN_TEXT:
252
- response+=responseBody
253
- response=ModuloStringhe.normalizzaEol(response)
254
- response=response.encode(ModuloStringhe.CODIFICA_UTF8)
255
- return response,tipo
256
-
257
- @staticmethod
258
- def __sendResponse(clientConnection,response):
259
- try:
260
- clientConnection.sendall(response)
261
- except (ConnectionResetError,BrokenPipeError,ssl.SSLEOFError,ssl.SSLZeroReturnError):
262
- pass
263
-
264
- def __handleOsError(self,ex:OSError):
265
- if ex.errno in (errno.ECONNRESET,errno.ETIMEDOUT):
266
- return
267
- self.callbackError(ex)
1
+ import errno
2
+ import os
3
+ import socket
4
+ import ssl
5
+ import time
6
+ from _io import BufferedReader
7
+ from abc import ABC
8
+ from abc import abstractmethod
9
+
10
+ from modulitiz_nano.ModuloListe import ModuloListe
11
+ from modulitiz_nano.ModuloStringhe import ModuloStringhe
12
+ from modulitiz_nano.eccezioni.EccezioneRuntime import EccezioneRuntime
13
+ from modulitiz_nano.files.ModuloFiles import ModuloFiles
14
+ from modulitiz_nano.files.ModuloLogging import ModuloLogging
15
+ from modulitiz_nano.multithread.ModuloThread import ModuloThread
16
+ from modulitiz_micro.rete.ModuloNetworking import ModuloNetworking
17
+ from modulitiz_micro.rete.http.ModuloHttp import ModuloHttp
18
+ from modulitiz_micro.rete.http.ModuloHttpUtils import ModuloHttpUtils
19
+ from modulitiz_micro.rete.ssl.ModuloSsl import ModuloSsl
20
+
21
+
22
+ class AbstractSocketServer(ABC):
23
+ HTTP_CODES={
24
+ ModuloHttp.STATUS_OK:"OK",
25
+ 404:"Not Found",
26
+ 500:"Internal Server Error",
27
+ 501:"Not Implemented",
28
+ }
29
+
30
+ MAX_CONNECTIONS=10
31
+ TIMEOUT_SERVER=30
32
+ TIMEOUT_CLIENT=60
33
+
34
+ TIPO_RESPONSE__PLAIN_TEXT=1
35
+ TIPO_RESPONSE__STREAM=2
36
+
37
+ def __init__(self,logger:ModuloLogging,porta:int,percorsoFileCertSsl:str):
38
+ self._logger=logger
39
+ self.__porta=porta
40
+ self.__percorsoFileCertSsl=percorsoFileCertSsl
41
+
42
+ self.isRequestedExit=False
43
+ self.countActiveConnections=0
44
+ self.contextSsl=None
45
+ self.serverSocket=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
46
+
47
+ def populate(self):
48
+ # controllo che la porta non sia gia' occupata
49
+ if self.isOpen():
50
+ raise EccezioneRuntime(f"La porta {self.__porta} e' gia' aperta")
51
+ # ssl
52
+ if self.__percorsoFileCertSsl is not None:
53
+ # se il certificato non esiste lo creo
54
+ if ModuloFiles.getFileSize(self.__percorsoFileCertSsl)==-1:
55
+ self._logger.info("Generazione certificato...")
56
+ moduloSsl=ModuloSsl()
57
+ moduloSsl.createSelfSignedCertAnonymous()
58
+ with ModuloFiles.open(self.__percorsoFileCertSsl,"w+t") as fp:
59
+ fp.write(moduloSsl.certStr)
60
+ contextSsl=ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
61
+ contextSsl.load_cert_chain(certfile=self.__percorsoFileCertSsl)
62
+ self.contextSsl=contextSsl
63
+ # creo la socket
64
+ self.serverSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
65
+ self.serverSocket.bind(('0.0.0.0', self.__porta))
66
+ self.serverSocket.listen(self.MAX_CONNECTIONS)
67
+ self.serverSocket.settimeout(self.TIMEOUT_SERVER)
68
+
69
+ @abstractmethod
70
+ def callbackError(self,ex: Exception):
71
+ """
72
+ Cosa fare in caso di errore della socket
73
+ """
74
+
75
+ @abstractmethod
76
+ def handleRequest(self,method:str,url:str,path:str,params:dict,httpType:str,clientIp:str,clientPort:int)->tuple:
77
+ """
78
+ Cosa fare se un client contatta il server.
79
+ Deve ritornare una tupla: (httpCode,header,body)
80
+ """
81
+
82
+ def isOpen(self)->bool:
83
+ return ModuloNetworking.isHttpPortOpen(None, self.__porta)
84
+
85
+ def avvia(self):
86
+ protocolSuffix="S" if self.contextSsl is not None else ""
87
+ self._logger.info("Server in ascolto sulla porta HTTP%s %d",protocolSuffix,self.__porta)
88
+ ModuloThread.startDaemonWithCallbackError(self.callbackError,self.__avviaLoopNoThreaded,())
89
+
90
+ def chiudi(self):
91
+ if not self.isOpen():
92
+ return
93
+ self.isRequestedExit=True
94
+ while self.countActiveConnections>0:
95
+ time.sleep(0.5)
96
+ # qui socket.shutdown() non ci vuole perche' deve essere usato solo lato client
97
+ self.serverSocket.close()
98
+
99
+ def __avviaLoopNoThreaded(self):
100
+ while not self.isRequestedExit:
101
+ self.__avviaNoThreaded()
102
+ self.countActiveConnections=0
103
+ def __avviaNoThreaded(self):
104
+ # aspetto una richiesta
105
+ try:
106
+ clientConnection,(clientIp,clientPort)=self.serverSocket.accept()
107
+ except TimeoutError:
108
+ clientConnection=None
109
+ clientIp=None
110
+ clientPort=None
111
+ except OSError as osError:
112
+ if osError.errno not in(errno.ENOTSOCK,errno.EBADF):
113
+ self.callbackError(osError)
114
+ clientConnection=None
115
+ clientIp=None
116
+ clientPort=None
117
+ if clientConnection is None:
118
+ return
119
+ self.countActiveConnections+=1
120
+ # richiedo i dati
121
+ request=None
122
+ try:
123
+ clientConnection.settimeout(self.TIMEOUT_CLIENT)
124
+ if self.contextSsl is not None:
125
+ clientConnection=self.contextSsl.wrap_socket(clientConnection,server_side=True)
126
+ request=clientConnection.recv(1024)
127
+ except (ssl.SSLEOFError,ssl.SSLZeroReturnError,TimeoutError):
128
+ self.countActiveConnections-=1
129
+ except ssl.SSLError as ex:
130
+ if ex.reason not in(
131
+ "NO_SHARED_CIPHER",
132
+ "TLSV1_ALERT_UNKNOWN_CA",
133
+ "SSLV3_ALERT_BAD_CERTIFICATE","SSLV3_ALERT_CERTIFICATE_UNKNOWN",
134
+ "HTTP_REQUEST","HTTPS_PROXY_REQUEST",
135
+ "UNKNOWN_PROTOCOL","WRONG_VERSION_NUMBER","WRONG_SSL_VERSION"):
136
+ self.callbackError(ex)
137
+ self.countActiveConnections-=1
138
+ except OSError as ex:
139
+ self.__handleOsError(ex)
140
+ self.countActiveConnections-=1
141
+ if request is None:
142
+ clientConnection.close()
143
+ return
144
+ # decodifico la richiesta
145
+ try:
146
+ request=request.decode(ModuloStringhe.CODIFICA_UTF8)
147
+ except UnicodeDecodeError:
148
+ request = None
149
+ self.countActiveConnections -= 1
150
+ if request is None:
151
+ clientConnection.close()
152
+ return
153
+ ModuloThread.startDaemonWithCallbackError(self.callbackError,self.__handleRequestNoThreaded,(request,clientConnection,clientIp,clientPort))
154
+
155
+ def __handleRequestNoThreaded(self,request:str|None,clientConnection,clientIp:str,clientPort:int):
156
+ valori=self.__parseRequest(request)
157
+ if valori is not None:
158
+ httpCode,responseHeader,responseBody=self.handleRequest(*valori,clientIp,clientPort)
159
+ response,tipo=self.__parseResponse(httpCode,responseHeader,responseBody)
160
+ else:
161
+ responseBody=None
162
+ response,tipo=self.__parseResponse(500,None,None)
163
+
164
+ if tipo==self.TIPO_RESPONSE__PLAIN_TEXT:
165
+ self.__sendResponse(clientConnection,response)
166
+ elif tipo==self.TIPO_RESPONSE__STREAM and responseBody is not None:
167
+ self.__sendResponse(clientConnection,response)
168
+ # se e' un file pointer leggo e invio un po' alla volta
169
+ fp=responseBody
170
+ chunk=fp.read(1024)
171
+ while chunk:
172
+ clientConnection.send(chunk)
173
+ chunk=fp.read(1024)
174
+ fp.close()
175
+ else:
176
+ response,tipo=self.__parseResponse(500,None,None)
177
+ self.__sendResponse(clientConnection,response)
178
+ try:
179
+ clientConnection.shutdown(socket.SHUT_RDWR)
180
+ except OSError as e:
181
+ if e.errno!=errno.ENOTCONN:
182
+ raise e
183
+ clientConnection.close()
184
+ self.countActiveConnections-=1
185
+
186
+ @staticmethod
187
+ def __parseRequest(request:str)->tuple|None:
188
+ request=ModuloStringhe.normalizzaEol(request)
189
+ index=request.find('\n\n')
190
+ if index==-1:
191
+ return None
192
+ headers=request[0:index]
193
+ headers=headers.split("\n")
194
+ # la prima riga dell'header deve contenere 3 info
195
+ header=headers[0]
196
+ if ModuloStringhe.isEmpty(header):
197
+ return None
198
+ arr=header.split()
199
+ method=ModuloListe.collectionSafeGet(arr,0)
200
+ url=ModuloListe.collectionSafeGet(arr,1)
201
+ httpType=ModuloListe.collectionSafeGet(arr,2)
202
+ if method is None or url is None or httpType is None:
203
+ return None
204
+
205
+ url=ModuloHttpUtils.decodeUrl(url)
206
+ if not ModuloStringhe.contains(url,"?"):
207
+ return method,url,url,{},httpType
208
+ # controllo url
209
+ path,params=url.split("?",1)
210
+ path=path[1:]
211
+ params=params.split("&")
212
+ params=[x.split('=') for x in params]
213
+ params=dict(zip([x[0] for x in params],[x[1] if len(x)>=2 else None for x in params]))
214
+ return method,url,path,params,httpType
215
+
216
+ def __parseResponse(self,httpCode:int,responseHeader:str|None,responseBody)->tuple:
217
+ if responseHeader is None:
218
+ responseHeader=""
219
+ if responseBody is None:
220
+ responseBody=""
221
+
222
+ lunghezza=None
223
+ tipo=None
224
+ filename=None
225
+ if isinstance(responseBody,str):
226
+ contentType="text/plain; charset=UTF-8"#TODO: se cors usare contentType dell'origine
227
+ tipo=self.TIPO_RESPONSE__PLAIN_TEXT
228
+ responseBody=ModuloStringhe.normalizzaEol(responseBody.rstrip())
229
+ lunghezza=len(responseBody.encode(ModuloStringhe.CODIFICA_UTF8))
230
+ elif isinstance(responseBody,BufferedReader):
231
+ contentType="application/octet-stream"
232
+ tipo=self.TIPO_RESPONSE__STREAM
233
+ filename=os.path.basename(responseBody.name)
234
+ else:
235
+ contentType="text/plain; charset=UTF-8"
236
+ httpCode=501
237
+
238
+ responseHeader+=("HTTP/1.1 %d %s"%(httpCode,self.HTTP_CODES.get(httpCode,"")))
239
+ if httpCode==ModuloHttp.STATUS_OK:
240
+ if lunghezza is not None:
241
+ responseHeader+="\nContent-Length: "+str(lunghezza)
242
+ if filename is not None:
243
+ responseHeader+='\nContent-Disposition: attachment; filename="'+filename+'"'
244
+ responseHeader+=f"""
245
+ Access-Control-Allow-Origin: *
246
+ Content-Type: {contentType}
247
+ Connection: close
248
+ X-Robots-Tag: noindex, nofollow"""
249
+ #compongo response
250
+ response=responseHeader+"\n\n"
251
+ if tipo==self.TIPO_RESPONSE__PLAIN_TEXT:
252
+ response+=responseBody
253
+ response=ModuloStringhe.normalizzaEol(response)
254
+ response=response.encode(ModuloStringhe.CODIFICA_UTF8)
255
+ return response,tipo
256
+
257
+ @staticmethod
258
+ def __sendResponse(clientConnection,response):
259
+ try:
260
+ clientConnection.sendall(response)
261
+ except (ConnectionResetError,BrokenPipeError,ssl.SSLEOFError,ssl.SSLZeroReturnError):
262
+ pass
263
+
264
+ def __handleOsError(self,ex:OSError):
265
+ if ex.errno in (errno.ECONNRESET,errno.ETIMEDOUT):
266
+ return
267
+ self.callbackError(ex)
@@ -1,56 +1,56 @@
1
- from OpenSSL import crypto
2
-
3
- from modulitiz_nano.ModuloDate import ModuloDate
4
- from modulitiz_nano.ModuloStringhe import ModuloStringhe
5
-
6
-
7
- class ModuloSsl(object):
8
- CA_CERT_FILE="cert.pem"
9
-
10
- def __init__(self):
11
- self.cert: crypto.X509|None=None
12
- self.certStr: str|None=None
13
-
14
- def createSelfSignedCertAnonymous(self):
15
- return self.createSelfSignedCert("XX","XX","Xxx","Xxx","Xx","Xx","x@x.com")
16
-
17
- def createSelfSignedCert(self,stato: str,provincia: str,via: str,organizzazione: str,organizzazioneUnita: str,nomeComune: str,email: str):
18
- privateKey=crypto.PKey()
19
- privateKey.generate_key(crypto.TYPE_RSA,2048)
20
-
21
- certReq=crypto.X509Req()
22
- certReq.get_subject().C=stato
23
- certReq.get_subject().ST=provincia
24
- certReq.get_subject().L=via
25
- certReq.get_subject().O=organizzazione
26
- certReq.get_subject().OU=organizzazioneUnita
27
- certReq.get_subject().CN=nomeComune
28
- certReq.get_subject().emailAddress=email
29
- certReq.set_pubkey(privateKey)
30
- certReq.sign(privateKey,'sha256')
31
-
32
- certIssuer=crypto.X509Req()
33
- certIssuer.get_subject().C=stato
34
- certIssuer.get_subject().ST=provincia
35
- certIssuer.get_subject().L=via
36
- certIssuer.get_subject().O=organizzazione
37
- certIssuer.get_subject().OU=organizzazioneUnita
38
- certIssuer.get_subject().CN=nomeComune
39
- certIssuer.get_subject().emailAddress=email
40
- certIssuer.set_pubkey(privateKey)
41
- certIssuer.sign(privateKey,'sha256')
42
-
43
- cert=crypto.X509()
44
- cert.set_serial_number(ModuloDate.getSecs())
45
- cert.gmtime_adj_notBefore(0)
46
- cert.gmtime_adj_notAfter(5*365*24*60*60)
47
- cert.set_issuer(certIssuer.get_subject())
48
- cert.set_subject(certReq.get_subject())
49
- cert.set_pubkey(certReq.get_pubkey())
50
- cert.sign(privateKey,'sha256')
51
- self.cert=cert
52
-
53
- certStr=crypto.dump_certificate(crypto.FILETYPE_PEM,cert).decode(ModuloStringhe.CODIFICA_UTF8)
54
- certStr+=certStr
55
- certStr+=crypto.dump_privatekey(crypto.FILETYPE_PEM,privateKey).decode(ModuloStringhe.CODIFICA_UTF8)
56
- self.certStr=certStr
1
+ from OpenSSL import crypto
2
+
3
+ from modulitiz_nano.ModuloDate import ModuloDate
4
+ from modulitiz_nano.ModuloStringhe import ModuloStringhe
5
+
6
+
7
+ class ModuloSsl(object):
8
+ CA_CERT_FILE="cert.pem"
9
+
10
+ def __init__(self):
11
+ self.cert: crypto.X509|None=None
12
+ self.certStr: str|None=None
13
+
14
+ def createSelfSignedCertAnonymous(self):
15
+ return self.createSelfSignedCert("XX","XX","Xxx","Xxx","Xx","Xx","x@x.com")
16
+
17
+ def createSelfSignedCert(self,stato: str,provincia: str,via: str,organizzazione: str,organizzazioneUnita: str,nomeComune: str,email: str):
18
+ privateKey=crypto.PKey()
19
+ privateKey.generate_key(crypto.TYPE_RSA,2048)
20
+
21
+ certReq=crypto.X509Req()
22
+ certReq.get_subject().C=stato
23
+ certReq.get_subject().ST=provincia
24
+ certReq.get_subject().L=via
25
+ certReq.get_subject().O=organizzazione
26
+ certReq.get_subject().OU=organizzazioneUnita
27
+ certReq.get_subject().CN=nomeComune
28
+ certReq.get_subject().emailAddress=email
29
+ certReq.set_pubkey(privateKey)
30
+ certReq.sign(privateKey,'sha256')
31
+
32
+ certIssuer=crypto.X509Req()
33
+ certIssuer.get_subject().C=stato
34
+ certIssuer.get_subject().ST=provincia
35
+ certIssuer.get_subject().L=via
36
+ certIssuer.get_subject().O=organizzazione
37
+ certIssuer.get_subject().OU=organizzazioneUnita
38
+ certIssuer.get_subject().CN=nomeComune
39
+ certIssuer.get_subject().emailAddress=email
40
+ certIssuer.set_pubkey(privateKey)
41
+ certIssuer.sign(privateKey,'sha256')
42
+
43
+ cert=crypto.X509()
44
+ cert.set_serial_number(ModuloDate.getSecs())
45
+ cert.gmtime_adj_notBefore(0)
46
+ cert.gmtime_adj_notAfter(5*365*24*60*60)
47
+ cert.set_issuer(certIssuer.get_subject())
48
+ cert.set_subject(certReq.get_subject())
49
+ cert.set_pubkey(certReq.get_pubkey())
50
+ cert.sign(privateKey,'sha256')
51
+ self.cert=cert
52
+
53
+ certStr=crypto.dump_certificate(crypto.FILETYPE_PEM,cert).decode(ModuloStringhe.CODIFICA_UTF8)
54
+ certStr+=certStr
55
+ certStr+=crypto.dump_privatekey(crypto.FILETYPE_PEM,privateKey).decode(ModuloStringhe.CODIFICA_UTF8)
56
+ self.certStr=certStr