Search and Replace in Linux Command Line

I wanted to search and replace every file in a directory tree and find a URL that linked to /web-design and remove that part of the URL, and i also wanted to find the phrase “Web Design” in a link and replace it with “Affordable Web Design”.

Usually i would have to go through each individual file via SSH or FTP and then open the file, make the edits, save the file and re-upload the file. The problem with that is, i needed to do this for over 15,000 files on over 3000 web sites, and that isn’t something i wanted to do.

Firstly, i needed to find all the html files that could possibly have these two defects, so i went with “find”, its simple, and easy, and crawls sub directories as default.

Find all files with the extension “.html” in the current directory and all sub directories:
find . -iname '*.html'

The problem i had then was, web sites that are still being worked on are in a private directory that i do not want to alter, so i needed to exclude these directories:
find . -iname '*.html' -not -path '*private*'

This now gives me a list of everything that i need to do a search and replace on.

For this next part, you can use either “sed” or “perl”. I chose to go with perl as i know perl better than sed.

This cold should replace “/web-design” with “” in a file called “index.html” in the current folder. (Follows the format “s/what to find/what to replace with/g”):
perl -pi -w -e 's/\/web-design//g;' index.html

So what we need to do now is use xargs to combine the two parts and make the search and replace in all files:
find . -iname '*.html' -not -path '*private*' | xargs perl -pi -w -e 's/\/web-design//g;' -sl

This code should now look in the current directory, and all sub-directories contained within for any html file not in a private folder, and remove the text “/web-design” and replace it with nothing.

The next bit was a simple modification to replace the phrase “Web Design” with “Affordable Web Design”, though we needed to take into account that we only wanted to replace content within a A HREF tag, so we need to search for “>Web Design<”
find . -iname '*.html' -not -path '*private*' | xargs perl -pi -w -e 's/\>Web Design\</\>Affordable Web Design\</g;' -sl

Make sure that when you are creating your regular expressions, you escape any special characters such as \ / < > and friends.

Pop3 Client Library for .NET (System.Net.Pop3)

C# .NET library implementing the Pop3 message retrieval protocol

Features:

  • Full Pop3 implementation
  • SSL Support
  • HTML Support
  • Plain Text Support
  • Mixed/Multi Mode Message Support
  • Attachments Support
  • .NET 2.0 + Compatable
  • Fully Self Contained Code
  • Extendible Message Parser

SVN: https://systemnetpop3.svn.sourceforge.net/svnroot/systemnetpop3
Files: https://sourceforge.net/projects/systemnetpop3/files/

Automated Search Engine Submission via Sitemap Ping

If you want to automate the way in which you submit your new websites to the major search engines, try using the sitemap.xml pinging service. You just replace [FULL SITEMAP URL] with a URL encoded version of the full URL of your sitemap and then GET request each ping service.

http://www.google.com/webmasters/tools/ping?sitemap=[FULL SITEMAP URL]
http://search.yahooapis.com/SiteExplorerService/V1/ping?sitemap=[FULL SITEMAP URL]
http://search.yahooapis.com/SiteExplorerService/V1/updateNotification?appid=SitemapWriter&url=[FULL SITEMAP URL]
http://submissions.ask.com/ping?sitemap=[FULL SITEMAP URL]
http://www.bing.com/webmaster/ping.aspx?siteMap=[FULL SITEMAP URL]
http://api.moreover.com/ping?u=[FULL SITEMAP URL]

Load and Parse Large XML Files in PHP

Usually, PHP is limited to using somewhere between 16mb and 128mb of RAM. So what happens if you want to parse a 1.1gb file of exported product data (over 500,000 products) and not hit the RAM limiter?

At first this seemed to be a pretty impossible task, as to parse the file you require the entire XML to parse it to a tree.

Usually you would run something such as file_get_contents() and then parse the contents returned, but this would load in the entire 1.1gb of XML and put you well beyond most PHP ram limiters.

What you need to do is parse the XML in small chunks (example below uses 128kb chunks) and parse those bit by bit, this way, you get to speedily parse through your XML file, while at the same time, steer clear of the PHP RAM limiter.

set_time_limit(0);
define('__BUFFER_SIZE__', 131072);
define('__XML_FILE__', 'pf_1360591.xml');

function elementStart($p, $n, $a) {
  //handle opening of elements
}

function elementEnd($p, $n) {
  //handle closing of elements
}

function elementData($p, $d) {
  //handle cdata in elements
}

$xml = xml_parser_create();

xml_parser_set_option($xml, XML_OPTION_TARGET_ENCODING, 'UTF-8');
xml_parser_set_option($xml, XML_OPTION_CASE_FOLDING, 0);
xml_parser_set_option($xml, XML_OPTION_SKIP_WHITE, 1);

xml_set_element_handler($xml, 'elementStart', 'elementEnd');
xml_set_character_data_handler($xml, 'elementData');

$f = fopen(__XML_FILE__, 'r');
if($f) {
  while(!feof($f)) {
    $content = fread($f, __BUFFER_SIZE__);

    xml_parse($xml, $content, feof($f));

    unset($content);
  }
  fclose($f);
}

Imitate target=_blank with jQuery

You can replace target=_blank with jquery, or prototype or with raw javascript if you like. Here is the code i came up with to do just this.

jQuery

$(function() {
	$('a[rel*=external]').click(function() {
		var w = window.open(this.href);
		if(!w) alert("Boo! A popup blocker stopped our window from opening");
		return false;
	});
});

PHP Installer for Web Apps

We all know uploading things via ftp like Squirrel Mail or phpMyAdmin, or any application that has 100′s of small files takes a long time. This is mainly due to the overhead in the commands that have to be preformed to upload each file individually.

