mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-19 21:03:48 -07:00
style
This commit is contained in:
parent
f5bff0d4e5
commit
2b25d86392
6 changed files with 68 additions and 68 deletions
|
@ -461,10 +461,10 @@ int CmdPrintDemodBuff(const char *Cmd) {
|
||||||
if (invert) {
|
if (invert) {
|
||||||
char *buf = (char *)(DemodBuffer + offset);
|
char *buf = (char *)(DemodBuffer + offset);
|
||||||
for (uint32_t i = 0; i < length; i++) {
|
for (uint32_t i = 0; i < length; i++) {
|
||||||
if ( buf[i] == 1 )
|
if (buf[i] == 1)
|
||||||
buf[i] = 0;
|
buf[i] = 0;
|
||||||
else {
|
else {
|
||||||
if ( buf[i] == 0 )
|
if (buf[i] == 0)
|
||||||
buf[i] = 1;
|
buf[i] = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -876,12 +876,12 @@ static int CmdHFiClassDecrypt(const char *Cmd) {
|
||||||
|
|
||||||
uint8_t dec_data[8] = {0};
|
uint8_t dec_data[8] = {0};
|
||||||
|
|
||||||
if ( have_data ) {
|
if (have_data) {
|
||||||
mbedtls_des3_crypt_ecb(&ctx, enc_data, dec_data);
|
mbedtls_des3_crypt_ecb(&ctx, enc_data, dec_data);
|
||||||
PrintAndLogEx(SUCCESS, "Data: %s", sprint_hex(dec_data, sizeof(dec_data)));
|
PrintAndLogEx(SUCCESS, "Data: %s", sprint_hex(dec_data, sizeof(dec_data)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( have_file ) {
|
if (have_file) {
|
||||||
picopass_hdr *hdr = (picopass_hdr *)decrypted;
|
picopass_hdr *hdr = (picopass_hdr *)decrypted;
|
||||||
|
|
||||||
uint8_t mem = hdr->conf.mem_config;
|
uint8_t mem = hdr->conf.mem_config;
|
||||||
|
@ -1019,7 +1019,7 @@ static bool select_only(uint8_t *CSN, uint8_t *CCNR, bool use_credit_key, bool v
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isOK <= 1) {
|
if (isOK <= 1) {
|
||||||
if ( verbose )
|
if (verbose)
|
||||||
PrintAndLogEx(FAILED, "failed to obtain CC! Tag-select is aborting... (%d)", isOK);
|
PrintAndLogEx(FAILED, "failed to obtain CC! Tag-select is aborting... (%d)", isOK);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -1056,7 +1056,7 @@ static bool select_and_auth(uint8_t *KEY, uint8_t *MAC, uint8_t *div_key, bool u
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( resp.status != PM3_SUCCESS ) {
|
if (resp.status != PM3_SUCCESS) {
|
||||||
if (verbose) PrintAndLogEx(ERR, "failed to communicate with card");
|
if (verbose) PrintAndLogEx(ERR, "failed to communicate with card");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1213,7 +1213,7 @@ static int CmdHFiClassReader_Dump(const char *Cmd) {
|
||||||
break;
|
break;
|
||||||
} while (numberAuthRetries--);
|
} while (numberAuthRetries--);
|
||||||
|
|
||||||
if ( numberAuthRetries <= 0) {
|
if (numberAuthRetries <= 0) {
|
||||||
PrintAndLogEx(WARNING, "failed authenticating with debit key");
|
PrintAndLogEx(WARNING, "failed authenticating with debit key");
|
||||||
DropField();
|
DropField();
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
|
@ -1271,7 +1271,7 @@ static int CmdHFiClassReader_Dump(const char *Cmd) {
|
||||||
break;
|
break;
|
||||||
} while (numberAuthRetries--);
|
} while (numberAuthRetries--);
|
||||||
|
|
||||||
if ( numberAuthRetries <= 0) {
|
if (numberAuthRetries <= 0) {
|
||||||
PrintAndLogEx(WARNING, "failed authenticating with credit key");
|
PrintAndLogEx(WARNING, "failed authenticating with credit key");
|
||||||
DropField();
|
DropField();
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
|
@ -1363,7 +1363,7 @@ static int WriteBlock(uint8_t blockno, uint8_t *bldata, uint8_t *KEY, bool use_c
|
||||||
memcpy(payload.data + 8, MAC, 4);
|
memcpy(payload.data + 8, MAC, 4);
|
||||||
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommandNG(CMD_HF_ICLASS_WRITEBL, (uint8_t*)&payload, sizeof(payload));
|
SendCommandNG(CMD_HF_ICLASS_WRITEBL, (uint8_t *)&payload, sizeof(payload));
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
|
|
||||||
if (WaitForResponseTimeout(CMD_HF_ICLASS_WRITEBL, &resp, 4000) == 0) {
|
if (WaitForResponseTimeout(CMD_HF_ICLASS_WRITEBL, &resp, 4000) == 0) {
|
||||||
|
@ -1372,7 +1372,7 @@ static int WriteBlock(uint8_t blockno, uint8_t *bldata, uint8_t *KEY, bool use_c
|
||||||
return PM3_ETIMEOUT;
|
return PM3_ETIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( resp.status != PM3_SUCCESS ) {
|
if (resp.status != PM3_SUCCESS) {
|
||||||
if (verbose) PrintAndLogEx(ERR, "failed to communicate with card");
|
if (verbose) PrintAndLogEx(ERR, "failed to communicate with card");
|
||||||
DropField();
|
DropField();
|
||||||
return PM3_EWRONGANSVER;
|
return PM3_EWRONGANSVER;
|
||||||
|
@ -1385,10 +1385,10 @@ static int WriteBlock(uint8_t blockno, uint8_t *bldata, uint8_t *KEY, bool use_c
|
||||||
|
|
||||||
DropField();
|
DropField();
|
||||||
|
|
||||||
if ( numberAuthRetries > 0 ) {
|
if (numberAuthRetries > 0) {
|
||||||
PrintAndLogEx(SUCCESS, "Write block %02X successful\n", blockno);
|
PrintAndLogEx(SUCCESS, "Write block %02X successful\n", blockno);
|
||||||
} else {
|
} else {
|
||||||
PrintAndLogEx(ERR,"failed to authenticate and write block");
|
PrintAndLogEx(ERR, "failed to authenticate and write block");
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1442,7 +1442,7 @@ static int CmdHFiClass_WriteBlock(const char *Cmd) {
|
||||||
} else if (dataLen == 1) {
|
} else if (dataLen == 1) {
|
||||||
keyNbr = param_get8(Cmd, cmdp + 1);
|
keyNbr = param_get8(Cmd, cmdp + 1);
|
||||||
if (keyNbr < ICLASS_KEYS_MAX) {
|
if (keyNbr < ICLASS_KEYS_MAX) {
|
||||||
PrintAndLogEx(SUCCESS, "Using key[%d] %s", keyNbr, sprint_hex(iClass_Key_Table[keyNbr], 8 ));
|
PrintAndLogEx(SUCCESS, "Using key[%d] %s", keyNbr, sprint_hex(iClass_Key_Table[keyNbr], 8));
|
||||||
memcpy(KEY, iClass_Key_Table[keyNbr], 8);
|
memcpy(KEY, iClass_Key_Table[keyNbr], 8);
|
||||||
} else {
|
} else {
|
||||||
PrintAndLogEx(WARNING, "\nERROR: Credit KeyNbr is invalid\n");
|
PrintAndLogEx(WARNING, "\nERROR: Credit KeyNbr is invalid\n");
|
||||||
|
@ -1469,7 +1469,7 @@ static int CmdHFiClass_WriteBlock(const char *Cmd) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( got_blockno == false)
|
if (got_blockno == false)
|
||||||
errors = true;
|
errors = true;
|
||||||
|
|
||||||
if (errors || cmdp < 6) return usage_hf_iclass_writeblock();
|
if (errors || cmdp < 6) return usage_hf_iclass_writeblock();
|
||||||
|
@ -1527,7 +1527,7 @@ static int CmdHFiClassCloneTag(const char *Cmd) {
|
||||||
} else if (dataLen == 1) {
|
} else if (dataLen == 1) {
|
||||||
keyNbr = param_get8(Cmd, cmdp + 1);
|
keyNbr = param_get8(Cmd, cmdp + 1);
|
||||||
if (keyNbr < ICLASS_KEYS_MAX) {
|
if (keyNbr < ICLASS_KEYS_MAX) {
|
||||||
PrintAndLogEx(SUCCESS, "Using key[%d] %s", keyNbr, sprint_hex(iClass_Key_Table[keyNbr], 8 ));
|
PrintAndLogEx(SUCCESS, "Using key[%d] %s", keyNbr, sprint_hex(iClass_Key_Table[keyNbr], 8));
|
||||||
memcpy(KEY, iClass_Key_Table[keyNbr], 8);
|
memcpy(KEY, iClass_Key_Table[keyNbr], 8);
|
||||||
} else {
|
} else {
|
||||||
PrintAndLogEx(WARNING, "\nERROR: Credit KeyNbr is invalid\n");
|
PrintAndLogEx(WARNING, "\nERROR: Credit KeyNbr is invalid\n");
|
||||||
|
@ -1559,7 +1559,7 @@ static int CmdHFiClassCloneTag(const char *Cmd) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( got_endblk == false || got_startblk == false)
|
if (got_endblk == false || got_startblk == false)
|
||||||
errors = true;
|
errors = true;
|
||||||
|
|
||||||
if (errors || cmdp < 8) return usage_hf_iclass_clone();
|
if (errors || cmdp < 8) return usage_hf_iclass_clone();
|
||||||
|
@ -1608,7 +1608,7 @@ static int CmdHFiClassCloneTag(const char *Cmd) {
|
||||||
break;
|
break;
|
||||||
} while (numberAuthRetries--);
|
} while (numberAuthRetries--);
|
||||||
|
|
||||||
if ( numberAuthRetries <= 0 ) {
|
if (numberAuthRetries <= 0) {
|
||||||
PrintAndLogEx(ERR, "failed to authenticate");
|
PrintAndLogEx(ERR, "failed to authenticate");
|
||||||
DropField();
|
DropField();
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
|
@ -1629,17 +1629,17 @@ static int CmdHFiClassCloneTag(const char *Cmd) {
|
||||||
memcpy(ptr + 8, MAC, 4);
|
memcpy(ptr + 8, MAC, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( verbose ) {
|
if (verbose) {
|
||||||
PrintAndLogEx(NORMAL,"------+--------------------------+-------------");
|
PrintAndLogEx(NORMAL, "------+--------------------------+-------------");
|
||||||
PrintAndLogEx(NORMAL,"block | data | mac");
|
PrintAndLogEx(NORMAL, "block | data | mac");
|
||||||
PrintAndLogEx(NORMAL,"------+--------------------------+-------------");
|
PrintAndLogEx(NORMAL, "------+--------------------------+-------------");
|
||||||
uint8_t p[12];
|
uint8_t p[12];
|
||||||
for (i = 0; i <= endblock - startblock; i++) {
|
for (i = 0; i <= endblock - startblock; i++) {
|
||||||
memcpy(p, data + (i * 12), 12);
|
memcpy(p, data + (i * 12), 12);
|
||||||
char *s = calloc(70, sizeof(uint8_t));
|
char *s = calloc(70, sizeof(uint8_t));
|
||||||
sprintf(s, "| %s ", sprint_hex(p, 8));
|
sprintf(s, "| %s ", sprint_hex(p, 8));
|
||||||
sprintf(s + strlen(s), "| %s", sprint_hex(p + 8, 4));
|
sprintf(s + strlen(s), "| %s", sprint_hex(p + 8, 4));
|
||||||
PrintAndLogEx(NORMAL, " %02X %s", i + startblock, s );
|
PrintAndLogEx(NORMAL, " %02X %s", i + startblock, s);
|
||||||
free(s);
|
free(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1656,7 +1656,7 @@ static int CmdHFiClassCloneTag(const char *Cmd) {
|
||||||
|
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommandNG(CMD_HF_ICLASS_CLONE, (uint8_t*)&payload, total_bytes + 2 );
|
SendCommandNG(CMD_HF_ICLASS_CLONE, (uint8_t *)&payload, total_bytes + 2);
|
||||||
|
|
||||||
if (WaitForResponseTimeout(CMD_HF_ICLASS_CLONE, &resp, 4500) == 0) {
|
if (WaitForResponseTimeout(CMD_HF_ICLASS_CLONE, &resp, 4500) == 0) {
|
||||||
PrintAndLogEx(WARNING, "command execute timeout");
|
PrintAndLogEx(WARNING, "command execute timeout");
|
||||||
|
@ -1665,7 +1665,7 @@ static int CmdHFiClassCloneTag(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resp.status == PM3_SUCCESS) {
|
if (resp.status == PM3_SUCCESS) {
|
||||||
if ( resp.data.asBytes[0] == 1 )
|
if (resp.data.asBytes[0] == 1)
|
||||||
PrintAndLogEx(SUCCESS, "Clone successful");
|
PrintAndLogEx(SUCCESS, "Clone successful");
|
||||||
else
|
else
|
||||||
PrintAndLogEx(WARNING, "Clone failed");
|
PrintAndLogEx(WARNING, "Clone failed");
|
||||||
|
@ -1706,7 +1706,7 @@ static int ReadBlock(uint8_t *KEY, uint8_t blockno, uint8_t keyType, bool elite,
|
||||||
|
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommandNG(CMD_HF_ICLASS_READBL, (uint8_t*)&blockno, sizeof(uint8_t));
|
SendCommandNG(CMD_HF_ICLASS_READBL, (uint8_t *)&blockno, sizeof(uint8_t));
|
||||||
|
|
||||||
if (WaitForResponseTimeout(CMD_HF_ICLASS_READBL, &resp, 2000) == 0) {
|
if (WaitForResponseTimeout(CMD_HF_ICLASS_READBL, &resp, 2000) == 0) {
|
||||||
if (verbose) PrintAndLogEx(WARNING, "Command execute timeout");
|
if (verbose) PrintAndLogEx(WARNING, "Command execute timeout");
|
||||||
|
@ -1714,13 +1714,13 @@ static int ReadBlock(uint8_t *KEY, uint8_t blockno, uint8_t keyType, bool elite,
|
||||||
return PM3_ETIMEOUT;
|
return PM3_ETIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( resp.status != PM3_SUCCESS ) {
|
if (resp.status != PM3_SUCCESS) {
|
||||||
if (verbose) PrintAndLogEx(ERR, "failed to communicate with card");
|
if (verbose) PrintAndLogEx(ERR, "failed to communicate with card");
|
||||||
DropField();
|
DropField();
|
||||||
return PM3_EWRONGANSVER;
|
return PM3_EWRONGANSVER;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = (struct p*)resp.data.asBytes;
|
result = (struct p *)resp.data.asBytes;
|
||||||
if (result->isOK)
|
if (result->isOK)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1728,8 +1728,8 @@ static int ReadBlock(uint8_t *KEY, uint8_t blockno, uint8_t keyType, bool elite,
|
||||||
|
|
||||||
DropField();
|
DropField();
|
||||||
|
|
||||||
if ( numberAuthRetries == 0 ) {
|
if (numberAuthRetries == 0) {
|
||||||
PrintAndLogEx(ERR,"failed to authenticate and read block");
|
PrintAndLogEx(ERR, "failed to authenticate and read block");
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1778,7 +1778,7 @@ static int CmdHFiClass_ReadBlock(const char *Cmd) {
|
||||||
} else if (dataLen == 1) {
|
} else if (dataLen == 1) {
|
||||||
keyNbr = param_get8(Cmd, cmdp + 1);
|
keyNbr = param_get8(Cmd, cmdp + 1);
|
||||||
if (keyNbr < ICLASS_KEYS_MAX) {
|
if (keyNbr < ICLASS_KEYS_MAX) {
|
||||||
PrintAndLogEx(SUCCESS, "Using key[%d] %s", keyNbr, sprint_hex(iClass_Key_Table[keyNbr], 8 ));
|
PrintAndLogEx(SUCCESS, "Using key[%d] %s", keyNbr, sprint_hex(iClass_Key_Table[keyNbr], 8));
|
||||||
memcpy(KEY, iClass_Key_Table[keyNbr], 8);
|
memcpy(KEY, iClass_Key_Table[keyNbr], 8);
|
||||||
} else {
|
} else {
|
||||||
PrintAndLogEx(WARNING, "\nERROR: Credit KeyNbr is invalid\n");
|
PrintAndLogEx(WARNING, "\nERROR: Credit KeyNbr is invalid\n");
|
||||||
|
@ -1805,7 +1805,7 @@ static int CmdHFiClass_ReadBlock(const char *Cmd) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( got_blockno == false)
|
if (got_blockno == false)
|
||||||
errors = true;
|
errors = true;
|
||||||
|
|
||||||
if (errors || cmdp < 4) return usage_hf_iclass_readblock();
|
if (errors || cmdp < 4) return usage_hf_iclass_readblock();
|
||||||
|
@ -2815,8 +2815,8 @@ int readIclass(bool loop, bool verbose) {
|
||||||
// no tag found or button pressed
|
// no tag found or button pressed
|
||||||
if ((readStatus == 0 && !loop) || readStatus == 0xFF) {
|
if ((readStatus == 0 && !loop) || readStatus == 0xFF) {
|
||||||
// abort
|
// abort
|
||||||
DropField();
|
DropField();
|
||||||
return PM3_EOPABORTED;
|
return PM3_EOPABORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (readStatus & FLAG_ICLASS_READER_CSN) {
|
if (readStatus & FLAG_ICLASS_READER_CSN) {
|
||||||
|
|
|
@ -325,7 +325,7 @@ void annotateIso14443a(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
|
||||||
void annotateIclass(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
|
void annotateIclass(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
|
||||||
uint8_t c = cmd[0] & 0x0F;
|
uint8_t c = cmd[0] & 0x0F;
|
||||||
uint8_t parity = 0;
|
uint8_t parity = 0;
|
||||||
for ( uint8_t i=0; i<7; i++) {
|
for (uint8_t i = 0; i < 7; i++) {
|
||||||
parity ^= (cmd[0] >> i) & 1;
|
parity ^= (cmd[0] >> i) & 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -363,7 +363,7 @@ void annotateIclass(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
|
||||||
snprintf(exp, size, "UPDATE(%d)", cmd[1]);
|
snprintf(exp, size, "UPDATE(%d)", cmd[1]);
|
||||||
break;
|
break;
|
||||||
case ICLASS_CMD_READCHECK:
|
case ICLASS_CMD_READCHECK:
|
||||||
if ( ICLASS_CREDIT(c) ) {
|
if (ICLASS_CREDIT(c)) {
|
||||||
snprintf(exp, size, "READCHECK[Kc](%d)", cmd[1]);
|
snprintf(exp, size, "READCHECK[Kc](%d)", cmd[1]);
|
||||||
} else {
|
} else {
|
||||||
snprintf(exp, size, "READCHECK[Kd](%d)", cmd[1]);
|
snprintf(exp, size, "READCHECK[Kd](%d)", cmd[1]);
|
||||||
|
|
|
@ -1780,7 +1780,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
|
||||||
|
|
||||||
// card prng type (weak=1 / hard=0 / select/card comm error = negative value)
|
// card prng type (weak=1 / hard=0 / select/card comm error = negative value)
|
||||||
prng_type = detect_classic_prng();
|
prng_type = detect_classic_prng();
|
||||||
if (prng_type < 0){
|
if (prng_type < 0) {
|
||||||
PrintAndLogEx(FAILED, "\nNo tag detected or other tag communication error");
|
PrintAndLogEx(FAILED, "\nNo tag detected or other tag communication error");
|
||||||
free(e_sector);
|
free(e_sector);
|
||||||
return prng_type;
|
return prng_type;
|
||||||
|
|
|
@ -64,7 +64,7 @@ static int print_barcode(uint8_t *barcode, const size_t barcode_len, bool verbos
|
||||||
} else {
|
} else {
|
||||||
PrintAndLogEx(SUCCESS, " Checksum : "_YELLOW_("too few data for checksum")"- " _RED_("fail"));
|
PrintAndLogEx(SUCCESS, " Checksum : "_YELLOW_("too few data for checksum")"- " _RED_("fail"));
|
||||||
}
|
}
|
||||||
PrintAndLogEx(SUCCESS, " Data len (bits) : "_YELLOW_("%i")"- %s", barcode_len*8, (barcode_len==16||barcode_len==32) ? _GREEN_("OK") : _YELLOW_("warning"));
|
PrintAndLogEx(SUCCESS, " Data len (bits) : "_YELLOW_("%i")"- %s", barcode_len * 8, (barcode_len == 16 || barcode_len == 32) ? _GREEN_("OK") : _YELLOW_("warning"));
|
||||||
PrintAndLogEx(SUCCESS, " Raw data : "_YELLOW_("%s"), sprint_hex(barcode, barcode_len));
|
PrintAndLogEx(SUCCESS, " Raw data : "_YELLOW_("%s"), sprint_hex(barcode, barcode_len));
|
||||||
if (barcode_len < 4) // too few to go to next decoding stages
|
if (barcode_len < 4) // too few to go to next decoding stages
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
|
|
|
@ -114,7 +114,7 @@ static int CmdParadoxRead(const char *Cmd) {
|
||||||
|
|
||||||
|
|
||||||
static int CmdParadoxSim(const char *Cmd) {
|
static int CmdParadoxSim(const char *Cmd) {
|
||||||
PrintAndLogEx(INFO," To be implemented, feel free to contribute!");
|
PrintAndLogEx(INFO, " To be implemented, feel free to contribute!");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue