├── .gitignore ├── .npmignore ├── .travis.yml ├── README.md ├── appveyor.yml ├── browser.js ├── example.js ├── example ├── base.css ├── example.html ├── example.php ├── index.html ├── test.html ├── test.php ├── websocket_client.php └── ws_request.php ├── package.json ├── php.ini ├── php_worker.php ├── sphp.js └── test ├── doc_root ├── phpinfo.php └── subdir │ └── required-phpinfo.php └── testexpress.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | example-wp.js 10 | 11 | # Dependency directory 12 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 13 | node_modules 14 | wp 15 | tmp 16 | 17 | # Editor backups 18 | *~ 19 | 20 | # Test cases 21 | example-ws.js 22 | apache.txt 23 | 24 | # Other 25 | notes.txt 26 | nyt.txt 27 | sphp-ingo.js 28 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | example-wp.js 10 | 11 | # Dependency directory 12 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 13 | node_modules 14 | wp 15 | tmp 16 | 17 | # Editor backups 18 | *~ 19 | 20 | # Test cases 21 | example-ws.js 22 | apache.txt 23 | 24 | # Other 25 | notes.txt 26 | nyt.txt 27 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | os: 2 | - linux 3 | - osx 4 | language: node_js 5 | node_js: 6 | - "4" 7 | - "6" 8 | - "8" 9 | before_install: 10 | - 'if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then travis_wait brew tap homebrew/homebrew-php; fi' 11 | - 'if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then travis_wait brew update; fi' 12 | - 'if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then travis_wait 30 brew install --with-cgi php71; fi' 13 | - 'if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then export PATH="$(brew --prefix homebrew/php/php71)/bin:$PATH"; fi' 14 | - export PHP_PATH="$(which php-cgi)" 15 | - echo $PHP_PATH 16 | - php-cgi -v 17 | addons: 18 | apt: 19 | sources: 20 | - ubuntu-toolchain-r-test 21 | - sourceline: 'ppa:ondrej/php' 22 | packages: 23 | - g++-4.8 24 | - php7.1-cgi 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Snappy PHP for node js 2 | A snappy PHP module / middleware. 3 | 4 | Fast response time is favored over use of resources and performance under load. This package is best suited embedded system and small application with few user, where you just need a fastest response time without much load. 5 | 6 | Features: 7 | * Use PHP in node with express, sessions and websockets. 8 | * Transfer node express session to php and reuse session ID and cookie from express 9 | * No dependencies (except for example) 10 | * Mimic Apache mod_php population of the PHP super globals 11 | * Highly configurable. 12 | * Comes with an example of a server using PHP websocket client 13 | 14 | **Note:** php-cgi must be installed. If its not in the PATH, the variable cgiEngine must be set to point to the executable binary. 15 | 16 | File upload is disabled at present. 17 | 18 | #### Install 19 | 20 | npm install sphp 21 | 22 | #### Run example server 23 | 24 | Make sure php-cgi is installed and in the path. (not just php) 25 | 26 | npm install express express-session ws body-parser 27 | 28 | Change directory to to where sphp reside (node_module/...): 29 | 30 | cd sphp 31 | 32 | Run the example server 33 | 34 | node example.js 35 | 36 | Connect to the exampleserver in a browser: 37 | 38 | http://localhost:8080 or http://
:8080 39 | 40 | You should now se the example pages. 41 | 42 | 43 | ### Set up with an express server 44 | 45 | var express = require('express'); 46 | var sphp = require('sphp'); 47 | 48 | var app = express(); 49 | var server = app.listen(8080); 50 | 51 | app.use(sphp.express('public/')); 52 | app.use(express.static('public/')); 53 | 54 | 55 | ### Set up with an express server and websockets 56 | 57 | var express = require('express'); 58 | var sphp = require('sphp'); 59 | 60 | var app = express(); 61 | var server = app.listen(8080); 62 | var ws = new require('ws').Server({server: server}); 63 | 64 | app.use(sphp.express('public/')); 65 | ws.on('connection',sphp.websocket()); 66 | app.use(express.static('public/')); 67 | 68 | 69 | #### Set up with an express server and express-session 70 | 71 | var express = require('express'); 72 | var expressSession = require('express-session'); 73 | var bodyParser = require('body-parser'); 74 | var sessionStore = new expressSession.MemoryStore(); 75 | var sphp = require('sphp'); 76 | 77 | var app = express(); 78 | var server = app.listen(8080); 79 | var sessionOptions={ 80 | store: sessionStore 81 | ,secret:'yes :c)' 82 | ,resave:false 83 | ,saveUninitialized:false 84 | ,rolling: true 85 | ,name: 'SID' 86 | } 87 | 88 | app.use(expressSession(sessionOptions)); 89 | app.use(function(request, response, next){ 90 | // Save session data 91 | request.session.ip=request.client.remoteAddress; 92 | next(); 93 | }); 94 | app.use(bodyParser.json()); 95 | app.use(bodyParser.urlencoded({extended: true})); 96 | 97 | app.use(sphp.express('example/')); 98 | ws.on('connection',sphp.websocket(sessionOptions)); 99 | app.use(express.static('example/')); 100 | 101 | 102 | ### Configuration 103 | SPHP settings can be changed by parsing an array of options to change to the setOptions or express methods. 104 | 105 | Set all options: 106 | 107 | var sphpOptions = { 108 | cgiEngine: “/usr/bin/php-cgi' 109 | ,docRoot: “/home/of/my/pubnlic/files” 110 | ,minSpareWorkers: 4 111 | ,maxWorkers: 20 112 | ,stepDowntime: 1800 113 | ,overwriteWSPath: “/ws_serveice.php” 114 | , preLoadScript: “pre_load.php” 115 | ,superglobals: {_SERVER.SERVER_NAME: “MyServer.com”} 116 | }; 117 | 118 | sphp.setOptions(sphpOptions); 119 | 120 | or alternatively parsed with the express middleware setup: 121 | 122 | app.use(sphp.express(sphpOptions)); 123 | 124 | To set the server name: 125 | 126 | sphp.setOptions({ 127 | superglobals: { 128 | _SERVER: { 129 | SERVER_NAME: "MyServer.com" 130 | } 131 | } 132 | }); 133 | 134 | To load the enviroment variables: 135 | 136 | sphp.setOptions({ 137 | superglobals: { 138 | _ENV: JSON.parse(JSON.stringify(process.env) 139 | } 140 | }); 141 | 142 | |variable name | | 143 | |---|---| 144 | |cgiEngine |Default: "php-cgi" Specify which binary file to use to execute PHP script. The executable must be in the environment PATH or use a full path to the executable file.| 145 | |docRoot |(default: "./public" Where to serve script files from. Might be relative or an absolute path. This is the variable set, when sphp.express is called with a parameter.| 146 | |minSpareWorkers |Default: 2. Define the minimum number of workers kept ready.
Note that when calling PHP scripts through websockets, an additional concurrent worker is used. | 147 | |maxWorkers |Default: 10. The maximum number of workers allowed to start. This number will never be exceeded. Requests will instead be rejected. Set this to limit the amount of RAM the server can use, when load is high. The footprint is about 20MB / worker as of php-cgi 5.4 php-gci. 148 | |stepDowntime |Default: 360 seconds. The number of worker are increased dynamically, When the need arises. This is the time it takes before, the number of workers, are reduced by one.| 149 | |overwriteWSPath |Default null. Used to specify which script should serve a websocket request.
If null, the URL of the connection GET request is used. The path is relative to docRoot.| 150 | |preLoadScript |Default null. This can be used to preload libraries, before a page is requested, thus improving reaponcetime. The preLoadScript variable contains a path to a php script, relative to docRoot. Be aware that the script pointet to will be executed when the php engine is loaded eg. before a client has made a page request. non of the super globals are set to usefull values at this point. The script sould contain generic library function that are use system wide, as it will be loaded with all page.| 151 | |superglobals | This can be used to preset PHP superglobals like $_SERVER['SERVER_NAME'] Any variable can be set, but will be overwriten, if the name is one of thouse that is set during request time, except SERVER_NAME.
The following variables are predefined and will be futher populated at request time:
_POST
_GET
_FILES
_SERVER: SERVER_SOFTWARE, SERVER_NAME
_COOKIE| 152 | 153 | ### Notes 154 | The aim of this project is to serve PHP scripts with the best response time possible. Another important functionality is integration with websocket and access to the express servers session data. 155 | 156 | The responsetime is achieved by sacrificing considerations of resources and performance under load. This is implemented by pre-emptively loading of the PHP-CGI engine and a user PHP script, typically including generic PHP library. The process is then put on hold until needed. 157 | 158 | ### Changes 159 | * 0.6.2 Super global SERVER_NAME respects option setting over value generated at request time 160 | Minor consistance corrections in the code 161 | Documentation update 162 | * 0.6.1 Fixed direct call to sphp.exec to function, before express is started. 163 | * 0.6.0 Adapted to windows and OSX platforms 164 | Option settings changed to match recognised usual praxis for express middleware 165 | Improved tests structure 166 | Check validity of PHP engine and respond with clearer error messages if missing 167 | Check and report PHP version in process.versions 168 | Report SPHP version correct in all instances 169 | * 0.5.2 Fixed Websocket parse url bug 170 | * 0.5.1 Documentation update 171 | * 0.5.0 Added superglobals preset options 172 | Fixed Cr/Nl in headers (compattible to express 4) 173 | fixed too few spare workers started, when minSpareWorkers > default value 174 | session.sid is no longer set 175 | * 0.4.3 Updated denendencies 176 | * 0.4.0 Updated to run with express v4 177 | * 0.4.0 Updated to run with express v4 178 | PHP output on standart-error are now send when closing. 179 | stderr now gets loged to console.error. 180 | Changed 'binary' transfer mode to 'UTF-8' to acommodate browser changes 181 | Fixed race condition when termination with error. 182 | Fixed websocket error, when not having a session id. 183 | Fixed PHP_worker.php warning. 184 | * 0.3.15 Output to stderr is now returned last, and loged to server erro output. 185 | * 0.3.14 Added server session ID to session 186 | conInfo.session.sid = request.sessionID; 187 | php_worker uses session.sid from server session rather than cookie 188 | node version 7 compatible 189 | Try harder to make sense og request record 190 | * 0.3.13 Websocket body can now be either a string or an object 191 | * 0.3.12 Documentation update 192 | * 0.3.11 Documentation update 193 | * 0.3.10 Preloading php library scripts, to improve responsetime 194 | * 0.3.9 Documentation update 195 | * 0.3.8 php_worker.php Typo 196 | * 0.3.7 PHP session cookie disabled. 197 | * 0.3.6 Websocket Error 'not opened' when script don't exists 198 | * 0.3.5 open_basedir restriction, without specifying doc roor in php.ini 199 | 200 | ### Help 201 | I appreciate contributions. Code should look good and compact, and be covered by a test case or example. 202 | Please don't change the formatting style laid out, without a good reason. I know its not the most common standard, but its a rather efficient one with node. 203 | 204 | Don't hesitate to submit an issue on github. But please provide a reproducible example. 205 | 206 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | version: 'test-{build}' 2 | environment: 3 | matrix: 4 | - nodejs_version: '4' 5 | - nodejs_version: '6' 6 | - nodejs_version: '8' 7 | platform: 8 | - x86 9 | - x64 10 | cache: 11 | - c:\php -> appveyor.yml 12 | init: 13 | - SET PATH=c:\php\71;%PATH% 14 | - SET PHP_PATH=c:\php\71\php-cgi.exe 15 | clone_folder: 'c:\projects\%APPVEYOR_PROJECT_NAME%' 16 | install: 17 | - IF EXIST c:\php\71 (SET PHP=0) ELSE (SET PHP=1) 18 | - IF %PHP%==1 mkdir c:\php\71 19 | - IF %PHP%==1 cd c:\php\71 20 | - IF %PHP%==1 appveyor DownloadFile http://windows.php.net/downloads/releases/archives/php-7.1.0-Win32-VC14-x64.zip 21 | - IF %PHP%==1 7z x php-7.1.0-Win32-VC14-x64.zip >nul 22 | - set PATH=c:\php\71\;%PATH% 23 | - c:\php\71\php-cgi.exe -v 24 | - cd c:\projects\%APPVEYOR_PROJECT_NAME% 25 | - ps: 'Install-Product node $env:nodejs_version $env:platform' 26 | - npm install 27 | test_script: 28 | - echo %cd% 29 | - node --version 30 | - npm --version 31 | - npm test 32 | build: 'off' 33 | -------------------------------------------------------------------------------- /browser.js: -------------------------------------------------------------------------------- 1 | console.log("Sorry. This module need to run with a server"); 2 | 3 | -------------------------------------------------------------------------------- /example.js: -------------------------------------------------------------------------------- 1 | /*============================================================================*\ 2 | Example of webserver using PHP and websockets served on the same port (80) 3 | 4 | (c) Paragi Aps, Simon Riget 2015. 5 | Free to use, provided copyright note is preserved 6 | 7 | This example is showing how to make a: 8 | * Snappy PHP serverside scripting 9 | * Websocket support, utilising PHP script to serve requests 10 | * Transferring node sessions to PHP 11 | 12 | Sessions are created on a regular HTTP page request. The generated session are 13 | then used with the websocket request, identified by the same session ID cookie 14 | 15 | Note: This example depends on the modules: express, ws express-session and 16 | body-parser: 17 | 18 | npm install express ws express-session body-parser 19 | 20 | 21 | The script php_worker.php is always called, to set globals correctly etc. 22 | The requested script are included by this script. 23 | \*============================================================================*/ 24 | // Catch missing modules 25 | process.on('uncaughtException', function(err) { 26 | console.error("example.js requires modules installed. Use:" 27 | + "\n\n npm install express express-session ws body-parser" 28 | + "\n\nError: ",err.message); 29 | }); 30 | 31 | // Load modules 32 | var express = require('express'); 33 | var expressSession = require('express-session'); 34 | var bodyParser = require('body-parser'); 35 | var _ws = require('ws'); 36 | var path = require('path'); 37 | 38 | process.removeAllListeners('uncaughtException'); 39 | 40 | // Initialize server 41 | var sessionStore = new expressSession.MemoryStore(); 42 | var sphp = require('./sphp.js'); 43 | var app = express(); 44 | var server = app.listen(8080,'0.0.0.0','',function () { 45 | console.log('Server listening at://%s:%s' 46 | ,server.address().address 47 | ,server.address().port); 48 | }); 49 | var ws = new _ws.Server({server: server}); 50 | 51 | // Set up session. store and name must be set, for sphp to catch it 52 | 53 | var docRoot = module.filename.substring(0,module.filename.lastIndexOf(path.sep)) + '/example/'; 54 | 55 | var sessionOptions={ 56 | store: sessionStore 57 | ,secret:'yes :c)' 58 | ,resave:false 59 | ,saveUninitialized:false 60 | ,rolling: true 61 | ,name: 'SID' 62 | } 63 | 64 | var sphpOptions = { 65 | overwriteWSPath: "/ws_request.php" 66 | ,docRoot: docRoot 67 | } 68 | /*============================================================================*\ 69 | Middleware 70 | \*============================================================================*/ 71 | // Attach session control 72 | app.use(expressSession(sessionOptions)); 73 | 74 | // Save some session specific data 75 | app.use(function(request, response, next){ 76 | request.session.ip=request.client.remoteAddress; 77 | next(); 78 | }); 79 | 80 | // Parsing POST requests (Not for websockets) 81 | app.use(bodyParser.json()); // to support JSON-encoded bodies 82 | app.use(bodyParser.urlencoded({extended: true})); // to support URL-encoded bodies 83 | 84 | // Attach sPHP 85 | app.use(sphp.express(sphpOptions)); 86 | 87 | // Attach sPHP execution to the websocket connect event 88 | ws.on('connection',sphp.websocket(sessionOptions)); 89 | 90 | // Setup html file server 91 | app.use(function(request, response, next){ 92 | if(request._parsedUrl.pathname == '/') 93 | request._parsedUrl.pathname='/example.html'; 94 | next(); 95 | }); 96 | app.use(express.static(docRoot)); 97 | -------------------------------------------------------------------------------- /example/base.css: -------------------------------------------------------------------------------- 1 | html { 2 | height:100%; 3 | } 4 | 5 | *{ 6 | color: #FFEDBA; 7 | border-color: #FFEDBA; 8 | border-color: #FFEDBA; 9 | font-size: 16pt; 10 | font-family: serif, Times,"Times New Roman" ; 11 | } 12 | 13 | body{ 14 | margin: 0px; 15 | background-color: #460918; 16 | inner-height:100%; 17 | } 18 | 19 | .container{ 20 | border:2px solid #f0d988; 21 | padding:3px; 22 | border-radius:10px; 23 | background-color: #460918; 24 | background-repeat: no-repeat; 25 | background-size:100% 100%; 26 | box-shadow: 3px 3px 3px #291b2c; 27 | float:left; 28 | margin: 10px; 29 | } 30 | 31 | .tile{ 32 | position: static; 33 | border:2px solid #f0d988; 34 | padding:3px; 35 | border-radius:10px; 36 | background-color:rgba(50,10,10,0.5); 37 | box-shadow: 3px 3px 3px #291b2c; 38 | float:left; 39 | margin: 10px; 40 | transition: opacity 1s ease-in-out; 41 | } 42 | 43 | .tile:hover{ 44 | background-color:rgba(240,217,136,0.2); 45 | cursor:pointer; 46 | } 47 | 48 | <<<<<<< HEAD 49 | 50 | .container{ 51 | border:2px solid #f0d988; 52 | padding:3px; 53 | border-radius:10px; 54 | background-color: #460918; 55 | background-repeat: no-repeat; 56 | background-size:100% 100%; 57 | box-shadow: 3px 3px 3px #291b2c; 58 | float:left; 59 | margin: 10px; 60 | } 61 | 62 | hr{border-color:#f0d988;} 63 | 64 | .withhoverbox {cursor:pointer;} 65 | 66 | -------------------------------------------------------------------------------- /example/example.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Websocket test 6 | 7 | 26 | 27 | 28 | 29 |

Snappy PHP

30 | This is a HTML page
31 |
32 | Go to PHP page
33 | 34 |
35 | Show PHP GLOBALS through websocket 36 |
37 |
38 |
39 | websocket output area:
40 |
41 |
42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /example/example.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Snappy PHP 5 | 6 | 12 | 13 | 14 | 15 |
16 | 17 |
18 |

Snappy PHP

19 | This is a PHP page
20 |
21 | Go to HTML page
22 |
23 | PHP GLOBALS from script
24 |
25 | Show PHP GLOBALS through PHP websocket
26 |
27 |
28 | 29 | Output from ".__FILE__.":
"; 36 | echo print_r($GLOBALS,true).""; 37 | echo "__FILE__: ",__FILE__; 38 | break; 39 | case 'WS': // Aks the websocket server to show its globals 40 | $sp=websocket_open('127.0.0.1:8080/ws_request.php?param=php_test',$errstr); 41 | if(!$sp) trigger_error($errstr); 42 | // Send command and wait for an answer synchronously 43 | websocket_write($sp,json_encode(["php"=>"websocket"])); 44 | echo "\n"; 45 | echo websocket_read($sp,true); 46 | break; 47 | } 48 | echo "
"; 49 | ?> 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /example/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Snappy PHP 6 | 7 | 36 | 37 | 38 |

Snappy PHP

39 | This is a HTML page 40 |
PHP GLOBALS from script
41 |
PHP GLOBALS from websocket 42 |
43 |
44 |
45 | websocket output area:
46 |
47 |
48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /example/test.html: -------------------------------------------------------------------------------- 1 |

Hello world

2 | -------------------------------------------------------------------------------- /example/test.php: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | Test page 10 | 11 | 12 | 14 | 15 | 16 | 17 |

Test af websocket klient

