Browse Source

Merge pull request #917 from weseek/master

release v3.4.5
Yuki Takei 7 years ago
parent
commit
cf4cd716c9

+ 12 - 2
CHANGES.md

@@ -1,8 +1,18 @@
 # CHANGES
 # CHANGES
 
 
-## 3.4.4-RC
+## 3.4.5-RC
 
 
-* 
+* Improvement: Pass autolink through the XSS filter according to CommonMark Spec
+* Fix: Update ElasticSearch index when deleting/duplicating pages
+* Fix: Xss filter breaks PlantUML arrows
+* Support: Support growi-plugin-lsx@2.2.0
+* Support: Upgrade libs
+    * growi-commons
+    * xss
+
+## 3.4.4
+
+* Fix: Comment component doesn't work
 
 
 ## 3.4.3
 ## 3.4.3
 
 

+ 3 - 3
package.json

@@ -1,6 +1,6 @@
 {
 {
   "name": "growi",
   "name": "growi",
-  "version": "3.4.4-RC",
+  "version": "3.4.5-RC",
   "description": "Team collaboration software using markdown",
   "description": "Team collaboration software using markdown",
   "tags": [
   "tags": [
     "wiki",
     "wiki",
@@ -88,7 +88,7 @@
     "express-webpack-assets": "^0.1.0",
     "express-webpack-assets": "^0.1.0",
     "googleapis": "^39.1.0",
     "googleapis": "^39.1.0",
     "graceful-fs": "^4.1.11",
     "graceful-fs": "^4.1.11",
-    "growi-commons": "^3.2.2",
+    "growi-commons": "^4.0.1",
     "helmet": "^3.13.0",
     "helmet": "^3.13.0",
     "i18next": "^15.0.9",
     "i18next": "^15.0.9",
     "i18next-express-middleware": "^1.4.1",
     "i18next-express-middleware": "^1.4.1",
@@ -124,7 +124,7 @@
     "swig-templates": "^2.0.2",
     "swig-templates": "^2.0.2",
     "uglifycss": "^0.0.29",
     "uglifycss": "^0.0.29",
     "url-join": "^4.0.0",
     "url-join": "^4.0.0",
-    "xss": "^1.0.3"
+    "xss": "^1.0.6"
   },
   },
   "devDependencies": {
   "devDependencies": {
     "@alienfast/i18next-loader": "^1.0.16",
     "@alienfast/i18next-loader": "^1.0.16",

+ 12 - 5
src/client/js/legacy/crowi.js

@@ -357,13 +357,12 @@ $(() => {
     $(this).serializeArray().forEach((obj) => {
     $(this).serializeArray().forEach((obj) => {
       nameValueMap[obj.name] = obj.value; // nameValueMap.new_path is renamed page path
       nameValueMap[obj.name] = obj.value; // nameValueMap.new_path is renamed page path
     });
     });
-
-    const data = `${$(this).serialize()}&socketClientId=${crowi.getSocketClientId()}`;
+    nameValueMap.socketClientId = crowi.getSocketClientId();
 
 
     $.ajax({
     $.ajax({
       type: 'POST',
       type: 'POST',
       url: '/_api/pages.rename',
       url: '/_api/pages.rename',
-      data,
+      data: nameValueMap,
       dataType: 'json',
       dataType: 'json',
     })
     })
       .done((res) => {
       .done((res) => {
@@ -396,11 +395,12 @@ $(() => {
     $(this).serializeArray().forEach((obj) => {
     $(this).serializeArray().forEach((obj) => {
       nameValueMap[obj.name] = obj.value; // nameValueMap.new_path is duplicated page path
       nameValueMap[obj.name] = obj.value; // nameValueMap.new_path is duplicated page path
     });
     });
+    nameValueMap.socketClientId = crowi.getSocketClientId();
 
 
     $.ajax({
     $.ajax({
       type: 'POST',
       type: 'POST',
       url: '/_api/pages.duplicate',
       url: '/_api/pages.duplicate',
-      data: $(this).serialize(),
+      data: nameValueMap,
       dataType: 'json',
       dataType: 'json',
     }).done((res) => {
     }).done((res) => {
       // error
       // error
@@ -426,10 +426,17 @@ $(() => {
     $('#deletePage .msg').hide();
     $('#deletePage .msg').hide();
   });
   });
   $('#delete-page-form').submit((e) => {
   $('#delete-page-form').submit((e) => {
+    // create name-value map
+    const nameValueMap = {};
+    $('#delete-page-form').serializeArray().forEach((obj) => {
+      nameValueMap[obj.name] = obj.value;
+    });
+    nameValueMap.socketClientId = crowi.getSocketClientId();
+
     $.ajax({
     $.ajax({
       type: 'POST',
       type: 'POST',
       url: '/_api/pages.remove',
       url: '/_api/pages.remove',
-      data: $('#delete-page-form').serialize(),
+      data: nameValueMap,
       dataType: 'json',
       dataType: 'json',
     }).done((res) => {
     }).done((res) => {
       // error
       // error

File diff suppressed because it is too large
+ 390 - 197
src/client/styles/agile-admin/inverse/eliteadmin.scss


+ 42 - 0
src/lib/service/xss/commonmark-spec.js

@@ -0,0 +1,42 @@
+/**
+ * Valid schemes
+ * @see https://spec.commonmark.org/0.16/#autolinks
+ */
+const schemesForAutolink = [
+  'coap', 'doi', 'javascript', 'aaa', 'aaas', 'about', 'acap', 'cap', 'cid', 'crid', 'data', 'dav', 'dict', 'dns',
+  'file', 'ftp', 'geo', 'go', 'gopher', 'h323', 'http', 'https', 'iax', 'icap', 'im', 'imap', 'info', 'ipp', 'iris',
+  'iris.beep', 'iris.xpc', 'iris.xpcs', 'iris.lwz', 'ldap', 'mailto', 'mid', 'msrp', 'msrps', 'mtqp', 'mupdate',
+  'news', 'nfs', 'ni', 'nih', 'nntp', 'opaquelocktoken', 'pop', 'pres', 'rtsp', 'service', 'session', 'shttp',
+  'sieve', 'sip', 'sips', 'sms', 'snmp,soap.beep', 'soap.beeps', 'tag', 'tel', 'telnet', 'tftp', 'thismessage',
+  'tn3270', 'tip', 'tv', 'urn', 'vemmi', 'ws', 'wss', 'xcon', 'xcon-userid', 'xmlrpc.beep', 'xmlrpc.beeps', 'xmpp',
+  'z39.50r', 'z39.50s', 'adiumxtra', 'afp', 'afs', 'aim', 'apt,attachment', 'aw', 'beshare', 'bitcoin', 'bolo',
+  'callto', 'chrome,chrome-extension', 'com-eventbrite-attendee', 'content', 'cvs,dlna-playsingle', 'dlna-playcontainer',
+  'dtn', 'dvb', 'ed2k', 'facetime', 'feed', 'finger', 'fish', 'gg', 'git', 'gizmoproject', 'gtalk', 'hcp', 'icon',
+  'ipn', 'irc', 'irc6', 'ircs', 'itms', 'jar', 'jms', 'keyparc', 'lastfm', 'ldaps', 'magnet', 'maps', 'market,message',
+  'mms', 'ms-help', 'msnim', 'mumble', 'mvn', 'notes', 'oid', 'palm', 'paparazzi', 'platform', 'proxy', 'psyc',
+  'query', 'res', 'resource', 'rmi', 'rsync', 'rtmp', 'secondlife', 'sftp', 'sgn', 'skype', 'smb', 'soldat', 'spotify',
+  'ssh', 'steam', 'svn', 'teamspeak', 'things', 'udp', 'unreal', 'ut2004', 'ventrilo', 'view-source', 'webcal',
+  'wtai', 'wyciwyg', 'xfire', 'xri', 'ymsgr',
+];
+const schemesCondition = schemesForAutolink.join('|');
+
+/**
+ * RegExp for URI
+ * @type {RegExp}
+ * @see https://spec.commonmark.org/0.16/#autolinks
+ */
+const uriAutolinkRegexp = new RegExp(`^(${schemesCondition}):\\/\\/.+$`);
+
+/**
+ * RegExp for email
+ * @type {RegExp}
+ * @see https://spec.commonmark.org/0.16/#autolinks
+ */
+// eslint-disable-next-line max-len
+const emailAutolinkRegexp = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
+
+
+module.exports = {
+  uriAutolinkRegexp,
+  emailAutolinkRegexp,
+};

+ 9 - 1
src/lib/service/xss/index.js

@@ -1,7 +1,9 @@
+const xss = require('xss');
+const commonmarkSpec = require('./commonmark-spec');
+
 class Xss {
 class Xss {
 
 
   constructor(xssOption) {
   constructor(xssOption) {
-    const xss = require('xss');
 
 
     xssOption = xssOption || {}; // eslint-disable-line no-param-reassign
     xssOption = xssOption || {}; // eslint-disable-line no-param-reassign
 
 
@@ -17,6 +19,12 @@ class Xss {
       css: false,
       css: false,
       whiteList: whiteListContent,
       whiteList: whiteListContent,
       escapeHtml: (html) => { return html }, // resolve https://github.com/weseek/growi/issues/221
       escapeHtml: (html) => { return html }, // resolve https://github.com/weseek/growi/issues/221
+      onTag: (tag, html, options) => {
+        // pass autolink
+        if (tag.match(commonmarkSpec.uriAutolinkRegexp) || tag.match(commonmarkSpec.emailAutolinkRegexp)) {
+          return html;
+        }
+      },
     };
     };
 
 
     tagWhiteList.forEach((tag) => {
     tagWhiteList.forEach((tag) => {

+ 1 - 1
src/lib/service/xss/recommendedXssWhiteList.js → src/lib/service/xss/recommended-whitelist.js

@@ -5,7 +5,7 @@
  */
  */
 
 
 const tags = [
 const tags = [
-  'a', 'b', 'blockquote', 'blockquote', 'code', 'del', 'dd', 'dl', 'dt', 'em',
+  '-', 'a', 'b', 'blockquote', 'blockquote', 'code', 'del', 'dd', 'dl', 'dt', 'em',
   'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'i', 'img', 'kbd', 'li', 'ol', 'p', 'pre',
   'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'i', 'img', 'kbd', 'li', 'ol', 'p', 'pre',
   's', 'sup', 'sub', 'strong', 'strike', 'ul', 'br', 'hr', 'span', 'div', 'iframe',
   's', 'sup', 'sub', 'strong', 'strike', 'ul', 'br', 'hr', 'span', 'div', 'iframe',
   'table', 'thead', 'tbody', 'tfoot', 'th', 'td', 'tr', 'colgroup', 'col',
   'table', 'thead', 'tbody', 'tfoot', 'th', 'td', 'tr', 'colgroup', 'col',

+ 3 - 3
src/lib/service/xss/xssOption.js

@@ -1,12 +1,12 @@
 class XssOption {
 class XssOption {
 
 
   constructor(config) {
   constructor(config) {
-    const recommendedXssWhiteList = require('./recommendedXssWhiteList');
+    const recommendedWhitelist = require('./recommended-whitelist');
     const initializedConfig = (config != null) ? config : {};
     const initializedConfig = (config != null) ? config : {};
 
 
     this.isEnabledXssPrevention = initializedConfig.isEnabledXssPrevention || true;
     this.isEnabledXssPrevention = initializedConfig.isEnabledXssPrevention || true;
-    this.tagWhiteList = initializedConfig.tagWhiteList || recommendedXssWhiteList.tags;
-    this.attrWhiteList = initializedConfig.attrWhiteList || recommendedXssWhiteList.attrs;
+    this.tagWhiteList = initializedConfig.tagWhiteList || recommendedWhitelist.tags;
+    this.attrWhiteList = initializedConfig.attrWhiteList || recommendedWhitelist.attrs;
   }
   }
 
 
 }
 }

+ 3 - 3
src/server/models/config.js

@@ -7,7 +7,7 @@ module.exports = function(crowi) {
   const mongoose = require('mongoose');
   const mongoose = require('mongoose');
   const debug = require('debug')('growi:models:config');
   const debug = require('debug')('growi:models:config');
   const uglifycss = require('uglifycss');
   const uglifycss = require('uglifycss');
-  const recommendedXssWhiteList = require('@commons/service/xss/recommendedXssWhiteList');
+  const recommendedWhitelist = require('@commons/service/xss/recommended-whitelist');
 
 
   const SECURITY_RESTRICT_GUEST_MODE_DENY = 'Deny';
   const SECURITY_RESTRICT_GUEST_MODE_DENY = 'Deny';
   const SECURITY_RESTRICT_GUEST_MODE_READONLY = 'Readonly';
   const SECURITY_RESTRICT_GUEST_MODE_READONLY = 'Readonly';
@@ -430,7 +430,7 @@ module.exports = function(crowi) {
           return [];
           return [];
 
 
         case 2: // recommended
         case 2: // recommended
-          return recommendedXssWhiteList.tags;
+          return recommendedWhitelist.tags;
 
 
         case 3: // custom white list
         case 3: // custom white list
           return config.markdown[key];
           return config.markdown[key];
@@ -453,7 +453,7 @@ module.exports = function(crowi) {
           return [];
           return [];
 
 
         case 2: // recommended
         case 2: // recommended
-          return recommendedXssWhiteList.attrs;
+          return recommendedWhitelist.attrs;
 
 
         case 3: // custom white list
         case 3: // custom white list
           return config.markdown[key];
           return config.markdown[key];

+ 1 - 4
src/server/models/page.js

@@ -1098,11 +1098,8 @@ module.exports = function(crowi) {
       }
       }
 
 
       pageData.status = STATUS_DELETED;
       pageData.status = STATUS_DELETED;
-      const updatedPageData = await this.rename(pageData, newPath, user, { createRedirectPage: true });
+      const updatedPageData = await this.rename(pageData, newPath, user, { socketClientId, createRedirectPage: true });
 
 
-      if (socketClientId != null) {
-        pageEvent.emit('delete', updatedPageData, user, socketClientId);
-      }
       return updatedPageData;
       return updatedPageData;
     }
     }
 
 

+ 2 - 2
src/server/routes/admin.js

@@ -14,7 +14,7 @@ module.exports = function(crowi, app) {
   const GlobalNotificationMailSetting = models.GlobalNotificationMailSetting;
   const GlobalNotificationMailSetting = models.GlobalNotificationMailSetting;
   const GlobalNotificationSlackSetting = models.GlobalNotificationSlackSetting; // eslint-disable-line no-unused-vars
   const GlobalNotificationSlackSetting = models.GlobalNotificationSlackSetting; // eslint-disable-line no-unused-vars
 
 
-  const recommendedXssWhiteList = require('@commons/service/xss/recommendedXssWhiteList');
+  const recommendedWhitelist = require('@commons/service/xss/recommended-whitelist');
   const PluginUtils = require('../plugins/plugin-utils');
   const PluginUtils = require('../plugins/plugin-utils');
   const ApiResponse = require('../util/apiResponse');
   const ApiResponse = require('../util/apiResponse');
   const importer = require('../util/importer')(crowi);
   const importer = require('../util/importer')(crowi);
@@ -117,7 +117,7 @@ module.exports = function(crowi, app) {
 
 
     return res.render('admin/markdown', {
     return res.render('admin/markdown', {
       markdownSetting,
       markdownSetting,
-      recommendedXssWhiteList,
+      recommendedWhitelist,
     });
     });
   };
   };
 
 

+ 2 - 2
src/server/views/admin/markdown.html

@@ -193,11 +193,11 @@
               <p class="font-weight-bold">{{ t('markdown_setting.Recommended setting') }}</p>
               <p class="font-weight-bold">{{ t('markdown_setting.Recommended setting') }}</p>
               <div class="m-t-15">
               <div class="m-t-15">
                 {{ t('markdown_setting.Tag names') }}
                 {{ t('markdown_setting.Tag names') }}
-                <textarea class="form-control xss-list" name="recommendedTags" rows="6" cols="40" readonly>{{ recommendedXssWhiteList.tags }}</textarea>
+                <textarea class="form-control xss-list" name="recommendedTags" rows="6" cols="40" readonly>{{ recommendedWhitelist.tags }}</textarea>
               </div>
               </div>
               <div class="m-t-15">
               <div class="m-t-15">
                 {{ t('markdown_setting.Tag attributes') }}
                 {{ t('markdown_setting.Tag attributes') }}
-                <textarea class="form-control xss-list" name="recommendedAttrs" rows="6" cols="40" readonly>{{ recommendedXssWhiteList.attrs }}</textarea>
+                <textarea class="form-control xss-list" name="recommendedAttrs" rows="6" cols="40" readonly>{{ recommendedWhitelist.attrs }}</textarea>
               </div>
               </div>
             </label>
             </label>
           </div>
           </div>

+ 8 - 7
yarn.lock

@@ -4826,10 +4826,10 @@ graceful-fs@^4.1.15:
   resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00"
   resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00"
   integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==
   integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==
 
 
-growi-commons@^3.2.2:
-  version "3.2.2"
-  resolved "https://registry.yarnpkg.com/growi-commons/-/growi-commons-3.2.2.tgz#36aaca18e23aaa13ecd9b26e72fed527b3d4c070"
-  integrity sha512-7tX7+rpduaJthVAuc6EIKGoIQ/bW6RpPLVLjpddW4tgU05Sw3KnGdXCGzEHAMYulrKRRo++DcPWdIoPuw7r0Zw==
+growi-commons@^4.0.1:
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/growi-commons/-/growi-commons-4.0.1.tgz#e0e71c9c286f493e11c0703c809385bcdc6a97a9"
+  integrity sha512-haH4Av1WuQIHic4Jv2RRwDprbKecRKF/3C0wVk9ssBzWtB3V6Oghj5gksajDpYOd7tOKdvkVEqqkFfIV4JQUyQ==
 
 
 growl@1.10.5:
 growl@1.10.5:
   version "1.10.5"
   version "1.10.5"
@@ -11601,9 +11601,10 @@ xpath@0.0.27:
   version "0.0.27"
   version "0.0.27"
   resolved "https://registry.yarnpkg.com/xpath/-/xpath-0.0.27.tgz#dd3421fbdcc5646ac32c48531b4d7e9d0c2cfa92"
   resolved "https://registry.yarnpkg.com/xpath/-/xpath-0.0.27.tgz#dd3421fbdcc5646ac32c48531b4d7e9d0c2cfa92"
 
 
-xss@^1.0.3:
-  version "1.0.3"
-  resolved "https://registry.yarnpkg.com/xss/-/xss-1.0.3.tgz#d04bd2558fd6c29c46113824d5e8b2a910054e23"
+xss@^1.0.6:
+  version "1.0.6"
+  resolved "https://registry.yarnpkg.com/xss/-/xss-1.0.6.tgz#eaf11e9fc476e3ae289944a1009efddd8a124b51"
+  integrity sha512-6Q9TPBeNyoTRxgZFk5Ggaepk/4vUOYdOsIUYvLehcsIZTFjaavbVnsuAkLA5lIFuug5hw8zxcB9tm01gsjph2A==
   dependencies:
   dependencies:
     commander "^2.9.0"
     commander "^2.9.0"
     cssfilter "0.0.10"
     cssfilter "0.0.10"

Some files were not shown because too many files changed in this diff