openc3 7.3.0 → 7.4.0

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 (499) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/Guardfile +0 -0
  4. data/LICENSE.md +0 -0
  5. data/README.md +0 -0
  6. data/Rakefile +0 -0
  7. data/bin/openc3cli +138 -0
  8. data/bin/pipuninstall +0 -0
  9. data/bin/uvinstall +10 -3
  10. data/data/config/_array_params.yaml +0 -0
  11. data/data/config/_canvas_values.yaml +0 -0
  12. data/data/config/_graph_params.yaml +0 -0
  13. data/data/config/_id_items.yaml +0 -0
  14. data/data/config/_id_params.yaml +0 -0
  15. data/data/config/_interfaces.yaml +0 -0
  16. data/data/config/_items.yaml +0 -0
  17. data/data/config/_params.yaml +0 -0
  18. data/data/config/command.yaml +0 -0
  19. data/data/config/command_modifiers.yaml +2 -0
  20. data/data/config/command_telemetry.yaml +0 -0
  21. data/data/config/conversions.yaml +0 -0
  22. data/data/config/graph_settings.yaml +0 -0
  23. data/data/config/interface_modifiers.yaml +103 -1
  24. data/data/config/item_modifiers.yaml +0 -0
  25. data/data/config/microservice.yaml +5 -2
  26. data/data/config/param_item_modifiers.yaml +0 -0
  27. data/data/config/parameter_modifiers.yaml +0 -0
  28. data/data/config/plugins.yaml +0 -0
  29. data/data/config/processors.yaml +0 -0
  30. data/data/config/protocols.yaml +0 -0
  31. data/data/config/screen.yaml +0 -0
  32. data/data/config/settings.yaml +0 -0
  33. data/data/config/table_manager.yaml +0 -0
  34. data/data/config/table_parameter_modifiers.yaml +0 -0
  35. data/data/config/target.yaml +0 -0
  36. data/data/config/target_config.yaml +0 -0
  37. data/data/config/telemetry.yaml +0 -0
  38. data/data/config/telemetry_modifiers.yaml +2 -0
  39. data/data/config/tool.yaml +0 -0
  40. data/data/config/unknown.yaml +0 -0
  41. data/data/config/widgets.yaml +6 -0
  42. data/data/xtce_schemas/SpaceSystem_20180204.xsd +0 -0
  43. data/data/xtce_schemas/xml.xsd +0 -0
  44. data/ext/openc3/ext/array/array.c +0 -0
  45. data/ext/openc3/ext/array/extconf.rb +0 -0
  46. data/ext/openc3/ext/buffered_file/buffered_file.c +0 -0
  47. data/ext/openc3/ext/buffered_file/extconf.rb +0 -0
  48. data/ext/openc3/ext/burst_protocol/burst_protocol.c +6 -0
  49. data/ext/openc3/ext/burst_protocol/extconf.rb +0 -0
  50. data/ext/openc3/ext/config_parser/config_parser.c +0 -0
  51. data/ext/openc3/ext/config_parser/extconf.rb +0 -0
  52. data/ext/openc3/ext/crc/crc.c +0 -0
  53. data/ext/openc3/ext/crc/extconf.rb +0 -0
  54. data/ext/openc3/ext/openc3_io/extconf.rb +0 -0
  55. data/ext/openc3/ext/openc3_io/openc3_io.c +0 -0
  56. data/ext/openc3/ext/packet/extconf.rb +0 -0
  57. data/ext/openc3/ext/packet/packet.c +0 -0
  58. data/ext/openc3/ext/platform/extconf.rb +0 -0
  59. data/ext/openc3/ext/platform/platform.c +4 -1
  60. data/ext/openc3/ext/polynomial_conversion/extconf.rb +0 -0
  61. data/ext/openc3/ext/polynomial_conversion/polynomial_conversion.c +0 -0
  62. data/ext/openc3/ext/string/extconf.rb +0 -0
  63. data/ext/openc3/ext/string/string.c +0 -0
  64. data/ext/openc3/ext/structure/structure.c +49 -17
  65. data/ext/openc3/ext/tabbed_plots_config/extconf.rb +0 -0
  66. data/ext/openc3/ext/tabbed_plots_config/tabbed_plots_config.c +0 -0
  67. data/ext/openc3/ext/telemetry/extconf.rb +0 -0
  68. data/ext/openc3/ext/telemetry/telemetry.c +0 -0
  69. data/lib/cosmos.rb +0 -0
  70. data/lib/cosmosc2.rb +0 -0
  71. data/lib/openc3/accessors/accessor.rb +0 -0
  72. data/lib/openc3/accessors/binary_accessor.rb +63 -9
  73. data/lib/openc3/accessors/cbor_accessor.rb +0 -0
  74. data/lib/openc3/accessors/form_accessor.rb +0 -0
  75. data/lib/openc3/accessors/html_accessor.rb +0 -0
  76. data/lib/openc3/accessors/http_accessor.rb +0 -0
  77. data/lib/openc3/accessors/json_accessor.rb +0 -0
  78. data/lib/openc3/accessors/template_accessor.rb +0 -0
  79. data/lib/openc3/accessors/xml_accessor.rb +0 -0
  80. data/lib/openc3/accessors.rb +0 -0
  81. data/lib/openc3/api/README.md +0 -0
  82. data/lib/openc3/api/api.rb +0 -0
  83. data/lib/openc3/api/authorized_api.rb +0 -0
  84. data/lib/openc3/api/calendar_api.rb +0 -0
  85. data/lib/openc3/api/cmd_api.rb +1 -1
  86. data/lib/openc3/api/config_api.rb +0 -0
  87. data/lib/openc3/api/interface_api.rb +0 -0
  88. data/lib/openc3/api/limits_api.rb +0 -0
  89. data/lib/openc3/api/metrics_api.rb +1 -1
  90. data/lib/openc3/api/offline_access_api.rb +1 -1
  91. data/lib/openc3/api/router_api.rb +0 -0
  92. data/lib/openc3/api/settings_api.rb +22 -18
  93. data/lib/openc3/api/stash_api.rb +1 -1
  94. data/lib/openc3/api/target_api.rb +0 -0
  95. data/lib/openc3/api/tlm_api.rb +4 -3
  96. data/lib/openc3/bridge/bridge.rb +0 -0
  97. data/lib/openc3/bridge/bridge_config.rb +0 -0
  98. data/lib/openc3/bridge/bridge_interface_thread.rb +0 -0
  99. data/lib/openc3/bridge/bridge_router_thread.rb +0 -0
  100. data/lib/openc3/ccsds/ccsds_packet.rb +0 -0
  101. data/lib/openc3/ccsds/ccsds_parser.rb +0 -0
  102. data/lib/openc3/config/config_parser.rb +78 -17
  103. data/lib/openc3/config/meta_config_parser.rb +0 -0
  104. data/lib/openc3/conversions/bit_reverse_conversion.rb +0 -0
  105. data/lib/openc3/conversions/conversion.rb +0 -0
  106. data/lib/openc3/conversions/generic_conversion.rb +0 -0
  107. data/lib/openc3/conversions/ip_read_conversion.rb +0 -0
  108. data/lib/openc3/conversions/ip_write_conversion.rb +0 -0
  109. data/lib/openc3/conversions/object_read_conversion.rb +0 -0
  110. data/lib/openc3/conversions/object_write_conversion.rb +0 -0
  111. data/lib/openc3/conversions/packet_time_formatted_conversion.rb +0 -0
  112. data/lib/openc3/conversions/packet_time_seconds_conversion.rb +0 -0
  113. data/lib/openc3/conversions/polynomial_conversion.rb +0 -0
  114. data/lib/openc3/conversions/processor_conversion.rb +0 -0
  115. data/lib/openc3/conversions/received_count_conversion.rb +0 -0
  116. data/lib/openc3/conversions/received_time_formatted_conversion.rb +0 -0
  117. data/lib/openc3/conversions/received_time_seconds_conversion.rb +0 -0
  118. data/lib/openc3/conversions/segmented_polynomial_conversion.rb +0 -0
  119. data/lib/openc3/conversions/unix_time_conversion.rb +0 -0
  120. data/lib/openc3/conversions/unix_time_formatted_conversion.rb +0 -0
  121. data/lib/openc3/conversions/unix_time_seconds_conversion.rb +0 -0
  122. data/lib/openc3/conversions.rb +0 -0
  123. data/lib/openc3/core_ext/array.rb +0 -0
  124. data/lib/openc3/core_ext/binding.rb +0 -0
  125. data/lib/openc3/core_ext/class.rb +0 -0
  126. data/lib/openc3/core_ext/exception.rb +0 -0
  127. data/lib/openc3/core_ext/faraday.rb +0 -0
  128. data/lib/openc3/core_ext/file.rb +0 -0
  129. data/lib/openc3/core_ext/io.rb +0 -0
  130. data/lib/openc3/core_ext/kernel.rb +0 -0
  131. data/lib/openc3/core_ext/math.rb +0 -0
  132. data/lib/openc3/core_ext/matrix.rb +0 -0
  133. data/lib/openc3/core_ext/objectspace.rb +0 -0
  134. data/lib/openc3/core_ext/openc3_io.rb +0 -0
  135. data/lib/openc3/core_ext/range.rb +0 -0
  136. data/lib/openc3/core_ext/socket.rb +0 -0
  137. data/lib/openc3/core_ext/string.rb +0 -0
  138. data/lib/openc3/core_ext/stringio.rb +0 -0
  139. data/lib/openc3/core_ext/tempfile.rb +0 -0
  140. data/lib/openc3/core_ext/time.rb +0 -0
  141. data/lib/openc3/core_ext.rb +0 -0
  142. data/lib/openc3/ext/.keep +0 -0
  143. data/lib/openc3/interfaces/file_interface.rb +0 -0
  144. data/lib/openc3/interfaces/http_client_interface.rb +0 -0
  145. data/lib/openc3/interfaces/http_server_interface.rb +0 -0
  146. data/lib/openc3/interfaces/interface.rb +5 -4
  147. data/lib/openc3/interfaces/mqtt_interface.rb +0 -0
  148. data/lib/openc3/interfaces/mqtt_stream_interface.rb +2 -0
  149. data/lib/openc3/interfaces/protocols/burst_protocol.rb +27 -0
  150. data/lib/openc3/interfaces/protocols/cmd_response_protocol.rb +0 -0
  151. data/lib/openc3/interfaces/protocols/cobs_protocol.rb +0 -0
  152. data/lib/openc3/interfaces/protocols/crc_protocol.rb +0 -0
  153. data/lib/openc3/interfaces/protocols/fixed_protocol.rb +0 -0
  154. data/lib/openc3/interfaces/protocols/ignore_packet_protocol.rb +0 -0
  155. data/lib/openc3/interfaces/protocols/length_protocol.rb +7 -0
  156. data/lib/openc3/interfaces/protocols/preidentified_protocol.rb +7 -0
  157. data/lib/openc3/interfaces/protocols/protocol.rb +4 -4
  158. data/lib/openc3/interfaces/protocols/slip_protocol.rb +0 -0
  159. data/lib/openc3/interfaces/protocols/template_protocol.rb +2 -2
  160. data/lib/openc3/interfaces/protocols/terminated_protocol.rb +0 -0
  161. data/lib/openc3/interfaces/serial_interface.rb +2 -0
  162. data/lib/openc3/interfaces/simulated_target_interface.rb +0 -0
  163. data/lib/openc3/interfaces/stream_interface.rb +0 -0
  164. data/lib/openc3/interfaces/tcpip_client_interface.rb +2 -0
  165. data/lib/openc3/interfaces/tcpip_server_interface.rb +0 -0
  166. data/lib/openc3/interfaces/udp_interface.rb +16 -5
  167. data/lib/openc3/interfaces.rb +0 -0
  168. data/lib/openc3/io/buffered_file.rb +0 -0
  169. data/lib/openc3/io/io_multiplexer.rb +0 -0
  170. data/lib/openc3/io/json_api.rb +3 -2
  171. data/lib/openc3/io/json_api_object.rb +0 -0
  172. data/lib/openc3/io/json_drb.rb +20 -4
  173. data/lib/openc3/io/json_drb_object.rb +0 -0
  174. data/lib/openc3/io/json_drb_rack.rb +0 -0
  175. data/lib/openc3/io/json_rpc.rb +0 -0
  176. data/lib/openc3/io/posix_serial_driver.rb +0 -0
  177. data/lib/openc3/io/serial_driver.rb +0 -0
  178. data/lib/openc3/io/stderr.rb +0 -0
  179. data/lib/openc3/io/stdout.rb +0 -0
  180. data/lib/openc3/io/udp_sockets.rb +38 -8
  181. data/lib/openc3/io/win32_serial_driver.rb +1 -0
  182. data/lib/openc3/logs/buffered_packet_log_reader.rb +0 -0
  183. data/lib/openc3/logs/buffered_packet_log_writer.rb +0 -0
  184. data/lib/openc3/logs/log_writer.rb +0 -0
  185. data/lib/openc3/logs/packet_log_constants.rb +0 -0
  186. data/lib/openc3/logs/packet_log_reader.rb +23 -2
  187. data/lib/openc3/logs/packet_log_writer.rb +5 -0
  188. data/lib/openc3/logs/stream_log.rb +1 -1
  189. data/lib/openc3/logs/stream_log_pair.rb +0 -0
  190. data/lib/openc3/logs/text_log_writer.rb +0 -0
  191. data/lib/openc3/logs.rb +0 -0
  192. data/lib/openc3/microservices/cleanup_microservice.rb +0 -0
  193. data/lib/openc3/microservices/decom_common.rb +0 -0
  194. data/lib/openc3/microservices/decom_microservice.rb +0 -0
  195. data/lib/openc3/microservices/interface_decom_common.rb +2 -1
  196. data/lib/openc3/microservices/interface_microservice.rb +72 -25
  197. data/lib/openc3/microservices/log_microservice.rb +0 -0
  198. data/lib/openc3/microservices/microservice.rb +3 -3
  199. data/lib/openc3/microservices/multi_microservice.rb +1 -1
  200. data/lib/openc3/microservices/periodic_microservice.rb +2 -2
  201. data/lib/openc3/microservices/plugin_microservice.rb +0 -0
  202. data/lib/openc3/microservices/queue_microservice.rb +0 -0
  203. data/lib/openc3/microservices/router_microservice.rb +0 -0
  204. data/lib/openc3/microservices/scope_cleanup_microservice.rb +0 -0
  205. data/lib/openc3/microservices/text_log_microservice.rb +0 -0
  206. data/lib/openc3/migrations/20220420190000_log_stuff.rb +0 -0
  207. data/lib/openc3/migrations/20221202214600_add_target_names.rb +0 -0
  208. data/lib/openc3/migrations/20221210174900_convert_to_multi.rb +0 -0
  209. data/lib/openc3/migrations/20230915000002_no_scope_log_messages.rb +0 -0
  210. data/lib/openc3/migrations/20231022000000_tlm_viewer_config.rb +0 -0
  211. data/lib/openc3/migrations/20241208080000_no_critical_cmd.rb +0 -0
  212. data/lib/openc3/migrations/20241208080001_no_trigger_group.rb +0 -0
  213. data/lib/openc3/migrations/20250108060000_news_feed.rb +0 -0
  214. data/lib/openc3/migrations/20250402000000_periodic_only_default.rb +0 -0
  215. data/lib/openc3/migrations/20260203000000_remove_store_id.rb +0 -0
  216. data/lib/openc3/migrations/20260204000000_remove_decom_reducer.rb +0 -0
  217. data/lib/openc3/migrations/20260701000000_updated_at_to_int.rb +0 -0
  218. data/lib/openc3/migrations/20260704000000_default_bridge.rb +38 -0
  219. data/lib/openc3/migrations/20260731000000_system_health_json.rb +11 -0
  220. data/lib/openc3/models/activity_model.rb +0 -0
  221. data/lib/openc3/models/auth_model.rb +35 -7
  222. data/lib/openc3/models/bridge_model.rb +133 -0
  223. data/lib/openc3/models/config_keyword_model.rb +63 -0
  224. data/lib/openc3/models/cvt_model.rb +0 -0
  225. data/lib/openc3/models/db_sharded_model.rb +0 -0
  226. data/lib/openc3/models/environment_model.rb +0 -0
  227. data/lib/openc3/models/gem_model.rb +12 -9
  228. data/lib/openc3/models/host_interface_microservice_model.rb +114 -0
  229. data/lib/openc3/models/info_model.rb +0 -0
  230. data/lib/openc3/models/interface_model.rb +178 -19
  231. data/lib/openc3/models/interface_status_model.rb +0 -0
  232. data/lib/openc3/models/metadata_model.rb +0 -0
  233. data/lib/openc3/models/metric_model.rb +0 -0
  234. data/lib/openc3/models/microservice_model.rb +9 -22
  235. data/lib/openc3/models/microservice_status_model.rb +0 -0
  236. data/lib/openc3/models/migration_model.rb +0 -0
  237. data/lib/openc3/models/model.rb +0 -0
  238. data/lib/openc3/models/news_model.rb +0 -0
  239. data/lib/openc3/models/note_model.rb +0 -0
  240. data/lib/openc3/models/offline_access_model.rb +0 -0
  241. data/lib/openc3/models/ping_model.rb +0 -0
  242. data/lib/openc3/models/plugin_model.rb +9 -2
  243. data/lib/openc3/models/plugin_store_model.rb +0 -0
  244. data/lib/openc3/models/process_status_model.rb +0 -0
  245. data/lib/openc3/models/python_package_model.rb +4 -4
  246. data/lib/openc3/models/queue_model.rb +0 -0
  247. data/lib/openc3/models/reaction_model.rb +0 -0
  248. data/lib/openc3/models/reingest_job_model.rb +0 -0
  249. data/lib/openc3/models/router_model.rb +0 -0
  250. data/lib/openc3/models/router_status_model.rb +0 -0
  251. data/lib/openc3/models/scope_model.rb +51 -26
  252. data/lib/openc3/models/script_engine_model.rb +0 -0
  253. data/lib/openc3/models/script_status_model.rb +0 -0
  254. data/lib/openc3/models/secret_model.rb +0 -0
  255. data/lib/openc3/models/setting_model.rb +546 -3
  256. data/lib/openc3/models/sorted_model.rb +0 -0
  257. data/lib/openc3/models/stash_model.rb +0 -0
  258. data/lib/openc3/models/target_model.rb +30 -25
  259. data/lib/openc3/models/timeline_model.rb +0 -0
  260. data/lib/openc3/models/tool_config_model.rb +0 -0
  261. data/lib/openc3/models/tool_model.rb +1 -0
  262. data/lib/openc3/models/trigger_group_model.rb +0 -0
  263. data/lib/openc3/models/trigger_model.rb +20 -0
  264. data/lib/openc3/models/widget_model.rb +0 -0
  265. data/lib/openc3/operators/microservice_operator.rb +64 -22
  266. data/lib/openc3/operators/operator.rb +4 -4
  267. data/lib/openc3/packets/binary_accessor.rb +0 -0
  268. data/lib/openc3/packets/command_validator.rb +0 -0
  269. data/lib/openc3/packets/commands.rb +0 -0
  270. data/lib/openc3/packets/json_packet.rb +0 -0
  271. data/lib/openc3/packets/limits.rb +0 -0
  272. data/lib/openc3/packets/limits_response.rb +0 -0
  273. data/lib/openc3/packets/packet.rb +4 -0
  274. data/lib/openc3/packets/packet_config.rb +0 -0
  275. data/lib/openc3/packets/packet_item.rb +0 -0
  276. data/lib/openc3/packets/packet_item_limits.rb +0 -0
  277. data/lib/openc3/packets/parsers/format_string_parser.rb +0 -0
  278. data/lib/openc3/packets/parsers/limits_parser.rb +0 -0
  279. data/lib/openc3/packets/parsers/limits_response_parser.rb +0 -0
  280. data/lib/openc3/packets/parsers/packet_item_parser.rb +0 -0
  281. data/lib/openc3/packets/parsers/packet_parser.rb +0 -0
  282. data/lib/openc3/packets/parsers/processor_parser.rb +0 -0
  283. data/lib/openc3/packets/parsers/state_parser.rb +0 -0
  284. data/lib/openc3/packets/parsers/xtce_converter.rb +0 -0
  285. data/lib/openc3/packets/parsers/xtce_parser.rb +0 -0
  286. data/lib/openc3/packets/structure.rb +7 -1
  287. data/lib/openc3/packets/structure_item.rb +0 -0
  288. data/lib/openc3/packets/telemetry.rb +0 -0
  289. data/lib/openc3/processors/processor.rb +2 -0
  290. data/lib/openc3/processors/statistics_processor.rb +0 -0
  291. data/lib/openc3/processors/watermark_processor.rb +0 -0
  292. data/lib/openc3/processors.rb +0 -0
  293. data/lib/openc3/script/api_shared.rb +0 -0
  294. data/lib/openc3/script/autonomic.rb +12 -12
  295. data/lib/openc3/script/calendar.rb +0 -0
  296. data/lib/openc3/script/commands.rb +0 -0
  297. data/lib/openc3/script/critical_cmd.rb +0 -0
  298. data/lib/openc3/script/exceptions.rb +0 -0
  299. data/lib/openc3/script/extract.rb +0 -0
  300. data/lib/openc3/script/limits.rb +0 -0
  301. data/lib/openc3/script/metadata.rb +0 -0
  302. data/lib/openc3/script/packages.rb +0 -0
  303. data/lib/openc3/script/plugins.rb +0 -0
  304. data/lib/openc3/script/queue.rb +0 -0
  305. data/lib/openc3/script/screen.rb +0 -0
  306. data/lib/openc3/script/script.rb +2 -2
  307. data/lib/openc3/script/script_runner.rb +0 -0
  308. data/lib/openc3/script/storage.rb +4 -4
  309. data/lib/openc3/script/suite.rb +0 -0
  310. data/lib/openc3/script/suite_results.rb +0 -0
  311. data/lib/openc3/script/suite_runner.rb +26 -0
  312. data/lib/openc3/script/tables.rb +0 -0
  313. data/lib/openc3/script/telemetry.rb +9 -3
  314. data/lib/openc3/script/web_socket_api.rb +218 -145
  315. data/lib/openc3/script.rb +0 -0
  316. data/lib/openc3/script_engines/script_engine.rb +0 -0
  317. data/lib/openc3/streams/mqtt_stream.rb +0 -0
  318. data/lib/openc3/streams/serial_stream.rb +0 -0
  319. data/lib/openc3/streams/stream.rb +0 -0
  320. data/lib/openc3/streams/tcpip_client_stream.rb +0 -0
  321. data/lib/openc3/streams/tcpip_socket_stream.rb +0 -0
  322. data/lib/openc3/streams/web_socket_client_stream.rb +0 -0
  323. data/lib/openc3/subpacketizers/subpacketizer.rb +0 -0
  324. data/lib/openc3/system/system.rb +0 -0
  325. data/lib/openc3/system/target.rb +0 -0
  326. data/lib/openc3/system.rb +0 -0
  327. data/lib/openc3/tools/cmd_tlm_server/api.rb +0 -0
  328. data/lib/openc3/tools/cmd_tlm_server/interface_thread.rb +7 -0
  329. data/lib/openc3/tools/table_manager/table.rb +0 -0
  330. data/lib/openc3/tools/table_manager/table_config.rb +0 -0
  331. data/lib/openc3/tools/table_manager/table_item.rb +0 -0
  332. data/lib/openc3/tools/table_manager/table_item_parser.rb +0 -0
  333. data/lib/openc3/tools/table_manager/table_manager_core.rb +0 -0
  334. data/lib/openc3/tools/table_manager/table_parser.rb +0 -0
  335. data/lib/openc3/tools/test_runner/test.rb +0 -0
  336. data/lib/openc3/top_level.rb +1 -1
  337. data/lib/openc3/topics/autonomic_topic.rb +0 -0
  338. data/lib/openc3/topics/calendar_topic.rb +0 -0
  339. data/lib/openc3/topics/command_decom_topic.rb +0 -0
  340. data/lib/openc3/topics/command_topic.rb +0 -0
  341. data/lib/openc3/topics/config_topic.rb +0 -0
  342. data/lib/openc3/topics/decom_interface_topic.rb +2 -1
  343. data/lib/openc3/topics/interface_topic.rb +8 -2
  344. data/lib/openc3/topics/limits_event_topic.rb +0 -0
  345. data/lib/openc3/topics/notebook_topic.rb +0 -0
  346. data/lib/openc3/topics/queue_topic.rb +0 -0
  347. data/lib/openc3/topics/router_topic.rb +6 -1
  348. data/lib/openc3/topics/system_events_topic.rb +0 -0
  349. data/lib/openc3/topics/telemetry_decom_topic.rb +0 -0
  350. data/lib/openc3/topics/telemetry_topic.rb +0 -0
  351. data/lib/openc3/topics/timeline_topic.rb +0 -0
  352. data/lib/openc3/topics/topic.rb +0 -0
  353. data/lib/openc3/utilities/authentication.rb +4 -4
  354. data/lib/openc3/utilities/authorization.rb +0 -0
  355. data/lib/openc3/utilities/aws_bucket.rb +2 -2
  356. data/lib/openc3/utilities/bucket.rb +1 -1
  357. data/lib/openc3/utilities/bucket_file_cache.rb +55 -22
  358. data/lib/openc3/utilities/bucket_require.rb +0 -0
  359. data/lib/openc3/utilities/bucket_utilities.rb +3 -4
  360. data/lib/openc3/utilities/cli_generator.rb +0 -0
  361. data/lib/openc3/utilities/cmd_log.rb +0 -0
  362. data/lib/openc3/utilities/config_overlay.rb +75 -0
  363. data/lib/openc3/utilities/cosmos_rails_formatter.rb +0 -0
  364. data/lib/openc3/utilities/crc.rb +59 -32
  365. data/lib/openc3/utilities/csv.rb +0 -0
  366. data/lib/openc3/utilities/ctrf.rb +0 -0
  367. data/lib/openc3/utilities/env_helper.rb +0 -0
  368. data/lib/openc3/utilities/local_bucket.rb +0 -0
  369. data/lib/openc3/utilities/local_mode.rb +32 -6
  370. data/lib/openc3/utilities/logger.rb +30 -8
  371. data/lib/openc3/utilities/message_log.rb +0 -0
  372. data/lib/openc3/utilities/metric.rb +0 -0
  373. data/lib/openc3/utilities/migration.rb +0 -0
  374. data/lib/openc3/utilities/open_telemetry.rb +0 -0
  375. data/lib/openc3/utilities/process_manager.rb +0 -0
  376. data/lib/openc3/utilities/pypi_url.rb +0 -0
  377. data/lib/openc3/utilities/python_proxy.rb +0 -0
  378. data/lib/openc3/utilities/python_venv.rb +135 -0
  379. data/lib/openc3/utilities/quaternion.rb +0 -0
  380. data/lib/openc3/utilities/questdb_client.rb +0 -0
  381. data/lib/openc3/utilities/redis_secrets.rb +0 -0
  382. data/lib/openc3/utilities/reingest_job.rb +0 -0
  383. data/lib/openc3/utilities/ruby_lex_utils.rb +0 -0
  384. data/lib/openc3/utilities/rubygems_url.rb +39 -0
  385. data/lib/openc3/utilities/running_script.rb +24 -55
  386. data/lib/openc3/utilities/s3_autoload.rb +5 -5
  387. data/lib/openc3/utilities/script.rb +12 -8
  388. data/lib/openc3/utilities/secrets.rb +48 -3
  389. data/lib/openc3/utilities/simulated_target.rb +0 -0
  390. data/lib/openc3/utilities/sleeper.rb +0 -0
  391. data/lib/openc3/utilities/store.rb +0 -0
  392. data/lib/openc3/utilities/store_autoload.rb +2 -2
  393. data/lib/openc3/utilities/store_queued.rb +0 -0
  394. data/lib/openc3/utilities/target_file.rb +18 -1
  395. data/lib/openc3/utilities/thread_manager.rb +0 -0
  396. data/lib/openc3/utilities/throttle.rb +0 -0
  397. data/lib/openc3/utilities/zip.rb +0 -0
  398. data/lib/openc3/utilities.rb +0 -0
  399. data/lib/openc3/version.rb +5 -5
  400. data/lib/openc3/win32/excel.rb +0 -0
  401. data/lib/openc3/win32/win32.rb +0 -0
  402. data/lib/openc3/win32/win32_main.rb +0 -0
  403. data/lib/openc3.rb +2 -2
  404. data/tasks/gemfile_stats.rake +0 -0
  405. data/tasks/spec.rake +0 -0
  406. data/templates/command_validator/command_validator.py +0 -0
  407. data/templates/command_validator/command_validator.rb +0 -0
  408. data/templates/conversion/conversion.py +0 -0
  409. data/templates/conversion/conversion.rb +0 -0
  410. data/templates/limits_response/response.py +0 -0
  411. data/templates/limits_response/response.rb +0 -0
  412. data/templates/microservice/microservices/TEMPLATE/microservice.py +0 -0
  413. data/templates/microservice/microservices/TEMPLATE/microservice.rb +0 -0
  414. data/templates/plugin/.gitignore +0 -0
  415. data/templates/plugin/LICENSE.md +0 -0
  416. data/templates/plugin/README.md +0 -0
  417. data/templates/plugin/Rakefile +0 -0
  418. data/templates/plugin/plugin.gemspec +0 -0
  419. data/templates/plugin/plugin.txt +0 -0
  420. data/templates/processor/processor.py +1 -1
  421. data/templates/processor/processor.rb +0 -0
  422. data/templates/target/targets/TARGET/cmd_tlm/cmd.txt +0 -0
  423. data/templates/target/targets/TARGET/cmd_tlm/tlm.txt +0 -0
  424. data/templates/target/targets/TARGET/lib/target.py +0 -0
  425. data/templates/target/targets/TARGET/lib/target.rb +0 -0
  426. data/templates/target/targets/TARGET/procedures/procedure.py +0 -0
  427. data/templates/target/targets/TARGET/procedures/procedure.rb +0 -0
  428. data/templates/target/targets/TARGET/public/README.txt +0 -0
  429. data/templates/target/targets/TARGET/screens/status.txt +0 -0
  430. data/templates/target/targets/TARGET/target.txt +0 -0
  431. data/templates/tool_angular/.editorconfig +0 -0
  432. data/templates/tool_angular/.gitignore +0 -0
  433. data/templates/tool_angular/.vscode/extensions.json +0 -0
  434. data/templates/tool_angular/.vscode/launch.json +0 -0
  435. data/templates/tool_angular/.vscode/tasks.json +0 -0
  436. data/templates/tool_angular/angular.json +0 -0
  437. data/templates/tool_angular/extra-webpack.config.js +0 -0
  438. data/templates/tool_angular/package.json +2 -2
  439. data/templates/tool_angular/src/app/app-routing.module.ts +0 -0
  440. data/templates/tool_angular/src/app/app.component.html +0 -0
  441. data/templates/tool_angular/src/app/app.component.scss +0 -0
  442. data/templates/tool_angular/src/app/app.component.spec.ts +0 -0
  443. data/templates/tool_angular/src/app/app.component.ts +0 -0
  444. data/templates/tool_angular/src/app/app.module.ts +0 -0
  445. data/templates/tool_angular/src/app/custom-overlay-container.ts +0 -0
  446. data/templates/tool_angular/src/app/empty-route/empty-route.component.ts +0 -0
  447. data/templates/tool_angular/src/app/openc3-api.d.ts +0 -0
  448. data/templates/tool_angular/src/assets/.gitkeep +0 -0
  449. data/templates/tool_angular/src/environments/environment.prod.ts +0 -0
  450. data/templates/tool_angular/src/environments/environment.ts +0 -0
  451. data/templates/tool_angular/src/favicon.ico +0 -0
  452. data/templates/tool_angular/src/index.html +0 -0
  453. data/templates/tool_angular/src/main.single-spa.ts +0 -0
  454. data/templates/tool_angular/src/single-spa/asset-url.ts +0 -0
  455. data/templates/tool_angular/src/single-spa/single-spa-props.ts +0 -0
  456. data/templates/tool_angular/src/styles.scss +0 -0
  457. data/templates/tool_angular/tsconfig.app.json +0 -0
  458. data/templates/tool_angular/tsconfig.json +0 -0
  459. data/templates/tool_angular/tsconfig.spec.json +0 -0
  460. data/templates/tool_react/.eslintrc +0 -0
  461. data/templates/tool_react/.gitignore +0 -0
  462. data/templates/tool_react/.prettierignore +0 -0
  463. data/templates/tool_react/babel.config.json +0 -0
  464. data/templates/tool_react/jest.config.js +0 -0
  465. data/templates/tool_react/package.json +1 -1
  466. data/templates/tool_react/src/openc3-tool_name.js +0 -0
  467. data/templates/tool_react/src/root.component.js +0 -0
  468. data/templates/tool_react/src/root.component.test.js +0 -0
  469. data/templates/tool_react/webpack.config.js +0 -0
  470. data/templates/tool_svelte/.gitignore +0 -0
  471. data/templates/tool_svelte/.prettierignore +0 -0
  472. data/templates/tool_svelte/.prettierrc.js +0 -0
  473. data/templates/tool_svelte/babel.config.js +0 -0
  474. data/templates/tool_svelte/build/smui.css +0 -0
  475. data/templates/tool_svelte/jest.config.js +0 -0
  476. data/templates/tool_svelte/package.json +1 -1
  477. data/templates/tool_svelte/rollup.config.js +0 -0
  478. data/templates/tool_svelte/src/App.svelte +0 -0
  479. data/templates/tool_svelte/src/App.test.js +0 -0
  480. data/templates/tool_svelte/src/theme/_smui-theme.scss +0 -0
  481. data/templates/tool_svelte/src/tool_name.js +0 -0
  482. data/templates/tool_vue/.env.standalone +0 -0
  483. data/templates/tool_vue/.gitignore +0 -0
  484. data/templates/tool_vue/.prettierrc.cjs +0 -0
  485. data/templates/tool_vue/eslint.config.mjs +0 -0
  486. data/templates/tool_vue/jsconfig.json +0 -0
  487. data/templates/tool_vue/package.json +3 -3
  488. data/templates/tool_vue/src/App.vue +0 -0
  489. data/templates/tool_vue/src/main.js +0 -0
  490. data/templates/tool_vue/src/router.js +0 -0
  491. data/templates/tool_vue/src/tools/tool_name/tool_name.vue +0 -0
  492. data/templates/tool_vue/vite.config.js +1 -1
  493. data/templates/widget/.prettierrc.cjs +0 -0
  494. data/templates/widget/LICENSE.md +0 -0
  495. data/templates/widget/Rakefile +0 -0
  496. data/templates/widget/package.json +2 -2
  497. data/templates/widget/src/Widget.vue +0 -0
  498. data/templates/widget/vite.config.js +0 -0
  499. metadata +36 -9
