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,284 +1,265 @@
1
- {% extends "base.html" %}
2
-
3
- {% block title %}Home - {{ title }}{% endblock %}
4
-
5
- {% block content %}
1
+ {% extends "base.html" %} {% block title %}Home - {{ title }}{% endblock %} {% block content %}
6
2
  <div class="row">
7
- <div class="col-lg-8 offset-lg-2">
8
- <div class="card mb-4">
9
- <div class="card-body">
10
- <h1 class="card-title mb-4">
11
- <i class="bi bi-cpu"></i> Protocol Analysis
12
- </h1>
13
- <p class="lead">
14
- Upload signal capture files for automated protocol reverse engineering.
15
- Supports VCD, WAV, PCAP, and other formats.
16
- </p>
17
- </div>
18
- </div>
3
+ <div class="col-lg-8 offset-lg-2">
4
+ <div class="card mb-4">
5
+ <div class="card-body">
6
+ <h1 class="card-title mb-4"><i class="bi bi-cpu"></i> Protocol Analysis</h1>
7
+ <p class="lead">
8
+ Upload signal capture files for automated protocol reverse engineering. Supports VCD, WAV, PCAP, and other
9
+ formats.
10
+ </p>
11
+ </div>
12
+ </div>
19
13
 
20
- <!-- File Upload -->
21
- <div class="card">
22
- <div class="card-body">
23
- <h5 class="card-title mb-4">Upload Capture File</h5>
24
-
25
- <form id="uploadForm" enctype="multipart/form-data">
26
- <!-- Dropzone -->
27
- <div class="dropzone mb-4" id="dropzone">
28
- <i class="bi bi-cloud-upload" style="font-size: 3rem; opacity: 0.5;"></i>
29
- <h5 class="mt-3">Drag & Drop File Here</h5>
30
- <p class="text-muted">or click to browse</p>
31
- <p class="text-muted small">Maximum file size: {{ max_file_size_mb }} MB</p>
32
- <input type="file" id="fileInput" name="file" class="d-none" accept=".vcd,.wav,.pcap,.pcapng,.csv,.bin">
33
- </div>
34
-
35
- <div id="fileInfo" class="mb-3 d-none">
36
- <div class="alert alert-info">
37
- <i class="bi bi-file-earmark"></i>
38
- <strong>Selected:</strong> <span id="fileName"></span>
39
- (<span id="fileSize"></span>)
40
- </div>
41
- </div>
42
-
43
- <!-- Analysis Options -->
44
- <div class="row mb-3">
45
- <div class="col-md-6">
46
- <label for="protocolHint" class="form-label">
47
- <i class="bi bi-hint"></i> Protocol Hint (Optional)
48
- </label>
49
- <select class="form-select" id="protocolHint" name="protocol_hint">
50
- <option value="">Auto-detect</option>
51
- <option value="uart">UART</option>
52
- <option value="spi">SPI</option>
53
- <option value="i2c">I2C</option>
54
- <option value="can">CAN Bus</option>
55
- <option value="usb">USB</option>
56
- <option value="ethernet">Ethernet</option>
57
- </select>
58
- </div>
59
- </div>
60
-
61
- <div class="row mb-4">
62
- <div class="col-md-4">
63
- <div class="form-check">
64
- <input class="form-check-input" type="checkbox" id="autoCRC" name="auto_crc" checked>
65
- <label class="form-check-label" for="autoCRC">
66
- Auto-detect CRC
67
- </label>
68
- </div>
69
- </div>
70
- <div class="col-md-4">
71
- <div class="form-check">
72
- <input class="form-check-input" type="checkbox" id="detectCrypto" name="detect_crypto" checked>
73
- <label class="form-check-label" for="detectCrypto">
74
- Detect Crypto
75
- </label>
76
- </div>
77
- </div>
78
- <div class="col-md-4">
79
- <div class="form-check">
80
- <input class="form-check-input" type="checkbox" id="generateTests" name="generate_tests" checked>
81
- <label class="form-check-label" for="generateTests">
82
- Generate Tests
83
- </label>
84
- </div>
85
- </div>
86
- </div>
87
-
88
- <!-- Submit Button -->
89
- <button type="submit" class="btn btn-primary btn-lg w-100" id="analyzeBtn">
90
- <i class="bi bi-play-circle"></i> Start Analysis
91
- </button>
92
- </form>
93
-
94
- <!-- Progress Indicator -->
95
- <div id="progressContainer" class="mt-4 d-none">
96
- <div class="progress">
97
- <div class="progress-bar progress-bar-striped progress-bar-animated" role="progressbar" id="progressBar" style="width: 0%"></div>
98
- </div>
99
- <p class="text-center mt-2" id="progressText">Initializing...</p>
100
- </div>
14
+ <!-- File Upload -->
15
+ <div class="card">
16
+ <div class="card-body">
17
+ <h5 class="card-title mb-4">Upload Capture File</h5>
18
+
19
+ <form id="uploadForm" enctype="multipart/form-data">
20
+ <!-- Dropzone -->
21
+ <div class="dropzone mb-4" id="dropzone">
22
+ <i class="bi bi-cloud-upload" style="font-size: 3rem; opacity: 0.5"></i>
23
+ <h5 class="mt-3">Drag & Drop File Here</h5>
24
+ <p class="text-muted">or click to browse</p>
25
+ <p class="text-muted small">Maximum file size: {{ max_file_size_mb }} MB</p>
26
+ <input type="file" id="fileInput" name="file" class="d-none" accept=".vcd,.wav,.pcap,.pcapng,.csv,.bin" />
27
+ </div>
28
+
29
+ <div id="fileInfo" class="mb-3 d-none">
30
+ <div class="alert alert-info">
31
+ <i class="bi bi-file-earmark"></i>
32
+ <strong>Selected:</strong> <span id="fileName"></span> (<span id="fileSize"></span>)
33
+ </div>
34
+ </div>
35
+
36
+ <!-- Analysis Options -->
37
+ <div class="row mb-3">
38
+ <div class="col-md-6">
39
+ <label for="protocolHint" class="form-label"> <i class="bi bi-hint"></i> Protocol Hint (Optional) </label>
40
+ <select class="form-select" id="protocolHint" name="protocol_hint">
41
+ <option value="">Auto-detect</option>
42
+ <option value="uart">UART</option>
43
+ <option value="spi">SPI</option>
44
+ <option value="i2c">I2C</option>
45
+ <option value="can">CAN Bus</option>
46
+ <option value="usb">USB</option>
47
+ <option value="ethernet">Ethernet</option>
48
+ </select>
101
49
  </div>
