Half-Elf on Tech

Thoughts From a Professional Lesbian

Category: How To

  • Multisite Login Loop

    Multisite Login Loop

    Congratulations, you’ve decided to go Multisite and added in all your lines to your config file. You’re raring to go, and the last step is to log out and back in.

    But you can’t.

    You get to the login screen, enter your credentials, and the page just refreshes. What’s on earth is going on?

    This is actually a pretty rare thing, and I was only able to reproduce it when I moved my site on the server. The fix is actually pretty easy, and there are three things to do.

    1) Edit your wp-config.php.

    Visit https://api.wordpress.org/secret-key/1.1/salt/ and get new salts/hashes. This should prompt your users to re-login and hopefully generate new cookies.

    2) Dump your cache.

    Sometimes, however, browsers are idiots and you have to flush the local cache. You shouldn’t need to dump caching plugins, since that doesn’t impact logins.

    3) Delete your cookies.

    I hate this one. Delete the cookies only for your domain if possible. Chrome hides this, but it’s doable for all sites.

    4) Check your .htaccess

    A lot of people miss this. When the directions say ‘Replace your .htaccess with this…’ what they mean is replace. And yet many people leave in the old WordPress rules. Remember to replace your .htaccess calls for WP with the correct one: Multisite .htaccess rules

    5) Check your wp-config.php again

    You need to have both define('WP_ALLOW_MULTISITE', true); and define('MULTISITE', true); in there.

    But what if you have this problem on Single Site? Do the same thing, but if you’re using CloudFlare, go check your settings. They’ve been known to cause problems with this, due to handling of redirects. Me and a coworker wasted a couple hours on that, before someone else pointed it out.

    Edited to add….

    6) Kick wp-config.php in the butt

    Tom McFarlin came up with added this to your file:

    define('ADMIN_COOKIE_PATH', '/');
    define('COOKIE_DOMAIN', '');
    define('COOKIEPATH', '');
    define('SITECOOKIEPATH', '');
    

    This kicks the cookies.

  • Switching Network Types

    Switching Network Types

    This actually isn’t hard to do, but it can be tricky to complete if you don’t remember what you started with.

    To start with, let’s say I have a multisite with subdomains: ipstenu.loc. I’ve added in two subsites, foo.ipstenu.loc and bar.ipstenu.loc. But then I decide I really wanted to have ipstenu.loc/bar and ipstenu.loc/foo instead.

    The easy part is first. I know my wp-config.php has this:

    define('WP_ALLOW_MULTISITE', true);
    define('MULTISITE', true);
    define('SUBDOMAIN_INSTALL', true);
    $base = '/';
    define('DOMAIN_CURRENT_SITE', 'ipstenu.loc');
    define('PATH_CURRENT_SITE', '/');
    define('SITE_ID_CURRENT_SITE', 1);
    define('BLOG_ID_CURRENT_SITE',1);
    

    All I have to change is the one line define('SUBDOMAIN_INSTALL', true); to define('SUBDOMAIN_INSTALL', false); and now I’m using sub-folders!

    But that means that foo.ipstenu.loc isn’t really valid. Amusingly, it doesn’t break anything at first, so the still will work. But once I change the .htaccess, things will get hinky, so I’m going to do the ‘hard’ part.

    Go in to Network Admin -> Sites and Edit each site that uses a subdomain and you’ll see this:

    Looks familiar, right? I’m going to change foo.ipstenu.org to ipstenu.org and the line with / becomes /foo/:

    As soon as I hit save, the site is ‘moved.’ Great! Do this for all my sites and .. wait. Now they look all ugly!

    That’s because I have to edit the .htaccess. Go to Network Admin -> Settings -> Network Setup, and copy the .htaccess from there, replace, and now it works too.

    The one last step is re-saving the permalinks in your main site, and remembering your links are about to break. What’s that now? Oh, yes, you see ipstenu.loc now gets /blog/ shoved in for any posts, so ipstenu.org/2012/postname became ipstenu.loc/blog/2012/postname. The catch here is that if you don’t resave the permalinks, they will continue to work until you do. Once you hit ‘save’ on permalinks, blog jumps in, and WordPress cheerfully redirects people for you, so you lose nothing.

    And now you know!

  • Google Apps

    Google Apps

    Google AppsI don’t like Google very much. However when my grandmother had a request for something to be added to her website, I realized Google’s email would actually be much easier for them, especially since her domain, taffys.org, is mapped to this server as a part of my Multisite network. Oh, it’s not terribly hard to make emails for her, but she wanted someone local to do that.

    There’s a minor story behind that, but the shortest version is she’s doing some totally awesome not-for-profit work with Parkinsons patients. One of the things she wants is an email, used by many people, to ‘collect’ messages like ‘I’ll be there.’ While I could do this on my site, it’s actually easier to get this up on Google, where I can tell people login to go to http://mail.google.com/a/taffys.org or http://mail.taffys.org and it’s something they know.

    I chose to do this by command line, for the experience. If I wanted to do it via cpanel and WHM, you’d go in to edit the DNS zone for the server and add in the mx records.

    MX Records

    The command dig mx taffys.org tells me what I have right now, which I knew was self referential.

    ; <<>> DiG 9.3.6-P1-RedHat-9.3.6-20.P1.el5_8.5 <<>> mx taffys.org
    ;; global options:  printcmd
    ;; Got answer:
    ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 20605
    ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 1
    
    ;; QUESTION SECTION:
    ;taffys.org.			IN	MX
    
    ;; ANSWER SECTION:
    taffys.org.		14010	IN	MX	0 taffys.org.
    
    ;; AUTHORITY SECTION:
    taffys.org.		78943	IN	NS	ns1.ipstenu.org.
    taffys.org.		78943	IN	NS	ns2.ipstenu.org.
    
    ;; ADDITIONAL SECTION:
    taffys.org.		6943	IN	A	50.28.84.96
    
    ;; Query time: 11 msec
    ;; SERVER: 69.167.128.254#53(69.167.128.254)
    ;; WHEN: Tue Nov 13 08:09:06 2012
    ;; MSG SIZE  rcvd: 104
    

    Looks like that for all my stuff. Okay, no problem, I go in and edit /var/named/taffys.org.db and find this:

    taffys.org. IN MX 0 taffys.org.
    

    Change it to this:

    ; Original
    ; taffys.org. IN MX 0 taffys.org.
    
    ; Gmail
    taffys.org.             14400   IN      MX      10 ASPMX.L.GOOGLE.COM.
    taffys.org.             14400   IN      MX      30 ASPMX2.GOOGLEMAIL.COM.
    taffys.org.             14400   IN      MX      20 ALT1.ASPMX.L.GOOGLE.COM.
    taffys.org.             14400   IN      MX      30 ASPMX4.GOOGLEMAIL.COM.
    taffys.org.             14400   IN      MX      30 ASPMX5.GOOGLEMAIL.COM.
    taffys.org.             14400   IN      MX      20 ALT2.ASPMX.L.GOOGLE.COM.
    taffys.org.             14400   IN      MX      30 ASPMX3.GOOGLEMAIL.COM.
    

    And then I ran /usr/sbin/rndc reload taffys.org to refresh it. But ... wait. Why does it still say I'm on taffys.org? Per usual, I didn't bother to change my TTL. As everyone always reminds me, if you make a change to DNS without lowering your TTL values, you're gonna have a bad time. Since I'm (rarely) in a rush for this stuff, meh. Besides, it takes 24-48 hours from changing TTL for it to be usable, and then I can make my change. Followed by waiting again, and then changing it back? DNS is pretty zippy these days. 72 hours max, and usually less, so I just don't.

    While I waited on that, I went ahead and made a Google Apps account for taffys.org. When you go to Google Apps they only show you business and education. I'm neither (though I suppose what I'm doing for Taffy would be non-profit). Really they're trying to sell, which makes sense. If you go to their pricing model, you'll see the free option. Unless you're running a business, click that.

    The rest of the directions are really straight forward, and Google shows you what to do. It's really just set up the account stuff from there out. The directions to make mail.yourdomain.com are under Create a custom web address.

    If you want to do it with a GUI, it's even easier. I went into my DNS management setup on cpanel and did this:

    Will I do this for other domains? Maybe. I think I'll be doing this for hosting going forward, since the people I host rarely (ever?) use cPanel. Congrats, Taffy! You're the first! Liv's the second.

    Now I have to fix up Taffy's site.

  • Sidebar Login Widget

    Sidebar Login Widget

    This comes up a lot.

    The basic concept is you want to allow users to log in and out via a sidebar, and never see the admin-end of WP. There’s an awesome plugin called Sidebar Login that already does this, but I decided to play around and make a dead simple widget. There’s no ajax going on here, and very little code since it all calls the built in functions and filters.

    It lets you make a few choices, as to what verbiage you want to use, and if you want to show login/registration info or not. The registration link won’t work if you have registration turned off, natch.

    All the code is here at Hack: Sidebar Login Widget

    Really those hacks are more ‘mu-plugins’ that I don’t want to support, but still wrote, but you get the idea.

    I’ve taken to writing up the code, when I can, for people in the forums a little more, since it helps me as a developer get better with WordPress. I’m still new at wrangling widgets, so this was a new, and interesting, experience for me. That brought up questions for me, as to where people like the plugin ‘settings’ to be.

    [polldaddy poll=6676462]

  • Sidebar Login Widget

    Sidebar Login Widget

    So this happened after people asked me about how to make a widget. This makes a slightly customizable widget that will let you have a slightly customized login form via a widget.

    As with all hacks, you’re on your own for support. Code is GPLv2, and it should be translatable.

    Download Code

    The code is in a .txt file. Rename if .php and toss it in mu-plugins

    Download TXT

    Code

    .

    Sidebar Login Widget is released WITHOUT any support, and you can
    use it at your own risk. The code should work, but I’m not spending
    a lot of time on it.
    */

    if (!defined(‘ABSPATH’)) {
    die();
    }

    // Register the widget
    function sli_register_widgets() {
    register_widget( ‘sli_SLI_widget’ );
    }
    add_action( ‘widgets_init’, ‘sli_register_widgets’ );

    // This is the widget!
    class sli_SLI_widget extends WP_Widget {

    function sli_SLI_widget() {
    $widget_ops = array( ‘classname’ => ‘sli_add_users’, ‘description’ => ‘Sidebar Login Form.’ );
    $control_ops = array( ‘width’ => 300, ‘height’ => 350, ‘id_base’ => ‘sli-add-user-widget’ );
    $this->WP_Widget( ‘sli-add-user-widget’, ‘Sidebar Login’, $widget_ops, $control_ops );
    }

    function widget( $args, $instance ) {
    extract( $args );

    /* User-selected settings. */
    $title = apply_filters(‘widget_title’, $instance[‘title’] );
    $errormsg = $instance[‘errormsg’];
    $lostmsg = $instance[‘lostmsg’];
    $show_for = $instance[‘show_for’];
    $show_reg = $instance[‘show_reg’];

    /* Before widget (defined by themes). */
    echo $before_widget;

    /* Title of widget (before and after defined by themes). */
    if ( $title )
    echo $before_title . $title . $after_title;

    // Code Goes Here

    global $user_login, $post;
    $redirect = $_SERVER[‘REQUEST_URI’];

    if (isset($_GET[‘sli’])) {
    $sli = $_GET[‘sli’];
    if ($sli == ‘fail’) { echo “

    “. $errormsg .”

    “; }
    if ($sli == ‘lost’) { echo “

    “. $lostmsg .”

    “; }
    }

    if (is_user_logged_in()) {
    _e( ‘Howdy’, ‘helfsli’ );
    echo $user_login, ‘. Logout‘;
    } else {
    wp_login_form(array( ‘value_remember’ => 1, ‘redirect’ => $redirect));

    if ( $show_reg && get_option(‘users_can_register’) ) {echo wp_register(”, ”);}
    if ( $show_reg && $show_for) {echo ‘ | ‘;}
    if ( $show_for) {echo ‘Lost Password‘;}

    }

    /* After widget (defined by themes). */
    echo $after_widget;
    }

    function update( $new_instance, $old_instance ) {
    $instance = $old_instance;

    /* Strip tags (if needed) and update the widget settings. */
    $instance[‘title’] = strip_tags( $new_instance[‘title’] );
    $instance[‘errormsg’] = strip_tags( $new_instance[‘errormsg’] );
    $instance[‘lostmsg’] = strip_tags( $new_instance[‘lostmsg’] );
    $instance[‘show_for’] = $new_instance[‘show_for’];
    $instance[‘show_reg’] = $new_instance[‘show_reg’];
    return $instance;
    }

    function form( $instance ) {

    /* Set up some default widget settings. */
    $defaults = array( ‘title’ => ‘Log In’, ‘errormsg’ => ‘Error: Incorrect username/password’, ‘lostmsg’ => ‘Password reset sent.’, ‘show_for’ => false, ‘show_reg’ => false, ‘show_sex’ => true );
    $instance = wp_parse_args( (array) $instance, $defaults ); ?>


  • Auto Multisite Registration

    Auto Multisite Registration

    There are plugins for this, and I’m rather fond of them. If you just want all new users to be added to some (or all) sites, then I suggest you use Multisite User Management. It’s a great plugin, and lets you pick and chose. But similar to how sometimes you want users to register per site, you may have a situation where you want users to be added to any and all sites when they visit.

    So how do we do this? It’s really not that painful, just make a add-users.php file in your mu-plugins folder with this:

    <?php
    
    /*
    Plugin Name: Add Users
    Description: Add users to blogs when they visit.
    */
    
    function helf_add_users( ) {
        global $current_user, $blog_id;
    
        if(!is_user_logged_in())
        return false;
     
        if( !is_user_member_of_blog() ) {
            add_user_to_blog($blog_id, $current_user->ID, "subscriber");
        }
    }
    
    add_action( 'wp' , 'helf_add_users' , 10);
    

    This code will automatically detect “John Doe is logged in.” and “John is not a member of this site.” If both of those are true, then it says “We will add him as a subscriber.” You can change subscriber as you see fit.

    Would it be more efficient to just do this check on registration? Sure. But there are moments you don’t want this. If you wanted to get extra sneaky, you could set this to only run on a specific page, and make that page password protected.

    If we want to add in a couple extra layers, that’s also not terrible. Let’s say we want people to press a button ‘Join This Site’? I have to admit, this actually took me longer to hash out than I wanted it to, mostly because I decided if I was going to do this, I should do it all the way.

    That’s why I came up with Join My Multisite, which is a handy plugin to give you some more options. It’s per-site configurable, so your site-admins will get to decide if they want everyone logged in user to be added to their site, or if they want a widget, or if they want nothing at all. I put some time into thinking about if it would be a good idea to have the network admin be able to pick, but when I got down to brass tacks, I realized there was no way to easily force a widget (i.e. the button to join the site) for all sites and make it always look good. If you need that, you should fork the plugin and hard-code in the widget.

    Join or Die

    In a way, this is an extension of the old ‘Add Users Sidebar’ plugin, which drifted off into the wayward lands of not-supported. I never looked at that code, though, and instead wrote all this from scratch.

    In addition to all that, Join My Multisite gives each site the ability, if registration is open, to easily make a per-site registration page. That one was Mason James’ suggestion.