<?php

// average number of chars until an obfuscation char appears
$obfuscation_average_interval=7;

// do not use these chars to obfuscate
$do_not_use_as_obfuscator=array('<','&','>',"'",'"',"`");

// example
print html_for_email('krichel@openlib.org');

// The End


function html_for_email ($address) {
  $obfuscated=get_obfuscated_address($address);
  $out='<span class="email">';
  $out.=$obfuscated['address'];
  $out.="</span>\n";
  $out.='<span class="obfuscation_note">';
  $out.='remove the character ';
  $out.='<span class="obfuscation_char">';
  $out.=$obfuscated['char'];
  $out.="</span>\n to the get the real address</span>.\n";
  return $out;
}


// obfuscate address with 
function get_obfuscated_address ($address) {
  // $r is the response
  $dirty_char=get_random_obfuscation_character($address);
  $r['char']=$dirty_char;
  // it could be that we don't find a dirty char for this
  // address, if it is very long or if we are very restrictive
  // with the allowable characters. In that case, just 
  // return the old address
  if(! $dirty_char) {
    $r['address']=$address;
    return $r;
  }
  // count chars in old address 
  $old_address_count=0;
  $new_address_count=0;
  $count_to_last_replacement=0;
  $new_address='';
  // calculate an initial obfusctation step
  $obfuscation_step=rand(0,$GLOBALS['obfuscation_average_interval']*2);
  while($sub=substr($address,$old_address_count,1)) {
    $new_address.=$sub;
    $old_address_count++;
    $count_to_last_replacement++;
    // if we reach the obfuscation step
    if($count_to_last_replacement==$obfuscation_step) {
      // take new obfuscation step
      $obfuscation_step=rand(0,$GLOBALS['obfuscation_average_interval']*2);
      $new_address.=$dirty_char;
      $count_to_last_replacement=0;
    }
  }
  # if obfuscation did work, do it again
  if($new_address == $address) {
    $r=get_obfuscated_address($address);
    return $r;
  }
  $r['address']=$new_address;
  return $r;
}

// gets a random obfuscation character
function get_random_obfuscation_character ($address) {
  // set random seed
  srand((float) microtime() * 10000000);
  // the start position where we start to look for an obfuscation char
  $start_char_position=33;
  // the end position where we stop to look for an obfuscation char
  $end_char_position=126;
  // define a number of maximum attempts. It's the maximum number of 
  // available chars
  $max_attempts=$end_char_position-$start_char_position;
  while($max_attempts--) {
    // pick a random candidate char position
    $candidate_position=rand($start_char_position,$end_char_position);
    // get the letter that is associated with that char
    $candidate_char=chr($candidate_position);
    if(is_eligible($candidate_char,$address,$GLOBALS['do_not_use_as_obfuscator'])) {
      return $candidate_char;
    }
  }
  // if it fails this will return false
}

// check if a letter can be used to obfuscate 
function is_eligible  ($letter,$address) {
  // check if the character is one of the prohibited characters
  foreach ($GLOBALS['do_not_use_as_obfuscator'] as $prohibited_char) { 
    if($letter == $prohibited_char ) {
      return 0;
    }   
  }
  // split the address into an array of characters
  $email_address_letters=split_into_letters($address);
  // go through each letter to find if the character is eligible
  foreach ($email_address_letters as $email_letter) {
    if($letter == $email_letter) {
      return 0;
    }
  }
  return 1;
}

// splits a string into letters
function split_into_letters ($string) {
  $count=0;
  while($sub=substr($string,$count,1)) {  
    $r[$count++]=$sub;
  }
  return $r;
}


?>

Valid XHTML 1.0!