Wednesday, October 05, 2005

PHP Tips -- MAGIC QUOTES

Copied from a webpage, can't remember the link...

It's recommend that developers do their own string escaping, as if magic quotes is off, and use the below code to strip the additional slashes resulting from a PHP installation where magic quotes is on.

//----------------------------------------------------
// Is magic quotes on?
if (get_magic_quotes_gpc()) {

// Yes? Strip the added slashes

$_REQUEST = array_map('stripslashes', $_REQUEST);
$_GET = array_map('stripslashes', $_GET);
$_POST = array_map('stripslashes', $_POST);
$_COOKIE = array_map('stripslashes', $_COOKIE);
}
//----------------------------------------------------


//----------------------------------------------------
Mysql blob data

In PHP, you can insert data into the database like so:

$data = addslashes(fread(fopen($_FILES['doc']['tmp_name'], "r"), $_FILES['doc']['size']));

Then insert the $data element into the blob field.

This is useful if the documents need to be kept secure, for example if you need each user to be able to only access one file but not another. Beats out trying to work out multiple htaccess directories, which otherwise the links can be passed around.


//------------------

string htmlentities(string string);
and
string htmlspecialchars(string string);
will convert special characters "&'<>.." to HTML string, such as "...
?>


<tr><td>
Last Name:
</td>
<td><input name="rlname" value="" type="text" maxlength=20 size="20"> </td>
</tr>

PHP Tips -- Send Email


<?php
//This is the location of your sendmail variable
$mail_path = "/usr/sbin/sendmail -i -t";

//The email address to be receiving emails from this form
$mail_to = $email1 . ','. $email2;

//the subject of the email sent by the form
$mail_subject = "Confirm email";

/* To send HTML mail, you can set the Content-type header. */
$headers = "MIME-Version: 1.0\r\n";
$headers .= "Content-type: text/html; charset=iso-8859-1\r\n";
$headers .= "From: ABC\r\n";
$headers .= "Reply-to: contact@mycom.com\r\n";
$headers .= "Bcc: logs@mycom.com\r\n";

//the name of the buisness or website that the form contacts
$message = "<html><head></head><body>";
$message .= "<p>Dear $name, <br /> <br /> Your order is successfully created. <br />".
"Please go to the following link to track the status of your order: <br />".
"<br /><a href='http://www.mycom.com/cgi-bin/ordtrk.php?ordnum=$order_num'>
http://www.mycom.com/cgi-bin/ordtrk.php?ordnum=$order_num
</a><br /><br />".
"Thank you.

";
$message .= "</body></html>";

//ini_set("sendmail_from", $mail_from);
ini_set("sendmail_path", $mail_path);

if( mail($mail_to, $mail_subject, $message, $headers) )
{
echo 'Email was sent to' . $email;
}else{
echo "There was an error in the email address";
}
?>


The general format of a multipart MIME message will be the following:
---------------- Begin -------------------

To: whoever@someplace.com
Subject: MIME test
Content-type: multipart/mixed; boundary="theBoundaryString"

--theBoundaryString

Plain text message goes in this part. Notice that it
has a blank line before it starts, meaning that this
part has no additional headers.

--theBoundaryString
Content-Type: text/html
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
Content-Base: "http://somewebsite.com/"

<body><font size=4>This</font> is a
<i>test</i>.
--theBoundaryString--

---------------- End -------------------
Notice each of the blank lines above. Each one is important because it separates the header from the body in each part of the multipart document. First, the standard email headers are listed. The string theBoundaryString is used to separate each part of the multipart document. For the plain text area, there are no additional headers. Thus, it simply has a blank line before the actual content starts. After that, the HTML file with its headers starts.

The an important header there is Content-Base. It specifies the relative address for links within the HTML document. In other words, the following hyperlink:

<a href="apage.html">

will be interpreted relative to http://somewebsite.com/. Therefore, its full URL is:

http://somewebsite.com/apage.html

If you use full URLs in the HTML document, then there will be no need to specify Content-Base. For more information on this, see RFC 2110.

PHP Tips -- Form

** get Multi-select data in a form

<tr>
<td valign="top">Area code:</td>
<td>
<select id="area" name="area[]" size=6 multiple>
//Use area[] for php to get more value
<script>
frm = this.document.formname;
frm.area.options[frm.area.length] = new Option("--", "", false, false);
</script>
<?php

