oscura 0.8.0__py3-none-any.whl → 0.10.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 (151) hide show
  1. oscura/__init__.py +19 -19
  2. oscura/analyzers/__init__.py +2 -0
  3. oscura/analyzers/digital/extraction.py +2 -3
  4. oscura/analyzers/digital/quality.py +1 -1
  5. oscura/analyzers/digital/timing.py +1 -1
  6. oscura/analyzers/patterns/__init__.py +66 -0
  7. oscura/analyzers/power/basic.py +3 -3
  8. oscura/analyzers/power/soa.py +1 -1
  9. oscura/analyzers/power/switching.py +3 -3
  10. oscura/analyzers/signal_classification.py +529 -0
  11. oscura/analyzers/signal_integrity/sparams.py +3 -3
  12. oscura/analyzers/statistics/basic.py +10 -7
  13. oscura/analyzers/validation.py +1 -1
  14. oscura/analyzers/waveform/measurements.py +200 -156
  15. oscura/analyzers/waveform/measurements_with_uncertainty.py +91 -35
  16. oscura/analyzers/waveform/spectral.py +164 -73
  17. oscura/api/dsl/commands.py +15 -6
  18. oscura/api/server/templates/base.html +137 -146
  19. oscura/api/server/templates/export.html +84 -110
  20. oscura/api/server/templates/home.html +248 -267
  21. oscura/api/server/templates/protocols.html +44 -48
  22. oscura/api/server/templates/reports.html +27 -35
  23. oscura/api/server/templates/session_detail.html +68 -78
  24. oscura/api/server/templates/sessions.html +62 -72
  25. oscura/api/server/templates/waveforms.html +54 -64
  26. oscura/automotive/__init__.py +1 -1
  27. oscura/automotive/can/session.py +1 -1
  28. oscura/automotive/dbc/generator.py +638 -23
  29. oscura/automotive/uds/decoder.py +99 -6
  30. oscura/cli/analyze.py +8 -2
  31. oscura/cli/batch.py +36 -5
  32. oscura/cli/characterize.py +18 -4
  33. oscura/cli/export.py +47 -5
  34. oscura/cli/main.py +2 -0
  35. oscura/cli/onboarding/wizard.py +10 -6
  36. oscura/cli/pipeline.py +585 -0
  37. oscura/cli/visualize.py +6 -4
  38. oscura/convenience.py +400 -32
  39. oscura/core/measurement_result.py +286 -0
  40. oscura/core/progress.py +1 -1
  41. oscura/core/types.py +232 -239
  42. oscura/correlation/multi_protocol.py +1 -1
  43. oscura/export/legacy/__init__.py +11 -0
  44. oscura/export/legacy/wav.py +75 -0
  45. oscura/exporters/__init__.py +19 -0
  46. oscura/exporters/wireshark.py +809 -0
  47. oscura/hardware/acquisition/file.py +5 -19
  48. oscura/hardware/acquisition/saleae.py +10 -10
  49. oscura/hardware/acquisition/socketcan.py +4 -6
  50. oscura/hardware/acquisition/synthetic.py +1 -5
  51. oscura/hardware/acquisition/visa.py +6 -6
  52. oscura/hardware/security/side_channel_detector.py +5 -508
  53. oscura/inference/message_format.py +686 -1
  54. oscura/jupyter/display.py +2 -2
  55. oscura/jupyter/magic.py +3 -3
  56. oscura/loaders/__init__.py +17 -12
  57. oscura/loaders/binary.py +1 -1
  58. oscura/loaders/chipwhisperer.py +1 -2
  59. oscura/loaders/configurable.py +1 -1
  60. oscura/loaders/csv_loader.py +2 -2
  61. oscura/loaders/hdf5_loader.py +1 -1
  62. oscura/loaders/lazy.py +6 -1
  63. oscura/loaders/mmap_loader.py +0 -1
  64. oscura/loaders/numpy_loader.py +8 -7
  65. oscura/loaders/preprocessing.py +3 -5
  66. oscura/loaders/rigol.py +21 -7
  67. oscura/loaders/sigrok.py +2 -5
  68. oscura/loaders/tdms.py +3 -2
  69. oscura/loaders/tektronix.py +38 -32
  70. oscura/loaders/tss.py +20 -27
  71. oscura/loaders/vcd.py +13 -8
  72. oscura/loaders/wav.py +1 -6
  73. oscura/pipeline/__init__.py +76 -0
  74. oscura/pipeline/handlers/__init__.py +165 -0
  75. oscura/pipeline/handlers/analyzers.py +1045 -0
  76. oscura/pipeline/handlers/decoders.py +899 -0
  77. oscura/pipeline/handlers/exporters.py +1103 -0
  78. oscura/pipeline/handlers/filters.py +891 -0
  79. oscura/pipeline/handlers/loaders.py +640 -0
  80. oscura/pipeline/handlers/transforms.py +768 -0
  81. oscura/reporting/formatting/measurements.py +55 -14
  82. oscura/reporting/templates/enhanced/protocol_re.html +504 -503
  83. oscura/side_channel/__init__.py +38 -57
  84. oscura/utils/builders/signal_builder.py +5 -5
  85. oscura/utils/comparison/compare.py +7 -9
  86. oscura/utils/comparison/golden.py +1 -1
  87. oscura/utils/filtering/convenience.py +2 -2
  88. oscura/utils/math/arithmetic.py +38 -62
  89. oscura/utils/math/interpolation.py +20 -20
  90. oscura/utils/pipeline/__init__.py +4 -17
  91. oscura/utils/progressive.py +1 -4
  92. oscura/utils/triggering/edge.py +1 -1
  93. oscura/utils/triggering/pattern.py +2 -2
  94. oscura/utils/triggering/pulse.py +2 -2
  95. oscura/utils/triggering/window.py +3 -3
  96. oscura/validation/hil_testing.py +11 -11
  97. oscura/visualization/__init__.py +46 -284
  98. oscura/visualization/batch.py +72 -433
  99. oscura/visualization/plot.py +542 -53
  100. oscura/visualization/styles.py +184 -318
  101. oscura/workflows/batch/advanced.py +1 -1
  102. oscura/workflows/batch/aggregate.py +7 -8
  103. oscura/workflows/complete_re.py +251 -23
  104. oscura/workflows/digital.py +27 -4
  105. oscura/workflows/multi_trace.py +136 -17
  106. oscura/workflows/waveform.py +11 -6
  107. {oscura-0.8.0.dist-info → oscura-0.10.0.dist-info}/METADATA +59 -79
  108. {oscura-0.8.0.dist-info → oscura-0.10.0.dist-info}/RECORD +111 -136
  109. oscura/side_channel/dpa.py +0 -1025
  110. oscura/utils/optimization/__init__.py +0 -19
  111. oscura/utils/optimization/parallel.py +0 -443
  112. oscura/utils/optimization/search.py +0 -532
  113. oscura/utils/pipeline/base.py +0 -338
  114. oscura/utils/pipeline/composition.py +0 -248
  115. oscura/utils/pipeline/parallel.py +0 -449
  116. oscura/utils/pipeline/pipeline.py +0 -375
  117. oscura/utils/search/__init__.py +0 -16
  118. oscura/utils/search/anomaly.py +0 -424
  119. oscura/utils/search/context.py +0 -294
  120. oscura/utils/search/pattern.py +0 -288
  121. oscura/utils/storage/__init__.py +0 -61
  122. oscura/utils/storage/database.py +0 -1166
  123. oscura/visualization/accessibility.py +0 -526
  124. oscura/visualization/annotations.py +0 -371
  125. oscura/visualization/axis_scaling.py +0 -305
  126. oscura/visualization/colors.py +0 -451
  127. oscura/visualization/digital.py +0 -436
  128. oscura/visualization/eye.py +0 -571
  129. oscura/visualization/histogram.py +0 -281
  130. oscura/visualization/interactive.py +0 -1035
  131. oscura/visualization/jitter.py +0 -1042
  132. oscura/visualization/keyboard.py +0 -394
  133. oscura/visualization/layout.py +0 -400
  134. oscura/visualization/optimization.py +0 -1079
  135. oscura/visualization/palettes.py +0 -446
  136. oscura/visualization/power.py +0 -508
  137. oscura/visualization/power_extended.py +0 -955
  138. oscura/visualization/presets.py +0 -469
  139. oscura/visualization/protocols.py +0 -1246
  140. oscura/visualization/render.py +0 -223
  141. oscura/visualization/rendering.py +0 -444
  142. oscura/visualization/reverse_engineering.py +0 -838
  143. oscura/visualization/signal_integrity.py +0 -989
  144. oscura/visualization/specialized.py +0 -643
  145. oscura/visualization/spectral.py +0 -1226
  146. oscura/visualization/thumbnails.py +0 -340
  147. oscura/visualization/time_axis.py +0 -351
  148. oscura/visualization/waveform.py +0 -454
  149. {oscura-0.8.0.dist-info → oscura-0.10.0.dist-info}/WHEEL +0 -0
  150. {oscura-0.8.0.dist-info → oscura-0.10.0.dist-info}/entry_points.txt +0 -0
  151. {oscura-0.8.0.dist-info → oscura-0.10.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 %}