提交 5b198ff5 authored 作者: husishuai's avatar husishuai

init

上级 960bf06c
无相关合并请求
9
README.md,8\e\8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d

_atlassian-plugins-sso/src/main/java/com/atlassian/jira/security/sso/SSOSeraphAuthenticator.java,1\6\1689af886dd8deae895ba642b3a59a4ce406d0e8

Q.idea/sonarlint/securityhotspotstore/8/e/8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d,1\0\10a03f31c4dce92cb371e761ce9429428bb6c176
w
G.idea/sonarlint/issuestore/8/e/8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d,b\4\b4a0b63ce8560bbc5de0f9995c20cc861dc2adb3
]
-.idea/sonarlint/securityhotspotstore/index.pb,8\8\88a9255124c95bdc913197c120a8d560edc59c8e
7
pom.xml,4\4\442292b8a7efeabbe4cc176709b833b1792140ec

^atlassian-plugins-sso/src/main/java/com/atlassian/jira/security/client/MySSLSocketFactory.java,c\9\c992807dc83ecef9c370e9dd277962bb434b69ef

\atlassian-plugins-sso/src/main/java/com/atlassian/jira/security/client/RequestParameter.java,3\6\369bce0938a4e2fae3e67bd6861a71f34498b189

eatlassian-plugins-sso/src/main/java/com/atlassian/jira/security/login/JiraSeraphAuthenticatorOld.java,5\5\551fc01adf23d9613f1d99384e6281834cadec69
J
docker/docker-compose.yaml,7\a\7af4da9a4193d42f3d9d71da112b58d728e70329
a
1atlassian-plugins-sso/src/test/java/com/test.java,5\6\56c63f93a9efc252443133d830e80f7e0b83261b
M
atlassian-plugins-sso/pom.xml,2\3\23feb3be76c5acfba8ebeede8683f38e2c57e3dc

Yatlassian-plugins-sso/src/main/java/com/atlassian/jira/security/client/Oauth2ApiUtil.java,e\d\ed8ef4354ee9c09e3c6790310fe792ce80351da9

[atlassian-plugins-sso/src/main/java/com/atlassian/jira/security/client/HttpClientUtils.java,7\6\76fa13fd4e5bfd521948e8267be3ae6a699dfb03

Tatlassian-plugins-sso/src/main/java/com/atlassian/jira/security/client/Response.java,d\c\dc2ffd0f310d4760b4845518c06d0f8ee9eb584f
S
#.idea/sonarlint/issuestore/index.pb,9\f\9fe84ebb15faf917b7def6236dba604453cc61e0
T
$docker/lib/classes/seraph-config.xml,7\1\71431f903fbb950cae5ee439cd9c9e8c27df2ee4
E
docker/lib/login.html,2\b\2ba9a7ac00271ee09aed9b575aab5fc97d68471b
\ No newline at end of file
9
README.md,8\e\8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d

_atlassian-plugins-sso/src/main/java/com/atlassian/jira/security/sso/SSOSeraphAuthenticator.java,1\6\1689af886dd8deae895ba642b3a59a4ce406d0e8

Q.idea/sonarlint/securityhotspotstore/8/e/8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d,1\0\10a03f31c4dce92cb371e761ce9429428bb6c176
w
G.idea/sonarlint/issuestore/8/e/8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d,b\4\b4a0b63ce8560bbc5de0f9995c20cc861dc2adb3
]
-.idea/sonarlint/securityhotspotstore/index.pb,8\8\88a9255124c95bdc913197c120a8d560edc59c8e
7
pom.xml,4\4\442292b8a7efeabbe4cc176709b833b1792140ec

^atlassian-plugins-sso/src/main/java/com/atlassian/jira/security/client/MySSLSocketFactory.java,c\9\c992807dc83ecef9c370e9dd277962bb434b69ef

\atlassian-plugins-sso/src/main/java/com/atlassian/jira/security/client/RequestParameter.java,3\6\369bce0938a4e2fae3e67bd6861a71f34498b189

eatlassian-plugins-sso/src/main/java/com/atlassian/jira/security/login/JiraSeraphAuthenticatorOld.java,5\5\551fc01adf23d9613f1d99384e6281834cadec69
J
docker/docker-compose.yaml,7\a\7af4da9a4193d42f3d9d71da112b58d728e70329
a
1atlassian-plugins-sso/src/test/java/com/test.java,5\6\56c63f93a9efc252443133d830e80f7e0b83261b
M
atlassian-plugins-sso/pom.xml,2\3\23feb3be76c5acfba8ebeede8683f38e2c57e3dc

