Skip to content

Commit

Permalink
Merge pull request #550 from Zhuoyuan1/main
Browse files Browse the repository at this point in the history
 Navicat链接导入
  • Loading branch information
Chat2DB-Pro authored Sep 24, 2023
2 parents 801c96c + 9201442 commit 3584f77
Show file tree
Hide file tree
Showing 14 changed files with 870 additions and 45 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package ai.chat2db.server.web.api.controller.ncx;

import ai.chat2db.server.tools.base.wrapper.result.DataResult;
import ai.chat2db.server.tools.common.util.ConfigUtils;
import ai.chat2db.server.web.api.controller.ncx.service.ConverterService;
import ai.chat2db.server.web.api.controller.ncx.vo.UploadVO;
import ai.chat2db.server.web.api.util.FileUtils;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.util.Objects;
import java.util.UUID;

/**
* ConverterController
*
* @author lzy
**/
@RequestMapping("/api/converter")
@RestController
@Slf4j
public class ConverterController {

@Autowired
private ConverterService converterService;

/**
* 导出教程
*
* @param file file
* @return DataResult<UploadVO>
* @see <a href="https://blog.csdn.net/kkk123445/article/details/122514124?spm=1001.2014.3001.5502" />
**/
@SneakyThrows
@PostMapping("/ncx/upload")
public DataResult<UploadVO> ncxUploadFile(@RequestParam("file") MultipartFile file) {
// 验证文件后缀
String fileExtension = FileUtils.getFileExtension(Objects.requireNonNull(file.getOriginalFilename()));
if (!fileExtension.equalsIgnoreCase(FileUtils.ConfigFile.NCX.name())) {
return DataResult.error("1", "上传的文件必须是ncx文件!");
}
File temp = new File(ConfigUtils.CONFIG_BASE_PATH + File.separator + UUID.randomUUID() + ".tmp");
file.transferTo(temp);
return DataResult.of(converterService.uploadFile(temp));
}

@SneakyThrows
@PostMapping("/dbp/upload")
public DataResult<UploadVO> dbpUploadFile(@RequestParam("file") MultipartFile file) {
// 验证文件后缀
String fileExtension = FileUtils.getFileExtension(Objects.requireNonNull(file.getOriginalFilename()));
if (!fileExtension.equalsIgnoreCase(FileUtils.ConfigFile.DBP.name())) {
return DataResult.error("1", "上传的文件必须是ncx文件!");
}
File temp = new File(ConfigUtils.CONFIG_BASE_PATH + File.separator + UUID.randomUUID() + ".tmp");
file.transferTo(temp);
return DataResult.of(converterService.dbpUploadFile(temp));
}


/**
* 导入datagrip的连接信息,通过 ctrl/cmd + c(shift多选)复制连接,再导入进来
* 目前复制的连接信息里面是没有密码的、ssh连接信息也没有
*
* @param text text
* @return DataResult<UploadVO>
**/
@SneakyThrows
@PostMapping("/datagrip/upload")
public DataResult<UploadVO> datagripUploadFile(@RequestParam("text") String text) {
return DataResult.of(converterService.datagripUploadFile(text));
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package ai.chat2db.server.web.api.controller.ncx.cipher;

import java.util.Formatter;

/**
* CommonCipher 公共加/解密
*
* @author lzy
*/
public abstract class CommonCipher {

public String encryptString(String plaintext) {
return null;
}

public String decryptString(String ciphertext) {
return null;
}

public String printHexBinary(byte[] data) {
StringBuilder hexBuilder = new StringBuilder();
Formatter formatter = new Formatter(hexBuilder);
for (byte b : data) {
formatter.format("%02x", b);
}
return hexBuilder.toString();
}

public static byte[] parseHexBinary(String data) {
return hexStringToByteArray(data);
}

public static byte[] hexStringToByteArray(String hex) {
if (hex.length() % 2 != 0) {
throw new IllegalArgumentException("Hex string length must be even");
}
byte[] bytes = new byte[hex.length() / 2];
for (int i = 0; i < hex.length(); i += 2) {
String byteString = hex.substring(i, i + 2);
bytes[i / 2] = (byte) Integer.parseInt(byteString, 16);
}
return bytes;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
package ai.chat2db.server.web.api.controller.ncx.cipher;

import org.apache.commons.lang3.StringUtils;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.Arrays;

/**
* Navicat11及以下密码加密解密
*
* @author lzy
*/
public class Navicat11Cipher extends CommonCipher {
public static final String DefaultUserKey = "3DC5CA39";
private static byte[] IV;

private static SecretKeySpec key;
private static Cipher encryptor;
private static Cipher decrypt;

private static void initKey() {
try {
MessageDigest sha1 = MessageDigest.getInstance("SHA1");
byte[] userKey_data = Navicat11Cipher.DefaultUserKey.getBytes(StandardCharsets.UTF_8);
sha1.update(userKey_data, 0, userKey_data.length);
key = new SecretKeySpec(sha1.digest(), "Blowfish");
} catch (Exception e) {
throw new RuntimeException(e);
}
}

private static void initCipherEncrypt() {
try {
// Must use NoPadding
encryptor = Cipher.getInstance("Blowfish/ECB/NoPadding");
encryptor.init(Cipher.ENCRYPT_MODE, key);
} catch (Exception e) {
throw new RuntimeException(e);
}
}

private static void initCipherDecrypt() {
try {
// Must use NoPadding
decrypt = Cipher.getInstance("Blowfish/ECB/NoPadding");
decrypt.init(Cipher.DECRYPT_MODE, key);
} catch (Exception e) {
throw new RuntimeException(e);
}
}

private static void initIV() {
try {
byte[] initVec = parseHexBinary("FFFFFFFFFFFFFFFF");
IV = encryptor.doFinal(initVec);
} catch (Exception e) {
throw new RuntimeException(e);
}
}

private void xorBytes(byte[] a, byte[] b) {
for (int i = 0; i < a.length; i++) {
int aVal = a[i] & 0xff; // convert byte to integer
int bVal = b[i] & 0xff;
a[i] = (byte) (aVal ^ bVal); // xor aVal and bVal and typecast to byte
}
}

private void xorBytes(byte[] a, byte[] b, int l) {
for (int i = 0; i < l; i++) {
int aVal = a[i] & 0xff; // convert byte to integer
int bVal = b[i] & 0xff;
a[i] = (byte) (aVal ^ bVal); // xor aVal and bVal and typecast to byte
}
}

static {
initKey();
initCipherEncrypt();
initCipherDecrypt();
initIV();
}

private byte[] Encrypt(byte[] inData) {
try {
byte[] CV = Arrays.copyOf(IV, IV.length);
byte[] ret = new byte[inData.length];

int blocks_len = inData.length / 8;
int left_len = inData.length % 8;

for (int i = 0; i < blocks_len; i++) {
byte[] temp = Arrays.copyOfRange(inData, i * 8, (i * 8) + 8);

xorBytes(temp, CV);
temp = encryptor.doFinal(temp);
xorBytes(CV, temp);

System.arraycopy(temp, 0, ret, i * 8, 8);
}

if (left_len != 0) {
CV = encryptor.doFinal(CV);
byte[] temp = Arrays.copyOfRange(inData, blocks_len * 8, (blocks_len * 8) + left_len);
xorBytes(temp, CV, left_len);
System.arraycopy(temp, 0, ret, blocks_len * 8, temp.length);
}

return ret;
} catch (Exception e) {
throw new RuntimeException(e);
}
}

@Override
public String encryptString(String inputString) {
try {
byte[] inData = inputString.getBytes(StandardCharsets.UTF_8);
byte[] outData = Encrypt(inData);
return printHexBinary(outData);
} catch (Exception e) {
throw new RuntimeException(e);
}
}

private byte[] Decrypt(byte[] inData) {
try {
byte[] cv = Arrays.copyOf(IV, IV.length);
byte[] ret = new byte[inData.length];

int blocks_len = inData.length / 8;
int left_len = inData.length % 8;

for (int i = 0; i < blocks_len; i++) {
byte[] temp = Arrays.copyOfRange(inData, i * 8, (i * 8) + 8);

temp = decrypt.doFinal(temp);
xorBytes(temp, cv);
System.arraycopy(temp, 0, ret, i * 8, 8);
for (int j = 0; j < cv.length; j++) {
cv[j] = (byte) (cv[j] ^ inData[i * 8 + j]);
}
}

if (left_len != 0) {
cv = encryptor.doFinal(cv);
byte[] temp = Arrays.copyOfRange(inData, blocks_len * 8, (blocks_len * 8) + left_len);

xorBytes(temp, cv, left_len);
for (int j = 0; j < temp.length; j++) {
ret[blocks_len * 8 + j] = temp[j];
}
}

return ret;
} catch (Exception e) {
throw new RuntimeException(e);
}
}

@Override
public String decryptString(String hexString) {
if (StringUtils.isEmpty(hexString)) {
return "";
}
try {
byte[] inData = parseHexBinary(hexString);
byte[] outData = Decrypt(inData);
return new String(outData, StandardCharsets.UTF_8);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package ai.chat2db.server.web.api.controller.ncx.cipher;

import org.apache.commons.lang3.StringUtils;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;

/**
* Navicat12及以上密码加密解密
*
* @author lzy
*/
public class Navicat12Cipher extends CommonCipher {
private static final SecretKeySpec AES_KEY;
private static final IvParameterSpec AES_IV;

static {
AES_KEY = new SecretKeySpec("libcckeylibcckey".getBytes(StandardCharsets.UTF_8), "AES");
AES_IV = new IvParameterSpec("libcciv libcciv ".getBytes(StandardCharsets.UTF_8));
}

@Override
public String encryptString(String plaintext) {
try {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, AES_KEY, AES_IV);
byte[] ret = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));
return printHexBinary(ret);
} catch (Exception e) {
throw new RuntimeException(e);
}
}

@Override
public String decryptString(String ciphertext) {
if (StringUtils.isEmpty(ciphertext)) {
return "";
}
try {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, AES_KEY, AES_IV);
byte[] ret = cipher.doFinal(parseHexBinary(ciphertext));
return new String(ret, StandardCharsets.UTF_8);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
Loading

0 comments on commit 3584f77

Please sign in to comment.