1 / 59

More PHP

More PHP. What we'll cover. A short history of php Parsing Variables Arrays Operators Control Structures Forms Functions Accessing the shell Sockets Regular Expressions. Forms. Obviously, one of the things you need to handle are forms

terah
Télécharger la présentation

More PHP

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. More PHP

  2. What we'll cover • A short history of php • Parsing • Variables • Arrays • Operators • Control Structures • Forms • Functions • Accessing the shell • Sockets • Regular Expressions

  3. Forms • Obviously, one of the things you need to handle are forms • You can make an html only form, and submit that to a php file • You can also make a single php file that makes the form, and submit that to itself, and on the submit, present a different page, and then after a confirmation present a third page, and so on, and so on…. • We'll talk about both

  4. Simple Form <form action="./simpleform.php" method="GET" name="choices"> <p>What is the meaning of life?</p> <p><textarea rows="1" cols="50" wrap="virtual" name = "answer"></textarea></p> <p>What is your name?</p> <p><textarea rows="1" cols="50" wrap="virtual" name = "name"></textarea></p> <p>Where is your car?</p> <p><textarea rows="1" cols="50" wrap="virtual" name = "car"></textarea></p> <p><input type="submit" value="Submit" align="middle" /></p> </form> simpleform/simpleform.html

  5. Simple Form php <?php if (count($_GET) < 1) { echo "no GETs!"; } else { echo "Here is the GET array:"; echo "<pre>"; print_r($_GET); echo "</pre>"; } ?> • The php that catches the form reads the GET array • All this one does is used print_r() to show the results • Can you think of any advantages or disadvantages to using two separate pages this way? • What about the first condition? When is it met? simpleform/simpleform.php

  6. Simple form to itself • To do all of this with one php file, we need a way to detect where we are in the process • So on first load, we present the form • On second load, after submitting the form, we process results…

  7. simpleform_self.php <?php if (!$_GET) { echo "<form action=\"" . $_SERVER["PHP_SELF"] . "\" method=\"GET\" name=\"choices\">\n"; echo "<p>What is the meaning of life?</p> <p><textarea rows=\"1\" cols=\"50\" wrap=\"virtual\" name = \"answer\"></textarea></p>\n"; echo "<p>What is your name?</p> <p><textarea rows=\"1\" cols=\"50\" wrap=\"virtual\" name = \"name\"></textarea></p>\n"; echo "<p>Where is your car?</p> <p><textarea rows=\"1\" cols=\"50\" wrap=\"virtual\" name = \"car\"></textarea></p>\n"; echo '<input type="hidden" value = "111" name = "key_number" />' ; echo '<p><input type="submit" value="Submit" align="middle" /></p>'; }

  8. simpleform_self.php else { echo "Here is the GET array:"; echo "<pre>"; print_r($_GET); echo "</pre>"; } ?> </form> </body> </html> • When the form is submitted, the url has a GET array • So it passes past the if statement, and lands on the else, where we process data • Again, we're just print_r()'ing the results • There's an error here, can you spot it?

  9. Sessions • A very useful aspect to php is the ability to maintain session data • To do this, you create a session, then load it with data • The session data is stored server side, usually in /etc, and is keyed (but not encrypted), and remains for that url and remote ip

  10. simpleform_self_session.php • Sessions need to be created before any html headers are sent, so do this at the very top of the page • Use session_register() to create slots for variables • After these variables are populated, you can access them via the $_SESSION array • In this example we'll define a key (randomly generated) and a counter (to track steps)

  11. simpleform_self_session.php <?php // Start a session, and set a key and a counter // A session is a method of tracking state for a given // browser session, and allows storage of data on the server session_start(); // create a session session_register('session_key'); // register a session var for a key to // track this session // this is done to help detect reloads session_register('session_counter'); // session counter is used to // track where we are in // a session ?>

  12. simpleform_self_session.php • Now, we can check see if the key is set, if not, we're on a first load and we generate a key and set the counter to 0…. // if the session_key is not yet set, generate a random number for the key // and set the session_counter to 0 (this situation indicates that the form // is being loaded for the first time) if (!$_SESSION['session_key']) { $_SESSION['session_key'] = rand(); $_SESSION['counter'] = 0; }

  13. simpleform_self_session.php • Then we build the form--note the use of PHP_SELF, and the hidden input…. // If we don't have key_number, then the user hasn't filled in the form if (!$_GET["key_number"]) { echo "<form action=\"" . $_SERVER["PHP_SELF"] . "\" method=\"GET\" name=\"choices\">\n"; echo "<p>What is the meaning of life?</p><p><textarea rows=\"1\" cols=\"50\" wrap=\"virtual\" name = \"answer\"></textarea></p>\n"; … echo '<input type="hidden" value = "' . $_SESSION['session_key'] . '" name = "key_number" />'; echo '</form>'; $_SESSION['counter'] = 1; }

  14. simpleform_self_session.php • Next, we have an elseif that looks to see that we have the data we need and that there's a key and that counter is set to one • Then we start by printing the results…. elseif ($_SESSION['session_key'] == $_GET["key_number"] && $_SESSION['counter'] == 1 && ($_GET["answer"] && $_GET["name"] && $_GET["car"])) { echo "Here is the GET array:"; echo "<pre>"; print_r($_GET); echo "</pre>";

  15. simpleform_self_session.php • … and then we make a confirmation form and set the counter to 2 • And again we submit the form to itself echo "<form action=\"" . $_SERVER["PHP_SELF"] . "\" method=\"GET\" name=\"choices\">\n"; echo '<input type="hidden" value = "' . $_SESSION['session_key'] . '" name = "key_number" />'; echo '<p>Are these ok?</p>'; echo '<input type="radio" value="yes" name = "yes_no" />yes <input type="radio" value="no" name = "yes_no" />no'; echo '<p><input type="submit" value="Submit" align="middle" /></p>'; echo '</form>'; $_SESSION['counter'] = 2; }

  16. simpleform_self_session.php • Next, we check for the confirmation and kill the session, if things are good here, we do good things….. // Check again that the session_key matches the key_number, and that we're on step number three, and for "yes" elseif ($_SESSION['session_key'] == $_GET["key_number"] && $_SESSION['counter'] == 2 && $_GET["yes_no"] == "yes") { echo '<p>Cool, everything\'s copacetic.</p>'; // Here you'd do the Good Thing, whatever that is. // Destroy the session session_unset(); session_destroy(); }

  17. simpleform_self_session.php • And we check for badness…. // Check again that the session_key matches the key_number, and that we're on step number three, and for "no" elseif ($_SESSION['session_key'] == $_GET["key_number"] && $_SESSION['counter'] == 2 && $_GET["yes_no"] == "no") { echo '<p>Oops, sorry, <a href="./simpleform_self_session.php"> try again?</a></p>'; // Here you'd do the Bad Thing, whatever that is // Destroy the session session_unset(); session_destroy(); }

  18. simpleform_self_session.php • And a final sanity check • This is not particularly clean, since we're not checking much, and esp. because this is where we land if not all fields are filled in--better ways to deal with this? // If no conditions matched, assume something went wrong and try to cope else { echo '<p>I\'m sorry, I found a problem, perhaps you didn\'t fill in all of the boxes. <a href="./simpleform_self_session.php"> Continue?</a></p>'; // Destroy the session session_unset(); session_destroy(); }

  19. User Defined Functions • Like javascript, php supports user defined functions • Declare your functions towards the top of your php file--this is not a requirement, just good practice • Functions are created when the program is read, and before execution • Or, build an exterior file with commonly used functions, and give that a version number. Then require that file to reuse your code (see the general functions file in the samples for examples I use)

  20. Passing Data • The simplest way to pass data into a function is through that functions argument list of variable (and arrays are a type of variable)// wrap the variable in pfunction echo_p($wrapped_item) { echo "<p>$wrapped_item</p>"; } • You can also set default values, but watch placement--defaults to the right please// wrap the variable in h// default to level 2function echo_h($wrapped_item, $level="2") { echo "<h" . $level . ">$wrapped_item</h" . $level. ">\n"; } 12

  21. Scope • Functions themselves have global scope--functions defined within functions are available everywhere • Variables assigned or modified inside of a function have their value only within the function • A variable can be declared global within a function, however, if you want to pass that variable into and out of the function • Generally, it's better to leave variable scope limited, this makes the function portable…. 15

  22. Functions have Global Scope • Unlike variables, functions are global in scope • But a function doesn't execute until called • Here, foo() is used to create bar() • Once foo() is called, bar() exists • bar() is available outside of foo() function foo() { function bar() { echo "I don't exist until foo() is called.\n"; } } /* We can't call bar() yes since it doesn't exist. */ foo(); /* Now we can call bar(), foo()'s processing has made it accessible. */ bar(); ?> this example is 17.3 from the php manual, up as 14_functions.php See also 15_function_scope.php

  23. Functions and Default Values function good_echo_h($wrapped_item, $level="2") { echo "<h" . $level . ">$wrapped_item</h" . $level. ">\n"; } function bad_echo_h($level="2", $wrapped_item) { echo "<h" . $level . ">$wrapped_item</h" . $level. ">\n"; } good_echo_h("A good heading"); good_echo_h("A good heading at level 1", 1); bad_echo_h(2, "A bad heading with level set"); bad_echo_h("A bad heading with no level set"); • Defaults must occur to the right 12_function_defaults.php

  24. An Example: Building an FAQ • Core program calls 5 functions, 3 local and 2 external • 1 Data file and some variables • This kind of program structure makes understanding a large program much easier…

  25. aform • This is set up in samples and the labs section, both, so you can do the lab to figure this out • Based on a general survey form I came up with a few years ago

  26. aform • Uses the general_functions file • Data is external in a text file • The code that makes the various types of question in the form is also external • By keeping data and question types separate, it's easy to use the same program to make different surveys

  27. Leveraging the Shell

  28. Back tick and shell_exec() • Php uses backticks (olde school) and the function shell_exec() to process shell commands (usually through bash) • Shell commands execute with the environment and rights of the web server • Opening a shell is not lightweight in terms of ram, so keep in mind it can be expensive • Very useful if a wheel already exists in your setup (Netcheck is an example)…. 04

  29. 10_show_source.php • I wanted to be able to display source code for the php programs • There is a function, highlight_file(), that will handle syntax highlighting for a php file • I could have written the whole thing in php (and that could be a portfolio project), but I already had this file listing shell script…. • This wheel already exists • If the server supports it, files ending in .phps will show highlighted source (this is an apache directive) • See also http://www.sitepoint.com/article/highlight-source-code-php

  30. Sockets

  31. Theory of Sockets • A socket is a combination of an ip number, a protocol and a port • Servers listen on a socket, clients will open a connection to that socket • What gets sent back and forth over the socket connection varies with the protocol • Generally, when working with a client, you don't specify the local socket you'll use (the os handles that), just the remote socket

  32. An example: Web Request $fp = fsockopen("www.cs.unc.edu", 80, $errno, $errstr, 30); if (!$fp) { echo "$errstr ($errno)<br />\n"; } else { $out = "GET /index.html HTTP/1.1\r\n"; $out .= "Host: www.example.com\r\n"; $out .= "Connection: Close\r\n\r\n"; fwrite($fp, $out); while (!feof($fp)) { echo fgets($fp, 128); } fclose($fp); } • This is a socket call to a web server • $fp represents a "handle" to the socket • If the handle is created, you have the socket 11_webconnection.php

  33. Sending email with PHP • The unix version of PHP includes support for sendmail:mail ( string to, string subject, string message) • Since windows doesn't support sendmail, the windows build of PHP uses an external smtp server, but uses the same command • But it doesn't work under OSX by default--OS X uses postfix, and that's off by default • I could have enabled postfix, but I'm a geek...

  34. Example Protocol: SMTP • By convention, smtp servers listen on ports 25 and 587 • By the rfc, smtp servers communicate in plain text--you can telnet to an smtp server to send email • Verbs in smtp include helo, mail from, rcpt to, data • Use "." to end the body of a message (and this is one place where a potential for hacking exists)

  35. An SMTP call gilgamesh:~ hays$ telnet smtp.unc.edu 25 Trying 152.2.1.140... Connected to smtp.unc.edu. Escape character is '^]'. 220 smtp.unc.edu ESMTP UNC-Chapel Hill - ITS Email; Tue, 30 Sep 2008 18:56:57 -0400 (EDT) helo gilgamesh 250 smtp.unc.edu Hello gilgamesh.cs.unc.edu [152.2.131.71], pleased to meet you mail from:hays@cs.unc.edu 250 2.1.0 hays@cs.unc.edu... Sender ok rcpt to:b@unc.edu 250 2.1.5 b@unc.edu... Recipient ok data 354 Enter mail, end with "." on a line by itself Subject: Test To: b@unc.edu From: hays@cs.unc.edu Howdy, this is a test. . 250 2.0.0 m8UMuvtq021026 Message accepted for delivery quit 221 2.0.0 smtp.unc.edu closing connection Connection closed by foreign host.

  36. Bits and pieces • fsockopen opens a connection, and establishes a point to that connection, with server, port and timeout specifiable • fwrite (or fputs) and fgets write and read to that connection, feof tests for end of file $fp = fsockopen("www.example.com", 80, $errno, $errstr, 30); if (!$fp) { echo "$errstr ($errno)<br />\n"; } else { $out = "GET / HTTP/1.1\r\n"; $out .= "Host: www.example.com\r\n"; $out .= "Connection: Close\r\n\r\n"; fwrite($fp, $out); while (!feof($fp)) { echo fgets($fp, 128); } fclose($fp); } this from php manual… 16

  37. My version of mail… • I didn't want to enable a mail server, so I hacked an emailer function that: • Checks the message for some possible hacks • Checks the MX record of the target domain • Opens a connection to an smtp server • Writes the message to that connection • Checks the responses for success or failure

  38. The call • Call this function with a message id, an array that contains the tos, a subject line, the message, the ip of the web server, the smtp server to use, and the port:emailer(rand(10000, 30000), $to_list, "hays@cs.unc.edu", "Test", "test test test", $_SERVER["REMOTE_ADDR"], "smtp.unc.edu", "587");

  39. Sanity Checks • Check for the to list to be an array (coercion can occur) • Check for embedded addresses and periods if (!is_array($email_to)) { die('Sorry, $email_to must be an array'); } $email_subject = str_replace("."," . ",$email_subject); $email_text = str_replace("."," . ",$email_text); $email_subject = str_replace("@"," AT ",$email_subject); $email_text = str_replace("@"," AT ",$email_text);

  40. Check Email Validity list($username,$domain) = split("@",$email_from); if (!getmxrr($domain,$mxrecords)) { echo "<p>Error: The email domain for the \"from\" address, $email_from, cannot be verified.</p>"; echo "<p>Mail sent from this address may not be deliverable, and replies may not work!</p>"; } // end of if $y=0; while ($email_to[$y] !='') { list($username,$domain) = split("@",$email_to[$y]); if (!getmxrr($domain,$mxrecords)) { echo "<p>Error: The email domain for the \"to\" address, $email_to[$y] cannot be verified.</p>"; echo "<p>Mail sent to this address may not be deliverable!</p>"; } // end of if $y++; } // end of while

  41. Build Messages • This part builds an array, message, that contains elements representing each line of the mail connection we need • We'll walk this array later to send the mail $x=0; // Build a helo message, using the php server's IP name $message[$x] = "HELO " . $php_server . "\r\n"; $x++; // Set the from address $message[$x] = "MAIL FROM:<" . $email_from . ">\r\n"; $x++;

  42. Now the from and tos $y=0; $message[$x] = "RCPT TO:<" . $email_to[$y] . ">\r\n"; $to_list = $email_to[$y]; $x++; // Now do a loop to set the rest of the recipients. // Pull each address out of the array email_to array // and also add that address to the to_list for inclusion in the headers $y++; while ($email_to[$y] != '') { $message[$x] = "RCPT TO:<" . $email_to[$y] . ">\r\n"; $to_list = $to_list . ", <" . $email_to[$y] . ">"; $x++; $y++; } // end of while

  43. Start a Data Statement • Start the data statement // Set the Data statement $message[$x] = "DATA\r\n"; $x++; • But the rest of the data statement is messy, it contains all of the header data you get in an email message--take a deep breath….

  44. Email Headers Message-ID: <11819@152.2.131.71> Date: Thu, 13 Sep 2007 16:20:51 -0400 From: hays@cs.unc.edu To: hays@cs.unc.edu Subject: Test Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit X-Mailer: Php program running from wwwx.cs.unc.edu/~hays/INLS668/samples/php/functions/test.php X-SAV-Scan-By: smf-sav v1.4.1 - http://smfs.sf.net/ Received-SAV: Pass (fafnir.cs.unc.edu: sender hays@cs.unc.edu passed Sender Address Verification Test receiver=fafnir.cs.unc.edu; client-ip=152.2.1.139 envelope-from=<hays@cs.unc.edu>; helo=smtp.unc.edu; X-Scanned-By: MIMEDefang 2.62 on 152.2.129.97 X-Scanned-By: MIMEDefang 2.62 on 152.2.129.90

  45. Making Email Headers $message[$x] = "Message-ID: <" . $email_messageid . "@" . $php_server . ">\r\nDate: " . date(r) . "\r\nFrom: " . $email_from . "\r\nTo: " . $to_list . "\r\nSubject: " . $email_subject . "\r\nContent-Type: text/plain; charset=us-ascii\r\nContent-Transfer-Encoding: 7bit\r\nX-Mailer: Php program running from ". $_SERVER["SERVER_NAME"] . $_SERVER["SCRIPT_NAME"] . "\r\n" . $email_text . "\r\n.\r\n"; $x++; // Build a quit message, this is the last step when it comes to the connection $message[$x] = "QUIT\r\n";

  46. Making the Connection $stream = fsockopen($smtp_server, $smtp_port, $errno, $errstr, 30); // Check for error messages from the socket connection. if (!$stream) { echo "<p>I'm sorry, there appears to be a problem sending email. \n"; echo '<p>Please report this error. <a href="mailto:' . $email_admin . '">' . $email_admin . "</a></p>\n"; echo "<p>Also, this error does not mean that anything else went wrong, it only indicates \n"; echo "that the email message this program was trying to send did not go out successfully. \n"; echo "Anything else you were trying to do likely was not affected by this error.</p>\n"; } // end of if

  47. Peel off the data else { // Since we got a socket, send the mail $x=0; // reset x for the loop while ($message[$x] != '') { $smtp_response = fgets($stream, 1024); // Check for server responses sleep(1); fputs($stream, $message[$x]); // Put the message line up to the server

  48. Check the Server Responses if (substr($smtp_response, 0, 1) > '3') { echo "<p>I'm sorry, there appears to be a problem sending email. \n"; echo "The particular message I received was:</p>\n"; echo "<pre>" . $smtp_response . "</pre>"; // Since there has been a nontransient error, try to reset and quit gracefully fputs($stream, "RSET"); sleep(1); fputs($stream, "QUIT"); sleep(1); // Set the next message to null // Since email failed we just give up and this exits the loop for us $message[($x + 1)] = ''; } //end of if

  49. See it in action • This is in the functions folder • There are earlier versions for comparison (why upgrade, and what to what for?)

  50. Regular Expressions

More Related