mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-CR-9966 add test, assert that decoded raw path starts with /
This commit is contained in:
@@ -50,7 +50,7 @@ class BuiltInWebServer : HttpRequestHandler() {
|
||||
return false
|
||||
}
|
||||
|
||||
val portIndex = host.indexOf(':')
|
||||
val portIndex = host!!.indexOf(':')
|
||||
if (portIndex > 0) {
|
||||
host = host.substring(0, portIndex)
|
||||
}
|
||||
@@ -134,8 +134,7 @@ private fun doProcess(request: FullHttpRequest, context: ChannelHandlerContext,
|
||||
return true
|
||||
}
|
||||
|
||||
// must be absolute path (relative to DOCUMENT_ROOT, i.e. scheme://authority/) to properly canonicalize
|
||||
val path = FileUtil.toCanonicalPath(decodedPath.substring(offset), '/').substring(1)
|
||||
val path = toIdeaPath(decodedPath, offset)
|
||||
for (pathHandler in WebServerPathHandler.EP_NAME.extensions) {
|
||||
LOG.catchAndLog {
|
||||
if (pathHandler.process(path, project, request, context, projectName, decodedPath, isCustomHost)) {
|
||||
@@ -146,6 +145,15 @@ private fun doProcess(request: FullHttpRequest, context: ChannelHandlerContext,
|
||||
return false
|
||||
}
|
||||
|
||||
private fun toIdeaPath(decodedPath: String, offset: Int): String {
|
||||
// must be absolute path (relative to DOCUMENT_ROOT, i.e. scheme://authority/) to properly canonicalize
|
||||
val path = decodedPath.substring(offset)
|
||||
if (!path.startsWith('/')) {
|
||||
throw AssertionError("Path must be absolute")
|
||||
}
|
||||
return FileUtil.toCanonicalPath(path, '/').substring(1)
|
||||
}
|
||||
|
||||
fun compareNameAndProjectBasePath(projectName: String, project: Project): Boolean {
|
||||
val basePath = project.basePath
|
||||
return basePath != null && endsWithName(basePath, projectName)
|
||||
|
||||
@@ -50,7 +50,7 @@ abstract class WebServerPathHandler {
|
||||
|
||||
fun redirectToDirectory(request: HttpRequest, channel: Channel, path: String) {
|
||||
val response = Responses.response(HttpResponseStatus.MOVED_PERMANENTLY)
|
||||
val url = VfsUtil.toUri("${channel.uriScheme}://${request.host}/$path/")!!
|
||||
val url = VfsUtil.toUri("${channel.uriScheme}://${request.host!!}/$path/")!!
|
||||
response.headers().add(HttpHeaderNames.LOCATION, url.toASCIIString())
|
||||
Responses.send(response, channel, request)
|
||||
}
|
||||
@@ -43,16 +43,18 @@ internal abstract class BuiltInServerTestCase {
|
||||
url += ":$column"
|
||||
}
|
||||
|
||||
val connection = URL(url).openConnection() as HttpURLConnection
|
||||
val expectedStatus = HttpResponseStatus.valueOf(manager.annotation?.status ?: 200)
|
||||
assertThat(HttpResponseStatus.valueOf(connection.responseCode)).isEqualTo(expectedStatus)
|
||||
|
||||
val connection = testUrl(url, expectedStatus)
|
||||
check(serviceUrl, expectedStatus)
|
||||
if (additionalCheck != null) {
|
||||
additionalCheck(connection)
|
||||
}
|
||||
additionalCheck?.invoke(connection)
|
||||
}
|
||||
|
||||
protected open fun check(serviceUrl: String, expectedStatus: HttpResponseStatus) {
|
||||
}
|
||||
}
|
||||
|
||||
internal fun testUrl(url: String, expectedStatus: HttpResponseStatus): HttpURLConnection {
|
||||
val connection = URL(url).openConnection() as HttpURLConnection
|
||||
assertThat(HttpResponseStatus.valueOf(connection.responseCode)).isEqualTo(expectedStatus)
|
||||
return connection
|
||||
}
|
||||
@@ -1,14 +1,20 @@
|
||||
package org.jetbrains.ide
|
||||
|
||||
import com.google.common.net.UrlEscapers
|
||||
import com.intellij.openapi.application.runWriteAction
|
||||
import com.intellij.openapi.module.EmptyModuleType
|
||||
import com.intellij.openapi.module.ModuleManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.roots.ModuleRootModificationUtil
|
||||
import com.intellij.testFramework.runInEdtAndWait
|
||||
import com.intellij.util.refreshVfs
|
||||
import com.intellij.util.systemIndependentPath
|
||||
import com.intellij.util.writeChild
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import com.intellij.openapi.vfs.LocalFileSystem
|
||||
import com.intellij.testFramework.*
|
||||
import com.intellij.util.*
|
||||
import io.netty.handler.codec.http.HttpResponseStatus
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.ClassRule
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
|
||||
internal class BuiltInWebServerTest : BuiltInServerTestCase() {
|
||||
@@ -39,13 +45,7 @@ internal class BuiltInWebServerTest : BuiltInServerTestCase() {
|
||||
newPath.writeChild(manager.filePath!!, "hello")
|
||||
newPath.refreshVfs()
|
||||
|
||||
runInEdtAndWait {
|
||||
runWriteAction {
|
||||
val systemIndependentPath = newPath.systemIndependentPath
|
||||
val module = ModuleManager.getInstance(project).newModule("$systemIndependentPath/test.iml", EmptyModuleType.EMPTY_MODULE)
|
||||
ModuleRootModificationUtil.addContentRoot(module, systemIndependentPath)
|
||||
}
|
||||
}
|
||||
createModule(newPath.systemIndependentPath, project)
|
||||
|
||||
for (path in paths) {
|
||||
doTest(path) {
|
||||
@@ -53,4 +53,40 @@ internal class BuiltInWebServerTest : BuiltInServerTestCase() {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createModule(systemIndependentPath: String, project: Project) {
|
||||
runInEdtAndWait {
|
||||
runWriteAction {
|
||||
val module = ModuleManager.getInstance(project).newModule("$systemIndependentPath/test.iml", EmptyModuleType.EMPTY_MODULE)
|
||||
ModuleRootModificationUtil.addContentRoot(module, systemIndependentPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class HeavyBuiltInWebServerTest {
|
||||
companion object {
|
||||
@JvmField
|
||||
@ClassRule val appRule = ProjectRule()
|
||||
}
|
||||
|
||||
@Rule
|
||||
@JvmField
|
||||
val tempDirManager = TemporaryDirectory()
|
||||
|
||||
@Test
|
||||
fun `path outside of project`() {
|
||||
val projectDir = tempDirManager.newPath().resolve("foo/bar")
|
||||
val projectDirPath = projectDir.systemIndependentPath
|
||||
createHeavyProject("$projectDirPath/test.ipr").use { project ->
|
||||
projectDir.createDirectories()
|
||||
LocalFileSystem.getInstance().refreshAndFindFileByPath(projectDirPath)
|
||||
createModule(projectDirPath, project)
|
||||
|
||||
val path = tempDirManager.newPath("doNotExposeMe.txt").write("doNotExposeMe").systemIndependentPath
|
||||
val relativePath = FileUtil.getRelativePath(project.basePath!!, path, '/')
|
||||
val webPath = StringUtil.replace(UrlEscapers.urlPathSegmentEscaper().escape("${project.name}/$relativePath"), "%2F", "/")
|
||||
testUrl("http://localhost:${BuiltInServerManager.getInstance().port}/$webPath", HttpResponseStatus.NOT_FOUND)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,6 @@ import com.intellij.openapi.components.*
|
||||
import com.intellij.openapi.components.StateStorage.SaveSession
|
||||
import com.intellij.openapi.components.impl.stores.IComponentStore
|
||||
import com.intellij.openapi.components.impl.stores.IProjectStore
|
||||
import com.intellij.openapi.fileTypes.FileTypeManager
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.module.ModuleManager
|
||||
import com.intellij.openapi.project.Project
|
||||
@@ -246,16 +245,7 @@ private open class ProjectStoreImpl(project: ProjectImpl, private val pathMacroM
|
||||
return PathUtilRt.getFileName(baseDir).replace(":", "")
|
||||
}
|
||||
else {
|
||||
var temp = PathUtilRt.getFileName(projectFilePath)
|
||||
val fileType = FileTypeManager.getInstance().getFileTypeByFileName(temp)
|
||||
if (fileType is ProjectFileType) {
|
||||
temp = temp.substring(0, temp.length - fileType.defaultExtension.length - 1)
|
||||
}
|
||||
val i = temp.lastIndexOf(File.separatorChar)
|
||||
if (i >= 0) {
|
||||
temp = temp.substring(i + 1, temp.length - i + 1)
|
||||
}
|
||||
return temp
|
||||
return PathUtilRt.getFileName(projectFilePath).removeSuffix(ProjectFileType.DOT_DEFAULT_EXTENSION)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ fun loadAndUseProject(tempDirManager: TemporaryDirectory, projectCreator: ((Virt
|
||||
|
||||
private fun createOrLoadProject(tempDirManager: TemporaryDirectory, task: (Project) -> Unit, projectCreator: ((VirtualFile) -> String)? = null, directoryBased: Boolean) {
|
||||
runInEdtAndWait {
|
||||
var filePath: String
|
||||
val filePath: String
|
||||
if (projectCreator == null) {
|
||||
filePath = tempDirManager.newPath("test${if (directoryBased) "" else ProjectFileType.DOT_DEFAULT_EXTENSION}").systemIndependentPath
|
||||
}
|
||||
@@ -59,15 +59,9 @@ private fun createOrLoadProject(tempDirManager: TemporaryDirectory, task: (Proje
|
||||
}
|
||||
|
||||
val projectManager = ProjectManagerEx.getInstanceEx() as ProjectManagerImpl
|
||||
var project = if (projectCreator == null) projectManager.newProject(null, filePath, true, false)!! else projectManager.loadProject(filePath)!!
|
||||
val project = if (projectCreator == null) createHeavyProject(filePath, true) else projectManager.loadProject(filePath)!!
|
||||
project.runInLoadComponentStateMode {
|
||||
try {
|
||||
projectManager.openTestProject(project)
|
||||
task(project)
|
||||
}
|
||||
finally {
|
||||
projectManager.closeProject(project, false, true, false)
|
||||
}
|
||||
project.use(task)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,6 +95,8 @@ fun Path.write(data: ByteArray, offset: Int = 0, length: Int = data.size): Path
|
||||
}
|
||||
|
||||
fun Path.write(data: String): Path {
|
||||
parent?.createDirectories()
|
||||
|
||||
Files.write(this, data.toByteArray())
|
||||
return this
|
||||
}
|
||||
|
||||
@@ -95,7 +95,7 @@ fun Bootstrap.connect(remoteAddress: InetSocketAddress, promise: AsyncPromise<*>
|
||||
val Channel.uriScheme: String
|
||||
get() = if (pipeline().get(SslHandler::class.java) == null) "http" else "https"
|
||||
|
||||
val HttpRequest.host: String
|
||||
val HttpRequest.host: String?
|
||||
get() = headers().getAsString(HttpHeaderNames.HOST)
|
||||
|
||||
inline fun <T> ByteBuf.releaseIfError(task: () -> T): T {
|
||||
|
||||
@@ -226,6 +226,19 @@ inline fun <T> Project.runInLoadComponentStateMode(task: () -> T): T {
|
||||
}
|
||||
}
|
||||
|
||||
fun createHeavyProject(path: String, useDefaultProjectSettings: Boolean = false) = ProjectManagerEx.getInstanceEx().newProject(null, path, useDefaultProjectSettings, false)!!
|
||||
|
||||
fun Project.use(task: (Project) -> Unit) {
|
||||
val projectManager = ProjectManagerEx.getInstanceEx() as ProjectManagerImpl
|
||||
try {
|
||||
runInEdtAndWait { projectManager.openTestProject(this) }
|
||||
task(this)
|
||||
}
|
||||
finally {
|
||||
runInEdtAndWait { projectManager.closeProject(this, false, true, false) }
|
||||
}
|
||||
}
|
||||
|
||||
class DisposeNonLightProjectsRule() : ExternalResource() {
|
||||
override fun after() {
|
||||
val projectManager = if (ApplicationManager.getApplication().isDisposed) null else ProjectManager.getInstance() as ProjectManagerImpl
|
||||
|
||||
Reference in New Issue
Block a user