Troubleshooting WordPress re-directs (301)

While trying to configure some internal URL re-writing in nginx for a WordPress site, I ran across an annoying issue:

Regardless of my re-writing efforts, WordPress would issue a re-direct (301) header (?!)

This wouldn’t have been such a big deal if I didn’t want the URL to stay the same in the browser’s address bar. If I didn’t have that requirement, I would naturally have used a simple re-direct.

After spending some time troubleshooting this, and making sure nginx was actually doing what I wanted it to do, I ran across a few posts talking about disabling “canonical redirects” (sic) in WordPress. So adding this snippet to the end of the active theme’s functions.php:

remove_filter('template_redirect','redirect_canonical');

got rid of WordPress re-directs. Unfortunately, another plugin “stepped in” and started doing it instead (this time, it was the Polylang plugin). I’m sure there are a number of other plugins that exhibit this behavior, and it may be possible to circumvent this in many/most/all of them by using something similar to the above snippet, but I still haven’t solved the actual problem.

Using cURL to debug URL re-writing and URL re-direction can save you a lot of time, like this:

curl -I https://yourwebsite.foo

(Please note that the issues I have experienced here are not related to nginx. This would happen in Apache too as the re-directs are issued by the WordPress stack. Once control is handed off to PHP, there’s little the web server can do.)

If you’re playing with nginx, PHP-FPM, and URL re-writing, you may also find this post of interest: URL re-writing with nginx, PHP, and WordPress

URL re-writing with nginx, PHP, and WordPress

There are many posts about nginx, re-directs, PHP, and WordPress. There are somewhat fewer posts that talk about (internal) re-writes, where the request by the web browser is mangled to be served by another resource than the one requested.

For example, I may want a request for https://mysite.foo/cool/penguin to actually be served by https://mysite.foo/coolstuff.php?id=penguin, or simply setup an alias such as https://mysite.foo/cool/penguin to be served by https://mysite.foo/cool/linux, but preserve the URL in the browser address bar.

With PHP-FPM and nginx, you run into an additional problem, which is the fastcgi_parm variables that are passed from nginx to PHP-FPM. So even if you have really fancy URL re-writing configured (and working), the end result may not be passed on to PHP-FPM from nginx.

So solve this, you should look into this construct, which is present in many nginx configurations as a default setup:

fastcgi_param REQUEST_URI $request_uri;

Since your needs probably differ from mine, I wont make this post any longer than it has to be, but that fastcgi_param line above may be a good starting point if you’re experiencing problems with nginx, PHP-FPM, and URL re-writing.

Good luck!

SwiftMailer 5, PHP5, and ISO-8859-15

I’ve been using SwiftMailer for as long as I can remember because it’s, IMHO, a great library and far more logical than PHPMailer and “others”. While maintaining a PHP5 codebase for a rather large project, I ran into an issue while using ISO-8859-15 encoded data. Most people won’t care about ISO-8859-15 over ISO-8859-1 (“Latin1”), but since I live in Europe, I prefer to have support for the โ‚ฌuro character ๐Ÿ™‚

To make a long story short, if you need SwiftMailer 5 to properly handle ISO-8859-15, look for a line in “MimePart.php” that looks like this:

