@ctrl/torrent-file 4.3.0 → 4.4.0

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.
@@ -1,5 +1,4 @@
1
1
  import { stringToUint8Array, uint8ArrayToString } from 'uint8array-extras';
2
- import { isValidUTF8 } from './utils.js';
3
2
  const td = new TextDecoder();
4
3
  class Decoder {
5
4
  idx = 0;
@@ -70,8 +69,7 @@ class Decoder {
70
69
  nextBufOrString() {
71
70
  const length = this.readNumber();
72
71
  this.assertByte(':');
73
- const buf = this.readBytes(length);
74
- return isValidUTF8(buf) ? td.decode(buf) : buf;
72
+ return this.readBytes(length);
75
73
  }
76
74
  nextString() {
77
75
  const length = this.readNumber();
@@ -1,5 +1,4 @@
1
1
  import { concatUint8Arrays, stringToUint8Array } from 'uint8array-extras';
2
- import { cmpRawString } from './utils.js';
3
2
  const te = new TextEncoder();
4
3
  const encodeString = (str) => {
5
4
  const lengthBytes = new TextEncoder().encode(str.length.toString());
@@ -33,7 +32,7 @@ const encodeNumber = (num) => {
33
32
  const encodeDictionary = (obj) => {
34
33
  const results = [];
35
34
  Object.keys(obj)
36
- .sort(cmpRawString)
35
+ .sort()
37
36
  .forEach(key => {
38
37
  results.push(encodeString(key));
39
38
  results.push(new Uint8Array(encode(obj[key])));
@@ -1,3 +1 @@
1
1
  export declare const cmpRawString: (str1: string, str2: string) => number;
2
- export declare const typedArraysAreEqual: <T extends Uint8Array>(a: T, b: T) => boolean;
3
- export declare const isValidUTF8: (buf: Uint8Array) => boolean;
@@ -18,73 +18,3 @@ export const cmpRawString = (str1, str2) => {
18
18
  }
19
19
  return v1.length < v2.length ? -1 : 1;
20
20
  };
21
- export const typedArraysAreEqual = (a, b) => {
22
- if (a.byteLength !== b.byteLength) {
23
- return false;
24
- }
25
- return a.every((val, i) => val === b[i]);
26
- };
27
- // Copied from https://github.com/hcodes/isutf8/blob/master/src/index.ts
28
- /*
29
- https://tools.ietf.org/html/rfc3629
30
- UTF8-char = UTF8-1 / UTF8-2 / UTF8-3 / UTF8-4
31
- UTF8-1 = %x00-7F
32
- UTF8-2 = %xC2-DF UTF8-tail
33
- UTF8-3 = %xE0 %xA0-BF UTF8-tail
34
- %xE1-EC 2( UTF8-tail )
35
- %xED %x80-9F UTF8-tail
36
- %xEE-EF 2( UTF8-tail )
37
- UTF8-4 = %xF0 %x90-BF 2( UTF8-tail )
38
- %xF1-F3 3( UTF8-tail )
39
- %xF4 %x80-8F 2( UTF8-tail )
40
- UTF8-tail = %x80-BF
41
- */
42
- export const isValidUTF8 = (buf) => {
43
- let i = 0;
44
- const len = buf.length;
45
- while (i < len) {
46
- // UTF8-1 = %x00-7F
47
- if (buf[i] <= 0x7f) {
48
- i++;
49
- continue;
50
- }
51
- // UTF8-2 = %xC2-DF UTF8-tail
52
- if (buf[i] >= 0xc2 && buf[i] <= 0xdf) {
53
- // if(buf[i + 1] >= 0x80 && buf[i + 1] <= 0xBF) {
54
- if (buf[i + 1] >> 6 === 2) {
55
- i += 2;
56
- continue;
57
- }
58
- return false;
59
- }
60
- // UTF8-3 = %xE0 %xA0-BF UTF8-tail
61
- // UTF8-3 = %xED %x80-9F UTF8-tail
62
- if (((buf[i] === 0xe0 && buf[i + 1] >= 0xa0 && buf[i + 1] <= 0xbf) ||
63
- (buf[i] === 0xed && buf[i + 1] >= 0x80 && buf[i + 1] <= 0x9f)) &&
64
- buf[i + 2] >> 6 === 2) {
65
- i += 3;
66
- continue;
67
- }
68
- // UTF8-3 = %xE1-EC 2( UTF8-tail )
69
- // UTF8-3 = %xEE-EF 2( UTF8-tail )
70
- if (((buf[i] >= 0xe1 && buf[i] <= 0xec) || (buf[i] >= 0xee && buf[i] <= 0xef)) &&
71
- buf[i + 1] >> 6 === 2 &&
72
- buf[i + 2] >> 6 === 2) {
73
- i += 3;
74
- continue;
75
- }
76
- // UTF8-4 = %xF0 %x90-BF 2( UTF8-tail )
77
- // %xF1-F3 3( UTF8-tail )
78
- // %xF4 %x80-8F 2( UTF8-tail )
79
- if (((buf[i] === 0xf0 && buf[i + 1] >= 0x90 && buf[i + 1] <= 0xbf) ||
80
- (buf[i] >= 0xf1 && buf[i] <= 0xf3 && buf[i + 1] >> 6 === 2) ||
81
- (buf[i] === 0xf4 && buf[i + 1] >= 0x80 && buf[i + 1] <= 0x8f)) &&
82
- buf[i + 2] >> 6 === 2 &&
83
- buf[i + 3] >> 6 === 2) {
84
- i += 4;
85
- continue;
86
- }
87
- return false;
88
- }
89
- return true;
90
- };
@@ -1,6 +1,6 @@
1
1
  export declare const sha1: (input: Uint8Array) => string;
2
2
  /**
3
- * sha1 of torrent file info. This hash is commenly used by torrent clients as the ID of the torrent.
3
+ * sha1 of torrent file info. This hash is commonly used by torrent clients as the ID of the torrent.
4
4
  */
5
5
  export declare function hash(file: Uint8Array): string;
6
6
  export interface TorrentFileData {
@@ -2,6 +2,13 @@ import { createHash } from 'node:crypto';
2
2
  import { join, sep } from 'node:path';
3
3
  import { isUint8Array, uint8ArrayToHex, uint8ArrayToString } from 'uint8array-extras';
4
4
  import { decode, encode } from './bencode/index.js';
5
+ // Helper function to convert Uint8Array to string for display
6
+ const toString = (value) => {
7
+ if (value instanceof Uint8Array) {
8
+ return uint8ArrayToString(value);
9
+ }
10
+ return value.toString();
11
+ };
5
12
  export const sha1 = (input) => {
6
13
  const hash = createHash('sha1');
7
14
  // Update the hash object with the data
@@ -9,7 +16,7 @@ export const sha1 = (input) => {
9
16
  return hash.digest('hex');
10
17
  };
11
18
  /**
12
- * sha1 of torrent file info. This hash is commenly used by torrent clients as the ID of the torrent.
19
+ * sha1 of torrent file info. This hash is commonly used by torrent clients as the ID of the torrent.
13
20
  */
14
21
  export function hash(file) {
15
22
  const torrent = decode(file);
@@ -28,9 +35,9 @@ export function files(file) {
28
35
  pieces: [],
29
36
  };
30
37
  const files = torrent.info.files || [torrent.info];
31
- const name = (torrent.info['name.utf-8'] || torrent.info.name).toString();
38
+ const name = toString(torrent.info['name.utf-8'] || torrent.info.name);
32
39
  result.files = files.map((file, i) => {
33
- const parts = [name, ...(file['path.utf-8'] || file.path || [])].map(p => p.toString());
40
+ const parts = [name, ...(file['path.utf-8'] || file.path || [])].map(p => toString(p));
34
41
  return {
35
42
  path: join(sep, ...parts).slice(1),
36
43
  name: parts[parts.length - 1],
@@ -61,7 +68,7 @@ function splitPieces(buf) {
61
68
  export function info(file) {
62
69
  const torrent = decode(file);
63
70
  const result = {
64
- name: (torrent.info['name.utf-8'] || torrent.info.name).toString(),
71
+ name: toString(torrent.info['name.utf-8'] || torrent.info.name),
65
72
  announce: [],
66
73
  urlList: [],
67
74
  };
@@ -72,10 +79,10 @@ export function info(file) {
72
79
  result.created = new Date(torrent['creation date'] * 1000);
73
80
  }
74
81
  if (torrent['created by']) {
75
- result.createdBy = torrent['created by'].toString();
82
+ result.createdBy = toString(torrent['created by']);
76
83
  }
77
- if (isUint8Array(torrent.comment)) {
78
- result.comment = uint8ArrayToString(torrent.comment);
84
+ if (torrent.comment) {
85
+ result.comment = toString(torrent.comment);
79
86
  }
80
87
  // announce and announce-list will be missing if metadata fetched via ut_metadata
81
88
  if (Array.isArray(torrent['announce-list']) &&
@@ -83,12 +90,12 @@ export function info(file) {
83
90
  torrent['announce-list'].length > 0) {
84
91
  torrent['announce-list'].forEach((urls) => {
85
92
  urls.forEach((url) => {
86
- result.announce.push(url.toString());
93
+ result.announce.push(toString(url));
87
94
  });
88
95
  });
89
96
  }
90
97
  else if (torrent.announce) {
91
- result.announce.push(torrent.announce.toString());
98
+ result.announce.push(toString(torrent.announce));
92
99
  }
93
100
  if (result.announce.length) {
94
101
  result.announce = Array.from(new Set(result.announce));
@@ -98,7 +105,7 @@ export function info(file) {
98
105
  // some clients set url-list to empty string
99
106
  torrent['url-list'] = torrent['url-list'].length > 0 ? [torrent['url-list']] : [];
100
107
  }
101
- result.urlList = (torrent['url-list'] || []).map((url) => url.toString());
108
+ result.urlList = (torrent['url-list'] || []).map((url) => toString(url));
102
109
  if (result.urlList.length) {
103
110
  result.urlList = Array.from(new Set(result.urlList));
104
111
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ctrl/torrent-file",
3
- "version": "4.3.0",
3
+ "version": "4.4.0",
4
4
  "description": "Parse a torrent file (name, hash, files, pieces)",
5
5
  "author": "Scott Cooper <scttcper@gmail.com>",
6
6
  "license": "MIT",