Category Archives: Web Development

Toughest Developer Puzzle Ever

Jeff Blankenburg has put together an incredible puzzle over at http://www.toughestdeveloperpuzzleever.com/tdpe/. Absolutely a ton of fun. It took me a few hours to get through it myself!

The Future of Web Pages

This morning I came across this jQuery library and it got me to thinking a little bit. All of the web sites that I currently have coded ( I don't really do the design) tend to use .NET or PHP that is mashed up with some Javascript here and there.


I'm wondering why we tend to still use PHP and .NET except for things that are absolutely on the back end. Why would I use .NET or PHP to manipulate elements in a page when I can just use JavaScript?


Maybe the web community should start developing pages that are JavaScript run and call PHP/.NET WebServices. That puts all the processing for display on the JS and all the data manipulation and retrieval where it should be - on the server.


Any thoughts?

Syncing WordPress Databases

Whenever I'm doing any WordPress development, I eventually have the need to sync the data between the current dev server, possibly a staging server, and a live server. What's the easiest way to move a WordPress database between 2 servers?


Let's start this example by saying that we have 2 servers: Dev and Live. Each server has a mostly identical WordPress installation and each server has it's own database. In order to sync the initial database from Dev to Live the following steps may be used:

  1. Use PHPMyAdmin to export the Dev database as a file
  2. Use PHPMyAdmin to export the Live database as a file (this is a backup, just in case)
  3. Import the Dev Database into the Live Database using PHPMyAdmin
  4. Run the following 5 SQL commands in order to update the domain name in your site:
    UPDATE wp_multirss SET URL=REPLACE(URL,'Dev_Address','Live_Address');
    UPDATE wp_multirss SET Favicon=REPLACE(Favicon,'Dev_Address','Live_Address');
    UPDATE wp_posts SET post_content=REPLACE(post_content,'Dev_Address','Live_Address');
    UPDATE wp_posts SET guid=REPLACE(guid,'Dev_Address','Live_Address');
    UPDATE wp_options SET option_value=REPLACE(option_value,'Dev_Address','Live_Address');
  5. And now, as long as you've written all your relative links correctly inside of your content, you're finished!

Once you have the initial transfer completed, future transfer are much simpler. Then you only need to complete the above steps by exporting, dropping, and importing the tables that are relevant to the changes that have been made. What tables are those? Honestly, it depends on what you have changed since last time. The best way to figure this out is to go to the Database Description over at WordPress.org to see what you need to move.


Happy migrating!

Replace HTML Text without Regular Expressions

One of my latest job requirements was replacing some basic American English words with some more British words ( color-colour, favor-favour, etc.). The original iteration of this project used JavaScript to scan the page content and the replace the words properly. The only problem with this version is that AJAX calls would make browsers complain about breaking the DOM. The script for this iteration was:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
function replaceTerms(){	
	var searchArray = new Array("favors","labors","colors","favor","labor","color");
	var replaceArray = new Array("favours","labours","colours","favour","labour","colour");
 
	if (!document.body || typeof(document.body.innerHTML) == "undefined") {
		//alert("Sorry, for some reason the text of this page is unavailable. Searching will not work.");
		return false;
	}
 
	var bodyText = document.body.innerHTML;
	for (var i = 0; i < searchArray.length; i++) {
		bodyText = doReplace(bodyText, searchArray[i], replaceArray[i]);
	}
 
	//document.body.innerHTML = bodyText;
	return true;
}
 
function doReplace(bodyText, searchTerm, replaceWith) {
 
	// find all occurences of the search term in the given text, and add some "highlight" tags to them (we're not using a
	// regular expression search, because we want to filter out matches that occur within HTML tags and script blocks, so
	// we have to do a little extra validation)
 
	var newText = "";
	var i = -1;
	var lcSearchTerm = searchTerm.toLowerCase();
	var lcBodyText = bodyText.toLowerCase();
 
	while (bodyText.length > 0) {
 
		//Get index of search term
		i = lcBodyText.indexOf(lcSearchTerm, i+1);
 
		//if we can't fine it, replace the newText with the BodyText and return
		if (i < 0) {
			newText += bodyText;
			bodyText = "";
		} else {
 
			// skip anything inside an HTML tag
			if (bodyText.lastIndexOf(">", i) >= bodyText.lastIndexOf("<", i)) {
				// skip anything inside a <script> block
				if (lcBodyText.lastIndexOf("/script>", i) >= lcBodyText.lastIndexOf("<script", i)) {
 
					//Get Ascii Representation
					var	charCode = bodyText.charAt(i).charCodeAt(0);
 
					//Is this uppercase
					var isUpper = (charCode >= 65 && charCode <= 90);
 
					//Do replacing
					if(isUpper){
						newText += bodyText.substring(0, i) +  replaceWith.charAt(0).toUpperCase() + replaceWith.substr(1) + " ";
					}else{
						newText += bodyText.substring(0, i) +  replaceWith + " ";
					}
					bodyText = bodyText.substr(i + searchTerm.length);
					lcBodyText = bodyText.toLowerCase();
					i = -1;
				}
			}
		}
	}
 
	return newText;
}

Since we could not have our site breaking the DOM, the filtering was moved into the Visual Basic code behind of the project. The trick to filtering content in .NET is to leverage the Response.Filter property along with a custom class. This class will intercept the content and re-write it to however you see fit. More details on this can be found here.

The first version of our filter used regular expressions in order to replace the appropriate words in the page. This also caused a severe problem: The RegEx was replacing properties of tags, css, and control names ( understand that the word 'color' was being replaced ). My first attempt at a solution was to find the proper RegEx to replace words only inside paragraph tags. It turns out that writing a RegEx to parse HTML is nearly impossible ;)

