Press "Enter" to skip to content

Tag: php

PHP SplFileInfo string values

Whilst PHP’s documentation of SplFileInfo isn’t “bad” as such, it can be tricky to remember what string functions (such as getBasename, getExtension, getFilename, getPath, getPathname, getRealPath and __toString) return under which circumstances. Hence this post!

To generate this data, we’re going to start off with a RecursiveDirectoryIterator with an optional callback filter (to enable us to later on, filter the returned values):

<?php 
$directoryIterator=new \RecursiveDirectoryIterator(
            '/var/task', // test directory
            \RecursiveDirectoryIterator::SKIP_DOTS // ignore "dot files"
        );
       
        $filterIterator = new \CallbackFilterIterator(
            new \RecursiveIteratorIterator($directoryIterator), 
            function (\SplFileInfo $file) {
           // add filter conditions here
            return true;
        });
        /** @var \SplFileInfo $fileInfo */
        foreach ($filterIterator as $fileInfo) {
            $objectNames= [
                'fileInfo',
                'directoryIterator',
                'filterIterator'
            ]; // which objects (defined above) are we interested in
          $methods = [
                'getBasename',
                'getExtension',
                'getFilename',
                'getPath',
                'getPathname',
                'getRealPath',
                '__toString'
            ]; // which methods of those objects do we want to get. 
           foreach ($objectNames as $objectName) {
               foreach ($methods as $method) {
                    print $objectName . '->' .
                        $method . ' = ' .
                        call_user_func([$$objectName, $method]) .
                        PHP_EOL;
               }
           }
           die(); // we only want the first one as an example
        }

Give the file /var/task/assets/fonts/montserrat-v14-latin-700.eot and the “start” directory of /var/task , we get the following:

  • fileInfo->getBasename = montserrat-v14-latin-700.eot
  • fileInfo->getExtension = eot
  • fileInfo->getFilename = montserrat-v14-latin-700.eot
  • fileInfo->getPath = /var/task/assets/fonts
  • fileInfo->getPathname = /var/task/assets/fonts/montserrat-v14-latin-700.eot
  • fileInfo->getRealPath = /var/task/assets/fonts/montserrat-v14-latin-700.eot
  • fileInfo->__toString = /var/task/assets/fonts/montserrat-v14-latin-700.eot
  • directoryIterator->getBasename = assets
  • directoryIterator->getExtension =
  • directoryIterator->getFilename = assets
  • directoryIterator->getPath = /var/task
  • directoryIterator->getPathname = /var/task/assets
  • directoryIterator->getRealPath = /var/task/assets
  • directoryIterator->__toString = assets
  • filterIterator->getBasename = montserrat-v14-latin-700.eot
  • filterIterator->getExtension = eot
  • filterIterator->getFilename = montserrat-v14-latin-700.eot
  • filterIterator->getPath = /var/task/assets/fonts
  • filterIterator->getPathname = /var/task/assets/fonts/montserrat-v14-latin-700.eot
  • filterIterator->getRealPath = /var/task/assets/fonts/montserrat-v14-latin-700.eot
  • filterIterator->__toString = montserrat-v14-latin-700.eot

Hope it’s useful to someone!

[Techy] Getting cURL to work with Let’s Encrypt: unable to get local issuer certificate error

On my test Debian jessie 8.2 and a staging server Ubuntu trusty 14.04, I had problems being able to use cURL to fetch data from a remote HTTPs site which was secured using a free Let’s Encrypt certificate (this problem manifested itself via both PHP 7 cURL functions and curl directly).

An example of the error is:

curl --verbose https://helloworld.letsencrypt.org/
...
curl: (60) SSL certificate problem: unable to get local issuer certificate
More details here: http://curl.haxx.se/docs/sslcerts.html

To fix this, I found the following steps worked:
sudo apt-get install --reinstall ca-certificates
to ensure you have the latest certificates by your distribution – this might help you, but it didn’t assist me 🙁

So I downloaded the Let’s Encrypt root certificates and forced a rebuild of the certificate store:

