lanscape 1.2.6a10__py3-none-any.whl → 1.2.6a12__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 (35) hide show
  1. lanscape/ui/static/css/style.css +715 -0
  2. lanscape/ui/static/img/ico/android-chrome-192x192.png +0 -0
  3. lanscape/ui/static/img/ico/android-chrome-512x512.png +0 -0
  4. lanscape/ui/static/img/ico/apple-touch-icon.png +0 -0
  5. lanscape/ui/static/img/ico/favicon-16x16.png +0 -0
  6. lanscape/ui/static/img/ico/favicon-32x32.png +0 -0
  7. lanscape/ui/static/img/ico/favicon.ico +0 -0
  8. lanscape/ui/static/img/ico/site.webmanifest +1 -0
  9. lanscape/ui/static/img/readme1.png +0 -0
  10. lanscape/ui/static/js/core.js +39 -0
  11. lanscape/ui/static/js/layout-sizing.js +31 -0
  12. lanscape/ui/static/js/main.js +208 -0
  13. lanscape/ui/static/js/quietReload.js +23 -0
  14. lanscape/ui/static/js/shutdown-server.js +17 -0
  15. lanscape/ui/static/js/subnet-info.js +19 -0
  16. lanscape/ui/static/js/subnet-selector.js +9 -0
  17. lanscape/ui/static/lanscape.webmanifest +19 -0
  18. lanscape/ui/templates/base.html +47 -0
  19. lanscape/ui/templates/core/head.html +10 -0
  20. lanscape/ui/templates/core/scripts.html +5 -0
  21. lanscape/ui/templates/error.html +35 -0
  22. lanscape/ui/templates/info.html +67 -0
  23. lanscape/ui/templates/main.html +89 -0
  24. lanscape/ui/templates/scan/export.html +27 -0
  25. lanscape/ui/templates/scan/ip-table-row.html +103 -0
  26. lanscape/ui/templates/scan/ip-table.html +26 -0
  27. lanscape/ui/templates/scan/overview.html +28 -0
  28. lanscape/ui/templates/scan/scan-error.html +33 -0
  29. lanscape/ui/templates/scan.html +14 -0
  30. lanscape/ui/templates/shutdown.html +23 -0
  31. {lanscape-1.2.6a10.dist-info → lanscape-1.2.6a12.dist-info}/METADATA +1 -1
  32. {lanscape-1.2.6a10.dist-info → lanscape-1.2.6a12.dist-info}/RECORD +35 -5
  33. {lanscape-1.2.6a10.dist-info → lanscape-1.2.6a12.dist-info}/LICENSE +0 -0
  34. {lanscape-1.2.6a10.dist-info → lanscape-1.2.6a12.dist-info}/WHEEL +0 -0
  35. {lanscape-1.2.6a10.dist-info → lanscape-1.2.6a12.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,715 @@
1
+ /* General Styles */
2
+ :root {
3
+ --primary-accent: #0a84ff; /* A brighter blue to add contrast */
4
+ --primary-accent-hover: #0077e6; /* Slightly darker for hover */
5
+ --secondary-accent: #5a5a5a; /* Mid-gray for neutral elements */
6
+ --secondary-accent-hover: #484848; /* Darker gray for hover */
7
+
8
+ --info-accent: #1cc3dc; /* Vivid cyan for information elements */
9
+ --success-accent: #019561; /* Bright green for positive actions */
10
+ --success-accent-hover: #008456; /* Darker shade for hover */
11
+ --danger-accent: #ff5252; /* Bright red for warnings */
12
+ --danger-accent-hover: #e64545;
13
+
14
+ --warning-accent: #cc8801; /* Vibrant amber for warnings */
15
+ --warning-accent-hover: #d08802;
16
+
17
+ --box-shadow: rgba(0, 0, 0, 0.6); /* Softer shadow */
18
+ --box-shadow-error: rgba(255, 82, 82, 0.4); /* Red shadow for error indication */
19
+
20
+ --text-color: #e4e4e4; /* Slightly lighter for readability */
21
+ --text-accent-color: #1ca3ec; /* A sharper blue accent */
22
+ --text-placeholder: #888; /* Lighter gray for input placeholders */
23
+ --text-danger-color: #ff6666; /* Softer red */
24
+ --text-almost-hidden: #3d3d3d; /* Subtle, dark gray */
25
+
26
+ --body-bg: #1b1b1b; /* Deeper dark for body background */
27
+ --primary-bg: #262626; /* Primary background with more contrast */
28
+ --primary-bg-accent: #2d2d2d; /* Accent for card areas */
29
+ --primary-bg-accent-hover: #3a3a3a; /* Slightly lighter for hover */
30
+ --secondary-bg: #202020; /* Secondary dark background */
31
+ --border-color: #555; /* Slightly lighter gray for borders */
32
+ --danger-border-color: #922; /* Bold red for danger borders */
33
+
34
+ --footer-height: 25px;
35
+ }
36
+
37
+ body {
38
+ background-color: var(--body-bg);
39
+ color: var(--text-color);
40
+ font-family: "Roboto Mono", monospace;
41
+ overflow: hidden; /* No body scrolling */
42
+ height: fit-content;
43
+ }
44
+
45
+ body:has(.submodule) {
46
+ background-color: #0000;
47
+ }
48
+ body:has(.submodule) footer {
49
+ display: none;
50
+ }
51
+
52
+ .container-fluid {
53
+ padding: 20px;
54
+ background-color: var(--primary-bg);
55
+ border-radius: 8px;
56
+ box-shadow: 0 0 10px var(--box-shadow);
57
+ width: 90%;
58
+ margin-top: 10px;
59
+ }
60
+
61
+ #header {
62
+ background-color: var(--primary-bg);
63
+ padding: 8px 20px;
64
+ margin: 0;
65
+ display: block;
66
+ position: relative;
67
+ box-shadow: 0 0 10px var(--box-shadow);
68
+ width: 100vw;
69
+ }
70
+
71
+ footer {
72
+ position: sticky;
73
+ background-color: var(--primary-bg);
74
+ box-shadow: 0 0 10px var(--box-shadow);
75
+ height: var(--footer-height);
76
+ transform:translateY(25px); /* removed in core.js */
77
+ display: flex;
78
+ justify-content: space-between;
79
+ padding: 0 10px;
80
+ align-items: center;
81
+ bottom: 0;
82
+ color: var(--text-color);
83
+ font-size: .8em;
84
+ transition: all .2s ease-in-out;
85
+ }
86
+ footer .version span {
87
+ color: var(--text-placeholder);
88
+ }
89
+ .div-hide {
90
+ display: none !important;
91
+ }
92
+
93
+ #content {
94
+ width: 100vw;
95
+ height: 100%;
96
+ overflow-y: auto;
97
+ }
98
+
99
+ .scroll-container {
100
+ width: 100vw;
101
+ height: 100vh;
102
+ overflow-y: auto;
103
+ }
104
+
105
+
106
+ h1, h2, h3 {
107
+ font-weight: 600;
108
+ color: var(--text-color);
109
+ }
110
+
111
+ hr {
112
+ border-color: var(--border-color);
113
+ margin: 20px 0;
114
+ }
115
+ h1.title{
116
+ cursor: pointer;
117
+ }
118
+ .title span {
119
+ color: var(--text-accent-color);
120
+ }
121
+
122
+ .overview-container {
123
+ display: flex;
124
+ justify-content: space-around;
125
+ width: 100vw;
126
+ height: 100px;
127
+ }
128
+
129
+ /* Layout Styles */
130
+ details {
131
+ background-color: var(--secondary-bg);
132
+ border: 1px solid var(--border-color);
133
+ padding: 10px;
134
+ border-radius: 5px;
135
+ }
136
+
137
+ #scan-results {
138
+ margin-top: 5px;
139
+ }
140
+
141
+ #overview-frame, #ip-table-frame {
142
+ width: 100%;
143
+ }
144
+
145
+ #overview-frame {
146
+ height: 105px;
147
+ }
148
+
149
+
150
+ #scan-form {
151
+ width: 500px;
152
+ margin: 0;
153
+ }
154
+ #scan-form label {
155
+ margin-bottom: 0;
156
+ }
157
+ #scan-form input {
158
+ z-index: 2;
159
+ transition: all .2s ease-in-out;
160
+ border-radius: 5px !important; /* override bootstrap stuff */
161
+ padding-right: 34px;
162
+ margin-right: -34px;
163
+ }
164
+
165
+
166
+ #scan-form .input-group button {
167
+ background-color: var(--primary-bg-accent);
168
+ border: 0;
169
+ border-left: 1px var(--border-color) solid;
170
+ transition: all .2s ease-in-out;
171
+ height: 40px;
172
+ border-radius: 0 5px 5px 0;
173
+ margin-top: 1px;
174
+ transform: translateX(.5px);
175
+ }
176
+ #scan-form .input-group button:hover {
177
+ background-color: var(--primary-bg-accent-hover);
178
+ }
179
+ #scan-form .input-group button:active {
180
+ background-color: var(--primary-accent);
181
+ }
182
+
183
+ .label-container {
184
+ display: flex;
185
+ justify-content: space-between;
186
+ }
187
+ #subnet-info {
188
+ margin-right: 5px;
189
+ font-size: .8em;
190
+ padding: 2px 5px;
191
+ background-color: var(--secondary-bg);
192
+ border: 1px solid var(--border-color);
193
+ border-bottom: none;
194
+ border-radius: 5px 5px 0 0;
195
+ color: var(--text-color);
196
+ transition: all .2s ease-in-out;
197
+ height: 25px;
198
+ }
199
+ #scan-form.error #subnet-info,
200
+ #scan-form.error input
201
+ {
202
+ color: var(--text-danger-color);
203
+ border-color: var(--danger-border-color);
204
+ outline: 0 none;
205
+ }
206
+ #scan-form.error input:focus {
207
+ box-shadow: 0 1px 1px var(--box-shadow) inset, 0 0 8px var(--box-shadow-error);
208
+ }
209
+
210
+ #scan-progress-bar {
211
+ position: absolute;
212
+ bottom: 0;
213
+ left: 0;
214
+ width: 0;
215
+ background-color: var(--primary-accent);
216
+ height:0px;
217
+ transition: all .5s ease-in-out
218
+ }
219
+
220
+ #app-actions a .material-symbols-outlined {
221
+ font-size: inherit
222
+ }
223
+ #app-actions {
224
+ padding-top: 5px;
225
+ }
226
+
227
+ #app-actions,
228
+ #app-actions a {
229
+ font-size: 1.1em;
230
+ color: var(--text-color);
231
+ text-decoration: none;
232
+ cursor: pointer;
233
+ }
234
+ #app-actions a:hover {
235
+ color: var(--text-placeholder)
236
+ }
237
+
238
+ #power-button {
239
+ color: var(--success-accent);
240
+ transition: all .2s ease-in-out;
241
+ cursor: pointer;
242
+ }
243
+ #power-button:hover {
244
+ color: var(--text-danger-color);
245
+ }
246
+ #scan-actions {
247
+ display: flex;
248
+ justify-content: space-around;
249
+ align-items: center;
250
+ a {
251
+ text-decoration: none;
252
+ margin: 0 3px;
253
+ }
254
+ }
255
+
256
+
257
+
258
+ @media screen and (max-width: 681px) {
259
+ #power-button {
260
+ left: auto;
261
+ right: 0;
262
+ border-width: 0 0 1px 1px;
263
+ border-radius: 0 0 0 5px;
264
+ }
265
+ .container-fluid {
266
+ width:98%;
267
+ padding: 8px;
268
+ }
269
+ }
270
+
271
+ /* Card Styles */
272
+ .card {
273
+ background-color: var(--secondary-bg);
274
+ border-color: var(--border-color);
275
+ }
276
+
277
+ .card-header {
278
+ background-color: rgba(0, 0, 0, 0.5);
279
+ color: var(--text-color);
280
+ border-bottom: 1px solid var(--border-color);
281
+ }
282
+
283
+
284
+ /* Form / Input Styles */
285
+ form {
286
+ display: flex;
287
+ justify-content: space-between;
288
+ align-items: center;
289
+ gap: 15px;
290
+ margin-bottom: 20px;
291
+ }
292
+
293
+ .form-group {
294
+ flex-grow: 1;
295
+ display: flex;
296
+ flex-direction: column;
297
+ margin-bottom: 15px;
298
+ }
299
+
300
+ label {
301
+ color: var(--text-color);
302
+ font-weight: 500;
303
+ margin-bottom: 5px;
304
+ }
305
+
306
+ input[type="text"], input[type="number"], select, .form-control {
307
+ background-color: var(--secondary-bg);
308
+ border: 1px solid var(--border-color);
309
+ color: var(--text-color);
310
+ padding: 8px 10px;
311
+ font-size: 1rem;
312
+ border-radius: 5px;
313
+ }
314
+
315
+ input[type="text"]:focus, select:focus, .form-control:focus {
316
+ background-color: var(--body-bg);
317
+ color: var(--text-color);
318
+ border-color: var(--primary-accent);
319
+ outline: none;
320
+ }
321
+
322
+ input::placeholder {
323
+ color: var(--text-placeholder) !important;
324
+ }
325
+
326
+ button {
327
+ margin-left: 15px;
328
+ padding: 10px 20px;
329
+ }
330
+ .div-hide {
331
+ display: none !important;
332
+ }
333
+
334
+ #scan-form #scan-submit {
335
+ border: none;
336
+ padding: 10px 20px;
337
+ }
338
+
339
+ /* Button Styling */
340
+ .btn-primary, button.btn-primary {
341
+ background-color: var(--primary-accent);
342
+ color: var(--text-color);
343
+ font-size: 1rem;
344
+ cursor: pointer;
345
+ border-radius: 5px;
346
+ transition: background-color 0.2s ease;
347
+ }
348
+
349
+
350
+ .btn-primary:hover {
351
+ background-color: var(--primary-accent-hover);
352
+ }
353
+ .btn-secondary, button.btn-secondary {
354
+ background-color: var(--secondary-accent);
355
+ border: none;
356
+ color: var(--text-color);
357
+ font-size: 1rem;
358
+ cursor: pointer;
359
+ border-radius: 5px;
360
+ transition: background-color 0.2s ease;
361
+ }
362
+ .btn-secondary:hover {
363
+ background-color: var(--secondary-accent-hover);
364
+ }
365
+ .btn-info, button.btn-info {
366
+ background-color: var(--info-accent);
367
+ border: none;
368
+ color: var(--text-color);
369
+ font-size: 1rem;
370
+ cursor: pointer;
371
+ border-radius: 5px;
372
+ transition: background-color 0.2s ease;
373
+ }
374
+ .btn-info:hover {
375
+ background-color: var(--info-accent);
376
+ color: var(--text-color);
377
+ }
378
+ input[type="range"] {
379
+ -webkit-appearance: none;
380
+ appearance: none;
381
+ width: 100%;
382
+ height: 8px;
383
+ background-color: var(--border-color);
384
+ outline: none;
385
+ border-radius: 5px;
386
+ margin: 5px 0;
387
+ }
388
+
389
+ input[type="range"]::-webkit-slider-thumb,
390
+ input[type="range"]::-moz-range-thumb {
391
+ -webkit-appearance: none;
392
+ appearance: none;
393
+ width: 16px;
394
+ height: 16px;
395
+ border-radius: 50%;
396
+ background: var(--primary-accent);
397
+ cursor: pointer;
398
+ }
399
+ #parallelism-value span {
400
+ color: var(--text-danger-color);
401
+ font-weight: 500;
402
+ }
403
+ .port-list-wrapper {
404
+ position: relative;
405
+ display: inline-block;
406
+ width: 100%;
407
+ }
408
+
409
+ .port-list {
410
+ position: relative;
411
+ background-color: var(--body-bg);
412
+ border: 1px solid var(--border-color);
413
+ color: var(--text-color);
414
+ padding: 10px;
415
+ cursor: pointer;
416
+ width: 100%;
417
+ user-select: none;
418
+ appearance: none; /* Hide default arrow */
419
+ transition: all .2s ease-in-out;
420
+ }
421
+
422
+ .port-list:focus {
423
+ border-color: var(--primary-accent-hover);
424
+ outline: none;
425
+ }
426
+
427
+ .port-list-wrapper::after {
428
+ content: '▼';
429
+ position: absolute;
430
+ top: 14px;
431
+ right: 10px;
432
+ pointer-events: none;
433
+ color: var(--text-color);
434
+ }
435
+
436
+ .port-list-dropdown {
437
+ display: none;
438
+ position: absolute;
439
+ background-color: var(--body-bg);
440
+ border: 1px solid var(--border-color);
441
+ width: 100%;
442
+ max-height: 200px;
443
+ overflow-y: auto;
444
+ z-index: 10;
445
+ }
446
+
447
+ .port-list-dropdown.open {
448
+ display: block;
449
+ }
450
+
451
+ .port-list-dropdown div {
452
+ padding: 10px;
453
+ color: var(--text-color);
454
+ cursor: pointer;
455
+ }
456
+
457
+ .port-list-dropdown div:hover {
458
+ background-color: var(--secondary-accent);
459
+ color: var(--text-color);
460
+ }
461
+
462
+ .text-secondary {
463
+ color: var(--secondary-accent)
464
+ }
465
+ .secondary-icon-btn {
466
+ color: var(--secondary-accent);
467
+ transition: .2s all ease-in-out;
468
+ }
469
+ .secondary-icon-btn:hover {
470
+ color: var(--text-color);
471
+ cursor: pointer;
472
+ }
473
+ /* Table Styles */
474
+ .table-container {
475
+ width: 100vw;
476
+ margin: auto;
477
+ }
478
+
479
+ .table {
480
+ color: var(--text-color);
481
+ width: 100%;
482
+ }
483
+
484
+ .table th, .table td {
485
+ background-color: var(--secondary-bg);
486
+ border-color: var(--border-color);
487
+ color: var(--text-color);
488
+ }
489
+
490
+ .table thead th {
491
+ background-color: var(--secondary-bg);
492
+ }
493
+
494
+ .table-striped tbody tr:nth-of-type(odd) td {
495
+ background-color: var(--secondary-bg);
496
+ }
497
+
498
+ .table-striped tbody tr:nth-of-type(even) td {
499
+ background-color: var(--primary-bg);
500
+ }
501
+
502
+ .table tbody tr:hover {
503
+ background-color: var(--primary-bg-accent);
504
+ }
505
+
506
+
507
+ /* Badge Styles */
508
+ .badge-warning {
509
+ background-color: var(--warning-accent);
510
+ }
511
+
512
+ .badge-success, .badge-info, .badge-secondary, .badge-warning {
513
+ color: var(--text-color);
514
+ }
515
+
516
+ .badge-success {
517
+ background-color: var(--success-accent);
518
+ }
519
+
520
+ .badge-info {
521
+ background-color: var(--info-accent);
522
+ }
523
+
524
+ .badge-secondary {
525
+ background-color: var(--secondary-accent);
526
+ }
527
+
528
+
529
+ /* Protocol Open Button Styles */
530
+ span.alt {
531
+ color: var(--text-accent-color);
532
+ }
533
+ .colorful-buttons a{
534
+ margin:2px;
535
+ color: var(--text-color);
536
+ border-color: var(--border-color);
537
+ }
538
+ .colorful-buttons a:nth-of-type(4n+1) {
539
+ background-color: var(--primary-accent);
540
+ }
541
+
542
+ .colorful-buttons a:nth-of-type(4n+1):hover {
543
+ background-color: var(--primary-accent-hover);
544
+ }
545
+
546
+ .colorful-buttons a:nth-of-type(4n+2) {
547
+ background-color: var(--success-accent);
548
+ }
549
+
550
+ .colorful-buttons a:nth-of-type(4n+2):hover {
551
+ background-color: var(--success-accent-hover);
552
+ }
553
+
554
+ .colorful-buttons a:nth-of-type(4n+3) {
555
+ background-color: var(--warning-accent);
556
+ }
557
+
558
+ .colorful-buttons a:nth-of-type(4n+3):hover {
559
+ background-color: var(--warning-accent-hover);
560
+ }
561
+
562
+ .colorful-buttons a:nth-of-type(4n+4) {
563
+ background-color: var(--danger-accent);
564
+ }
565
+
566
+ .colorful-buttons a:nth-of-type(4n+4):hover {
567
+ background-color: var(--danger-accent-hover);
568
+ }
569
+
570
+
571
+ /* Transitions */
572
+ input, select, button, details {
573
+ transition: all 0.3s ease-in-out;
574
+ }
575
+
576
+ /* Scrollbar styling */
577
+ ::-webkit-scrollbar {
578
+ width: 12px; /* Width of the scrollbar */
579
+ }
580
+
581
+ ::-webkit-scrollbar-track {
582
+ background-color: var(--secondary-bg); /* Background of the scrollbar track */
583
+ border-radius: 10px;
584
+ }
585
+
586
+ ::-webkit-scrollbar-thumb {
587
+ background-color: var(--border-color); /* Darker thumb for the scrollbar */
588
+ border-radius: 10px;
589
+ border: 3px solid var(--secondary-bg); /* Adds padding between the thumb and track */
590
+ }
591
+
592
+ .error-container {
593
+ height: 300px;
594
+ overflow-y: scroll;
595
+ margin: 10px;
596
+ padding: 5px;
597
+ background-color: var(--secondary-bg);
598
+ }
599
+
600
+ /* For Firefox */
601
+ html {
602
+ scrollbar-width: thin;
603
+ scrollbar-color: var(--border-color) var(--secondary-bg);
604
+ }
605
+
606
+ .dropdown-menu {
607
+ background-color: var(--body-bg);
608
+ border: 1px solid var(--border-color);
609
+
610
+ }
611
+ .dropdown-menu.show{
612
+ width: 100%;
613
+ transform: translate(0px, 42px);
614
+ }
615
+
616
+ .dropdown-item {
617
+ color: var(--text-color);
618
+ }
619
+
620
+ .dropdown-item:hover {
621
+ background-color: var(--border-color);
622
+ color: var(--text-color);
623
+ }
624
+
625
+
626
+ .material-symbols-outlined {
627
+ font-variation-settings:
628
+ 'FILL' 0,
629
+ 'wght' 400,
630
+ 'GRAD' 0,
631
+ 'opsz' 24
632
+ }
633
+
634
+ #shutdown-sub-sub {
635
+ color: var(--text-almost-hidden);
636
+ }
637
+
638
+
639
+ /* START overview container */
640
+
641
+ #overview-container .card {
642
+ height: 85px;
643
+ }
644
+
645
+ #overview-container .card-header {
646
+ padding: 5px;
647
+ font-size: 1rem;
648
+ text-wrap: nowrap;
649
+ height: 35px;
650
+ display: flex;
651
+ justify-content: center;
652
+ align-items: center;
653
+ font-weight: bold;
654
+ }
655
+
656
+ #overview-container .card-body {
657
+ padding: 5px;
658
+ display: flex;
659
+ justify-content: center;
660
+ align-items: center;
661
+ text-wrap: nowrap;
662
+ }
663
+
664
+ #scan-devices-alive,
665
+ #scan-devices-scanned,
666
+ #scan-devices-total {
667
+ margin: 3px;
668
+ }
669
+
670
+ #overview-container .col-4 {
671
+ min-width: 100px;
672
+ }
673
+
674
+ #progress-card {
675
+ background-color: var(--primary-accent);
676
+ }
677
+
678
+ #runtime-card {
679
+ background-color: var(--success-accent);
680
+ }
681
+
682
+ #stage-card {
683
+ background-color: var(--warning-accent);
684
+ }
685
+
686
+ /* width of iFrame, not page */
687
+
688
+ @media screen and (max-width: 885px) {
689
+ #overview-container .col-4 {
690
+ padding: 0 5px;
691
+ }
692
+
693
+ }
694
+ @media screen and (max-width: 760px) {
695
+ #overview-container .card-header {
696
+ font-size: .8rem;
697
+ }
698
+ }
699
+ @media screen and (max-width: 555px) {
700
+ #overview-container .col-4 {
701
+ padding: 0 2px;
702
+ }
703
+
704
+ }
705
+ @media screen and (max-width: 533px) {
706
+ #overview-container .card-header {
707
+ font-size: .6rem;
708
+ }
709
+ #overview-container .card-body {
710
+ font-size: .8rem;
711
+ }
712
+
713
+ }
714
+
715
+ /* END overview container */
Binary file
@@ -0,0 +1 @@
1
+ {"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
Binary file