Lucia's Linky Love) once or publish a post before this works properly. Until you do, everything will be marked "nofollow". Author: Lucia Liljegren Version: 0.3 (Added number count toggles.) Author URI: http://money.bigbucksblogger.com */ /* *Copyright (c) 2007 Lucia Liljegren * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * 3. The name of the author may not be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ add_action('admin_menu', 'luciaLinkyLove_admin_menu'); add_filter('get_comment_author_link', 'adjust_nofollow_author',11); add_filter('comment_text', 'adjust_nofollow_text',11); add_action('loop_end', 'addLuciaLinkyLoveLink'); add_action('publish_post', 'updateLuciaLinkyLoveDate'); // ************ ************ function updateLuciaLinkyLoveDate() { $lastposts = get_posts('numberposts=1'); foreach($lastposts as $post) { setup_postdata($post); the_title(); $lastLinkyLoveDate=$post->post_date; //echo('
lastLinkyLoveDate= '.$lastLinkyLoveDate); update_option('lastLinkyLoveDate',$lastLinkyLoveDate); } } // ************ ************ function addLuciaLinkyLoveLink($text='') { // called at loop end. global $single, $feed, $post; $commentPolicyPage= get_option('commentPolicyPage'); if(!$feed && $single ){ if( $commentPolicyPage==2 || ($commentPolicyPage==1 && ($post->post_date < $old_Post )) ){ echo("
Comments protected by Lucia's Linky Love.");} }// feed return $text; } // ************ ************ function luciaLinkyLove_admin_menu() { add_options_page( __('LuciaLinkyLove Options'), __('Lucia_LinkyLove'), 5, basename(__FILE__),'set_LuciaLinkyLove_options_page'); } // ************ ************ function set_LuciaLinkyLove_options_page(){ $text="Your current settings are shown below."; if($_POST['LuciaLinkyLove']=='Submit'){ $authorMatchNumber= min(max(floor($_POST['authorMatchNumber']),3),10); $commentMatchNumber= max(floor($_POST['theCommentMatchNumber']),-1); if(-1<$commentMatchNumber){$commentMatchNumber=max($commentMatchNumber,3);} $commentPolicyPage= $_POST['commentPolicyPage']; $maxCharactersInName= max($_POST['maxCharactersInName'],15); $adminNameExclude= $_POST['adminNameExclude']; $luciaLinkyDays= max($_POST['luciaLinkyDays'],0); $showCommentNumber= $_POST['showCommentNumber']; echo('

You requested these settings:
commentMatchNumber= '.$commentMatchNumber.' | authorMatchNumber='.$authorMatchNumber.' | commentPolicyPage='.$commentPolicyPage.' | maxCharactersInName='.$maxCharactersInName.' | adminNameExclude='.$adminNameExclude.' | days to delay '.$luciaLinkyDays.'| Show comments count '.$showCommentNumber.'

'); update_option('commentsMatchNumber',$commentMatchNumber); update_option('authorMatchNumber',$authorMatchNumber); update_option('commentPolicyPage',$commentPolicyPage); update_option('maxCharactersInName',$maxCharactersInName); update_option('adminNameExclude',$adminNameExclude); update_option('luciaLinkyDays',$luciaLinkyDays); update_option('showCommentNumber',$showCommentNumber); $text="Your updated settings are shown below."; } LuciaLinkyLoveAdminPage($text); }// set_LuciaLinkyLove_options_page() // ************ ************ function LuciaLinkyLoveAdminPage($textAdded=""){ updateLuciaLinkyLoveDate(); // this will force user to update! $authorMatchNumber= get_option('authorMatchNumber'); $commentsMatchNumber= get_option('commentsMatchNumber'); if(0<$commentsMatchNumber){$commentsMatchNumber=max($commentsMatchNumber,$authorMatchNumber);} $commentPolicyPage= get_option('commentPolicyPage'); if($authorMatchNumber==''){$commentPolicyPage=1; } $maxCharactersInName=max(get_option('maxCharactersInName'),15); $adminNameExclude=get_option('adminNameExclude'); $luciaLinkyDays=get_option('luciaLinkyDays'); $showCommentNumber=get_option('showCommentNumber'); if($showCommentNumber=="No"){ $selectCommentNo='selected="selected"'; $selectCommentYes=''; } else{ $selectCommentYes='selected="selected"'; $selectCommentNo=''; } if($commentPolicyPage=="0"){$selectZero='selected="selected"'; $selectOne=''; $selectTwo='';} else if($commentPolicyPage=="1" ){$selectOne='selected="selected"';$selectZero='';$selectTwo='';} else{$selectTwo='selected="selected"';$selectZero='';$selectOne=''; } //echo('
| commentMatchNumber= '.$commentsMatchNumber.' | authorMatchNumber='.$authorMatchNumber.' | linksPerHour= '.$linksPerHour.' | linksPerDay= '.$linksPerDay.' | commentPolicyPage='.$commentPolicyPage); echo('
'); if($textAdded!=""){echo('
'.$textAdded.'



