node-ipconfig 1.0.0 → 1.0.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/src/parser.js CHANGED
@@ -1,182 +1,182 @@
1
- const LABELS = [
2
- ['hostname', /^(?:host name|hostname|computer name|hostname del equipo|nombre de host)$/i],
3
- ['description', /^(?:description|beschreibung|descripción)$/i],
4
- ['macAddress', /^(?:physical address|physikalische adresse|dirección física|mac address)$/i],
5
- ['dhcpEnabled', /^(?:dhcp enabled|dhcp aktiviert|dhcp habilitado)$/i],
6
- ['autoconfigurationEnabled', /^(?:autoconfiguration enabled|autokonfiguration aktiviert)$/i],
7
- ['ipv4Address', /^(?:ipv4 address|ip address|ipv4-adresse|ip-adresse|dirección ipv4)(?: \((?:preferred|bevorzugt)\))?$/i],
8
- ['ipv6Address', /^(?:ipv6 address|ipv6-adresse|dirección ipv6)(?: \((?:preferred|bevorzugt)\))?$/i],
9
- ['subnetMask', /^(?:subnet mask|subnetzmaske|máscara de subred)$/i],
10
- ['defaultGateway', /^(?:default gateway|standardgateway|puerta de enlace predeterminada)$/i],
11
- ['dnsServers', /^(?:dns servers?|dns-server|servidores dns)$/i],
12
- ['connectionSpecificDnsSuffix', /^(?:connection-specific dns suffix|verbindungsspezifisches dns-suffix|sufijo dns específico para la conexión)$/i],
13
- ['linkLocalIpv6Address', /^(?:link-local ipv6 address|verbindungslokale ipv6-adresse|dirección ipv6 de vínculo local)$/i],
14
- ['leaseObtained', /^(?:lease obtained|lease erhalten|concesión obtenida)$/i],
15
- ['leaseExpires', /^(?:lease expires|lease läuft ab|la concesión expira)$/i],
16
- ['dhcpServer', /^(?:dhcp server|dhcp-server|servidor dhcp)$/i],
17
- ['winsServers', /^(?:wins servers?|wins-server)$/i],
18
- ['mediaState', /^(?:media state|medienstatus|estado de los medios)$/i],
19
- ['netbiosOverTcpip', /^(?:netbios over tcpip|netbios über tcpip aktiviert)$/i],
20
- ['ipv4PrefixLength', /^(?:ipv4 prefix length|ipv4-präfixlänge)$/i]
21
- ];
22
-
23
- const LIST_FIELDS = new Set(["dnsServers", "defaultGateway", "winsServers"]);
24
- const EMPTY_VALUES =
25
- /^(?:n\/a|not applicable|none|keine|nicht zutreffend|ninguno|no disponible)$/i;
26
- const ADDRESS =
27
- /^(?:\d{1,3}\.){3}\d{1,3}(?:\/\d{1,2})?$|^[0-9a-f]*:[0-9a-f:.%]+(?:\/\d{1,3})?$/i;
28
-
29
- function tidy(value) {
30
- return value
31
- .trim()
32
- .replace(/^\.+$/, "")
33
- .replace(/\s*\((?:preferred|bevorzugt|preferido)\)$/i, "")
34
- .trim();
35
- }
36
- function bool(value) {
37
- if (/^(?:yes|true|ja|sí|si|enabled|aktiviert)$/i.test(value)) return true;
38
- if (/^(?:no|false|nein|disabled|deaktiviert)$/i.test(value)) return false;
39
- return value;
40
- }
41
- function fieldLabel(line) {
42
- return line.match(/^\s*(.+?)\s*:\s*(.*)$/);
43
- }
44
- function normalizeLabel(value) {
45
- return value
46
- .trim()
47
- .replace(/\s*\.\s*/g, " ")
48
- .replace(/\s+/g, " ")
49
- .trim();
50
- }
51
- function makeAdapter(type, name) {
52
- return {
53
- name: name.trim().replace(/^\*+\s*/, ""),
54
- type: type.trim(),
55
- addresses: [],
56
- ipv4: [],
57
- ipv6: [],
58
- dnsServers: [],
59
- defaultGateways: [],
60
- };
61
- }
62
- function addAddress(adapter, value, family, scope) {
63
- const address = value.replace(/\/\d+$/, "");
64
- const item = { address, family, ...(scope ? { scope } : {}) };
65
- adapter.addresses.push(item);
66
- (family === 4 ? adapter.ipv4 : adapter.ipv6).push(address);
67
- adapter[family === 4 ? "ipv4Address" : "ipv6Address"] = address;
68
- const prefix = value.match(/\/(\d+)$/)?.[1];
69
- if (prefix !== undefined) item.prefixLength = Number(prefix);
70
- }
71
-
72
- /** Parse localized ipconfig text into normalized adapter objects. */
73
- export function parseIpconfig(output) {
74
- if (typeof output !== "string")
75
- throw new TypeError("ipconfig output must be a string");
76
- const adapters = [];
77
- let hostname;
78
- let adapter;
79
- let currentList;
80
- for (const rawLine of output.replace(/^\uFEFF/, "").split(/\r?\n/)) {
81
- const line = rawLine.trim();
82
- if (!line) {
83
- currentList = undefined;
84
- continue;
85
- }
86
- const header =
87
- line.match(/^(.+?)\s+adapter\s+(.+):$/i) ??
88
- line.match(/^(.+?)-Adapter\s+(.+):$/i) ??
89
- line.match(/^(.+?) adaptador\s+(.+):$/i) ??
90
- line.match(/^(.+?)-Adapter\s+(.+):$/i);
91
- if (header) {
92
- adapter = makeAdapter(header[1], header[2]);
93
- adapters.push(adapter);
94
- currentList = undefined;
95
- continue;
96
- }
97
- if (
98
- /(?:pseudo-interface|loopback interface)/i.test(line) &&
99
- line.endsWith(":")
100
- ) {
101
- adapter = makeAdapter("Loopback", line.slice(0, -1));
102
- adapters.push(adapter);
103
- currentList = undefined;
104
- continue;
105
- }
106
- const field = fieldLabel(rawLine);
107
- if (!adapter) {
108
- if (field) {
109
- const label = normalizeLabel(field[1]);
110
- const found = LABELS.find(
111
- ([key, regex]) => key === "hostname" && regex.test(label),
112
- );
113
- if (found && field[2].trim()) hostname = tidy(field[2]);
114
- }
115
- continue;
116
- }
117
- const valueLine = line.match(ADDRESS);
118
- if (currentList && valueLine) {
119
- const target =
120
- currentList === "defaultGateway"
121
- ? adapter.defaultGateways
122
- : adapter[currentList];
123
- target.push(tidy(valueLine[0]));
124
- continue;
125
- }
126
- if (!field) continue;
127
- const label = normalizeLabel(field[1]);
128
- const value = tidy(field[2]);
129
- const match = LABELS.find(([, regex]) => regex.test(label));
130
- if (!match) {
131
- if (label && value)
132
- ((adapter.fields ??= {}), (adapter.fields[label] = value));
133
- currentList = undefined;
134
- continue;
135
- }
136
- const key = match[0];
137
- if (key === "hostname") {
138
- if (value) hostname = value;
139
- continue;
140
- }
141
- if (LIST_FIELDS.has(key)) {
142
- currentList = key;
143
- const target =
144
- key === "defaultGateway"
145
- ? adapter.defaultGateways
146
- : key === "winsServers"
147
- ? (adapter.winsServers ??= [])
148
- : adapter.dnsServers;
149
- if (value && value !== "::" && !EMPTY_VALUES.test(value))
150
- target.push(value);
151
- continue;
152
- }
153
- currentList = undefined;
154
- if (!value || EMPTY_VALUES.test(value)) continue;
155
- if (key === "ipv4Address") addAddress(adapter, value, 4);
156
- else if (key === "ipv6Address") addAddress(adapter, value, 6);
157
- else if (key === "linkLocalIpv6Address") {
158
- adapter.linkLocalIpv6Address = value;
159
- addAddress(adapter, value, 6, "link-local");
160
- } else if (key === "dhcpEnabled" || key === "autoconfigurationEnabled")
161
- adapter[key] = bool(value);
162
- else if (key === "ipv4PrefixLength") {
163
- adapter.ipv4PrefixLength = Number(value);
164
- } else adapter[key] = value;
165
- }
166
- for (const item of adapters) {
167
- if (item.subnetMask && item.ipv4PrefixLength === undefined)
168
- item.ipv4PrefixLength = maskPrefix(item.subnetMask);
169
- if (item.connectionSpecificDnsSuffix === undefined)
170
- item.connectionSpecificDnsSuffix = null;
171
- }
172
- return { ...(hostname ? { hostname } : {}), adapters };
173
- }
174
-
175
- function maskPrefix(mask) {
176
- const octets = mask.split(".").map(Number);
177
- if (octets.length !== 4 || octets.some((part) => part < 0 || part > 255))
178
- return undefined;
179
- const bits = octets.map((part) => part.toString(2).padStart(8, "0")).join("");
180
- if (!/^1*0*$/.test(bits)) return undefined;
181
- return bits.indexOf("0") < 0 ? 32 : bits.indexOf("0");
182
- }
1
+ const LABELS = [
2
+ ['hostname', /^(?:host name|hostname|computer name|hostname del equipo|nombre de host)$/i],
3
+ ['description', /^(?:description|beschreibung|descripción)$/i],
4
+ ['macAddress', /^(?:physical address|physikalische adresse|dirección física|mac address)$/i],
5
+ ['dhcpEnabled', /^(?:dhcp enabled|dhcp aktiviert|dhcp habilitado)$/i],
6
+ ['autoconfigurationEnabled', /^(?:autoconfiguration enabled|autokonfiguration aktiviert)$/i],
7
+ ['ipv4Address', /^(?:ipv4 address|ip address|ipv4-adresse|ip-adresse|dirección ipv4)(?: \((?:preferred|bevorzugt)\))?$/i],
8
+ ['ipv6Address', /^(?:ipv6 address|ipv6-adresse|dirección ipv6)(?: \((?:preferred|bevorzugt)\))?$/i],
9
+ ['subnetMask', /^(?:subnet mask|subnetzmaske|máscara de subred)$/i],
10
+ ['defaultGateway', /^(?:default gateway|standardgateway|puerta de enlace predeterminada)$/i],
11
+ ['dnsServers', /^(?:dns servers?|dns-server|servidores dns)$/i],
12
+ ['connectionSpecificDnsSuffix', /^(?:connection-specific dns suffix|verbindungsspezifisches dns-suffix|sufijo dns específico para la conexión)$/i],
13
+ ['linkLocalIpv6Address', /^(?:link-local ipv6 address|verbindungslokale ipv6-adresse|dirección ipv6 de vínculo local)$/i],
14
+ ['leaseObtained', /^(?:lease obtained|lease erhalten|concesión obtenida)$/i],
15
+ ['leaseExpires', /^(?:lease expires|lease läuft ab|la concesión expira)$/i],
16
+ ['dhcpServer', /^(?:dhcp server|dhcp-server|servidor dhcp)$/i],
17
+ ['winsServers', /^(?:wins servers?|wins-server)$/i],
18
+ ['mediaState', /^(?:media state|medienstatus|estado de los medios)$/i],
19
+ ['netbiosOverTcpip', /^(?:netbios over tcpip|netbios über tcpip aktiviert)$/i],
20
+ ['ipv4PrefixLength', /^(?:ipv4 prefix length|ipv4-präfixlänge)$/i]
21
+ ];
22
+
23
+ const LIST_FIELDS = new Set(["dnsServers", "defaultGateway", "winsServers"]);
24
+ const EMPTY_VALUES =
25
+ /^(?:n\/a|not applicable|none|keine|nicht zutreffend|ninguno|no disponible)$/i;
26
+ const ADDRESS =
27
+ /^(?:\d{1,3}\.){3}\d{1,3}(?:\/\d{1,2})?$|^[0-9a-f]*:[0-9a-f:.%]+(?:\/\d{1,3})?$/i;
28
+
29
+ function tidy(value) {
30
+ return value
31
+ .trim()
32
+ .replace(/^\.+$/, "")
33
+ .replace(/\s*\((?:preferred|bevorzugt|preferido)\)$/i, "")
34
+ .trim();
35
+ }
36
+ function bool(value) {
37
+ if (/^(?:yes|true|ja|sí|si|enabled|aktiviert)$/i.test(value)) return true;
38
+ if (/^(?:no|false|nein|disabled|deaktiviert)$/i.test(value)) return false;
39
+ return value;
40
+ }
41
+ function fieldLabel(line) {
42
+ return line.match(/^\s*(.+?)\s*:\s*(.*)$/);
43
+ }
44
+ function normalizeLabel(value) {
45
+ return value
46
+ .trim()
47
+ .replace(/\s*\.\s*/g, " ")
48
+ .replace(/\s+/g, " ")
49
+ .trim();
50
+ }
51
+ function makeAdapter(type, name) {
52
+ return {
53
+ name: name.trim().replace(/^\*+\s*/, ""),
54
+ type: type.trim(),
55
+ addresses: [],
56
+ ipv4: [],
57
+ ipv6: [],
58
+ dnsServers: [],
59
+ defaultGateways: [],
60
+ };
61
+ }
62
+ function addAddress(adapter, value, family, scope) {
63
+ const address = value.replace(/\/\d+$/, "");
64
+ const item = { address, family, ...(scope ? { scope } : {}) };
65
+ adapter.addresses.push(item);
66
+ (family === 4 ? adapter.ipv4 : adapter.ipv6).push(address);
67
+ adapter[family === 4 ? "ipv4Address" : "ipv6Address"] = address;
68
+ const prefix = value.match(/\/(\d+)$/)?.[1];
69
+ if (prefix !== undefined) item.prefixLength = Number(prefix);
70
+ }
71
+
72
+ /** Parse localized ipconfig text into normalized adapter objects. */
73
+ export function parseIpconfig(output) {
74
+ if (typeof output !== "string")
75
+ throw new TypeError("ipconfig output must be a string");
76
+ const adapters = [];
77
+ let hostname;
78
+ let adapter;
79
+ let currentList;
80
+ for (const rawLine of output.replace(/^\uFEFF/, "").split(/\r?\n/)) {
81
+ const line = rawLine.trim();
82
+ if (!line) {
83
+ currentList = undefined;
84
+ continue;
85
+ }
86
+ const header =
87
+ line.match(/^(.+?)\s+adapter\s+(.+):$/i) ??
88
+ line.match(/^(.+?)-Adapter\s+(.+):$/i) ??
89
+ line.match(/^(.+?) adaptador\s+(.+):$/i) ??
90
+ line.match(/^(.+?)-Adapter\s+(.+):$/i);
91
+ if (header) {
92
+ adapter = makeAdapter(header[1], header[2]);
93
+ adapters.push(adapter);
94
+ currentList = undefined;
95
+ continue;
96
+ }
97
+ if (
98
+ /(?:pseudo-interface|loopback interface)/i.test(line) &&
99
+ line.endsWith(":")
100
+ ) {
101
+ adapter = makeAdapter("Loopback", line.slice(0, -1));
102
+ adapters.push(adapter);
103
+ currentList = undefined;
104
+ continue;
105
+ }
106
+ const field = fieldLabel(rawLine);
107
+ if (!adapter) {
108
+ if (field) {
109
+ const label = normalizeLabel(field[1]);
110
+ const found = LABELS.find(
111
+ ([key, regex]) => key === "hostname" && regex.test(label),
112
+ );
113
+ if (found && field[2].trim()) hostname = tidy(field[2]);
114
+ }
115
+ continue;
116
+ }
117
+ const valueLine = line.match(ADDRESS);
118
+ if (currentList && valueLine) {
119
+ const target =
120
+ currentList === "defaultGateway"
121
+ ? adapter.defaultGateways
122
+ : adapter[currentList];
123
+ target.push(tidy(valueLine[0]));
124
+ continue;
125
+ }
126
+ if (!field) continue;
127
+ const label = normalizeLabel(field[1]);
128
+ const value = tidy(field[2]);
129
+ const match = LABELS.find(([, regex]) => regex.test(label));
130
+ if (!match) {
131
+ if (label && value)
132
+ ((adapter.fields ??= {}), (adapter.fields[label] = value));
133
+ currentList = undefined;
134
+ continue;
135
+ }
136
+ const key = match[0];
137
+ if (key === "hostname") {
138
+ if (value) hostname = value;
139
+ continue;
140
+ }
141
+ if (LIST_FIELDS.has(key)) {
142
+ currentList = key;
143
+ const target =
144
+ key === "defaultGateway"
145
+ ? adapter.defaultGateways
146
+ : key === "winsServers"
147
+ ? (adapter.winsServers ??= [])
148
+ : adapter.dnsServers;
149
+ if (value && value !== "::" && !EMPTY_VALUES.test(value))
150
+ target.push(value);
151
+ continue;
152
+ }
153
+ currentList = undefined;
154
+ if (!value || EMPTY_VALUES.test(value)) continue;
155
+ if (key === "ipv4Address") addAddress(adapter, value, 4);
156
+ else if (key === "ipv6Address") addAddress(adapter, value, 6);
157
+ else if (key === "linkLocalIpv6Address") {
158
+ adapter.linkLocalIpv6Address = value;
159
+ addAddress(adapter, value, 6, "link-local");
160
+ } else if (key === "dhcpEnabled" || key === "autoconfigurationEnabled")
161
+ adapter[key] = bool(value);
162
+ else if (key === "ipv4PrefixLength") {
163
+ adapter.ipv4PrefixLength = Number(value);
164
+ } else adapter[key] = value;
165
+ }
166
+ for (const item of adapters) {
167
+ if (item.subnetMask && item.ipv4PrefixLength === undefined)
168
+ item.ipv4PrefixLength = maskPrefix(item.subnetMask);
169
+ if (item.connectionSpecificDnsSuffix === undefined)
170
+ item.connectionSpecificDnsSuffix = null;
171
+ }
172
+ return { ...(hostname ? { hostname } : {}), adapters };
173
+ }
174
+
175
+ function maskPrefix(mask) {
176
+ const octets = mask.split(".").map(Number);
177
+ if (octets.length !== 4 || octets.some((part) => part < 0 || part > 255))
178
+ return undefined;
179
+ const bits = octets.map((part) => part.toString(2).padStart(8, "0")).join("");
180
+ if (!/^1*0*$/.test(bits)) return undefined;
181
+ return bits.indexOf("0") < 0 ? 32 : bits.indexOf("0");
182
+ }