diff --git a/ChangeLog b/ChangeLog index d19e97b8..a59bab3c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -7,11 +7,14 @@ Version 2.12.0.9 (dev) not released yet Changes ------- -- None yet +- BMP/EMF/EPS/GIF/PCX/PNG/SVG/TIF/TXT: check for errors on writing to output + file (ticket #275) +- manual/man page: document octal escape; Code 128 subset/mode -> Code Set Bugs ---- - CEPNET: fix no HRT (library: `has_hrt()`) +- man page: fix Code 11 check digit info Version 2.12.0 (2022-12-12) diff --git a/backend/bmp.c b/backend/bmp.c index 32c94f54..0632e35f 100644 --- a/backend/bmp.c +++ b/backend/bmp.c @@ -199,18 +199,35 @@ INTERNAL int bmp_pixel_plot(struct zint_symbol *symbol, unsigned char *pixelbuf) bmp_file = stdout; } else { if (!(bmp_file = out_fopen(symbol->outfile, "wb"))) { - free(bitmap_file_start); sprintf(symbol->errtxt, "601: Could not open output file (%d: %.30s)", errno, strerror(errno)); + free(bitmap_file_start); return ZINT_ERROR_FILE_ACCESS; } } fwrite(bitmap_file_start, file_header.file_size, 1, bmp_file); + if (ferror(bmp_file)) { + sprintf(symbol->errtxt, "603: Incomplete write to output (%d: %.30s)", errno, strerror(errno)); + free(bitmap_file_start); + if (!output_to_stdout) { + (void) fclose(bmp_file); + } + return ZINT_ERROR_FILE_WRITE; + } + if (output_to_stdout) { - fflush(bmp_file); + if (fflush(bmp_file) != 0) { + sprintf(symbol->errtxt, "604: Incomplete flush to output (%d: %.30s)", errno, strerror(errno)); + free(bitmap_file_start); + return ZINT_ERROR_FILE_WRITE; + } } else { - fclose(bmp_file); + if (fclose(bmp_file) != 0) { + sprintf(symbol->errtxt, "605: Failure on closing output file (%d: %.30s)", errno, strerror(errno)); + free(bitmap_file_start); + return ZINT_ERROR_FILE_WRITE; + } } free(bitmap_file_start); diff --git a/backend/emf.c b/backend/emf.c index af9883bf..6194342a 100644 --- a/backend/emf.c +++ b/backend/emf.c @@ -832,10 +832,24 @@ INTERNAL int emf_plot(struct zint_symbol *symbol, int rotate_angle) { fwrite(&emr_eof, sizeof(emr_eof_t), 1, emf_file); + if (ferror(emf_file)) { + sprintf(symbol->errtxt, "644: Incomplete write to output (%d: %.30s)", errno, strerror(errno)); + if (!output_to_stdout) { + (void) fclose(emf_file); + } + return ZINT_ERROR_FILE_WRITE; + } + if (output_to_stdout) { - fflush(emf_file); + if (fflush(emf_file) != 0) { + sprintf(symbol->errtxt, "940: Incomplete flush to output (%d: %.30s)", errno, strerror(errno)); + return ZINT_ERROR_FILE_WRITE; + } } else { - fclose(emf_file); + if (fclose(emf_file) != 0) { + sprintf(symbol->errtxt, "941: Failure on closing output file (%d: %.30s)", errno, strerror(errno)); + return ZINT_ERROR_FILE_WRITE; + } } return error_number; } diff --git a/backend/gif.c b/backend/gif.c index 337a60e4..4a228515 100644 --- a/backend/gif.c +++ b/backend/gif.c @@ -584,7 +584,7 @@ INTERNAL int gif_pixel_plot(struct zint_symbol *symbol, unsigned char *pixelbuf) State.InLen = bitmapSize; if (!(State.pOut = (unsigned char *) malloc(lzoutbufSize))) { if (!output_to_stdout) { - fclose(gif_file); + (void) fclose(gif_file); } strcpy(symbol->errtxt, "614: Insufficient memory for LZW buffer"); return ZINT_ERROR_MEMORY; @@ -596,7 +596,7 @@ INTERNAL int gif_pixel_plot(struct zint_symbol *symbol, unsigned char *pixelbuf) if (byte_out <= 0) { free(State.pOut); if (!output_to_stdout) { - fclose(gif_file); + (void) fclose(gif_file); } strcpy(symbol->errtxt, "613: Insufficient memory for LZW buffer"); return ZINT_ERROR_MEMORY; @@ -606,10 +606,25 @@ INTERNAL int gif_pixel_plot(struct zint_symbol *symbol, unsigned char *pixelbuf) /* GIF terminator */ fputc('\x3b', gif_file); + + if (ferror(gif_file)) { + sprintf(symbol->errtxt, "615: Incomplete write to output (%d: %.30s)", errno, strerror(errno)); + if (!output_to_stdout) { + (void) fclose(gif_file); + } + return ZINT_ERROR_FILE_WRITE; + } + if (output_to_stdout) { - fflush(gif_file); + if (fflush(gif_file) != 0) { + sprintf(symbol->errtxt, "616: Incomplete flush to output (%d: %.30s)", errno, strerror(errno)); + return ZINT_ERROR_FILE_WRITE; + } } else { - fclose(gif_file); + if (fclose(gif_file) != 0) { + sprintf(symbol->errtxt, "617: Failure on closing output file (%d: %.30s)", errno, strerror(errno)); + return ZINT_ERROR_FILE_WRITE; + } } return 0; diff --git a/backend/library.c b/backend/library.c index a21af86a..806cc482 100644 --- a/backend/library.c +++ b/backend/library.c @@ -249,11 +249,11 @@ INTERNAL int error_tag_test(struct zint_symbol *symbol, int error_number, const static int dump_plot(struct zint_symbol *symbol) { FILE *f; int i, r; - char hex[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', - '9', 'A', 'B', 'C', 'D', 'E', 'F'}; + static const char hex[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; int space = 0; + const int output_to_stdout = symbol->output_options & BARCODE_STDOUT; - if (symbol->output_options & BARCODE_STDOUT) { + if (output_to_stdout) { f = stdout; } else { f = fopen(symbol->outfile, "w"); @@ -295,10 +295,24 @@ static int dump_plot(struct zint_symbol *symbol) { space = 0; } - if (symbol->output_options & BARCODE_STDOUT) { - fflush(f); + if (ferror(f)) { + sprintf(symbol->errtxt, "790: Incomplete write to output (%d: %.30s)", errno, strerror(errno)); + if (!output_to_stdout) { + (void) fclose(f); + } + return ZINT_ERROR_FILE_WRITE; + } + + if (output_to_stdout) { + if (fflush(f) != 0) { + sprintf(symbol->errtxt, "791: Incomplete flush to output (%d: %.30s)", errno, strerror(errno)); + return ZINT_ERROR_FILE_WRITE; + } } else { - fclose(f); + if (fclose(f) != 0) { + sprintf(symbol->errtxt, "792: Failure on closing output file (%d: %.30s)", errno, strerror(errno)); + return ZINT_ERROR_FILE_WRITE; + } } return 0; @@ -1426,26 +1440,36 @@ int ZBarcode_Encode_File(struct zint_symbol *symbol, const char *filename) { file_opened = 1; /* Get file length */ - fseek(file, 0, SEEK_END); + if (fseek(file, 0, SEEK_END) != 0) { + sprintf(symbol->errtxt, "792: Unable to seek input file (%d: %.30s)", errno, strerror(errno)); + (void) fclose(file); + return error_tag(symbol, ZINT_ERROR_INVALID_DATA, NULL); + } + fileLen = ftell(file); - fseek(file, 0, SEEK_SET); /* On many Linux distros ftell() returns LONG_MAX not -1 on error */ if (fileLen <= 0 || fileLen == LONG_MAX) { - fclose(file); + (void) fclose(file); return error_tag(symbol, ZINT_ERROR_INVALID_DATA, "235: Input file empty or unseekable"); } if (fileLen > ZINT_MAX_DATA_LEN) { - fclose(file); + (void) fclose(file); return error_tag(symbol, ZINT_ERROR_TOO_LONG, "230: Input file too long"); } + + if (fseek(file, 0, SEEK_SET) != 0) { + sprintf(symbol->errtxt, "793: Unable to seek input file (%d: %.30s)", errno, strerror(errno)); + (void) fclose(file); + return error_tag(symbol, ZINT_ERROR_INVALID_DATA, NULL); + } } /* Allocate memory */ buffer = (unsigned char *) malloc(fileLen); if (!buffer) { if (file_opened) { - fclose(file); + (void) fclose(file); } return error_tag(symbol, ZINT_ERROR_MEMORY, "231: Insufficient memory for file read buffer"); } @@ -1456,17 +1480,21 @@ int ZBarcode_Encode_File(struct zint_symbol *symbol, const char *filename) { n = fread(buffer + nRead, 1, fileLen - nRead, file); if (ferror(file)) { sprintf(symbol->errtxt, "241: Input file read error (%d: %.30s)", errno, strerror(errno)); - if (file_opened) { - fclose(file); - } free(buffer); + if (file_opened) { + (void) fclose(file); + } return error_tag(symbol, ZINT_ERROR_INVALID_DATA, NULL); } nRead += n; } while (!feof(file) && (0 < n) && ((long) nRead < fileLen)); if (file_opened) { - fclose(file); + if (fclose(file) != 0) { + sprintf(symbol->errtxt, "794: Failure on closing input file (%d: %.30s)", errno, strerror(errno)); + free(buffer); + return error_tag(symbol, ZINT_ERROR_INVALID_DATA, NULL); + } } ret = ZBarcode_Encode(symbol, buffer, (int) nRead); free(buffer); diff --git a/backend/mailmark.c b/backend/mailmark.c index a3cd435d..1339a120 100644 --- a/backend/mailmark.c +++ b/backend/mailmark.c @@ -597,7 +597,8 @@ INTERNAL int mailmark_2d(struct zint_symbol *symbol, unsigned char source[], int } if (!is_sane(RUBIDIUM_F, local_source, 45)) { - strcpy(symbol->errtxt, "866: Invalid character in data (alphanumerics and space only in first 45 characters)"); + strcpy(symbol->errtxt, + "866: Invalid character in data (alphanumerics and space only in first 45 characters)"); return ZINT_ERROR_INVALID_DATA; } diff --git a/backend/pcx.c b/backend/pcx.c index e7b2c1e9..1f5841c0 100644 --- a/backend/pcx.c +++ b/backend/pcx.c @@ -207,10 +207,24 @@ INTERNAL int pcx_pixel_plot(struct zint_symbol *symbol, unsigned char *pixelbuf) } } + if (ferror(pcx_file)) { + sprintf(symbol->errtxt, "622: Incomplete write to output (%d: %.30s)", errno, strerror(errno)); + if (!output_to_stdout) { + (void) fclose(pcx_file); + } + return ZINT_ERROR_FILE_WRITE; + } + if (output_to_stdout) { - fflush(pcx_file); + if (fflush(pcx_file) != 0) { + sprintf(symbol->errtxt, "623: Incomplete flush to output (%d: %.30s)", errno, strerror(errno)); + return ZINT_ERROR_FILE_WRITE; + } } else { - fclose(pcx_file); + if (fclose(pcx_file) != 0) { + sprintf(symbol->errtxt, "624: Failure on closing output file (%d: %.30s)", errno, strerror(errno)); + return ZINT_ERROR_FILE_WRITE; + } } return 0; diff --git a/backend/png.c b/backend/png.c index 89d7687b..3617452e 100644 --- a/backend/png.c +++ b/backend/png.c @@ -245,7 +245,7 @@ INTERNAL int png_pixel_plot(struct zint_symbol *symbol, unsigned char *pixelbuf) if (!png_ptr) { strcpy(symbol->errtxt, "633: Insufficient memory for PNG write structure buffer"); if (!output_to_stdout) { - fclose(outfile); + (void) fclose(outfile); } return ZINT_ERROR_MEMORY; } @@ -255,7 +255,7 @@ INTERNAL int png_pixel_plot(struct zint_symbol *symbol, unsigned char *pixelbuf) png_destroy_write_struct(&png_ptr, NULL); strcpy(symbol->errtxt, "634: Insufficient memory for PNG info structure buffer"); if (!output_to_stdout) { - fclose(outfile); + (void) fclose(outfile); } return ZINT_ERROR_MEMORY; } @@ -264,7 +264,7 @@ INTERNAL int png_pixel_plot(struct zint_symbol *symbol, unsigned char *pixelbuf) if (setjmp(wpng_error.jmpbuf)) { png_destroy_write_struct(&png_ptr, &info_ptr); if (!output_to_stdout) { - fclose(outfile); + (void) fclose(outfile); } return ZINT_ERROR_MEMORY; } @@ -343,10 +343,24 @@ INTERNAL int png_pixel_plot(struct zint_symbol *symbol, unsigned char *pixelbuf) /* make sure we have disengaged */ png_destroy_write_struct(&png_ptr, &info_ptr); + if (ferror(outfile)) { + sprintf(symbol->errtxt, "638: Incomplete write to output (%d: %.30s)", errno, strerror(errno)); + if (!output_to_stdout) { + (void) fclose(outfile); + } + return ZINT_ERROR_FILE_WRITE; + } + if (output_to_stdout) { - fflush(outfile); + if (fflush(outfile) != 0) { + sprintf(symbol->errtxt, "639: Incomplete flush to output (%d: %.30s)", errno, strerror(errno)); + return ZINT_ERROR_FILE_WRITE; + } } else { - fclose(outfile); + if (fclose(outfile) != 0) { + sprintf(symbol->errtxt, "960: Failure on closing output file (%d: %.30s)", errno, strerror(errno)); + return ZINT_ERROR_FILE_WRITE; + } } return 0; diff --git a/backend/ps.c b/backend/ps.c index de956259..94009daf 100644 --- a/backend/ps.c +++ b/backend/ps.c @@ -271,38 +271,38 @@ INTERNAL int ps_plot(struct zint_symbol *symbol) { } /* Start writing the header */ - fprintf(feps, "%%!PS-Adobe-3.0 EPSF-3.0\n"); + fputs("%!PS-Adobe-3.0 EPSF-3.0\n", feps); if (ZINT_VERSION_BUILD) { fprintf(feps, "%%%%Creator: Zint %d.%d.%d.%d\n", ZINT_VERSION_MAJOR, ZINT_VERSION_MINOR, ZINT_VERSION_RELEASE, ZINT_VERSION_BUILD); } else { fprintf(feps, "%%%%Creator: Zint %d.%d.%d\n", ZINT_VERSION_MAJOR, ZINT_VERSION_MINOR, ZINT_VERSION_RELEASE); } - fprintf(feps, "%%%%Title: Zint Generated Symbol\n"); - fprintf(feps, "%%%%Pages: 0\n"); + fputs("%%Title: Zint Generated Symbol\n" + "%%Pages: 0\n", feps); fprintf(feps, "%%%%BoundingBox: 0 0 %d %d\n", (int) ceilf(symbol->vector->width), (int) ceilf(symbol->vector->height)); - fprintf(feps, "%%%%EndComments\n"); + fputs("%%EndComments\n", feps); /* Definitions */ if (have_circles_without_width) { /* Disc: x y radius TD */ - fprintf(feps, "/TD { newpath 0 360 arc fill } bind def\n"); + fputs("/TD { newpath 0 360 arc fill } bind def\n", feps); } if (have_circles_with_width) { /* Circle (ring): x y radius width TC (adapted from BWIPP renmaxicode.ps) */ - fprintf(feps, "/TC { newpath 4 1 roll 3 copy 0 360 arc closepath 4 -1 roll add 360 0 arcn closepath fill }" - " bind def\n"); + fputs("/TC { newpath 4 1 roll 3 copy 0 360 arc closepath 4 -1 roll add 360 0 arcn closepath fill }" + " bind def\n", feps); } if (symbol->vector->hexagons) { - fprintf(feps, "/TH { 0 setlinewidth moveto lineto lineto lineto lineto lineto closepath fill } bind def\n"); + fputs("/TH { 0 setlinewidth moveto lineto lineto lineto lineto lineto closepath fill } bind def\n", feps); } - fprintf(feps, "/TB { 2 copy } bind def\n"); - fprintf(feps, "/TR { newpath 4 1 roll exch moveto 1 index 0 rlineto 0 exch rlineto neg 0 rlineto closepath fill }" - " bind def\n"); - fprintf(feps, "/TE { pop pop } bind def\n"); + fputs("/TB { 2 copy } bind def\n" + "/TR { newpath 4 1 roll exch moveto 1 index 0 rlineto 0 exch rlineto neg 0 rlineto closepath fill }" + " bind def\n" + "/TE { pop pop } bind def\n", feps); - fprintf(feps, "newpath\n"); + fputs("newpath\n", feps); /* Now the actual representation */ @@ -315,7 +315,7 @@ INTERNAL int ps_plot(struct zint_symbol *symbol) { } fprintf(feps, "%.2f 0.00 TB 0.00 %.2f TR\n", symbol->vector->height, symbol->vector->width); - fprintf(feps, "TE\n"); + fputs("TE\n", feps); } if (symbol->symbology != BARCODE_ULTRA) { @@ -344,7 +344,7 @@ INTERNAL int ps_plot(struct zint_symbol *symbol) { } fprintf(feps, "%.2f %.2f TB %.2f %.2f TR\n", rect->height, (symbol->vector->height - rect->y) - rect->height, rect->x, rect->width); - fprintf(feps, "TE\n"); + fputs("TE\n", feps); } rect = rect->next; } @@ -361,7 +361,7 @@ INTERNAL int ps_plot(struct zint_symbol *symbol) { } fprintf(feps, "%.2f %.2f TB %.2f %.2f TR\n", rect->height, (symbol->vector->height - rect->y) - rect->height, rect->x, rect->width); - fprintf(feps, "TE\n"); + fputs("TE\n", feps); } rect = rect->next; } @@ -371,7 +371,7 @@ INTERNAL int ps_plot(struct zint_symbol *symbol) { while (rect) { fprintf(feps, "%.2f %.2f TB %.2f %.2f TR\n", rect->height, (symbol->vector->height - rect->y) - rect->height, rect->x, rect->width); - fprintf(feps, "TE\n"); + fputs("TE\n", feps); rect = rect->next; } } @@ -473,17 +473,17 @@ INTERNAL int ps_plot(struct zint_symbol *symbol) { if (iso_latin1) { /* Change encoding to ISO 8859-1, see Postscript Language Reference Manual 2nd Edition Example 5.6 */ fprintf(feps, "/%s findfont\n", font); - fprintf(feps, "dup length dict begin\n"); - fprintf(feps, "{1 index /FID ne {def} {pop pop} ifelse} forall\n"); - fprintf(feps, "/Encoding ISOLatin1Encoding def\n"); - fprintf(feps, "currentdict\n"); - fprintf(feps, "end\n"); - fprintf(feps, "/Helvetica-ISOLatin1 exch definefont pop\n"); + fputs("dup length dict begin\n" + "{1 index /FID ne {def} {pop pop} ifelse} forall\n" + "/Encoding ISOLatin1Encoding def\n" + "currentdict\n" + "end\n" + "/Helvetica-ISOLatin1 exch definefont pop\n", feps); font = "Helvetica-ISOLatin1"; } do { ps_convert(string->text, ps_string); - fprintf(feps, "matrix currentmatrix\n"); + fputs("matrix currentmatrix\n", feps); fprintf(feps, "/%s findfont\n", font); fprintf(feps, "%.2f scalefont setfont\n", string->fsize); fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", @@ -492,31 +492,45 @@ INTERNAL int ps_plot(struct zint_symbol *symbol) { fprintf(feps, " (%s) stringwidth\n", ps_string); } if (string->rotation != 0) { - fprintf(feps, "gsave\n"); + fputs("gsave\n", feps); fprintf(feps, "%d rotate\n", 360 - string->rotation); } if (string->halign == 0 || string->halign == 2) { - fprintf(feps, "pop\n"); + fputs("pop\n", feps); fprintf(feps, "%s 0 rmoveto\n", string->halign == 2 ? "neg" : "-2 div"); } fprintf(feps, " (%s) show\n", ps_string); if (string->rotation != 0) { - fprintf(feps, "grestore\n"); + fputs("grestore\n", feps); } - fprintf(feps, "setmatrix\n"); + fputs("setmatrix\n", feps); string = string->next; } while (string); } - if (output_to_stdout) { - fflush(feps); - } else { - fclose(feps); - } - if (locale) setlocale(LC_ALL, locale); + if (ferror(feps)) { + sprintf(symbol->errtxt, "647: Incomplete write to output (%d: %.30s)", errno, strerror(errno)); + if (!output_to_stdout) { + (void) fclose(feps); + } + return ZINT_ERROR_FILE_WRITE; + } + + if (output_to_stdout) { + if (fflush(feps) != 0) { + sprintf(symbol->errtxt, "648: Incomplete flush to output (%d: %.30s)", errno, strerror(errno)); + return ZINT_ERROR_FILE_WRITE; + } + } else { + if (fclose(feps) != 0) { + sprintf(symbol->errtxt, "649: Failure on closing output file (%d: %.30s)", errno, strerror(errno)); + return ZINT_ERROR_FILE_WRITE; + } + } + return error_number; } diff --git a/backend/qr.c b/backend/qr.c index 5e5d9c81..59de05e2 100644 --- a/backend/qr.c +++ b/backend/qr.c @@ -1013,7 +1013,7 @@ static int append_log(char log) { file = fopen("zintlog.txt", "a+"); fprintf(file, "%c", log); - fclose(file); + (void) fclose(file); return 0; } @@ -1023,7 +1023,7 @@ static int write_log(char log[]) { file = fopen("zintlog.txt", "a+"); fprintf(file, log); /*writes*/ fprintf(file, "\r\n"); /*writes*/ - fclose(file); + (void) fclose(file); return 0; } #endif diff --git a/backend/svg.c b/backend/svg.c index 41171814..4b1c5ed4 100644 --- a/backend/svg.c +++ b/backend/svg.c @@ -136,6 +136,7 @@ INTERNAL int svg_plot(struct zint_symbol *symbol) { char colour_code[7]; int len, html_len; + const int output_to_stdout = symbol->output_options & BARCODE_STDOUT; char *html_string; for (i = 0; i < 6; i++) { @@ -181,7 +182,7 @@ INTERNAL int svg_plot(struct zint_symbol *symbol) { strcpy(symbol->errtxt, "681: Vector header NULL"); return ZINT_ERROR_INVALID_DATA; } - if (symbol->output_options & BARCODE_STDOUT) { + if (output_to_stdout) { fsvg = stdout; } else { if (!(fsvg = out_fopen(symbol->outfile, "w"))) { @@ -193,14 +194,14 @@ INTERNAL int svg_plot(struct zint_symbol *symbol) { locale = setlocale(LC_ALL, "C"); /* Start writing the header */ - fprintf(fsvg, "\n"); - fprintf(fsvg, "\n"); + fputs("\n" + "\n", fsvg); fprintf(fsvg, "vector->width), (int) ceilf(symbol->vector->height)); - fprintf(fsvg, " xmlns=\"http://www.w3.org/2000/svg\">\n"); - fprintf(fsvg, " Zint Generated Symbol\n"); - fprintf(fsvg, " \n"); + fputs(" xmlns=\"http://www.w3.org/2000/svg\">\n" + " Zint Generated Symbol\n" + " \n", fsvg); fprintf(fsvg, "\n \n", fgcolour_string); if (bg_alpha != 0) { @@ -209,7 +210,7 @@ INTERNAL int svg_plot(struct zint_symbol *symbol) { if (bg_alpha != 0xff) { fprintf(fsvg, " opacity=\"%.3f\"", bg_alpha_opacity); } - fprintf(fsvg, " />\n"); + fputs(" />\n", fsvg); } rect = symbol->vector->rectangles; @@ -223,7 +224,7 @@ INTERNAL int svg_plot(struct zint_symbol *symbol) { if (fg_alpha != 0xff) { fprintf(fsvg, " opacity=\"%.3f\"", fg_alpha_opacity); } - fprintf(fsvg, " />\n"); + fputs(" />\n", fsvg); rect = rect->next; } @@ -268,7 +269,7 @@ INTERNAL int svg_plot(struct zint_symbol *symbol) { if (fg_alpha != 0xff) { fprintf(fsvg, " opacity=\"%.3f\"", fg_alpha_opacity); } - fprintf(fsvg, " />\n"); + fputs(" />\n", fsvg); hex = hex->next; } @@ -300,7 +301,7 @@ INTERNAL int svg_plot(struct zint_symbol *symbol) { fprintf(fsvg, " opacity=\"%.3f\"", fg_alpha_opacity); } } - fprintf(fsvg, " />\n"); + fputs(" />\n", fsvg); circle = circle->next; } @@ -312,7 +313,7 @@ INTERNAL int svg_plot(struct zint_symbol *symbol) { fprintf(fsvg, " x, string->y, halign); fprintf(fsvg, " font-family=\"%s\" font-size=\"%.1f\"", font_family, string->fsize); if (bold) { - fprintf(fsvg, " font-weight=\"bold\""); + fputs(" font-weight=\"bold\"", fsvg); } if (fg_alpha != 0xff) { fprintf(fsvg, " opacity=\"%.3f\"", fg_alpha_opacity); @@ -320,25 +321,39 @@ INTERNAL int svg_plot(struct zint_symbol *symbol) { if (string->rotation != 0) { fprintf(fsvg, " transform=\"rotate(%d,%.2f,%.2f)\"", string->rotation, string->x, string->y); } - fprintf(fsvg, " >\n"); + fputs(" >\n", fsvg); make_html_friendly(string->text, html_string); fprintf(fsvg, " %s\n", html_string); - fprintf(fsvg, " \n"); + fputs(" \n", fsvg); string = string->next; } - fprintf(fsvg, " \n"); - fprintf(fsvg, "\n"); - - if (symbol->output_options & BARCODE_STDOUT) { - fflush(fsvg); - } else { - fclose(fsvg); - } + fputs(" \n" + "\n", fsvg); if (locale) setlocale(LC_ALL, locale); + if (ferror(fsvg)) { + sprintf(symbol->errtxt, "682: Incomplete write to output (%d: %.30s)", errno, strerror(errno)); + if (!output_to_stdout) { + (void) fclose(fsvg); + } + return ZINT_ERROR_FILE_WRITE; + } + + if (output_to_stdout) { + if (fflush(fsvg) != 0) { + sprintf(symbol->errtxt, "683: Incomplete flush to output (%d: %.30s)", errno, strerror(errno)); + return ZINT_ERROR_FILE_WRITE; + } + } else { + if (fclose(fsvg) != 0) { + sprintf(symbol->errtxt, "684: Failure on closing output file (%d: %.30s)", errno, strerror(errno)); + return ZINT_ERROR_FILE_WRITE; + } + } + return error_number; } diff --git a/backend/tif.c b/backend/tif.c index c64287b5..060bf25c 100644 --- a/backend/tif.c +++ b/backend/tif.c @@ -398,7 +398,7 @@ INTERNAL int tif_pixel_plot(struct zint_symbol *symbol, unsigned char *pixelbuf) file_pos = ftell(tif_file); if (!tif_lzw_encode(&lzw_state, tif_file, strip_buf, bytes_put)) { /* Only fails if can't malloc */ tif_lzw_cleanup(&lzw_state); - fclose(tif_file); /* Only use LZW if not STDOUT, so ok to close */ + (void) fclose(tif_file); /* Only use LZW if not STDOUT, so ok to close */ strcpy(symbol->errtxt, "673: Failed to malloc LZW hash table"); return ZINT_ERROR_MEMORY; } @@ -603,15 +603,29 @@ INTERNAL int tif_pixel_plot(struct zint_symbol *symbol, unsigned char *pixelbuf) total_bytes_put += 6 * color_map_size; } + if (ferror(tif_file)) { + sprintf(symbol->errtxt, "679: Incomplete write to output (%d: %.30s)", errno, strerror(errno)); + if (!output_to_stdout) { + (void) fclose(tif_file); + } + return ZINT_ERROR_FILE_WRITE; + } + if (output_to_stdout) { - fflush(tif_file); + if (fflush(tif_file) != 0) { + sprintf(symbol->errtxt, "980: Incomplete flush to output (%d: %.30s)", errno, strerror(errno)); + return ZINT_ERROR_FILE_WRITE; + } } else { if (ftell(tif_file) != total_bytes_put) { - fclose(tif_file); + (void) fclose(tif_file); strcpy(symbol->errtxt, "674: Failed to write all output"); return ZINT_ERROR_FILE_WRITE; } - fclose(tif_file); + if (fclose(tif_file) != 0) { + sprintf(symbol->errtxt, "981: Failure on closing output file (%d: %.30s)", errno, strerror(errno)); + return ZINT_ERROR_FILE_WRITE; + } } return 0; diff --git a/backend/zint.h b/backend/zint.h index 9c13b7cb..43b23670 100644 --- a/backend/zint.h +++ b/backend/zint.h @@ -42,31 +42,34 @@ extern "C" { #endif /* __cplusplus */ + /* Vector elements - see vector header `zint_vector` below */ struct zint_vector_rect { - float x, y, height, width; + float x, y; /* Top left */ + float height, width; int colour; /* -1 for foreground, 1-8 for Cyan, Blue, Magenta, Red, Yellow, Green, Black, White */ struct zint_vector_rect *next; /* Pointer to next rectangle */ }; struct zint_vector_hexagon { - float x, y, diameter; - int rotation; /* 0, 90, 180, 270 degrees */ + float x, y; /* Centre */ + float diameter; /* Short (minimal) diameter (i.e. diameter of inscribed circle) */ + int rotation; /* 0, 90, 180, 270 degrees, where 0 has apex at top, i.e. short diameter is horizontal */ struct zint_vector_hexagon *next; /* Pointer to next hexagon */ }; struct zint_vector_string { - float x, y; /* x, y position relative to halign */ + float x, y; /* Top with x relative to halign (i.e. centre, left, right) */ float fsize; /* Font size */ float width; /* Suggested string width, may be 0 if none recommended */ int length; /* Number of characters */ int rotation; /* 0, 90, 180, 270 degrees */ int halign; /* Horizontal alignment: 0 for centre, 1 for left, 2 for right (end) */ - unsigned char *text; + unsigned char *text; /* UTF-8, NUL-terminated */ struct zint_vector_string *next; /* Pointer to next string */ }; struct zint_vector_circle { - float x, y; + float x, y; /* Centre */ float diameter; /* Circle diameter. Does not include width (if any) */ float width; /* Width of circle perimeter (circumference). 0 for fill (disc) */ int colour; /* Non-zero for draw with background colour (else draw with foreground colour) */ @@ -185,7 +188,7 @@ extern "C" { #define BARCODE_PDF417TRUNC 56 /* Legacy */ #define BARCODE_MAXICODE 57 /* MaxiCode */ #define BARCODE_QRCODE 58 /* QR Code */ -#define BARCODE_CODE128AB 60 /* Code 128 (Suppress subset C) */ +#define BARCODE_CODE128AB 60 /* Code 128 (Suppress Code Set C) */ #define BARCODE_CODE128B 60 /* Legacy */ #define BARCODE_AUSPOST 63 /* Australia Post Standard Customer */ #define BARCODE_AUSREPLY 66 /* Australia Post Reply Paid */ diff --git a/docs/manual.pmd b/docs/manual.pmd index 12c64e28..a307fb0a 100644 --- a/docs/manual.pmd +++ b/docs/manual.pmd @@ -492,15 +492,20 @@ Sequence Equivalent `\\` 0x5C `\` Backslash -`\dNNN` NNN Any 8-bit character where NNN is decimal (0-255) +`\dNNN` NNN Any 8-bit character where NNN is decimal + (000-255) + +`\oNNN` 0oNNN Any 8-bit character where NNN is octal + (000-377) `\xNN` 0xNN Any 8-bit character where NN is hexadecimal + (00-FF) `\uNNNN` Any 16-bit Unicode BMP[^2] character where - NNNN is hexadecimal + NNNN is hexadecimal (0000-FFFF) `\UNNNNNN` Any 21-bit Unicode character where NNNNNN - is hexadecimal (maximum 0x10FFFF) + is hexadecimal (000000-10FFFF) --------------------------------------------------------------------------- Table: {#tbl:escape_sequences tag=": Escape Sequences"} @@ -593,7 +598,7 @@ Value 18 `BARCODE_CODABAR` Codabar - 20 `BARCODE_CODE128` Code 128 (automatic subset switching) + 20 `BARCODE_CODE128` Code 128 (automatic Code Set switching) 21 `BARCODE_DPLEIT` Deutsche Post Leitcode @@ -648,7 +653,7 @@ Value 58 `BARCODE_QRCODE` QR Code - 60 `BARCODE_CODE128AB` Code 128 (Suppress subset C) + 60 `BARCODE_CODE128AB` Code 128 (Suppress Code Set C) 63 `BARCODE_AUSPOST` Australia Post Standard Customer @@ -2776,20 +2781,22 @@ pharmaceuticals. The symbology is able to encode whole numbers between 3 and One of the most ubiquitous one-dimensional barcode symbologies, Code 128 was developed in 1981 by Computer Identics. This symbology supports full ASCII text -and uses a three-mode system to compress the data into a smaller symbol. Zint -automatically switches between modes and adds a modulo-103 check digit. Code -128 is the default barcode symbology used by Zint. In addition Zint supports -the encoding of ISO/IEC 8859-1 (non-English) characters in Code 128 symbols. The -ISO/IEC 8859-1 character set is shown in Appendix [A.2 Latin Alphabet No. 1 -(ISO/IEC 8859-1)]. +and uses a three-Code Set system to compress the data into a smaller symbol. +Zint automatically switches between Code Sets A, B and C and adds a modulo-103 +check digit. -#### 6.1.10.2 Code 128 Suppress Subset C (Subsets A and B only) +Code 128 is the default barcode symbology used by Zint. In addition Zint +supports the encoding of ISO/IEC 8859-1 (non-English) characters in Code 128 +symbols. The ISO/IEC 8859-1 character set is shown in Appendix [A.2 Latin +Alphabet No. 1 (ISO/IEC 8859-1)]. + +#### 6.1.10.2 Code 128 Suppress Code Set C (Code Sets A and B only) ![`zint -b CODE128AB -d "130170X178"`](images/code128ab.svg) -It is sometimes advantageous to stop Code 128 from using subset mode C which +It is sometimes advantageous to stop Code 128 from using Code Set C which compresses numerical data. The `BARCODE_CODE128AB`[^10] variant (symbology 60) -suppresses mode C in favour of modes A and B. +suppresses Code Set C in favour of Code Sets A and B. [^10]: `BARCODE_CODE128AB` previously used the name `BARCODE_CODE128B`, which is still recognised. diff --git a/docs/manual.txt b/docs/manual.txt index af7e5169..6c5e108c 100644 --- a/docs/manual.txt +++ b/docs/manual.txt @@ -106,7 +106,7 @@ December 2022 - 6.1.9 Pharmacode - 6.1.10 Code 128 - 6.1.10.1 Standard Code 128 (ISO 15417) - - 6.1.10.2 Code 128 Suppress Subset C (Subsets A and B only) + - 6.1.10.2 Code 128 Suppress Code Set C (Code Sets A and B only) - 6.1.10.3 GS1-128 - 6.1.10.4 EAN-14 - 6.1.10.5 NVE-18 (SSCC-18) @@ -646,15 +646,19 @@ sequences are shown in the table below. \\ 0x5C \ Backslash \dNNN NNN Any 8-bit character where NNN is decimal - (0-255) + (000-255) + + \oNNN 0oNNN Any 8-bit character where NNN is octal + (000-377) \xNN 0xNN Any 8-bit character where NN is hexadecimal + (00-FF) \uNNNN Any 16-bit Unicode BMP[2] character where - NNNN is hexadecimal + NNNN is hexadecimal (0000-FFFF) \UNNNNNN Any 21-bit Unicode character where NNNNNN - is hexadecimal (maximum 0x10FFFF) + is hexadecimal (000000-10FFFF) ---------------------------------------------------------------------------- : Table : Escape Sequences: @@ -731,7 +735,7 @@ underscores are optional. 18 BARCODE_CODABAR Codabar - 20 BARCODE_CODE128 Code 128 (automatic subset switching) + 20 BARCODE_CODE128 Code 128 (automatic Code Set switching) 21 BARCODE_DPLEIT Deutsche Post Leitcode @@ -786,7 +790,7 @@ underscores are optional. 58 BARCODE_QRCODE QR Code - 60 BARCODE_CODE128AB Code 128 (Suppress subset C) + 60 BARCODE_CODE128AB Code 128 (Suppress Code Set C) 63 BARCODE_AUSPOST Australia Post Standard Customer @@ -2729,20 +2733,22 @@ pharmaceuticals. The symbology is able to encode whole numbers between 3 and One of the most ubiquitous one-dimensional barcode symbologies, Code 128 was developed in 1981 by Computer Identics. This symbology supports full ASCII text -and uses a three-mode system to compress the data into a smaller symbol. Zint -automatically switches between modes and adds a modulo-103 check digit. Code 128 -is the default barcode symbology used by Zint. In addition Zint supports the -encoding of ISO/IEC 8859-1 (non-English) characters in Code 128 symbols. The -ISO/IEC 8859-1 character set is shown in Appendix A.2 Latin Alphabet No. 1 -(ISO/IEC 8859-1). +and uses a three-Code Set system to compress the data into a smaller symbol. +Zint automatically switches between Code Sets A, B and C and adds a modulo-103 +check digit. -6.1.10.2 Code 128 Suppress Subset C (Subsets A and B only) +Code 128 is the default barcode symbology used by Zint. In addition Zint +supports the encoding of ISO/IEC 8859-1 (non-English) characters in Code 128 +symbols. The ISO/IEC 8859-1 character set is shown in Appendix A.2 Latin +Alphabet No. 1 (ISO/IEC 8859-1). + +6.1.10.2 Code 128 Suppress Code Set C (Code Sets A and B only) [zint -b CODE128AB -d "130170X178"] -It is sometimes advantageous to stop Code 128 from using subset mode C which +It is sometimes advantageous to stop Code 128 from using Code Set C which compresses numerical data. The BARCODE_CODE128AB[10] variant (symbology 60) -suppresses mode C in favour of modes A and B. +suppresses Code Set C in favour of Code Sets A and B. 6.1.10.3 GS1-128 @@ -4497,8 +4503,10 @@ OPTIONS \\ (0x5C) \ Backslash \dNNN (NNN) Any 8-bit character where NNN is decimal (000-255) + \oNNN (0oNNN) Any 8-bit character where NNN is + octal (000-377) \xNN (0xNN) Any 8-bit character where NN is - hexadecimal + hexadecimal (00-FF) \uNNNN (U+NNNN) Any 16-bit Unicode BMP character where NNNN is hexadecimal \UNNNNNN (U+NNNNNN) Any 21-bit Unicode character @@ -4749,8 +4757,10 @@ OPTIONS C25LOGIC ditto C25STANDARD ditto Codabar 1 or 2 (add hidden or visible check digit) - Code 11 0 or 1 (no or 1 visible check digit only) - (default is 2 visible check digits) + Code 11 0 to 2 (2 visible check digits to none) + 0 (default 2 visible check digits) + 1 (1 visible check digit) + 2 (no check digits) Code 39 1 (add visible check digit) Code 93 1 (hide the default check characters) EXCODE39 1 (add visible check digit) diff --git a/docs/zint.1 b/docs/zint.1 index df97a860..21e16ddc 100644 --- a/docs/zint.1 +++ b/docs/zint.1 @@ -187,8 +187,10 @@ The escape sequences are: \[rs]\[rs] (0x5C) \[rs] Backslash \[rs]dNNN (NNN) Any 8-bit character where NNN is decimal (000-255) +\[rs]oNNN (0oNNN) Any 8-bit character where NNN is + octal (000-377) \[rs]xNN (0xNN) Any 8-bit character where NN is - hexadecimal + hexadecimal (00-FF) \[rs]uNNNN (U+NNNN) Any 16-bit Unicode BMP character where NNNN is hexadecimal \[rs]UNNNNNN (U+NNNNNN) Any 21-bit Unicode character @@ -466,8 +468,10 @@ C25INTER ditto C25LOGIC ditto C25STANDARD ditto Codabar 1 or 2 (add hidden or visible check digit) -Code 11 0 or 1 (no or 1 visible check digit only) - (default is 2 visible check digits) +Code 11 0 to 2 (2 visible check digits to none) + 0 (default 2 visible check digits) + 1 (1 visible check digit) + 2 (no check digits) Code 39 1 (add visible check digit) Code 93 1 (hide the default check characters) EXCODE39 1 (add visible check digit) diff --git a/docs/zint.1.pmd b/docs/zint.1.pmd index 4e6964c0..7dca801b 100644 --- a/docs/zint.1.pmd +++ b/docs/zint.1.pmd @@ -139,8 +139,10 @@ Paintbrush (`PCX`), Portable Network Format (`PNG`), Scalable Vector Graphic (`S \\ (0x5C) \ Backslash \dNNN (NNN) Any 8-bit character where NNN is decimal (000-255) + \oNNN (0oNNN) Any 8-bit character where NNN is + octal (000-377) \xNN (0xNN) Any 8-bit character where NN is - hexadecimal + hexadecimal (00-FF) \uNNNN (U+NNNN) Any 16-bit Unicode BMP character where NNNN is hexadecimal \UNNNNNN (U+NNNNNN) Any 21-bit Unicode character @@ -368,8 +370,10 @@ Paintbrush (`PCX`), Portable Network Format (`PNG`), Scalable Vector Graphic (`S C25LOGIC ditto C25STANDARD ditto Codabar 1 or 2 (add hidden or visible check digit) - Code 11 0 or 1 (no or 1 visible check digit only) - (default is 2 visible check digits) + Code 11 0 to 2 (2 visible check digits to none) + 0 (default 2 visible check digits) + 1 (1 visible check digit) + 2 (no check digits) Code 39 1 (add visible check digit) Code 93 1 (hide the default check characters) EXCODE39 1 (add visible check digit) diff --git a/frontend_qt/mainWindow.ui b/frontend_qt/mainWindow.ui index 073a925e..c405564e 100644 --- a/frontend_qt/mainWindow.ui +++ b/frontend_qt/mainWindow.ui @@ -1530,6 +1530,7 @@ or import from file <tr><td>\R&nbsp;</td><td>Record Separator (0x1E)</td></tr> <tr><td>\\&nbsp;</td><td>Backslash (0x5C)</td></tr> <tr><td>\dNNN&nbsp;</td><td>8-bit character (N decimal)</td></tr> +<tr><td>\oNNN&nbsp;</td><td>8-bit character (N octal)</td></tr> <tr><td>\xNN&nbsp;</td><td>8-bit character (N hex)</td></tr> <tr><td>\uNNNN&nbsp;</td><td>16-bit Unicode BMP (N hex)</td></tr> <tr><td>\UNNNNNN&nbsp;</td><td>21-bit Unicode (N hex)</td></tr>