50
+ </div>
51
+
52
+ <div class="row mb-4">
53
+ <div class="col-md-4">
54
+ <div class="form-check">
55
+ <input class="form-check-input" type="checkbox" id="autoCRC" name="auto_crc" checked />
56
+ <label class="form-check-label" for="autoCRC"> Auto-detect CRC </label>
57
+ </div>
58
+ </div>
59
+ <div class="col-md-4">
60
+ <div class="form-check">
61
+ <input class="form-check-input" type="checkbox" id="detectCrypto" name="detect_crypto" checked />
62
+ <label class="form-check-label" for="detectCrypto"> Detect Crypto </label>
63
+ </div>
64
+ </div>
65
+ <div class="col-md-4">
66
+ <div class="form-check">
67
+ <input class="form-check-input" type="checkbox" id="generateTests" name="generate_tests" checked />
68
+ <label class="form-check-label" for="generateTests"> Generate Tests </label>
69
+ </div>
70
+ </div>
71
+ </div>
72
+
73
+ <!-- Submit Button -->
74
+ <button type="submit" class="btn btn-primary btn-lg w-100" id="analyzeBtn">
75
+ <i class="bi bi-play-circle"></i> Start Analysis
76
+ </button>
77
+ </form>
78
+
79
+ <!-- Progress Indicator -->
80
+ <div id="progressContainer" class="mt-4 d-none">
81
+ <div class="progress">
82
+ <div
83
+ class="progress-bar progress-bar-striped progress-bar-animated"
84
+ role="progressbar"
85
+ id="progressBar"
86
+ style="width: 0%"
87
+ ></div>
88
+ </div>
89
+ <p class="text-center mt-2" id="progressText">Initializing...</p>
102
90
  </div>
91
+ </div>
92
+ </div>
103
93
 
