battis.net and I'm all out of bubble gum…

There seems to be some discussion online, but no actual, y’know… documentation regarding these two server variables.

Apparently they were introduced in Apache 2.3, and they are wicked useful, it turns out. At least, wicked useful if what you want to do is figure out what the URL of a to a specific file on the server is, assuming that you have only its path and some other file’s URL.

What follows seems to be empirically correct, but I welcome corrections:

DOCUMENT_ROOT is the system file path to the root of the web server’s document directory (usually something like '/var/www/')

But, imagine that per-user web directories have been enabled on your server. That is, if my user is foo, then there is a directory /home/foo/public_html in which all of foo’s web documents are stored (and served from). This is (probably) outside of the main server document root directory. The URL of foo’s web files would be something like http://example.net/~foo/index.html.

And this is where our variables enter the story.

The Empirically-based Theory

CONTEXT_PREFIX is the portion of the REQUEST_URI that triggered the server to serve up a file outside of the document root. And CONTEXT_DOCUMENT_ROOT is the root directory that that particular CONTEXT_PREFIX is rooted at. Nota bene: conveniently CONTEXT_DOCUMENT_ROOT contains the path the document root for whichever context this particular script was accessed through (so it would be the same as DOCUMENT_ROOT within the server’s document root, while CONTEXT_PREFIX would be an empty string, since there is no context prefix within the server’s document root.

A file in a user web directory

Consider this extended example:

User foo has placed files in that user’s public_html directory. There are nested directories within that public_html directory, and we are accessing a file at this URL:

http://example.com/~foo/dir1/dir2/dir3/file.php?paramA=bar#baz

This file is stored at the following path in the file system:

/home/foo/public_html/dir1/dir2/dir3/file.php

Thus, a sampling of relevant server variables (presented in $_SERVER for the PHP users amongst us) would be:

REQUEST_URI is /~foo/dir1/dir2/dir3/file.php?paramA

SCRIPT_NAME is /~foo/dir1/dir2/dir3/file.php

CONTEXT_PREFIX is /~foo

CONTEXT_DOCUMENT_ROOT is /home/foo/public_html

A file within server’s document root

Alternatively, a similar example within the server’s document root:

http://example.com/dir1/dir2/dir3/file.php?paramA=bar#baz

is a URL that access a file at:

/var/www/dir1/dir2/dir3/file.php

This results in the following values:

REQUEST_URI is /dir1/dir2/dir3/file.php?paramA

SCRIPT_NAME is /dir1/dir2/dir3/file.php

CONTEXT_PREFIX is (the empty string)

CONTEXT_DOCUMENT_ROOT is /var/www

For giggles, I cooked up some code to generate the URL of particular directory based on this information. I used the following little snippet to do this in DataUtilities::overlap() in battis/data-utilities:

use Battis\DataUtilities;
 
$path = __FILE__;
$url = (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] != 'on' ?
		'http://' :
		'https://'
	) .
	$_SERVER['SERVER_NAME'] .
	$_SERVER['CONTEXT_PREFIX'] .
	str_replace(
		$_SERVER['CONTEXT_DOCUMENT_ROOT'],
		'',
		$path
	);

March 30th, 2016

Posted In: How To

Tags: ,

This is really just a quick hack: all it does is insert the correct timezone description in the header of an iCalendar feed. But if the server that is generating the iCalendar feed doesn’t do it, someone has to. The script generates a URL that can then be subscribed to by your Calendar reader of choice. (I’m running this on my server and using it daily to good effect, but decline to share bandwidth with the world for this one):

$filename = "calendar";
 
if (isset($_GET["url"]))
{
	$url = $_GET["url"];
 
	if (!isset($_GET["show_url"]))
	{
		preg_match("|.+\/([^?]+)\??|", $url, $matches);
		if (isset ($matches[1]))
		{
			$filename = $matches[1];
		}
 
		$calendar = file_get_contents ($url);
 
		if ($calendar)
		{
 
			//$output = preg_replace_callback ("/(DATE-TIME:)(\d{4,4})(\d{2,2})(\d{2,2})T(\d{2,2})(\d{2,2})(\d{2,2})[^Z]/", "adjustTimeZone", $calendar);
 
			$timezone = "X-WR-TIMEZONE:America/Los_Angeles\n" .
				"CALSCALE:GREGORIAN\n" .
				"BEGIN:VTIMEZONE\n" .
				"TZID:America/Los_Angeles\n" .
				"BEGIN:DAYLIGHT\n" .
				"TZOFFSETFROM:-0800\n" .
				"RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU\n" .
				"DTSTART:20070311T020000\n" .
				"TZNAME:PDT\n" .
				"TZOFFSETTO:-0700\n" .
				"END:DAYLIGHT\n" .
				"BEGIN:STANDARD\n" .
				"TZOFFSETFROM:-0700\n" .
				"RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU\n" .
				"DTSTART:20071104T020000\n" .
				"TZNAME:PST\n" .
				"TZOFFSETTO:-0800\n" .
				"END:STANDARD\n" .
				"END:VTIMEZONE\n";
 
			$loc = strpos($calendar, "BEGIN:VEVENT");
 
			$output = substr($calendar, 0, $loc) . $timezone . substr($calendar, $loc, strlen($calendar));
 
		    header("Content-Type: text/calendar");
		    header("Content-Disposition: inline; filename=$filename-pacific-timezone.ics");
			echo $output;
			exit;
		}
	}
}
<h1>vCalendar Time Zone timezone</h1>
	<p>This is quick script to "de-float" calendars in the vCalendar format which do not specify time zones for their events. This script will automatically add the Pacific time zone information to the calendar at the URL entered below. Copy-and-paste the resulting URL below into your calendar reader of choice. <a href="http://battis.net/link/timezonescript">The source of this script is freely available.</a></p>
	<form action="<?= $_SERVER["PHP_SELF"] ?>" method="get">
		<input type="hidden" name="show_url" value="" />
		<p>Calendar URL <input name="url" type="text" value="<?= $url ?/>" /></p>
		< ?php
				$newUrl = "http://" . $_SERVER["SERVER_NAME"] . $_SERVER["PHP_SELF"] . "?url=" . urlencode($url);
				echo "<p><a href=\"$newUrl\">$newUrl</a>";
		?>
		<p><input type="submit" value="Generate"/></p>
	</form>

