@push.rocks/smartproxy 19.3.2 → 19.3.4

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 (313) hide show
  1. package/dist_ts/00_commitinfo_data.js +1 -1
  2. package/dist_ts/forwarding/factory/forwarding-factory.js +29 -1
  3. package/dist_ts/http/index.d.ts +1 -3
  4. package/dist_ts/http/index.js +4 -10
  5. package/dist_ts/http/models/http-types.d.ts +4 -91
  6. package/dist_ts/http/models/http-types.js +5 -60
  7. package/dist_ts/http/router/proxy-router.d.ts +1 -1
  8. package/dist_ts/http/router/route-router.d.ts +1 -1
  9. package/dist_ts/index.d.ts +9 -7
  10. package/dist_ts/index.js +10 -7
  11. package/dist_ts/proxies/{network-proxy → http-proxy}/certificate-manager.d.ts +2 -2
  12. package/dist_ts/proxies/{network-proxy → http-proxy}/certificate-manager.js +1 -1
  13. package/dist_ts/proxies/{network-proxy → http-proxy}/connection-pool.d.ts +2 -2
  14. package/dist_ts/proxies/http-proxy/connection-pool.js +210 -0
  15. package/dist_ts/proxies/http-proxy/context-creator.js +108 -0
  16. package/dist_ts/proxies/{network-proxy → http-proxy}/function-cache.js +1 -1
  17. package/dist_ts/proxies/http-proxy/handlers/index.d.ts +5 -0
  18. package/dist_ts/proxies/http-proxy/handlers/index.js +6 -0
  19. package/dist_ts/proxies/http-proxy/handlers/redirect-handler.d.ts +18 -0
  20. package/dist_ts/proxies/http-proxy/handlers/redirect-handler.js +78 -0
  21. package/dist_ts/proxies/http-proxy/handlers/static-handler.d.ts +19 -0
  22. package/dist_ts/proxies/http-proxy/handlers/static-handler.js +203 -0
  23. package/dist_ts/proxies/{network-proxy/network-proxy.d.ts → http-proxy/http-proxy.d.ts} +10 -9
  24. package/dist_ts/proxies/{network-proxy/network-proxy.js → http-proxy/http-proxy.js} +13 -12
  25. package/dist_ts/proxies/{network-proxy → http-proxy}/http-request-handler.js +1 -1
  26. package/dist_ts/proxies/http-proxy/http2-request-handler.js +201 -0
  27. package/dist_ts/proxies/{network-proxy → http-proxy}/index.d.ts +2 -2
  28. package/dist_ts/proxies/http-proxy/index.js +12 -0
  29. package/dist_ts/proxies/http-proxy/models/http-types.d.ts +119 -0
  30. package/dist_ts/proxies/http-proxy/models/http-types.js +112 -0
  31. package/dist_ts/proxies/http-proxy/models/index.d.ts +5 -0
  32. package/dist_ts/proxies/http-proxy/models/index.js +6 -0
  33. package/dist_ts/proxies/{network-proxy → http-proxy}/models/types.d.ts +2 -2
  34. package/dist_ts/proxies/http-proxy/models/types.js +276 -0
  35. package/dist_ts/proxies/{network-proxy → http-proxy}/request-handler.d.ts +3 -3
  36. package/dist_ts/proxies/{network-proxy → http-proxy}/request-handler.js +2 -2
  37. package/dist_ts/proxies/http-proxy/security-manager.js +255 -0
  38. package/dist_ts/proxies/{network-proxy → http-proxy}/websocket-handler.d.ts +3 -3
  39. package/dist_ts/proxies/{network-proxy → http-proxy}/websocket-handler.js +2 -2
  40. package/dist_ts/proxies/index.d.ts +5 -5
  41. package/dist_ts/proxies/index.js +5 -5
  42. package/dist_ts/proxies/smart-proxy/certificate-manager.d.ts +4 -4
  43. package/dist_ts/proxies/smart-proxy/certificate-manager.js +11 -11
  44. package/dist_ts/proxies/smart-proxy/http-proxy-bridge.d.ts +41 -0
  45. package/dist_ts/proxies/smart-proxy/http-proxy-bridge.js +121 -0
  46. package/dist_ts/proxies/smart-proxy/index.d.ts +2 -1
  47. package/dist_ts/proxies/smart-proxy/index.js +4 -2
  48. package/dist_ts/proxies/smart-proxy/models/interfaces.d.ts +2 -2
  49. package/dist_ts/proxies/smart-proxy/port-manager.js +3 -3
  50. package/dist_ts/proxies/smart-proxy/route-connection-handler.d.ts +3 -3
  51. package/dist_ts/proxies/smart-proxy/route-connection-handler.js +24 -265
  52. package/dist_ts/proxies/smart-proxy/smart-proxy.d.ts +1 -1
  53. package/dist_ts/proxies/smart-proxy/smart-proxy.js +25 -25
  54. package/dist_ts/routing/index.d.ts +5 -0
  55. package/dist_ts/routing/index.js +8 -0
  56. package/dist_ts/routing/models/http-types.d.ts +6 -0
  57. package/dist_ts/routing/models/http-types.js +7 -0
  58. package/dist_ts/routing/router/index.d.ts +8 -0
  59. package/dist_ts/routing/router/index.js +7 -0
  60. package/dist_ts/{classes.router.d.ts → routing/router/proxy-router.d.ts} +14 -11
  61. package/dist_ts/{classes.router.js → routing/router/proxy-router.js} +2 -2
  62. package/dist_ts/routing/router/route-router.d.ts +108 -0
  63. package/dist_ts/routing/router/route-router.js +393 -0
  64. package/package.json +1 -1
  65. package/readme.md +18 -35
  66. package/readme.plan.md +173 -271
  67. package/ts/00_commitinfo_data.ts +1 -1
  68. package/ts/forwarding/factory/forwarding-factory.ts +28 -0
  69. package/ts/index.ts +13 -9
  70. package/ts/proxies/{network-proxy → http-proxy}/certificate-manager.ts +2 -2
  71. package/ts/proxies/{network-proxy → http-proxy}/connection-pool.ts +2 -2
  72. package/ts/proxies/http-proxy/handlers/index.ts +6 -0
  73. package/ts/proxies/http-proxy/handlers/redirect-handler.ts +105 -0
  74. package/ts/proxies/http-proxy/handlers/static-handler.ts +251 -0
  75. package/ts/proxies/{network-proxy/network-proxy.ts → http-proxy/http-proxy.ts} +15 -14
  76. package/ts/proxies/{network-proxy → http-proxy}/index.ts +3 -3
  77. package/ts/proxies/http-proxy/models/http-types.ts +165 -0
  78. package/ts/proxies/http-proxy/models/index.ts +5 -0
  79. package/ts/proxies/{network-proxy → http-proxy}/models/types.ts +2 -2
  80. package/ts/proxies/{network-proxy → http-proxy}/request-handler.ts +3 -3
  81. package/ts/proxies/{network-proxy → http-proxy}/websocket-handler.ts +3 -3
  82. package/ts/proxies/index.ts +7 -7
  83. package/ts/proxies/smart-proxy/certificate-manager.ts +10 -10
  84. package/ts/proxies/smart-proxy/{network-proxy-bridge.ts → http-proxy-bridge.ts} +44 -44
  85. package/ts/proxies/smart-proxy/index.ts +4 -1
  86. package/ts/proxies/smart-proxy/models/interfaces.ts +3 -3
  87. package/ts/proxies/smart-proxy/port-manager.ts +2 -2
  88. package/ts/proxies/smart-proxy/route-connection-handler.ts +23 -307
  89. package/ts/proxies/smart-proxy/smart-proxy.ts +25 -25
  90. package/ts/routing/index.ts +9 -0
  91. package/ts/routing/models/http-types.ts +6 -0
  92. package/ts/{http → routing}/router/proxy-router.ts +1 -1
  93. package/ts/{http → routing}/router/route-router.ts +1 -1
  94. package/dist_ts/certificate/acme/acme-factory.d.ts +0 -17
  95. package/dist_ts/certificate/acme/acme-factory.js +0 -40
  96. package/dist_ts/certificate/acme/challenge-handler.d.ts +0 -44
  97. package/dist_ts/certificate/acme/challenge-handler.js +0 -92
  98. package/dist_ts/certificate/acme/index.d.ts +0 -4
  99. package/dist_ts/certificate/acme/index.js +0 -5
  100. package/dist_ts/certificate/certificate-manager.d.ts +0 -150
  101. package/dist_ts/certificate/certificate-manager.js +0 -505
  102. package/dist_ts/certificate/events/certificate-events.d.ts +0 -33
  103. package/dist_ts/certificate/events/certificate-events.js +0 -38
  104. package/dist_ts/certificate/events/simplified-events.d.ts +0 -56
  105. package/dist_ts/certificate/events/simplified-events.js +0 -13
  106. package/dist_ts/certificate/index.d.ts +0 -30
  107. package/dist_ts/certificate/index.js +0 -37
  108. package/dist_ts/certificate/models/certificate-errors.d.ts +0 -69
  109. package/dist_ts/certificate/models/certificate-errors.js +0 -141
  110. package/dist_ts/certificate/models/certificate-strategy.d.ts +0 -60
  111. package/dist_ts/certificate/models/certificate-strategy.js +0 -73
  112. package/dist_ts/certificate/models/certificate-types.d.ts +0 -97
  113. package/dist_ts/certificate/models/certificate-types.js +0 -2
  114. package/dist_ts/certificate/providers/cert-provisioner.d.ts +0 -119
  115. package/dist_ts/certificate/providers/cert-provisioner.js +0 -422
  116. package/dist_ts/certificate/providers/index.d.ts +0 -4
  117. package/dist_ts/certificate/providers/index.js +0 -5
  118. package/dist_ts/certificate/simplified-certificate-manager.d.ts +0 -150
  119. package/dist_ts/certificate/simplified-certificate-manager.js +0 -501
  120. package/dist_ts/certificate/storage/file-storage.d.ts +0 -66
  121. package/dist_ts/certificate/storage/file-storage.js +0 -194
  122. package/dist_ts/certificate/storage/index.d.ts +0 -4
  123. package/dist_ts/certificate/storage/index.js +0 -5
  124. package/dist_ts/certificate/utils/certificate-helpers.d.ts +0 -17
  125. package/dist_ts/certificate/utils/certificate-helpers.js +0 -45
  126. package/dist_ts/classes.iptablesproxy.d.ts +0 -112
  127. package/dist_ts/classes.iptablesproxy.js +0 -765
  128. package/dist_ts/classes.networkproxy.d.ts +0 -243
  129. package/dist_ts/classes.networkproxy.js +0 -1424
  130. package/dist_ts/classes.nftablesproxy.d.ts +0 -219
  131. package/dist_ts/classes.nftablesproxy.js +0 -1542
  132. package/dist_ts/classes.port80handler.d.ts +0 -215
  133. package/dist_ts/classes.port80handler.js +0 -736
  134. package/dist_ts/classes.portproxy.d.ts +0 -171
  135. package/dist_ts/classes.portproxy.js +0 -1802
  136. package/dist_ts/classes.pp.acmemanager.d.ts +0 -34
  137. package/dist_ts/classes.pp.acmemanager.js +0 -123
  138. package/dist_ts/classes.pp.connectionhandler.d.ts +0 -39
  139. package/dist_ts/classes.pp.connectionhandler.js +0 -754
  140. package/dist_ts/classes.pp.connectionmanager.d.ts +0 -78
  141. package/dist_ts/classes.pp.connectionmanager.js +0 -378
  142. package/dist_ts/classes.pp.domainconfigmanager.d.ts +0 -55
  143. package/dist_ts/classes.pp.domainconfigmanager.js +0 -103
  144. package/dist_ts/classes.pp.interfaces.d.ts +0 -133
  145. package/dist_ts/classes.pp.interfaces.js +0 -2
  146. package/dist_ts/classes.pp.networkproxybridge.d.ts +0 -57
  147. package/dist_ts/classes.pp.networkproxybridge.js +0 -306
  148. package/dist_ts/classes.pp.portproxy.d.ts +0 -64
  149. package/dist_ts/classes.pp.portproxy.js +0 -567
  150. package/dist_ts/classes.pp.portrangemanager.d.ts +0 -56
  151. package/dist_ts/classes.pp.portrangemanager.js +0 -179
  152. package/dist_ts/classes.pp.securitymanager.d.ts +0 -47
  153. package/dist_ts/classes.pp.securitymanager.js +0 -126
  154. package/dist_ts/classes.pp.snihandler.d.ts +0 -153
  155. package/dist_ts/classes.pp.snihandler.js +0 -1053
  156. package/dist_ts/classes.pp.timeoutmanager.d.ts +0 -47
  157. package/dist_ts/classes.pp.timeoutmanager.js +0 -154
  158. package/dist_ts/classes.pp.tlsalert.d.ts +0 -149
  159. package/dist_ts/classes.pp.tlsalert.js +0 -225
  160. package/dist_ts/classes.pp.tlsmanager.d.ts +0 -57
  161. package/dist_ts/classes.pp.tlsmanager.js +0 -132
  162. package/dist_ts/classes.snihandler.d.ts +0 -198
  163. package/dist_ts/classes.snihandler.js +0 -1210
  164. package/dist_ts/classes.sslredirect.d.ts +0 -8
  165. package/dist_ts/classes.sslredirect.js +0 -28
  166. package/dist_ts/common/acmeFactory.d.ts +0 -9
  167. package/dist_ts/common/acmeFactory.js +0 -20
  168. package/dist_ts/common/port80-adapter.d.ts +0 -11
  169. package/dist_ts/common/port80-adapter.js +0 -87
  170. package/dist_ts/examples/forwarding-example.d.ts +0 -1
  171. package/dist_ts/examples/forwarding-example.js +0 -96
  172. package/dist_ts/forwarding/config/domain-config.d.ts +0 -12
  173. package/dist_ts/forwarding/config/domain-config.js +0 -12
  174. package/dist_ts/forwarding/config/domain-manager.d.ts +0 -86
  175. package/dist_ts/forwarding/config/domain-manager.js +0 -242
  176. package/dist_ts/helpers.certificates.d.ts +0 -5
  177. package/dist_ts/helpers.certificates.js +0 -23
  178. package/dist_ts/http/port80/acme-interfaces.d.ts +0 -108
  179. package/dist_ts/http/port80/acme-interfaces.js +0 -51
  180. package/dist_ts/http/port80/challenge-responder.d.ts +0 -53
  181. package/dist_ts/http/port80/challenge-responder.js +0 -203
  182. package/dist_ts/http/port80/index.d.ts +0 -6
  183. package/dist_ts/http/port80/index.js +0 -9
  184. package/dist_ts/http/port80/port80-handler.d.ts +0 -136
  185. package/dist_ts/http/port80/port80-handler.js +0 -592
  186. package/dist_ts/http/redirects/index.d.ts +0 -4
  187. package/dist_ts/http/redirects/index.js +0 -5
  188. package/dist_ts/networkproxy/classes.np.certificatemanager.d.ts +0 -77
  189. package/dist_ts/networkproxy/classes.np.certificatemanager.js +0 -372
  190. package/dist_ts/networkproxy/classes.np.connectionpool.d.ts +0 -47
  191. package/dist_ts/networkproxy/classes.np.connectionpool.js +0 -210
  192. package/dist_ts/networkproxy/classes.np.networkproxy.d.ts +0 -118
  193. package/dist_ts/networkproxy/classes.np.networkproxy.js +0 -387
  194. package/dist_ts/networkproxy/classes.np.requesthandler.d.ts +0 -56
  195. package/dist_ts/networkproxy/classes.np.requesthandler.js +0 -393
  196. package/dist_ts/networkproxy/classes.np.types.d.ts +0 -83
  197. package/dist_ts/networkproxy/classes.np.types.js +0 -35
  198. package/dist_ts/networkproxy/classes.np.websockethandler.d.ts +0 -38
  199. package/dist_ts/networkproxy/classes.np.websockethandler.js +0 -188
  200. package/dist_ts/networkproxy/index.d.ts +0 -1
  201. package/dist_ts/networkproxy/index.js +0 -4
  202. package/dist_ts/nfttablesproxy/classes.nftablesproxy.d.ts +0 -219
  203. package/dist_ts/nfttablesproxy/classes.nftablesproxy.js +0 -1542
  204. package/dist_ts/port80handler/classes.port80handler.d.ts +0 -10
  205. package/dist_ts/port80handler/classes.port80handler.js +0 -16
  206. package/dist_ts/proxies/network-proxy/connection-pool.js +0 -210
  207. package/dist_ts/proxies/network-proxy/context-creator.js +0 -108
  208. package/dist_ts/proxies/network-proxy/http2-request-handler.js +0 -201
  209. package/dist_ts/proxies/network-proxy/index.js +0 -12
  210. package/dist_ts/proxies/network-proxy/models/index.d.ts +0 -4
  211. package/dist_ts/proxies/network-proxy/models/index.js +0 -5
  212. package/dist_ts/proxies/network-proxy/models/types.js +0 -276
  213. package/dist_ts/proxies/network-proxy/security-manager.js +0 -255
  214. package/dist_ts/proxies/network-proxy/simplified-certificate-bridge.d.ts +0 -48
  215. package/dist_ts/proxies/network-proxy/simplified-certificate-bridge.js +0 -76
  216. package/dist_ts/proxies/smart-proxy/connection-handler.d.ts +0 -39
  217. package/dist_ts/proxies/smart-proxy/connection-handler.js +0 -894
  218. package/dist_ts/proxies/smart-proxy/domain-config-manager.d.ts +0 -110
  219. package/dist_ts/proxies/smart-proxy/domain-config-manager.js +0 -386
  220. package/dist_ts/proxies/smart-proxy/legacy-smart-proxy.d.ts +0 -168
  221. package/dist_ts/proxies/smart-proxy/legacy-smart-proxy.js +0 -642
  222. package/dist_ts/proxies/smart-proxy/models/simplified-smartproxy-config.d.ts +0 -65
  223. package/dist_ts/proxies/smart-proxy/models/simplified-smartproxy-config.js +0 -31
  224. package/dist_ts/proxies/smart-proxy/models/smartproxy-options.d.ts +0 -102
  225. package/dist_ts/proxies/smart-proxy/models/smartproxy-options.js +0 -73
  226. package/dist_ts/proxies/smart-proxy/network-proxy-bridge.d.ts +0 -41
  227. package/dist_ts/proxies/smart-proxy/network-proxy-bridge.js +0 -121
  228. package/dist_ts/proxies/smart-proxy/port-range-manager.d.ts +0 -56
  229. package/dist_ts/proxies/smart-proxy/port-range-manager.js +0 -176
  230. package/dist_ts/proxies/smart-proxy/route-helpers/index.d.ts +0 -9
  231. package/dist_ts/proxies/smart-proxy/route-helpers/index.js +0 -11
  232. package/dist_ts/proxies/smart-proxy/route-helpers.d.ts +0 -7
  233. package/dist_ts/proxies/smart-proxy/route-helpers.js +0 -9
  234. package/dist_ts/proxies/smart-proxy/simplified-smart-proxy.d.ts +0 -41
  235. package/dist_ts/proxies/smart-proxy/simplified-smart-proxy.js +0 -132
  236. package/dist_ts/proxies/smart-proxy/utils/route-migration-utils.d.ts +0 -51
  237. package/dist_ts/proxies/smart-proxy/utils/route-migration-utils.js +0 -124
  238. package/dist_ts/redirect/classes.redirect.d.ts +0 -96
  239. package/dist_ts/redirect/classes.redirect.js +0 -194
  240. package/dist_ts/smartproxy/classes.pp.certprovisioner.d.ts +0 -54
  241. package/dist_ts/smartproxy/classes.pp.certprovisioner.js +0 -179
  242. package/dist_ts/smartproxy/classes.pp.connectionhandler.d.ts +0 -39
  243. package/dist_ts/smartproxy/classes.pp.connectionhandler.js +0 -894
  244. package/dist_ts/smartproxy/classes.pp.connectionmanager.d.ts +0 -78
  245. package/dist_ts/smartproxy/classes.pp.connectionmanager.js +0 -378
  246. package/dist_ts/smartproxy/classes.pp.domainconfigmanager.d.ts +0 -94
  247. package/dist_ts/smartproxy/classes.pp.domainconfigmanager.js +0 -255
  248. package/dist_ts/smartproxy/classes.pp.interfaces.d.ts +0 -103
  249. package/dist_ts/smartproxy/classes.pp.interfaces.js +0 -2
  250. package/dist_ts/smartproxy/classes.pp.networkproxybridge.d.ts +0 -62
  251. package/dist_ts/smartproxy/classes.pp.networkproxybridge.js +0 -316
  252. package/dist_ts/smartproxy/classes.pp.portrangemanager.d.ts +0 -56
  253. package/dist_ts/smartproxy/classes.pp.portrangemanager.js +0 -176
  254. package/dist_ts/smartproxy/classes.pp.securitymanager.d.ts +0 -64
  255. package/dist_ts/smartproxy/classes.pp.securitymanager.js +0 -149
  256. package/dist_ts/smartproxy/classes.pp.snihandler.d.ts +0 -153
  257. package/dist_ts/smartproxy/classes.pp.snihandler.js +0 -1053
  258. package/dist_ts/smartproxy/classes.pp.timeoutmanager.d.ts +0 -47
  259. package/dist_ts/smartproxy/classes.pp.timeoutmanager.js +0 -154
  260. package/dist_ts/smartproxy/classes.pp.tlsalert.d.ts +0 -149
  261. package/dist_ts/smartproxy/classes.pp.tlsalert.js +0 -225
  262. package/dist_ts/smartproxy/classes.pp.tlsmanager.d.ts +0 -57
  263. package/dist_ts/smartproxy/classes.pp.tlsmanager.js +0 -132
  264. package/dist_ts/smartproxy/classes.smartproxy.d.ts +0 -63
  265. package/dist_ts/smartproxy/classes.smartproxy.js +0 -521
  266. package/dist_ts/smartproxy/forwarding/domain-config.d.ts +0 -12
  267. package/dist_ts/smartproxy/forwarding/domain-config.js +0 -12
  268. package/dist_ts/smartproxy/forwarding/domain-manager.d.ts +0 -86
  269. package/dist_ts/smartproxy/forwarding/domain-manager.js +0 -241
  270. package/dist_ts/smartproxy/forwarding/forwarding.factory.d.ts +0 -24
  271. package/dist_ts/smartproxy/forwarding/forwarding.factory.js +0 -137
  272. package/dist_ts/smartproxy/forwarding/forwarding.handler.d.ts +0 -55
  273. package/dist_ts/smartproxy/forwarding/forwarding.handler.js +0 -94
  274. package/dist_ts/smartproxy/forwarding/http.handler.d.ts +0 -25
  275. package/dist_ts/smartproxy/forwarding/http.handler.js +0 -123
  276. package/dist_ts/smartproxy/forwarding/https-passthrough.handler.d.ts +0 -24
  277. package/dist_ts/smartproxy/forwarding/https-passthrough.handler.js +0 -154
  278. package/dist_ts/smartproxy/forwarding/https-terminate-to-http.handler.d.ts +0 -36
  279. package/dist_ts/smartproxy/forwarding/https-terminate-to-http.handler.js +0 -229
  280. package/dist_ts/smartproxy/forwarding/https-terminate-to-https.handler.d.ts +0 -35
  281. package/dist_ts/smartproxy/forwarding/https-terminate-to-https.handler.js +0 -254
  282. package/dist_ts/smartproxy/forwarding/index.d.ts +0 -16
  283. package/dist_ts/smartproxy/forwarding/index.js +0 -23
  284. package/dist_ts/smartproxy/types/forwarding.types.d.ts +0 -104
  285. package/dist_ts/smartproxy/types/forwarding.types.js +0 -50
  286. package/dist_ts/smartproxy.classes.networkproxy.d.ts +0 -31
  287. package/dist_ts/smartproxy.classes.networkproxy.js +0 -305
  288. package/dist_ts/smartproxy.classes.router.d.ts +0 -13
  289. package/dist_ts/smartproxy.classes.router.js +0 -33
  290. package/dist_ts/smartproxy.classes.sslredirect.d.ts +0 -8
  291. package/dist_ts/smartproxy.classes.sslredirect.js +0 -28
  292. package/dist_ts/smartproxy.helpers.certificates.d.ts +0 -5
  293. package/dist_ts/smartproxy.helpers.certificates.js +0 -23
  294. package/dist_ts/smartproxy.plugins.d.ts +0 -18
  295. package/dist_ts/smartproxy.plugins.js +0 -23
  296. package/dist_ts/smartproxy.portproxy.d.ts +0 -26
  297. package/dist_ts/smartproxy.portproxy.js +0 -295
  298. package/ts/http/index.ts +0 -16
  299. package/ts/http/models/http-types.ts +0 -108
  300. package/ts/http/redirects/index.ts +0 -3
  301. package/ts/proxies/network-proxy/models/index.ts +0 -4
  302. package/ts/redirect/classes.redirect.ts +0 -295
  303. /package/dist_ts/proxies/{network-proxy → http-proxy}/context-creator.d.ts +0 -0
  304. /package/dist_ts/proxies/{network-proxy → http-proxy}/function-cache.d.ts +0 -0
  305. /package/dist_ts/proxies/{network-proxy → http-proxy}/http-request-handler.d.ts +0 -0
  306. /package/dist_ts/proxies/{network-proxy → http-proxy}/http2-request-handler.d.ts +0 -0
  307. /package/dist_ts/proxies/{network-proxy → http-proxy}/security-manager.d.ts +0 -0
  308. /package/ts/proxies/{network-proxy → http-proxy}/context-creator.ts +0 -0
  309. /package/ts/proxies/{network-proxy → http-proxy}/function-cache.ts +0 -0
  310. /package/ts/proxies/{network-proxy → http-proxy}/http-request-handler.ts +0 -0
  311. /package/ts/proxies/{network-proxy → http-proxy}/http2-request-handler.ts +0 -0
  312. /package/ts/proxies/{network-proxy → http-proxy}/security-manager.ts +0 -0
  313. /package/ts/{http → routing}/router/index.ts +0 -0
