Merge pull request #932 from ethereum/open-save-workspace

Forbids plugin to access root file system
pull/5370/head
yann300 4 years ago committed by GitHub
commit 9132be320d
  1. 2
      apps/remix-ide/src/app.js
  2. 29
      apps/remix-ide/src/app/files/fileManager.js
  3. 4
      apps/remix-ide/src/app/files/fileProvider.js
  4. 30
      apps/remix-ide/src/app/panels/file-panel.js
  5. 15
      apps/remix-ide/src/migrateFileSystem.js
  6. 14
      libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx

@ -485,7 +485,7 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
// get the file list from the parent iframe
loadFileFromParent(fileManager)
migrateToWorkspace(fileManager)
migrateToWorkspace(fileManager, filePanel)
if (params.embed) framingService.embed()
}

@ -57,6 +57,10 @@ class FileManager extends Plugin {
this.mode = mode
}
limitPluginScope (path) {
return path.replace(/^\/browser\//, '').replace(/^browser\//, '') // forbids plugin to access the root filesystem
}
/**
* Emit error if path doesn't exist
* @param {string} path path of the file/directory
@ -110,6 +114,7 @@ class FileManager extends Plugin {
* @returns {boolean} true if the path exists
*/
exists (path) {
path = this.limitPluginScope(path)
const provider = this.fileProviderOf(path)
const result = provider.exists(path, (err, result) => {
if (err) return false
@ -149,6 +154,7 @@ class FileManager extends Plugin {
* @returns {void}
*/
async open (path) {
path = this.limitPluginScope(path)
await this._handleExists(path, `Cannot open file ${path}`)
await this._handleIsFile(path, `Cannot open file ${path}`)
return this.openFile(path)
@ -161,6 +167,7 @@ class FileManager extends Plugin {
* @returns {void}
*/
async writeFile (path, data) {
path = this.limitPluginScope(path)
if (await this.exists(path)) {
await this._handleIsFile(path, `Cannot write file ${path}`)
return await this.setFileContent(path, data)
@ -177,6 +184,7 @@ class FileManager extends Plugin {
* @returns {string} content of the file
*/
async readFile (path) {
path = this.limitPluginScope(path)
await this._handleExists(path, `Cannot read file ${path}`)
await this._handleIsFile(path, `Cannot read file ${path}`)
return this.getFileContent(path)
@ -189,6 +197,8 @@ class FileManager extends Plugin {
* @returns {void}
*/
async copyFile (src, dest) {
src = this.limitPluginScope(src)
dest = this.limitPluginScope(dest)
await this._handleExists(src, `Cannot copy from ${src}`)
await this._handleIsFile(src, `Cannot copy from ${src}`)
await this._handleIsFile(dest, `Cannot paste content into ${dest}`)
@ -204,6 +214,8 @@ class FileManager extends Plugin {
* @returns {void}
*/
async rename (oldPath, newPath) {
oldPath = this.limitPluginScope(oldPath)
newPath = this.limitPluginScope(newPath)
await this._handleExists(oldPath, `Cannot rename ${oldPath}`)
const isFile = await this.isFile(oldPath)
const newPathExists = await this.exists(newPath)
@ -230,6 +242,7 @@ class FileManager extends Plugin {
* @returns {void}
*/
async mkdir (path) {
path = this.limitPluginScope(path)
if (await this.exists(path)) {
throw createError({ code: 'EEXIST', message: `Cannot create directory ${path}` })
}
@ -244,6 +257,7 @@ class FileManager extends Plugin {
* @returns {string[]} list of the file/directory name in this directory
*/
async readdir (path) {
path = this.limitPluginScope(path)
await this._handleExists(path)
await this._handleIsDir(path)
@ -263,6 +277,7 @@ class FileManager extends Plugin {
* @returns {void}
*/
async remove (path) {
path = this.limitPluginScope(path)
await this._handleExists(path, `Cannot remove file or directory ${path}`)
const provider = this.fileProviderOf(path)
@ -585,20 +600,6 @@ class FileManager extends Plugin {
if (callback) callback(error)
})
}
async createWorkspace (name) {
const workspaceProvider = this._deps.filesProviders.workspace
const workspacePath = 'browser/' + workspaceProvider.workspacesPath + '/' + name
const workspaceRootPath = 'browser/' + workspaceProvider.workspacesPath
if (!this.exists(workspaceRootPath)) await this.mkdir(workspaceRootPath)
if (!this.exists(workspacePath)) await this.mkdir(workspacePath)
}
async workspaceExists (name) {
const workspaceProvider = this._deps.filesProviders.workspace
const workspacePath = 'browser/' + workspaceProvider.workspacesPath + '/' + name
return this.exists(workspacePath)
}
}
module.exports = FileManager

@ -66,7 +66,9 @@ class FileProvider {
exists (path, cb) {
// todo check the type (directory/file) as well #2386
// currently it is not possible to have a file and folder with same path
return cb(null, this._exists(path))
const ret = this._exists(path)
if (cb) cb(null, ret)
return ret
}
_exists (path) {

@ -131,7 +131,6 @@ module.exports = class Filepanel extends ViewPlugin {
async initWorkspace () {
const queryParams = new QueryParams()
const gistHandler = new GistHandler()
const workspacesPath = this._deps.fileProviders.workspace.workspacesPath
const params = queryParams.get()
// get the file from gist
const loadedFromGist = gistHandler.loadFromGist(params, this._deps.fileManager)
@ -139,12 +138,12 @@ module.exports = class Filepanel extends ViewPlugin {
if (loadedFromGist) return
if (params.code) {
try {
await this._deps.fileManager.createWorkspace('code-sample')
await this.processCreateWorkspace('code-sample')
this._deps.fileProviders.workspace.setWorkspace('code-sample')
var hash = ethutil.bufferToHex(ethutil.keccak(params.code))
const fileName = 'contract-' + hash.replace('0x', '').substring(0, 10) + '.sol'
const path = 'browser/' + workspacesPath + '/code-sample/' + fileName
await this._deps.fileManager.writeFile(path, atob(params.code))
const path = fileName
await this._deps.fileProviders.workspace.set(path, atob(params.code))
this.initialWorkspace = 'code-sample'
await this._deps.fileManager.openFile(fileName)
} catch (e) {
@ -170,13 +169,30 @@ module.exports = class Filepanel extends ViewPlugin {
return await this.request.uploadFile()
}
async processCreateWorkspace (name) {
const workspaceProvider = this._deps.fileProviders.workspace
const browserProvider = this._deps.fileProviders.browser
const workspacePath = 'browser/' + workspaceProvider.workspacesPath + '/' + name
const workspaceRootPath = 'browser/' + workspaceProvider.workspacesPath
if (!browserProvider.exists(workspaceRootPath)) browserProvider.createDir(workspaceRootPath)
if (!browserProvider.exists(workspacePath)) browserProvider.createDir(workspacePath)
}
async workspaceExists (name) {
const workspaceProvider = this._deps.fileProviders.workspace
const browserProvider = this._deps.fileProviders.browser
const workspacePath = 'browser/' + workspaceProvider.workspacesPath + '/' + name
return browserProvider.exists(workspacePath)
}
async createWorkspace (workspaceName) {
if (await this._deps.fileManager.workspaceExists(workspaceName)) throw new Error('workspace already exists')
if (await this.workspaceExists(workspaceName)) throw new Error('workspace already exists')
const browserProvider = this._deps.fileProviders.browser
const workspacesPath = this._deps.fileProviders.workspace.workspacesPath
await this._deps.fileManager.createWorkspace(workspaceName)
await this.processCreateWorkspace(workspaceName)
for (const file in examples) {
try {
await this._deps.fileManager.writeFile('browser/' + workspacesPath + '/' + workspaceName + '/' + examples[file].name, examples[file].content)
await browserProvider.set('browser/' + workspacesPath + '/' + workspaceName + '/' + examples[file].name, examples[file].content)
} catch (error) {
console.error(error)
}

@ -21,7 +21,7 @@ export default (fileProvider) => {
fileStorageBrowserFS.set(flag, 'done')
}
export async function migrateToWorkspace (fileManager) {
export async function migrateToWorkspace (fileManager, filePanel) {
const browserProvider = fileManager.getProvider('browser')
const workspaceProvider = fileManager.getProvider('workspace')
const flag = 'status'
@ -31,19 +31,20 @@ export async function migrateToWorkspace (fileManager) {
console.log(files)
const workspaceName = 'default_workspace'
const workspacePath = joinPath('browser', workspaceProvider.workspacesPath, workspaceName)
await fileManager.createWorkspace(workspaceName)
await populateWorkspace(workspacePath, files, fileManager)
await filePanel.createWorkspace(workspaceName)
filePanel.getWorkspaces() // refresh list
await populateWorkspace(workspacePath, files, browserProvider)
fileStorageBrowserWorkspace.set(flag, 'done')
}
const populateWorkspace = async (workspace, json, fileManager) => {
const populateWorkspace = async (workspace, json, browserProvider) => {
for (const item in json) {
const isFolder = json[item].content === undefined
if (isFolder) {
await fileManager.mkdir(joinPath(workspace, item))
await populateWorkspace(workspace, json[item].children, fileManager)
browserProvider.createDir(joinPath(workspace, item))
await populateWorkspace(workspace, json[item].children, browserProvider)
} else {
await fileManager.writeFile(joinPath(workspace, item), json[item].content)
await browserProvider.set(joinPath(workspace, item), json[item].content)
}
}
}

@ -62,12 +62,7 @@ export const Workspace = (props: WorkspaceProps) => {
useEffect(() => {
const getWorkspaces = async () => {
if (props.workspaces && Array.isArray(props.workspaces)) {
if (props.initialWorkspace) {
props.workspace.setWorkspace(props.initialWorkspace)
setState(prevState => {
return { ...prevState, workspaces: props.workspaces, currentWorkspace: props.initialWorkspace }
})
} else if (props.workspaces.length > 0 && state.currentWorkspace === NO_WORKSPACE) {
if (props.workspaces.length > 0 && state.currentWorkspace === NO_WORKSPACE) {
props.workspace.setWorkspace(props.workspaces[0])
setState(prevState => {
return { ...prevState, workspaces: props.workspaces, currentWorkspace: props.workspaces[0] }
@ -91,6 +86,13 @@ export const Workspace = (props: WorkspaceProps) => {
props.localhost.event.register('disconnected', (event) => {
remixdExplorer.hide()
})
if (props.initialWorkspace) {
props.workspace.setWorkspace(props.initialWorkspace)
setState(prevState => {
return { ...prevState, currentWorkspace: props.initialWorkspace }
})
}
}, [])
const [state, setState] = useState({

Loading…
Cancel
Save