oscura 0.8.0__py3-none-any.whl → 0.11.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (161) hide show
  1. oscura/__init__.py +19 -19
  2. oscura/__main__.py +4 -0
  3. oscura/analyzers/__init__.py +2 -0
  4. oscura/analyzers/digital/extraction.py +2 -3
  5. oscura/analyzers/digital/quality.py +1 -1
  6. oscura/analyzers/digital/timing.py +1 -1
  7. oscura/analyzers/ml/signal_classifier.py +6 -0
  8. oscura/analyzers/patterns/__init__.py +66 -0
  9. oscura/analyzers/power/basic.py +3 -3
  10. oscura/analyzers/power/soa.py +1 -1
  11. oscura/analyzers/power/switching.py +3 -3
  12. oscura/analyzers/signal_classification.py +529 -0
  13. oscura/analyzers/signal_integrity/sparams.py +3 -3
  14. oscura/analyzers/statistics/basic.py +10 -7
  15. oscura/analyzers/validation.py +1 -1
  16. oscura/analyzers/waveform/measurements.py +200 -156
  17. oscura/analyzers/waveform/measurements_with_uncertainty.py +91 -35
  18. oscura/analyzers/waveform/spectral.py +182 -84
  19. oscura/api/dsl/commands.py +15 -6
  20. oscura/api/server/templates/base.html +137 -146
  21. oscura/api/server/templates/export.html +84 -110
  22. oscura/api/server/templates/home.html +248 -267
  23. oscura/api/server/templates/protocols.html +44 -48
  24. oscura/api/server/templates/reports.html +27 -35
  25. oscura/api/server/templates/session_detail.html +68 -78
  26. oscura/api/server/templates/sessions.html +62 -72
  27. oscura/api/server/templates/waveforms.html +54 -64
  28. oscura/automotive/__init__.py +1 -1
  29. oscura/automotive/can/session.py +1 -1
  30. oscura/automotive/dbc/generator.py +638 -23
  31. oscura/automotive/dtc/data.json +17 -102
  32. oscura/automotive/flexray/fibex.py +9 -1
  33. oscura/automotive/uds/decoder.py +99 -6
  34. oscura/cli/analyze.py +8 -2
  35. oscura/cli/batch.py +36 -5
  36. oscura/cli/characterize.py +18 -4
  37. oscura/cli/export.py +47 -5
  38. oscura/cli/main.py +2 -0
  39. oscura/cli/onboarding/wizard.py +10 -6
  40. oscura/cli/pipeline.py +585 -0
  41. oscura/cli/visualize.py +6 -4
  42. oscura/convenience.py +400 -32
  43. oscura/core/measurement_result.py +286 -0
  44. oscura/core/progress.py +1 -1
  45. oscura/core/schemas/device_mapping.json +2 -8
  46. oscura/core/schemas/packet_format.json +4 -24
  47. oscura/core/schemas/protocol_definition.json +2 -12
  48. oscura/core/types.py +232 -239
  49. oscura/correlation/multi_protocol.py +1 -1
  50. oscura/export/legacy/__init__.py +11 -0
  51. oscura/export/legacy/wav.py +75 -0
  52. oscura/exporters/__init__.py +19 -0
  53. oscura/exporters/wireshark.py +809 -0
  54. oscura/hardware/acquisition/file.py +5 -19
  55. oscura/hardware/acquisition/saleae.py +10 -10
  56. oscura/hardware/acquisition/socketcan.py +4 -6
  57. oscura/hardware/acquisition/synthetic.py +1 -5
  58. oscura/hardware/acquisition/visa.py +6 -6
  59. oscura/hardware/security/side_channel_detector.py +5 -508
  60. oscura/inference/message_format.py +686 -1
  61. oscura/jupyter/display.py +2 -2
  62. oscura/jupyter/magic.py +3 -3
  63. oscura/loaders/__init__.py +17 -12
  64. oscura/loaders/binary.py +1 -1
  65. oscura/loaders/chipwhisperer.py +1 -2
  66. oscura/loaders/configurable.py +1 -1
  67. oscura/loaders/csv_loader.py +2 -2
  68. oscura/loaders/hdf5_loader.py +1 -1
  69. oscura/loaders/lazy.py +6 -1
  70. oscura/loaders/mmap_loader.py +0 -1
  71. oscura/loaders/numpy_loader.py +8 -7
  72. oscura/loaders/preprocessing.py +3 -5
  73. oscura/loaders/rigol.py +21 -7
  74. oscura/loaders/sigrok.py +2 -5
  75. oscura/loaders/tdms.py +3 -2
  76. oscura/loaders/tektronix.py +38 -32
  77. oscura/loaders/tss.py +20 -27
  78. oscura/loaders/validation.py +17 -10
  79. oscura/loaders/vcd.py +13 -8
  80. oscura/loaders/wav.py +1 -6
  81. oscura/pipeline/__init__.py +76 -0
  82. oscura/pipeline/handlers/__init__.py +165 -0
  83. oscura/pipeline/handlers/analyzers.py +1045 -0
  84. oscura/pipeline/handlers/decoders.py +899 -0
  85. oscura/pipeline/handlers/exporters.py +1103 -0
  86. oscura/pipeline/handlers/filters.py +891 -0
  87. oscura/pipeline/handlers/loaders.py +640 -0
  88. oscura/pipeline/handlers/transforms.py +768 -0
  89. oscura/reporting/formatting/measurements.py +55 -14
  90. oscura/reporting/templates/enhanced/protocol_re.html +504 -503
  91. oscura/sessions/legacy.py +49 -1
  92. oscura/side_channel/__init__.py +38 -57
  93. oscura/utils/builders/signal_builder.py +5 -5
  94. oscura/utils/comparison/compare.py +7 -9
  95. oscura/utils/comparison/golden.py +1 -1
  96. oscura/utils/filtering/convenience.py +2 -2
  97. oscura/utils/math/arithmetic.py +38 -62
  98. oscura/utils/math/interpolation.py +20 -20
  99. oscura/utils/pipeline/__init__.py +4 -17
  100. oscura/utils/progressive.py +1 -4
  101. oscura/utils/triggering/edge.py +1 -1
  102. oscura/utils/triggering/pattern.py +2 -2
  103. oscura/utils/triggering/pulse.py +2 -2
  104. oscura/utils/triggering/window.py +3 -3
  105. oscura/validation/hil_testing.py +11 -11
  106. oscura/visualization/__init__.py +46 -284
  107. oscura/visualization/batch.py +72 -433
  108. oscura/visualization/plot.py +542 -53
  109. oscura/visualization/styles.py +184 -318
  110. oscura/workflows/batch/advanced.py +1 -1
  111. oscura/workflows/batch/aggregate.py +12 -9
  112. oscura/workflows/complete_re.py +251 -23
  113. oscura/workflows/digital.py +27 -4
  114. oscura/workflows/multi_trace.py +136 -17
  115. oscura/workflows/waveform.py +11 -6
  116. oscura-0.11.0.dist-info/METADATA +460 -0
  117. {oscura-0.8.0.dist-info → oscura-0.11.0.dist-info}/RECORD +120 -145
  118. oscura/side_channel/dpa.py +0 -1025
  119. oscura/utils/optimization/__init__.py +0 -19
  120. oscura/utils/optimization/parallel.py +0 -443
  121. oscura/utils/optimization/search.py +0 -532
  122. oscura/utils/pipeline/base.py +0 -338
  123. oscura/utils/pipeline/composition.py +0 -248
  124. oscura/utils/pipeline/parallel.py +0 -449
  125. oscura/utils/pipeline/pipeline.py +0 -375
  126. oscura/utils/search/__init__.py +0 -16
  127. oscura/utils/search/anomaly.py +0 -424
  128. oscura/utils/search/context.py +0 -294
  129. oscura/utils/search/pattern.py +0 -288
  130. oscura/utils/storage/__init__.py +0 -61
  131. oscura/utils/storage/database.py +0 -1166
  132. oscura/visualization/accessibility.py +0 -526
  133. oscura/visualization/annotations.py +0 -371
  134. oscura/visualization/axis_scaling.py +0 -305
  135. oscura/visualization/colors.py +0 -451
  136. oscura/visualization/digital.py +0 -436
  137. oscura/visualization/eye.py +0 -571
  138. oscura/visualization/histogram.py +0 -281
  139. oscura/visualization/interactive.py +0 -1035
  140. oscura/visualization/jitter.py +0 -1042
  141. oscura/visualization/keyboard.py +0 -394
  142. oscura/visualization/layout.py +0 -400
  143. oscura/visualization/optimization.py +0 -1079
  144. oscura/visualization/palettes.py +0 -446
  145. oscura/visualization/power.py +0 -508
  146. oscura/visualization/power_extended.py +0 -955
  147. oscura/visualization/presets.py +0 -469
  148. oscura/visualization/protocols.py +0 -1246
  149. oscura/visualization/render.py +0 -223
  150. oscura/visualization/rendering.py +0 -444
  151. oscura/visualization/reverse_engineering.py +0 -838
  152. oscura/visualization/signal_integrity.py +0 -989
  153. oscura/visualization/specialized.py +0 -643
  154. oscura/visualization/spectral.py +0 -1226
  155. oscura/visualization/thumbnails.py +0 -340
  156. oscura/visualization/time_axis.py +0 -351
  157. oscura/visualization/waveform.py +0 -454
  158. oscura-0.8.0.dist-info/METADATA +0 -661
  159. {oscura-0.8.0.dist-info → oscura-0.11.0.dist-info}/WHEEL +0 -0
  160. {oscura-0.8.0.dist-info → oscura-0.11.0.dist-info}/entry_points.txt +0 -0
  161. {oscura-0.8.0.dist-info → oscura-0.11.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,525 +1,526 @@
1
- <!DOCTYPE html>
1
+ <!doctype html>
2
2
  <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>{{ title }}</title>
7
7
  <script src="https://cdn.plot.ly/plotly-2.27.0.min.js"></script>
8
8
  <style>
9
- :root {
10
- --bg-color: {{ theme.background_color }};
11
- --text-color: {{ theme.text_color }};
12
- --primary-color: {{ theme.primary_color }};
13
- --secondary-color: {{ theme.secondary_color }};
14
- --border-color: {{ theme.border_color }};
15
- --code-bg: {{ theme.code_background }};
16
- }
17
-
18
- * {
19
- box-sizing: border-box;
20
- margin: 0;
21
- padding: 0;
22
- }
23
-
24
- body {
25
- font-family: 'Segoe UI', -apple-system, BlinkMacSystemFont, Roboto, sans-serif;
26
- line-height: 1.6;
27
- background-color: var(--bg-color);
28
- color: var(--text-color);
29
- padding: 0;
30
- }
31
-
32
- .container {
33
- max-width: 1400px;
34
- margin: 0 auto;
35
- padding: 40px 20px;
36
- }
37
-
38
- /* Header */
39
- .header {
40
- background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
41
- color: white;
42
- padding: 60px 40px;
43
- margin: -40px -20px 40px -20px;
44
- box-shadow: 0 4px 6px rgba(0,0,0,0.1);
45
- }
46
-
47
- .header h1 {
48
- font-size: 2.5rem;
49
- margin-bottom: 10px;
50
- font-weight: 600;
51
- }
52
-
53
- .header .meta {
54
- opacity: 0.9;
55
- font-size: 0.95rem;
56
- }
57
-
58
- /* Table of Contents */
59
- .toc {
60
- background: var(--code-bg);
61
- border-left: 4px solid var(--primary-color);
62
- padding: 20px;
63
- margin: 30px 0;
64
- border-radius: 4px;
65
- }
66
-
67
- .toc h2 {
68
- margin-bottom: 15px;
69
- font-size: 1.3rem;
70
- }
71
-
72
- .toc ul {
73
- list-style: none;
74
- }
75
-
76
- .toc li {
77
- margin: 8px 0;
78
- }
79
-
80
- .toc a {
81
- color: var(--secondary-color);
82
- text-decoration: none;
83
- transition: color 0.2s;
84
- }
85
-
86
- .toc a:hover {
87
- color: var(--primary-color);
88
- text-decoration: underline;
89
- }
90
-
91
- /* Sections */
92
- .section {
93
- margin: 50px 0;
94
- scroll-margin-top: 20px;
95
- }
96
-
97
- .section h2 {
98
- color: var(--primary-color);
99
- border-bottom: 3px solid var(--primary-color);
100
- padding-bottom: 12px;
101
- margin-bottom: 25px;
102
- font-size: 1.8rem;
103
- }
104
-
105
- .section h3 {
106
- color: var(--secondary-color);
107
- margin-top: 30px;
108
- margin-bottom: 15px;
109
- font-size: 1.4rem;
110
- }
111
-
112
- /* Cards */
113
- .card {
114
- background: var(--code-bg);
115
- border: 1px solid var(--border-color);
116
- border-radius: 8px;
117
- padding: 25px;
118
- margin: 20px 0;
119
- box-shadow: 0 2px 4px rgba(0,0,0,0.05);
120
- }
121
-
122
- .card-header {
123
- font-weight: 600;
124
- color: var(--primary-color);
125
- margin-bottom: 15px;
126
- font-size: 1.1rem;
127
- }
128
-
129
- /* Tables */
130
- table {
131
- width: 100%;
132
- border-collapse: collapse;
133
- margin: 20px 0;
134
- background: white;
135
- box-shadow: 0 2px 4px rgba(0,0,0,0.05);
136
- }
137
-
138
- th {
139
- background: var(--primary-color);
140
- color: white;
141
- padding: 15px;
142
- text-align: left;
143
- font-weight: 600;
144
- }
145
-
146
- td {
147
- padding: 12px 15px;
148
- border-bottom: 1px solid var(--border-color);
149
- }
150
-
151
- tr:nth-child(even) {
152
- background-color: rgba(0,0,0,0.02);
153
- }
154
-
155
- tr:hover {
156
- background-color: rgba(0,0,0,0.05);
157
- }
158
-
159
- /* Badges */
160
- .badge {
161
- display: inline-block;
162
- padding: 4px 12px;
163
- border-radius: 12px;
164
- font-size: 0.85rem;
165
- font-weight: 600;
166
- }
167
-
168
- .badge-success {
169
- background: #d4edda;
170
- color: #155724;
171
- }
172
-
173
- .badge-warning {
174
- background: #fff3cd;
175
- color: #856404;
176
- }
177
-
178
- .badge-danger {
179
- background: #f8d7da;
180
- color: #721c24;
181
- }
182
-
183
- /* Warnings */
184
- .warning {
185
- background: #fff3cd;
186
- border-left: 4px solid #ffc107;
187
- padding: 15px;
188
- margin: 15px 0;
189
- border-radius: 4px;
190
- }
191
-
192
- .warning::before {
193
- content: "⚠ ";
194
- font-weight: bold;
195
- }
196
-
197
- /* Plots */
198
- .plot-container {
199
- margin: 30px 0;
200
- padding: 20px;
201
- background: white;
202
- border-radius: 8px;
203
- box-shadow: 0 2px 8px rgba(0,0,0,0.1);
204
- }
205
-
206
- .plot-title {
207
- font-size: 1.2rem;
208
- font-weight: 600;
209
- margin-bottom: 15px;
210
- color: var(--primary-color);
211
- }
212
-
213
- .plot-container img {
214
- max-width: 100%;
215
- height: auto;
216
- display: block;
217
- margin: 0 auto;
218
- }
219
-
220
- /* Artifacts List */
221
- .artifacts-list {
222
- list-style: none;
223
- padding: 0;
224
- }
225
-
226
- .artifacts-list li {
227
- background: var(--code-bg);
228
- padding: 15px;
229
- margin: 10px 0;
230
- border-left: 4px solid var(--secondary-color);
231
- border-radius: 4px;
232
- }
233
-
234
- .artifacts-list strong {
235
- color: var(--primary-color);
236
- }
237
-
238
- /* Metrics Grid */
239
- .metrics-grid {
240
- display: grid;
241
- grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
242
- gap: 20px;
243
- margin: 20px 0;
244
- }
245
-
246
- .metric-card {
247
- background: var(--code-bg);
248
- padding: 20px;
249
- border-radius: 8px;
250
- text-align: center;
251
- border: 1px solid var(--border-color);
252
- }
253
-
254
- .metric-value {
255
- font-size: 2rem;
256
- font-weight: 700;
257
- color: var(--primary-color);
258
- margin: 10px 0;
259
- }
260
-
261
- .metric-label {
262
- font-size: 0.9rem;
263
- color: var(--text-color);
264
- opacity: 0.8;
265
- }
266
-
267
- /* Code blocks */
268
- code {
269
- background: var(--code-bg);
270
- padding: 2px 6px;
271
- border-radius: 3px;
272
- font-family: 'Consolas', 'Monaco', monospace;
273
- font-size: 0.9em;
274
- }
275
-
276
- /* Responsive */
277
- @media (max-width: 768px) {
278
- .header {
279
- padding: 40px 20px;
280
- }
281
-
282
- .header h1 {
283
- font-size: 2rem;
284
- }
285
-
286
- .section h2 {
287
- font-size: 1.5rem;
288
- }
289
-
290
- .metrics-grid {
291
- grid-template-columns: 1fr;
292
- }
293
- }
294
-
295
- /* Print styles */
296
- @media print {
297
- .header {
298
- background: white !important;
299
- color: black !important;
300
- box-shadow: none !important;
301
- }
302
-
303
- .toc {
304
- display: none;
305
- }
306
-
307
- .section {
308
- page-break-inside: avoid;
309
- }
310
- }
9
+ :root {
10
+ --bg-color: {{ theme.background_color }};
11
+ --text-color: {{ theme.text_color }};
12
+ --primary-color: {{ theme.primary_color }};
13
+ --secondary-color: {{ theme.secondary_color }};
14
+ --border-color: {{ theme.border_color }};
15
+ --code-bg: {{ theme.code_background }};
16
+ }
17
+
18
+ * {
19
+ box-sizing: border-box;
20
+ margin: 0;
21
+ padding: 0;
22
+ }
23
+
24
+ body {
25
+ font-family: 'Segoe UI', -apple-system, BlinkMacSystemFont, Roboto, sans-serif;
26
+ line-height: 1.6;
27
+ background-color: var(--bg-color);
28
+ color: var(--text-color);
29
+ padding: 0;
30
+ }
31
+
32
+ .container {
33
+ max-width: 1400px;
34
+ margin: 0 auto;
35
+ padding: 40px 20px;
36
+ }
37
+
38
+ /* Header */
39
+ .header {
40
+ background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
41
+ color: white;
42
+ padding: 60px 40px;
43
+ margin: -40px -20px 40px -20px;
44
+ box-shadow: 0 4px 6px rgba(0,0,0,0.1);
45
+ }
46
+
47
+ .header h1 {
48
+ font-size: 2.5rem;
49
+ margin-bottom: 10px;
50
+ font-weight: 600;
51
+ }
52
+
53
+ .header .meta {
54
+ opacity: 0.9;
55
+ font-size: 0.95rem;
56
+ }
57
+
58
+ /* Table of Contents */
59
+ .toc {
60
+ background: var(--code-bg);
61
+ border-left: 4px solid var(--primary-color);
62
+ padding: 20px;
63
+ margin: 30px 0;
64
+ border-radius: 4px;
65
+ }
66
+
67
+ .toc h2 {
68
+ margin-bottom: 15px;
69
+ font-size: 1.3rem;
70
+ }
71
+
72
+ .toc ul {
73
+ list-style: none;
74
+ }
75
+
76
+ .toc li {
77
+ margin: 8px 0;
78
+ }
79
+
80
+ .toc a {
81
+ color: var(--secondary-color);
82
+ text-decoration: none;
83
+ transition: color 0.2s;
84
+ }
85
+
86
+ .toc a:hover {
87
+ color: var(--primary-color);
88
+ text-decoration: underline;
89
+ }
90
+
91
+ /* Sections */
92
+ .section {
93
+ margin: 50px 0;
94
+ scroll-margin-top: 20px;
95
+ }
96
+
97
+ .section h2 {
98
+ color: var(--primary-color);
99
+ border-bottom: 3px solid var(--primary-color);
100
+ padding-bottom: 12px;
101
+ margin-bottom: 25px;
102
+ font-size: 1.8rem;
103
+ }
104
+
105
+ .section h3 {
106
+ color: var(--secondary-color);
107
+ margin-top: 30px;
108
+ margin-bottom: 15px;
109
+ font-size: 1.4rem;
110
+ }
111
+
112
+ /* Cards */
113
+ .card {
114
+ background: var(--code-bg);
115
+ border: 1px solid var(--border-color);
116
+ border-radius: 8px;
117
+ padding: 25px;
118
+ margin: 20px 0;
119
+ box-shadow: 0 2px 4px rgba(0,0,0,0.05);
120
+ }
121
+
122
+ .card-header {
123
+ font-weight: 600;
124
+ color: var(--primary-color);
125
+ margin-bottom: 15px;
126
+ font-size: 1.1rem;
127
+ }
128
+
129
+ /* Tables */
130
+ table {
131
+ width: 100%;
132
+ border-collapse: collapse;
133
+ margin: 20px 0;
134
+ background: white;
135
+ box-shadow: 0 2px 4px rgba(0,0,0,0.05);
136
+ }
137
+
138
+ th {
139
+ background: var(--primary-color);
140
+ color: white;
141
+ padding: 15px;
142
+ text-align: left;
143
+ font-weight: 600;
144
+ }
145
+
146
+ td {
147
+ padding: 12px 15px;
148
+ border-bottom: 1px solid var(--border-color);
149
+ }
150
+
151
+ tr:nth-child(even) {
152
+ background-color: rgba(0,0,0,0.02);
153
+ }
154
+
155
+ tr:hover {
156
+ background-color: rgba(0,0,0,0.05);
157
+ }
158
+
159
+ /* Badges */
160
+ .badge {
161
+ display: inline-block;
162
+ padding: 4px 12px;
163
+ border-radius: 12px;
164
+ font-size: 0.85rem;
165
+ font-weight: 600;
166
+ }
167
+
168
+ .badge-success {
169
+ background: #d4edda;
170
+ color: #155724;
171
+ }
172
+
173
+ .badge-warning {
174
+ background: #fff3cd;
175
+ color: #856404;
176
+ }
177
+
178
+ .badge-danger {
179
+ background: #f8d7da;
180
+ color: #721c24;
181
+ }
182
+
183
+ /* Warnings */
184
+ .warning {
185
+ background: #fff3cd;
186
+ border-left: 4px solid #ffc107;
187
+ padding: 15px;
188
+ margin: 15px 0;
189
+ border-radius: 4px;
190
+ }
191
+
192
+ .warning::before {
193
+ content: "⚠ ";
194
+ font-weight: bold;
195
+ }
196
+
197
+ /* Plots */
198
+ .plot-container {
199
+ margin: 30px 0;
200
+ padding: 20px;
201
+ background: white;
202
+ border-radius: 8px;
203
+ box-shadow: 0 2px 8px rgba(0,0,0,0.1);
204
+ }
205
+
206
+ .plot-title {
207
+ font-size: 1.2rem;
208
+ font-weight: 600;
209
+ margin-bottom: 15px;
210
+ color: var(--primary-color);
211
+ }
212
+
213
+ .plot-container img {
214
+ max-width: 100%;
215
+ height: auto;
216
+ display: block;
217
+ margin: 0 auto;
218
+ }
219
+
220
+ /* Artifacts List */
221
+ .artifacts-list {
222
+ list-style: none;
223
+ padding: 0;
224
+ }
225
+
226
+ .artifacts-list li {
227
+ background: var(--code-bg);
228
+ padding: 15px;
229
+ margin: 10px 0;
230
+ border-left: 4px solid var(--secondary-color);
231
+ border-radius: 4px;
232
+ }
233
+
234
+ .artifacts-list strong {
235
+ color: var(--primary-color);
236
+ }
237
+
238
+ /* Metrics Grid */
239
+ .metrics-grid {
240
+ display: grid;
241
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
242
+ gap: 20px;
243
+ margin: 20px 0;
244
+ }
245
+
246
+ .metric-card {
247
+ background: var(--code-bg);
248
+ padding: 20px;
249
+ border-radius: 8px;
250
+ text-align: center;
251
+ border: 1px solid var(--border-color);
252
+ }
253
+
254
+ .metric-value {
255
+ font-size: 2rem;
256
+ font-weight: 700;
257
+ color: var(--primary-color);
258
+ margin: 10px 0;
259
+ }
260
+
261
+ .metric-label {
262
+ font-size: 0.9rem;
263
+ color: var(--text-color);
264
+ opacity: 0.8;
265
+ }
266
+
267
+ /* Code blocks */
268
+ code {
269
+ background: var(--code-bg);
270
+ padding: 2px 6px;
271
+ border-radius: 3px;
272
+ font-family: 'Consolas', 'Monaco', monospace;
273
+ font-size: 0.9em;
274
+ }
275
+
276
+ /* Responsive */
277
+ @media (max-width: 768px) {
278
+ .header {
279
+ padding: 40px 20px;
280
+ }
281
+
282
+ .header h1 {
283
+ font-size: 2rem;
284
+ }
285
+
286
+ .section h2 {
287
+ font-size: 1.5rem;
288
+ }
289
+
290
+ .metrics-grid {
291
+ grid-template-columns: 1fr;
292
+ }
293
+ }
294
+
295
+ /* Print styles */
296
+ @media print {
297
+ .header {
298
+ background: white !important;
299
+ color: black !important;
300
+ box-shadow: none !important;
301
+ }
302
+
303
+ .toc {
304
+ display: none;
305
+ }
306
+
307
+ .section {
308
+ page-break-inside: avoid;
309
+ }
310
+ }
311
311
  </style>
312
- </head>
313
- <body>
312
+ </head>
313
+ <body>
314
314
  <div class="container">
315
- <div class="header">
316
- <h1>{{ title }}</h1>
317
- <div class="meta">
318
- {% if config.show_timestamps %}
319
- <p>Generated: {{ generated_at|format_timestamp }}</p>
320
- {% endif %}
321
- <p>Author: {{ author }}</p>
322
- <p>Report Type: Protocol Reverse Engineering</p>
323
- </div>
315
+ <div class="header">
316
+ <h1>{{ title }}</h1>
317
+ <div class="meta">
318
+ {% if config.show_timestamps %}
319
+ <p>Generated: {{ generated_at|format_timestamp }}</p>
320
+ {% endif %}
321
+ <p>Author: {{ author }}</p>
322
+ <p>Report Type: Protocol Reverse Engineering</p>
324
323
  </div>
325
-
326
- {% if config.show_toc %}
327
- <div class="toc">
328
- <h2>Table of Contents</h2>
329
- <ul>
330
- <li><a href="#executive-summary">Executive Summary</a></li>
331
- <li><a href="#protocol-spec">Protocol Specification</a></li>
332
- {% if plots %}<li><a href="#visualizations">Visualizations</a></li>{% endif %}
333
- {% if artifacts %}<li><a href="#artifacts">Generated Artifacts</a></li>{% endif %}
334
- {% if partial_results %}<li><a href="#analysis">Detailed Analysis</a></li>{% endif %}
335
- {% if warnings %}<li><a href="#warnings">Warnings</a></li>{% endif %}
336
- </ul>
324
+ </div>
325
+
326
+ {% if config.show_toc %}
327
+ <div class="toc">
328
+ <h2>Table of Contents</h2>
329
+ <ul>
330
+ <li><a href="#executive-summary">Executive Summary</a></li>
331
+ <li><a href="#protocol-spec">Protocol Specification</a></li>
332
+ {% if plots %}
333
+ <li><a href="#visualizations">Visualizations</a></li>
334
+ {% endif %} {% if artifacts %}
335
+ <li><a href="#artifacts">Generated Artifacts</a></li>
336
+ {% endif %} {% if partial_results %}
337
+ <li><a href="#analysis">Detailed Analysis</a></li>
338
+ {% endif %} {% if warnings %}
339
+ <li><a href="#warnings">Warnings</a></li>
340
+ {% endif %}
341
+ </ul>
342
+ </div>
343
+ {% endif %}
344
+
345
+ <!-- Executive Summary -->
346
+ <div class="section" id="executive-summary">
347
+ <h2>Executive Summary</h2>
348
+ <div class="card">
349
+ <p>
350
+ This report presents the results of automated protocol reverse engineering performed by the Oscura
351
+ framework. The analysis identified protocol characteristics, decoded message structures, and generated
352
+ working dissectors for further analysis.
353
+ </p>
337
354
  </div>
338
- {% endif %}
339
355
 
340
- <!-- Executive Summary -->
341
- <div class="section" id="executive-summary">
342
- <h2>Executive Summary</h2>
343
- <div class="card">
344
- <p>This report presents the results of automated protocol reverse engineering
345
- performed by the Oscura framework. The analysis identified protocol characteristics,
346
- decoded message structures, and generated working dissectors for further analysis.</p>
347
- </div>
348
-
349
- {% if confidence_score %}
350
- <div class="metrics-grid">
351
- <div class="metric-card">
352
- <div class="metric-label">Overall Confidence</div>
353
- <div class="metric-value">{{ (confidence_score * 100)|round(1) }}%</div>
354
- {% if confidence_score >= 0.8 %}
355
- <span class="badge badge-success">High</span>
356
- {% elif confidence_score >= 0.6 %}
357
- <span class="badge badge-warning">Medium</span>
358
- {% else %}
359
- <span class="badge badge-danger">Low</span>
360
- {% endif %}
361
- </div>
362
-
363
- {% if execution_time %}
364
- <div class="metric-card">
365
- <div class="metric-label">Execution Time</div>
366
- <div class="metric-value">{{ execution_time|round(1) }}s</div>
367
- </div>
368
- {% endif %}
369
-
370
- {% if protocol_spec %}
371
- <div class="metric-card">
372
- <div class="metric-label">Fields Detected</div>
373
- <div class="metric-value">{{ protocol_spec.fields|length }}</div>
374
- </div>
375
- {% endif %}
376
-
377
- {% if artifacts %}
378
- <div class="metric-card">
379
- <div class="metric-label">Artifacts Generated</div>
380
- <div class="metric-value">{{ artifacts|length }}</div>
381
- </div>
382
- {% endif %}
383
- </div>
356
+ {% if confidence_score %}
357
+ <div class="metrics-grid">
358
+ <div class="metric-card">
359
+ <div class="metric-label">Overall Confidence</div>
360
+ <div class="metric-value">{{ (confidence_score * 100)|round(1) }}%</div>
361
+ {% if confidence_score >= 0.8 %}
362
+ <span class="badge badge-success">High</span>
363
+ {% elif confidence_score >= 0.6 %}
364
+ <span class="badge badge-warning">Medium</span>
365
+ {% else %}
366
+ <span class="badge badge-danger">Low</span>
384
367
  {% endif %}
368
+ </div>
369
+
370
+ {% if execution_time %}
371
+ <div class="metric-card">
372
+ <div class="metric-label">Execution Time</div>
373
+ <div class="metric-value">{{ execution_time|round(1) }}s</div>
374
+ </div>
375
+ {% endif %} {% if protocol_spec %}
376
+ <div class="metric-card">
377
+ <div class="metric-label">Fields Detected</div>
378
+ <div class="metric-value">{{ protocol_spec.fields|length }}</div>
379
+ </div>
380
+ {% endif %} {% if artifacts %}
381
+ <div class="metric-card">
382
+ <div class="metric-label">Artifacts Generated</div>
383
+ <div class="metric-value">{{ artifacts|length }}</div>
384
+ </div>
385
+ {% endif %}
385
386
  </div>
386
-
387
- <!-- Protocol Specification -->
388
- {% if protocol_spec %}
389
- <div class="section" id="protocol-spec">
390
- <h2>Protocol Specification</h2>
391
-
392
- <div class="card">
393
- <div class="card-header">Overview</div>
394
- <table>
395
- <tr>
396
- <th>Property</th>
397
- <th>Value</th>
398
- </tr>
399
- <tr>
400
- <td><strong>Protocol Name</strong></td>
401
- <td>{{ protocol_spec.name }}</td>
402
- </tr>
403
- <tr>
404
- <td><strong>Baud Rate</strong></td>
405
- <td>{{ protocol_spec.baud_rate|format_number }} bps</td>
406
- </tr>
407
- <tr>
408
- <td><strong>Frame Format</strong></td>
409
- <td><code>{{ protocol_spec.frame_format }}</code></td>
410
- </tr>
411
- <tr>
412
- <td><strong>Sync Pattern</strong></td>
413
- <td><code>{{ protocol_spec.sync_pattern }}</code></td>
414
- </tr>
415
- <tr>
416
- <td><strong>Frame Length</strong></td>
417
- <td>{{ protocol_spec.frame_length or "Variable" }} bytes</td>
418
- </tr>
419
- <tr>
420
- <td><strong>Checksum Type</strong></td>
421
- <td>{{ protocol_spec.checksum_type or "None detected" }}</td>
422
- </tr>
423
- {% if protocol_spec.checksum_position %}
424
- <tr>
425
- <td><strong>Checksum Position</strong></td>
426
- <td>Byte {{ protocol_spec.checksum_position }}</td>
427
- </tr>
428
- {% endif %}
429
- <tr>
430
- <td><strong>Detection Confidence</strong></td>
431
- <td>{{ (protocol_spec.confidence * 100)|round(1) }}%</td>
432
- </tr>
433
- </table>
434
- </div>
435
-
436
- {% if protocol_spec.fields %}
437
- <h3>Field Structure</h3>
438
- <div class="card">
439
- <table>
440
- <thead>
441
- <tr>
442
- <th>Field Name</th>
443
- <th>Offset (bytes)</th>
444
- <th>Size (bytes)</th>
445
- <th>Type</th>
446
- </tr>
447
- </thead>
448
- <tbody>
449
- {% for field in protocol_spec.fields %}
450
- <tr>
451
- <td><code>{{ field.name }}</code></td>
452
- <td>{{ field.offset }}</td>
453
- <td>{{ field.size }}</td>
454
- <td>{{ field.type }}</td>
455
- </tr>
456
- {% endfor %}
457
- </tbody>
458
- </table>
459
- </div>
387
+ {% endif %}
388
+ </div>
389
+
390
+ <!-- Protocol Specification -->
391
+ {% if protocol_spec %}
392
+ <div class="section" id="protocol-spec">
393
+ <h2>Protocol Specification</h2>
394
+
395
+ <div class="card">
396
+ <div class="card-header">Overview</div>
397
+ <table>
398
+ <tr>
399
+ <th>Property</th>
400
+ <th>Value</th>
401
+ </tr>
402
+ <tr>
403
+ <td><strong>Protocol Name</strong></td>
404
+ <td>{{ protocol_spec.name }}</td>
405
+ </tr>
406
+ <tr>
407
+ <td><strong>Baud Rate</strong></td>
408
+ <td>{{ protocol_spec.baud_rate|format_number }} bps</td>
409
+ </tr>
410
+ <tr>
411
+ <td><strong>Frame Format</strong></td>
412
+ <td><code>{{ protocol_spec.frame_format }}</code></td>
413
+ </tr>
414
+ <tr>
415
+ <td><strong>Sync Pattern</strong></td>
416
+ <td><code>{{ protocol_spec.sync_pattern }}</code></td>
417
+ </tr>
418
+ <tr>
419
+ <td><strong>Frame Length</strong></td>
420
+ <td>{{ protocol_spec.frame_length or "Variable" }} bytes</td>
421
+ </tr>
422
+ <tr>
423
+ <td><strong>Checksum Type</strong></td>
424
+ <td>{{ protocol_spec.checksum_type or "None detected" }}</td>
425
+ </tr>
426
+ {% if protocol_spec.checksum_position %}
427
+ <tr>
428
+ <td><strong>Checksum Position</strong></td>
429
+ <td>Byte {{ protocol_spec.checksum_position }}</td>
430
+ </tr>
460
431
  {% endif %}
432
+ <tr>
433
+ <td><strong>Detection Confidence</strong></td>
434
+ <td>{{ (protocol_spec.confidence * 100)|round(1) }}%</td>
435
+ </tr>
436
+ </table>
461
437
  </div>
462
- {% endif %}
463
438
 
464
- <!-- Visualizations -->
465
- {% if plots %}
466
- <div class="section" id="visualizations">
467
- <h2>Visualizations</h2>
468
- {% for plot in plots %}
469
- <div class="plot-container">
470
- <div class="plot-title">{{ plot.title }}</div>
471
- {% if plot.type == "embedded" %}
472
- <img src="{{ plot.data }}" alt="{{ plot.title }}">
473
- {% else %}
474
- <img src="{{ plot.path }}" alt="{{ plot.title }}">
475
- {% endif %}
476
- </div>
477
- {% endfor %}
439
+ {% if protocol_spec.fields %}
440
+ <h3>Field Structure</h3>
441
+ <div class="card">
442
+ <table>
443
+ <thead>
444
+ <tr>
445
+ <th>Field Name</th>
446
+ <th>Offset (bytes)</th>
447
+ <th>Size (bytes)</th>
448
+ <th>Type</th>
449
+ </tr>
450
+ </thead>
451
+ <tbody>
452
+ {% for field in protocol_spec.fields %}
453
+ <tr>
454
+ <td><code>{{ field.name }}</code></td>
455
+ <td>{{ field.offset }}</td>
456
+ <td>{{ field.size }}</td>
457
+ <td>{{ field.type }}</td>
458
+ </tr>
459
+ {% endfor %}
460
+ </tbody>
461
+ </table>
478
462
  </div>
479
463
  {% endif %}
480
-
481
- <!-- Generated Artifacts -->
482
- {% if artifacts %}
483
- <div class="section" id="artifacts">
484
- <h2>Generated Artifacts</h2>
485
- <div class="card">
486
- <p>The following artifacts were generated and can be used for further analysis:</p>
487
- <ul class="artifacts-list">
488
- {% for artifact in artifacts %}
489
- <li>
490
- <strong>{{ artifact.name }}</strong><br>
491
- <code>{{ artifact.path }}</code>
492
- </li>
493
- {% endfor %}
494
- </ul>
495
- </div>
464
+ </div>
465
+ {% endif %}
466
+
467
+ <!-- Visualizations -->
468
+ {% if plots %}
469
+ <div class="section" id="visualizations">
470
+ <h2>Visualizations</h2>
471
+ {% for plot in plots %}
472
+ <div class="plot-container">
473
+ <div class="plot-title">{{ plot.title }}</div>
474
+ {% if plot.type == "embedded" %}
475
+ <img src="{{ plot.data }}" alt="{{ plot.title }}" />
476
+ {% else %}
477
+ <img src="{{ plot.path }}" alt="{{ plot.title }}" />
478
+ {% endif %}
496
479
  </div>
497
- {% endif %}
498
-
499
- <!-- Detailed Analysis -->
500
- {% if partial_results %}
501
- <div class="section" id="analysis">
502
- <h2>Detailed Analysis Results</h2>
503
- {% for key, value in partial_results.items() %}
504
- {% if key not in ['traces'] %}
505
- <div class="card">
506
- <div class="card-header">{{ key|replace('_', ' ')|title }}</div>
507
- <p>{{ value }}</p>
508
- </div>
509
- {% endif %}
480
+ {% endfor %}
481
+ </div>
482
+ {% endif %}
483
+
484
+ <!-- Generated Artifacts -->
485
+ {% if artifacts %}
486
+ <div class="section" id="artifacts">
487
+ <h2>Generated Artifacts</h2>
488
+ <div class="card">
489
+ <p>The following artifacts were generated and can be used for further analysis:</p>
490
+ <ul class="artifacts-list">
491
+ {% for artifact in artifacts %}
492
+ <li>
493
+ <strong>{{ artifact.name }}</strong><br />
494
+ <code>{{ artifact.path }}</code>
495
+ </li>
510
496
  {% endfor %}
497
+ </ul>
511
498
  </div>
512
- {% endif %}
513
-
514
- <!-- Warnings -->
515
- {% if warnings %}
516
- <div class="section" id="warnings">
517
- <h2>Warnings and Notes</h2>
518
- {% for warning in warnings %}
519
- <div class="warning">{{ warning }}</div>
520
- {% endfor %}
499
+ </div>
500
+ {% endif %}
501
+
502
+ <!-- Detailed Analysis -->
503
+ {% if partial_results %}
504
+ <div class="section" id="analysis">
505
+ <h2>Detailed Analysis Results</h2>
506
+ {% for key, value in partial_results.items() %} {% if key not in ['traces'] %}
507
+ <div class="card">
508
+ <div class="card-header">{{ key|replace('_', ' ')|title }}</div>
509
+ <p>{{ value }}</p>
521
510
  </div>
522
- {% endif %}
511
+ {% endif %} {% endfor %}
512
+ </div>
513
+ {% endif %}
514
+
515
+ <!-- Warnings -->
516
+ {% if warnings %}
517
+ <div class="section" id="warnings">
518
+ <h2>Warnings and Notes</h2>
519
+ {% for warning in warnings %}
520
+ <div class="warning">{{ warning }}</div>
521
+ {% endfor %}
522
+ </div>
523
+ {% endif %}
523
524
  </div>
524
- </body>
525
+ </body>
525
526
  </html>