diff --git a/backend/library.c b/backend/library.c index 028c2bd4..cb4b48d8 100644 --- a/backend/library.c +++ b/backend/library.c @@ -191,20 +191,17 @@ INTERNAL int dpd_parcel(struct zint_symbol *symbol, unsigned char source[], int INTERNAL int plot_raster(struct zint_symbol *symbol, int rotate_angle, int file_type); /* Plot to PNG/BMP/PCX */ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_type); /* Plot to EPS/EMF/SVG */ -static void error_tag(char error_string[], int error_number) { +STATIC_UNLESS_ZINT_TEST int error_tag(char error_string[100], int error_number) { if (error_number != 0) { + const char *fmt = error_number >= ZINT_ERROR ? "Error %.93s" : "Warning %.91s"; /* Truncate if too long */ char error_buffer[100]; strcpy(error_buffer, error_string); - if (error_number >= ZINT_ERROR) { - strcpy(error_string, "Error "); - } else { - strcpy(error_string, "Warning "); - } - - strcat(error_string, error_buffer); + sprintf(error_string, fmt, error_buffer); } + + return error_number; } /* Output a hexadecimal representation of the rendered symbol */ @@ -931,17 +928,16 @@ static int reduced_charset(struct zint_symbol *symbol, unsigned char *source, in return error_number; } -static void strip_bom(unsigned char *source, int *input_length) { +STATIC_UNLESS_ZINT_TEST void strip_bom(unsigned char *source, int *input_length) { int i; - if (*input_length > 3) { - if((source[0] == 0xef) && (source[1] == 0xbb) && (source[2] == 0xbf)) { - /* BOM at start of input data, strip in accordance with RFC 3629 */ - for (i = 3; i < *input_length; i++) { - source[i - 3] = source[i]; - } - *input_length -= 3; + /* Note if BOM is only data then not stripped */ + if (*input_length > 3 && (source[0] == 0xef) && (source[1] == 0xbb) && (source[2] == 0xbf)) { + /* BOM at start of input data, strip in accordance with RFC 3629 */ + for (i = 3; i <= *input_length; i++) { /* Include terminating NUL */ + source[i - 3] = source[i]; } + *input_length -= 3; } } @@ -1077,7 +1073,7 @@ static int escape_char_process(struct zint_symbol *symbol, unsigned char *input_ } /* Is string valid UTF-8? */ -static int is_valid_utf8(const unsigned char source[], const int length) { +STATIC_UNLESS_ZINT_TEST int is_valid_utf8(const unsigned char source[], const int length) { int i; unsigned int codepoint, state = 0; @@ -1091,7 +1087,7 @@ static int is_valid_utf8(const unsigned char source[], const int length) { } int ZBarcode_Encode(struct zint_symbol *symbol, const unsigned char *source, int in_length) { - int error_number, error_buffer; + int error_number, warn_number; #ifdef _MSC_VER unsigned char *local_source; #endif @@ -1107,25 +1103,22 @@ int ZBarcode_Encode(struct zint_symbol *symbol, const unsigned char *source, int source, symbol->primary); } - error_number = 0; + warn_number = 0; if (source == NULL) { strcpy(symbol->errtxt, "200: Input data NULL"); - error_tag(symbol->errtxt, ZINT_ERROR_INVALID_DATA); - return ZINT_ERROR_INVALID_DATA; + return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_DATA); } if (in_length <= 0) { - in_length = (int)ustrlen(source); + in_length = (int) ustrlen(source); } if (in_length <= 0) { strcpy(symbol->errtxt, "205: No input data"); - error_tag(symbol->errtxt, ZINT_ERROR_INVALID_DATA); - return ZINT_ERROR_INVALID_DATA; + return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_DATA); } if (in_length > ZINT_MAX_DATA_LEN) { strcpy(symbol->errtxt, "243: Input data too long"); - error_tag(symbol->errtxt, ZINT_ERROR_TOO_LONG); - return ZINT_ERROR_TOO_LONG; + return error_tag(symbol->errtxt, ZINT_ERROR_TOO_LONG); } if (*symbol->outfile == '\0') { @@ -1141,11 +1134,10 @@ int ZBarcode_Encode(struct zint_symbol *symbol, const unsigned char *source, int if (symbol->symbology < 1) { strcpy(symbol->errtxt, "206: Symbology out of range"); if (symbol->warn_level == WARN_FAIL_ALL) { - error_number = ZINT_ERROR_INVALID_OPTION; - } else { - symbol->symbology = BARCODE_CODE128; - error_number = ZINT_WARN_INVALID_OPTION; + return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION); } + symbol->symbology = BARCODE_CODE128; + warn_number = ZINT_WARN_INVALID_OPTION; /* symbol->symbologys 1 to 86 are defined by tbarcode */ } else if (symbol->symbology == 5) { symbol->symbology = BARCODE_C25STANDARD; @@ -1158,16 +1150,15 @@ int ZBarcode_Encode(struct zint_symbol *symbol, const unsigned char *source, int } else if (symbol->symbology == 19) { strcpy(symbol->errtxt, "207: Codabar 18 not supported"); if (symbol->warn_level == WARN_FAIL_ALL) { - error_number = ZINT_ERROR_INVALID_OPTION; - } else { - symbol->symbology = BARCODE_CODABAR; - error_number = ZINT_WARN_INVALID_OPTION; + return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION); } + symbol->symbology = BARCODE_CODABAR; + warn_number = ZINT_WARN_INVALID_OPTION; } else if (symbol->symbology == 26) { symbol->symbology = BARCODE_UPCA; } else if (symbol->symbology == 27) { strcpy(symbol->errtxt, "208: UPCD1 not supported"); - error_number = ZINT_ERROR_INVALID_OPTION; + return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION); } else if (symbol->symbology == 33) { symbol->symbology = BARCODE_GS1_128; } else if (symbol->symbology == 36) { @@ -1181,11 +1172,10 @@ int ZBarcode_Encode(struct zint_symbol *symbol, const unsigned char *source, int } else if (symbol->symbology == 54) { strcpy(symbol->errtxt, "210: General Parcel Code not supported"); if (symbol->warn_level == WARN_FAIL_ALL) { - error_number = ZINT_ERROR_INVALID_OPTION; - } else { - symbol->symbology = BARCODE_CODE128; - error_number = ZINT_WARN_INVALID_OPTION; + return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION); } + symbol->symbology = BARCODE_CODE128; + warn_number = ZINT_WARN_INVALID_OPTION; } else if ((symbol->symbology == 59) || (symbol->symbology == 61)) { symbol->symbology = BARCODE_CODE128; } else if (symbol->symbology == 62) { @@ -1201,19 +1191,17 @@ int ZBarcode_Encode(struct zint_symbol *symbol, const unsigned char *source, int } else if (symbol->symbology == 91) { strcpy(symbol->errtxt, "212: Symbology out of range"); if (symbol->warn_level == WARN_FAIL_ALL) { - error_number = ZINT_ERROR_INVALID_OPTION; - } else { - symbol->symbology = BARCODE_CODE128; - error_number = ZINT_WARN_INVALID_OPTION; + return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION); } + symbol->symbology = BARCODE_CODE128; + warn_number = ZINT_WARN_INVALID_OPTION; } else if ((symbol->symbology >= 94) && (symbol->symbology <= 95)) { strcpy(symbol->errtxt, "213: Symbology out of range"); if (symbol->warn_level == WARN_FAIL_ALL) { - error_number = ZINT_ERROR_INVALID_OPTION; - } else { - symbol->symbology = BARCODE_CODE128; - error_number = ZINT_WARN_INVALID_OPTION; + return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION); } + symbol->symbology = BARCODE_CODE128; + warn_number = ZINT_WARN_INVALID_OPTION; } else if (symbol->symbology == 100) { symbol->symbology = BARCODE_HIBC_128; } else if (symbol->symbology == 101) { @@ -1231,69 +1219,57 @@ int ZBarcode_Encode(struct zint_symbol *symbol, const unsigned char *source, int } else if ((symbol->symbology == 113) || (symbol->symbology == 114)) { strcpy(symbol->errtxt, "214: Symbology out of range"); if (symbol->warn_level == WARN_FAIL_ALL) { - error_number = ZINT_ERROR_INVALID_OPTION; - } else { - symbol->symbology = BARCODE_CODE128; - error_number = ZINT_WARN_INVALID_OPTION; + return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION); } + symbol->symbology = BARCODE_CODE128; + warn_number = ZINT_WARN_INVALID_OPTION; } else if (symbol->symbology == 115) { symbol->symbology = BARCODE_DOTCODE; } else if ((symbol->symbology >= 117) && (symbol->symbology <= 127)) { if (symbol->symbology != 121) { strcpy(symbol->errtxt, "215: Symbology out of range"); if (symbol->warn_level == WARN_FAIL_ALL) { - error_number = ZINT_ERROR_INVALID_OPTION; - } else { - symbol->symbology = BARCODE_CODE128; - error_number = ZINT_WARN_INVALID_OPTION; + return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION); } + symbol->symbology = BARCODE_CODE128; + warn_number = ZINT_WARN_INVALID_OPTION; } /* Everything from 128 up is Zint-specific */ } else if (symbol->symbology > 145) { strcpy(symbol->errtxt, "216: Symbology out of range"); if (symbol->warn_level == WARN_FAIL_ALL) { - error_number = ZINT_ERROR_INVALID_OPTION; - } else { - symbol->symbology = BARCODE_CODE128; - error_number = ZINT_WARN_INVALID_OPTION; + return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION); } - } - if (error_number >= ZINT_ERROR) { - error_tag(symbol->errtxt, error_number); - return error_number; + symbol->symbology = BARCODE_CODE128; + warn_number = ZINT_WARN_INVALID_OPTION; } } if (symbol->eci != 0) { if (!(supports_eci(symbol->symbology))) { strcpy(symbol->errtxt, "217: Symbology does not support ECI switching"); - error_number = ZINT_ERROR_INVALID_OPTION; - } else if ((symbol->eci < 0) || (symbol->eci == 1) || (symbol->eci == 2) || (symbol->eci > 999999)) { + return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION); + } + if ((symbol->eci < 0) || (symbol->eci == 1) || (symbol->eci == 2) || (symbol->eci > 999999)) { strcpy(symbol->errtxt, "218: Invalid ECI mode"); - error_number = ZINT_ERROR_INVALID_OPTION; + return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION); } } if ((symbol->dot_size < 0.01f) || (symbol->dot_size > 20.0f)) { strcpy(symbol->errtxt, "221: Invalid dot size"); - error_number = ZINT_ERROR_INVALID_OPTION; + return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION); } if ((symbol->input_mode & 0x07) == UNICODE_MODE && !is_valid_utf8(source, in_length)) { strcpy(symbol->errtxt, "245: Invalid UTF-8"); - error_number = ZINT_ERROR_INVALID_DATA; + return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_DATA); } if ((symbol->input_mode & 0x07) > 2) { symbol->input_mode = DATA_MODE; /* Reset completely */ } - if (error_number >= ZINT_ERROR) { - error_tag(symbol->errtxt, error_number); - return error_number; - } - error_buffer = error_number; - #ifndef _MSC_VER unsigned char local_source[in_length + 1]; #else @@ -1307,8 +1283,7 @@ int ZBarcode_Encode(struct zint_symbol *symbol, const unsigned char *source, int if (symbol->input_mode & ESCAPE_MODE) { error_number = escape_char_process(symbol, local_source, &in_length); if (error_number != 0) { - error_tag(symbol->errtxt, error_number); - return error_number; + return error_tag(symbol->errtxt, error_number); } } @@ -1328,19 +1303,18 @@ int ZBarcode_Encode(struct zint_symbol *symbol, const unsigned char *source, int #endif error_number = gs1_verify(symbol, local_source, in_length, reduced); if (error_number != 0) { - if (is_composite(symbol->symbology)) { - strcat(symbol->errtxt, " in 2D component"); + const char in_2d_comp[] = " in 2D component"; + if (is_composite(symbol->symbology) && strlen(symbol->errtxt) < 100 - strlen(in_2d_comp)) { + strcat(symbol->errtxt, in_2d_comp); } - error_tag(symbol->errtxt, error_number); - return error_number; + return error_tag(symbol->errtxt, error_number); } ustrcpy(local_source, reduced); // Cannot contain nul char in_length = (int) ustrlen(local_source); } } else { strcpy(symbol->errtxt, "220: Selected symbology does not support GS1 mode"); - error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION); - return ZINT_ERROR_INVALID_OPTION; + return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION); } } @@ -1358,14 +1332,14 @@ int ZBarcode_Encode(struct zint_symbol *symbol, const unsigned char *source, int if (!(symbol->debug & ZINT_DEBUG_TEST)) { strcpy(symbol->errtxt, "222: Encoded data includes ECI"); } - if (symbol->debug & ZINT_DEBUG_PRINT) printf("Data ECI %d\n", symbol->eci); + if (symbol->debug & ZINT_DEBUG_PRINT) printf("Added ECI %d\n", symbol->eci); } } if (error_number == 0) { - error_number = error_buffer; + error_number = warn_number; } - error_tag(symbol->errtxt, error_number); + (void)error_tag(symbol->errtxt, error_number); if (error_number < ZINT_ERROR) { check_row_heights(symbol); @@ -1387,15 +1361,14 @@ int ZBarcode_Print(struct zint_symbol *symbol, int rotate_angle) { break; default: strcpy(symbol->errtxt, "223: Invalid rotation angle"); - error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION); - return ZINT_ERROR_INVALID_OPTION; + return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION); + break; } if (symbol->output_options & BARCODE_DOTTY_MODE) { if (!(is_dotty(symbol->symbology))) { strcpy(symbol->errtxt, "224: Selected symbology cannot be rendered as dots"); - error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION); - return ZINT_ERROR_INVALID_OPTION; + return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION); } } @@ -1405,62 +1378,60 @@ int ZBarcode_Print(struct zint_symbol *symbol, int rotate_angle) { output[1] = symbol->outfile[strlen(symbol->outfile) - 2]; output[2] = symbol->outfile[strlen(symbol->outfile) - 1]; output[3] = '\0'; - to_upper((unsigned char*) output); + to_upper((unsigned char *) output); if (!(strcmp(output, "PNG"))) { if (symbol->scale < 1.0f) { symbol->text[0] = '\0'; } error_number = plot_raster(symbol, rotate_angle, OUT_PNG_FILE); - } else - if (!(strcmp(output, "BMP"))) { + + } else if (!(strcmp(output, "BMP"))) { if (symbol->scale < 1.0f) { symbol->text[0] = '\0'; } error_number = plot_raster(symbol, rotate_angle, OUT_BMP_FILE); - } else - if (!(strcmp(output, "PCX"))) { + + } else if (!(strcmp(output, "PCX"))) { if (symbol->scale < 1.0f) { symbol->text[0] = '\0'; } error_number = plot_raster(symbol, rotate_angle, OUT_PCX_FILE); - } else - if (!(strcmp(output, "GIF"))) { + + } else if (!(strcmp(output, "GIF"))) { if (symbol->scale < 1.0f) { symbol->text[0] = '\0'; } error_number = plot_raster(symbol, rotate_angle, OUT_GIF_FILE); - } else - if (!(strcmp(output, "TIF"))) { + + } else if (!(strcmp(output, "TIF"))) { if (symbol->scale < 1.0f) { symbol->text[0] = '\0'; } error_number = plot_raster(symbol, rotate_angle, OUT_TIF_FILE); - } else - if (!(strcmp(output, "TXT"))) { + + } else if (!(strcmp(output, "TXT"))) { error_number = dump_plot(symbol); - } else - if (!(strcmp(output, "EPS"))) { + + } else if (!(strcmp(output, "EPS"))) { error_number = plot_vector(symbol, rotate_angle, OUT_EPS_FILE); - } else - if (!(strcmp(output, "SVG"))) { + + } else if (!(strcmp(output, "SVG"))) { error_number = plot_vector(symbol, rotate_angle, OUT_SVG_FILE); - } else - if (!(strcmp(output, "EMF"))) { + + } else if (!(strcmp(output, "EMF"))) { error_number = plot_vector(symbol, rotate_angle, OUT_EMF_FILE); + } else { strcpy(symbol->errtxt, "225: Unknown output format"); - error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION); - return ZINT_ERROR_INVALID_OPTION; + return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION); } } else { strcpy(symbol->errtxt, "226: Unknown output format"); - error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION); - return ZINT_ERROR_INVALID_OPTION; + return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION); } - error_tag(symbol->errtxt, error_number); - return error_number; + return error_tag(symbol->errtxt, error_number); } int ZBarcode_Buffer(struct zint_symbol *symbol, int rotate_angle) { @@ -1476,21 +1447,19 @@ int ZBarcode_Buffer(struct zint_symbol *symbol, int rotate_angle) { break; default: strcpy(symbol->errtxt, "228: Invalid rotation angle"); - error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION); - return ZINT_ERROR_INVALID_OPTION; + return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION); + break; } if (symbol->output_options & BARCODE_DOTTY_MODE) { if (!(is_dotty(symbol->symbology))) { strcpy(symbol->errtxt, "237: Selected symbology cannot be rendered as dots"); - error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION); - return ZINT_ERROR_INVALID_OPTION; + return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION); } } error_number = plot_raster(symbol, rotate_angle, OUT_BUFFER); - error_tag(symbol->errtxt, error_number); - return error_number; + return error_tag(symbol->errtxt, error_number); } int ZBarcode_Buffer_Vector(struct zint_symbol *symbol, int rotate_angle) { @@ -1506,21 +1475,19 @@ int ZBarcode_Buffer_Vector(struct zint_symbol *symbol, int rotate_angle) { break; default: strcpy(symbol->errtxt, "219: Invalid rotation angle"); - error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION); - return ZINT_ERROR_INVALID_OPTION; + return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION); + break; } if (symbol->output_options & BARCODE_DOTTY_MODE) { if (!(is_dotty(symbol->symbology))) { strcpy(symbol->errtxt, "238: Selected symbology cannot be rendered as dots"); - error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION); - return ZINT_ERROR_INVALID_OPTION; + return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION); } } error_number = plot_vector(symbol, rotate_angle, OUT_BUFFER); - error_tag(symbol->errtxt, error_number); - return error_number; + return error_tag(symbol->errtxt, error_number); } int ZBarcode_Encode_and_Print(struct zint_symbol *symbol, unsigned char *input, int length, int rotate_angle) { @@ -1589,8 +1556,7 @@ int ZBarcode_Encode_File(struct zint_symbol *symbol, char *filename) { if (!filename) { strcpy(symbol->errtxt, "239: Filename NULL"); - error_tag(symbol->errtxt, ZINT_ERROR_INVALID_DATA); - return ZINT_ERROR_INVALID_DATA; + return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_DATA); } if (!strcmp(filename, "-")) { @@ -1600,8 +1566,7 @@ int ZBarcode_Encode_File(struct zint_symbol *symbol, char *filename) { file = fopen(filename, "rb"); if (!file) { sprintf(symbol->errtxt, "229: Unable to read input file (%.30s)", strerror(errno)); - error_tag(symbol->errtxt, ZINT_ERROR_INVALID_DATA); - return ZINT_ERROR_INVALID_DATA; + return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_DATA); } file_opened = 1; @@ -1613,15 +1578,13 @@ int ZBarcode_Encode_File(struct zint_symbol *symbol, char *filename) { /* On many Linux distros ftell() returns LONG_MAX not -1 on error */ if (fileLen <= 0 || fileLen == LONG_MAX) { strcpy(symbol->errtxt, "235: Input file empty or unseekable"); - error_tag(symbol->errtxt, ZINT_ERROR_INVALID_DATA); fclose(file); - return ZINT_ERROR_INVALID_DATA; + return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_DATA); } if (fileLen > ZINT_MAX_DATA_LEN) { strcpy(symbol->errtxt, "230: Input file too long"); - error_tag(symbol->errtxt, ZINT_ERROR_TOO_LONG); fclose(file); - return ZINT_ERROR_TOO_LONG; + return error_tag(symbol->errtxt, ZINT_ERROR_TOO_LONG); } } @@ -1629,11 +1592,10 @@ int ZBarcode_Encode_File(struct zint_symbol *symbol, char *filename) { buffer = (unsigned char *) malloc(fileLen); if (!buffer) { strcpy(symbol->errtxt, "231: Internal memory error"); - error_tag(symbol->errtxt, ZINT_ERROR_MEMORY); if (file_opened) { fclose(file); } - return ZINT_ERROR_MEMORY; + return error_tag(symbol->errtxt, ZINT_ERROR_MEMORY); } /* Read file contents into buffer */ @@ -1642,12 +1604,11 @@ int ZBarcode_Encode_File(struct zint_symbol *symbol, char *filename) { n = fread(buffer + nRead, 1, fileLen - nRead, file); if (ferror(file)) { sprintf(symbol->errtxt, "241: Input file read error (%.30s)", strerror(errno)); - error_tag(symbol->errtxt, ZINT_ERROR_INVALID_DATA); if (file_opened) { fclose(file); } free(buffer); - return ZINT_ERROR_INVALID_DATA; + return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_DATA); } nRead += n; } while (!feof(file) && (0 < n) && (nRead < fileLen)); diff --git a/backend/tests/test_library.c b/backend/tests/test_library.c index 830df00b..71436afe 100644 --- a/backend/tests/test_library.c +++ b/backend/tests/test_library.c @@ -50,26 +50,53 @@ static void test_checks(int index, int debug) { int ret; char *expected; + int expected_symbology; }; // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) struct item data[] = { - /* 0*/ { BARCODE_CODE128, "1234", -1, -1, 3, -1, -1, ZINT_ERROR_INVALID_OPTION, "Error 217: Symbology does not support ECI switching" }, - /* 1*/ { BARCODE_CODE128, "1234", -1, -1, 0, -1, -1, 0, "" }, - /* 2*/ { BARCODE_QRCODE, "1234", -1, -1, 3, -1, -1, 0, "" }, - /* 3*/ { BARCODE_QRCODE, "1234", -1, -1, 999999 + 1, -1, -1, ZINT_ERROR_INVALID_OPTION, "Error 218: Invalid ECI mode" }, - /* 4*/ { BARCODE_CODE128, "1234", -1, -1, -1, 20.1, -1, ZINT_ERROR_INVALID_OPTION, "Error 221: Invalid dot size" }, - /* 5*/ { BARCODE_CODE128, "1234", -1, GS1_MODE, -1, -1, -1, ZINT_ERROR_INVALID_OPTION, "Error 220: Selected symbology does not support GS1 mode" }, - /* 6*/ { BARCODE_GS1_128, "[21]12\0004", 8, GS1_MODE, -1, -1, -1, ZINT_ERROR_INVALID_DATA, "Error 262: NUL characters not permitted in GS1 mode" }, - /* 7*/ { BARCODE_GS1_128, "[21]12é4", -1, GS1_MODE, -1, -1, -1, ZINT_ERROR_INVALID_DATA, "Error 250: Extended ASCII characters are not supported by GS1" }, - /* 8*/ { BARCODE_GS1_128, "[21]12\0074", -1, GS1_MODE, -1, -1, -1, ZINT_ERROR_INVALID_DATA, "Error 251: Control characters are not supported by GS1" }, - /* 9*/ { BARCODE_GS1_128, "[21]1234", -1, GS1_MODE, -1, -1, -1, 0, "" }, - /* 10*/ { 0, "1", -1, -1, -1, -1, -1, ZINT_WARN_INVALID_OPTION, "Warning 206: Symbology out of range" }, - /* 11*/ { 0, "1", -1, -1, -1, -1, WARN_FAIL_ALL, ZINT_ERROR_INVALID_OPTION, "Error 206: Symbology out of range" }, - /* 12*/ { 0, "1", -1, -1, 1, -1, -1, ZINT_ERROR_INVALID_OPTION, "Error 217: Symbology does not support ECI switching" }, // Not supporting beats invalid ECI - /* 13*/ { 0, "1", -1, -1, 1, -1, WARN_FAIL_ALL, ZINT_ERROR_INVALID_OPTION, "Error 206: Symbology out of range" }, - /* 14*/ { 0, "1", -1, -1, -1, 0.009, -1, ZINT_ERROR_INVALID_OPTION, "Error 221: Invalid dot size" }, - /* 15*/ { 0, "1", -1, -1, -1, 0.009, WARN_FAIL_ALL, ZINT_ERROR_INVALID_OPTION, "Error 206: Symbology out of range" }, - /* 16*/ { 0, "1", -1, -1, 1, 0.009, -1, ZINT_ERROR_INVALID_OPTION, "Error 221: Invalid dot size" }, // Invalid dot size beats invalid ECI + /* 0*/ { BARCODE_CODE128, "1234", -1, -1, 3, -1, -1, ZINT_ERROR_INVALID_OPTION, "Error 217: Symbology does not support ECI switching", -1 }, + /* 1*/ { BARCODE_CODE128, "1234", -1, -1, 0, -1, -1, 0, "", -1 }, + /* 2*/ { BARCODE_QRCODE, "1234", -1, -1, 3, -1, -1, 0, "", -1 }, + /* 3*/ { BARCODE_QRCODE, "1234", -1, -1, 999999 + 1, -1, -1, ZINT_ERROR_INVALID_OPTION, "Error 218: Invalid ECI mode", -1 }, + /* 4*/ { BARCODE_CODE128, "1234", -1, -1, -1, 20.1, -1, ZINT_ERROR_INVALID_OPTION, "Error 221: Invalid dot size", -1 }, + /* 5*/ { BARCODE_CODE128, "1234", -1, GS1_MODE, -1, -1, -1, ZINT_ERROR_INVALID_OPTION, "Error 220: Selected symbology does not support GS1 mode", -1 }, + /* 6*/ { BARCODE_GS1_128, "[21]12\0004", 8, GS1_MODE, -1, -1, -1, ZINT_ERROR_INVALID_DATA, "Error 262: NUL characters not permitted in GS1 mode", -1 }, + /* 7*/ { BARCODE_GS1_128, "[21]12é4", -1, GS1_MODE, -1, -1, -1, ZINT_ERROR_INVALID_DATA, "Error 250: Extended ASCII characters are not supported by GS1", -1 }, + /* 8*/ { BARCODE_GS1_128, "[21]12\0074", -1, GS1_MODE, -1, -1, -1, ZINT_ERROR_INVALID_DATA, "Error 251: Control characters are not supported by GS1", -1 }, + /* 9*/ { BARCODE_GS1_128, "[21]1234", -1, GS1_MODE, -1, -1, -1, 0, "", -1 }, + /* 10*/ { 0, "1", -1, -1, -1, -1, -1, ZINT_WARN_INVALID_OPTION, "Warning 206: Symbology out of range", BARCODE_CODE128 }, + /* 11*/ { 0, "1", -1, -1, -1, -1, WARN_FAIL_ALL, ZINT_ERROR_INVALID_OPTION, "Error 206: Symbology out of range", -1 }, + /* 12*/ { 0, "1", -1, -1, 1, -1, -1, ZINT_ERROR_INVALID_OPTION, "Error 217: Symbology does not support ECI switching", BARCODE_CODE128 }, // Not supporting beats invalid ECI + /* 13*/ { 0, "1", -1, -1, 1, -1, WARN_FAIL_ALL, ZINT_ERROR_INVALID_OPTION, "Error 206: Symbology out of range", -1 }, + /* 14*/ { 0, "1", -1, -1, -1, 0.009, -1, ZINT_ERROR_INVALID_OPTION, "Error 221: Invalid dot size", BARCODE_CODE128 }, + /* 15*/ { 0, "1", -1, -1, -1, 0.009, WARN_FAIL_ALL, ZINT_ERROR_INVALID_OPTION, "Error 206: Symbology out of range", -1 }, + /* 16*/ { 0, "1", -1, -1, 1, 0.009, -1, ZINT_ERROR_INVALID_OPTION, "Error 217: Symbology does not support ECI switching", BARCODE_CODE128 }, // Invalid dot size no longer beats invalid ECI + /* 17*/ { 0, "1", -1, -1, -1, 0.009, WARN_FAIL_ALL, ZINT_ERROR_INVALID_OPTION, "Error 206: Symbology out of range", -1 }, + /* 18*/ { 5, "1", -1, -1, -1, -1, -1, 0, "", BARCODE_C25STANDARD }, + /* 19*/ { 5, "1", -1, -1, -1, -1, WARN_FAIL_ALL, 0, "", BARCODE_C25STANDARD }, + /* 20*/ { 12, "1", -1, -1, -1, -1, -1, 0, "", BARCODE_EANX }, + /* 21*/ { 12, "1", -1, -1, -1, -1, WARN_FAIL_ALL, 0, "", BARCODE_EANX }, + /* 22*/ { 19, "1", -1, -1, -1, -1, -1, ZINT_ERROR_TOO_LONG, "Error 362: Input too short", BARCODE_CODABAR }, + /* 23*/ { 19, "A1B", -1, -1, -1, -1, -1, ZINT_WARN_INVALID_OPTION, "Warning 207: Codabar 18 not supported", BARCODE_CODABAR }, + /* 24*/ { 19, "A1B", -1, -1, -1, -1, WARN_FAIL_ALL, ZINT_ERROR_INVALID_OPTION, "Error 207: Codabar 18 not supported", -1 }, + /* 25*/ { 26, "1", -1, -1, -1, -1, -1, 0, "", BARCODE_UPCA }, + /* 26*/ { 26, "1", -1, -1, -1, -1, WARN_FAIL_ALL, 0, "", BARCODE_UPCA }, + /* 27*/ { 27, "1", -1, -1, -1, -1, -1, ZINT_ERROR_INVALID_OPTION, "Error 208: UPCD1 not supported", 27 }, + /* 28*/ { 54, "1", -1, -1, -1, -1, -1, ZINT_WARN_INVALID_OPTION, "Warning 210: General Parcel Code not supported", BARCODE_CODE128 }, + /* 29*/ { 54, "1", -1, -1, -1, -1, WARN_FAIL_ALL, ZINT_ERROR_INVALID_OPTION, "Error 210: General Parcel Code not supported", -1 }, + /* 30*/ { 91, "1", -1, -1, -1, -1, -1, ZINT_WARN_INVALID_OPTION, "Warning 212: Symbology out of range", BARCODE_CODE128 }, + /* 31*/ { 91, "1", -1, -1, -1, -1, WARN_FAIL_ALL, ZINT_ERROR_INVALID_OPTION, "Error 212: Symbology out of range", -1 }, + /* 32*/ { 95, "1", -1, -1, -1, -1, -1, ZINT_WARN_INVALID_OPTION, "Warning 213: Symbology out of range", BARCODE_CODE128 }, + /* 33*/ { 95, "1", -1, -1, -1, -1, WARN_FAIL_ALL, ZINT_ERROR_INVALID_OPTION, "Error 213: Symbology out of range", -1 }, + /* 34*/ { 111, "1", -1, -1, -1, -1, -1, 0, "", BARCODE_HIBC_BLOCKF }, + /* 35*/ { 111, "1", -1, -1, -1, -1, WARN_FAIL_ALL, 0, "", BARCODE_HIBC_BLOCKF }, + /* 36*/ { 114, "1", -1, -1, -1, -1, -1, ZINT_WARN_INVALID_OPTION, "Warning 214: Symbology out of range", BARCODE_CODE128 }, + /* 37*/ { 114, "1", -1, -1, -1, -1, WARN_FAIL_ALL, ZINT_ERROR_INVALID_OPTION, "Error 214: Symbology out of range", -1 }, + /* 38*/ { 120, "1", -1, -1, -1, -1, -1, ZINT_WARN_INVALID_OPTION, "Warning 215: Symbology out of range", BARCODE_CODE128 }, + /* 39*/ { 120, "1", -1, -1, -1, -1, WARN_FAIL_ALL, ZINT_ERROR_INVALID_OPTION, "Error 215: Symbology out of range", -1 }, + /* 40*/ { 146, "1", -1, -1, -1, -1, -1, ZINT_WARN_INVALID_OPTION, "Warning 216: Symbology out of range", BARCODE_CODE128 }, + /* 41*/ { 146, "1", -1, -1, -1, -1, WARN_FAIL_ALL, ZINT_ERROR_INVALID_OPTION, "Error 216: Symbology out of range", -1 }, + /* 42*/ { BARCODE_CODE128, "\200", -1, UNICODE_MODE, -1, -1, -1, ZINT_ERROR_INVALID_DATA, "Error 245: Invalid UTF-8", -1 }, }; int data_size = sizeof(data) / sizeof(struct item); @@ -80,22 +107,13 @@ static void test_checks(int index, int debug) { struct zint_symbol *symbol = ZBarcode_Create(); assert_nonnull(symbol, "Symbol not created\n"); - symbol->symbology = data[i].symbology; - if (data[i].input_mode != -1) { - symbol->input_mode = data[i].input_mode; - } - if (data[i].eci != -1) { - symbol->eci = data[i].eci; - } + int length = testUtilSetSymbol(symbol, data[i].symbology, data[i].input_mode, data[i].eci, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data[i].data, data[i].length, debug); if (data[i].dot_size != -1) { symbol->dot_size = data[i].dot_size; } if (data[i].warn_level != -1) { symbol->warn_level = data[i].warn_level; } - symbol->debug |= debug; - - int length = data[i].length == -1 ? (int) strlen(data[i].data) : data[i].length; ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length); assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode(%d) ret %d != %d (%s)\n", i, data[i].symbology, ret, data[i].ret, symbol->errtxt); @@ -103,6 +121,12 @@ static void test_checks(int index, int debug) { ret = strcmp(symbol->errtxt, data[i].expected); assert_zero(ret, "i:%d (%d) strcmp(%s, %s) %d != 0\n", i, data[i].symbology, symbol->errtxt, data[i].expected, ret); + if (data[i].expected_symbology == -1) { + assert_equal(symbol->symbology, data[i].symbology, "i:%d symbol->symbology %d != original %d\n", i, symbol->symbology, data[i].symbology); + } else { + assert_equal(symbol->symbology, data[i].expected_symbology, "i:%d symbol->symbology %d != expected %d\n", i, symbol->symbology, data[i].expected_symbology); + } + ZBarcode_Delete(symbol); } @@ -450,6 +474,117 @@ static void test_valid_id(void) { testFinish(); } +static void test_error_tag(int index) { + + testStart(""); + + int ret; + struct item { + int error_number; + char* data; + int ret; + char* expected; + }; + // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) + struct item data[] = { + /* 0*/ { ZINT_WARN_INVALID_OPTION, "", ZINT_WARN_INVALID_OPTION, "Warning " }, + /* 1*/ { ZINT_ERROR_TOO_LONG, "", ZINT_ERROR_TOO_LONG, "Error " }, + /* 2*/ { ZINT_WARN_USES_ECI, "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789", ZINT_WARN_USES_ECI, "Warning 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901" }, + /* 3*/ { ZINT_ERROR_INVALID_DATA, "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789", ZINT_ERROR_INVALID_DATA, "Error 123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123" }, + }; + int data_size = ARRAY_SIZE(data); + + char errtxt[100]; + + for (int i = 0; i < data_size; i++) { + + if (index != -1 && i != index) continue; + + assert_nonzero(strlen(data[i].data) < 100, "i:%d strlen(data) %d >= 100\n", i, (int) strlen(data[i].data)); + strcpy(errtxt, data[i].data); + ret = error_tag(errtxt, data[i].error_number); + assert_equal(ret, data[i].ret, "i:%d ret %d != %d\n", i, ret, data[i].ret); + assert_zero(strcmp(errtxt, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, errtxt, data[i].expected); + assert_nonzero(strlen(errtxt) >= strlen(data[i].data), "i:%d strlen(errtxt) %d < %d\n", i, (int) strlen(errtxt), (int) strlen(data[i].data)); + } + + testFinish(); +} + +STATIC_UNLESS_ZINT_TEST void strip_bom(unsigned char *source, int *input_length); + +static void test_strip_bom(void) { + + testStart(""); + + int ret; + char data[] = "\357\273\277A"; // U+FEFF BOM, with "A" + int length; + char buf[6]; + + strcpy(buf, data); + length = (int) strlen(buf); + strip_bom((unsigned char *) buf, &length); + assert_equal(length, 1, "length %d != 1\n", length); + assert_zero(buf[1], "buf[1] %d != 0\n", buf[1]); + + // BOM not stripped if only data + + char bom_only[] = "\357\273\277"; // U+FEFF BOM only + + strcpy(buf, bom_only); + length = (int) strlen(buf); + strip_bom((unsigned char *) buf, &length); + assert_equal(length, 3, "BOM only length %d != 3\n", length); + ret = strcmp(buf, bom_only); + assert_zero(ret, "BOM only strcmp ret %d != 0\n", ret); + + testFinish(); +} + +STATIC_UNLESS_ZINT_TEST int is_valid_utf8(const unsigned char source[], const int length); + +static void test_is_valid_utf8(int index) { + + testStart(""); + + int ret; + struct item { + char* data; + int length; + int ret; + char* comment; + }; + // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) + struct item data[] = { + /* 0*/ { "", -1, 1, "" }, + /* 1*/ { "abcdefghijklmnopqrstuvwxyz", -1, 1, "" }, + /* 2*/ { "éa", -1, 1, "" }, + /* 3*/ { "a\000b", 3, 1, "Embedded nul" }, + /* 4*/ { "\357\273\277a", -1, 1, "Bom" }, + + /* 5*/ { "a\xC2", -1, 0, "Missing 2nd byte" }, + /* 6*/ { "a\200b", -1, 0, "Orphan continuation 0x80" }, + /* 7*/ { "\300\201", -1, 0, "Overlong 0xC081" }, + /* 8*/ { "\355\240\200", -1, 0, "Surrogate 0xEDA080" }, + }; + int data_size = ARRAY_SIZE(data); + + for (int i = 0; i < data_size; i++) { + + if (index != -1 && i != index) continue; + + int length = data[i].length == -1 ? (int) strlen(data[i].data) : data[i].length; + + ret = is_valid_utf8((const unsigned char *) data[i].data, length); + assert_equal(ret, data[i].ret, "i:%d ret %d != %d\n", i, ret, data[i].ret); + } + + testFinish(); +} + +STATIC_UNLESS_ZINT_TEST int error_tag(char error_string[100], int error_number); + int main(int argc, char *argv[]) { testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */ @@ -461,6 +596,9 @@ int main(int argc, char *argv[]) { { "test_encode_file_directory", test_encode_file_directory, 0, 0, 0 }, { "test_bad_args", test_bad_args, 0, 0, 0 }, { "test_valid_id", test_valid_id, 0, 0, 0 }, + { "test_error_tag", test_error_tag, 1, 0, 0 }, + { "test_strip_bom", test_strip_bom, 0, 0, 0 }, + { "test_is_valid_utf8", test_is_valid_utf8, 1, 0, 0 }, }; testRun(argc, argv, funcs, ARRAY_SIZE(funcs));