@@ -18,6 +18,7 @@
18
18
  */
19
19
 
20
20
  #include "ruby.h"
21
+ #include "stdint.h"
21
22
  #include "stdio.h"
22
23
 
23
24
  #define TO_BIGNUM(x) (FIXNUM_P(x) ? rb_int2big(FIX2LONG(x)) : x)
@@ -400,11 +401,13 @@ static void check_bit_offset_and_size(VALUE self, VALUE type_param, VALUE bit_of
400
401
 
401
402
  if (bit_offset < 0)
402
403
  {
403
- bit_offset = ((int)(RSTRING_LEN(buffer_param) * 8) + bit_offset);
404
- if (bit_offset < 0)
404
+ /* Calculate in 64 bits since a large buffer times 8 does not fit in an int */
405
+ int64_t calculated_bit_offset = (((int64_t)RSTRING_LEN(buffer_param)) * 8) + bit_offset;
406
+ if ((calculated_bit_offset < 0) || (calculated_bit_offset > INT32_MAX))
405
407
  {
406
408
  rb_funcall(self, id_method_raise_buffer_error, 5, type_param, buffer_param, data_type_param, bit_offset_param, bit_size_param);
407
409
  }
410
+ bit_offset = (int)calculated_bit_offset;
408
411
  }
409
412
 
410
413
  *new_bit_offset = bit_offset;
@@ -418,23 +421,45 @@ static int even_bit_size(int bit_size)
418
421
 
419
422
  /* Calculate the bounds of the string to access the item based on the bit_offset and bit_size.
420
423
  * Also determine if the buffer size is sufficient. */
421
- static int check_bounds_and_buffer_size(int bit_offset, int bit_size, int buffer_length, VALUE endianness, VALUE data_type, int *lower_bound, int *upper_bound)
424
+ static int check_bounds_and_buffer_size(int bit_offset, int bit_size, long buffer_length, VALUE endianness, VALUE data_type, int *lower_bound, int *upper_bound)
422
425
  {
423
426
  int result = 1; /* Assume ok */
424
-
425
- /* Define bounds of string to access this item */
426
- *lower_bound = bit_offset / 8;
427
- *upper_bound = (bit_offset + bit_size - 1) / 8;
427
+ int64_t calculated_lower_bound = 0;
428
+ int64_t calculated_upper_bound = 0;
429
+
430
+ /* Calculate in 64 bits so attacker-controlled offsets and sizes cannot
431
+ * overflow before the buffer bounds are checked. */
432
+ calculated_lower_bound = ((int64_t)bit_offset) / 8;
433
+ calculated_upper_bound = (((int64_t)bit_offset) + ((int64_t)bit_size) - 1) / 8;
434
+ *lower_bound = (int)calculated_lower_bound;
435
+ *upper_bound = (int)calculated_upper_bound;
436
+
437
+ /* The read starts at lower_bound, so it must be checked independently of
438
+ * upper_bound. Also reject reversed bounds before considering the special
439
+ * little-endian bitfield case below. */
440
+ if ((calculated_lower_bound < 0) ||
441
+ (calculated_lower_bound >= buffer_length) ||
442
+ (calculated_upper_bound < calculated_lower_bound))
443
+ {
444
+ return 0;
445
+ }
428
446
 
429
447
  /* Sanity check buffer size */
430
- if (*upper_bound >= buffer_length)
448
+ if (calculated_upper_bound >= buffer_length)
431
449
  {
432
450
  /* If it's not the special case of little endian bit field then we fail and return 0 */
451
+ /* Note lower_bound is already known to be inside the buffer */
433
452
  if (!((endianness == symbol_LITTLE_ENDIAN) &&
434
453
  ((data_type == symbol_INT) || (data_type == symbol_UINT)) &&
435
454
  /* Not byte aligned with an even bit size */
436
- (!((BYTE_ALIGNED(bit_offset)) && (even_bit_size(bit_size)))) &&
437
- (*lower_bound < buffer_length)))
455
+ (!((BYTE_ALIGNED(bit_offset)) && (even_bit_size(bit_size))))))
456
+ {
457
+ result = 0;
458
+ }
459
+ /* Little endian bitfields are accessed backwards from bit_offset, so the bytes
460
+ * they span must all be inside the buffer. Checking this here keeps a huge
461
+ * bit_size from allocating memory before it is rejected. */
462
+ else if ((calculated_lower_bound - ((((bit_offset % 8) + ((int64_t)bit_size) - 1) / 8) + 1) + 1) < 0)
438
463
  {
439
464
  result = 0;
440
465
  }
@@ -456,8 +481,8 @@ static int check_bounds_and_buffer_size(int bit_offset, int bit_size, int buffer
456
481
  static VALUE binary_accessor_read(VALUE self, VALUE param_bit_offset, VALUE param_bit_size, VALUE param_data_type, VALUE param_buffer, VALUE param_endianness)
457
482
  {
458
483
  /* Convert Parameters to C Data Types */
459
- int bit_offset = FIX2INT(param_bit_offset);
460
- int bit_size = FIX2INT(param_bit_size);
484
+ int bit_offset = NUM2INT(param_bit_offset);
485
+ int bit_size = NUM2INT(param_bit_size);
461
486
 
462
487
  /* Local Variables */
463
488
  int given_bit_offset = bit_offset;
@@ -502,18 +527,20 @@ static VALUE binary_accessor_read(VALUE self, VALUE param_bit_offset, VALUE para
502
527
  * recalculate based on the buffer length */
503
528
  if ((bit_size <= 0) && ((param_data_type == symbol_STRING) || (param_data_type == symbol_BLOCK)))
504
529
  {
505
- bit_size = (((int)buffer_length * 8) - bit_offset + bit_size);
506
- if (bit_size == 0)
530
+ /* Calculate in 64 bits since a large buffer times 8 does not fit in an int */
531
+ int64_t calculated_bit_size = (((int64_t)buffer_length) * 8) - bit_offset + bit_size;
532
+ if (calculated_bit_size == 0)
507
533
  {
508
534
  return rb_str_new2("");
509
535
  }
510
- else if (bit_size < 0)
536
+ else if ((calculated_bit_size < 0) || (calculated_bit_size > INT32_MAX))
511
537
  {
512
538
  rb_funcall(self, id_method_raise_buffer_error, 5, symbol_read, param_buffer, param_data_type, param_bit_offset, param_bit_size);
513
539
  }
540
+ bit_size = (int)calculated_bit_size;
514
541
  }
515
542
 
516
- if (!check_bounds_and_buffer_size(bit_offset, bit_size, (int)buffer_length, param_endianness, param_data_type, &lower_bound, &upper_bound))
543
+ if (!check_bounds_and_buffer_size(bit_offset, bit_size, buffer_length, param_endianness, param_data_type, &lower_bound, &upper_bound))
517
544
  {
518
545
  /* Return nil for out-of-bounds reads (supports undersized packets with ALLOW_SHORT) */
519
546
  return Qnil;
@@ -1005,10 +1032,15 @@ static VALUE binary_accessor_write(VALUE self, VALUE value, VALUE param_bit_offs
1005
1032
  {
1006
1033
  value = rb_funcall(value, id_method_to_s, 0);
1007
1034
  }
1035
+ /* Calculate in 64 bits since a large value times 8 does not fit in an int */
1036
+ if ((((int64_t)RSTRING_LEN(value)) * 8) > INT32_MAX)
1037
+ {
1038
+ rb_funcall(self, id_method_raise_buffer_error, 5, symbol_write, param_buffer, param_data_type, param_bit_offset, param_bit_size);
1039
+ }
1008
1040
  bit_size = (int)RSTRING_LEN(value) * 8;
1009
1041
  }
1010
1042
 
1011
- if ((!check_bounds_and_buffer_size(bit_offset, bit_size, (int)buffer_length, param_endianness, param_data_type, &lower_bound, &upper_bound)) && (given_bit_size > 0))
1043
+ if ((!check_bounds_and_buffer_size(bit_offset, bit_size, buffer_length, param_endianness, param_data_type, &lower_bound, &upper_bound)) && (given_bit_size > 0))
1012
1044
  {
1013
1045
  rb_funcall(self, id_method_raise_buffer_error, 5, symbol_write, param_buffer, param_data_type, param_bit_offset, param_bit_size);
1014
1046
  }
File without changes
File without changes
File without changes
data/lib/cosmos.rb CHANGED
File without changes
data/lib/cosmosc2.rb CHANGED
File without changes
File without changes
@@ -105,35 +105,70 @@ module OpenC3
105
105
  HOST_ENDIANNESS = get_host_endianness()
106
106
  # Valid endianness
107
107
  ENDIANNESS = [:BIG_ENDIAN, :LITTLE_ENDIAN]
108
+ NATIVE_INT_MIN = -(2**31)
109
+ NATIVE_INT_MAX = (2**31) - 1
108
110
 
109
- def handle_read_variable_bit_size(item, _buffer)
111
+ def handle_read_variable_bit_size(item, buffer)
110
112
  length_value = @packet.read(item.variable_bit_size['length_item_name'], :CONVERTED)
111
113
  # length_value can be nil when reading an undersized packet where the length
112
114
  # item falls outside the buffer bounds
113
115
  raise "Length value #{item.variable_bit_size['length_item_name']} for item #{item.name} is nil" if length_value.nil?
114
116
 
115
117
  if item.array_size
116
- item.array_size = (length_value * item.variable_bit_size['length_bits_per_count']) + item.variable_bit_size['length_value_bit_offset']
118
+ array_size = (length_value * item.variable_bit_size['length_bits_per_count']) + item.variable_bit_size['length_value_bit_offset']
119
+ validate_variable_bit_size(item, array_size, buffer)
120
+ item.array_size = array_size
117
121
  else
118
122
  if item.data_type == :INT or item.data_type == :UINT
119
123
  # QUIC encoding is currently assumed for individual variable sized integers
120
124
  # see https://datatracker.ietf.org/doc/html/rfc9000#name-variable-length-integer-enc
121
125
  case length_value
122
126
  when 0
123
- item.bit_size = 6
127
+ bit_size = 6
124
128
  when 1
125
- item.bit_size = 14
129
+ bit_size = 14
126
130
  when 2
127
- item.bit_size = 30
131
+ bit_size = 30
128
132
  else
129
- item.bit_size = 62
133
+ bit_size = 62
130
134
  end
131
135
  else
132
- item.bit_size = (length_value * item.variable_bit_size['length_bits_per_count']) + item.variable_bit_size['length_value_bit_offset']
136
+ bit_size = (length_value * item.variable_bit_size['length_bits_per_count']) + item.variable_bit_size['length_value_bit_offset']
133
137
  end
138
+ validate_variable_bit_size(item, bit_size, buffer)
139
+ item.bit_size = bit_size
134
140
  end
135
141
  end
136
142
 
143
+ # A negative bit size is always invalid. A bit size larger than the buffer is
144
+ # only an error when the packet does not allow short buffers, otherwise the
145
+ # oversized item simply reads as nil (ALLOW_SHORT).
146
+ def validate_variable_bit_size(item, bit_size, buffer)
147
+ available_bit_size = (buffer.length * 8) - item.bit_offset
148
+ if bit_size < 0 || (!@packet.short_buffer_allowed && (available_bit_size < 0 || bit_size > available_bit_size))
149
+ raise ArgumentError, "Variable bit size #{bit_size} for item #{item.name} exceeds the #{[available_bit_size, 0].max} bits available in the buffer"
150
+ end
151
+ end
152
+
153
+ # The native accessor takes C ints, so values outside that range must be
154
+ # rejected here rather than raising RangeError out of the extension.
155
+ def native_value_out_of_range?(item)
156
+ [item.bit_offset, item.bit_size, item.array_size].compact.any? do |value|
157
+ value < NATIVE_INT_MIN || value > NATIVE_INT_MAX
158
+ end
159
+ end
160
+
161
+ # Items that derive their size from the buffer (0 or negative bit_size or
162
+ # array_size) calculate a negative size when the buffer ends before the item
163
+ # starts. Such an item is simply not present in a short buffer.
164
+ def derived_size_negative?(item, buffer)
165
+ available_bit_size = (buffer.length * 8) - item.bit_offset
166
+ if item.array_size
167
+ return item.array_size <= 0 && (available_bit_size + item.array_size) < 0
168
+ end
169
+ return item.bit_size <= 0 && (available_bit_size + item.bit_size) < 0
170
+ end
171
+
137
172
  def read_item(item, buffer)
138
173
  return nil if item.data_type == :DERIVED
139
174
  if item.parent_item
@@ -145,6 +180,9 @@ module OpenC3
145
180
  structure.read(item.key, :RAW, structure_buffer)
146
181
  else
147
182
  handle_read_variable_bit_size(item, buffer) if item.variable_bit_size
183
+ if @packet.short_buffer_allowed && (native_value_out_of_range?(item) || derived_size_negative?(item, buffer))
184
+ return nil
185
+ end
148
186
  self.class.read_item(item, buffer)
149
187
  end
150
188
  end
@@ -288,6 +326,11 @@ module OpenC3
288
326
  self.class.write_item(parent_item, structure_buffer, buffer)
289
327
  else
290
328
  handle_write_variable_bit_size(item, value, buffer) if item.variable_bit_size
329
+ # Raise the normal buffer error rather than letting the native accessor
330
+ # raise RangeError when converting the offset or size to a C int
331
+ if native_value_out_of_range?(item)
332
+ self.class.raise_buffer_error(:write, buffer, item.data_type, item.bit_offset, item.bit_size)
333
+ end
291
334
  self.class.write_item(item, value, buffer)
292
335
  end
293
336
  end
@@ -800,16 +843,27 @@ module OpenC3
800
843
  lower_bound = bit_offset / 8
801
844
  upper_bound = (bit_offset + bit_size - 1) / 8
802
845
 
846
+ # The access starts at lower_bound, so validate it independently rather
847
+ # than relying on upper_bound to imply that it is safe.
848
+ if lower_bound < 0 || lower_bound >= buffer_length || upper_bound < lower_bound
849
+ return false, lower_bound, upper_bound
850
+ end
851
+
803
852
  # Sanity check buffer size
804
853
  if upper_bound >= buffer_length
805
854
  # If it's not the special case of little endian bit field then we fail and return false
855
+ # Note lower_bound is already known to be inside the buffer
806
856
  if !((endianness == :LITTLE_ENDIAN) &&
807
857
  ((data_type == :INT) || (data_type == :UINT)) &&
808
858
  # Not byte aligned with an even bit size
809
- (!((byte_aligned(bit_offset)) && (even_bit_size(bit_size)))) &&
810
- (lower_bound < buffer_length)
859
+ (!((byte_aligned(bit_offset)) && (even_bit_size(bit_size))))
811
860
  )
812
861
  result = false
862
+ # Little endian bitfields are accessed backwards from bit_offset, so the
863
+ # bytes they span must all be inside the buffer. Checking this here keeps
864
+ # a huge bit_size from allocating memory before it is rejected.
865
+ elsif (lower_bound - ((((bit_offset % 8) + bit_size - 1) / 8) + 1) + 1) < 0
866
+ result = false
813
867
  end
814
868
  end
815
869
  return result, lower_bound, upper_bound
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -484,7 +484,7 @@ module OpenC3
484
484
  user = authorize(permission: 'cmd', target_name: target_name, packet_name: cmd_name, manual: manual, scope: scope, token: token)
485
485
  if user.nil?
486
486
  user = {}
487
- user['username'] = ENV['OPENC3_MICROSERVICE_NAME']
487
+ user['username'] = ENV.fetch('OPENC3_MICROSERVICE_NAME', nil)
488
488
 
489
489
  # Get the caller stack trace to determine the point in the code where the command was called
490
490
  # This code works but ultimately we didn't want to overload 'username' and take a performance hit
File without changes
File without changes
File without changes
@@ -1,6 +1,6 @@
1
1
  # encoding: ascii-8bit
2
2
 
3
- # Copyright 2023 OpenC3, Inc
3
+ # Copyright 2026 OpenC3, Inc.
4
4
  # All Rights Reserved.
5
5
  #
6
6
  # This program is distributed in the hope that it will be useful,
@@ -1,6 +1,6 @@
1
1
  # encoding: ascii-8bit
2
2
 
3
- # Copyright 2022 OpenC3, Inc
3
+ # Copyright 2026 OpenC3, Inc.
4
4
  # All Rights Reserved.
5
5
  #
6
6
  # This program is distributed in the hope that it will be useful,
File without changes
@@ -81,26 +81,30 @@ module OpenC3
81
81
 
82
82
  # Update the news feed on demand to respond to frontend setting changes
83
83
  def update_news(manual: false, scope: $openc3_scope, token: $openc3_token)
84
+ # Authorize outside the begin/rescue so AuthError propagates to the caller
85
+ # rather than being swallowed and written into the news feed
84
86
  authorize(permission: 'admin', manual: manual, scope: scope, token: token)
85
- conn = Faraday.new(
86
- url: 'https://news.openc3.com',
87
- params: {version: VERSION, enterprise: ENTERPRISE},
88
- )
89
- response = conn.get('/news')
90
- if response.success?
91
- NewsModel.set(response.body)
92
- else
93
- NewsModel.news_error("Error contacting OpenC3 news feed (status: #{response.status})")
94
- end
87
+ begin
88
+ conn = Faraday.new(
89
+ url: 'https://news.openc3.com',
90
+ params: {version: VERSION, enterprise: ENTERPRISE},
91
+ )
92
+ response = conn.get('/news')
93
+ if response.success?
94
+ NewsModel.set(response.body)
95
+ else
96
+ NewsModel.news_error("Error contacting OpenC3 news feed (status: #{response.status})")
97
+ end
95
98
 
96
- # Test code to update the news feed with a dummy message
97
- # data = NewsModel.all()
98
- # json = JSON.parse(data)
99
- # json.unshift( { date: Time.now.utc.iso8601, title: "News at #{Time.now}", body: "The news feed has been updated at #{Time.now}." })
100
- # json.pop if json.length > 5
101
- # NewsModel.set(json.to_json)
102
- rescue Exception => e
103
- NewsModel.news_error("Error contacting OpenC3 news feed. #{e.message})")
99
+ # Test code to update the news feed with a dummy message
100
+ # data = NewsModel.all()
101
+ # json = JSON.parse(data)
102
+ # json.unshift( { date: Time.now.utc.iso8601, title: "News at #{Time.now}", body: "The news feed has been updated at #{Time.now}." })
103
+ # json.pop if json.length > 5
104
+ # NewsModel.set(json.to_json)
105
+ rescue StandardError => e
106
+ NewsModel.news_error("Error contacting OpenC3 news feed. #{e.message}")
107
+ end
104
108
  end
105
109
 
106
110
  # Update the local copy of the plugin store data
@@ -1,6 +1,6 @@
1
1
  # encoding: ascii-8bit
2
2
 
3
- # Copyright 2024 OpenC3, Inc
3
+ # Copyright 2026 OpenC3, Inc.
4
4
  # All Rights Reserved.
5
5
  #
6
6
  # This program is distributed in the hope that it will be useful,
File without changes
@@ -117,7 +117,8 @@ module OpenC3
117
117
  # @param packet_name [String] Packet name of the packet
118
118
  # @param item_hash [Hash] Hash of item_name and value for each item you want to change from the current value table
119
119
  # @param type [Symbol] Telemetry type, :RAW, :CONVERTED (default), :FORMATTED
120
- def inject_tlm(target_name, packet_name, item_hash = nil, type: :CONVERTED, stored: false, manual: false, scope: $openc3_scope, token: $openc3_token)
120
+ # @param received_time [Integer, nil] Optional received time as nanoseconds since Unix epoch
121
+ def inject_tlm(target_name, packet_name, item_hash = nil, type: :CONVERTED, stored: false, received_time: nil, manual: false, scope: $openc3_scope, token: $openc3_token)
121
122
  authorize(permission: 'tlm_set', target_name: target_name, packet_name: packet_name, manual: manual, scope: scope, token: token)
122
123
  type = type.to_s.intern
123
124
  target_name = target_name.upcase
@@ -155,9 +156,9 @@ module OpenC3
155
156
 
156
157
  # Use an interface microservice if it exists, other use the decom microservice
157
158
  if interface_name
158
- InterfaceTopic.inject_tlm(interface_name, target_name, packet_name, item_hash, type: type, stored: stored, scope: scope)
159
+ InterfaceTopic.inject_tlm(interface_name, target_name, packet_name, item_hash, type: type, stored: stored, received_time: received_time, scope: scope)
159
160
  else
160
- DecomInterfaceTopic.inject_tlm(target_name, packet_name, item_hash, type: type, stored: stored, scope: scope)
161
+ DecomInterfaceTopic.inject_tlm(target_name, packet_name, item_hash, type: type, stored: stored, received_time: received_time, scope: scope)
161
162
  end
162
163
  end
163
164
 
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -166,19 +166,46 @@ module OpenC3
166
166
  return ERB.new(read_file(template_name).comment_erb(), trim_mode: "-").result(b)
167
167
  end
168
168
 
169
- # Can be called during parsing to read a referenced file
169
+ # Can be called during parsing to read a referenced file. The filename must
170
+ # be relative to the configuration file being parsed and must resolve to a
171
+ # location inside that file's directory.
170
172
  def read_file(filename)
171
- # Assume the file is there. If not we raise a pretty obvious error
172
- if File.expand_path(filename) == filename # absolute path
173
- path = filename
174
- else # relative to the current @filename
175
- path = File.join(File.dirname(@filename), filename)
176
- end
173
+ path = resolve_config_path(filename)
177
174
  OpenC3.set_working_dir(File.dirname(path)) do
178
175
  return File.read(path).force_encoding("UTF-8")
179
176
  end
180
177
  end
181
178
 
179
+ # Resolves a filename referenced by a configuration file (TEMPLATE_FILE, ERB
180
+ # render, etc) into an absolute path contained by the directory of the file
181
+ # being parsed. Absolute paths and paths containing '..' are rejected so a
182
+ # configuration file can not read arbitrary files on the filesystem.
183
+ #
184
+ # @param filename [String] Relative path from the configuration file
185
+ # @return [String] Absolute path to the referenced file
186
+ private def resolve_config_path(filename)
187
+ filename = filename.to_s
188
+ raise Error.new(self, "Filename must be given") if filename.strip.empty?
189
+
190
+ if File.absolute_path?(filename) or File.expand_path(filename) == filename
191
+ raise Error.new(self, "Absolute paths are not allowed: #{filename}")
192
+ end
193
+ if filename.include?('..')
194
+ raise Error.new(self, "Path traversal is not allowed: #{filename}")
195
+ end
196
+ if @filename.nil? or @filename.to_s.empty?
197
+ raise Error.new(self, "No configuration file is being parsed, can not resolve: #{filename}")
198
+ end
199
+
200
+ base = File.expand_path(File.dirname(@filename))
201
+ path = File.expand_path(File.join(base, filename))
202
+ # Final containment check in case the OS or Ruby normalizes something unexpected
203
+ unless path.start_with?(base + File::SEPARATOR)
204
+ raise Error.new(self, "Path is outside the configuration directory: #{filename}")
205
+ end
206
+ path
207
+ end
208
+
182
209
  # Processes a file and yields |config| to the given block
183
210
  #
184
211
  # @param filename [String] The full name and path of the configuration file
@@ -307,6 +334,38 @@ module OpenC3
307
334
  return value
308
335
  end
309
336
 
337
+ # Values handle_true_false_strict accepts. Deliberately NOT shared with
338
+ # handle_true_false, which passes unrecognized values through and so can't
339
+ # tell the number 1 from a boolean - TABLE_MANAGER item defaults rely on 1
340
+ # staying 1. Named and scoped so they can't be mistaken for a truth table
341
+ # the whole parser honors.
342
+ STRICT_TRUE_VALUES = ['TRUE', '1']
343
+ STRICT_FALSE_VALUES = ['FALSE', '0', '']
344
+ private_constant :STRICT_TRUE_VALUES, :STRICT_FALSE_VALUES
345
+
346
+ # Converts a String containing 'TRUE', '1', 'FALSE', '0' or '' to a true or
347
+ # false Ruby primitive. Unlike handle_true_false, which returns anything it
348
+ # doesn't recognize unchanged, an unrecognized value raises.
349
+ #
350
+ # Use this for a flag where guessing is worse than failing - notably an
351
+ # environment variable that is enabled by presence elsewhere in COSMOS, so
352
+ # that 'VAR=false' (or 'VAR=0') means off here rather than the surprising on.
353
+ #
354
+ # @param value [Object] value to convert, nil returns the default
355
+ # @param description [String] what the value is, used in the error message
356
+ # @param default [true|false] returned when value is nil
357
+ # @return [true|false]
358
+ def self.handle_true_false_strict(value, description: 'value', default: false)
359
+ return default if value.nil?
360
+ normalized = value.to_s.strip.upcase
361
+ return true if STRICT_TRUE_VALUES.include?(normalized)
362
+ return false if STRICT_FALSE_VALUES.include?(normalized)
363
+ # Name empty explicitly - it is accepted (as false) but isn't a value
364
+ # anyone can read off the list
365
+ raise ArgumentError, "Invalid value #{value.to_s.strip.inspect} for #{description}. " \
366
+ "Must be one of: #{(STRICT_TRUE_VALUES + STRICT_FALSE_VALUES - ['']).join(', ')}, or empty"
367
+ end
368
+
310
369
  # Converts a String containing '', 'NIL', 'NULL', 'TRUE' or 'FALSE' to nil,
311
370
  # true or false Ruby primitives. All other values are simply returned.
312
371
  #
@@ -321,6 +380,8 @@ module OpenC3
321
380
  return false
322
381
  when '', 'NIL', 'NULL'
323
382
  return nil
383
+ else
384
+ # All other strings are returned unmodified below
324
385
  end
325
386
  end
326
387
  return value
@@ -378,11 +439,12 @@ module OpenC3
378
439
  return Float::INFINITY
379
440
  when 'NEG_INFINITY'
380
441
  return -Float::INFINITY
442
+ else
443
+ # NOTE: The else case does not raise because of the following scenario:
444
+ # If the value type is a UINT but they have a WRITE_CONVERSION that takes a string
445
+ # then the default value will be a string. In that case we just want to return the string.
446
+ # For example, the IP_ADDRESS parameter in the TIME_OFFSET command in the Demo plugin.
381
447
  end
382
- # NOTE: No else case because of the following scenario:
383
- # If the value type is a UINT but they have a WRITE_CONVERSION that takes a string
384
- # then the default value will be a string. In that case we just want to return the string.
385
- # For example, the IP_ADDRESS parameter in the TIME_OFFSET command in the Demo plugin.
386
448
  end
387
449
  return value
388
450
  end
@@ -494,8 +556,8 @@ module OpenC3
494
556
  while true
495
557
  @line_number += 1
496
558
 
497
- if @@progress_callback && ((@line_number % 10) == 0)
498
- @@progress_callback.call(io.pos / size) if size > 0.0
559
+ if @@progress_callback && ((@line_number % 10) == 0) && size > 0.0
560
+ @@progress_callback.call(io.pos / size)
499
561
  end
500
562
 
501
563
  begin
@@ -586,10 +648,9 @@ module OpenC3
586
648
  # KEYWORD PARAM #This is a comment
587
649
  # But still process Ruby string interpolations such as:
588
650
  # KEYWORD PARAM #{var}
589
- if (string.length > 0) && (string[0] == '#')
590
- if !((string.length > 1) && (string[1] == '{'))
591
- break
592
- end
651
+ if (string.length > 0) && (string[0] == '#') &&
652
+ !((string.length > 1) && (string[1] == '{'))
653
+ break
593
654
  end
594
655
 
595
656
  if remove_quotes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes