1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-08-02 07:47:32 +00:00

Repair xss bug (#5256)

* repair upload file with same script name bug

* update repo name xss bug

* fix: transform lib xss bug

* optimize code
This commit is contained in:
杨顺强 2022-09-08 16:42:55 +08:00 committed by GitHub
parent db77c8e8ad
commit 91d1751a57
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 71 additions and 25 deletions

View File

@ -5,6 +5,7 @@ import { gettext, repoPasswordMinLength } from '../../utils/constants';
import { Utils } from '../../utils/utils';
import { seafileAPI } from '../../utils/seafile-api';
import toaster from '../toast';
import StyledTitle from '../styled-title';
const propTypes = {
repoID: PropTypes.string.isRequired,
@ -98,7 +99,9 @@ class ChangeRepoPasswordDialog extends React.Component {
return (
<Modal isOpen={true} centered={true} style={{height: 'auto'}}>
<ModalHeader toggle={toggleDialog}>
<span dangerouslySetInnerHTML={{__html: Utils.generateDialogTitle(gettext('Change Password of Library {placeholder}'), repoName)}}></span>
<span>
{gettext("Change Password of Library")}{' '}<StyledTitle title={repoName} />
</span>
</ModalHeader>
<ModalBody>
<form id="repo-change-passwd-form" action="" method="post">

View File

@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
import { Modal, ModalHeader, ModalBody, TabContent, TabPane, Nav, NavItem, NavLink } from 'reactstrap';
import { gettext } from '../../utils/constants';
import { Utils } from '../../utils/utils';
import StyledTitle from '../styled-title';
import LibSubFolderSetUserPermissionDialog from './lib-sub-folder-set-user-permission-dialog';
import LibSubFolderSetGroupPermissionDialog from './lib-sub-folder-set-group-permission-dialog';
import '../../css/share-link-dialog.css';
@ -32,7 +33,7 @@ class LibSubFolderPermissionDialog extends React.Component {
}
renderContent = () => {
let activeTab = this.state.activeTab;
const activeTab = this.state.activeTab;
return (
<Fragment>
@ -64,14 +65,28 @@ class LibSubFolderPermissionDialog extends React.Component {
);
}
render() {
renderHeader = () => {
const { repoName, folderName } = this.props;
if (repoName) {
return (
<Fragment>
<StyledTitle title={repoName} />{gettext('Folder Permission')}
</Fragment>
);
}
return (
<Fragment>
{gettext('Set')}{' '}<StyledTitle title={folderName} />{gettext('permission')}
</Fragment>
);
}
render() {
return (
<div>
<Modal isOpen={true} style={{maxWidth: '980px'}} className="share-dialog" toggle={this.props.toggleDialog}>
<ModalHeader toggle={this.props.toggleDialog}>
<span dangerouslySetInnerHTML={{__html: repoName ? Utils.generateDialogTitle(gettext('{placeholder} Folder Permission'), repoName) : Utils.generateDialogTitle(gettext('Set {placeholder}\'s permission'), folderName)}}></span>
{this.renderHeader()}
</ModalHeader>
<ModalBody className="dialog-list-container share-dialog-content" role="tablist">
{this.renderContent()}

View File

@ -8,6 +8,7 @@ import { gettext, isPro } from '../../utils/constants';
import { Utils } from '../../utils/utils';
import toaster from '../toast';
import UserSelect from '../user-select';
import StyledTitle from '../styled-title/index.js';
const propTypes = {
itemName: PropTypes.string.isRequired,
@ -61,10 +62,6 @@ class TransferDialog extends React.Component {
render() {
const itemName = this.props.itemName;
const innerSpan = '<span class="op-target" title=' + itemName + '>' + itemName +'</span>';
let msg = gettext('Transfer Library {library_name}');
let message = msg.replace('{library_name}', innerSpan);
let canTransferToDept = true;
if (this.props.canTransferToDept != undefined) {
canTransferToDept = this.props.canTransferToDept;
@ -72,7 +69,7 @@ class TransferDialog extends React.Component {
return (
<Modal isOpen={true}>
<ModalHeader toggle={this.props.toggleDialog}>
<div dangerouslySetInnerHTML={{__html:message}} />
{gettext('Transfer Library')}{' '}<StyledTitle title={itemName} />
</ModalHeader>
<ModalBody>
{this.state.transferToUser ?

View File

@ -28,12 +28,16 @@ class UploadRemindDialog extends React.Component {
}
render() {
let title = gettext('Replace file {filename}?');
title = title.replace('{filename}', '<span class="a-simaulte">' + this.props.currentResumableFile.fileName + '</span>');
const { fileName } = this.props.currentResumableFile;
const titlePrefix = gettext('Replace file');
return (
<Modal isOpen={true} toggle={this.toggle}>
<ModalHeader toggle={this.toggle} ><div dangerouslySetInnerHTML={{__html: title}}></div></ModalHeader>
<ModalHeader toggle={this.toggle} >
<div>
<span>{titlePrefix}{' '}</span>
<span class="a-simulate">{fileName}?</span>
</div>
</ModalHeader>
<ModalBody>
<p>{gettext('A file with the same name already exists in this folder.')}</p>
<p>{gettext('Replacing it will overwrite its content.')}</p>

View File

@ -0,0 +1,26 @@
import React from 'react';
import PropTypes from 'prop-types';
const propTypes = {
title: PropTypes.string.isRequired,
className: PropTypes.string,
};
class StyledTitle extends React.Component {
static defaultProps = {
className: '',
}
render() {
const { title } = this.props;
const className = `op-target ellipsis ellipsis-op-target ${className}`
return (
<span className={className}>{title}{' '}</span>
);
}
}
StyledTitle.propTypes = propTypes;
export default StyledTitle;

View File

@ -10,6 +10,7 @@ import ModalPortal from './components/modal-portal';
import toaster from './components/toast';
import CommonToolbar from './components/toolbar/common-toolbar';
import CleanTrash from './components/dialog/clean-trash';
import StyledTitle from './components/styled-title';
import './css/toolbar.css';
import './css/search.css';
@ -192,7 +193,9 @@ class RepoFolderTrash extends React.Component {
<div className="flex-auto container-fluid pt-4 pb-6 o-auto">
<div className="row">
<div className="col-md-10 offset-md-1">
<h2 dangerouslySetInnerHTML={{__html: Utils.generateDialogTitle(gettext('{placeholder} Trash'), repoFolderName)}}></h2>
<h2>
<StyledTitle title={repoFolderName} />{gettext('Trash')}
</h2>
<a href="#" className="go-back" title={gettext('Back')} onClick={this.goBack} role="button" role={gettext('Back')}>
<span className="fas fa-chevron-left"></span>
</a>

View File

@ -11,6 +11,7 @@ import ModalPortal from './components/modal-portal';
import CommonToolbar from './components/toolbar/common-toolbar';
import CommitDetails from './components/dialog/commit-details';
import UpdateRepoCommitLabels from './components/dialog/edit-repo-commit-labels';
import StyledTitle from './components/styled-title';
import './css/toolbar.css';
import './css/search.css';
@ -104,7 +105,9 @@ class RepoHistory extends React.Component {
<div className="flex-auto container-fluid pt-4 pb-6 o-auto">
<div className="row">
<div className="col-md-10 offset-md-1">
<h2 dangerouslySetInnerHTML={{__html: Utils.generateDialogTitle(gettext('{placeholder} Modification History'), repoName)}}></h2>
<h2>
<StyledTitle title={repoName} />{gettext('Modification History')}
</h2>
<a href="#" className="go-back" title={gettext('Back')} onClick={this.goBack} role="button" aria-label={gettext('Back')}>
<span className="fas fa-chevron-left"></span>
</a>

View File

@ -9,6 +9,7 @@ import ModalPortal from './components/modal-portal';
import toaster from './components/toast';
import CommonToolbar from './components/toolbar/common-toolbar';
import ConfirmRestoreRepo from './components/dialog/confirm-restore-repo';
import StyledTitle from './components/styled-title';
import './css/toolbar.css';
import './css/search.css';
@ -139,7 +140,10 @@ class RepoSnapshot extends React.Component {
<div className="flex-auto container-fluid pt-4 pb-6 o-auto">
<div className="row">
<div className="col-md-10 offset-md-1">
<h2 dangerouslySetInnerHTML={{__html: Utils.generateDialogTitle(gettext('{placeholder} Snapshot'), repoName) + ` <span class="heading-commit-time">(${commitTime})</span>`}}></h2>
<h2>
<StyledTitle title={repoName} />{gettext('Snapshot')}{' '}
<span class="heading-commit-time">(${commitTime})</span>
</h2>
<a href="#" className="go-back" title={gettext('Back')} role="button" aria-label={gettext('Back')} onClick={this.goBack}>
<span className="fas fa-chevron-left"></span>
</a>

View File

@ -231,15 +231,6 @@ export const Utils = {
.innerHTML;
},
generateDialogTitle: function(title, operationTarget) {
/*
* @param title: gettext('...{placeholder}...')
*/
const targetStr = this.HTMLescape(operationTarget);
const str = `<span class="op-target ellipsis ellipsis-op-target" title=${targetStr}>${targetStr}</span>`;
return title.replace('{placeholder}', str);
},
getFileName: function(filePath) {
let lastIndex = filePath.lastIndexOf('/');
return filePath.slice(lastIndex+1);