├── .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 |
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 | ; and ?> 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 = shorthand tag, which can be
198 | ; used regardless of this directive.
199 | ; Default Value: On
200 | ; Development Value: Off
201 | ; Production Value: Off
202 | ; http://php.net/short-open-tag
203 | short_open_tag = On
204 |
205 | ; Allow ASP-style <% %> 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 |
--------------------------------------------------------------------------------