mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
cleanup, JetBrains Academy site as trusted origin for about service
GitOrigin-RevId: 5fd1f46b931d698a3e3d54330757cae3bb87ec81
This commit is contained in:
committed by
intellij-monorepo-bot
parent
60ae273374
commit
8a4659f30d
@@ -27,5 +27,6 @@
|
||||
<orderEntry type="library" name="netty-codec-http" level="project" />
|
||||
<orderEntry type="library" name="fastutil-min" level="project" />
|
||||
<orderEntry type="library" name="Trove4j" level="project" />
|
||||
<orderEntry type="library" name="jackson" level="project" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -66,7 +66,7 @@ class BuiltInWebServer : HttpRequestHandler() {
|
||||
override fun isSupported(request: FullHttpRequest): Boolean = super.isSupported(request) || request.method() == HttpMethod.POST
|
||||
|
||||
override fun process(urlDecoder: QueryStringDecoder, request: FullHttpRequest, context: ChannelHandlerContext): Boolean {
|
||||
var hostName = request.hostName ?: return false
|
||||
var hostName = getHostName(request) ?: return false
|
||||
val projectName: String?
|
||||
val isIpv6 = hostName[0] == '[' && hostName.length > 2 && hostName[hostName.length - 1] == ']'
|
||||
if (isIpv6) {
|
||||
|
||||
@@ -1,21 +1,24 @@
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package org.jetbrains.ide;
|
||||
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package org.jetbrains.ide
|
||||
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
import com.intellij.ide.IdeAboutInfoUtil;
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.application.ex.ApplicationInfoEx;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.fileTypes.FileTypeRegistry;
|
||||
import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.http.FullHttpRequest;
|
||||
import io.netty.handler.codec.http.QueryStringDecoder;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import com.fasterxml.jackson.core.JsonFactory
|
||||
import com.fasterxml.jackson.core.JsonGenerator
|
||||
import com.intellij.openapi.application.ApplicationInfo
|
||||
import com.intellij.openapi.application.ApplicationNamesInfo
|
||||
import com.intellij.openapi.application.PathManager
|
||||
import com.intellij.openapi.application.ex.ApplicationInfoEx
|
||||
import com.intellij.openapi.fileTypes.FileTypeRegistry
|
||||
import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream
|
||||
import com.intellij.util.PlatformUtils
|
||||
import com.intellij.util.io.jackson.array
|
||||
import com.intellij.util.io.jackson.obj
|
||||
import com.intellij.util.io.origin
|
||||
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.QueryStringDecoder
|
||||
import org.jetbrains.ide.RestService.Companion.getBooleanParameter
|
||||
import java.io.OutputStream
|
||||
|
||||
/**
|
||||
* @api {get} /about The application info
|
||||
@@ -35,61 +38,83 @@ import java.io.OutputStream;
|
||||
* @apiSuccess {String} registeredFileTypes.description The user-readable description of the file type.
|
||||
* @apiSuccess {Boolean} registeredFileTypes.isBinary Whether files of the specified type contain binary data.
|
||||
*
|
||||
* * @apiExample Request-Example:
|
||||
* * @apiExample Request-Example:
|
||||
* /rest/about?registeredFileTypes
|
||||
*
|
||||
* @apiUse SuccessExample
|
||||
* @apiUse SuccessExampleWithRegisteredFileTypes
|
||||
*/
|
||||
public class AboutHttpService extends RestService {
|
||||
@NotNull
|
||||
@Override
|
||||
protected String getServiceName() {
|
||||
return "about";
|
||||
internal class AboutHttpService : RestService() {
|
||||
override fun getServiceName() = "about"
|
||||
|
||||
override fun isHostTrusted(request: FullHttpRequest, urlDecoder: QueryStringDecoder): Boolean {
|
||||
return isTrustedOrigin(request) || super.isHostTrusted(request, urlDecoder)
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String execute(@NotNull QueryStringDecoder urlDecoder, @NotNull FullHttpRequest request, @NotNull ChannelHandlerContext context) throws IOException {
|
||||
BufferExposingByteArrayOutputStream byteOut = new BufferExposingByteArrayOutputStream();
|
||||
getAbout(byteOut, urlDecoder);
|
||||
send(byteOut, request, context);
|
||||
return null;
|
||||
override fun isAccessible(request: HttpRequest): Boolean {
|
||||
return isTrustedOrigin(request) || super.isAccessible(request)
|
||||
}
|
||||
|
||||
public static void getAbout(@NotNull OutputStream out, @Nullable QueryStringDecoder urlDecoder) throws IOException {
|
||||
JsonWriter writer = createJsonWriter(out);
|
||||
writer.beginObject();
|
||||
|
||||
IdeAboutInfoUtil.writeAboutJson(writer);
|
||||
|
||||
if (urlDecoder != null && getBooleanParameter("registeredFileTypes", urlDecoder)) {
|
||||
writer.name("registeredFileTypes").beginArray();
|
||||
for (FileType fileType : FileTypeRegistry.getInstance().getRegisteredFileTypes()) {
|
||||
writer.beginObject();
|
||||
writer.name("name").value(fileType.getName());
|
||||
writer.name("description").value(fileType.getDescription());
|
||||
writer.name("isBinary").value(fileType.isBinary());
|
||||
writer.endObject();
|
||||
}
|
||||
writer.endArray();
|
||||
}
|
||||
|
||||
if (urlDecoder != null && getBooleanParameter("more", urlDecoder)) {
|
||||
ApplicationInfoEx appInfo = ApplicationInfoEx.getInstanceEx();
|
||||
writer.name("vendor").value(appInfo.getCompanyName());
|
||||
writer.name("isEAP").value(appInfo.isEAP());
|
||||
writer.name("productCode").value(appInfo.getBuild().getProductCode());
|
||||
writer.name("buildDate").value(appInfo.getBuildDate().getTime().getTime());
|
||||
writer.name("isSnapshot").value(appInfo.getBuild().isSnapshot());
|
||||
writer.name("configPath").value(PathManager.getConfigPath());
|
||||
writer.name("systemPath").value(PathManager.getSystemPath());
|
||||
writer.name("binPath").value(PathManager.getBinPath());
|
||||
writer.name("logPath").value(PathManager.getLogPath());
|
||||
writer.name("homePath").value(PathManager.getHomePath());
|
||||
}
|
||||
|
||||
writer.endObject();
|
||||
writer.close();
|
||||
override fun execute(urlDecoder: QueryStringDecoder, request: FullHttpRequest, context: ChannelHandlerContext): String? {
|
||||
val byteOut = BufferExposingByteArrayOutputStream()
|
||||
writeApplicationInfoJson(byteOut, urlDecoder)
|
||||
send(byteOut, request, context)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
private fun isTrustedOrigin(request: HttpRequest): Boolean {
|
||||
val origin = request.origin ?: return false
|
||||
@Suppress("SpellCheckingInspection")
|
||||
return origin == "hyperskill.org"
|
||||
}
|
||||
|
||||
fun writeApplicationInfoJson(out: OutputStream, urlDecoder: QueryStringDecoder?) {
|
||||
val writer = JsonFactory().createGenerator(out).useDefaultPrettyPrinter()
|
||||
writer.obj {
|
||||
writeAboutJson(writer)
|
||||
if (urlDecoder != null && getBooleanParameter("registeredFileTypes", urlDecoder)) {
|
||||
writer.array("registeredFileTypes") {
|
||||
for (fileType in FileTypeRegistry.getInstance().registeredFileTypes) {
|
||||
writer.obj {
|
||||
writer.writeStringField("name", fileType.name)
|
||||
writer.writeStringField("description", fileType.description)
|
||||
writer.writeBooleanField("isBinary", fileType.isBinary)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (urlDecoder != null && getBooleanParameter("more", urlDecoder)) {
|
||||
val appInfo = ApplicationInfoEx.getInstanceEx()
|
||||
writer.writeStringField("vendor", appInfo.companyName)
|
||||
writer.writeBooleanField("isEAP", appInfo.isEAP)
|
||||
writer.writeStringField("productCode", appInfo.build.productCode)
|
||||
writer.writeNumberField("buildDate", appInfo.buildDate.time.time)
|
||||
writer.writeBooleanField("isSnapshot", appInfo.build.isSnapshot)
|
||||
writer.writeStringField("configPath", PathManager.getConfigPath())
|
||||
writer.writeStringField("systemPath", PathManager.getSystemPath())
|
||||
writer.writeStringField("binPath", PathManager.getBinPath())
|
||||
writer.writeStringField("logPath", PathManager.getLogPath())
|
||||
writer.writeStringField("homePath", PathManager.getHomePath())
|
||||
}
|
||||
}
|
||||
writer.close()
|
||||
}
|
||||
|
||||
fun writeAboutJson(writer: JsonGenerator) {
|
||||
var appName = ApplicationInfoEx.getInstanceEx().fullApplicationName
|
||||
if (!PlatformUtils.isIdeaUltimate()) {
|
||||
val productName = ApplicationNamesInfo.getInstance().productName
|
||||
appName = appName
|
||||
.replace("$productName ($productName)", productName)
|
||||
.removePrefix("JetBrains ")
|
||||
}
|
||||
writer.writeStringField("name", appName)
|
||||
writer.writeStringField("productName", ApplicationNamesInfo.getInstance().productName)
|
||||
|
||||
val build = ApplicationInfo.getInstance().build
|
||||
writer.writeNumberField("baselineVersion", build.baselineVersion)
|
||||
if (!build.isSnapshot) {
|
||||
writer.writeStringField("buildNumber", build.asStringWithoutProductCode())
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package org.jetbrains.ide
|
||||
|
||||
import com.intellij.ide.plugins.marketplace.MarketplaceRequests
|
||||
@@ -10,12 +10,11 @@ import com.intellij.openapi.diagnostic.logger
|
||||
import com.intellij.openapi.extensions.PluginId
|
||||
import com.intellij.openapi.project.ProjectManager
|
||||
import com.intellij.openapi.updateSettings.impl.pluginsAdvertisement.PluginsAdvertiser
|
||||
import com.intellij.openapi.util.BuildNumber
|
||||
import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import com.intellij.ui.AppIcon
|
||||
import com.intellij.util.PlatformUtils
|
||||
import com.intellij.util.io.hostName
|
||||
import com.intellij.util.io.getHostName
|
||||
import com.intellij.util.io.origin
|
||||
import com.intellij.util.net.NetUtils
|
||||
import com.intellij.util.text.nullize
|
||||
@@ -127,7 +126,7 @@ internal class InstallPluginService : RestService() {
|
||||
return false
|
||||
}
|
||||
|
||||
val hostName = request.hostName
|
||||
val hostName = getHostName(request)
|
||||
if (hostName != null && !NetUtils.isLocalhost(hostName)) {
|
||||
LOG.error("Expected 'request.hostName' to be localhost. hostName='$hostName', origin='$origin'")
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package org.jetbrains.ide
|
||||
|
||||
import com.intellij.diagnostic.StartUpPerformanceService
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.application.ex.ApplicationInfoEx
|
||||
import com.intellij.openapi.diagnostic.logger
|
||||
import com.intellij.util.io.hostName
|
||||
import com.intellij.util.io.getHostName
|
||||
import com.intellij.util.io.origin
|
||||
import com.intellij.util.net.NetUtils
|
||||
import io.netty.buffer.Unpooled
|
||||
@@ -45,7 +45,7 @@ internal class StartUpMeasurementService : RestService() {
|
||||
}
|
||||
|
||||
private fun isTrustedHostName(request: HttpRequest): Boolean {
|
||||
val hostName = request.hostName ?: return false
|
||||
val hostName = getHostName(request) ?: return false
|
||||
if (!NetUtils.isLocalhost(hostName)) {
|
||||
LOG.error("Expected 'request.hostName' to be localhost. hostName=$hostName, origin=${request.origin}")
|
||||
}
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.ide;
|
||||
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
import com.intellij.openapi.application.ApplicationInfo;
|
||||
import com.intellij.openapi.application.ApplicationNamesInfo;
|
||||
import com.intellij.openapi.application.ex.ApplicationInfoEx;
|
||||
import com.intellij.openapi.util.BuildNumber;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.PlatformUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public final class IdeAboutInfoUtil {
|
||||
public static void writeAboutJson(JsonWriter writer) throws IOException {
|
||||
String appName = ApplicationInfoEx.getInstanceEx().getFullApplicationName();
|
||||
BuildNumber build = ApplicationInfo.getInstance().getBuild();
|
||||
|
||||
if (!PlatformUtils.isIdeaUltimate()) {
|
||||
String productName = ApplicationNamesInfo.getInstance().getProductName();
|
||||
appName = appName.replace(productName + " (" + productName + ")", productName);
|
||||
appName = StringUtil.trimStart(appName, "JetBrains ");
|
||||
}
|
||||
|
||||
writer.name("name").value(appName);
|
||||
writer.name("productName").value(ApplicationNamesInfo.getInstance().getProductName());
|
||||
writer.name("baselineVersion").value(build.getBaselineVersion());
|
||||
if (!build.isSnapshot()) {
|
||||
writer.name("buildNumber").value(build.asStringWithoutProductCode());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -197,12 +197,11 @@ val Channel.uriScheme: String
|
||||
val HttpRequest.host: String?
|
||||
get() = headers().getAsString(HttpHeaderNames.HOST)
|
||||
|
||||
val HttpRequest.hostName: String?
|
||||
get() {
|
||||
val hostAndPort = headers().getAsString(HttpHeaderNames.HOST)?.ifBlank { null } ?: return null
|
||||
val portIndex = hostAndPort.lastIndexOf(':')
|
||||
return if (portIndex > 0) hostAndPort.substring(0, portIndex).ifBlank { null } else hostAndPort
|
||||
}
|
||||
fun getHostName(httpRequest: HttpRequest): String? {
|
||||
val hostAndPort = httpRequest.headers().getAsString(HttpHeaderNames.HOST)?.ifBlank { null } ?: return null
|
||||
val portIndex = hostAndPort.lastIndexOf(':')
|
||||
return if (portIndex > 0) hostAndPort.substring(0, portIndex).ifBlank { null } else hostAndPort
|
||||
}
|
||||
|
||||
val HttpRequest.origin: String?
|
||||
get() = headers().getAsString(HttpHeaderNames.ORIGIN)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
package org.jetbrains.ide
|
||||
|
||||
import com.intellij.openapi.extensions.ExtensionPointName
|
||||
import com.intellij.util.io.hostName
|
||||
import com.intellij.util.io.getHostName
|
||||
import com.intellij.util.io.isLocalHost
|
||||
import com.intellij.util.io.isLocalOrigin
|
||||
import io.netty.channel.Channel
|
||||
@@ -42,7 +42,7 @@ abstract class HttpRequestHandler {
|
||||
*/
|
||||
@SuppressWarnings("SpellCheckingInspection")
|
||||
open fun isAccessible(request: HttpRequest): Boolean {
|
||||
val hostName = request.hostName
|
||||
val hostName = getHostName(request)
|
||||
// If attacker.com DNS rebound to 127.0.0.1 and user open site directly - no Origin or Referrer headers.
|
||||
// So we should check Host header.
|
||||
return hostName != null && request.isLocalOrigin() && isLocalHost(hostName)
|
||||
|
||||
Reference in New Issue
Block a user