sudo curl https://letsencrypt.org/certs/isrgrootx1.pem.txt -o /usr/local/share/ca-certificates/isrgrootx1.crt
sudo curl https://letsencrypt.org/certs/letsencryptauthorityx1.pem.txt -o /usr/local/share/ca-certificates/letsencryptauthorityx1.crt
sudo curl https://letsencrypt.org/certs/letsencryptauthorityx2.pem.txt -o /usr/local/share/ca-certificates/letsencryptauthorityx2.crt
sudo curl https://letsencrypt.org/certs/lets-encrypt-x1-cross-signed.pem.txt -o /usr/local/share/ca-certificates/letsencryptx1.crt
sudo curl https://letsencrypt.org/certs/lets-encrypt-x2-cross-signed.pem.txt -o /usr/local/share/ca-certificates/letsencryptx2.crt
sudo curl https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem.txt -o /usr/local/share/ca-certificates/letsencryptx3.crt
sudo curl https://letsencrypt.org/certs/lets-encrypt-x4-cross-signed.pem.txt -o /usr/local/share/ca-certificates/letsencryptx4.crt
sudo dpkg-reconfigure ca-certificates

and everything worked!

If you are running Java, you may need to also add the certificates to the Java Keytool:
keytool -trustcacerts -keystore $JAVA_HOME/jre/lib/security/cacerts -storepass changeit -noprompt -importcert -file /usr/local/share/ca-certificates/isrgrootx1.crt
keytool -trustcacerts -keystore $JAVA_HOME/jre/lib/security/cacerts -storepass changeit -noprompt -importcert -file /usr/local/share/ca-certificates/letsencryptauthorityx1.crt

(change the storepass password [default of “changeme”] to whatever is relevant to you)

Jobs ahoy!

I know of quite a few companies currently recruiting – so if you are job hunting and think any of the following are of interest to you, please get in contact:

Leicester based
Senior Magento Developer
Senior Digital Designer
WordPress Developer
Account Manager

London based
Account Manager
Big Data Engineer
DevOps Engineer / Big Data SysAdmin
Machine Learning Specialist
Partnership Development Manager?

Guidford based
Sales Executive
DevOps Engineer
Python Software Developer
Systems Administrator

Brighton based
Java Developer
Head of User Experience and Design (UI / UX)
Senior Designer/UI Developer
Accountant
Senior Accountant
Trainee Account Manager (Finance Industry)
Outbound Sales Advisor

UK (contract/remote work)
WordPress Developer (up to £30/per hour)
Senior WordPress Developer (up to £45/per hour)
Symfony Developer

Techy/Old posts: What is FTP?

This post was originally published, commercially, in “Archive Magazine” Volume 13/Issue 9 (June 2000) pages 45-47.

This article was written for publication by Archive Magazine in response to a request by the editor for an article covering FTP.

What Is FTP?
Richard Chiswell

A few years ago (around the time of the BBC Micros), the easiest and simplest way to transfer files from one computer to another was via ‘sneaker net’ – the (American) term given to the method of copying files to a floppy disc (or even tape) and taking it to another machine. Nowadays this isn’t so simple, as many people (such as myself) keep files on many machines many miles apart. For example, my website is hosted on a machine in London while I’m based in Leicester. I’m certainly not going to sit on a train for a few hours just to be able to make a few small changes to my website.

Hence, in June 1971 (very, very old by internet standards – think around 100 years in real life times), FTP was designed and implemented. FTP is an abbreviation for ‘File Transfer Protocol’ and, as its name suggests, it is a method of transferring files – allowing you to easily and simply upload and download files from remote machines. For the complete technical specification on how it all works, see RFC 172 and RFC 959 (Request for Comments). The details contained in the RFCs are quite complex and you will only really need to read them if you are designing an FTP client or want to get in-depth information about it all.

What’s This To Do With RISC OS?

Well, many people (including myself) maintain websites using our RISC OS machines – after all, it is our ‘platform of choice’ and I find development easier under RISC OS than on other platforms (for example, Zap’s colour coding for Perl and HTML beats any PC software that I know of).

First of all, you need a working internet stack. An internet stack is the program that actually dials up your internet service provider (ISP) and connects you to the internet. The most common internet stacks on RISC OS are the ANT Internet Suite, Acornet or the Argonet Voyager suite. So if you haven’t installed any of those then go get a copy and install it now – you need to be able to connect to the internet for this article to be at all useful for you. The very old Doggysoft Termite internet stack didn’t conform to the ‘Acorn’ standard and very few third-party programs will work with it; as it isn’t being actively supported or developed any more, you may as well upgrade now.

