VERSION HISTORY for what's new and current bugfixes. Author: Oliver Seidel Version: 8.6.2 Author URI: http://www.deliciousdays.com */ /* Copyright 2006-2008 Oliver Seidel (email : oliver.seidel@deliciousdays.com) WHAT's NEW in cformsII - v8.6.2 *) feature: Q&A now also not displayed for logged in users *) bugfix: email bug: broken HTML message when user was logged in while submitting a form *) bugfix: comment feature, ajax submission: 'wait a moment...' wasn't replaced by success message *) */ $localversion = '8.6.2'; load_plugin_textdomain('cforms'); ### http://trac.wordpress.org/ticket/3002 $plugindir = basename(dirname(__FILE__)); $cforms_root = get_option('siteurl') . '/wp-content/plugins/'.$plugindir; global $wpdb; ### db settings $wpdb->cformssubmissions = $wpdb->prefix . 'cformssubmissions'; $wpdb->cformsdata = $wpdb->prefix . 'cformsdata'; if( !class_exists('buttonsnap') ) require_once (dirname(__FILE__) . '/buttonsnap.php'); require_once (dirname(__FILE__) . '/editor.php'); require_once (dirname(__FILE__) . '/lib_aux.php'); ### need this for captchas add_action('template_redirect', 'start_cforms_session'); function start_cforms_session() { @session_cache_limiter('private, must-revalidate'); @session_cache_expire(0); @session_start(); } ### do a couple of things necessary as part of plugin activation if (isset($_GET['activate']) && $_GET['activate'] == 'true') require_once(dirname(__FILE__) . '/lib_activate.php'); ### ### main function ### function cforms($args = '',$no = '') { global $smtpsettings, $styles, $subID, $cforms_root, $wpdb, $track, $wp_db_version; //Safety, in case someone uses '1' for the default form $no = ($no=='1')?'':$no; parse_str($args, $r); // parse all args, and if not specified, initialize to defaults //custom fields support if ( !(strpos($no,'+') === false) ) { $no = substr($no,0,-1); $customfields = build_fstat($args); $field_count = count($customfields); $custom=true; } else { $custom=false; $field_count = get_option('cforms'.$no.'_count_fields'); } $content = ''; $err=0; $filefield=0; ### for multiple file upload fields $validations = array(); $all_valid = 1; $off=0; $fieldsetnr=1; $c_errflag=false; $custom_error=''; $usermessage_class=''; ### ??? check for WP2.0.2 if ( $wp_db_version >= 3440 && function_exists('wp_get_current_user') ) $user = wp_get_current_user(); if( isset($_REQUEST['sendbutton'.$no]) ) { /* alternative sending: both events r ok! */ require_once (dirname(__FILE__) . '/lib_nonajax.php'); $usermessage_class = $all_valid?' success':' failure'; } if ( substr(get_option('cforms'.$no.'_tellafriend'),0,1)=='2' && $send2author ) ### called from lib_WPcomments ? return $all_valid; ### ### paint form ### $success=false; if ( isset($_GET['cfemail']) && substr(get_option('cforms'.$no.'_tellafriend'),0,1)=='2' ){ ### fix for WP Comment (loading after redirect) $usermessage_class = ' success'; $success=true; if ( $_GET['cfemail']=='sent' ) $usermessage_text = preg_replace ( '|\r\n|', '
', stripslashes(get_option('cforms'.$no.'_success')) ); elseif ( $_GET['cfemail']=='posted' ) $usermessage_text = preg_replace ( '|\r\n|', '
', stripslashes(get_option('cforms_commentsuccess')) ); } $break='
'; $nl="\n"; $tab="\t"; $tt="\t\t"; $ntt="\n\t\t"; $nttt="\n\t\t\t"; ### either show message above or below $usermessage_text = check_default_vars($usermessage_text,$no); $usermessage_text = check_cust_vars($usermessage_text,$track,$no); if( substr(get_option('cforms'.$no.'_showpos'),0,1)=='y' ) { $content .= $ntt . '
' . $usermessage_text . '
'; $actiontarget = 'a'; } else if ( substr(get_option('cforms'.$no.'_showpos'),1,1)=='y' ) $actiontarget = 'b'; ### redirect == 2 : hide form? || or if max entries reached! if ( (get_option('cforms'.$no.'_redirect')==2 && isset($_REQUEST['sendbutton'.$no]) && $all_valid) ) return $content; else if ( get_option('cforms'.$no.'_maxentries')<>'' && get_cforms_submission_left($no)==0 ){ if ( $cflimit == "reached" ) return stripslashes(get_option('cforms'.$no.'_limittxt')); else return $content.stripslashes(get_option('cforms'.$no.'_limittxt')); } ### alternative form action $alt_action=false; if( get_option('cforms'.$no.'_action')=='1' ) { $action = get_option('cforms'.$no.'_action_page'); $alt_action=true; } else if( substr(get_option('cforms'.$no.'_tellafriend'),0,1)=='2' ) $action = $cforms_root . '/lib_WPcomment.php'; ### re-route and use WP comment processing else $action = $_SERVER['REQUEST_URI'] . '#usermessage'. $no . $actiontarget; $content .= $ntt . '
' . $nl; ### start with no fieldset $fieldsetopen = false; $verification = false; $captcha = false; $upload = false; $fscount = 1; $ol = false; for($i = 1; $i <= $field_count; $i++) { if ( !$custom ) $field_stat = explode('$#$', get_option('cforms'.$no.'_count_field_' . $i)); else $field_stat = explode('$#$', $customfields[$i-1]); $field_name = $field_stat[0]; $field_type = $field_stat[1]; $field_required = $field_stat[2]; $field_emailcheck = $field_stat[3]; $field_clear = $field_stat[4]; $field_disabled = $field_stat[5]; $field_readonly = $field_stat[6]; ### ommit certain fields if( in_array($field_type,array('cauthor','url','email')) && $user->ID ) continue; ### check for custom err message and split field_name $obj = explode('|err:', $field_name,2); $fielderr = $obj[1]; if ( $fielderr <> '') { switch ( $field_type ) { case 'upload': $custom_error .= 'cf_uploadfile' . $no . '-'. $i . '$#$'.$fielderr.'|'; break; case 'captcha': $custom_error .= 'cforms_captcha' . $no . '$#$'.$fielderr.'|'; break; case 'verification': $custom_error .= 'cforms_q'. $no . '$#$'.$fielderr.'|'; break; case "cauthor": case "url": case "email": case "comment": $custom_error .= $field_type . '$#$'.$fielderr.'|'; break; default: preg_match('/^([^#\|]*).*/',$field_name,$input_name); if ( strpos($input_name[1],'[id:')>0 ) preg_match ('/\[id:(.+)\]/',$input_name[1],$input_name); $custom_error .= (get_option('cforms'.$no.'_customnames')=='1')?cf_sanitize_ids($input_name[1]):'cf'.$no.'_field_'.$i; $custom_error .= '$#$'.$fielderr.'|'; break; } } ### check for title attrib $obj = explode('|title:', $obj[0],2); $fieldTitle = ($obj[1]<>'')?' title="'.str_replace('"','"',stripslashes($obj[1])).'"':''; ### special treatment for selectboxes if ( in_array($field_type,array('multiselectbox','selectbox','radiobuttons','send2author','luv','subscribe','checkbox','checkboxgroup','ccbox','emailtobox')) ){ $chkboxClicked = array(); if ( in_array($field_type,array('luv','subscribe','checkbox','ccbox')) && strpos($obj[0],'|set:')>1 ){ $chkboxClicked = explode('|set:', stripslashes($obj[0]) ); $obj[0] = $chkboxClicked[0]; } $options = explode('#', stripslashes($obj[0]) ); $field_name = $options[0]; } ### check if fieldset is open if ( !$fieldsetopen && !$ol && $field_type<>'fieldsetstart') { $content .= $tt . '
    '; $ol = true; } $labelclass=''; ### visitor verification if ( !$verification && $field_type == 'verification' ) { srand(microtime()*1000003); $qall = explode( "\r\n", get_option('cforms_sec_qa') ); $n = rand(0,(count(array_keys($qall))-1)); $q = $qall[ $n ]; $q = explode( '=', $q ); ### q[0]=qestion q[1]=answer $field_name = stripslashes(htmlspecialchars($q[0])); $labelclass = ' class="secq"'; } else if ( $field_type == 'captcha' ) $labelclass = ' class="seccap"'; $defaultvalue = ''; ### setting the default val & regexp if it exists if ( ! in_array($field_type,array('fieldsetstart','fieldsetend','radiobuttons','send2author','luv','subscribe','checkbox','checkboxgroup','ccbox','emailtobox','multiselectbox','selectbox','verification')) ) { ### check if default val & regexp are set $obj = explode('|', $obj[0],3); if ( $obj[2] <> '') $reg_exp = str_replace('"','"',stripslashes($obj[2])); else $reg_exp=''; if ( $obj[1] <> '') $defaultvalue = str_replace('"','"', check_default_vars(stripslashes(($obj[1])),$no) ); $field_name = $obj[0]; } ### Label ID's $labelIDx = ''; $labelID = (get_option('cforms_labelID')=='1')?' id="label-'.$no.'-'.$i.'"':''; ###
  1. ID's $liID = ( get_option('cforms_liID')=='1' || substr(get_option('cforms'.$no.'_showpos'),2,1)=="y" || substr(get_option('cforms'.$no.'_showpos'),3,1)=="y" )?' id="li-'.$no.'-'.$i.'"':''; ### input field names & label if ( get_option('cforms'.$no.'_customnames')=='1' ){ if ( strpos($field_name,'[id:')!==false ){ $idPartA = strpos($field_name,'[id:'); $idPartB = strpos($field_name,']',$idPartA); $input_id = $input_name = cf_sanitize_ids( substr($field_name,$idPartA+4,($idPartB-$idPartA)-4) ); $field_name = substr_replace($field_name,'',$idPartA,($idPartB-$idPartA)+1); } else $input_id = $input_name = cf_sanitize_ids($field_name); } else $input_id = $input_name = 'cf'.$no.'_field_'.$i; $field_class = ''; switch ($field_type){ case 'luv': $input_id = $input_name = 'luv'; break; case 'subscribe': $input_id = $input_name = 'subscribe'; break; case 'verification': if( is_user_logged_in() ) continue(2); $input_id = $input_name = 'cforms_q'.$no; break; case 'captcha': if( is_user_logged_in() ) continue(2); $input_id = $input_name = 'cforms_captcha'.$no; break; case 'upload': $input_id = $input_name = 'cf_uploadfile'.$no.'-'.$i; $field_class = 'upload'; break; case "send2author": case "email": case "cauthor": case "url": $input_id = $input_name = $field_type; case "datepicker": case "yourname": case "youremail": case "friendsname": case "friendsemail": case "textfield": case "pwfield": $field_class = 'single'; break; case "hidden": $field_class = 'hidden'; break; case 'comment': $input_id = $input_name = $field_type; $field_class = 'area'; break; case 'textarea': $field_class = 'area'; break; } ### additional field classes if ( $field_disabled ) $field_class .= ' disabled'; if ( $field_readonly ) $field_class .= ' readonly'; if ( $field_emailcheck ) $field_class .= ' fldemail'; if ( $field_required ) $field_class .= ' fldrequired'; $field_value = ''; ### pre-populating fields... if( !isset($_REQUEST['sendbutton'.$no]) && isset($_REQUEST[$input_name]) ) $field_value = $_REQUEST[$input_name]; ### an error ocurred: $liERR = $insertErr = ''; if(! $all_valid){ if ( $validations[$i]==1 ) $field_class .= ''; else{ $field_class .= ' cf_error'; ### enhanced error display if(substr(get_option('cforms'.$no.'_showpos'),2,1)=="y") $liERR = ' class="cf_li_err"'; if(substr(get_option('cforms'.$no.'_showpos'),3,1)=="y") $insertErr = ($fielderr<>'')?'
    • '.stripslashes($fielderr).'
    ':''; } if ( $field_type == 'multiselectbox' || $field_type == 'checkboxgroup' ){ $field_value = $_REQUEST[$input_name]; ### in this case it's an array! will do the stripping later } else $field_value = str_replace('"','"',stripslashes($_REQUEST[$input_name])); } ### print label only for non "textonly" fields! Skip some others too, and handle them below indiv. if( ! in_array($field_type,array('hidden','textonly','fieldsetstart','fieldsetend','ccbox','luv','subscribe','checkbox','checkboxgroup','send2author','radiobuttons')) ) $content .= $nttt . ''.$insertErr.'' . stripslashes(($field_name)) . ''; if ( $field_value=='' && $defaultvalue<>'' ) ### if not reloaded (due to err) then use default values $field_value=$defaultvalue; ### field disabled or readonly, greyed out? $disabled = $field_disabled?' disabled="disabled"':''; $readonly = $field_readonly?' readonly="readonly"':''; $dp = ''; $naming = false; $field = ''; $val = ''; $force_checked = false; switch($field_type) { case "upload": $upload=true; ### set upload flag for ajax suppression! $field = ''; break; case "textonly": $field .= $nttt . ''')?' style="'.$reg_exp.'" ':'') . '>' . stripslashes(($field_name)) . '
  2. '; break; case "fieldsetstart": if ($fieldsetopen) { $field = $ntt . '