18 | 19 | ".print_r($_SERVER,true).""; 21 | 22 | function hex_dump($data, $newline="\n") 23 | { 24 | static $from = ''; 25 | static $to = ''; 26 | 27 | static $width = 16; # number of bytes per line 28 | 29 | static $pad = '.'; # padding for non-visible characters 30 | 31 | if ($from==='') 32 | { 33 | for ($i=0; $i<=0xFF; $i++) 34 | { 35 | $from .= chr($i); 36 | $to .= ($i >= 0x20 && $i <= 0x7E) ? chr($i) : $pad; 37 | } 38 | } 39 | 40 | $hex = str_split(bin2hex($data), $width*2); 41 | $chars = str_split(strtr($data, $from, $to), $width); 42 | 43 | $offset = 0; 44 | foreach ($hex as $i => $line) 45 | { 46 | echo sprintf('%6X',$offset).' : '.implode(' ', str_split($line,2)) . ' [' . $chars[$i] . ']' . $newline; 47 | $offset += $width; 48 | } 49 | } 50 | /*----------------------------------------------------------------------------*\ 51 | Set timeouts to very small values. 52 | 53 | This code is very simple and dose not handle different versions or negotiations 54 | of any kind. It only has to work with this particular server. 55 | 56 | Send a command or a list of commands to the eventhandler handler 57 | 58 | send_event_signal 59 | 60 | Event names for interactions are a full path context + interaction name 61 | 62 | Commands (and events) coded into a page, must have an underscore or slash to 63 | avoid confusing them with spoken user commands. 64 | 65 | message format 66 | command: 67 | cmd: 68 | cmd_id: a scalar value will bereturned with the reply, to identify callback 69 | token: a scalar value that bust be passed back and forth with the server 70 | to validate commands. 71 | 72 | responce: 73 | reply: Verbal reply to user. Simpel forms are: ok, Unable to comply, working. 74 | error: Optional. Explanation of failure 75 | cmd_id: returned from the request 76 | token: New token to use 77 | 78 | event: 79 | event: An unique event name (Must be a valid HTML tag id as well) 80 | state: New state of the object of the event 81 | html: Optional. HTML code update 82 | message: Optional. A text message update 83 | token: New token to use 84 | 85 | 86 | \*----------------------------------------------------------------------------*/ 87 | 88 | $req['serverinfo']='all'; 89 | $req['token']=false; 90 | 91 | //$req['fill']="sdkfjghsdjkfghsdlk vmhsdkfjlvnsdjæknvsdæjknbsdkjænbsjdfbnsdjkfbnksjdgnbskjdfnbsdnbkjsdnbvkjsdnbkjsdnbjksndfjkbnsdkjbnsdjkbnsdjkbnsdjbgnsd sjdfng sdfghsæ dhgj sdfgjsdh gæosjdghæosdhhhhhhhhhhhgasdnf æsdofngsædofdofgæsodfhgsæodfgsædo"; 92 | 93 | //sys_handler($req); 94 | 95 | function sys_handler($req){ 96 | 97 | static $sp; 98 | 99 | // Validate request 100 | if(!is_array($req)) 101 | trigger_error("Event server call with mallformed or empty request", E_USER_ERROR); 102 | 103 | 104 | // Make websocket connection to server (Keep it open and let it close on exit) 105 | $headers=[ 106 | "cookie: $_SERVER[HTTP_COOKIE_PARSE_RAW]" 107 | //,"user-agent: $_SERVER[HTTP_USER_AGENT]" 108 | ]; 109 | 110 | if(!$sp) $sp=websocket_open('127.0.0.1',$headers); 111 | if(!$sp) trigger_error("Unable to connect to event server: $errstr ($errno)"); 112 | 113 | // Send command and wait for an answer synchronously 114 | websocket_write($sp,json_encode($req,JSON_NUMERIC_CHECK | JSON_NUMERIC_CHECK)); 115 | echo "Request:
".print_r($req,true) . "
"; 116 | 117 | // Get reply 118 | $data=websocket_read($sp); 119 | echo "Response:
".print_r(json_decode($data,true),true) . "
"; 120 | 121 | return json_decode($data,true); 122 | 123 | } 124 | 125 | // Stack opdater 126 | // http://stackoverflow.com/questions/7160899/websocket-client-in-php 127 | // http://stackoverflow.com/questions/22370966/connecting-to-websocket-with-php-client 128 | 129 | function websocket_open($host="127.0.0.1",$headers=''){ 130 | // Make websocket connection to server (Let it close on exit) 131 | // or socket pointer invalid! 132 | 133 | // Make websocket upgrade request header 134 | // Make a header for a http GET upgrade to websocket. End with double CR+LF 135 | // The key is only for the server to prove it i websocket aware. 136 | // We know it is. 137 | 138 | // Generate a key (to convince server that the update is not random) 139 | $key=base64_encode(uniqid()); 140 | 141 | $header = "GET / HTTP/1.1\r\n" 142 | ."Host: $host\r\n" 143 | ."pragma: no-cache\r\n" 144 | ."Upgrade: WebSocket\r\n" 145 | ."Connection: Upgrade\r\n" 146 | ."Sec-WebSocket-Key: $key\r\n" 147 | ."Sec-WebSocket-Version: 13\r\n"; 148 | // Add extra headers 149 | foreach($headers as $h) $header.=$h."\r\n"; 150 | // Add end of header marker 151 | $header.="\r\n"; 152 | 153 | echo "
$header
"; 154 | // Connect to server 155 | $sp=fsockopen("127.0.0.1", 80, $errno, $errstr,1) 156 | or die("Unable to connect to event server: $errstr ($errno)"); 157 | // Set timeouts 158 | stream_set_timeout($sp,1,100); 159 | // stream_set_blocking($sp, false); 160 | //Request upgrade to websocket 161 | fwrite($sp,$header ) 162 | or die("Unable to send upgrade header to event server: $errstr ($errno)"); 163 | 164 | // Read response into an assotiative array of headers. Fails if upgrade to ws failes. 165 | $reaponse_header=fread($sp, 1024); 166 | 167 | // Verify that server upgraded to websocket 168 | 169 | // status code 101 indicates that the WebSocket handshake has completed. 170 | if(!strpos($reaponse_header," 101 ") || !strpos($reaponse_header,'Sec-WebSocket-Accept: ')) 171 | trigger_error("Event server did not accept to upgrade connection to websocket.".$reaponse_header, E_USER_ERROR); 172 | 173 | // The key we send is returned, concatenate with "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" 174 | // and then base64-encoded. one can verify if one feels the need... 175 | echo "Connected to websocket server
"; 176 | return $sp; 177 | } 178 | 179 | 180 | // Read websocket 181 | 182 | // Read to the end of the message and store the rest as the next message. 183 | 184 | /*Using hybi10 Decoding 185 | 186 | 0 1 2 3 187 | 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 188 | +-+-+-+-+-------+-+-------------+-------------------------------+ 189 | |F|R|R|R| opcode|M| Payload len | Extended payload length | 190 | |I|S|S|S| (4) |A| (7) | (16/63) | 191 | |N|V|V|V| |S| | (if payload len==126/127) | 192 | | |1|2|3| |K| | | 193 | +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - + 194 | | Extended payload length continued, if payload len == 127 | 195 | + - - - - - - - - - - - - - - - +-------------------------------+ 196 | | |Masking-key, if MASK set to 1 | 197 | +-------------------------------+-------------------------------+ 198 | | Masking-key (continued) | Payload Data | 199 | +-------------------------------- - - - - - - - - - - - - - - - + 200 | : Payload Data continued ... : 201 | + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + 202 | | Payload Data continued ... | 203 | +---------------------------------------------------------------+ 204 | 205 | https://tools.ietf.org/rfc/rfc6455.txt 206 | 207 | http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-10#section-4.2 208 | 209 | 210 | 211 | // Always sending binary messages 212 | // Always using masked data 213 | // This one is done with a maximum of 32 bit lenght of data 214 | // Application length are limited to 1GB to support small 32 bit system 215 | // This can easily be changed. 216 | 217 | 218 | // node_modules/ws crashes if sending unmasked data - test new wersion 219 | */ 220 | function websocket_write($sp, $data,$final=true){ 221 | // Assamble header: FINal 0x80 | Opcode 0x02 222 | $header=chr(($final?0x80:0) | 0x02); // 0x02 binary 223 | 224 | // Mask 0x80 | payload length (0-125) 225 | if(strlen($data)<126) $header.=chr(0x80 | strlen($data)); 226 | elseif (strlen($data)<0xFFFF) $header.=chr(0x80 | 126) . pack("n",strlen($data)); 227 | else $header.=chr(0x80 | 127) . pack("N",0) . pack("N",strlen($data)); 228 | 229 | // Add mask 230 | $mask=pack("N",rand(1,0x7FFFFFFF)); 231 | $header.=$mask; 232 | 233 | // Mask application data. 234 | for($i = 0; $i < strlen($data); $i++) 235 | $data[$i]=chr(ord($data[$i]) ^ ord($mask[$i % 4])); 236 | 237 | fwrite($sp,$header.$data); 238 | 239 | echo "Send:
"; 240 | hex_dump($header.$data,"
"); 241 | } 242 | 243 | 244 | function websocket_read($sp){ 245 | $data=""; 246 | 247 | do{ 248 | // Read header 249 | $header=fread($sp,2); 250 | if(!$header) trigger_error("Reading header from websocket failed", E_USER_ERROR); 251 | $opcode = ord($header[0]) & 0x0F; 252 | $final = ord($header[0]) & 0x80; 253 | $masked = ord($header[1]) & 0x80; 254 | $payload_len = ord($header[1]) & 0x7F; 255 | 256 | // Get payload length extensions 257 | $ext_len=0; 258 | if($payload_len>125) $ext_len+=2; 259 | if($payload_len>126) $ext_len+=6; 260 | if($ext_len){ 261 | $header=fread($sp,$ext_len); 262 | if(!$header) trigger_error("Reading header extension from websocket failed", E_USER_ERROR); 263 | // Set extented paylod length 264 | $payload_len=0; 265 | for($i=0;$i<$ext_len;$i++) 266 | $payload_len += ord($header[$i]) << ($ext_len-$i)*8; 267 | } 268 | 269 | // Get Mask key 270 | if($masked){ 271 | $mask=fread($sp,4); 272 | if(!$mask) trigger_error("Reading header mask from websocket failed", E_USER_ERROR); 273 | } 274 | 275 | // Get application data 276 | $data_len=$payload_len-$ext_len-($masked?4:0); 277 | $frame_data=fread($sp,$data_len); 278 | if(!$frame_data) trigger_error("Reading from websocket failed", E_USER_ERROR); 279 | 280 | // Unmask data 281 | if($masked) 282 | for ($i = 0; $i < $data_len; $i++) 283 | $data.= $frame_data[$i] ^ $mask[$i % 4]; 284 | else 285 | $data.= $frame_data; 286 | 287 | // If opcode 0 its a continuation of previous message. look for FINal 288 | // if opcode ping, send pong and continue to read 289 | 290 | }while(!$final); 291 | 292 | return $data; 293 | } 294 | 295 | 296 | 297 | ?> 298 | 299 | 300 | -------------------------------------------------------------------------------- /example/websocket_client.php: -------------------------------------------------------------------------------- 1 | = 0x20 && $i <= 0x7E) ? chr($i) : "."; 52 | } 53 | // Break up in chunks and translate 54 | $hex = str_split(bin2hex($data),32); 55 | $chars = str_split(strtr($data, $from, $to), 16); 56 | 57 | // display 58 | $offset = 0; 59 | foreach ($hex as $i => $line){ 60 | echo sprintf('%6X',$offset).' : '.implode(' ', str_split($line,2)); 61 | echo " [" . $chars[$i] . "]
\n"; 62 | $offset += 16; 63 | } 64 | } 65 | 66 | /*----------------------------------------------------------------------------*\ 67 | Open websocket (url[,error string pointer]) 68 | 69 | Make a connection to the websocket server. 70 | 71 | Return: on succes: a file pointer to the socket. 72 | \*----------------------------------------------------------------------------*/ 73 | function websocket_open($url="127.0.0.1",&$err=''){ 74 | // Generate a key for the server to prove it i websocket aware. 75 | $key=base64_encode(uniqid()); 76 | 77 | // Make a GET header for upgrade request to websocket. 78 | $query=parse_url($url); 79 | $header="GET " 80 | .(isset($query['path']) ? "$query[path]" : "") 81 | .(isset($query['query']) ? "?$query[query]" : "") 82 | ." HTTP/1.1\r\nHost: " 83 | .(isset($query['scheme']) ? "$query[scheme]://" : "") 84 | .(isset($query['host']) ? "$query[host]" : "127.0.0.1") 85 | .(isset($query['port']) ? ":$query[port]" : "") 86 | ."\r\npragma: no-cache\r\n" 87 | ."cache-control: no-cache\r\n" 88 | ."Upgrade: WebSocket\r\n" 89 | ."Connection: Upgrade\r\n" 90 | ."Sec-WebSocket-Key: $key\r\n" 91 | ."Sec-WebSocket-Version: 13\r\n" 92 | .(isset($_SERVER['HTTP_COOKIE']) ? "cookie: $_SERVER[HTTP_COOKIE]\r\n": "") 93 | ."\r\n"; 94 | 95 | // Connect to server 96 | do{ 97 | $sp=fsockopen((isset($query['scheme']) ? "$query[scheme]://" : "") 98 | .$query['host'],$query['port'], $errno, $errstr,1); 99 | if(!$sp) break; 100 | 101 | // Set timeouts 102 | stream_set_timeout($sp,3,100); 103 | // stream_set_blocking($sp, false); 104 | 105 | //Request upgrade to websocket 106 | $len=fwrite($sp,$header); 107 | if(!$len) break; 108 | 109 | // Read response into an assotiative array of headers. Fails if upgrade to ws failes. 110 | $reaponse_header=fread($sp, 1024); 111 | }while(false); 112 | 113 | // Errors 114 | if(!$sp) 115 | $err="Unable to connect to event server: $errstr ($errno)"; 116 | elseif(!$len) 117 | $err="Unable to send upgrade header to event server: $errstr ($errno)"; 118 | elseif(!strpos($reaponse_header," 101 ") 119 | || !strpos($reaponse_header,'Sec-WebSocket-Accept: ')) 120 | $err="Event server did not accept to upgrade connection to websocket." 121 | .$reaponse_header; 122 | 123 | if($err){ 124 | @fclose($sp); 125 | return false; 126 | } 127 | return $sp; 128 | } 129 | 130 | /*----------------------------------------------------------------------------*\ 131 | Write to websocket (, [,] ) 132 | 133 | Protocol options are fixed to: 134 | - Sending data in binary mode 135 | - Always using masked data 136 | 137 | return succes 138 | \*----------------------------------------------------------------------------*/ 139 | function websocket_write($sp, $data,$final=true){ 140 | // Assamble header: FINal 0x80 | Opcode 0x02 141 | $header=chr(($final?0x80:0) | 0x02); // 0x02 binary 142 | 143 | // Mask 0x80 | payload length (0-125) 144 | if(strlen($data)<126) $header.=chr(0x80 | strlen($data)); 145 | elseif (strlen($data)<0xFFFF) $header.=chr(0x80 | 126) . pack("n",strlen($data)); 146 | elseif(PHP_INT_SIZE>4) // 64 bit 147 | $header.=chr(0x80 | 127) . pack("Q",strlen($data)); 148 | else // 32 bit (pack Q dosen't work) 149 | $header.=chr(0x80 | 127) . pack("N",0) . pack("N",strlen($data)); 150 | 151 | // Make a random mask 152 | $mask=pack("N",rand(1,0x7FFFFFFF)); 153 | $header.=$mask; 154 | 155 | // Apply mask to data 156 | for($i = 0; $i < strlen($data); $i++) 157 | $data[$i]=chr(ord($data[$i]) ^ ord($mask[$i % 4])); 158 | 159 | return fwrite($sp,$header.$data); 160 | } 161 | 162 | /*----------------------------------------------------------------------------*\ 163 | Read websocket( [[,], error string pointer]) 164 | 165 | if wait_for_end is set, all messages send from the server are buffered and 166 | returned as one coherent string, when the final message fragment are recieved. 167 | Otherwise each message fragment are returned. 168 | 169 | Pings are answered silently 170 | \*----------------------------------------------------------------------------*/ 171 | function websocket_read($sp,$wait_for_end=true,&$err=''){ 172 | $out_buffer=""; 173 | 174 | do{ 175 | // Read header 176 | $header=fread($sp,2); 177 | if(!$header) trigger_error("Reading header from websocket failed", E_USER_ERROR); 178 | $opcode = ord($header[0]) & 0x0F; 179 | $final = ord($header[0]) & 0x80; 180 | $masked = ord($header[1]) & 0x80; 181 | $payload_len = ord($header[1]) & 0x7F; 182 | 183 | // Get payload length extensions 184 | $ext_len=0; 185 | if($payload_len>125) $ext_len+=2; 186 | if($payload_len>126) $ext_len+=6; 187 | if($ext_len){ 188 | $ext=fread($sp,$ext_len); 189 | if(!$ext) trigger_error("Reading header extension from websocket failed", E_USER_ERROR); 190 | 191 | // Set extented paylod length 192 | $payload_len=$ext_len; 193 | for($i=0;$i<$ext_len;$i++) 194 | $payload_len += ord($ext[$i]) << ($ext_len-$i-1)*8; 195 | } 196 | 197 | // Get Mask key 198 | if($masked){ 199 | $mask=fread($sp,4); 200 | if(!$mask) trigger_error("Reading header mask from websocket failed", E_USER_ERROR); 201 | } 202 | 203 | // Get application data 204 | $data_len=$payload_len-$ext_len-($masked?4:0); 205 | $frame_data=fread($sp,$data_len); 206 | if(!$frame_data) trigger_error("Reading from websocket failed", E_USER_ERROR); 207 | 208 | // if opcode ping, reuse headers to send a pong and continue to read 209 | if($opcode==9){ 210 | // Assamble header: FINal 0x80 | Opcode 0x02 211 | $header[0]=chr(($final?0x80:0) | 0x0A); // 0x0A Pong 212 | fwrite($sp,$header.$ext.$mask.$frame_data); 213 | 214 | // Recieve and unmask data 215 | }elseif($opcode<9){ 216 | $data=""; 217 | if($masked) 218 | for ($i = 0; $i < $data_len; $i++) 219 | $data.= $frame_data[$i] ^ $mask[$i % 4]; 220 | else 221 | $data.= $frame_data; 222 | $out_buffer.=$data; 223 | } 224 | 225 | // wait for Final 226 | }while($wait_for_end && !$final); 227 | 228 | return $out_buffer; 229 | } 230 | ?> 231 | -------------------------------------------------------------------------------- /example/ws_request.php: -------------------------------------------------------------------------------- 1 | Output from ".__FILE__."\n".print_r($GLOBALS,true).""; 6 | ?> 7 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sphp", 3 | "version": "0.6.3", 4 | "description": "A snappy PHP execution module / middleware", 5 | "main": "sphp.js", 6 | "runkitExampleFilename": "browser.js", 7 | "repository": { 8 | "type": "git", 9 | "url": "git+https://github.com/paragi/sphp.git" 10 | }, 11 | "keywords": [ 12 | "snappy", 13 | "snap", 14 | "execute", 15 | "script", 16 | "cgi", 17 | "session", 18 | "websocket", 19 | "fast", 20 | "php" 21 | ], 22 | "author": "Paragi Aps, Simon Rigét 2013", 23 | "license": "MIT", 24 | "bugs": { 25 | "url": "https://github.com/paragi/sphp/issues" 26 | }, 27 | "homepage": "https://github.com/paragi/sphp#readme", 28 | "devDependencies": { 29 | "express": "^4", 30 | "express-session": "^1", 31 | "body-parser": "^1", 32 | "ws": "^3", 33 | "mocha": "^4.1.0", 34 | "chai": "^4.1.2", 35 | "request": "^2.69.0" 36 | }, 37 | "peerDependencies": {}, 38 | "directories": { 39 | "example": "example", 40 | "test": "test" 41 | }, 42 | "scripts": { 43 | "test": "node node_modules/mocha/bin/mocha --exit" 44 | }, 45 | "dependencies": { 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /php.ini: -------------------------------------------------------------------------------- 1 | [PHP] 2 | 3 | ;;;;;;;;;;;;;;;;;;; 4 | ; About php.ini ; 5 | ;;;;;;;;;;;;;;;;;;; 6 | ; PHP's initialization file, generally called php.ini, is responsible for 7 | ; configuring many of the aspects of PHP's behavior. 8 | 9 | ; PHP attempts to find and load this configuration from a number of locations. 10 | ; The following is a summary of its search order: 11 | ; 1. SAPI module specific location. 12 | ; 2. The PHPRC environment variable. (As of PHP 5.2.0) 13 | ; 3. A number of predefined registry keys on Windows (As of PHP 5.2.0) 14 | ; 4. Current working directory (except CLI) 15 | ; 5. The web server's directory (for SAPI modules), or directory of PHP 16 | ; (otherwise in Windows) 17 | ; 6. The directory from the --with-config-file-path compile time option, or the 18 | ; Windows directory (C:\windows or C:\winnt) 19 | ; See the PHP docs for more specific information. 20 | ; http://php.net/configuration.file 21 | 22 | ; The syntax of the file is extremely simple. Whitespace and lines 23 | ; beginning with a semicolon are silently ignored (as you probably guessed). 24 | ; Section headers (e.g. [Foo]) are also silently ignored, even though 25 | ; they might mean something in the future. 26 | 27 | ; Directives following the section heading [PATH=/www/mysite] only 28 | ; apply to PHP files in the /www/mysite directory. Directives 29 | ; following the section heading [HOST=www.example.com] only apply to 30 | ; PHP files served from www.example.com. Directives set in these 31 | ; special sections cannot be overridden by user-defined INI files or 32 | ; at runtime. Currently, [PATH=] and [HOST=] sections only work under 33 | ; CGI/FastCGI. 34 | ; http://php.net/ini.sections 35 | 36 | ; Directives are specified using the following syntax: 37 | ; directive = value 38 | ; Directive names are *case sensitive* - foo=bar is different from FOO=bar. 39 | ; Directives are variables used to configure PHP or PHP extensions. 40 | ; There is no name validation. If PHP can't find an expected 41 | ; directive because it is not set or is mistyped, a default value will be used. 42 | 43 | ; The value can be a string, a number, a PHP constant (e.g. E_ALL or M_PI), one 44 | ; of the INI constants (On, Off, True, False, Yes, No and None) or an expression 45 | ; (e.g. E_ALL & ~E_NOTICE), a quoted string ("bar"), or a reference to a 46 | ; previously set variable or directive (e.g. ${foo}) 47 | 48 | ; Expressions in the INI file are limited to bitwise operators and parentheses: 49 | ; | bitwise OR 50 | ; ^ bitwise XOR 51 | ; & bitwise AND 52 | ; ~ bitwise NOT 53 | ; ! boolean NOT 54 | 55 | ; Boolean flags can be turned on using the values 1, On, True or Yes. 56 | ; They can be turned off using the values 0, Off, False or No. 57 | 58 | ; An empty string can be denoted by simply not writing anything after the equal 59 | ; sign, or by using the None keyword: 60 | 61 | ; foo = ; sets foo to an empty string 62 | ; foo = None ; sets foo to an empty string 63 | ; foo = "None" ; sets foo to the string 'None' 64 | 65 | ; If you use constants in your value, and these constants belong to a 66 | ; dynamically loaded extension (either a PHP extension or a Zend extension), 67 | ; you may only use these constants *after* the line that loads the extension. 68 | 69 | ;;;;;;;;;;;;;;;;;;; 70 | ; About this file ; 71 | ;;;;;;;;;;;;;;;;;;; 72 | ; PHP comes packaged with two INI files. One that is recommended to be used 73 | ; in production environments and one that is recommended to be used in 74 | ; development environments. 75 | 76 | ; php.ini-production contains settings which hold security, performance and 77 | ; best practices at its core. But please be aware, these settings may break 78 | ; compatibility with older or less security conscience applications. We 79 | ; recommending using the production ini in production and testing environments. 80 | 81 | ; php.ini-development is very similar to its production variant, except it is 82 | ; much more verbose when it comes to errors. We recommend using the 83 | ; development version only in development environments, as errors shown to 84 | ; application users can inadvertently leak otherwise secure information. 85 | 86 | ; This is php.ini-production INI file. 87 | 88 | ;;;;;;;;;;;;;;;;;;; 89 | ; Quick Reference ; 90 | ;;;;;;;;;;;;;;;;;;; 91 | ; The following are all the settings which are different in either the production 92 | ; or development versions of the INIs with respect to PHP's default behavior. 93 | ; Please see the actual settings later in the document for more details as to why 94 | ; we recommend these changes in PHP's behavior. 95 | 96 | display_errors=on 97 | ; Default Value: On 98 | ; Development Value: On 99 | ; Production Value: Off 100 | 101 | display_startup_errors=on 102 | ; Default Value: Off 103 | ; Development Value: On 104 | ; Production Value: Off 105 | 106 | ; Set to serious only 107 | error_reporting = E_ALL 108 | ; Default Value: E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED 109 | ; Development Value: E_ALL 110 | ; Production Value: E_ALL & ~E_DEPRECATED & ~E_STRICT 111 | 112 | ; html_errors 113 | ; Default Value: On 114 | ; Development Value: On 115 | ; Production value: On 116 | 117 | ; log_errors 118 | ; Default Value: Off 119 | ; Development Value: On 120 | ; Production Value: On 121 | 122 | max_input_time=-1 123 | ; Default Value: -1 (Unlimited) 124 | ; Development Value: 60 (60 seconds) 125 | ; Production Value: 60 (60 seconds) 126 | 127 | ; output_buffering 128 | ; Default Value: Off 129 | ; Development Value: 4096 130 | ; Production Value: 4096 131 | 132 | ; register_argc_argv 133 | ; Default Value: On 134 | ; Development Value: Off 135 | ; Production Value: Off 136 | 137 | ; request_order 138 | ; Default Value: None 139 | ; Development Value: "GP" 140 | ; Production Value: "GP" 141 | 142 | ; session.gc_divisor 143 | ; Default Value: 100 144 | ; Development Value: 1000 145 | ; Production Value: 1000 146 | 147 | ; session.hash_bits_per_character 148 | ; Default Value: 4 149 | ; Development Value: 5 150 | ; Production Value: 5 151 | 152 | ; short_open_tag 153 | ; Default Value: On 154 | ; Development Value: Off 155 | ; Production Value: Off 156 | 157 | track_errors=on 158 | ; Default Value: Off 159 | ; Development Value: On 160 | ; Production Value: Off 161 | 162 | ; url_rewriter.tags 163 | ; Default Value: "a=href,area=href,frame=src,form=,fieldset=" 164 | ; Development Value: "a=href,area=href,frame=src,input=src,form=fakeentry" 165 | ; Production Value: "a=href,area=href,frame=src,input=src,form=fakeentry" 166 | 167 | variables_order = GPCS 168 | ; Default Value: "EGPCS" 169 | ; Development Value: "GPCS" 170 | ; Production Value: "GPCS" 171 | 172 | ;;;;;;;;;;;;;;;;;;;; 173 | ; php.ini Options ; 174 | ;;;;;;;;;;;;;;;;;;;; 175 | ; Name for user-defined php.ini (.htaccess) files. Default is ".user.ini" 176 | ;user_ini.filename = ".user.ini" 177 | 178 | ; To disable this feature set this option to empty value 179 | user_ini.filename = 180 | 181 | ; TTL for user-defined php.ini files (time-to-live) in seconds. Default is 300 seconds (5 minutes) 182 | user_ini.cache_ttl = -1 183 | 184 | ;;;;;;;;;;;;;;;;;;;; 185 | ; Language Options ; 186 | ;;;;;;;;;;;;;;;;;;;; 187 | 188 | ; Enable the PHP scripting language engine under Apache. 189 | ; http://php.net/engine 190 | engine = Off 191 | 192 | ; This directive determines whether or not PHP will recognize code between 193 | ; tags as PHP source which should be processed as such. It is 194 | ; generally recommended that should be used and that this feature 195 | ; should be disabled, as enabling it may result in issues when generating XML 196 | ; documents, however this remains supported for backward compatibility reasons. 197 | ; Note that this directive does not control the tags. 206 | ; http://php.net/asp-tags 207 | asp_tags = Off 208 | 209 | ; The number of significant digits displayed in floating point numbers. 210 | ; http://php.net/precision 211 | precision = 14 212 | 213 | ; Output buffering is a mechanism for controlling how much output data 214 | ; (excluding headers and cookies) PHP should keep internally before pushing that 215 | ; data to the client. If your application's output exceeds this setting, PHP 216 | ; will send that data in chunks of roughly the size you specify. 217 | ; Turning on this setting and managing its maximum buffer size can yield some 218 | ; interesting side-effects depending on your application and web server. 219 | ; You may be able to send headers and cookies after you've already sent output 220 | ; through print or echo. You also may see performance benefits if your server is 221 | ; emitting less packets due to buffered output versus PHP streaming the output 222 | ; as it gets it. On production servers, 4096 bytes is a good setting for performance 223 | ; reasons. 224 | ; Note: Output buffering can also be controlled via Output Buffering Control 225 | ; functions. 226 | ; Possible Values: 227 | ; On = Enabled and buffer is unlimited. (Use with caution) 228 | ; Off = Disabled 229 | ; Integer = Enables the buffer and sets its maximum size in bytes. 230 | ; Note: This directive is hardcoded to Off for the CLI SAPI 231 | ; Default Value: Off 232 | ; Development Value: 4096 233 | ; Production Value: 4096 234 | ; http://php.net/output-buffering 235 | output_buffering = Off 236 | 237 | ; You can redirect all of the output of your scripts to a function. For 238 | ; example, if you set output_handler to "mb_output_handler", character 239 | ; encoding will be transparently converted to the specified encoding. 240 | ; Setting any output handler automatically turns on output buffering. 241 | ; Note: People who wrote portable scripts should not depend on this ini 242 | ; directive. Instead, explicitly set the output handler using ob_start(). 243 | ; Using this ini directive may cause problems unless you know what script 244 | ; is doing. 245 | ; Note: You cannot use both "mb_output_handler" with "ob_iconv_handler" 246 | ; and you cannot use both "ob_gzhandler" and "zlib.output_compression". 247 | ; Note: output_handler must be empty if this is set 'On' !!!! 248 | ; Instead you must use zlib.output_handler. 249 | ; http://php.net/output-handler 250 | ;output_handler = 251 | 252 | ; Transparent output compression using the zlib library 253 | ; Valid values for this option are 'off', 'on', or a specific buffer size 254 | ; to be used for compression (default is 4KB) 255 | ; Note: Resulting chunk size may vary due to nature of compression. PHP 256 | ; outputs chunks that are few hundreds bytes each as a result of 257 | ; compression. If you prefer a larger chunk size for better 258 | ; performance, enable output_buffering in addition. 259 | ; Note: You need to use zlib.output_handler instead of the standard 260 | ; output_handler, or otherwise the output will be corrupted. 261 | ; http://php.net/zlib.output-compression 262 | zlib.output_compression = Off 263 | 264 | ; http://php.net/zlib.output-compression-level 265 | ;zlib.output_compression_level = -1 266 | 267 | ; You cannot specify additional output handlers if zlib.output_compression 268 | ; is activated here. This setting does the same as output_handler but in 269 | ; a different order. 270 | ; http://php.net/zlib.output-handler 271 | ;zlib.output_handler = 272 | 273 | ; Implicit flush tells PHP to tell the output layer to flush itself 274 | ; automatically after every output block. This is equivalent to calling the 275 | ; PHP function flush() after each and every call to print() or echo() and each 276 | ; and every HTML block. Turning this option on has serious performance 277 | ; implications and is generally recommended for debugging purposes only. 278 | ; http://php.net/implicit-flush 279 | ; Note: This directive is hardcoded to On for the CLI SAPI 280 | implicit_flush = Off 281 | 282 | ; The unserialize callback function will be called (with the undefined class' 283 | ; name as parameter), if the unserializer finds an undefined class 284 | ; which should be instantiated. A warning appears if the specified function is 285 | ; not defined, or if the function doesn't include/implement the missing class. 286 | ; So only set this entry, if you really want to implement such a 287 | ; callback-function. 288 | unserialize_callback_func = 289 | 290 | ; When floats & doubles are serialized store serialize_precision significant 291 | ; digits after the floating point. The default value ensures that when floats 292 | ; are decoded with unserialize, the data will remain the same. 293 | serialize_precision = 17 294 | 295 | ; open_basedir, if set, limits all file operations to the defined directory 296 | ; and below. This directive makes most sense if used in a per-directory 297 | ; or per-virtualhost web server configuration file. 298 | ; http://php.net/open-basedir 299 | open_basedir = ./ 300 | 301 | ; This directive allows you to disable certain functions for security reasons. 302 | ; It receives a comma-delimited list of function names. 303 | ; http://php.net/disable-functions 304 | ;disable_functions = pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority, 305 | 306 | ; This directive allows you to disable certain classes for security reasons. 307 | ; It receives a comma-delimited list of class names. 308 | ; http://php.net/disable-classes 309 | disable_classes = 310 | 311 | ; Colors for Syntax Highlighting mode. Anything that's acceptable in 312 | ; would work. 313 | ; http://php.net/syntax-highlighting 314 | highlight.string = #DD0000 315 | highlight.comment = #FF9900 316 | highlight.keyword = #007700 317 | highlight.default = #0000BB 318 | highlight.html = #000000 319 | 320 | ; If enabled, the request will be allowed to complete even if the user aborts 321 | ; the request. Consider enabling it if executing long requests, which may end up 322 | ; being interrupted by the user or a browser timing out. PHP's default behavior 323 | ; is to disable this feature. 324 | ; http://php.net/ignore-user-abort 325 | ;ignore_user_abort = On 326 | 327 | ; Determines the size of the realpath cache to be used by PHP. This value should 328 | ; be increased on systems where PHP opens many files to reflect the quantity of 329 | ; the file operations performed. 330 | ; http://php.net/realpath-cache-size 331 | ;realpath_cache_size = 16k 332 | 333 | ; Duration of time, in seconds for which to cache realpath information for a given 334 | ; file or directory. For systems with rarely changing files, consider increasing this 335 | ; value. 336 | ; http://php.net/realpath-cache-ttl 337 | realpath_cache_ttl = -1 338 | 339 | ; Enables or disables the circular reference collector. 340 | ; http://php.net/zend.enable-gc 341 | zend.enable_gc = On 342 | 343 | ; If enabled, scripts may be written in encodings that are incompatible with 344 | ; the scanner. CP936, Big5, CP949 and Shift_JIS are the examples of such 345 | ; encodings. To use this feature, mbstring extension must be enabled. 346 | ; Default: Off 347 | ;zend.multibyte = Off 348 | 349 | ; Allows to set the default encoding for the scripts. This value will be used 350 | ; unless "declare(encoding=...)" directive appears at the top of the script. 351 | ; Only affects if zend.multibyte is set. 352 | ; Default: "" 353 | ;zend.script_encoding = 354 | 355 | ;;;;;;;;;;;;;;;;; 356 | ; Miscellaneous ; 357 | ;;;;;;;;;;;;;;;;; 358 | 359 | ; Decides whether PHP may expose the fact that it is installed on the server 360 | ; (e.g. by adding its signature to the Web server header). It is no security 361 | ; threat in any way, but it makes it possible to determine whether you use PHP 362 | ; on your server or not. 363 | ; http://php.net/expose-php 364 | expose_php = Off 365 | 366 | ;;;;;;;;;;;;;;;;;;; 367 | ; Resource Limits ; 368 | ;;;;;;;;;;;;;;;;;;; 369 | 370 | ; Maximum execution time of each script, in seconds 371 | ; http://php.net/max-execution-time 372 | ; Note: This directive is hardcoded to 0 for the CLI SAPI 373 | max_execution_time = 60 374 | 375 | ; Maximum amount of time each script may spend parsing request data. It's a good 376 | ; idea to limit this time on productions servers in order to eliminate unexpectedly 377 | ; long running scripts. 378 | ; Note: This directive is hardcoded to -1 for the CLI SAPI 379 | ; Default Value: -1 (Unlimited) 380 | ; Development Value: 60 (60 seconds) 381 | ; Production Value: 60 (60 seconds) 382 | ; http://php.net/max-input-time 383 | max_input_time = 60 384 | 385 | ; Maximum input variable nesting level 386 | ; http://php.net/max-input-nesting-level 387 | ;max_input_nesting_level = 64 388 | 389 | ; How many GET/POST/COOKIE input variables may be accepted 390 | ; max_input_vars = 1000 391 | 392 | ; Maximum amount of memory a script may consume (128MB) 393 | ; http://php.net/memory-limit 394 | memory_limit = 128M 395 | 396 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 397 | ; Error handling and logging ; 398 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 399 | 400 | ; This directive informs PHP of which errors, warnings and notices you would like 401 | ; it to take action for. The recommended way of setting values for this 402 | ; directive is through the use of the error level constants and bitwise 403 | ; operators. The error level constants are below here for convenience as well as 404 | ; some common settings and their meanings. 405 | ; By default, PHP is set to take action on all errors, notices and warnings EXCEPT 406 | ; those related to E_NOTICE and E_STRICT, which together cover best practices and 407 | ; recommended coding standards in PHP. For performance reasons, this is the 408 | ; recommend error reporting setting. Your production server shouldn't be wasting 409 | ; resources complaining about best practices and coding standards. That's what 410 | ; development servers and development settings are for. 411 | ; Note: The php.ini-development file has this setting as E_ALL. This 412 | ; means it pretty much reports everything which is exactly what you want during 413 | ; development and early testing. 414 | ; 415 | ; Error Level Constants: 416 | ; E_ALL - All errors and warnings (includes E_STRICT as of PHP 5.4.0) 417 | ; E_ERROR - fatal run-time errors 418 | ; E_RECOVERABLE_ERROR - almost fatal run-time errors 419 | ; E_WARNING - run-time warnings (non-fatal errors) 420 | ; E_PARSE - compile-time parse errors 421 | ; E_NOTICE - run-time notices (these are warnings which often result 422 | ; from a bug in your code, but it's possible that it was 423 | ; intentional (e.g., using an uninitialized variable and 424 | ; relying on the fact it is automatically initialized to an 425 | ; empty string) 426 | ; E_STRICT - run-time notices, enable to have PHP suggest changes 427 | ; to your code which will ensure the best interoperability 428 | ; and forward compatibility of your code 429 | ; E_CORE_ERROR - fatal errors that occur during PHP's initial startup 430 | ; E_CORE_WARNING - warnings (non-fatal errors) that occur during PHP's 431 | ; initial startup 432 | ; E_COMPILE_ERROR - fatal compile-time errors 433 | ; E_COMPILE_WARNING - compile-time warnings (non-fatal errors) 434 | ; E_USER_ERROR - user-generated error message 435 | ; E_USER_WARNING - user-generated warning message 436 | ; E_USER_NOTICE - user-generated notice message 437 | ; E_DEPRECATED - warn about code that will not work in future versions 438 | ; of PHP 439 | ; E_USER_DEPRECATED - user-generated deprecation warnings 440 | ; 441 | ; Common Values: 442 | ; E_ALL (Show all errors, warnings and notices including coding standards.) 443 | ; E_ALL & ~E_NOTICE (Show all errors, except for notices) 444 | ; E_ALL & ~E_NOTICE & ~E_STRICT (Show all errors, except for notices and coding standards warnings.) 445 | ; E_COMPILE_ERROR|E_RECOVERABLE_ERROR|E_ERROR|E_CORE_ERROR (Show only errors) 446 | ; Default Value: E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED 447 | ; Development Value: E_ALL 448 | ; Production Value: E_ALL & ~E_DEPRECATED & ~E_STRICT 449 | ; http://php.net/error-reporting 450 | error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT 451 | 452 | ; This directive controls whether or not and where PHP will output errors, 453 | ; notices and warnings too. Error output is very useful during development, but 454 | ; it could be very dangerous in production environments. Depending on the code 455 | ; which is triggering the error, sensitive information could potentially leak 456 | ; out of your application such as database usernames and passwords or worse. 457 | ; For production environments, we recommend logging errors rather than 458 | ; sending them to STDOUT. 459 | ; Possible Values: 460 | ; Off = Do not display any errors 461 | ; stderr = Display errors to STDERR (affects only CGI/CLI binaries!) 462 | ; On or stdout = Display errors to STDOUT 463 | ; Default Value: On 464 | ; Development Value: On 465 | ; Production Value: Off 466 | ; http://php.net/display-errors 467 | display_errors = On 468 | 469 | ; The display of errors which occur during PHP's startup sequence are handled 470 | ; separately from display_errors. PHP's default behavior is to suppress those 471 | ; errors from clients. Turning the display of startup errors on can be useful in 472 | ; debugging configuration problems. We strongly recommend you 473 | ; set this to 'off' for production servers. 474 | ; Default Value: Off 475 | ; Development Value: On 476 | ; Production Value: Off 477 | ; http://php.net/display-startup-errors 478 | display_startup_errors = Off 479 | 480 | ; Besides displaying errors, PHP can also log errors to locations such as a 481 | ; server-specific log, STDERR, or a location specified by the error_log 482 | ; directive found below. While errors should not be displayed on productions 483 | ; servers they should still be monitored and logging is a great way to do that. 484 | ; Default Value: Off 485 | ; Development Value: On 486 | ; Production Value: On 487 | ; http://php.net/log-errors 488 | log_errors = Off 489 | 490 | ; Set maximum length of log_errors. In error_log information about the source is 491 | ; added. The default is 1024 and 0 allows to not apply any maximum length at all. 492 | ; http://php.net/log-errors-max-len 493 | log_errors_max_len = 1024 494 | 495 | ; Do not log repeated messages. Repeated errors must occur in same file on same 496 | ; line unless ignore_repeated_source is set true. 497 | ; http://php.net/ignore-repeated-errors 498 | ignore_repeated_errors = Off 499 | 500 | ; Ignore source of message when ignoring repeated messages. When this setting 501 | ; is On you will not log errors with repeated messages from different files or 502 | ; source lines. 503 | ; http://php.net/ignore-repeated-source 504 | ignore_repeated_source = Off 505 | 506 | ; If this parameter is set to Off, then memory leaks will not be shown (on 507 | ; stdout or in the log). This has only effect in a debug compile, and if 508 | ; error reporting includes E_WARNING in the allowed list 509 | ; http://php.net/report-memleaks 510 | report_memleaks = On 511 | 512 | ; This setting is on by default. 513 | ;report_zend_debug = 0 514 | 515 | ; Store the last error/warning message in $php_errormsg (boolean). Setting this value 516 | ; to On can assist in debugging and is appropriate for development servers. It should 517 | ; however be disabled on production servers. 518 | ; Default Value: Off 519 | ; Development Value: On 520 | ; Production Value: Off 521 | ; http://php.net/track-errors 522 | track_errors = On 523 | 524 | ; Turn off normal error reporting and emit XML-RPC error XML 525 | ; http://php.net/xmlrpc-errors 526 | ;xmlrpc_errors = 0 527 | 528 | ; An XML-RPC faultCode 529 | ;xmlrpc_error_number = 0 530 | 531 | ; When PHP displays or logs an error, it has the capability of formatting the 532 | ; error message as HTML for easier reading. This directive controls whether 533 | ; the error message is formatted as HTML or not. 534 | ; Note: This directive is hardcoded to Off for the CLI SAPI 535 | ; Default Value: On 536 | ; Development Value: On 537 | ; Production value: On 538 | ; http://php.net/html-errors 539 | html_errors = On 540 | 541 | ; If html_errors is set to On *and* docref_root is not empty, then PHP 542 | ; produces clickable error messages that direct to a page describing the error 543 | ; or function causing the error in detail. 544 | ; You can download a copy of the PHP manual from http://php.net/docs 545 | ; and change docref_root to the base URL of your local copy including the 546 | ; leading '/'. You must also specify the file extension being used including 547 | ; the dot. PHP's default behavior is to leave these settings empty, in which 548 | ; case no links to documentation are generated. 549 | ; Note: Never use this feature for production boxes. 550 | ; http://php.net/docref-root 551 | ; Examples 552 | ;docref_root = "/phpmanual/" 553 | 554 | ; http://php.net/docref-ext 555 | ;docref_ext = .html 556 | 557 | ; String to output before an error message. PHP's default behavior is to leave 558 | ; this setting blank. 559 | ; http://php.net/error-prepend-string 560 | ; Example: 561 | ;error_prepend_string = "" 562 | 563 | ; String to output after an error message. PHP's default behavior is to leave 564 | ; this setting blank. 565 | ; http://php.net/error-append-string 566 | ; Example: 567 | ;error_append_string = "" 568 | 569 | ; Log errors to specified file. PHP's default behavior is to leave this value 570 | ; empty. 571 | ; http://php.net/error-log 572 | ; Example: 573 | ;error_log = php_errors.log 574 | ; Log errors to syslog (Event Log on Windows). 575 | ;error_log = syslog 576 | 577 | ;windows.show_crt_warning 578 | ; Default value: 0 579 | ; Development value: 0 580 | ; Production value: 0 581 | 582 | ;;;;;;;;;;;;;;;;; 583 | ; Data Handling ; 584 | ;;;;;;;;;;;;;;;;; 585 | 586 | ; The separator used in PHP generated URLs to separate arguments. 587 | ; PHP's default setting is "&". 588 | ; http://php.net/arg-separator.output 589 | ; Example: 590 | ;arg_separator.output = "&" 591 | 592 | ; List of separator(s) used by PHP to parse input URLs into variables. 593 | ; PHP's default setting is "&". 594 | ; NOTE: Every character in this directive is considered as separator! 595 | ; http://php.net/arg-separator.input 596 | ; Example: 597 | ;arg_separator.input = ";&" 598 | 599 | ; This directive determines which super global arrays are registered when PHP 600 | ; starts up. G,P,C,E & S are abbreviations for the following respective super 601 | ; globals: GET, POST, COOKIE, ENV and SERVER. There is a performance penalty 602 | ; paid for the registration of these arrays and because ENV is not as commonly 603 | ; used as the others, ENV is not recommended on productions servers. You 604 | ; can still get access to the environment variables through getenv() should you 605 | ; need to. 606 | ; Default Value: "EGPCS" 607 | ; Development Value: "GPCS" 608 | ; Production Value: "GPCS"; 609 | ; http://php.net/variables-order 610 | variables_order = "GPCS" 611 | 612 | ; This directive determines which super global data (G,P & C) should be 613 | ; registered into the super global array REQUEST. If so, it also determines 614 | ; the order in which that data is registered. The values for this directive 615 | ; are specified in the same manner as the variables_order directive, 616 | ; EXCEPT one. Leaving this value empty will cause PHP to use the value set 617 | ; in the variables_order directive. It does not mean it will leave the super 618 | ; globals array REQUEST empty. 619 | ; Default Value: None 620 | ; Development Value: "GP" 621 | ; Production Value: "GP" 622 | ; http://php.net/request-order 623 | request_order = "GP" 624 | 625 | ; This directive determines whether PHP registers $argv & $argc each time it 626 | ; runs. $argv contains an array of all the arguments passed to PHP when a script 627 | ; is invoked. $argc contains an integer representing the number of arguments 628 | ; that were passed when the script was invoked. These arrays are extremely 629 | ; useful when running scripts from the command line. When this directive is 630 | ; enabled, registering these variables consumes CPU cycles and memory each time 631 | ; a script is executed. For performance reasons, this feature should be disabled 632 | ; on production servers. 633 | ; Note: This directive is hardcoded to On for the CLI SAPI 634 | ; Default Value: On 635 | ; Development Value: Off 636 | ; Production Value: Off 637 | ; http://php.net/register-argc-argv 638 | register_argc_argv = Off 639 | 640 | ; When enabled, the ENV, REQUEST and SERVER variables are created when they're 641 | ; first used (Just In Time) instead of when the script starts. If these 642 | ; variables are not used within a script, having this directive on will result 643 | ; in a performance gain. The PHP directive register_argc_argv must be disabled 644 | ; for this directive to have any affect. 645 | ; http://php.net/auto-globals-jit 646 | auto_globals_jit = On 647 | 648 | ; Whether PHP will read the POST data. 649 | ; This option is enabled by default. 650 | ; Most likely, you won't want to disable this option globally. It causes $_POST 651 | ; and $_FILES to always be empty; the only way you will be able to read the 652 | ; POST data will be through the php://input stream wrapper. This can be useful 653 | ; to proxy requests or to process the POST data in a memory efficient fashion. 654 | ; http://php.net/enable-post-data-reading 655 | ;enable_post_data_reading = Off 656 | 657 | ; Maximum size of POST data that PHP will accept. 658 | ; Its value may be 0 to disable the limit. It is ignored if POST data reading 659 | ; is disabled through enable_post_data_reading. 660 | ; http://php.net/post-max-size 661 | post_max_size = 8M 662 | 663 | ; Automatically add files before PHP document. 664 | ; http://php.net/auto-prepend-file 665 | auto_prepend_file = 666 | 667 | ; Automatically add files after PHP document. 668 | ; http://php.net/auto-append-file 669 | auto_append_file = 670 | 671 | ; By default, PHP will output a character encoding using 672 | ; the Content-type: header. To disable sending of the charset, simply 673 | ; set it to be empty. 674 | ; 675 | ; PHP's built-in default is text/html 676 | ; http://php.net/default-mimetype 677 | default_mimetype = "text/html" 678 | 679 | ; PHP's default character set is set to UTF-8. 680 | ; http://php.net/default-charset 681 | default_charset = "UTF-8" 682 | 683 | ; PHP internal character encoding is set to empty. 684 | ; If empty, default_charset is used. 685 | ; http://php.net/internal-encoding 686 | ;internal_encoding = 687 | 688 | ; PHP input character encoding is set to empty. 689 | ; If empty, default_charset is used. 690 | ; http://php.net/input-encoding 691 | ;input_encoding = 692 | 693 | ; PHP output character encoding is set to empty. 694 | ; If empty, default_charset is used. 695 | ; mbstring or iconv output handler is used. 696 | ; See also output_buffer. 697 | ; http://php.net/output-encoding 698 | ;output_encoding = 699 | 700 | ; Always populate the $HTTP_RAW_POST_DATA variable. PHP's default behavior is 701 | ; to disable this feature and it will be removed in a future version. 702 | ; If post reading is disabled through enable_post_data_reading, 703 | ; $HTTP_RAW_POST_DATA is *NOT* populated. 704 | ; http://php.net/always-populate-raw-post-data 705 | ;always_populate_raw_post_data = -1 706 | 707 | ;;;;;;;;;;;;;;;;;;;;;;;;; 708 | ; Paths and Directories ; 709 | ;;;;;;;;;;;;;;;;;;;;;;;;; 710 | 711 | ; UNIX: "/path1:/path2" 712 | ;include_path = ".:/usr/share/php" 713 | ; 714 | ; Windows: "\path1;\path2" 715 | ;include_path = ".;c:\php\includes" 716 | ; 717 | ; PHP's default setting for include_path is ".;/path/to/php/pear" 718 | ; http://php.net/include-path 719 | 720 | ; The root of the PHP pages, used only if nonempty. 721 | ; if PHP was not compiled with FORCE_REDIRECT, you SHOULD set doc_root 722 | ; if you are running php as a CGI under any web server (other than IIS) 723 | ; see documentation for security issues. The alternate is to use the 724 | ; cgi.force_redirect configuration below 725 | ; http://php.net/doc-root 726 | doc_root = 727 | 728 | ; The directory under which PHP opens the script using /~username used only 729 | ; if nonempty. 730 | ; http://php.net/user-dir 731 | user_dir = 732 | 733 | ; Directory in which the loadable extensions (modules) reside. 734 | ; http://php.net/extension-dir 735 | ; extension_dir = "./" 736 | ; On windows: 737 | ; extension_dir = "ext" 738 | 739 | ; Directory where the temporary files should be placed. 740 | ; Defaults to the system default (see sys_get_temp_dir) 741 | ; sys_temp_dir = "/tmp" 742 | 743 | ; Whether or not to enable the dl() function. The dl() function does NOT work 744 | ; properly in multithreaded servers, such as IIS or Zeus, and is automatically 745 | ; disabled on them. 746 | ; http://php.net/enable-dl 747 | enable_dl = Off 748 | 749 | ; cgi.force_redirect is necessary to provide security running PHP as a CGI under 750 | ; most web servers. Left undefined, PHP turns this on by default. You can 751 | ; turn it off here AT YOUR OWN RISK 752 | ; **You CAN safely turn this off for IIS, in fact, you MUST.** 753 | ; http://php.net/cgi.force-redirect 754 | ;cgi.force_redirect = 1 755 | 756 | ; if cgi.nph is enabled it will force cgi to always sent Status: 200 with 757 | ; every request. PHP's default behavior is to disable this feature. 758 | ;cgi.nph = 1 759 | 760 | ; if cgi.force_redirect is turned on, and you are not running under Apache or Netscape 761 | ; (iPlanet) web servers, you MAY need to set an environment variable name that PHP 762 | ; will look for to know it is OK to continue execution. Setting this variable MAY 763 | ; cause security issues, KNOW WHAT YOU ARE DOING FIRST. 764 | ; http://php.net/cgi.redirect-status-env 765 | ;cgi.redirect_status_env = 766 | 767 | ; cgi.fix_pathinfo provides *real* PATH_INFO/PATH_TRANSLATED support for CGI. PHP's 768 | ; previous behaviour was to set PATH_TRANSLATED to SCRIPT_FILENAME, and to not grok 769 | ; what PATH_INFO is. For more information on PATH_INFO, see the cgi specs. Setting 770 | ; this to 1 will cause PHP CGI to fix its paths to conform to the spec. A setting 771 | ; of zero causes PHP to behave as before. Default is 1. You should fix your scripts 772 | ; to use SCRIPT_FILENAME rather than PATH_TRANSLATED. 773 | ; http://php.net/cgi.fix-pathinfo 774 | ;cgi.fix_pathinfo=1 775 | 776 | ; FastCGI under IIS (on WINNT based OS) supports the ability to impersonate 777 | ; security tokens of the calling client. This allows IIS to define the 778 | ; security context that the request runs under. mod_fastcgi under Apache 779 | ; does not currently support this feature (03/17/2002) 780 | ; Set to 1 if running under IIS. Default is zero. 781 | ; http://php.net/fastcgi.impersonate 782 | ;fastcgi.impersonate = 1 783 | 784 | ; Disable logging through FastCGI connection. PHP's default behavior is to enable 785 | ; this feature. 786 | ;fastcgi.logging = 0 787 | 788 | ; cgi.rfc2616_headers configuration option tells PHP what type of headers to 789 | ; use when sending HTTP response code. If set to 0, PHP sends Status: header that 790 | ; is supported by Apache. When this option is set to 1, PHP will send 791 | ; RFC2616 compliant header. 792 | ; Default is zero. 793 | ; http://php.net/cgi.rfc2616-headers 794 | ;cgi.rfc2616_headers = 0 795 | 796 | ;;;;;;;;;;;;;;;; 797 | ; File Uploads ; 798 | ;;;;;;;;;;;;;;;; 799 | 800 | ; Whether to allow HTTP file uploads. 801 | ; http://php.net/file-uploads 802 | file_uploads = Off 803 | 804 | ; Temporary directory for HTTP uploaded files (will use system default if not 805 | ; specified). 806 | ; http://php.net/upload-tmp-dir 807 | ;upload_tmp_dir = 808 | 809 | ; Maximum allowed size for uploaded files. 810 | ; http://php.net/upload-max-filesize 811 | upload_max_filesize = 2M 812 | 813 | ; Maximum number of files that can be uploaded via a single request 814 | max_file_uploads = 20 815 | 816 | ;;;;;;;;;;;;;;;;;; 817 | ; Fopen wrappers ; 818 | ;;;;;;;;;;;;;;;;;; 819 | 820 | ; Whether to allow the treatment of URLs (like http:// or ftp://) as files. 821 | ; http://php.net/allow-url-fopen 822 | allow_url_fopen = On 823 | 824 | ; Whether to allow include/require to open URLs (like http:// or ftp://) as files. 825 | ; http://php.net/allow-url-include 826 | allow_url_include = On 827 | 828 | ; Define the anonymous ftp password (your email address). PHP's default setting 829 | ; for this is empty. 830 | ; http://php.net/from 831 | ;from="john@doe.com" 832 | 833 | ; Define the User-Agent string. PHP's default setting for this is empty. 834 | ; http://php.net/user-agent 835 | ;user_agent="PHP" 836 | 837 | ; Default timeout for socket based streams (seconds) 838 | ; http://php.net/default-socket-timeout 839 | default_socket_timeout = -1 840 | 841 | ; If your scripts have to deal with files from Macintosh systems, 842 | ; or you are running on a Mac and need to deal with files from 843 | ; unix or win32 systems, setting this flag will cause PHP to 844 | ; automatically detect the EOL character in those files so that 845 | ; fgets() and file() will work regardless of the source of the file. 846 | ; http://php.net/auto-detect-line-endings 847 | ;auto_detect_line_endings = Off 848 | 849 | ;;;;;;;;;;;;;;;;;;;;;; 850 | ; Dynamic Extensions ; 851 | ;;;;;;;;;;;;;;;;;;;;;; 852 | 853 | ; If you wish to have an extension loaded automatically, use the following 854 | ; syntax: 855 | ; 856 | ; extension=modulename.extension 857 | ; 858 | ; For example, on Windows: 859 | ; 860 | ; extension=msql.dll 861 | ; 862 | ; ... or under UNIX: 863 | ; 864 | ; extension=msql.so 865 | ; 866 | ; ... or with a path: 867 | ; 868 | ; extension=/path/to/extension/msql.so 869 | ; 870 | ; If you only provide the name of the extension, PHP will look for it in its 871 | ; default extension directory. 872 | ; 873 | 874 | ;;;;;;;;;;;;;;;;;;; 875 | ; Module Settings ; 876 | ;;;;;;;;;;;;;;;;;;; 877 | 878 | [CLI Server] 879 | ; Whether the CLI web server uses ANSI color coding in its terminal output. 880 | cli_server.color = On 881 | 882 | [Date] 883 | ; Defines the default timezone used by the date functions 884 | ; http://php.net/date.timezone 885 | ;date.timezone = 886 | 887 | ; http://php.net/date.default-latitude 888 | ;date.default_latitude = 31.7667 889 | 890 | ; http://php.net/date.default-longitude 891 | ;date.default_longitude = 35.2333 892 | 893 | ; http://php.net/date.sunrise-zenith 894 | ;date.sunrise_zenith = 90.583333 895 | 896 | ; http://php.net/date.sunset-zenith 897 | ;date.sunset_zenith = 90.583333 898 | 899 | [filter] 900 | ; http://php.net/filter.default 901 | ;filter.default = unsafe_raw 902 | 903 | ; http://php.net/filter.default-flags 904 | ;filter.default_flags = 905 | 906 | [iconv] 907 | ; Use of this INI entry is deprecated, use global input_encoding instead. 908 | ; If empty, default_charset or input_encoding or iconv.input_encoding is used. 909 | ; The precedence is: default_charset < intput_encoding < iconv.input_encoding 910 | ;iconv.input_encoding = 911 | 912 | ; Use of this INI entry is deprecated, use global internal_encoding instead. 913 | ; If empty, default_charset or internal_encoding or iconv.internal_encoding is used. 914 | ; The precedence is: default_charset < internal_encoding < iconv.internal_encoding 915 | ;iconv.internal_encoding = 916 | 917 | ; Use of this INI entry is deprecated, use global output_encoding instead. 918 | ; If empty, default_charset or output_encoding or iconv.output_encoding is used. 919 | ; The precedence is: default_charset < output_encoding < iconv.output_encoding 920 | ; To use an output encoding conversion, iconv's output handler must be set 921 | ; otherwise output encoding conversion cannot be performed. 922 | ;iconv.output_encoding = 923 | 924 | [intl] 925 | ;intl.default_locale = 926 | ; This directive allows you to produce PHP errors when some error 927 | ; happens within intl functions. The value is the level of the error produced. 928 | ; Default is 0, which does not produce any errors. 929 | ;intl.error_level = E_WARNING 930 | 931 | [sqlite] 932 | ; http://php.net/sqlite.assoc-case 933 | ;sqlite.assoc_case = 0 934 | 935 | [sqlite3] 936 | ;sqlite3.extension_dir = 937 | 938 | [Pcre] 939 | ;PCRE library backtracking limit. 940 | ; http://php.net/pcre.backtrack-limit 941 | ;pcre.backtrack_limit=100000 942 | 943 | ;PCRE library recursion limit. 944 | ;Please note that if you set this value to a high number you may consume all 945 | ;the available process stack and eventually crash PHP (due to reaching the 946 | ;stack size limit imposed by the Operating System). 947 | ; http://php.net/pcre.recursion-limit 948 | ;pcre.recursion_limit=100000 949 | 950 | [Pdo] 951 | ; Whether to pool ODBC connections. Can be one of "strict", "relaxed" or "off" 952 | ; http://php.net/pdo-odbc.connection-pooling 953 | ;pdo_odbc.connection_pooling=strict 954 | 955 | ;pdo_odbc.db2_instance_name 956 | 957 | [Pdo_mysql] 958 | ; If mysqlnd is used: Number of cache slots for the internal result set cache 959 | ; http://php.net/pdo_mysql.cache_size 960 | pdo_mysql.cache_size = 2000 961 | 962 | ; Default socket name for local MySQL connects. If empty, uses the built-in 963 | ; MySQL defaults. 964 | ; http://php.net/pdo_mysql.default-socket 965 | pdo_mysql.default_socket= 966 | 967 | [Phar] 968 | ; http://php.net/phar.readonly 969 | ;phar.readonly = On 970 | 971 | ; http://php.net/phar.require-hash 972 | ;phar.require_hash = On 973 | 974 | ;phar.cache_list = 975 | 976 | [mail function] 977 | ; For Win32 only. 978 | ; http://php.net/smtp 979 | SMTP = localhost 980 | ; http://php.net/smtp-port 981 | smtp_port = 25 982 | 983 | ; For Win32 only. 984 | ; http://php.net/sendmail-from 985 | ;sendmail_from = me@example.com 986 | 987 | ; For Unix only. You may supply arguments as well (default: "sendmail -t -i"). 988 | ; http://php.net/sendmail-path 989 | ;sendmail_path = 990 | 991 | ; Force the addition of the specified parameters to be passed as extra parameters 992 | ; to the sendmail binary. These parameters will always replace the value of 993 | ; the 5th parameter to mail(). 994 | ;mail.force_extra_parameters = 995 | 996 | ; Add X-PHP-Originating-Script: that will include uid of the script followed by the filename 997 | mail.add_x_header = On 998 | 999 | ; The path to a log file that will log all mail() calls. Log entries include 1000 | ; the full path of the script, line number, To address and headers. 1001 | ;mail.log = 1002 | ; Log mail to syslog (Event Log on Windows). 1003 | ;mail.log = syslog 1004 | 1005 | [SQL] 1006 | ; http://php.net/sql.safe-mode 1007 | sql.safe_mode = Off 1008 | 1009 | [ODBC] 1010 | ; http://php.net/odbc.default-db 1011 | ;odbc.default_db = Not yet implemented 1012 | 1013 | ; http://php.net/odbc.default-user 1014 | ;odbc.default_user = Not yet implemented 1015 | 1016 | ; http://php.net/odbc.default-pw 1017 | ;odbc.default_pw = Not yet implemented 1018 | 1019 | ; Controls the ODBC cursor model. 1020 | ; Default: SQL_CURSOR_STATIC (default). 1021 | ;odbc.default_cursortype 1022 | 1023 | ; Allow or prevent persistent links. 1024 | ; http://php.net/odbc.allow-persistent 1025 | odbc.allow_persistent = On 1026 | 1027 | ; Check that a connection is still valid before reuse. 1028 | ; http://php.net/odbc.check-persistent 1029 | odbc.check_persistent = On 1030 | 1031 | ; Maximum number of persistent links. -1 means no limit. 1032 | ; http://php.net/odbc.max-persistent 1033 | odbc.max_persistent = -1 1034 | 1035 | ; Maximum number of links (persistent + non-persistent). -1 means no limit. 1036 | ; http://php.net/odbc.max-links 1037 | odbc.max_links = -1 1038 | 1039 | ; Handling of LONG fields. Returns number of bytes to variables. 0 means 1040 | ; passthru. 1041 | ; http://php.net/odbc.defaultlrl 1042 | odbc.defaultlrl = 4096 1043 | 1044 | ; Handling of binary data. 0 means passthru, 1 return as is, 2 convert to char. 1045 | ; See the documentation on odbc_binmode and odbc_longreadlen for an explanation 1046 | ; of odbc.defaultlrl and odbc.defaultbinmode 1047 | ; http://php.net/odbc.defaultbinmode 1048 | odbc.defaultbinmode = 1 1049 | 1050 | ;birdstep.max_links = -1 1051 | 1052 | [Interbase] 1053 | ; Allow or prevent persistent links. 1054 | ibase.allow_persistent = 1 1055 | 1056 | ; Maximum number of persistent links. -1 means no limit. 1057 | ibase.max_persistent = -1 1058 | 1059 | ; Maximum number of links (persistent + non-persistent). -1 means no limit. 1060 | ibase.max_links = -1 1061 | 1062 | ; Default database name for ibase_connect(). 1063 | ;ibase.default_db = 1064 | 1065 | ; Default username for ibase_connect(). 1066 | ;ibase.default_user = 1067 | 1068 | ; Default password for ibase_connect(). 1069 | ;ibase.default_password = 1070 | 1071 | ; Default charset for ibase_connect(). 1072 | ;ibase.default_charset = 1073 | 1074 | ; Default timestamp format. 1075 | ibase.timestampformat = "%Y-%m-%d %H:%M:%S" 1076 | 1077 | ; Default date format. 1078 | ibase.dateformat = "%Y-%m-%d" 1079 | 1080 | ; Default time format. 1081 | ibase.timeformat = "%H:%M:%S" 1082 | 1083 | [MySQL] 1084 | ; Allow accessing, from PHP's perspective, local files with LOAD DATA statements 1085 | ; http://php.net/mysql.allow_local_infile 1086 | mysql.allow_local_infile = On 1087 | 1088 | ; Allow or prevent persistent links. 1089 | ; http://php.net/mysql.allow-persistent 1090 | mysql.allow_persistent = On 1091 | 1092 | ; If mysqlnd is used: Number of cache slots for the internal result set cache 1093 | ; http://php.net/mysql.cache_size 1094 | mysql.cache_size = 2000 1095 | 1096 | ; Maximum number of persistent links. -1 means no limit. 1097 | ; http://php.net/mysql.max-persistent 1098 | mysql.max_persistent = -1 1099 | 1100 | ; Maximum number of links (persistent + non-persistent). -1 means no limit. 1101 | ; http://php.net/mysql.max-links 1102 | mysql.max_links = -1 1103 | 1104 | ; Default port number for mysql_connect(). If unset, mysql_connect() will use 1105 | ; the $MYSQL_TCP_PORT or the mysql-tcp entry in /etc/services or the 1106 | ; compile-time value defined MYSQL_PORT (in that order). Win32 will only look 1107 | ; at MYSQL_PORT. 1108 | ; http://php.net/mysql.default-port 1109 | mysql.default_port = 1110 | 1111 | ; Default socket name for local MySQL connects. If empty, uses the built-in 1112 | ; MySQL defaults. 1113 | ; http://php.net/mysql.default-socket 1114 | mysql.default_socket = 1115 | 1116 | ; Default host for mysql_connect() (doesn't apply in safe mode). 1117 | ; http://php.net/mysql.default-host 1118 | mysql.default_host = 1119 | 1120 | ; Default user for mysql_connect() (doesn't apply in safe mode). 1121 | ; http://php.net/mysql.default-user 1122 | mysql.default_user = 1123 | 1124 | ; Default password for mysql_connect() (doesn't apply in safe mode). 1125 | ; Note that this is generally a *bad* idea to store passwords in this file. 1126 | ; *Any* user with PHP access can run 'echo get_cfg_var("mysql.default_password") 1127 | ; and reveal this password! And of course, any users with read access to this 1128 | ; file will be able to reveal the password as well. 1129 | ; http://php.net/mysql.default-password 1130 | mysql.default_password = 1131 | 1132 | ; Maximum time (in seconds) for connect timeout. -1 means no limit 1133 | ; http://php.net/mysql.connect-timeout 1134 | mysql.connect_timeout = 10 1135 | 1136 | ; Trace mode. When trace_mode is active (=On), warnings for table/index scans and 1137 | ; SQL-Errors will be displayed. 1138 | ; http://php.net/mysql.trace-mode 1139 | mysql.trace_mode = Off 1140 | 1141 | [MySQLi] 1142 | 1143 | ; Maximum number of persistent links. -1 means no limit. 1144 | ; http://php.net/mysqli.max-persistent 1145 | mysqli.max_persistent = -1 1146 | 1147 | ; Allow accessing, from PHP's perspective, local files with LOAD DATA statements 1148 | ; http://php.net/mysqli.allow_local_infile 1149 | ;mysqli.allow_local_infile = On 1150 | 1151 | ; Allow or prevent persistent links. 1152 | ; http://php.net/mysqli.allow-persistent 1153 | mysqli.allow_persistent = On 1154 | 1155 | ; Maximum number of links. -1 means no limit. 1156 | ; http://php.net/mysqli.max-links 1157 | mysqli.max_links = -1 1158 | 1159 | ; If mysqlnd is used: Number of cache slots for the internal result set cache 1160 | ; http://php.net/mysqli.cache_size 1161 | mysqli.cache_size = 2000 1162 | 1163 | ; Default port number for mysqli_connect(). If unset, mysqli_connect() will use 1164 | ; the $MYSQL_TCP_PORT or the mysql-tcp entry in /etc/services or the 1165 | ; compile-time value defined MYSQL_PORT (in that order). Win32 will only look 1166 | ; at MYSQL_PORT. 1167 | ; http://php.net/mysqli.default-port 1168 | mysqli.default_port = 3306 1169 | 1170 | ; Default socket name for local MySQL connects. If empty, uses the built-in 1171 | ; MySQL defaults. 1172 | ; http://php.net/mysqli.default-socket 1173 | mysqli.default_socket = 1174 | 1175 | ; Default host for mysql_connect() (doesn't apply in safe mode). 1176 | ; http://php.net/mysqli.default-host 1177 | mysqli.default_host = 1178 | 1179 | ; Default user for mysql_connect() (doesn't apply in safe mode). 1180 | ; http://php.net/mysqli.default-user 1181 | mysqli.default_user = 1182 | 1183 | ; Default password for mysqli_connect() (doesn't apply in safe mode). 1184 | ; Note that this is generally a *bad* idea to store passwords in this file. 1185 | ; *Any* user with PHP access can run 'echo get_cfg_var("mysqli.default_pw") 1186 | ; and reveal this password! And of course, any users with read access to this 1187 | ; file will be able to reveal the password as well. 1188 | ; http://php.net/mysqli.default-pw 1189 | mysqli.default_pw = 1190 | 1191 | ; Allow or prevent reconnect 1192 | mysqli.reconnect = Off 1193 | 1194 | [mysqlnd] 1195 | ; Enable / Disable collection of general statistics by mysqlnd which can be 1196 | ; used to tune and monitor MySQL operations. 1197 | ; http://php.net/mysqlnd.collect_statistics 1198 | mysqlnd.collect_statistics = On 1199 | 1200 | ; Enable / Disable collection of memory usage statistics by mysqlnd which can be 1201 | ; used to tune and monitor MySQL operations. 1202 | ; http://php.net/mysqlnd.collect_memory_statistics 1203 | mysqlnd.collect_memory_statistics = Off 1204 | 1205 | ; Size of a pre-allocated buffer used when sending commands to MySQL in bytes. 1206 | ; http://php.net/mysqlnd.net_cmd_buffer_size 1207 | ;mysqlnd.net_cmd_buffer_size = 2048 1208 | 1209 | ; Size of a pre-allocated buffer used for reading data sent by the server in 1210 | ; bytes. 1211 | ; http://php.net/mysqlnd.net_read_buffer_size 1212 | ;mysqlnd.net_read_buffer_size = 32768 1213 | 1214 | [OCI8] 1215 | 1216 | ; Connection: Enables privileged connections using external 1217 | ; credentials (OCI_SYSOPER, OCI_SYSDBA) 1218 | ; http://php.net/oci8.privileged-connect 1219 | ;oci8.privileged_connect = Off 1220 | 1221 | ; Connection: The maximum number of persistent OCI8 connections per 1222 | ; process. Using -1 means no limit. 1223 | ; http://php.net/oci8.max-persistent 1224 | ;oci8.max_persistent = -1 1225 | 1226 | ; Connection: The maximum number of seconds a process is allowed to 1227 | ; maintain an idle persistent connection. Using -1 means idle 1228 | ; persistent connections will be maintained forever. 1229 | ; http://php.net/oci8.persistent-timeout 1230 | ;oci8.persistent_timeout = -1 1231 | 1232 | ; Connection: The number of seconds that must pass before issuing a 1233 | ; ping during oci_pconnect() to check the connection validity. When 1234 | ; set to 0, each oci_pconnect() will cause a ping. Using -1 disables 1235 | ; pings completely. 1236 | ; http://php.net/oci8.ping-interval 1237 | ;oci8.ping_interval = 60 1238 | 1239 | ; Connection: Set this to a user chosen connection class to be used 1240 | ; for all pooled server requests with Oracle 11g Database Resident 1241 | ; Connection Pooling (DRCP). To use DRCP, this value should be set to 1242 | ; the same string for all web servers running the same application, 1243 | ; the database pool must be configured, and the connection string must 1244 | ; specify to use a pooled server. 1245 | ;oci8.connection_class = 1246 | 1247 | ; High Availability: Using On lets PHP receive Fast Application 1248 | ; Notification (FAN) events generated when a database node fails. The 1249 | ; database must also be configured to post FAN events. 1250 | ;oci8.events = Off 1251 | 1252 | ; Tuning: This option enables statement caching, and specifies how 1253 | ; many statements to cache. Using 0 disables statement caching. 1254 | ; http://php.net/oci8.statement-cache-size 1255 | ;oci8.statement_cache_size = 20 1256 | 1257 | ; Tuning: Enables statement prefetching and sets the default number of 1258 | ; rows that will be fetched automatically after statement execution. 1259 | ; http://php.net/oci8.default-prefetch 1260 | ;oci8.default_prefetch = 100 1261 | 1262 | ; Compatibility. Using On means oci_close() will not close 1263 | ; oci_connect() and oci_new_connect() connections. 1264 | ; http://php.net/oci8.old-oci-close-semantics 1265 | ;oci8.old_oci_close_semantics = Off 1266 | 1267 | [PostgreSQL] 1268 | ; Allow or prevent persistent links. 1269 | ; http://php.net/pgsql.allow-persistent 1270 | pgsql.allow_persistent = On 1271 | 1272 | ; Detect broken persistent links always with pg_pconnect(). 1273 | ; Auto reset feature requires a little overheads. 1274 | ; http://php.net/pgsql.auto-reset-persistent 1275 | pgsql.auto_reset_persistent = Off 1276 | 1277 | ; Maximum number of persistent links. -1 means no limit. 1278 | ; http://php.net/pgsql.max-persistent 1279 | pgsql.max_persistent = -1 1280 | 1281 | ; Maximum number of links (persistent+non persistent). -1 means no limit. 1282 | ; http://php.net/pgsql.max-links 1283 | pgsql.max_links = -1 1284 | 1285 | ; Ignore PostgreSQL backends Notice message or not. 1286 | ; Notice message logging require a little overheads. 1287 | ; http://php.net/pgsql.ignore-notice 1288 | pgsql.ignore_notice = 0 1289 | 1290 | ; Log PostgreSQL backends Notice message or not. 1291 | ; Unless pgsql.ignore_notice=0, module cannot log notice message. 1292 | ; http://php.net/pgsql.log-notice 1293 | pgsql.log_notice = 0 1294 | 1295 | [Sybase-CT] 1296 | ; Allow or prevent persistent links. 1297 | ; http://php.net/sybct.allow-persistent 1298 | sybct.allow_persistent = On 1299 | 1300 | ; Maximum number of persistent links. -1 means no limit. 1301 | ; http://php.net/sybct.max-persistent 1302 | sybct.max_persistent = -1 1303 | 1304 | ; Maximum number of links (persistent + non-persistent). -1 means no limit. 1305 | ; http://php.net/sybct.max-links 1306 | sybct.max_links = -1 1307 | 1308 | ; Minimum server message severity to display. 1309 | ; http://php.net/sybct.min-server-severity 1310 | sybct.min_server_severity = 10 1311 | 1312 | ; Minimum client message severity to display. 1313 | ; http://php.net/sybct.min-client-severity 1314 | sybct.min_client_severity = 10 1315 | 1316 | ; Set per-context timeout 1317 | ; http://php.net/sybct.timeout 1318 | ;sybct.timeout= 1319 | 1320 | ;sybct.packet_size 1321 | 1322 | ; The maximum time in seconds to wait for a connection attempt to succeed before returning failure. 1323 | ; Default: one minute 1324 | ;sybct.login_timeout= 1325 | 1326 | ; The name of the host you claim to be connecting from, for display by sp_who. 1327 | ; Default: none 1328 | ;sybct.hostname= 1329 | 1330 | ; Allows you to define how often deadlocks are to be retried. -1 means "forever". 1331 | ; Default: 0 1332 | ;sybct.deadlock_retry_count= 1333 | 1334 | [bcmath] 1335 | ; Number of decimal digits for all bcmath functions. 1336 | ; http://php.net/bcmath.scale 1337 | bcmath.scale = 0 1338 | 1339 | [browscap] 1340 | ; http://php.net/browscap 1341 | ;browscap = extra/browscap.ini 1342 | 1343 | [Session] 1344 | ; Handler used to store/retrieve data. 1345 | ; http://php.net/session.save-handler 1346 | session.save_handler = files 1347 | 1348 | ; Argument passed to save_handler. In the case of files, this is the path 1349 | ; where data files are stored. Note: Windows users have to change this 1350 | ; variable in order to use PHP's session functions. 1351 | ; 1352 | ; The path can be defined as: 1353 | ; 1354 | ; session.save_path = "N;/path" 1355 | ; 1356 | ; where N is an integer. Instead of storing all the session files in 1357 | ; /path, what this will do is use subdirectories N-levels deep, and 1358 | ; store the session data in those directories. This is useful if 1359 | ; your OS has problems with many files in one directory, and is 1360 | ; a more efficient layout for servers that handle many sessions. 1361 | ; 1362 | ; NOTE 1: PHP will not create this directory structure automatically. 1363 | ; You can use the script in the ext/session dir for that purpose. 1364 | ; NOTE 2: See the section on garbage collection below if you choose to 1365 | ; use subdirectories for session storage 1366 | ; 1367 | ; The file storage module creates files using mode 600 by default. 1368 | ; You can change that by using 1369 | ; 1370 | ; session.save_path = "N;MODE;/path" 1371 | ; 1372 | ; where MODE is the octal representation of the mode. Note that this 1373 | ; does not overwrite the process's umask. 1374 | ; http://php.net/session.save-path 1375 | ;session.save_path = "/var/lib/php5/sessions" 1376 | 1377 | ; Whether to use strict session mode. 1378 | ; Strict session mode does not accept uninitialized session ID and regenerate 1379 | ; session ID if browser sends uninitialized session ID. Strict mode protects 1380 | ; applications from session fixation via session adoption vulnerability. It is 1381 | ; disabled by default for maximum compatibility, but enabling it is encouraged. 1382 | ; https://wiki.php.net/rfc/strict_sessions 1383 | session.use_strict_mode = 0 1384 | 1385 | ; Whether to use cookies. 1386 | ; http://php.net/session.use-cookies 1387 | session.use_cookies = 1 1388 | 1389 | ; http://php.net/session.cookie-secure 1390 | ;session.cookie_secure = 1391 | 1392 | ; This option forces PHP to fetch and use a cookie for storing and maintaining 1393 | ; the session id. We encourage this operation as it's very helpful in combating 1394 | ; session hijacking when not specifying and managing your own session id. It is 1395 | ; not the be-all and end-all of session hijacking defense, but it's a good start. 1396 | ; http://php.net/session.use-only-cookies 1397 | session.use_only_cookies = 1 1398 | 1399 | ; Name of the session (used as cookie name). 1400 | ; http://php.net/session.name 1401 | session.name = PHPSESSID 1402 | 1403 | ; Initialize session on request startup. 1404 | ; http://php.net/session.auto-start 1405 | session.auto_start = 0 1406 | 1407 | ; Lifetime in seconds of cookie or, if 0, until browser is restarted. 1408 | ; http://php.net/session.cookie-lifetime 1409 | session.cookie_lifetime = 0 1410 | 1411 | ; The path for which the cookie is valid. 1412 | ; http://php.net/session.cookie-path 1413 | session.cookie_path = / 1414 | 1415 | ; The domain for which the cookie is valid. 1416 | ; http://php.net/session.cookie-domain 1417 | session.cookie_domain = 1418 | 1419 | ; Whether or not to add the httpOnly flag to the cookie, which makes it inaccessible to browser scripting languages such as JavaScript. 1420 | ; http://php.net/session.cookie-httponly 1421 | session.cookie_httponly = 1422 | 1423 | ; Handler used to serialize data. php is the standard serializer of PHP. 1424 | ; http://php.net/session.serialize-handler 1425 | session.serialize_handler = php 1426 | 1427 | ; Defines the probability that the 'garbage collection' process is started 1428 | ; on every session initialization. The probability is calculated by using 1429 | ; gc_probability/gc_divisor. Where session.gc_probability is the numerator 1430 | ; and gc_divisor is the denominator in the equation. Setting this value to 1 1431 | ; when the session.gc_divisor value is 100 will give you approximately a 1% chance 1432 | ; the gc will run on any give request. 1433 | ; Default Value: 1 1434 | ; Development Value: 1 1435 | ; Production Value: 1 1436 | ; http://php.net/session.gc-probability 1437 | session.gc_probability = 0 1438 | 1439 | ; Defines the probability that the 'garbage collection' process is started on every 1440 | ; session initialization. The probability is calculated by using the following equation: 1441 | ; gc_probability/gc_divisor. Where session.gc_probability is the numerator and 1442 | ; session.gc_divisor is the denominator in the equation. Setting this value to 1 1443 | ; when the session.gc_divisor value is 100 will give you approximately a 1% chance 1444 | ; the gc will run on any give request. Increasing this value to 1000 will give you 1445 | ; a 0.1% chance the gc will run on any give request. For high volume production servers, 1446 | ; this is a more efficient approach. 1447 | ; Default Value: 100 1448 | ; Development Value: 1000 1449 | ; Production Value: 1000 1450 | ; http://php.net/session.gc-divisor 1451 | session.gc_divisor = 1000 1452 | 1453 | ; After this number of seconds, stored data will be seen as 'garbage' and 1454 | ; cleaned up by the garbage collection process. 1455 | ; http://php.net/session.gc-maxlifetime 1456 | session.gc_maxlifetime = 1440 1457 | 1458 | ; NOTE: If you are using the subdirectory option for storing session files 1459 | ; (see session.save_path above), then garbage collection does *not* 1460 | ; happen automatically. You will need to do your own garbage 1461 | ; collection through a shell script, cron entry, or some other method. 1462 | ; For example, the following script would is the equivalent of 1463 | ; setting session.gc_maxlifetime to 1440 (1440 seconds = 24 minutes): 1464 | ; find /path/to/sessions -cmin +24 -type f | xargs rm 1465 | 1466 | ; Check HTTP Referer to invalidate externally stored URLs containing ids. 1467 | ; HTTP_REFERER has to contain this substring for the session to be 1468 | ; considered as valid. 1469 | ; http://php.net/session.referer-check 1470 | session.referer_check = 1471 | 1472 | ; How many bytes to read from the file. 1473 | ; http://php.net/session.entropy-length 1474 | ;session.entropy_length = 32 1475 | 1476 | ; Specified here to create the session id. 1477 | ; http://php.net/session.entropy-file 1478 | ; Defaults to /dev/urandom 1479 | ; On systems that don't have /dev/urandom but do have /dev/arandom, this will default to /dev/arandom 1480 | ; If neither are found at compile time, the default is no entropy file. 1481 | ; On windows, setting the entropy_length setting will activate the 1482 | ; Windows random source (using the CryptoAPI) 1483 | ;session.entropy_file = /dev/urandom 1484 | 1485 | ; Set to {nocache,private,public,} to determine HTTP caching aspects 1486 | ; or leave this empty to avoid sending anti-caching headers. 1487 | ; http://php.net/session.cache-limiter 1488 | session.cache_limiter = nocache 1489 | 1490 | ; Document expires after n minutes. 1491 | ; http://php.net/session.cache-expire 1492 | session.cache_expire = 180 1493 | 1494 | ; trans sid support is disabled by default. 1495 | ; Use of trans sid may risk your users' security. 1496 | ; Use this option with caution. 1497 | ; - User may send URL contains active session ID 1498 | ; to other person via. email/irc/etc. 1499 | ; - URL that contains active session ID may be stored 1500 | ; in publicly accessible computer. 1501 | ; - User may access your site with the same session ID 1502 | ; always using URL stored in browser's history or bookmarks. 1503 | ; http://php.net/session.use-trans-sid 1504 | session.use_trans_sid = 0 1505 | 1506 | ; Select a hash function for use in generating session ids. 1507 | ; Possible Values 1508 | ; 0 (MD5 128 bits) 1509 | ; 1 (SHA-1 160 bits) 1510 | ; This option may also be set to the name of any hash function supported by 1511 | ; the hash extension. A list of available hashes is returned by the hash_algos() 1512 | ; function. 1513 | ; http://php.net/session.hash-function 1514 | session.hash_function = 0 1515 | 1516 | ; Define how many bits are stored in each character when converting 1517 | ; the binary hash data to something readable. 1518 | ; Possible values: 1519 | ; 4 (4 bits: 0-9, a-f) 1520 | ; 5 (5 bits: 0-9, a-v) 1521 | ; 6 (6 bits: 0-9, a-z, A-Z, "-", ",") 1522 | ; Default Value: 4 1523 | ; Development Value: 5 1524 | ; Production Value: 5 1525 | ; http://php.net/session.hash-bits-per-character 1526 | session.hash_bits_per_character = 5 1527 | 1528 | ; The URL rewriter will look for URLs in a defined set of HTML tags. 1529 | ; form/fieldset are special; if you include them here, the rewriter will 1530 | ; add a hidden field with the info which is otherwise appended 1531 | ; to URLs. If you want XHTML conformity, remove the form entry. 1532 | ; Note that all valid entries require a "=", even if no value follows. 1533 | ; Default Value: "a=href,area=href,frame=src,form=,fieldset=" 1534 | ; Development Value: "a=href,area=href,frame=src,input=src,form=fakeentry" 1535 | ; Production Value: "a=href,area=href,frame=src,input=src,form=fakeentry" 1536 | ; http://php.net/url-rewriter.tags 1537 | url_rewriter.tags = "a=href,area=href,frame=src,input=src,form=fakeentry" 1538 | 1539 | ; Enable upload progress tracking in $_SESSION 1540 | ; Default Value: On 1541 | ; Development Value: On 1542 | ; Production Value: On 1543 | ; http://php.net/session.upload-progress.enabled 1544 | ;session.upload_progress.enabled = On 1545 | 1546 | ; Cleanup the progress information as soon as all POST data has been read 1547 | ; (i.e. upload completed). 1548 | ; Default Value: On 1549 | ; Development Value: On 1550 | ; Production Value: On 1551 | ; http://php.net/session.upload-progress.cleanup 1552 | ;session.upload_progress.cleanup = On 1553 | 1554 | ; A prefix used for the upload progress key in $_SESSION 1555 | ; Default Value: "upload_progress_" 1556 | ; Development Value: "upload_progress_" 1557 | ; Production Value: "upload_progress_" 1558 | ; http://php.net/session.upload-progress.prefix 1559 | ;session.upload_progress.prefix = "upload_progress_" 1560 | 1561 | ; The index name (concatenated with the prefix) in $_SESSION 1562 | ; containing the upload progress information 1563 | ; Default Value: "PHP_SESSION_UPLOAD_PROGRESS" 1564 | ; Development Value: "PHP_SESSION_UPLOAD_PROGRESS" 1565 | ; Production Value: "PHP_SESSION_UPLOAD_PROGRESS" 1566 | ; http://php.net/session.upload-progress.name 1567 | ;session.upload_progress.name = "PHP_SESSION_UPLOAD_PROGRESS" 1568 | 1569 | ; How frequently the upload progress should be updated. 1570 | ; Given either in percentages (per-file), or in bytes 1571 | ; Default Value: "1%" 1572 | ; Development Value: "1%" 1573 | ; Production Value: "1%" 1574 | ; http://php.net/session.upload-progress.freq 1575 | ;session.upload_progress.freq = "1%" 1576 | 1577 | ; The minimum delay between updates, in seconds 1578 | ; Default Value: 1 1579 | ; Development Value: 1 1580 | ; Production Value: 1 1581 | ; http://php.net/session.upload-progress.min-freq 1582 | ;session.upload_progress.min_freq = "1" 1583 | 1584 | [MSSQL] 1585 | ; Allow or prevent persistent links. 1586 | mssql.allow_persistent = On 1587 | 1588 | ; Maximum number of persistent links. -1 means no limit. 1589 | mssql.max_persistent = -1 1590 | 1591 | ; Maximum number of links (persistent+non persistent). -1 means no limit. 1592 | mssql.max_links = -1 1593 | 1594 | ; Minimum error severity to display. 1595 | mssql.min_error_severity = 10 1596 | 1597 | ; Minimum message severity to display. 1598 | mssql.min_message_severity = 10 1599 | 1600 | ; Compatibility mode with old versions of PHP 3.0. 1601 | mssql.compatibility_mode = Off 1602 | 1603 | ; Connect timeout 1604 | ;mssql.connect_timeout = 5 1605 | 1606 | ; Query timeout 1607 | ;mssql.timeout = 60 1608 | 1609 | ; Valid range 0 - 2147483647. Default = 4096. 1610 | ;mssql.textlimit = 4096 1611 | 1612 | ; Valid range 0 - 2147483647. Default = 4096. 1613 | ;mssql.textsize = 4096 1614 | 1615 | ; Limits the number of records in each batch. 0 = all records in one batch. 1616 | ;mssql.batchsize = 0 1617 | 1618 | ; Specify how datetime and datetim4 columns are returned 1619 | ; On => Returns data converted to SQL server settings 1620 | ; Off => Returns values as YYYY-MM-DD hh:mm:ss 1621 | ;mssql.datetimeconvert = On 1622 | 1623 | ; Use NT authentication when connecting to the server 1624 | mssql.secure_connection = Off 1625 | 1626 | ; Specify max number of processes. -1 = library default 1627 | ; msdlib defaults to 25 1628 | ; FreeTDS defaults to 4096 1629 | ;mssql.max_procs = -1 1630 | 1631 | ; Specify client character set. 1632 | ; If empty or not set the client charset from freetds.conf is used 1633 | ; This is only used when compiled with FreeTDS 1634 | ;mssql.charset = "ISO-8859-1" 1635 | 1636 | [Assertion] 1637 | ; Assert(expr); active by default. 1638 | ; http://php.net/assert.active 1639 | ;assert.active = On 1640 | 1641 | ; Issue a PHP warning for each failed assertion. 1642 | ; http://php.net/assert.warning 1643 | ;assert.warning = On 1644 | 1645 | ; Don't bail out by default. 1646 | ; http://php.net/assert.bail 1647 | ;assert.bail = Off 1648 | 1649 | ; User-function to be called if an assertion fails. 1650 | ; http://php.net/assert.callback 1651 | ;assert.callback = 0 1652 | 1653 | ; Eval the expression with current error_reporting(). Set to true if you want 1654 | ; error_reporting(0) around the eval(). 1655 | ; http://php.net/assert.quiet-eval 1656 | ;assert.quiet_eval = 0 1657 | 1658 | [COM] 1659 | ; path to a file containing GUIDs, IIDs or filenames of files with TypeLibs 1660 | ; http://php.net/com.typelib-file 1661 | ;com.typelib_file = 1662 | 1663 | ; allow Distributed-COM calls 1664 | ; http://php.net/com.allow-dcom 1665 | ;com.allow_dcom = true 1666 | 1667 | ; autoregister constants of a components typlib on com_load() 1668 | ; http://php.net/com.autoregister-typelib 1669 | ;com.autoregister_typelib = true 1670 | 1671 | ; register constants casesensitive 1672 | ; http://php.net/com.autoregister-casesensitive 1673 | ;com.autoregister_casesensitive = false 1674 | 1675 | ; show warnings on duplicate constant registrations 1676 | ; http://php.net/com.autoregister-verbose 1677 | ;com.autoregister_verbose = true 1678 | 1679 | ; The default character set code-page to use when passing strings to and from COM objects. 1680 | ; Default: system ANSI code page 1681 | ;com.code_page= 1682 | 1683 | [mbstring] 1684 | ; language for internal character representation. 1685 | ; This affects mb_send_mail() and mbstrig.detect_order. 1686 | ; http://php.net/mbstring.language 1687 | ;mbstring.language = Japanese 1688 | 1689 | ; Use of this INI entry is deprecated, use global internal_encoding instead. 1690 | ; internal/script encoding. 1691 | ; Some encoding cannot work as internal encoding. (e.g. SJIS, BIG5, ISO-2022-*) 1692 | ; If empty, default_charset or internal_encoding or iconv.internal_encoding is used. 1693 | ; The precedence is: default_charset < internal_encoding < iconv.internal_encoding 1694 | ;mbstring.internal_encoding = 1695 | 1696 | ; Use of this INI entry is deprecated, use global input_encoding instead. 1697 | ; http input encoding. 1698 | ; mbstring.encoding_traslation = On is needed to use this setting. 1699 | ; If empty, default_charset or input_encoding or mbstring.input is used. 1700 | ; The precedence is: default_charset < intput_encoding < mbsting.http_input 1701 | ; http://php.net/mbstring.http-input 1702 | ;mbstring.http_input = 1703 | 1704 | ; Use of this INI entry is deprecated, use global output_encoding instead. 1705 | ; http output encoding. 1706 | ; mb_output_handler must be registered as output buffer to function. 1707 | ; If empty, default_charset or output_encoding or mbstring.http_output is used. 1708 | ; The precedence is: default_charset < output_encoding < mbstring.http_output 1709 | ; To use an output encoding conversion, mbstring's output handler must be set 1710 | ; otherwise output encoding conversion cannot be performed. 1711 | ; http://php.net/mbstring.http-output 1712 | ;mbstring.http_output = 1713 | 1714 | ; enable automatic encoding translation according to 1715 | ; mbstring.internal_encoding setting. Input chars are 1716 | ; converted to internal encoding by setting this to On. 1717 | ; Note: Do _not_ use automatic encoding translation for 1718 | ; portable libs/applications. 1719 | ; http://php.net/mbstring.encoding-translation 1720 | ;mbstring.encoding_translation = Off 1721 | 1722 | ; automatic encoding detection order. 1723 | ; "auto" detect order is changed according to mbstring.language 1724 | ; http://php.net/mbstring.detect-order 1725 | ;mbstring.detect_order = auto 1726 | 1727 | ; substitute_character used when character cannot be converted 1728 | ; one from another 1729 | ; http://php.net/mbstring.substitute-character 1730 | ;mbstring.substitute_character = none 1731 | 1732 | ; overload(replace) single byte functions by mbstring functions. 1733 | ; mail(), ereg(), etc are overloaded by mb_send_mail(), mb_ereg(), 1734 | ; etc. Possible values are 0,1,2,4 or combination of them. 1735 | ; For example, 7 for overload everything. 1736 | ; 0: No overload 1737 | ; 1: Overload mail() function 1738 | ; 2: Overload str*() functions 1739 | ; 4: Overload ereg*() functions 1740 | ; http://php.net/mbstring.func-overload 1741 | ;mbstring.func_overload = 0 1742 | 1743 | ; enable strict encoding detection. 1744 | ; Default: Off 1745 | ;mbstring.strict_detection = On 1746 | 1747 | ; This directive specifies the regex pattern of content types for which mb_output_handler() 1748 | ; is activated. 1749 | ; Default: mbstring.http_output_conv_mimetype=^(text/|application/xhtml\+xml) 1750 | ;mbstring.http_output_conv_mimetype= 1751 | 1752 | [gd] 1753 | ; Tell the jpeg decode to ignore warnings and try to create 1754 | ; a gd image. The warning will then be displayed as notices 1755 | ; disabled by default 1756 | ; http://php.net/gd.jpeg-ignore-warning 1757 | ;gd.jpeg_ignore_warning = 0 1758 | 1759 | [exif] 1760 | ; Exif UNICODE user comments are handled as UCS-2BE/UCS-2LE and JIS as JIS. 1761 | ; With mbstring support this will automatically be converted into the encoding 1762 | ; given by corresponding encode setting. When empty mbstring.internal_encoding 1763 | ; is used. For the decode settings you can distinguish between motorola and 1764 | ; intel byte order. A decode setting cannot be empty. 1765 | ; http://php.net/exif.encode-unicode 1766 | ;exif.encode_unicode = ISO-8859-15 1767 | 1768 | ; http://php.net/exif.decode-unicode-motorola 1769 | ;exif.decode_unicode_motorola = UCS-2BE 1770 | 1771 | ; http://php.net/exif.decode-unicode-intel 1772 | ;exif.decode_unicode_intel = UCS-2LE 1773 | 1774 | ; http://php.net/exif.encode-jis 1775 | ;exif.encode_jis = 1776 | 1777 | ; http://php.net/exif.decode-jis-motorola 1778 | ;exif.decode_jis_motorola = JIS 1779 | 1780 | ; http://php.net/exif.decode-jis-intel 1781 | ;exif.decode_jis_intel = JIS 1782 | 1783 | [Tidy] 1784 | ; The path to a default tidy configuration file to use when using tidy 1785 | ; http://php.net/tidy.default-config 1786 | ;tidy.default_config = /usr/local/lib/php/default.tcfg 1787 | 1788 | ; Should tidy clean and repair output automatically? 1789 | ; WARNING: Do not use this option if you are generating non-html content 1790 | ; such as dynamic images 1791 | ; http://php.net/tidy.clean-output 1792 | tidy.clean_output = Off 1793 | 1794 | [soap] 1795 | ; Enables or disables WSDL caching feature. 1796 | ; http://php.net/soap.wsdl-cache-enabled 1797 | soap.wsdl_cache_enabled=1 1798 | 1799 | ; Sets the directory name where SOAP extension will put cache files. 1800 | ; http://php.net/soap.wsdl-cache-dir 1801 | soap.wsdl_cache_dir="/tmp" 1802 | 1803 | ; (time to live) Sets the number of second while cached file will be used 1804 | ; instead of original one. 1805 | ; http://php.net/soap.wsdl-cache-ttl 1806 | soap.wsdl_cache_ttl=86400 1807 | 1808 | ; Sets the size of the cache limit. (Max. number of WSDL files to cache) 1809 | soap.wsdl_cache_limit = 5 1810 | 1811 | [sysvshm] 1812 | ; A default size of the shared memory segment 1813 | ;sysvshm.init_mem = 10000 1814 | 1815 | [ldap] 1816 | ; Sets the maximum number of open links or -1 for unlimited. 1817 | ldap.max_links = -1 1818 | 1819 | [mcrypt] 1820 | ; For more information about mcrypt settings see http://php.net/mcrypt-module-open 1821 | 1822 | ; Directory where to load mcrypt algorithms 1823 | ; Default: Compiled in into libmcrypt (usually /usr/local/lib/libmcrypt) 1824 | ;mcrypt.algorithms_dir= 1825 | 1826 | ; Directory where to load mcrypt modes 1827 | ; Default: Compiled in into libmcrypt (usually /usr/local/lib/libmcrypt) 1828 | ;mcrypt.modes_dir= 1829 | 1830 | [dba] 1831 | ;dba.default_handler= 1832 | 1833 | [opcache] 1834 | ; Determines if Zend OPCache is enabled 1835 | ;opcache.enable=0 1836 | 1837 | ; Determines if Zend OPCache is enabled for the CLI version of PHP 1838 | ;opcache.enable_cli=0 1839 | 1840 | ; The OPcache shared memory storage size. 1841 | ;opcache.memory_consumption=64 1842 | 1843 | ; The amount of memory for interned strings in Mbytes. 1844 | ;opcache.interned_strings_buffer=4 1845 | 1846 | ; The maximum number of keys (scripts) in the OPcache hash table. 1847 | ; Only numbers between 200 and 100000 are allowed. 1848 | ;opcache.max_accelerated_files=2000 1849 | 1850 | ; The maximum percentage of "wasted" memory until a restart is scheduled. 1851 | ;opcache.max_wasted_percentage=5 1852 | 1853 | ; When this directive is enabled, the OPcache appends the current working 1854 | ; directory to the script key, thus eliminating possible collisions between 1855 | ; files with the same name (basename). Disabling the directive improves 1856 | ; performance, but may break existing applications. 1857 | ;opcache.use_cwd=1 1858 | 1859 | ; When disabled, you must reset the OPcache manually or restart the 1860 | ; webserver for changes to the filesystem to take effect. 1861 | ;opcache.validate_timestamps=1 1862 | 1863 | ; How often (in seconds) to check file timestamps for changes to the shared 1864 | ; memory storage allocation. ("1" means validate once per second, but only 1865 | ; once per request. "0" means always validate) 1866 | ;opcache.revalidate_freq=2 1867 | 1868 | ; Enables or disables file search in include_path optimization 1869 | ;opcache.revalidate_path=0 1870 | 1871 | ; If disabled, all PHPDoc comments are dropped from the code to reduce the 1872 | ; size of the optimized code. 1873 | ;opcache.save_comments=1 1874 | 1875 | ; If disabled, PHPDoc comments are not loaded from SHM, so "Doc Comments" 1876 | ; may be always stored (save_comments=1), but not loaded by applications 1877 | ; that don't need them anyway. 1878 | ;opcache.load_comments=1 1879 | 1880 | ; If enabled, a fast shutdown sequence is used for the accelerated code 1881 | ;opcache.fast_shutdown=0 1882 | 1883 | ; Allow file existence override (file_exists, etc.) performance feature. 1884 | ;opcache.enable_file_override=0 1885 | 1886 | ; A bitmask, where each bit enables or disables the appropriate OPcache 1887 | ; passes 1888 | ;opcache.optimization_level=0xffffffff 1889 | 1890 | ;opcache.inherited_hack=1 1891 | ;opcache.dups_fix=0 1892 | 1893 | ; The location of the OPcache blacklist file (wildcards allowed). 1894 | ; Each OPcache blacklist file is a text file that holds the names of files 1895 | ; that should not be accelerated. The file format is to add each filename 1896 | ; to a new line. The filename may be a full path or just a file prefix 1897 | ; (i.e., /var/www/x blacklists all the files and directories in /var/www 1898 | ; that start with 'x'). Line starting with a ; are ignored (comments). 1899 | ;opcache.blacklist_filename= 1900 | 1901 | ; Allows exclusion of large files from being cached. By default all files 1902 | ; are cached. 1903 | ;opcache.max_file_size=0 1904 | 1905 | ; Check the cache checksum each N requests. 1906 | ; The default value of "0" means that the checks are disabled. 1907 | ;opcache.consistency_checks=0 1908 | 1909 | ; How long to wait (in seconds) for a scheduled restart to begin if the cache 1910 | ; is not being accessed. 1911 | ;opcache.force_restart_timeout=180 1912 | 1913 | ; OPcache error_log file name. Empty string assumes "stderr". 1914 | ;opcache.error_log= 1915 | 1916 | ; All OPcache errors go to the Web server log. 1917 | ; By default, only fatal errors (level 0) or errors (level 1) are logged. 1918 | ; You can also enable warnings (level 2), info messages (level 3) or 1919 | ; debug messages (level 4). 1920 | ;opcache.log_verbosity_level=1 1921 | 1922 | ; Preferred Shared Memory back-end. Leave empty and let the system decide. 1923 | ;opcache.preferred_memory_model= 1924 | 1925 | ; Protect the shared memory from unexpected writing during script execution. 1926 | ; Useful for internal debugging only. 1927 | ;opcache.protect_memory=0 1928 | 1929 | [curl] 1930 | ; A default value for the CURLOPT_CAINFO option. This is required to be an 1931 | ; absolute path. 1932 | ;curl.cainfo = 1933 | 1934 | [openssl] 1935 | ; The location of a Certificate Authority (CA) file on the local filesystem 1936 | ; to use when verifying the identity of SSL/TLS peers. Most users should 1937 | ; not specify a value for this directive as PHP will attempt to use the 1938 | ; OS-managed cert stores in its absence. If specified, this value may still 1939 | ; be overridden on a per-stream basis via the "cafile" SSL stream context 1940 | ; option. 1941 | ;openssl.cafile= 1942 | 1943 | ; If openssl.cafile is not specified or if the CA file is not found, the 1944 | ; directory pointed to by openssl.capath is searched for a suitable 1945 | ; certificate. This value must be a correctly hashed certificate directory. 1946 | ; Most users should not specify a value for this directive as PHP will 1947 | ; attempt to use the OS-managed cert stores in its absence. If specified, 1948 | ; this value may still be overridden on a per-stream basis via the "capath" 1949 | ; SSL stream context option. 1950 | ;openssl.capath= 1951 | 1952 | ; Local Variables: 1953 | ; tab-width: 4 1954 | ; End: 1955 | -------------------------------------------------------------------------------- /php_worker.php: -------------------------------------------------------------------------------- 1 | $value) 35 | $$key = $value; 36 | 37 | // Clean up 38 | unset($request, $key, $value); 39 | 40 | // Set server signature 41 | $_SERVER['SERVER_SIGNATURE'] = 42 | "
" 43 | . $_SERVER['SERVER_SOFTWARE'] 44 | . ". With " . $_SERVER['GATEWAY_INTERFACE'] 45 | . (empty($_SERVER['SERVER_HOST']) ? '' : " at " . $_SERVER['SERVER_HOST']) 46 | . "
"; 47 | ; 48 | 49 | // Run script 50 | if(realpath($_SERVER['SCRIPT_FILENAME'])){ 51 | chdir(dirname($_SERVER['SCRIPT_FILENAME'])); 52 | require $_SERVER['SCRIPT_FILENAME']; 53 | }else{ 54 | trigger_error("File $_SERVER[SCRIPT_FILENAME] Missing", E_USER_ERROR); 55 | } 56 | 57 | ?> 58 | -------------------------------------------------------------------------------- /sphp.js: -------------------------------------------------------------------------------- 1 | /*============================================================================*\ 2 | Snappy PHP Script Launcher 3 | 4 | PHP script execution module for node 5 | Maintain a pool of ready workers for fast responcetime. 6 | 7 | Use as express middleware: 8 | app.use(sphp.express()); 9 | 10 | or direct call 11 | sphp.exec 12 | 13 | To attach to websocket server: 14 | ws.on('connection',sphp.websocket()); 15 | 16 | (c) Copyrights Paragi, Simon Riget 2013 17 | License MIT 18 | \*============================================================================*/ 19 | var fs = require('fs'); 20 | var path = require('path'); 21 | var child_process = require('child_process'); 22 | var url = require('url'); 23 | 24 | var moduleVersion = 'Snappy PHP ' + require(__dirname + path.sep + 'package.json').version; 25 | 26 | // Define module object 27 | var sphp = {}; 28 | module.exports = exports = sphp; 29 | 30 | // Initialize 31 | sphp.worker=[]; 32 | sphp.increaseTime = false; 33 | 34 | /*============================================================================*\ 35 | Express Middleware to execute a PHP script. 36 | 37 | app.use(sphp.express( | )); 38 | 39 | The script is expected to return a complete HTML response. 40 | The response will be partitioned into segments (using callback) of type: 41 | status 42 | header 43 | data (including stderr) 44 | end 45 | error 46 | 47 | \*============================================================================*/ 48 | sphp.express = function (options) { 49 | // Maintain backwards compatibility 50 | if(typeof options !== 'undefined') 51 | if(typeof options === 'object') 52 | sphp.setOptions(options); 53 | else 54 | sphp.setOptions({'docRoot': options}); 55 | 56 | // Return middleware function 57 | return function (request, response, next) { 58 | // Check file extension 59 | if (path.extname(request._parsedUrl.pathname).substring(1) !== 'php') { 60 | next(); 61 | return 0; 62 | } 63 | 64 | // Launch script 65 | sphp.exec(request, function (event, data, param) { 66 | // console.log('----Receiving ',event,' With: ',data,':',param); 67 | if (!response.finished) { 68 | switch (event) { 69 | case 'status': 70 | response.status(data); 71 | break; 72 | 73 | case 'header': 74 | if (response.headersSent) break; 75 | response.setHeader(data, param); 76 | // Handle redirect header 77 | if (data.toLowerCase() === 'location') { 78 | response.writeHead(302, {'Content-Type': 'text/plain'}); 79 | response.end('ok'); 80 | } 81 | break; 82 | 83 | case 'data': 84 | response.write(data, 'utf-8'); 85 | break; 86 | 87 | case 'end': 88 | response.end(); 89 | break; 90 | 91 | case 'error': 92 | console.error(data); 93 | response.write(data, 'utf-8'); 94 | break; 95 | 96 | default: 97 | console.error('PHP script unknown event: "%s"', event); 98 | } 99 | } 100 | }); 101 | }; 102 | }; 103 | 104 | /*============================================================================*\ 105 | Execute PHP script 106 | 107 | Start a PHP session, by deploying a prespawned worker. 108 | 109 | Using the script php_worker.php as a launcher script, to set predefined globals 110 | \*============================================================================*/ 111 | sphp.exec=function(request,callback){ 112 | var deployed=false; 113 | var freeWorker=false; 114 | 115 | // Initialize workers 116 | if(sphp.worker.length < 1) 117 | sphp.maintain(); 118 | 119 | // Check disabled for now. Is consistency really that important here? or is it 120 | // ok that PHP version is unknown to the first instanses of PHP scripts? 121 | if(false && typeof process.versions.php === 'undefined'){ 122 | console.log('PHP engine is not initialized yet. The request was droped'); 123 | return; 124 | } 125 | 126 | // Parse URL for websocket calls 127 | if(typeof request._parsedUrl === 'undefined') 128 | request._parsedUrl=url.parse(request.socket.upgradeReq.url); 129 | 130 | if(process.stdout.isTTY) 131 | console.log("Serving PHP page:", request._parsedUrl.pathname); 132 | 133 | // Check that script exists 134 | fs.exists(sphp.docRoot + request._parsedUrl.pathname, function(exists){ 135 | // Deploy worker 136 | if(exists){ 137 | // See if there is a free worker 138 | for(var i = sphp.worker.length-1; i >= 0 ; i--){ 139 | // Deploy worker 140 | if(sphp.worker[i].proc.state=='ready') { 141 | // Set state 142 | sphp.worker[i].proc.state='running'; 143 | sphp.worker[i].proc.time=Date.now(); 144 | sphp.worker[i].proc.callback = callback; 145 | 146 | //Transfer conInfo request informastion to stdin 147 | sphp.worker[i].proc.conInfo = sphp._getConInfo(request); 148 | 149 | // Attach response handlers 150 | sphp._responseHandler(sphp.worker[i],callback) 151 | 152 | // Release input to worker (Let it run) 153 | sphp.worker[i].stdin.write(JSON.stringify(sphp.worker[i].proc.conInfo)); 154 | sphp.worker[i].stdin.end(); 155 | 156 | if(process.stdout.isTTY && false) 157 | console.info("Deploying worker PID: ",sphp.worker[i].pid); 158 | 159 | deployed=true; 160 | break; 161 | } 162 | } 163 | 164 | // Too busy 165 | if(!deployed){ 166 | callback('status',503 167 | , "Sorry, too busy right now. Please try again later"); 168 | callback('end'); 169 | } 170 | 171 | // File not found 172 | }else{ 173 | callback('status',404, "Sorry, unable to locate file: " 174 | +sphp.docRoot + request._parsedUrl.pathname); 175 | callback('end'); 176 | console.info("File not found (404): " 177 | +sphp.docRoot + request._parsedUrl.pathname); 178 | } 179 | }); 180 | } 181 | 182 | /*============================================================================*\ 183 | Websocket: Attach on connection event 184 | 185 | Attach a "receive message" event handler 186 | If its a php file, execute it 187 | 188 | The options are the ones uset to setup express-session: 189 | 190 | var expressSession = require('express-session'); 191 | var sessionStore = new expressSession.MemoryStore(); 192 | var server = app.listen(8080,'0.0.0.0'); 193 | var ws = new require('ws').Server({server: server}); 194 | var sessionOptions={ 195 | store: sessionStore 196 | ,secret:'yes :c)' 197 | ,resave:false 198 | ,saveUninitialized:false 199 | ,rolling: true 200 | ,name: 'SID' 201 | } 202 | 203 | app.use(expressSession(sessionOptions)); 204 | ws.on('connection',sphp.websocket(sessionOptions)); 205 | 206 | options: store and name must be set. 207 | 208 | \*============================================================================*/ 209 | sphp.websocket = function (opt){ 210 | var sessionCookieRegExp = new RegExp('(^|;)\\s*' + opt.name + '\\s*=\\s*([^;]+)'); 211 | 212 | return function(socket,IncomingMessage) { 213 | //console.info("Client connected"); 214 | 215 | if(typeof socket.upgradeReq == 'undefined') // WS 3.0 fix 216 | socket.upgradeReq = IncomingMessage; 217 | 218 | // Handler for incomming messages 219 | socket.on('message', function(msg){ 220 | var sid; 221 | var parts; 222 | //console.info("Received ws message: ",request.body); 223 | 224 | // Create a pseudo request record 225 | var request={ 226 | socket: socket 227 | ,body: msg.toString() 228 | }; 229 | 230 | // Parse POST body as JSON to PHP 231 | //socket.upgradeReq.headers['Content-Type']="application/json"; 232 | 233 | //console.log("WS Headers: ",socket.upgradeReq.headers); 234 | 235 | // Find session cookie content, by name 236 | parts = decodeURI(socket.upgradeReq.headers.cookie).match(sessionCookieRegExp); 237 | //console.log("ws session parts: ",parts); 238 | if(parts){ 239 | request.sessionID = parts[0].split(/[=.]/)[1]; 240 | // SID is serialised. Use value between s: and . as index (SID) 241 | if(request.sessionID.substr(0,2) == 's:') 242 | request.sessionID=request.sessionID.substr(2); 243 | 244 | // Find session. Use value between s: and . as index (SID) 245 | opt.store.get(request.sessionID,function(error,data){ 246 | if(data) request.session=data; 247 | // Execute php script 248 | 249 | sphp.exec(request,function(event,data){ 250 | // Handle returned data 251 | if(event=='data' && request.socket.upgradeReq.socket.writable) 252 | request.socket.send(data); 253 | //console.log("Sending:",event,data); 254 | }); 255 | },request); 256 | 257 | // Execute PHP without session 258 | }else sphp.exec(request,function(event,data){ 259 | // Handle returned data 260 | if(event=='data' && request.socket.upgradeReq.socket.writable) 261 | request.socket.send(data); 262 | //console.log("Sending:",event,data); 263 | }); 264 | }); 265 | } 266 | } 267 | 268 | /*============================================================================*\ 269 | Set options / configure sphp 270 | 271 | set one or more options. 272 | 273 | Options array of named key values pairs. 274 | 275 | sphp.setOptions(options); 276 | All options has been set to a defauls value 277 | \*============================================================================*/ 278 | sphp.setOptions = function(option, callback){ 279 | if(typeof option !== 'object') return; 280 | 281 | // Configure/overwrite option if any 282 | sphp.docRoot = option.docRoot || sphp.docRoot; 283 | sphp.minSpareWorkers = option.minSpareWorkers || sphp.minSpareWorkers; 284 | sphp.maxWorkers = option.maxWorkers || sphp.maxWorkers; 285 | sphp.stepDowntime = option.stepDowntime || sphp.stepDowntime; 286 | sphp.overwriteWSPath = option.overwriteWSPaths || sphp.overwriteWSPath; 287 | sphp.preLoadScript = option.preLoadScript || sphp.preLoadScript; 288 | sphp.superglobals = option.superglobals || sphp.superglobals; 289 | sphp.workerScript = option.workerScript || sphp.workerScript; 290 | sphp.cgiEngine = option.cgiEngine || sphp.cgiEngine; 291 | 292 | var list = []; 293 | for(var i in sphp) 294 | if(typeof sphp[i] !=='object' && typeof sphp[i] !=='function') 295 | list[i] = sphp[i]; 296 | // console.log("Sphp options: ",list); 297 | // Get info on PHP engine. Throw fatal error if it fails. 298 | if(typeof option.cgiEngine === 'string'){ 299 | var child = child_process.spawn(option.cgiEngine, ['-v']); 300 | child.resp = ''; 301 | 302 | child.stdout.on('data', function (buffer) { 303 | child.resp += buffer.toString(); 304 | }); 305 | 306 | child.stderr.on('data', function (buffer) { 307 | child.resp += buffer.toString(); 308 | }); 309 | 310 | child.on('close', function () { 311 | process.versions.php = child.resp.split('\n')[0]; 312 | if(process.versions.php.length <1) 313 | throw new Error("PHP engine '" +sphp.cgiEngine + "' failed to start."); 314 | console.log("PHP engine: " + process.versions.php); 315 | if( typeof callback === 'function') 316 | callback(); 317 | }); 318 | 319 | child.on('error', (error) => { 320 | throw new Error('PHP engine failed to start (' + sphp.cgiEngine +')'); 321 | }); 322 | } 323 | } 324 | 325 | /*============================================================================*\ 326 | Maintain PHP workers 327 | 328 | PHP workers are preforked and kept ready, to improve response time. 329 | The number of workers are determined by the demand. When minSpareWorkers are not 330 | met do to demand, it is increased for a time. When it has not been needed for 331 | stepDownTime, it is decreased again. 332 | 333 | MinSpareWorkers: When a worker is spend (has run a script) it is terminated. If 334 | the number of spare workers are below minSpareWorkers, new workers are forked. 335 | 336 | Allocating more workers, will only improve response time up to a point. When the 337 | resources becomes depleted, the only option is to prioritise and queue the 338 | requests. 339 | 340 | MaxWorkers: the number of workers that will never be exceed. Instead, the 341 | request will be queued for maxWait time. If it expires the request are rejected. 342 | 343 | Global variables are transfered via stdin, rather than enviroment variables, in 344 | order to mimic the settings of Apache mod_php. That requires the pressens of a 345 | php script that populates GLOBALS with data from stdin. 346 | 347 | stdin is used to hold the process, until needed. 348 | 349 | The list of workers are ordered with the oldest last, so that length reflects 350 | the actual number of workers (Using add=>unshift delete=>splice) 351 | 352 | Worker array objects layout: 353 | state: enum ready, running, spend 354 | time: of last state change 355 | proc: handle to spawned process 356 | cminSpareWorkers: current dynamic minimum of spare workers 357 | increaseTime: Time that i changed 358 | 359 | \*============================================================================*/ 360 | sphp.maintain = function(){ 361 | 362 | var spares = 0, workers = 0; 363 | 364 | if(typeof sphp.cminSpareWorkers === 'undefined') 365 | sphp.cminSpareWorkers = sphp.minSpareWorkers; 366 | 367 | // Count free workers 368 | for(var i in sphp.worker){ 369 | if(sphp.worker[i].proc.state == 'ready') spares++ 370 | if(sphp.worker[i].proc.state == 'dead') 371 | sphp.worker.splice(i,1); 372 | else 373 | workers++; 374 | } 375 | 376 | if(sphp.cminSpareWorkers < sphp.minSpareWorkers) 377 | sphp.cminSpareWorkers = sphp.minSpareWorkers; 378 | 379 | // increase number of workers 380 | if(spares<1 && workers < sphp.maxWorkers){ 381 | if(sphp.increaseTime) sphp.cminSpareWorkers++; 382 | sphp.increaseTime = Date.now(); 383 | 384 | // Decrease number of workers 385 | }else if(Date.now() - sphp.increaseTime>sphp.stepDowntime * 1000) { 386 | if(sphp.cminSpareWorkers > sphp.minSpareWorkers) sphp.cminSpareWorkers--; 387 | sphp.increaseTime = Date.now(); 388 | } 389 | 390 | // Start spare workers 391 | var option = {cwd: sphp.docRoot, env: process.env}; 392 | 393 | if(sphp.preLoadScript) 394 | option.env.preload = sphp.docRoot + path.sep + sphp.preLoadScript; 395 | 396 | for(; spares < sphp.cminSpareWorkers && workers < sphp.maxWorkers; spares++){ 397 | // Start child process and Append worker to array 398 | sphp.worker.unshift( 399 | child_process.spawn( 400 | sphp.cgiEngine 401 | ,[sphp.workerScript] 402 | ,option 403 | ) 404 | ); 405 | 406 | // Attach end of process event 407 | sphp.worker[0].on('exit' , handleExit ); 408 | sphp.worker[0].on('close', handleExit ); 409 | sphp.worker[0].on('error', handleExit ); 410 | 411 | // Some process settings 412 | sphp.worker[0].stderr.setEncoding('utf-8'); 413 | sphp.worker[0].stdout.setEncoding('utf-8'); 414 | sphp.worker[0].stdout.parent = sphp.worker[0]; 415 | sphp.worker[0].stderr.parent = sphp.worker[0]; 416 | sphp.worker[0].proc = { 417 | state: 'ready' 418 | ,time: Date.now() 419 | ,outBuffer: '' 420 | ,errorBuffer: '' 421 | } 422 | 423 | if(!sphp.worker[0].pid) return; 424 | 425 | // Make temporary listners for output (Errors) 426 | sphp.worker[0].stdout.on('data', function(data) { 427 | if(sphp.worker[0].proc.outBuffer.length < 4096) 428 | sphp.worker[0].proc.outBuffer += data.toString(); 429 | }); 430 | 431 | sphp.worker[0].stderr.on('data', function(data) { 432 | if(this.parent.proc.errorBuffer.length < 4096) 433 | this.parent.proc.errorBuffer += data.toString(); 434 | }); 435 | 436 | workers++; 437 | } 438 | 439 | function handleExit(report) { 440 | if(report && (typeof this.proc === 'undefined' || this.proc.state=='ready')){ 441 | //console.log("Exit handler:", report); 442 | var str = "Failed to start PHP worker." 443 | str += "\n PHP engine: " + sphp.cgiEngine; 444 | str += "\n PHP engine version: " + process.versions.php; 445 | str += "\n Worker script: " + sphp.workerScript; 446 | //str += "\n Worker PID: "+worker.pid; 447 | str+="\n Error: " + report; 448 | if(this.proc.errorBuffer.length || this.proc.outBuffer.length){ 449 | str += "\n Script error message: " 450 | str += "\n" + this.proc.outBuffer 451 | str += "\n" + this.proc.errorBuffer; 452 | } 453 | this.proc.state="dead"; 454 | throw new Error(str); 455 | } 456 | if(this.proc.state!='dead') 457 | process.nextTick(sphp.maintain); 458 | } 459 | 460 | // report on workers 461 | if(process.stdout.isTTY && false){ 462 | console.info(("=").repeat(80)); 463 | console.info( 464 | "PHP Workers spares:" 465 | ,spares 466 | ," min:" 467 | ,sphp.cminSpareWorkers 468 | ," Max:" 469 | ,sphp.maxWorkers 470 | ); 471 | 472 | workers=0; spares=0; 473 | for(var i in sphp.worker){ 474 | workers++; 475 | console.info(i,"PID:",sphp.worker[i].pid," State:",sphp.worker[i].proc.state 476 | ," age:",+(Date.now()-sphp.worker[i].proc.time)/1000+" Seconds"); 477 | // Find free workers 478 | if(sphp.worker[i].state=='ready') spares++ 479 | } 480 | console.info(("=").repeat(80)); 481 | } 482 | } 483 | 484 | /*============================================================================*\ 485 | Handle output from the spawned process 486 | 487 | request body part and other information are parsed through stdin, to the php 488 | process. body including multipart are interpreted by the server, before parsing 489 | it to the cgi. 490 | Node provides for the uploaded files to be stored. they only need to be renamed 491 | and information passed. 492 | 493 | on reveiving data on stdid, all input is treated as headers, until end of 494 | header section is send (double windows end of line: \n\r\n\r) 495 | 496 | Data are received in multi part blocks, with no regard to the content. 497 | eg. a data block might contain both headers, [end of header] and body 498 | 499 | The receiving callback function must have data separated in: 500 | status, header, data, error and end request. 501 | 502 | Status 200 OK is assumed, if not set. 503 | 504 | Note: if header contains a redirect (Location) the status must be set accordingly 505 | 506 | Quirks: 507 | 1. php-cgi might send error text formatted in HTML before the headers 508 | Fix: 1. error messages are stores until headers are send. 509 | 2. a default header of Content-type: text/html (overwritten if other)) 510 | 2. php-cgi might send a header in one block and the line ending in another 511 | Fix: buffer all headers until end of header section are received 512 | 3. the phpinfo() function requests pseudo pages for logo images. 513 | 514 | for strange 404 see http://woozle.org/~neale/papers/php-cgi.html 515 | 516 | \*============================================================================*/ 517 | sphp._responseHandler= function (worker,callback){ 518 | worker.proc.outBuffer=''; 519 | worker.proc.errorBuffer=''; 520 | worker.proc.headersSent = false; 521 | worker.proc.headers=''; 522 | 523 | // Remove listners for workers in idle state 524 | worker.stdout.removeAllListeners('data'); 525 | worker.stderr.removeAllListeners('data'); 526 | worker.removeAllListeners('error'); 527 | worker.removeAllListeners('exit'); 528 | worker.removeAllListeners('close'); 529 | 530 | // Catch output from script and send it to client 531 | worker.stdout.on('data', function(data){ 532 | var worker = this.parent; 533 | var redirect = false; 534 | if(worker.proc.state != 'running') return; 535 | if(!worker.proc.headersSent){ 536 | // Store headers until a end of header is received (\r\n\r\n) 537 | worker.proc.headers += data.toString(); 538 | 539 | // Pre-process headers: divide headers into lines and separate body data 540 | var eoh = worker.proc.headers.indexOf('\r\n\r\n'); 541 | var eohLen = 4; 542 | if(eoh <= 0){ 543 | eoh = worker.proc.headers.indexOf('\n\n'); 544 | eohLen = 2; 545 | } 546 | 547 | if(eoh >= 0){ 548 | var line = worker.proc.headers.substr(0,eoh).split('\n'); 549 | var div; 550 | for(var i in line){ 551 | // Split header line into key, value pair 552 | div = line[i].indexOf(":"); 553 | if(div>0){ 554 | var key = line[i].substr(0,div); 555 | var value = line[i].substr(div+2).replace("\r",""); 556 | // console.log("Sending header 1:",key,":",value); 557 | callback('header',key,value); 558 | } 559 | } 560 | worker.proc.headersSent = true; 561 | 562 | // Handle redirect location header 563 | // Send body part if any 564 | if(worker.proc.headers.length>eoh+eohLen){ 565 | callback('data',worker.proc.headers.substr(eoh+eohLen)); 566 | } 567 | } 568 | 569 | // Body 570 | }else{; 571 | callback('data',data.toString()); 572 | } 573 | }); 574 | 575 | // Error. Catch standard error output from script (but don't send it until the end) 576 | worker.stderr.on('data', (function(worker,callback){ 577 | return function (data) { 578 | if(worker.proc.errorBuffer.length < 4096) 579 | worker.proc.errorBuffer += data.toString(); 580 | }; 581 | })(worker,callback)); 582 | 583 | worker.stdout.on('close', (function(worker,callback){ 584 | return function () { endWithGrace(worker,callback); }; 585 | })(worker,callback)); 586 | 587 | worker.stderr.on('close', (function(worker,callback){ 588 | return function () { endWithGrace(worker,callback); }; 589 | })(worker,callback)); 590 | 591 | worker.on('exit', (function(worker,callback){ 592 | return function () { endWithGrace(worker,callback); }; 593 | })(worker,callback)); 594 | 595 | worker.on('error', (function(worker,callback){ 596 | return function () { endWithGrace(worker,callback); }; 597 | })(worker,callback)); 598 | 599 | function endWithGrace(worker,callback){ 600 | if(worker.proc.state == 'running'){ 601 | worker.proc.state = 'dead'; 602 | if(!worker.proc.headersSent){ 603 | callback('header','Content-type','text/html'); // Fix 1 604 | var eoh = worker.proc.headers.indexOf('\r\n\r\n'); 605 | if(eoh >= 0 && worker.proc.headers.length > eoh+4) 606 | callback('data',worker.proc.headers.substr(eoh+4)); 607 | } 608 | if(worker.proc.outBuffer.length) callback('data',worker.proc.outBuffer); 609 | if(worker.proc.errorBuffer.length) callback('error',worker.proc.errorBuffer); 610 | callback('end'); 611 | process.nextTick(sphp.maintain); 612 | } 613 | } 614 | } 615 | 616 | /*============================================================================*\ 617 | Compose a connection information record on client request 618 | 619 | ┌─────────────────────────────────────────────────────────────────────────────────────────────┐ 620 | │ href │ 621 | ├──────────┬──┬─────────────────────┬─────────────────────┬───────────────────────────┬───────┤ 622 | │ protocol │ │ auth │ host │ path │ hash │ 623 | │ │ │ ├──────────────┬──────┼──────────┬────────────────┤ │ 624 | │ │ │ │ hostname │ port │ pathname │ search │ │ 625 | │ │ │ │ │ │ ├─┬──────────────┤ │ 626 | │ │ │ │ │ │ │ │ query │ │ 627 | " https: // user : pass @ sub.host.com : 8080 /p/a/t/h ? query=string #hash " 628 | │ │ │ │ │ hostname │ port │ │ │ │ 629 | │ │ │ │ ├──────────────┴──────┤ │ │ │ 630 | │ protocol │ │ username │ password │ host │ │ │ │ 631 | ├──────────┴──┼──────────┴──────────┼─────────────────────┤ │ │ │ 632 | │ origin │ │ origin │ pathname │ search │ hash │ 633 | ├─────────────┴─────────────────────┴─────────────────────┴──────────┴────────────────┴───────┤ 634 | │ URI │ 635 | ├─────────────────────────────────────────────────────────┬───────────────────────────┬───────┤ 636 | │ │ URL │ │ 637 | └─────────────────────────────────────────────────────────┴───────────────────────────┴───────┘ 638 | 639 | REMOTE_PORT = socket.remotePort 640 | REMOTE_ADDR = socket.remoteAddress 641 | DOCUMENT_ROOT = File system full path to root of hosted files. 642 | SCRIPT_NAME = pathname: path relative to document root, with filename and extention 643 | PHP_SELF = SCRIPT_NAME; 644 | SCRIPT_FILENAME = DOCUMENT_ROOT + SCRIPT_NAME 645 | SERVER_HOST = host (with port) 646 | SERVER_NAME = hostname (SERVER_HOST without port) 647 | \*============================================================================*/ 648 | sphp._getConInfo=function(request){ 649 | // Copy predefined super globals 650 | var conInfo = JSON.parse(JSON.stringify(sphp.superglobals)); 651 | var extReq; 652 | 653 | /*==========================================================================*\ 654 | Websocket request 655 | \*==========================================================================*/ 656 | if(typeof request.socket == 'object' 657 | && typeof request.socket.upgradeReq != 'undefined' 658 | && typeof request.socket.upgradeReq.headers != 'undefined'){ 659 | 660 | extReq = request.socket.upgradeReq; 661 | conInfo._SERVER.REMOTE_PORT = request.socket._socket.remotePort || ''; 662 | conInfo._SERVER.REMOTE_ADDR = request.socket._socket.remoteAddress || ''; 663 | conInfo._SERVER.REQUEST_METHOD = 'websocket'; 664 | conInfo._GET = url.parse(request.socket.upgradeReq.url, true).query; 665 | 666 | /*==========================================================================*\ 667 | basic HTTP request 668 | \*==========================================================================*/ 669 | }else{ 670 | extReq = request; 671 | if(typeof request.client == 'object'){ 672 | conInfo._SERVER.REMOTE_ADDR = request.client.remoteAddress || ''; 673 | conInfo._SERVER.REMOTE_PORT = request.client.remotePort || ''; 674 | } 675 | conInfo._SERVER.REQUEST_METHOD = request.method || ''; 676 | conInfo._GET = request.query || {}; 677 | conInfo._FILES = {}; 678 | for(var f in request.files){ 679 | conInfo._FILES[f]={}; 680 | conInfo._FILES[f].name=request.files[f].name; 681 | conInfo._FILES[f].size=request.files[f].size; 682 | conInfo._FILES[f].tmp_name=request.files[f].path; 683 | conInfo._FILES[f].type=request.files[f].type; 684 | } 685 | } 686 | 687 | /*==========================================================================*\ 688 | // Non method specifics 689 | \*==========================================================================*/ 690 | conInfo._SERVER.SERVER_PROTOCOL = 691 | extReq.httpVersion ? "HTTP/" + extReq.httpVersion : ''; 692 | 693 | conInfo._SERVER.DOCUMENT_ROOT = path.resolve(sphp.docRoot); 694 | 695 | if(request._parsedUrl){ 696 | conInfo._SERVER.REQUEST_URI = request._parsedUrl.href; 697 | conInfo._SERVER.QUERY_STRING = request._parsedUrl.query; 698 | 699 | // Does this work in windows !? 700 | conInfo._SERVER.SCRIPT_NAME = request._parsedUrl.pathname || '/'; 701 | if(conInfo._SERVER.SCRIPT_NAME.charAt(0) != '/') 702 | conInfo._SERVER.SCRIPT_NAME = '/' + conInfo._SERVER.SCRIPT_NAME; 703 | conInfo._SERVER.PHP_SELF = conInfo._SERVER.SCRIPT_NAME; 704 | conInfo._SERVER.SCRIPT_FILENAME = conInfo._SERVER.DOCUMENT_ROOT 705 | + conInfo._SERVER.SCRIPT_NAME; 706 | 707 | if(request._parsedUrl.host) 708 | conInfo._SERVER.SERVER_HOST = request._parsedUrl.host; 709 | } 710 | 711 | if(typeof extReq.headers === 'object') 712 | for(var key in extReq.headers) 713 | conInfo._SERVER['HTTP_' + key.toUpperCase().replace('-','_')] 714 | = extReq.headers[key]; 715 | 716 | if(typeof conInfo._SERVER.HTTP_REFERER !== 'undefined'){ 717 | var refererUrl = url.parse(conInfo._SERVER.HTTP_REFERER); 718 | conInfo._SERVER.SERVER_PORT = refererUrl.port; 719 | conInfo._SERVER.SERVER_ADDR = refererUrl.hostname; 720 | if(typeof conInfo._SERVER.SERVER_NAME === 'undefined' 721 | || conInfo._SERVER.SERVER_NAME.length == 0) 722 | conInfo._SERVER.SERVER_NAME = refererUrl.hostname; 723 | } 724 | 725 | if(typeof conInfo._SERVER.HTTP_COOKIE !== 'undefined'){ 726 | conInfo._SERVER.HTTP_COOKIE_PARSE_RAW = conInfo._SERVER.HTTP_COOKIE; 727 | var line = conInfo._SERVER.HTTP_COOKIE_PARSE_RAW.split(';'); 728 | for(var i in line){ 729 | var cookie = line[i].split('='); 730 | if(cookie.length >0) 731 | conInfo._COOKIE[cookie[0].trim()] = cookie[1].trim(); 732 | } 733 | } 734 | 735 | if(typeof request.body !== 'object' && request.body) 736 | try{ 737 | conInfo._POST = JSON.parse(request.body); 738 | }catch(e){} 739 | else 740 | conInfo._POST = request.body || {}; 741 | 742 | conInfo._REQUEST = Object.assign({}, conInfo._GET, conInfo._POST, conInfo._COOKIE); 743 | 744 | if(request.session) 745 | conInfo._SERVER.SESSION = request.session; 746 | 747 | return conInfo; 748 | } 749 | 750 | // Set defaults 751 | sphp.setOptions({ 752 | docRoot: path.resolve("." + path.sep + 'public') 753 | ,minSpareWorkers: 10 754 | ,maxWorkers: 20 755 | ,stepDowntime: 360 756 | ,overwriteWSPath: null 757 | ,cgiEngine: 'php-cgi' + (/^win/.test(process.platform) ? '.exe' : '') 758 | ,workerScript: __dirname + path.sep + 'php_worker.php' 759 | ,superglobals: { 760 | _POST: {}, 761 | _GET: {}, 762 | _FILES: {}, 763 | _SERVER: { 764 | GATEWAY_INTERFACE: moduleVersion, 765 | SERVER_SOFTWARE: 'PHP Appilation Server using Node.js and WS Websockets', 766 | SERVER_NAME: 'localhost' 767 | }, 768 | _COOKIE: {} 769 | } 770 | }); 771 | -------------------------------------------------------------------------------- /test/doc_root/phpinfo.php: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /test/doc_root/subdir/required-phpinfo.php: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /test/testexpress.js: -------------------------------------------------------------------------------- 1 | /* jshint -W097 */// jshint strict:false 2 | /*jslint node: true */ 3 | var expect = require('chai').expect; 4 | var path = require('path'); 5 | var request = require('request'); 6 | 7 | var express = require('express'); 8 | var sphp = require('../sphp'); 9 | var expressSession = require('express-session'); 10 | var bodyParser = require('body-parser'); 11 | var _ws = require('ws'); 12 | 13 | var serving = false; 14 | describe('Test Express server', function() { 15 | before('Setup Server', function (_done) { 16 | this.timeout(600000); // because of first install from npm 17 | 18 | var doc_root = __dirname + path.sep + 'doc_root'; 19 | var sessionStore = new expressSession.MemoryStore(); 20 | var sessionOptions={ 21 | store: sessionStore 22 | ,secret:'yes :c)' 23 | ,resave:false 24 | ,saveUninitialized:false 25 | ,rolling: true 26 | ,name: 'SID' 27 | } 28 | var app = express(); 29 | if (process.env.PHP_PATH && process.env.PHP_PATH !== "") { 30 | sphp.setOptions({docRoot: doc_root, cgiEngine: process.env.PHP_PATH}); 31 | console.log('SPHP Use cgiEngine ' + sphp.cgiEngine); 32 | } 33 | 34 | var server = app.listen(20000, function() { 35 | console.log('SPHP Server started on port 20000 with Doc-Root ' + doc_root); 36 | serving = true; 37 | }); 38 | 39 | var ws = new _ws.Server({server: server}); 40 | app.use(expressSession(sessionOptions)); 41 | app.use(bodyParser.json()); 42 | app.use(bodyParser.urlencoded({extended: true})); 43 | ws.on('connection',sphp.websocket(sessionOptions)); 44 | 45 | app.use(sphp.express(doc_root)); 46 | app.use(express.static(doc_root)); 47 | 48 | _done(); 49 | }); 50 | 51 | it('Test phpinfo()', function (done) { 52 | request('http://127.0.0.1:20000/phpinfo.php', function (error, response, body) { 53 | console.log('BODY: ' + body); 54 | expect(serving).to.be.true; 55 | expect(error).to.be.not.ok; 56 | expect(body.indexOf('phpinfo()')).to.be.not.equal(-1); 57 | expect(response.statusCode).to.equal(200); 58 | done(); 59 | }); 60 | }); 61 | 62 | it('Test required-phpinfo()', function (done) { 63 | request('http://127.0.0.1:20000/subdir/required-phpinfo.php', function (error, response, body) { 64 | console.log('BODY: ' + body); 65 | expect(serving).to.be.true; 66 | expect(error).to.be.not.ok; 67 | expect(body.indexOf('phpinfo()')).to.be.not.equal(-1); 68 | expect(response.statusCode).to.equal(200); 69 | done(); 70 | }); 71 | }); 72 | 73 | after('Stop Server', function (done) { 74 | this.timeout(10000); 75 | try { 76 | if (serving) { 77 | app.close(); 78 | console.log('SPHP Server stopped'); 79 | } 80 | } catch (e) { 81 | } 82 | done(); 83 | }); 84 | }); 85 | --------------------------------------------------------------------------------