if (!in_array($charset, array('utf-8', 'iso-8859-1', ''))) {

and change it to this:

if (!in_array($charset, array('utf-8', 'iso-8859-15', 'iso-8859-1', ''))) {

(Yes, the project will move to a PHP7 codebase at some not so distant point in the future.)

Simple password construct validator for PHP

/* 
 * Simple password construct validator for PHP 
 * Joaquim Homrighausen <joho@webbplatsen.se>
 * May 30, 2019 
 * TEAMYUJO 
 * 
 * Do whatever you want with this snippet :) 
 * 
 * This may not necessarily agree with the section
 * "Strength of Memorized Secrets" in the document
 * from NIST:
 *
 * NIST Special Publication 800-63B 
 * Digital Identity Guidelines 
 * Authentication and Lifecycle Management 
 * https://pages.nist.gov/800-63-3/sp800-63b.html 
 */

function password_check_construct ($pstr, $min_length = 8)
{
  //Setup pattern and stuff minimum requested length into it
  if ($min_length < 4) {
    //We need at least four characters to satisfy our regexp
    $min_length = 4;
  }

  $match_rules = '/^(?=.{'.(int)$min_length.',})(?=.*[a-z])(?=.*[0-9])(?=.*[A-Z])(?=.*[[:punct:]]).*$/';

  //Require at least one a-z, one A-z, one 0-9, and one punctuation/special character
  if (preg_match ($match_rules, $pstr) === 1) {
    return (true);
  }
  return (false);
}

This is also available as a gist on GitHub. Knock yourself out ๐Ÿ™‚

Setting PHP.INI path (or file) for PHP CLI shell scripts

Running a PHP script from the command-line, or CLI, is quite useful at times and is often used to perform some automated task, like a CRON cleanup script, to send out reminders, etc.

It’s common that these CLI scripts need some, but possibly not all, settings that are similar to the main application’s. I may, for example want to include the database configuration settings shared with the main application. So I often create a separate php.ini file for this purpose.

Running /usr/bin/php -c /my/very/special/path cronScript.php is simple enough, but what if I want to be able to create an “executable” PHP shell script? The obvious answer would be something like:

#!/usr/bin/php -c /my/very/special/path

at the top of the .php file, followed by my PHP code, right? Except that may not do what you want. I could not get the PHP interpreter to load anything in /my/very/special/path by using the above construct, even if it works from the actual command-line. After banging my head against the wall for a while, this turns out to work for these “shell scripts”:

#!/usr/bin/php -c=/my/very/special/path

Note the use of the = (equal) sign between the -c and the path (or file).

Carry on.

PHP is_numeric () fails WordPress version string check

This is, perhaps, obvious to most PHP developers. But it came somewhat as a surprise to me.

Using is_numeric () for validating a WordPress version string, such as ‘4.7’, does not seem to work very well when WordPress introduces minor releases such as ‘4.7.1’.

Since I cannot be bothered to figure out why it behaves in this (erratic, IMHO) way, I have since replaced the call to is_numeric () with a small function using a simple regular expression (regexp):

    function wpVersionStringCheck ($vs)                                                                                                 
    {                                                                                                                                   
        return (preg_match ('/^(\d+\.)+\d+$/', $vs));                                                                                   
    }

I’m sure there is a hole in there somewhere, but on the following strings at least, it gives me the desired result:

1.0 is valid
1.0. is invalid
1.0.1 is valid
1.banana.0 is invalid

Making SimpleXML truly simple using JSON in PHP

JSON_vs_XML
So using SimpleXML in PHP is possibly one of the worst hells of typecasting and data extraction procedures one can encounter, or close to it ๐Ÿ™‚ But more the point, you don’t need to walk down that road alone, enter JSON.

In the simplest of ways, this will typically get you something useful:

    $pvar = json_decode ($xml);

 

(Where $xml is a SimpleXML-type object) This returns a “slightly easier to manage” PHP array.

If you want an associative array, do this:

    $pvar = json_decode ($xml, true);

 

To get it back to JSON, you simply use:

    $json = json_encode ($pvar).

 

You may need to handle XML data, but you don’t necessarily need to work with it in XML form inside your application. The above examples may not work fully for you if you have to deal with “foreign” files or clean the input data prior to conversion, but you get the idea.

This is, obviously, obvious to many. It’s a lifesaver for others ๐Ÿ™‚

LinkedIn:
www.linkedin.com/pulse/making-simplexml-truly-simple-using-json-php-joaquim-homrighausen

Look inside, think outside (the box)

20150816_183520_IKEA

Doing things the same way as they have always been done isn’t necessarily a good idea. In the case of IKEA, I cannot recall the last time they did NOT include their “universal tool”. This is the first time I remember opening one of their self-assembly products and finding this type of mistake. Though in the case of IKEA, it may be that they’re just too lazy to change the production system.

You must not fear change ๐Ÿ™‚

Bye bye NetBeans, still fails on remote projects, cannot detect source file changes

So NetBeans 7.x is out since a few months. With many new functions, new and updated plugins, a lot of bugfixes, etc. Fantastic! Go NetBeans!

And just because I’m a sucker for punishment, I open up a new PHP project, select a WordPress site where I do some plugin sandbox development, enter all the parameters NetBeans wants, and click “OK”.

And … NetBeans starts doing its normal routine of scanning the remote (via SSH) directories, asks me to confirm that I want to download some 1714 files to my local computer, and when I do (why wouldn’t I, right?), it begins its glorious work.

In the meantime, I set-up a new project using ActiveState’s Komodo 6.13 IDE, I point it to the same server and directory and click “OK”. Three seconds later, I have my project.

NetBeans you ask? Oh, it’s still downloading. My Internet connection is too slow (it’ll max out around 20 mbit/s) of course .. I should have at least 100 mbit/s, or possibly GB/s. Because if you want to do NetBeans development on remote servers and do it the “proper NetBeans way”, you STILL have to download your entire project locally.

I could live with that rather awkward way of doing things if NetBeans could only detect changes to the file(s) on the remote. As it is now, and as it has been for many years with NetBeans, it’ll simply consider itself to be the master, and overwrite whatever is on the server.

Of course I’m doing it all wrong. I should use version control, I should not expect myself to be able to use my workstation as a terminal to the server. I mean, those days are gone, right? We ARE in the MODEM ERA of Internet, where you REALLY wanted to do EVERYTHING LOCALLY due to bandwidth limitations, etc.

Oh no, wait .. this is 2011 .. everyone but your pet is connected 24/7/365.

So, I think now that NetBeans have shown (again), that they have no intention of EVER fixing this problem, I’ll just do rm -r -f and be happy. And what’s more, so will the rest of the NetBeans community, because they won’t need to listen to me whining about it ๐Ÿ™‚

Bye Bye NetBeans.

#NetBeans #IDE #PHP #fail #SSH #remote #development

Increasing the phpMyAdmin session timeout

When phpMyAdmin is installed, the default session timeout value is too low for many users, making your phpMyAdmin session expire too soon. One could argue that a low session timeout value is a good idea from a security perspective. If you do not think this is an issue, here are a few simple steps that’ll let you change how long phpMyAdmin will keep your session(s) alive.

Open config.inc.php in the phpMyAdmin “root” directory. Look for a line that contains this: $cfg[‘LoginCookieValidity’]. Set the value to the desired number of seconds you want the session to stay alive (3600 = one hour, which is reasonable for most users). If you do not have that line in your config.inc.php file, add it like this:

$cfg[‘LoginCookieValidity’] = 3600;

Don’t forget to save the file, and then login again to phpMyAdmin. You may need to close the browser and re-open your phpMyAdmin URL.

This also assumes that the PHP session garbage collection is set-up accordingly. This can be done in a number of ways:

  • php.ini; add a line (or change an existing) that contains session.gc_maxlifetime = <seconds>
  • Apache configuration; add a line to the appropriate <Directory> block that says “php_admin_value session.gc_maxlifetime <seconds>”
  • config.inc.php (phpMyAdmin); after the previously edited line, add a line with “ini_set(‘session.gc_maxlifetime’, <seconds>);”

The <seconds> above is the same value that you set your variable to in config.inc.php at the beginning of this post, “3600” (sans quotes) in my case. (Some of these methods may or may not work on the server you’re using.)

This isn’t the only way to circumvent phpMyAdmin sessions expiring on you in the middle of that important work; you can, of course, configure phpMyAdmin to have appropriate access directly, thus allowing you to access your MySQL database(s) without entering a username and a password. You’ll find more information about this on the phpMyAdmin website.

(phpMyAdmin is, IMHO, one of the best tools ever written in its class. My only gripe is that I’d really like to have a much less bloated visual display theme as the default, but you can accomplish this yourself quite easily.)