Yatlassian-plugins-sso/src/main/java/com/atlassian/jira/security/client/Oauth2ApiUtil.java,e\d\ed8ef4354ee9c09e3c6790310fe792ce80351da9

[atlassian-plugins-sso/src/main/java/com/atlassian/jira/security/client/HttpClientUtils.java,7\6\76fa13fd4e5bfd521948e8267be3ae6a699dfb03

Tatlassian-plugins-sso/src/main/java/com/atlassian/jira/security/client/Response.java,d\c\dc2ffd0f310d4760b4845518c06d0f8ee9eb584f
S
#.idea/sonarlint/issuestore/index.pb,9\f\9fe84ebb15faf917b7def6236dba604453cc61e0
T
$docker/lib/classes/seraph-config.xml,7\1\71431f903fbb950cae5ee439cd9c9e8c27df2ee4
E
docker/lib/login.html,2\b\2ba9a7ac00271ee09aed9b575aab5fc97d68471b
\ No newline at end of file
# jira-sso
extlib为相关依赖,供离线环境使用
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>jira-study</artifactId>
<groupId>org.atlassian</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>atlassian-plugins-sso</artifactId>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.36</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.26</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.18</version>
</dependency>
</dependencies>
</project>
\ No newline at end of file
package com.atlassian.jira.security.client;
import com.atlassian.jira.security.sso.SSOSeraphAuthenticator;
import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.httpclient.params.HttpClientParams;
import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.httpclient.protocol.Protocol;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.http.HttpServletRequest;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.Objects;
/**
* @Description HttpClientUtils 类(或接口)
* @Author huangshun
* @Date 2023/10/11
*/
//@Slf4j
public class HttpClientUtils implements Serializable {
private static final Logger log = LoggerFactory.getLogger(SSOSeraphAuthenticator.class);
private static final long serialVersionUID = -176092625883595547L;
public static final String SYMBOL_EQUAL = "=";
public static final String SYMBOL_JOIN = "&";
public static final String SYMBOL_JOIN_PARAMETER = "?";
public static final String SYMBOL_SLASH = "/";
public static final String ENCODE_UTF8 = "UTF-8";
HttpClient client;
private MultiThreadedHttpConnectionManager connectionManager;
private int maxSize;
public HttpClientUtils() {
this(150, 30000, 30000, 1048576);
}
public HttpClientUtils(int maxConPerHost, int conTimeOutMs, int soTimeOutMs, int maxSize) {
this.client = null;
this.connectionManager = new MultiThreadedHttpConnectionManager();
HttpConnectionManagerParams params = this.connectionManager.getParams();
params.setDefaultMaxConnectionsPerHost(maxConPerHost);
params.setConnectionTimeout(conTimeOutMs);
params.setSoTimeout(soTimeOutMs);
HttpClientParams clientParams = new HttpClientParams();
clientParams.setCookiePolicy("ignoreCookies");
this.client = new HttpClient(clientParams, this.connectionManager);
Protocol myhttps = new Protocol("https", new MySSLSocketFactory(), 443);
Protocol.registerProtocol("https", myhttps);
this.maxSize = maxSize;
}
public Response get(String url, RequestParameter[] requestParameters) {
log.debug("Request:");
log.info("GET:" + url);
log.info("get request parameter : " + Arrays.asList(requestParameters));
String getUrl = addParameter(url, requestParameters);
GetMethod getmethod = new GetMethod(getUrl);
return this.dealRequest(getmethod);
}
public Response post(String url, RequestParameter[] requestParameters) {
log.debug("Request:");
log.debug("POST:" + url);
PostMethod postMethod = new PostMethod(url);
for(int i = 0; i < requestParameters.length; ++i) {
postMethod.addParameter(requestParameters[i].getName(), requestParameters[i].getValue());
}
log.debug("post request parameter : " + Arrays.asList(requestParameters));
HttpMethodParams param = postMethod.getParams();
param.setContentCharset("UTF-8");
return this.dealRequest(postMethod);
}
public Response post(String url, Header[] headers, RequestParameter[] requestParameters) {
log.debug("Request:");
log.debug("POST:" + url);
PostMethod postMethod = new PostMethod(url);
if(Objects.nonNull(headers)){
for(int i = 0; i < headers.length; ++i) {
postMethod.addRequestHeader(headers[i]);
}
log.debug("post header : " + Arrays.asList(headers));
}
if(Objects.nonNull(requestParameters)){
for(int i = 0; i < requestParameters.length; ++i) {
postMethod.addParameter(requestParameters[i].getName(), requestParameters[i].getValue());
}
log.debug("post request parameter : " + Arrays.asList(requestParameters));
}
HttpMethodParams param = postMethod.getParams();
param.setContentCharset("UTF-8");
return this.dealRequest(postMethod);
}
public Response post(String url, String params) {
log.info("Request:");
log.info("POST:" + url);
PostMethod postMethod = new PostMethod(url);
try {
postMethod.setRequestEntity(new StringRequestEntity(params, "application/json", "UTF-8"));
} catch (UnsupportedEncodingException var5) {
log.error(var5.getMessage(), var5);
}
return this.dealRequest(postMethod);
}
public Response dealRequest(HttpMethod httpMethod) {
int statusCode = 0;
Response response = new Response();
try {
httpMethod.getParams().setParameter("http.method.retry-handler", new DefaultHttpMethodRetryHandler(3, false));
log.info("=======start httpClient excuteMethod========");
this.client.executeMethod(httpMethod);
log.info("=======end httpClient excuteMethod=======");
statusCode = httpMethod.getStatusCode();
log.debug("Response:");
log.debug("http StatusCode:" + statusCode);
response.setStatusCode(statusCode);
response.setResponseBody(httpMethod.getResponseBody());
log.info("http response string:" + response.asString());
} catch (Exception var8) {
log.error("Invoke HttpMethod" + httpMethod.getName() + " error!", var8);
} finally {
httpMethod.releaseConnection();
}
return response;
}
public static String addParameter(String url, RequestParameter[] requestParameters) {
StringBuilder buffer = new StringBuilder(url);
if (null != requestParameters && requestParameters.length > 0) {
String encodedParams = encodeParameters(requestParameters);
if (-1 == buffer.indexOf("?")) {
buffer.append("?").append(encodedParams);
} else {
buffer.append("&").append(encodedParams);
}
}
return buffer.toString();
}
public static String encodeParameters(RequestParameter[] requestParameters) {
StringBuilder buf = new StringBuilder();
for(int j = 0; j < requestParameters.length; ++j) {
if (j != 0) {
buf.append("&");
}
try {
buf.append(URLEncoder.encode(requestParameters[j].getName(), "UTF-8")).append("=").append(URLEncoder.encode(requestParameters[j].getValue(), "UTF-8"));
} catch (UnsupportedEncodingException var4) {
log.error(var4.getMessage(), var4);
}
}
return buf.toString();
}
public static String getRealRemoteAddress(HttpServletRequest request) {
String ip = request.getHeader("x-forwarded-for");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("X-Real-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return ip;
}
}
package com.atlassian.jira.security.client;
import com.atlassian.jira.security.sso.SSOSeraphAuthenticator;
import org.apache.commons.httpclient.ConnectTimeoutException;
import org.apache.commons.httpclient.params.HttpConnectionParams;
import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.net.SocketFactory;
import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.net.*;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
/**
* @Description MySSLSocketFactory 类(或接口)
* @Author huangshun
* @Date 2023/10/11
*/
//@Slf4j
public class MySSLSocketFactory implements ProtocolSocketFactory {
private static final Logger log = LoggerFactory.getLogger(SSOSeraphAuthenticator.class);
private SSLContext sslcontext = null;
public MySSLSocketFactory() {
}
private SSLContext createSSLContext() {
SSLContext sslcontext = null;
try {
sslcontext = SSLContext.getInstance("TLS");
sslcontext.init((KeyManager[])null, new TrustManager[]{new TrustAnyTrustManager()}, new SecureRandom());
} catch (NoSuchAlgorithmException var3) {
log.error(var3.getMessage(), var3);
} catch (KeyManagementException var4) {
log.error(var4.getMessage(), var4);
}
return sslcontext;
}
private SSLContext getSSLContext() {
if (this.sslcontext == null) {
this.sslcontext = this.createSSLContext();
}
return this.sslcontext;
}
public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException {
return this.getSSLContext().getSocketFactory().createSocket(socket, host, port, autoClose);
}
@Override
public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
return this.getSSLContext().getSocketFactory().createSocket(host, port);
}
@Override
public Socket createSocket(String host, int port, InetAddress clientHost, int clientPort) throws IOException, UnknownHostException {
return this.getSSLContext().getSocketFactory().createSocket(host, port, clientHost, clientPort);
}
@Override
public Socket createSocket(String host, int port, InetAddress localAddress, int localPort, HttpConnectionParams params) throws IOException, UnknownHostException, ConnectTimeoutException {
if (params == null) {
throw new IllegalArgumentException("Parameters may not be null");
} else {
int timeout = params.getConnectionTimeout();
SocketFactory socketfactory = this.getSSLContext().getSocketFactory();
if (timeout == 0) {
return socketfactory.createSocket(host, port, localAddress, localPort);
} else {
Socket socket = socketfactory.createSocket();
SocketAddress localaddr = new InetSocketAddress(localAddress, localPort);
SocketAddress remoteaddr = new InetSocketAddress(host, port);
socket.bind(localaddr);
socket.connect(remoteaddr, timeout);
return socket;
}
}
}
private static class TrustAnyTrustManager implements X509TrustManager {
private TrustAnyTrustManager() {
}
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}
}
package com.atlassian.jira.security.client;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.atlassian.config.bootstrap.AtlassianBootstrapManager;
import com.atlassian.jira.security.sso.SSOSeraphAuthenticator;
import org.apache.commons.httpclient.Header;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Objects;
import java.util.Properties;
//@Slf4j
public class Oauth2ApiUtil {
private static HttpClientUtils clientUtils = new HttpClientUtils();
private static Properties props = new Properties();
public final static String ENABLED_KEY = "sso.oauth2.enabled";
public final static String API_PREX_KEY = "sso.oauth2.apiPrex";
public final static String CLIENT_ID_KEY = "sso.oauth2.clientId";
public final static String CLIENT_SECRET_KEY = "sso.oauth2.clientSecret";
public final static String REDIRECT_URI_KEY = "sso.oauth2.redirectUri";
private static final Logger log = LoggerFactory.getLogger(SSOSeraphAuthenticator.class);
private String client_id;
private String client_secret;
private String redirect_uri;
private String api_prex;
private static Oauth2ApiUtil instance;
private enum API {
accessTokenApi("/oauth2/token"),
userInfoApi("/userinfo");
private String apiUrl;
API(String apiUrl) {
this.apiUrl = apiUrl;
}
public String getApiUrl(String apiPrex) {
return String.format("%s%s", apiPrex, this.apiUrl);
}
}
// public Oauth2ApiUtil() {
// this.api_prex = "http://192.168.1.227:8181/auth";
// this.client_id = "1754020039490535424";
// this.client_secret = "2650863febb842c48a6e054c07f233aa";
// this.redirect_uri = "http://scjoyedu.eicp.net:58001/login.action";
// }
public Oauth2ApiUtil(String apiPrex, String client_id, String client_secret, String redirect_uri) {
this.client_id = client_id;
this.client_secret = client_secret;
this.redirect_uri = redirect_uri;
this.api_prex = apiPrex;
}
public static Oauth2ApiUtil getInstance(AtlassianBootstrapManager bootstrapManager) {
if(Objects.isNull(instance)){
// Boolean enabled = bootstrapManager.isPropertyTrue(Oauth2ApiUtil.ENABLED_KEY);
// String apiPrex = (String)bootstrapManager.getProperty(Oauth2ApiUtil.API_PREX_KEY);
// String clientId = (String)bootstrapManager.getProperty(Oauth2ApiUtil.CLIENT_ID_KEY);
// String clientSecret = (String)bootstrapManager.getProperty(Oauth2ApiUtil.CLIENT_SECRET_KEY);
// String redirectUri = (String)bootstrapManager.getProperty(Oauth2ApiUtil.REDIRECT_URI_KEY);
// instance = new Oauth2ApiUtil(apiPrex,clientId,clientSecret,redirectUri);
Boolean enabled = true;
String apiPrex = "http://192.168.1.115:8180/auth";
String clientId = "1759151517098573824";
String clientSecret = "ef75da89794e424d9936df3573d8b0c7";
String redirectUri = "http://192.168.1.115:8080/login.html";
instance = new Oauth2ApiUtil(apiPrex,clientId,clientSecret,redirectUri);
System.out.println(String.format("sso.oauth2参数: enabled -> %s , apiPrex -> %s , clientId -> %s , clientSecret -> %s , redirectUri -> %s", enabled,apiPrex,clientId,clientSecret,redirectUri));
}
return instance;
}
public String getAccessTokenInfo(String code) {
try {
System.out.println(String.format("redirect_uri -> %s", redirect_uri));
Response response = clientUtils.post(API.accessTokenApi.getApiUrl(this.api_prex), new RequestParameter[]{
new RequestParameter("redirect_uri", redirect_uri)
, new RequestParameter("client_id", client_id)
, new RequestParameter("client_secret", client_secret)
, new RequestParameter("code", code)
, new RequestParameter("grant_type", "authorization_code")});
System.out.println("response = " + response);
String result = response.asString();
if (StringUtils.isBlank(result)) {
System.out.println("isBlank");
return null;
} else {
System.out.println("notBlank");
try {
JSONObject map = JSONUtil.parseObj(result);
// JSONObject map = new JSONObject(result);
System.out.println();
System.out.println("access_token " + map.get("access_token"));
System.out.println("msg " + map.get("msg"));
if (map.get("access_token") != null) {
return map.get("access_token").toString();
} else {
return map.get("msg").toString();
}
}catch (Exception e) {
System.out.println();
System.out.println("error----> " + e.getMessage());
return null;
}
}
} catch (Exception var7) {
System.out.println();
System.out.println("var7.getMessage() -> " + var7.getMessage());
log.error(var7.getMessage(), var7);
return null;
}
}
public JSONObject findUserInfo(String code) {
System.out.println();
System.out.println("获取accessToken开始");
String access_token = this.getAccessTokenInfo(code);
System.out.println();
System.out.println("access_token = " + access_token);
if (access_token == null) {
return null;
}
return this.getUserInfo(access_token);
}
public JSONObject getUserInfo(String access_token) {
try {
Response response = clientUtils.post(API.userInfoApi.getApiUrl(this.api_prex)
, new Header[]{new Header("Authorization", String.format("Bearer %s", access_token))}, null);
System.out.println();
System.out.println("response -> " + response.asString());
String result = response.asString();
if (StringUtils.isBlank(result)) {
return null;
} else {
System.out.println(" hahaha ");
// JSONObject map = new JSONObject(result);
JSONObject map = JSONUtil.parseObj(result);
System.out.println("hehehe");
return map;
}
} catch (Exception var7) {
log.error(var7.getMessage(), var7);
return null;
}
}
public static void printServerResponseToWeb(HttpServletResponse response,String message){
response.setCharacterEncoding("UTF-8");
PrintWriter printWriter = null;
try {
printWriter = response.getWriter();
printWriter.write(message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
\ No newline at end of file
package com.atlassian.jira.security.client;
import com.atlassian.jira.security.sso.SSOSeraphAuthenticator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.Serializable;
public class RequestParameter implements Serializable {
private static final long serialVersionUID = 2542042197233331049L;
private static final Logger log = LoggerFactory.getLogger(SSOSeraphAuthenticator.class);
private String name;
private String value;
public RequestParameter(String name, String value) {
this.name = name;
this.value = value;
}
public RequestParameter(String name, long value) {
this.name = name;
this.value = String.valueOf(value);
}
public RequestParameter(String name, double value) {
this.name = name;
this.value = String.valueOf(value);
}
public RequestParameter(String name, int value) {
this.name = name;
this.value = String.valueOf(value);
}
public String getName() {
return this.name;
}
public String getValue() {
return this.value;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("RequestParameter{");
sb.append("name='").append(this.name).append('\'');
sb.append(", value='").append(this.value).append('\'');
sb.append('}');
return sb.toString();
}
}
\ No newline at end of file
package com.atlassian.jira.security.client;
//import groovy.util.logging.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.UnsupportedEncodingException;
//@Slf4j
public class Response {
private int statusCode = 0;
private byte[] responseBody;
public void setStatusCode(int statusCode) {
this.statusCode = statusCode;
}
public void setResponseBody(byte[] responseBody) {
this.responseBody = responseBody;
}
private static final Logger log = LoggerFactory.getLogger(Response.class);
public Response() {
}
public Response(int statusCode, byte[] responseBody) {
this.statusCode = statusCode;
this.responseBody = responseBody;
}
public String asString() {
String result = "";
try {
if (this.responseBody != null) {
result = new String(this.responseBody, "UTF-8");
}
} catch (UnsupportedEncodingException var3) {
log.error(var3.getMessage(), var3);
}
return result;
}
public int getStatusCode() {
return this.statusCode;
}
}
This source diff could not be displayed because it is too large. You can view the blob instead.
<atlassian-plugin name="Atlassian JIRA - Plugins - Global Issue Navigator" key="com.atlassian.jira.jira-issue-nav-plugin">
<!--
This file is just a mock to provide web-resources that JIRA's system webresources depend upon
from the issuenav plugin.
-->
<plugin-info>
<description>A mock of com.atlassian.jira.jira-issue-nav-plugin</description>
<vendor name="Atlassian" url="http://www.atlassian.com"/>
<version>8.1.3</version>
</plugin-info>
<web-resource key="issuenav-legacy">
<dependency>com.atlassian.plugins.jquery:jquery</dependency>
<dependency>jira.webresources:almond</dependency>
<resource type="download" name="setup-legacyissue-mock.js" location="js/setup-legacyissue-mock.js"/>
</web-resource>
</atlassian-plugin>
<atlassian-plugin name="Atlassian Plugins - Web Resources - Implementation Plugin" key="com.atlassian.plugins.atlassian-plugins-webresource-plugin">
<!--
This file is just a mock to enable Soy usage in setup - without it Soy templates cannot be rendered, as there is no
com.atlassian.plugins.atlassian-plugins-webresource-plugin:context-path web resource, so this needs to be mocked.
Previously there was an implementation of AuiIntegration interface, but it was removed as there is no auiplugin-spi
since AUI 5.7.0; before that, contextPath() soy helper was provided by JiraAuiIntegration, now it is provided by
com.atlassian.soy:atlassian-soy-core plugin (which is dependency of com.atlassian.soy.soy-template-plugin - JIRA's
webresources depend on this one). Due to dependencies of atlassian-plugins-webresource-plugin, is cannot be
enabled in setup.
LEGO-666: This also provides the noop implementation of jsI18n resource transformer that is provided by
com.atlassian.plugins.atlassian-plugins-webresource-plugin and if not present results in many WARNING messages
in log files during setup.
-->
<plugin-info>
<description>A mock of com.atlassian.plugins.atlassian-plugins-webresource-plugin</description>
<vendor name="Atlassian" url="http://www.atlassian.com"/>
<version>3.1.5</version>
</plugin-info>
<url-reading-web-resource-transformer key="jsI18n" name="JavaScript I18n Transformer" class="com.atlassian.jira.NoopResourceTransformer" />
<web-resource key="context-path">
<dependency>com.atlassian.plugins.jquery:jquery</dependency>
<dependency>com.atlassian.auiplugin:aui-core</dependency>
<dependency>jira.webresources:almond</dependency>
<resource type="download" name="setup-ajs-context-path-mock.js" location="js/setup-ajs-context-path-mock.js"/>
</web-resource>
<web-resource key="data">
<resource type="download" name="setup-wrm-data-mock.js" location="js/setup-wrm-data-mock.js"/>
</web-resource>
</atlassian-plugin>
\ No newline at end of file
<atlassian-plugin name="Atlassian Plugins - Web Resources - REST Plugin" key="com.atlassian.plugins.atlassian-plugins-webresource-rest">
<!--
This file is just a mock to enable dependent webresources to depend on WRM while not having the possibility to
dynamically load resources (all dependent modules must be explicitly defined).
-->
<plugin-info>
<description>A mock of com.atlassian.plugins.atlassian-plugins-webresource-rest</description>
<vendor name="Atlassian" url="http://www.atlassian.com"/>
<version>3.1.5</version>
</plugin-info>
<web-resource key="web-resource-manager">
<dependency>jira.webresources:almond</dependency>
<resource type="download" name="setup-wrm-mock.js" location="js/setup-wrm-require-mock.js"/>
</web-resource>
</atlassian-plugin>
\ No newline at end of file
## Defines some default values for the wiki-renderer
## relative location of the emoticon icons
EMOTICONS_PATH = icons/emoticons/
## relative location of the icons
ICONS_PATH = icons/
## the alt/title message to show on an external link
URL_LINK_TITLE = Visit page outside Jira
## the alt/title message to show on an internal link
SITE_RELATIVE_LINK_TITLE = Visit page in Jira
## the alt/title message to show a link on this server
RELATIVE_LINK_TITLE = Visit page on this server
# DO NOT HAND EDIT; Generated by src/etc/groovy/GenerateBuildVersions.groovy
22 1.4.3
46 2.0.2
49 2.1
52 2.2
53 2.3
54 2.4
55 2.4.1
57 2.5.1
58 2.5.2
59 2.5.3
64 2.6
65 2.6.1
68 3.0-preview
69 3.0-preview2
70 3.0-preview3
71 3.0-beta
72 3.0
73 3.0.1
74 3.0.2
75 3.0.3
80 3.1
81 3.1.1
88 3.2-beta1
89 3.2.1
90 3.2.2
91 3.2.3
92 3.3-beta1
96 3.3
97 3.3.1
98 3.3.2
99 3.3.3
102 3.4-beta1
106 3.4
107 3.4.1
108 3.4.2
109 3.4.3
131 3.5
133 3.5.1
134 3.5.2
135 3.5.3
153 3.6
154 3.6.1
156 3.6.2
159 3.6.3
160 3.6.4
161 3.6.5
179 3.7-beta1
181 3.7-beta2
184 3.7
185 3.7.1
186 3.7.2
187 3.7.3
189 3.7.4
209 3.8
210 3.8.1
233 3.9
234 3.9.1
235 3.9.2
236 3.9.3
260 3.10
261 3.10.1
262 3.10.2
288 3.11
298 3.12
299 3.12.1
300 3.12.2
302 3.12.3
328 3.13_beta1
330 3.13
333 3.13.1
335 3.13.2
343 3.13.3
354 3.13.4
360 3.13.5
423 4.0.0-Beta1
432 4.0.0-Beta2
439 4.0.0-rc1
466 4.0
471 4.0.1
472 4.0.2
505 4.1-M1
516 4.1-rc1
519 4.1
522 4.1.1
531 4.1.2
555 4.2-m6
572 4.2-beta1
577 4.2-beta2
581 4.2-beta3
585 4.2-rc1
586 4.2
587 4.2-b587
588 4.2.1-b588
589 4.2.2-b589
590 4.2.3-b590
591 4.2.4-b591
604 4.3-m1
605 4.3-m2-b605
606 4.3-m3-b606
608 4.3-m4-b608
609 4.3-m5-b609
611 4.3-rc1
612 4.3
615 4.3.1
616 4.3.2
617 4.3.3
620 4.3.4
649 4.4
660 4.4.1
662 4.4.2
663 4.4.5
710 5.0-aTestRelease-20120104
711 5.0-rc3
712 5.0-rc4
713 5.0-ondemand-6
718 5.0.1-rc1
725 5.0.2
756 5.1-ondemand-1
719 5.0.1-rc2
720 5.0.1-rc3
721 5.0.1
757 5.1-m3
729 5.0.3
731 5.0.4
761 5.1-beta1
732 5.0.5
733 5.0.6-od2
762 5.1-rc1
734 5.0.7
763 5.1-rc2
764 5.1-rc3
800 5.2.KA2
765 5.1-rc5
766 5.1-rc6
767 5.1-rc7
768 5.1
801 5.2-m01
771 5.1.1-rc1
772 5.1.1
773 5.1.2
802 5.2-m02
804 5.2-m03
782 5.1.3
806 5.2-m04
783 5.1.4
807 5.2-m05
784 5.1.5
808 5.2-rotp4
785 5.1.6
809 5.2-beta1
786 5.1.7
787 5.1.8
810 5.2-rc1
811 5.2
813 5.2.1
6001 6.0-OD-01
843 5.2.2
6007 6.0-OD-02
6010 6.0-OD-04
844 5.2.3
845 5.2.4
6015 6.0-OD-05
847 5.2.5
848 5.2.6-m1
6020 6.0-OD-06
849 5.2.6
6025 6.0-OD-07
850 5.2.7
6050 6.0-OD-09
851 5.2.8
852 5.2.9
6070 6.0-beta-1
853 5.2.10
854 5.2.11
6085 6.0-OD-12
6090 6.0-OD-13
6092 6.0-OD-15
6093 6.0
6097 6.0.2
6098 6.1-OD-1
6099 6.0.3
6124 6.1-OD-02
855 5.2.11-SP1
6100 6.0.4
6132 6.1-OD-03
6134 6.1-OD-04
6102 6.0.5
default.maxSize=0
default.expireTime=0
UtilPropertiesCache.maxSize=0
UtilPropertiesCache.expireTime=0
## This file maps the language code to the file name which supports it in the calendar implementation.
## This mapping was used in the past to find the file name of the localized calendar JavaScript.
## However, now it only serves the purpose of a check, an entry in this file means that
## a localized version exists, the actual value is irrelevant as the real mapping is
## in system-webresources-plugin.xml
## IMPORTANT: The locales listed here must match the ones in system-webresources-plugin.xml
af=calendar-af.js
al=calendar-al.js
bg=calendar-bg.js
br=calendar-br.js
ca=calendar-ca.js
cs=calendar-cs.js
da=calendar-da.js
de=calendar-de.js
du=calendar-du.js
el=calendar-el.js
en=calendar-en.js
es=calendar-es.js
fi=calendar-fi.js
fr=calendar-fr.js
he=calendar-he-utf8.js
hr=calendar-hr.js
hu=calendar-hu.js
it=calendar-it.js
ja=calendar-ja.js
jp=calendar-jp.js
ko=calendar-ko.js
lt=calendar-lt.js
lv=calendar-lv.js
nl=calendar-nl.js
no=calendar-no.js
pl=calendar-pl.js
pt=calendar-pt.js
ro=calendar-ro.js
ru=calendar-ru.js
si=calendar-si.js
sk=calendar-sk.js
sl=calendar-sl.js
sp=calendar-sp.js
sv=calendar-sv.js
tr=calendar-tr.js
zh=calendar-zh.js
#
# Default configuration for JIRA's built-in connection pool.
#
# See http://commons.apache.org/dbcp/configuration.html for a full list of options.
#
# Expose the DBCP JMX bean under a well known name.
#
# If the MBean is not found under this name then connection pool stats will not show up in the monitoring page.
jmx = true
mbeanName = com.atlassian.jira:name=BasicDataSource
# Flag to remove abandoned connections if they exceed the removeAbandonedTimout.
#
# If set to true a connection is considered abandoned and eligible for removal if it has been idle longer than the
# removeAbandonedTimeout. Setting this to true can recover db connections from poorly written applications which fail
# to close a connection.
removeAbandoned = true
# Timeout in seconds before an abandoned connection can be removed.
removeAbandonedTimeout = 900
# Flag to log stack traces for application code which abandoned a Statement or Connection.
#
# Logging of abandoned Statements and Connections adds overhead for every Connection open or new Statement because a
# stack trace has to be generated.
logAbandoned = false
print.verbose=false
print.timing=false
print.info=true
print.important=true
print.warning=true
print.error=true
print.fatal=true
<!--
Details of all the downgrade tasks for JIRA.
A downgrade task is an explicit reversal of an upgrade task.
The "build number" for a downgrade task is the number of the upgrade task it reverses.
eg downgrade task 117 would reverse upgrade task 117 and move the current build number to 116.
Not all upgrade tasks have explicit downgrade tasks - most often the reversal is a NO-OP.
The UpgradeHistory DB table stores a history of all upgrades that have run along with a flag of whether the reversal
is a no-op or if it requires a downgrade task.
See also the "upgrades.xml" file.
-->
<downgrades>
<downgrade>
<class>com.atlassian.jira.upgrade.tasks.DowngradeTask_Build70024</class>
</downgrade>
<downgrade>
<class>com.atlassian.jira.upgrade.tasks.DowngradeTask_Build70027</class>
</downgrade>
<downgrade>
<class>com.atlassian.jira.upgrade.tasks.DowngradeTask_Build810001</class>
</downgrade>
</downgrades>
<?xml version="1.0" encoding="UTF-8"?>
<!-- This is the configuration file for Ehcache in JIRA.
Caches requiring special handling are configured in this file.
Most configuration is done programmatically within JIRA including:
* Most caches,
* The CacheManagerPeerProviderFactory for peer discovery and
* The RMICacheManagerPeerListenerFactory for cache replication.
-->
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="ehcache.xsd"
updateCheck="false" monitoring="autodetect" dynamicConfig="true">
<defaultCache maxEntriesLocalHeap="0"/>
<cache name="com.atlassian.jira.task.TaskManagerImpl.futureMap" eternal="true" maxEntriesLocalHeap="0">
<pinning store="inCache"/>
</cache>
<!-- JIRA requires these caches to be fully-populated during startup, hence they are pinned and eternal -->
<cache name="com.atlassian.jira.task.TaskManagerImpl.taskMap" eternal="true" maxEntriesLocalHeap="0">
<cacheEventListenerFactory
class="com.atlassian.jira.cluster.cache.ehcache.ReplicatorFactory"
properties="replicateAsynchronously=false, replicatePuts=true, replicateUpdates=true,
replicateUpdatesViaCopy=true, replicateRemovals=true"/>
<!-- Ensure the cache gets initialised on secondary nodes before we try and use it, otherwise tasks in progress
may go unnoticed for a while. -->
<bootstrapCacheLoaderFactory
class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
properties="bootstrapAsynchronously=false"/>
<pinning store="inCache"/>
</cache>
<cache name="com.atlassian.jira.application.DefaultApplicationRoleManager.activeUsersCountForLicenseUnflushableCache" eternal="true"
maxEntriesLocalHeap="0">
<cacheEventListenerFactory
class="com.atlassian.jira.cluster.cache.ehcache.ReplicatorFactory"
properties="replicateAsynchronously=false, replicatePuts=true, replicateUpdates=true,
replicateUpdatesViaCopy=true, replicateRemovals=true "/>
</cache>
</ehcache>
\ No newline at end of file
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论