');} ?>
Customize Lucia's Linky Love
Enter the number of matches when the author links become do follow:
LLL permits 3 through 10.
Enter the number of matches when comment links become do follow:
LLL permits any number greater than 3 and also greater than the number entered above. If you never want to permit visitors to enter links in comments, enter -1.
Keep dofollow off comments less than some number of days old?

The default is zero, and I advise using that.
If you set a value greater than zero, you the blogger have an extra time buffer. Comments will be dofollows only after there are enough from the same visitor and even then only when a individual comment is old enough. (This option was requested and is useful if you find the same spammer arriving and suddenly leaving many comments immediately. )
Keep dofollow off one particular name?

This is useful to avoid looking like you are trying to google bomb your own name. I leave comments on my own site as "lucia", so I exclude that name.
Show comment count?

If you choose yes, the number of comments by a particular visitor will appear after their name. The default is yes.
Permit 'dofollow' in 'names' with fewer than characters.

Why? Spammers often leave names like "Joe -- SEO expert" or "Cashemere Dog Sweater". You can refuse to add a 'dofollow' if the name is too long. LLL will permit you to enter any number greater than 15.
Insert informational links telling visitors your site is 'dofollow' is protected by Lucia's Linky Love?

Dear Fellow DoFollow Blogger,

Of course, you aren't required to post links to my site or blog about this plugin. However, we bloggers often post about interesting posts, which take only minutes to write. Then we all forget to mention the plugins we use and don't drop links to the plugin developer who spent hours writing the code. If you find the plugin useful, please mention it at your blog and include a link to my blog, Big Bucks Blogger ( http://money.bigbucksblogger.com ).

Meanwhile, I hope you enjoy my plugin. If you'd like to find more of my plugis, visit Big Bucks Blogger where you will find

  1. Kontera Control: Keep Kontera Ads out of Sponsored Posts.
  2. NoOldSpamLinks: Nofollow old links that have become spammy.
  3. Hide Sponsored Categories: Hide some categories used in Wordpress. (Useful for some PayPerPost Opps) and
  4. Plugin Hog Detector: Good for diagnosing which plugins ar using excess system resources.
If you have problems, suggestions or request, let me know!

Sincerely, Lucia

'); }// ' LuciaLinkyLoveAdminPage($textAdded="") // ************ ************ function adjust_nofollow_author($text = ''){ global $table_prefix, $wpdb, $comment, $noFollowingText, $limited_comment_count; static $firstCommentLinkyLove, $authorMatchNumber, $commentsMatchNumber, $linksPerHour, $linksPerDay, $commentPolicyPage, $commentAuthorURL,$commentAuthorEmail,$commentAuthorIP,$numCommentsShownSoFar,$lastLinkyLoveDate,$countForMatch,$maxCharactersInName, $adminNameExclude,$luciaLinkyDays,$oldCommentDate,$commentAuthorName,$showCommentNumber ; if($firstCommentLinkyLove !=1){ $authorMatchNumber= max(get_option('authorMatchNumber'),3); $commentsMatchNumber= get_option('commentsMatchNumber'); if(0<$commentsMatchNumber){$commentsMatchNumber=max($commentsMatchNumber,3);} $commentPolicyPage= get_option('commentPolicyPage'); if(!isset($commentPolicyPage)){$commentPolicyPage=1;} $maxCharactersInName=max(get_option('maxCharactersInName'),15); $lastLinkyLoveDate=mysql2date('U', get_option('lastLinkyLoveDate')); // //echo('lastLinkyLoveDate'. $lastLinkyLoveDate.'
'); $showCommentNumber=get_option('showCommentNumber'); $adminNameExclude=get_option('adminNameExclude'); $luciaLinkyDays=get_option('luciaLinkyDays'); $oldCommentDate=time() -86400*$luciaLinkyDays; //echo('days'. $luciaLinkyDays.' | oldCommentDat '.$oldCommentDate.'
'); $firstCommentLinkyLove =1; //echo('
First Comment'); } //$firstCommentLinkyLove !=1) // Now decide whether to do follow $limited_count=0; // default, will count if necessary. // only check comments that have author, url etc. $daysBefore= -( mysql2date('U', $comment->comment_date) -$lastLinkyLoveDate)/86400; //echo('daysBefore'. $daysBefore.'
'); $sameNameExclude=strcasecmp($comment->comment_author,$adminNameExclude); if (!$sameNameExclude ){ //echo('
This is new or 14 days after last post or excluded name: return '); return $text; } if (($oldCommentDate < mysql2date('U', $comment->comment_date)) || $daysBefore < -14 ||!$sameNameExclude ){ //echo('
This is new or 14 days after last post or excluded name: return '); if( is_user_logged_in() ) $text .= " (new comment) "; return $text; } //echo('
Pre-check comment to make sure no zero length stuff. '); if(isset($comment->comment_ID) && isset($comment->comment_author) && isset($comment->comment_author_url) && isset($comment->comment_author_email) ){ // explode on '/' $domainToMatch=explode('/',$comment->comment_author_url,4); //echo('
domain? '.$domainToMatch[2]); $lengthAuthor=strlen($comment->comment_author); $lengthURL=strlen($domainToMatch[2]); $lengthEmail=strlen($comment->comment_author_email); if ($lengthAuthor<2 || $lengthURL<2 || $lengthEmail<3 ){ //echo('
short strings: return '); return $text; } $nameExplode=explode(' ',ltrim($comment->comment_author),3); $nameExplode=explode("'",ltrim($nameExplode[0]),3);// fix problem with 's $nameToMatch=$nameExplode[0]; $lengthShortAuthor=strlen($nameToMatch); $match=0; if($lengthShortAuthor<2 ){ // after exploding, not enough remains to check. return $text; } // ============ ACTUAL COUNTING and CHECKING //echo('
Now find out how many matches '); // check if they already shown for($i=0; $i<$numCommentsShownSoFar && $match!=1; $i++){ if( ($domainToMatch[2] == $commentAuthorsURL[$i]) && ($comment->comment_author_email == $commentAuthorsEmail[$i]) && $nameToMatch== $commentAuthorName[$i]){ $match=1; $limited_count=$countForMatch[$i]; //echo(' matched'); } } // for i // if there is no match, add to array so I can check next comment. if($match==0){ $commentAuthorURL[$numCommentsShownSoFar]=$domainToMatch[2]; $commentAuthorEmail[$numCommentsShownSoFar]=$comment->comment_author_email; $commentAuthorName[$numCommentsShownSoFar]=$nameToMatch; //echo('
numCommentsShownSoFar.'. $numCommentsShownSoFar.' | url '.$commentAuthorURL[$numCommentsShownSoFar].' | email'.$commentAuthorEmail[$numCommentsShownSoFar]); // read http://www.techonthenet.com/sql/count.php recommends chaning count(*) to count (1) if($comment->comment_type=='pingback' || $comment->comment_type=='trackback' ){ $pingBack=1; $queryString="select count(1) as comments from $wpdb->comments where `comment_author_url` LIKE '%$domainToMatch[2]%' "; } else{ $pingBack=0; $queryString="select count(1) as comments from $wpdb->comments where `comment_author_url` LIKE '%$domainToMatch[2]%' and `comment_author_email` = '$comment->comment_author_email' and `comment_author` LIKE '%$nameToMatch%'"; } //echo('
'.$queryString.'
'); $limited_count = $wpdb->get_var($queryString); $countForMatch[$numCommentsShownSoFar]=$limited_count; // remember how many matched $numCommentsShownSoFar++; } //($match ==0) // if enough author matches, follow //if($authorMatchNumber <= $limited_count)echo('| 1 | enough comments '); //if($lengthAuthor<$maxCharactersInName)echo('| 3 | $lengthAuthor<$maxCharactersInName '); //if(3<$lengthEmail)echo('| 4 | 3<$lengthEmail '); //if($sameNameExclude!=0 )echo('|5 | $sameNameExclude!=0 '); //if(3 <= $limited_count )echo('| 6 | 3 <= $limited_count '); if( ($authorMatchNumber <= $limited_count && $lengthAuthor<$maxCharactersInName ) || (3 <= $limited_count && $pingBack==1 ) ){ // follow! $text = preg_replace("/(]*[^\s])(\s*nofollow\s*)/i", "$1", $text); $text = preg_replace("/(]*[^\s])(\s*rel=\"\s*\")/i", "$1", $text); $pattern='/external nofollow/';// $replacement=' '; $text = preg_replace($pattern, $replacement,$text); } elseif( $authorMatchNumber > $limited_count && !is_user_logged_in() && !isset($_COOKIE['comment_author_'.COOKIEHASH]) ) { $text = preg_replace("/(]*[^\s])('>)/i", "", $text); $text = str_replace( '', '', $text ); } // if enough matches, follow comments. if( ( $commentsMatchNumber <= $limited_count) && (1 < $commentsMatchNumber) && $lengthAuthor<$maxCharactersInName && 3<$lengthEmail ){ $noFollowingText=0;// do follows //echo('follow text '); } else{ $noFollowingText=1; //echo('no follow text'); } }// if ($comment->comment_ID) if($sameNameExclude!=0){ if($showCommentNumber!="No") $text .= " (".$limited_count." comments.)"; } return $text; }// function adjust_nofollow_author($text = '') // ************ ************ at least cut out the second database call. function adjust_nofollow_text($text = ''){ global $table_prefix, $wpdb, $comment, $noFollowingText, $supressLuciaLinkyLove; if (isset($comment->comment_ID)){ // remove any nofollows applied by some other function. if($noFollowingText ==0 ) { //echo('follow text '); $text = preg_replace("/(]*[^\s])(\s*nofollow\s*)/i", "$1", $text); $text = preg_replace("/(]*[^\s])(\s*rel=\"\s*\")/i", "$1", $text); $pattern='/" rel="nofollow">/'; $replacement='" >'; $text = preg_replace($pattern, $replacement,$text); } else { // this must be made to run *before* NoOldSpamLinks. //echo('add follows to text'); $text= addNoFollowToLinksInCommentsIfNew($text); $suppressChowLinksNoFollow=1; // if they are running chowlinks, this will prevent double insertion of nofollow and save cpu. } }// (isset($comment->comment_ID)) return $text; }// function adjust_nofollow_text($text = '') // ************************ function addNoFollowToLinksInCommentsIfNew($content) { // This function will add nofollow to links in a comment. Logic must be applied before calling the function. $breakString='"http://'; //$content=str_ireplace( "$breakString", "$breakString", $content); // only works in php4. //replace this with $content=str_ireplace_for_php4( "$breakString", "$breakString", $content); $pieces = explode($breakString, $content); if(count($pieces)==1){ } else { for($j=1; $j', $pieces[$j], 2); if(1'.$parts[1]; } else{ $parts[0].=' rel="nofollow" ';} $pieces[$j] = implode($parts); }// for }// else $content=implode( $breakString, $pieces); return $content; } // addNoFollowToLinksInCommentsIfNew($content) // ************************ function str_ireplace_for_php4($search,$replace,$subject) { $search = preg_quote($search, "/"); return preg_replace("/".$search."/i", $replace, $subject); } ?>