@xaypay/tui 0.3.1 → 0.3.2
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/CHANGELOG.md +4 -0
- package/dist/index.es.js +53 -22
- package/dist/index.js +53 -22
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,10 @@ All notable changes to `@xaypay/tui` will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
|
|
9
|
+
## [0.3.2] - 2026-04-02
|
|
10
|
+
- **FILE** Refactor: pdf / heic / heif validation.
|
|
11
|
+
|
|
8
12
|
## [0.3.1] - 2026-03-19
|
|
9
13
|
|
|
10
14
|
### Added
|
package/dist/index.es.js
CHANGED
|
@@ -2145,20 +2145,17 @@ const File = /*#__PURE__*/forwardRef(({
|
|
|
2145
2145
|
const hasTable = names.has("1Table") || names.has("0Table");
|
|
2146
2146
|
return hasWordDocument && hasTable ? Promise.resolve() : Promise.reject();
|
|
2147
2147
|
} else if (type === 'pdf') {
|
|
2148
|
+
const text = new TextDecoder().decode(buffer);
|
|
2149
|
+
if (!text.includes("%%EOF")) return Promise.reject();
|
|
2150
|
+
if (!text.startsWith("%PDF-")) return Promise.reject();
|
|
2151
|
+
if (!text.includes("startxref")) return Promise.reject();
|
|
2148
2152
|
if (dataView.byteLength < 8) {
|
|
2149
2153
|
return Promise.reject();
|
|
2150
2154
|
} else {
|
|
2151
2155
|
if (dataView.getUint8(0) === 0x25 && dataView.getUint8(1) === 0x50 && dataView.getUint8(2) === 0x44 && dataView.getUint8(3) === 0x46) {
|
|
2152
2156
|
const len = dataView.byteLength;
|
|
2153
2157
|
let end = len - 1;
|
|
2154
|
-
while (end >= 0 && (dataView.getUint8(end) === 0x0A ||
|
|
2155
|
-
// \n
|
|
2156
|
-
dataView.getUint8(end) === 0x0D ||
|
|
2157
|
-
// \r
|
|
2158
|
-
dataView.getUint8(end) === 0x20 ||
|
|
2159
|
-
// space
|
|
2160
|
-
dataView.getUint8(end) === 0x09 // tab
|
|
2161
|
-
)) {
|
|
2158
|
+
while (end >= 0 && (dataView.getUint8(end) === 0x0A || dataView.getUint8(end) === 0x0D || dataView.getUint8(end) === 0x20 || dataView.getUint8(end) === 0x09)) {
|
|
2162
2159
|
end--;
|
|
2163
2160
|
}
|
|
2164
2161
|
if (end >= 4 && dataView.getUint8(end - 4) === 0x25 && dataView.getUint8(end - 3) === 0x25 && dataView.getUint8(end - 2) === 0x45 && dataView.getUint8(end - 1) === 0x4F && dataView.getUint8(end) === 0x46) {
|
|
@@ -2171,23 +2168,57 @@ const File = /*#__PURE__*/forwardRef(({
|
|
|
2171
2168
|
}
|
|
2172
2169
|
}
|
|
2173
2170
|
} else if (type === 'heic') {
|
|
2174
|
-
|
|
2171
|
+
const length = dataView.byteLength;
|
|
2172
|
+
if (length < 32) {
|
|
2175
2173
|
return Promise.reject();
|
|
2176
|
-
}
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2174
|
+
}
|
|
2175
|
+
|
|
2176
|
+
// --- Check 'ftyp' at offset 4 ---
|
|
2177
|
+
if (dataView.getUint8(4) !== 0x66 ||
|
|
2178
|
+
// f
|
|
2179
|
+
dataView.getUint8(5) !== 0x74 ||
|
|
2180
|
+
// t
|
|
2181
|
+
dataView.getUint8(6) !== 0x79 ||
|
|
2182
|
+
// y
|
|
2183
|
+
dataView.getUint8(7) !== 0x70 // p
|
|
2184
|
+
) {
|
|
2185
|
+
return Promise.reject();
|
|
2186
|
+
}
|
|
2187
|
+
|
|
2188
|
+
// --- Check major brand ---
|
|
2189
|
+
const majorBrand = String.fromCharCode(dataView.getUint8(8), dataView.getUint8(9), dataView.getUint8(10), dataView.getUint8(11));
|
|
2190
|
+
const validBrands = ['heic', 'heix', 'hevc', 'hevx', 'mif1', 'msf1', 'heif'];
|
|
2191
|
+
if (!validBrands.includes(majorBrand)) {
|
|
2192
|
+
return Promise.reject();
|
|
2193
|
+
}
|
|
2194
|
+
|
|
2195
|
+
// --- Scan boxes (basic ISO BMFF parsing) ---
|
|
2196
|
+
let offset = 0;
|
|
2197
|
+
let foundMeta = false;
|
|
2198
|
+
let foundMdat = false;
|
|
2199
|
+
while (offset + 8 <= length) {
|
|
2200
|
+
const size = dataView.getUint32(offset);
|
|
2201
|
+
const type = String.fromCharCode(dataView.getUint8(offset + 4), dataView.getUint8(offset + 5), dataView.getUint8(offset + 6), dataView.getUint8(offset + 7));
|
|
2202
|
+
|
|
2203
|
+
// Invalid size → corrupted file
|
|
2204
|
+
if (size < 8 || offset + size > length) {
|
|
2205
|
+
return Promise.reject();
|
|
2189
2206
|
}
|
|
2207
|
+
if (type === "meta") foundMeta = true;
|
|
2208
|
+
if (type === "mdat") foundMdat = true;
|
|
2209
|
+
offset += size;
|
|
2210
|
+
}
|
|
2211
|
+
|
|
2212
|
+
// --- Require at least meta box ---
|
|
2213
|
+
if (!foundMeta) {
|
|
2214
|
+
return Promise.reject();
|
|
2215
|
+
}
|
|
2216
|
+
|
|
2217
|
+
// Optional but recommended
|
|
2218
|
+
if (!foundMdat) {
|
|
2219
|
+
return Promise.reject();
|
|
2190
2220
|
}
|
|
2221
|
+
return Promise.resolve();
|
|
2191
2222
|
} else {
|
|
2192
2223
|
return Promise.reject();
|
|
2193
2224
|
}
|
package/dist/index.js
CHANGED
|
@@ -2176,20 +2176,17 @@ const File = /*#__PURE__*/React.forwardRef(({
|
|
|
2176
2176
|
const hasTable = names.has("1Table") || names.has("0Table");
|
|
2177
2177
|
return hasWordDocument && hasTable ? Promise.resolve() : Promise.reject();
|
|
2178
2178
|
} else if (type === 'pdf') {
|
|
2179
|
+
const text = new TextDecoder().decode(buffer);
|
|
2180
|
+
if (!text.includes("%%EOF")) return Promise.reject();
|
|
2181
|
+
if (!text.startsWith("%PDF-")) return Promise.reject();
|
|
2182
|
+
if (!text.includes("startxref")) return Promise.reject();
|
|
2179
2183
|
if (dataView.byteLength < 8) {
|
|
2180
2184
|
return Promise.reject();
|
|
2181
2185
|
} else {
|
|
2182
2186
|
if (dataView.getUint8(0) === 0x25 && dataView.getUint8(1) === 0x50 && dataView.getUint8(2) === 0x44 && dataView.getUint8(3) === 0x46) {
|
|
2183
2187
|
const len = dataView.byteLength;
|
|
2184
2188
|
let end = len - 1;
|
|
2185
|
-
while (end >= 0 && (dataView.getUint8(end) === 0x0A ||
|
|
2186
|
-
// \n
|
|
2187
|
-
dataView.getUint8(end) === 0x0D ||
|
|
2188
|
-
// \r
|
|
2189
|
-
dataView.getUint8(end) === 0x20 ||
|
|
2190
|
-
// space
|
|
2191
|
-
dataView.getUint8(end) === 0x09 // tab
|
|
2192
|
-
)) {
|
|
2189
|
+
while (end >= 0 && (dataView.getUint8(end) === 0x0A || dataView.getUint8(end) === 0x0D || dataView.getUint8(end) === 0x20 || dataView.getUint8(end) === 0x09)) {
|
|
2193
2190
|
end--;
|
|
2194
2191
|
}
|
|
2195
2192
|
if (end >= 4 && dataView.getUint8(end - 4) === 0x25 && dataView.getUint8(end - 3) === 0x25 && dataView.getUint8(end - 2) === 0x45 && dataView.getUint8(end - 1) === 0x4F && dataView.getUint8(end) === 0x46) {
|
|
@@ -2202,23 +2199,57 @@ const File = /*#__PURE__*/React.forwardRef(({
|
|
|
2202
2199
|
}
|
|
2203
2200
|
}
|
|
2204
2201
|
} else if (type === 'heic') {
|
|
2205
|
-
|
|
2202
|
+
const length = dataView.byteLength;
|
|
2203
|
+
if (length < 32) {
|
|
2206
2204
|
return Promise.reject();
|
|
2207
|
-
}
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2205
|
+
}
|
|
2206
|
+
|
|
2207
|
+
// --- Check 'ftyp' at offset 4 ---
|
|
2208
|
+
if (dataView.getUint8(4) !== 0x66 ||
|
|
2209
|
+
// f
|
|
2210
|
+
dataView.getUint8(5) !== 0x74 ||
|
|
2211
|
+
// t
|
|
2212
|
+
dataView.getUint8(6) !== 0x79 ||
|
|
2213
|
+
// y
|
|
2214
|
+
dataView.getUint8(7) !== 0x70 // p
|
|
2215
|
+
) {
|
|
2216
|
+
return Promise.reject();
|
|
2217
|
+
}
|
|
2218
|
+
|
|
2219
|
+
// --- Check major brand ---
|
|
2220
|
+
const majorBrand = String.fromCharCode(dataView.getUint8(8), dataView.getUint8(9), dataView.getUint8(10), dataView.getUint8(11));
|
|
2221
|
+
const validBrands = ['heic', 'heix', 'hevc', 'hevx', 'mif1', 'msf1', 'heif'];
|
|
2222
|
+
if (!validBrands.includes(majorBrand)) {
|
|
2223
|
+
return Promise.reject();
|
|
2224
|
+
}
|
|
2225
|
+
|
|
2226
|
+
// --- Scan boxes (basic ISO BMFF parsing) ---
|
|
2227
|
+
let offset = 0;
|
|
2228
|
+
let foundMeta = false;
|
|
2229
|
+
let foundMdat = false;
|
|
2230
|
+
while (offset + 8 <= length) {
|
|
2231
|
+
const size = dataView.getUint32(offset);
|
|
2232
|
+
const type = String.fromCharCode(dataView.getUint8(offset + 4), dataView.getUint8(offset + 5), dataView.getUint8(offset + 6), dataView.getUint8(offset + 7));
|
|
2233
|
+
|
|
2234
|
+
// Invalid size → corrupted file
|
|
2235
|
+
if (size < 8 || offset + size > length) {
|
|
2236
|
+
return Promise.reject();
|
|
2220
2237
|
}
|
|
2238
|
+
if (type === "meta") foundMeta = true;
|
|
2239
|
+
if (type === "mdat") foundMdat = true;
|
|
2240
|
+
offset += size;
|
|
2241
|
+
}
|
|
2242
|
+
|
|
2243
|
+
// --- Require at least meta box ---
|
|
2244
|
+
if (!foundMeta) {
|
|
2245
|
+
return Promise.reject();
|
|
2246
|
+
}
|
|
2247
|
+
|
|
2248
|
+
// Optional but recommended
|
|
2249
|
+
if (!foundMdat) {
|
|
2250
|
+
return Promise.reject();
|
|
2221
2251
|
}
|
|
2252
|
+
return Promise.resolve();
|
|
2222
2253
|
} else {
|
|
2223
2254
|
return Promise.reject();
|
|
2224
2255
|
}
|