$id = @mysql_connect($host, $user,$dbpasswd) or
ErrMsg("Cannot connect to MySQL server");
@mysql_select_db($dbname,$id) or ErrMsg("Cannot open database");
$query = "select * from area where id=$uid;";
$result = mysql_query($query, $id);

while ($uarray = mysql_fetch_array($result)){
$area = $uarray["area"];
echo "<option value='$area'>$area";
}

mysql_free_result($result);
mysql_close($id);
?>
</select>

</td>
</tr>

<?php
// Get Multi-select data in a form

foreach($_POST['area'] as $value){
if ($value != ''){
$query = "insert into area (uid, area) values($uid, '$value');";
$result = mysql_query($query, $id) or ErrMsg("Query Error: $query");
}
}


/* To get multi check in a form:
Give the group of check box the same name, end with [],
PHP compiles the user input for this field into an array.
*/
?>
<input type='checkbox' name="codes[]" value='aaa'>
//Use codes[] for php to get more value as an array
<input type='checkbox' name="codes[]" value='bbb'>
//if didn't set value, php will get 'on' when checked
//else php get the value when checked.
//If unchecked, php get null no matter value is set.
<input type='hidden' value='' name='codesarray'>

<script>
function validate()
{
// Get checkbox array before submit
codearray = document.Formname.elements['codes[]'];

for (i=0; i {
if (codearray[i].checked == true)
{
document.Formname.codesarray.value += codearray[i].value + ",";
}
}
}
</script>

<?php
if (!isset($_POST['codes']))
{
$codesarray = '';
}else{
// Get an array of codes
$codes = $_POST['codes'];
$codesStr = implode(",", $codes); // combine entries into a string
}
echo "\n";
?>

PHP Tips -- DB Functions

MySQL Functions
<?php
$host="localhost:3306";
$user="root";
$dbpasswd="passwd";
$dbname="mydb";

$id = @mysql_connect($host, $user, $dbpasswd) or die(mysql_error());

@mysql_select_db($dbname,$id)
or die("DBCannot open database" . mysql_error());

$query = "select * from mycontact;";
$result = mysql_query($query, $id)
or die("mysql_query: $query" . mysql_error());

// Retrieves the number of fields from a query.
$num_fields = mysql_num_fields($result);
$rows = mysql_num_rows($result);
if ($rows === false) return false;

$i=0;
while($i<$num_fields)
{
$fname[$i] = mysql_field_name($result,$i);
$i++;
}

while ($accarray = mysql_fetch_row($result))
//No. 1 fast, but difficult to remember column number.
while ($accarray = mysql_fetch_assoc($result))
//No. 2 fast, with associated array, recommend
while ($conarray = mysql_fetch_array($result))
//No. 3 fast
while ($conarray = mysql_fetch_array($result, MYSQL_NUM))
//No. 4 fast
while ($conarray = mysql_fetch_array($result, MYSQL_ASSOC))
//No. 5 fast
while ($conarray = mysql_fetch_array($result, MYSQL_BOTH))
//The slowest
{
foreach($conarray as $k=>$v) $message .= $v. " ";
$fname = $conarray['firstname'];
}

mysql_data_seek($result, 0);

mysql_close($id);
?>


ODBC Functions

<?php
//connect to database
$connectionstring = odbc_connect("myapp", "user", "pswd");

//SQL query
$Query = "delete from company where id=$jid";
$Query = "update company set description='$description', company='$company', Website = '$web', name='$name', tel='$tel', fax='$fax', email='$email', address='$address', date='$date' where id=$jid";
$Query = "SELECT *, DATEPART('yyyy',date) AS mydate FROM company where id=$jid";

//execute query
$queryexe = odbc_do($connectionstring, $Query);
if (odbc_fetch_row($queryexe))
{
//collect results
$position = odbc_result($queryexe, "position");
}

//disconnect from database
odbc_close($connectionstring);
?>

PHP Tips -- File & Output Buffer Functions

File
/* Creates a file with a unique filename in the specified directory. If the directory does not exist, tempnam() may generate a file in the system's temporary directory, and return the name of that.
*/
string tempnam ( string dir, string prefix)

/* Given a string containing a path to a file, this function will return the base name of the file. If the filename ends in suffix this will also be cut off.
*/
string basename ( string path [, string suffix])

/* Given a string containing a path to a file, this function will return the name of the directory.
*/
string dirname ( string path)

bool file_exists("file_name");

is_file("file_name");
is_dir("dir_name");
is_readable();
is_writable();
is_executable();
int filesize(); // bytes
timestamp fileatime("file_name"); // when a file was last accessed
timestamp filemtime("file_name"); // when a file was last modified
timestamp filectime("file_name"); // when a file was last changed(unix) / created(other platform)

//Deletes filename
bool unlink ( string filename [, resource context]);

// Attempts to set the access and modification
// time of the file named by filename to the value given by time.
// If the file does not exist, it is created.
bool touch ( string filename [, int time [, int atime]])

// Reading ends when length - 1 bytes have been read,
// on a newline (which is included in the return value),
// or on EOF (whichever comes first).
// If no length is specified, the length defaults to 1k(1024 bytes).
string fgets ( resource handle [, int length]);

string fread ( resource handle, int length);

flock( $fp, LOCK_SH/LOCK_EX/LOCK_UN);

Output Buffer
bool ob_start ( [callback output_callback [, int chunk_size [, bool erase]]])

This function will turn output buffering on. While output buffering is active no output is sent from the script (other than headers), instead the output is stored in an internal buffer.

The contents of this internal buffer may be copied into a string variable using ob_get_contents(). To output what is stored in the internal buffer, use ob_end_flush(). Alternatively, ob_end_clean() will silently discard the buffer contents.

Example:

<?php
// Buffer the current html page so we can write it to file later
ob_start();
$var = "Generated html script";
?>

<html>
<head>
<title>HTMLGEN</title>
</head>
<body>
Loading.... <br />
<?php echo $var; ?>
More contents!<br />
</body>
</html>

<?php
// Write the buffered HTML file
$fp = fopen($htmlFile, 'w');
fwrite($fp, ob_get_contents());
fclose($fp);
ob_end_flush();
?>

PHP Tips -- String & Time Functions

String Functions

string trim($str);
string ltrim($str);
string rtrim($str);
int strlen($str)

string strtoupper($str);
string strtolower($str);
// make the first letter of $str uppercase
string ucfirst($str);
// make the first letter of every word in $str uppercase
string ucwords($str);

string nl2br($str);
string wordwrap($str[, $maxlinelen, $linebrkStr, $bBreakLongWord]);

false/string strstr($srcstr, $substr);
//case sensitive, return false if $substr not in $srcstr
// return the portion of the source string begining with the substring.
// Ex. strstr("abcd","bc") return "bcd"

false/string stristr($srcstr, $substr);
//not case sensitive, return false if $substr not in $srcstr

false/int strpos($srcstr, $substr, $index=0);

string substr($str, $index[, $len]);
string substr_replace($str, $rplace_str, $index, $len);
string str_replace($search_str(or a str array), $rplace_str(or a str array), $source_str(or a str array)); //replace all

$str_array = explode($delimiter, $str);

string/flase strtok([$str,] $delimiters)
Ex:

$test = "http://www.test.com/test.php?op=window&ver=5.0&db=sql&dev=php+mysql";
$delims = "?&";

$word = strtok($test, $delims);
//first time call, give the string as a para, the string will be catched.

// if $test contain empty string in it, should pass here
while(is_string($word)) {
if($word) { //not an empty string
echo "$word
";
}
// After the first time call, only give the delimiters
$word = strtok($delims);
}


string strip_tags()
$test = "<p>test: this <b>paragraph</b><br /> will return a line</p>";
echo "<pre>before: $test </pre>";
echo strip_tags($test, "<br />");


$billnum = "TAASD000012";
sscanf($billnum, "%1s%10s", $w1,$w2);
$counter = $w2 + 0;
// when $w2 isn't a number("AASD000012"), $counter will be 0


* ----------------------------------------------------- *
number_format -- Format a number with grouped thousands
Description
string number_format ( float number [, int decimals [, string dec_point, string thousands_sep]] )

number_format() returns a formatted version of number. This function accepts either one, two or four parameters (not three):

If only one parameter is given, number will be formatted without decimals, but with a comma (",") between every group of thousands.

If two parameters are given, number will be formatted with 'decimals' decimals with a dot (".") in front, and a comma (",") between every group of thousands.

If all four parameters are given, number will be formatted with 'decimals' decimals, dec_point instead of a dot (".") before the decimals and thousands_sep instead of a comma (",") between every group of thousands.

Only the first character of thousands_sep is used. For example, if you use foo as thousands_sep on the number 1000, number_format() will return 1f000.
* ----------------------------------------------------- *

PHP Tips -- Array & Class

Array
* Create a numerical array with more than one elements:
$colors = array("red", "yellow", "black", "green");

* Create a associative array with more than one elements:
$member = array(
"name" => "Bob",
"age" => 30,
"occupation" => "superman",
);

* Array functions:
array_merge();
// different with ( $array1 + $array2 ).
// the later will completely preserve the arrays and just append them to each other

$arrA+$arrB : combine two arrays

array_unique();
// Two elements are considered equal if and only if
// (string) $elem1 === (string) $elem2.
// In words: when the string representation is the same.


$codes = implode(",", $codesarray);
// Join array elements with a string

$codesarray = explode(',',$codes);
// Split a string by string

$num1=count($codes);
// Count elements in an array, or properties in an object

split -- split string into array by regular expression
array split ( string pattern, string string [, int limit] )


Class

class myclass{
var $name;

function myclass($n) { $this->name =$n; }

function sayhi(){
echo "Hi! My name is ". $this->name;
}
}

class childclass extends myclass {

function myclass($n)
{
parent::myclass($n);
}

function sayhi(){
echo "Hi! My name is ". $this->name .". How are you?";
}

}

$obj1 = new childclass("Bob");
$obj1->sayhi();

PHP Tips -- Constant, Variable & Operator

Constant

Predefined constants
__FILE__ : The name of the file that the PHP engine is currently reading, contains the full path and filename of the current (i.e. included) file.

__LINE__ : The line number of the file.

PHP_VERSION : Current PHP version

How to Define Constants

if (!defined("NO")) define("NO", 0);
if (!defined("YES")) define("YES", 1);


Use constant

if ($answer == YES) return true;


VARIABLE

integer, double, string, boolean, object, array,
NULL, Resource(reference to a third-party resource(a db,for example))

Some related functions:

gettype($var)
settype($var, 'typestr'); // changes the original data type
(datatype)$var //use cast, like in C, doesn't change the original data type


A variable declared in a function remains local to that function ( not available to outside the function or within other functions.

A variable declared outside a function will not automatically be available within it.
To access for a global variable, you need to use the global statement in the function.

Use static to declare a static variable in a function
Ex.

$var1 = 1;
$var2 = 3;
function a()
{
static $svar1 = 0;
global $var1, $var2;

$svar++;
}




=== : Identical, Left is equivalent to right and they are the same type.

Ex:

$x = 4;
$x === 4; //true
$x === '4'; //flase

$teststr = "mz00xyz";
if (strpos($teststr, "mz") === 0) {
// returns index 0, which could be resolve to false.
// Use "===" can work around this,
// the condition will be true (false and 0 are diffrent data type)
echo"Hello mz";
}


Have a browse of the PHP Cheat Sheet

PHP Tips -- SUPER GLOBALS

$GLOBALS---An array of all global variables (Like the global keyword, this allows you to access global variables inside a function---for example, as $GLOBALS[#myvariable#].)

$_SERVER---An array of server environment variables contains information such as headers, file paths, and script locations.

Ex:
header("Location: http://" . $_SERVER['HTTP_HOST'] . dirname($_SERVER['PHP_SELF']) . "/" . "mypage.php?msg=1");
$WEB_HOST = "https://" . $_SERVER['HTTP_HOST'];
header("Location: " . $WEB_HOST . dirname($_SERVER['PHP_SELF']) . "/" . "mypage.php?msg=1");

$_GET---An array of variables passed to the script via the GET method

$_POST---An array of variables passed to the script via the POST method

$_COOKIE---An array of cookie variables

$_ENV---An array of the server environment variables

$_REQUEST---An array of all user input including the contents of input including $_GET, $_POST, and $_COOKIE

$_SESSION---An array of currently registered session variables

------------- initial -------------
session_start();
/* When this script is run for the first time from a browser, a session ID is generated by session_start(). session_start() attempts to set a cookie when initiating a session for the first time. If the page is reloaded, the same session ID is allocated to the user. This action assumes that the user has cookies enabled. You must call this function before output anything to the browser. If 'session.cookie_lifetime' is not set in php.ini, the cookie is no longer stored when the user restart the browser. It's not sure that the client's browser will accept cookies. The safe way is to use SID (PHP makes a name/value pair for a session ID)
Ex. <a href="apage.html?<?php echo SID; ?>"> Go Here</a>

// to set or get a session id
session_id();

//return the current dir to which session files are saved or set the dir.
session_save_path([path]);

Ex.

if(!session_id()){
session_start();
}

$_SESSION['loginname'] = $_POST['loginname'];


------------- destroy -------------
$_SESSION=array();
session_destroy();

****** It seems that $varname and $_SESSION['varname'] use the same memory address.
When modify $varname, $_SESSION['varname'] changes at the same time.



$_FILES---An array of variables related to file uploads
$_FILES['fileupload']['name']: Original name of uploaded file
$_FILES['fileupload']['tmp_name'] Path to temporary file
$_FILES['fileupload']['size'] Size of uploaded file(in bytes)
$_FILES['fileupload']['type'] MIME type of uploaded file (where given by client) -> [image/gif]

Ex.
// HTML forms that include file upload fields must include an ENCTYPE argument:
<p>
<form action="dfa" enctype="multipart/form-data" method="post">
<!-- max file size: 50K, must be 'MAX_FILE_SIZE' for PHP to work with -->
<input type='hidden' name='MAX_FILE_SIZE' value='51200' />
<p> File to Upload: <input type="file" name="fileupload" id="name"> </p>
</form>
</p>
// Accept file


<?php
$file_dir = "/path/to/upload/dir";

foreach($_FILES as $file_name => $file_array)
{
echo "path: $file_array['tmp_name'] < br /> /n";
echo "name: $file_array['name'] < br /> /n";
echo "type: $file_array['type'] < br /> /n";
echo "size: $file_array['size'] < br /> /n";
}

if (is_uploaded_file($file_array['tmp_name']))
{
move_uploaded_file($file_array['tmp_name'], "$file_dir/$file_array['name']") or die("Couldn't copy");
echo "file was moved";
}
?>

Tuesday, October 04, 2005

HTTP Essentials

Digest from "HTTP Essentials" By Stephen A.Thomas

* URI
http://user:passwd@www.example.com:80/html.filepath/filename.html?query1=1#Fragment

* TCP Connection

Client ---------------> Server
1) TCP SYN
<---------------
2) TCP SYN, ACK
--------------->
3) TCP ACK (3-way handshake)

--------------->
4) HTTP Request
<---------------
5) HTTP Response

<---------------
6) TCP FIN
--------------->
7) TCP FIN, ACK

* Persistent

With persistent connections, a client can issue many HTTP requests over a single TCP connection.

* Pipelining

With Pipelining, a client dosen't have to wait for a response to one request before issuing a new request on the connection.

Client ---------------> Server
1) TCP SYN
<---------------
2) TCP SYN, ACK
--------------->
3) TCP ACK (3-way handshake)

--------------->
4.1) HTTP Request1
--------------->
4.2) HTTP Request2
<---------------
5.1) HTTP Response1
<---------------
5.2) HTTP Response2

<---------------
6) TCP FIN
--------------->
7) TCP FIN, ACK


* User Operations

GET

Client ---------------> Server
1) GET URI
<---------------
2) 200 OK, DATA (if error, return other status code.)


POST

Client ---------------> Server
1) POST URI (action URI), DATA
<---------------
2) 200 OK[, DATA] (if error, return other status code.)


PUT (File Upload)

Client ---------------> Server
1) PUT URI (where to put object), DATA
<---------------
2) 200 OK[, DATA] (if error, return other status code.)


DELETE (File Deletion)

Client ---------------> Server
1) DELETE URI (remove object), DATA
<---------------
2) 200 OK[, DATA] (if error, return other status code.)


* Behind the Scenes

OPTIONS
Discover what capabilities a server supports. Such information would let the client adjust how it interacts with the server or how it actually requests a specific object.

Client ---------------> Server
1) OPTIONS URI/*(General options)
<---------------
2) 200 OK, OPTIONS


HEAD
Just like the a GET operation, except that the server doesn't return the actual object request. It can be used to verify that an obj exists.

Client ---------------> Server
1) HEAD URI
<---------------
2) 200 OK


TRACE
Check the network path to a server.

Client ---------------> Intermediate Server ---------------> Ultimate Server
1) TRACE 2) TRACE, Via
<--------------- <---------------
4) 200 OK, message 3) 200 OK, message


* Cooperating Servers

Virtual Hosts
The 'HOST' header in HTTP 1.1 lets clients explicitly identify the Web site they are accessing, so the virtual hosting Web server can return the right content.

Client ---------------> Server --|--------- www.company1.com
1) GET /news.html |
Host:www.company1.com |--------- www.company2.com
<---------------
2) 200 OK, DATA (if error, return other status code.)


Redirection

Client ---------------> Server1
1) GET URI
<---------------
2) 301 Moved, NewURI
---------------> Server2
3) GET NewURI
<---------------
4) 200 OK