The solution? The original JavaScript code was migrated into the Visual Basic filter. This worked like a charm as it was using no RegExes and was also based upon the original code that worked. The final Visual Basic code is as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
Private Function doReplace(ByVal bodyText As String, ByVal searchTerm As String, ByVal replaceWith As String) As String
	Private Function doReplace(ByVal bodyText As String, ByVal searchTerm As String, ByVal replaceWith As String) As String
	Dim newText As String = ""
	Dim i As Integer = -1
	Dim lcSearchTerm As String = searchTerm.ToLower()
	Dim lcBodyText As String = bodyText.ToLower()
 
	While bodyText.Length > 0
		'Get the index of the search term
		i = lcBodyText.IndexOf(lcSearchTerm, i + 1)
 
		'If it isn't there, just return
		If i < 0 Then
			newText += bodyText
			bodyText = ""
		Else
			'Avoid tags
			If bodyText.LastIndexOf(">", i) >= bodyText.LastIndexOf("<", i) Then
				'Avoid scripts
				If lcBodyText.LastIndexOf("/script>", i) >= lcBodyText.LastIndexOf("<script", i) Then
					'Is the first character uppercase?
					Dim isUpper As Boolean = Char.IsUpper(bodyText.Chars(i))
 
					'If it is, then capitalize the replacement
					If isUpper Then
						newText += bodyText.Substring(0, i) + Char.ToUpper(replaceWith.Chars(0)) + replaceWith.Substring(1) + " "
					Else
						newText += bodyText.Substring(0, i) + replaceWith + " "
					End If
 
					'Truncate body text
					bodyText = bodyText.Substring(i + searchTerm.Length())
 
					'Reset current text
					lcBodyText = bodyText.ToLower()
					i = -1
				End If
			End If
		End If
	End While
 
	Return newText
End Function

The lesson learned here? Think before you code. If I would have simply migrated the JavaScript code I would have saved a lot of time.

ISAPI Rewrite 3 with WordPress

