This patch is untested, my apologies for that. I don't have a working Visual 
C++ environment in
which to compile PHP at the moment. I have, however, tested the concepts 
involved. I can also
provide test cases and expected output if that would help.

The problem is PHP's incorrect invocation of cmd.exe, which causes no end of 
trouble to those
developing PHP applications on Windows systems. You can find many workarounds 
for it in the manual
comments, but a permanent, robust fix is actually quite simple, at least for 
NT-based versions of
Windows.

Here is an extract of the output of "help cmd" on Windows XP:

CMD [/A | /U] [/Q] [/D] [/E:ON | /E:OFF] [/F:ON | /F:OFF] [/V:ON | /V:OFF]
    [[/S] [/C | /K] string]

/C      Carries out the command specified by string and then terminates
/K      Carries out the command specified by string but remains

[...]

If /C or /K is specified, then the remainder of the command line after
the switch is processed as a command line, where the following logic is
used to process quote (") characters:

    1.  If all of the following conditions are met, then quote characters
        on the command line are preserved:

        - no /S switch
        - exactly two quote characters
        - no special characters between the two quote characters,
          where special is one of: &<>()@^|
        - there are one or more whitespace characters between the
          the two quote characters
        - the string between the two quote characters is the name
          of an executable file.

    2.  Otherwise, old behavior is to see if the first character is
        a quote character and if so, strip the leading character and
        remove the last quote character on the command line, preserving
        any text after the last quote character.

[end quote]

This provides a simple, robust means to execute a command via cmd.exe:

cmd.exe /s /c "...command goes here..."

Otherwise, the programmer risks being plunged into a world of heuristic pain 
that only a Microsoft
developer could love. Some instructive examples:

C:\>cmd /c "C:\Program Files\ImageMagick-6.2.6-Q16\convert.exe"
Version: ImageMagick 6.2.6 01/27/06 Q16 http://www.imagemagick.org
Copyright: Copyright (C) 1999-2006 ImageMagick Studio LLC

Usage: convert.exe [options ...] file [ [options ...] file ...] [options ...] 
file
[...]

C:\>cmd /c "C:\Program Files\ImageMagick-6.2.6-Q16\convert.exe" -version
Version: ImageMagick 6.2.6 01/27/06 Q16 http://www.imagemagick.org
Copyright: Copyright (C) 1999-2006 ImageMagick Studio LLC

C:\>cmd /c "C:\Program Files\ImageMagick-6.2.6-Q16\convert.exe" "some file"
'C:\Program' is not recognized as an internal or external command,
operable program or batch file.

C:\>cd "C:\Program Files\ImageMagick-6.2.6-Q16"

C:\Program Files\ImageMagick-6.2.6-Q16>cmd /c "convert source dest"
convert: unable to open image `source': No such file or directory.
convert: missing an image filename `dest'.

C:\Program Files\ImageMagick-6.2.6-Q16>echo @echo G'day > "convert source 
dest.bat"

C:\Program Files\ImageMagick-6.2.6-Q16>cmd /c "convert source dest"
G'day



Positively scary. /s restores sanity to the situation:

C:\Program Files\ImageMagick-6.2.6-Q16>cmd /s /c "convert source dest"
convert: unable to open image `source': No such file or directory.
convert: missing an image filename `dest'.


Users of COMMAND.COM are not so blessed. There's no handling for double quotes 
at all, so if you
want to execute a program with spaces in the name, you just have to use the 8.3 
alias. In my patch,
this is the responsibility of the application.

C:\>command.com /s /c "echo hello"
Invalid switch
Bad command or file name

The problem as it manifests itself in PHP was reported as Bug #34671, and 
closed as bogus by a
trigger-happy admin. You can't work around it properly in application-level 
code, because you can't
specify /s.

-- Tim Starling
Index: TSRM/tsrm_win32.c
===================================================================
RCS file: /repository/TSRM/tsrm_win32.c,v
retrieving revision 1.28
diff -u -r1.28 tsrm_win32.c
--- TSRM/tsrm_win32.c   1 Jan 2006 13:09:48 -0000       1.28
+++ TSRM/tsrm_win32.c   6 Feb 2006 01:53:29 -0000
@@ -209,8 +209,15 @@
                startup.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
        }
 
-       cmd = (char*)malloc(strlen(command)+strlen(TWG(comspec))+sizeof(" /c 
"));
-       sprintf(cmd, "%s /c %s", TWG(comspec), command);
+       if (GetVersion()<0x80000000) {
+               /* NT calling convention: quotes around everything, /s to 
disable heuristics */
+               cmd = 
(char*)malloc(strlen(command)+strlen(TWG(comspec))+sizeof(" /s /c \"\""));
+               sprintf(cmd, "%s /s /c \"%s\"", TWG(comspec), command);
+       } else {
+               /* 95/98/Me calling convention. Long names need to be converted 
to short names by the application. */
+               cmd = 
(char*)malloc(strlen(command)+strlen(TWG(comspec))+sizeof(" /c "));
+               sprintf(cmd, "%s /c %s", TWG(comspec), command);
+       }
        if (!CreateProcess(NULL, cmd, &security, &security, 
security.bInheritHandle, NORMAL_PRIORITY_CLASS, env, cwd, &startup, &process)) {
                return NULL;
        }

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to