From 991d45b68d8b19c075e5b16bb63b6b8898090341 Mon Sep 17 00:00:00 2001 From: pabs Date: Thu, 27 Dec 2007 07:34:47 +0000 Subject: [PATCH] Port the security fixes to Windows. Thanks to PXEGeek for much patience and testing the changes. git-svn-id: http://svn.voria.com/code@1237 1f10aa63-cdf2-0310-b900-c93c546f37ac --- synfig-core/trunk/configure.ac | 7 ++ synfig-core/trunk/src/modules/mod_dv/trgt_dv.cpp | 88 ++++++++++++++++++- .../trunk/src/modules/mod_ffmpeg/mptr_ffmpeg.cpp | 87 ++++++++++++++++++- .../trunk/src/modules/mod_ffmpeg/trgt_ffmpeg.cpp | 85 ++++++++++++++++++- .../modules/mod_imagemagick/mptr_imagemagick.cpp | 32 ++++++- .../modules/mod_imagemagick/trgt_imagemagick.cpp | 98 +++++++++++++++++++++- 6 files changed, 391 insertions(+), 6 deletions(-) diff --git a/synfig-core/trunk/configure.ac b/synfig-core/trunk/configure.ac index 52eb846..aec847f 100644 --- a/synfig-core/trunk/configure.ac +++ b/synfig-core/trunk/configure.ac @@ -472,6 +472,9 @@ esac # -- H E A D E R S -------------------------------------------- +AC_HEADER_SYS_WAIT +AC_CHECK_HEADERS([process.h io.h fcntl.h]) + # -- T Y P E S & S T R U C T S -------------------------------- # -- F U N C T I O N S ---------------------------------------- @@ -483,6 +486,10 @@ dnl ]) AC_CHECK_FUNCS([fork]) AC_CHECK_FUNCS([kill]) AC_CHECK_FUNCS([pipe]) +AC_CHECK_FUNCS([waitpid]) +AC_CHECK_FUNCS([_spawnlp]) +AC_CHECK_FUNCS([_pipe]) +AC_CHECK_FUNCS([cwait]) AC_CHECK_FUNCS( [isnan], diff --git a/synfig-core/trunk/src/modules/mod_dv/trgt_dv.cpp b/synfig-core/trunk/src/modules/mod_dv/trgt_dv.cpp index a820c33..d4b7440 100644 --- a/synfig-core/trunk/src/modules/mod_dv/trgt_dv.cpp +++ b/synfig-core/trunk/src/modules/mod_dv/trgt_dv.cpp @@ -37,7 +37,18 @@ #include "trgt_dv.h" #include #include -#include +#if HAVE_SYS_WAIT_H + #include +#endif +#if HAVE_IO_H + #include +#endif +#if HAVE_PROCESS_H + #include +#endif +#if HAVE_FCNTL_H + #include +#endif #include #include #include @@ -51,6 +62,12 @@ using namespace synfig; using namespace std; using namespace etl; +#if defined(HAVE_FORK) && defined(HAVE_PIPE) && defined(HAVE_WAITPID) + #define UNIX_PIPE_TO_PROCESSES +#elif defined(HAVE__SPAWNLP) && defined(HAVE__PIPE) && defined(HAVE_CWAIT) + #define WIN32_PIPE_TO_PROCESSES +#endif + /* === G L O B A L S ======================================================= */ SYNFIG_TARGET_INIT(dv_trgt); @@ -79,7 +96,11 @@ dv_trgt::~dv_trgt() if(file){ fclose(file); int status; +#if defined(WIN32_PIPE_TO_PROCESSES) + cwait(&status,pid,0); +#elif defined(UNIX_PIPE_TO_PROCESSES) waitpid(pid,&status,0); +#endif } file=NULL; delete [] buffer; @@ -127,6 +148,66 @@ dv_trgt::init() { imagecount=desc.get_frame_start(); +#if defined(WIN32_PIPE_TO_PROCESSES) + + int p[2]; + int stdin_fileno, stdout_fileno; + + if(_pipe(p, 512, O_BINARY | O_NOINHERIT) < 0) { + synfig::error(_("Unable to open pipe to encodedv")); + return false; + } + + // Save stdin/stdout so we can restore them later + stdin_fileno = _dup(_fileno(stdin)); + stdout_fileno = _dup(_fileno(stdout)); + + // encodedv should read from the pipe + if(_dup2(p[0], _fileno(stdin)) != 0) { + synfig::error(_("Unable to open pipe to encodedv")); + return false; + } + + FILE* outfile = fopen(filename.c_str(),"wb"); + if( outfile == NULL ){ + synfig::error(_("Unable to open pipe to encodedv")); + return false; + } + if(_dup2(_fileno(outfile), _fileno(stdout)) != 0) { + synfig::error(_("Unable to open pipe to encodedv")); + return false; + } + + if(wide_aspect) + pid = _spawnlp(_P_NOWAIT, "encodedv", "encodedv", "-w", "1", "-", (const char *)NULL); + else + pid = _spawnlp(_P_NOWAIT, "encodedv", "encodedv", "-", (const char *)NULL); + + if( pid < 0) { + synfig::error(_("Unable to open pipe to encodedv")); + return false; + } + + // Restore stdin/stdout + if(_dup2(stdin_fileno, _fileno(stdin)) != 0) { + synfig::error(_("Unable to open pipe to encodedv")); + return false; + } + if(_dup2(stdout_fileno, _fileno(stdout)) != 0) { + synfig::error(_("Unable to open pipe to encodedv")); + return false; + } + close(stdin_fileno); + close(stdout_fileno); + + // Close the pipe read end - encodedv uses it + close(p[0]); + + // We write data to the write end of the pipe + file = fdopen(p[1], "wb"); + +#elif defined(UNIX_PIPE_TO_PROCESSES) + int p[2]; if (pipe(p)) { @@ -187,6 +268,11 @@ dv_trgt::init() } } +#else + #error There are no known APIs for creating child processes +#endif + + // Sleep for a moment to let the pipe catch up etl::clock().sleep(0.25f); diff --git a/synfig-core/trunk/src/modules/mod_ffmpeg/mptr_ffmpeg.cpp b/synfig-core/trunk/src/modules/mod_ffmpeg/mptr_ffmpeg.cpp index f1f7e0b..827a527 100644 --- a/synfig-core/trunk/src/modules/mod_ffmpeg/mptr_ffmpeg.cpp +++ b/synfig-core/trunk/src/modules/mod_ffmpeg/mptr_ffmpeg.cpp @@ -35,7 +35,18 @@ #include "mptr_ffmpeg.h" #include #include -#include +#if HAVE_SYS_WAIT_H + #include +#endif +#if HAVE_IO_H + #include +#endif +#if HAVE_PROCESS_H + #include +#endif +#if HAVE_FCNTL_H + #include +#endif #include #include #include @@ -49,6 +60,12 @@ using namespace synfig; using namespace std; using namespace etl; +#if defined(HAVE_FORK) && defined(HAVE_PIPE) && defined(HAVE_WAITPID) + #define UNIX_PIPE_TO_PROCESSES +#elif defined(HAVE__SPAWNLP) && defined(HAVE__PIPE) && defined(HAVE_CWAIT) + #define WIN32_PIPE_TO_PROCESSES +#endif + /* === G L O B A L S ======================================================= */ SYNFIG_IMPORTER_INIT(ffmpeg_mptr); @@ -68,9 +85,67 @@ ffmpeg_mptr::seek_to(int frame) { fclose(file); int status; - waitpid(pid,&status,0); +#if defined(WIN32_PIPE_TO_PROCESSES) + cwait(&status,pid,0); +#elif defined(UNIX_PIPE_TO_PROCESSES) + waitpid(pid,&status,0); +#endif } +#if defined(WIN32_PIPE_TO_PROCESSES) + + int p[2]; + int stdin_fileno, stdout_fileno; + + if(_pipe(p, 512, O_BINARY | O_NOINHERIT) < 0) { + cerr<<"Unable to open pipe to ffmpeg"< #include -#include +#if HAVE_SYS_WAIT_H + #include +#endif +#if HAVE_IO_H + #include +#endif +#if HAVE_PROCESS_H + #include +#endif +#if HAVE_FCNTL_H + #include +#endif #include #include #include @@ -51,6 +62,12 @@ using namespace synfig; using namespace std; using namespace etl; +#if defined(HAVE_FORK) && defined(HAVE_PIPE) && defined(HAVE_WAITPID) + #define UNIX_PIPE_TO_PROCESSES +#elif defined(HAVE__SPAWNLP) && defined(HAVE__PIPE) && defined(HAVE_CWAIT) + #define WIN32_PIPE_TO_PROCESSES +#endif + /* === G L O B A L S ======================================================= */ SYNFIG_TARGET_INIT(ffmpeg_trgt); @@ -80,7 +97,11 @@ ffmpeg_trgt::~ffmpeg_trgt() sleep(1); fclose(file); int status; +#if defined(WIN32_PIPE_TO_PROCESSES) + cwait(&status,pid,0); +#elif defined(UNIX_PIPE_TO_PROCESSES) waitpid(pid,&status,0); +#endif } file=NULL; delete [] buffer; @@ -131,6 +152,64 @@ ffmpeg_trgt::init() if(desc.get_frame_end()-desc.get_frame_start()>0) multi_image=true; +#if defined(WIN32_PIPE_TO_PROCESSES) + + int p[2]; + int stdin_fileno, stdout_fileno; + + if(_pipe(p, 512, O_BINARY | O_NOINHERIT) < 0) { + synfig::error(_("Unable to open pipe to ffmpeg")); + return false; + } + + // Save stdin/stdout so we can restore them later + stdin_fileno = _dup(_fileno(stdin)); + stdout_fileno = _dup(_fileno(stdout)); + + // ffmpeg should read from the pipe + if(_dup2(p[0], _fileno(stdin)) != 0) { + synfig::error(_("Unable to open pipe to ffmpeg")); + return false; + } + + /* + ffmpeg accepts the output filename on the command-line + if(_dup2(_fileno(output), _fileno(stdout)) != 0) { + synfig::error(_("Unable to open pipe to ffmpeg")); + return false; + } + */ + + if( filename.c_str()[0] == '-' ) + pid = _spawnlp(_P_NOWAIT, "ffmpeg", "ffmpeg", "-f", "image2pipe", "-vcodec", "ppm", "-an", "-r", strprintf("%f", desc.get_frame_rate()).c_str(), "-i", "pipe:", "-loop", "-hq", "-title", get_canvas()->get_name().c_str(), "-vcodec", "mpeg1video", "-y", "--", filename.c_str(), (const char *)NULL); + else + pid = _spawnlp(_P_NOWAIT, "ffmpeg", "ffmpeg", "-f", "image2pipe", "-vcodec", "ppm", "-an", "-r", strprintf("%f", desc.get_frame_rate()).c_str(), "-i", "pipe:", "-loop", "-hq", "-title", get_canvas()->get_name().c_str(), "-vcodec", "mpeg1video", "-y", filename.c_str(), (const char *)NULL); + + if( pid < 0) { + synfig::error(_("Unable to open pipe to ffmpeg")); + return false; + } + + // Restore stdin/stdout + if(_dup2(stdin_fileno, _fileno(stdin)) != 0) { + synfig::error(_("Unable to open pipe to ffmpeg")); + return false; + } + if(_dup2(stdout_fileno, _fileno(stdout)) != 0) { + synfig::error(_("Unable to open pipe to ffmpeg")); + return false; + } + close(stdin_fileno); + close(stdout_fileno); + + // Close the pipe read end - ffmpeg uses it + close(p[0]); + + // We write data to the write end of the pipe + file = fdopen(p[1], "wb"); + +#elif defined(UNIX_PIPE_TO_PROCESSES) + int p[2]; if (pipe(p)) { @@ -171,6 +250,10 @@ ffmpeg_trgt::init() file = fdopen(p[1], "wb"); } +#else + #error There are no known APIs for creating child processes +#endif + // etl::yield(); if(!file) diff --git a/synfig-core/trunk/src/modules/mod_imagemagick/mptr_imagemagick.cpp b/synfig-core/trunk/src/modules/mod_imagemagick/mptr_imagemagick.cpp index 4d7ca20..c945ee5 100644 --- a/synfig-core/trunk/src/modules/mod_imagemagick/mptr_imagemagick.cpp +++ b/synfig-core/trunk/src/modules/mod_imagemagick/mptr_imagemagick.cpp @@ -35,7 +35,18 @@ #include "mptr_imagemagick.h" #include #include -#include +#if HAVE_SYS_WAIT_H + #include +#endif +#if HAVE_IO_H + #include +#endif +#if HAVE_PROCESS_H + #include +#endif +#if HAVE_FCNTL_H + #include +#endif #include #include #include @@ -50,6 +61,12 @@ using namespace synfig; using namespace std; using namespace etl; +#if defined(HAVE_FORK) && defined(HAVE_PIPE) && defined(HAVE_WAITPID) + #define UNIX_PIPE_TO_PROCESSES +#elif defined(HAVE__SPAWNLP) && defined(HAVE__PIPE) && defined(HAVE_CWAIT) + #define WIN32_PIPE_TO_PROCESSES +#endif + /* === G L O B A L S ======================================================= */ SYNFIG_IMPORTER_INIT(imagemagick_mptr); @@ -89,6 +106,15 @@ imagemagick_mptr::get_frame(synfig::Surface &surface,Time /*time*/, synfig::Prog string temp_file="/tmp/deleteme.png"; string output="png32:"+temp_file; +#if defined(WIN32_PIPE_TO_PROCESSES) + + if(filename.find("psd")!=String::npos) + _spawnlp(_P_WAIT, "convert", "convert", filename.c_str(), "-flatten", output.c_str(), (const char *)NULL); + else + _spawnlp(_P_WAIT, "convert", "convert", filename.c_str(), output.c_str(), (const char *)NULL); + +#elif defined(UNIX_PIPE_TO_PROCESSES) + pid_t pid = fork(); if (pid == -1) { @@ -110,6 +136,10 @@ imagemagick_mptr::get_frame(synfig::Surface &surface,Time /*time*/, synfig::Prog if( (WIFEXITED(status) && WEXITSTATUS(status) != 0) || !WIFEXITED(status) ) return false; +#else + #error There are no known APIs for creating child processes +#endif + Importer::Handle importer(Importer::open(temp_file)); DEBUGPOINT(); diff --git a/synfig-core/trunk/src/modules/mod_imagemagick/trgt_imagemagick.cpp b/synfig-core/trunk/src/modules/mod_imagemagick/trgt_imagemagick.cpp index bfd8f59..f33b98f 100644 --- a/synfig-core/trunk/src/modules/mod_imagemagick/trgt_imagemagick.cpp +++ b/synfig-core/trunk/src/modules/mod_imagemagick/trgt_imagemagick.cpp @@ -37,7 +37,18 @@ #include "trgt_imagemagick.h" #include #include -#include +#if HAVE_SYS_WAIT_H + #include +#endif +#if HAVE_IO_H + #include +#endif +#if HAVE_PROCESS_H + #include +#endif +#if HAVE_FCNTL_H + #include +#endif #include #include #include @@ -52,6 +63,12 @@ using namespace synfig; using namespace std; using namespace etl; +#if defined(HAVE_FORK) && defined(HAVE_PIPE) && defined(HAVE_WAITPID) + #define UNIX_PIPE_TO_PROCESSES +#elif defined(HAVE__SPAWNLP) && defined(HAVE__PIPE) && defined(HAVE_CWAIT) + #define WIN32_PIPE_TO_PROCESSES +#endif + /* === G L O B A L S ======================================================= */ SYNFIG_TARGET_INIT(imagemagick_trgt); @@ -77,7 +94,11 @@ imagemagick_trgt::~imagemagick_trgt() if(file){ fclose(file); int status; +#if defined(WIN32_PIPE_TO_PROCESSES) + cwait(&status,pid,0); +#elif defined(UNIX_PIPE_TO_PROCESSES) waitpid(pid,&status,0); +#endif } file=NULL; delete [] buffer; @@ -119,7 +140,11 @@ imagemagick_trgt::end_frame() fflush(file); fclose(file); int status; +#if defined(WIN32_PIPE_TO_PROCESSES) + cwait(&status,pid,0); +#elif defined(UNIX_PIPE_TO_PROCESSES) waitpid(pid,&status,0); +#endif } file=NULL; imagecount++; @@ -139,6 +164,73 @@ imagemagick_trgt::start_frame(synfig::ProgressCallback *cb) else newfilename = filename; +#if defined(WIN32_PIPE_TO_PROCESSES) + + int p[2]; + int stdin_fileno, stdout_fileno; + + if(_pipe(p, 512, O_BINARY | O_NOINHERIT) < 0) { + if(cb) cb->error(N_(msg)); + else synfig::error(N_(msg)); + return false; + } + + // Save stdin/stdout so we can restore them later + stdin_fileno = _dup(_fileno(stdin)); + stdout_fileno = _dup(_fileno(stdout)); + + // convert should read from the pipe + if(_dup2(p[0], _fileno(stdin)) != 0) { + if(cb) cb->error(N_(msg)); + else synfig::error(N_(msg)); + return false; + } + + /* + convert accepts the output filename on the command-line + if(_dup2(_fileno(output), _fileno(stdout)) != 0) { + if(cb) cb->error(N_(msg)); + else synfig::error(N_(msg)); + return false; + } + */ + + pid = _spawnlp(_P_NOWAIT, "convert", "convert", + "-depth", "8", + "-size", strprintf("%dx%d", desc.get_w(), desc.get_h()).c_str(), + ((channels(pf) == 4) ? "rgba:-[0]" : "rgb:-[0]"), + "-density", strprintf("%dx%d", round_to_int(desc.get_x_res()/39.3700787402), round_to_int(desc.get_y_res()/39.3700787402)).c_str(), + newfilename.c_str(), + (const char *)NULL); + + if( pid < 0) { + if(cb) cb->error(N_(msg)); + else synfig::error(N_(msg)); + return false; + } + + // Restore stdin/stdout + if(_dup2(stdin_fileno, _fileno(stdin)) != 0) { + if(cb) cb->error(N_(msg)); + else synfig::error(N_(msg)); + return false; + } + if(_dup2(stdout_fileno, _fileno(stdout)) != 0) { + if(cb) cb->error(N_(msg)); + else synfig::error(N_(msg)); + return false; + } + close(stdin_fileno); + close(stdout_fileno); + + // Close the pipe read end - convert uses it + close(p[0]); + + // We write data to the write end of the pipe + file = fdopen(p[1], "wb"); + +#elif defined(UNIX_PIPE_TO_PROCESSES) + int p[2]; if (pipe(p)) { @@ -186,6 +278,10 @@ imagemagick_trgt::start_frame(synfig::ProgressCallback *cb) file = fdopen(p[1], "wb"); } +#else + #error There are no known APIs for creating child processes +#endif + if(!file) { if(cb)cb->error(N_(msg)); -- 2.7.4