104
- <!-- Recent Sessions -->
105
- <div class="card mt-4">
106
- <div class="card-body">
107
- <h5 class="card-title mb-3">
108
- <i class="bi bi-clock-history"></i> Quick Actions
109
- </h5>
110
- <div class="d-grid gap-2">
111
- <a href="/sessions" class="btn btn-outline-primary">
112
- <i class="bi bi-list-task"></i> View All Sessions
113
- </a>
114
- <a href="/protocols" class="btn btn-outline-primary">
115
- <i class="bi bi-diagram-3"></i> Browse Protocols
116
- </a>
117
- </div>
118
- </div>
94
+ <!-- Recent Sessions -->
95
+ <div class="card mt-4">
96
+ <div class="card-body">
97
+ <h5 class="card-title mb-3"><i class="bi bi-clock-history"></i> Quick Actions</h5>
98
+ <div class="d-grid gap-2">
99
+ <a href="/sessions" class="btn btn-outline-primary"> <i class="bi bi-list-task"></i> View All Sessions </a>
100
+ <a href="/protocols" class="btn btn-outline-primary"> <i class="bi bi-diagram-3"></i> Browse Protocols </a>
119
101
  </div>
102
+ </div>
120
103
  </div>
104
+ </div>
121
105
  </div>
122
- {% endblock %}
123
-
124
- {% block extra_scripts %}
106
+ {% endblock %} {% block extra_scripts %}
125
107
  <script>