If you're using these 2 tools together, you have to make small effort in order to get rewriting working properly. 

  1. Do what it says here
  2. Open wp-includes/classes.php
  3. Go to line 158. You should see something like $req_uri = $_SERVER['REQUEST_URI'];
  4. Replace that with $req_uri = $_SERVER['HTTP_X_REWRITE_URL'];
  5. You're good to go!

Run Javascript when UpdatePanel request ends

This was helpful.

Using Linq to Find items Selected in ListBox

I needed to do this today and found a nice article here.

Digital Patience

Has anyone noticed how impatient everyone is these days? I would describe it as ridiculous.

Just as an example, this morning I had some one write a blog post. At the moment of publishing, they assumed that this post should propagate itself across the internet through all feeds and caching. Did it appear in 5 seconds? No. Did it appear in less than a minute? Yes.

How about a little patience in the digital age?

Drupal, Clean URLs, IIS, and ISAPI Rewrite

Yesterday I had to deploy a Drupal site to a client's server. Our development server runs Ubuntu 8.04, Apache, PHP,  and MySQL. Our client's server runs Windows Server 2003, IIS, PHP,  and MySQL.  The goal was to perform a clean move that implemented clean URLs. Following are the steps that I followed. They are split into two parts: Deploy and Clean URLs.  I do assume that you already have PHP and MySQL installed and working properly with IIS.

Deploy

  1. Turn off clean URLs in Drupal (Administer -> Site Configuration -> Clean URLs)
  2. Export current site database using PhPMyAdmin.  You will most likely run into an error saying that the import file is too large for PhpMyAdmin or that there is trouble inserting the data from the cache_ tables. If this is the case, the following two steps should solve your problems:
    • Export all tables (including data) except for those starting with cache_
    • Export the structure of all tables starting with cache_
  3. Create the database on your new server using PhpMyAdmin
  4. Import the data exported in (2)
  5. Copy all of your Drupal file into your new location. Also create the virtual directory or website for this directory in IIS.
  6. Adjust the database settings for Drupal in your sites/default/settings.php file
  7. Everything should be working!

Clean URLs

  1. Download and install Helicon ISAPI Rewrite 3 Lite
  2. Open the httpd.conf file in the installation directory
  3. Save httpd.conf as httpd.ini
  4. Enter the following in httpd.ini
    1
    2
    3
    4
    5
    6
    
    [ISAPI_Rewrite]
    RewriteEngine on
    RewriteBase /
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)$ index.php?1=$1 [L,QSA]
  5. If you have Drupal installed in a sub-directory (/drupal/) change RewriteBase to /drupal/. Do remember that ISAPI Rewrite 3 Lite only supports 1 domain or site! This makes the RewriteBase very important!
  6. Enable Clean URLs in Drupal (Administer -> Site Configuration -> Clean URLs)
  7. Enjoy your clean URLs1


Making public_html Work in Ubuntu 8.04 with Apache2

Ever wanted each user on your server to have their own web directory? I wanted users on my server to have access to the public_html directory in their home directory so that they could display content at http://www.mydomain.com/~USERNAME. How do you do this?

  1. Edit /etc/apache2/apache2.conf
  2. Find the section that looks like this:
  3. 1
    2
    3
    4
    5
    6
    7
    8
    
    #UserDir is now a module
    #UserDir public_html
    #UserDir disabled root
     
    #<Directory /home/*/public_html>
    #	AllowOverride FileInfo AuthConfig Limit
    #   Options Indexes SymLinksIfOwnerMatch IncludesNoExec
    #</Directory>
  4. Make it look like this:

    1
    2
    3
    4
    5
    6
    7
    8
    
    #UserDir is now a module
    UserDir public_html
    #UserDir disabled root
     
    <Directory /home/*/public_html>
    	AllowOverride FileInfo AuthConfig Limit
    	Options Indexes SymLinksIfOwnerMatch IncludesNoExec
    </Directory>

  5. Sit back and relish in your own glory knowing that you have just accomplished something done today!

How did I figure this out? Click here.