+ All Categories
Home > Documents > More PHP

More PHP

Date post: 11-Jan-2016
Category:
Upload: terah
View: 26 times
Download: 0 times
Share this document with a friend
Description:
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 - PowerPoint PPT Presentation
59
More PHP
Transcript
  • More PHP

  • What we'll coverA short history of phpParsingVariablesArraysOperatorsControl StructuresFormsFunctionsAccessing the shellSocketsRegular Expressions

  • FormsObviously, one of the things you need to handle are formsYou can make an html only form, and submit that to a php fileYou 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

  • Simple Formsimpleform/simpleform.html

    What is the meaning of life?

    What is your name?

    Where is your car?

  • Simple Form phpThe php that catches the form reads the GET arrayAll this one does is used print_r() to show the resultsCan 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

  • Simple form to itselfTo do all of this with one php file, we need a way to detect where we are in the processSo on first load, we present the formOn second load, after submitting the form, we process results

  • simpleform_self.php
  • simpleform_self.phpWhen the form is submitted, the url has a GET arraySo it passes past the if statement, and lands on the else, where we process dataAgain, we're just print_r()'ing the resultsThere's an error here, can you spot it?else { echo "Here is the GET array:"; echo ""; print_r($_GET); echo ""; }?>

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

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

  • simpleform_self_session.php

  • simpleform_self_session.phpNow, 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; }

  • simpleform_self_session.phpThen 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 formif (!$_GET["key_number"]) { echo "\n"; echo "What is the meaning of life?\n"; echo ''; echo ''; $_SESSION['counter'] = 1; }

  • simpleform_self_session.phpNext, 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 oneThen 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 ""; print_r($_GET); echo "";

  • simpleform_self_session.php and then we make a confirmation form and set the counter to 2And again we submit the form to itselfecho "\n";echo '';echo 'Are these ok?'; echo 'yes no';echo ''; echo ''; $_SESSION['counter'] = 2; }

  • simpleform_self_session.phpNext, 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 'Cool, everything\'s copacetic.'; // Here you'd do the Good Thing, whatever that is. // Destroy the session session_unset(); session_destroy(); }

  • simpleform_self_session.phpAnd 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 'Oops, sorry, try again?'; // Here you'd do the Bad Thing, whatever that is // Destroy the session session_unset(); session_destroy(); }

  • simpleform_self_session.phpAnd a final sanity checkThis 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 copeelse { echo 'I\'m sorry, I found a problem, perhaps you didn\'t fill in all of the boxes. Continue?'; // Destroy the session session_unset(); session_destroy(); }

  • User Defined FunctionsLike javascript, php supports user defined functionsDeclare your functions towards the top of your php file--this is not a requirement, just good practiceFunctions are created when the program is read, and before executionOr, 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)

  • Passing DataThe 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 p function echo_p($wrapped_item) { echo "$wrapped_item"; }You can also set default values, but watch placement--defaults to the right please // wrap the variable in h // default to level 2 function echo_h($wrapped_item, $level="2") { echo "$wrapped_item\n"; }

    12

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

  • Functions have Global ScopeUnlike variables, functions are global in scopeBut a function doesn't execute until calledHere, foo() is used to create bar()Once foo() is called, bar() existsbar() 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.phpSee also 15_function_scope.php

  • Functions and Default ValuesDefaults must occur to the rightfunction good_echo_h($wrapped_item, $level="2") { echo "$wrapped_item\n"; }function bad_echo_h($level="2", $wrapped_item) { echo "$wrapped_item\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");12_function_defaults.php

  • An Example: Building an FAQCore program calls 5 functions, 3 local and 2 external1 Data file and some variablesThis kind of program structure makes understanding a large program much easier

  • aformThis is set up in samples and the labs section, both, so you can do the lab to figure this outBased on a general survey form I came up with a few years ago

  • aformUses the general_functions fileData is external in a text fileThe code that makes the various types of question in the form is also externalBy keeping data and question types separate, it's easy to use the same program to make different surveys

  • Leveraging the Shell

  • 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 serverOpening a shell is not lightweight in terms of ram, so keep in mind it can be expensiveVery useful if a wheel already exists in your setup (Netcheck is an example).04

  • 10_show_source.phpI wanted to be able to display source code for the php programsThere is a function, highlight_file(), that will handle syntax highlighting for a php fileI 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 existsIf 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

  • Sockets

  • Theory of SocketsA socket is a combination of an ip number, a protocol and a portServers listen on a socket, clients will open a connection to that socketWhat gets sent back and forth over the socket connection varies with the protocolGenerally, when working with a client, you don't specify the local socket you'll use (the os handles that), just the remote socket

  • An example: Web RequestThis is a socket call to a web server$fp represents a "handle" to the socketIf the handle is created, you have the socket$fp = fsockopen("www.cs.unc.edu", 80, $errno, $errstr, 30);if (!$fp) { echo "$errstr ($errno)\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);}11_webconnection.php

  • Sending email with PHPThe 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 commandBut it doesn't work under OSX by default--OS X uses postfix, and that's off by defaultI could have enabled postfix, but I'm a geek...

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

  • An SMTP callgilgamesh:~ hays$ telnet smtp.unc.edu 25Trying 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 gilgamesh250 smtp.unc.edu Hello gilgamesh.cs.unc.edu [152.2.131.71], pleased to meet youmail from:[email protected] 2.1.0 [email protected]... Sender okrcpt to:[email protected] 2.1.5 [email protected]... Recipient okdata354 Enter mail, end with "." on a line by itselfSubject: TestTo: [email protected]: [email protected], this is a test..250 2.0.0 m8UMuvtq021026 Message accepted for deliveryquit221 2.0.0 smtp.unc.edu closing connectionConnection closed by foreign host.

  • Bits and piecesfsockopen opens a connection, and establishes a point to that connection, with server, port and timeout specifiablefwrite (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)\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 manual16

  • My version of mailI didn't want to enable a mail server, so I hacked an emailer function that:Checks the message for some possible hacksChecks the MX record of the target domainOpens a connection to an smtp serverWrites the message to that connectionChecks the responses for success or failure

  • The callCall 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, "[email protected]", "Test", "test test test", $_SERVER["REMOTE_ADDR"], "smtp.unc.edu", "587");

  • Sanity ChecksCheck for the to list to be an array (coercion can occur)Check for embedded addresses and periodsif (!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);

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

  • Build MessagesThis part builds an array, message, that contains elements representing each line of the mail connection we needWe'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:\r\n"; $x++;

  • Now the from and tos $y=0; $message[$x] = "RCPT TO:\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:\r\n"; $to_list = $to_list . ", "; $x++; $y++; } // end of while

  • Start a Data StatementStart 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.

  • Email HeadersMessage-ID: Date: Thu, 13 Sep 2007 16:20:51 -0400From: [email protected]: [email protected]: TestContent-Type: text/plain; charset=us-asciiContent-Transfer-Encoding: 7bitX-Mailer: Php program running from wwwx.cs.unc.edu/~hays/INLS668/samples/php/functions/test.phpX-SAV-Scan-By: smf-sav v1.4.1 - http://smfs.sf.net/Received-SAV: Pass (fafnir.cs.unc.edu: sender [email protected] Sender Address Verification Testreceiver=fafnir.cs.unc.edu; client-ip=152.2.1.139envelope-from=; helo=smtp.unc.edu;X-Scanned-By: MIMEDefang 2.62 on 152.2.129.97X-Scanned-By: MIMEDefang 2.62 on 152.2.129.90

  • Making Email Headers $message[$x] = "Message-ID: \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";

  • Making the Connection $stream = fsockopen($smtp_server, $smtp_port, $errno, $errstr, 30);

    // Check for error messages from the socket connection. if (!$stream) { echo "I'm sorry, there appears to be a problem sending email. \n"; echo 'Please report this error. ' . $email_admin . "\n"; echo "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.\n"; } // end of if

  • 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

  • Check the Server Responses if (substr($smtp_response, 0, 1) > '3') { echo "I'm sorry, there appears to be a problem sending email. \n"; echo "The particular message I received was:\n"; echo "" . $smtp_response . ""; // 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

  • See it in actionThis is in the functions folderThere are earlier versions for comparison (why upgrade, and what to what for?)

  • Regular Expressions

  • Simple regular expression// Check for malodorous site callsif (ereg("(//)", $_GET[name])){ //echo "Call to an external site"; $email_messageid = date(U); $email_to[0] = "[email protected]"; $email_subject = 'Intrusion Attempt from frame.php'; $email_text = 'There has been an intrusion attempt originating from ' . $HTTP_SERVER_VARS[REMOTE_ADDR] ; $email_from = "[email protected]"; $php_server = $HTTP_SERVER_VARS[HTTP_HOST]; $smtp_server = "smtp.cs.unc.edu"; $smtp_port = "25"; emailer($email_messageid, $email_to, $email_from, $email_subject, $email_text, $php_server, $smtp_server, $smtp_port); }

  • Regular Expressions SyntaxTwo major dialects, posix and perl (we're using the former)The basic usage is "match a_string a_blob", where the string is what you're looking for and the blob is where it might beThere are a lot of variants that do search and replace, forward and back, etc., but the basic function in PHP is ereg()

  • ereg() examplesereg("fair", $blob) looks for the string "fair"ereg([0-9], $blob) looks for any instance of a digit from 0 to 9ereg([cq], $blob) looks for either a c or q (this is the same as "c|q" ereg(([0-3])|(fair), $blob) looks for any digit 0-3 or the string "fair" (the | is an or)

  • ereg and Anchorsereg((^This), $blob) looks for This at the beginning of $blobereg((This$), $blob) looks for This at the end of $blob

  • More examplesereg([7-9].ing, $blob) looks for a 7-9 digit, following by any single character, followed by the string "ing" (the period is a wildcard)ereg(rx{4,7}, $blob) looks for an r followed by 4-7 x's (the brackets provide the range on the prior characterereg([0-9]{5}s, $blob) looks for 5 digits each in the range of 0-9, followed by an s15_ereg.php

  • Escaping ereg Characters^.[$()|*+?{\ are special characters for regular expressions, and must be escaped with a backslashereg(\[@@@\], $blob) looks for '[@@@]'ereg(",\.\[@@, $blob) looks for '",.[@@'

  • For the masochistic: Some examples of validationhttp://www.ilovejackdaniels.com/php/email-address-validation/http://www.zend.com/codex.php?id=371&single=1http://scripts.franciscocharrua.com/verify-email-address.php

  • Regex infohttp://www.tin.org/bin/man.cgi?section=7&topic=regexhttp://analyser.oli.tudelft.nl/regex/index.html.enhttp://weblogtoolscollection.com/regex/regex.php

  • Sourceshttp://www.zend.com/zend/art/intro.phphttp://www.php.net/http://hotwired.lycos.com/webmonkey/programming/php/index.html


Recommended