Next, you’ll be needing what is called an ‘FTP client’. These allow you to upload and download files using FTP. Yes, I know Fresco, ArcWeb, Browse et al support FTP downloads, but you need an FTP client to be able to upload files. Personally, I find ANT’s !FTP and Colin Granville’s FTPc the best FTP clients for my use. Why two? Well, FTPc supports ‘recursive files’ (I can just drag a directory to it and it will upload all the contents of the directory and subdirectories), whereas !FTP allows me to see ‘hidden files’ on my Posix machines (i.e. .htaccess etc).

What Is Posix?

As this term crops up quite a few times in this article, I thought I might as well tell you what it means. Posix is the now accepted term for Unix, Linux, NetBSD, RiscBSD type computer systems – the term used to be ‘Unix-clone’ but AT&T, who own the trademark on the Unix name have previously raised objections, so the terminology has changed to ‘Posix’ or ‘Posix-clone’.

Most of the internet services you access use Posix themselves. If you dial up to connect to the internet, your ISP’s servers probably use Posix to hold the log-on details. If you browse a website, it is most likely to be hosted on a Posix machine (either that or Microsoft Windows NT), if you send email it will pass through Posix machines. Internet systems which don’t actually run Posix (such as Microsoft Windows and, of course, RISC OS) have to try and ‘pretend’ to be Posix because of the standard that has evolved. This means that filenames should be case-sensitive and of any length, that directories are separated by a / instead of the RISC OS ‘.’ and file extensions (such as .txt and .html) are optional and of any length. Most of the time, you won’t have to worry about the differences as the internet programs you use will make the conversion themselves, but it is a ‘good thing to know’.

Posix is also aware of things like ‘user groups’, ‘user permissions’, ‘hidden files’ (these normally start with a dot as in the ‘common’ files: .htpasswd, .htaccess and .sig) and symbolic links (where a file or directory can appear to be in two places at once, but only one copy actually exists).

About FTP Sites

You may notice that FTP sites follow the ‘Posix directory format’ – files are in the format directory/file.extension instead of the RISC OS format directory.file/extension – but again don’t worry as your FTP client should convert the files to RISC OS format automatically. Also, file extensions are completely optional on FTP sites, as they are on RISC OS, but you will probably find that most files have extensions for the benefit of PC users.

FTP files can be transferred in two formats – ASCII and binary. Most (if not all) FTP clients nowadays have an ‘auto’ setting that will sort this out for you, so you will probably never have to worry about it. The main difference is that you cannot transfer programs and data as ASCII text as it may contain ‘top- bit’ characters which may not transfer correctly, so the ‘binary’ format transfers them slightly differently. Likewise, if you transfer ASCII files (such as a text file) in binary, you may end up with garbage. So try to keep ‘auto’ selected.

What Are Top-Bit Characters?

The internet, for historical reasons, was mostly designed around the 7-bit character set, whereas modern computers normally use 8- bit characters. What’s the difference? Well, in a 7-bit system, you have a smaller selection of characters – the highest ASCII code is 127, which gives you all the letters (in both cases) and all the numbers and a few other characters, but that’s it. In an 8-bit system, the ASCII code limit goes up to 255 and this allows all sorts of exotic characters such as the £ pound sterling symbol, super-script characters such as 1, accented characters, the copyright © symbol and quite a few more.

The problem arises because program code (including archives, graphics and sound files) sometimes contain code which uses these exotic characters, so if you transfer them onto a 7-bit system and back off again, all the files are corrupted. When you transfer an FTP file in ‘binary’ mode, it encodes these files in a special format to get around this possible corruption problem, but in ASCII mode, it doesn’t bother.

The main thing to remember is to use ‘auto’ mode if you are offered it and, failing that, to use ASCII to transfer plain text (such as HTML and Zap/StrongEd/Edit text files) and binary for anything else (such as graphics, Ovation Pro documents, MP3s etc).

Anonymous FTP

