Vid's thoughts, comments and code

I ran in to a situation with some inherited code today.
The developer wanted to redirect users to a course listing page if they landed on a date/time listing that couldn’t be found.
See this code below; they check for an empty $dateTime var and create a log message before attempting to redirect the user.

if (empty($dateTime)) {
$logger->err('DateTime with the id of '.$_REQUEST['dt_id'].' cannot be located.');
Header( 'Location: course_list.php'); // Go back to the course list
exit;
}

Unfortunately the headers had already been sent to the browser and the Header function call was ignored and the user only saw a partially loaded web page with no body content.

In the past I had implemented a fall-back with a meta and js redirect but I thought that could be improved upon.Stack Overflow had some nice responses to a previous question and one of them included Redirect function that checked if the headers were already sent: headers_sent().
I liked that. So I added my fall back to that function.

Next I swapped that Header function call with the Redirect function call:

if (empty($dateTime)) {
$logger->err('DateTime with the id of '.$_REQUEST['dt_id'].' cannot be located.');
Redirect('course_list.php'); // Go back to the course list
}

Problem solved.

Here’s the function (note: it’s wrapped in a function_exists() call to make sure I don’t declare this twice at any point):

I’ve been using make files a lot lately and when ever I’m ready to release an updated file I like to verify that all the project versions are up to date.
To leverage Drupal’s update functionality each project needs to be enabled. So I typically generate a new site from the make file and enable all the projects with drush. The key to that is the combination of commands:

drush en `drush pm-list --status="disabled,not installed" --pipe`

Here I’m enabling a list of module; specifically drush’s list of disabled and not installed modules.

drush pm-list --status="disabled,not installed"

That code gets you part of the way there. The addition of this:

--pipe

makes it a script-able list. Then when I surround that with back-ticks and feed it to

The old script opened a URL in several browsers (failing to load the web page in parallels VM browsers). The updated script now plays nice with Parallels and captures any URL in your clipboard if applicable.
The key to playing nice with Parallels is to manually drag the application icon into the script so that the address of the browser in the remote VM is accessible to the script.
Here’s the updated script: (more…)

I have 20000 email subscribers for two email lists (cjobs and ucjobs). These were all imported into our new Mailman service.
I had a few settings I needed to change to accommodate using Mailman as a bulk mailer. And it’s going pretty well.
First there were normal things like pre-pending the default email subject, updating the list name and bounce protocols, making sure no-one can post to the list except the one authorized user (bulk moderate every user).
That was easy.

But then there’s a default setting where any list member can view all the other members of the list… not good.
First I updated the html docs, removing the relevant info.
Then I needed update all the users; but there’s no bulk operation for that.
Instead there’s a Member Mgmt screen with columns of check boxes. CheckBoxMate to the rescue…
Almost; Mailman displays a max of 30 members at a time… (20000 / 30 = ouch), that’s a lot of clicking and dragging. (more…)

When I’ve migrated sites into Aegir recently, I find that the users have many links in the content hard-coded to files in the default directory.
While it is possible to use the Scanner search & replace module to ferret those out. It’s not always thorough enough. For example, it doesn’t search and replace menu link urls, or content in blocks, views, headers, footers or custom fields. You can specify custom fields and locations to search but that’s another bag of worms that fraught with issues.
So I wanted to find a simple way to catch any hard coded links that I missed.
Enter the Custom Error module.

I’ve been using it to provide a populated search form on the 404 ‘Not found’ page as well as a site map but I also have a few custom redirects in there so adding an option for sites/default/files was simple.

