index.js 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. // !!!!! Do not use in release mode. Just a native inject fake wrapper for test spider. !!!!!
  2. // !!!!! Do not use in release mode. Just a native inject fake wrapper for test spider. !!!!!
  3. // !!!!! Do not use in release mode. Just a native inject fake wrapper for test spider. !!!!!
  4. import axios from 'axios';
  5. import crypto from 'crypto';
  6. import https from 'https';
  7. import fs from 'node:fs';
  8. import qs from 'qs';
  9. import { Uri, _ } from '../lib/cat.js';
  10. const confs = {};
  11. function initLocalStorage(storage) {
  12. if (!_.has(confs, storage)) {
  13. if (!fs.existsSync('local')) {
  14. fs.mkdirSync('local');
  15. }
  16. const storagePath = 'local/js_' + storage;
  17. if (!fs.existsSync(storagePath)) {
  18. fs.writeFileSync(storagePath, '{}');
  19. confs[storage] = {};
  20. } else {
  21. confs[storage] = JSON.parse(fs.readFileSync(storagePath).toString());
  22. }
  23. }
  24. }
  25. function localGet(storage, key) {
  26. initLocalStorage(storage);
  27. return _.get(confs[storage], key, '');
  28. }
  29. function localSet(storage, key, value) {
  30. initLocalStorage(storage);
  31. confs[storage][key] = value;
  32. fs.writeFileSync('local/js_' + storage, JSON.stringify(confs[storage]));
  33. }
  34. async function request(url, opt) {
  35. try {
  36. var data = opt ? opt.data || null : null;
  37. var postType = opt ? opt.postType || null : null;
  38. var returnBuffer = opt ? opt.buffer || 0 : 0;
  39. var timeout = opt ? opt.timeout || 5000 : 5000;
  40. var headers = opt ? opt.headers || {} : {};
  41. if (postType == 'form') {
  42. headers['Content-Type'] = 'application/x-www-form-urlencoded';
  43. if (data != null) {
  44. data = qs.stringify(data, { encode: false });
  45. }
  46. }
  47. let respType = returnBuffer == 1 || returnBuffer == 2 ? 'arraybuffer' : undefined;
  48. var resp = await axios(url, {
  49. responseType: respType,
  50. method: opt ? opt.method || 'get' : 'get',
  51. headers: headers,
  52. data: data,
  53. timeout: timeout,
  54. httpsAgent: https.Agent({
  55. rejectUnauthorized: false,
  56. }),
  57. });
  58. var data = resp.data;
  59. var resHeader = {};
  60. for (const hks of resp.headers) {
  61. var v = hks[1];
  62. resHeader[hks[0]] = Array.isArray(v) ? (v.length == 1 ? v[0] : v) : v;
  63. }
  64. if (!returnBuffer) {
  65. if (typeof data === 'object') {
  66. data = JSON.stringify(data);
  67. }
  68. } else if (returnBuffer == 1) {
  69. return { code: resp.status, headers: resHeader, content: data };
  70. } else if (returnBuffer == 2) {
  71. return { code: resp.status, headers: resHeader, content: data.toString('base64') };
  72. }
  73. return { code: resp.status, headers: resHeader, content: data };
  74. } catch (error) {
  75. console.error(error);
  76. }
  77. return { headers: {}, content: '' };
  78. }
  79. function base64EncodeBuf(buff, urlsafe = false) {
  80. return buff.toString(urlsafe ? 'base64url' : 'base64');
  81. }
  82. function base64Encode(text, urlsafe = false) {
  83. return base64EncodeBuf(Buffer.from(text, 'utf8'), urlsafe);
  84. }
  85. function base64DecodeBuf(text) {
  86. return Buffer.from(text, 'base64');
  87. }
  88. function base64Decode(text) {
  89. return base64DecodeBuf(text).toString('utf8');
  90. }
  91. function md5(text) {
  92. return crypto.createHash('md5').update(Buffer.from(text, 'utf8')).digest('hex');
  93. }
  94. function aes(mode, encrypt, input, inBase64, key, iv, outBase64) {
  95. if (iv.length == 0) iv = null;
  96. try {
  97. if (mode.startsWith('AES/CBC')) {
  98. switch (key.length) {
  99. case 16:
  100. mode = 'aes-128-cbc';
  101. break;
  102. case 32:
  103. mode = 'aes-256-cbc';
  104. break;
  105. }
  106. } else if (mode.startsWith('AES/ECB')) {
  107. switch (key.length) {
  108. case 16:
  109. mode = 'aes-128-ecb';
  110. break;
  111. case 32:
  112. mode = 'aes-256-ecb';
  113. break;
  114. }
  115. }
  116. const inBuf = inBase64 ? base64DecodeBuf(input) : Buffer.from(input, 'utf8');
  117. let keyBuf = Buffer.from(key);
  118. if (keyBuf.length < 16) keyBuf = Buffer.concat([keyBuf], 16);
  119. let ivBuf = iv == null ? Buffer.alloc(0) : Buffer.from(iv);
  120. if (iv != null && ivBuf.length < 16) ivBuf = Buffer.concat([ivBuf], 16);
  121. const cipher = encrypt ? crypto.createCipheriv(mode, keyBuf, ivBuf) : crypto.createDecipheriv(mode, keyBuf, ivBuf);
  122. const outBuf = Buffer.concat([cipher.update(inBuf), cipher.final()]);
  123. return outBase64 ? base64EncodeBuf(outBuf) : outBuf.toString('utf8');
  124. } catch (error) {
  125. console.log(error);
  126. }
  127. return '';
  128. }
  129. function des(mode, encrypt, input, inBase64, key, iv, outBase64) {
  130. try {
  131. if (mode.startsWith('DESede/CBC')) {
  132. // https://stackoverflow.com/questions/29831300/convert-desede-ecb-nopadding-algorithm-written-in-java-into-nodejs-using-crypto
  133. switch (key.length) {
  134. case 16:
  135. mode = 'des-ede-cbc';
  136. break;
  137. case 24:
  138. mode = 'des-ede3-cbc';
  139. break;
  140. }
  141. }
  142. const inBuf = inBase64 ? base64DecodeBuf(input) : Buffer.from(input, 'utf8');
  143. let keyBuf = Buffer.from(key);
  144. if (keyBuf.length < 16) keyBuf = Buffer.concat([keyBuf], 16);
  145. let ivBuf = iv == null ? Buffer.alloc(0) : Buffer.from(iv);
  146. if (iv != null && ivBuf.length < 8) ivBuf = Buffer.concat([ivBuf], 8);
  147. const cipher = encrypt ? crypto.createCipheriv(mode, keyBuf, ivBuf) : crypto.createDecipheriv(mode, keyBuf, ivBuf);
  148. const outBuf = Buffer.concat([cipher.update(inBuf), cipher.final()]);
  149. return outBase64 ? base64EncodeBuf(outBuf) : outBuf.toString('utf8');
  150. } catch (error) {
  151. console.log(error);
  152. }
  153. return '';
  154. }
  155. // pkcs8 only
  156. function rsa(mode, pub, encrypt, input, inBase64, key, outBase64) {
  157. try {
  158. let pd = undefined;
  159. const keyObj = pub ? crypto.createPublicKey(key) : crypto.createPrivateKey(key);
  160. if (!keyObj.asymmetricKeyDetails || !keyObj.asymmetricKeyDetails.modulusLength) return '';
  161. const moduleLen = keyObj.asymmetricKeyDetails.modulusLength;
  162. let blockLen = moduleLen / 8;
  163. switch (mode) {
  164. case 'RSA/PKCS1':
  165. pd = crypto.constants.RSA_PKCS1_PADDING;
  166. blockLen = encrypt ? blockLen - 11 : blockLen;
  167. break;
  168. case 'RSA/None/NoPadding':
  169. pd = crypto.constants.RSA_NO_PADDING;
  170. break;
  171. case 'RSA/None/OAEPPadding':
  172. pd = crypto.constants.RSA_PKCS1_OAEP_PADDING;
  173. blockLen = encrypt ? blockLen - 41 : blockLen;
  174. break;
  175. default:
  176. throw Error('not support ' + mode);
  177. }
  178. let inBuf = inBase64 ? base64DecodeBuf(input) : Buffer.from(input, 'utf8');
  179. let bufIdx = 0;
  180. let outBuf = Buffer.alloc(0);
  181. while (bufIdx < inBuf.length) {
  182. const bufEndIdx = Math.min(bufIdx + blockLen, inBuf.length);
  183. let tmpInBuf = inBuf.subarray(bufIdx, bufEndIdx);
  184. if (pd == crypto.constants.RSA_NO_PADDING) {
  185. if (tmpInBuf.length < blockLen) {
  186. tmpInBuf = Buffer.concat([Buffer.alloc(128 - tmpInBuf.length), tmpInBuf]);
  187. }
  188. }
  189. let tmpBuf;
  190. if (pub) {
  191. tmpBuf = encrypt ? crypto.publicEncrypt({ key: keyObj, padding: pd }, tmpInBuf) : crypto.publicDecrypt({ key: keyObj, padding: pd }, tmpInBuf);
  192. } else {
  193. tmpBuf = encrypt ? crypto.privateEncrypt({ key: keyObj, padding: pd }, tmpInBuf) : crypto.privateDecrypt({ key: keyObj, padding: pd }, tmpInBuf);
  194. }
  195. bufIdx = bufEndIdx;
  196. outBuf = Buffer.concat([outBuf, tmpBuf]);
  197. }
  198. return outBase64 ? base64EncodeBuf(outBuf) : outBuf.toString('utf8');
  199. } catch (error) {
  200. console.log(error);
  201. }
  202. return '';
  203. }
  204. var charStr = 'abacdefghjklmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ0123456789';
  205. function randStr(len, withNum) {
  206. var _str = '';
  207. let containsNum = withNum === undefined ? true : withNum;
  208. for (var i = 0; i < len; i++) {
  209. let idx = _.random(0, containsNum ? charStr.length - 1 : charStr.length - 11);
  210. _str += charStr[idx];
  211. }
  212. return _str;
  213. }
  214. globalThis.local = {
  215. get: async function (storage, key) {
  216. return localGet(storage, key);
  217. },
  218. set: async function (storage, key, val) {
  219. localSet(storage, key, val);
  220. },
  221. };
  222. globalThis.md5X = md5;
  223. globalThis.rsaX = rsa;
  224. globalThis.aesX = aes;
  225. globalThis.desX = des;
  226. globalThis.req = request;
  227. globalThis.url2Proxy = async function (type, url, headers) {
  228. let hd = Object.keys(headers).length == 0 ? '_' : encodeURIComponent(JSON.stringify(headers));
  229. let uri = new Uri(url);
  230. let path = uri.path();
  231. path = path.substring(path.lastIndexOf('/'));
  232. let ext = path.indexOf('.') >= 0 ? path.substring(path.indexOf('.')) : '.bin';
  233. return 'http://127.0.0.1:13333/up/' + randStr(6) + '/' + type + '/' + hd + '/' + encodeURIComponent(url) + '/' + ext;
  234. };
  235. globalThis.js2Proxy = async function (dynamic, siteType, site, url, headers) {
  236. let hd = Object.keys(headers).length == 0 ? '_' : encodeURIComponent(JSON.stringify(headers));
  237. return (dynamic ? 'js2p://_WEB_/' : 'http://127.0.0.1:13333/jp/') + randStr(6) + '/' + siteType + '/' + site + '/' + hd + '/' + encodeURIComponent(url);
  238. };
  239. export default {};