If you are downloading from a publicly accessible site (which you most likely will be), you should use a method called ‘anonymous’ FTP. This is where you don’t have to log on to the remote server to access the files. However, owing to the way FTP works, you do need to send a ‘username’ and ‘password’. In anonymous FTP, the username is ‘anonymous’ and the password is normally your email address. Anonymous accounts usually have restrictions – this stops you from uploading files, or makes sure you upload them only to special places on the FTP server. Other limitations could include the number of files downloaded or which directories you can browse.

So, let’s try it. We’ll try accessing the RISC OS software stored on Demon Internet’s FTP server (you don’t need to be a customer of theirs to access these files – so don’t worry). Load your internet stack and FTP client and connect to the internet. Once connected, enter the following details into the FTP client (see the documentation for full details).

Host (or Server) ftp.demon.co.uk
Path (or Directory) /pub/acorn/
User anonymous
Password [your email address]
Account [Leave blank]

Then just click connect. Your FTP client will connect to the FTP site and log you in and give you access to the files. Try downloading a file or two from the site. Once you’ve finished, disconnect from the server.

Non-Anonymous FTP

If you are maintaining your own website, or uploading data for a third party, you may need to log in to an FTP site. From what I’ve already said about anonymous FTP, you may have an idea about how this is done. However, to illustrate in detail, let’s assume that somebody wants to upload their website to their free webspace on Demon Internet. This person’s log-in name is ‘example’ and their password is ‘pa55w0rd’ (a good mix of numbers and letters helps create a good password). Demon’s free webspace server is called homepages.demon.net. So let’s fire up an FTP client and enter the details:

Host (or Server) homepages.demon.net
Path (or Directory) [leave blank]
User example
Password pa55w0rd
Account [Leave blank]

And then you’ll be able to download the files from your website.

A better example of this is Demon’s ‘Batch-FTP’ facility, whereyou send commands to Demon in an email in the following format:

To ftp@demon.net
Subject [anything]
Body ftp.demon.co.uk:/pub/doc/Services.txt
quit

Demon will then fetch the file in question (which, in this example, is the file Services.txt in the directory pub/doc on ftp.demon.co.uk) and store it for you. To retrieve the files, you can connect as:

Host (or Server) ftp.demon.co.uk
Path (or Directory) [leave blank]
User example
Password pa55w0rd
Account [Leave blank]

This is extremely handy when transferring large files (such as the IMDB data) from an FTP site to a ‘closer site’ which will be quicker for you to fetch.

Uploading Data

Most RISC OS FTP clients now have a ‘filer-like’ interface which means they will look very similar to the normal RISC OS filer and operate in a very similar manner. So, to upload files, you just drag the file in question to the FTP client’s window. The file will then be uploaded to the FTP site.

One point to bear in mind is that ‘/’ is translated to ‘.’, so file filename/ext will be uploaded as filename.ext. Another point is that some web hosts (mainly commercial) expect you to upload your site into a directory called public_html or similar. If you don’t, your files will not be visible via your website. A final point is to make sure that the data is transferred in the correct format – transferring text files (such as HTML) in binary format is a waste of time and uploading binary files (such as graphics, archives and executables) in ASCII format is a bigger waste of time. Your FTP client should really be set to ‘auto’, and it will detect the filetype and change mode for you automatically.

Command Line Options

If your FTP client has an option to enter command line strings, you might find this little ‘RISC OS to FTP’ converter handy. If your FTP client doesn’t support this option (and not many do), you may be able to get your ‘telnet’ to issue these commands. Don’t worry if the RISC OS versions don’t look familiar – you probably have no need to use these options in FTP if you don’t use them in RISC OS.

RISC OS command FTP Command
*Rename mv
*Cat ls -al
*Dir cd
*Delete rm

What next?
Hopefully this article has managed to teach you some of the basics of FTP and how useful it can be. There’s plenty more detail available, from file permissions through to protecting your website, but there’s no point in me telling you things you don’t want to know, so do get in touch and let me know what you want to hear about.

New Relic, cPanel, Apache and FastCGI PHP

We tend to operate RedHat Enterprise/CentOS based cPanel web hosting accounts for ourselves and our customers and for security, they are configured running PHP under suPHP via CGI/FastCGI. However, for server monitoring, we wanted to be able to use NewRelic for monitoring the sites on an individual level but without the customers having to add newrelic.appname to each of their applications – and we didn’t want each site to have to have its own php.ini, and under suPHP PHP ignores any php_value settings in the Apache configuration. So what to do?