I recently wanted to combine two tables; Hoping to show all OA employees and any ‘1 on 1’ Review data for each. A simple query restricted my results to only show those employees who had review data. So a Left Join was in order. Luckily we’re using Oracle 9 and I didn’t have mess with weird join syntax (see Burleson’s article here: http://www.dba-oracle.com/tips_oracle_left_outer_join.htm).

All I had to work out was how to separate my criteria for the left table from the rest of the query.

We have 7 units at the University and a Chart of Accounts is maintained defining each department and where they fall in the organization structure. The unit for each department is determined by looking up the 2nd level of depth in the roll-up hierarchy.

For example; here’s the first few rows of the chart:

Orgn

Title

Pred

Data-Rollup

0

University of Oregon

/University of Oregon

500

President of the University

0

/University of Oregon/President of the University

100100

President Administrative Operations

500

/University of Oregon/President of the University/President Administrative Operations

101001

President’s Office Ops

100100

/University of Oregon/President of the University/President Administrative Operations/President’s Office Ops

The Pres. Department (500) reports to the University (0) and the Presidents Office Operations (100100) reports to the President (500) and you can see that hierarchical chain in the Data-Rollup column.
I’ve posted about how I created the data-rollup column in Data Warehouse queries here: updating-the-chart-of-accounts-to-include-the-hierarchy-path.

The units are only departments that report to the University (0):

Orgn

Title

Pred

Data-Rollup

Unit from rollup

500

President of the University

0

/University of Oregon/President of the University

President of the University

100000

Senior VP & Provost

0

/University of Oregon/Senior VP & Provost

Senior VP & Provost

200000

VP Academic Affairs

0

/University of Oregon/VP Academic Affairs

VP Academic Affairs

400000

VP Finance & Administration

0

/University of Oregon/VP Finance & Administration

VP Finance & Administration

422000

VP Student Affairs

0

/University of Oregon/VP Student Affairs

VP Student Affairs

500000

VP University Relations

0

/University of Oregon/VP University Relations

VP University Relations

540001

VP University Development

0

/University of Oregon/VP University Development

VP University Development

690000

VP Rsch, Innovation & Graduate Educ

0

/University of Oregon/VP Rsch, Innovation & Graduate Educ

VP Rsch, Innovation & Graduate Educ

900000

UO General

0

/University of Oregon/UO General

UO General

Here you can see I’ve added a new column highlighting the unit as well. That column is the result of parsing out the Data-Rollup value and displaying the 2nd level.

Column G is the Data-Rollup value and basically, I look up the position of the 2nd ‘/’ and then capture everything between that and the next slash.

That’s handy later on when you’re looking a department that is nested 7 levels deep and you want to organized your data by unit.
In this use case, I have a report review dates for employees which includes their Department Title and Org Code.
To add the Unit to that report I used a simple vlookup in excel referencing the Chart of Accounts.
Steps:
Include a copy of the Chart of Accounts spreadsheet in your workbook.
Highlight the relevant section of the chart and create name for that section; I used ‘chart_of_accounts’.
With vlookup you need the first column of the selection to be the lookup value so be sure to start with the org code.
The add a column to your spreadsheet for the Unit and add the vlookup code.
Here’s the formula for Row 4 of that spreadsheet:

=VLOOKUP(I4,chart_of_accounts,6,FALSE)

Column I is employee’s Org Code and I use that to find the unit in the Chart of Accounts.
Here’s a quick look at what that looks like in the report:

Nothing too exciting going on here but I wanted to document it so I have a reference later.
I’m inclined to add the unit to my data warehouse query and do away with this step but that’s for later.

I have a couple of personal sites that I don’t use much but they have been getting pounded by hackers or at least hacker’s scripts.
So I grown tired of watching the same IP addresses bombard my different sites looking for vulnerabilities. They usually generate about 100 404’s at a time and those are only the attempts that failed. So to stop repeat offenders I wrote this script.
Many thanks to some code examples at cyberciti.biz and gabeanderson.com.

for i in $FILES
do
echo "working on " "$i"
cp "$i" "$i.blockip_saved"
sed "s##Deny from $1n#g" "$i.blockip_saved" > "$i"

rm $i.blockip_saved #comment this line to save backup.
done

So it takes the ip address I pass it and looks in each of the .htaccess files for the tag: prepending that with “Deny from _ipaddress_” and we’re good to go.

So now I just have to type the offending ip address in once and it propagates across my sites.
It works for multiple ip’s as well; for ex: ./blockip “91.121.83.100, 91.121.160.160”

This method seems to work OK for now. I still get 404’s when the repeat offender returns but this time they are denied access before they might find a vulnerability.

It’s not a perfect solution. I would be nice to detect the hack attempt while it’s happening and block them dynamically while sending an abuse notification email to their ISP, but I haven’t stumbled across any scripts that will get me there yet.