From a91d0a7b194159d541aa86c650f762267952c730 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Tue, 30 Apr 2019 00:41:52 +0200 Subject: [PATCH] Smart color handling: * if on Windows, no color, as usual * if on Linux, color only on real term * no color when > foo * no color in the logfile --- armsrc/mifareutil.h | 2 +- armsrc/util.h | 7 +---- client/comms.c | 57 ++++++++---------------------------- client/emv/emvjson.h | 1 - client/fido/cose.h | 1 - client/proxmark3.c | 30 +++++++++---------- client/ui.c | 70 +++++++++++++++++++++++++++++++++++++++----- client/ui.h | 1 + client/util.h | 37 +---------------------- common/commonutil.h | 7 +++++ 10 files changed, 101 insertions(+), 112 deletions(-) diff --git a/armsrc/mifareutil.h b/armsrc/mifareutil.h index 7d384fff9..110f41eaa 100644 --- a/armsrc/mifareutil.h +++ b/armsrc/mifareutil.h @@ -15,7 +15,7 @@ #include "proxmark3.h" #include "apps.h" #include "parity.h" -#include "commonutil.h" +#include "util.h" #include "string.h" #include "iso14443a.h" #include "crapto1/crapto1.h" diff --git a/armsrc/util.h b/armsrc/util.h index c01915195..1ea6ae741 100644 --- a/armsrc/util.h +++ b/armsrc/util.h @@ -12,18 +12,13 @@ #define __UTIL_H #include "common.h" +#include "commonutil.h" #include "proxmark3.h" #include "string.h" #include "BigBuf.h" #include "ticks.h" // Basic macros -# define _BLUE_(s) "\x1b[34m" s "\x1b[0m " -# define _RED_(s) "\x1b[31m" s "\x1b[0m " -# define _GREEN_(s) "\x1b[32m" s "\x1b[0m " -# define _YELLOW_(s) "\x1b[33m" s "\x1b[0m " -# define _MAGENTA_(s) "\x1b[35m" s "\x1b[0m " -# define _CYAN_(s) "\x1b[36m" s "\x1b[0m " #ifndef SHORT_COIL #define SHORT_COIL() LOW(GPIO_SSC_DOUT) diff --git a/client/comms.c b/client/comms.c index 2cb397007..e3bb602bb 100644 --- a/client/comms.c +++ b/client/comms.c @@ -11,6 +11,10 @@ #include "comms.h" #include "crc16.h" +#if defined(__linux__) || (__APPLE__) +#include +#include +#endif //#define COMMS_DEBUG //#define COMMS_DEBUG_RAW @@ -249,48 +253,6 @@ static int getReply(PacketResponseNG *packet) { return 1; } -static void memcpy_filtered(void *dest, const void *src, size_t n, bool filter) { -#if defined(__linux__) || (__APPLE__) - memcpy(dest, src, n); -#else - if (filter) { - // Filter out ANSI sequences on these OS - uint8_t *rdest = (uint8_t *)dest; - uint8_t *rsrc = (uint8_t *)src; - uint16_t si = 0; - for (uint16_t i = 0; i < n; i++) { - if ((rsrc[i] == '\x1b') - && (i < n - 1) - && (rsrc[i + 1] >= 0x40) - && (rsrc[i + 1] <= 0x5F)) { // entering ANSI sequence - - i++; - if ((rsrc[i] == '[') && (i < n - 1)) { // entering CSI sequence - i++; - - while ((i < n - 1) && (rsrc[i] >= 0x30) && (rsrc[i] <= 0x3F)) { // parameter bytes - i++; - } - - while ((i < n - 1) && (rsrc[i] >= 0x20) && (rsrc[i] <= 0x2F)) { // intermediate bytes - i++; - } - - if ((rsrc[i] >= 0x40) && (rsrc[i] <= 0x7F)) { // final byte - continue; - } - } else { - continue; - } - } - rdest[si++] = rsrc[i]; - } - } else { - memcpy(dest, src, n); - } -#endif -} - //----------------------------------------------------------------------------- // Entry point into our code: called whenever we received a packet over USB // that we weren't necessarily expecting, for example a debug print. @@ -303,6 +265,13 @@ static void PacketResponseReceived(PacketResponseNG *packet) { // we got a packet, reset WaitForResponseTimeout timeout timeout_start_time = msclock(); + bool filter_ansi = true; +#if defined(__linux__) || (__APPLE__) + struct stat tmp_stat; + if ((fstat (STDOUT_FILENO, &tmp_stat) == 0) && (S_ISCHR (tmp_stat.st_mode)) && isatty(STDIN_FILENO)) + filter_ansi = false; +#endif + switch (packet->cmd) { // First check if we are handling a debug message case CMD_DEBUG_PRINT_STRING: { @@ -320,11 +289,11 @@ static void PacketResponseReceived(PacketResponseNG *packet) { struct d *data = (struct d *)&packet->data.asBytes; len = packet->length - sizeof(data->flag); flag = data->flag; - memcpy_filtered(s, data->buf, len, flag & FLAG_ANSI); + memcpy_filter_ansi(s, data->buf, len, (flag & FLAG_ANSI) && filter_ansi); } else { len = MIN(packet->oldarg[0], USB_CMD_DATA_SIZE); flag = packet->oldarg[1]; - memcpy_filtered(s, packet->data.asBytes, len, flag & FLAG_ANSI); + memcpy_filter_ansi(s, packet->data.asBytes, len, (flag & FLAG_ANSI) && filter_ansi); } if (flag & FLAG_LOG) { diff --git a/client/emv/emvjson.h b/client/emv/emvjson.h index edff18bcd..6bcf8243d 100644 --- a/client/emv/emvjson.h +++ b/client/emv/emvjson.h @@ -12,7 +12,6 @@ #include #include "tlv.h" -#include "commonutil.h" typedef struct { tlv_tag_t Tag; diff --git a/client/fido/cose.h b/client/fido/cose.h index 3243a1632..e62054646 100644 --- a/client/fido/cose.h +++ b/client/fido/cose.h @@ -16,7 +16,6 @@ #include #include #include -#include "commonutil.h" #include "util.h" const char *GetCOSEAlgName(int id); diff --git a/client/proxmark3.c b/client/proxmark3.c index bb6553a09..c8f10a49a 100644 --- a/client/proxmark3.c +++ b/client/proxmark3.c @@ -30,25 +30,25 @@ #include "usart.h" static void showBanner(void) { - printf("\n\n"); + PrintAndLogEx(NORMAL, "\n"); #if defined(__linux__) || (__APPLE__) - printf(_BLUE_("██████╗ ███╗ ███╗ ████╗ ") " ...iceman fork\n"); - printf(_BLUE_("██╔══██╗████╗ ████║ ══█║") " ...dedicated to " _BLUE_("RDV40") "\n"); - printf(_BLUE_("██████╔╝██╔████╔██║ ████╔╝") "\n"); - printf(_BLUE_("██╔═══╝ ██║╚██╔╝██║ ══█║") " iceman@icesql.net\n"); - printf(_BLUE_("██║ ██║ ╚═╝ ██║ ████╔╝") " https://github.com/rfidresearchgroup/proxmark3/\n"); - printf(_BLUE_("╚═╝ ╚═╝ ╚═╝ ╚═══╝ ") "pre-release v4.0\n"); + PrintAndLogEx(NORMAL, _BLUE_("██████╗ ███╗ ███╗ ████╗ ") " ...iceman fork"); + PrintAndLogEx(NORMAL, _BLUE_("██╔══██╗████╗ ████║ ══█║") " ...dedicated to " _BLUE_("RDV40")); + PrintAndLogEx(NORMAL, _BLUE_("██████╔╝██╔████╔██║ ████╔╝")); + PrintAndLogEx(NORMAL, _BLUE_("██╔═══╝ ██║╚██╔╝██║ ══█║") " iceman@icesql.net"); + PrintAndLogEx(NORMAL, _BLUE_("██║ ██║ ╚═╝ ██║ ████╔╝") " https://github.com/rfidresearchgroup/proxmark3/"); + PrintAndLogEx(NORMAL, _BLUE_("╚═╝ ╚═╝ ╚═╝ ╚═══╝ ") "pre-release v4.0"); #else - printf("======. ===. ===. ====. ...iceman fork\n"); - printf("==...==.====. ====. ..=. ...dedicated to RDV40\n"); - printf("======..==.====.==. ====..\n"); - printf("==..... ==..==..==. ..=. iceman@icesql.net\n"); - printf("==. ==. ... ==. ====.. https://github.com/rfidresearchgroup/proxmark3/\n"); - printf("... ... ... ..... pre-release v4.0\n"); + PrintAndLogEx(NORMAL, "======. ===. ===. ====. ...iceman fork"); + PrintAndLogEx(NORMAL, "==...==.====. ====. ..=. ...dedicated to RDV40"); + PrintAndLogEx(NORMAL, "======..==.====.==. ====.."); + PrintAndLogEx(NORMAL, "==..... ==..==..==. ..=. iceman@icesql.net"); + PrintAndLogEx(NORMAL, "==. ==. ... ==. ====.. https://github.com/rfidresearchgroup/proxmark3/"); + PrintAndLogEx(NORMAL, "... ... ... ..... pre-release v4.0"); #endif - printf("\nSupport iceman on patreon, https://www.patreon.com/iceman1001/"); + PrintAndLogEx(NORMAL, "\nSupport iceman on patreon, https://www.patreon.com/iceman1001/"); // printf("\nMonero: 43mNJLpgBVaTvyZmX9ajcohpvVkaRy1kbZPm8tqAb7itZgfuYecgkRF36rXrKFUkwEGeZedPsASRxgv4HPBHvJwyJdyvQuP"); - printf("\n\n\n"); + PrintAndLogEx(NORMAL, "\n"); fflush(stdout); } diff --git a/client/ui.c b/client/ui.c index fb976c56b..cff0881ff 100644 --- a/client/ui.c +++ b/client/ui.c @@ -16,6 +16,10 @@ #endif #include "ui.h" +#if defined(__linux__) || (__APPLE__) +#include +#include +#endif double CursorScaleFactor = 1; int PlotGridX = 0, PlotGridY = 0, PlotGridXdefault = 64, PlotGridYdefault = 64; @@ -138,10 +142,11 @@ void PrintAndLogEx(logLevel_t level, const char *fmt, ...) { void PrintAndLog(const char *fmt, ...) { char *saved_line; int saved_point; - va_list argptr, argptr2; + va_list argptr; static FILE *logfile = NULL; static int logging = 1; - + char buffer[MAX_PRINT_BUFFER] = {0}; + char buffer2[MAX_PRINT_BUFFER] = {0}; // lock this section to avoid interlacing prints from different threads pthread_mutex_lock(&print_lock); @@ -171,10 +176,18 @@ void PrintAndLog(const char *fmt, ...) { #endif va_start(argptr, fmt); - va_copy(argptr2, argptr); - vprintf(fmt, argptr); - printf(" "); // cleaning prompt + vsnprintf(buffer, sizeof(buffer), fmt, argptr); va_end(argptr); + + bool filter_ansi = true; +#if defined(__linux__) || (__APPLE__) + struct stat tmp_stat; + if ((fstat (STDOUT_FILENO, &tmp_stat) == 0) && (S_ISCHR (tmp_stat.st_mode)) && isatty(STDIN_FILENO)) + filter_ansi = false; +#endif + memcpy_filter_ansi(buffer2, buffer, sizeof(buffer), filter_ansi); + printf("%s", buffer2); + printf(" "); // cleaning prompt printf("\n"); #ifdef RL_STATE_READCMD @@ -189,11 +202,14 @@ void PrintAndLog(const char *fmt, ...) { #endif if (logging && logfile) { - vfprintf(logfile, fmt, argptr2); - fprintf(logfile, "\n"); + if (filter_ansi) { // already done + fprintf(logfile, "%s\n", buffer2); + } else { + memcpy_filter_ansi(buffer, buffer2, sizeof(buffer2), true); + fprintf(logfile, "%s\n", buffer); + } fflush(logfile); } - va_end(argptr2); if (flushAfterWrite) fflush(stdout); @@ -210,6 +226,44 @@ void SetFlushAfterWrite(bool value) { flushAfterWrite = value; } +void memcpy_filter_ansi(void *dest, const void *src, size_t n, bool filter) { + if (filter) { + // Filter out ANSI sequences on these OS + uint8_t *rdest = (uint8_t *)dest; + uint8_t *rsrc = (uint8_t *)src; + uint16_t si = 0; + for (uint16_t i = 0; i < n; i++) { + if ((rsrc[i] == '\x1b') + && (i < n - 1) + && (rsrc[i + 1] >= 0x40) + && (rsrc[i + 1] <= 0x5F)) { // entering ANSI sequence + + i++; + if ((rsrc[i] == '[') && (i < n - 1)) { // entering CSI sequence + i++; + + while ((i < n - 1) && (rsrc[i] >= 0x30) && (rsrc[i] <= 0x3F)) { // parameter bytes + i++; + } + + while ((i < n - 1) && (rsrc[i] >= 0x20) && (rsrc[i] <= 0x2F)) { // intermediate bytes + i++; + } + + if ((rsrc[i] >= 0x40) && (rsrc[i] <= 0x7F)) { // final byte + continue; + } + } else { + continue; + } + } + rdest[si++] = rsrc[i]; + } + } else { + memcpy(dest, src, n); + } +} + void iceIIR_Butterworth(int *data, const size_t len) { int *output = (int *) calloc(sizeof(int) * len, sizeof(uint8_t)); diff --git a/client/ui.h b/client/ui.h index 574881918..1f493d346 100644 --- a/client/ui.h +++ b/client/ui.h @@ -39,6 +39,7 @@ void PrintAndLogOptions(const char *str[][2], size_t size, size_t space); void PrintAndLogEx(logLevel_t level, const char *fmt, ...); void SetLogFilename(char *fn); void SetFlushAfterWrite(bool value); +void memcpy_filter_ansi(void *dest, const void *src, size_t n, bool filter); extern double CursorScaleFactor; extern int PlotGridX, PlotGridY, PlotGridXdefault, PlotGridYdefault, GridOffset; diff --git a/client/util.h b/client/util.h index 78ecf6b91..0222097b7 100644 --- a/client/util.h +++ b/client/util.h @@ -19,6 +19,7 @@ #include #include #include "ui.h" // PrintAndLog +#include "commonutil.h" #ifdef ANDROID #include @@ -112,42 +113,6 @@ # define FILE_PATH_SIZE 1000 #endif -#if defined(__linux__) || (__APPLE__) -# define _BLUE_(s) "\x1b[34m" s "\x1b[0m " -#else -# define _BLUE_(s) s " " -#endif - -#if defined(__linux__) || (__APPLE__) -# define _RED_(s) "\x1b[31m" s "\x1b[0m " -#else -# define _RED_(s) s " " -#endif - -#if defined(__linux__) || (__APPLE__) -# define _GREEN_(s) "\x1b[32m" s "\x1b[0m " -#else -# define _GREEN_(s) s " " -#endif - -#if defined(__linux__) || (__APPLE__) -# define _YELLOW_(s) "\x1b[33m" s "\x1b[0m " -#else -# define _YELLOW_(s) s " " -#endif - -#if defined(__linux__) || (__APPLE__) -# define _MAGENTA_(s) "\x1b[35m" s "\x1b[0m " -#else -# define _MAGENTA_(s) s " " -#endif - -#if defined(__linux__) || (__APPLE__) -# define _CYAN_(s) "\x1b[36m" s "\x1b[0m " -#else -# define _CYAN_(s) s " " -#endif - #ifndef DropField #define DropField() { \ clearCommandBuffer(); SendCommandOLD(CMD_READER_ISO_14443a, 0, 0, 0, NULL, 0); \ diff --git a/common/commonutil.h b/common/commonutil.h index 2d1a3776c..9504abd5b 100644 --- a/common/commonutil.h +++ b/common/commonutil.h @@ -53,4 +53,11 @@ void lsl(uint8_t *data, size_t len); int32_t le24toh(uint8_t data[3]); void htole24(uint32_t val, uint8_t data[3]); +# define _BLUE_(s) "\x1b[34m" s "\x1b[0m " +# define _RED_(s) "\x1b[31m" s "\x1b[0m " +# define _GREEN_(s) "\x1b[32m" s "\x1b[0m " +# define _YELLOW_(s) "\x1b[33m" s "\x1b[0m " +# define _MAGENTA_(s) "\x1b[35m" s "\x1b[0m " +# define _CYAN_(s) "\x1b[36m" s "\x1b[0m " + #endif