Install New Relic
Well, first of all install New Relic according to your server architecture, then run “newrelic-install” and select all. Now we move on to the cPanel specific setup.

Getting PHP to notice the NewRelic PHP Module
In WHM (:2087), select “PHP Configuration Editor” and then “Advanced mode”. Search for Core “extension” and change the list from something like:
/usr/lib/php/extensions/no-debug-non-zts-20090626/apc.so, pdo.so, pdo_sqlite.so, sqlite.so, pdo_mysql.so, timezonedb.so, uploadprogress.so
to:
/usr/lib/php/extensions/no-debug-non-zts-20090626/apc.so, pdo.so, pdo_sqlite.so, sqlite.so, pdo_mysql.so, timezonedb.so, uploadprogress.so, newrelic.so

Restart Apache (via either WHM or /scripts/restartsrv_apache on the command line) and check everything is still working.

Configuring the newrelic.appname settings – Apache
From from command line/shell, cd into /var/cpanel/templates/apache2_2 (or whichever version of Apache you are running) and copy vhost.default to vhost.local (cp vhost.default vhost.local) if there isn’t already a vhost.local file. Now open that file up in your favourite text editor (for simplicities sake, I’m using nano : nano -w /var/cpanel/templates/apache2_2/vhost.local).

Near the top of the file it will say something like:

<VirtualHost[% FOREACH ipblock IN vhost.ips %] [% ipblock.ip %]:[% ipblock.port %][% END %]>
ServerName [% wildcard_safe(vhost.servername) %]
[% IF vhost.serveralias_array.size -%]
[% FOREACH alias IN vhost.serveralias_array -%]
ServerAlias [% alias %]
[% END -%]

Add a suitable “SetEnv newrelic_appname” line. For example, I want all of the sites to be recorded against the main virtual host’s server name, so I would use:

<VirtualHost[% FOREACH ipblock IN vhost.ips %] [% ipblock.ip %]:[% ipblock.port %][% END %]>
ServerName [% wildcard_safe(vhost.servername) %]
SetEnv newrelic_appname [% wildcard_safe(vhost.servername) %]
[% IF vhost.serveralias_array.size -%]
[% FOREACH alias IN vhost.serveralias_array -%]
ServerAlias [% alias %]
[% END -%]

You could also use the user’s username SetEnv newrelic_appname [% % vhost.user %] if you wanted to.

Use the Distiller to check everything looks good:
/usr/local/cpanel/bin/apache_conf_distiller --update
and if it does, rebuild the Apache configuration:
/usr/local/cpanel/bin/build_apache_conf
and again restart Apache and test.

Now, there is an environment variable called “newrelic_appname” available for usage. But we’re not using it yet: so we move onto:

Configuring the newrelic.appname settings – PHP
Using a <?php phpinfo(); ?> script find where your php.ini file – ours was in /usr/local/lib/php.ini . Open it open in your text editor again (nano -w /usr/local/lib/php.ini) and search for the newrelic.appname setting which should appear (Press Ctrl+W and then type appname in nano). You should see something like:

; Setting: newrelic.appname
; Type : string
; Scope : per-directory
; Default: “PHP Application”
; Info : Sets the name of the application that metrics will be reported into.
; This can in fact be a list of up to 3 application names, each of
; which must be separated by a semi-colon. The first name in any such
; list is considered the ‘primary’ application name and must be unique
; for each account / license key.
;
;newrelic.appname = “PHP Application”

;
; Beginning with version 3.0 of the agent, the daemon can be automatically
; started by the agent. There is no need to start the daemon before starting

Remove the colon and the start of the line and change it to read from ${newrelic_appname} for example:

; for each account / license key.
;
newrelic.appname = “${newrelic_appname}”

;
; Beginning with version 3.0 of the agent, the daemon can be automatically

This will read in the newrelic_appname environment variable upon run and dynamically replace it in the PHP settings. Restart Apache again (just to be safe) and check a few sites are working. Within a couple of minutes, you should see the records appear in NewRelic.

All done! Have fun!