Location: PHPKode > scripts > CSS Protector > css-protector/class_cssprotector.php
<?php
/*
 * Filename.....: class_cssprotector.php
 * Aufgabe......: Output text which is not readable by spam bots
 * Parameter....: none
 * Erstellt am..: Donnerstag, 5. Mai 2005
 *       _  __      _ _
 *  ||| | |/ /     (_) |        Wirtschaftsinformatiker IHK
 * \. ./| ' / _ __  _| |_ ___   www.ingoknito.de
 * - ^ -|  < | '_ \| | __/ _ \
 * / - \| . \| | | | | || (_) | Peter Klauer
 *  ||| |_|\_\_| |_|_|\__\___/  06131-651236
 * mailto.......: hide@address.com
 *
 * This PHP4 class protects strings from being read by email harvesters (spam bots).
 * The main purpose is to protect email addresses from being stolen easily.
 * Another possible use may be to issue a bot blocking but human readable, randomly
 * generated phrase which the user has to enter into a field to reach the next step
 * of processing. (=start the download or get forgotten pw sent or something else)
 * It randomly renames the css classes which are used in this class, so the
 * same phrase is different in the page source when it is protected again,
 * but looks the same for the user.
 *
 * Mozilla will render the CSS font just fine. Opera and IE will display garbage in quirks mode.
 * For that reason the doctype DTD of the page using cssprotector *MUST* be set to STRICT.
 *
 * Strict DTD:
 *
 * <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
 *
 * How to use this class on STRICT DTD pages:
 *
 * <?php
 *    include 'class_cssprotector.php';
 *    $cssprotector = new cssprotector( ); // See arglist in the function definition
 *
 *    # put this into the head-section of the page:
 *    $cssprotector->head(); // the style sheet definitions
 *
 *    # put this into the body-section of the page:
 *    $cssprotector->write( 'Oook!' );
 * ?>
 *
 * Idea and initial font come from http://www.stunicholls.myby.co.uk/menu/cssfont.html
 *
 * History:
 * 2005-05-07: Code protection enhanced with randomized class names for the divs
 */

 class cssprotector
 {

   var $size = 1; // 1 is the original size factor compared to Stu Nicholls' font
   var $unit = 'px'; // PX, MM and PT may not be resizable in IE
   var $color = '#000';
   var $coloredges = '#ccc';

   #
   # internal values:
   #
   var $head_written = false; // Help the programmer
   var $keychars = 'abcdefghijkmnopqrstuvwxyz'; // for generatekey(), valid keychars
   var $count_keychars = 0; // for generatekey(), will be initialized in the constructor
   var $classcaptions = array(); // will be filled by constructor

   var $chars = array(
   '0' => '<div class="ou"><div class="lc"></div><div class="ls"></div><div class="li"><div class="lq"></div></div><div class="lo"></div><div class="lb"></div></div>',
   '1' => '<div class="ou"><div class="lg"></div><div class="lh"></div><div class="lh"></div><div class="lh"></div><div class="lj"></div></div>',
   '2' => '<div class="ou"><div class="lb"></div><div class="lf"></div><div class="lj"></div><div class="le"></div><div class="la"></div></div>',
   '3' => '<div class="ou"><div class="lb"></div><div class="lf"></div><div class="lb"></div><div class="lf"></div><div class="lb"></div></div>',
   '4' => '<div class="ou"><div class="ld"></div><div class="ld"></div><div class="la"></div><div class="lh"></div><div class="lh"></div></div>',
   '5' => '<div class="ou"><div class="la"></div><div class="le"></div><div class="lb"></div><div class="lf"></div><div class="lb"></div></div>',
   '6' => '<div class="ou"><div class="lj"></div><div class="le"></div><div class="lb"></div><div class="li"></div><div class="lj"></div></div>',
   '7' => '<div class="ou"><div class="la"></div><div class="lk"></div><div class="lh"></div><div class="lh"></div><div class="lh"></div></div>',
   '8' => '<div class="ou"><div class="lj"></div><div class="li"></div><div class="lj"></div><div class="li"></div><div class="lj"></div></div>',
   '9' => '<div class="ou"><div class="lj"></div><div class="li"></div><div class="lc"></div><div class="lf"></div><div class="lj"></div></div>',
   'A' => '<div class="ou"><div class="lj"></div><div class="li"></div><div class="la"></div><div class="li"></div><div class="li"></div></div>',
   'B' => '<div class="ou"><div class="lb"></div><div class="li"></div><div class="lb"></div><div class="li"></div><div class="lb"></div></div>',
   'C' => '<div class="ou"><div class="lj"></div><div class="li"></div><div class="le"></div><div class="li"></div><div class="lj"></div></div>',
   'D' => '<div class="ou"><div class="lb"></div><div class="li"></div><div class="li"></div><div class="li"></div><div class="lb"></div></div>',
   'E' => '<div class="ou"><div class="la"></div><div class="le"></div><div class="lb"></div><div class="le"></div><div class="la"></div></div>',
   'F' => '<div class="ou"><div class="la"></div><div class="le"></div><div class="lb"></div><div class="le"></div><div class="le"></div></div>',
   'G' => '<div class="ou"><div class="lc"></div><div class="le"></div><div class="li"></div><div class="li"></div><div class="lc"></div></div>',
   'H' => '<div class="ou"><div class="li"></div><div class="li"></div><div class="la"></div><div class="li"></div><div class="li"></div></div>',
   'I' => '<div class="ou"><div class="lj"></div><div class="lh"></div><div class="lh"></div><div class="lh"></div><div class="lj"></div></div>',
   'J' => '<div class="ou"><div class="lj"></div><div class="lh"></div><div class="lh"></div><div class="lh"></div><div class="ll"></div></div>',
   'K' => '<div class="ou"><div class="li"></div><div class="lm"></div><div class="lr"></div><div class="lm"></div><div class="li"></div></div>',
   'L' => '<div class="ou"><div class="le"></div><div class="le"></div><div class="le"></div><div class="le"></div><div class="la"></div></div>',
   'M' => '<div class="ou"><div class="li"></div><div class="ln"></div><div class="li"><div class="lq"></div></div><div class="li"></div><div class="li"></div></div>',
   'N' => '<div class="ou"><div class="li"></div><div class="lo"></div><div class="li"><div class="lq"></div></div><div class="ls"></div><div class="li"></div></div>',
   'O' => '<div class="ou"><div class="lj"></div><div class="li"></div><div class="li"></div><div class="li"></div><div class="lj"></div></div>',
   'P' => '<div class="ou"><div class="lb"></div><div class="li"></div><div class="lb"></div><div class="le"></div><div class="le"></div></div>',
   'Q' => '<div class="ou"><div class="lj"></div><div class="li"></div><div class="li"><div class="lq"></div></div><div class="lm"></div><div class="lc"></div></div>',
   'R' => '<div class="ou"><div class="lb"></div><div class="li"></div><div class="lb"></div><div class="li"></div><div class="li"></div></div>',
   'S' => '<div class="ou"><div class="lc"></div><div class="le"></div><div class="lj"></div><div class="lf"></div><div class="lb"></div></div>',
   'T' => '<div class="ou"><div class="la"></div><div class="lh"></div><div class="lh"></div><div class="lh"></div><div class="lh"></div></div>',
   'U' => '<div class="ou"><div class="li"></div><div class="li"></div><div class="li"></div><div class="li"></div><div class="lj"></div></div>',
   'V' => '<div class="ou"><div class="li"></div><div class="li"></div><div class="li"></div><div class="lj"></div><div class="lh"></div></div>',
   'W' => '<div class="ou"><div class="li"></div><div class="li"></div><div class="li"><div class="lq"></div></div><div class="ln"></div><div class="li"></div></div>',
   'X' => '<div class="ou"><div class="li"></div><div class="li"></div><div class="lj"></div><div class="li"></div><div class="li"></div></div>',
   'Y' => '<div class="ou"><div class="li"></div><div class="li"></div><div class="lj"></div><div class="lh"></div><div class="lh"></div></div>',
   'Z' => '<div class="ou"><div class="la"></div><div class="lp"></div><div class="lh"></div><div class="lq"></div><div class="la"></div></div>',

   # This is the original "AT":
   #   '@' => '<div class="ou"><div class="lj"></div><div class="li"></div><div class="ls"><div class="lq"></div></div><div class="li"><div class="lq"></div></div><div class="lj"></div></div>',
   # I tried to make my own "AT" but it does not look the same on all browsers:
   '@' => '<div class="ou"><div class="lj"></div><div class="li"></div><div class="ls"><div class="lq"></div></div><div class="li"><div class="lq"></div></div><div class="lv"></div></div>',

   '.' => '<div class="ou"><div class="lz"></div><div class="lz"></div><div class="lz"></div><div class="lg"></div><div class="lg"></div></div>',
   '-' => '<div class="ou"><div class="lz"></div><div class="lz"></div><div class="lj"></div></div>',
   '_' => '<div class="ou"><div class="lz"></div><div class="lz"></div><div class="lz"></div><div class="lz"></div><div class="lj"></div></div>',
   ' ' => '<div class="ou"><div class="lz"></div></div>'
   );

   /**
   * Constructor of function.
   * @param float $size = Size factor
   * @param string $unit = Unit name px pt mm em cm ex
   * @param string $color = Font colour
   * @param string $coloredges = Colour of the corner points in the font
   * @return void
   **/
   function cssprotector( $size=0.25, $unit='ex', $color='#000', $coloredges='#ccc' )
   {
     $this->size = $size;
     $this->unit = $unit;
     $this->color= $color;
     $this->coloredges=$coloredges;

     $this->classcaptions = array();
     $this->count_keychars = strlen( $this->keychars )-1;

     #
     # fill array $this->classcaption with random names
     # be sure every name is unique
     #
     srand((double)microtime()*1000000);

     while( count( $this->classcaptions ) < 27 )
     {
       $newclassname = $this->generatekey();
       if( !in_array($newclassname,$this->classcaptions))
       {
         $this->classcaptions[] = $newclassname;
       }
     }

     $small_a = ord('a');
     $max_chars = count($this->chars);
     $max_captions = count($this->classcaptions)-1;
     $keys = array_keys( $this->chars );

     for( $i=0; $i<$max_chars; $i++ )
     {

       #
       # replace class "ou" with 27th caption
       #
       $this->chars[$keys[$i]] =
       str_replace( '"ou"',
       '"'.$this->classcaptions[26].'"',
       $this->chars[$keys[$i]]);

       #
       # replace other classes
       #
       for( $j = 0; $j<$max_captions; $j++ )
       {
         #
         # generate mask to be replaced.
         # It starts with a small "L" and
         # ends with "a"+$j
         #
         $replacemask = '"l'.chr( $small_a + $j ).'"';
         $this->chars[$keys[$i]] = 
          str_replace( $replacemask,
                       '"'.$this->classcaptions[$j].'"',
                       $this->chars[$keys[$i]]);
       }
     }
   } // eof constructor cssprotector(...)


   /**
   * Output a css section into the code. To be called in the head-section of the page
   * @param void
   * @return void
   **/
   function head()
   {

     $style = '
<style type="text/css">

.ou {display:block; width:'.$this->sizefunc(5).$this->unit.'; height:'.$this->sizefunc(10).$this->unit.'; float:left; margin:'.$this->sizefunc(1).$this->unit.'; background:transparent;}

* html .ou {height:'.$this->sizefunc(12).$this->unit.'; he\ight:'.$this->sizefunc(10).$this->unit.';}

.ou div {display:block; overflow:hidden; height:'.$this->sizefunc(2).$this->unit.';}
* html .ou div {float:left;}
.la, .lz {width:'.$this->sizefunc(5).$this->unit.';}

.lb, .lc, .ld, .lg, .ll, .ln, .lq, .lt {width:'.$this->sizefunc(1).$this->unit.';}
.lh, .lm, .lo, .ls {width:'.$this->sizefunc(2).$this->unit.';}
.li, .lk, .lr, .lp, lj {width:'.$this->sizefunc(3).$this->unit.';}
.le, .lf {width:'.$this->sizefunc(4).$this->unit.';}
.la, .lr, .lt {background:'.$this->color.';}
.lz {background:transparent;}
.lh {margin-right:'.$this->sizefunc(1).$this->unit.';}
.ld, .lf, .lh, .lk, .li, .lm, .lo, .lp, .lq {border-right:'.$this->sizefunc(1).$this->unit.' solid '.$this->color.';}
.ld, .le, .li, .lm, .ls {border-left:'.$this->sizefunc(1).$this->unit.' solid '.$this->color.';}
.lc {border-right:'.$this->sizefunc(4).$this->unit.' solid '.$this->color.'; background:'.$this->coloredges.';}
.lb {border-left:'.$this->sizefunc(4).$this->unit.' solid '.$this->color.'; background:'.$this->coloredges.';}
.lg, .ln, .ls {border-right:'.$this->sizefunc(2).$this->unit.' solid '.$this->color.';}
.lj {border-right:'.$this->sizefunc(1).$this->unit.' solid '.$this->coloredges.'; border-left:'.$this->sizefunc(1).$this->unit.' solid '.$this->coloredges.'; background:'.$this->color.';}
.ll, .ln, .lo {border-left:'.$this->sizefunc(2).$this->unit.' solid '.$this->color.';}
     
.lv{margin-left:'.$this->sizefunc(2).$this->unit.'; background:'.$this->color.'; border-right: '.$this->sizefunc(1).$this->unit.' solid '.$this->coloredges.'; width:'.$this->sizefunc(2).$this->unit.'; }      

* html .lb, * html .lc {width:'.$this->sizefunc(5).$this->unit.'; w\idth:'.$this->sizefunc(1).$this->unit.';}
* html .ld, * html .lg, * html .ll {width:'.$this->sizefunc(3).$this->unit.'; w\idth:'.$this->sizefunc(1).$this->unit.';}
* html .le, * html .lf {width:'.$this->sizefunc(5).$this->unit.'; w\idth:'.$this->sizefunc(4).$this->unit.';}
* html .lh {width:'.$this->sizefunc(3).$this->unit.'; w\idth:'.$this->sizefunc(2).$this->unit.';}
* html .li {width:'.$this->sizefunc(5).$this->unit.'; w\idth:'.$this->sizefunc(3).$this->unit.';}
* html .lj {width:'.$this->sizefunc(5).$this->unit.'; w\idth:'.$this->sizefunc(3).$this->unit.';}
* html .lk, * html .lp {width:'.$this->sizefunc(4).$this->unit.'; w\idth:'.$this->sizefunc(3).$this->unit.';}
* html .lm {width:'.$this->sizefunc(4).$this->unit.'; w\idth:'.$this->sizefunc(2).$this->unit.';}
* html .lo, * html .ls {width:'.$this->sizefunc(5).$this->unit.'; w\idth:'.$this->sizefunc(2).$this->unit.';}
* html .lq {width:'.$this->sizefunc(2).$this->unit.'; w\idth:'.$this->sizefunc(1).$this->unit.';}
* html .ln {width:'.$this->sizefunc(5).$this->unit.'; w\idth:'.$this->sizefunc(1).$this->unit.';}

.clr {clear:left; height:1em;}

</style>
';    

     #
     # replace class "ou" with 27th caption
     #
     $style = str_replace( '.ou','.'.$this->classcaptions[26],$style);

     $max_captions = count($this->classcaptions)-1;
     $small_a = ord('a');

     for( $j = 0; $j<$max_captions; $j++ )
     {
       #
       # generate mask to be replaced.
       # It starts with a small "L" and
       # ends with "a"+$j
       #
       $replacemask = '.l'.chr( $small_a + $j );
       $style = str_replace( $replacemask,'.'.$this->classcaptions[$j],$style);
     }

     echo $style;
     $this->head_written = true;

   } // eof cssprotector::head()


   /**
   * output a string as cssprotector. the string is converted into uppercase because
   * there aren't any lowercase letters. Letters not found are converted
   * to spaces.
   * @param string $s = String to be css protected
   **/
   function write( $s )
   {

     if( $this->head_written )
     {
       $l = strlen( $s );
       $s = strtoupper( $s );

       for( $i = 0 ; $i < $l; $i++ )
       {
         $c = substr( $s, $i, 1 );
         if( !isset( $this->chars[$c] ) )
         {
           $c = ' ';
         }
         echo $this->chars[$c];
       }

     }
     else
     {
       echo '<br><strong>cssprotector: Ooops! You forgot to put cssprotector::head() '.
       'into the &lt;head&gt; section of this page. '.
       'Please correct this and try again!</strong><br>';
     }

   } // eof cssprotector::write()


   /**
   * Calculates the new size of a div tag attribute
   * @param float $x = size factor
   * @return float
   **/
   function sizefunc( $x = 1 )
   {
     return $x * $this->size;
   }


   /**
   * random string generator function
   * @return string
   **/
   function generatekey()
   {

     $result = '';

     for ($i=0; $i < 2; $i++)
     {
       $result .= substr($this->keychars, rand(0, $this->count_keychars), 1);
     }
     return $result;

   } // eof cssprotector::generatekey()


 } // eoc cssprotector

?>
Return current item: CSS Protector