Half-Elf on Tech

Thoughts From a Professional Lesbian

Tag: coding

  • No More PHP Code (In Widgets)

    No More PHP Code (In Widgets)

    I consider Otto one of my friends. He’s a guy I don’t mind hanging out with in a bar for hours. His code advice (and debugging advice) has furthered my career. He’s also one of the more realistic folks out there when it comes to work/life balance. Enjoy your beers, bro. So you can guess my surprise when, a couple years ago, he lamented to me about his plugin, PHP Code Widget, and how he wished everyone would quit using it. “I use it.” I replied, and earned an Otto-Grumpy Cat glare. “Don’t.”

    25508154Further conversations illuminated the situation. The code works, but it’s not great since people can use it to insert anything PHPish. Sure, in the wrong hands that is hella dangerous. I was about to broadly declare “I’m not the wrong hands!” when I thought back on everything I do, and where I do it, and I sheepishly replied, “I guess I’m just lazy.”

    And that’s the crux. I am lazy, and I looked for the easier way to include a PHP file in my widget areas. I was using it to show ads (the ones you see all over this site) via include("/home/foo/public_html/blah.php");. Why? Because I use the same ads on multiple places. But that’s it for my PHP usage. Which means for me, replacing it with anything else is super easy!

    Shortcodes

    They work in widgets, so hey! I knew I just needed to include a specific PHP file from a specific location, so for me, this was pretty simple. Also it meant I could call a do_shortcode in other places in my theme functions to add it in.

    // My Ads [myads name="name"]
    function myads_func( $atts ) {
            extract( shortcode_atts( array(
                    'name' => 'placeholder',
            ), $atts ) );
    
            $filename = '/home/foo/public_html/ads/'.$name.'.php';
    
            if ( !file_exists($filename) ) { return '<!-- Ad would go here, but you messed up! '.$filename.' not found -->'; }
    
            ob_start();
            include($filename);
            $content = ob_get_clean();
            return '<div id="'.$name.'">'.$content.'</div>';
            }
    
    add_shortcode( 'myads', 'myads_func' );
    

    I put in the little fail check to be hidden, so I would know where to look. This obviously works well for me since I’m pretty limited in how I was using Otto’s code. Before this, though, I was also using it for some BuddyPress sidebar trickery which could not be done (easily) with shortcodes, and really nor should it be, so that brings us to number two…

    Make Your Own Widget

    phpcode-287392Widget code is … weird. It’s not as easy as a function, and it’s way the heck larger than shortcode code, for many things. But you should remember that better or worse is subjective, I know, but for me it wasn’t worth the time to do it. It takes me way longer to master widget code, which I can’t use everywhere (in post content, in footers etc). But Otto’s general advice has been to make a widget.

    It’s also probably way safer than doing an include like I am, but when I started needing the shortcode all over the place, that’s what it was.

  • My Super Secret .htaccess File

    My Super Secret .htaccess File

    This came up back in April in the comments of WordPress Login Protection With .htaccess, where I remarked my .htaccess was pretty long and weird. It came up again when I was doing a MeetWP presentation about hacked sites and some security.

    So what is it? Actually less long and weird these days. I’ve been trimming stuff out. But since people ask, here it is, broken out into ‘chunks.’

    Security

    Everything in this section is for security purposes. That is, I feel it helps my site be safer.

    # Tinfoil Hat Stuff
    Options +Includes
    Options +FollowSymLinks -Indexes
    

    This is basic .htaccess stuff, says to allow includes and symlinks, but stop indexes. This means if you go to halfelf.org/wp-content/uploads/ you don’t see anything, even if I don’t have an index file.

    ### Blocking Spammers Section ###
    <files wp-config.php>
    order allow,deny
    deny from all
    </files>
    

    Now we’re into a little odder bits. This stops anyone from surfing to my wp-config.php file. It shouldn’t matter, PHP won’t let it load the content, but if my PHP is off, it protects me just in case!

    # Stop protected folders from being narked. Also helps with spammers
    ErrorDocument 401 /401.html
    

    This is because of the next section. It gives a nice error for 401s, which WP normally gets gitty over. And not the fun way.

    <IfModule mod_rewrite.c>
    # Stop spam attack logins and comments
    	RewriteEngine On
    	RewriteCond %{REQUEST_METHOD} POST
    	RewriteCond %{REQUEST_URI} .(wp-comments-post|wp-login)\.php*
    	RewriteCond %{HTTP_REFERER} !.*(ipstenu.org|halfelf.org|ipstenu.org|otherplace.net).* [OR]
    	RewriteCond %{HTTP_USER_AGENT} ^$
    	RewriteRule (.*) http://%{REMOTE_ADDR}/$ [R=301,L]
     # SVN & Git protection
    	RewriteRule ^(.*/)?(\.svn|\.git)/ - [F,L]
    	ErrorDocument 403 "Access Forbidden"
    </ifModule>
    

    Ahhh, yes. Here I say “If you’re coming to wp-comments-post OR wp-login and you are NOT refereed by one of my domains, sod off.” And then it says “Oh and if you’re looking for .svn or .git files? Go away.” This isn’t perfect, but it works for some of the botnets. The fun part is that the rewrite sends them back to themselves, which should cause annoying things to happen. Don’t want that? Redirect them to fbi.gov. Actually, if some tool had a page “Redirect botnets here…” I would use that, but generally I send them to http://lmgtfy.com/?q=wordpress+botnet because I’m that sort of kid.

    Speed and Bandwidth

    Now that I’m safer, lets speed this stuff up!

    <IfModule mod_rewrite.c>
     RewriteEngine on
    # ultimate hotlink protection
     RewriteCond %{HTTP_REFERER}     !^$
     RewriteCond %{REQUEST_FILENAME} -f
     RewriteCond %{REQUEST_FILENAME} \.(gif|jpe?g?|png)$               [NC]
     RewriteCond %{HTTP_REFERER}     !^https?://([^.]+\.)?(ipstenu.org|taffys.org|halfelf.org|poohnau.us|ipstenu.org) [NC]
     RewriteRule \.(gif|jpe?g?|png)$                                 - [F,NC,L]
    </ifModule>
    

    First up, stop the hotlinks! I got the idea from Perishable Press, and it stops you from embedding my images. This means my site is faster, as you’re not sucking up my bandwidth. I get 5G so it’s not too much of a concern right now, but it’s the principle of the thing. Don’t hotlink images!

    ### Caching Section ###
    # mod_pagespeed
    <IfModule pagespeed_module>
    	ModPagespeed on
    	ModPagespeedEnableFilters defer_javascript,combine_javascript,move_css_to_head,insert_dns_prefetch,insert_image_dimensions,inline_preview_images,resize_mobile_images
    	ModPagespeedDisallow */FOLDERNAME/*
    	ModPagespeedEnableFilters insert_ga
    	ModPagespeedAnalyticsID UA-MYCODE-4
    </IfModule>
    

    I use Pagespeed on my server, so here I’ve added in my extra rules. Not everything is active for all sites. This is my default WP rule-set though, and it works well. I have it skipping a couple non WP folders, who have their own rules inside on their own .htaccess files anyway. If you don’t have pagespeed? Skip this section.

    # Expired
    <IfModule mod_expires.c>
    <Filesmatch "\.(jp?eg|png|gif|ico|woff)$">
        ExpiresActive on
        ExpiresDefault "access 1 year"
    </Filesmatch>
    
    <Filesmatch "\.(css|js|swf|mov|mp3|mpeg|mp4|ogg|ogv|ttf|xml|svg|html)$">
        ExpiresActive on
        ExpiresDefault "access 1 month"
    </Filesmatch>
    
        ExpiresDefault "access 2 days"
    </IfModule>
    ## END EXPIRES ##
    

    Oy. There are a couple ways you can control all these things. One is the way I did (filesmatch) and the other is ExpiresByType image/jpg "access plus 1 year". Is one better than they other? I don’t know. Not that I’ve managed to see, but I find the filesmatch to be easier to read and add things too. It’s shorter. Does that make it better? Only in so far as my management goes.

    #Gzip
    <IfModule mod_deflate.c>
    AddOutputFilterByType DEFLATE text/text text/html text/plain text/xml text/css application/x-javascript application/javascript text/javascript font/opentype font/truetype font/eot application/x-font-ttf
    </IfModule>
    #End Gzip
    

    Finally we have gzip, which compresses and makes things smaller and thus faster. Using gzip saves me about 80% in filesize, so it makes things faster to download and, thus, display. If you’re using this in your .htaccess, do not also try to use it in plugins/extensions for other web apps, that way likes double compression and garbage on your pages.

    Add support!

    This is a really short bit to add in support for filetypes I use that aren’t always standard:

    # Add filetypes
    AddType application/x-mobipocket-ebook mobi
    AddType application/epub+zip epub .epub
    AddType video/ogg .ogv
    AddType video/mp4 .mp4
    AddType video/webm .webm
    

    Rewrites

    In general, this is useless to everyone else, save as an example.

    ### Massive Redirect Section! ###
    <IfModule mod_rewrite.c>
    RewriteEngine On
    
    # Apple Touch Icons
    RewriteRule ^(.*)-precomposed.png /code/images/apple/$1.png [L,R=301]
    RewriteRule ^apple-touch-icon(.*) /code/images/apple/apple-touch-icon$1 [L,R=301]
    
    # Ipstenu Moves
    RewriteCond %{HTTP_HOST} ^blog\.ipstenu\.org
    RewriteRule ^(.*) https://ipstenu.org/$1 [L,R=301]
    RewriteCond %{HTTP_HOST} ^ipstenu\.org
    RewriteRule ^blog/([0-9]{4})/([0-9]{2})/(.*)$ https://ipstenu.org/$1/$3 [L,R=301]
    RewriteCond %{HTTP_HOST} ^ipstenu\.org
    RewriteRule ^blog/(.*)$ https://ipstenu.org/$1 [L,R=301]
    RewriteCond %{HTTP_HOST} ^ipstenu\.org
    RewriteRule ^wp-content/blogs.dir/1/files/(.*)$ https://ipstenu.org/wp-content/uploads/sites/1/$1 [L,R=301]
    RewriteCond %{HTTP_HOST} ^ipstenu\.org
    RewriteRule ^(.*)favicon.(ico|png)$ /code/images/favicons/ipstenu.ico [L,R=301]
    
    [NB: This sort of thing is duplicated for other domains which also had things moved around]
    </IfModule>
    

    I cut out a couple of sections, where what I did with the ‘Only redirect ipstenu.org’ stuff is repeated for each site. I built much of that after reading my 404 logs and determining what needed to be redirected. Everything is commented and in logical sections, so I can easily find and remember what the heck I was doing.

    This is the longest section, the stuff under # Ipstenu Moves and such, because they’re accounting for files that moved a million years ago. But the moves section is pretty straightforward too, as you can see where things went. I try to keep it as compact as I can. Sometimes I go through and make them more and more efficient, as I learn new tricks.

    What used to be here?

    I used to include the 5G Blacklist 2013 and/or the 2013 User Agent Blacklist (or whatever the current versions are), but now I don’t have it on all my sites because of the work I’ve been putting in on my firewall and ModSecurity instead. Every once in a while, someone tells me I’m putting too much work on Apache to handle the hackers and spammers, and I generally reply “Better Apache than WordPress.”

    Regularly, I go through my .htaccess and see what I can push over to ModSec. I also trim down my PageSpeed rules into things that work on most sites, things that only work on this site, and things that work for everything. This is why there’s no blacklisting here, it’s all handled by my firewall and mod_security and that’s that. I like to take the load off of apache and .htaccess and PHP and make the server do the work.

    Why not nginx?

    Per site configuration is still a pill. No, really that’s it. It’s a hassle to re-do everything I have in htaccess, I can’t just toss a .nginx file in there on the fly without restarting nginx, which means for shared hosts it’s just not gonna happen. Sucks. For managed hosting, where you don’t allow users to make those changes, sure, it’s great. But that’s not my use case. I may use it for a Varnish in front server one day, after I rebuild everything from scratch.

  • Don’t Fear The Auto Update

    Don’t Fear The Auto Update

    I was not surprised to see the backlash to Auto Updates. We spent a lot of time trying to figure out how to explain to people that while you can disable it, we really, really, really, really, don’t want you to, and basically ended up with a Codex page that explained how to configure it and then Nacin’s followup post that is, indeed, the definitive guide to disabling updates. But people hate it or love it, and there’s no middle ground. This was, as I implied, somewhat expected.

    No auto-updates makes me sadReasons why people hate it have varied from “I want to control my own updates!” to “This 3.7 upgrade broke something, so clearly you’re not ready!” Oh and don’t forget “You suck, I hate this! Why would you default this to on!?”

    I want to stress one really important thing here. The automatic background updates for WordPress are for minor updates only. We’re not talking about auto-upgrading people from 3.7 to 3.8, but just 3.7 to 3.7.1 – These are small, minor, updates. When someone comes to me and complains that major releases don’t always work, I have actually said, “So? We’re not talking about major releases.” And of course, “You are making good backups on these super important websites, right? Right?”

    It’s really easy to get bogged down with all the variable permutations about what updates could include and forget that WordPress started out simple. Yes, it’s defaulted to “on” because after intensive testing, and careful thought, WordPress core devs are pretty darn sure that these minor updates, which are more often than not security related, will not break a site. I’ll get back to breaking sites in a second. The point is that minor updates were picked specifically because it’s known that major upgrades can often break things.

    Why is it defaulted to on? This is my reasoning here… Because the people who wouldn’t turn it on are the people who need it most. If they don’t know it can be turned on, they won’t do it. And they need it. The people who don’t read all the nerdy things are the ones who are still running WordPress 3.4 (no I’m not kidding). I spend a lot of time debugging WP without ever seeing or really ever looking at their site. I know a lot of users don’t upgrade because of laziness, or fear, so I want to address this (see? told you I’d get back to breaking sites).

    Don’t fear updates

    Don't Fear The ReaperI said this on Twitter: If your site breaks every time you update WordPress, it’s time for a theme and plugin audit.

    So what’s an audit? How does one audit?

    It’s really simple. I have a longer presentation I give on this, but let’s go over how simple and basic this is.

    Who is the author?

    This is really obvious. With one exception, every plugin I use that’s made by core developers is updated to fix problems right away. It’s tested on versions of WordPress in the Beta stage, or even on trunk. It’s reliable because the author is reliable. Using a plugin by Mark Jaquith? No fear!

    How active is the author?

    Sometimes even I have no idea who that author is, so I look them up. And I want to see how active they are in WordPress. If someone is engaging on trac and writing plugins and themes, and posting about WordPress, yes, I take the time to read up on them. Remember, I’m auditing the plugin! So I want to see that this author is active and writes or contributes in a way that I approve of. That helps me trust them. Now I’m not expecting them to code as prolifically as Nacin, or write as frequently as Chris Lema, or even scour trac like Scribu. I have realistic expectations. One of my favorite developers is ‘try-lingual’ when it comes to CMSs, so I’ll check on her to see if she’s able to keep up with all the myriad CMSs her code works on. She knows about every release coming up? No fear!

    How popular is it?

    The more a plugin is used, the more people are banging on it in a diverse myriad of environments in ways the author probably never imagined. This is good. This means that the odds are higher than normal that the plugin will work on a bog-standard setup. It also means if I have a common server type (shared) it will probably work. The odds also go up for a more active volunteer environment. Popular plugin, used by thousands? No fear!

    How often is it updated?

    This is a careful thing. I don’t particularly worry if a plugin is old (i.e. not updated in over two years) if the plugin is simple, or made by someone very reliable. Heck, I haven’t touched the code in Impostercide in years, but I do update the readme every couple of WordPress releases to avoid people thinking it’s been abandoned. That said, I do like to see if the complicated ones are at the very least updating their readmes to say “yes, compatible up to the most recent version.” That tells me not only are they testing, but they’re aware of what’s going on in WordPress. Updates are reasonable? No fear!

    What does the code look like?

    The Reaper is Melvin'dThis is hard. This is really hard. I review plugins, and write them, and it’s just plain hard okay? If I’m lucky, I don’t actually have to do this. Examples? Okay, try StudioPress’ Genesis Theme. I don’t look at their code, unless I need to make a child theme. Even then, it’s a case of trusting them to do the best by me. I believe in their code more than mine most of the time. Another example? Anything managed by WordPress.org. But what about the rest? When it’s simple, I can read through the code, make sure it’s not doing anything nefarious and move on. When it’s not, I hire someone else to do it. You heard me. I pay people to do what I can’t because an audit of code is important. Now I don’t do this for every site. Personal/play sites? I may wing it, knowing I make good backups. But a big, company site? Oh you bet every single line of code was checked. Good code? No fear!

    Really? No fear?

    No. Not really. You have to keep in mind that none of these are absolutes. I don’t look at just one thing and say “Done, I have no fear.” I mean, I say ‘no fear’ in these explanations, but the truth is it’s the combination of these things that makes me fear less. WordPress is doing a good thing here and I’m not afraid of it.

    And in case you’re wondering, I’m using auto-updates on all my sites.

  • Genesis: Static Nav Bar

    Genesis: Static Nav Bar

    One of my sites got a facelift, and mid-stream I thought “This site would be the perfect place to have one of those floating nav bars.” You know, like how Twitter has this?

    sticky bar example

    Well guess what? It was easy! Presuming you already have a Primary Navigation Menu (like the one I have here with the Genericons), it’s two steps. Of note, you don’t have to do this in your functions.php, but since this will be a part of your theme, it probably belongs there. I tested, and it works in an mu-plugin as well. I should also point out that there are some official directions in the My.StudioPress.com site, but I didn’t use them. I like making it hard.

    Step One: Put the nav menu above your header

    This one was super easy, it’s even in one of the official Genesis Snippits under Navigation Menus. Put this in your functions.php file:

    //* Reposition the primary navigation menu
    remove_action( 'genesis_after_header', 'genesis_do_nav' );
    add_action( 'genesis_before_header', 'genesis_do_nav' );
    

    That puts the primary navigation menu above the header. If you want to use the secondary menu, it would be genesis_do_subnav but you can sort that out.

    Step Two: Make it stick

    This is pure CSS, so into your style.css goes:

    .nav-primary {
        position:fixed;
        z-index:99;
        top: 0;
        width: 100%
    }
    

    At first I didn’t add in the top: 0; but I found out that without it, a fixed position meant my header was suddenly under the navbar all the time. Oops. So I moved that to on, after spending an hour trying to math out the permutations with margins, and ended up with my navbar under the WordPress toolbar! Don’t worry, CSS to the rescue!

    body.admin-bar .nav-primary {
        top: 28px!important;
    }
    body.admin-bar .site-container {
        margin: 30px 0 0 0;
    }
    

    This simply says that for the body class of admin-bar, bump everything down by 28 pixels.

    Step Three: Return to Top

    I know, I know, I said two steps. This one is optional. I made a menu item called ‘Top’ with a link of #top and a CSS label of ‘top’ and it looks like this:

    Top Menu

    Now since I called this menu ‘primary’ and I’m using Genericons, I made this my CSS (keep in mind .nav-primary would also work):

    .menu-primary top {
        float: right;
    }
    
    .menu-primary li.top a {
        font-size: 0;
    }
    
    .menu-primary li.top a::before  {
        vertical-align: middle;
        padding: 0 5px 0 0;
        font-family: 'Genericons';
        content: '\f435';
    }
    

    This gives me a happy little top arrow that, when clicked on, takes people to the top. If you want to mess with colors, remember that to be specific for just the before calls, it’s a:hover:before (the pseudo-element is last).

  • Writing Evil Code

    Writing Evil Code

    Malicious CodeLately I’ve been doing a lot more training than ever before, and I think (Jen, tell me if I’m wrong) I’m decent at it. I certainly know I have issues with planning exactly what I’m going to teach, though in the case of WordPress troubleshooting, I’m not teaching people what the right answer is, but actually how to look at the error in order to find the right answer. It’s like a code philosophy class, and the more I give it, the more I think I should go back to school to actually ‘learn’ this stuff.

    One thing we’ve been learning about all this stuff, though, is that the hands-on lessons go way better than the lectures (to which every one of you is going ‘Duh, Mika!’ I’m sure), and in the interests of that, I’ve been writing intentionally bad and evil plugins. Actually, Kailey Lampert wrote most of the bad/broken plugins, and I’ve been writing the evil ones. I have a hard time writing broken, as it turns out.

    On the other hand, when it comes to writing intentionally nefarious code, it’s pretty easy. Either that or I’m actually really good at it and don’t think I’m not pondering what that means about me.

    The following are some of the one’s I’ve not only written, but explained what they do, why and how.

    Computers with Errors

    • I Love DC: When installed and activated, you will be redirected elsewhere. Forever.
    • I Love San Diego: Changes your password to something you have no idea what it is, and also changes your email so you can’t easily reset.
    • Hello D0LLY: Redirects non-logged in users to a different site.

    Now it’s intended that all these plugins are simple. They don’t take long to fix your site, and they don’t take long to decyrpt and understand. Every page where you can download them even tells you how to fix them. The point of them is not to make super complex hacks that can never be detected (no such thing), but to explain the process of how one looks through your own site to figure out what happened, and then the plugin file itself to see why it happened at all.

    You see, I’m not aiming for these to make someone the world’s best coder. The goal is to help people understand what’s going on and in general, how to un-do it. Personally, I’ve found that these are great ways for me to understand better how naughty people do things, but also the unraveling has proven delightful for people wanting to learn more about code and cleaning up sites. The only worry left with that is hackers might see this and get great ideas of what do to people. I finally decided that since I’m showing you all how to fix this, you’d know what was wrong when you saw it.

    If you want to download these hacks, check out Break/Fix over on my ElfTest network, and download away. Every example comes with a walkthrough on how to solve it, so if you need a hand held, it’s there for you.

  • WP Comments ReplyTwo

    WP Comments ReplyTwo

    WPTavern has this cool thing where, without threaded comments, you still have a reply link, AND it creates an automatic link back to the original comment.

    Let me rewind. If you have threaded comments, then you get a ‘reply’ link on the bottom of a comment, and it lets you make a threaded reply. Yay! There are problems with this, though, as after a while, if you get nested deep enough, you can’t reply under anymore, and have to go up to click reply on the previous post and on and on.

    Threaded PipeBack eons ago, WPTavern solved this with a function, and like all great sites documented it! The problem? The documentation was busted. Now, yes, I did ping Jeff about this and asked him how it went, but in the meantime, I was impatient and looked up a plugin that almost fit my bill.

    Enter @ Reply (aka Reply To), which add in a reply link to all comments! Plus is gives you ‘Twitter like’ @replies, so when you comment, it starts “@foo:” automatically. This is just like what WPTavern has, perfect! Except… not quite.

    My problems became two:

    1. I want all comments to have a ‘reply’ link.
    2. I don’t want the hover over image.

    And I solved this with two code chunks: a plugin and a theme.

    See, by default WP stops showing you the ‘reply’ link when you can’t nest anymore. To change that, you have to edit how your theme calls comments. Or rather, you have to change the comment_reply_link() call.

    The Theme Code

    I’m already customizing my comments in Genesis so this was surprisingly simple.

    What was this:

    &lt;div class=&quot;comment-reply&quot;&gt;
        &lt;?php comment_reply_link( array_merge( $args, array( 'depth' =&gt; $depth, 'max_depth' =&gt; $args['max_depth'] ) ) ); ?&gt;
        &lt;/div&gt;
    

    Becomes this:

    &lt;div class=&quot;comment-reply&quot;&gt;
        &lt;?php comment_reply_link( array_merge( $args, array( 'depth' =&gt; 1, 'max_depth' =&gt; 2 ) ) ); ?&gt;
    &lt;/div&gt;
    

    Basically we’re lying to WP and saying we always show the link. I got that idea from this stackexchange post, and as I understand it, we’re tricking WP by saying that every post is depth of 1, and has a max of 2, instead of letting it figure it out on it’s own. This is probably inelegant, but I couldn’t find another way to have the reply link always on.

    The Plugin Code

    nested-commentsThis was easier, in that I took the existing code, cleaned it up and removed the reply image, and that was pretty much it. Downside is that this does not work on every site. Notably, it doesn’t work unless threaded comments are turned on. When they’re not, it does a double-refresh.

    That said, this is probably never going to be a plugin for the masses, so I’m content with having it work this way for me. Even if I only thread one comment at a time, it would let me group them together and get the @-reply. It’s already rather popular on the site I intended it for, and people like it.

    So here’s the code:

    class AtReplyTwoHELF {
        public function __construct() {
            add_action( 'init', array( &amp;$this, 'init' ) );
        }
    
        public function init() {
    		if (!is_admin()) {
    			 add_action('comment_form', array( $this, 'r2_reply_js'));
    			 add_filter('comment_reply_link', array( $this,'r2_reply'));
    		}
    	}
    
    	public function r2_reply_js() {
    	?&gt;
    		&lt;script type=&quot;text/javascript&quot;&gt;
    			//&lt;![CDATA[
    			function r2_replyTwo(commentID, author) {
    				var inReplyTo = '@&lt;a href=&quot;' + commentID + '&quot;&gt;' + author + '&lt;\/a&gt;: ';
    				var myField;
    				if (document.getElementById('comment') &amp;&amp; document.getElementById('comment').type == 'textarea') {
    					myField = document.getElementById('comment');
    				} else {
    					return false;
    				}
    				if (document.selection) {
    					myField.focus();
    					sel = document.selection.createRange();
    					sel.text = inReplyTo;
    					myField.focus();
    				}
    				else if (myField.selectionStart || myField.selectionStart == '0') {
    					var startPos = myField.selectionStart;
    					var endPos = myField.selectionEnd;
    					var cursorPos = endPos;
    					myField.value = myField.value.substring(0, startPos) + inReplyTo + myField.value.substring(endPos, myField.value.length);
    					cursorPos += inReplyTo.length;
    					myField.focus();
    					myField.selectionStart = cursorPos;
    					myField.selectionEnd = cursorPos;
    				}
    				else {
    					myField.value += inReplyTo;
    					myField.focus();
    				}
    			}
    			//]]&gt;
    		&lt;/script&gt;
    	&lt;?php
    	}
    
    	public function r2_reply($reply_link) {
    		 $comment_ID = '#comment-' . get_comment_ID();
    		 $comment_author = esc_html(get_comment_author());
    		 $r2_reply_link = 'onclick=\'return r2_replyTwo(&quot;' . $comment_ID . '&quot;, &quot;' . $comment_author . '&quot;),';
    		 return str_replace(&quot;onclick='return&quot;, &quot;$r2_reply_link&quot;, $reply_link);
    	}
    }
    
    new AtReplyTwoHELF();
    

    Most of the javascript stuff is copy/pasta for me (just left of witchcraft), and I left it barebones (no configurations) on purpose. Simple is as simple does.

    Suggestions and tweaks welcome!