Thursday, August 24. 2006A New DirectionIt's been quite some time since my last blogging. Most of the reason for this is that I have been extremely busy with my current job as well as a few other responsibilities. However, the time has now come for me to move on and try something new. Early this month I accepted an offer to work for The Selling Source in Las Vegas. It is a hard move since I have been employed by my current employer, FT11 Interactive, for my entire professional career. I am looking forward to the change and the new people I will meet. Since I will be moving away from a smaller startup type atmosphere I am hoping I will have a little more time to work on some of the little projects I have been chipping away at for the last year. Late Static BindingI haven't been able to touch this in what seems like ages and have (unfortunately) completely missed the boat for PHP 5.2. But I am hoping to take a look at the current patch, come up with some solid use cases and tests, and submit the whole package to PHP Internals for review. Scriptable Browser for PHP 5.1+This is actually a fairly new project and one that I haven't put alot of time into yet. The goal behind this is to create the scriptable browser and then soon thereafter create a binding for it so it can be easily used with PHPUnit 3. I am sure there are at least 3 or 4 people wondering why I don't just work with SimpleBrowser or Selenium, and the simple answer to that is: Cause that's no fun. Refactoring ToolsThis little project is actually one that I haven't even talked about yet. I am finding that there is a real lack of tools to assist in refactoring php scripts. What tools we do have (aside from testing tools) are not at all php specific. With the advent of Greg Beaver's PHP lexer it has all of a sudden became fairly trivial to do in-depth source code analysis. I have almost completed a small code metrics suite and will (hopefully) be releasing it to the public soon. A Bigger, Badder Looking SiteI promised myself around 2 years ago that I would create a site that wasn't a s9y stock theme, I have yet to do that, so that's also going to be on my agenda for the very near future. So, I have to thank FT11 Interactive and it's management for 5 excellent years, and while I am sad to be leaving I would be lying to say I am not excited about this new opportunity. Hopefully now I can hit some of those conferences Monday, May 22. 2006Finally used PHPUnit and I like itI have been working quite a bit lately with the cvs version PHPUnit3. I have spent alot of time in testing using SimpleTest and I have also given some time to test-more.php. However, up until just recently I had honestly never used PHPUnit before. The big motivational factor for me (other than to try something new) was to see how the code coverage feature was coming along. I would have to say that after a few weeks of tinkering with it I am impressed. Now, keep in mind that I am talking about software that is still in development, so a degree of lattitude is required. The featureset of PHPUnit 3 is great. Here are a few notable features (in my mind):
Using the framework is an absolute breeze and there is excellent documentation in the form of a free book (draft version) written by Sebastian Bergmann and published by O'Reilly called "PHPUnit Pocket Guide." The API is also documented quite nicely and serves as a good second-source for learning how to do specific things. The most impressive part of this experience in my mind was how runnable the software is straight out of CVS. Most of the time when I am crazy enough to use CVS version I always seem to get my copy of the source at a point where it is very unstable and requires tweaking just to get the software to fulfill its basic requirements. PHPUnit 3 on the other hand was able to run in it's standard mode without a flaw. The only thing that was missing that I felt I needed was html reports for the pass/fail status of the unit tests. The report templates and code was already to a point however that it was actually fairly trivial for me to make the changes to it that I thought would be needed to make it work. I have since passed those changes along to Sebastian and they have been added to CVS, so html reports are now in the cvs version as well. It felt good to be able to contribute a little bit to a very worthwhile project. Sebastian has posted about the new reporting features on his blog that include some screenshots so I won't bother to rehash over all of that. You can just go check them out on his site. Friday, April 28. 2006I <3 RegexsI was toying around with regexs this morning and learned a few things I had just never taken the time to learn before. In any case, I came up with this: #((?:(?<!\\)\"(?:(?:(?:[\x20\x09]*[\r\n])?[\x20\x09]+)?(?:[\x01-\x08\x0b-\x0c\x0 (of course ignoring line breaks.) An 'atta boy' (or girl as the case may be) to anybody that can tell me what this would be used for Sunday, February 26. 2006Intercepting php mail() spam with sendmail and formail
I have noticed alot of people talking about mail header inections this past week. I have actually had a run in with this on one of my servers this last week too. On one of our servers where we host around 50 clients I have recieved in the neighboorhood of 7000 delivery failure notices to the server's postmaster account. Almost all of them being failed spam messages. I was told that sendmail client on the server was for sure configured such that it couldn't be used directly via smtp as an open relay, which means the e-mails were most likely coming from a compromised mail form script. So I spend an entire day tracking all of them down and patching them. I was pretty sure I got them all, but then the next day I got a bunch more failures which dated the original e-mail about 26 hours after the holes were all patched.
So, I was trying to think of a way to be able to monitor the php mail() so I can have it flag me when it detects possible spam being sent with it. Then I was reminded of an article fom the November 2005 php|architect by Ben Ramsey title mail() hacks. The article basically looks at various ways to intercept the mail() function for site testing purposes. So I am now using a variant of the same technique to catch spam being sent through php. Php allows you to specify the path of your sendmail program via the sendmail_path ini option. Whatever program this points to is then passed a formatted e-mail message (with headers) via its STDIN whenever the php mail() program is called. So simply put you can swap out any program/script for sendmail to allow you to log e-mails, redirect it, or even modify it's headers. A while ago I wrote a script that I use with my servers' postmaster accounts to notify me whenever there are any serious problems. This lets me know when there are any abnormalities (a large number of delivery failures, missing accounts, server errors, reports etc.) without me ever actually having to sift through each an every e-mail. So I figured it would be fairly trivial to just add some logic in there to sift through mail submitted via the mail() functions. The only problem was to find a way to intercept the messages. Unix has a handy little program called formail (yes with one 'm') that makes it extremely easy to edit an email's headers via the command line. So using this program I am now able to add a Bcc line with my address to any function sent with mail. In order to make it easy for my script to determine which e-mails come from php I am also adding a custom header: "x-php-formmail: yes." Also since I amp having a severe problem with injections I have taken the extra, temporary step of removing all other Bcc Addresses but my own and moving them to a different custom header. The script looks like this: /usr/sbin/formail -R bcc x-original-bcc -f \ Eventually, once I am sure that I have all the holes patched I will remove the '-R bcc x-original-bcc' and at that point usage of this script will be completely transparent from a programming perspective. Curse the spammers. For those of you who would like more information about mail header injections I found this site. It has some pretty decent information: What they are, how they happen, how you fix them, it's all covered. Chris Shiflett also did a podcast with Marcus Whitney recently about mail header injections. Then of course there is always the good 'ole php manual. The comments have quite a bit to say about mail header injections. However, I recommend caution when reading through them, as always there of some good recommendations and some very, very bad recommendations. Thursday, February 23. 2006Late Static Binding in PHPI have just sent an e-mail to the internals list for PHP that implements late static binding. Many of you probably remember hearing about all of this a few months ago not too long after the Zend Framework webcast where they showed off an API that appeared to be somewhat impossible to create short of some poor hacks with terrible performance. A good summary of the problem this patch fixes can be found on Joshua Eichorns blog: http://blog.joshuaeichorn.com/archives/2006/01/09/zactiverecord-cant-work/ So, for a more detailed summary Take the following code: <?php
class Foo {
protected static $staticVar = 'Foo';
public static function test() {
echo self::$staticVar . "\n";
}
}
Foo::test();
class Bar extends Foo {
protected static $staticVar = 'Bar';
}
Bar::test();
?>The above code seems fairly straight forward. What happens behind the scenes is that a Foo class is created and has the static function added to it's function table (among other things.) At that time the class Foo is also added to the Foo::test function struct that is added to that table. So, the when Foo::test() is called, the engine looks for the Foo class, finds the test function in Foo's function table and executes it. So, when Bar is defined, it creates the Bar class. Then it notices that Bar extends foo and adds all of Foo's functions, properties, and what not to the function table, property table, etc. Now, when this is done no additional changes are made to the Foo::test function struct to show that there is a new class (Bar) that can call it. So when you call Bar::test() it will find Bar, and find Foo::test but when the test function is ran no information is passed to the function to let it know that Bar was the class that called it. To put it more succinctly, Foo and Bar both know about ::test, but ::test has no idea who Bar is. The function will always execute in Foo's class scope. So self:: always calls Foo::. Now, this isn't always a problem. The only time it becomes an issue is if you have an inherited static function that wants to call another static function, static property, or constant that has been redefined in a child class. The change I made basically allows the engine to store the class calling the static function. The caller can then be accessed using 'static' (as opposed to self.) This should open the door to many other framework implementation possibilities (First thing that comes to mind for me is a Rubyish Active Record object.) So, if you take part in the PHP-DEV mailing list and you want late-static-binding let them know. Friday, February 3. 2006TAP Compliant PHP Testing HarnessI have been doing a fair bit of thinking concerning testing over the last couple of days. This was partially driven by a couple of emails Paul and I have sent back and forth as well as a posting in his blog. I am of course a big proponent of TAP. I think it provides alot of possibilities for integrating the current libraries that offer TAP support (test-more.php, SimpleTest + TAP-Reporter, PHPUnit2.) However, having libraries that support TAP compliant output are honestly of little extra value if there isn't a way to read it and subsequently aggregate the data. TAP Compliancy allows you to use any framework/harness that supports TAP. However, to date, the only harness I could find for reading TAP was perl's Test::Harness and the only framework was Apache-Test. Now, I will be the first to admit that there is a fairly steep learning curve when it comes to using Apache-Test. Once you get the hang of it, things get pretty simple. Getting the hang of it though tends to be a problem. Because of this I thought it was time for someone to create a harness in php that is capable of being used to build a framework. So, I spent my free time the last couple of days working on such an item and this is what I came up with: test-harness.php This is a very rough first draft, if you will. I have successfully used it to run a 1,000 file testing suite that I use for my firm's internal API. It should be stated immediatly that my goal is NOT to mimic Test::Harness. My goal is to simply provide another option for people to use in their testing. It is fairly simple to use. All you need to do is place it in your tests' folder, make a few configuration changes (if necessary) and you will be ready to go. The script does depend on your test-files being self sustaining (to a point) and they must also output TAP compliant results. So basically if you can run your individual test files from the command line you should be alright. There are three different configuration settings that need to be looked at. They can all be found at the top of the test-harness.php file. The first one is the TAP_PHP_CLI constant. This simple needs to be the path to your php-cli. The second one is TAP_PHP_CLI_ARGS. This can be used to pass command line arguments straight to php. I anticipate (as the default value shows) that this will be used most often to set the include_path for the testing scripts. The final setting is the $_EXCLUDE_FILES array. This is used to specify which files the harness should ignore when cycling through the directories. test-harness.php should of course always be set. I have also set test-more.php as I was using this library for most of my testing. Here is a brief list of the current features:
This is the first version of this file and I plan on releasing many more in the very near future. Some features I have in mind for the future are:
Thursday, December 15. 2005Updated Simpletest+Apache-TestA couple days ago I came across a post in Chris Shiflett's blog concerning a tutorial that Geoff Young and he were giving at JApacheCon. Part of this post was giving some information on a small extension I wrote for SimpleTest called TAP Reporter. I never realized anybody was actively using the extension and as a result I failed to develop it or even update the version I have on my site. Chris, Geoff, Marcus Baker, and I have since opened discussion on possible mods to Simple Test as well as a little discussion on how to make PHP testing an overall nicer experience. So it looks like there will be some changes to the TAP Reporter in the very near future. That all being said, I do have an updated version of the tarball that fixes some bugs in tap-reporter.php and also enables a few more TAP featuers. The new features are support for SKIP and TODO directives as well as support for 'bail out!.' The code is very well documented (yay me) so I don't think there's much of a need for me to describe how to use it. If you want some general information on TAP, Apache-Test and how they relate to SimpleTest then take a look at my older posts on the subject. A link to the new tar ball can be found below. Friday, October 28. 2005Arrays, Objects, and CloningGeorge Schlossnaglewrote a blog entry debating the "copy" vs. "handle" debate. While you can see my opinion on the whole matter in his blog someone else did ask whether or not Arrays are sopied or referenced with a handle by default, as well as whether the objects that may be indexed in the array are copied or just passed via a handle. Well, as to the first question, arrays are copied as shown by this code: $array1 = array(1, 2, 3); which outputs: Array That should be inferred as arrays are not objects in php, they are handled completely differently in almost every sence of the word.
class Object {Which outputs: Original ID: 1 Clone ID: 1 Objects Match So as you can see even though the arrays are cloned, objects within them are not. Reason for this is that any given variable holding an object in php does not technically hold an object. It holds a handle to that object (basically the original ID in my example.) The same thing is true for the 'new' construct. It also passes a handle, not an object. So, when an array is copied, php will just replicate each index's value into the new array, when it comes accross an object it sees the handle, and copies it over (not the object itself). Now, when you call 'clone' on an object, it does one of two things if there is a __clone() method defined for the object it will be called, if the method does not exist, then php creates a shallow copy of the object. Basically it copies each property from the original object to the new object. If a property contains a reference in the original object, the new object will contain that same reference. This is all made MUCH clearer probably in PHP's manual. However I thought I hadn't added to much to my blog lately, so instead of making a horrendously long comment in someone else's post I would just make a post of my own. Thursday, August 18. 2005Propel StuffI have spent most of this last week fiddling with Propel trying to get it to suite my needs. Overall I would have to say it's worked pretty nicely. There is some quirks about it that I absolutely can't stand. Since no one is in their channel on IRC I figured I would just write them down here in the hopes that someone, someday, that knows something about the internals of Propel can help me out. For those that don't know what Propel is: Propel is a full-service object persistence and query toolkit for PHP. I use to use my own library for object persistance, but I just no longer had the time to develop on it and propel did everything I needed much better. (For instance, my library wouldn't generate my stubs for me I have several different applications that I do constant work on for this example I will use two of the applications, one of them is a product catalog and one of them is a CMS system. In many of these application, there are several domain level objects that are actually shared throught several applications. One of the objects that are shared between my cms and my product catalog is a database I use to hold media file data (images, flash, pdf, word docs, anything really.) I like to keep most of my domain level classes (with the exception of a few extremely specialized ones) in a central location on my production and dev servers. This media object is one of them. If I make a change to my media object to allow for some more meta data to be associated with each object I want these changes to effect all applications that use this object. If I all of a sudden want to add thumbnail support to my media object (it's already there btw, just using it as an example.) I don't want to have to maintain seperate copies of a media object to allow this. Now, the way the propel generator works, is it allows you to generate source code for database schemas that are defined in xml files. It gives you some degree of organization to the resulting classes by allowing you to assign databases, or even tables to specific packages. The resulting code is then seperated into directories with the same names as the package. So I have accordingly used this to my advantage. I have one package called medialibrary that contains the object classes for the tables required by the medialibrary. I have another package called productcatalog that holds those classes. I of course don't include the medialibrary classes in that package as really they are more of an 'add-on' to the product catalog (granted, very few people would want a media catalog with no pictures In order to prevent my schema files from being inordinately long and to keep the generated sql files somewhat specific to each application. I have a seperate schema xml file for each package. However, obviously some of the tables from the productcatalog package are going to need to link (foreign keys) to tables from the medialibrary package. Thankfully there is a tag supported by propel called <external-schema> which allows you to pass a filename to another schema file as an attribute. The generator will then open this schema and use it as a reference to figure out what functions are needed. However, whenever a group of tables is opened via external-schema, the package names are overwritten! Which mean all of the classes in my productcatalog package that depend on classes in the medialibrary package are attempting to load them from the productcatalog folder. I can't figure it out. So, if you know alot about propel and can help...please oh please oh please leave a comment. New 'AJAX' Tutorial, ala Joshua EichornI just got done reading through this post by Joshua Eichorn. It is a nice little tutorial on how to set up and create a small little app with HTML_AJAX. Unfortunately for me I just started using JPSpan and have finally gotten use to all of it's quirks. So I probably won't change anytime real soon. I'm definantly putting it on my list of things to explore though. If you know JPSpan well, from what I can tell you could figure HTML_AJAX out very quickly. It is extremely similar. Maybe after I get some breathing room I'll do a full review of HTML_AJAX. For those that just want to know a little more about the latest technology to be named after a cleaning product, Joshua has alot of excellent AJAX resources on his site and linked to from his site. Tuesday, August 16. 2005var_export/print_rIlia Alshanetsky posted this a few hours ago on his blog: Security Implications of var_export/print_r It basically talks about how allowing user supplied (POST, GET or even COOKIE really) posts to be saved to strings via var_export and print_r can be hazardous to one's server's health. I hadn't thought about this in a long time. I ran into this when I used smarty for the first time. I had inadvertantely passed a rather large object with quite a few references to other objects to the template, so when I tried to enable smarty's debug feature, it choked on me cause I went passed my memory limit. (I think it was still at the default at that time: 8MB) I think this post, yet again, shows how important it is that user supplied data gets filtered. I just read an article Ben Ramsey wrote for PHP|Architect's latest issue regarding input filtering. It's actually the first part of an 'n' part series so it didn't really get into alot of the meat. However he makes some really good points about why input filtering is needed and gave an overview of a couple principles to use when filtering input. If I recall right, Chris Shiflett also has a small bit on input filtering in that issue too. So i would recommend picking it up if you have some spare change. Thinking too muchI have spent the last couple days of my life observing and occasionally lending a hand in some of the php channels on irc.freenode.net. While I was watching questions and answers fly by in #php I observed something peculiar that has now led me to this thought: One of the biggest problems many new PHP Programmers face is that they completely overthink their problem. What I mean by this is that they have a tendancy, when they run into a new problem, to quickly think of a single possible solution, and then before coming up with a few alternatives they just dive headlong into that solution. After thinking about it a little longer I also realized that more experienced developers have the exact same problem. I'll get to that in a second. First I want to talk about the events that led me to this conclusion. For instance, someone asked the following question: Is it possible to suck jpeg data out of a database and display it in a webpage without saving the data to a temp file? Now, first off most of would probably say "why would you want to do that? It slows down your db! Save the image to a file, reference the filename somehow in your database and then create a script that will just pull the filename out of the database and pass thru the contents. That reply however would be completely countertuitive to my example and I don't want to go dig through logs to find another one. So, in my fantasy world where we are not going to tell him that he doesn't want to store the image in a database we would tell him this: "Sure, just create a seperate script that will accept a record id, have it load the image field from that record and pass the results with an image/jpeg header. Well...here is what happened. The guy asking the question is Q, the guy(s) answering are A<n> (n denoting the different answerers) Q: Is it possible to suck jpeg data out of a database and display it in a webpage without saving the data to a temp file? A: yes, store as a blob. then re-create the headers using php's header() Q: thanks. I tried that, but I only get the image.. What I want is to embed this image in html. When I use the header method it doesn't render the rest of the html. A: like inline mime images? Q: yea, I guess. You know, have some text, tables, and then this image that I sucked out of the database all on the same page. A: so you want the image data embedded in a single html output? Q: yes, if possible. I guess I could store the image data in a tmp file then use <img src> but I was hoping I could do it without using tmp files. do you know if this is possible? A: I'm pretty sure it's possible...with modern browsers. but pretty rare to inline images like that At this point another guy jumps in to lend a hand....we will call him...A2 A2: you can't mix text and image data in the same docuement, without using browser specific tricks Q -> A2: ahh, okay A2: your best bet is to have a sepeerate image "proxy" poage, that you simply call with parameters to return n image. like image.php?imageid=102 A: best to just use sessions and pass stuff to an image gen script Q: Hmm. I can probably do <img src='createImage.php'> and then output the headers and data in the createImage.php file. At this point everybody tells him yup, that's what you want to do, he then says thanks and accuses himself of having a 'brain hiccup' So, from what I gathered of the situation it almost looked as though he knew what the solution was...he just kept on subconciously blocking it out so he could figure out how to literally embedd the image within the page. At first I thought, rookie mistake. Then I realized I am guilty of the same thing sometimes. Granted I don't fret over things like how to display images effectively. However, I probably have at least a few more years of experience under my belt. He's probably just getting started, so it's perfectly acceptable for him to have the question of how to display images the best. I tend to make my overthinking mistakes on a much more grandios scale.
Now the newest thing is AJAX, and we are all again scrambling to figure out, "how can I use that in my code?" or more appropriatly for some of us "how can I use this in ALL of my code?" Now, don't get me wrong, I like the whole AJAX concept (hate the name...even if it's very...clean) and I like the whole SOAP concept. My point is that us, "bleeding-edge" developers have the tendancy to try and fit all this technology in alot of places where it probably doesn't belong. Now, to try my best and bring this full circle. If we didn't concentrate so much on new technology maybe we wouldn't have all these "pushing square pegs into round holes" problems. I am now resolving to give equal thought time to both new technology and the old ways of doing things. Like some wise man once said, "Moderation is the best medicine." New technology isn't bad, but old, proven technology is pretty darn good. So, am I crazy, justified, or just plain stupid? Friday, May 13. 2005Trinity AnnFinally had my first baby I would expound a little more but I am on a pretty tight schedule Things didn't go completely as expected. We were shooting for a natural birth but our baby decided she really wanted to come out but first so we ultimately ended up having to op for a c-section. My wife did absolutely amazing, I don't think I have ever seen anybody with so much determination. Baby and mom are both doing terrific now. So without further adieu, here are some pictures. (click on the thumbnails for full size) Thursday, May 5. 2005Implementing Apache-Test Support into Simple TestI have successfully gotten Simple Test to test itself in Apache-Test. It wasn't that hard really. I have added very basic Apache-Test support by just subclassing the SimpleReporter class in SimpleTest. The new class name is TAPReporter. It basically just allows a test to create TAP compliant (see this post) output which is then read by Apache-Test. There are a few things which in my opinion could be changed in SimpleTest in order to make TAP complancy much better and it would actually improve some of the functionality of SimpleTest apart from Apache-Test. I am somewhat hesitant to make those changes right now however as the code is not mine and really should be discussed with the creator of SimpleTest. (Which I do plan on doing.) I will outline later in this articles the changes I think would be useful. For now I would just like to review what I did do and how to run the tests. Continue reading "Implementing Apache-Test Support into Simple Test" Wednesday, May 4. 2005TAP Format Explained (Apache-Test)
As some of you know I am currently working on a project to allow Simple Test to be Apache-Test
compliant. The process to take in doing so is to enable Simple Test to
produce TAP compliant output. To do so obviously requires a healthy
knowledge of the different aspects of the TAP protocol. The best way
for me to get a grasp of something is of course to write about it. I
gleaned pretty much all of this information from CPAN's TAP format documentation.
Continue reading "TAP Format Explained (Apache-Test)"
« previous page
(Page 2 of 5, totaling 63 entries)
» next page
|
Paying for the SiteQuicksearchCategoriesArchivesDaily Readsadam trachtenberg
Ben Ramsey Chris Shiflett Dynamically Typed (Harry Fuecks) george schlossnagle John Coggeshall John Lim Marco Tabini PHP Application Tools PHPCommunity.org Planet PHP Sebastian Bergmann Sklar The PHP WTF Tobias Schlitt Tom Sommer Wez Furlong Syndicate This Blog |