126
- const dropzone = document.getElementById('dropzone');
127
- const fileInput = document.getElementById('fileInput');
128
- const fileInfo = document.getElementById('fileInfo');
129
- const fileName = document.getElementById('fileName');
130
- const fileSize = document.getElementById('fileSize');
131
- const uploadForm = document.getElementById('uploadForm');
132
- const progressContainer = document.getElementById('progressContainer');
133
- const progressBar = document.getElementById('progressBar');
134
- const progressText = document.getElementById('progressText');
135
- const analyzeBtn = document.getElementById('analyzeBtn');
136
-
137
- // Dropzone click
138
- dropzone.addEventListener('click', () => fileInput.click());
139
-
140
- // Drag and drop
141
- dropzone.addEventListener('dragover', (e) => {
142
- e.preventDefault();
143
- dropzone.classList.add('drag-over');
144
- });
145
-
146
- dropzone.addEventListener('dragleave', () => {
147
- dropzone.classList.remove('drag-over');
148
- });
149
-
150
- dropzone.addEventListener('drop', (e) => {
151
- e.preventDefault();
152
- dropzone.classList.remove('drag-over');
153
-
154
- const files = e.dataTransfer.files;
155
- if (files.length > 0) {
156
- fileInput.files = files;
157
- updateFileInfo(files[0]);
158
- }
159
- });
160
-
161
- // File selection
162
- fileInput.addEventListener('change', (e) => {
163
- const file = e.target.files[0];
164
- if (file) {
165
- updateFileInfo(file);
166
- }
167
- });
168
-
169
- function updateFileInfo(file) {
170
- fileName.textContent = file.name;
171
- fileSize.textContent = formatFileSize(file.size);
172
- fileInfo.classList.remove('d-none');
108
+ const dropzone = document.getElementById('dropzone');
109
+ const fileInput = document.getElementById('fileInput');
110
+ const fileInfo = document.getElementById('fileInfo');
111
+ const fileName = document.getElementById('fileName');
112
+ const fileSize = document.getElementById('fileSize');
113
+ const uploadForm = document.getElementById('uploadForm');
114
+ const progressContainer = document.getElementById('progressContainer');
115
+ const progressBar = document.getElementById('progressBar');
116
+ const progressText = document.getElementById('progressText');
117
+ const analyzeBtn = document.getElementById('analyzeBtn');
118
+
119
+ // Dropzone click
120
+ dropzone.addEventListener('click', () => fileInput.click());
121
+
122
+ // Drag and drop
123
+ dropzone.addEventListener('dragover', (e) => {
124
+ e.preventDefault();
125
+ dropzone.classList.add('drag-over');
126
+ });
127
+
128
+ dropzone.addEventListener('dragleave', () => {
129
+ dropzone.classList.remove('drag-over');
130
+ });
131
+
132
+ dropzone.addEventListener('drop', (e) => {
133
+ e.preventDefault();
134
+ dropzone.classList.remove('drag-over');
135
+
136
+ const files = e.dataTransfer.files;
137
+ if (files.length > 0) {
138
+ fileInput.files = files;
139
+ updateFileInfo(files[0]);
173
140
  }
141
+ });
174
142
 
175
- function formatFileSize(bytes) {
176
- if (bytes < 1024) return bytes + ' B';
177
- if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(2) + ' KB';
178
- return (bytes / (1024 * 1024)).toFixed(2) + ' MB';
143
+ // File selection
144
+ fileInput.addEventListener('change', (e) => {
145
+ const file = e.target.files[0];
146
+ if (file) {
147
+ updateFileInfo(file);
148
+ }
149
+ });
150
+
151
+ function updateFileInfo(file) {
152
+ fileName.textContent = file.name;
153
+ fileSize.textContent = formatFileSize(file.size);
154
+ fileInfo.classList.remove('d-none');
155
+ }
156
+
157
+ function formatFileSize(bytes) {
158
+ if (bytes < 1024) return bytes + ' B';
159
+ if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(2) + ' KB';
160
+ return (bytes / (1024 * 1024)).toFixed(2) + ' MB';
161
+ }
162
+
163
+ // Form submission
164
+ uploadForm.addEventListener('submit', async (e) => {
165
+ e.preventDefault();
166
+
167
+ const file = fileInput.files[0];
168
+ if (!file) {
169
+ alert('Please select a file first');
170
+ return;
179
171
  }
180
172
 
181
- // Form submission
182
- uploadForm.addEventListener('submit', async (e) => {
183
- e.preventDefault();
184
-
185
- const file = fileInput.files[0];
186
- if (!file) {
187
- alert('Please select a file first');
188
- return;
189
- }
190
-
191
- // Show progress
192
- progressContainer.classList.remove('d-none');
193
- analyzeBtn.disabled = true;
194
- progressBar.style.width = '10%';
195
- progressText.textContent = 'Uploading file...';
196
-
197
- // Create form data
198
- const formData = new FormData();
199
- formData.append('file', file);
200
- formData.append('protocol_hint', document.getElementById('protocolHint').value);
201
- formData.append('auto_crc', document.getElementById('autoCRC').checked);
202
- formData.append('detect_crypto', document.getElementById('detectCrypto').checked);
203
- formData.append('generate_tests', document.getElementById('generateTests').checked);
204
-
205
- try {
206
- // Upload file
207
- const response = await fetch('/api/upload', {
208
- method: 'POST',
209
- body: formData
210
- });
211
-
212
- if (!response.ok) {
213
- throw new Error('Upload failed');
214
- }
215
-
216
- const data = await response.json();
217
- const sessionId = data.session_id;
218
-
219
- // Update progress
220
- progressBar.style.width = '30%';
221
- progressText.textContent = 'Analysis started...';
222
-
223
- // Connect WebSocket for real-time updates
224
- const ws = new WebSocket(`ws://${window.location.host}/ws/${sessionId}`);
225
-
226
- ws.onmessage = (event) => {
227
- const update = JSON.parse(event.data);
228
-
229
- if (update.type === 'status') {
230
- progressBar.style.width = update.progress + '%';
231
- progressText.textContent = update.message;
232
-
233
- if (update.status === 'complete') {
234
- setTimeout(() => {
235
- window.location.href = `/session/${sessionId}`;
236
- }, 1000);
237
- }
238
- } else if (update.type === 'error') {
239
- progressBar.classList.add('bg-danger');
240
- progressText.textContent = 'Error: ' + update.message;
241
- analyzeBtn.disabled = false;
242
- }
243
- };
244
-
245
- ws.onerror = () => {
246
- // Fallback to polling if WebSocket fails
247
- pollSessionStatus(sessionId);
248
- };
249
-
250
- } catch (error) {
251
- alert('Upload failed: ' + error.message);
252
- progressContainer.classList.add('d-none');
253
- analyzeBtn.disabled = false;
173
+ // Show progress
174
+ progressContainer.classList.remove('d-none');
175
+ analyzeBtn.disabled = true;
176
+ progressBar.style.width = '10%';
177
+ progressText.textContent = 'Uploading file...';
178
+
179
+ // Create form data
180
+ const formData = new FormData();
181
+ formData.append('file', file);
182
+ formData.append('protocol_hint', document.getElementById('protocolHint').value);
183
+ formData.append('auto_crc', document.getElementById('autoCRC').checked);
184
+ formData.append('detect_crypto', document.getElementById('detectCrypto').checked);
185
+ formData.append('generate_tests', document.getElementById('generateTests').checked);
186
+
187
+ try {
188
+ // Upload file
189
+ const response = await fetch('/api/upload', {
190
+ method: 'POST',
191
+ body: formData,
192
+ });
193
+
194
+ if (!response.ok) {
195
+ throw new Error('Upload failed');
196
+ }
197
+
198
+ const data = await response.json();
199
+ const sessionId = data.session_id;
200
+
201
+ // Update progress
202
+ progressBar.style.width = '30%';
203
+ progressText.textContent = 'Analysis started...';
204
+
205
+ // Connect WebSocket for real-time updates
206
+ const ws = new WebSocket(`ws://${window.location.host}/ws/${sessionId}`);
207
+
208
+ ws.onmessage = (event) => {
209
+ const update = JSON.parse(event.data);
210
+
211
+ if (update.type === 'status') {
212
+ progressBar.style.width = update.progress + '%';
213
+ progressText.textContent = update.message;
214
+
215
+ if (update.status === 'complete') {
216
+ setTimeout(() => {
217
+ window.location.href = `/session/${sessionId}`;
218
+ }, 1000);
219
+ }
220
+ } else if (update.type === 'error') {
221
+ progressBar.classList.add('bg-danger');
222
+ progressText.textContent = 'Error: ' + update.message;
223
+ analyzeBtn.disabled = false;
254
224
  }
255
- });
256
-
257
- // Fallback polling function
258
- async function pollSessionStatus(sessionId) {
259
- const interval = setInterval(async () => {
260
- try {
261
- const response = await fetch(`/api/session/${sessionId}/status`);
262
- const data = await response.json();
263
-
264
- progressText.textContent = `Status: ${data.status}`;
265
-
266
- if (data.status === 'complete') {
267
- clearInterval(interval);
268
- progressBar.style.width = '100%';
269
- setTimeout(() => {
270
- window.location.href = `/session/${sessionId}`;
271
- }, 1000);
272
- } else if (data.status === 'error') {
273
- clearInterval(interval);
274
- progressBar.classList.add('bg-danger');
275
- progressText.textContent = 'Error: ' + data.error;
276
- analyzeBtn.disabled = false;
277
- }
278
- } catch (error) {
279
- console.error('Poll error:', error);
280
- }
281
- }, 2000);
225
+ };
226
+
227
+ ws.onerror = () => {
228
+ // Fallback to polling if WebSocket fails
229
+ pollSessionStatus(sessionId);
230
+ };
231
+ } catch (error) {
232
+ alert('Upload failed: ' + error.message);
233
+ progressContainer.classList.add('d-none');
234
+ analyzeBtn.disabled = false;
282
235
  }
236
+ });
237
+
238
+ // Fallback polling function
239
+ async function pollSessionStatus(sessionId) {
240
+ const interval = setInterval(async () => {
241
+ try {
242
+ const response = await fetch(`/api/session/${sessionId}/status`);
243
+ const data = await response.json();
244
+
245
+ progressText.textContent = `Status: ${data.status}`;
246
+
247
+ if (data.status === 'complete') {
248
+ clearInterval(interval);
249
+ progressBar.style.width = '100%';
250
+ setTimeout(() => {
251
+ window.location.href = `/session/${sessionId}`;
252
+ }, 1000);
253
+ } else if (data.status === 'error') {
254
+ clearInterval(interval);
255
+ progressBar.classList.add('bg-danger');
256
+ progressText.textContent = 'Error: ' + data.error;
257
+ analyzeBtn.disabled = false;
258
+ }
259
+ } catch (error) {
260
+ console.error('Poll error:', error);
261
+ }
262
+ }, 2000);
263
+ }
283
264
  </script>
284
265
  {% endblock %}
@@ -1,58 +1,54 @@
1
- {% extends "base.html" %}
2
-
3
- {% block title %}Protocols - {{ title }}{% endblock %}
4
-
5
- {% block content %}
1
+ {% extends "base.html" %} {% block title %}Protocols - {{ title }}{% endblock %} {% block content %}
6
2
  <div class="row">
7
- <div class="col-12">
8
- <div class="card">
9
- <div class="card-body">
10
- <h1 class="card-title mb-4">
11
- <i class="bi bi-diagram-3"></i> Discovered Protocols
12
- </h1>
13
-
14
- {% if protocols %}
15
- <div class="row">
16
- {% for protocol in protocols %}
17
- <div class="col-md-6 col-lg-4 mb-4">
18
- <div class="card h-100">
19
- <div class="card-body">
20
- <h5 class="card-title">{{ protocol.protocol_name }}</h5>
21
- <p class="text-muted small">{{ protocol.filename }}</p>
22
-
23
- <div class="mb-2">
24
- <strong>Confidence:</strong>
25
- <div class="progress" style="height: 20px;">
26
- <div class="progress-bar" role="progressbar"
27
- style="width: {{ (protocol.confidence * 100)|round }}%"
28
- aria-valuenow="{{ (protocol.confidence * 100)|round }}"
29
- aria-valuemin="0" aria-valuemax="100">
30
- {{ (protocol.confidence * 100)|round(1) }}%
31
- </div>
32
- </div>
33
- </div>
3
+ <div class="col-12">
4
+ <div class="card">
5
+ <div class="card-body">
6
+ <h1 class="card-title mb-4"><i class="bi bi-diagram-3"></i> Discovered Protocols</h1>
34
7
 
35
- <p class="mb-1"><strong>Messages:</strong> {{ protocol.message_count }}</p>
36
- <p class="mb-3"><strong>Fields:</strong> {{ protocol.field_count }}</p>
8
+ {% if protocols %}
9
+ <div class="row">
10
+ {% for protocol in protocols %}
11
+ <div class="col-md-6 col-lg-4 mb-4">
12
+ <div class="card h-100">
13
+ <div class="card-body">
14
+ <h5 class="card-title">{{ protocol.protocol_name }}</h5>
15
+ <p class="text-muted small">{{ protocol.filename }}</p>
37
16
 
38
- <a href="/session/{{ protocol.session_id }}" class="btn btn-primary btn-sm">
39
- <i class="bi bi-eye"></i> View Details
40
- </a>
41
- </div>
42
- <div class="card-footer text-muted small">
43
- {{ protocol.created_at[:19] }}
44
- </div>
45
- </div>
17
+ <div class="mb-2">
18
+ <strong>Confidence:</strong>
19
+ <div class="progress" style="height: 20px">
20
+ <div
21
+ class="progress-bar"
22
+ role="progressbar"
23
+ style="width: {{ (protocol.confidence * 100)|round }}%"
24
+ aria-valuenow="{{ (protocol.confidence * 100)|round }}"
25
+ aria-valuemin="0"
26
+ aria-valuemax="100"
27
+ >
28
+ {{ (protocol.confidence * 100)|round(1) }}%
46
29
  </div>
47
- {% endfor %}
30
+ </div>
48
31
  </div>
49
- {% else %}
50
- <div class="alert alert-info">
51
- <i class="bi bi-info-circle"></i> No protocols discovered yet. <a href="/">Upload a file</a> to analyze.
52
- </div>
53
- {% endif %}
32
+
33
+ <p class="mb-1"><strong>Messages:</strong> {{ protocol.message_count }}</p>
34
+ <p class="mb-3"><strong>Fields:</strong> {{ protocol.field_count }}</p>
35
+
36
+ <a href="/session/{{ protocol.session_id }}" class="btn btn-primary btn-sm">
37
+ <i class="bi bi-eye"></i> View Details
38
+ </a>
39
+ </div>
40
+ <div class="card-footer text-muted small">{{ protocol.created_at[:19] }}</div>
54
41
  </div>
42
+ </div>
43
+ {% endfor %}
44
+ </div>
45
+ {% else %}
46
+ <div class="alert alert-info">
47
+ <i class="bi bi-info-circle"></i> No protocols discovered yet. <a href="/">Upload a file</a> to analyze.
55
48
  </div>
49
+ {% endif %}
50
+ </div>
56
51
  </div>
52
+ </div>
57
53
  </div>
58
54
  {% endblock %}