Stop custom editing core WordPress files… It’s all here: http://codex.wordpress.org/Writing_a_Plugin. It only seems like a small mountain the first time through. ;-)
Category Archives: PHP
Post via script
I just whipped up some PHP and threw it in the root of a brand new WordPress 2.9.2 install:
Voila. The post appeared when navigating to the .php file.
See: http://prex.wordpress.org/Function_Reference/wp_insert_post.
For more creativity, get into the database: http://prex.wordpress.org/Function_Reference/wpdb_Class
Portfolio
I have gathered some of the better work that I have done over the years, took some screenshots, and posted them to a running instance of MooFlow.
See it at the following url: http://karlherrick.com/demo/pub/mooflow/
iUI and the iPhone
My employer recently purchased a set of iPhones from AT&T for those in the workforce that have a need for such a thing. One of our first priorities was getting our rolodex accessible (read only) from the road. The main problem is that the data is in a restrictive, old school database. Until we can find time to move it into a more open platform I did the following:
- Set up a routine for dumping the rolodex into a flat xml file monthly
- Coded the searching of the the data using PHP and SimpleXML
- Coded the cookie management (sessions) and most important, a “remember me” feature (because Safari doesn’t remember passwords on the iPhone)
- Found this lovely library for creating iPhone compatible user intarfaces via the web (read, looks like a native app): iUI (User Interface Library for Safari development on iPhone)
Checkout the screenshots:
It’s pretty cool, because if the contact in the rolodex has a telephone number, address, email address, or webpage associated with them, the data will be displayed and linked to iPhone friendly functions… For example, the telephone number, when clicked on will provide a call button. An address clicked on will link to the built in maps app. Email links open up directly in the built in mail app. Finally, of course, webpages openup in Safari.
So here’s for getting the world more connected… one app at at time.
Goldfish and forged spam
Recently I had the goldfish autoresponder (vacation responses / email auto reply) setup for a user for about one week. Checking their inbox about half way through this time period revealed it having over 47,000 unread messages. What was happening is that spammers were sending email with forged headers. Have you ever received a spam message that apparently has been sent from yourself?
I suppose it can be accomplished via a variety of ways, however I was able to reproduce this particular issue via generating one of these tasty spam mails via the following (all internally of course… I am not a spammer):
telnet smtp.example.com 25and then issuing these commands:
ehlo workstation.example.com mail from: rcpt to: data From: To: Subject: testing a loop Message text . quit
Notice the mail is being sent to the user… and from the user…
- The server would receive the email addressed to emailuser@example.com
- goldfish would parse the message and notice it needed to respond to… emailuser@example.com
- The mail was delivered
- Rinse, wash, repeat
The source of the message looked something like this:
root@server:/var/local/vmail/example.com/emailuser# cat new/1220557062.P6882Q0M652544.server,S=1082 Return-Path: Delivered-To: emailuser@example.com Received: from localhost (localhost [127.0.0.1]) by server.example.com (Postfix) with ESMTP id 923E9185F7 for ; Thu, 4 Sep 2008 15:37:42 -0400 (EDT) X-Virus-Scanned: Debian amavisd-new at server.example.com Received: from server.example.com ([127.0.0.1]) by localhost (server.example.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id q3tScOaitRoS for ; Thu, 4 Sep 2008 15:37:42 -0400 (EDT) Received: from workstation.example.com (workstation.example.com [xx.xxx.xxx.xx]) by server.example.com (Postfix) with ESMTP id B89E1185EB for ; Thu, 4 Sep 2008 15:37:25 -0400 (EDT) From: To: Subject: testing a loop Message-Id: Date: Thu, 4 Sep 2008 15:37:25 -0400 (EDT) Message text
and to prevent goldfish from causing havoc on the particular inbox (or mitigating what was already done… and preventing future issues), I added the following PHP:
//strip the line break from $address for checks $addressCheck = substr($address,0,strlen($address)-1); if ($addressCheck==$email) { $log->addLine("Email address from autoresponder table is the same as the intended recipient! Not sending the mail!"); break; }
just before letting the mail being sent…
mail($address, $subject, $message, $headers);
I love goldfish. It’s like a do it yourself autoresponder! Keep in mind, this code works on Version 002, patch level 1, but could very well not work on any future releases (there have been indications that a newer version is in the works). Maybe I will post a few more tweaks in upcoming posts if the latest stable stays around for much longer.
Autoresponders – a loop
This past week I encountered an interesting situation between two web applications I work with regularly. The first is the goldfish autoresponder for postfix. The second is RT: Request Tracker.
The situation went something like this:
- I had a ticket in RT that I wanted to resolve.
- I set the form to cc the comment to a group of users who were interested in the details of the resolution.
- I applied the ticket in RT.
- RT cc’ed the users about the resolution.
- One of the users had an autoresponder setup using goldfish, so it emailed back to RT about the user’s absence.
- RT opened a ticket with the content of the email from the autoresponder, faithfully attaching the subject explaining the user’s absence.
- RT then responded to the user’s email account about the new ticket’s creation.
- Again goldfish autoresponds to a message from RT, creating a loop.
Every five minutes a new ticket was being created in RT because of goldfish’s configuration and cron job being set to run that often. I caught the cycle happening when the incoming queue of tickets had three or four created with their subjects typical of those created by an autoresponder.
reCAPTCHA plugin error messages
By default, on two of my installs of reCAPTCHA Plugin for WordPress – v2.7, I receive no error message if the captcha is entered incorrectly… the user of the weblog is to assume that they made a mistake I guess…
That is until I wrote this script to check for error messages being passed around on the URL by the plugin:
if (window.location.search != "") { var searchArray = window.location.search.split("&"); for (var i=0; i < searchArray.length; i++) { var searchSubArray = searchArray[i].split("="); if (searchSubArray[0] == "rerror" && searchSubArray[1] == "incorrect-captcha-sol") { document.write("<p>The two words in the picture were typed incorrectly.</p>"); } } }
Just drop that snippet into your “comments.php” template. When the captcha is filled in incorrectly, the plugin adds “rerror=incorrect-captcha-sol” to the url. This checks for that string, and if found, writes an error message in red.
reCAPTCHA plugin styling
Installing a CAPTCHA implementation on WordPress is quite easy when using the reCAPTCHA plugin, however the styling is hard coded into the main php file included.
Goto the installation directory, for example, “wp-content/plugins/recaptcha-wordpress-2.7″ and edit recaptcha.php. Look for the line that embeds the theme type and change it.
var RecaptchaOptions = { theme : "red", tabindex : 5 };
I used the “clean” theme. There are other options and ideas for editing the code with css changes.
Motion Capture Sorting
When using Motion for a security camera setup, it can generate a lot of files… One installation I have setup has “Encode movies in real-time” enabled, so not only are there many .jpgs in the capture directory, but also .avis.
This can become quite tedious… copying and pasting them from a GUI every day. Consequently, I would let the files simply pile up for a few days before moving them around. Then it became a big job.
Scripting to the rescue. The following below is a PHP-CLI script, that when run from the motion capture directory will sort the various files into a nice little structure that allows for dropping the .avis into a play list for viewing, and keeps the .jpgs around for backup.
#!/usr/bin/php <?php $fileExtOne = ".jpg"; $fileExtTwo = ".avi"; $fileNameArray = array(); //dump filenames (ending in .jpg or .avi) //in current directory into array if ($handle = opendir(".")) { while (false !== ($file = readdir($handle))) { if (substr($file, -4) == $fileExtOne || substr($file, -4) == $fileExtTwo) { array_push($fileNameArray, $file); } } closedir($handle); } //make multi-dimensional array with substrs of filename for ($i=0; $i<count($fileNameArray); $i++) { $fileNameSplit = split("-",$fileNameArray[$i]); $dirArray[$i]["group"] = $fileNameSplit[0]; $dirArray[$i]["year"] = substr($fileNameSplit[1], 0, 4); $dirArray[$i]["month"] = substr($fileNameSplit[1], 4, 2); $dirArray[$i]["day"] = substr($fileNameSplit[1], 6, 2); $dirArray[$i]["name"] = $fileNameArray[$i]; } //create unique array with new directory names and mkdir them for ($i=0; $i<count($dirArray); $i++) { $dirNameArray[$i] = $dirArray[$i]["year"] ."-". $dirArray[$i]["month"] ."-". $dirArray[$i]["day"] ."/". $dirArray[$i]["group"]; } $uniqueNewDirNames = array_unique($dirNameArray); foreach ($uniqueNewDirNames as $value) { $splitUniqueDirNames = split("/", $value); mkdir($splitUniqueDirNames[0], 0755); mkdir($splitUniqueDirNames[0] ."/". $splitUniqueDirNames[1], 0755); } //move files into the appropriate directories for ($i=0; $i<count($dirArray); $i++) { if (substr($dirArray[$i]["name"], -4) == $fileExtOne) { rename($dirArray[$i]["name"], $dirArray[$i]["year"] ."-". $dirArray[$i]["month"] ."-". $dirArray[$i]["day"] ."/". $dirArray[$i]["group"] ."/". $dirArray[$i]["name"]); } if (substr($dirArray[$i]["name"], -4) == $fileExtTwo) { rename($dirArray[$i]["name"], $dirArray[$i]["year"] ."-". $dirArray[$i]["month"] ."-". $dirArray[$i]["day"] ."/". $dirArray[$i]["name"]); } } ?>
Here’s what find returns after running the script on the capture directory full of sample .avis and .jpgs.
username@workstation:~/captures> find . . ./2008-01-06 ./2008-01-06/01 ./2008-01-06/01/01-20080106145755-02.jpg ./2008-01-06/01/01-20080106145755-04.jpg ./2008-01-06/01/01-20080106145756-00.jpg ./2008-01-06/01/01-20080106145757-00.jpg ./2008-01-06/01/01-20080106145757-01.jpg ./2008-01-06/01/01-20080106145758-00.jpg ./2008-01-06/01/01-20080106145758-01.jpg ./2008-01-06/01/01-20080106145758-02.jpg ./2008-01-06/01/01-20080106145758-04.jpg ./2008-01-06/01/01-20080106145758-05.jpg ./2008-01-06/01/01-20080106145758-06.jpg ./2008-01-06/01/01-20080106145759-00.jpg ./2008-01-06/01/01-20080106145808-01.jpg ./2008-01-06/01-20080106145755.avi
Currency Conversion
A long time ago, I wrote a PHP script to compare current gas prices from Michigan and Ontario in current US and Canadian dollar rates from the following three sites:
http://ontariogasprices.com/
http://michigangasprices.com
http://finance.yahoo.com
as soon as all of the data was retreived (gas prices used a php web scraping library, currency data from Yahoo! Finance retrieved similarly to how Exch does), do the math, and it would let me know who was paying what for gas prices… well using a little Google search, most of the logic of this script became a lot easier (well it has been for some time, but I thought I would share on this little known secret :-)… for example Google these searches below:
3.16 USD per gallon in CAD per liter
3.16 (U.S. dollars per US gallon) = 0.945976868 Canadian dollars per liter
1.10 CAD per litre in USD per gallon
1.10 (Canadian dollars per litre) = 3.67450845 U.S. dollars per US gallon
1.10 CAD per litre in EUR per gallon
1.10 (Canadian dollars per litre) = 2.90268461 Euros per US gallon
1.10 CAD per litre in EUR per litre
1.10 (Canadian dollars per litre) = 0.766808149 Euros per litre
Google even acknowledges the alternative spellings of “liter/litre” … nice huh?