any asset must be requested with valid Refer (from regular browser)
authorVladimir Krivosheev <vladimir.krivosheev@jetbrains.com>
Mon, 18 Apr 2016 11:31:47 +0000 (13:31 +0200)
committerVladimir Krivosheev <vladimir.krivosheev@jetbrains.com>
Fri, 22 Apr 2016 13:16:44 +0000 (15:16 +0200)
platform/built-in-server/src/org/jetbrains/builtInWebServer/BuiltInWebServer.kt
platform/built-in-server/src/org/jetbrains/builtInWebServer/StaticFileHandler.kt
platform/built-in-server/src/org/jetbrains/builtInWebServer/WebServerFileHandler.kt
platform/platform-impl/src/org/jetbrains/io/netty.kt

index fae51c09cf8cbcf8f5abc0d55f1cc8f0e3834cd5..a754c1dcb5c6ed4e7788ee7583d730a1f3422513 100644 (file)
@@ -22,6 +22,7 @@ import com.intellij.openapi.project.Project
 import com.intellij.openapi.project.ProjectManager
 import com.intellij.openapi.util.SystemInfoRt
 import com.intellij.openapi.util.io.FileUtil
+import com.intellij.openapi.util.io.FileUtilRt
 import com.intellij.openapi.util.io.endsWithName
 import com.intellij.openapi.vfs.VirtualFile
 import com.intellij.util.UriUtil
@@ -32,9 +33,7 @@ import com.intellij.util.net.NetUtils
 import io.netty.channel.ChannelHandlerContext
 import io.netty.handler.codec.http.*
 import org.jetbrains.ide.HttpRequestHandler
-import org.jetbrains.io.host
-import org.jetbrains.io.isLocalOrigin
-import org.jetbrains.io.send
+import org.jetbrains.io.*
 import java.io.IOException
 import java.net.InetAddress
 import java.nio.file.Path
@@ -143,6 +142,11 @@ private fun doProcess(request: FullHttpRequest, context: ChannelHandlerContext,
     return true
   }
 
+  if (request.origin == null && request.referrer == null && request.isRegularBrowser() && !canBeAccessedDirectly(path)) {
+    HttpResponseStatus.NOT_FOUND.send(context.channel(), request)
+    return true
+  }
+
   for (pathHandler in WebServerPathHandler.EP_NAME.extensions) {
     LOG.catchAndLog {
       if (pathHandler.process(path, project, request, context, projectName, decodedPath, isCustomHost)) {
@@ -243,4 +247,15 @@ internal fun isOwnHostName(host: String): Boolean {
   catch (ignored: IOException) {
     return false
   }
+}
+
+private fun canBeAccessedDirectly(path: String): Boolean {
+  for (fileHandler in WebServerFileHandler.EP_NAME.extensions) {
+    for (ext in fileHandler.pageFileExtensions) {
+      if (FileUtilRt.extensionEquals(path, ext)) {
+        return true
+      }
+    }
+  }
+  return false
 }
\ No newline at end of file
index d1b67c2f6cd9f6283990c6b922a470257276d274..2158b67948d6c279d880409f6d2ebe10338879db 100644 (file)
@@ -18,6 +18,8 @@ import java.nio.file.Path
 import java.nio.file.Paths
 
 private class StaticFileHandler : WebServerFileHandler() {
+  override val pageFileExtensions = arrayOf("html", "htm", "shtml")
+
   private var ssiProcessor: SsiProcessor? = null
 
   override fun process(pathInfo: PathInfo, canonicalPath: CharSequence, project: Project, request: FullHttpRequest, channel: Channel, projectNameIfNotCustomHost: String?): Boolean {
index d2eed3717aca7bfb71b3c910fcbd1171082538e5..1e823c4861a475e8a9254d4790904247a6e1722e 100644 (file)
@@ -25,6 +25,9 @@ abstract class WebServerFileHandler {
     internal val EP_NAME = ExtensionPointName.create<WebServerFileHandler>("org.jetbrains.webServerFileHandler")
   }
 
+  open val pageFileExtensions: Array<String>
+    get() = emptyArray()
+
   /**
    * canonicalRequestPath contains index file name (if not specified in the request)
    */
@@ -34,7 +37,6 @@ abstract class WebServerFileHandler {
                        request: FullHttpRequest,
                        channel: Channel,
                        projectNameIfNotCustomHost: String?): Boolean
-
 }
 
 fun getRequestPath(canonicalPath: CharSequence, projectNameIfNotCustomHost: String?) = if (projectNameIfNotCustomHost == null) "/$canonicalPath" else "/$projectNameIfNotCustomHost/$canonicalPath"
\ No newline at end of file
index 760f54b84becace07c3737539658bfad6f109b8e..fd09296971cd6ebdccd2dbb0d34b082869a66586 100644 (file)
@@ -183,9 +183,11 @@ fun parseAndCheckIsLocalHost(uri: String?, onlyAnyOrLoopback: Boolean = true, ho
   return false
 }
 
+fun HttpRequest.isRegularBrowser() = userAgent?.startsWith("Mozilla/5.0") ?: false
+
 // forbid POST requests from browser without Origin
 fun HttpRequest.isWriteFromBrowserWithoutOrigin(): Boolean {
   val userAgent = userAgent ?: return false
   val method = method()
-  return origin.isNullOrEmpty() && userAgent.startsWith("Mozilla/5.0") && (method == HttpMethod.POST || method == HttpMethod.PATCH || method == HttpMethod.PUT || method == HttpMethod.DELETE)
+  return origin.isNullOrEmpty() && isRegularBrowser() && (method == HttpMethod.POST || method == HttpMethod.PATCH || method == HttpMethod.PUT || method == HttpMethod.DELETE)
 }
\ No newline at end of file