node-hp-scan-to 1.6.1 → 1.7.1
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.
- package/README.md +247 -143
- package/dist/Destination.js +17 -7
- package/dist/Destination.js.map +1 -1
- package/dist/DeviceCapabilities.d.ts +2 -0
- package/dist/DeviceCapabilities.js.map +1 -1
- package/dist/DiscoveryTree.js.map +1 -1
- package/dist/Event.js.map +1 -1
- package/dist/EventTable.js.map +1 -1
- package/dist/HPApi.js +23 -15
- package/dist/HPApi.js.map +1 -1
- package/dist/InputSource.js +1 -1
- package/dist/InputSource.js.map +1 -1
- package/dist/Job.js +6 -6
- package/dist/Job.js.map +1 -1
- package/dist/JpegUtil.d.ts +0 -2
- package/dist/JpegUtil.js.map +1 -1
- package/dist/KnownShortcut.js.map +1 -1
- package/dist/PathHelper.js +2 -0
- package/dist/PathHelper.js.map +1 -1
- package/dist/ScanCaps.d.ts +6 -0
- package/dist/ScanCaps.js +18 -0
- package/dist/ScanCaps.js.map +1 -1
- package/dist/ScanContent.js.map +1 -1
- package/dist/ScanJobManifest.js.map +1 -1
- package/dist/ScanJobSettings.js.map +1 -1
- package/dist/ScanStatus.js.map +1 -1
- package/dist/WalkupScanDestination.js.map +1 -1
- package/dist/WalkupScanDestinations.js.map +1 -1
- package/dist/WalkupScanManifest.js.map +1 -1
- package/dist/WalkupScanToCompCaps.js.map +1 -1
- package/dist/WalkupScanToCompDestination.js.map +1 -1
- package/dist/WalkupScanToCompDestinations.js.map +1 -1
- package/dist/WalkupScanToCompEvent.js.map +1 -1
- package/dist/WalkupScanToCompManifest.js.map +1 -1
- package/dist/commitInfo.json +1 -1
- package/dist/delay.js +1 -2
- package/dist/delay.js.map +1 -1
- package/dist/healthcheck.js +1 -2
- package/dist/healthcheck.js.map +1 -1
- package/dist/index.js +22 -12
- package/dist/index.js.map +1 -1
- package/dist/listening.js +5 -6
- package/dist/listening.js.map +1 -1
- package/dist/nextcloud/NextcloudConfig.js.map +1 -1
- package/dist/nextcloud/nextcloud.js +4 -6
- package/dist/nextcloud/nextcloud.js.map +1 -1
- package/dist/paperless/PaperlessConfig.js.map +1 -1
- package/dist/paperless/paperless.js +4 -5
- package/dist/paperless/paperless.js.map +1 -1
- package/dist/pdfProcessing.js +4 -5
- package/dist/pdfProcessing.js.map +1 -1
- package/dist/postProcessing.js +2 -4
- package/dist/postProcessing.js.map +1 -1
- package/dist/readDeviceCapabilities.js +24 -20
- package/dist/readDeviceCapabilities.js.map +1 -1
- package/dist/scanProcessing.d.ts +2 -2
- package/dist/scanProcessing.js +28 -30
- package/dist/scanProcessing.js.map +1 -1
- package/package.json +19 -17
- package/dist/PaperlessCOnfig.d.ts +0 -7
- package/dist/PaperlessCOnfig.js +0 -3
- package/dist/PaperlessCOnfig.js.map +0 -1
- package/dist/PaperlessConfig.d.ts +0 -7
- package/dist/PaperlessConfig.js +0 -3
- package/dist/PaperlessConfig.js.map +0 -1
- package/dist/paperless.d.ts +0 -7
- package/dist/paperless.js +0 -83
- package/dist/paperless.js.map +0 -1
- package/dist/test/DiscoveryTree.test.d.ts +0 -1
- package/dist/test/DiscoveryTree.test.js +0 -68
- package/dist/test/DiscoveryTree.test.js.map +0 -1
- package/dist/test/EtagEventTable.test.d.ts +0 -1
- package/dist/test/EtagEventTable.test.js +0 -93
- package/dist/test/EtagEventTable.test.js.map +0 -1
- package/dist/test/Job.test.d.ts +0 -1
- package/dist/test/Job.test.js +0 -104
- package/dist/test/Job.test.js.map +0 -1
- package/dist/test/JpegUtil.test.d.ts +0 -1
- package/dist/test/JpegUtil.test.js +0 -53
- package/dist/test/JpegUtil.test.js.map +0 -1
- package/dist/test/PathHelper.test.d.ts +0 -1
- package/dist/test/PathHelper.test.js +0 -98
- package/dist/test/PathHelper.test.js.map +0 -1
- package/dist/test/ScanCaps.test.d.ts +0 -1
- package/dist/test/ScanCaps.test.js +0 -96
- package/dist/test/ScanCaps.test.js.map +0 -1
- package/dist/test/ScanJobManifest.test.d.ts +0 -1
- package/dist/test/ScanJobManifest.test.js +0 -56
- package/dist/test/ScanJobManifest.test.js.map +0 -1
- package/dist/test/ScanJobSettings.test.d.ts +0 -1
- package/dist/test/ScanJobSettings.test.js +0 -59
- package/dist/test/ScanJobSettings.test.js.map +0 -1
- package/dist/test/ScanStatus.test.d.ts +0 -1
- package/dist/test/ScanStatus.test.js +0 -75
- package/dist/test/ScanStatus.test.js.map +0 -1
- package/dist/test/WalkupScanDestination.test.d.ts +0 -1
- package/dist/test/WalkupScanDestination.test.js +0 -80
- package/dist/test/WalkupScanDestination.test.js.map +0 -1
- package/dist/test/WalkupScanDestinations.test.d.ts +0 -1
- package/dist/test/WalkupScanDestinations.test.js +0 -68
- package/dist/test/WalkupScanDestinations.test.js.map +0 -1
- package/dist/test/WalkupScanManifest.test.d.ts +0 -1
- package/dist/test/WalkupScanManifest.test.js +0 -46
- package/dist/test/WalkupScanManifest.test.js.map +0 -1
- package/dist/test/WalkupScanToCompCaps.test.d.ts +0 -1
- package/dist/test/WalkupScanToCompCaps.test.js +0 -56
- package/dist/test/WalkupScanToCompCaps.test.js.map +0 -1
- package/dist/test/WalkupScanToCompDestination.test.d.ts +0 -1
- package/dist/test/WalkupScanToCompDestination.test.js +0 -58
- package/dist/test/WalkupScanToCompDestination.test.js.map +0 -1
- package/dist/test/WalkupScanToCompDestinations.test.d.ts +0 -1
- package/dist/test/WalkupScanToCompDestinations.test.js +0 -58
- package/dist/test/WalkupScanToCompDestinations.test.js.map +0 -1
- package/dist/test/WalkupScanToCompEvent.test.d.ts +0 -1
- package/dist/test/WalkupScanToCompEvent.test.js +0 -46
- package/dist/test/WalkupScanToCompEvent.test.js.map +0 -1
- package/dist/test/WalkupScanToCompManifest.test.d.ts +0 -1
- package/dist/test/WalkupScanToCompManifest.test.js +0 -46
- package/dist/test/WalkupScanToCompManifest.test.js.map +0 -1
- package/dist/test/clean.d.ts +0 -1
- package/dist/test/clean.js +0 -21
- package/dist/test/clean.js.map +0 -1
- package/dist/test/nextcloud.test.d.ts +0 -1
- package/dist/test/nextcloud.test.js +0 -165
- package/dist/test/nextcloud.test.js.map +0 -1
- package/dist/test/scanProcessing.test.d.ts +0 -1
- package/dist/test/scanProcessing.test.js +0 -105
- package/dist/test/scanProcessing.test.js.map +0 -1
- package/dist/test-bonjour.d.ts +0 -1
- package/dist/test-bonjour.js +0 -20
- package/dist/test-bonjour.js.map +0 -1
- package/nodemon.json +0 -6
- package/src/Destination.ts +0 -63
- package/src/DeviceCapabilities.ts +0 -8
- package/src/DiscoveryTree.ts +0 -56
- package/src/Event.ts +0 -55
- package/src/EventTable.ts +0 -45
- package/src/HPApi.ts +0 -510
- package/src/InputSource.ts +0 -4
- package/src/Job.ts +0 -134
- package/src/JpegUtil.ts +0 -327
- package/src/KnownShortcut.ts +0 -6
- package/src/PathHelper.ts +0 -106
- package/src/ScanCaps.ts +0 -81
- package/src/ScanContent.ts +0 -15
- package/src/ScanJobManifest.ts +0 -56
- package/src/ScanJobSettings.ts +0 -84
- package/src/ScanStatus.ts +0 -48
- package/src/WalkupScanDestination.ts +0 -74
- package/src/WalkupScanDestinations.ts +0 -46
- package/src/WalkupScanManifest.ts +0 -59
- package/src/WalkupScanToCompCaps.ts +0 -36
- package/src/WalkupScanToCompDestination.ts +0 -79
- package/src/WalkupScanToCompDestinations.ts +0 -47
- package/src/WalkupScanToCompEvent.ts +0 -30
- package/src/WalkupScanToCompManifest.ts +0 -59
- package/src/commitInfo.json +0 -3
- package/src/delay.ts +0 -5
- package/src/healthcheck.ts +0 -17
- package/src/index.ts +0 -588
- package/src/listening.ts +0 -144
- package/src/nextcloud/NextcloudConfig.ts +0 -7
- package/src/nextcloud/nextcloud.ts +0 -146
- package/src/paperless/PaperlessConfig.ts +0 -7
- package/src/paperless/paperless.ts +0 -110
- package/src/pdfProcessing.ts +0 -67
- package/src/postProcessing.ts +0 -165
- package/src/readDeviceCapabilities.ts +0 -52
- package/src/scanProcessing.ts +0 -570
- package/tsconfig.json +0 -34
package/src/Job.ts
DELETED
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
import { Parser } from "xml2js";
|
|
3
|
-
const parser = new Parser();
|
|
4
|
-
import { promisify } from "util";
|
|
5
|
-
const parseString = promisify<string, JobData>(parser.parseString);
|
|
6
|
-
|
|
7
|
-
export interface JobData {
|
|
8
|
-
"j:Job": {
|
|
9
|
-
ScanJob: {
|
|
10
|
-
PreScanPage?: {
|
|
11
|
-
PageState: string[];
|
|
12
|
-
BinaryURL: string[];
|
|
13
|
-
PageNumber: string[];
|
|
14
|
-
BufferInfo: {
|
|
15
|
-
ImageWidth: string[];
|
|
16
|
-
ImageHeight: string[];
|
|
17
|
-
ScanSettings: {
|
|
18
|
-
InputSource: string[];
|
|
19
|
-
ContentType: string[];
|
|
20
|
-
XResolution: string[];
|
|
21
|
-
YResolution: string[];
|
|
22
|
-
}[];
|
|
23
|
-
}[];
|
|
24
|
-
}[];
|
|
25
|
-
PostScanPage?: {
|
|
26
|
-
PageNumber: string[];
|
|
27
|
-
}[];
|
|
28
|
-
}[];
|
|
29
|
-
"j:JobState": string[];
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export default class Job {
|
|
34
|
-
private readonly data: JobData;
|
|
35
|
-
constructor(data: JobData) {
|
|
36
|
-
this.data = data;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
static async createJob(content: string): Promise<Job> {
|
|
40
|
-
const parsed = await parseString(content);
|
|
41
|
-
return new Job(parsed);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
get currentPageNumber(): string | null {
|
|
45
|
-
const preScanPage = this.data["j:Job"].ScanJob[0].PreScanPage;
|
|
46
|
-
if (preScanPage) {
|
|
47
|
-
return preScanPage[0].PageNumber[0];
|
|
48
|
-
} else {
|
|
49
|
-
return null;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
get totalPageNumber(): number | null {
|
|
54
|
-
if (this.data["j:Job"].ScanJob[0].PostScanPage) {
|
|
55
|
-
return parseInt(
|
|
56
|
-
this.data["j:Job"].ScanJob[0].PostScanPage[0].PageNumber[0],
|
|
57
|
-
10,
|
|
58
|
-
);
|
|
59
|
-
}
|
|
60
|
-
return null;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
get jobState():
|
|
64
|
-
| "Completed"
|
|
65
|
-
| "Processing"
|
|
66
|
-
| "ReadyToUpload"
|
|
67
|
-
| "Canceled"
|
|
68
|
-
| string {
|
|
69
|
-
return this.data["j:Job"]["j:JobState"][0];
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
get pageState(): string | null {
|
|
73
|
-
const preScanPage = this.data["j:Job"].ScanJob[0].PreScanPage;
|
|
74
|
-
if (preScanPage) {
|
|
75
|
-
return preScanPage[0].PageState[0];
|
|
76
|
-
} else {
|
|
77
|
-
return null;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
get binaryURL(): string | null {
|
|
82
|
-
if (this.data["j:Job"].ScanJob[0].PreScanPage) {
|
|
83
|
-
return this.data["j:Job"].ScanJob[0].PreScanPage[0].BinaryURL[0];
|
|
84
|
-
}
|
|
85
|
-
return null;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
get imageWidth(): number | null {
|
|
89
|
-
if (
|
|
90
|
-
!Object.prototype.hasOwnProperty.call(
|
|
91
|
-
this.data["j:Job"].ScanJob[0],
|
|
92
|
-
"PreScanPage",
|
|
93
|
-
)
|
|
94
|
-
) {
|
|
95
|
-
return null;
|
|
96
|
-
}
|
|
97
|
-
return parseInt(
|
|
98
|
-
this.data["j:Job"].ScanJob[0].PreScanPage?.[0]?.BufferInfo?.[0]
|
|
99
|
-
?.ImageWidth[0] ?? "",
|
|
100
|
-
);
|
|
101
|
-
}
|
|
102
|
-
get imageHeight(): number | null {
|
|
103
|
-
if (this.data["j:Job"].ScanJob[0].PreScanPage) {
|
|
104
|
-
return parseInt(
|
|
105
|
-
this.data["j:Job"].ScanJob[0].PreScanPage[0].BufferInfo[0]
|
|
106
|
-
.ImageHeight[0],
|
|
107
|
-
);
|
|
108
|
-
}
|
|
109
|
-
return null;
|
|
110
|
-
}
|
|
111
|
-
get xResolution(): number | null {
|
|
112
|
-
if (this.data["j:Job"].ScanJob[0].PreScanPage) {
|
|
113
|
-
return parseInt(
|
|
114
|
-
this.data["j:Job"].ScanJob[0].PreScanPage?.[0]?.BufferInfo?.[0]
|
|
115
|
-
?.ScanSettings?.[0]?.XResolution[0] ?? "",
|
|
116
|
-
);
|
|
117
|
-
}
|
|
118
|
-
return null;
|
|
119
|
-
}
|
|
120
|
-
get yResolution(): number | null {
|
|
121
|
-
if (
|
|
122
|
-
Object.prototype.hasOwnProperty.call(
|
|
123
|
-
this.data["j:Job"].ScanJob[0],
|
|
124
|
-
"PreScanPage",
|
|
125
|
-
)
|
|
126
|
-
) {
|
|
127
|
-
return parseInt(
|
|
128
|
-
this.data["j:Job"].ScanJob[0].PreScanPage?.[0]?.BufferInfo?.[0]
|
|
129
|
-
?.ScanSettings?.[0]?.YResolution[0] ?? "",
|
|
130
|
-
);
|
|
131
|
-
}
|
|
132
|
-
return null;
|
|
133
|
-
}
|
|
134
|
-
}
|
package/src/JpegUtil.ts
DELETED
|
@@ -1,327 +0,0 @@
|
|
|
1
|
-
let debug = false;
|
|
2
|
-
|
|
3
|
-
const start_of_Frame_0 = "FFC0";
|
|
4
|
-
const define_number_of_lines = "FFDC";
|
|
5
|
-
|
|
6
|
-
export default class JpegUtil {
|
|
7
|
-
static setDebug(dbg: boolean) {
|
|
8
|
-
debug = dbg;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
private static logDebug(msg: string | object) {
|
|
12
|
-
if (debug) {
|
|
13
|
-
console.log(msg);
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
private static numToHex(s: number) {
|
|
18
|
-
return s.toString(16).padStart(2, "0").toUpperCase();
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
static GetJpgSize(buffer: Buffer): { height: number; width: number } | null {
|
|
22
|
-
let size: { height: number; width: number } | null = null;
|
|
23
|
-
this.parse(buffer, {
|
|
24
|
-
[start_of_Frame_0]: (start: number, length: number) => {
|
|
25
|
-
// read the the "Start of frame" marker which contains the file size
|
|
26
|
-
if (6 < length) {
|
|
27
|
-
const pHeight = buffer[start + 3] * 256 + buffer[start + 4];
|
|
28
|
-
const pWidth = buffer[start + 5] * 256 + buffer[start + 6];
|
|
29
|
-
|
|
30
|
-
size = { height: pHeight, width: pWidth };
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// stop processing
|
|
34
|
-
return true;
|
|
35
|
-
},
|
|
36
|
-
});
|
|
37
|
-
return size;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
static setJpgSize(
|
|
41
|
-
buffer: Buffer,
|
|
42
|
-
size: { height: number; width: number },
|
|
43
|
-
): boolean {
|
|
44
|
-
let sizeWritten = false;
|
|
45
|
-
const parsingSucceed = this.parse(buffer, {
|
|
46
|
-
[start_of_Frame_0]: (start: number, length: number) => {
|
|
47
|
-
// read the the "Start of frame" marker which contains the file size
|
|
48
|
-
|
|
49
|
-
// write the picture size
|
|
50
|
-
if (6 < length) {
|
|
51
|
-
const height = Buffer.from([0x00, 0x00]);
|
|
52
|
-
height.writeInt16BE(size.height);
|
|
53
|
-
buffer[start + 3] = height[0];
|
|
54
|
-
buffer[start + 4] = height[1];
|
|
55
|
-
|
|
56
|
-
const width = Buffer.from([0x00, 0x00]);
|
|
57
|
-
width.writeInt16BE(size.width);
|
|
58
|
-
buffer[start + 5] = width[0];
|
|
59
|
-
buffer[start + 6] = width[1];
|
|
60
|
-
|
|
61
|
-
sizeWritten = true;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// stop processing
|
|
65
|
-
return true;
|
|
66
|
-
},
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
if (!parsingSucceed) {
|
|
70
|
-
return false;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
return sizeWritten;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
static setJpgHeight(buffer: Buffer, height: number): boolean {
|
|
77
|
-
let heightWritten = false;
|
|
78
|
-
const parsingSucceed = this.parse(buffer, {
|
|
79
|
-
[start_of_Frame_0]: (start: number, length: number) => {
|
|
80
|
-
// read the "Start of frame" marker which contains the file size
|
|
81
|
-
|
|
82
|
-
// write the picture size
|
|
83
|
-
heightWritten = this.writeHeightInStartOfFrame(
|
|
84
|
-
buffer,
|
|
85
|
-
start,
|
|
86
|
-
length,
|
|
87
|
-
height,
|
|
88
|
-
);
|
|
89
|
-
|
|
90
|
-
// stop processing
|
|
91
|
-
return true;
|
|
92
|
-
},
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
if (!parsingSucceed) {
|
|
96
|
-
return false;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
return heightWritten;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
static fixSizeWithDNL(buffer: Buffer): number | null {
|
|
103
|
-
let numberOfLine: number | null = null;
|
|
104
|
-
let startOfStartOfFrame: number | null = null;
|
|
105
|
-
let lengthOfStartOfFrame: number | null = null;
|
|
106
|
-
this.parse(buffer, {
|
|
107
|
-
[define_number_of_lines]: (start: number, length: number) => {
|
|
108
|
-
numberOfLine = this.readNumberOfLineFromDNL(buffer, start, length);
|
|
109
|
-
return false; // don't stop
|
|
110
|
-
},
|
|
111
|
-
[start_of_Frame_0]: (start: number, length: number) => {
|
|
112
|
-
startOfStartOfFrame = start;
|
|
113
|
-
lengthOfStartOfFrame = length;
|
|
114
|
-
return false; // don't stop
|
|
115
|
-
},
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
if (numberOfLine == null) {
|
|
119
|
-
this.logDebug("DNL marker not found impossible to fix height");
|
|
120
|
-
return null;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
if (startOfStartOfFrame == null || lengthOfStartOfFrame == null) {
|
|
124
|
-
this.logDebug(
|
|
125
|
-
"Start of frame 0 not found, either jpeg parsing is broken either the stream is corrupted",
|
|
126
|
-
);
|
|
127
|
-
return null;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
if (
|
|
131
|
-
this.writeHeightInStartOfFrame(
|
|
132
|
-
buffer,
|
|
133
|
-
startOfStartOfFrame,
|
|
134
|
-
lengthOfStartOfFrame,
|
|
135
|
-
numberOfLine,
|
|
136
|
-
)
|
|
137
|
-
) {
|
|
138
|
-
return numberOfLine;
|
|
139
|
-
}
|
|
140
|
-
return null;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
private static writeHeightInStartOfFrame(
|
|
144
|
-
buffer: Buffer,
|
|
145
|
-
startOfStartOfFrame: number,
|
|
146
|
-
lengthOfStartOfFrame: number,
|
|
147
|
-
numberOfLine: number,
|
|
148
|
-
): boolean {
|
|
149
|
-
// write the picture height
|
|
150
|
-
if (6 < lengthOfStartOfFrame) {
|
|
151
|
-
const heightBuffer = Buffer.from([0x00, 0x00]);
|
|
152
|
-
heightBuffer.writeInt16BE(numberOfLine);
|
|
153
|
-
buffer[startOfStartOfFrame + 3] = heightBuffer[0];
|
|
154
|
-
buffer[startOfStartOfFrame + 4] = heightBuffer[1];
|
|
155
|
-
|
|
156
|
-
return true;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
return false;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
static readNumberOfLineFromDNL(
|
|
163
|
-
buffer: Buffer,
|
|
164
|
-
start: number,
|
|
165
|
-
length: number,
|
|
166
|
-
): number | null {
|
|
167
|
-
let numberOfLine: number | null = null;
|
|
168
|
-
|
|
169
|
-
// read the number of line
|
|
170
|
-
if (3 < length) {
|
|
171
|
-
numberOfLine = buffer[start + 2] * 256 + buffer[start + 3];
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
return numberOfLine;
|
|
175
|
-
}
|
|
176
|
-
static parse(
|
|
177
|
-
buffer: Buffer,
|
|
178
|
-
markerHandler: {
|
|
179
|
-
[key: string]: (start: number, length: number) => boolean;
|
|
180
|
-
},
|
|
181
|
-
): boolean {
|
|
182
|
-
let i: number = 0;
|
|
183
|
-
|
|
184
|
-
if (!this.isSOIHeader(i, buffer)) {
|
|
185
|
-
this.logDebug("Not a valid SOI header");
|
|
186
|
-
return false;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
i += 4;
|
|
190
|
-
|
|
191
|
-
// Check for valid JPEG header (null terminated JFIF)
|
|
192
|
-
if (!this.isValidJpegHeader(i, buffer)) {
|
|
193
|
-
this.logDebug("Not a valid JFIF string");
|
|
194
|
-
return false;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
return this.parseMarker(buffer, i, markerHandler);
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
private static isValidJpegHeader(i: number, buffer: Buffer) {
|
|
201
|
-
return (
|
|
202
|
-
i + 6 < buffer.length &&
|
|
203
|
-
buffer[i + 2] == "J".charCodeAt(0) &&
|
|
204
|
-
buffer[i + 3] == "F".charCodeAt(0) &&
|
|
205
|
-
buffer[i + 4] == "I".charCodeAt(0) &&
|
|
206
|
-
buffer[i + 5] == "F".charCodeAt(0) &&
|
|
207
|
-
buffer[i + 6] == 0x00
|
|
208
|
-
);
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
private static isSOIHeader(i: number, buffer: Buffer) {
|
|
212
|
-
return (
|
|
213
|
-
i + 3 < buffer.length &&
|
|
214
|
-
buffer[i] == 0xff &&
|
|
215
|
-
buffer[i + 1] == 0xd8 &&
|
|
216
|
-
buffer[i + 2] == 0xff &&
|
|
217
|
-
buffer[i + 3] == 0xe0
|
|
218
|
-
);
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
private static getBlockLength(
|
|
222
|
-
buffer: Buffer,
|
|
223
|
-
i: number,
|
|
224
|
-
marker: string,
|
|
225
|
-
): number | null {
|
|
226
|
-
if (
|
|
227
|
-
marker === "FFDA" ||
|
|
228
|
-
marker === "FFD0" ||
|
|
229
|
-
marker === "FFD1" ||
|
|
230
|
-
marker === "FFD2" ||
|
|
231
|
-
marker === "FFD3" ||
|
|
232
|
-
marker === "FFD4" ||
|
|
233
|
-
marker === "FFD5" ||
|
|
234
|
-
marker === "FFD6" ||
|
|
235
|
-
marker === "FFD7"
|
|
236
|
-
) {
|
|
237
|
-
return JpegUtil.findCurrentBlockSize(buffer, i + 2, marker);
|
|
238
|
-
} else {
|
|
239
|
-
// read the new block length
|
|
240
|
-
const blockLength = buffer[i + 2] * 256 + buffer[i + 3];
|
|
241
|
-
|
|
242
|
-
this.logDebug(`block size for ${marker} is ${blockLength}`);
|
|
243
|
-
return blockLength;
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
private static findCurrentBlockSize(
|
|
248
|
-
buffer: Buffer,
|
|
249
|
-
i: number,
|
|
250
|
-
current_marker: string,
|
|
251
|
-
): number | null {
|
|
252
|
-
for (let j = 0; i + j < buffer.length; j++) {
|
|
253
|
-
if (buffer[i + j] === 0xff) {
|
|
254
|
-
if (i + j + 1 < buffer.length) {
|
|
255
|
-
if (buffer[i + j + 1] == 0x00) {
|
|
256
|
-
// it's ok just continue
|
|
257
|
-
} else {
|
|
258
|
-
// we've just found the end of the Start of Scan
|
|
259
|
-
return j;
|
|
260
|
-
}
|
|
261
|
-
} else {
|
|
262
|
-
this.logDebug(
|
|
263
|
-
`Premature end of stream reach while searching for the block size inside marker ${current_marker}`,
|
|
264
|
-
);
|
|
265
|
-
return null;
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
return null;
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
private static parseMarker(
|
|
273
|
-
buffer: Buffer,
|
|
274
|
-
i: number,
|
|
275
|
-
markerHandler: {
|
|
276
|
-
[key: string]: (start: number, length: number) => boolean;
|
|
277
|
-
},
|
|
278
|
-
): boolean {
|
|
279
|
-
let marker = "";
|
|
280
|
-
|
|
281
|
-
//Retrieve the block length of the first block since the first block will not contain the size of file
|
|
282
|
-
let blockLength = buffer[i] * 256 + buffer[i + 1];
|
|
283
|
-
|
|
284
|
-
//Increase the file index to get to the next block
|
|
285
|
-
i += blockLength;
|
|
286
|
-
while (i < buffer.length) {
|
|
287
|
-
if (buffer[i] != 0xff) {
|
|
288
|
-
this.logDebug(
|
|
289
|
-
"We should be at the begining of the next block, but got: " +
|
|
290
|
-
buffer[i],
|
|
291
|
-
);
|
|
292
|
-
return false;
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
if (i + 1 >= buffer.length) {
|
|
296
|
-
this.logDebug("End of stream prematurely found in marker: " + marker);
|
|
297
|
-
return false;
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
if (buffer[i + 1] == 0x00) {
|
|
301
|
-
this.logDebug(`Bad marker at ${i} 0x00 just after marker ${marker}`);
|
|
302
|
-
return false;
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
marker = this.numToHex(buffer[i]) + this.numToHex(buffer[i + 1]);
|
|
306
|
-
|
|
307
|
-
const foundBlockLength = this.getBlockLength(buffer, i, marker);
|
|
308
|
-
if (foundBlockLength == null) {
|
|
309
|
-
this.logDebug(
|
|
310
|
-
`Was not able to determine block size for marker ${marker}`,
|
|
311
|
-
);
|
|
312
|
-
return false;
|
|
313
|
-
}
|
|
314
|
-
blockLength = foundBlockLength;
|
|
315
|
-
|
|
316
|
-
const handler = markerHandler[marker];
|
|
317
|
-
if (handler != null && handler(i + 2, blockLength)) {
|
|
318
|
-
return true;
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
i = i + 2 + blockLength;
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
this.logDebug("End of payload reached");
|
|
325
|
-
return true;
|
|
326
|
-
}
|
|
327
|
-
}
|
package/src/KnownShortcut.ts
DELETED
package/src/PathHelper.ts
DELETED
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
import path from "path";
|
|
2
|
-
import dateformat from "dateformat";
|
|
3
|
-
import os from "os";
|
|
4
|
-
import { promises as Fs } from "fs";
|
|
5
|
-
import fs from "fs";
|
|
6
|
-
|
|
7
|
-
export default class PathHelper {
|
|
8
|
-
static getFileForPage(
|
|
9
|
-
folder: string,
|
|
10
|
-
scanCount: number,
|
|
11
|
-
currentPageNumber: number,
|
|
12
|
-
filePattern: string | undefined,
|
|
13
|
-
extension: string,
|
|
14
|
-
date: Date,
|
|
15
|
-
): string {
|
|
16
|
-
if (filePattern) {
|
|
17
|
-
return path.join(folder, `${dateformat(date, filePattern)}.${extension}`);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
return this.makeUnique(
|
|
21
|
-
path.join(
|
|
22
|
-
folder,
|
|
23
|
-
`scan${scanCount}_page${currentPageNumber}.${extension}`,
|
|
24
|
-
),
|
|
25
|
-
date,
|
|
26
|
-
);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
static async getNextScanNumber(
|
|
30
|
-
folder: string,
|
|
31
|
-
currentScanCount: number,
|
|
32
|
-
filePattern: string | undefined,
|
|
33
|
-
): Promise<number> {
|
|
34
|
-
if (filePattern) {
|
|
35
|
-
return currentScanCount++;
|
|
36
|
-
}
|
|
37
|
-
const files = await Fs.readdir(folder);
|
|
38
|
-
for (let i = currentScanCount + 1; i < Number.MAX_SAFE_INTEGER; i++) {
|
|
39
|
-
const currentScanCountProbe = `scan${i}`;
|
|
40
|
-
if (
|
|
41
|
-
!(
|
|
42
|
-
files.some((x) => x.startsWith(currentScanCountProbe)) &&
|
|
43
|
-
files.some(
|
|
44
|
-
(x) =>
|
|
45
|
-
x.startsWith(currentScanCountProbe + "_") ||
|
|
46
|
-
files.some((x) => x.startsWith(currentScanCountProbe + ".")),
|
|
47
|
-
)
|
|
48
|
-
)
|
|
49
|
-
) {
|
|
50
|
-
return i;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
return Promise.reject(
|
|
54
|
-
`Unable to find the valid scan number in folder ${folder}`,
|
|
55
|
-
);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
static makeUnique(filePath: string, date: Date): string {
|
|
59
|
-
if (!fs.existsSync(filePath)) {
|
|
60
|
-
return filePath;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
let parsed = path.parse(filePath);
|
|
64
|
-
let tryName = `${parsed.dir}${path.sep}${parsed.name}_${dateformat(
|
|
65
|
-
date,
|
|
66
|
-
"yyyymmdd",
|
|
67
|
-
)}${parsed.ext}`;
|
|
68
|
-
if (!fs.existsSync(tryName)) {
|
|
69
|
-
return tryName;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
parsed = path.parse(tryName);
|
|
73
|
-
let i = "a";
|
|
74
|
-
while (i <= "z") {
|
|
75
|
-
tryName = `${parsed.dir}${path.sep}${parsed.name}_${i}${parsed.ext}`;
|
|
76
|
-
if (!fs.existsSync(tryName)) {
|
|
77
|
-
return tryName;
|
|
78
|
-
}
|
|
79
|
-
i = String.fromCharCode(i.charCodeAt(0) + 1);
|
|
80
|
-
}
|
|
81
|
-
throw new Error(
|
|
82
|
-
`Can not create unique file: ${filePath} iterated until: ${tryName}`,
|
|
83
|
-
);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
static getFileForScan(
|
|
87
|
-
folder: string,
|
|
88
|
-
scanCount: number,
|
|
89
|
-
filePattern: string | undefined,
|
|
90
|
-
extension: string,
|
|
91
|
-
date: Date,
|
|
92
|
-
): string {
|
|
93
|
-
if (filePattern) {
|
|
94
|
-
return path.join(folder, `${dateformat(date, filePattern)}.${extension}`);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
return path.join(folder, `scan${scanCount}.${extension}`);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
static async getOutputFolder(folder?: string | undefined): Promise<string> {
|
|
101
|
-
if (typeof folder !== "string") {
|
|
102
|
-
return Fs.mkdtemp(path.join(os.tmpdir(), "scan-to-pc"));
|
|
103
|
-
}
|
|
104
|
-
return folder;
|
|
105
|
-
}
|
|
106
|
-
}
|
package/src/ScanCaps.ts
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
import { Parser } from "xml2js";
|
|
3
|
-
const parser = new Parser();
|
|
4
|
-
import { promisify } from "util";
|
|
5
|
-
const parseString = promisify<string, ScanCapsData>(parser.parseString);
|
|
6
|
-
|
|
7
|
-
export interface ScanCapsData {
|
|
8
|
-
ScanCaps: {
|
|
9
|
-
Platen: {
|
|
10
|
-
InputSourceCaps: {
|
|
11
|
-
MaxWidth: string[];
|
|
12
|
-
MaxHeight: string[];
|
|
13
|
-
}[];
|
|
14
|
-
}[];
|
|
15
|
-
Adf: {
|
|
16
|
-
InputSourceCaps: {
|
|
17
|
-
MaxWidth: string[];
|
|
18
|
-
MaxHeight: string[];
|
|
19
|
-
}[];
|
|
20
|
-
}[];
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export default class ScanCaps {
|
|
25
|
-
private readonly data: ScanCapsData;
|
|
26
|
-
|
|
27
|
-
constructor(data: ScanCapsData) {
|
|
28
|
-
this.data = data;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
static async createScanCaps(content: string): Promise<ScanCaps> {
|
|
32
|
-
const parsed = await parseString(content);
|
|
33
|
-
return new ScanCaps(parsed);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
get platenMaxWidth(): number | null {
|
|
37
|
-
if (Object.prototype.hasOwnProperty.call(this.data["ScanCaps"], "Platen")) {
|
|
38
|
-
return Number.parseInt(
|
|
39
|
-
this.data["ScanCaps"]["Platen"][0]["InputSourceCaps"][0]["MaxWidth"][0],
|
|
40
|
-
10,
|
|
41
|
-
);
|
|
42
|
-
} else {
|
|
43
|
-
return null;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
get platenMaxHeight(): number | null {
|
|
48
|
-
if (Object.prototype.hasOwnProperty.call(this.data["ScanCaps"], "Platen")) {
|
|
49
|
-
return Number.parseInt(
|
|
50
|
-
this.data["ScanCaps"]["Platen"][0]["InputSourceCaps"][0][
|
|
51
|
-
"MaxHeight"
|
|
52
|
-
][0],
|
|
53
|
-
10,
|
|
54
|
-
);
|
|
55
|
-
} else {
|
|
56
|
-
return null;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
get adfMaxWidth(): number | null {
|
|
61
|
-
if (Object.prototype.hasOwnProperty.call(this.data["ScanCaps"], "Adf")) {
|
|
62
|
-
return Number.parseInt(
|
|
63
|
-
this.data["ScanCaps"]["Adf"][0]["InputSourceCaps"][0]["MaxWidth"][0],
|
|
64
|
-
10,
|
|
65
|
-
);
|
|
66
|
-
} else {
|
|
67
|
-
return null;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
get adfMaxHeight(): number | null {
|
|
72
|
-
if (Object.prototype.hasOwnProperty.call(this.data["ScanCaps"], "Adf")) {
|
|
73
|
-
return Number.parseInt(
|
|
74
|
-
this.data["ScanCaps"]["Adf"][0]["InputSourceCaps"][0]["MaxHeight"][0],
|
|
75
|
-
10,
|
|
76
|
-
);
|
|
77
|
-
} else {
|
|
78
|
-
return null;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
}
|
package/src/ScanContent.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import fs from "fs/promises";
|
|
2
|
-
|
|
3
|
-
import { jsPDF } from "jspdf";
|
|
4
|
-
|
|
5
|
-
export interface ScanContent {
|
|
6
|
-
elements: ScanPage[];
|
|
7
|
-
}
|
|
8
|
-
export interface ScanPage {
|
|
9
|
-
path: string;
|
|
10
|
-
pageNumber: number;
|
|
11
|
-
width: number;
|
|
12
|
-
height: number;
|
|
13
|
-
xResolution: number;
|
|
14
|
-
yResolution: number;
|
|
15
|
-
}
|