Răsfoiți Sursa

fix: check content before installing from URL

Gerald 8 ani în urmă
părinte
comite
5a2fda8a4b

+ 2 - 1
src/background/app.js

@@ -1,6 +1,6 @@
 import { i18n, defaultImage } from 'src/common';
 import * as sync from './sync';
-import { getRequestId, httpRequest, abortRequest } from './utils/requests';
+import { getRequestId, httpRequest, abortRequest, confirmInstall } from './utils/requests';
 import cache from './utils/cache';
 import { newScript, parseMeta } from './utils/script';
 import { setClipboard } from './utils/clipboard';
@@ -193,6 +193,7 @@ const commands = {
     items.forEach(item => { setOption(item.key, item.value); });
   },
   CheckPosition: vmdb.checkPosition,
+  ConfirmInstall: confirmInstall,
 };
 
 vmdb.initialized.then(() => {

+ 28 - 12
src/background/utils/requests.js

@@ -1,5 +1,6 @@
-import { getUniqId } from 'src/common';
+import { getUniqId, request, i18n } from 'src/common';
 import cache from './cache';
+import { isUserScript } from './script';
 
 const requests = {};
 const verify = {};
@@ -195,6 +196,26 @@ browser.webRequest.onBeforeSendHeaders.addListener(details => {
 //   types: ['xmlhttprequest'],
 // });
 
+export function confirmInstall(info) {
+  return (info.code
+    ? Promise.resolve(info.code)
+    : request(info.url).then(({ data }) => {
+      if (!isUserScript(data)) return Promise.reject(i18n('msgInvalidScript'));
+      return data;
+    })
+  )
+  .then(code => {
+    cache.put(info.url, code, 3000);
+    const confirmKey = getUniqId();
+    cache.put(`confirm-${confirmKey}`, {
+      url: info.url,
+      from: info.from,
+    });
+    const optionsURL = browser.runtime.getURL(browser.runtime.getManifest().options_page);
+    browser.tabs.create({ url: `${optionsURL}#confirm?id=${confirmKey}` });
+  });
+}
+
 browser.webRequest.onBeforeRequest.addListener(req => {
   // onBeforeRequest is fired for local files too
   if (req.method === 'GET' && /\.user\.js([?#]|$)/.test(req.url)) {
@@ -208,21 +229,16 @@ browser.webRequest.onBeforeRequest.addListener(req => {
       // Request is redirected
       return;
     }
-    if ((!x.status || x.status === 200) && !/^\s*</.test(x.responseText)) {
-      cache.put(req.url, x.responseText, 3000);
-      const confirmInfo = {
-        url: req.url,
-      };
-      const confirmKey = getUniqId();
+    if ((!x.status || x.status === 200) && isUserScript(x.responseText)) {
       // Firefox: slashes are decoded automatically by Firefox, thus cannot be
       // used as separators
-      const optionsURL = browser.runtime.getURL(browser.runtime.getManifest().options_page);
-      const url = `${optionsURL}#confirm?id=${confirmKey}`;
       (req.tabId < 0 ? Promise.resolve() : browser.tabs.get(req.tabId))
       .then(tab => {
-        confirmInfo.from = tab && tab.url;
-        cache.put(`confirm-${confirmKey}`, confirmInfo);
-        browser.tabs.create({ url });
+        confirmInstall({
+          url: req.url,
+          from: tab && tab.url,
+          code: x.responseText,
+        });
       });
       return noredirect;
     }

+ 11 - 2
src/background/utils/script.js

@@ -1,7 +1,16 @@
+const metaStart = '==UserScript==';
+const metaEnd = '==/UserScript==';
+
 export function isRemote(url) {
   return url && !(/^(file|data):/.test(url));
 }
 
+export function isUserScript(text) {
+  if (/^\s*</.test(text)) return false; // HTML
+  if (text.indexOf(metaStart) < 0) return false;  // Lack of meta block
+  return true;
+}
+
 export function parseMeta(code) {
   // initialize meta, specify those with multiple values allowed
   const meta = {
@@ -14,10 +23,10 @@ export function parseMeta(code) {
   };
   let flag = -1;
   code.replace(/(?:^|\n)\/\/\s*([@=]\S+)(.*)/g, (_match, group1, group2) => {
-    if (flag < 0 && group1 === '==UserScript==') {
+    if (flag < 0 && group1 === metaStart) {
       // start meta
       flag = 1;
-    } else if (flag > 0 && group1 === '==/UserScript==') {
+    } else if (flag > 0 && group1 === metaEnd) {
       // end meta
       flag = 0;
     }

+ 5 - 7
src/options/views/tab-installed.vue

@@ -75,13 +75,11 @@ export default {
         });
       })
       .then(url => {
-        if (url && url.includes('://')) {
-          const urlOptions = browser.runtime.getURL(browser.runtime.getManifest().options_page);
-          browser.tabs.create({
-            url: `${urlOptions}#confirm?u=${encodeURIComponent(url)}`,
-          });
-        }
-      }, noop);
+        if (url && url.includes('://')) return sendMessage({ cmd: 'ConfirmInstall', data: { url } });
+      }, noop)
+      .catch(err => {
+        if (err) showMessage({ text: err });
+      });
     },
     editScript(id) {
       this.script = this.store.scripts.find(script => script.id === id);