mirror of
https://github.com/github/codeql.git
synced 2026-04-27 17:55:19 +02:00
[Java] CWE-348: Use of less trusted source
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
@Controller
|
||||
public class UseOfLessTrustedSource {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(UseOfLessTrustedSource.class);
|
||||
|
||||
@GetMapping(value = "bad1")
|
||||
@ResponseBody
|
||||
public String bad1(HttpServletRequest request) {
|
||||
String remoteAddr = "";
|
||||
if (request != null) {
|
||||
remoteAddr = request.getHeader("X-FORWARDED-FOR");
|
||||
remoteAddr = remoteAddr.split(",")[0];
|
||||
if (remoteAddr == null || "".equals(remoteAddr)) {
|
||||
remoteAddr = request.getRemoteAddr();
|
||||
}
|
||||
}
|
||||
return remoteAddr;
|
||||
}
|
||||
|
||||
@GetMapping(value = "bad2")
|
||||
public void bad2(HttpServletRequest request) {
|
||||
String ip = request.getHeader("X-Forwarded-For");
|
||||
|
||||
log.debug("getClientIP header X-Forwarded-For:{}", ip);
|
||||
|
||||
if (StringUtils.isBlank(ip) || StringUtils.equalsIgnoreCase("unknown", ip)) {
|
||||
ip = request.getHeader("Proxy-Client-IP");
|
||||
log.debug("getClientIP header Proxy-Client-IP:{}", ip);
|
||||
}
|
||||
if (StringUtils.isBlank(ip) || StringUtils.equalsIgnoreCase("unknown", ip)) {
|
||||
ip = request.getHeader("WL-Proxy-Client-IP");
|
||||
log.debug("getClientIP header WL-Proxy-Client-IP:{}", ip);
|
||||
}
|
||||
if (StringUtils.isBlank(ip) || StringUtils.equalsIgnoreCase("unknown", ip)) {
|
||||
ip = request.getHeader("HTTP_CLIENT_IP");
|
||||
log.debug("getClientIP header HTTP_CLIENT_IP:{}", ip);
|
||||
}
|
||||
if (StringUtils.isBlank(ip) || StringUtils.equalsIgnoreCase("unknown", ip)) {
|
||||
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
|
||||
log.debug("getClientIP header HTTP_X_FORWARDED_FOR:{}", ip);
|
||||
}
|
||||
if (StringUtils.isBlank(ip) || StringUtils.equalsIgnoreCase("unknown", ip)) {
|
||||
ip = request.getHeader("X-Real-IP");
|
||||
log.debug("getClientIP header X-Real-IP:{}", ip);
|
||||
}
|
||||
if (StringUtils.isBlank(ip) || StringUtils.equalsIgnoreCase("unknown", ip)) {
|
||||
ip = request.getRemoteAddr();
|
||||
log.debug("getRemoteAddr IP:{}", ip);
|
||||
}
|
||||
System.out.println("client ip is: " + ip);
|
||||
}
|
||||
|
||||
@GetMapping(value = "good1")
|
||||
@ResponseBody
|
||||
public String good1(HttpServletRequest request) {
|
||||
String remoteAddr = "";
|
||||
if (request != null) {
|
||||
remoteAddr = request.getHeader("X-FORWARDED-FOR");
|
||||
remoteAddr = remoteAddr.split(",")[remoteAddr.split(",").length - 1]; // good
|
||||
if (remoteAddr == null || "".equals(remoteAddr)) {
|
||||
remoteAddr = request.getRemoteAddr();
|
||||
}
|
||||
}
|
||||
return remoteAddr;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>The software obtains the original client IP address through the http header <code>X-Forwarded-For</code>, which is used to ensure
|
||||
security or track it in the log for statistical or other reasons. Attackers can use <code>X-Forwarded-For </code> Spoofing software.</p>
|
||||
|
||||
</overview>
|
||||
<recommendation>
|
||||
|
||||
<p>When the software is not using a proxy server, get the last ip.</p>
|
||||
|
||||
</recommendation>
|
||||
<example>
|
||||
|
||||
<p>The following examples show the bad case and the good case respectively. Bad case, such as <code>bad1</code> to <code>bad2</code>.
|
||||
In the <code>bad1</code> method, the value of <code>X-Forwarded-For</code> in <code>header</code> is split, and the first value of
|
||||
the split array is obtained. Good case, such as <code>good1</code>, split the value of <code>X-Forwarded-For</code> in <code>header</code>
|
||||
and get the last value of the split array.</p>
|
||||
|
||||
<sample src="UseOfLessTrustedSource.java" />
|
||||
|
||||
</example>
|
||||
<references>
|
||||
|
||||
<li>Prevent IP address spoofing with X-Forwarded-For header when using AWS ELB and Clojure Ring:
|
||||
<a href="https://www.dennis-schneider.com/blog/prevent-ip-address-spoofing-with-x-forwarded-for-header-and-aws-elb-in-clojure-ring/">
|
||||
Prevent IP address spoofing with...</a>
|
||||
</li>
|
||||
|
||||
<li>Security Rule Zero: A Warning about X-Forwarded-For:
|
||||
<a href="https://www.f5.com/company/blog/security-rule-zero-a-warning-about-x-forwarded-for">
|
||||
Security Rule Zero: A Warning about X-Forwarded-For</a>
|
||||
</li>
|
||||
|
||||
</references>
|
||||
</qhelp>
|
||||
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* @name X-Forwarded-For spoofing
|
||||
* @description The software obtains the client ip through `X-Forwarded-For`,
|
||||
* and the attacker can modify the value of `X-Forwarded-For` to forge the ip.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @precision high
|
||||
* @id java/use-of-less-trusted-source
|
||||
* @tags security
|
||||
* external/cwe/cwe-348
|
||||
*/
|
||||
|
||||
import java
|
||||
import UseOfLessTrustedSourceLib
|
||||
import semmle.code.java.dataflow.FlowSources
|
||||
import DataFlow::PathGraph
|
||||
|
||||
class UseOfLessTrustedSourceConfig extends TaintTracking::Configuration {
|
||||
UseOfLessTrustedSourceConfig() { this = "UseOfLessTrustedSourceConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { source instanceof UseOfLessTrustedSource }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { sink instanceof UseOfLessTrustedSink }
|
||||
|
||||
/**
|
||||
* When using `,` split request data and not taking the first value of
|
||||
* the array, it is considered as `good`.
|
||||
*/
|
||||
override predicate isSanitizer(DataFlow::Node node) {
|
||||
exists(ArrayAccess aa, MethodAccess ma | aa.getArray() = ma |
|
||||
ma.getQualifier() = node.asExpr() and
|
||||
ma.getMethod() instanceof SplitMethod and
|
||||
not aa.getIndexExpr().toString() = "0"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
from DataFlow::PathNode source, DataFlow::PathNode sink, UseOfLessTrustedSourceConfig conf
|
||||
where
|
||||
conf.hasFlowPath(source, sink) and
|
||||
source.getNode().getEnclosingCallable() = sink.getNode().getEnclosingCallable() and
|
||||
xffIsFirstGet(source.getNode())
|
||||
select sink.getNode(), source, sink, "X-Forwarded-For spoofing might include code from $@.",
|
||||
source.getNode(), "this user input"
|
||||
@@ -0,0 +1,88 @@
|
||||
import java
|
||||
import DataFlow
|
||||
import semmle.code.java.dataflow.DataFlow
|
||||
import experimental.semmle.code.java.Logging
|
||||
|
||||
/** A data flow source of the value of the `x-forwarded-for` field in the `header`. */
|
||||
class UseOfLessTrustedSource extends DataFlow::Node {
|
||||
UseOfLessTrustedSource() {
|
||||
exists(MethodAccess ma |
|
||||
ma.getMethod().hasName("getHeader") and
|
||||
ma.getArgument(0).toString().toLowerCase() = "\"x-forwarded-for\"" and
|
||||
ma = this.asExpr()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** A data flow sink of method return or log output or local print. */
|
||||
class UseOfLessTrustedSink extends DataFlow::Node {
|
||||
UseOfLessTrustedSink() {
|
||||
exists(ReturnStmt rs | rs.getResult() = this.asExpr())
|
||||
or
|
||||
exists(MethodAccess ma |
|
||||
ma.getMethod().getName() in ["print", "println"] and
|
||||
(
|
||||
ma.getMethod().getDeclaringType().hasQualifiedName("java.io", "PrintWriter") or
|
||||
ma.getMethod().getDeclaringType().hasQualifiedName("java.io", "PrintStream")
|
||||
) and
|
||||
ma.getAnArgument() = this.asExpr()
|
||||
)
|
||||
or
|
||||
exists(LoggingCall lc | lc.getAnArgument() = this.asExpr())
|
||||
}
|
||||
}
|
||||
|
||||
/** A method that split string. */
|
||||
class SplitMethod extends Method {
|
||||
SplitMethod() {
|
||||
this.getNumberOfParameters() = 1 and
|
||||
this.hasQualifiedName("java.lang", "String", "split")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the ServletRequest.getHeader method and the argument are
|
||||
* `wl-proxy-client-ip`/`proxy-client-ip`/`http_client_ip`/`http_x_forwarded_for`/`x-real-ip`.
|
||||
*/
|
||||
class HeaderIpCall extends MethodAccess {
|
||||
HeaderIpCall() {
|
||||
this.getMethod().hasName("getHeader") and
|
||||
this.getMethod()
|
||||
.getDeclaringType()
|
||||
.getASupertype*()
|
||||
.hasQualifiedName("javax.servlet", "ServletRequest") and
|
||||
this.getArgument(0).toString().toLowerCase() in [
|
||||
"\"wl-proxy-client-ip\"", "\"proxy-client-ip\"", "\"http_client_ip\"",
|
||||
"\"http_x_forwarded_for\"", "\"x-real-ip\""
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/** A call to `ServletRequest.getRemoteAddr` method. */
|
||||
class RemoteAddrCall extends MethodAccess {
|
||||
RemoteAddrCall() {
|
||||
this.getMethod().hasName("getRemoteAddr") and
|
||||
this.getMethod()
|
||||
.getDeclaringType()
|
||||
.getASupertype*()
|
||||
.hasQualifiedName("javax.servlet", "ServletRequest")
|
||||
}
|
||||
}
|
||||
|
||||
/** The first one in the method to get the ip value through `x-forwarded-for`. */
|
||||
predicate xffIsFirstGet(Node node) {
|
||||
exists(HeaderIpCall hic |
|
||||
node.getEnclosingCallable() = hic.getEnclosingCallable() and
|
||||
node.getLocation().getEndLine() < hic.getLocation().getEndLine()
|
||||
)
|
||||
or
|
||||
exists(RemoteAddrCall rac |
|
||||
node.getEnclosingCallable() = rac.getEnclosingCallable() and
|
||||
node.getLocation().getEndLine() < rac.getLocation().getEndLine()
|
||||
)
|
||||
or
|
||||
not exists(HeaderIpCall hic, RemoteAddrCall rac |
|
||||
node.getEnclosingCallable() = hic.getEnclosingCallable() and
|
||||
node.getEnclosingCallable() = rac.getEnclosingCallable()
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
edges
|
||||
| UseOfLessTrustedSource.java:19:26:19:61 | getHeader(...) : String | UseOfLessTrustedSource.java:25:16:25:25 | remoteAddr |
|
||||
| UseOfLessTrustedSource.java:30:21:30:56 | getHeader(...) : String | UseOfLessTrustedSource.java:32:60:32:61 | ip |
|
||||
| UseOfLessTrustedSource.java:30:21:30:56 | getHeader(...) : String | UseOfLessTrustedSource.java:58:28:58:48 | ... + ... |
|
||||
nodes
|
||||
| UseOfLessTrustedSource.java:19:26:19:61 | getHeader(...) : String | semmle.label | getHeader(...) : String |
|
||||
| UseOfLessTrustedSource.java:25:16:25:25 | remoteAddr | semmle.label | remoteAddr |
|
||||
| UseOfLessTrustedSource.java:30:21:30:56 | getHeader(...) : String | semmle.label | getHeader(...) : String |
|
||||
| UseOfLessTrustedSource.java:32:60:32:61 | ip | semmle.label | ip |
|
||||
| UseOfLessTrustedSource.java:58:28:58:48 | ... + ... | semmle.label | ... + ... |
|
||||
#select
|
||||
| UseOfLessTrustedSource.java:25:16:25:25 | remoteAddr | UseOfLessTrustedSource.java:19:26:19:61 | getHeader(...) : String | UseOfLessTrustedSource.java:25:16:25:25 | remoteAddr | X-Forwarded-For spoofing might include code from $@. | UseOfLessTrustedSource.java:19:26:19:61 | getHeader(...) | this user input |
|
||||
| UseOfLessTrustedSource.java:32:60:32:61 | ip | UseOfLessTrustedSource.java:30:21:30:56 | getHeader(...) : String | UseOfLessTrustedSource.java:32:60:32:61 | ip | X-Forwarded-For spoofing might include code from $@. | UseOfLessTrustedSource.java:30:21:30:56 | getHeader(...) | this user input |
|
||||
| UseOfLessTrustedSource.java:58:28:58:48 | ... + ... | UseOfLessTrustedSource.java:30:21:30:56 | getHeader(...) : String | UseOfLessTrustedSource.java:58:28:58:48 | ... + ... | X-Forwarded-For spoofing might include code from $@. | UseOfLessTrustedSource.java:30:21:30:56 | getHeader(...) | this user input |
|
||||
@@ -0,0 +1,74 @@
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
@Controller
|
||||
public class UseOfLessTrustedSource {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(UseOfLessTrustedSource.class);
|
||||
|
||||
@GetMapping(value = "bad1")
|
||||
@ResponseBody
|
||||
public String bad1(HttpServletRequest request) {
|
||||
String remoteAddr = "";
|
||||
if (request != null) {
|
||||
remoteAddr = request.getHeader("X-FORWARDED-FOR");
|
||||
remoteAddr = remoteAddr.split(",")[0];
|
||||
if (remoteAddr == null || "".equals(remoteAddr)) {
|
||||
remoteAddr = request.getRemoteAddr();
|
||||
}
|
||||
}
|
||||
return remoteAddr;
|
||||
}
|
||||
|
||||
@GetMapping(value = "bad2")
|
||||
public void bad2(HttpServletRequest request) {
|
||||
String ip = request.getHeader("X-Forwarded-For");
|
||||
|
||||
log.debug("getClientIP header X-Forwarded-For:{}", ip);
|
||||
|
||||
if (StringUtils.isBlank(ip) || StringUtils.equalsIgnoreCase("unknown", ip)) {
|
||||
ip = request.getHeader("Proxy-Client-IP");
|
||||
log.debug("getClientIP header Proxy-Client-IP:{}", ip);
|
||||
}
|
||||
if (StringUtils.isBlank(ip) || StringUtils.equalsIgnoreCase("unknown", ip)) {
|
||||
ip = request.getHeader("WL-Proxy-Client-IP");
|
||||
log.debug("getClientIP header WL-Proxy-Client-IP:{}", ip);
|
||||
}
|
||||
if (StringUtils.isBlank(ip) || StringUtils.equalsIgnoreCase("unknown", ip)) {
|
||||
ip = request.getHeader("HTTP_CLIENT_IP");
|
||||
log.debug("getClientIP header HTTP_CLIENT_IP:{}", ip);
|
||||
}
|
||||
if (StringUtils.isBlank(ip) || StringUtils.equalsIgnoreCase("unknown", ip)) {
|
||||
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
|
||||
log.debug("getClientIP header HTTP_X_FORWARDED_FOR:{}", ip);
|
||||
}
|
||||
if (StringUtils.isBlank(ip) || StringUtils.equalsIgnoreCase("unknown", ip)) {
|
||||
ip = request.getHeader("X-Real-IP");
|
||||
log.debug("getClientIP header X-Real-IP:{}", ip);
|
||||
}
|
||||
if (StringUtils.isBlank(ip) || StringUtils.equalsIgnoreCase("unknown", ip)) {
|
||||
ip = request.getRemoteAddr();
|
||||
log.debug("getRemoteAddr IP:{}", ip);
|
||||
}
|
||||
System.out.println("client ip is: " + ip);
|
||||
}
|
||||
|
||||
@GetMapping(value = "good1")
|
||||
@ResponseBody
|
||||
public String good1(HttpServletRequest request) {
|
||||
String remoteAddr = "";
|
||||
if (request != null) {
|
||||
remoteAddr = request.getHeader("X-FORWARDED-FOR");
|
||||
remoteAddr = remoteAddr.split(",")[remoteAddr.split(",").length - 1]; // good
|
||||
if (remoteAddr == null || "".equals(remoteAddr)) {
|
||||
remoteAddr = request.getRemoteAddr();
|
||||
}
|
||||
}
|
||||
return remoteAddr;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
experimental/Security/CWE/CWE-348/UseOfLessTrustedSource.ql
|
||||
@@ -0,0 +1,2 @@
|
||||
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/servlet-api-2.4:${testdir}/../../../../stubs/springframework-5.2.3/:${tes
|
||||
tdir}/../../../../stubs/slf4j-api-1.6.4/:${testdir}/../../../../stubs/apache-commons-lang3-3.7/
|
||||
127
java/ql/test/stubs/slf4j-api-1.6.4/org/slf4j/Logger.java
Normal file
127
java/ql/test/stubs/slf4j-api-1.6.4/org/slf4j/Logger.java
Normal file
@@ -0,0 +1,127 @@
|
||||
package org.slf4j;
|
||||
|
||||
public interface Logger {
|
||||
String ROOT_LOGGER_NAME = "ROOT";
|
||||
|
||||
String getName();
|
||||
|
||||
boolean isTraceEnabled();
|
||||
|
||||
void trace(String var1);
|
||||
|
||||
void trace(String var1, Object var2);
|
||||
|
||||
void trace(String var1, Object var2, Object var3);
|
||||
|
||||
void trace(String var1, Object[] var2);
|
||||
|
||||
void trace(String var1, Throwable var2);
|
||||
|
||||
boolean isTraceEnabled(Marker var1);
|
||||
|
||||
void trace(Marker var1, String var2);
|
||||
|
||||
void trace(Marker var1, String var2, Object var3);
|
||||
|
||||
void trace(Marker var1, String var2, Object var3, Object var4);
|
||||
|
||||
void trace(Marker var1, String var2, Object[] var3);
|
||||
|
||||
void trace(Marker var1, String var2, Throwable var3);
|
||||
|
||||
boolean isDebugEnabled();
|
||||
|
||||
void debug(String var1);
|
||||
|
||||
void debug(String var1, Object var2);
|
||||
|
||||
void debug(String var1, Object var2, Object var3);
|
||||
|
||||
void debug(String var1, Object[] var2);
|
||||
|
||||
void debug(String var1, Throwable var2);
|
||||
|
||||
boolean isDebugEnabled(Marker var1);
|
||||
|
||||
void debug(Marker var1, String var2);
|
||||
|
||||
void debug(Marker var1, String var2, Object var3);
|
||||
|
||||
void debug(Marker var1, String var2, Object var3, Object var4);
|
||||
|
||||
void debug(Marker var1, String var2, Object[] var3);
|
||||
|
||||
void debug(Marker var1, String var2, Throwable var3);
|
||||
|
||||
boolean isInfoEnabled();
|
||||
|
||||
void info(String var1);
|
||||
|
||||
void info(String var1, Object var2);
|
||||
|
||||
void info(String var1, Object var2, Object var3);
|
||||
|
||||
void info(String var1, Object[] var2);
|
||||
|
||||
void info(String var1, Throwable var2);
|
||||
|
||||
boolean isInfoEnabled(Marker var1);
|
||||
|
||||
void info(Marker var1, String var2);
|
||||
|
||||
void info(Marker var1, String var2, Object var3);
|
||||
|
||||
void info(Marker var1, String var2, Object var3, Object var4);
|
||||
|
||||
void info(Marker var1, String var2, Object[] var3);
|
||||
|
||||
void info(Marker var1, String var2, Throwable var3);
|
||||
|
||||
boolean isWarnEnabled();
|
||||
|
||||
void warn(String var1);
|
||||
|
||||
void warn(String var1, Object var2);
|
||||
|
||||
void warn(String var1, Object[] var2);
|
||||
|
||||
void warn(String var1, Object var2, Object var3);
|
||||
|
||||
void warn(String var1, Throwable var2);
|
||||
|
||||
boolean isWarnEnabled(Marker var1);
|
||||
|
||||
void warn(Marker var1, String var2);
|
||||
|
||||
void warn(Marker var1, String var2, Object var3);
|
||||
|
||||
void warn(Marker var1, String var2, Object var3, Object var4);
|
||||
|
||||
void warn(Marker var1, String var2, Object[] var3);
|
||||
|
||||
void warn(Marker var1, String var2, Throwable var3);
|
||||
|
||||
boolean isErrorEnabled();
|
||||
|
||||
void error(String var1);
|
||||
|
||||
void error(String var1, Object var2);
|
||||
|
||||
void error(String var1, Object var2, Object var3);
|
||||
|
||||
void error(String var1, Object[] var2);
|
||||
|
||||
void error(String var1, Throwable var2);
|
||||
|
||||
boolean isErrorEnabled(Marker var1);
|
||||
|
||||
void error(Marker var1, String var2);
|
||||
|
||||
void error(Marker var1, String var2, Object var3);
|
||||
|
||||
void error(Marker var1, String var2, Object var3, Object var4);
|
||||
|
||||
void error(Marker var1, String var2, Object[] var3);
|
||||
|
||||
void error(Marker var1, String var2, Throwable var3);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package org.slf4j;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.Arrays;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
|
||||
public final class LoggerFactory {
|
||||
|
||||
public static Logger getLogger(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Logger getLogger(Class clazz) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
30
java/ql/test/stubs/slf4j-api-1.6.4/org/slf4j/Marker.java
Normal file
30
java/ql/test/stubs/slf4j-api-1.6.4/org/slf4j/Marker.java
Normal file
@@ -0,0 +1,30 @@
|
||||
package org.slf4j;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Iterator;
|
||||
|
||||
public interface Marker extends Serializable {
|
||||
String ANY_MARKER = "*";
|
||||
String ANY_NON_NULL_MARKER = "+";
|
||||
|
||||
String getName();
|
||||
|
||||
void add(Marker var1);
|
||||
|
||||
boolean remove(Marker var1);
|
||||
|
||||
/** @deprecated */
|
||||
boolean hasChildren();
|
||||
|
||||
boolean hasReferences();
|
||||
|
||||
Iterator iterator();
|
||||
|
||||
boolean contains(Marker var1);
|
||||
|
||||
boolean contains(String var1);
|
||||
|
||||
boolean equals(Object var1);
|
||||
|
||||
int hashCode();
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package org.springframework.core.annotation;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.METHOD})
|
||||
@Documented
|
||||
public @interface AliasFor {
|
||||
@AliasFor("attribute")
|
||||
String value() default "";
|
||||
|
||||
@AliasFor("value")
|
||||
String attribute() default "";
|
||||
|
||||
Class<? extends Annotation> annotation() default Annotation.class;
|
||||
}
|
||||
@@ -1,9 +1,14 @@
|
||||
package org.springframework.stereotype;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(value=ElementType.TYPE)
|
||||
@Retention(value=RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Component
|
||||
public @interface Controller { }
|
||||
public @interface Controller {
|
||||
String value() default "";
|
||||
}
|
||||
|
||||
@@ -0,0 +1,202 @@
|
||||
package org.springframework.util;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.StringJoiner;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
public abstract class ObjectUtils {
|
||||
|
||||
private static final int INITIAL_HASH = 7;
|
||||
private static final int MULTIPLIER = 31;
|
||||
private static final String EMPTY_STRING = "";
|
||||
private static final String NULL_STRING = "null";
|
||||
private static final String ARRAY_START = "{";
|
||||
private static final String ARRAY_END = "}";
|
||||
private static final String EMPTY_ARRAY = "{}";
|
||||
private static final String ARRAY_ELEMENT_SEPARATOR = ", ";
|
||||
private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
|
||||
|
||||
public ObjectUtils() {
|
||||
}
|
||||
|
||||
public static boolean isCheckedException(Throwable ex) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isCompatibleWithThrowsClause(Throwable ex, @Nullable Class<?>... declaredExceptions) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isArray(@Nullable Object obj) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isEmpty(@Nullable Object[] array) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isEmpty(@Nullable Object obj) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Object unwrapOptional(@Nullable Object obj) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean containsElement(@Nullable Object[] array, Object element) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean containsConstant(Enum<?>[] enumValues, String constant) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean containsConstant(Enum<?>[] enumValues, String constant, boolean caseSensitive) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static <E extends Enum<?>> E caseInsensitiveValueOf(E[] enumValues, String constant) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <A, O extends A> A[] addObjectToArray(@Nullable A[] array, @Nullable O obj) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Object[] toObjectArray(@Nullable Object source) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean nullSafeEquals(@Nullable Object o1, @Nullable Object o2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean arrayEquals(Object o1, Object o2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static int nullSafeHashCode(@Nullable Object obj) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
public static int nullSafeHashCode(@Nullable Object[] array) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
public static int nullSafeHashCode(@Nullable boolean[] array) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
public static int nullSafeHashCode(@Nullable byte[] array) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
public static int nullSafeHashCode(@Nullable char[] array) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
public static int nullSafeHashCode(@Nullable double[] array) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
public static int nullSafeHashCode(@Nullable float[] array) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
public static int nullSafeHashCode(@Nullable int[] array) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
public static int nullSafeHashCode(@Nullable long[] array) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
public static int nullSafeHashCode(@Nullable short[] array) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** @deprecated */
|
||||
@Deprecated
|
||||
public static int hashCode(boolean bool) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** @deprecated */
|
||||
@Deprecated
|
||||
public static int hashCode(double dbl) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** @deprecated */
|
||||
@Deprecated
|
||||
public static int hashCode(float flt) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** @deprecated */
|
||||
@Deprecated
|
||||
public static int hashCode(long lng) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
public static String identityToString(@Nullable Object obj) {
|
||||
return "";
|
||||
}
|
||||
|
||||
public static String getIdentityHexString(Object obj) {
|
||||
return "";
|
||||
}
|
||||
|
||||
public static String getDisplayString(@Nullable Object obj) {
|
||||
return "";
|
||||
}
|
||||
|
||||
public static String nullSafeClassName(@Nullable Object obj) {
|
||||
return "";
|
||||
}
|
||||
|
||||
public static String nullSafeToString(@Nullable Object obj) {
|
||||
return "";
|
||||
}
|
||||
|
||||
public static String nullSafeToString(@Nullable Object[] array) {
|
||||
return "";
|
||||
}
|
||||
|
||||
public static String nullSafeToString(@Nullable boolean[] array) {
|
||||
return "";
|
||||
}
|
||||
|
||||
public static String nullSafeToString(@Nullable byte[] array) {
|
||||
return "";
|
||||
}
|
||||
|
||||
public static String nullSafeToString(@Nullable char[] array) {
|
||||
return "";
|
||||
}
|
||||
|
||||
public static String nullSafeToString(@Nullable double[] array) {
|
||||
return "";
|
||||
}
|
||||
|
||||
public static String nullSafeToString(@Nullable float[] array) {
|
||||
return "";
|
||||
}
|
||||
|
||||
public static String nullSafeToString(@Nullable int[] array) {
|
||||
return "";
|
||||
}
|
||||
|
||||
public static String nullSafeToString(@Nullable long[] array) {
|
||||
return "";
|
||||
}
|
||||
|
||||
public static String nullSafeToString(@Nullable short[] array) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package org.springframework.util;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Deque;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.StringJoiner;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.TimeZone;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
public abstract class StringUtils {
|
||||
|
||||
@Deprecated
|
||||
public static boolean isEmpty(@Nullable Object str) {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package org.springframework.web.bind.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
|
||||
@Target({ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@RequestMapping(
|
||||
method = {RequestMethod.GET}
|
||||
)
|
||||
public @interface GetMapping {
|
||||
@AliasFor(
|
||||
annotation = RequestMapping.class
|
||||
)
|
||||
String name() default "";
|
||||
|
||||
@AliasFor(
|
||||
annotation = RequestMapping.class
|
||||
)
|
||||
String[] value() default {};
|
||||
|
||||
@AliasFor(
|
||||
annotation = RequestMapping.class
|
||||
)
|
||||
String[] path() default {};
|
||||
|
||||
@AliasFor(
|
||||
annotation = RequestMapping.class
|
||||
)
|
||||
String[] params() default {};
|
||||
|
||||
@AliasFor(
|
||||
annotation = RequestMapping.class
|
||||
)
|
||||
String[] headers() default {};
|
||||
|
||||
@AliasFor(
|
||||
annotation = RequestMapping.class
|
||||
)
|
||||
String[] consumes() default {};
|
||||
|
||||
@AliasFor(
|
||||
annotation = RequestMapping.class
|
||||
)
|
||||
String[] produces() default {};
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package org.springframework.web.bind.annotation;
|
||||
|
||||
public @interface Mapping {
|
||||
}
|
||||
@@ -1,11 +1,32 @@
|
||||
package org.springframework.web.bind.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
|
||||
@Target(value={ElementType.METHOD,ElementType.TYPE})
|
||||
@Retention(value=RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Mapping
|
||||
public @interface RequestMapping {
|
||||
String name() default "";
|
||||
|
||||
@AliasFor("path")
|
||||
String[] value() default {};
|
||||
|
||||
@AliasFor("value")
|
||||
String[] path() default {};
|
||||
|
||||
RequestMethod[] method() default {};
|
||||
|
||||
String[] params() default {};
|
||||
|
||||
String[] headers() default {};
|
||||
|
||||
String[] consumes() default {};
|
||||
|
||||
String[] produces() default {};
|
||||
}
|
||||
|
||||
@@ -1,8 +1,23 @@
|
||||
package org.springframework.web.bind.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
|
||||
@Target(value=ElementType.PARAMETER)
|
||||
@Retention(value=RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.PARAMETER})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface RequestParam { }
|
||||
public @interface RequestParam {
|
||||
@AliasFor("name")
|
||||
String value() default "";
|
||||
|
||||
@AliasFor("value")
|
||||
String name() default "";
|
||||
|
||||
boolean required() default true;
|
||||
|
||||
String defaultValue() default "\n\t\t\n\t\t\n\ue000\ue001\ue002\n\t\t\t\t\n";
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package org.springframework.web.bind.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target({ElementType.TYPE, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface ResponseBody {
|
||||
}
|
||||
Reference in New Issue
Block a user