Gradle 添加私有仓库

# Gradle 添加私有仓库 以Android Studio为例 在build.gradle(Project)中添加maven{…},如下所示: buildscript { repositories { maven { url "https://maven.imcaoxuan.cn:8443/repository/public/" credentials { username = 'public' password = 'public' } } google() mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:7.0.4' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } } 在settings.gradle(Project)中添加maven{…},如下所示: dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { maven { url "https://maven.imcaoxuan.cn:8443/repository/public/" credentials { username = 'public' password = 'public' } } google() mavenCentral() jcenter() // Warning: this repository is going to shut down soon } } 3.Sync now!

August 25, 2022 · 1 min

转发:解决warning: LF will be replaced by CRLF in方法

[https://blog.csdn.net/chenxijie1985/article/details/107759826][1] 在windows下add代码时一直提示:warning: LF will be replaced by CRLF in,虽然没多大影响,但是看得不爽。 解决办法: git config –global core.autocrlf false

August 21, 2022 · 1 min

转发:Ubuntu 创建 RAID1 阵列

转发:https://www.jianshu.com/p/3e6d5da2db81 # 列出所有磁盘信息 $ sudo fdisk -l # 建立分区 $ sudo fdisk /dev/sdb # 然后依次输入 $ n (新建分区表) $ p (主分区,然后根据提示操作) $ w (保存分区信息) $ sudo mdadm --create --verbose /dev/md0 --level=1 --raid-devices=2 /dev/sdb1 /dev/sdc1 mdadm: Note: this array has metadata at the start and may not be suitable as a boot device. If you plan to store '/boot' on this device please ensure that your boot-loader understands md/v1.x metadata, or use --metadata=0.90 mdadm: size set to 20953088K Continue creating array? y mdadm: Defaulting to version 1.2 metadata mdadm: array /dev/md0 started.

July 24, 2022 · 1 min

JAVA_HOME

# JAVA_HOME #JAVA_HOME export JAVA_HOME=/opt/jdk1.8.0_201 export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib export PATH=${JAVA_HOME}/bin:$PATH

July 17, 2022 · 1 min

定时任务

# 定时任务 example: */1 * * * * /home/admin/traffic.sh echo > /home/admin/log/traffic.log

July 17, 2022 · 1 min

Ubuntu修改代理

# Ubuntu修改代理 vim /etc/apt/apt.conf.d/90curtin-aptproxy 然后…

July 17, 2022 · 1 min

整合代码:TOTP+Hex+Base32

代码引用:org.apache.commons.codec.binary.Base32, org.apache.commons.codec.binary.Hex, TOTP(Johan Rydell, PortWise, Inc) import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import java.lang.reflect.UndeclaredThrowableException; import java.math.BigInteger; import java.nio.charset.StandardCharsets; import java.security.GeneralSecurityException; import java.util.Arrays; public class TotpDemo { private static final int[] DIGITS_POWER // 0 1 2 3 4 5 6 7 8 = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000}; public static void main(String[] args) { // todo String secretKey = ""; Base32 base32 = new Base32(); byte[] bytes = base32.decode(secretKey.toUpperCase()); // [-84, -88, -126, -19, 116, -72, -61, -58, 117, 53] String hexKey = Hex.encodeHexString(bytes); String hexTime = Long.toHexString(System.currentTimeMillis() / 30 / 1000); System.out.println(generateTOTP(hexKey, hexTime, "6")); } static class Hex { public static String encodeHexString(final byte[] data) { return new String(encodeHex(data)); } public static char[] encodeHex(final byte[] data) { return encodeHex(data, true); } public static char[] encodeHex(final byte[] data, final boolean toLowerCase) { return encodeHex(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER); } protected static char[] encodeHex(final byte[] data, final char[] toDigits) { final int l = data.length; final char[] out = new char[l << 1]; // two characters form the hex value. for (int i = 0, j = 0; i < l; i++) { out[j++] = toDigits[(0xF0 & data[i]) >>> 4]; out[j++] = toDigits[0x0F & data[i]]; } return out; } private static final char[] DIGITS_LOWER = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; /** * Used to build output as Hex */ private static final char[] DIGITS_UPPER = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; } public static String generateTOTP(String key, String time, String returnDigits) { return generateTOTP(key, time, returnDigits, "HmacSHA1"); } private static byte[] hmac_sha1(String crypto, byte[] keyBytes, byte[] text) { try { Mac hmac; hmac = Mac.getInstance(crypto); SecretKeySpec macKey = new SecretKeySpec(keyBytes, "RAW"); hmac.init(macKey); return hmac.doFinal(text); } catch (GeneralSecurityException gse) { throw new UndeclaredThrowableException(gse); } } private static byte[] hexStr2Bytes(String hex) { // Adding one byte to get the right conversion // values starting with "0" can be converted byte[] bArray = new BigInteger("10" + hex, 16).toByteArray(); // Copy all the REAL bytes, not the "first" byte[] ret = new byte[bArray.length - 1]; for (int i = 0; i < ret.length; i++) ret[i] = bArray[i + 1]; return ret; } private static String generateTOTP(String key, String time, String returnDigits, String crypto) { int codeDigits = Integer.decode(returnDigits).intValue(); String result; byte[] hash; // Using the counter // First 8 bytes are for the movingFactor // Complaint with base RFC 4226 (HOTP) while (time.length() < 16) time = "0" + time; // Get the HEX in a Byte[] byte[] msg = hexStr2Bytes(time); // Adding one byte to get the right conversion byte[] k = hexStr2Bytes(key); hash = hmac_sha1(crypto, k, msg); // put selected bytes into result int int offset = hash[hash.length - 1] & 0xf; int binary = ((hash[offset] & 0x7f) << 24) | ((hash[offset + 1] & 0xff) << 16) | ((hash[offset + 2] & 0xff) << 8) | (hash[offset + 3] & 0xff); int otp = binary % DIGITS_POWER[codeDigits]; result = Integer.toString(otp); while (result.length() < codeDigits) { result = "0" + result; } return result; } static abstract class BaseNCodec { static final int EOF = -1; protected final byte pad; protected static final int MASK_8BITS = 0xff; protected static final byte PAD_DEFAULT = '='; // Allow static access to default private final int unencodedBlockSize; /** * Number of bytes in each full block of encoded data, e.g. 3 for Base64 and 8 for Base32 */ private final int encodedBlockSize; protected final int lineLength; /** * Size of chunk separator. Not used unless {@link #lineLength} &gt; 0. */ private final int chunkSeparatorLength; protected BaseNCodec(final int unencodedBlockSize, final int encodedBlockSize, final int lineLength, final int chunkSeparatorLength, final byte pad) { this.unencodedBlockSize = unencodedBlockSize; this.encodedBlockSize = encodedBlockSize; final boolean useChunking = lineLength > 0 && chunkSeparatorLength > 0; this.lineLength = useChunking ? (lineLength / encodedBlockSize) * encodedBlockSize : 0; this.chunkSeparatorLength = chunkSeparatorLength; this.pad = pad; } public byte[] decode(final String pArray) { return decode(pArray.getBytes(StandardCharsets.UTF_8)); } public byte[] decode(final byte[] pArray) { if (pArray == null || pArray.length == 0) { return pArray; } final Context context = new Context(); decode(pArray, 0, pArray.length, context); decode(pArray, 0, EOF, context); // Notify decoder of EOF. final byte[] result = new byte[context.pos]; readResults(result, 0, result.length, context); return result; } abstract void decode(byte[] pArray, int i, int length, Context context); int readResults(final byte[] b, final int bPos, final int bAvail, final Context context) { if (context.buffer != null) { final int len = Math.min(available(context), bAvail); System.arraycopy(context.buffer, context.readPos, b, bPos, len); context.readPos += len; if (context.readPos >= context.pos) { context.buffer = null; // so hasData() will return false, and this method can return -1 } return len; } return context.eof ? EOF : 0; } int available(final Context context) { // package protected for access from I/O streams return context.buffer != null ? context.pos - context.readPos : 0; } protected byte[] ensureBufferSize(int size, Context context) { if (context.buffer == null) { context.buffer = new byte[this.getDefaultBufferSize()]; context.pos = 0; context.readPos = 0; } else if (context.pos + size - context.buffer.length > 0) { return resizeBuffer(context, context.pos + size); } return context.buffer; } protected int getDefaultBufferSize() { return 8192; } private static byte[] resizeBuffer(Context context, int minCapacity) { int oldCapacity = context.buffer.length; int newCapacity = oldCapacity * 2; if (compareUnsigned(newCapacity, minCapacity) < 0) { newCapacity = minCapacity; } if (compareUnsigned(newCapacity, 2147483639) > 0) { newCapacity = createPositiveCapacity(minCapacity); } byte[] b = new byte[newCapacity]; System.arraycopy(context.buffer, 0, b, 0, context.buffer.length); context.buffer = b; return b; } private static int compareUnsigned(int x, int y) { return Integer.compare(x + -2147483648, y + -2147483648); } private static int createPositiveCapacity(int minCapacity) { if (minCapacity < 0) { throw new OutOfMemoryError("Unable to allocate array size: " + ((long) minCapacity & 4294967295L)); } else { return minCapacity > 2147483639 ? minCapacity : 2147483639; } } protected boolean containsAlphabetOrPad(final byte[] arrayOctet) { if (arrayOctet == null) { return false; } for (final byte element : arrayOctet) { if (pad == element || isInAlphabet(element)) { return true; } } return false; } protected abstract boolean isInAlphabet(byte value); protected static boolean isWhiteSpace(final byte byteToCheck) { switch (byteToCheck) { case ' ': case '\n': case '\r': case '\t': return true; default: return false; } } static class Context { int ibitWorkArea; long lbitWorkArea; byte[] buffer; int pos; int readPos; boolean eof; int currentLinePos; int modulus; Context() { } public String toString() { return String.format("%s[buffer=%s, currentLinePos=%s, eof=%s, ibitWorkArea=%s, lbitWorkArea=%s, modulus=%s, pos=%s, readPos=%s]", this.getClass().getSimpleName(), Arrays.toString(this.buffer), this.currentLinePos, this.eof, this.ibitWorkArea, this.lbitWorkArea, this.modulus, this.pos, this.readPos); } } } static class Base32 extends TotpForXuandembp.BaseNCodec { private final int decodeSize; private final int encodeSize; private final byte[] decodeTable; private final byte[] encodeTable; private final byte[] lineSeparator; private static final int BITS_PER_ENCODED_BYTE = 5; private static final int BYTES_PER_ENCODED_BLOCK = 8; private static final int BYTES_PER_UNENCODED_BLOCK = 5; private static final long MASK_2BITS = 0x03L; private static final long MASK_7BITS = 0x7fL; /** * Mask used to extract 6 bits, used when decoding final trailing character. */ private static final long MASK_6BITS = 0x3fL; /** * Mask used to extract 5 bits, used when encoding Base32 bytes */ private static final int MASK_5BITS = 0x1f; /** * Mask used to extract 4 bits, used when decoding final trailing character. */ private static final long MASK_4BITS = 0x0fL; /** * Mask used to extract 3 bits, used when decoding final trailing character. */ private static final long MASK_3BITS = 0x07L; /** Mask used to extract 2 bits, used when decoding final trailing character. */ /** * Mask used to extract 1 bits, used when decoding final trailing character. */ private static final long MASK_1BITS = 0x01L; public Base32() { this(false); } public Base32(final boolean useHex) { this(0, null, useHex, PAD_DEFAULT); } public Base32(final int lineLength, final byte[] lineSeparator, final boolean useHex, final byte pad) { super(BYTES_PER_UNENCODED_BLOCK, BYTES_PER_ENCODED_BLOCK, lineLength, lineSeparator == null ? 0 : lineSeparator.length, pad); if (useHex) { this.encodeTable = HEX_ENCODE_TABLE; this.decodeTable = HEX_DECODE_TABLE; } else { this.encodeTable = ENCODE_TABLE; this.decodeTable = DECODE_TABLE; } if (lineLength > 0) { if (lineSeparator == null) { throw new IllegalArgumentException("lineLength " + lineLength + " > 0, but lineSeparator is null"); } // Must be done after initializing the tables if (containsAlphabetOrPad(lineSeparator)) { final String sep = new String(lineSeparator, StandardCharsets.UTF_8); throw new IllegalArgumentException("lineSeparator must not contain Base32 characters: [" + sep + "]"); } this.encodeSize = BYTES_PER_ENCODED_BLOCK + lineSeparator.length; this.lineSeparator = new byte[lineSeparator.length]; System.arraycopy(lineSeparator, 0, this.lineSeparator, 0, lineSeparator.length); } else { this.encodeSize = BYTES_PER_ENCODED_BLOCK; this.lineSeparator = null; } this.decodeSize = this.encodeSize - 1; if (isInAlphabet(pad) || isWhiteSpace(pad)) { throw new IllegalArgumentException("pad must not be in alphabet or whitespace"); } } private static final byte[] HEX_DECODE_TABLE = { // 0 1 2 3 4 5 6 7 8 9 A B C D E F -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 00-0f -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 10-1f -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 20-2f 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, // 30-3f 2-7 -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, // 40-4f A-O 25, 26, 27, 28, 29, 30, 31, // 50-56 P-V -1, -1, -1, -1, -1, -1, -1, -1, -1, // 57-5f Z-_ -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, // 60-6f `-o 25, 26, 27, 28, 29, 30, 31 // 70-76 p-v }; /** * This array is a lookup table that translates 5-bit positive integer index values into their * "Base32 Hex Alphabet" equivalents as specified in Table 4 of RFC 4648. */ private static final byte[] HEX_ENCODE_TABLE = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', }; private static final byte[] DECODE_TABLE = { // 0 1 2 3 4 5 6 7 8 9 A B C D E F -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 00-0f -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 10-1f -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 20-2f -1, -1, 26, 27, 28, 29, 30, 31, -1, -1, -1, -1, -1, -1, -1, -1, // 30-3f 2-7 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 40-4f A-O 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // 50-5a P-Z -1, -1, -1, -1, -1, // 5b - 5f -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 60 - 6f a-o 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // 70 - 7a p-z/**/ }; /** * This array is a lookup table that translates 5-bit positive integer index values into their "Base32 Alphabet" * equivalents as specified in Table 3 of RFC 4648. */ private static final byte[] ENCODE_TABLE = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '2', '3', '4', '5', '6', '7', }; private static void validateCharacter(final long emptyBitsMask, final Context context) { // Use the long bit work area if ((context.lbitWorkArea & emptyBitsMask) != 0) { throw new IllegalArgumentException( "Last encoded character (before the paddings if any) is a valid base 32 alphabet but not a possible value. " + "Expected the discarded bits to be zero."); } } void decode(final byte[] input, int inPos, final int inAvail, final Context context) { // package protected for access from I/O streams if (context.eof) { return; } if (inAvail < 0) { context.eof = true; } for (int i = 0; i < inAvail; i++) { final byte b = input[inPos++]; if (b == pad) { // We're done. context.eof = true; break; } final byte[] buffer = ensureBufferSize(decodeSize, context); if (b >= 0 && b < this.decodeTable.length) { final int result = this.decodeTable[b]; if (result >= 0) { context.modulus = (context.modulus + 1) % BYTES_PER_ENCODED_BLOCK; // collect decoded bytes context.lbitWorkArea = (context.lbitWorkArea << BITS_PER_ENCODED_BYTE) + result; if (context.modulus == 0) { // we can output the 5 bytes buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 32) & MASK_8BITS); buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 24) & MASK_8BITS); buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 16) & MASK_8BITS); buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 8) & MASK_8BITS); buffer[context.pos++] = (byte) (context.lbitWorkArea & MASK_8BITS); } } } } // Two forms of EOF as far as Base32 decoder is concerned: actual // EOF (-1) and first time '=' character is encountered in stream. // This approach makes the '=' padding characters completely optional. if (context.eof && context.modulus >= 2) { // if modulus < 2, nothing to do final byte[] buffer = ensureBufferSize(decodeSize, context); // we ignore partial bytes, i.e. only multiples of 8 count switch (context.modulus) { case 2: // 10 bits, drop 2 and output one byte validateCharacter(MASK_2BITS, context); buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 2) & MASK_8BITS); break; case 3: // 15 bits, drop 7 and output 1 byte validateCharacter(MASK_7BITS, context); buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 7) & MASK_8BITS); break; case 4: // 20 bits = 2*8 + 4 validateCharacter(MASK_4BITS, context); context.lbitWorkArea = context.lbitWorkArea >> 4; // drop 4 bits buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 8) & MASK_8BITS); buffer[context.pos++] = (byte) ((context.lbitWorkArea) & MASK_8BITS); break; case 5: // 25bits = 3*8 + 1 validateCharacter(MASK_1BITS, context); context.lbitWorkArea = context.lbitWorkArea >> 1; buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 16) & MASK_8BITS); buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 8) & MASK_8BITS); buffer[context.pos++] = (byte) ((context.lbitWorkArea) & MASK_8BITS); break; case 6: // 30bits = 3*8 + 6 validateCharacter(MASK_6BITS, context); context.lbitWorkArea = context.lbitWorkArea >> 6; buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 16) & MASK_8BITS); buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 8) & MASK_8BITS); buffer[context.pos++] = (byte) ((context.lbitWorkArea) & MASK_8BITS); break; case 7: // 35 = 4*8 +3 validateCharacter(MASK_3BITS, context); context.lbitWorkArea = context.lbitWorkArea >> 3; buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 24) & MASK_8BITS); buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 16) & MASK_8BITS); buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 8) & MASK_8BITS); buffer[context.pos++] = (byte) ((context.lbitWorkArea) & MASK_8BITS); break; default: // modulus can be 0-7, and we excluded 0,1 already throw new IllegalStateException("Impossible modulus " + context.modulus); } } } @Override protected boolean isInAlphabet(byte octet) { return octet >= 0 && octet < decodeTable.length && decodeTable[octet] != -1; } } }

March 22, 2022 · 12 min

转发:nginx反向代理websocket返回403

原文:[Solution of nginx reverse proxy websocket response 403][1] The log accessed through nginx has the following entry: DEBUG ... o.s.w.s.s.s.OriginHandshakeInterceptor : Handshake request rejected, Origin header value https://some-host.com not allowed Then Google queries related solutions to find the issue on GitHub, so you only need to modify the configuration of nginx and addproxy_set_header Origin “";That’s it. http { //SSL related configuration map $http_upgrade $connection_upgrade { default upgrade; '' close; } server { listen 8020; location /ws { proxy_pass http://some-ip:8080; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; proxy_set_header Origin ""; } } 在我的access.log中并未发现关于“Origin”的信息,但是按照此方案修改配置文件后却可以解决问题。 [1]: https://developpaper.com/solution-of-nginx-reverse-proxy-websocket-response-403/

February 9, 2022 · 1 min

复习:StringBuilder和String拼接字符串效率差距真大

今天在解析一个5M的文本文件时,耗时两分多钟,找了半天才发现原因是使用String += s的方式拼接字符串导致的。 换成StringBuilder后速度提升了4个数量级! 至于原因,大家应该都懂,我就不再赘述了。 基础不能忘!!! 基础不能忘!!! 基础不能忘!!!

January 23, 2022 · 1 min

转载:一个好用的zip库zip4j

原文:[what-is-a-good-java-library-to-zip-unzip-files][1] Demo:@user2003470 import net.lingala.zip4j.exception.ZipException; import net.lingala.zip4j.core.ZipFile; public static void unzip(){ String source = "some/compressed/file.zip"; String destination = "some/destination/folder"; String password = "password"; try { ZipFile zipFile = new ZipFile(source); if (zipFile.isEncrypted()) { zipFile.setPassword(password); } zipFile.extractAll(destination); } catch (ZipException e) { e.printStackTrace(); } } The Maven dependency is: <dependency> <groupId>net.lingala.zip4j</groupId> <artifactId>zip4j</artifactId> <version>1.3.2</version> </dependency>

January 23, 2022 · 1 min