Feb 25

php — how to detect spider/crawler with php

I am going to write a PHP script today that detects whether a search engine spider is crawling a page.With PHP, we can check the value of $_SERVER['HTTP_USER_AGENT'],a predefined variables which store the contents of the User-Agent: header from the current request, if there is one.

$pattern = ‘/(google|msnbot|MSNPTC|yahoo|Slurp|overture.com|del.icio.us|DoCoMo|DoCoMo)/i’;
if ( preg_match($pattern, $_SERVER['HTTP_USER_AGENT'] === FALSE) { // not a spider

} else { // spider

}

You can find a list of search engine spiders/crawlers from  http://www.user-agents.org/.

Nov 27

remove server info and PHP info from response header

Below is a comm http response header:

HTTP/1.1 200 OK
Date: Wed, 27 Nov 2013 01:18:27 GMT
Server: Apache/2.0.55 (Debian) PHP/5.1.2
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Content-Encoding: gzip
Vary: Accept-Encoding
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: text/html; charset=utf-8

To keep your server from attack, you should hide all unnecessary information about your system.With apache web server,this was control by ServerTokens  and ServerSignature config directive.From apache manual,we find out  all available config value of ServerTokens and its sample out.

ServerTokens Prod[uctOnly]
Server sends (e.g.): Server: Apache
ServerTokens Major
Server sends (e.g.): Server: Apache/2
ServerTokens Minor
Server sends (e.g.): Server: Apache/2.0
ServerTokens Min[imal]
Server sends (e.g.): Server: Apache/2.0.41
ServerTokens OS
Server sends (e.g.): Server: Apache/2.0.41 (Unix)
ServerTokens Full (or not specified)
Server sends (e.g.): Server: Apache/2.0.41 (Unix) PHP/4.2.2 MyMod/1.2

Obviously, we should turn our config to ServerTokens Prod.

To stop apache from exposing info in related error page,we need to turn off ServerSignature.

ServerSignature off

To hide the php related information,locate your php config file, find or add expose_php.

expose_php off

Jul 06

how to check if php suport jpeg or png

how to check if your php support jpeg or png on your web server? you can create a phpinfo page to check the gd section. or you can run the following command directly in your shell:

# php -r 'print_r(gd_info());'
Array
(
 [GD Version] => bundled (2.0.34 compatible)
 [FreeType Support] =>
 [T1Lib Support] =>
 [GIF Read Support] => 1
 [GIF Create Support] => 1
 [JPEG Support] =>
 [PNG Support] => 1
 [WBMP Support] => 1
 [XPM Support] =>
 [XBM Support] => 1
 [JIS-mapped Japanese Font Support] =>
)
May 01

php — fsockopen post https request

to make a https post request, the difference is the port and the protocal used.take a look at the example code below:

Source code    
$data = array();
$data['name'] = $name;
$data['tel'] = $tel;
//error_log('data: ' . print_r($data,1) ."\n" , 3, 'log');    
$req = '';
foreach ($data as $key => $value) {
    //$value = urlencode(stripslashes($value));
    $req .= "&$key=$value";
}
//error_log('req: ' . $req ."\n" , 3, 'log');   
$post_url = 'ssl://www.abcdomain.com';
$header = '';
$header .= "POST /index.php/api/ HTTP/1.0\r\n";
$header .= "Host: www.abcdomain.com\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Content-Length: " . strlen($req) . "\r\n\r\n";
$fp = fsockopen ($post_url, 443, $errno, $errstr, 60);
//error_log('errno: ' . $errno . ' errstr: ' . $errstr ."\n" , 3, 'log');
if (!$fp) {
    //do something
} else {
    fputs ($fp, $header . $req);
    while (!feof($fp)) {
        if ($body == '' && strpos ( $res, "\r\n\r\n" ) === FALSE) {
            $res = fgets ($fp, 1024);
        } else {
            $body = fgets ($fp, 1024);
        }
    }
}
$objRes = json_decode($body);
//error_log('res: ' . $res . "\n", 3 , 'log');

make sure your php is configured with openssl extension enabled

extension=php_openssl.dll

Posted in php
Mar 22

php — how to check if js enabled in the client

PHP is running in the server side,so it has no access to the client’s browser.how to check if the the javascript status of the client’s browser?Technically no way but we may get some way to work out.

setting cookies with JS and detecting them from PHP, see the example code below:

Source code    
<?
if($_SESSION['JSexe']){     //3rd check js
    if($_COOKIE['JS'])  setcookie('JS','JS',time()-1);//check on every page load
    else            header('Location: js.html');
}               //2nd so far it's been server-side scripting. Client-side scripting must be executed once to set second cookie.
                //Without JSexe, user with cookies and js enabled would be sent to js.html the first page load.
elseif($_COOKIE['PHP'])     $_SESSION['JSexe'] = true;
else{               //1st check cookies
    if($_GET['cookie']) header('Location: cookies.html');
    else{
                setcookie('PHP','PHP');
                header('Location: '.$_SERVER['REQUEST_URI'].'?cookie=1');
    }
}
?>
<head>
<script type="text/javascript">document.cookie = 'JS=JS'</script>
</head>

 

FYI:

http://asdlog.com/Check_if_cookies_and_javascript_are_enabled

http://stackoverflow.com/questions/4454551/check-if-javascript-is-enabled-with-php

 

 

Posted in php
Jul 17

php — my experience of send post request via fsockopen function

i need to send post request to remote server without redirecting the client browser.With the help of php manual,i got the following code to work:

Source code    
$req = '';
foreach ($_POST as $key => $value) {
    $value = urlencode(stripslashes($value));
    $req .= "&$key=$value";
}
 
$post_url = 'www.abcdomain.com';
$header = '';
$header .= "POST /cgi-bin/search HTTP/1.0\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Content-Length: " . strlen($req) . "\r\n\r\n";
$fp = fsockopen ($post_url, 80, $errno, $errstr, 60);
if (!$fp) {
    //do something
} else {
     fputs ($fp, $header . $req);
     while (!feof($fp)) {
         $res = fgets ($fp, 1024);
        //   
  }
}

yes,the code can send post request but it not always work well.sometimes,it can not go to the specified host(domain) because from the apache error log,i found the apache server route the request to the default server.It was obviously that the script  need to add a host header info.

Source code    
$req = '';
foreach ($_POST as $key => $value) {
    $value = urlencode(stripslashes($value));
    $req .= "&$key=$value";
}
 
$post_url = 'www.abcdomain.com';
$header = '';
$header .= "POST /cgi-bin/search HTTP/1.0\r\n";
$header .= "Host: www.abcdomain.com\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Content-Length: " . strlen($req) . "\r\n\r\n";
$fp = fsockopen ($post_url, 80, $errno, $errstr, 60);
if (!$fp) {
    //do something
} else {
     fputs ($fp, $header . $req);
     while (!feof($fp)) {
         $res = fgets ($fp, 1024);
        //   
  }
}

it works like a charm!!

 

May 31

PHP — Line break affect how regular expression work

As you know,regular expression is very import in text processing.I had never noticed the “link break” in the regular expression.when i matched my “multiple line” regular expression against the string,i found that the line break in both the regular expression and the string to match will affect the match result.below is the detail.

PCRE(Perl-Compatible Regular Expression) for example,let’s take a close look at two special pattern modifier,below is the explanation from php manual document for both PCRE_MULTILINE and PCRE_DOTALL modifier:

m (PCRE_MULTILINE)
By default, PCRE treats the subject string as consisting of a single “line” of characters (even if it actually contains several newlines). The “start of line” metacharacter (^) matches only at the start of the string, while the “end of line” metacharacter ($) matches only at the end of the string, or before a terminating newline (unless D modifier is set). This is the same as Perl. When this modifier is set, the “start of line” and “end of line” constructs match immediately following or immediately before any newline in the subject string, respectively, as well as at the very start and end. This is equivalent to Perl’s /m modifier. If there are no “\n” characters in a subject string, or no occurrences of ^ or $ in a pattern, setting this modifier has no effect.
s (PCRE_DOTALL)
If this modifier is set, a dot metacharacter in the pattern matches all characters, including newlines. Without it, newlines are excluded. This modifier is equivalent to Perl’s /s modifier. A negative class such as [^a] always matches a newline character, independent of the setting of this modifier.

so regular expression can match multiple line string and it will be affected by m and s pattern modifier.we do not need to define a regular expression in multiple line like this,thought it’s ok in syntax:

$pattern = “/\| Domain: .*$domainstr.*
\| Expired domain: .*
\| Ip: \d+\.\d+\.\d+\.\d+
\| UserName: .*
\| PassWord: .*
/”;

however,we can rewrite it in this way:

$pattern = “/\| Domain: .*$domainstr.*(\r)?\n(\| Expired domain: .*?(\r)?\n)?\| Ip: \d+\.\d+\.\d+\.\d+(\s\(n\))?(\r)?\n(\| HasCgi: y(\r)?\n)?\| UserName: .*(\r)?\n\| PassWord: .*/i”;

The line break depends on system.so it will affect the match result.so we need to pay more attention when define the regular expression.

Apr 26

php – how to locate php.ini file of the server

well,you need to locate the php.ini file to tweak some configuration of the php to meet your script.where is the php.ini file.Especial there may be more that one php.ini file on the server,which is the one take effect?

the easiest way is to code a phpinfo page,than browse to the phpinfo page.it will show the location of the php.ini current in use.

<?php phpinfo(); ?>

On some webservers, the php are installed from some binary package,you can list all file of that package to get some clue,ie

rpm -ql php5.2 OR
rpm -ql lamp

Yes,you may also use the locate command to do that

locate php.ini

Apr 24

bash — get a random password from shell script

As i managed more than ten linux server,i need to update all user account per customer request. i need to generate rand password for each account.here comes the shell script to generate a random password

#/bin/bash
#author george zheng <xinhaozheng@gmail.com>
#date 04 – 22 – 2012

LENGTH=12
array1=(w e r t y u p a s d f h j k z x c v b m Q W E R T Y U P A D F H J K L Z X C V B N M 2 3 4 7 8 ! @ $ % \# \& \* \= \- \+ \?)
MODNUM=${#array1[*]}
pwd_len=0
while (( “$pwd_len” < “$LENGTH” ))
do
index=$(($RANDOM%$MODNUM))
password=”${password}${array1[$index]}”
pwd_len=$pwd_len+1
done
echo $password > passfile

or you may define a function,check the get_pass function below

#/bin/bash
#author george zheng
function gen_pass()
{
LENGTH=12
array1=(w e r t y u p a s d f h j k z x c v b m Q W E R T Y U P A D F H J K L Z X C V B N M 2 3 4 7 8 ! @ $ % \# \& \* \= \- \+ \?)
MODNUM=${#array1[*]}
pwd_len=0
while (( “$pwd_len” < “$LENGTH” ))
do
index=$(($RANDOM%$MODNUM))
password=”${password}${array1[$index]}”
pwd_len=$pwd_len+1
done
}
gen_pass
echo $password

Keep in mind that definition of the function  need to be put before the first call to the function.

Apr 23

mysql – how to check if table existed with php

One of our zen cart website throw out an error after system crashed.The error message is something as below:

abc.configuration does not exist (abc is the db name)

i logged into mysql console with

mysql -u root -p

then i issue those command in the mysql console

use abc;
show tables;

The configuration table is showed in the result list.When I browse to the phpmyadmin page,i found the configuration is missing.This make me confused.I thought the configuration table may be corrupted.so it’s not shown in phpmyadmin and any sql query on it will result in error.that’s why the zen cart website got 404 error page.

I usually check the table existence with following php function which based upon ‘show table’ query.

function table_exists($link,$db,$table) {

if (empty($table)) {
die('No table name provided to check');
}
$tables = array();
$sql = "SHOW TABLES FROM $db";
$result = mysql_query($sql, $link);

if (!$result) {
echo 'DB Error, could not list tables,' . mysql_error();
exit;
}

while ($row = mysql_fetch_row($result)) {
$tables[] = $row[0];
}
return in_array('configuration', $tables);
}

it is obviously that the ‘show tables’ query will lead to error when a table is corrupted.so is there better way to check?After some seconds i got solution from google.Below is the php function to check the existence of a table.It worked upon MySQL information(the information_schema database).

function table_exists($tablename, $link, $database = false) {

if(!$database) {
  $res = mysql_query("SELECT DATABASE()", $link);
  $database = mysql_result($res, 0);
}

$res = mysql_query("SELECT COUNT(*) AS count FROM information_schema.tables WHERE table_schema = '$database' AND table_name = '$tablename'", $link);

return mysql_result($res, 0) == 1;
}

i thought this would be better way to go.