@@ -1,894 +0,0 @@
1
- import * as plugins from '../../plugins.js';
2
- import { ConnectionManager } from './connection-manager.js';
3
- import { SecurityManager } from './security-manager.js';
4
- import { DomainConfigManager } from './domain-config-manager.js';
5
- import { TlsManager } from './tls-manager.js';
6
- import { NetworkProxyBridge } from './network-proxy-bridge.js';
7
- import { TimeoutManager } from './timeout-manager.js';
8
- import { PortRangeManager } from './port-range-manager.js';
9
- /**
10
- * Handles new connection processing and setup logic
11
- */
12
- export class ConnectionHandler {
13
- constructor(settings, connectionManager, securityManager, domainConfigManager, tlsManager, networkProxyBridge, timeoutManager, portRangeManager) {
14
- this.settings = settings;
15
- this.connectionManager = connectionManager;
16
- this.securityManager = securityManager;
17
- this.domainConfigManager = domainConfigManager;
18
- this.tlsManager = tlsManager;
19
- this.networkProxyBridge = networkProxyBridge;
20
- this.timeoutManager = timeoutManager;
21
- this.portRangeManager = portRangeManager;
22
- }
23
- /**
24
- * Handle a new incoming connection
25
- */
26
- handleConnection(socket) {
27
- const remoteIP = socket.remoteAddress || '';
28
- const localPort = socket.localPort || 0;
29
- // Validate IP against rate limits and connection limits
30
- const ipValidation = this.securityManager.validateIP(remoteIP);
31
- if (!ipValidation.allowed) {
32
- console.log(`Connection rejected from ${remoteIP}: ${ipValidation.reason}`);
33
- socket.end();
34
- socket.destroy();
35
- return;
36
- }
37
- // Create a new connection record
38
- const record = this.connectionManager.createConnection(socket);
39
- const connectionId = record.id;
40
- // Apply socket optimizations
41
- socket.setNoDelay(this.settings.noDelay);
42
- // Apply keep-alive settings if enabled
43
- if (this.settings.keepAlive) {
44
- socket.setKeepAlive(true, this.settings.keepAliveInitialDelay);
45
- record.hasKeepAlive = true;
46
- // Apply enhanced TCP keep-alive options if enabled
47
- if (this.settings.enableKeepAliveProbes) {
48
- try {
49
- // These are platform-specific and may not be available
50
- if ('setKeepAliveProbes' in socket) {
51
- socket.setKeepAliveProbes(10);
52
- }
53
- if ('setKeepAliveInterval' in socket) {
54
- socket.setKeepAliveInterval(1000);
55
- }
56
- }
57
- catch (err) {
58
- // Ignore errors - these are optional enhancements
59
- if (this.settings.enableDetailedLogging) {
60
- console.log(`[${connectionId}] Enhanced TCP keep-alive settings not supported: ${err}`);
61
- }
62
- }
63
- }
64
- }
65
- if (this.settings.enableDetailedLogging) {
66
- console.log(`[${connectionId}] New connection from ${remoteIP} on port ${localPort}. ` +
67
- `Keep-Alive: ${record.hasKeepAlive ? 'Enabled' : 'Disabled'}. ` +
68
- `Active connections: ${this.connectionManager.getConnectionCount()}`);
69
- }
70
- else {
71
- console.log(`New connection from ${remoteIP} on port ${localPort}. Active connections: ${this.connectionManager.getConnectionCount()}`);
72
- }
73
- // Check if this connection should be forwarded directly to NetworkProxy
74
- if (this.portRangeManager.shouldUseNetworkProxy(localPort)) {
75
- this.handleNetworkProxyConnection(socket, record);
76
- }
77
- else {
78
- // For non-NetworkProxy ports, proceed with normal processing
79
- this.handleStandardConnection(socket, record);
80
- }
81
- }
82
- /**
83
- * Handle a connection that should be forwarded to NetworkProxy
84
- */
85
- handleNetworkProxyConnection(socket, record) {
86
- const connectionId = record.id;
87
- let initialDataReceived = false;
88
- // Set an initial timeout for handshake data
89
- let initialTimeout = setTimeout(() => {
90
- if (!initialDataReceived) {
91
- console.log(`[${connectionId}] Initial data warning (${this.settings.initialDataTimeout}ms) for connection from ${record.remoteIP}`);
92
- // Add a grace period instead of immediate termination
93
- setTimeout(() => {
94
- if (!initialDataReceived) {
95
- console.log(`[${connectionId}] Final initial data timeout after grace period`);
96
- if (record.incomingTerminationReason === null) {
97
- record.incomingTerminationReason = 'initial_timeout';
98
- this.connectionManager.incrementTerminationStat('incoming', 'initial_timeout');
99
- }
100
- socket.end();
101
- this.connectionManager.cleanupConnection(record, 'initial_timeout');
102
- }
103
- }, 30000); // 30 second grace period
104
- }
105
- }, this.settings.initialDataTimeout);
106
- // Make sure timeout doesn't keep the process alive
107
- if (initialTimeout.unref) {
108
- initialTimeout.unref();
109
- }
110
- // Set up error handler
111
- socket.on('error', this.connectionManager.handleError('incoming', record));
112
- // First data handler to capture initial TLS handshake for NetworkProxy
113
- socket.once('data', (chunk) => {
114
- // Clear the initial timeout since we've received data
115
- if (initialTimeout) {
116
- clearTimeout(initialTimeout);
117
- initialTimeout = null;
118
- }
119
- initialDataReceived = true;
120
- record.hasReceivedInitialData = true;
121
- // Block non-TLS connections on port 443
122
- const localPort = record.localPort;
123
- if (!this.tlsManager.isTlsHandshake(chunk) && localPort === 443) {
124
- console.log(`[${connectionId}] Non-TLS connection detected on port 443. ` +
125
- `Terminating connection - only TLS traffic is allowed on standard HTTPS port.`);
126
- if (record.incomingTerminationReason === null) {
127
- record.incomingTerminationReason = 'non_tls_blocked';
128
- this.connectionManager.incrementTerminationStat('incoming', 'non_tls_blocked');
129
- }
130
- socket.end();
131
- this.connectionManager.cleanupConnection(record, 'non_tls_blocked');
132
- return;
133
- }
134
- // Check if this looks like a TLS handshake
135
- if (this.tlsManager.isTlsHandshake(chunk)) {
136
- record.isTLS = true;
137
- // Check for ClientHello to extract SNI - but don't enforce it for NetworkProxy
138
- if (this.tlsManager.isClientHello(chunk)) {
139
- // Create connection info for SNI extraction
140
- const connInfo = {
141
- sourceIp: record.remoteIP,
142
- sourcePort: socket.remotePort || 0,
143
- destIp: socket.localAddress || '',
144
- destPort: socket.localPort || 0,
145
- };
146
- // Extract SNI for domain-specific forwarding if available
147
- const serverName = this.tlsManager.extractSNI(chunk, connInfo);
148
- // For NetworkProxy connections, we'll allow session tickets even without SNI
149
- // We'll only use the serverName if available to determine the specific forwarding
150
- if (serverName) {
151
- // Save domain config and SNI in connection record
152
- const domainConfig = this.domainConfigManager.findDomainConfig(serverName);
153
- record.domainConfig = domainConfig;
154
- record.lockedDomain = serverName;
155
- // If we have a domain config and it has a forwarding config
156
- if (domainConfig) {
157
- try {
158
- // Get the forwarding type for this domain
159
- const forwardingType = this.domainConfigManager.getForwardingType(domainConfig);
160
- // For TLS termination types, use NetworkProxy
161
- if (forwardingType === 'https-terminate-to-http' ||
162
- forwardingType === 'https-terminate-to-https') {
163
- const networkProxyPort = this.domainConfigManager.getNetworkProxyPort(domainConfig);
164
- if (this.settings.enableDetailedLogging) {
165
- console.log(`[${connectionId}] Using TLS termination (${forwardingType}) for ${serverName} on port ${networkProxyPort}`);
166
- }
167
- // Forward to NetworkProxy with domain-specific port
168
- this.networkProxyBridge.forwardToNetworkProxy(connectionId, socket, record, chunk, networkProxyPort, (reason) => this.connectionManager.initiateCleanupOnce(record, reason));
169
- return;
170
- }
171
- // For HTTPS passthrough, use the forwarding handler directly
172
- if (forwardingType === 'https-passthrough') {
173
- const handler = this.domainConfigManager.getForwardingHandler(domainConfig);
174
- if (this.settings.enableDetailedLogging) {
175
- console.log(`[${connectionId}] Using forwarding handler for SNI passthrough to ${serverName}`);
176
- }
177
- // Handle the connection using the handler
178
- handler.handleConnection(socket);
179
- return;
180
- }
181
- // For HTTP-only, we shouldn't get TLS connections
182
- if (forwardingType === 'http-only') {
183
- console.log(`[${connectionId}] Received TLS connection for HTTP-only domain ${serverName}`);
184
- socket.end();
185
- this.connectionManager.cleanupConnection(record, 'wrong_protocol');
186
- return;
187
- }
188
- }
189
- catch (err) {
190
- console.log(`[${connectionId}] Error using forwarding handler: ${err}`);
191
- // Fall through to default NetworkProxy handling
192
- }
193
- }
194
- }
195
- else if (this.settings.allowSessionTicket === false &&
196
- this.settings.enableDetailedLogging) {
197
- // Log that we're allowing a session resumption without SNI for NetworkProxy
198
- console.log(`[${connectionId}] Allowing session resumption without SNI for NetworkProxy forwarding`);
199
- }
200
- }
201
- // Forward directly to NetworkProxy without domain-specific settings
202
- this.networkProxyBridge.forwardToNetworkProxy(connectionId, socket, record, chunk, undefined, (reason) => this.connectionManager.initiateCleanupOnce(record, reason));
203
- }
204
- else {
205
- // If not TLS, handle as plain HTTP
206
- console.log(`[${connectionId}] Non-TLS connection on NetworkProxy port ${record.localPort}`);
207
- // Check if we have a domain config based on port
208
- const portBasedDomainConfig = this.domainConfigManager.findDomainConfigForPort(record.localPort);
209
- if (portBasedDomainConfig) {
210
- try {
211
- // If this domain supports HTTP via a forwarding handler, use it
212
- if (this.domainConfigManager.supportsHttp(portBasedDomainConfig)) {
213
- const handler = this.domainConfigManager.getForwardingHandler(portBasedDomainConfig);
214
- if (this.settings.enableDetailedLogging) {
215
- console.log(`[${connectionId}] Using forwarding handler for non-TLS connection to port ${record.localPort}`);
216
- }
217
- // Handle the connection using the handler
218
- handler.handleConnection(socket);
219
- return;
220
- }
221
- }
222
- catch (err) {
223
- console.log(`[${connectionId}] Error using forwarding handler for HTTP: ${err}`);
224
- // Fall through to direct connection
225
- }
226
- }
227
- // Use legacy direct connection as fallback
228
- this.setupDirectConnection(socket, record, undefined, undefined, chunk);
229
- }
230
- });
231
- }
232
- /**
233
- * Handle a standard (non-NetworkProxy) connection
234
- */
235
- handleStandardConnection(socket, record) {
236
- const connectionId = record.id;
237
- const localPort = record.localPort;
238
- // Define helpers for rejecting connections
239
- const rejectIncomingConnection = (reason, logMessage) => {
240
- console.log(`[${connectionId}] ${logMessage}`);
241
- socket.end();
242
- if (record.incomingTerminationReason === null) {
243
- record.incomingTerminationReason = reason;
244
- this.connectionManager.incrementTerminationStat('incoming', reason);
245
- }
246
- this.connectionManager.cleanupConnection(record, reason);
247
- };
248
- let initialDataReceived = false;
249
- // Set an initial timeout for SNI data if needed
250
- let initialTimeout = null;
251
- if (this.settings.sniEnabled) {
252
- initialTimeout = setTimeout(() => {
253
- if (!initialDataReceived) {
254
- console.log(`[${connectionId}] Initial data warning (${this.settings.initialDataTimeout}ms) for connection from ${record.remoteIP}`);
255
- // Add a grace period instead of immediate termination
256
- setTimeout(() => {
257
- if (!initialDataReceived) {
258
- console.log(`[${connectionId}] Final initial data timeout after grace period`);
259
- if (record.incomingTerminationReason === null) {
260
- record.incomingTerminationReason = 'initial_timeout';
261
- this.connectionManager.incrementTerminationStat('incoming', 'initial_timeout');
262
- }
263
- socket.end();
264
- this.connectionManager.cleanupConnection(record, 'initial_timeout');
265
- }
266
- }, 30000); // 30 second grace period
267
- }
268
- }, this.settings.initialDataTimeout);
269
- // Make sure timeout doesn't keep the process alive
270
- if (initialTimeout.unref) {
271
- initialTimeout.unref();
272
- }
273
- }
274
- else {
275
- initialDataReceived = true;
276
- record.hasReceivedInitialData = true;
277
- }
278
- socket.on('error', this.connectionManager.handleError('incoming', record));
279
- // Track data for bytes counting
280
- socket.on('data', (chunk) => {
281
- record.bytesReceived += chunk.length;
282
- this.timeoutManager.updateActivity(record);
283
- // Check for TLS handshake if this is the first chunk
284
- if (!record.isTLS && this.tlsManager.isTlsHandshake(chunk)) {
285
- record.isTLS = true;
286
- if (this.settings.enableTlsDebugLogging) {
287
- console.log(`[${connectionId}] TLS handshake detected from ${record.remoteIP}, ${chunk.length} bytes`);
288
- }
289
- }
290
- });
291
- /**
292
- * Sets up the connection to the target host.
293
- */
294
- const setupConnection = (serverName, initialChunk, forcedDomain, overridePort) => {
295
- // Clear the initial timeout since we've received data
296
- if (initialTimeout) {
297
- clearTimeout(initialTimeout);
298
- initialTimeout = null;
299
- }
300
- // Mark that we've received initial data
301
- initialDataReceived = true;
302
- record.hasReceivedInitialData = true;
303
- // Check if this looks like a TLS handshake
304
- if (initialChunk && this.tlsManager.isTlsHandshake(initialChunk)) {
305
- record.isTLS = true;
306
- if (this.settings.enableTlsDebugLogging) {
307
- console.log(`[${connectionId}] TLS handshake detected in setup, ${initialChunk.length} bytes`);
308
- }
309
- }
310
- // If a forcedDomain is provided (port-based routing), use it; otherwise, use SNI-based lookup.
311
- const domainConfig = forcedDomain
312
- ? forcedDomain
313
- : serverName
314
- ? this.domainConfigManager.findDomainConfig(serverName)
315
- : undefined;
316
- // Save domain config in connection record
317
- record.domainConfig = domainConfig;
318
- // Check if this domain should use NetworkProxy (domain-specific setting)
319
- if (domainConfig &&
320
- this.domainConfigManager.shouldUseNetworkProxy(domainConfig) &&
321
- this.networkProxyBridge.getNetworkProxy()) {
322
- if (this.settings.enableDetailedLogging) {
323
- console.log(`[${connectionId}] Domain ${serverName} is configured to use NetworkProxy`);
324
- }
325
- const networkProxyPort = this.domainConfigManager.getNetworkProxyPort(domainConfig);
326
- if (initialChunk && record.isTLS) {
327
- // For TLS connections with initial chunk, forward to NetworkProxy
328
- this.networkProxyBridge.forwardToNetworkProxy(connectionId, socket, record, initialChunk, networkProxyPort, (reason) => this.connectionManager.initiateCleanupOnce(record, reason));
329
- return; // Skip normal connection setup
330
- }
331
- }
332
- // IP validation
333
- if (domainConfig) {
334
- const ipRules = this.domainConfigManager.getEffectiveIPRules(domainConfig);
335
- // Perform IP validation using security rules
336
- if (!this.securityManager.isIPAuthorized(record.remoteIP, ipRules.allowedIPs, ipRules.blockedIPs)) {
337
- return rejectIncomingConnection('rejected', `Connection rejected: IP ${record.remoteIP} not allowed for domain ${domainConfig.domains.join(', ')}`);
338
- }
339
- }
340
- else if (this.settings.defaultAllowedIPs && this.settings.defaultAllowedIPs.length > 0) {
341
- if (!this.securityManager.isIPAuthorized(record.remoteIP, this.settings.defaultAllowedIPs, this.settings.defaultBlockedIPs || [])) {
342
- return rejectIncomingConnection('rejected', `Connection rejected: IP ${record.remoteIP} not allowed by default allowed list`);
343
- }
344
- }
345
- // Save the initial SNI
346
- if (serverName) {
347
- record.lockedDomain = serverName;
348
- }
349
- // Set up the direct connection
350
- this.setupDirectConnection(socket, record, domainConfig, serverName, initialChunk, overridePort);
351
- };
352
- // --- PORT RANGE-BASED HANDLING ---
353
- // Only apply port-based rules if the incoming port is within one of the global port ranges.
354
- if (this.portRangeManager.isPortInGlobalRanges(localPort)) {
355
- if (this.portRangeManager.shouldUseGlobalForwarding(localPort)) {
356
- // Create a virtual domain config for global forwarding with security settings
357
- const globalDomainConfig = {
358
- domains: ['global'],
359
- forwarding: {
360
- type: 'http-only',
361
- target: {
362
- host: this.settings.targetIP,
363
- port: this.settings.toPort
364
- },
365
- security: {
366
- allowedIps: this.settings.defaultAllowedIPs || [],
367
- blockedIps: this.settings.defaultBlockedIPs || []
368
- }
369
- },
370
- };
371
- // Use the same IP filtering mechanism as domain-specific configs
372
- const ipRules = this.domainConfigManager.getEffectiveIPRules(globalDomainConfig);
373
- if (!this.securityManager.isIPAuthorized(record.remoteIP, ipRules.allowedIPs, ipRules.blockedIPs)) {
374
- console.log(`[${connectionId}] Connection from ${record.remoteIP} rejected: IP ${record.remoteIP} not allowed in global default allowed list.`);
375
- socket.end();
376
- return;
377
- }
378
- if (this.settings.enableDetailedLogging) {
379
- console.log(`[${connectionId}] Port-based connection from ${record.remoteIP} on port ${localPort} forwarded to global target IP ${this.settings.targetIP}.`);
380
- }
381
- setupConnection('', undefined, globalDomainConfig, localPort);
382
- return;
383
- }
384
- else {
385
- // Attempt to find a matching forced domain config based on the local port.
386
- const forcedDomain = this.domainConfigManager.findDomainConfigForPort(localPort);
387
- if (forcedDomain) {
388
- // Get effective IP rules from the domain config's forwarding security settings
389
- const ipRules = this.domainConfigManager.getEffectiveIPRules(forcedDomain);
390
- if (!this.securityManager.isIPAuthorized(record.remoteIP, ipRules.allowedIPs, ipRules.blockedIPs)) {
391
- console.log(`[${connectionId}] Connection from ${record.remoteIP} rejected: IP not allowed for domain ${forcedDomain.domains.join(', ')} on port ${localPort}.`);
392
- socket.end();
393
- return;
394
- }
395
- if (this.settings.enableDetailedLogging) {
396
- console.log(`[${connectionId}] Port-based connection from ${record.remoteIP} on port ${localPort} matched domain ${forcedDomain.domains.join(', ')}.`);
397
- }
398
- setupConnection('', undefined, forcedDomain, localPort);
399
- return;
400
- }
401
- // Fall through to SNI/default handling if no forced domain config is found.
402
- }
403
- }
404
- // --- FALLBACK: SNI-BASED HANDLING (or default when SNI is disabled) ---
405
- if (this.settings.sniEnabled) {
406
- initialDataReceived = false;
407
- socket.once('data', (chunk) => {
408
- // Clear timeout immediately
409
- if (initialTimeout) {
410
- clearTimeout(initialTimeout);
411
- initialTimeout = null;
412
- }
413
- initialDataReceived = true;
414
- // Block non-TLS connections on port 443
415
- if (!this.tlsManager.isTlsHandshake(chunk) && localPort === 443) {
416
- console.log(`[${connectionId}] Non-TLS connection detected on port 443 in SNI handler. ` +
417
- `Terminating connection - only TLS traffic is allowed on standard HTTPS port.`);
418
- if (record.incomingTerminationReason === null) {
419
- record.incomingTerminationReason = 'non_tls_blocked';
420
- this.connectionManager.incrementTerminationStat('incoming', 'non_tls_blocked');
421
- }
422
- socket.end();
423
- this.connectionManager.cleanupConnection(record, 'non_tls_blocked');
424
- return;
425
- }
426
- // Try to extract SNI
427
- let serverName = '';
428
- if (this.tlsManager.isTlsHandshake(chunk)) {
429
- record.isTLS = true;
430
- if (this.settings.enableTlsDebugLogging) {
431
- console.log(`[${connectionId}] Extracting SNI from TLS handshake, ${chunk.length} bytes`);
432
- }
433
- // Create connection info object for SNI extraction
434
- const connInfo = {
435
- sourceIp: record.remoteIP,
436
- sourcePort: socket.remotePort || 0,
437
- destIp: socket.localAddress || '',
438
- destPort: socket.localPort || 0,
439
- };
440
- // Extract SNI
441
- serverName = this.tlsManager.extractSNI(chunk, connInfo) || '';
442
- // If allowSessionTicket is false and this is a ClientHello with no SNI, terminate the connection
443
- if (this.settings.allowSessionTicket === false &&
444
- this.tlsManager.isClientHello(chunk) &&
445
- !serverName) {
446
- // Missing SNI: forward to NetworkProxy if available
447
- const proxyInstance = this.networkProxyBridge.getNetworkProxy();
448
- if (proxyInstance) {
449
- if (this.settings.enableDetailedLogging) {
450
- console.log(`[${connectionId}] No SNI in ClientHello; forwarding to NetworkProxy.`);
451
- }
452
- this.networkProxyBridge.forwardToNetworkProxy(connectionId, socket, record, chunk, undefined, (_reason) => {
453
- // On proxy failure, send TLS unrecognized_name alert and cleanup
454
- if (record.incomingTerminationReason === null) {
455
- record.incomingTerminationReason = 'session_ticket_blocked_no_sni';
456
- this.connectionManager.incrementTerminationStat('incoming', 'session_ticket_blocked_no_sni');
457
- }
458
- const alert = Buffer.from([0x15, 0x03, 0x03, 0x00, 0x02, 0x01, 0x70]);
459
- try {
460
- socket.cork();
461
- socket.write(alert);
462
- socket.uncork();
463
- socket.end();
464
- }
465
- catch {
466
- socket.end();
467
- }
468
- this.connectionManager.initiateCleanupOnce(record, 'session_ticket_blocked_no_sni');
469
- });
470
- return;
471
- }
472
- // Fallback: send TLS unrecognized_name alert and terminate
473
- console.log(`[${connectionId}] No SNI detected and proxy unavailable; sending TLS alert.`);
474
- if (record.incomingTerminationReason === null) {
475
- record.incomingTerminationReason = 'session_ticket_blocked_no_sni';
476
- this.connectionManager.incrementTerminationStat('incoming', 'session_ticket_blocked_no_sni');
477
- }
478
- const alert = Buffer.from([0x15, 0x03, 0x03, 0x00, 0x02, 0x01, 0x70]);
479
- try {
480
- socket.cork();
481
- socket.write(alert);
482
- socket.uncork();
483
- socket.end();
484
- }
485
- catch {
486
- socket.end();
487
- }
488
- this.connectionManager.cleanupConnection(record, 'session_ticket_blocked_no_sni');
489
- return;
490
- }
491
- }
492
- // Lock the connection to the negotiated SNI.
493
- record.lockedDomain = serverName;
494
- if (this.settings.enableDetailedLogging) {
495
- console.log(`[${connectionId}] Received connection from ${record.remoteIP} with SNI: ${serverName || '(empty)'}`);
496
- }
497
- setupConnection(serverName, chunk);
498
- });
499
- }
500
- else {
501
- initialDataReceived = true;
502
- record.hasReceivedInitialData = true;
503
- // Create default security settings for non-SNI connections
504
- const defaultSecurity = {
505
- allowedIPs: this.settings.defaultAllowedIPs || [],
506
- blockedIPs: this.settings.defaultBlockedIPs || []
507
- };
508
- if (defaultSecurity.allowedIPs.length > 0 &&
509
- !this.securityManager.isIPAuthorized(record.remoteIP, defaultSecurity.allowedIPs, defaultSecurity.blockedIPs)) {
510
- return rejectIncomingConnection('rejected', `Connection rejected: IP ${record.remoteIP} not allowed for non-SNI connection`);
511
- }
512
- setupConnection('');
513
- }
514
- }
515
- /**
516
- * Sets up a direct connection to the target
517
- */
518
- setupDirectConnection(socket, record, domainConfig, serverName, initialChunk, overridePort) {
519
- const connectionId = record.id;
520
- // If we have a domain config, try to use a forwarding handler
521
- if (domainConfig) {
522
- try {
523
- // Get the forwarding handler for this domain
524
- const forwardingHandler = this.domainConfigManager.getForwardingHandler(domainConfig);
525
- // Check the forwarding type to determine how to handle the connection
526
- const forwardingType = this.domainConfigManager.getForwardingType(domainConfig);
527
- // For TLS connections, handle differently based on forwarding type
528
- if (record.isTLS) {
529
- // For HTTP-only, we shouldn't get TLS connections
530
- if (forwardingType === 'http-only') {
531
- console.log(`[${connectionId}] Received TLS connection for HTTP-only domain ${serverName || 'unknown'}`);
532
- socket.end();
533
- this.connectionManager.initiateCleanupOnce(record, 'wrong_protocol');
534
- return;
535
- }
536
- // For HTTPS passthrough, use the handler's connection handling
537
- if (forwardingType === 'https-passthrough') {
538
- // If there's initial data, process it first
539
- if (initialChunk) {
540
- record.bytesReceived += initialChunk.length;
541
- }
542
- // Let the handler take over
543
- if (this.settings.enableDetailedLogging) {
544
- console.log(`[${connectionId}] Using forwarding handler for ${forwardingType} connection to ${serverName || 'unknown'}`);
545
- }
546
- // Pass the connection to the handler
547
- forwardingHandler.handleConnection(socket);
548
- // Set metadata fields
549
- record.usingNetworkProxy = false;
550
- // Add connection information to record
551
- if (serverName) {
552
- record.lockedDomain = serverName;
553
- }
554
- return;
555
- }
556
- // For TLS termination types, we'll fall through to the legacy connection setup
557
- // because NetworkProxy is used for termination
558
- }
559
- // For non-TLS connections, check if we support HTTP
560
- else if (!record.isTLS && this.domainConfigManager.supportsHttp(domainConfig)) {
561
- // For HTTP handling that the handler supports natively
562
- if (forwardingType === 'http-only' ||
563
- (forwardingType === 'https-terminate-to-http' || forwardingType === 'https-terminate-to-https')) {
564
- // If there's redirect to HTTPS configured and this is a normal HTTP connection
565
- if (this.domainConfigManager.shouldRedirectToHttps(domainConfig)) {
566
- // We'll let the handler deal with the HTTP request and potential redirect
567
- // Once an HTTP request arrives, it can redirect as needed
568
- }
569
- // Let the handler take over for HTTP handling
570
- if (this.settings.enableDetailedLogging) {
571
- console.log(`[${connectionId}] Using forwarding handler for HTTP connection to ${serverName || 'unknown'}`);
572
- }
573
- // Pass the connection to the handler
574
- forwardingHandler.handleConnection(socket);
575
- // Add connection information to record
576
- if (serverName) {
577
- record.lockedDomain = serverName;
578
- }
579
- return;
580
- }
581
- }
582
- }
583
- catch (err) {
584
- console.log(`[${connectionId}] Error using forwarding handler: ${err}`);
585
- // Fall through to legacy connection handling
586
- }
587
- }
588
- // If we get here, we'll use legacy connection handling
589
- // Determine target host
590
- const targetHost = domainConfig
591
- ? this.domainConfigManager.getTargetIP(domainConfig)
592
- : this.settings.targetIP;
593
- // Determine target port - first try forwarding config, then fallback
594
- const targetPort = domainConfig
595
- ? this.domainConfigManager.getTargetPort(domainConfig, overridePort !== undefined ? overridePort : this.settings.toPort)
596
- : (overridePort !== undefined ? overridePort : this.settings.toPort);
597
- // Setup connection options
598
- const connectionOptions = {
599
- host: targetHost,
600
- port: targetPort,
601
- };
602
- // Preserve source IP if configured
603
- if (this.settings.preserveSourceIP) {
604
- connectionOptions.localAddress = record.remoteIP.replace('::ffff:', '');
605
- }
606
- // Create a safe queue for incoming data
607
- const dataQueue = [];
608
- let queueSize = 0;
609
- let processingQueue = false;
610
- let drainPending = false;
611
- let pipingEstablished = false;
612
- // Pause the incoming socket to prevent buffer overflows
613
- socket.pause();
614
- // Function to safely process the data queue without losing events
615
- const processDataQueue = () => {
616
- if (processingQueue || dataQueue.length === 0 || pipingEstablished)
617
- return;
618
- processingQueue = true;
619
- try {
620
- // Process all queued chunks with the current active handler
621
- while (dataQueue.length > 0) {
622
- const chunk = dataQueue.shift();
623
- queueSize -= chunk.length;
624
- // Once piping is established, we shouldn't get here,
625
- // but just in case, pass to the outgoing socket directly
626
- if (pipingEstablished && record.outgoing) {
627
- record.outgoing.write(chunk);
628
- continue;
629
- }
630
- // Track bytes received
631
- record.bytesReceived += chunk.length;
632
- // Check for TLS handshake
633
- if (!record.isTLS && this.tlsManager.isTlsHandshake(chunk)) {
634
- record.isTLS = true;
635
- if (this.settings.enableTlsDebugLogging) {
636
- console.log(`[${connectionId}] TLS handshake detected in tempDataHandler, ${chunk.length} bytes`);
637
- }
638
- }
639
- // Check if adding this chunk would exceed the buffer limit
640
- const newSize = record.pendingDataSize + chunk.length;
641
- if (this.settings.maxPendingDataSize && newSize > this.settings.maxPendingDataSize) {
642
- console.log(`[${connectionId}] Buffer limit exceeded for connection from ${record.remoteIP}: ${newSize} bytes > ${this.settings.maxPendingDataSize} bytes`);
643
- socket.end(); // Gracefully close the socket
644
- this.connectionManager.initiateCleanupOnce(record, 'buffer_limit_exceeded');
645
- return;
646
- }
647
- // Buffer the chunk and update the size counter
648
- record.pendingData.push(Buffer.from(chunk));
649
- record.pendingDataSize = newSize;
650
- this.timeoutManager.updateActivity(record);
651
- }
652
- }
653
- finally {
654
- processingQueue = false;
655
- // If there's a pending drain and we've processed everything,
656
- // signal we're ready for more data if we haven't established piping yet
657
- if (drainPending && dataQueue.length === 0 && !pipingEstablished) {
658
- drainPending = false;
659
- socket.resume();
660
- }
661
- }
662
- };
663
- // Unified data handler that safely queues incoming data
664
- const safeDataHandler = (chunk) => {
665
- // If piping is already established, just let the pipe handle it
666
- if (pipingEstablished)
667
- return;
668
- // Add to our queue for orderly processing
669
- dataQueue.push(Buffer.from(chunk)); // Make a copy to be safe
670
- queueSize += chunk.length;
671
- // If queue is getting large, pause socket until we catch up
672
- if (this.settings.maxPendingDataSize && queueSize > this.settings.maxPendingDataSize * 0.8) {
673
- socket.pause();
674
- drainPending = true;
675
- }
676
- // Process the queue
677
- processDataQueue();
678
- };
679
- // Add our safe data handler
680
- socket.on('data', safeDataHandler);
681
- // Add initial chunk to pending data if present
682
- if (initialChunk) {
683
- record.bytesReceived += initialChunk.length;
684
- record.pendingData.push(Buffer.from(initialChunk));
685
- record.pendingDataSize = initialChunk.length;
686
- }
687
- // Create the target socket but don't set up piping immediately
688
- const targetSocket = plugins.net.connect(connectionOptions);
689
- record.outgoing = targetSocket;
690
- record.outgoingStartTime = Date.now();
691
- // Apply socket optimizations
692
- targetSocket.setNoDelay(this.settings.noDelay);
693
- // Apply keep-alive settings to the outgoing connection as well
694
- if (this.settings.keepAlive) {
695
- targetSocket.setKeepAlive(true, this.settings.keepAliveInitialDelay);
696
- // Apply enhanced TCP keep-alive options if enabled
697
- if (this.settings.enableKeepAliveProbes) {
698
- try {
699
- if ('setKeepAliveProbes' in targetSocket) {
700
- targetSocket.setKeepAliveProbes(10);
701
- }
702
- if ('setKeepAliveInterval' in targetSocket) {
703
- targetSocket.setKeepAliveInterval(1000);
704
- }
705
- }
706
- catch (err) {
707
- // Ignore errors - these are optional enhancements
708
- if (this.settings.enableDetailedLogging) {
709
- console.log(`[${connectionId}] Enhanced TCP keep-alive not supported for outgoing socket: ${err}`);
710
- }
711
- }
712
- }
713
- }
714
- // Setup specific error handler for connection phase
715
- targetSocket.once('error', (err) => {
716
- // This handler runs only once during the initial connection phase
717
- const code = err.code;
718
- console.log(`[${connectionId}] Connection setup error to ${targetHost}:${connectionOptions.port}: ${err.message} (${code})`);
719
- // Resume the incoming socket to prevent it from hanging
720
- socket.resume();
721
- if (code === 'ECONNREFUSED') {
722
- console.log(`[${connectionId}] Target ${targetHost}:${connectionOptions.port} refused connection`);
723
- }
724
- else if (code === 'ETIMEDOUT') {
725
- console.log(`[${connectionId}] Connection to ${targetHost}:${connectionOptions.port} timed out`);
726
- }
727
- else if (code === 'ECONNRESET') {
728
- console.log(`[${connectionId}] Connection to ${targetHost}:${connectionOptions.port} was reset`);
729
- }
730
- else if (code === 'EHOSTUNREACH') {
731
- console.log(`[${connectionId}] Host ${targetHost} is unreachable`);
732
- }
733
- // Clear any existing error handler after connection phase
734
- targetSocket.removeAllListeners('error');
735
- // Re-add the normal error handler for established connections
736
- targetSocket.on('error', this.connectionManager.handleError('outgoing', record));
737
- if (record.outgoingTerminationReason === null) {
738
- record.outgoingTerminationReason = 'connection_failed';
739
- this.connectionManager.incrementTerminationStat('outgoing', 'connection_failed');
740
- }
741
- // If we have a forwarding handler for this domain, let it handle the error
742
- if (domainConfig) {
743
- try {
744
- const forwardingHandler = this.domainConfigManager.getForwardingHandler(domainConfig);
745
- forwardingHandler.emit('connection_error', {
746
- socket,
747
- error: err,
748
- connectionId
749
- });
750
- }
751
- catch (handlerErr) {
752
- // If getting the handler fails, just log and continue with normal cleanup
753
- console.log(`Error getting forwarding handler for error handling: ${handlerErr}`);
754
- }
755
- }
756
- // Clean up the connection
757
- this.connectionManager.initiateCleanupOnce(record, `connection_failed_${code}`);
758
- });
759
- // Setup close handler
760
- targetSocket.on('close', this.connectionManager.handleClose('outgoing', record));
761
- socket.on('close', this.connectionManager.handleClose('incoming', record));
762
- // Handle timeouts with keep-alive awareness
763
- socket.on('timeout', () => {
764
- // For keep-alive connections, just log a warning instead of closing
765
- if (record.hasKeepAlive) {
766
- console.log(`[${connectionId}] Timeout event on incoming keep-alive connection from ${record.remoteIP} after ${plugins.prettyMs(this.settings.socketTimeout || 3600000)}. Connection preserved.`);
767
- return;
768
- }
769
- // For non-keep-alive connections, proceed with normal cleanup
770
- console.log(`[${connectionId}] Timeout on incoming side from ${record.remoteIP} after ${plugins.prettyMs(this.settings.socketTimeout || 3600000)}`);
771
- if (record.incomingTerminationReason === null) {
772
- record.incomingTerminationReason = 'timeout';
773
- this.connectionManager.incrementTerminationStat('incoming', 'timeout');
774
- }
775
- this.connectionManager.initiateCleanupOnce(record, 'timeout_incoming');
776
- });
777
- targetSocket.on('timeout', () => {
778
- // For keep-alive connections, just log a warning instead of closing
779
- if (record.hasKeepAlive) {
780
- console.log(`[${connectionId}] Timeout event on outgoing keep-alive connection from ${record.remoteIP} after ${plugins.prettyMs(this.settings.socketTimeout || 3600000)}. Connection preserved.`);
781
- return;
782
- }
783
- // For non-keep-alive connections, proceed with normal cleanup
784
- console.log(`[${connectionId}] Timeout on outgoing side from ${record.remoteIP} after ${plugins.prettyMs(this.settings.socketTimeout || 3600000)}`);
785
- if (record.outgoingTerminationReason === null) {
786
- record.outgoingTerminationReason = 'timeout';
787
- this.connectionManager.incrementTerminationStat('outgoing', 'timeout');
788
- }
789
- this.connectionManager.initiateCleanupOnce(record, 'timeout_outgoing');
790
- });
791
- // Apply socket timeouts
792
- this.timeoutManager.applySocketTimeouts(record);
793
- // Track outgoing data for bytes counting
794
- targetSocket.on('data', (chunk) => {
795
- record.bytesSent += chunk.length;
796
- this.timeoutManager.updateActivity(record);
797
- });
798
- // Wait for the outgoing connection to be ready before setting up piping
799
- targetSocket.once('connect', () => {
800
- // Clear the initial connection error handler
801
- targetSocket.removeAllListeners('error');
802
- // Add the normal error handler for established connections
803
- targetSocket.on('error', this.connectionManager.handleError('outgoing', record));
804
- // Process any remaining data in the queue before switching to piping
805
- processDataQueue();
806
- // Set up piping immediately
807
- pipingEstablished = true;
808
- // Flush all pending data to target
809
- if (record.pendingData.length > 0) {
810
- const combinedData = Buffer.concat(record.pendingData);
811
- if (this.settings.enableDetailedLogging) {
812
- console.log(`[${connectionId}] Forwarding ${combinedData.length} bytes of initial data to target`);
813
- }
814
- // Write pending data immediately
815
- targetSocket.write(combinedData, (err) => {
816
- if (err) {
817
- console.log(`[${connectionId}] Error writing pending data to target: ${err.message}`);
818
- return this.connectionManager.initiateCleanupOnce(record, 'write_error');
819
- }
820
- });
821
- // Clear the buffer now that we've processed it
822
- record.pendingData = [];
823
- record.pendingDataSize = 0;
824
- }
825
- // Setup piping in both directions without any delays
826
- socket.pipe(targetSocket);
827
- targetSocket.pipe(socket);
828
- // Resume the socket to ensure data flows
829
- socket.resume();
830
- // Process any data that might be queued in the interim
831
- if (dataQueue.length > 0) {
832
- // Write any remaining queued data directly to the target socket
833
- for (const chunk of dataQueue) {
834
- targetSocket.write(chunk);
835
- }
836
- // Clear the queue
837
- dataQueue.length = 0;
838
- queueSize = 0;
839
- }
840
- if (this.settings.enableDetailedLogging) {
841
- console.log(`[${connectionId}] Connection established: ${record.remoteIP} -> ${targetHost}:${connectionOptions.port}` +
842
- `${serverName
843
- ? ` (SNI: ${serverName})`
844
- : domainConfig
845
- ? ` (Port-based for domain: ${domainConfig.domains.join(', ')})`
846
- : ''}` +
847
- ` TLS: ${record.isTLS ? 'Yes' : 'No'}, Keep-Alive: ${record.hasKeepAlive ? 'Yes' : 'No'}`);
848
- }
849
- else {
850
- console.log(`Connection established: ${record.remoteIP} -> ${targetHost}:${connectionOptions.port}` +
851
- `${serverName
852
- ? ` (SNI: ${serverName})`
853
- : domainConfig
854
- ? ` (Port-based for domain: ${domainConfig.domains.join(', ')})`
855
- : ''}`);
856
- }
857
- // Add the renegotiation handler for SNI validation
858
- if (serverName) {
859
- // Create connection info object for the existing connection
860
- const connInfo = {
861
- sourceIp: record.remoteIP,
862
- sourcePort: record.incoming.remotePort || 0,
863
- destIp: record.incoming.localAddress || '',
864
- destPort: record.incoming.localPort || 0,
865
- };
866
- // Create a renegotiation handler function
867
- const renegotiationHandler = this.tlsManager.createRenegotiationHandler(connectionId, serverName, connInfo, (connectionId, reason) => this.connectionManager.initiateCleanupOnce(record, reason));
868
- // Store the handler in the connection record so we can remove it during cleanup
869
- record.renegotiationHandler = renegotiationHandler;
870
- // Add the handler to the socket
871
- socket.on('data', renegotiationHandler);
872
- if (this.settings.enableDetailedLogging) {
873
- console.log(`[${connectionId}] TLS renegotiation handler installed for SNI domain: ${serverName}`);
874
- if (this.settings.allowSessionTicket === false) {
875
- console.log(`[${connectionId}] Session ticket usage is disabled. Connection will be reset on reconnection attempts.`);
876
- }
877
- }
878
- }
879
- // Set connection timeout
880
- record.cleanupTimer = this.timeoutManager.setupConnectionTimeout(record, (record, reason) => {
881
- console.log(`[${connectionId}] Connection from ${record.remoteIP} exceeded max lifetime, forcing cleanup.`);
882
- this.connectionManager.initiateCleanupOnce(record, reason);
883
- });
884
- // Mark TLS handshake as complete for TLS connections
885
- if (record.isTLS) {
886
- record.tlsHandshakeComplete = true;
887
- if (this.settings.enableTlsDebugLogging) {
888
- console.log(`[${connectionId}] TLS handshake complete for connection from ${record.remoteIP}`);
889
- }
890
- }
891
- });
892
- }
893
- }
894
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29ubmVjdGlvbi1oYW5kbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdHMvcHJveGllcy9zbWFydC1wcm94eS9jb25uZWN0aW9uLWhhbmRsZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxrQkFBa0IsQ0FBQztBQU01QyxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUM1RCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDeEQsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDakUsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQzlDLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQy9ELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUN0RCxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUkzRDs7R0FFRztBQUNILE1BQU0sT0FBTyxpQkFBaUI7SUFDNUIsWUFDVSxRQUE0QixFQUM1QixpQkFBb0MsRUFDcEMsZUFBZ0MsRUFDaEMsbUJBQXdDLEVBQ3hDLFVBQXNCLEVBQ3RCLGtCQUFzQyxFQUN0QyxjQUE4QixFQUM5QixnQkFBa0M7UUFQbEMsYUFBUSxHQUFSLFFBQVEsQ0FBb0I7UUFDNUIsc0JBQWlCLEdBQWpCLGlCQUFpQixDQUFtQjtRQUNwQyxvQkFBZSxHQUFmLGVBQWUsQ0FBaUI7UUFDaEMsd0JBQW1CLEdBQW5CLG1CQUFtQixDQUFxQjtRQUN4QyxlQUFVLEdBQVYsVUFBVSxDQUFZO1FBQ3RCLHVCQUFrQixHQUFsQixrQkFBa0IsQ0FBb0I7UUFDdEMsbUJBQWMsR0FBZCxjQUFjLENBQWdCO1FBQzlCLHFCQUFnQixHQUFoQixnQkFBZ0IsQ0FBa0I7SUFDekMsQ0FBQztJQUVKOztPQUVHO0lBQ0ksZ0JBQWdCLENBQUMsTUFBMEI7UUFDaEQsTUFBTSxRQUFRLEdBQUcsTUFBTSxDQUFDLGFBQWEsSUFBSSxFQUFFLENBQUM7UUFDNUMsTUFBTSxTQUFTLEdBQUcsTUFBTSxDQUFDLFNBQVMsSUFBSSxDQUFDLENBQUM7UUFFeEMsd0RBQXdEO1FBQ3hELE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQy9ELElBQUksQ0FBQyxZQUFZLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDMUIsT0FBTyxDQUFDLEdBQUcsQ0FBQyw0QkFBNEIsUUFBUSxLQUFLLFlBQVksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO1lBQzVFLE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQztZQUNiLE1BQU0sQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUNqQixPQUFPO1FBQ1QsQ0FBQztRQUVELGlDQUFpQztRQUNqQyxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQUMsZ0JBQWdCLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDL0QsTUFBTSxZQUFZLEdBQUcsTUFBTSxDQUFDLEVBQUUsQ0FBQztRQUUvQiw2QkFBNkI7UUFDN0IsTUFBTSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRXpDLHVDQUF1QztRQUN2QyxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDNUIsTUFBTSxDQUFDLFlBQVksQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO1lBQy9ELE1BQU0sQ0FBQyxZQUFZLEdBQUcsSUFBSSxDQUFDO1lBRTNCLG1EQUFtRDtZQUNuRCxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMscUJBQXFCLEVBQUUsQ0FBQztnQkFDeEMsSUFBSSxDQUFDO29CQUNILHVEQUF1RDtvQkFDdkQsSUFBSSxvQkFBb0IsSUFBSSxNQUFNLEVBQUUsQ0FBQzt3QkFDbEMsTUFBYyxDQUFDLGtCQUFrQixDQUFDLEVBQUUsQ0FBQyxDQUFDO29CQUN6QyxDQUFDO29CQUNELElBQUksc0JBQXNCLElBQUksTUFBTSxFQUFFLENBQUM7d0JBQ3BDLE1BQWMsQ0FBQyxvQkFBb0IsQ0FBQyxJQUFJLENBQUMsQ0FBQztvQkFDN0MsQ0FBQztnQkFDSCxDQUFDO2dCQUFDLE9BQU8sR0FBRyxFQUFFLENBQUM7b0JBQ2Isa0RBQWtEO29CQUNsRCxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMscUJBQXFCLEVBQUUsQ0FBQzt3QkFDeEMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLFlBQVkscURBQXFELEdBQUcsRUFBRSxDQUFDLENBQUM7b0JBQzFGLENBQUM7Z0JBQ0gsQ0FBQztZQUNILENBQUM7UUFDSCxDQUFDO1FBRUQsSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLHFCQUFxQixFQUFFLENBQUM7WUFDeEMsT0FBTyxDQUFDLEdBQUcsQ0FDVCxJQUFJLFlBQVkseUJBQXlCLFFBQVEsWUFBWSxTQUFTLElBQUk7Z0JBQ3hFLGVBQWUsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxVQUFVLElBQUk7Z0JBQy9ELHVCQUF1QixJQUFJLENBQUMsaUJBQWlCLENBQUMsa0JBQWtCLEVBQUUsRUFBRSxDQUN2RSxDQUFDO1FBQ0osQ0FBQzthQUFNLENBQUM7WUFDTixPQUFPLENBQUMsR0FBRyxDQUNULHVCQUF1QixRQUFRLFlBQVksU0FBUyx5QkFBeUIsSUFBSSxDQUFDLGlCQUFpQixDQUFDLGtCQUFrQixFQUFFLEVBQUUsQ0FDM0gsQ0FBQztRQUNKLENBQUM7UUFFRCx3RUFBd0U7UUFDeEUsSUFBSSxJQUFJLENBQUMsZ0JBQWdCLENBQUMscUJBQXFCLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQztZQUMzRCxJQUFJLENBQUMsNEJBQTRCLENBQUMsTUFBTSxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQ3BELENBQUM7YUFBTSxDQUFDO1lBQ04sNkRBQTZEO1lBQzdELElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxNQUFNLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFDaEQsQ0FBQztJQUNILENBQUM7SUFFRDs7T0FFRztJQUNLLDRCQUE0QixDQUNsQyxNQUEwQixFQUMxQixNQUF5QjtRQUV6QixNQUFNLFlBQVksR0FBRyxNQUFNLENBQUMsRUFBRSxDQUFDO1FBQy9CLElBQUksbUJBQW1CLEdBQUcsS0FBSyxDQUFDO1FBRWhDLDRDQUE0QztRQUM1QyxJQUFJLGNBQWMsR0FBMEIsVUFBVSxDQUFDLEdBQUcsRUFBRTtZQUMxRCxJQUFJLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztnQkFDekIsT0FBTyxDQUFDLEdBQUcsQ0FDVCxJQUFJLFlBQVksMkJBQTJCLElBQUksQ0FBQyxRQUFRLENBQUMsa0JBQWtCLDJCQUEyQixNQUFNLENBQUMsUUFBUSxFQUFFLENBQ3hILENBQUM7Z0JBRUYsc0RBQXNEO2dCQUN0RCxVQUFVLENBQUMsR0FBRyxFQUFFO29CQUNkLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO3dCQUN6QixPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksWUFBWSxpREFBaUQsQ0FBQyxDQUFDO3dCQUMvRSxJQUFJLE1BQU0sQ0FBQyx5QkFBeUIsS0FBSyxJQUFJLEVBQUUsQ0FBQzs0QkFDOUMsTUFBTSxDQUFDLHlCQUF5QixHQUFHLGlCQUFpQixDQUFDOzRCQUNyRCxJQUFJLENBQUMsaUJBQWlCLENBQUMsd0JBQXdCLENBQUMsVUFBVSxFQUFFLGlCQUFpQixDQUFDLENBQUM7d0JBQ2pGLENBQUM7d0JBQ0QsTUFBTSxDQUFDLEdBQUcsRUFBRSxDQUFDO3dCQUNiLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxpQkFBaUIsQ0FBQyxNQUFNLEVBQUUsaUJBQWlCLENBQUMsQ0FBQztvQkFDdEUsQ0FBQztnQkFDSCxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQyx5QkFBeUI7WUFDdEMsQ0FBQztRQUNILENBQUMsRUFBRSxJQUFJLENBQUMsUUFBUSxDQUFDLGtCQUFtQixDQUFDLENBQUM7UUFFdEMsbURBQW1EO1FBQ25ELElBQUksY0FBYyxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ3pCLGNBQWMsQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUN6QixDQUFDO1FBRUQsdUJBQXVCO1FBQ3ZCLE1BQU0sQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLENBQUMsVUFBVSxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUM7UUFFM0UsdUVBQXVFO1FBQ3ZFLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUMsS0FBYSxFQUFFLEVBQUU7WUFDcEMsc0RBQXNEO1lBQ3RELElBQUksY0FBYyxFQUFFLENBQUM7Z0JBQ25CLFlBQVksQ0FBQyxjQUFjLENBQUMsQ0FBQztnQkFDN0IsY0FBYyxHQUFHLElBQUksQ0FBQztZQUN4QixDQUFDO1lBRUQsbUJBQW1CLEdBQUcsSUFBSSxDQUFDO1lBQzNCLE1BQU0sQ0FBQyxzQkFBc0IsR0FBRyxJQUFJLENBQUM7WUFFckMsd0NBQXdDO1lBQ3hDLE1BQU0sU0FBUyxHQUFHLE1BQU0sQ0FBQyxTQUFTLENBQUM7WUFDbkMsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsY0FBYyxDQUFDLEtBQUssQ0FBQyxJQUFJLFNBQVMsS0FBSyxHQUFHLEVBQUUsQ0FBQztnQkFDaEUsT0FBTyxDQUFDLEdBQUcsQ0FDVCxJQUFJLFlBQVksNkNBQTZDO29CQUMzRCw4RUFBOEUsQ0FDakYsQ0FBQztnQkFDRixJQUFJLE1BQU0sQ0FBQyx5QkFBeUIsS0FBSyxJQUFJLEVBQUUsQ0FBQztvQkFDOUMsTUFBTSxDQUFDLHlCQUF5QixHQUFHLGlCQUFpQixDQUFDO29CQUNyRCxJQUFJLENBQUMsaUJBQWlCLENBQUMsd0JBQXdCLENBQUMsVUFBVSxFQUFFLGlCQUFpQixDQUFDLENBQUM7Z0JBQ2pGLENBQUM7Z0JBQ0QsTUFBTSxDQUFDLEdBQUcsRUFBRSxDQUFDO2dCQUNiLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxpQkFBaUIsQ0FBQyxNQUFNLEVBQUUsaUJBQWlCLENBQUMsQ0FBQztnQkFDcEUsT0FBTztZQUNULENBQUM7WUFFRCwyQ0FBMkM7WUFDM0MsSUFBSSxJQUFJLENBQUMsVUFBVSxDQUFDLGNBQWMsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO2dCQUMxQyxNQUFNLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQztnQkFFcEIsK0VBQStFO2dCQUMvRSxJQUFJLElBQUksQ0FBQyxVQUFVLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7b0JBQ3pDLDRDQUE0QztvQkFDNUMsTUFBTSxRQUFRLEdBQUc7d0JBQ2YsUUFBUSxFQUFFLE1BQU0sQ0FBQyxRQUFRO3dCQUN6QixVQUFVLEVBQUUsTUFBTSxDQUFDLFVBQVUsSUFBSSxDQUFDO3dCQUNsQyxNQUFNLEVBQUUsTUFBTSxDQUFDLFlBQVksSUFBSSxFQUFFO3dCQUNqQyxRQUFRLEVBQUUsTUFBTSxDQUFDLFNBQVMsSUFBSSxDQUFDO3FCQUNoQyxDQUFDO29CQUVGLDBEQUEwRDtvQkFDMUQsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUMsS0FBSyxFQUFFLFFBQVEsQ0FBQyxDQUFDO29CQUUvRCw2RUFBNkU7b0JBQzdFLGtGQUFrRjtvQkFDbEYsSUFBSSxVQUFVLEVBQUUsQ0FBQzt3QkFDZixrREFBa0Q7d0JBQ2xELE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxnQkFBZ0IsQ0FBQyxVQUFVLENBQUMsQ0FBQzt3QkFDM0UsTUFBTSxDQUFDLFlBQVksR0FBRyxZQUFZLENBQUM7d0JBQ25DLE1BQU0sQ0FBQyxZQUFZLEdBQUcsVUFBVSxDQUFDO3dCQUVqQyw0REFBNEQ7d0JBQzVELElBQUksWUFBWSxFQUFFLENBQUM7NEJBQ2pCLElBQUksQ0FBQztnQ0FDSCwwQ0FBMEM7Z0NBQzFDLE1BQU0sY0FBYyxHQUFHLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxpQkFBaUIsQ0FBQyxZQUFZLENBQUMsQ0FBQztnQ0FFaEYsOENBQThDO2dDQUM5QyxJQUFJLGNBQWMsS0FBSyx5QkFBeUI7b0NBQzVDLGNBQWMsS0FBSywwQkFBMEIsRUFBRSxDQUFDO29DQUNsRCxNQUFNLGdCQUFnQixHQUFHLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxtQkFBbUIsQ0FBQyxZQUFZLENBQUMsQ0FBQztvQ0FFcEYsSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLHFCQUFxQixFQUFFLENBQUM7d0NBQ3hDLE9BQU8sQ0FBQyxHQUFHLENBQ1QsSUFBSSxZQUFZLDRCQUE0QixjQUFjLFNBQVMsVUFBVSxZQUFZLGdCQUFnQixFQUFFLENBQzVHLENBQUM7b0NBQ0osQ0FBQztvQ0FFRCxvREFBb0Q7b0NBQ3BELElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxxQkFBcUIsQ0FDM0MsWUFBWSxFQUNaLE1BQU0sRUFDTixNQUFNLEVBQ04sS0FBSyxFQUNMLGdCQUFnQixFQUNoQixDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLG1CQUFtQixDQUFDLE1BQU0sRUFBRSxNQUFNLENBQUMsQ0FDdkUsQ0FBQztvQ0FDRixPQUFPO2dDQUNULENBQUM7Z0NBRUQsNkRBQTZEO2dDQUM3RCxJQUFJLGNBQWMsS0FBSyxtQkFBbUIsRUFBRSxDQUFDO29DQUMzQyxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsbUJBQW1CLENBQUMsb0JBQW9CLENBQUMsWUFBWSxDQUFDLENBQUM7b0NBRTVFLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO3dDQUN4QyxPQUFPLENBQUMsR0FBRyxDQUNULElBQUksWUFBWSxxREFBcUQsVUFBVSxFQUFFLENBQ2xGLENBQUM7b0NBQ0osQ0FBQztvQ0FFRCwwQ0FBMEM7b0NBQzFDLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxNQUFNLENBQUMsQ0FBQztvQ0FFakMsT0FBTztnQ0FDVCxDQUFDO2dDQUVELGtEQUFrRDtnQ0FDbEQsSUFBSSxjQUFjLEtBQUssV0FBVyxFQUFFLENBQUM7b0NBQ25DLE9BQU8sQ0FBQyxHQUFHLENBQUMsSUFBSSxZQUFZLGtEQUFrRCxVQUFVLEVBQUUsQ0FBQyxDQUFDO29DQUM1RixNQUFNLENBQUMsR0FBRyxFQUFFLENBQUM7b0NBQ2IsSUFBSSxDQUFDLGlCQUFpQixDQUFDLGlCQUFpQixDQUFDLE1BQU0sRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDO29DQUNuRSxPQUFPO2dDQUNULENBQUM7NEJBQ0gsQ0FBQzs0QkFBQyxPQUFPLEdBQUcsRUFBRSxDQUFDO2dDQUNiLE9BQU8sQ0FBQyxHQUFHLENBQUMsSUFBSSxZQUFZLHFDQUFxQyxHQUFHLEVBQUUsQ0FBQyxDQUFDO2dDQUN4RSxnREFBZ0Q7NEJBQ2xELENBQUM7d0JBQ0gsQ0FBQztvQkFDSCxDQUFDO3lCQUFNLElBQ0wsSUFBSSxDQUFDLFFBQVEsQ0FBQyxrQkFBa0IsS0FBSyxLQUFLO3dCQUMxQyxJQUFJLENBQUMsUUFBUSxDQUFDLHFCQUFxQixFQUNuQyxDQUFDO3dCQUNELDRFQUE0RTt3QkFDNUUsT0FBTyxDQUFDLEdBQUcsQ0FDVCxJQUFJLFlBQVksdUVBQXVFLENBQ3hGLENBQUM7b0JBQ0osQ0FBQztnQkFDSCxDQUFDO2dCQUVELG9FQUFvRTtnQkFDcEUsSUFBSSxDQUFDLGtCQUFrQixDQUFDLHFCQUFxQixDQUMzQyxZQUFZLEVBQ1osTUFBTSxFQUNOLE1BQU0sRUFDTixLQUFLLEVBQ0wsU0FBUyxFQUNULENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsbUJBQW1CLENBQUMsTUFBTSxFQUFFLE1BQU0sQ0FBQyxDQUN2RSxDQUFDO1lBQ0osQ0FBQztpQkFBTSxDQUFDO2dCQUNOLG1DQUFtQztnQkFDbkMsT0FBTyxDQUFDLEdBQUcsQ0FDVCxJQUFJLFlBQVksNkNBQTZDLE1BQU0sQ0FBQyxTQUFTLEVBQUUsQ0FDaEYsQ0FBQztnQkFFRixpREFBaUQ7Z0JBQ2pELE1BQU0scUJBQXFCLEdBQUcsSUFBSSxDQUFDLG1CQUFtQixDQUFDLHVCQUF1QixDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQztnQkFFakcsSUFBSSxxQkFBcUIsRUFBRSxDQUFDO29CQUMxQixJQUFJLENBQUM7d0JBQ0gsZ0VBQWdFO3dCQUNoRSxJQUFJLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxZQUFZLENBQUMscUJBQXFCLENBQUMsRUFBRSxDQUFDOzRCQUNqRSxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsbUJBQW1CLENBQUMsb0JBQW9CLENBQUMscUJBQXFCLENBQUMsQ0FBQzs0QkFFckYsSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLHFCQUFxQixFQUFFLENBQUM7Z0NBQ3hDLE9BQU8sQ0FBQyxHQUFHLENBQ1QsSUFBSSxZQUFZLDZEQUE2RCxNQUFNLENBQUMsU0FBUyxFQUFFLENBQ2hHLENBQUM7NEJBQ0osQ0FBQzs0QkFFRCwwQ0FBMEM7NEJBQzFDLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxNQUFNLENBQUMsQ0FBQzs0QkFFakMsT0FBTzt3QkFDVCxDQUFDO29CQUNILENBQUM7b0JBQUMsT0FBTyxHQUFHLEVBQUUsQ0FBQzt3QkFDYixPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksWUFBWSw4Q0FBOEMsR0FBRyxFQUFFLENBQUMsQ0FBQzt3QkFDakYsb0NBQW9DO29CQUN0QyxDQUFDO2dCQUNILENBQUM7Z0JBRUQsMkNBQTJDO2dCQUMzQyxJQUFJLENBQUMscUJBQXFCLENBQUMsTUFBTSxFQUFFLE1BQU0sRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLEtBQUssQ0FBQyxDQUFDO1lBQzFFLENBQUM7UUFDSCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRDs7T0FFRztJQUNLLHdCQUF3QixDQUFDLE1BQTBCLEVBQUUsTUFBeUI7UUFDcEYsTUFBTSxZQUFZLEdBQUcsTUFBTSxDQUFDLEVBQUUsQ0FBQztRQUMvQixNQUFNLFNBQVMsR0FBRyxNQUFNLENBQUMsU0FBUyxDQUFDO1FBRW5DLDJDQUEyQztRQUMzQyxNQUFNLHdCQUF3QixHQUFHLENBQUMsTUFBYyxFQUFFLFVBQWtCLEVBQUUsRUFBRTtZQUN0RSxPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksWUFBWSxLQUFLLFVBQVUsRUFBRSxDQUFDLENBQUM7WUFDL0MsTUFBTSxDQUFDLEdBQUcsRUFBRSxDQUFDO1lBQ2IsSUFBSSxNQUFNLENBQUMseUJBQXlCLEtBQUssSUFBSSxFQUFFLENBQUM7Z0JBQzlDLE1BQU0sQ0FBQyx5QkFBeUIsR0FBRyxNQUFNLENBQUM7Z0JBQzFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyx3QkFBd0IsQ0FBQyxVQUFVLEVBQUUsTUFBTSxDQUFDLENBQUM7WUFDdEUsQ0FBQztZQUNELElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxpQkFBaUIsQ0FBQyxNQUFNLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFDM0QsQ0FBQyxDQUFDO1FBRUYsSUFBSSxtQkFBbUIsR0FBRyxLQUFLLENBQUM7UUFFaEMsZ0RBQWdEO1FBQ2hELElBQUksY0FBYyxHQUEwQixJQUFJLENBQUM7UUFDakQsSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQzdCLGNBQWMsR0FBRyxVQUFVLENBQUMsR0FBRyxFQUFFO2dCQUMvQixJQUFJLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztvQkFDekIsT0FBTyxDQUFDLEdBQUcsQ0FDVCxJQUFJLFlBQVksMkJBQTJCLElBQUksQ0FBQyxRQUFRLENBQUMsa0JBQWtCLDJCQUEyQixNQUFNLENBQUMsUUFBUSxFQUFFLENBQ3hILENBQUM7b0JBRUYsc0RBQXNEO29CQUN0RCxVQUFVLENBQUMsR0FBRyxFQUFFO3dCQUNkLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxDQUFDOzRCQUN6QixPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksWUFBWSxpREFBaUQsQ0FBQyxDQUFDOzRCQUMvRSxJQUFJLE1BQU0sQ0FBQyx5QkFBeUIsS0FBSyxJQUFJLEVBQUUsQ0FBQztnQ0FDOUMsTUFBTSxDQUFDLHlCQUF5QixHQUFHLGlCQUFpQixDQUFDO2dDQUNyRCxJQUFJLENBQUMsaUJBQWlCLENBQUMsd0JBQXdCLENBQUMsVUFBVSxFQUFFLGlCQUFpQixDQUFDLENBQUM7NEJBQ2pGLENBQUM7NEJBQ0QsTUFBTSxDQUFDLEdBQUcsRUFBRSxDQUFDOzRCQUNiLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxpQkFBaUIsQ0FBQyxNQUFNLEVBQUUsaUJBQWlCLENBQUMsQ0FBQzt3QkFDdEUsQ0FBQztvQkFDSCxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQyx5QkFBeUI7Z0JBQ3RDLENBQUM7WUFDSCxDQUFDLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxrQkFBbUIsQ0FBQyxDQUFDO1lBRXRDLG1EQUFtRDtZQUNuRCxJQUFJLGNBQWMsQ0FBQyxLQUFLLEVBQUUsQ0FBQztnQkFDekIsY0FBYyxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ3pCLENBQUM7UUFDSCxDQUFDO2FBQU0sQ0FBQztZQUNOLG1CQUFtQixHQUFHLElBQUksQ0FBQztZQUMzQixNQUFNLENBQUMsc0JBQXNCLEdBQUcsSUFBSSxDQUFDO1FBQ3ZDLENBQUM7UUFFRCxNQUFNLENBQUMsRUFBRSxDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsaUJBQWlCLENBQUMsV0FBVyxDQUFDLFVBQVUsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDO1FBRTNFLGdDQUFnQztRQUNoQyxNQUFNLENBQUMsRUFBRSxDQUFDLE1BQU0sRUFBRSxDQUFDLEtBQWEsRUFBRSxFQUFFO1lBQ2xDLE1BQU0sQ0FBQyxhQUFhLElBQUksS0FBSyxDQUFDLE1BQU0sQ0FBQztZQUNyQyxJQUFJLENBQUMsY0FBYyxDQUFDLGNBQWMsQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUUzQyxxREFBcUQ7WUFDckQsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLElBQUksSUFBSSxDQUFDLFVBQVUsQ0FBQyxjQUFjLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztnQkFDM0QsTUFBTSxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUM7Z0JBRXBCLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO29CQUN4QyxPQUFPLENBQUMsR0FBRyxDQUNULElBQUksWUFBWSxpQ0FBaUMsTUFBTSxDQUFDLFFBQVEsS0FBSyxLQUFLLENBQUMsTUFBTSxRQUFRLENBQzFGLENBQUM7Z0JBQ0osQ0FBQztZQUNILENBQUM7UUFDSCxDQUFDLENBQUMsQ0FBQztRQUVIOztXQUVHO1FBQ0gsTUFBTSxlQUFlLEdBQUcsQ0FDdEIsVUFBa0IsRUFDbEIsWUFBcUIsRUFDckIsWUFBNEIsRUFDNUIsWUFBcUIsRUFDckIsRUFBRTtZQUNGLHNEQUFzRDtZQUN0RCxJQUFJLGNBQWMsRUFBRSxDQUFDO2dCQUNuQixZQUFZLENBQUMsY0FBYyxDQUFDLENBQUM7Z0JBQzdCLGNBQWMsR0FBRyxJQUFJLENBQUM7WUFDeEIsQ0FBQztZQUVELHdDQUF3QztZQUN4QyxtQkFBbUIsR0FBRyxJQUFJLENBQUM7WUFDM0IsTUFBTSxDQUFDLHNCQUFzQixHQUFHLElBQUksQ0FBQztZQUVyQywyQ0FBMkM7WUFDM0MsSUFBSSxZQUFZLElBQUksSUFBSSxDQUFDLFVBQVUsQ0FBQyxjQUFjLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQztnQkFDakUsTUFBTSxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUM7Z0JBRXBCLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO29CQUN4QyxPQUFPLENBQUMsR0FBRyxDQUNULElBQUksWUFBWSxzQ0FBc0MsWUFBWSxDQUFDLE1BQU0sUUFBUSxDQUNsRixDQUFDO2dCQUNKLENBQUM7WUFDSCxDQUFDO1lBRUQsK0ZBQStGO1lBQy9GLE1BQU0sWUFBWSxHQUFHLFlBQVk7Z0JBQy9CLENBQUMsQ0FBQyxZQUFZO2dCQUNkLENBQUMsQ0FBQyxVQUFVO29CQUNaLENBQUMsQ0FBQyxJQUFJLENBQUMsbUJBQW1CLENBQUMsZ0JBQWdCLENBQUMsVUFBVSxDQUFDO29CQUN2RCxDQUFDLENBQUMsU0FBUyxDQUFDO1lBRWQsMENBQTBDO1lBQzFDLE1BQU0sQ0FBQyxZQUFZLEdBQUcsWUFBWSxDQUFDO1lBRW5DLHlFQUF5RTtZQUN6RSxJQUNFLFlBQVk7Z0JBQ1osSUFBSSxDQUFDLG1CQUFtQixDQUFDLHFCQUFxQixDQUFDLFlBQVksQ0FBQztnQkFDNUQsSUFBSSxDQUFDLGtCQUFrQixDQUFDLGVBQWUsRUFBRSxFQUN6QyxDQUFDO2dCQUNELElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO29CQUN4QyxPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksWUFBWSxZQUFZLFVBQVUsb0NBQW9DLENBQUMsQ0FBQztnQkFDMUYsQ0FBQztnQkFFRCxNQUFNLGdCQUFnQixHQUFHLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxtQkFBbUIsQ0FBQyxZQUFZLENBQUMsQ0FBQztnQkFFcEYsSUFBSSxZQUFZLElBQUksTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDO29CQUNqQyxrRUFBa0U7b0JBQ2xFLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxxQkFBcUIsQ0FDM0MsWUFBWSxFQUNaLE1BQU0sRUFDTixNQUFNLEVBQ04sWUFBWSxFQUNaLGdCQUFnQixFQUNoQixDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLG1CQUFtQixDQUFDLE1BQU0sRUFBRSxNQUFNLENBQUMsQ0FDdkUsQ0FBQztvQkFDRixPQUFPLENBQUMsK0JBQStCO2dCQUN6QyxDQUFDO1lBQ0gsQ0FBQztZQUVELGdCQUFnQjtZQUNoQixJQUFJLFlBQVksRUFBRSxDQUFDO2dCQUNqQixNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsbUJBQW1CLENBQUMsbUJBQW1CLENBQUMsWUFBWSxDQUFDLENBQUM7Z0JBRTNFLDZDQUE2QztnQkFDN0MsSUFDRSxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsY0FBYyxDQUNsQyxNQUFNLENBQUMsUUFBUSxFQUNmLE9BQU8sQ0FBQyxVQUFVLEVBQ2xCLE9BQU8sQ0FBQyxVQUFVLENBQ25CLEVBQ0QsQ0FBQztvQkFDRCxPQUFPLHdCQUF3QixDQUM3QixVQUFVLEVBQ1YsMkJBQ0UsTUFBTSxDQUFDLFFBQ1QsMkJBQTJCLFlBQVksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQzdELENBQUM7Z0JBQ0osQ0FBQztZQUNILENBQUM7aUJBQU0sSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLGlCQUFpQixJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsaUJBQWlCLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO2dCQUN6RixJQUNFLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxjQUFjLENBQ2xDLE1BQU0sQ0FBQyxRQUFRLEVBQ2YsSUFBSSxDQUFDLFFBQVEsQ0FBQyxpQkFBaUIsRUFDL0IsSUFBSSxDQUFDLFFBQVEsQ0FBQyxpQkFBaUIsSUFBSSxFQUFFLENBQ3RDLEVBQ0QsQ0FBQztvQkFDRCxPQUFPLHdCQUF3QixDQUM3QixVQUFVLEVBQ1YsMkJBQTJCLE1BQU0sQ0FBQyxRQUFRLHNDQUFzQyxDQUNqRixDQUFDO2dCQUNKLENBQUM7WUFDSCxDQUFDO1lBRUQsdUJBQXVCO1lBQ3ZCLElBQUksVUFBVSxFQUFFLENBQUM7Z0JBQ2YsTUFBTSxDQUFDLFlBQVksR0FBRyxVQUFVLENBQUM7WUFDbkMsQ0FBQztZQUVELCtCQUErQjtZQUMvQixJQUFJLENBQUMscUJBQXFCLENBQ3hCLE1BQU0sRUFDTixNQUFNLEVBQ04sWUFBWSxFQUNaLFVBQVUsRUFDVixZQUFZLEVBQ1osWUFBWSxDQUNiLENBQUM7UUFDSixDQUFDLENBQUM7UUFFRixvQ0FBb0M7UUFDcEMsNEZBQTRGO1FBQzVGLElBQUksSUFBSSxDQUFDLGdCQUFnQixDQUFDLG9CQUFvQixDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUM7WUFDMUQsSUFBSSxJQUFJLENBQUMsZ0JBQWdCLENBQUMseUJBQXlCLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQztnQkFDL0QsOEVBQThFO2dCQUM5RSxNQUFNLGtCQUFrQixHQUFHO29CQUN6QixPQUFPLEVBQUUsQ0FBQyxRQUFRLENBQUM7b0JBQ25CLFVBQVUsRUFBRTt3QkFDVixJQUFJLEVBQUUsV0FBOEI7d0JBQ3BDLE1BQU0sRUFBRTs0QkFDTixJQUFJLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFTOzRCQUM3QixJQUFJLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNO3lCQUMzQjt3QkFDRCxRQUFRLEVBQUU7NEJBQ1IsVUFBVSxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsaUJBQWlCLElBQUksRUFBRTs0QkFDakQsVUFBVSxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsaUJBQWlCLElBQUksRUFBRTt5QkFDbEQ7cUJBQ0Y7aUJBQ0YsQ0FBQztnQkFFRixpRUFBaUU7Z0JBQ2pFLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxtQkFBbUIsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO2dCQUVqRixJQUNFLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxjQUFjLENBQ2xDLE1BQU0sQ0FBQyxRQUFRLEVBQ2YsT0FBTyxDQUFDLFVBQVUsRUFDbEIsT0FBTyxDQUFDLFVBQVUsQ0FDbkIsRUFDRCxDQUFDO29CQUNELE9BQU8sQ0FBQyxHQUFHLENBQ1QsSUFBSSxZQUFZLHFCQUFxQixNQUFNLENBQUMsUUFBUSxpQkFBaUIsTUFBTSxDQUFDLFFBQVEsOENBQThDLENBQ25JLENBQUM7b0JBQ0YsTUFBTSxDQUFDLEdBQUcsRUFBRSxDQUFDO29CQUNiLE9BQU87Z0JBQ1QsQ0FBQztnQkFFRCxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMscUJBQXFCLEVBQUUsQ0FBQztvQkFDeEMsT0FBTyxDQUFDLEdBQUcsQ0FDVCxJQUFJLFlBQVksZ0NBQWdDLE1BQU0sQ0FBQyxRQUFRLFlBQVksU0FBUyxrQ0FBa0MsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLEdBQUcsQ0FDaEosQ0FBQztnQkFDSixDQUFDO2dCQUVELGVBQWUsQ0FBQyxFQUFFLEVBQUUsU0FBUyxFQUFFLGtCQUFrQixFQUFFLFNBQVMsQ0FBQyxDQUFDO2dCQUM5RCxPQUFPO1lBQ1QsQ0FBQztpQkFBTSxDQUFDO2dCQUNOLDJFQUEyRTtnQkFDM0UsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLG1CQUFtQixDQUFDLHVCQUF1QixDQUFDLFNBQVMsQ0FBQyxDQUFDO2dCQUVqRixJQUFJLFlBQVksRUFBRSxDQUFDO29CQUNqQiwrRUFBK0U7b0JBQy9FLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxtQkFBbUIsQ0FBQyxZQUFZLENBQUMsQ0FBQztvQkFFM0UsSUFDRSxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsY0FBYyxDQUNsQyxNQUFNLENBQUMsUUFBUSxFQUNmLE9BQU8sQ0FBQyxVQUFVLEVBQ2xCLE9BQU8sQ0FBQyxVQUFVLENBQ25CLEVBQ0QsQ0FBQzt3QkFDRCxPQUFPLENBQUMsR0FBRyxDQUNULElBQUksWUFBWSxxQkFDZCxNQUFNLENBQUMsUUFDVCx3Q0FBd0MsWUFBWSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQy9ELElBQUksQ0FDTCxZQUFZLFNBQVMsR0FBRyxDQUMxQixDQUFDO3dCQUNGLE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQzt3QkFDYixPQUFPO29CQUNULENBQUM7b0JBRUQsSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLHFCQUFxQixFQUFFLENBQUM7d0JBQ3hDLE9BQU8sQ0FBQyxHQUFHLENBQ1QsSUFBSSxZQUFZLGdDQUNkLE1BQU0sQ0FBQyxRQUNULFlBQVksU0FBUyxtQkFBbUIsWUFBWSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FDM0UsQ0FBQztvQkFDSixDQUFDO29CQUVELGVBQWUsQ0FBQyxFQUFFLEVBQUUsU0FBUyxFQUFFLFlBQVksRUFBRSxTQUFTLENBQUMsQ0FBQztvQkFDeEQsT0FBTztnQkFDVCxDQUFDO2dCQUNELDRFQUE0RTtZQUM5RSxDQUFDO1FBQ0gsQ0FBQztRQUVELHlFQUF5RTtRQUN6RSxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsVUFBVSxFQUFFLENBQUM7WUFDN0IsbUJBQW1CLEdBQUcsS0FBSyxDQUFDO1lBRTVCLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUMsS0FBYSxFQUFFLEVBQUU7Z0JBQ3BDLDRCQUE0QjtnQkFDNUIsSUFBSSxjQUFjLEVBQUUsQ0FBQztvQkFDbkIsWUFBWSxDQUFDLGNBQWMsQ0FBQyxDQUFDO29CQUM3QixjQUFjLEdBQUcsSUFBSSxDQUFDO2dCQUN4QixDQUFDO2dCQUVELG1CQUFtQixHQUFHLElBQUksQ0FBQztnQkFFM0Isd0NBQXdDO2dCQUN4QyxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxjQUFjLENBQUMsS0FBSyxDQUFDLElBQUksU0FBUyxLQUFLLEdBQUcsRUFBRSxDQUFDO29CQUNoRSxPQUFPLENBQUMsR0FBRyxDQUNULElBQUksWUFBWSw0REFBNEQ7d0JBQzFFLDhFQUE4RSxDQUNqRixDQUFDO29CQUNGLElBQUksTUFBTSxDQUFDLHlCQUF5QixLQUFLLElBQUksRUFBRSxDQUFDO3dCQUM5QyxNQUFNLENBQUMseUJBQXlCLEdBQUcsaUJBQWlCLENBQUM7d0JBQ3JELElBQUksQ0FBQyxpQkFBaUIsQ0FBQyx3QkFBd0IsQ0FBQyxVQUFVLEVBQUUsaUJBQWlCLENBQUMsQ0FBQztvQkFDakYsQ0FBQztvQkFDRCxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUM7b0JBQ2IsSUFBSSxDQUFDLGlCQUFpQixDQUFDLGlCQUFpQixDQUFDLE1BQU0sRUFBRSxpQkFBaUIsQ0FBQyxDQUFDO29CQUNwRSxPQUFPO2dCQUNULENBQUM7Z0JBRUQscUJBQXFCO2dCQUNyQixJQUFJLFVBQVUsR0FBRyxFQUFFLENBQUM7Z0JBRXBCLElBQUksSUFBSSxDQUFDLFVBQVUsQ0FBQyxjQUFjLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztvQkFDMUMsTUFBTSxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUM7b0JBRXBCLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO3dCQUN4QyxPQUFPLENBQUMsR0FBRyxDQUNULElBQUksWUFBWSx3Q0FBd0MsS0FBSyxDQUFDLE1BQU0sUUFBUSxDQUM3RSxDQUFDO29CQUNKLENBQUM7b0JBRUQsbURBQW1EO29CQUNuRCxNQUFNLFFBQVEsR0FBRzt3QkFDZixRQUFRLEVBQUUsTUFBTSxDQUFDLFFBQVE7d0JBQ3pCLFVBQVUsRUFBRSxNQUFNLENBQUMsVUFBVSxJQUFJLENBQUM7d0JBQ2xDLE1BQU0sRUFBRSxNQUFNLENBQUMsWUFBWSxJQUFJLEVBQUU7d0JBQ2pDLFFBQVEsRUFBRSxNQUFNLENBQUMsU0FBUyxJQUFJLENBQUM7cUJBQ2hDLENBQUM7b0JBRUYsY0FBYztvQkFDZCxVQUFVLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUMsS0FBSyxFQUFFLFFBQVEsQ0FBQyxJQUFJLEVBQUUsQ0FBQztvQkFFL0QsaUdBQWlHO29CQUNqRyxJQUNFLElBQUksQ0FBQyxRQUFRLENBQUMsa0JBQWtCLEtBQUssS0FBSzt3QkFDMUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDO3dCQUNwQyxDQUFDLFVBQVUsRUFDWCxDQUFDO3dCQUNELG9EQUFvRDt3QkFDcEQsTUFBTSxhQUFhLEdBQUcsSUFBSSxDQUFDLGtCQUFrQixDQUFDLGVBQWUsRUFBRSxDQUFDO3dCQUNoRSxJQUFJLGFBQWEsRUFBRSxDQUFDOzRCQUNsQixJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMscUJBQXFCLEVBQUUsQ0FBQztnQ0FDeEMsT0FBTyxDQUFDLEdBQUcsQ0FDVCxJQUFJLFlBQVksc0RBQXNELENBQ3ZFLENBQUM7NEJBQ0osQ0FBQzs0QkFDSCxJQUFJLENBQUMsa0JBQWtCLENBQUMscUJBQXFCLENBQzNDLFlBQVksRUFDWixNQUFNLEVBQ04sTUFBTSxFQUNOLEtBQUssRUFDTCxTQUFTLEVBQ1QsQ0FBQyxPQUFPLEVBQUUsRUFBRTtnQ0FDVixpRUFBaUU7Z0NBQ2pFLElBQUksTUFBTSxDQUFDLHlCQUF5QixLQUFLLElBQUksRUFBRSxDQUFDO29DQUM5QyxNQUFNLENBQUMseUJBQXlCLEdBQUcsK0JBQStCLENBQUM7b0NBQ25FLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyx3QkFBd0IsQ0FDN0MsVUFBVSxFQUNWLCtCQUErQixDQUNoQyxDQUFDO2dDQUNKLENBQUM7Z0NBQ0QsTUFBTSxLQUFLLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUM7Z0NBQ3RFLElBQUksQ0FBQztvQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLENBQUM7b0NBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQztvQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFLENBQUM7b0NBQUMsTUFBTSxDQUFDLEdBQUcsRUFBRSxDQUFDO2dDQUFDLENBQUM7Z0NBQzFFLE1BQU0sQ0FBQztvQ0FBQyxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUM7Z0NBQUMsQ0FBQztnQ0FDdkIsSUFBSSxDQUFDLGlCQUFpQixDQUFDLG1CQUFtQixDQUFDLE1BQU0sRUFBRSwrQkFBK0IsQ0FBQyxDQUFDOzRCQUN0RixDQUFDLENBQ0YsQ0FBQzs0QkFDQSxPQUFPO3dCQUNULENBQUM7d0JBQ0QsMkRBQTJEO3dCQUMzRCxPQUFPLENBQUMsR0FBRyxDQUNULElBQUksWUFBWSw2REFBNkQsQ0FDOUUsQ0FBQzt3QkFDRixJQUFJLE1BQU0sQ0FBQyx5QkFBeUIsS0FBSyxJQUFJLEVBQUUsQ0FBQzs0QkFDOUMsTUFBTSxDQUFDLHlCQUF5QixHQUFHLCtCQUErQixDQUFDOzRCQUNuRSxJQUFJLENBQUMsaUJBQWlCLENBQUMsd0JBQXdCLENBQzdDLFVBQVUsRUFDViwrQkFBK0IsQ0FDaEMsQ0FBQzt3QkFDSixDQUFDO3dCQUNELE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDO3dCQUN0RSxJQUFJLENBQUM7NEJBQUMsTUFBTSxDQUFDLElBQUksRUFBRSxDQUFDOzRCQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUM7NEJBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxDQUFDOzRCQUFDLE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQzt3QkFBQyxDQUFDO3dCQUMxRSxNQUFNLENBQUM7NEJBQUMsTUFBTSxDQUFDLEdBQUcsRUFBRSxDQUFDO3dCQUFDLENBQUM7d0JBQ3ZCLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxpQkFBaUIsQ0FBQyxNQUFNLEVBQUUsK0JBQStCLENBQUMsQ0FBQzt3QkFDbEYsT0FBTztvQkFDVCxDQUFDO2dCQUNILENBQUM7Z0JBRUQsNkNBQTZDO2dCQUM3QyxNQUFNLENBQUMsWUFBWSxHQUFHLFVBQVUsQ0FBQztnQkFFakMsSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLHFCQUFxQixFQUFFLENBQUM7b0JBQ3hDLE9BQU8sQ0FBQyxHQUFHLENBQ1QsSUFBSSxZQUFZLDhCQUE4QixNQUFNLENBQUMsUUFBUSxjQUMzRCxVQUFVLElBQUksU0FDaEIsRUFBRSxDQUNILENBQUM7Z0JBQ0osQ0FBQztnQkFFRCxlQUFlLENBQUMsVUFBVSxFQUFFLEtBQUssQ0FBQyxDQUFDO1lBQ3JDLENBQUMsQ0FBQyxDQUFDO1FBQ0wsQ0FBQzthQUFNLENBQUM7WUFDTixtQkFBbUIsR0FBRyxJQUFJLENBQUM7WUFDM0IsTUFBTSxDQUFDLHNCQUFzQixHQUFHLElBQUksQ0FBQztZQUVyQywyREFBMkQ7WUFDM0QsTUFBTSxlQUFlLEdBQUc7Z0JBQ3RCLFVBQVUsRUFBRSxJQUFJLENBQUMsUUFBUSxDQUFDLGlCQUFpQixJQUFJLEVBQUU7Z0JBQ2pELFVBQVUsRUFBRSxJQUFJLENBQUMsUUFBUSxDQUFDLGlCQUFpQixJQUFJLEVBQUU7YUFDbEQsQ0FBQztZQUVGLElBQUksZUFBZSxDQUFDLFVBQVUsQ0FBQyxNQUFNLEdBQUcsQ0FBQztnQkFDckMsQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLGNBQWMsQ0FDbEMsTUFBTSxDQUFDLFFBQVEsRUFDZixlQUFlLENBQUMsVUFBVSxFQUMxQixlQUFlLENBQUMsVUFBVSxDQUMzQixFQUNILENBQUM7Z0JBQ0QsT0FBTyx3QkFBd0IsQ0FDN0IsVUFBVSxFQUNWLDJCQUEyQixNQUFNLENBQUMsUUFBUSxxQ0FBcUMsQ0FDaEYsQ0FBQztZQUNKLENBQUM7WUFFRCxlQUFlLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDdEIsQ0FBQztJQUNILENBQUM7SUFFRDs7T0FFRztJQUNLLHFCQUFxQixDQUMzQixNQUEwQixFQUMxQixNQUF5QixFQUN6QixZQUE0QixFQUM1QixVQUFtQixFQUNuQixZQUFxQixFQUNyQixZQUFxQjtRQUVyQixNQUFNLFlBQVksR0FBRyxNQUFNLENBQUMsRUFBRSxDQUFDO1FBRS9CLDhEQUE4RDtRQUM5RCxJQUFJLFlBQVksRUFBRSxDQUFDO1lBQ2pCLElBQUksQ0FBQztnQkFDSCw2Q0FBNkM7Z0JBQzdDLE1BQU0saUJBQWlCLEdBQUcsSUFBSSxDQUFDLG1CQUFtQixDQUFDLG9CQUFvQixDQUFDLFlBQVksQ0FBQyxDQUFDO2dCQUV0RixzRUFBc0U7Z0JBQ3RFLE1BQU0sY0FBYyxHQUFHLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxpQkFBaUIsQ0FBQyxZQUFZLENBQUMsQ0FBQztnQkFFaEYsbUVBQW1FO2dCQUNuRSxJQUFJLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQztvQkFDakIsa0RBQWtEO29CQUNsRCxJQUFJLGNBQWMsS0FBSyxXQUFXLEVBQUUsQ0FBQzt3QkFDbkMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLFlBQVksa0RBQWtELFVBQVUsSUFBSSxTQUFTLEVBQUUsQ0FBQyxDQUFDO3dCQUN6RyxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUM7d0JBQ2IsSUFBSSxDQUFDLGlCQUFpQixDQUFDLG1CQUFtQixDQUFDLE1BQU0sRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDO3dCQUNyRSxPQUFPO29CQUNULENBQUM7b0JBRUQsK0RBQStEO29CQUMvRCxJQUFJLGNBQWMsS0FBSyxtQkFBbUIsRUFBRSxDQUFDO3dCQUMzQyw0Q0FBNEM7d0JBQzVDLElBQUksWUFBWSxFQUFFLENBQUM7NEJBQ2pCLE1BQU0sQ0FBQyxhQUFhLElBQUksWUFBWSxDQUFDLE1BQU0sQ0FBQzt3QkFDOUMsQ0FBQzt3QkFFRCw0QkFBNEI7d0JBQzVCLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxxQkFBcUIsRUFBRSxDQUFDOzRCQUN4QyxPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksWUFBWSxrQ0FBa0MsY0FBYyxrQkFBa0IsVUFBVSxJQUFJLFNBQVMsRUFBRSxDQUFDLENBQUM7d0JBQzNILENBQUM7d0JBRUQscUNBQXFDO3dCQUNyQyxpQkFBaUIsQ0FBQyxnQkFBZ0IsQ0FBQyxNQUFNLENBQUMsQ0FBQzt3QkFFM0Msc0JBQXNCO3dCQUN0QixNQUFNLENBQUMsaUJBQWlCLEdBQUcsS0FBSyxDQUFDO3dCQUVqQyx1Q0FBdUM7d0JBQ3ZDLElBQUksVUFBVSxFQUFFLENBQUM7NEJBQ2YsTUFBTSxDQUFDLFlBQVksR0FBRyxVQUFVLENBQUM7d0JBQ25DLENBQUM7d0JBRUQsT0FBTztvQkFDVCxDQUFDO29CQUVELCtFQUErRTtvQkFDL0UsK0NBQStDO2dCQUNqRCxDQUFDO2dCQUNELG9EQUFvRDtxQkFDL0MsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLElBQUksSUFBSSxDQUFDLG1CQUFtQixDQUFDLFlBQVksQ0FBQyxZQUFZLENBQUMsRUFBRSxDQUFDO29CQUM5RSx1REFBdUQ7b0JBQ3ZELElBQUksY0FBYyxLQUFLLFdBQVc7d0JBQzlCLENBQUMsY0FBYyxLQUFLLHlCQUF5QixJQUFJLGNBQWMsS0FBSywwQkFBMEIsQ0FBQyxFQUFFLENBQUM7d0JBRXBHLCtFQUErRTt3QkFDL0UsSUFBSSxJQUFJLENBQUMsbUJBQW1CLENBQUMscUJBQXFCLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQzs0QkFDakUsMEVBQTBFOzRCQUMxRSwwREFBMEQ7d0JBQzVELENBQUM7d0JBRUQsOENBQThDO3dCQUM5QyxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMscUJBQXFCLEVBQUUsQ0FBQzs0QkFDeEMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLFlBQVkscURBQXFELFVBQVUsSUFBSSxTQUFTLEVBQUUsQ0FBQyxDQUFDO3dCQUM5RyxDQUFDO3dCQUVELHFDQUFxQzt3QkFDckMsaUJBQWlCLENBQUMsZ0JBQWdCLENBQUMsTUFBTSxDQUFDLENBQUM7d0JBRTNDLHVDQUF1Qzt3QkFDdkMsSUFBSSxVQUFVLEVBQUUsQ0FBQzs0QkFDZixNQUFNLENBQUMsWUFBWSxHQUFHLFVBQVUsQ0FBQzt3QkFDbkMsQ0FBQzt3QkFFRCxPQUFPO29CQUNULENBQUM7Z0JBQ0gsQ0FBQztZQUNILENBQUM7WUFBQyxPQUFPLEdBQUcsRUFBRSxDQUFDO2dCQUNiLE9BQU8sQ0FBQyxHQUFHLENBQUMsSUFBSSxZQUFZLHFDQUFxQyxHQUFHLEVBQUUsQ0FBQyxDQUFDO2dCQUN4RSw2Q0FBNkM7WUFDL0MsQ0FBQztRQUNILENBQUM7UUFFRCx1REFBdUQ7UUFFdkQsd0JBQXdCO1FBQ3hCLE1BQU0sVUFBVSxHQUFHLFlBQVk7WUFDN0IsQ0FBQyxDQUFDLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxXQUFXLENBQUMsWUFBWSxDQUFDO1lBQ3BELENBQUMsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVMsQ0FBQztRQUU1QixxRUFBcUU7UUFDckUsTUFBTSxVQUFVLEdBQUcsWUFBWTtZQUM3QixDQUFDLENBQUMsSUFBSSxDQUFDLG1CQUFtQixDQUFDLGFBQWEsQ0FBQyxZQUFZLEVBQUUsWUFBWSxLQUFLLFNBQVMsQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQztZQUN4SCxDQUFDLENBQUMsQ0FBQyxZQUFZLEtBQUssU0FBUyxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUM7UUFFdkUsMkJBQTJCO1FBQzNCLE1BQU0saUJBQWlCLEdBQStCO1lBQ3BELElBQUksRUFBRSxVQUFVO1lBQ2hCLElBQUksRUFBRSxVQUFVO1NBQ2pCLENBQUM7UUFFRixtQ0FBbUM7UUFDbkMsSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLGdCQUFnQixFQUFFLENBQUM7WUFDbkMsaUJBQWlCLENBQUMsWUFBWSxHQUFHLE1BQU0sQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLFNBQVMsRUFBRSxFQUFFLENBQUMsQ0FBQztRQUMxRSxDQUFDO1FBRUQsd0NBQXdDO1FBQ3hDLE1BQU0sU0FBUyxHQUFhLEVBQUUsQ0FBQztRQUMvQixJQUFJLFNBQVMsR0FBRyxDQUFDLENBQUM7UUFDbEIsSUFBSSxlQUFlLEdBQUcsS0FBSyxDQUFDO1FBQzVCLElBQUksWUFBWSxHQUFHLEtBQUssQ0FBQztRQUN6QixJQUFJLGlCQUFpQixHQUFHLEtBQUssQ0FBQztRQUU5Qix3REFBd0Q7UUFDeEQsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBRWYsa0VBQWtFO1FBQ2xFLE1BQU0sZ0JBQWdCLEdBQUcsR0FBRyxFQUFFO1lBQzVCLElBQUksZUFBZSxJQUFJLFNBQVMsQ0FBQyxNQUFNLEtBQUssQ0FBQyxJQUFJLGlCQUFpQjtnQkFBRSxPQUFPO1lBRTNFLGVBQWUsR0FBRyxJQUFJLENBQUM7WUFFdkIsSUFBSSxDQUFDO2dCQUNILDREQUE0RDtnQkFDNUQsT0FBTyxTQUFTLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO29CQUM1QixNQUFNLEtBQUssR0FBRyxTQUFTLENBQUMsS0FBSyxFQUFHLENBQUM7b0JBQ2pDLFNBQVMsSUFBSSxLQUFLLENBQUMsTUFBTSxDQUFDO29CQUUxQixxREFBcUQ7b0JBQ3JELHlEQUF5RDtvQkFDekQsSUFBSSxpQkFBaUIsSUFBSSxNQUFNLENBQUMsUUFBUSxFQUFFLENBQUM7d0JBQ3pDLE1BQU0sQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO3dCQUM3QixTQUFTO29CQUNYLENBQUM7b0JBRUQsdUJBQXVCO29CQUN2QixNQUFNLENBQUMsYUFBYSxJQUFJLEtBQUssQ0FBQyxNQUFNLENBQUM7b0JBRXJDLDBCQUEwQjtvQkFDMUIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLElBQUksSUFBSSxDQUFDLFVBQVUsQ0FBQyxjQUFjLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQzt3QkFDM0QsTUFBTSxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUM7d0JBRXBCLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxxQkFBcUIsRUFBRSxDQUFDOzRCQUN4QyxPQUFPLENBQUMsR0FBRyxDQUNULElBQUksWUFBWSxnREFBZ0QsS0FBSyxDQUFDLE1BQU0sUUFBUSxDQUNyRixDQUFDO3dCQUNKLENBQUM7b0JBQ0gsQ0FBQztvQkFFRCwyREFBMkQ7b0JBQzNELE1BQU0sT0FBTyxHQUFHLE1BQU0sQ0FBQyxlQUFlLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQztvQkFFdEQsSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLGtCQUFrQixJQUFJLE9BQU8sR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLGtCQUFrQixFQUFFLENBQUM7d0JBQ25GLE9BQU8sQ0FBQyxHQUFHLENBQ1QsSUFBSSxZQUFZLCtDQUErQyxNQUFNLENBQUMsUUFBUSxLQUFLLE9BQU8sWUFBWSxJQUFJLENBQUMsUUFBUSxDQUFDLGtCQUFrQixRQUFRLENBQy9JLENBQUM7d0JBQ0YsTUFBTSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsOEJBQThCO3dCQUM1QyxJQUFJLENBQUMsaUJBQWlCLENBQUMsbUJBQW1CLENBQUMsTUFBTSxFQUFFLHVCQUF1QixDQUFDLENBQUM7d0JBQzVFLE9BQU87b0JBQ1QsQ0FBQztvQkFFRCwrQ0FBK0M7b0JBQy9DLE1BQU0sQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztvQkFDNUMsTUFBTSxDQUFDLGVBQWUsR0FBRyxPQUFPLENBQUM7b0JBQ2pDLElBQUksQ0FBQyxjQUFjLENBQUMsY0FBYyxDQUFDLE1BQU0sQ0FBQyxDQUFDO2dCQUM3QyxDQUFDO1lBQ0gsQ0FBQztvQkFBUyxDQUFDO2dCQUNULGVBQWUsR0FBRyxLQUFLLENBQUM7Z0JBRXhCLDZEQUE2RDtnQkFDN0Qsd0VBQXdFO2dCQUN4RSxJQUFJLFlBQVksSUFBSSxTQUFTLENBQUMsTUFBTSxLQUFLLENBQUMsSUFBSSxDQUFDLGlCQUFpQixFQUFFLENBQUM7b0JBQ2pFLFlBQVksR0FBRyxLQUFLLENBQUM7b0JBQ3JCLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQztnQkFDbEIsQ0FBQztZQUNILENBQUM7UUFDSCxDQUFDLENBQUM7UUFFRix3REFBd0Q7UUFDeEQsTUFBTSxlQUFlLEdBQUcsQ0FBQyxLQUFhLEVBQUUsRUFBRTtZQUN4QyxnRUFBZ0U7WUFDaEUsSUFBSSxpQkFBaUI7Z0JBQUUsT0FBTztZQUU5QiwwQ0FBMEM7WUFDMUMsU0FBUyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyx5QkFBeUI7WUFDN0QsU0FBUyxJQUFJLEtBQUssQ0FBQyxNQUFNLENBQUM7WUFFMUIsNERBQTREO1lBQzVELElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxrQkFBa0IsSUFBSSxTQUFTLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxrQkFBa0IsR0FBRyxHQUFHLEVBQUUsQ0FBQztnQkFDM0YsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDO2dCQUNmLFlBQVksR0FBRyxJQUFJLENBQUM7WUFDdEIsQ0FBQztZQUVELG9CQUFvQjtZQUNwQixnQkFBZ0IsRUFBRSxDQUFDO1FBQ3JCLENBQUMsQ0FBQztRQUVGLDRCQUE0QjtRQUM1QixNQUFNLENBQUMsRUFBRSxDQUFDLE1BQU0sRUFBRSxlQUFlLENBQUMsQ0FBQztRQUVuQywrQ0FBK0M7UUFDL0MsSUFBSSxZQUFZLEVBQUUsQ0FBQztZQUNqQixNQUFNLENBQUMsYUFBYSxJQUFJLFlBQVksQ0FBQyxNQUFNLENBQUM7WUFDNUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDO1lBQ25ELE1BQU0sQ0FBQyxlQUFlLEdBQUcsWUFBWSxDQUFDLE1BQU0sQ0FBQztRQUMvQyxDQUFDO1FBRUQsK0RBQStEO1FBQy9ELE1BQU0sWUFBWSxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLGlCQUFpQixDQUFDLENBQUM7UUFDNUQsTUFBTSxDQUFDLFFBQVEsR0FBRyxZQUFZLENBQUM7UUFDL0IsTUFBTSxDQUFDLGlCQUFpQixHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUV0Qyw2QkFBNkI7UUFDN0IsWUFBWSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRS9DLCtEQUErRDtRQUMvRCxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDNUIsWUFBWSxDQUFDLFlBQVksQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO1lBRXJFLG1EQUFtRDtZQUNuRCxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMscUJBQXFCLEVBQUUsQ0FBQztnQkFDeEMsSUFBSSxDQUFDO29CQUNILElBQUksb0JBQW9CLElBQUksWUFBWSxFQUFFLENBQUM7d0JBQ3hDLFlBQW9CLENBQUMsa0JBQWtCLENBQUMsRUFBRSxDQUFDLENBQUM7b0JBQy9DLENBQUM7b0JBQ0QsSUFBSSxzQkFBc0IsSUFBSSxZQUFZLEVBQUUsQ0FBQzt3QkFDMUMsWUFBb0IsQ0FBQyxvQkFBb0IsQ0FBQyxJQUFJLENBQUMsQ0FBQztvQkFDbkQsQ0FBQztnQkFDSCxDQUFDO2dCQUFDLE9BQU8sR0FBRyxFQUFFLENBQUM7b0JBQ2Isa0RBQWtEO29CQUNsRCxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMscUJBQXFCLEVBQUUsQ0FBQzt3QkFDeEMsT0FBTyxDQUFDLEdBQUcsQ0FDVCxJQUFJLFlBQVksZ0VBQWdFLEdBQUcsRUFBRSxDQUN0RixDQUFDO29CQUNKLENBQUM7Z0JBQ0gsQ0FBQztZQUNILENBQUM7UUFDSCxDQUFDO1FBRUQsb0RBQW9EO1FBQ3BELFlBQVksQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUMsR0FBRyxFQUFFLEVBQUU7WUFDakMsa0VBQWtFO1lBQ2xFLE1BQU0sSUFBSSxHQUFJLEdBQVcsQ0FBQyxJQUFJLENBQUM7WUFDL0IsT0FBTyxDQUFDLEdBQUcsQ0FDVCxJQUFJLFlBQVksK0JBQStCLFVBQVUsSUFBSSxpQkFBaUIsQ0FBQyxJQUFJLEtBQUssR0FBRyxDQUFDLE9BQU8sS0FBSyxJQUFJLEdBQUcsQ0FDaEgsQ0FBQztZQUVGLHdEQUF3RDtZQUN4RCxNQUFNLENBQUMsTUFBTSxFQUFFLENBQUM7WUFFaEIsSUFBSSxJQUFJLEtBQUssY0FBYyxFQUFFLENBQUM7Z0JBQzVCLE9BQU8sQ0FBQyxHQUFHLENBQ1QsSUFBSSxZQUFZLFlBQVksVUFBVSxJQUFJLGlCQUFpQixDQUFDLElBQUkscUJBQXFCLENBQ3RGLENBQUM7WUFDSixDQUFDO2lCQUFNLElBQUksSUFBSSxLQUFLLFdBQVcsRUFBRSxDQUFDO2dCQUNoQyxPQUFPLENBQUMsR0FBRyxDQUNULElBQUksWUFBWSxtQkFBbUIsVUFBVSxJQUFJLGlCQUFpQixDQUFDLElBQUksWUFBWSxDQUNwRixDQUFDO1lBQ0osQ0FBQztpQkFBTSxJQUFJLElBQUksS0FBSyxZQUFZLEVBQUUsQ0FBQztnQkFDakMsT0FBTyxDQUFDLEdBQUcsQ0FDVCxJQUFJLFlBQVksbUJBQW1CLFVBQVUsSUFBSSxpQkFBaUIsQ0FBQyxJQUFJLFlBQVksQ0FDcEYsQ0FBQztZQUNKLENBQUM7aUJBQU0sSUFBSSxJQUFJLEtBQUssY0FBYyxFQUFFLENBQUM7Z0JBQ25DLE9BQU8sQ0FBQyxHQUFHLENBQUMsSUFBSSxZQUFZLFVBQVUsVUFBVSxpQkFBaUIsQ0FBQyxDQUFDO1lBQ3JFLENBQUM7WUFFRCwwREFBMEQ7WUFDMUQsWUFBWSxDQUFDLGtCQUFrQixDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBRXpDLDhEQUE4RDtZQUM5RCxZQUFZLENBQUMsRUFBRSxDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsaUJBQWlCLENBQUMsV0FBVyxDQUFDLFVBQVUsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDO1lBRWpGLElBQUksTUFBTSxDQUFDLHlCQUF5QixLQUFLLElBQUksRUFBRSxDQUFDO2dCQUM5QyxNQUFNLENBQUMseUJBQXlCLEdBQUcsbUJBQW1CLENBQUM7Z0JBQ3ZELElBQUksQ0FBQyxpQkFBaUIsQ0FBQyx3QkFBd0IsQ0FBQyxVQUFVLEVBQUUsbUJBQW1CLENBQUMsQ0FBQztZQUNuRixDQUFDO1lBRUQsMkVBQTJFO1lBQzNFLElBQUksWUFBWSxFQUFFLENBQUM7Z0JBQ2pCLElBQUksQ0FBQztvQkFDSCxNQUFNLGlCQUFpQixHQUFHLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxvQkFBb0IsQ0FBQyxZQUFZLENBQUMsQ0FBQztvQkFDdEYsaUJBQWlCLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO3dCQUN6QyxNQUFNO3dCQUNOLEtBQUssRUFBRSxHQUFHO3dCQUNWLFlBQVk7cUJBQ2IsQ0FBQyxDQUFDO2dCQUNMLENBQUM7Z0JBQUMsT0FBTyxVQUFVLEVBQUUsQ0FBQztvQkFDcEIsMEVBQTBFO29CQUMxRSxPQUFPLENBQUMsR0FBRyxDQUFDLHdEQUF3RCxVQUFVLEVBQUUsQ0FBQyxDQUFDO2dCQUNwRixDQUFDO1lBQ0gsQ0FBQztZQUVELDBCQUEwQjtZQUMxQixJQUFJLENBQUMsaUJBQWlCLENBQUMsbUJBQW1CLENBQUMsTUFBTSxFQUFFLHFCQUFxQixJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQ2xGLENBQUMsQ0FBQyxDQUFDO1FBRUgsc0JBQXNCO1FBQ3RCLFlBQVksQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLENBQUMsVUFBVSxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUM7UUFDakYsTUFBTSxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLGlCQUFpQixDQUFDLFdBQVcsQ0FBQyxVQUFVLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQztRQUUzRSw0Q0FBNEM7UUFDNUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxTQUFTLEVBQUUsR0FBRyxFQUFFO1lBQ3hCLG9FQUFvRTtZQUNwRSxJQUFJLE1BQU0sQ0FBQyxZQUFZLEVBQUUsQ0FBQztnQkFDeEIsT0FBTyxDQUFDLEdBQUcsQ0FDVCxJQUFJLFlBQVksMERBQ2QsTUFBTSxDQUFDLFFBQ1QsVUFBVSxPQUFPLENBQUMsUUFBUSxDQUN4QixJQUFJLENBQUMsUUFBUSxDQUFDLGFBQWEsSUFBSSxPQUFPLENBQ3ZDLHlCQUF5QixDQUMzQixDQUFDO2dCQUNGLE9BQU87WUFDVCxDQUFDO1lBRUQsOERBQThEO1lBQzlELE9BQU8sQ0FBQyxHQUFHLENBQ1QsSUFBSSxZQUFZLG1DQUNkLE1BQU0sQ0FBQyxRQUNULFVBQVUsT0FBTyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLGFBQWEsSUFBSSxPQUFPLENBQUMsRUFBRSxDQUNyRSxDQUFDO1lBQ0YsSUFBSSxNQUFNLENBQUMseUJBQXlCLEtBQUssSUFBSSxFQUFFLENBQUM7Z0JBQzlDLE1BQU0sQ0FBQyx5QkFBeUIsR0FBRyxTQUFTLENBQUM7Z0JBQzdDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyx3QkFBd0IsQ0FBQyxVQUFVLEVBQUUsU0FBUyxDQUFDLENBQUM7WUFDekUsQ0FBQztZQUNELElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxtQkFBbUIsQ0FBQyxNQUFNLEVBQUUsa0JBQWtCLENBQUMsQ0FBQztRQUN6RSxDQUFDLENBQUMsQ0FBQztRQUVILFlBQVksQ0FBQyxFQUFFLENBQUMsU0FBUyxFQUFFLEdBQUcsRUFBRTtZQUM5QixvRUFBb0U7WUFDcEUsSUFBSSxNQUFNLENBQUMsWUFBWSxFQUFFLENBQUM7Z0JBQ3hCLE9BQU8sQ0FBQyxHQUFHLENBQ1QsSUFBSSxZQUFZLDBEQUNkLE1BQU0sQ0FBQyxRQUNULFVBQVUsT0FBTyxDQUFDLFFBQVEsQ0FDeEIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxhQUFhLElBQUksT0FBTyxDQUN2Qyx5QkFBeUIsQ0FDM0IsQ0FBQztnQkFDRixPQUFPO1lBQ1QsQ0FBQztZQUVELDhEQUE4RDtZQUM5RCxPQUFPLENBQUMsR0FBRyxDQUNULElBQUksWUFBWSxtQ0FDZCxNQUFNLENBQUMsUUFDVCxVQUFVLE9BQU8sQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxhQUFhLElBQUksT0FBTyxDQUFDLEVBQUUsQ0FDckUsQ0FBQztZQUNGLElBQUksTUFBTSxDQUFDLHlCQUF5QixLQUFLLElBQUksRUFBRSxDQUFDO2dCQUM5QyxNQUFNLENBQUMseUJBQXlCLEdBQUcsU0FBUyxDQUFDO2dCQUM3QyxJQUFJLENBQUMsaUJBQWlCLENBQUMsd0JBQXdCLENBQUMsVUFBVSxFQUFFLFNBQVMsQ0FBQyxDQUFDO1lBQ3pFLENBQUM7WUFDRCxJQUFJLENBQUMsaUJBQWlCLENBQUMsbUJBQW1CLENBQUMsTUFBTSxFQUFFLGtCQUFrQixDQUFDLENBQUM7UUFDekUsQ0FBQyxDQUFDLENBQUM7UUFFSCx3QkFBd0I7UUFDeEIsSUFBSSxDQUFDLGNBQWMsQ0FBQyxtQkFBbUIsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUVoRCx5Q0FBeUM7UUFDekMsWUFBWSxDQUFDLEVBQUUsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxLQUFhLEVBQUUsRUFBRTtZQUN4QyxNQUFNLENBQUMsU0FBUyxJQUFJLEtBQUssQ0FBQyxNQUFNLENBQUM7WUFDakMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxjQUFjLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDN0MsQ0FBQyxDQUFDLENBQUM7UUFFSCx3RUFBd0U7UUFDeEUsWUFBWSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsR0FBRyxFQUFFO1lBQ2hDLDZDQUE2QztZQUM3QyxZQUFZLENBQUMsa0JBQWtCLENBQUMsT0FBTyxDQUFDLENBQUM7WUFFekMsMkRBQTJEO1lBQzNELFlBQVksQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLENBQUMsVUFBVSxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUM7WUFFakYscUVBQXFFO1lBQ3JFLGdCQUFnQixFQUFFLENBQUM7WUFFbkIsNEJBQTRCO1lBQzVCLGlCQUFpQixHQUFHLElBQUksQ0FBQztZQUV6QixtQ0FBbUM7WUFDbkMsSUFBSSxNQUFNLENBQUMsV0FBVyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztnQkFDbEMsTUFBTSxZQUFZLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLENBQUM7Z0JBRXZELElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO29CQUN4QyxPQUFPLENBQUMsR0FBRyxDQUNULElBQUksWUFBWSxnQkFBZ0IsWUFBWSxDQUFDLE1BQU0sa0NBQWtDLENBQ3RGLENBQUM7Z0JBQ0osQ0FBQztnQkFFRCxpQ0FBaUM7Z0JBQ2pDLFlBQVksQ0FBQyxLQUFLLENBQUMsWUFBWSxFQUFFLENBQUMsR0FBRyxFQUFFLEVBQUU7b0JBQ3ZDLElBQUksR0FBRyxFQUFFLENBQUM7d0JBQ1IsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLFlBQVksMkNBQTJDLEdBQUcsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO3dCQUN0RixPQUFPLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxtQkFBbUIsQ0FBQyxNQUFNLEVBQUUsYUFBYSxDQUFDLENBQUM7b0JBQzNFLENBQUM7Z0JBQ0gsQ0FBQyxDQUFDLENBQUM7Z0JBRUgsK0NBQStDO2dCQUMvQyxNQUFNLENBQUMsV0FBVyxHQUFHLEVBQUUsQ0FBQztnQkFDeEIsTUFBTSxDQUFDLGVBQWUsR0FBRyxDQUFDLENBQUM7WUFDN0IsQ0FBQztZQUVELHFEQUFxRDtZQUNyRCxNQUFNLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQzFCLFlBQVksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7WUFFMUIseUNBQXlDO1lBQ3pDLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUVoQix1REFBdUQ7WUFDdkQsSUFBSSxTQUFTLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO2dCQUN6QixnRUFBZ0U7Z0JBQ2hFLEtBQUssTUFBTSxLQUFLLElBQUksU0FBUyxFQUFFLENBQUM7b0JBQzlCLFlBQVksQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUM7Z0JBQzVCLENBQUM7Z0JBQ0Qsa0JBQWtCO2dCQUNsQixTQUFTLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQztnQkFDckIsU0FBUyxHQUFHLENBQUMsQ0FBQztZQUNoQixDQUFDO1lBRUQsSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLHFCQUFxQixFQUFFLENBQUM7Z0JBQ3hDLE9BQU8sQ0FBQyxHQUFHLENBQ1QsSUFBSSxZQUFZLDZCQUE2QixNQUFNLENBQUMsUUFBUSxPQUFPLFVBQVUsSUFBSSxpQkFBaUIsQ0FBQyxJQUFJLEVBQUU7b0JBQ3ZHLEdBQ0UsVUFBVTt3QkFDUixDQUFDLENBQUMsVUFBVSxVQUFVLEdBQUc7d0JBQ3pCLENBQUMsQ0FBQyxZQUFZOzRCQUNkLENBQUMsQ0FBQyw0QkFBNEIsWUFBWSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUc7NEJBQ2hFLENBQUMsQ0FBQyxFQUNOLEVBQUU7b0JBQ0YsU0FBUyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUksaUJBQ2xDLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFDaEMsRUFBRSxDQUNMLENBQUM7WUFDSixDQUFDO2lCQUFNLENBQUM7Z0JBQ04sT0FBTyxDQUFDLEdBQUcsQ0FDVCwyQkFBMkIsTUFBTSxDQUFDLFFBQVEsT0FBTyxVQUFVLElBQUksaUJBQWlCLENBQUMsSUFBSSxFQUFFO29CQUNyRixHQUNFLFVBQVU7d0JBQ1IsQ0FBQyxDQUFDLFVBQVUsVUFBVSxHQUFHO3dCQUN6QixDQUFDLENBQUMsWUFBWTs0QkFDZCxDQUFDLENBQUMsNEJBQTRCLFlBQVksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHOzRCQUNoRSxDQUFDLENBQUMsRUFDTixFQUFFLENBQ0wsQ0FBQztZQUNKLENBQUM7WUFFRCxtREFBbUQ7WUFDbkQsSUFBSSxVQUFVLEVBQUUsQ0FBQztnQkFDZiw0REFBNEQ7Z0JBQzVELE1BQU0sUUFBUSxHQUFHO29CQUNmLFFBQVEsRUFBRSxNQUFNLENBQUMsUUFBUTtvQkFDekIsVUFBVSxFQUFFLE1BQU0sQ0FBQyxRQUFRLENBQUMsVUFBVSxJQUFJLENBQUM7b0JBQzNDLE1BQU0sRUFBRSxNQUFNLENBQUMsUUFBUSxDQUFDLFlBQVksSUFBSSxFQUFFO29CQUMxQyxRQUFRLEVBQUUsTUFBTSxDQUFDLFFBQVEsQ0FBQyxTQUFTLElBQUksQ0FBQztpQkFDekMsQ0FBQztnQkFFRiwwQ0FBMEM7Z0JBQzFDLE1BQU0sb0JBQW9CLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQywwQkFBMEIsQ0FDckUsWUFBWSxFQUNaLFVBQVUsRUFDVixRQUFRLEVBQ1IsQ0FBQyxZQUFZLEVBQUUsTUFBTSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsbUJBQW1CLENBQUMsTUFBTSxFQUFFLE1BQU0sQ0FBQyxDQUNyRixDQUFDO2dCQUVGLGdGQUFnRjtnQkFDaEYsTUFBTSxDQUFDLG9CQUFvQixHQUFHLG9CQUFvQixDQUFDO2dCQUVuRCxnQ0FBZ0M7Z0JBQ2hDLE1BQU0sQ0FBQyxFQUFFLENBQUMsTUFBTSxFQUFFLG9CQUFvQixDQUFDLENBQUM7Z0JBRXhDLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO29CQUN4QyxPQUFPLENBQUMsR0FBRyxDQUNULElBQUksWUFBWSx5REFBeUQsVUFBVSxFQUFFLENBQ3RGLENBQUM7b0JBQ0YsSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLGtCQUFrQixLQUFLLEtBQUssRUFBRSxDQUFDO3dCQUMvQyxPQUFPLENBQUMsR0FBRyxDQUNULElBQUksWUFBWSx3RkFBd0YsQ0FDekcsQ0FBQztvQkFDSixDQUFDO2dCQUNILENBQUM7WUFDSCxDQUFDO1lBRUQseUJBQXlCO1lBQ3pCLE1BQU0sQ0FBQyxZQUFZLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxzQkFBc0IsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxNQUFNLEVBQUUsTUFBTSxFQUFFLEVBQUU7Z0JBQzFGLE9BQU8sQ0FBQyxHQUFHLENBQ1QsSUFBSSxZQUFZLHFCQUFxQixNQUFNLENBQUMsUUFBUSwwQ0FBMEMsQ0FDL0YsQ0FBQztnQkFDRixJQUFJLENBQUMsaUJBQWlCLENBQUMsbUJBQW1CLENBQUMsTUFBTSxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQzdELENBQUMsQ0FBQyxDQUFDO1lBRUgscURBQXFEO1lBQ3JELElBQUksTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDO2dCQUNqQixNQUFNLENBQUMsb0JBQW9CLEdBQUcsSUFBSSxDQUFDO2dCQUVuQyxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMscUJBQXFCLEVBQUUsQ0FBQztvQkFDeEMsT0FBTyxDQUFDLEdBQUcsQ0FDVCxJQUFJLFlBQVksZ0RBQWdELE1BQU0sQ0FBQyxRQUFRLEVBQUUsQ0FDbEYsQ0FBQztnQkFDSixDQUFDO1lBQ0gsQ0FBQztRQUNILENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztDQUNGIn0=