All pastes #1296199 Raw Edit

php-cgi wrapper

public c v1 · immutable
#1296199 ·published 2008-12-30 05:26 UTC
rendered paste body
/** * Simple wrapper for php-cgi that workarounds * the bug: http://bugs.php.net/bug.php?id=28227 * Tested with thttpd only. * * Compilation: *   gcc -Wall -Os -s -o wrapper wrapper.c * * Usage: * 1. Put 'wrapper' binary in the /bin directory. * 2. In the first line of the script instead of line: *      #!/bin/php-cgi *    use the line: *      #!/bin/wrapper /bin/php-cgi */// Translation use-cases://// 1. http://localhost/script/phpinfo.php//   PWD=/html/script//   PATH_INFO is not set//   SCRIPT_NAME=/script/phpinfo.php//   -> SCRIPT_FILENAME=/html/script/phpinfo.php//// 2. http://localhost/script/phpinfo.php/asd/qwe//   PWD=/html/script//   PATH_INFO=/asd/qwe//   SCRIPT_NAME=/script/phpinfo.php//   -> SCRIPT_FILENAME=/html/script/phpinfo.php//// 3. http://localhost/script/ (here index.htm is a CGI)//   PWD=/html/script//   PATH_INFO is not set//   SCRIPT_NAME=/script/                     -> /script/index.htm//   -> SCRIPT_FILENAME=/html/script/index.htm   - take it from argv[2]//// 4. http://localhost/script/phpinfo.php/asd/qwe///   PWD=/html/script//   PATH_INFO=/asd/qwe                       -> /asd/qwe///   SCRIPT_NAME=/script/phpinfo.php/asd/qwe/ -> /script/phpinfo.php//   -> SCRIPT_FILENAME=/html/script/phpinfo.php//// 5. http://localhost/script/phpinfo.php///   PWD=/html/script//   PATH_INFO is not set                     -> ///   SCRIPT_NAME=/script/phpinfo.php/         -> /script/phpinfo.php//   -> SCRIPT_FILENAME=/html/script/phpinfo.php#include <stdlib.h>#include <unistd.h>#include <string.h>int main(int argc, char *argv[]){  char pwd[1024];  char *name = getenv("SCRIPT_NAME");  if (name && getcwd(pwd, sizeof(pwd)) && !getenv("SCRIPT_FILENAME"))  {    name = strdup(name);    // First check if it has '/' at the end    if (name[strlen(name)-1]=='/')    {      char *info = getenv("PATH_INFO");      if (info)      { // case 4, making it similar to case 2:        // * stripping tail from SCRIPT_NAME        name[strlen(name) - strlen(info) - 1] = 0;        // * adding slash to PATH_INFO        int infolen = strlen(info);        char *newinfo = (char*)malloc(infolen + 2);        strcpy(newinfo, info);        newinfo[infolen] = '/';        newinfo[infolen+1] = 0;        setenv("PATH_INFO", newinfo, 1);        free(newinfo);      }      else      { // case 3 or case 5, trying to guess one        int pwdlen = strlen(pwd);        int namelen = strlen(name);        if (pwdlen >= namelen-1 && strncmp(pwd+pwdlen-namelen+1, name, namelen-1) == 0)        { // looks like case 3, changing it to case 1          char *newname = (char*)malloc(namelen + strlen(argv[2]) + 2);          strcpy(newname, name);          strcat(newname, argv[2]);          free(name);          name = newname;        }        else        { // looks like case 5, changing it to case 2          name[namelen-1] = 0;          setenv("PATH_INFO", "/", 0);          setenv("PATH_TRANSLATED", "/", 0);        }      }    }    // processing cases 1 and 2    // adding SCRIPT_FILENAME variable to environment    int pathlen = strrchr(name, '/') - name;    int prefixlen = strlen(pwd) - pathlen;    char *newenv = (char*)malloc(prefixlen + strlen(name) + 2);    strcpy(newenv, pwd);    newenv[prefixlen] = 0;    strcat(newenv, name);    setenv("SCRIPT_FILENAME", newenv, 0);    setenv("SCRIPT_NAME", name, 1); // required for cases 3-5    free(newenv);    free(name);  }  else  {    // Not running from thttpd? What can we do... :(    return 1;  }  // execute real interpreter  argv++;  return execvp(argv[0], argv);}