February 14th, 2011

Posted In: How To

Tags: , , ,

A few days ago (well, maybe a couple weeks ago), I was chatting with one of my colleagues about how I go about testing out new plugins and themes for WordPress µ before loading them on our school blog server. It seems like documenting my process might be generally helpful, so…

To start with, I decided (after ten years of mucking out Apache config files and PHP extensions and custom MySQL installs — thank you so, so much Marc Liyange for your timely and helpful installers!), that I was a grown-up and could spend $60 on a tool that makes my life easier: I run MAMP Pro on my MacBook. This means that I have a generic Apache/PHP/MySQL stack that supports commonly-used PHP extensions, Apache configurations, etc. I have redirected the document root of my install to my regular user’s Sites directory in OS X (~/Sites) so that I have ready access to the backend files of for my test installs. The net result: WordPress’ famous “Five Minute Install” is now true of almost any LAMP-based web application — I had a five-minute install of Drupal, Moodle, Joomla… you name it.

I’ve also settled into using Coda ($99) to edit HTML/PHP source code, since I particularly like the built-in terminal and publishing management features.

With WordPress µ installed (which, I guess, is now calling itself WPMU or WordPress MU or even WordPress 3 in betas), I now do the following:

  • I install create a new blog for each new theme or plugin that I want to test out. I follow a pretty intuitive naming scheme: the URL for the blog is the URL for the plugin or theme, and the name of the blog is the name of the plugin or theme (so WordPress Hashcash is at …/wp-hashcash and named WordPress Hashcash).
  • As I create each new blog, I create a new user to be that blog’s administrator. I almost never use this login, but it means that I have one user who is matched to each blog. In doing this, I make heavy use of Gmail’s + modifiers, so new user emails look like mygmailaddress+talyn+wpmu+blogurl@gmail.com — this lets me catch and filter relevant emails easily on the other end. (I developed this system when I was testing plugins that sent email notifications). For the curious, Talyn is the name of my laptop (so I know which server is sending me email) and WPMU is the keyword to distinguish these emails from, say, Drupal notifications.
  • I also have six generic users that I add to most (not all — I add them as needed) blogs, each with their own standard privileges:
    • Anna “Annie” Administrator
    • Edward “Eddie” Editor
    • Allison “Allie” Author
    • Christine “Chrissy” Contributor
    • Samuel “Sammy” Subscriber
    • Nathan “Nate” No Privileges

    I actually included nicknames so that I could control for how different themes displayed usernames (since I’m thinking about FERPA and how it may apply to our students on our school blogserver).

  • I have one blog on which I never activate themes or plugins, which I lyrically call “Is this blog in the blast radius?” This is based on my experience installing Digress.it on WordPress µ at the start of the year (it hosed every blog on the server, rather than just the one where it was activated). I check this before I deem any test complete.
  • One tricky thing that I did was that I set up MAMP to run Apache and MySQL as my local user account on my MacBook, and I have set permissions on my Sites directory so that my local user has all privileges, as does the www group, and other users have read/execute privileges (chown -R seth ~/Sites; chgrp -R www ~/Sites; chmod -R 775 ~/Sites). This means that I usually don’t run into problems with web apps that want to move or create files. This is also, of course, totally insecure. Que sera, sera.
  • I have an extra blog set up on my WordPress µ install that runs Feed WordPress, and it republishes the feeds for all of the other blogs on the server tagged Note. This means that I can post something tagged Note to any blog that I’m working on and then have all my notes together in one place. Adding the subscriptions to the Feed WordPress blog is a manual step, but not prohibitively difficult. And it really does mean that I have one place for all of my notes on how things went (or didn’t went) in my WordPress µ testing. I have the feeds categorized as Plugins, Themes, Configuration and Hacks, since those are generally what I’m testing (and mostly Plugins, at that).
  • One hitch in my system is that I have opted to keep my system entirely up-to-date (I’m running WordPress µ 2.9.2 with the most recent versions of all my plugins), while our school blog server is still at 2.8.4a. Generally speaking, this hasn’t been much of a problem, but when I’m particularly concerned, I will sometimes check things out on a lingering 2.8.4a install before loading it.

May 18th, 2010

Posted In: How To

Tags: , , , , , , , , , ,

css.php