From 771a883e9b82ba1ebfabdc7c636ef01204b019e2 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Thu, 8 Sep 2016 16:17:54 +0200 Subject: [PATCH] some (not a public API) of org.jetbrains.io classes moved to com.intellij.util.io, part 1 --- .../DefaultWebServerPathHandler.kt | 5 +- .../builtInWebServer/WebServerPathHandler.kt | 4 +- .../src/org/jetbrains/ide/RestService.java | 2 +- .../jetbrains/io/fastCgi/FastCgiRequest.kt | 2 +- .../org/jetbrains/io/jsonRpc/JsonRpcServer.kt | 6 +- .../io/webSocket/MessageChannelHandler.java | 5 +- .../util/io}/ChannelBufferToStringTest.kt | 2 +- .../intellij/util/io}/IsLocalHostTest.kt | 2 +- .../ide}/BinaryRequestHandlerTest.kt | 0 .../jetbrains/ide}/BuiltInServerTestCase.kt | 8 +- .../jetbrains/ide}/BuiltInWebServerTest.kt | 0 .../{ => org/jetbrains/ide}/RestApiTest.kt | 0 .../{ => org/jetbrains/ide}/TestManager.kt | 0 .../src/com/intellij/util/io/netty.kt | 131 ++++++++++++++++++ .../jetbrains/io/ChannelBufferToString.java | 4 +- .../io/DelegatingHttpRequestHandler.kt | 3 +- .../src/org/jetbrains/io/netty.kt | 116 +--------------- .../org/jetbrains/jsonProtocol/OutMessage.kt | 24 ++-- 18 files changed, 166 insertions(+), 148 deletions(-) rename platform/built-in-server/testSrc/{ => com/intellij/util/io}/ChannelBufferToStringTest.kt (92%) rename platform/built-in-server/testSrc/{ => com/intellij/util/io}/IsLocalHostTest.kt (97%) rename platform/built-in-server/testSrc/{ => org/jetbrains/ide}/BinaryRequestHandlerTest.kt (100%) rename platform/built-in-server/testSrc/{ => org/jetbrains/ide}/BuiltInServerTestCase.kt (94%) rename platform/built-in-server/testSrc/{ => org/jetbrains/ide}/BuiltInWebServerTest.kt (100%) rename platform/built-in-server/testSrc/{ => org/jetbrains/ide}/RestApiTest.kt (100%) rename platform/built-in-server/testSrc/{ => org/jetbrains/ide}/TestManager.kt (100%) create mode 100644 platform/platform-impl/src/com/intellij/util/io/netty.kt diff --git a/platform/built-in-server/src/org/jetbrains/builtInWebServer/DefaultWebServerPathHandler.kt b/platform/built-in-server/src/org/jetbrains/builtInWebServer/DefaultWebServerPathHandler.kt index 591553e37413..1ff618f41732 100644 --- a/platform/built-in-server/src/org/jetbrains/builtInWebServer/DefaultWebServerPathHandler.kt +++ b/platform/built-in-server/src/org/jetbrains/builtInWebServer/DefaultWebServerPathHandler.kt @@ -25,13 +25,14 @@ import com.intellij.openapi.util.text.StringUtil import com.intellij.openapi.vfs.VFileProperty import com.intellij.openapi.vfs.VirtualFile import com.intellij.util.PathUtilRt -import com.intellij.util.io.isDirectory +import com.intellij.util.io.* import io.netty.channel.Channel import io.netty.channel.ChannelHandlerContext import io.netty.handler.codec.http.FullHttpRequest import io.netty.handler.codec.http.HttpRequest import io.netty.handler.codec.http.HttpResponseStatus -import org.jetbrains.io.* +import org.jetbrains.io.orInSafeMode +import org.jetbrains.io.send import java.nio.file.Path import java.nio.file.Paths import java.util.regex.Pattern diff --git a/platform/built-in-server/src/org/jetbrains/builtInWebServer/WebServerPathHandler.kt b/platform/built-in-server/src/org/jetbrains/builtInWebServer/WebServerPathHandler.kt index 772c9c35a6a1..97189cb23630 100644 --- a/platform/built-in-server/src/org/jetbrains/builtInWebServer/WebServerPathHandler.kt +++ b/platform/built-in-server/src/org/jetbrains/builtInWebServer/WebServerPathHandler.kt @@ -18,13 +18,13 @@ package org.jetbrains.builtInWebServer import com.intellij.openapi.extensions.ExtensionPointName import com.intellij.openapi.project.Project import com.intellij.openapi.vfs.VfsUtil +import com.intellij.util.io.host +import com.intellij.util.io.uriScheme import io.netty.channel.Channel import io.netty.channel.ChannelHandlerContext import io.netty.handler.codec.http.* -import org.jetbrains.io.host import org.jetbrains.io.response import org.jetbrains.io.send -import org.jetbrains.io.uriScheme /** * By default [WebServerPathToFileManager] will be used to map request to file. diff --git a/platform/built-in-server/src/org/jetbrains/ide/RestService.java b/platform/built-in-server/src/org/jetbrains/ide/RestService.java index 1afdbc1bacd7..ba0ff07fe7af 100644 --- a/platform/built-in-server/src/org/jetbrains/ide/RestService.java +++ b/platform/built-in-server/src/org/jetbrains/ide/RestService.java @@ -41,6 +41,7 @@ import com.intellij.openapi.wm.IdeFrame; import com.intellij.util.ExceptionUtil; import com.intellij.util.ObjectUtils; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.io.NettyKt; import com.intellij.util.net.NetUtils; import io.netty.buffer.ByteBufInputStream; import io.netty.buffer.Unpooled; @@ -50,7 +51,6 @@ import io.netty.handler.codec.http.*; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.builtInWebServer.BuiltInWebServerKt; -import org.jetbrains.io.NettyKt; import org.jetbrains.io.Responses; import javax.swing.*; diff --git a/platform/built-in-server/src/org/jetbrains/io/fastCgi/FastCgiRequest.kt b/platform/built-in-server/src/org/jetbrains/io/fastCgi/FastCgiRequest.kt index 35161ea62ed6..1fe1f0f294f0 100644 --- a/platform/built-in-server/src/org/jetbrains/io/fastCgi/FastCgiRequest.kt +++ b/platform/built-in-server/src/org/jetbrains/io/fastCgi/FastCgiRequest.kt @@ -1,6 +1,7 @@ package org.jetbrains.io.fastCgi import com.intellij.openapi.util.io.FileUtil +import com.intellij.util.io.writeUtf8 import io.netty.buffer.ByteBuf import io.netty.buffer.ByteBufAllocator import io.netty.buffer.ByteBufUtil @@ -8,7 +9,6 @@ import io.netty.channel.Channel import io.netty.handler.codec.http.FullHttpRequest import org.jetbrains.builtInWebServer.PathInfo import org.jetbrains.io.serverHeaderValue -import org.jetbrains.io.writeUtf8 import java.net.InetSocketAddress import java.util.* diff --git a/platform/built-in-server/src/org/jetbrains/io/jsonRpc/JsonRpcServer.kt b/platform/built-in-server/src/org/jetbrains/io/jsonRpc/JsonRpcServer.kt index fd48276dbf1d..e59efb3bbe3d 100644 --- a/platform/built-in-server/src/org/jetbrains/io/jsonRpc/JsonRpcServer.kt +++ b/platform/built-in-server/src/org/jetbrains/io/jsonRpc/JsonRpcServer.kt @@ -15,14 +15,14 @@ import com.intellij.util.ArrayUtil import com.intellij.util.ArrayUtilRt import com.intellij.util.Consumer import com.intellij.util.SmartList +import com.intellij.util.io.releaseIfError +import com.intellij.util.io.writeUtf8 import gnu.trove.THashMap import gnu.trove.TIntArrayList import io.netty.buffer.* import org.jetbrains.concurrency.Promise import org.jetbrains.io.JsonReaderEx import org.jetbrains.io.JsonUtil -import org.jetbrains.io.releaseIfError -import org.jetbrains.io.writeUtf8 import java.io.IOException import java.lang.reflect.Method import java.util.concurrent.atomic.AtomicInteger @@ -40,7 +40,7 @@ private val INT_LIST_TYPE_ADAPTER_FACTORY = object : TypeAdapterFactory { if (typeAdapter == null) { typeAdapter = IntArrayListTypeAdapter() } - @Suppress("CAST_NEVER_SUCCEEDS") + @Suppress("UNCHECKED_CAST") return typeAdapter as TypeAdapter? } } diff --git a/platform/built-in-server/src/org/jetbrains/io/webSocket/MessageChannelHandler.java b/platform/built-in-server/src/org/jetbrains/io/webSocket/MessageChannelHandler.java index fe482bc618f1..dc691b1e019e 100644 --- a/platform/built-in-server/src/org/jetbrains/io/webSocket/MessageChannelHandler.java +++ b/platform/built-in-server/src/org/jetbrains/io/webSocket/MessageChannelHandler.java @@ -6,12 +6,13 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame; import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; import org.jetbrains.annotations.NotNull; -import org.jetbrains.io.NettyKt; import org.jetbrains.io.jsonRpc.Client; import org.jetbrains.io.jsonRpc.ClientManager; import org.jetbrains.io.jsonRpc.ClientManagerKt; import org.jetbrains.io.jsonRpc.MessageServer; +import static com.intellij.util.io.NettyKt.readUtf8; + @ChannelHandler.Sharable final class MessageChannelHandler extends WebSocketProtocolHandler { private final ClientManager clientManager; @@ -43,7 +44,7 @@ final class MessageChannelHandler extends WebSocketProtocolHandler { WebSocketClient client = (WebSocketClient)channel.attr(ClientManagerKt.getCLIENT()).get(); CharSequence chars; try { - chars = NettyKt.readUtf8(message.content()); + chars = readUtf8(message.content()); } catch (Throwable e) { try { diff --git a/platform/built-in-server/testSrc/ChannelBufferToStringTest.kt b/platform/built-in-server/testSrc/com/intellij/util/io/ChannelBufferToStringTest.kt similarity index 92% rename from platform/built-in-server/testSrc/ChannelBufferToStringTest.kt rename to platform/built-in-server/testSrc/com/intellij/util/io/ChannelBufferToStringTest.kt index 6948eaab879e..4e5406cb7349 100644 --- a/platform/built-in-server/testSrc/ChannelBufferToStringTest.kt +++ b/platform/built-in-server/testSrc/com/intellij/util/io/ChannelBufferToStringTest.kt @@ -1,4 +1,4 @@ -package org.jetbrains.io +package com.intellij.util.io import io.netty.buffer.Unpooled import org.assertj.core.api.Assertions.assertThat diff --git a/platform/built-in-server/testSrc/IsLocalHostTest.kt b/platform/built-in-server/testSrc/com/intellij/util/io/IsLocalHostTest.kt similarity index 97% rename from platform/built-in-server/testSrc/IsLocalHostTest.kt rename to platform/built-in-server/testSrc/com/intellij/util/io/IsLocalHostTest.kt index 722138936003..bf6c2521df84 100644 --- a/platform/built-in-server/testSrc/IsLocalHostTest.kt +++ b/platform/built-in-server/testSrc/com/intellij/util/io/IsLocalHostTest.kt @@ -1,4 +1,4 @@ -package org.jetbrains.io +package com.intellij.util.io import org.assertj.core.api.Assertions.assertThat import org.junit.Test diff --git a/platform/built-in-server/testSrc/BinaryRequestHandlerTest.kt b/platform/built-in-server/testSrc/org/jetbrains/ide/BinaryRequestHandlerTest.kt similarity index 100% rename from platform/built-in-server/testSrc/BinaryRequestHandlerTest.kt rename to platform/built-in-server/testSrc/org/jetbrains/ide/BinaryRequestHandlerTest.kt diff --git a/platform/built-in-server/testSrc/BuiltInServerTestCase.kt b/platform/built-in-server/testSrc/org/jetbrains/ide/BuiltInServerTestCase.kt similarity index 94% rename from platform/built-in-server/testSrc/BuiltInServerTestCase.kt rename to platform/built-in-server/testSrc/org/jetbrains/ide/BuiltInServerTestCase.kt index 1e84816f1801..af561527be10 100644 --- a/platform/built-in-server/testSrc/BuiltInServerTestCase.kt +++ b/platform/built-in-server/testSrc/org/jetbrains/ide/BuiltInServerTestCase.kt @@ -23,10 +23,10 @@ internal abstract class BuiltInServerTestCase { protected val manager = TestManager(projectRule, tempDirManager) private val ruleChain = RuleChain( - tempDirManager, - Timeout(60, TimeUnit.SECONDS), - manager, - DisposeModulesRule(projectRule)) + tempDirManager, + Timeout(60, TimeUnit.SECONDS), + manager, + DisposeModulesRule(projectRule)) @Rule fun getChain() = ruleChain protected open val urlPathPrefix = "" diff --git a/platform/built-in-server/testSrc/BuiltInWebServerTest.kt b/platform/built-in-server/testSrc/org/jetbrains/ide/BuiltInWebServerTest.kt similarity index 100% rename from platform/built-in-server/testSrc/BuiltInWebServerTest.kt rename to platform/built-in-server/testSrc/org/jetbrains/ide/BuiltInWebServerTest.kt diff --git a/platform/built-in-server/testSrc/RestApiTest.kt b/platform/built-in-server/testSrc/org/jetbrains/ide/RestApiTest.kt similarity index 100% rename from platform/built-in-server/testSrc/RestApiTest.kt rename to platform/built-in-server/testSrc/org/jetbrains/ide/RestApiTest.kt diff --git a/platform/built-in-server/testSrc/TestManager.kt b/platform/built-in-server/testSrc/org/jetbrains/ide/TestManager.kt similarity index 100% rename from platform/built-in-server/testSrc/TestManager.kt rename to platform/built-in-server/testSrc/org/jetbrains/ide/TestManager.kt diff --git a/platform/platform-impl/src/com/intellij/util/io/netty.kt b/platform/platform-impl/src/com/intellij/util/io/netty.kt new file mode 100644 index 000000000000..af269e388b72 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/util/io/netty.kt @@ -0,0 +1,131 @@ +/* + * Copyright 2000-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.util.io + +import com.google.common.net.InetAddresses +import com.intellij.util.Url +import com.intellij.util.Urls +import com.intellij.util.net.NetUtils +import io.netty.buffer.ByteBuf +import io.netty.channel.Channel +import io.netty.handler.codec.http.HttpHeaderNames +import io.netty.handler.codec.http.HttpMethod +import io.netty.handler.codec.http.HttpRequest +import io.netty.handler.ssl.SslHandler +import java.io.IOException +import java.net.InetAddress +import java.net.NetworkInterface + +val Channel.uriScheme: String + get() = if (pipeline().get(SslHandler::class.java) == null) "http" else "https" + +val HttpRequest.host: String? + get() = headers().getAsString(HttpHeaderNames.HOST) + +val HttpRequest.origin: String? + get() = headers().getAsString(HttpHeaderNames.ORIGIN) + +val HttpRequest.referrer: String? + get() = headers().getAsString(HttpHeaderNames.REFERER) + +val HttpRequest.userAgent: String? + get() = headers().getAsString(HttpHeaderNames.USER_AGENT) + +inline fun ByteBuf.releaseIfError(task: () -> T): T { + try { + return task() + } + catch (e: Exception) { + try { + release() + } + finally { + throw e + } + } +} + +fun isLocalHost(host: String, onlyAnyOrLoopback: Boolean, hostsOnly: Boolean = false): Boolean { + if (NetUtils.isLocalhost(host)) { + return true + } + + // if IP address, it is safe to use getByName (not affected by DNS rebinding) + if (onlyAnyOrLoopback && !InetAddresses.isInetAddress(host)) { + return false + } + + fun InetAddress.isLocal() = isAnyLocalAddress || isLoopbackAddress || NetworkInterface.getByInetAddress(this) != null + + try { + val address = InetAddress.getByName(host) + if (!address.isLocal()) { + return false + } + // be aware - on windows hosts file doesn't contain localhost + // hosts can contain remote addresses, so, we check it + if (hostsOnly && !InetAddresses.isInetAddress(host)) { + return io.netty.resolver.HostsFileEntriesResolver.DEFAULT.address(host).let { it != null && it.isLocal() } + } + else { + return true + } + } + catch (ignored: IOException) { + return false + } +} + +@JvmOverloads +fun HttpRequest.isLocalOrigin(onlyAnyOrLoopback: Boolean = true, hostsOnly: Boolean = false) = parseAndCheckIsLocalHost(origin, onlyAnyOrLoopback, hostsOnly) && parseAndCheckIsLocalHost(referrer, onlyAnyOrLoopback, hostsOnly) + +private fun isTrustedChromeExtension(url: Url): Boolean { + return url.scheme == "chrome-extension" && (url.authority == "hmhgeddbohgjknpmjagkdomcpobmllji" || url.authority == "offnedcbhjldheanlbojaefbfbllddna") +} + +private val Url.host: String? + get() = authority?.let { + val portIndex = it.indexOf(':') + if (portIndex > 0) it.substring(0, portIndex) else it + } + +@JvmOverloads +fun parseAndCheckIsLocalHost(uri: String?, onlyAnyOrLoopback: Boolean = true, hostsOnly: Boolean = false): Boolean { + if (uri == null || uri == "about:blank") { + return true + } + + try { + val parsedUri = Urls.parse(uri, false) ?: return false + val host = parsedUri.host + return host != null && (isTrustedChromeExtension(parsedUri) || isLocalHost(host, onlyAnyOrLoopback, hostsOnly)) + } + catch (ignored: Exception) { + } + return false +} + +fun HttpRequest.isRegularBrowser() = userAgent?.startsWith("Mozilla/5.0") ?: false + +// forbid POST requests from browser without Origin +fun HttpRequest.isWriteFromBrowserWithoutOrigin(): Boolean { + val method = method() + return origin.isNullOrEmpty() && isRegularBrowser() && (method == HttpMethod.POST || method == HttpMethod.PATCH || method == HttpMethod.PUT || method == HttpMethod.DELETE) +} + +fun ByteBuf.readUtf8() = toString(Charsets.UTF_8) + +fun ByteBuf.writeUtf8(data: CharSequence) = writeCharSequence(data, Charsets.UTF_8) \ No newline at end of file diff --git a/platform/platform-impl/src/org/jetbrains/io/ChannelBufferToString.java b/platform/platform-impl/src/org/jetbrains/io/ChannelBufferToString.java index bb2878d332fd..83da1f70f73b 100644 --- a/platform/platform-impl/src/org/jetbrains/io/ChannelBufferToString.java +++ b/platform/platform-impl/src/org/jetbrains/io/ChannelBufferToString.java @@ -20,11 +20,13 @@ import org.jetbrains.annotations.NotNull; import java.io.IOException; +import static com.intellij.util.io.NettyKt.readUtf8; + @SuppressWarnings("unused") @Deprecated public final class ChannelBufferToString { @NotNull public static CharSequence readChars(@NotNull ByteBuf buffer) throws IOException { - return NettyKt.readUtf8(buffer); + return readUtf8(buffer); } } diff --git a/platform/platform-impl/src/org/jetbrains/io/DelegatingHttpRequestHandler.kt b/platform/platform-impl/src/org/jetbrains/io/DelegatingHttpRequestHandler.kt index ee17b364b0d7..1ef83fc23726 100644 --- a/platform/platform-impl/src/org/jetbrains/io/DelegatingHttpRequestHandler.kt +++ b/platform/platform-impl/src/org/jetbrains/io/DelegatingHttpRequestHandler.kt @@ -18,6 +18,7 @@ package org.jetbrains.io import com.intellij.openapi.application.ex.ApplicationInfoEx import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.util.IconLoader +import com.intellij.util.io.isWriteFromBrowserWithoutOrigin import com.intellij.util.ui.UIUtil import io.netty.buffer.Unpooled import io.netty.channel.ChannelHandler @@ -82,7 +83,7 @@ internal class DelegatingHttpRequestHandler : DelegatingHttpRequestHandlerBase() @Suppress("OverridingDeprecatedMember") override fun exceptionCaught(context: ChannelHandlerContext, cause: Throwable) { try { - context.channel().attr(PREV_HANDLER).remove() + context.channel().attr(PREV_HANDLER).set(null) } finally { @Suppress("DEPRECATION") diff --git a/platform/platform-impl/src/org/jetbrains/io/netty.kt b/platform/platform-impl/src/org/jetbrains/io/netty.kt index 4642a40a243f..07da533be89c 100644 --- a/platform/platform-impl/src/org/jetbrains/io/netty.kt +++ b/platform/platform-impl/src/org/jetbrains/io/netty.kt @@ -15,33 +15,20 @@ */ package org.jetbrains.io -import com.google.common.net.InetAddresses import com.intellij.openapi.util.Condition import com.intellij.openapi.util.Conditions -import com.intellij.util.Url -import com.intellij.util.Urls -import com.intellij.util.net.NetUtils import io.netty.bootstrap.Bootstrap import io.netty.bootstrap.ServerBootstrap -import io.netty.buffer.ByteBuf import io.netty.channel.* import io.netty.channel.nio.NioEventLoopGroup import io.netty.channel.oio.OioEventLoopGroup import io.netty.channel.socket.nio.NioServerSocketChannel import io.netty.channel.socket.oio.OioServerSocketChannel import io.netty.channel.socket.oio.OioSocketChannel -import io.netty.handler.codec.http.HttpHeaderNames -import io.netty.handler.codec.http.HttpMethod -import io.netty.handler.codec.http.HttpRequest -import io.netty.handler.ssl.SslHandler -import io.netty.resolver.HostsFileEntriesResolver import io.netty.util.concurrent.GenericFutureListener import org.jetbrains.concurrency.AsyncPromise import org.jetbrains.ide.PooledThreadExecutor -import java.io.IOException -import java.net.InetAddress import java.net.InetSocketAddress -import java.net.NetworkInterface import java.util.concurrent.TimeUnit inline fun Bootstrap.handler(crossinline task: (Channel) -> Unit): Bootstrap { @@ -99,105 +86,4 @@ fun Bootstrap.connect(remoteAddress: InetSocketAddress, promise: AsyncPromise<*> promise?.setError(e) return null } -} - -val Channel.uriScheme: String - get() = if (pipeline().get(SslHandler::class.java) == null) "http" else "https" - -val HttpRequest.host: String? - get() = headers().getAsString(HttpHeaderNames.HOST) - -val HttpRequest.origin: String? - get() = headers().getAsString(HttpHeaderNames.ORIGIN) - -val HttpRequest.referrer: String? - get() = headers().getAsString(HttpHeaderNames.REFERER) - -val HttpRequest.userAgent: String? - get() = headers().getAsString(HttpHeaderNames.USER_AGENT) - -inline fun ByteBuf.releaseIfError(task: () -> T): T { - try { - return task() - } - catch (e: Exception) { - try { - release() - } - finally { - throw e - } - } -} - -fun isLocalHost(host: String, onlyAnyOrLoopback: Boolean, hostsOnly: Boolean = false): Boolean { - if (NetUtils.isLocalhost(host)) { - return true - } - - // if IP address, it is safe to use getByName (not affected by DNS rebinding) - if (onlyAnyOrLoopback && !InetAddresses.isInetAddress(host)) { - return false - } - - fun InetAddress.isLocal() = isAnyLocalAddress || isLoopbackAddress || NetworkInterface.getByInetAddress(this) != null - - try { - val address = InetAddress.getByName(host) - if (!address.isLocal()) { - return false - } - // be aware - on windows hosts file doesn't contain localhost - // hosts can contain remote addresses, so, we check it - if (hostsOnly && !InetAddresses.isInetAddress(host)) { - return HostsFileEntriesResolver.DEFAULT.address(host).let { it != null && it.isLocal() } - } - else { - return true - } - } - catch (ignored: IOException) { - return false - } -} - -@JvmOverloads -fun HttpRequest.isLocalOrigin(onlyAnyOrLoopback: Boolean = true, hostsOnly: Boolean = false) = parseAndCheckIsLocalHost(origin, onlyAnyOrLoopback, hostsOnly) && parseAndCheckIsLocalHost(referrer, onlyAnyOrLoopback, hostsOnly) - -private fun isTrustedChromeExtension(url: Url): Boolean { - return url.scheme == "chrome-extension" && (url.authority == "hmhgeddbohgjknpmjagkdomcpobmllji" || url.authority == "offnedcbhjldheanlbojaefbfbllddna") -} - -private val Url.host: String? - get() = authority?.let { - val portIndex = it.indexOf(':') - if (portIndex > 0) it.substring(0, portIndex) else it - } - -@JvmOverloads -fun parseAndCheckIsLocalHost(uri: String?, onlyAnyOrLoopback: Boolean = true, hostsOnly: Boolean = false): Boolean { - if (uri == null || uri == "about:blank") { - return true - } - - try { - val parsedUri = Urls.parse(uri, false) ?: return false - val host = parsedUri.host - return host != null && (isTrustedChromeExtension(parsedUri) || isLocalHost(host, onlyAnyOrLoopback, hostsOnly)) - } - catch (ignored: Exception) { - } - return false -} - -fun HttpRequest.isRegularBrowser() = userAgent?.startsWith("Mozilla/5.0") ?: false - -// forbid POST requests from browser without Origin -fun HttpRequest.isWriteFromBrowserWithoutOrigin(): Boolean { - val method = method() - return origin.isNullOrEmpty() && isRegularBrowser() && (method == HttpMethod.POST || method == HttpMethod.PATCH || method == HttpMethod.PUT || method == HttpMethod.DELETE) -} - -fun ByteBuf.readUtf8() = toString(Charsets.UTF_8) - -fun ByteBuf.writeUtf8(data: CharSequence) = writeCharSequence(data, Charsets.UTF_8) \ No newline at end of file +} \ No newline at end of file diff --git a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/OutMessage.kt b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/OutMessage.kt index 31f8c204d278..318bf2743481 100644 --- a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/OutMessage.kt +++ b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/OutMessage.kt @@ -18,14 +18,13 @@ package org.jetbrains.jsonProtocol import com.google.gson.stream.JsonWriter import com.intellij.openapi.vfs.CharsetToolkit import com.intellij.util.containers.isNullOrEmpty +import com.intellij.util.io.writeUtf8 import gnu.trove.TIntArrayList import gnu.trove.TIntHashSet import io.netty.buffer.ByteBuf import io.netty.buffer.ByteBufAllocator import io.netty.buffer.ByteBufUtf8Writer import org.jetbrains.io.JsonUtil -import org.jetbrains.io.writeUtf8 -import java.io.IOException open class OutMessage() { val buffer: ByteBuf = ByteBufAllocator.DEFAULT.heapBuffer() @@ -204,19 +203,16 @@ open class OutMessage() { beginArguments() writer.name(name).value(value?.toString() ?: null) } +} - companion object { - @Throws(IOException::class) - fun prepareWriteRaw(message: OutMessage, name: String) { - message.writer.name(name).nullValue() - val itemBuffer = message.buffer - itemBuffer.writerIndex(itemBuffer.writerIndex() - "null".length) - } +fun prepareWriteRaw(message: OutMessage, name: String) { + message.writer.name(name).nullValue() + val itemBuffer = message.buffer + itemBuffer.writerIndex(itemBuffer.writerIndex() - "null".length) +} - fun doWriteRaw(message: OutMessage, rawValue: String) { - message.buffer.writeUtf8(rawValue) - } - } +fun doWriteRaw(message: OutMessage, rawValue: String) { + message.buffer.writeUtf8(rawValue) } fun OutMessage.writeEnum(name: String, value: Enum<*>?, defaultValue: Enum<*>?) { @@ -238,7 +234,7 @@ fun OutMessage.writeString(name: String, value: CharSequence?, defaultValue: Cha fun OutMessage.writeString(name: String, value: CharSequence) { beginArguments() - OutMessage.prepareWriteRaw(this, name) + prepareWriteRaw(this, name) JsonUtil.escape(value, buffer) }