server_stats.php

Chris Boulton, 06/04/2009 06:17 pm

Download (11.4 kB)

 
1
<?php
2
/**
3
* This file sends anonymous stats about modules that a server has installed and versions of those modules.
4
*
5
* serverStats_Send will return an associative array with the options for you to use on your project. The
6
* array contain the following keys:
7
*  InfoSent Boolean that tells if the information was sent through CURL or FOpen. If he information is
8
*  sent properly, InfoSent is set to true. Otherwise, it is set to false.
9
*  InfoQueryString String that contains the stats
10
*  InfoImage String with an image tag to send the stats
11
* So if the info can't be sent through curl or fopen, you still have the options to put out an image (which
12
* you just need to include in your template somewhere) or store the data in any other way you may find
13
* convenient.
14
*
15
* Example:
16
* <code>
17
* require_once('server_stats.php');
18
* $sending = serverStats_Send(0, '', 'NX 1.3.2', 'WE');
19
* if ($sending['InfoSent'] === false) {
20
*  $GLOBALS['InfoImage'] = $sending['InfoImage'];
21
* }
22
* </code>
23
*/
24
25
/**
26
* serverStats_Send
27
* Works out the modules you have installed and attempts to send the info across to the other server for recording.
28
*
29
* @param Mixed $installtype An install type of '0' is a fresh install. An install type of '1' is an upgrade. Or alternatively, pass in 'install' or 'upgrade'.
30
* @param String $prev_version The version the upgrade is from if applicable.
31
* @param String $current_version The new version for the upgrade or fresh install.
32
* @param String $product_name The name of the product that is being installed.
33
*
34
* @return Array An associative array with the following keys
35
*  InfoSent Boolean If the info was sent through CURL or fopen
36
*  InfoQueryString String The data to be collected from the server
37
*  InfoImage Boolean The image tag with the data to be collected, like <img src='http://server-stats.info/blank.gif?".$string."' />
38
*/
39
function serverStats_Send($installtype=0, $prev_version='', $current_version='', $product_name='', $charset='')
40
{
41
        if ($installtype === 'install') {
42
                $installtype = 0;
43
        }
44
45
        if ($installtype === 'upgrade') {
46
                $installtype = 1;
47
        }
48
49
        # making sure its either an install or upgrade, must be one or the other
50
        if($installtype !== 0 && $installtype !== 1) {
51
                $installtype = 0;
52
        }
53
54
        # parse the PHP Info to get module information
55
        $phpinfo = _serverStats_ParsePHPModules();
56
57
        # check php info
58
        $info['php'] = phpversion();
59
60
        #check the mysql version
61
        $info['mysql'] = $phpinfo['mysql']['Client API version'];
62
63
        # check the postgresql version
64
        $info['pgsql'] = 0;
65
        if (isset($phpinfo['pgsql'])) {
66
                $info['pgsql'] = $phpinfo['pgsql']['PostgreSQL(libpq) Version'];
67
        }
68
69
        # check for sqlite
70
        $info['sqlite'] = 0;
71
        if(isset($phpinfo['sqlite'])) {
72
                $info['sqlite'] = $phpinfo['sqlite']['SQLite Library'];
73
        }
74
75
        # check for mbstring
76
        $info['mbstring'] = 0;
77
        if(isset($phpinfo['mbstring'])) {
78
                $info['mbstring'] = 1;
79
        }
80
81
        # curl check
82
        $info['curl'] = 0;
83
        if(function_exists('curl_init')) {
84
                $info['curl'] = 1;
85
        }
86
87
        # curl check
88
        $info['exif'] = 0;
89
        if(isset($phpinfo['exif'])) {
90
                $info['exif'] = 1;
91
        }
92
93
        # check their charset being used
94
        $info['charset'] = $charset;
95
96
        # check for iconv, also check the lib version
97
        $info['iconv'] = '';
98
        if(function_exists('iconv')) {
99
                $info['iconv'] = 1;
100
        }
101
102
        if(isset($phpinfo['iconv'])) {
103
                $info['iconvlib'] = $phpinfo['iconv']["iconv implementation"] . '|' . $phpinfo['iconv']["iconv library version"];
104
        } else {
105
                $info['iconvlib'] = '0';
106
        }
107
108
        # check for GD, return the version if so
109
        if (isset($phpinfo['gd'])) {
110
                $info['gd'] = $phpinfo['gd']["GD Version"];
111
        }else{
112
                $info['gd'] = '0';
113
        }
114
115
        # check for GD, return the version if so
116
        if(isset($phpinfo['gd'])) {
117
                $info['gd'] = $phpinfo['gd']["GD Version"];
118
        } else {
119
                $info['gd'] = '0';
120
        }
121
122
        # check cgi mode
123
        $sapi_type = php_sapi_name();
124
125
        if(strpos($sapi_type, 'cgi') !== false) {
126
                $info['cgimode'] = '1';
127
        }
128
        else {
129
                $info['cgimode'] = '0';
130
        }
131
132
        $info['serversoftware']     = $_SERVER["SERVER_SOFTWARE"];
133
        $info['allow_fopen_url']    = (!(bool)ini_get('safe_mode') && ini_get('allow_url_fopen'));
134
135
        $info['safe_mode'] = 0;
136
        if((bool)ini_get('safe_mode')) {
137
                $info['safe_mode'] = 1;
138
        }
139
140
        $info['postsize']        = ini_get('post_max_size');
141
        $info['uploadsize'] = ini_get('upload_max_filesize');
142
143
        $info['doccorrect'] = 0;
144
        if(_serverStats_CheckDocRoot()) {
145
                $info['doccorrect'] = 1;
146
        }
147
148
        $info['zlib'] = 0;
149
        if(isset($phpinfo['zlib'])) {
150
                $info['zlib'] = 1;
151
        }
152
153
        $info['installtype'] = $installtype;
154
        $info['prev'] = (empty($prev_version)) ? '0' : $prev_version;
155
        $info['new']  = $current_version;
156
        $info['app']  = $product_name;
157
158
        $info['hosturl'] = $info['hostname'] = 'unknown/local';
159
        if ($_SERVER['HTTP_HOST'] == 'localhost') {
160
                $info['hosturl'] = $info['hostname'] = 'localhost';
161
        }
162
163
        if (strpos($_SERVER['HTTP_HOST'], '.') !== false) {
164
                $host_url = 'http://www.whoishostingthis.com/' . $_SERVER['HTTP_HOST'];
165
166
                $hosting = _serverStats_UrlOpen($host_url);
167
168
                if ($hosting) {
169
                        preg_match_all('#'.preg_quote('is hosted by:<br />', '#').'[\n\r]*'.preg_quote('<b><a ', '#').'(title="([^"]*)" )?'.preg_quote('href="/linkout/?t=', '#') .'[0-9]'.preg_quote('&amp;url=', '#') .'([^"]*)" (title="([^"]*)" )?rel="external">([^<]*)'.preg_quote('</a>', '#').'#ism', $hosting, $matches);
170
171
                        if (isset($matches[3][0]) && strlen(trim($matches[3][0])) != 0) {
172
                                $info['hosturl'] = strtolower($matches[3][0]);
173
                        }else{
174
                                $info['hosturl'] = 'unknown/no-url';
175
                        }
176
177
                        if (isset($matches[6][0]) && strlen(trim($matches[6][0])) != 0) {
178
                                $info['hostname'] = $matches[6][0];
179
                        } elseif(isset($matches[5][0]) && strlen(trim($matches[5][0])) != 0) {
180
                                $info['hostname'] = $matches[5][0];
181
                        } elseif(isset($matches[4][0]) && strlen(trim($matches[4][0])) != 0) {
182
                                $info['hostname'] = str_replace(array('title=', '"'), '', $matches[4][0]);
183
                        } elseif(isset($matches[1][0]) && strlen(trim($matches[1][0])) != 0) {
184
                                $info['hostname'] = str_replace(array('title=', '"'), '', $matches[1][0]);
185
                        } elseif(strlen(trim($info['hosturl'])) != 0 && $info['hosturl'] != 'unknown/no-url') {
186
                                $info['hostname'] = $info['hosturl'];
187
                        } else {
188
                                $info['hostname'] = 'unknown/no-name';
189
                        }
190
                }
191
        }
192
193
        $functionsToCheck = array(
194
                'sockets' => 'fsockopen',
195
                'mcrypt' => 'mcrypt_encrypt',
196
                'simplexml' => 'simplexml_load_string',
197
                'ldap' => 'ldap_connect',
198
                'mysqli' => 'mysqli_connect',
199
                'imap' => 'imap_open',
200
                'ftp' => 'ftp_login',
201
                'pspell' => 'pspell_new',
202
                'apc' => 'apc_cache_info'
203
        );
204
205
        foreach($functionsToCheck as $what => $function) {
206
                if(function_exists($function)) {
207
                        $info[$what] = 1;
208
                }
209
                else {
210
                        $info[$what] = 0;
211
                }
212
        }
213
214
        $classesToCheck = array(
215
                'dom' => 'DOMElement',
216
                'soap' => 'SoapClient',
217
                'xmlwriter' => 'XMLWriter',
218
                'imagemagick' => 'Imagick',
219
        );
220
221
        foreach($classesToCheck as $what => $class) {
222
                if(class_exists($class)) {
223
                        $info[$what] = 1;
224
                }
225
                else {
226
                        $info[$what] = 0;
227
                }
228
        }
229
230
        $extensionsToCheck = array(
231
                'zendopt' => 'Zend Optimizer',
232
                'xcache' => 'XCache',
233
                'eaccelerator' => 'eAccelerator',
234
                'ioncube' => 'ionCube Loader',
235
                'PDO' => 'PDO',
236
                'pdo_mysql' => 'pdo_mysql',
237
                'pdo_pgsql' => 'pdo_pgsql',
238
                'pdo_sqlite' => 'pdo_sqlite',
239
                'pdo_oci' => 'pdo_oci',
240
                'pdo_odbc' => 'pdo_odbc',
241
        );
242
        foreach($extensionsToCheck as $what => $extension) {
243
                if(extension_loaded($extension)) {
244
                        $info[$what] = 1;
245
                }
246
                else {
247
                        $info[$what] = 0;
248
                }
249
        }
250
251
        if(isset($_SERVER['HTTP_USER_AGENT'])) {
252
                $info['useragent'] = $_SERVER['HTTP_USER_AGENT'];
253
        }
254
255
        $string = '';
256
257
        foreach ($info as $key=>$value) {
258
                $string .= $key. '=' .urlencode($value).'&';
259
        }
260
261
        /**
262
        * We need a unique ID for the host
263
        * if we sha1 it here, the ID will always be the same
264
        * but no one will know what the host name is
265
        * so it preserves the privacy of the user
266
        * sha1() is the best for this, but if its not aval, md5() is
267
        * almost as good.
268
        */
269
        if ($_SERVER['HTTP_HOST'] == "localhost") {
270
                $_id = $_SERVER['HTTP_HOST']. time();
271
        }else{
272
                $_id = $_SERVER['HTTP_HOST'];
273
        }
274
275
        if (function_exists('sha1')) {
276
                $string .= 'id='. sha1($_id);
277
        }else{
278
                $string .= 'id='. md5($_id);
279
        }
280
281
        $server_stats_url = 'http://server-stats.info/stats.php?'.$string;
282
283
        $ret = array();
284
        $ret['InfoSent'] = _serverStats_UrlOpen($server_stats_url);
285
        $ret['InfoImage'] = "<img src='http://server-stats.info/blank.gif?".$string."' />";
286
        $ret['InfoQueryString'] = $string;
287
288
        return $ret;
289
}
290
291
/**
292
* _serverStats_UrlOpen
293
* Opens the url passed in and returns the output that the url returns.
294
* Checks for curl support first and uses that if it's available.
295
* If curl support isn't available, then it tries to use fopen.
296
* If that's not available, it will return false.
297
*
298
* If curl fails, it tries to use fopen.
299
* If fopen fails, it returns false.
300
*
301
* @param String $url The url to 'open'.
302
*
303
* @return Mixed Returns false if you don't provide a url, or if the url can't be opened. Otherwise returns the data from the url provided.
304
*/
305
function _serverStats_UrlOpen($url='')
306
{
307
        if (!$url) {
308
                return false;
309
        }
310
311
        if (function_exists('curl_init')) {
312
                if ($ch = @curl_init()) {
313
                        curl_setopt($ch, CURLOPT_URL, $url);
314
                        //curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
315
                        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
316
                        curl_setopt($ch, CURLOPT_FAILONERROR, true);
317
                        curl_setopt($ch, CURLOPT_TIMEOUT, 10);
318
                        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
319
                        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
320
321
                        $data = curl_exec($ch);
322
                        curl_close($ch);
323
                        return $data;
324
                }
325
        }
326
327
        if (ini_get('allow_url_fopen')) {
328
                $data = '';
329
                if ($fp = @fopen($url, 'rb')) {
330
                        while (!@feof($fp)) {
331
                                $data .= @fgets($fp, 4096);
332
                        }
333
                        @fclose($fp);
334
                        return $data;
335
                }
336
                return false;
337
        }
338
339
        return false;
340
}
341
342
/**
343
* _serverStats_CheckDocRoot
344
* Checks whether the document root is set up correctly.
345
* It will return false if there is no document root, or it's empty
346
* It will also return false if the current file (using __FILE__) is reportedly outside the server's document root.
347
* If all of that works out ok, this will return true.
348
*
349
* @return Boolean Returns true or false based on the built in checks.
350
*/
351
function _serverStats_CheckDocRoot()
352
{
353
        if (!isset($_SERVER['DOCUMENT_ROOT'])) {
354
                return false;
355
        }
356
357
        if ($_SERVER['DOCUMENT_ROOT']=='') {
358
                return false;
359
        }
360
361
        $s = str_replace('\\','/', $_SERVER['DOCUMENT_ROOT']);
362
        $f = str_replace('\\','/', __FILE__);
363
        $check = strpos(strtolower($f), strtolower($s));
364
        if (!is_numeric($check) || $check === false) {
365
                return false;
366
        }
367
368
        if ($check != 0) {
369
                return false;
370
        }
371
372
        return true;
373
}
374
375
/**
376
* serverStats_ParsePHPModules
377
* Function to grab the list of PHP modules installed
378
*
379
* @return Array An associative array of all the modules installed for PHP
380
*/
381
function _serverStats_ParsePHPModules()
382
{
383
        ob_start();
384
        phpinfo(INFO_MODULES);
385
        $s = ob_get_contents();
386
        ob_end_clean();
387
388
        $s = strip_tags($s,'<h2><th><td>');
389
        $s = preg_replace('/<th[^>]*>([^<]+)<\/th>/',"<info>\\1</info>",$s);
390
        $s = preg_replace('/<td[^>]*>([^<]+)<\/td>/',"<info>\\1</info>",$s);
391
        $vTmp = preg_split('/(<h2[^>]*>[^<]+<\/h2>)/',$s,-1,PREG_SPLIT_DELIM_CAPTURE);
392
        $vModules = array();
393
        for ($i=1;$i<count($vTmp);$i++) {
394
                if (preg_match('/<h2[^>]*>([^<]+)<\/h2>/',$vTmp[$i],$vMat)) {
395
                        $vName = trim($vMat[1]);
396
                        $vTmp2 = explode("\n",$vTmp[$i+1]);
397
                        foreach ($vTmp2 AS $vOne) {
398
                                $vPat = '<info>([^<]+)<\/info>';
399
                                $vPat3 = "/$vPat\s*$vPat\s*$vPat/";
400
                                $vPat2 = "/$vPat\s*$vPat/";
401
                                if (preg_match($vPat3,$vOne,$vMat)) { // 3cols
402
                                        $vModules[$vName][trim($vMat[1])] = array(trim($vMat[2]),trim($vMat[3]));
403
                                } elseif (preg_match($vPat2,$vOne,$vMat)) { // 2cols
404
                                        $vModules[$vName][trim($vMat[1])] = trim($vMat[2]);
405
                                }
406
                        }
407
                }
408
        }
409
        return $vModules;
410
}
411
412