From 46e4c42edde1f920ddd8acee3f4a2b55ab7ab12b Mon Sep 17 00:00:00 2001 From: Ralph Little Date: Fri, 13 May 2022 09:42:59 -0700 Subject: [PATCH 1/3] configure.in: updated GIMP checks for 2.10.0 minimal and only supported version We do not now support GIMP before 2.10.0 since they moved to the GEGL API. --- configure.in | 29 +----- m4/gimp-orauch.m4 | 251 ---------------------------------------------- 2 files changed, 3 insertions(+), 277 deletions(-) delete mode 100644 m4/gimp-orauch.m4 Index: trunk/configure.in =================================================================== --- trunk.orig/configure.in +++ trunk/configure.in @@ -47,13 +47,6 @@ AC_MSG_CHECKING([whether GIMP plugin is AC_ARG_ENABLE(gimp, [ --disable-gimp do not include GIMP plugin mode], USE_GIMP=$enableval, USE_GIMP=yes) AC_MSG_RESULT($USE_GIMP) -if test "${USE_GIMP}" = "yes"; then - dnl Check for gimp-2 plugin support, default is enabled - AC_MSG_CHECKING([whether GIMP-2.0 is requested]) - AC_ARG_ENABLE(gimp2, [ --disable-gimp2 do not use GIMP-2.0, use GIMP-1.x if available], TRY_GIMP_2=$enableval, TRY_GIMP_2=yes) - AC_MSG_RESULT($TRY_GIMP_2) -fi - dnl Check for jpeg support AC_MSG_CHECKING([whether JPEG support is requested]) dnl Default is enabled JPEG @@ -170,20 +163,16 @@ PKG_CHECK_VAR([SANE_PREFIX], [sane-backe PKG_CHECK_VAR([SANE_LDFLAGS], [sane-backends >= 1.0.0], [ldflags]) if test "${USE_GIMP}" = "yes"; then - if test "${TRY_GIMP_2}" = "yes"; then - AM_PATH_GIMP_2_0(1.3.23, HAVE_GIMP=yes, ) - fi + AM_PATH_GIMP_2_0(2.10.0, HAVE_GIMP=yes, ) fi if test "${HAVE_GIMP}" = "yes"; then HAVE_GTK=yes - AC_DEFINE([HAVE_GIMP_2], 1, [Define to 1 if you have gimp-2.0.]) + AC_DEFINE([HAVE_ANY_GIMP], 1, [Define to 1 if you have gimp - no matter what version.]) else dnl *** We do not have gimp-2.0 *** dnl *** if xsane is compiled as gimp plugin it is possible that we do not - dnl *** need the test for gtk, but when we have gimp-1.0.x installed - dnl *** (gimp-1.0.x does not have gimp-config) or we compile xsane without - dnl *** gimp support we need the test for gtk. + dnl *** need the test for gtk. dnl *** we start with the test for GTK+-2.0, if this fails or is diabled dnl *** then we test for gtk+-1.2 @@ -194,19 +183,7 @@ else if test "x${HAVE_GTK}" = "x"; then AM_PATH_GTK(1.2.0, HAVE_GTK=yes, ) fi - - if test "${USE_GIMP}" = "yes"; then - dnl *** now we can test for gimp-1.x.x, for gimp-1.0.x we need GTK_* settings *** - AM_PATH_GIMP_ORAUCH(1.0.0, HAVE_GIMP=yes) - fi -fi - -if test "${HAVE_GIMP}" = "yes"; then - dnl *** we have gimp *** - dnl *** define macro HAVE_ANY_GIMP for sourcecode tests for gimp *** - AC_DEFINE([HAVE_ANY_GIMP], 1, [Define to 1 if you have gimp - no matter what version.]) fi - # png test must stand after test for zlib # png test must stand behind GTK-check (X-Window-check) Index: trunk/m4/gimp-orauch.m4 =================================================================== --- trunk.orig/m4/gimp-orauch.m4 +++ /dev/null @@ -1,251 +0,0 @@ -###################################################################### -# Configure paths for The GIMP -# Oliver Rauch 2000-12-28, Changes 2004-04-20 -# Parts from the original gimp.m4 -# with extensions that this version can handle gimp-1.0.x - -dnl AM_PATH_GIMP_ORAUCH([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) -dnl Test for GIMP, and define GIMP_CFLAGS and GIMP_LIBS -dnl -AC_DEFUN(AM_PATH_GIMP_ORAUCH, -[dnl -dnl Get the cflags and libraries from the gimp-config script -dnl - AC_ARG_WITH(gimp-prefix,[ --with-gimp-prefix=PFX Prefix where GIMP is installed (optional)], - gimp_config_prefix="$withval", gimp_config_prefix="") - AC_ARG_WITH(gimp-exec-prefix,[ --with-gimp-exec-prefix=PFX Exec prefix where GIMP is installed (optional)], - gimp_config_exec_prefix="$withval", gimp_config_exec_prefix="") - AC_ARG_ENABLE(gimptest, [ --disable-gimptest do not try to compile and run a test GIMP program], , enable_gimptest=yes) - - ac_save_CFLAGS="$CFLAGS" - ac_save_LIBS="$LIBS" - ac_save_GTK_CFLAGS="$GTK_CFLAGS" - ac_save_GTK_LIBS="$GTK_LIBS" - - if test x$gimp_config_exec_prefix != x ; then - gimp_config_args="$gimp_config_args --exec-prefix=$gimp_config_exec_prefix" - if test x${GIMP_CONFIG+set} != xset ; then - GIMP_CONFIG=$gimp_config_exec_prefix/bin/gimp-config - fi - fi - - if test x$gimp_config_prefix != x ; then - gimp_config_args="$gimp_config_args --prefix=$gimp_config_prefix" - if test x${GIMP_CONFIG+set} != xset ; then - GIMP_CONFIG=$gimp_config_prefix/bin/gimp-config - fi - fi - - AC_PATH_PROG(GIMP_CONFIG, gimp-config, no) - if test "$GIMP_CONFIG" = "no" ; then - if test x$gimp_config_exec_prefix != x ; then - gimp_config_args="$gimp_config_args --exec-prefix=$gimp_config_exec_prefix" - if test x${GIMP_TOOL+set} != xset ; then - GIMP_TOOL=$gimp_config_exec_prefix/bin/gimptool - fi - fi - if test x$gimp_config_prefix != x ; then - gimp_config_args="$gimp_config_args --prefix=$gimp_config_prefix" - if test x${GIMP_TOOL+set} != xset ; then - GIMP_TOOL=$gimp_config_prefix/bin/gimptool - fi - fi - AC_PATH_PROG(GIMP_TOOL, gimptool, no) - GIMP_CONFIG=$GIMP_TOOL - fi - - min_gimp_version=ifelse([$1], ,1.0.0,$1) - no_gimp="" - - if test "$GIMP_CONFIG" = "no" ; then -dnl we do not have gimp-config (gimp-1.0.x does not have gimp-config) -dnl so we have to use the GTK_* things for testing for gimp.h and gimpfeatures.h - ac_save_CPPFLAGS="$CPPFLAGS" - CPPFLAGS="${CPPFLAGS} ${GTK_CFLAGS}" - AC_CHECK_HEADERS(libgimp/gimp.h, GIMP_LIBS="-lgimp", no_gimp=yes) - AC_CHECK_HEADERS(libgimp/gimpfeatures.h) - CPPFLAGS="$ac_save_CPPFLAGS" - CFLAGS="${CFLAGS} ${GTK_CFLAGS}" - LIBS="${LIBS} ${GTK_LIBS} ${GIMP_LIBS}" - - if test "x$no_gimp" = x ; then - dnl *** we have found libgimp/gimp.h *** - AC_MSG_CHECKING(GIMP compilation) - gimp_config_major_version=-1 - gimp_config_minor_version=0 - gimp_config_micro_version=0 - fi - else -dnl Ok, we have gimp-config and so we do not need the GTK_* things because they are -dnl included in the output of gimp-config - GTK_CFLAGS="" - GTK_LIBS="" - GIMP_CFLAGS=`$GIMP_CONFIG $gimp_config_args --cflags` - GIMP_LIBS=`$GIMP_CONFIG $gimp_config_args --libs`" -lgimp" - gimp_config_major_version=`$GIMP_CONFIG $gimp_config_args --version | \ - sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` - gimp_config_minor_version=`$GIMP_CONFIG $gimp_config_args --version | \ - sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` - gimp_config_micro_version=`$GIMP_CONFIG $gimp_config_args --version | \ - sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` - CFLAGS="${CFLAGS} ${GIMP_CFLAGS}" - LIBS="${LIBS} ${GIMP_LIBS}" - AC_MSG_CHECKING(for GIMP - version >= $min_gimp_version) - fi - -dnl -dnl Now check if the installed GIMP is sufficiently new. (Also sanity -dnl checks the results of gimp-config to some extent -dnl - if test "x$no_gimp" = x ; then - if test "$enable_gimptest" = "yes" ; then - rm -f conf.gimptest - AC_TRY_RUN([ -#include -#include - -#define GIMP_TEST_CHECK_VERSION(major, minor, micro) \ - ($gimp_config_major_version > (major) || \ - ($gimp_config_major_version == (major) && $gimp_config_minor_version > (minor)) || \ - ($gimp_config_major_version == (major) && $gimp_config_minor_version == (minor) && \ - $gimp_config_micro_version >= (micro))) - -#if !GIMP_TEST_CHECK_VERSION(1,1,25) -# define GimpPlugInInfo GPlugInInfo /* do test with gimp interface version 1.0 */ -#endif - -GimpPlugInInfo PLUG_IN_INFO = -{ - NULL, NULL, NULL, NULL -}; - - -int -main () -{ - int major, minor, micro; - - system ("touch conf.gimptest"); - - if (sscanf("$min_gimp_version", "%d.%d.%d", &major, &minor, µ) != 3) { - printf("%s, bad version string\n", "$min_gimp_version"); - exit(1); - } - - if ( ($gimp_config_major_version != -1) && - ((gimp_major_version != $gimp_config_major_version) || - (gimp_minor_version != $gimp_config_minor_version) || - (gimp_micro_version != $gimp_config_micro_version)) ) - { - printf("\n*** 'gimp-config --version' returned %d.%d.%d, but GIMP (%d.%d.%d)\n", - $gimp_config_major_version, $gimp_config_minor_version, $gimp_config_micro_version, - gimp_major_version, gimp_minor_version, gimp_micro_version); - printf ("*** was found! If gimp-config was correct, then it is best\n"); - printf ("*** to remove the old version of GIMP. You may also be able to fix the error\n"); - printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n"); - printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n"); - printf("*** required on your system.\n"); - printf("*** If gimp-config was wrong, set the environment variable GIMP_CONFIG\n"); - printf("*** to point to the correct copy of gimp-config, and remove the file config.cache\n"); - printf("*** before re-running configure\n"); - } - else - { - if ((gimp_major_version > major) || - ((gimp_major_version == major) && (gimp_minor_version > minor)) || - ((gimp_major_version == major) && (gimp_minor_version == minor) && (gimp_micro_version >= micro))) - { - return 0; - } - else - { - printf("\n*** An old version of GIMP (%d.%d.%d) was found.\n", - gimp_major_version, gimp_minor_version, gimp_micro_version); - printf("*** You need a version of GIMP newer than %d.%d.%d. The latest version of\n", - major, minor, micro); - printf("*** GIMP is always available from ftp://ftp.gimp.org.\n"); - printf("***\n"); - printf("*** If you have already installed a sufficiently new version, this error\n"); - printf("*** probably means that the wrong copy of the gimp-config shell script is\n"); - printf("*** being found. The easiest way to fix this is to remove the old version\n"); - printf("*** of GIMP, but you can also set the GIMP_CONFIG environment to point to the\n"); - printf("*** correct copy of gimp-config. (In this case, you will have to\n"); - printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n"); - printf("*** so that the correct libraries are found at run-time))\n"); - } - } - return 1; -} -], , no_gimp=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) - fi - fi - - if test "x$no_gimp" = x ; then - dnl *** gimp test succeeded or not tested *** - if test "$enable_gimptest" = "yes" ; then - AC_MSG_RESULT(yes) - else - AC_MSG_RESULT(not tested) - fi - if test "$GIMP_CONFIG" != "no" ; then - ac_save_CPPFLAGS="$CPPFLAGS" - CPPFLAGS="${CPPFLAGS} ${GIMP_CFLAGS}" - AC_CHECK_HEADERS(libgimp/gimp.h) - AC_CHECK_HEADERS(libgimp/gimpfeatures.h) - CPPFLAGS="$ac_save_CPPFLAGS" - fi - CFLAGS="$ac_save_CFLAGS" - LIBS="$ac_save_LIBS" - ifelse([$2], , :, [$2]) - else - AC_MSG_RESULT(no) - if test -f conf.gimptest ; then - : - else - echo "" - echo "*** Could not run GIMP test program, checking why..." - CFLAGS="$CFLAGS $GIMP_CFLAGS" - LIBS="$LIBS $GIMP_LIBS" - AC_TRY_LINK([ -#include -#include -#define GIMP_TEST_CHECK_VERSION(major, minor, micro) \ - ($gimp_config_major_version > (major) || \ - ($gimp_config_major_version == (major) && $gimp_config_minor_version > (minor)) || \ - ($gimp_config_major_version == (major) && $gimp_config_minor_version == (minor) && \ - $gimp_config_micro_version >= (micro))) - -#if !GIMP_TEST_CHECK_VERSION(1,1,25) -# define GimpPlugInInfo GPlugInInfo /* do test with gimp interface version 1.0 */ -#endif -GimpPlugInInfo PLUG_IN_INFO = { NULL, NULL, NULL, NULL }; -], [ return ((gimp_major_version) || (gimp_minor_version) || (gimp_micro_version)); ], - [ echo "*** The test program compiled, but did not run. This usually means" - echo "*** that the run-time linker is not finding GIMP or finding the wrong" - echo "*** version of GIMP. If it is not finding GIMP, you'll need to set your" - echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" - echo "*** to the installed location Also, make sure you have run ldconfig if that" - echo "*** is required on your system" - echo "***" - echo "*** If you have an old version installed, it is best to remove it, although" - echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" - echo "***" - echo "***" ]) - CFLAGS="$ac_save_CFLAGS" - LIBS="$ac_save_LIBS" - fi - - dnl *** ok, gimp does not work, so we have to use the gtk_* things again *** - GIMP_CFLAGS="" - GIMP_LIBS="" - GTK_CFLAGS="$ac_save_GTK_CFLAGS" - GTK_LIBS="$ac_save_GTK_LIBS" - CFLAGS="${CFLAGS} ${GTK_CFLAGS}" - LIBS="${LIBS} ${GTK_LIBS}" - ifelse([$3], , :, [$3]) - fi - AC_SUBST(GIMP_CFLAGS) - AC_SUBST(GIMP_LIBS) - rm -f conf.gimptest -]) - Index: trunk/src/xsane.h =================================================================== --- trunk.orig/src/xsane.h +++ trunk/src/xsane.h @@ -100,7 +100,7 @@ typedef DWORD cmsUInt32Number; #define XSANE_VERSION "0.999" #define XSANE_AUTHOR "Oliver Rauch" #define XSANE_COPYRIGHT "Oliver Rauch" -#define XSANE_DATE "1998-2013" +#define XSANE_DATE "1998-2022" #define XSANE_EMAIL_ADR "Oliver.Rauch@xsane.org" #define XSANE_HOMEPAGE "http://www.xsane.org" #define XSANE_COPYRIGHT_TXT XSANE_DATE " " XSANE_COPYRIGHT Index: trunk/src/xsane-text.h =================================================================== --- trunk.orig/src/xsane-text.h +++ trunk/src/xsane-text.h @@ -871,7 +871,8 @@ The format of [DEVICE] is backendname:de /* Menu path must not be translated, this is done by the gimp. Only translate the text behind the last "/" */ #define XSANE_GIMP_MENU_DIALOG _("/File/Acquire/XSane: Device dialog...") -#define XSANE_GIMP_MENU _("/File/Acquire/XSane: ") +#define XSANE_GIMP_MENU _("/File/Create/Acquire/XSane") +#define XSANE_GIMP_MENU_DEVICE _("/File/Create/Acquire/XSane/Device") #define XSANE_GIMP_MENU_DIALOG_OLD _("/Xtns/XSane/Device dialog...") #define XSANE_GIMP_MENU_OLD _("/Xtns/XSane/") Index: trunk/src/xsane-save.c =================================================================== --- trunk.orig/src/xsane-save.c +++ trunk/src/xsane-save.c @@ -31,6 +31,8 @@ #include #include +#include + /* the following test is always false */ #ifdef _native_WIN32 # include @@ -45,6 +47,7 @@ #endif #ifdef HAVE_LIBZ +#define ZLIB_CONST 1 #include #endif @@ -71,11 +74,7 @@ #include static void xsane_gimp_query(void); -#ifdef HAVE_GIMP_2 static void xsane_gimp_run(const gchar *name, gint nparams, const GimpParam *param, gint *nreturn_vals, GimpParam **return_vals); -#else -static void xsane_gimp_run(char *name, int nparams, GimpParam *param, int *nreturn_vals, GimpParam **return_vals); -#endif GimpPlugInInfo PLUG_IN_INFO = { @@ -90,8 +89,7 @@ GimpPlugInInfo PLUG_IN_INFO = }; -static int xsane_decode_devname(const char *encoded_devname, int n, -char *buf); +static int xsane_decode_devname(const char *encoded_devname, int n, char *buf); static int xsane_encode_devname(const char *devname, int n, char *buf); void null_print_func(gchar *msg); @@ -257,7 +255,7 @@ void xsane_convert_text_to_filename(char /* ---------------------------------------------------------------------------------------------------------------------- */ -int xsane_get_filesize(char *filename) +int xsane_get_filesize(const char *filename) { FILE *infile; int pos; @@ -283,8 +281,8 @@ int xsane_get_filesize(char *filename) void xsane_ensure_counter_in_filename(char **filename, int counter_len) { - char *position_point = NULL; - char *position; + const char *position_point = NULL; + const char *position; int counter = 1; DBG(DBG_proc, "xsane_ensure_counter_in_filename\n"); @@ -420,16 +418,20 @@ void xsane_update_counter_in_filename(ch } /* ---------------------------------------------------------------------------------------------------------------------- */ - -void xsane_read_pnm_header(FILE *file, Image_info *image_info) +/* + * Return 0 on success, other on failure. + */ +int xsane_read_pnm_header(FILE *file, Image_info *image_info) { int max_val, filetype_nr; char buf[TEXTBUFSIZE]; - int items_done; - memset(image_info, '\0', sizeof(Image_info)); + if (!fgets(buf, sizeof(buf)-1, file)) + { + DBG(DBG_error, "failed to read pnm header\n"); + return 1; + } - fgets(buf, sizeof(buf)-1, file); DBG(DBG_info, "filetype header :%s", buf); if (buf[0] == 'P') @@ -443,7 +445,11 @@ void xsane_read_pnm_header(FILE *file, I while (strcmp(buf, "# XSANE data follows\n")) { - fgets(buf, sizeof(buf)-1, file); + if (!fgets(buf, sizeof(buf)-1, file)) + { + DBG(DBG_error, "failed to read pnm header, file truncated\n"); + return 1; + } if (!strncmp(buf, "# resolution_x =", 20)) { @@ -519,13 +525,21 @@ void xsane_read_pnm_header(FILE *file, I } } - items_done = fscanf(file, "%d %d", &image_info->image_width, &image_info->image_height); + if (fscanf(file, "%d %d", &image_info->image_width, &image_info->image_height) != 2) + { + DBG(DBG_error, "failed to read pnm header width/height\n"); + return 1; + } image_info->depth = 1; if (filetype_nr != 4) /* P4 = lineart */ { - items_done = fscanf(file, "%d", &max_val); + if (fscanf(file, "%d", &max_val) != 1) + { + DBG(DBG_error, "failed to read pnm header max val\n"); + return 1; + } if (max_val == 255) { @@ -537,8 +551,12 @@ void xsane_read_pnm_header(FILE *file, I } } - fgetc(file); /* read exactly one newline character */ - + /* read exactly one newline character */ + if (fgetc(file) == EOF) + { + DBG(DBG_error, "failed to read pnm newline\n"); + return 1; + } image_info->channels = 1; @@ -550,7 +568,11 @@ void xsane_read_pnm_header(FILE *file, I #ifdef SUPPORT_RGBA else if (buf[0] == 'S') /* RGBA format */ { - items_done = fscanf(file, "%d %d\n%d", &image_info->image_width, &image_info->image_height, &max_val); + if (fscanf(file, "%d %d\n%d", &image_info->image_width, &image_info->image_height, &max_val) != 3) + { + DBG(DBG_error, "failed to read pnm RGBA width/height/max val\n"); + return 1; + } fgetc(file); /* read exactly one newline character */ image_info->depth = 1; @@ -567,15 +589,22 @@ void xsane_read_pnm_header(FILE *file, I image_info->channels = 4; } #endif + else + { + DBG(DBG_error, "failed to read pnm header: initial char invalid\n"); + return 1; + } DBG(DBG_info, "xsane_read_pnm_header: width=%d, height=%d, depth=%d, colors=%d, resolution_x=%f, resolution_y=%f\n", image_info->image_width, image_info->image_height, image_info->depth, image_info->channels, image_info->resolution_x, image_info->resolution_y); + + return 0; } /* ---------------------------------------------------------------------------------------------------------------------- */ -void xsane_write_pnm_header(FILE *file, Image_info *image_info, int save_pnm16_as_ascii) +void xsane_write_pnm_header(FILE *file, const Image_info *image_info, int save_pnm16_as_ascii) { int maxval; int magic; @@ -785,7 +814,8 @@ int xsane_copy_file(FILE *outfile, FILE /* ---------------------------------------------------------------------------------------------------------------------- */ -int xsane_copy_file_by_name(char *output_filename, char *input_filename, GtkProgressBar *progress_bar, int *cancel_save) +int xsane_copy_file_by_name(const char *output_filename, const char *input_filename, + GtkProgressBar *progress_bar, int *cancel_save) { FILE *infile; FILE *outfile; @@ -886,7 +916,10 @@ cmsHTRANSFORM xsane_create_cms_transform { char buf[TEXTBUFSIZE]; - snprintf(buf, sizeof(buf), "%s\n%s %s: %s\n", ERR_CMS_CONVERSION, ERR_CMS_OPEN_ICM_FILE, CMS_SCANNER_ICM, image_info->icm_profile); + /* Length restriction of icm_profile to silence copiler warning. */ + snprintf(buf, sizeof(buf), "%s\n%s %s: %.*s\n", ERR_CMS_CONVERSION, + ERR_CMS_OPEN_ICM_FILE, CMS_SCANNER_ICM, (int)(sizeof(buf) - 6), + image_info->icm_profile); xsane_back_gtk_error(buf, TRUE); } if (cms_function == XSANE_CMS_FUNCTION_CONVERT_TO_SRGB) @@ -998,8 +1031,9 @@ int xsane_save_grayscale_image_as_linear if (bit != 128) { fputc(packed, outfile); - bit = 128; - packed = 0; +// TODO: has no effect. [RL] +// bit = 128; +// packed = 0; } if (ferror(outfile)) @@ -1013,7 +1047,6 @@ int xsane_save_grayscale_image_as_linear break; } - xsane_progress_bar_set_fraction(progress_bar, (float) y / image_info->image_height); /* update progress bar */ if (*cancel_save) @@ -1027,14 +1060,16 @@ int xsane_save_grayscale_image_as_linear /* ---------------------------------------------------------------------------------------------------------------------- */ -int xsane_save_scaled_image(FILE *outfile, FILE *imagefile, Image_info *image_info, float x_scale, float y_scale, GtkProgressBar *progress_bar, int *cancel_save) +int xsane_save_scaled_image(FILE *outfile, FILE *imagefile, Image_info *image_info, + float x_scale, float y_scale, GtkProgressBar *progress_bar, + int *cancel_save) { int original_image_width = image_info->image_width; int original_image_height = image_info->image_height; int new_image_width = image_info->image_width * x_scale + 0.5; int new_image_height = image_info->image_height * y_scale + 0.5; unsigned char *original_line; - guint16 *original_line16 = NULL; + const guint16 *original_line16 = NULL; unsigned char *new_line; float *pixel_val; float *pixel_norm; @@ -1047,7 +1082,6 @@ int xsane_save_scaled_image(FILE *outfil float factor, x_factor, y_factor; guint16 color; int read_line; - size_t bytes_read; DBG(DBG_proc, "xsane_save_scaled_image\n"); @@ -1118,7 +1152,17 @@ int xsane_save_scaled_image(FILE *outfil if (read_line) { DBG(DBG_info, "xsane_save_scaled_image: reading original line %d\n", (int) y); - bytes_read = fread(original_line, original_image_width, image_info->channels * bytespp, imagefile); /* read one line */ + /* read one line */ + if (fread(original_line, original_image_width, image_info->channels * bytespp, imagefile) != image_info->channels * bytespp) + { + char buf[TEXTBUFSIZE]; + + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno)); + DBG(DBG_error, "xsane_save_scaled_image: short read (%s)\n", buf); + xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */); + *cancel_save = 1; + break; + } original_line16 = (guint16 *) original_line; } @@ -1340,13 +1384,12 @@ int xsane_save_despeckle_image(FILE *out int ymin, ymax; int count; unsigned char *line_cache; - unsigned char *line_cache_ptr; + const unsigned char *line_cache_ptr; guint16 *color_cache; guint16 *color_cache_ptr; int bytespp = 1; int color_radius; int color_width = image_info->image_width * image_info->channels; - size_t bytes_read; radius--; /* correct radius : 1 means nothing happens */ @@ -1371,7 +1414,13 @@ int xsane_save_despeckle_image(FILE *out return -1; } - bytes_read = fread(line_cache, color_width * bytespp, (2 * radius + 1), imagefile); + if (fread(line_cache, color_width * bytespp, (2 * radius + 1), imagefile) != (2 * radius + 1)) + { + free(line_cache); + + DBG(DBG_error, "xsane_despeckle_image: input file truncated\n"); + return -1; + } color_cache = malloc((size_t) sizeof(guint16) * (2*radius+1)*(2*radius+1)); @@ -1414,7 +1463,8 @@ int xsane_save_despeckle_image(FILE *out xmax = color_width; } - count = 0; +// TODO: has no effect. [RL] +// count = 0; color_cache_ptr = color_cache; @@ -1445,7 +1495,9 @@ int xsane_save_despeckle_image(FILE *out { for (i = d; i < count; i++) { - for (j = i - d, color_cache_ptr = color_cache + j; j >= 0 && color_cache_ptr[0] > color_cache_ptr[d]; j -= d, color_cache_ptr -= d) + for (j = i - d, color_cache_ptr = color_cache + j; + j >= 0 && color_cache_ptr[0] > color_cache_ptr[d]; + j -= d, color_cache_ptr -= d) { val = color_cache_ptr[0]; color_cache_ptr[0] = color_cache_ptr[d]; @@ -1488,7 +1540,9 @@ int xsane_save_despeckle_image(FILE *out { for (i = d; i < count; i++) { - for (j = i - d, color_cache_ptr = color_cache + j; j >= 0 && color_cache_ptr[0] > color_cache_ptr[d]; j -= d, color_cache_ptr -= d) + for (j = i - d, color_cache_ptr = color_cache + j; + j >= 0 && color_cache_ptr[0] > color_cache_ptr[d]; + j -= d, color_cache_ptr -= d) { val = color_cache_ptr[0]; color_cache_ptr[0] = color_cache_ptr[d]; @@ -1499,8 +1553,15 @@ int xsane_save_despeckle_image(FILE *out } val16 = color_cache[count/2]; - fputc(bytes16[0], outfile); /* write bytes in machine byte order */ - fputc(bytes16[1], outfile); + /* write bytes in machine byte order */ + if ((fputc(bytes16[0], outfile) == EOF) || (fputc(bytes16[1], outfile) == EOF)) + { + free(line_cache); + free(color_cache); + + DBG(DBG_error, "xsane_despeckle_image: failed to write to output file\n"); + return -1; + } } } @@ -1519,8 +1580,15 @@ int xsane_save_despeckle_image(FILE *out { memcpy(line_cache, line_cache + color_width * bytespp, color_width * bytespp * 2 * radius); - bytes_read = fread(line_cache + color_width * bytespp * 2 * radius, - color_width * bytespp, 1, imagefile); + if (fread(line_cache + color_width * bytespp * 2 * radius, + color_width * bytespp, 1, imagefile) != 1) + { + free(line_cache); + free(color_cache); + + DBG(DBG_error, "xsane_despeckle_image: input file truncated\n"); + return -1; + } } } @@ -1547,7 +1615,6 @@ int xsane_save_blur_image(FILE *outfile, int xmax_flag; int ymin_flag; int ymax_flag; - size_t bytes_read; *cancel_save = 0; @@ -1569,7 +1636,14 @@ int xsane_save_blur_image(FILE *outfile, return -1; } - bytes_read = fread(line_cache, image_info->image_width * image_info->channels * bytespp, (2 * intradius + 1), imagefile); + if (fread(line_cache, image_info->image_width * image_info->channels * bytespp, + (2 * intradius + 1), imagefile) != (2 * intradius + 1)) + { + free(line_cache); + + DBG(DBG_error, "xsane_blur_image: input file truncated\n"); + return -1; + } for (y = 0; y < image_info->image_height; y++) { @@ -1712,8 +1786,13 @@ int xsane_save_blur_image(FILE *outfile, } val16 = val / norm; - fputc(bytes16[0], outfile); /* write bytes in machine byte order */ - fputc(bytes16[1], outfile); + + /* write bytes in machine byte order */ + if ((fputc(bytes16[0], outfile) == EOF) || (fputc(bytes16[1], outfile) == EOF)) + { + DBG(DBG_error, "xsane_save_blur_image: failed to write bytes\n"); + break; + } } } @@ -1734,8 +1813,14 @@ int xsane_save_blur_image(FILE *outfile, { memcpy(line_cache, line_cache + image_info->image_width * image_info->channels * bytespp, image_info->image_width * image_info->channels * bytespp * 2 * intradius); - bytes_read = fread(line_cache + image_info->image_width * image_info->channels * bytespp * 2 * intradius, - image_info->image_width * image_info->channels * bytespp, 1, imagefile); + if (fread(line_cache + image_info->image_width * image_info->channels * bytespp * 2 * intradius, + image_info->image_width * image_info->channels * bytespp, 1, imagefile) != 1) + { + free(line_cache); + + DBG(DBG_error, "xsane_blur_image: input file truncated\n"); + return -1; + } } } @@ -1923,7 +2008,7 @@ int xsane_save_rotate_image(FILE *outfil #ifdef HAVE_MMAP if (mmaped_imagefile) { - char *p = mmaped_imagefile + pos0 + bytespp * (x + y * pixel_width); /* calculate correct position */ + const char *p = mmaped_imagefile + pos0 + bytespp * (x + y * pixel_width); /* calculate correct position */ for (i=0; i\n"); a85tuple = 0; a85count = 0; - cbuflen = 0; - linelen = 0; count = 0; } @@ -2904,7 +2983,7 @@ static int xsane_write_compressed_a85(FI /* ---------------------------------------------------------------------------------------------------------------------- */ #ifdef HAVE_LIBLCMS -static int xsane_write_CSA(FILE *outfile, char *input_profile, int intent) +static int xsane_write_CSA(FILE *outfile, const char *input_profile, int intent) { cmsHPROFILE hProfile; size_t n; @@ -2950,7 +3029,7 @@ static int xsane_write_CSA(FILE *outfile /* ---------------------------------------------------------------------------------------------------------------------- */ -static int xsane_write_CRD(FILE *outfile, char *output_profile, int intent, int cms_bpc) +static int xsane_write_CRD(FILE *outfile, const char *output_profile, int intent, int cms_bpc) { cmsHPROFILE hProfile; size_t n; @@ -3003,7 +3082,9 @@ static int xsane_write_CRD(FILE *outfile /* ---------------------------------------------------------------------------------------------------------------------- */ -static int xsane_save_ps_pdf_bw(FILE *outfile, FILE *imagefile, Image_info *image_info, int ascii85decode, int flatedecode, GtkProgressBar *progress_bar, int *cancel_save) +static int xsane_save_ps_pdf_bw(FILE *outfile, FILE *imagefile, const Image_info *image_info, + int ascii85decode, int flatedecode, GtkProgressBar *progress_bar, + int *cancel_save) { int x, y; int bytes_per_line = (image_info->image_width+7)/8; @@ -3094,7 +3175,9 @@ static int xsane_save_ps_pdf_bw(FILE *ou /* ---------------------------------------------------------------------------------------------------------------------- */ -static int xsane_save_ps_pdf_gray(FILE *outfile, FILE *imagefile, Image_info *image_info, int ascii85decode, int flatedecode, cmsHTRANSFORM hTransform, int do_transform, GtkProgressBar *progress_bar, int *cancel_save) +static int xsane_save_ps_pdf_gray(FILE *outfile, FILE *imagefile, const Image_info *image_info, + int ascii85decode, int flatedecode, cmsHTRANSFORM hTransform, + int do_transform, GtkProgressBar *progress_bar, int *cancel_save) { int x, y; int ret = 0; @@ -3209,7 +3292,10 @@ static int xsane_save_ps_pdf_gray(FILE * if (do_transform && (hTransform != NULL)) { bytes_read = fread(line_raw, 2, image_info->image_width, imagefile); - cmsDoTransform(hTransform, line_raw, line16, image_info->image_width); + if (bytes_read == image_info->image_width) + { + cmsDoTransform(hTransform, line_raw, line16, image_info->image_width); + } } else #endif @@ -3217,6 +3303,26 @@ static int xsane_save_ps_pdf_gray(FILE * bytes_read = fread(line16, 2, image_info->image_width, imagefile); } + /* check for short read. */ + if (bytes_read != image_info->image_width) + { + char buf[TEXTBUFSIZE]; + + snprintf(buf, sizeof(buf), "%s: %s", ERR_DURING_SAVE, ERR_INPUT_TRUNCATED); + DBG(DBG_error, "%s\n", buf); + xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */); + + free(line); + + if (line16) + { + free(line16); + } + + *cancel_save = 1; + return (*cancel_save); + } + linep = line; #if __BYTE_ORDER == __LITTLE_ENDIAN @@ -3262,7 +3368,10 @@ static int xsane_save_ps_pdf_gray(FILE * if (do_transform && (hTransform != NULL)) { bytes_read = fread(line_raw, 1, image_info->image_width, imagefile); - cmsDoTransform(hTransform, line_raw, line, image_info->image_width); + if (bytes_read == image_info->image_width) + { + cmsDoTransform(hTransform, line_raw, line, image_info->image_width); + } } else #endif @@ -3271,6 +3380,27 @@ static int xsane_save_ps_pdf_gray(FILE * } } + /* check again for short read. */ + if (bytes_read != image_info->image_width) + { + char buf[TEXTBUFSIZE]; + + snprintf(buf, sizeof(buf), "%s: %s", ERR_DURING_SAVE, ERR_INPUT_TRUNCATED); + DBG(DBG_error, "%s\n", buf); + xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */); + + free(line); + + if (line16) + { + free(line16); + } + + *cancel_save = 1; + return (*cancel_save); + } + + if (ascii85decode) { #ifdef HAVE_LIBZ @@ -3343,7 +3473,8 @@ static int xsane_save_ps_pdf_gray(FILE * /* ---------------------------------------------------------------------------------------------------------------------- */ -static int xsane_save_ps_pdf_color(FILE *outfile, FILE *imagefile, Image_info *image_info, int ascii85decode, int flatedecode, +static int xsane_save_ps_pdf_color(FILE *outfile, FILE *imagefile, const Image_info *image_info, + int ascii85decode, int flatedecode, cmsHTRANSFORM hTransform, int do_transform, GtkProgressBar *progress_bar, int *cancel_save) { @@ -3457,7 +3588,10 @@ static int xsane_save_ps_pdf_color(FILE if (do_transform && (hTransform != NULL)) { bytes_read = fread(line_raw, 6, image_info->image_width, imagefile); - cmsDoTransform(hTransform, line_raw, line16, image_info->image_width); + if (bytes_read == image_info->image_width) + { + cmsDoTransform(hTransform, line_raw, line16, image_info->image_width); + } } else #endif @@ -3465,6 +3599,24 @@ static int xsane_save_ps_pdf_color(FILE bytes_read = fread(line16, 6, image_info->image_width, imagefile); } + /* check for short read */ + if (bytes_read != image_info->image_width) + { + char buf[TEXTBUFSIZE]; + + snprintf(buf, sizeof(buf), "%s: %s", ERR_DURING_SAVE, ERR_INPUT_TRUNCATED); + DBG(DBG_error, "%s\n", buf); + xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */); + + if (line16) + { + free(line16); + } + + *cancel_save = 1; + return (*cancel_save); + } + #if __BYTE_ORDER == __LITTLE_ENDIAN for (x = 0; x < image_info->image_width; x=x+2) { @@ -3517,13 +3669,34 @@ static int xsane_save_ps_pdf_color(FILE if (do_transform && (hTransform != NULL)) { bytes_read = fread(line_raw, 3, image_info->image_width, imagefile); - cmsDoTransform(hTransform, line_raw, line, image_info->image_width); + if (bytes_read == image_info->image_width) + { + cmsDoTransform(hTransform, line_raw, line, image_info->image_width); + } } else #endif { bytes_read = fread(line, 3, image_info->image_width, imagefile); } + + /* check for short read again */ + if (bytes_read != image_info->image_width) + { + char buf[TEXTBUFSIZE]; + + snprintf(buf, sizeof(buf), "%s: %s", ERR_DURING_SAVE, ERR_INPUT_TRUNCATED); + DBG(DBG_error, "%s\n", buf); + xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */); + + if (line16) + { + free(line16); + } + + *cancel_save = 1; + return (*cancel_save); + } } if (ascii85decode) @@ -3596,11 +3769,10 @@ static int xsane_save_ps_pdf_color(FILE /* ---------------------------------------------------------------------------------------------------------------------- */ -int xsane_save_ps_page(FILE *outfile, int page, - FILE *imagefile, Image_info *image_info, float width, float height, - int paper_left_margin, int paper_bottom_margin, int paper_width, int paper_height, int paper_orientation, - int flatedecode, - cmsHTRANSFORM hTransform, int apply_ICM_profile, int embed_CSA, char *CSA_profile, int intent, +int xsane_save_ps_page(FILE *outfile, int page, FILE *imagefile, const Image_info *image_info, + float width, float height, int paper_left_margin, int paper_bottom_margin, + int paper_width, int paper_height, int paper_orientation, int flatedecode, + cmsHTRANSFORM hTransform, int apply_ICM_profile, int embed_CSA, const char *CSA_profile, int intent, GtkProgressBar *progress_bar, int *cancel_save) { int degree, position_left, position_bottom, box_left, box_bottom, box_right, box_top; @@ -3745,11 +3917,11 @@ int xsane_save_ps_page(FILE *outfile, in /* ---------------------------------------------------------------------------------------------------------------------- */ -int xsane_save_ps(FILE *outfile, FILE *imagefile, Image_info *image_info, float width, float height, - int paper_left_margin, int paper_bottom_margin, int paper_width, int paper_height, int paper_orientation, - int flatedecode, - cmsHTRANSFORM hTransform, int apply_ICM_profile, int embed_CSA, char *CSA_profile, - int embed_CRD, char *CRD_profile, int cms_bpc, int intent, +int xsane_save_ps(FILE *outfile, FILE *imagefile, const Image_info *image_info, float width, float height, + int paper_left_margin, int paper_bottom_margin, int paper_width, int paper_height, + int paper_orientation, int flatedecode, + cmsHTRANSFORM hTransform, int apply_ICM_profile, int embed_CSA, const char *CSA_profile, + int embed_CRD, const char *CRD_profile, int cms_bpc, int intent, GtkProgressBar *progress_bar, int *cancel_save) { DBG(DBG_proc, "xsane_save_ps\n"); @@ -3765,8 +3937,6 @@ int xsane_save_ps(FILE *outfile, FILE *i } #endif - - xsane_save_ps_page(outfile, 1 /* page */, imagefile, image_info, width, height, paper_left_margin, paper_bottom_margin, paper_width, paper_height, paper_orientation, @@ -3791,7 +3961,8 @@ int xsane_save_ps(FILE *outfile, FILE *i /* ---------------------------------------------------------------------------------------------------------------------- */ -static int xsane_embed_pdf_icm_profile(FILE *outfile, struct pdf_xref *xref, char *icm_filename, int flatedecode, int icc_object) +static int xsane_embed_pdf_icm_profile(FILE *outfile, struct pdf_xref *xref, const char *icm_filename, + int flatedecode, int icc_object) { FILE *icm_profile; size_t size, embed_len; @@ -3922,7 +4093,7 @@ void xsane_save_pdf_create_document_head /* page = [1 .. pages] */ static void xsane_save_pdf_create_page_header(FILE *outfile, struct pdf_xref *xref, int page, - Image_info *image_info, + const Image_info *image_info, float width, float height, int paper_left_margin, int paper_bottom_margin, int paper_width, int paper_height, @@ -4189,9 +4360,9 @@ static void xsane_save_pdf_create_page_t /* ---------------------------------------------------------------------------------------------------------------------- */ int xsane_save_pdf_page(FILE *outfile, struct pdf_xref *xref, int page, - FILE *imagefile, Image_info *image_info, float width, float height, - int paper_left_margin, int paper_bottom_margin, int paper_width, int paper_height, int paper_orientation, - int flatedecode, + FILE *imagefile, const Image_info *image_info, float width, float height, + int paper_left_margin, int paper_bottom_margin, int paper_width, int paper_height, + int paper_orientation, int flatedecode, cmsHTRANSFORM hTransform, int do_transform, int icc_object, GtkProgressBar *progress_bar, int *cancel_save) { @@ -4237,9 +4408,9 @@ int xsane_save_pdf_page(FILE *outfile, s /* ---------------------------------------------------------------------------------------------------------------------- */ -int xsane_save_pdf(FILE *outfile, FILE *imagefile, Image_info *image_info, float width, float height, - int paper_left_margin, int paper_bottom_margin, int paper_width, int paper_height, int paper_orientation, - int flatedecode, +int xsane_save_pdf(FILE *outfile, FILE *imagefile, const Image_info *image_info, float width, float height, + int paper_left_margin, int paper_bottom_margin, int paper_width, int paper_height, + int paper_orientation, int flatedecode, cmsHTRANSFORM hTransform, int apply_ICM_profile, int cms_function, GtkProgressBar *progress_bar, int *cancel_save) { @@ -4287,17 +4458,16 @@ typedef struct { struct jpeg_error_mgr pub;/* "public" fields */ int *cancel_save; -} xsane_jpeg_error_mgr; +} XSaneJpegErrorMgr; -typedef xsane_jpeg_error_mgr *xsane_jpeg_error_mgr_ptr; +typedef XSaneJpegErrorMgr *XSaneJpegErrorMgrPtr; static void xsane_jpeg_error_exit(j_common_ptr cinfo) { char buf[TEXTBUFSIZE]; /* cinfo->err points to a xsane_jpeg_error_mgr struct */ - xsane_jpeg_error_mgr_ptr xsane_jpeg_error_mgr_data = (xsane_jpeg_error_mgr_ptr) cinfo->err; - + XSaneJpegErrorMgrPtr xsane_jpeg_error_mgr_data = (XSaneJpegErrorMgrPtr) cinfo->err; if (!*xsane_jpeg_error_mgr_data->cancel_save) { @@ -4411,7 +4581,7 @@ static void xsane_jpeg_embed_scanner_icm /* ---------------------------------------------------------- */ -int xsane_save_jpeg(FILE *outfile, int quality, FILE *imagefile, Image_info *image_info, +int xsane_save_jpeg(FILE *outfile, int quality, FILE *imagefile, const Image_info *image_info, cmsHTRANSFORM hTransform, int apply_ICM_profile, int cms_function, GtkProgressBar *progress_bar, int *cancel_save) { @@ -4421,7 +4591,7 @@ int xsane_save_jpeg(FILE *outfile, int q int x,y; int bytespp = 1; struct jpeg_compress_struct cinfo; - xsane_jpeg_error_mgr jerr; + XSaneJpegErrorMgr jerr; JSAMPROW row_pointer[1]; size_t bytes_read; #ifdef HAVE_LIBLCMS @@ -4528,10 +4698,10 @@ int xsane_save_jpeg(FILE *outfile, int q { if ( (x % 8) == 0) - { + { byte = fgetc(imagefile); mask = 128; - } + } if (byte & mask) { @@ -4551,7 +4721,10 @@ int xsane_save_jpeg(FILE *outfile, int q if (apply_ICM_profile && (cms_function != XSANE_CMS_FUNCTION_EMBED_SCANNER_ICM_PROFILE) && (hTransform != NULL)) { bytes_read = fread(data_raw, components * 2, image_info->image_width, imagefile); - cmsDoTransform(hTransform, data_raw, data, image_info->image_width); + if (bytes_read == image_info->image_width) + { + cmsDoTransform(hTransform, data_raw, data, image_info->image_width); + } } else #endif @@ -4559,11 +4732,26 @@ int xsane_save_jpeg(FILE *outfile, int q bytes_read = fread(data, components * 2, image_info->image_width, imagefile); } + /* check for short read. */ + if (bytes_read != image_info->image_width) + { +#ifdef HAVE_LIBLCMS + if (data_raw) + { + free(data_raw); + } +#endif + free(data); + + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_INPUT_TRUNCATED); + xsane_back_gtk_error(buf, TRUE); + return -1; /* error */ + } + for (x = 0; x < image_info->image_width * components; x++) { data[x] = data16[x] / 256; } - } else /* 8 bits/sample */ { @@ -4571,13 +4759,32 @@ int xsane_save_jpeg(FILE *outfile, int q if (apply_ICM_profile && (cms_function != XSANE_CMS_FUNCTION_EMBED_SCANNER_ICM_PROFILE) && (hTransform != NULL)) { bytes_read = fread(data_raw, components, image_info->image_width, imagefile); - cmsDoTransform(hTransform, data_raw, data, image_info->image_width); + if (bytes_read == image_info->image_width) + { + cmsDoTransform(hTransform, data_raw, data, image_info->image_width); + } } else #endif { bytes_read = fread(data, components, image_info->image_width, imagefile); } + + /* check for short read again. */ + if (bytes_read != image_info->image_width) + { +#ifdef HAVE_LIBLCMS + if (data_raw) + { + free(data_raw); + } +#endif + free(data); + + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_INPUT_TRUNCATED); + xsane_back_gtk_error(buf, TRUE); + return -1; /* error */ + } } row_pointer[0] = data; @@ -4657,7 +4864,8 @@ static void xsane_tiff_embed_scanner_icm /* pages = 0 => single page tiff, page = 0 */ /* pages > 0 => page = [1 .. pages] */ -int xsane_save_tiff_page(TIFF *tiffile, int page, int pages, int quality, FILE *imagefile, Image_info *image_info, +int xsane_save_tiff_page(TIFF *tiffile, int page, int pages, int quality, + FILE *imagefile, const Image_info *image_info, cmsHTRANSFORM hTransform, int apply_ICM_profile, int cms_function, GtkProgressBar *progress_bar, int *cancel_save) { @@ -4667,7 +4875,7 @@ int xsane_save_tiff_page(TIFF *tiffile, int components; int compression; int bytes; - struct tm *ptm; + const struct tm *ptm; time_t now; size_t bytes_read; #ifdef HAVE_LIBLCMS @@ -4736,7 +4944,6 @@ int xsane_save_tiff_page(TIFF *tiffile, } } #endif - TIFFSetField(tiffile, TIFFTAG_IMAGEWIDTH, image_info->image_width); TIFFSetField(tiffile, TIFFTAG_IMAGELENGTH, image_info->image_height); @@ -4825,7 +5032,10 @@ int xsane_save_tiff_page(TIFF *tiffile, if ((cms_function != XSANE_CMS_FUNCTION_EMBED_SCANNER_ICM_PROFILE) && (hTransform != NULL)) { bytes_read = fread(data_raw, 1, w, imagefile); - cmsDoTransform(hTransform, data_raw, data, image_info->image_width); + if (bytes_read == w) + { + cmsDoTransform(hTransform, data_raw, data, image_info->image_width); + } } else #endif @@ -4833,6 +5043,24 @@ int xsane_save_tiff_page(TIFF *tiffile, bytes_read = fread(data, 1, w, imagefile); } + /* check for short read */ + if (bytes_read != w) + { + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_INPUT_TRUNCATED); + DBG(DBG_error, "%s\n", buf); + xsane_back_gtk_error(buf, TRUE); + +#ifdef HAVE_LIBLCMS + if (data_raw) + { + free(data_raw); + } +#endif + + _TIFFfree(data); + return -1; /* error */ + } + if (TIFFWriteScanline(tiffile, data, y, 0) != 1) { char buf[TEXTBUFSIZE]; @@ -4892,7 +5120,8 @@ static void xsane_png_embed_scanner_icm_ { if (fread(profile_buffer, 1, size, icm_profile) == size) { - png_set_iCCP(png_ptr, png_info_ptr, "ICC profile", 0, profile_buffer, size); + png_set_iCCP(png_ptr, png_info_ptr, "ICC profile", 0, + (png_const_bytep)profile_buffer, size); } else { @@ -4920,7 +5149,7 @@ static void xsane_png_embed_scanner_icm_ #ifdef HAVE_LIBPNG #ifdef HAVE_LIBZ -int xsane_save_png(FILE *outfile, int compression, FILE *imagefile, Image_info *image_info, +int xsane_save_png(FILE *outfile, int compression, FILE *imagefile, const Image_info *image_info, cmsHTRANSFORM hTransform, int apply_ICM_profile, int cms_function, GtkProgressBar *progress_bar, int *cancel_save) { @@ -5077,7 +5306,10 @@ int xsane_save_png(FILE *outfile, int co if ((cms_function != XSANE_CMS_FUNCTION_EMBED_SCANNER_ICM_PROFILE) && (hTransform != NULL)) { bytes_read = fread(data_raw, components, byte_width, imagefile); - cmsDoTransform(hTransform, data_raw, data, image_info->image_width); + if (bytes_read == byte_width) + { + cmsDoTransform(hTransform, data_raw, data, image_info->image_width); + } } else #endif @@ -5085,6 +5317,22 @@ int xsane_save_png(FILE *outfile, int co bytes_read = fread(data, components, byte_width, imagefile); } + /* check for short read. */ + if (bytes_read != byte_width) + { + free(data); +#ifdef HAVE_LIBLCMS + if (data_raw) + { + free(data_raw); + } +#endif + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_NO_MEM); + xsane_back_gtk_error(buf, TRUE); + png_destroy_write_struct(&png_ptr, (png_infopp) 0); + return -1; /* error */ + } + row_ptr = data; png_write_rows(png_ptr, &row_ptr, 1); /* errors are caught by test sor setjmp(...) */ @@ -5113,7 +5361,7 @@ int xsane_save_png(FILE *outfile, int co #ifdef HAVE_LIBPNG #ifdef HAVE_LIBZ -int xsane_save_png_16(FILE *outfile, int compression, FILE *imagefile, Image_info *image_info, +int xsane_save_png_16(FILE *outfile, int compression, FILE *imagefile, const Image_info *image_info, cmsHTRANSFORM hTransform, int apply_ICM_profile, int cms_function, GtkProgressBar *progress_bar, int *cancel_save) { @@ -5254,7 +5502,10 @@ int xsane_save_png_16(FILE *outfile, int if ((cms_function != XSANE_CMS_FUNCTION_EMBED_SCANNER_ICM_PROFILE) && (hTransform != NULL)) { bytes_read = fread(data_raw, components * 2, image_info->image_width, imagefile); - cmsDoTransform(hTransform, data_raw, data, image_info->image_width); + if (bytes_read == image_info->image_width) + { + cmsDoTransform(hTransform, data_raw, data, image_info->image_width); + } } else #endif @@ -5262,6 +5513,22 @@ int xsane_save_png_16(FILE *outfile, int bytes_read = fread(data, components * 2, image_info->image_width, imagefile); } + /* check for short read. */ + if (bytes_read != image_info->image_width) + { + free(data); +#ifdef HAVE_LIBLCMS + if (data_raw) + { + free(data_raw); + } +#endif + + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_INPUT_TRUNCATED); + xsane_back_gtk_error(buf, TRUE); + png_destroy_write_struct(&png_ptr, (png_infopp) 0); + return -1; /* error */ } + #if __BYTE_ORDER == __LITTLE_ENDIAN /* we have to write data in network order (MSB first), so when we run on a low endian machine then we have to swap bytes */ { @@ -5303,7 +5570,7 @@ int xsane_save_png_16(FILE *outfile, int /* ---------------------------------------------------------------------------------------------------------------------- */ -static int xsane_save_pnm_16_ascii_gray(FILE *outfile, FILE *imagefile, Image_info *image_info, +static int xsane_save_pnm_16_ascii_gray(FILE *outfile, FILE *imagefile, const Image_info *image_info, cmsHTRANSFORM hTransform, int apply_ICM_profile, GtkProgressBar *progress_bar, int *cancel_save) { @@ -5356,7 +5623,10 @@ static int xsane_save_pnm_16_ascii_gray( if ((apply_ICM_profile) && (hTransform != NULL)) { bytes_read = fread(data_raw, 2, image_info->image_width, imagefile); - cmsDoTransform(hTransform, data_raw, data, image_info->image_width); + if (bytes_read == image_info->image_width) + { + cmsDoTransform(hTransform, data_raw, data, image_info->image_width); + } } else #endif @@ -5364,6 +5634,23 @@ static int xsane_save_pnm_16_ascii_gray( bytes_read = fread(data, 2, image_info->image_width, imagefile); } + /* check for short read. */ + if (bytes_read != image_info->image_width) + { + char buf[TEXTBUFSIZE]; + + free(data); +#ifdef HAVE_LIBLCMS + if (data_raw) + { + free(data_raw); + } +#endif + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_INPUT_TRUNCATED); + xsane_back_gtk_error(buf, TRUE); + return -1; /* error */ + } + for (x = 0; x < image_info->image_width; x++) { fprintf(outfile, "%d ", data[x]); @@ -5371,7 +5658,7 @@ static int xsane_save_pnm_16_ascii_gray( if (++count >= 10) { fprintf(outfile, "\n"); - count = 0; + count = 0; } } @@ -5411,7 +5698,7 @@ static int xsane_save_pnm_16_ascii_gray( /* ---------------------------------------------------------------------------------------------------------------------- */ -static int xsane_save_pnm_16_ascii_color(FILE *outfile, FILE *imagefile, Image_info *image_info, +static int xsane_save_pnm_16_ascii_color(FILE *outfile, FILE *imagefile, const Image_info *image_info, cmsHTRANSFORM hTransform, int apply_ICM_profile, GtkProgressBar *progress_bar, int *cancel_save) { @@ -5465,7 +5752,10 @@ static int xsane_save_pnm_16_ascii_color if ((apply_ICM_profile) && (hTransform != NULL)) { bytes_read = fread(data_raw, 6, image_info->image_width, imagefile); - cmsDoTransform(hTransform, data_raw, data, image_info->image_width); + if (bytes_read == image_info->image_width) + { + cmsDoTransform(hTransform, data_raw, data, image_info->image_width); + } } else #endif @@ -5473,6 +5763,23 @@ static int xsane_save_pnm_16_ascii_color bytes_read = fread(data, 6, image_info->image_width, imagefile); } + /* check for short read. */ + if (bytes_read != image_info->image_width) + { + char buf[TEXTBUFSIZE]; + + free(data); +#ifdef HAVE_LIBLCMS + if (data_raw) + { + free(data_raw); + } +#endif + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_INPUT_TRUNCATED); + xsane_back_gtk_error(buf, TRUE); + return -1; /* error */ + } + for (x = 0; x < image_info->image_width; x++) { fprintf(outfile, "%d ", data[3*x+0]); @@ -5482,7 +5789,7 @@ static int xsane_save_pnm_16_ascii_color if (++count >= 3) { fprintf(outfile, "\n"); - count = 0; + count = 0; } } fprintf(outfile, "\n"); @@ -5521,7 +5828,7 @@ static int xsane_save_pnm_16_ascii_color /* ---------------------------------------------------------------------------------------------------------------------- */ -static int xsane_save_pnm_16_binary_gray(FILE *outfile, FILE *imagefile, Image_info *image_info, +static int xsane_save_pnm_16_binary_gray(FILE *outfile, FILE *imagefile, const Image_info *image_info, cmsHTRANSFORM hTransform, int apply_ICM_profile, GtkProgressBar *progress_bar, int *cancel_save) { @@ -5573,7 +5880,10 @@ static int xsane_save_pnm_16_binary_gray if (hTransform != NULL) { bytes_read = fread(data_raw, 2, image_info->image_width, imagefile); - cmsDoTransform(hTransform, data_raw, data, image_info->image_width); + if (bytes_read == image_info->image_width) + { + cmsDoTransform(hTransform, data_raw, data, image_info->image_width); + } } else #endif @@ -5581,6 +5891,23 @@ static int xsane_save_pnm_16_binary_gray bytes_read = fread(data, 2, image_info->image_width, imagefile); } + /* check for short read. */ + if (bytes_read == image_info->image_width) + { + char buf[TEXTBUFSIZE]; + + free(data); +#ifdef HAVE_LIBLCMS + if (data_raw) + { + free(data_raw); + } +#endif + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_INPUT_TRUNCATED); + xsane_back_gtk_error(buf, TRUE); + return -1; /* error */ + } + for (x = 0; x < image_info->image_width; x++) { fputc(data[3*x+0] / 256, outfile); @@ -5619,7 +5946,7 @@ static int xsane_save_pnm_16_binary_gray /* ---------------------------------------------------------------------------------------------------------------------- */ -static int xsane_save_pnm_16_binary_color(FILE *outfile, FILE *imagefile, Image_info *image_info, +static int xsane_save_pnm_16_binary_color(FILE *outfile, FILE *imagefile, const Image_info *image_info, cmsHTRANSFORM hTransform, int apply_ICM_profile, GtkProgressBar *progress_bar, int *cancel_save) { @@ -5671,7 +5998,10 @@ static int xsane_save_pnm_16_binary_colo if (hTransform != NULL) { bytes_read = fread(data_raw, 6, image_info->image_width, imagefile); - cmsDoTransform(hTransform, data_raw, data, image_info->image_width); + if (bytes_read == image_info->image_width) + { + cmsDoTransform(hTransform, data_raw, data, image_info->image_width); + } } else #endif @@ -5679,6 +6009,23 @@ static int xsane_save_pnm_16_binary_colo bytes_read = fread(data, 6, image_info->image_width, imagefile); } + /* check for short read. */ + if (bytes_read != image_info->image_width) + { + char buf[TEXTBUFSIZE]; + + free(data); +#ifdef HAVE_LIBLCMS + if (data_raw) + { + free(data_raw); + } +#endif + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_INPUT_TRUNCATED); + xsane_back_gtk_error(buf, TRUE); + return -1; /* error */ + } + for (x = 0; x < image_info->image_width; x++) { fputc(data[3*x+0] / 256, outfile); @@ -5721,7 +6068,7 @@ static int xsane_save_pnm_16_binary_colo /* ---------------------------------------------------------------------------------------------------------------------- */ -static int xsane_save_pnm_8_gray(FILE *outfile, FILE *imagefile, Image_info *image_info, +static int xsane_save_pnm_8_gray(FILE *outfile, FILE *imagefile, const Image_info *image_info, cmsHTRANSFORM hTransform, int apply_ICM_profile, GtkProgressBar *progress_bar, int *cancel_save) { @@ -5773,7 +6120,10 @@ static int xsane_save_pnm_8_gray(FILE *o if (hTransform != NULL) { bytes_read = fread(data_raw, 1, image_info->image_width, imagefile); - cmsDoTransform(hTransform, data_raw, data, image_info->image_width); + if (bytes_read == image_info->image_width) + { + cmsDoTransform(hTransform, data_raw, data, image_info->image_width); + } } else #endif @@ -5781,6 +6131,23 @@ static int xsane_save_pnm_8_gray(FILE *o bytes_read = fread(data, 1, image_info->image_width, imagefile); } + /* check for short read. */ + if (bytes_read != image_info->image_width) + { + char buf[TEXTBUFSIZE]; + + free(data); +#ifdef HAVE_LIBLCMS + if (data_raw) + { + free(data_raw); + } +#endif + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_INPUT_TRUNCATED); + xsane_back_gtk_error(buf, TRUE); + return -1; /* error */ + } + for (x = 0; x < image_info->image_width; x++) { fputc(data[x], outfile); @@ -5817,7 +6184,7 @@ static int xsane_save_pnm_8_gray(FILE *o } /* ---------------------------------------------------------------------------------------------------------------------- */ -static int xsane_save_pnm_8_color(FILE *outfile, FILE *imagefile, Image_info *image_info, +static int xsane_save_pnm_8_color(FILE *outfile, FILE *imagefile, const Image_info *image_info, cmsHTRANSFORM hTransform, int apply_ICM_profile, GtkProgressBar *progress_bar, int *cancel_save) { @@ -5869,7 +6236,10 @@ static int xsane_save_pnm_8_color(FILE * if (hTransform != NULL) { bytes_read = fread(data_raw, 3, image_info->image_width, imagefile); - cmsDoTransform(hTransform, data_raw, data, image_info->image_width); + if (bytes_read == image_info->image_width) + { + cmsDoTransform(hTransform, data_raw, data, image_info->image_width); + } } else #endif @@ -5877,6 +6247,23 @@ static int xsane_save_pnm_8_color(FILE * bytes_read = fread(data, 3, image_info->image_width, imagefile); } + /* check for short read. */ + if (bytes_read != image_info->image_width) + { + char buf[TEXTBUFSIZE]; + + free(data); +#ifdef HAVE_LIBLCMS + if (data_raw) + { + free(data_raw); + } +#endif + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_INPUT_TRUNCATED); + xsane_back_gtk_error(buf, TRUE); + return -1; /* error */ + } + for (x = 0; x < image_info->image_width; x++) { fputc(data[3*x+0], outfile); @@ -5916,7 +6303,7 @@ static int xsane_save_pnm_8_color(FILE * /* ---------------------------------------------------------------------------------------------------------------------- */ -static int xsane_save_pnm_8(FILE *outfile, FILE *imagefile, Image_info *image_info, +static int xsane_save_pnm_8(FILE *outfile, FILE *imagefile, const Image_info *image_info, cmsHTRANSFORM hTransform, int apply_ICM_profile, GtkProgressBar *progress_bar, int *cancel_save) { @@ -5940,7 +6327,7 @@ static int xsane_save_pnm_8(FILE *outfil /* ---------------------------------------------------------------------------------------------------------------------- */ -int xsane_save_pnm_16(FILE *outfile, FILE *imagefile, Image_info *image_info, +int xsane_save_pnm_16(FILE *outfile, FILE *imagefile, const Image_info *image_info, cmsHTRANSFORM hTransform, int apply_ICM_profile, GtkProgressBar *progress_bar, int *cancel_save) { @@ -5978,8 +6365,9 @@ int xsane_save_pnm_16(FILE *outfile, FIL /* ---------------------------------------------------------------------------------------------------------------------- */ -/* 0=ok, <0=error, 1=canceled */ -int xsane_save_image_as_lineart(char *output_filename, char *input_filename, GtkProgressBar *progress_bar, int *cancel_save) +/* 0=ok, <0=error, 1=cancelled */ +int xsane_save_image_as_lineart(const char *output_filename, const char *input_filename, + GtkProgressBar *progress_bar, int *cancel_save) { FILE *outfile; FILE *infile; @@ -6009,7 +6397,18 @@ int xsane_save_image_as_lineart(char *ou return -1; } - xsane_read_pnm_header(infile, &image_info); + if (xsane_read_pnm_header(infile, &image_info) != 0) + { + char buf[TEXTBUFSIZE]; + + fclose(infile); + fclose(outfile); + + snprintf(buf, sizeof(buf), "%s `%s': failed to read pnm header", ERR_OPEN_FAILED, input_filename); + xsane_back_gtk_error(buf, TRUE); + DBG(DBG_error, "xsane_save_image_as_lineart: could not read imagefile pnm header %s\n", input_filename); + return -1; + } xsane_save_grayscale_image_as_lineart(outfile, infile, &image_info, progress_bar, cancel_save); @@ -6026,7 +6425,8 @@ int xsane_save_image_as_lineart(char *ou /* ---------------------------------------------------------------------------------------------------------------------- */ -int xsane_save_image_as_text(char *output_filename, char *input_filename, GtkProgressBar *progress_bar, int *cancel_save) +int xsane_save_image_as_text(const char *output_filename, const char *input_filename, + GtkProgressBar *progress_bar, int *cancel_save) { char *arg[1000]; char buf[TEXTBUFSIZE]; @@ -6038,7 +6438,7 @@ int xsane_save_image_as_text(char *outpu DBG(DBG_proc, "xsane_save_image_as_text\n"); - argnr = xsane_parse_options(preferences.ocr_command, arg); + argnr = xsane_parse_options(preferences.ocr_command, (const char **)arg); arg[argnr++] = strdup(preferences.ocr_inputfile_option); arg[argnr++] = strdup(input_filename); @@ -6093,13 +6493,17 @@ int xsane_save_image_as_text(char *outpu DBG(DBG_info, "trying to change user id for new subprocess:\n"); DBG(DBG_info, "old effective uid = %d\n", (int) geteuid()); - setuid(getuid()); - DBG(DBG_info, "new effective uid = %d\n", (int) geteuid()); - - - execvp(arg[0], arg); /* does not return if successfully */ - DBG(DBG_error, "%s %s\n", ERR_FAILED_EXEC_OCR_CMD, preferences.ocr_command); - + if (!setuid(getuid())) + { + DBG(DBG_info, "new effective uid = %d\n", (int) geteuid()); + execvp(arg[0], arg); /* does not return if successfully */ + DBG(DBG_error, "%s %s\n", ERR_FAILED_EXEC_OCR_CMD, preferences.ocr_command); + } + else + { + DBG(DBG_error, "%s %s\n", ERR_FAILED_PRIV_OCR_CMD, preferences.ocr_command); + } + /* send error message via IPC pipe to parent process */ if (ipc_file) { @@ -6139,7 +6543,10 @@ int xsane_save_image_as_text(char *outpu int progress, subprogress; float fprogress; - fgets(buf, sizeof(buf), ocr_progress); + if (!fgets(buf, sizeof(buf), ocr_progress)) + { + break; + } if (!strncmp(preferences.ocr_progress_keyword, buf, strlen(preferences.ocr_progress_keyword))) { @@ -6201,7 +6608,7 @@ int xsane_save_image_as_text(char *outpu /* ---------------------------------------------------------------------------------------------------------------------- */ /* save image in destination file format. lineart images that are stored as grayscale image are reduced to lineart! */ -int xsane_save_image_as(char *output_filename, char *input_filename, int output_format, +int xsane_save_image_as(const char *output_filename, const char *input_filename, int output_format, int apply_ICM_profile, int cms_function, int cms_intent, int cms_bpc, GtkProgressBar *progress_bar, int *cancel_save) { @@ -6227,7 +6634,17 @@ int xsane_save_image_as(char *output_fil return -1; } - xsane_read_pnm_header(infile, &image_info); + if (xsane_read_pnm_header(infile, &image_info) != 0) + { + char buf[TEXTBUFSIZE]; + + fclose(infile); + snprintf(buf, sizeof(buf), "%s `%s': failed to read image pnm header", ERR_OPEN_FAILED, input_filename); + xsane_back_gtk_error(buf, TRUE); + + DBG(DBG_error, "xsane_save_image_as: could not read imagefile pnm header %s\n", input_filename); + return -1; + } if ((image_info.reduce_to_lineart) && (output_format != XSANE_PNM)) { @@ -6255,7 +6672,16 @@ int xsane_save_image_as(char *output_fil return -1; } - xsane_read_pnm_header(infile, &image_info); + if (xsane_read_pnm_header(infile, &image_info) != 0) + { + char buf[TEXTBUFSIZE]; + + fclose(infile); + snprintf(buf, sizeof(buf), "%s `%s': failed to read image pnm header", ERR_OPEN_FAILED, input_filename); + xsane_back_gtk_error(buf, TRUE); + DBG(DBG_error, "xsane_save_image_as: could not read imagefile pnm header %s\n", input_filename); + return -1; + } } #ifdef HAVE_LIBLCMS @@ -6621,15 +7047,7 @@ static void xsane_gimp_query(void) DBG(DBG_proc, "xsane_gimp_query\n"); snprintf(name, sizeof(name), "%s", xsane.prog_name); -#ifdef GIMP_CHECK_VERSION -# if GIMP_CHECK_VERSION(1,1,9) snprintf(mpath, sizeof(mpath), "%s", XSANE_GIMP_MENU_DIALOG); -# else - snprintf(mpath, sizeof(mpath), "%s", XSANE_GIMP_MENU_DIALOG_OLD); -# endif -#else - snprintf(mpath, sizeof(mpath), "%s", XSANE_GIMP_MENU_DIALOG_OLD); -#endif gimp_install_procedure(name, XSANE_GIMP_INSTALL_BLURB, XSANE_GIMP_INSTALL_HELP, @@ -6641,6 +7059,7 @@ static void xsane_gimp_query(void) GIMP_EXTENSION, nargs, nreturn_vals, args, return_vals); + gimp_plugin_menu_register(name, XSANE_GIMP_MENU); sane_init(&xsane.sane_backend_versioncode, (void *) xsane_authorization_callback); if (SANE_VERSION_MAJOR(xsane.sane_backend_versioncode) != SANE_V_MAJOR) @@ -6669,40 +7088,18 @@ static void xsane_gimp_query(void) continue; /* name too long... */ } -#ifdef GIMP_CHECK_VERSION -# if GIMP_CHECK_VERSION(1,1,9) - snprintf(mpath, sizeof(mpath), "%s", XSANE_GIMP_MENU); -# else - snprintf(mpath, sizeof(mpath), "%s", XSANE_GIMP_MENU_OLD); -# endif -#else - snprintf(mpath, sizeof(mpath), "%s", XSANE_GIMP_MENU_OLD); -#endif - len = strlen(mpath); - for (j = 0; xsane.devlist[i]->name[j]; ++j) - { - if (xsane.devlist[i]->name[j] == '/') - { - mpath[len++] = '\''; - } - else - { - mpath[len++] = xsane.devlist[i]->name[j]; - } - } - mpath[len++] = '\0'; - gimp_install_procedure(name, XSANE_GIMP_INSTALL_BLURB, XSANE_GIMP_INSTALL_HELP, XSANE_AUTHOR, XSANE_COPYRIGHT, XSANE_DATE, - mpath, + xsane.devlist[i]->name, 0, /* "RGB, GRAY", */ GIMP_EXTENSION, nargs, nreturn_vals, args, return_vals); + gimp_plugin_menu_register(name, XSANE_GIMP_MENU_DEVICE); } sane_exit(); @@ -6710,15 +7107,9 @@ static void xsane_gimp_query(void) /* ---------------------------------------------------------------------------------------------------------------------- */ -#ifdef HAVE_GIMP_2 -static void xsane_gimp_run(const gchar *name, gint nparams, const GimpParam *param, gint *nreturn_vals, GimpParam **return_vals) -{ +static void xsane_gimp_run(const gchar *name, gint nparams, + const GimpParam *param, gint *nreturn_vals, GimpParam **return_vals) { GimpRunMode run_mode; -#else /* GIMP-1.x */ -static void xsane_gimp_run(char *name, int nparams, GimpParam *param, int *nreturn_vals, GimpParam **return_vals) -{ - GimpRunModeType run_mode; -#endif static GimpParam values[2]; char devname[1024]; @@ -6753,9 +7144,7 @@ static void xsane_gimp_run(char *name, i switch (run_mode) { case GIMP_RUN_INTERACTIVE: -#ifdef HAVE_GIMP_2 gimp_extension_ack(); -#endif xsane_interface(nargs, args); values[0].data.d_status = GIMP_PDB_SUCCESS; break; @@ -6782,24 +7171,24 @@ void null_print_func(gchar *msg) /* ---------------------------------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------------------------------- */ -int xsane_transfer_to_gimp(char *input_filename, int apply_ICM_profile, int cms_function, GtkProgressBar *progress_bar, int *cancel_save) +int xsane_transfer_to_gimp(const char *input_filename, int apply_ICM_profile, int cms_function, + GtkProgressBar *progress_bar, int *cancel_save) { int remaining; size_t tile_size; - GimpImageType image_type = GIMP_GRAY; + GimpImageBaseType image_type = GIMP_GRAY; GimpImageType drawable_type = GIMP_GRAY_IMAGE; gint32 layer_ID; gint32 image_ID; - GimpDrawable *drawable; + GeglBuffer* buffer; guchar *tile; - GimpPixelRgn region; unsigned tile_offset; int i, x, y; Image_info image_info; FILE *imagefile; int bytes; unsigned char *data = NULL; - guint16 *data16 = NULL; + const guint16 *data16 = NULL; size_t bytes_read; #ifdef HAVE_LIBLCMS unsigned char *data_raw = NULL; @@ -6820,7 +7209,14 @@ int xsane_transfer_to_gimp(char *input_f return -1; } - xsane_read_pnm_header(imagefile, &image_info); + if (xsane_read_pnm_header(imagefile, &image_info) != 0) + { + char buf[TEXTBUFSIZE]; + snprintf(buf, sizeof(buf), "%s `%s': failed to read image pnm header", ERR_OPEN_FAILED, input_filename); + xsane_back_gtk_error(buf, TRUE); + DBG(DBG_error, "xsane_transfer_to_gimp: could not read imagefile pnm header %s\n", input_filename); + return -1; + } if (image_info.depth == 16) { @@ -6913,7 +7309,7 @@ int xsane_transfer_to_gimp(char *input_f if (fread(profile_buffer, 1, size, icm_profile) == size) { parasite = gimp_parasite_new("icc-profile", 0, size, profile_buffer); - gimp_image_parasite_attach(image_ID, parasite); + gimp_image_attach_parasite(image_ID, parasite); gimp_parasite_free(parasite); } else @@ -6939,18 +7335,15 @@ int xsane_transfer_to_gimp(char *input_f /* the following is supported since gimp-1.1.? */ -#ifdef GIMP_HAVE_RESOLUTION_INFO if (image_info.resolution_x > 0) { gimp_image_set_resolution(image_ID, image_info.resolution_x, image_info.resolution_y); } /* gimp_image_set_unit(image_ID, unit?); */ -#endif - - layer_ID = gimp_layer_new(image_ID, "Background", image_info.image_width, image_info.image_height, drawable_type, 100.0, GIMP_NORMAL_MODE); - gimp_image_add_layer(image_ID, layer_ID, 0); - drawable = gimp_drawable_get(layer_ID); - gimp_pixel_rgn_init(®ion, drawable, 0, 0, drawable->width, drawable->height, TRUE, FALSE); + + layer_ID = gimp_layer_new(image_ID, "Background", image_info.image_width, image_info.image_height, drawable_type, 100.0, + gimp_image_get_default_new_layer_mode(image_ID)); + gimp_image_insert_layer(image_ID, layer_ID, -1 ,0); tile = g_new(guchar, tile_size); @@ -6981,7 +7374,9 @@ int xsane_transfer_to_gimp(char *input_f if (y % tile_height == 0) { - gimp_pixel_rgn_set_rect(®ion, tile, 0, y - tile_height, image_info.image_width, tile_height); + buffer = gimp_drawable_get_buffer(layer_ID); + gegl_buffer_set(buffer,GEGL_RECTANGLE(0, y - tile_height, image_info.image_width, tile_height), 0, NULL, tile, GEGL_AUTO_ROWSTRIDE); + g_object_unref(buffer); tile_offset = 0; } @@ -7007,7 +7402,10 @@ int xsane_transfer_to_gimp(char *input_f if ((cms_function != XSANE_CMS_FUNCTION_EMBED_SCANNER_ICM_PROFILE) && apply_ICM_profile && (hTransform != NULL)) { bytes_read = fread(data_raw, 1, image_info.image_width, imagefile); - cmsDoTransform(hTransform, data_raw, data, image_info.image_width); + if (bytes_read == image_info.image_width) + { + cmsDoTransform(hTransform, data_raw, data, image_info.image_width); + } } else #endif @@ -7015,14 +7413,27 @@ int xsane_transfer_to_gimp(char *input_f bytes_read = fread(data, 1, image_info.image_width, imagefile); } + /* Check for short read. */ + if (bytes_read != image_info.image_width) + { + char buf[TEXTBUFSIZE]; + + g_free(tile); + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_INPUT_TRUNCATED); + xsane_back_gtk_error(buf, TRUE); + return -1; /* error */ + } + for (x = 0; x < image_info.image_width; x++) - { + { tile[tile_offset++] = data[x]; - } + } if (y % tile_height == 0) { - gimp_pixel_rgn_set_rect(®ion, tile, 0, y - tile_height, image_info.image_width, tile_height); + buffer = gimp_drawable_get_buffer(layer_ID); + gegl_buffer_set(buffer,GEGL_RECTANGLE(0, y - tile_height, image_info.image_width, tile_height), 0, NULL, tile, GEGL_AUTO_ROWSTRIDE); + g_object_unref(buffer); tile_offset = 0; } @@ -7045,7 +7456,10 @@ int xsane_transfer_to_gimp(char *input_f if ((cms_function != XSANE_CMS_FUNCTION_EMBED_SCANNER_ICM_PROFILE) && apply_ICM_profile && (hTransform != NULL)) { bytes_read = fread(data_raw, 2, image_info.image_width, imagefile); - cmsDoTransform(hTransform, data_raw, data, image_info.image_width); + if (bytes_read == image_info.image_width) + { + cmsDoTransform(hTransform, data_raw, data, image_info.image_width); + } } else #endif @@ -7053,6 +7467,17 @@ int xsane_transfer_to_gimp(char *input_f bytes_read = fread(data, 2, image_info.image_width, imagefile); } + if (bytes_read != image_info.image_width) + { + char buf[TEXTBUFSIZE]; + + g_free(tile); + snprintf(buf, sizeof(buf), "%s `%s': failed to read image raw data", ERR_INPUT_TRUNCATED, input_filename); + xsane_back_gtk_error(buf, TRUE); + DBG(DBG_error, "xsane_transfer_to_gimp: could not read imagefile raw data %s\n", input_filename); + return -1; + } + for (x = 0; x < image_info.image_width; x++) { tile[tile_offset++] = data16[x]/256; @@ -7060,7 +7485,9 @@ int xsane_transfer_to_gimp(char *input_f if (y % tile_height == 0) { - gimp_pixel_rgn_set_rect(®ion, tile, 0, y - tile_height, image_info.image_width, tile_height); + buffer = gimp_drawable_get_buffer(layer_ID); + gegl_buffer_set(buffer,GEGL_RECTANGLE(0, y - tile_height, image_info.image_width, tile_height), 0, NULL, tile, GEGL_AUTO_ROWSTRIDE); + g_object_unref(buffer); tile_offset = 0; } @@ -7091,7 +7518,10 @@ int xsane_transfer_to_gimp(char *input_f if ((cms_function != XSANE_CMS_FUNCTION_EMBED_SCANNER_ICM_PROFILE) && apply_ICM_profile && (hTransform != NULL)) { bytes_read = fread(data_raw, 3, image_info.image_width, imagefile); - cmsDoTransform(hTransform, data_raw, data, image_info.image_width); + if (bytes_read == image_info.image_width) + { + cmsDoTransform(hTransform, data_raw, data, image_info.image_width); + } } else #endif @@ -7099,6 +7529,17 @@ int xsane_transfer_to_gimp(char *input_f bytes_read = fread(data, 3, image_info.image_width, imagefile); } + if (bytes_read != image_info.image_width) + { + char buf[TEXTBUFSIZE]; + + g_free(tile); + snprintf(buf, sizeof(buf), "%s `%s': failed to read image raw data", ERR_INPUT_TRUNCATED, input_filename); + xsane_back_gtk_error(buf, TRUE); + DBG(DBG_error, "xsane_transfer_to_gimp: could not read imagefile raw data %s\n", input_filename); + return -1; + } + for (x = 0; x < image_info.image_width; x++) { tile[tile_offset++] = data[3*x+0]; @@ -7108,7 +7549,9 @@ int xsane_transfer_to_gimp(char *input_f if (y % tile_height == 0) { - gimp_pixel_rgn_set_rect(®ion, tile, 0, y - tile_height, image_info.image_width, tile_height); + buffer = gimp_drawable_get_buffer(layer_ID); + gegl_buffer_set(buffer,GEGL_RECTANGLE(0, y - tile_height, image_info.image_width, tile_height), 0, NULL, tile, GEGL_AUTO_ROWSTRIDE); + g_object_unref(buffer); tile_offset = 0; } @@ -7132,7 +7575,10 @@ int xsane_transfer_to_gimp(char *input_f if ((cms_function != XSANE_CMS_FUNCTION_EMBED_SCANNER_ICM_PROFILE) && apply_ICM_profile && (hTransform != NULL)) { bytes_read = fread(data_raw, 6, image_info.image_width, imagefile); - cmsDoTransform(hTransform, data_raw, data, image_info.image_width); + if (bytes_read == image_info.image_width) + { + cmsDoTransform(hTransform, data_raw, data, image_info.image_width); + } } else #endif @@ -7140,16 +7586,29 @@ int xsane_transfer_to_gimp(char *input_f bytes_read = fread(data, 6, image_info.image_width, imagefile); } + if (bytes_read != image_info.image_width) + { + char buf[TEXTBUFSIZE]; + + g_free(tile); + snprintf(buf, sizeof(buf), "%s `%s': failed to read image raw data", ERR_INPUT_TRUNCATED, input_filename); + xsane_back_gtk_error(buf, TRUE); + DBG(DBG_error, "xsane_transfer_to_gimp: could not read imagefile raw data %s\n", input_filename); + return -1; + } + for (x = 0; x < image_info.image_width; x++) - { + { tile[tile_offset++] = data16[3*x+0]/256; tile[tile_offset++] = data16[3*x+1]/256; tile[tile_offset++] = data16[3*x+2]/256; - } + } if (y % tile_height == 0) { - gimp_pixel_rgn_set_rect(®ion, tile, 0, y - tile_height, image_info.image_width, tile_height); + buffer = gimp_drawable_get_buffer(layer_ID); + gegl_buffer_set(buffer,GEGL_RECTANGLE(0, y - tile_height, image_info.image_width, tile_height), 0, NULL, tile, GEGL_AUTO_ROWSTRIDE); + g_object_unref(buffer); tile_offset = 0; } @@ -7191,7 +7650,9 @@ int xsane_transfer_to_gimp(char *input_f if (y % tile_height == 0) { - gimp_pixel_rgn_set_rect(®ion, tile, 0, y - tile_height, image_info.image_width, tile_height); + buffer = gimp_drawable_get_buffer(layer_ID); + gegl_buffer_set(buffer,GEGL_RECTANGLE(0, y - tile_height, image_info.image_width, tile_height), 0, NULL, tile, GEGL_AUTO_ROWSTRIDE); + g_object_unref(buffer); tile_offset = 0; } @@ -7222,12 +7683,12 @@ int xsane_transfer_to_gimp(char *input_f if (remaining) { - gimp_pixel_rgn_set_rect(®ion, tile, 0, y - remaining, image_info.image_width, remaining); + buffer = gimp_drawable_get_buffer(layer_ID); + gegl_buffer_set(buffer,GEGL_RECTANGLE(0, y - remaining, image_info.image_width, remaining), 0, NULL, tile, GEGL_AUTO_ROWSTRIDE); + g_object_unref(buffer); } - gimp_drawable_flush(drawable); gimp_display_new(image_ID); - gimp_drawable_detach(drawable); g_free(tile); tile = 0; @@ -7262,12 +7723,12 @@ static const char base64[] = "ABCDEFGHIJ /* ---------------------------------------------------------------------------------------------------------------------- */ -static void write_3chars_as_base64(unsigned char c1, unsigned char c2, unsigned char c3, int pads, int fd_socket) +/* Return 0=success, -1 on error. */ +static int write_3chars_as_base64(unsigned char c1, unsigned char c2, unsigned char c3, int pads, int fd_socket) { char buf[4]; - ssize_t bytes_written; - buf[0] = base64[c1>>2]; /* wirte bits 7-2 of first char */ + buf[0] = base64[c1>>2]; /* write bits 7-2 of first char */ buf[1] = base64[((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4)]; /* write bits 1,0 of first and bits 7-4 of second char */ if (pads == 2) /* only one byte used */ @@ -7286,17 +7747,21 @@ static void write_3chars_as_base64(unsig buf[3] = base64[c3 & 0x3F]; /* write bits 5-0 of third char as lsb */ } - bytes_written = write(fd_socket, buf, 4); + if (write(fd_socket, buf, 4) != 4) + { + return -1; + } + + return 0; } /* ---------------------------------------------------------------------------------------------------------------------- */ -void write_string_base64(int fd_socket, char *string, int len) +int write_string_base64(int fd_socket, const char *string, int len) { int i; int pad; unsigned char c1, c2, c3; - ssize_t bytes_written; for (i = 0; i < len; i+=3) { @@ -7320,18 +7785,25 @@ void write_string_base64(int fd_socket, } } - write_3chars_as_base64(c1, c2, c3, pad, fd_socket); + if (write_3chars_as_base64(c1, c2, c3, pad, fd_socket) != 0) + { + return -1; + } } - bytes_written = write(fd_socket, "\r\n", 2); + if (write(fd_socket, "\r\n", 2) != 2) + { + return -1; + } + + return 0; } /* ---------------------------------------------------------------------------------------------------------------------- */ -void write_base64(int fd_socket, FILE *infile) +int write_base64(int fd_socket, FILE *infile) { int c1, c2, c3; int pos = 0; - ssize_t bytes_written; while ((c1 = getc(infile)) != EOF) { @@ -7356,7 +7828,10 @@ void write_base64(int fd_socket, FILE *i pos += 4; if (pos > 71) { - bytes_written = write(fd_socket, "\r\n", 2); + if (write(fd_socket, "\r\n", 2) != 2) + { + return -1; + } pos = 0; } @@ -7371,237 +7846,386 @@ void write_base64(int fd_socket, FILE *i if (pos) { - bytes_written = write(fd_socket, "\r\n", 2); + if (write(fd_socket, "\r\n", 2) != 2) + { + return -1; + } } xsane.email_progress_val = 1.0; xsane_front_gtk_email_project_update_lockfile_status(); + + return 0; } /* ---------------------------------------------------------------------------------------------------------------------- */ -void write_email_header(int fd_socket, char *from, char *reply_to, char *to, char *subject, char *boundary, int related) +/* Return 0=success, -1=error */ +int write_email_header(int fd_socket, const char *from, const char *reply_to, const char *to, + const char *subject, const char *boundary, int related) { char buf[1024]; - ssize_t bytes_written; +// ssize_t bytes_written; snprintf(buf, sizeof(buf), "From: %s\r\n", from); - bytes_written = write(fd_socket, buf, strlen(buf)); + if (write(fd_socket, buf, strlen(buf)) != strlen(buf)) + { + return -1; + } snprintf(buf, sizeof(buf), "Reply-To: %s\r\n", reply_to); - bytes_written = write(fd_socket, buf, strlen(buf)); + if (write(fd_socket, buf, strlen(buf)) != strlen(buf)) + { + return -1; + } snprintf(buf, sizeof(buf), "To: %s\r\n", to); - bytes_written = write(fd_socket, buf, strlen(buf)); + if (write(fd_socket, buf, strlen(buf)) != strlen(buf)) + { + return -1; + } snprintf(buf, sizeof(buf), "Subject: %s\r\n", subject); - bytes_written = write(fd_socket, buf, strlen(buf)); + if (write(fd_socket, buf, strlen(buf)) != strlen(buf)) + { + return -1; + } snprintf(buf, sizeof(buf), "MIME-Version: 1.0\r\n"); - bytes_written = write(fd_socket, buf, strlen(buf)); + if (write(fd_socket, buf, strlen(buf)) != strlen(buf)) + { + return -1; + } if (related) /* related means that we need a special link in the html part to display the image */ { snprintf(buf, sizeof(buf), "Content-Type: multipart/related;\r\n"); - bytes_written = write(fd_socket, buf, strlen(buf)); + if (write(fd_socket, buf, strlen(buf)) != strlen(buf)) + { + return -1; + } } else { snprintf(buf, sizeof(buf), "Content-Type: multipart/mixed;\r\n"); - bytes_written = write(fd_socket, buf, strlen(buf)); + if (write(fd_socket, buf, strlen(buf)) != strlen(buf)) + { + return -1; + } } snprintf(buf, sizeof(buf), " boundary=\"%s\"\r\n\r\n", boundary); - bytes_written = write(fd_socket, buf, strlen(buf)); + if (write(fd_socket, buf, strlen(buf)) != strlen(buf)) + { + return -1; + } + + return 0; } /* ---------------------------------------------------------------------------------------------------------------------- */ -void write_email_footer(int fd_socket, char *boundary) +int write_email_footer(int fd_socket, const char *boundary) { char buf[1024]; - ssize_t bytes_written; snprintf(buf, sizeof(buf), "--%s--\r\n", boundary); - bytes_written = write(fd_socket, buf, strlen(buf)); + if (write(fd_socket, buf, strlen(buf)) != strlen(buf)) + { + return -1; + } + + return 0; } /* ---------------------------------------------------------------------------------------------------------------------- */ -void write_email_mime_ascii(int fd_socket, char *boundary) +int write_email_mime_ascii(int fd_socket, const char *boundary) { char buf[1024]; - ssize_t bytes_written; +// ssize_t bytes_written; snprintf(buf, sizeof(buf), "--%s\r\n", boundary); - bytes_written = write(fd_socket, buf, strlen(buf)); + if (write(fd_socket, buf, strlen(buf)) != strlen(buf)) + { + return -1; + } snprintf(buf, sizeof(buf), "Content-Type: text/plain;\r\n"); - bytes_written = write(fd_socket, buf, strlen(buf)); + if (write(fd_socket, buf, strlen(buf)) != strlen(buf)) + { + return -1; + } snprintf(buf, sizeof(buf), " charset=\"iso-8859-1\"\r\n"); - bytes_written = write(fd_socket, buf, strlen(buf)); + if (write(fd_socket, buf, strlen(buf)) != strlen(buf)) + { + return -1; + } snprintf(buf, sizeof(buf), "Content-Transfer-Encoding: 8bit\r\n\r\n"); - bytes_written = write(fd_socket, buf, strlen(buf)); + if (write(fd_socket, buf, strlen(buf)) != strlen(buf)) + { + return -1; + } + + return 0; } /* ---------------------------------------------------------------------------------------------------------------------- */ -void write_email_mime_html(int fd_socket, char *boundary) +int write_email_mime_html(int fd_socket, const char *boundary) { char buf[1024]; - ssize_t bytes_written; +// ssize_t bytes_written; snprintf(buf, sizeof(buf), "--%s\r\n", boundary); - bytes_written = write(fd_socket, buf, strlen(buf)); + if (write(fd_socket, buf, strlen(buf)) != strlen(buf)) + { + return -1; + } snprintf(buf, sizeof(buf), "Content-Type: text/html;\r\n"); - bytes_written = write(fd_socket, buf, strlen(buf)); + if (write(fd_socket, buf, strlen(buf)) != strlen(buf)) + { + return -1; + } snprintf(buf, sizeof(buf), " charset=\"us-ascii\"\r\n"); - bytes_written = write(fd_socket, buf, strlen(buf)); + if (write(fd_socket, buf, strlen(buf)) != strlen(buf)) + { + return -1; + } snprintf(buf, sizeof(buf), "Content-Transfer-Encoding: 7bit\r\n\r\n"); - bytes_written = write(fd_socket, buf, strlen(buf)); + if (write(fd_socket, buf, strlen(buf)) != strlen(buf)) + { + return -1; + } snprintf(buf, sizeof(buf), "\r\n"); - bytes_written = write(fd_socket, buf, strlen(buf)); + if (write(fd_socket, buf, strlen(buf)) != strlen(buf)) + { + return -1; + } snprintf(buf, sizeof(buf), "\r\n"); - bytes_written = write(fd_socket, buf, strlen(buf)); + if (write(fd_socket, buf, strlen(buf)) != strlen(buf)) + { + return -1; + } + + return 0; } /* ---------------------------------------------------------------------------------------------------------------------- */ -void write_email_attach_image(int fd_socket, char *boundary, char *content_id, char *content_type, FILE *infile, char *filename) +/* Return 0=success, -1=error */ +int write_email_attach_image(int fd_socket, const char *boundary, const char *content_id, + const char *content_type, FILE *infile, const char *filename) { char buf[1024]; - ssize_t bytes_written; +// ssize_t bytes_written; snprintf(buf, sizeof(buf), "--%s\r\n", boundary); - bytes_written = write(fd_socket, buf, strlen(buf)); + if (write(fd_socket, buf, strlen(buf)) != strlen(buf)) + { + return -1; + } snprintf(buf, sizeof(buf), "Content-Type: %s\r\n", content_type); - bytes_written = write(fd_socket, buf, strlen(buf)); + if (write(fd_socket, buf, strlen(buf)) != strlen(buf)) + { + return -1; + } if (content_id) { snprintf(buf, sizeof(buf), "Content-ID: <%s>\r\n", content_id); - bytes_written = write(fd_socket, buf, strlen(buf)); + if (write(fd_socket, buf, strlen(buf)) != strlen(buf)) + { + return -1; + } } snprintf(buf, sizeof(buf), "Content-Transfer-Encoding: base64\r\n"); - bytes_written = write(fd_socket, buf, strlen(buf)); + if (write(fd_socket, buf, strlen(buf)) != strlen(buf)) + { + return -1; + } snprintf(buf, sizeof(buf), "Content-Disposition: inline;\r\n"); - bytes_written = write(fd_socket, buf, strlen(buf)); + if (write(fd_socket, buf, strlen(buf)) != strlen(buf)) + { + return -1; + } snprintf(buf, sizeof(buf), " filename=\"%s\"\r\n", filename); - bytes_written = write(fd_socket, buf, strlen(buf)); + if (write(fd_socket, buf, strlen(buf)) != strlen(buf)) + { + return -1; + } snprintf(buf, sizeof(buf), "\r\n"); - bytes_written = write(fd_socket, buf, strlen(buf)); + if (write(fd_socket, buf, strlen(buf)) != strlen(buf)) + { + return -1; + } + + if (write_base64(fd_socket, infile) != 0) + { + return -1; + } - write_base64(fd_socket, infile); + return 0; } /* ---------------------------------------------------------------------------------------------------------------------- */ +// TODO: This function doesn't appear to be used. [RL] +//int write_email_attach_file(int fd_socket, char *boundary, FILE *infile, char *filename) +//{ +// char buf[1024]; +// +// snprintf(buf, sizeof(buf), "--%s\r\n", boundary); +// if (write(fd_socket, buf, strlen(buf)) != strlen(buf)) +// { +// return -1; +// } +// +// snprintf(buf, sizeof(buf), "Content-Type: application/octet-stream\r\n"); +// if (write(fd_socket, buf, strlen(buf)) != strlen(buf)) +// { +// return -1; +// } +// +// snprintf(buf, sizeof(buf), " name=\"%s\"\r\n", filename); +// if (write(fd_socket, buf, strlen(buf)) != strlen(buf)) +// { +// return -1; +// } +// +// snprintf(buf, sizeof(buf), "Content-Transfer-Encoding: base64\r\n"); +// if (write(fd_socket, buf, strlen(buf)) != strlen(buf)) +// { +// return -1; +// } +// +// snprintf(buf, sizeof(buf), "Content-Disposition: attachment;\r\n"); +// if (write(fd_socket, buf, strlen(buf)) != strlen(buf)) +// { +// return -1; +// } +// +// snprintf(buf, sizeof(buf), " filename=\"%s\"\r\n", filename); +// if (write(fd_socket, buf, strlen(buf)) != strlen(buf)) +// { +// return -1; +// } +// +// snprintf(buf, sizeof(buf), "\r\n"); +// if (write(fd_socket, buf, strlen(buf)) != strlen(buf)) +// { +// return -1; +// } +// +// if (write_base64(fd_socket, infile) != 0) +// { +// return -1; +// } +// +// return 0; +//} + +/* ---------------------------------------------------------------------------------------------------------------------- */ -void write_email_attach_file(int fd_socket, char *boundary, FILE *infile, char *filename) +/* returns fd_socket if successful, < 0 when error occurred */ +int open_socket(char *server, int port) { - char buf[1024]; - ssize_t bytes_written; + int fd_socket, e; - snprintf(buf, sizeof(buf), "--%s\r\n", boundary); - bytes_written = write(fd_socket, buf, strlen(buf)); + struct addrinfo *ai_list, *ai; + struct addrinfo hints; + gchar *port_s; + gint connected; - snprintf(buf, sizeof(buf), "Content-Type: application/octet-stream\r\n"); - bytes_written = write(fd_socket, buf, strlen(buf)); + memset(&hints, '\0', sizeof(hints)); + hints.ai_flags = AI_ADDRCONFIG; + hints.ai_socktype = SOCK_STREAM; - snprintf(buf, sizeof(buf), " name=\"%s\"\r\n", filename); - bytes_written = write(fd_socket, buf, strlen(buf)); + port_s = g_strdup_printf("%d", port); + e = getaddrinfo(server, port_s, &hints, &ai_list); + g_free(port_s); - snprintf(buf, sizeof(buf), "Content-Transfer-Encoding: base64\r\n"); - bytes_written = write(fd_socket, buf, strlen(buf)); + if (e != 0) + { + DBG(DBG_error, "open_socket: Could not lookup \"%s\"\n", server); + return -1; + } - snprintf(buf, sizeof(buf), "Content-Disposition: attachment;\r\n"); - bytes_written = write(fd_socket, buf, strlen(buf)); + connected = 0; + for (ai = ai_list; ai != NULL && !connected; ai = ai->ai_next) + { + gchar hostname[NI_MAXHOST]; + gchar hostaddr[NI_MAXHOST]; - snprintf(buf, sizeof(buf), " filename=\"%s\"\r\n", filename); - bytes_written = write(fd_socket, buf, strlen(buf)); + /* If all else fails */ + strncpy(hostname, "(unknown name)", NI_MAXHOST-1); + strncpy(hostaddr, "(unknown address)", NI_MAXHOST-1); - snprintf(buf, sizeof(buf), "\r\n"); - bytes_written = write(fd_socket, buf, strlen(buf)); + /* Determine canonical name and IPv4/IPv6 address */ + (void) getnameinfo(ai->ai_addr, ai->ai_addrlen, hostname, sizeof(hostname), + NULL, 0, 0); + (void) getnameinfo(ai->ai_addr, ai->ai_addrlen, hostaddr, sizeof(hostaddr), + NULL, 0, NI_NUMERICHOST); - write_base64(fd_socket, infile); -} + DBG(DBG_info, "open_socket: connecting to \"%s\" (\"%s\"): %s\n", + server, hostname, hostaddr); + + if ((ai->ai_family != AF_INET) && (ai->ai_family != AF_INET6)) + { + DBG(DBG_error, "open_socket: Unknown address family: %d\n", ai->ai_family); + continue; + } -/* ---------------------------------------------------------------------------------------------------------------------- */ + fd_socket = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); -/* returns fd_socket if sucessfull, < 0 when error occured */ -int open_socket(char *server, int port) -{ - int fd_socket; - struct sockaddr_in sin; - struct hostent *he; + if (fd_socket < 0) + { + DBG(DBG_error, "open_socket: Could not create socket: %s\n", strerror(errno)); + continue; + } - he = gethostbyname(server); - if (!he) - { - DBG(DBG_error, "open_socket: Could not get hostname of \"%s\"\n", server); - return -1; - } - else - { - DBG(DBG_info, "open_socket: connecting to \"%s\" = %d.%d.%d.%d\n", - he->h_name, - (unsigned char) he->h_addr_list[0][0], - (unsigned char) he->h_addr_list[0][1], - (unsigned char) he->h_addr_list[0][2], - (unsigned char) he->h_addr_list[0][3]); - } - - if (he->h_addrtype != AF_INET) - { - DBG(DBG_error, "open_socket: Unknown address family: %d\n", he->h_addrtype); - return -1; - } + /* setsockopt (dev->ctl, level, TCP_NODELAY, &on, sizeof (on)); */ - fd_socket = socket(AF_INET, SOCK_STREAM, 0); + if (connect(fd_socket, ai->ai_addr, ai->ai_addrlen) != 0) + { + DBG(DBG_error, "open_socket: Could not connect with port %d of socket: %s\n", port, strerror(errno)); + continue; + } - if (fd_socket < 0) - { - DBG(DBG_error, "open_socket: Could not create socket: %s\n", strerror(errno)); - return -1; + /* All went well */ + connected = 1; } -/* setsockopt (dev->ctl, level, TCP_NODELAY, &on, sizeof (on)); */ - - sin.sin_port = htons(port); - sin.sin_family = AF_INET; - memcpy(&sin.sin_addr, he->h_addr_list[0], he->h_length); - - if (connect(fd_socket, &sin, sizeof(sin))) + if (!connected) { - DBG(DBG_error, "open_socket: Could not connect with port %d of socket: %s\n", ntohs(sin.sin_port), strerror(errno)); - return -1; + DBG(DBG_info, "open_socket: Could not connect to any address"); + return -1; } - DBG(DBG_info, "open_socket: Connected with port %d\n", ntohs(sin.sin_port)); + DBG(DBG_info, "open_socket: Connected with port %d\n", port); - return fd_socket; + return fd_socket; } /* ---------------------------------------------------------------------------------------------------------------------- */ /* returns 0 if success */ /* not only a write routine, also reads data */ -int pop3_login(int fd_socket, char *user, char *passwd) +int pop3_login(int fd_socket, const char *user, const char *passwd) { char buf[1024]; int len; - ssize_t bytes_written; len = read(fd_socket, buf, sizeof(buf)); if (len >= 0) @@ -7612,7 +8236,10 @@ int pop3_login(int fd_socket, char *user snprintf(buf, sizeof(buf), "USER %s\r\n", user); DBG(DBG_info2, "> USER xxx\n"); - bytes_written = write(fd_socket, buf, strlen(buf)); + if (write(fd_socket, buf, strlen(buf)) != strlen(buf)) + { + return -1; + } len = read(fd_socket, buf, sizeof(buf)); if (len >= 0) { @@ -7626,7 +8253,10 @@ int pop3_login(int fd_socket, char *user snprintf(buf, sizeof(buf), "PASS %s\r\n", passwd); DBG(DBG_info2, "> PASS xxx\n"); - bytes_written = write(fd_socket, buf, strlen(buf)); + if (write(fd_socket, buf, strlen(buf)) != strlen(buf)) + { + return -1; + } len = read(fd_socket, buf, sizeof(buf)); if (len >= 0) { @@ -7640,7 +8270,10 @@ int pop3_login(int fd_socket, char *user snprintf(buf, sizeof(buf), "QUIT\r\n"); DBG(DBG_info2, "> QUIT\n"); - bytes_written = write(fd_socket, buf, strlen(buf)); + if (write(fd_socket, buf, strlen(buf))) + { + return -1; + } len = read(fd_socket, buf, sizeof(buf)); if (len >= 0) { @@ -7653,11 +8286,11 @@ int pop3_login(int fd_socket, char *user /* ---------------------------------------------------------------------------------------------------------------------- */ -int asmtp_authentication(int fd_socket, int auth_type, char *user, char *passwd) +int asmtp_authentication(int fd_socket, int auth_type, const char *user, const char *passwd) { int len; char buf[1024]; - ssize_t bytes_written; +// ssize_t bytes_written; DBG(DBG_proc, "asmtp_authentication\n"); @@ -7666,9 +8299,16 @@ int asmtp_authentication(int fd_socket, case EMAIL_AUTH_ASMTP_PLAIN: snprintf(buf, sizeof(buf), "AUTH PLAIN "); DBG(DBG_info2, "> %s\\0(USER)\\0(PASSWORD)\n", buf); - bytes_written = write(fd_socket, buf, strlen(buf)); + if (write(fd_socket, buf, strlen(buf)) != strlen(buf)) + { + return -1; + } snprintf(buf, sizeof(buf), "%c%s%c%s", 0, user, 0, passwd); - write_string_base64(fd_socket, buf, strlen(user)+strlen(passwd)+2); + if (write_string_base64(fd_socket, buf, strlen(user)+strlen(passwd)+2) != 0) + { + DBG(DBG_info, "=> error\n"); + return (-1); + } len = read(fd_socket, buf, sizeof(buf)); if (len >= 0) { @@ -7680,7 +8320,10 @@ int asmtp_authentication(int fd_socket, case EMAIL_AUTH_ASMTP_LOGIN: snprintf(buf, sizeof(buf), "AUTH LOGIN\r\n"); DBG(DBG_info2, "> %s", buf); - bytes_written = write(fd_socket, buf, strlen(buf)); + if (write(fd_socket, buf, strlen(buf)) != strlen(buf)) + { + return -1; + } len = read(fd_socket, buf, sizeof(buf)); if (len >= 0) { @@ -7694,7 +8337,11 @@ int asmtp_authentication(int fd_socket, } DBG(DBG_info2, "> (USERNAME)\n"); - write_string_base64(fd_socket, user, strlen(user)); + if (write_string_base64(fd_socket, user, strlen(user)) != 0) + { + DBG(DBG_info, "=> error\n"); + return (-1); + } len = read(fd_socket, buf, sizeof(buf)); if (len >= 0) @@ -7709,7 +8356,11 @@ int asmtp_authentication(int fd_socket, } DBG(DBG_info2, "> (PASSWORD)\n"); - write_string_base64(fd_socket, passwd, strlen(passwd)); + if (write_string_base64(fd_socket, passwd, strlen(passwd)) != 0) + { + DBG(DBG_info, "=> error\n"); + return (-1); + } len = read(fd_socket, buf, sizeof(buf)); if (len >= 0) @@ -7728,7 +8379,10 @@ int asmtp_authentication(int fd_socket, case EMAIL_AUTH_ASMTP_CRAM_MD5: snprintf(buf, sizeof(buf), "AUTH CRAM-MD5\r\n"); DBG(DBG_info2, "> %s", buf); - bytes_written = write(fd_socket, buf, strlen(buf)); + if (write(fd_socket, buf, strlen(buf)) != strlen(buf)) + { + return -1; + } len = read(fd_socket, buf, sizeof(buf)); if (len >= 0) { @@ -7750,14 +8404,13 @@ int asmtp_authentication(int fd_socket, /* not only a write routine, also reads data */ /* returns -1 on error, 0 when ok */ -int write_smtp_header(int fd_socket, char *from, char *to, int auth_type, char *user, char *passwd) +int write_smtp_header(int fd_socket, const char *from, const char *to, int auth_type, const char *user, const char *passwd) { char buf[1024]; int len; char to_line[1024]; char *to_pos = NULL; char *pos = NULL; - ssize_t bytes_written; len = read(fd_socket, buf, sizeof(buf)); if (len >= 0) @@ -7775,7 +8428,10 @@ int write_smtp_header(int fd_socket, cha snprintf(buf, sizeof(buf), "EHLO localhost\r\n"); } DBG(DBG_info2, "> %s", buf); - bytes_written = write(fd_socket, buf, strlen(buf)); + if (write(fd_socket, buf, strlen(buf)) != strlen(buf)) + { + return -1; + } len = read(fd_socket, buf, sizeof(buf)); if (len >= 0) { @@ -7809,7 +8465,10 @@ int write_smtp_header(int fd_socket, cha } snprintf(buf, sizeof(buf), "MAIL FROM: <%s>\r\n", from); DBG(DBG_info2, "> %s", buf); - bytes_written = write(fd_socket, buf, strlen(buf)); + if (write(fd_socket, buf, strlen(buf)) != strlen(buf)) + { + return -1; + } len = read(fd_socket, buf, sizeof(buf)); if (len >= 0) { @@ -7849,7 +8508,10 @@ int write_smtp_header(int fd_socket, cha snprintf(buf, sizeof(buf), "RCPT TO: <%s>\r\n", to_pos); DBG(DBG_info2, "> %s", buf); - bytes_written = write(fd_socket, buf, strlen(buf)); + if (write(fd_socket, buf, strlen(buf)) != strlen(buf)) + { + return -1; + } len = read(fd_socket, buf, sizeof(buf)); if (len >= 0) { @@ -7882,7 +8544,10 @@ int write_smtp_header(int fd_socket, cha snprintf(buf, sizeof(buf), "DATA\r\n"); DBG(DBG_info2, "> %s", buf); - bytes_written = write(fd_socket, buf, strlen(buf)); + if (write(fd_socket, buf, strlen(buf)) != strlen(buf)) + { + return -1; + } len = read(fd_socket, buf, sizeof(buf)); if (len >= 0) { @@ -7913,11 +8578,14 @@ int write_smtp_footer(int fd_socket) { char buf[1024]; int len; - ssize_t bytes_written; +// ssize_t bytes_written; snprintf(buf, sizeof(buf), "\r\n.\r\n"); DBG(DBG_info2, "> %s", buf); - bytes_written = write(fd_socket, buf, strlen(buf)); + if (write(fd_socket, buf, strlen(buf)) != strlen(buf)) + { + return -1; + } len = read(fd_socket, buf, sizeof(buf)); if (len >= 0) { @@ -7927,7 +8595,10 @@ int write_smtp_footer(int fd_socket) snprintf(buf, sizeof(buf), "QUIT\r\n"); DBG(DBG_info2, "> %s", buf); - bytes_written = write(fd_socket, buf, strlen(buf)); + if (write(fd_socket, buf, strlen(buf)) != 0) + { + return -1; + } len = read(fd_socket, buf, sizeof(buf)); if (len >= 0) {