The first thing we need to do is to package all of our files into a single large file, this will allow us to massively reduce overhead, since there is only ever one send file command sent. How we do this, is simply add all the files (and the root directory if required) into a zip, so that when they are extracted to the directory on the server, they will appear on the server correctly.

Once we have zipped all of our files up, how do we then expect to be able to unzip them? We need a small bootstrap script (example below) to extract them to the server, which yes, is a second file that is small, but beats having to upload those over few 100 files.

$zip = new ZipArchive();
$r = $zip->open("myzip.zip");
if($r == TRUE) {
  $zip->extractTo("./");
}
$zip->close();

If you now upload and run your bootstrap script, you will notice (if you have the zip extension loaded in PHP) that your zip file has been extracted on the server, and was done a vast amount quicker than it would have taken to upload the individual files.

$package = "myadmin.zip";

$c = file_get_contents($package);

$content = base64_encode($c);
$bcontent = "";

for($i=0; $i<strlen($content); $i+=1024) {
  $c = substr($content, $i, 1024);
  $bcontent .= "\$content .= \"{$c}\";\r\n";
}

$f = fopen("installer.php", "w+");
if($f) {
  fwrite($f, "<?php\r\n");
  fwrite($f, "\$content = \"\";\r\n");
  fwrite($f, $bcontent);
  fwrite($f, "file_put_contents('{$package}', base64_decode(\$content));\r\n");
  fwrite($f, "\$zip = new ZipArchive();\r\n");
  fwrite($f, "\$zip->open('{$package}');\r\n");
  fwrite($f, "\$zip->extractTo('./');\r\n");
  fwrite($f, "\$zip->close();\r\n");
  fwrite($f, "?" . ">");
  fclose($f);
}

Set font size in Win32 API EDIT Window

i have recently been attempting to write a small text editor application, and the main problem i found was migrating notepad settings over to my application, the font for 10pt was stored as 100.

obviously, i needed to divide by 10, but when i did this, the font came out so small it was unreadable.

after some digging, i found the following works perfectly.

int m_height = -MulDiv(g_point_size/10, GetDeviceCaps(m_dc, LOGPIXELSY), 72);

once you have done this, just SendMessage to the EDIT you want to set the font size of, and bingo, we have a correct font size

Init Google Gears with jQuery

I took a look around the web for a jQuery plugin for google gears as i would like to initialise gears on user input, and not as the web page loads, but could not find one anywhere.

So i have written the following plugin, based on googles own gears_init.js code which inits gears on page load.

/*
 * jQuery Gears Init by Darren Horrocks
 *
 * jQuery Plugin to init google gears at any point during a page
 *
 * code based on gears_init.js from http://code.google.com/apis/gears/gears_init.js
 *
 */
(function() {
  jQuery.initGears = function() {
    // We are already defined. Hooray!
    if (window.google && google.gears) {
      return;
    }

    var factory = null;

    // Firefox
    if (typeof GearsFactory != 'undefined') {
      factory = new GearsFactory();
    } else {
      // IE
      try {
        factory = new ActiveXObject('Gears.Factory');
        // privateSetGlobalObject is only required and supported on IE Mobile on
        // WinCE.
        if (factory.getBuildInfo().indexOf('ie_mobile') != -1) {
          factory.privateSetGlobalObject(this);
        }
      } catch (e) {
        // Safari
        if ((typeof navigator.mimeTypes != 'undefined') && navigator.mimeTypes["application/x-googlegears"]) {
          factory = document.createElement("object");
          factory.style.display = "none";
          factory.width = 0;
          factory.height = 0;
          factory.type = "application/x-googlegears";
          document.documentElement.appendChild(factory);
        }
      }
    }

    // *Do not* define any objects if Gears is not installed. This mimics the
    // behavior of Gears defining the objects in the future.
    if (!factory) {
      return;
    }

    // Now set up the objects, being careful not to overwrite anything.
    if (!window.google) {
      google = {};
    }

    if (!google.gears) {
      google.gears = {factory: factory};
    }
  };
})();

You can now initialise gears using the the jQuery class or the dollar shortcut.

jQuery.initGears();
$.initGears();

PHP Keyword Generator and Keyword Density Generator

What we do here is first, create an array of bad words that we want to filter out, ie, the most common words in the most common languages such as “and” “or” “are”.

We also need to have a lower boundary to check against, most search engines have a lower word bound of 3 characters, so this is what we will use here.

We now check valid keywords against a string of text which will explode the string into an array based on commas or spaces and check each word against our list and that its 3 characters or greater. If we are not in the bad words list and we are 3 characters or greater, add it to the valid array, and if we are already there, increase the count by 1.

once we have cycled through all the words, we then order by largest first to smallest and then return our array.

we now have an array of words ordered by their popularity in the string that was given.

function get_filter_words() {
  $words = array('000', ..., 'zwölf' );
  return $words;
}

function is_valid_keyword($word) {
  $common_words = get_filter_words();

  return (strlen($word) >= 3 && !in_array($word, $common_words)) ? true : false;
}

function get_valid_keywords($words) {
  $word_arr = array();
  $word_ret = array();

  if(!is_array($words)) {
    $word_arr = preg_split("/[\s,]/", $words, -1, PREG_SPLIT_NO_EMPTY);
  }

  foreach($word_arr as $word) {
    if(is_valid_keyword($word)) {
      if(empty($word_ret[$word])) {
        $word_ret[$word] = 1;
      } else {
        $word_ret[$word]++;
      }
    }
  }

  arsort($word_ret, SORT_NUMERIC);

  return $word_ret;
}

Btw, you need to find your own bad word list