' . $nl . $tt . '' . $nl; $fieldsetopen = false; $ol = false; } if (!$fieldsetopen) { if ($ol) $field = $ntt . '' . $nl; $field .= $tt .'
' . $nl . $tt . '' . stripslashes($field_name) . '' . $nl . $tt . '
    '; $fieldsetopen = true; $ol = true; } break; case "fieldsetend": if ($fieldsetopen) { $field = $ntt . '
' . $nl . $tt . '
' . $nl; $fieldsetopen = false; $ol = false; } else $field=''; break; case "verification": $field = ''; $verification=true; break; case "captcha": $_SESSION['turing_string_'.$no] = rc(); $field = ''. ''. 'Captcha'; $captcha=true; break; case "cauthor": case "url": case "email": case "datepicker": case "yourname": case "youremail": case "friendsname": case "friendsemail": case "textfield": case "pwfield": $type = ($field_type=='pwfield')?'password':'text'; $field_class = ($field_type=='datepicker')?$field_class.' cf_date':$field_class; $onfocus = $field_clear?' onfocus="clearField(this)" onblur="setField(this)"' : ''; $field = ''; if ( $reg_exp<>'' ) $field .= ''; $field .= $dp; break; case "hidden": preg_match_all('/\\{([^\\{]+)\\}/',$field_value,$findall); if ( count($findall[1]) > 0 ) { $allfields = get_post_custom( get_the_ID() ); foreach ( $findall[1] as $fvar ) { if( $allfields[$fvar][0] <> '') $field_value = str_replace('{'.$fvar.'}', $allfields[$fvar][0], $field_value); } } if ( preg_match('/^<([a-zA-Z0-9]+)>$/',$field_value,$getkey) ) $field_value = $_GET[$getkey[1]]; $field .= $nttt . '
  • '; break; case "comment": $onfocus = $field_clear?' onfocus="clearField(this)" onblur="setField(this)"' : ''; $field = '' . $field_value . ''; if ( $reg_exp<>'' ) $field .= ''; break; case "textarea": $onfocus = $field_clear?' onfocus="clearField(this)" onblur="setField(this)"' : ''; $field = '' . $field_value . ''; if ( $reg_exp<>'' ) $field .= ''; break; case "subscribe": if ( class_exists('sg_subscribe') && $field_type=='subscribe' ){ global $sg_subscribe; sg_subscribe_start(); if( ($email = $sg_subscribe->current_viewer_subscription_status())=='admin' && current_user_can('manage_options') ){ $field .= ''.str_replace('[manager_link]', $sg_subscribe->manage_link($email, true, false), $sg_subscribe->author_text).''; continue; }else if($email<>''){ $field .= ''.str_replace('[manager_link]', $sg_subscribe->manage_link($email, true, false), $sg_subscribe->subscribed_text).''; continue; } $val = ' value="subscribe"'; } case "luv": if ( function_exists('comment_luv') && $field_type=='luv' ){ get_currentuserinfo() ; global $user_level; if( $user_level==10 ) continue (2); //empty for now $val = ' value="luv"'; } case "ccbox": case "checkbox": if ( ! $field_value ) $preChecked = ( strpos($chkboxClicked[1],'true') !== false ) ? ' checked="checked"':''; else $preChecked = $field_value ? ' checked="checked"':''; $err=''; if( !$all_valid && $validations[$i]<>1 ) $err = ' cf_errortxt'; if ( $options[1]<>'' ) { $opt = explode('|', $options[1],2); $before = ''.$insertErr; $after = '' . $opt[0] . ''; $ba = 'a'; } else { $opt = explode('|', $field_name,2); $before = ''.$insertErr.'' . $opt[0] . ''; $after = ''; $ba = 'b'; } ### if | val provided, then use "X" if( $val=='' ) $val = ($opt[1]<>'')?' value="'.$opt[1].'"':''; $field = $nttt . $before . '' . $after; break; case "checkboxgroup": $liID_b = ($liID <>'')?substr($liID,0,-1) . 'items"':''; array_shift($options); $field .= $nttt . '' . (($field_name)) . '' . $nttt . ''; $id=1; $j=0; foreach( $options as $option ) { ### supporting names & values $boxPreset = explode('|set:', $option ); $opt = explode('|', $boxPreset[0],2); if ( $opt[1]=='' ) $opt[1] = $opt[0]; $checked = ''; if ( is_array($field_value) ){ if ( $opt[1]==stripslashes(($field_value[$j])) ) { $checked = 'checked="checked"'; $j++; } }else{ if ( strpos($boxPreset[1],'true')!==false ) $checked = ' checked="checked"'; } if ( $labelID<>'' ) $labelIDx = substr($labelID,0,-1) . $id . '"'; if ( $opt[0]=='' ) $field .= $nttt . $tab . '
    '; else $field .= $nttt . $tab . ''. ''.$opt[0] . ""; } $field .= $nttt . ''; break; case "multiselectbox": ### $field .= $nttt . '
  • '; $field .= ''; array_shift($options); $j=0; foreach( $options as $option ) { ### supporting names & values $optPreset = explode('|set:', $option ); $opt = explode('|', $optPreset[0],2); if ( $opt[1]=='' ) $opt[1] = $opt[0]; $checked = ''; if ( is_array($field_value) ){ if ( $opt[1]==stripslashes(htmlspecialchars($field_value[$j])) ) { $checked = ' selected="selected"'; $j++; } }else{ if ( strpos($optPreset[1],'true')!==false ) $checked = ' selected="selected"'; } $field.= $nttt . $tab . ''; } $field.= $nttt . ''; break; case "emailtobox": case "selectbox": $field = ''; array_shift($options); $jj=$j=0; foreach( $options as $option ) { ### supporting names & values $optPreset = explode('|set:', $option ); $opt = explode('|', $optPreset[0],2); if ( $opt[1]=='' ) $opt[1] = $opt[0]; ### email-to-box valid entry? if ( $field_type == 'emailtobox' && $opt[1]<>'-' ) $jj = $j++; else $jj = '-'; $checked = ''; if( $field_value == '' ) { if ( strpos($optPreset[1],'true')!==false ) $checked = ' selected="selected"'; } else if ( $opt[1]==$field_value || $jj==$field_value ) $checked = ' selected="selected"'; $field.= $nttt . $tab . ''; } $field.= $nttt . ''; break; case "send2author": $force_checked = ( strpos($field_stat[0],'|set:')===false )? true:false; case "radiobuttons": $liID_b = ($liID <>'')?substr($liID,0,-1) . 'items"':''; ### only if label ID's active array_shift($options); $field .= $nttt . '' . (($field_name)) . '
  • ' . $nttt . ''; $id=1; foreach( $options as $option ) { $checked = ''; ### supporting names & values $radioPreset = explode('|set:', $option ); $opt = explode('|', $radioPreset[0],2); if ( $opt[1]=='' ) $opt[1] = $opt[0]; if( $field_value == '' ) { if ( strpos($radioPreset[1],'true')!==false || ($force_checked && $id==1)) $checked = ' checked="checked"'; } else if ( $opt[1]==$field_value ) $checked = ' checked="checked"'; if ( $labelID<>'' ) $labelIDx = substr($labelID,0,-1) . $id . '"'; if ( $opt[0]=='' ) $field .= $nttt . $tab . '
    '; else $field .= $nttt . $tab . ''. ''.$opt[0] . ""; } $field .= $nttt . ''; break; } ### add new field $content .= $field; ### adding "required" text if needed if($field_emailcheck == 1) $content .= ''.stripslashes(get_option('cforms'.$no.'_emailrequired')).''; else if($field_required == 1 && !in_array($field_type,array('ccbox','luv','subscribe','checkbox')) ) $content .= ''.stripslashes(get_option('cforms'.$no.'_required')).''; ### close out li item if ( ! in_array($field_type,array('hidden','fieldsetstart','fieldsetend','radiobuttons','luv','subscribe','checkbox','checkboxgroup','ccbox','textonly','send2author')) ) $content .= ''; } ### all fields if ( $ol ) $content .= $ntt . ''; if ( $fieldsetopen ) $content .= $ntt . ''; ### rest of the form if ( get_option('cforms'.$no.'_ajax')=='1' && !$upload && !$custom && !$alt_action ) $ajaxenabled = ' onclick="return cforms_validate(\''.$no.'\', false)"'; else if ( ($upload || $custom || $alt_action) && get_option('cforms'.$no.'_ajax')=='1' ) $ajaxenabled = ' onclick="return cforms_validate(\''.$no.'\', true)"'; else $ajaxenabled = ''; ### just to appease "strict" $content .= $ntt . '
    '.$nttt.' '; ### if visitor verification turned on: if ( $verification ) $content .= $nttt .''; if ( $captcha ){ $captcha = get_option('cforms_captcha_def'); if ( $captcha['i']=='i' ) $tu = strtolower($_SESSION['turing_string_'.$no]); else $tu = $_SESSION['turing_string_'.$no]; $content .= $nttt .''; } $custom_error=substr(get_option('cforms'.$no.'_showpos'),2,1).substr(get_option('cforms'.$no.'_showpos'),3,1).substr(get_option('cforms'.$no.'_showpos'),4,1).$custom_error; if ( get_option('cforms'.$no.'_tellafriend')>0 ){ if ( substr(get_option('cforms'.$no.'_tellafriend'),0,1)==2 ) $nono = ''; else $nono = $no; $content .= $nttt . '' . $nttt . ''; } $content .= $nttt . ''. $nttt . ''. $nttt . ''. $nttt . ''. $nttt . ''; $content .= $ntt . '
    '; $content .= $ntt . '

    '; $content .= $ntt . ''; ### link love? you bet ;) $content .= $ntt . '

    cforms contact form by delicious:days

    '; ### either show message above or below $usermessage_text = check_default_vars($usermessage_text,$no); $usermessage_text = check_cust_vars($usermessage_text,$track,$no); if( substr(get_option('cforms'.$no.'_showpos'),1,1)=='y' && !($success&&get_option('cforms'.$no.'_redirect')==2)) $content .= $tt . '
    ' . $usermessage_text . '
    ' . $nl; return $content; } ### some css for positioning the form elements function cforms_style() { global $wp_query, $cforms_root, $localversion; ### add content actions and filters $page_obj = $wp_query->get_queried_object(); $onPages = str_replace(' ','',stripslashes(htmlspecialchars( get_option('cforms_include') ))); $onPagesA = explode(',', $onPages); if( $onPages=='' || in_array($page_obj->ID,$onPagesA) ){ echo "\n\n"; if( get_option('cforms_no_css')<>'1' ) echo ''."\n"; echo ''."\n"; if( get_option('cforms_datepicker')=='1' ){ $nav = get_option('cforms_dp_nav'); $dformat = str_replace(array('M','EE','E'),array('m','dddd','ddd'),stripslashes(get_option('cforms_dp_date'))); echo ''."\n"; echo ''."\n"; } echo ''."\n\n"; } } function findlast( $haystack,$needle,$offset=NULL ){ if( ($pos = strpos( strrev($haystack) , strrev($needle) , $offset)) === false ) return false; return strlen($haystack) - $pos - strlen($needle); } ### replace placeholder by generated code function cforms_insert( $content ) { global $post; $newcontent=''; $last=0; if ( ($a=strpos($content,'',$a); $Fid = substr($content,$a+10,($b-$a-10)); $Fname = ''; if ( ($fQ=strpos($Fid,'"'))!==false ) $Fname = sanitize_title_with_dashes(substr( $Fid, $fQ+1, strpos($Fid,'"',$fQ+1)-$fQ-1 )); $newcontent .= substr($content,$last,$p_offset-$last); if( $Fname !== '' ) $newcontent .= cforms('',$fns[$Fname]); else $newcontent .= cforms('',$Fid); $p_open_after = strpos($content,'

    ',$b); $p_close_after = strpos($content,'

    ',$b); ### wrapped in

    ? $b = ($p_close_after < $p_open_after || ($p_close_after!==false && $p_open_after===false)) ? $p_close_after+1 : $b; //add'l +3 covered by $last = $b+3; !! :-) $a = strpos($content,'