Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
163a0f46df |
@@ -1,594 +0,0 @@
|
||||
package sc545.pay.utils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.NameValuePair;
|
||||
import org.apache.http.client.CookieStore;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.client.entity.UrlEncodedFormEntity;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.message.BasicNameValuePair;
|
||||
import org.apache.http.ssl.SSLContextBuilder;
|
||||
import org.apache.http.ssl.TrustStrategy;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
|
||||
|
||||
/**
|
||||
* 基于 httpclient 4.5版本的 http工具类
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class HttpUtils {
|
||||
|
||||
private static final CloseableHttpClient httpClient;
|
||||
public static final String CHARSET = "UTF-8";
|
||||
// 采用静态代码块,初始化超时时间配置,再根据配置生成默认httpClient对象
|
||||
static {
|
||||
//10秒相应超时
|
||||
RequestConfig config = RequestConfig.custom().setConnectTimeout(10000).setSocketTimeout(10000).setConnectionRequestTimeout(5000).build();
|
||||
httpClient = HttpClientBuilder.create().setDefaultRequestConfig(config).build();
|
||||
}
|
||||
|
||||
public static String doGet(String url, Map<String, String> params) {
|
||||
return doGet(url, params, CHARSET);
|
||||
}
|
||||
|
||||
public static String doGetSSL(String url, Map<String, String> params) {
|
||||
return doGetSSL(url, params, CHARSET);
|
||||
}
|
||||
|
||||
public static String doPost(String url, Map<String, String> params){
|
||||
return doPost(url, params, CHARSET);
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP Get 获取内容
|
||||
* @param url 请求的url地址 ?之前的地址
|
||||
* @param params 请求的参数
|
||||
* @param charset 编码格式
|
||||
* @return 页面内容
|
||||
*/
|
||||
public static String doGet(String url, Map<String, String> params, String charset) {
|
||||
if(charset==null||charset.trim().length()<1) charset="UTF-8";
|
||||
if (StringUtils.isBlank(url)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
if (params != null && !params.isEmpty()) {
|
||||
List<NameValuePair> pairs = new ArrayList<NameValuePair>(params.size());
|
||||
for (Map.Entry<String, String> entry : params.entrySet()) {
|
||||
String value = entry.getValue();
|
||||
if (value != null) {
|
||||
pairs.add(new BasicNameValuePair(entry.getKey(), value));
|
||||
}
|
||||
}
|
||||
// 将请求参数和url进行拼接
|
||||
url += "?" + EntityUtils.toString(new UrlEncodedFormEntity(pairs, charset));
|
||||
}
|
||||
HttpGet httpGet = new HttpGet(url);
|
||||
CloseableHttpResponse response = httpClient.execute(httpGet);
|
||||
int statusCode = response.getStatusLine().getStatusCode();
|
||||
if (statusCode != 200) {
|
||||
httpGet.abort();
|
||||
throw new RuntimeException("HttpClient,error status code :" + statusCode);
|
||||
}
|
||||
HttpEntity entity = response.getEntity();
|
||||
String result = null;
|
||||
if (entity != null) {
|
||||
result = EntityUtils.toString(entity, charset);
|
||||
}
|
||||
EntityUtils.consume(entity);
|
||||
response.close();
|
||||
if(!"UTF-8".equals(getEncoding(result))) result=GBKtoUTF8(result);
|
||||
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
System.out.println("url错误:::"+e.toString());
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* HTTP Post 获取内容
|
||||
* @param url 请求的url地址 ?之前的地址
|
||||
* @param params 请求的参数
|
||||
* @param charset 编码格式
|
||||
* @return 页面内容
|
||||
* @throws IOException
|
||||
*/
|
||||
public static String doPost(String url, Map<String, String> params, String charset) {
|
||||
if(charset==null||charset.trim().length()<1) charset="UTF-8";
|
||||
if (StringUtils.isBlank(url)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<NameValuePair> pairs = null;
|
||||
if (params != null && !params.isEmpty()) {
|
||||
pairs = new ArrayList<NameValuePair>(params.size());
|
||||
for (Map.Entry<String, String> entry : params.entrySet()) {
|
||||
String value = entry.getValue();
|
||||
if (value != null) {
|
||||
pairs.add(new BasicNameValuePair(entry.getKey(), value));
|
||||
}
|
||||
}
|
||||
}
|
||||
HttpPost httpPost = new HttpPost(url);
|
||||
CloseableHttpResponse response = null;
|
||||
try {
|
||||
if (pairs != null && pairs.size() > 0) {
|
||||
httpPost.setEntity(new UrlEncodedFormEntity(pairs, CHARSET));
|
||||
}
|
||||
|
||||
response = httpClient.execute(httpPost);
|
||||
int statusCode = response.getStatusLine().getStatusCode();
|
||||
if (statusCode != 200) {
|
||||
httpPost.abort();
|
||||
throw new RuntimeException("HttpClient,error status code :" + statusCode);
|
||||
}
|
||||
HttpEntity entity = response.getEntity();
|
||||
String result = null;
|
||||
if (entity != null) {
|
||||
result = EntityUtils.toString(entity, charset);
|
||||
}
|
||||
EntityUtils.consume(entity);
|
||||
if(!"UTF-8".equals(getEncoding(result))) result=GBKtoUTF8(result);
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
return "";
|
||||
} finally {
|
||||
if (response != null)
|
||||
try {
|
||||
response.close();
|
||||
} catch (IOException e) {}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTPS Get 获取内容
|
||||
* @param url 请求的url地址 ?之前的地址
|
||||
* @param params 请求的参数
|
||||
* @param charset 编码格式
|
||||
* @return 页面内容
|
||||
*/
|
||||
public static String doGetSSL(String url, Map<String, String> params, String charset) {
|
||||
if(charset==null||charset.trim().length()<1) charset="UTF-8";
|
||||
if (StringUtils.isBlank(url)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
if (params != null && !params.isEmpty()) {
|
||||
List<NameValuePair> pairs = new ArrayList<NameValuePair>(params.size());
|
||||
for (Map.Entry<String, String> entry : params.entrySet()) {
|
||||
String value = entry.getValue();
|
||||
if (value != null) {
|
||||
pairs.add(new BasicNameValuePair(entry.getKey(), value));
|
||||
}
|
||||
}
|
||||
url += "?" + EntityUtils.toString(new UrlEncodedFormEntity(pairs, charset));
|
||||
}
|
||||
HttpGet httpGet = new HttpGet(url);
|
||||
|
||||
// https 注意这里获取https内容,使用了忽略证书的方式,当然还有其他的方式来获取https内容
|
||||
CloseableHttpClient httpsClient = HttpUtils.createSSLClientDefault();
|
||||
CloseableHttpResponse response = httpsClient.execute(httpGet);
|
||||
int statusCode = response.getStatusLine().getStatusCode();
|
||||
if (statusCode != 200) {
|
||||
httpGet.abort();
|
||||
throw new RuntimeException("HttpClient,error status code :" + statusCode);
|
||||
}
|
||||
HttpEntity entity = response.getEntity();
|
||||
String result = null;
|
||||
if (entity != null) {
|
||||
result = EntityUtils.toString(entity, charset);
|
||||
}
|
||||
EntityUtils.consume(entity);
|
||||
response.close();
|
||||
if(!"UTF-8".equals(getEncoding(result))) result=GBKtoUTF8(result);
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 这里创建了忽略整数验证的CloseableHttpClient对象
|
||||
* @return
|
||||
*/
|
||||
public static CloseableHttpClient createSSLClientDefault() {
|
||||
try {
|
||||
SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
|
||||
// 信任所有
|
||||
public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
|
||||
return true;
|
||||
}
|
||||
}).build();
|
||||
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext);
|
||||
return HttpClients.custom().setSSLSocketFactory(sslsf).build();
|
||||
} catch (KeyManagementException e) {
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
} catch (KeyStoreException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return HttpClients.createDefault();
|
||||
}
|
||||
|
||||
/**
|
||||
* 这里创建了忽略整数验证的CloseableHttpClient对象
|
||||
* @return
|
||||
*/
|
||||
public static CloseableHttpClient createSSLClientCookie(CookieStore cookie) {
|
||||
try {
|
||||
SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
|
||||
// 信任所有
|
||||
public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
|
||||
return true;
|
||||
}
|
||||
}).build();
|
||||
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext);
|
||||
return HttpClients.custom().setSSLSocketFactory(sslsf).setDefaultCookieStore(cookie).build();
|
||||
} catch (KeyManagementException e) {
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
} catch (KeyStoreException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return HttpClients.createDefault();
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送post请求
|
||||
* @param url 请求地址
|
||||
* @param json json格式字符串
|
||||
* @param contentType 这里用 "application/json"
|
||||
* @return
|
||||
*/
|
||||
public static String post(String url, String json, String contentType,String charset) {
|
||||
if(charset==null||charset.trim().length()<1) charset="UTF-8";
|
||||
if("json".equals(contentType)) contentType="application/json";
|
||||
HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
|
||||
//HttpClient
|
||||
CloseableHttpClient client = httpClientBuilder.build();
|
||||
client = (CloseableHttpClient) wrapClient(client);
|
||||
HttpPost post = new HttpPost(url);
|
||||
try {
|
||||
StringEntity s = new StringEntity(json, "utf-8");
|
||||
if (StringUtils.isBlank(contentType)) {
|
||||
s.setContentType("application/json");
|
||||
}
|
||||
s.setContentType(contentType);
|
||||
post.setEntity(s);
|
||||
HttpResponse res = client.execute(post);
|
||||
HttpEntity entity = res.getEntity();
|
||||
String str = EntityUtils.toString(entity, charset);
|
||||
if(!"UTF-8".equals(getEncoding(str))) str=GBKtoUTF8(str);
|
||||
return str;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private static org.apache.http.client.HttpClient wrapClient(HttpClient base) {
|
||||
try {
|
||||
SSLContext ctx = SSLContext.getInstance("TLSv1");
|
||||
X509TrustManager tm = new X509TrustManager() {
|
||||
public void checkClientTrusted(X509Certificate[] xcs,
|
||||
String string) throws CertificateException {
|
||||
}
|
||||
|
||||
public void checkServerTrusted(X509Certificate[] xcs,
|
||||
String string) throws CertificateException {
|
||||
}
|
||||
|
||||
public X509Certificate[] getAcceptedIssuers() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
ctx.init(null, new TrustManager[]{tm}, null);
|
||||
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(ctx, new String[]{"TLSv1"}, null,
|
||||
SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
|
||||
CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
|
||||
return httpclient;
|
||||
|
||||
} catch (Exception ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//正则找出所有
|
||||
public static String getUrl(String s){
|
||||
String regex = "http[s]?:\\/\\/([\\w]+\\.)+[\\w]+([\\w./?%&=]*)?";
|
||||
Pattern pattern = Pattern.compile(regex);
|
||||
Matcher m = pattern.matcher(s);
|
||||
String r="";
|
||||
while(m.find()){
|
||||
r+=m.group()+",";
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查url是否可访问
|
||||
* @param url
|
||||
* @return
|
||||
*/
|
||||
public static boolean ckUrl(String url) {
|
||||
|
||||
if (StringUtils.isBlank(url)) {
|
||||
return false;
|
||||
}
|
||||
HttpGet httpGet = new HttpGet(url);
|
||||
try {
|
||||
CloseableHttpResponse response = httpClient.execute(httpGet);
|
||||
int statusCode = response.getStatusLine().getStatusCode();
|
||||
if (statusCode != 200) return false;
|
||||
} catch (Exception e) {
|
||||
String s = e.getMessage();
|
||||
if("Timeout waiting for connection from pool".equals(s)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**检查字符串编码格式*/
|
||||
public static String getEncoding(String str)
|
||||
{
|
||||
String encode;
|
||||
|
||||
encode = "UTF-16";
|
||||
try
|
||||
{
|
||||
if(str.equals(new String(str.getBytes(), encode)))
|
||||
{
|
||||
return encode;
|
||||
}
|
||||
}
|
||||
catch(Exception ex) {}
|
||||
|
||||
encode = "ASCII";
|
||||
try
|
||||
{
|
||||
if(str.equals(new String(str.getBytes(), encode)))
|
||||
{
|
||||
//字符串 str 中仅由数字和英文字母组成,无法识别其编码格式
|
||||
return "UTF-8";
|
||||
}
|
||||
}
|
||||
catch(Exception ex) {}
|
||||
|
||||
encode = "ISO-8859-1";
|
||||
try
|
||||
{
|
||||
if(str.equals(new String(str.getBytes(), encode)))
|
||||
{
|
||||
return encode;
|
||||
}
|
||||
}
|
||||
catch(Exception ex) {}
|
||||
|
||||
encode = "GB2312";
|
||||
try
|
||||
{
|
||||
if(str.equals(new String(str.getBytes(), encode)))
|
||||
{
|
||||
return encode;
|
||||
}
|
||||
}
|
||||
catch(Exception ex) {}
|
||||
|
||||
encode = "UTF-8";
|
||||
try
|
||||
{
|
||||
if(str.equals(new String(str.getBytes(), encode)))
|
||||
{
|
||||
return encode;
|
||||
}
|
||||
}
|
||||
catch(Exception ex) {}
|
||||
|
||||
/*
|
||||
*......待完善
|
||||
*/
|
||||
|
||||
return "UTF-8";
|
||||
}
|
||||
|
||||
/**将字符串转换字符编码*/
|
||||
public static String GBKtoUTF8(String str) {
|
||||
if("UTF-8".equals(getEncoding(str))) return str;
|
||||
|
||||
return getUTF8StringFromGBKString(str);
|
||||
|
||||
}
|
||||
|
||||
public static String getUTF8StringFromGBKString(String gbkStr) {
|
||||
try {
|
||||
return new String(getUTF8BytesFromGBKString(gbkStr), "UTF-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new InternalError();
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] getUTF8BytesFromGBKString(String gbkStr) {
|
||||
int n = gbkStr.length();
|
||||
byte[] utfBytes = new byte[3 * n];
|
||||
int k = 0;
|
||||
for (int i = 0; i < n; i++) {
|
||||
int m = gbkStr.charAt(i);
|
||||
if (m < 128 && m >= 0) {
|
||||
utfBytes[k++] = (byte) m;
|
||||
continue;
|
||||
}
|
||||
utfBytes[k++] = (byte) (0xe0 | (m >> 12));
|
||||
utfBytes[k++] = (byte) (0x80 | ((m >> 6) & 0x3f));
|
||||
utfBytes[k++] = (byte) (0x80 | (m & 0x3f));
|
||||
}
|
||||
if (k < utfBytes.length) {
|
||||
byte[] tmp = new byte[k];
|
||||
System.arraycopy(utfBytes, 0, tmp, 0, k);
|
||||
return tmp;
|
||||
}
|
||||
return utfBytes;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 带有cookie和header 的post请求
|
||||
* @param url
|
||||
* @param params
|
||||
* @param cookie
|
||||
* @param header
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public static String doPost2(String url, Map<String, String> params, CookieStore cookie,Map<String, String> header,String charset) {
|
||||
if(charset==null||charset.trim().length()<1) charset="UTF-8";
|
||||
if (StringUtils.isBlank(url)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<NameValuePair> pairs = null;
|
||||
if (params != null && !params.isEmpty()) {
|
||||
pairs = new ArrayList<NameValuePair>(params.size());
|
||||
for (Map.Entry<String, String> entry : params.entrySet()) {
|
||||
String value = entry.getValue();
|
||||
if (value != null) {
|
||||
pairs.add(new BasicNameValuePair(entry.getKey(), value));
|
||||
}
|
||||
}
|
||||
}
|
||||
HttpPost httpPost = new HttpPost(url);
|
||||
|
||||
Set<Entry<String, String>> set = header.entrySet();
|
||||
Iterator<Entry<String, String>> s = set.iterator();
|
||||
while (s.hasNext()) {
|
||||
Map.Entry m = (Map.Entry) s.next();
|
||||
httpPost.addHeader(m.getKey().toString(),m.getValue().toString());
|
||||
}
|
||||
|
||||
CloseableHttpResponse response = null;
|
||||
try {
|
||||
if (pairs != null && pairs.size() > 0) {
|
||||
httpPost.setEntity(new UrlEncodedFormEntity(pairs, CHARSET));
|
||||
}
|
||||
|
||||
CloseableHttpClient httpClientc = HttpUtils.createSSLClientCookie(cookie);
|
||||
response = httpClientc.execute(httpPost);
|
||||
int statusCode = response.getStatusLine().getStatusCode();
|
||||
if (statusCode != 200) {
|
||||
httpPost.abort();
|
||||
throw new RuntimeException("HttpClient,error status code :" + statusCode);
|
||||
}
|
||||
HttpEntity entity = response.getEntity();
|
||||
String result = null;
|
||||
if (entity != null) {
|
||||
result = EntityUtils.toString(entity, charset);
|
||||
}
|
||||
EntityUtils.consume(entity);
|
||||
if(!"UTF-8".equals(getEncoding(result))) result=GBKtoUTF8(result);
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (response != null)
|
||||
try {
|
||||
response.close();
|
||||
} catch (IOException e) {e.printStackTrace();}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
public static String doGet2(String url, Map<String, String> params, CookieStore cookie,Map<String, String> header,String charset) {
|
||||
if(charset==null||charset.trim().length()<1) charset="UTF-8";
|
||||
if (StringUtils.isBlank(url)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
if (params != null && !params.isEmpty()) {
|
||||
List<NameValuePair> pairs = new ArrayList<NameValuePair>(params.size());
|
||||
for (Map.Entry<String, String> entry : params.entrySet()) {
|
||||
String value = entry.getValue();
|
||||
if (value != null) {
|
||||
pairs.add(new BasicNameValuePair(entry.getKey(), value));
|
||||
}
|
||||
}
|
||||
url += "?" + EntityUtils.toString(new UrlEncodedFormEntity(pairs, charset));
|
||||
}
|
||||
HttpGet httpGet = new HttpGet(url);
|
||||
|
||||
Set<Entry<String, String>> set = header.entrySet();
|
||||
Iterator<Entry<String, String>> s = set.iterator();
|
||||
while (s.hasNext()) {
|
||||
Map.Entry m = (Map.Entry) s.next();
|
||||
httpGet.addHeader(m.getKey().toString(),m.getValue().toString());
|
||||
}
|
||||
|
||||
// https 注意这里获取https内容,使用了忽略证书的方式,当然还有其他的方式来获取https内容
|
||||
CloseableHttpClient httpsClient = HttpUtils.createSSLClientCookie(cookie);
|
||||
CloseableHttpResponse response = httpsClient.execute(httpGet);
|
||||
int statusCode = response.getStatusLine().getStatusCode();
|
||||
if (statusCode != 200) {
|
||||
httpGet.abort();
|
||||
throw new RuntimeException("HttpClient,error status code :" + statusCode);
|
||||
}
|
||||
HttpEntity entity = response.getEntity();
|
||||
String result = null;
|
||||
if (entity != null) {
|
||||
result = EntityUtils.toString(entity, charset);
|
||||
}
|
||||
EntityUtils.consume(entity);
|
||||
response.close();
|
||||
if(!"UTF-8".equals(getEncoding(result))) result=GBKtoUTF8(result);
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user