Half-Elf on Tech

Thoughts From a Professional Lesbian

Author: Ipstenu (Mika Epstein)

  • WordPress 3.1 and Network Menu

    WordPress 3.1 and Network Menu

    This one’s really fast, but the word should get out there. It’s extremely important if you’ve built a BuddyPress plugin, because the BuddyPress menu has been moved. If you do not do this, your BuddyPress menus will vanish, and you will have very angry users.

    WordPress 3.1 has moved the admin menu for MultiSite. Instead of having a Super Admin menu available on the sidebar of your Admin section all the time, there’s a new link in the header bar for Network Admin. Thats right, it’s its own page! The problem with this is that a lot of plugins aren’t ready for that and because of the move, their admin menu links vanished.

    Thankfully it’s an easy fix!

    The WP Codex Doc on Admin Menus tells us to use “admin_menu” when adding menus. Well, if you want your plugin to show up on the Network Admin page, you have to use “network_admin_menu” instead. (Trac #14435)

    See? I said it was easy.

    add_action( 'network_admin_menu', 'MENU_FUNCTION', ## );
    

    There’s on catch to this. What if your plugin is for Multisite and NON MultiSite? Honestly I don’t know if this matters, but just to be safe, I would do this:

    if ( is_multisite() ) { 
         add_action( 'network_admin_menu', 'MENU_FUNCTION', ## );
    } else {
         add_action( 'admin_menu', 'MENU_FUNCTION', ## );
    }
    

    Or this:

         add_action( 'network_admin_menu', 'MENU_FUNCTION', ## );
         add_action( 'admin_menu', 'MENU_FUNCTION', ## );
    

    That’s right! If it’s there and not-needed, it does no harm! I’m not 100% certain right now if you need to do this for the non-menu calls people make (like calling a function on admin_menu to check for installation), but I’ve been adding it in to no ill effects. I figure, the BuddyPress core code does it, so it can’t hurt!

  • Fighting Spam – We’re Doing it Wrong

    Fighting Spam – We’re Doing it Wrong

    I’ve talked about this before (Spam/Splog Wars) but instead of telling you how to fight spam, I’m going to talk about how it works.

    There are two main kinds of spambots, email and forum. Forum bots are a misnomer, as they’re really ‘posting’ bots, but we won’t get into the semantics of names. These posting bots basically are written to scan the web, via links, looking for anything that accepts data (like a comment form on your blog) and submit spam content. There is a limited number of ways for data to be entered on a website, and generally it’s all done via a form. All a bot has to to so is search the code of the page for form data and input it’s crap content. Given that coders tend to label forms things like ‘content’ and ’email’ and ‘username’ for ease of support and modification, it’s not too hard to see how the spambots are written to exploit that functionality.

    The main ways to prevent spam are to block the spammers or make users prove their real people. Obviously manual spammers (and yes, there are people paid to post spam on blogs) can’t be defeated this way. Blocking spammers is either done by their behavior (if they access your site via anything other than a browser, or if they post data in any way other than from the ‘post comment’ link on your site, they’re probably a spammer) or by a known-bad-guy list. Those both have problems, as spammers have multiple methods of attack. Making a person prove their humanity is generally done via CAPTCHA, which I’ve mentioned before has its own issues. (CAPTCHA Isn’t Accessible ) Another way is to go at it in reverse. Knowing that the spam bots scan a webpage for fields they can fill in, you set it up so there’s a hidden field which only a spammer would fill in. If they fill that field in, they’re spam and they go to the bin.

    I think that our methods for blocking spammers is wrong.

    Everything we’re doing is defensive. We wait for a spammer to attack, sort out what they did, and write better code to stop them. Sure, we have some Bayesian spam tools out there, and some fairly impressive algorithmic learning engines that check the content of a post and punt it to the trash. But in the end, it’s all reactive medicine.

    Anyone who does support will tell you that even one email or comment sent to the spam bin accidentally is bad. How bad? How many times have you said ‘Did you check your spam emails?’ to someone who didn’t get an email? Any time you impede your real users, the regular people who visit your site, the worse your spam-fighting is. If a user has to jump through hoops to comment, they’re not going to do it. If a user has to register to post, they probably won’t do it (forums are an exception to this).

    The goal of spam fighting should be to prevent the spam from being sent.

    We all know why spammers spam. If even one person clicks on their links and buys a product, they’ve profited. It’s just that simple. They make money for a low-cost output, it works, so they keep doing it. Therefore the only way to make them stop is to remove the profitability. Of course if it was that easy, we’d have done it already.

    This begs the question ‘Who runs these spam bots?’ It’s two fold. There are people out there who run spamming programs, certainly, but there are also people who’ve had their computers infected by a virus or malware, and unknowingly spam people. That’s part of why I don’t like blocking IPs. However the software had to come from somewhere. Cut off the head of the snake and the spam stops! We already have the Spamhaus project, which patrols the internet and looks for sites pushing malware, as well as sending spam email. There’s also Project Honey Pot, which fakes links and forms to trick a spam-bot.

    Sadly, until we have more resources dedicated to stopping spam service providers, we’re going to have to keep trying to out think them and play defense.

  • WordPress Google Libraries

    WordPress Google Libraries

    A lot of people would rather use Google Hosted JavaScript Libraries. Why? Here are three good reasons. Okay, great. How do you do it in WordPress? DigWP has you covered.

    But if you want to do it for WordPress MultiSite, for all sites on your network, you can toss this into your mu-plugins folder. I named my file googlelib.php and dropped it in. Bam.

    Oh and there’s also the Use Google Libraries plugin, by Jason Penney, which works great too. Just drop the use-google-libraries.php file into your mu-plugins folder and call it a day.

    <?php
    /*
    Plugin Name: Google Lib
    Plugin URI: http://digwp.com/2009/06/use-google-hosted-javascript-libraries-still-the-right-way/
    Description: Use Google Hosted JavaScript Libraries (... Still the right way)
    Version: 1.0
    Author: Mika Epstein
    Author URI: http://ipstenu.org/
    */
    
    if( !is_admin()){
       wp_deregister_script('jquery');
       wp_register_script('jquery', ("http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"), false, '1.4.4');
       wp_enqueue_script('jquery');
    }
    
    ?>
    
  • Make An RSS Powered Email List

    Make An RSS Powered Email List

    Sometimes the problems we have are insanely more complicated than they should be, because our heads get trapped in a space they shouldn’t be. For years, I used FeedBurner to manage my RSS feeds. Then I realized I didn’t care that much, I didn’t need to know who was accessing my feeds, and really the only benefit was that I could put ads in my feeds (which … no one clicked on anyway) and 12 people could subscribe via email. Well, with some research I found that I could put ads in my feeds with some WordPress functions (I’ve since removed them) and I could use Subscribe2 as a plugin to email when I had new posts. Don’t get me wrong, I really like Subscribe2 except I didn’t like the interface. It’s on the back end of WordPress. My site is a BuddyPress site. Everything is on the front end for my users, and I like it that way. It all looks ‘branded.’ The plugin dev was, fairly, under the idea of ‘Works how I want it.’ I thought about forking, but as I looked at the code, I thought that I really didn’t need WordPress to handle this. I needed a way to email an RSS feed to a mailing list. A proper, opt-in, stable, mailing list, that wouldn’t affect my blog while processing.

    I found an answer that can be applied to any site, WordPress or not.

    What?

    The problem:
    I have an RSS feed I want to be able to email to people who don’t like RSS, and I don’t want to use FeedBurner, MailChimp or any external process.

    The solution:

    • Setup a MailMan list for your emails and configure as needed
    • Install and configure rss2email
    • Setup a cron job

    Why?

    Why not use [this product]? When I presented this to people the first thing they said was ‘Just use FeedBurner!’ or ‘Use MailChimp!’ I get that I can use those third-party vendors, but I don’t want to. I like to self-host because then, if things go wrong, I have the ability to do something about it. This is also how I increase my IT toolkit. I have a need, I find a solution. Sometimes I write the code, and sometimes I just master a new tool.

    Why Mailman? Mailman (or properly GNU Mailman) is installed on my server and while it may be old, the current stable version is 2.1.14, and that came out September 2010. It’s still updated, maintained and supported. And it works. I’m familiar with it, I’m comfortable with it, and there’s no reason not to. I did experiment with phpList, which claims to be able to handle RSS feeds as ‘source’ on it’s own. The problem, as my Twitter buddy @JohnPBloch warned me, is it’s not friendly. He said “I don’t care much for phpList. I always felt like the software was working against me instead of with me.” And he’s right. It took 5 minutes of setup for me to gag and delete it.

    Why rss2email? I don’t think RSS is dead. In fact, I still prefer it to email (or Twitter). My unread RSS list (currently run via Google Reader) sits, quietly, patiently, waiting my attention. I don’t get spam or junk feeds, and if I decided to mark all my Fail Blog feeds as read without reading them, no one knows but me. I don’t have to reply to anything, and I can go back to using my email for communication. That said, I know a lot of people who like to get updates in their email, so I have to take that into consideration when running a site. Sometimes, when you make a site, you cater to yourself. Sometimes you cater to your audience.

    Why cron? I’m on Linux. That’s what you do when you want to schedule things.

    How?

    Bear in mind that my details are going to be specific to my situation.

    Mailman is the easiest. You make a mailing list. I wanted an announcement mailing list, so under Privacy options -> Sender Filters I set up that all users were moderated by default and to discard their emails. Then added my email under “List of non-member addresses whose postings should be automatically accepted.” I knew I was going to have emails sent from a specific address, and I didn’t want that address to GET the emails, so by putting it on that list, I don’t have to worry about approving posts. That’s pretty much all the ‘special’ customization I did. If I’d wanted to put a reject to other people’s emails to the list, instead of a discard, I’d have added this “This is an announcement only list. Your post has been rejected.”

    rss2email was the hardest, but only because it was new. The install process is really straightforward. I made very minor tweaks to the config.py file, based on a first run when I realized that my mailing list would strip HTML. I set HTML_EMAIL and USE_CSS_STYLING to 0 to get it all to plain text. I changed my DEFAULT_FROM and OVERRIDE_FROM to ‘pretty’ versions of my domain information. Then I had to customize my SMTP stuff, since it requires authentication and is on a special port (not 25).

    cron was the most surprising. Since I have to run rss2email out of the same folder it’s in (Python…) I wrote a quick shell script called rss2email.sh that has two steps. It changes directory to my install of rss2email and then it calls the command ./r2e run. Then I called it with a twice-daily (0 and 12) cron job with /home/USERNAME/rss2email.sh and it’s done. I’m not going to give you a blow by detail on how to do cron stuff. It’s way too complicated to try and overview here.

    Satisfied?

    Pretty well. I’m still massaging the output a bit. The HTML output of a full RSS entry was weird. After changing my WordPress feed to excerpts, I ended up with some weird lines in my emails:

    This was caused by some old functions I had in my theme to insert ads into my feeds (mentioned above). I took that out, called ./r2e reset to clean out the database, and then re-ran the script. Worked fine! I admit, I had some moments where I didn’t like putting the excerpt in. I use a custom crafted excerpt in every single post on this site as part of my layout, and while I prefer to avoid ‘read more!’ type things in my feeds, I realized my custom excerpts would be ‘good enough’ for anyone who cared. I do wish WordPress would make two feeds, one excerpt and one none, but that’s a job for another day. At least I’ve managed to semi-customize my Mailman digest header (via manually editing masthead.txt).

    After all my testing, I deleted the mailing list and reset everything, did a clean build, and voila! Works like a champ, without putting extra stress on things!

  • Customizing a Sidebar Profile – BuddyPress

    Customizing a Sidebar Profile – BuddyPress

    I was looking at BP Tricks and thought ‘You know what would rock my site? A sidebar profile controller!’ Turns out this is pretty easy and only ‘requires’ two plugins.

    My final product (see left) isn’t super impressive, but it’s pretty simple and easy to use. The basic idea is that I have two master widgets. One is what the non-logged in user sees (a simple signup window) and one is what the logged in user sees. The logged in user should be able to see their profile info, their notifications and anythign else I want. Before I got started I made a list of what I wanted them to see.

    • Profile – This lists your profile, edit links, settings links, and a logout link
    • Notifications – This lists everything that can email you: notices/messages, comment subscriptions, newsletters, mailing lists
    • Achivements – I use Paul Gibbs’ Achievements for BuddyPress
    • Activity – Links to the various activity screens

    First I decided I wanted an accordian style profile, where you had sections. I grabbed Tabbed Widgets and tossed that in my widget area. Then I used Widget Logic and set the tab to only show if a user was logged in. If the user is NOT logged in, I used the PHP Code Widget to display a login form. Since I’m using BuddyPress, I just grabbed this wholesale from the source.

    <form id="sidebar-login-form" class="standard-form" action="<?php echo site_url( 'wp-login.php', 'login_post' ) ?>" method="post" name="login-form"><label><!--?php _e( 'Username', 'buddypress' ) ?--> <input id="sidebar-user-login" class="input" type="text" name="log" value="<?php echo esc_attr(stripslashes($user_login)); ?>" /></label><label><!--?php _e( 'Password', 'buddypress' ) ?--> <input id="sidebar-user-pass" class="input" type="password" name="pwd" value="" /></label>
    <p class="forgetmenot"><label> <input id="sidebar-rememberme" type="checkbox" name="rememberme" value="forever" /> <!--?php _e( 'Remember Me', 'buddypress' ) ?--></label></p>
    
    <center><!--?php do_action( 'bp_sidebar_login_form' ) ?--> <input id="sidebar-wp-submit" tabindex="100" type="submit" name="wp-submit" value="<?php _e('Log In'); ?>" /> <input type="hidden" name="testcookie" value="1" /></center></form>
    

    I could have probably done this with a widget, but I like being able to customize my PHP as I want to. Next it was time to build my tabs. The Tabbed Widget plugin is pretty easy to use. You make your widgets in the Invisible Widget area and they show up available for the Tabbed Widget. Using the list I made above, I pulled in the obvious widgets. Three are PHP and one is the Achievements widget which came with the plugin. I dislike using plugins just for widgets, so my PHP is how I customized things. The PHP for notifications has extra cruft you probably won’t need, but I wanted you to see how you could easily port in any link.

    My profile

    <div>
    <div style="float: left; padding-left: 5px;"><strong>Hello, <!--?php echo bp_loggedin_user_fullname() ?--></strong>
     • <a href="<?php echo bp_loggedin_user_domain() ?>profile/">Visit My Profile</a>
     • <a href="<?php echo bp_loggedin_user_domain() ?>profile/edit/">Edit My Profile</a> 
     • <a href="<?php echo bp_loggedin_user_domain() ?>settings/">Edit My Settings</a> </div>
    </div>
    

    My Notifications

    • <a href="http://jorjafox.net/comment-subscriptions/">Edit Comment Subscriptions</a>
    • <a href="http://jorjafox.net/wp-admin/users.php?page=s2_users">Edit Daily Update Emails</a>
    • <a href="http://jorjafox.net/csiwatch/">Edit CSI Watch Subscription</a>
    • <?php if ( messages_get_unread_count() > 0 ) {
    	?><a href="<?php echo bp_loggedin_user_domain() ? rel="nofollow"><?php echo BP_MESSAGES_SLUG ?>">Inbox (<?php echo messages_get_unread_count(); ?>)</a><?php 
    } else {
    	?><a href="<?php echo bp_loggedin_user_domain() ? rel="nofollow">/messages/">No new messages</a><?php 
    } ?>
    

    Activity

    <div style="padding-left: 5px;">
    <ul id="user-menu">
    	<li><a href="<?php echo bp_loggedin_user_domain() ?>activity/">Site Activity</a></li>
    	<li><a href="<?php echo bp_loggedin_user_domain() ?>activity/just-me/">My Activity</a></li>
    	<li><a href="<?php echo bp_loggedin_user_domain() ?>activity/favorites/">My Favorites</a></li>
    	<li><a href="<?php echo bp_loggedin_user_domain() ?>activity/groups/">My Groups</a></li>
    	<li><a href="<?php echo bp_loggedin_user_domain() ?>activity/mentions/">@<!--?php echo bp_loggedin_user_fullname() ?--></a></li>
    </ul>
    </div>
    

    Once I was done making those, I just pulled them into my Tabbed Widget in the order I wanted, with the style and defaults I wanted. The rest was all CSS, which you can do yourself.

    Basically, this just goes to show you that you can do pretty much anything you want with WordPress plugins. I really only needed two to do this, though the third (PHP Code Widget) really helped me take it to the next level. If you’re PHP shy, you can use Login with Ajax instead of my ‘Login’ code, BP Notification Widget instead of my Notification code, and I’m sure people can pick out some alternatives to other code bits.

    Hope this gets you started!

  • Common IT Answers

    I actually have this sitting on my desk at work. It’s so old that the fluid has evaporated enough that it doesn’t work right anymore. But I keep it and use it. What is it? A magic 8-ball of tech support! Many moons ago, our CDW Vendor gave my boss a Magic 8-Ball for programmers showing the answer “IT’S NOT A BUG – IT’S A FEATURE”. The top of the ball says “For your most commonly asked IT requests.” Some of the answers are blatant CDW adverts, but the rest are answers I know I’ve used at least once:

    • Did you press the right button?
    • I can’t test everything
    • It worked yesterday
    • It works like I programmed it
    • It works on my machine
    • It’ll be fixed in the next release
    • It’s a Beta – What did you expect?
    • It’s an unlikely coincidence
    • It’s just an isolated incident
    • it’s not a bug, it’s a feature
    • It’s not supposed to do that
    • Please submit a formal request
    • Plug it in
    • Program works. Must be user error
    • Reboot
    • Someone changed my code.

    Sadly, the thing is dying. I may have to learn how to make a new one, since right now it’s stuck showing me a corner instead of a face.

    I’m not the only person who uses these, though. Eric Mack did as of 2004!