Skip to content →

Category archive for: Software

New WordPress plugin: URL Builder for Analytics

tl;dr: I’ve built a WordPress plugin for creating Google Analytics tracking URLs for your posts, straight in the post editor. Development of the plugin happens on the GitHub repository

Website Analytics in short

When doing website analytics, it can be really helpful to know which channels site visitors come from. If you use Google Analytics this can be specified easily, as a couple of GET parameters in the site URL. The main issue here is that remembering the names of the parameters can be bothersome, and writing them manually is error prone. That’s why Google supplies a URL builder tool, where you just fill out the fields and it’ll give you an URL with the tracking parameters.

URL builder for Analytics

Since I was doing a bunch of tracking URLs for WordPress posts, I decided it would be helpful to just to it all straight from the WordPress interface. I couldn’t find a proper plugin for it, so I decided to build my own, the URL builder for Analytics.

The plugin is pretty simple. It adds a meta box to the edit page of all post types. The meta box has 2 tabs, social sharing, and custom sharing.

Social Sharing

The Social Sharing tab
The Social Sharing tab

Most of my URL sharing happened on various social channels, so to streamline that I made the social sharing tab, heavily inspired by this linktagger tool (thanks to Søren Sprogøe for showing me that). Using the social sharing you just fill out your campaign name, and the plugin will give you links for various social media sites (Facebook, Twitter, Google+ and LinkedIn). The created links will have it’s source set to the social site’s name, and the medium will be “social”, this ensures consistency for all posts shared to social media.

Custom sharing

The Custom Sharing tabs
The Custom Sharing tabs

The other tab allows you to specify your own tracking values for all five of the parameters Google Analytics allows for it’s tracking URLs. The plugin will then give you a full tracking URL ready to cut and paste into your newsletter, or where you’d want to use it.

Development and Next step

The development of the plugin is done on a GitHub repository, which also hosts the current issues and feature requests queue.

The next thing I’d like to add is support. This would include doing OAuth authentication with the service, allowing the use of the URL shortening service, to shorten the URLs and saving them to your account.

The plugin can be downloaded from the WordPress repository, and bug reports and feature requests are very welcome both in the issues queue, or in the comments below.

Leave a Comment

PHP 7 – What’s up, and what’s new?

Update nov. 9 – Looks like the PHP 7 release date has been postponed due to some outstanding bugs and regressions. It should still be right around the corner, though.

PHP 7 overview

The next major version of PHP, PHP 7, should be right around the corner, with a planned release date on November 12th, according to the current release timetable. PHP 7 will include of a lot of performance improvements, and a range of new features. In thi of post I’ll try to go through the major new stuff.

But, what about PHP 6?

You probably know that the current version is PHP 5.6, and if the next version is PHP 7, obviously PHP 6 was skipped. I won’t go into details with this choice since I’d rather just forget about it.

But in short, first politics happened, then bullshit happened, and then finally they had a vote and moved on.


Since PHP 7 is a major version release, backwards compatibility breaks are allowed. BC breaks are never nice, so the dev team is trying to keep them at a minimum, but some BC breaks should be expected.

Deprecation of PHP 4 style constructors

PHP 4 introduced object oriented programming to PHP. Back in those days an object constructor was a method named like the class you wanted to create an object from.

class MyObject {
  protected $param;

  // Object constructor.
  function MyObject($param) {
    $this->param = $param;

In PHP 5 the class name constructor was replaced with the new magic method __construct() as the recommended way to create objects.

class MyObject {
  protected $param;

  // Object constructor.
  function __construct($param) {
    $this->param = $param;

PHP 4 style constructors is still available in PHP 5, unless you’re using namespaces, in which case they are ignored and only the PHP 5 style constructors are available. This inconsistency can cause some confusion, and this is the main reason that the PHP 4 style constructors will be marked as deprecated in PHP 7 and removed in the following PHP 8. This means that in PHP 7 a class with a PHP 4 style constructor, but no PHP 5 style constructor will cause PHP to emit an E_DEPRECATED error.

Removal of SAPIs and extensions

PHP 7 also removes a bunch of SAPIs (Server APIs – PHP interfaces for module developers to extend the webserver) and extensions. I’ll skip on the SAPIs as I doubt that change will affect me.

Two modules have been removed. The ext/ereg regex module which has been deprecated since PHP 5.3, and the ext/mysql extension, which has been deprecated since PHP 5.5. If you are using the ereg functionality, it is recommended that you switch to using pcre, and if you are still using the mysql functions, you should switch over to using either MySQLi or PDO, more info for choosing which of the two to use can be found in the manual.

Removal of other functionality

Besides the removed SAPIs and extensions, a bunch of other functionality will be removed, most notably probably being some mcrypt, iconv and mbstring functionality. For a full list, refer to the rfc.

PHP 7 Performance

Internally the Zend Engine has been completely refactored and rebuilt, a project known as PHPNG (next generation). This rewrite allows for a lot of improvements, most of which go way over my head (I’m a web developer, not a language developer), but you can find a lot of details on the wiki.

Some of the notable improvements includes improved hash tables and improvements to the internal representation of values and objects, which Nikita Popov has written some interesting articles about: part 1 and part 2.

For PHP developers, the most notable improvements will probably be the drastically improved performance, that Rasmus Lerdorf has been talking about.

Engine Exceptions

Until now when something went really wrong in a PHP script, it would cause either an error, or an exception. An error was an internal PHP things that would either kill the script, or at least output an error message, either to the user, but hopefully just to a log file, depending on your setup. An exception was a part of the script, it would stop the execution and bubble up through the call stack until it hit something designed to catch it, or kill the script if nothing would catch it.

An exception would change the script’s execution flow, but could be mitigated in a properly designed application, while errors were a bit harder to handle on runtime.
In PHP 7 the Exception hierarchy has been extended, and the error types that would previously stop the entire script execution, will be catchable, so the developer is able to handle the errors more gracefully.
To keep backwards compatibility all exceptions still extend the Exception class, while the errors will extend a new Error class. To ensure both errors and exceptions can be handled together they will both implement a new Throwable interface, making it possible to make catch-all solutions.
You can learn more about the new engine exceptions in this rfc, and about the new Throwable interface in this rfc.

Scalar type hints

PHP 5 introduced type hinting, the notion of allowing methods to expect it’s parameters to be of a certain type, and throw a recoverable fatal error if the input didn’t match the type hint. This was possible for objects and arrays.
In PHP 7 it is also possible to type hint scalar types, ie. integers, floats, booleans and strings. If an input parameter doesn’t match the hinted type, the default behaviour will be to convert the value to the type hinted type, but it’s possible to turn on strict mode, in this case a TypeError Exception will be thrown if an input parameter has the wrong value. Strict mode will have to be set for each file where it should be activated.
I’m really looking forward to this change, and will probably be writing a lot of strict files. I’ll probably get more into this in a later post.

Return type hints

Another new thing that I think will be really awesome is return type hints. In the same way that methods can define which parameter types it expects as input, it will also be able to make a promise of which data type it will return. Declared return types will be included in PHP 7, but an rfc extending the concept by adding void return types is currently being voted on.
Another cool extensions would be nullable types, the rfc is currently only a draft, but I’m hoping to see this for PHP 7.1.
Return types is another thing I’m really looking forward to, and will probably write more about later.

Null coalesce

Null coalesce is a variant of the ternary operators, aka shorthand ifs. The new ternary operator ?? will also check if a value is null.

$category = $_GET['category'] ?? 'cakes';

In human terms this means, $category should get the value of $_GET[‘category’] if it is set, otherwise, it should be ‘cakes’.
This could, of course, also be done using the existing ternary operator

$category = isset($_GET['category']) ? $_GET['category'] : 'cakes';

This is not a revolutionary addition, but rather some nice syntactic sugar.

Anonymous classes

PHP 5.3 introduced anonymous functions, which is unnamed functions defined during runtime. In PHP 7 the concept is expanded with anonymous classes. I believe their main purpose is for single use objects where stdClass might not be enough, but I’ll have to work with it for real before I’ll figure out their real purpose.

Group use

PHP 5.3 also introduced namespaces, logical separation of classes into groups.
To use classes from other namespaces you can either use their fully qualified name:

namespace Foo;

class Bar
  protected $baz;

  public function __construct()
     $this->baz = new \Xyz\Baz();

or use the required class from it’s namespace

namespace Foo;

use Xyz\Baz;

class Bar
  protected $baz;

  public function __construct()
    $this->baz = new Baz();

PHP 7 introduces grouped use declarations, so it’s possible to include multiple classes from a namespace in a single use statement. This is done by stuffing the class names in curly braces. It’s still possible to name individual includes

use Name\Space\{Foo as Xyz, Bar}

I’ll let you decide whether this is nice syntactical sugar, or another way to build an unreadable mess, since I havn’t fully decided yet.

Uniform variable syntax

The uniform variable syntax tries to make variable syntax more consistent. I don’t have a full overview over all of the changes yet, but the RFC contains a lot of examples. This is a pretty important change to be aware of, since it might actually change the behaviour of, or just break, some of your running code since it changes how a lot of expressions are evaluated.


PHP has always had functionality to generate pseudo-random data, the standard functionality just havn’t been cryptographically secure (aka. random enough). PHP 7 introduces some new functionality for creating data that is even more random.

Further reading about PHP 7

In this post I’ve introduced a bunch of the major changes in PHP 7 that I believe will be the most impactful to m daily life as a developer. There is a lot of more stuff being added and removed, and a full list is available here.

Do you have any change that you look forward to more than the rest of PHP 7? Or do you see anything coming up in one of the following versions that makes everything even cooler? Leave your answer in a comment.

Leave a Comment

Code reviews


I’ve recently taken part in introducing code reviews at my current workplace, so I’d like to spend some time here to tell a bit about why I believe code reviews is a good thing, what I believe code reviews can do for the code and for the development team, how we’re currently doing code reviews and what a I believe a good code reviewer is looking for.

The aim of this post is not to be a checklist of how or what to do at code reviews, but rather to provide a broader perspective on some of the benefits of code reviews, and some broader points about what to look for.

Purpose of the code reviews

At first some people might get the feeling that they are being supervised, or that they aren’t trusted. The point of code reviews isn’t to point out how bad a developer you are, or to point out your flaws, it actually has very little to do with you as a person at all. A code review has two main purposes:

  1. To improve the overall quality of the software
  2. To improve the overall quality of the developers

The first point should be obvious. Better code means less bugs, which means less maintenance. This translates directly into better value for the customer, and more time for us as developers to build new exciting things, instead of maintaining old boring things.

The second point has two sides to it. First, there is a lot to learn from reading other people’s code. They might do stuff in a way that you never thought about, using libraries you didn’t know about. Even on the off chance that you have to do reviews for somebody you could never learn anything from at all, there is still a lot to be learned from condensing your current knowledge into useful actionable feedback.

Before a code review

It is important to prioritise code reviews, as having code reviews lying around waiting for reviews will both be a showstopper for the developer, and hold back the project. At the same time a code review will require you to disturb one of your colleagues, so please respect your colleagues’ time; this means that you should prepare properly as to take as little of your colleague’s time as possible away from his own project.

Be sure to read through your pull request again and make sure it is actually ready for review. Make sure everything is documented as expected, and that any debugging info is removed, so your colleague doesn’t have to waste time rejecting your pull request because of something obvious like that.

Small pull requests are easier to grasp and review, so be sure to only include things that actually needs review in your pull request.

What needs to be reviewed

What needs to be reviewed is up to your organisation and project; the rule at our office is that if you wrote it, it needs to be reviewed. This might seem strict, but it saves everybody the trouble of thinking “is this actually a large enough change to require a code review?” since the answer is always yes. This saves us the trouble of having small bugs go into production because “it was just a minor change”.

Exception: hotfixes

If a critical bug has been found which requires an immediate hotfix, we obviously won’t be able to wait for a code review. In this case the hotfix will be made and deployed to solve the issue, the hotfix will then be code reviewed afterwards and fixed to live up to normal coding standards. This can be done in a more calm and considered fashion since the immediate problem has been fixed.

What doesn’t need to be reviewed

Since the rule is “if you wrote it, it needs a review” it goes that if you didn’t write it, it doesn’t need a review.
We do a lot of sites in Drupal which makes it possible to deploy settings and configurations using a module called features. Features creates a PHP version of your configuration, since this is auto-generated we do not bother code reviewing this.

The same goes for community contributed code, like Composer packages Drupal modules since these are expected to be tested and vetted elsewhere and it is expected that the developer uses his critical sense before including these in a project.

The review

A code review is very similar to any other kind of text review, and should happen on 4 different levels using a top-down approach starting with the architectural thoughts and ending with the actual lines of code.

  • Architectural level: A code review should start at the architectural level, which is the bird’s eye view of the code. Does the structure make sense? Is the code modular? Testable? Performant? Maintainable? Does the chosen design patterns make sense for the problem at hand? Could the code be made more modular or maintainable by using more abstractions? Fewer abstractions? Are the concerns properly separated?
  • Functional level: Jumping down a level we look at the individual functions. Does every function serve one, and only one, clear purpose? Is it obvious what that purpose is from the function name? Is the documentation descriptive? Do functions duplicate functionality from each other, or from built-in functions? Is the function itself readable and understandable?
  • Line level: Does every line have a clear purpose? Are the lines compressed enough to allow you to keep an overview of the methods? Are they compressed to the point of unreadability? Are inline comments included? Are they necessary, or should they be replaced by properly named methods/functions/variables?
  • Word level: At the lowest level we’re looking at the words. Naming is known to be one of the hardest disciplines in computer science, so make sure the names makes sense now, and in 6 months when you come back to maintain the code. Does method names clearly describe what a method does, what it needs and what it’s output should be? Does variables and properties tell you what might be in them?

Post code reviews

After the code review, the pull request is sent back to the developer to fix any issues and it will likely go back and forth a few times with the developer asking questions, fixing issues and questioning feedback.

It’s important to note that the reviewer’s word isn’t set in stone, but should be considered feedback and suggestions. Everything is up for discussion, especially because there is no one right way to structure code. Again, the entire point of code reviews is to improve the quality and maintainability of the software, and learning from each others. Different developers have different strengths and skills, and bringing these together will both improve the software, the people developing it and the team.

Further reading

  • Kevin London Code review best practices – A more in-depth view of the actual code review, and suggestions on what to look for.
  • Smartbear 11 best practices for peer code review – Real life experiences condensed into a set of best practices. Many of them can be directly put into use, like the max size of a code review and how to articulate feedback.
Leave a Comment


What is Composer

Composer is a dependency manager for PHP. It makes it easy to include 3rd party libraries in your PHP project. It’s inspired by npm and aims to bring some of the same ideas to PHP will fixing some of the deficiencies.

But, what about PEAR

It is true. We have had dependency management using PEAR for quite a while. Composer brings some advantages and modernizations to the table:


  • Requires libraries to follow a specific structure.
  • Installs libraries globally, not per project. Requires all libraries to be installed globally on all servers. Causes trouble with different versions of a library on servers running multiple services.


  • De-facto standard (everybody does it).
  • Install per-project, or globally, depending on library and needs.
  • Better version handling when following semver. Automatically handling of allowed versions.
  • Lazy-loading autoloader.
  • Even handles pear packages if required.

Installing Composer

Installing composer is easy, go to for the latest release.
Just download and run the installer:

curl -sS | php

And the move the created composer.phar file to a bin dir, or any directory in your $PATH.

Composer basics

Using composer in your project only requires 2 files: composer.json and composer.lock.
composer.json is a json formatted file which describes your project. It contains stuff like your project’s dependencies, and how to load your own files, and examples:

    "require": {
        "monolog/monolog": "1.12.0"
    "autoload": {
        "psr-4": {
            "app\\": "src/"

This file tells composer 2 things; first is that the project is dependent on the project called monolog/monolog, in the specific version 1.12.0, second that everything in the app namespace should be loaded from the src directory, using a psr-4 autoloader.

To install your dependencies run
composer.phar install
This will make composer look up the package monolog/monolog in it’s default repository, packagist, and try to install the required version. It will then install any requirements the monolog/monolog package might have, as well as any requirements of the required packages etc. it then sets up the required autoloaders making the use of the installed libraries a charm. The last thing it does is to create a composer.lock file, which lists all the installed packages, along with the exact version that has been installed.

Now including your required packages is as easy as including composers autoloader:


require __DIR__ . '/vendor/autoload.php';
// Your project goes here

Composer best practices

JSON builds upon a very strict syntax, and editing it by hand is error prone, and not recommended. That’s where the composer cli tool saves the day.

Instead of installing new packages by adding them to the composer.json manually, it is recommended to install them using:
composer.phar require {vendor/package[:version]}
The version number is optional, if it isn’t specified composer will find the newest version of the library and create a dependency on that version. Unless you require a specific version of a library, omitting the version number is the recommended practice. Ie. to install the newest version of monolog/monolog, run:
composer.phar require monolog/monolog
At the time of writing, the newest version of monolog/monolog is version 1.16.0, so the above will add the require clause:

"require": {
    "monolog/monolog": "~1.16"

When checking versions, ~1.16 is equivalent to “>=1.16,<2.0.0", but more on specifying versions later.

Daily usage

Daily usage of composer mainly consists of 3 commands; composer require as explained above, composer install and composer update.

composer install

Composer install is the most used of the two.
The command first checks if a composer.lock file exists, if it does, it will install all of the exact versions specified in the .lock, if no .lock file exists, it will install the newest versions of the libraries allowed by the package requirements. It will then create it’s required autoloaders. If the composer.lock file did not exist, it is then created, or if new packages has been added that wasn’t in the previous .lock file, it will be updated.

composer update

Composer update basically does the same as composer install, except that it will ignore any existsing composer.lock file, and just install the newest allowed version. It then creates autoloaders and writes a new composer.lock file.

Bulk-updating all of a projects dependencies is bound to cause a world of pain, so it’s recommended to update one dependency at a time, and then running your test suite, to make sure nothing breaks in the update process.

composer update vendor/package

Version control

composer.lock specifies the exact installed versions of all dependencies. This file should be commited to versioning system to make deployment faster and to guarantee that tested versions are installed. The vendor dir is where the actual dependecies are kept. This is a bunch of code that is already hosted on version control systems somewhere else, and should not be included in your version control system.
When deploying your project, running composer install will install the required version the project has been tested with, using the composer.lock file.


Composer allows for a bunch of different ways to specify the allowed versions of each package, by specifying ranges, wildcards etc.

Most of the specifiers are built to support projects using SemVer as a promise of predictability in version numbers, so if you are a library maintainer and not using semver, please do, to make it easier for people to use your library.


>, <, >=, <=, !=, ||, ,, (comma and space, logical AND)


I.e. “2.3.*” == “>=2.3.0 <2.4”


Recommended usage! (For libraries following semver).
Specifies a min. version, and allows updates to next minor/major version, depending on specificity.
I.e. “~3.6” == “>=3.6 <4.0”, “~3.6.0” == “>=3.6.0 <3.7.0”

Advanced usage

So far I’ve went through the basic usage of composer, but it actually does quite a lot. In this last section I’ll do a quick run-through of some nice to know features, but I won’t be going through everything that is possible with the program.

Neat cli options

–verbose – Prints more information when running commands.
–profile – Provides profiling information.
–dry-run – Pretend to do install/update, but don’t actually touch any files. Useful for getting an idea of what has been changed.

Composer repositories

By default composer installs from packagist, but it is possible to install from other sources like github, SitePoint has a nice tutorial on that.

Cli commands

composer.phar show -i – Show all installed libraries and their version.

composer.phar create-project namespace/project
Clones the specified project and runs composer install in the install directory.

If in doubt: composer help

Further study

Some other nice features that I might touch upon in future blog posts includes:

  • Creating your own composer-ready packages
  • Scripts – allows running scripts during various parts of the installation process


Some nice references to know about
The Composer Homepage
Official documentation
Interactive composer cheat-sheet
Composer on

Leave a Comment

WordPress-sikkerhed og brute force angreb

Der er i øjeblikket mange der taler om et botnet der på nuværende tidspunkt skulle være i gang med at brute force sig adgang til WordPress sites overalt. Der skulle efter sigende være tale om et angreb fra op til 90.000 forskellige kilder.

Om et sådan angreb er i gang eller ej skal jeg ikke kunne sige, men det har tilsyneladende fået rigtig mange WordPressbrugere til at genoverveje deres nuværende sikkerhedsniveau, så noget positivt er der da kommet ud af det lige meget hvad.

Jeg ser mange der diskuterer problemet og mulige løsninger, hvilket igen er positivt, men der er mange der ikke har helt styr på hvad der er godt og skidt, og evt. hvorfor, så jeg vil her prøve at give mit bud på nogle overvejelser man bør gøre sig inden man hovedløst kaster sig ud i installation af tilfældige sikkerhedsplugins.

En række supportere på det officielle WordPress support forum har sammen lavet en side på WordPress codex med tips og tricks til at sikre sig mod angrebet, så hvis du vil have den korte version på engelsk kan den findes her. Jeg vil gå lidt mere i dybden og forsøge at forklare det hele på dansk.

Hvad sker der egentlig?

For god ordens skyld vil jeg lige starte med at forklare det egentlige problem, så vi allesammen snakker om de samme ting, og for at give en idé om de overvejelser man bør gøre sig.

Botnets? What?

Det omtalte angreb stammer fra et stort botnet. Et botnet er et antal computere der, for det meste uden at ejeren ved det, bliver brugt af tredjepart til andre formål end hvad ejeren af computeren havde til hensigt.

I dette tilfælde handler det efter sigende om at bagmændende bag botnettet prøver at tiltvinge sig kontrol over flere computere, for på den måde at udvide deres botnet. De gør det ved at “brute force” sig administratoradgang til maskiner der kører websites bygget på WordPressplatformen. Hvis det lykkedes dem at få adgang til et WordPress-site gør de så dette site til en del af deres botnet, og på den måde vil angrebet vokse hver gang det lykkedes dem at overtage et WordPress-site.

Hvad så med det “brute forcing”?

Brute forcing handler om at tiltvinge sig adgang ved “brute force”, altså rå magt. Det foregår ved de simpelthen prøver at logge ind som adminbrugeren, ved at prøve mere eller mere tilfældige passwords, i teorien kan man jo gætte alle passwords hvis man har uendelige forsøg og god tålmodighed. Da der er tale om et automatisk angreb er det ikke noget der koster bagmændende noget tid, og de har derfor rigeligt med tålmodighed.

Men hvad kan jeg gøre ved det?

For det første skal du tage dine normale forholdsregler. Sørg ALTID for at holde WordPress fuldt opdateret. Det samme gælder alle installerede plugins og temaer. Dette er ikke specielt for det nuværende angreb, men alt software er usikkert på den ene eller anden måde. Folkene bag WordPress arbejder hårdt for at lukke alle sikkerhedshuller der bliver fundet så hurtigt så muligt, så sørg for altid at være opdateret. Sørg desuden for at slå alle plugins fra du ikke bruger. Som nævnt er intet software 100% sikkert, så en tommelfingerregel er at jo mindre software du har jo bedre.

Mht. det nuværende angreb er der selvfølgelig nogle ekstra ting du kan gøre.

Tag backup af alt!

En backup sikrer dig selvfølgelig ikke imod angreb udefra. Men hvis du skulle være uheldig enten at blive offer for angrebet, eller at få ødelagt dit site i et forsøg på at sikre det er det altså noget rarere at have end up-to-date backup, end at skulle starte helt forfra. Sørg altså for at tage backup af både selvesitet (via. FTP) og databasen (f.eks. via phpmyadmin), gerne lige nu, inden du forsøger at øge din sikkerhed.

Selve backupprocessen er afhængig af hvor du har dit website liggende, så der kan jeg ikke være så behjælpelig, men der findes som sædvanlig en række forslag på WordPress Codex.

Skift navnet på din adminbruger

Det igangværende angreb udnytter tilsyneladende at WordPress i gamle dage automatisk oprettede en administratorbruger med brugernavnet. Fra version 3.0 og frem har det været muligt selv at bestemme dette brugernavn, men det er ikke alle der har ændret det. En ændring af dette brugernavn vil gøre det sværere at brute force sig adgang til dit site, da angriberne så både skal finde brugernavn og password, i stedet for kun password.

Hvis du har en administratorbruger med brugernavnet admin kan det ændres forholdsvist enkelt med et plugin, eller ved et par manuelle skridt:

  1. Login som din administratorbruger
  2. I adminpanelet gå til “Brugere” -> “Tilføj ny”
  3. Opret en ny bruger, sæt brugerens rolle til administrator (med et ordentlig password!)
  4. Log ud.
  5. Log ind med din nyoprettede administratorbruger.
  6. I adminpanelet gå til “Brugere” -> “Alle brugere”.
  7. Hold musen hen over admin-brugeren, og tryk på det “slet”-link der kommer frem.

Hvis du oplever at du ikke kan slette admin-brugeren så dobbeltcheck lige at du har logget ind med din nyoprettede bruger, og ikke stadig er logget ind som adminbrugere (ja, vi kan alle lave trykfejl :-)).

Brug ordentlige passwords

Dette er vel nok det vigtigste punkt på listen, og desværre nok også det mest besværlige at gøre ordentligt. Sørg altid for at bruge ordentlige passwords der ikke er lige til at gætte. Som sagt foregår det nuværende angreb som et brute force angreb, hvor de prøver sig at gætte sig til dit password, dette vil normalt foregå på en af to måder.

Enten kan man prøve fra en ende af, med “a” som password, derefter “b”, når alle muligheder er opbrugt prøver man så med to bogstaver, “aa”. Dette kan selvsagt tage lang tid, men hvis dit password f.eks. er “asdf” tager det altså ikke lang tid.

En anden metode er at tage udgangspunkt i en ordbog. I stedet for at prøve alle kombinationer af tal og bogstaver nøjes man med ord fra en prædefineret liste af ord. Disse liste vil ofte også indeholde ofte brugte afarter af ord, hvor f.eks bogstaver er udskiftet med tal. Dette betyder at hverken “password” eller “p4ssw0rd” er særlig gode passwords.

Der er skrevet rigtig, rigtig, rigtig, meget om hvordan man gør sine passwords sikre. WordPress Codex nævner også nogle gode forholdsregler man kan forholde sig til. Der henvises desuden til nogle services der kan hjælpe med at generere og huske gode passwords. De væsentligste ting må være:

  • Lad være med at bruge personlige oplysninger, såsom dit navn, din fødselsdag eller lignende offentlige oplysninger.
  • Lad være med at bruge ord fra ordbogen.
  • Længere passwords er generelt bedre passwords.
  • Brug en blanding af store og små bogstaver, tal og tegn

Men husk altid på de ovenstående metoder der bruges til at gætte passwords. 5up3rM4nRul3z43v3r (superman rules forever) er altså ikke nødvendigvis et godt password, da det stadig er en sammensætning af ord der garanteret vil stå i enhver password breaking ordbog.
Gode passwords vil oftest (altid?) være svære at huske. En metode til at gøre det lettere er at bruge en passwordmanager, et program eller en service til at huske dine passwords for dig. Jeg bruger selv LastPass som gør at jeg har et meget stærkt password som jeg skal huske. Dette masterpassword giver så adgang til alle mine passwords til diverse websites. Det betyder at jeg kan bruge services til at generere tilfældige passwords (eller, ihvertfald tilfældige nok), uden selv at skulle huske alle disse passwords, eller nedskrive dem på papirer som jeg kan smide væk.

Bloker adgang til din loginside

Da det igangværende angreb forsøger at få adgang administratorinterfacet på WordPress sites via den normale loginmetode, er en mulighed for øget beskyttelse at begrænse adgangen til adminpanelet. De to mest brugte metoder til dette er:

  • Password-beskyt adminpanelet
  • Bloker adgang til filen på IP-niveau

Fælles for de to metoder er at de kan fungere på et af to niveauer. Det kan enten gøres via. WordPress selv, eller det kan gøres direkte på serverniveau. Om man bruger den ene eller anden metode kan umiddelbart virke ligegyldigt, men jeg vil gerne lige understrege hvorfor det gør en forskel.

WordPress er skrevet i PHP, som bl.a. bruges til at skabe dynamiske hjemmesider. Det betyder at hver gang sikkerheden bliver håndteret i WordPress skal serveren have hele WordPress i gang med at arbejde for først at finde ud af om en bruger skal have adgang til en ressource. Samme sikkerhed kan ofte klares på serverniveau, hvilket betyder meget mindre arbejde for serveren, da en evt. angriber vil blive forment adgang allerede inden WordPress bliver sat i gang.

Password-beskyt adminpanelet

Passwordbeskyttelse kan som nævnt foregå både på server- og på WordPressniveau. Passwordbeskyttelse på WordPressniveau foregår via. WordPress eget loginsystem, det er en beskyttelse vi snakkede om tidligere med ændring af adminbrugernavn, og brug af gode passwords.

Passwordbeskyttelsen kan dog også flyttes ned på serverniveau med HTTP authentication. Dette vil resultere i at når du tilgår din WordPress loginside vil du først møde en popup hvor du skal skrive brugernavn og password, og derefter vil du møde den normale WordPress loginside. Dette er selvfølgelig en afvejning af sikkerhed vs. convenience da det kan virke lidt irriterende at skulle logge ind to gange. Hvis du vælger denne metode skal du selvfølgelig huske ikke at bruge samme brugernavn/passwordkombination til begge lag af beskyttelse. WordPress Codex har selvfølgelig også instruktioner til hvordan du opsætter HTTP authentication, både på Apache og Nginx servere.

Bloker adgangen på IP-niveau

En anden metode er at blokere adgangen til WordPress-loginformen ud fra forespørgerens IP-adresse. Hvis du ved at du har en fast IP-adresse og at du vil have den samme adresse lige så længe som du har din WordPressside kan du selvfølgelig lave en opsætning der kun giver den ene IP-adresse adgang til din loginside, men det er de færreste forundt (og nu er ikke tidspunktet til en IPv6-diskussion).

Et alternativ, som vil være mere relevant for de fleste, er kun at tillade en IP-adresse X antal loginforsøg, før denne blokeres. Dette kan gøres på WordPressniveau vha. et plugin som WordFence (tak til Kasper Bergholt for anbefaling af pluginet, der tilsyneladende også kan mange andre lækre ting), men igen har vi problemet med at hele WordPresspakken skal startes op, før der kan tages stilling til om en bruger skal have adgang eller ej. Dette er dog noget mere besværligt, og nok ikke noget alle og enhver bare bør kaste sig ud i, men en guide til opsætning af af rate-limiting på Apache kan findes her. Hvis man vil opsætte rate limiting i .htaccess, kræver det dog at man kører Apache med mod_security 2.7.3 eller senere.

Et problem med denne tilgang til det igangværende angreb er at angrebet som forklaret udføres af et botnet der arbejder fra mere end 90.000 forskellige IP-adresser (med mulighed for udvidelse, hvis de får succes). Det betyder at de potentielt kan fortsætte angrebet fra en ny IP, hvis en af adresserne bliver spærret. Dog må der altid være en form for ressource cost tilknyttet hvis angrebet skal flyttes til en ny afsender, da der skal holdes styr på hvor langt hver angriber er nået i ordbogen. Så jo flere lag af sikkerhed du kan opsætte, jo sværere bliver det for angriberen.


Så for at opsummere hvad jeg mener du bør gøre for at højne din WordPress-sikkerhed generelt, og imod det måske igangværende angreb er:

  1. Hold WordPress opdateret, inkl.
    • WordPress core
    • Alle installerede plugins
    • Alle installerede temaer
  2. Tag backup. Om ikke andet for at gøre det lettere at komme tilbage på benene hvis uheldet skulle være ude.
  3. Lad være med at have en adminbruger med navnet admin.
  4. Brug ordentlige passwords. Brug evt. en passwordmanager.
  5. Passwordbeskyt din loginside.
  6. Bloker adgangen for IP-adresser der prøver at gætte dit password.

Hvis i har andre gode råd til beskyttelse af WordPress hører jeg selvfølgelig også gerne om det i kommentarfeltet nedenfor, så vi kan få spredt ordet om ordentlig sikkerhed (At lade være med at bruge WordPress godtages ikke som et godt råd, så hvis det er din mission, så spar dig selv besværet og lad være med at skrive det her).

Leave a Comment

Drupal – opbygning og termer

Drupal er et stort og komplekst system. Der er mange ting man skal sætte sig ind i for at forstå, og kunne arbejde med det. Dette indlæg vil være en oversigt over en del af Drupals terminologi, og en række vigtige koncepter vil blive opsummeret. Dette er mere en huskeliste, end en introduktion, så forvent ikke at det lærer dig alt om Drupal, men hvis du er i gang med at lære Drupal kan det forhåbentlig hjælpe til at forstå nogle af koncepterne bedre.

For at gøre det hele lidt sjovere har nogle af termerne flere forskellige betydninger i Drupal, så det gælder om at holde tunge lige i munden.

  • Drupals fundamentale klasse til indholdstyper.
  • Basistypen for det meste indhold i Drupal.
  • Et indholdselement, f.eks. et blogindlæg.
Content type
  • En definition af en type indhold, f.eks. billede, eller blogindlæg. Nedarver fra Node.
  • En content type til statisk indhold
  • En display type. En page kan definere hvordan indholdet på en side skal struktureres.
  • Et mindre, selvstændigt element på en page. En block kan f.eks indeholde en statisk tekst såsom en copyright disclaimer, eller funktionalitet i form at et søgefelt eller en loginformular.
  • Et view definerer et dataudtræk fra en database. Views kan inkluderes på andre sider og f.eks vise nyeste indlæg eller lignende.
  • Et field er et datafelt tilknyttet en contenttype. Det kan f.eks. være et tekst-felt til nodens brødtekst, eller et datofelt der fortæller hvornår en node er offentliggjort.
  • En template er en skabelonsfil. Det er en PHP-fil der beskriver hvordan sider skal opbygges. Templates kan både være meget generelle, såsom node.tpl.php, men kan overskrives af mere specifikke templates, såsom node-type.tpl.php.
    • En region er en underdel af en template.
    • Et theme beskriver et websites udseende. Det består af en række templatefiler, css-filer og PHP-filer hvor Drupals theme_ funktioner overskrives.
    • Taxonomies bruger til at styre kategoriseringen af indhold på et website
    • Et vocabulary, eller et ordforråd, er en kategori af de tags der bruges til at kategorisere indhold på et website.
    • En term er selve det tag der bruges til at kategorisere indhold på et website. Tags er hierarkiske, dvs. de kan have andre termer som parents og childrens.

    Forskellige content typer kan få tildelt ordforråd. Hvis du f.eks. driver en webshop der sælger tøj, kan man lave et ordforråd der hedder farver. Der kan så laves en content type der hedder “trøjer”, der linkes til ordforrådet “farver”. En trøje node, vil så kunne tagges med farver fra ordforrådet, alt efter hvilke farve trøjen findes i. Hvis trøjer også er linket til et ordforråd kalder “størrelser” vil man f.eks. hurtigt og enkelt kunne søge efter ting som “røde trøjer i størrelse XL”.

    Jeg er stadig ny til Drupal, så dette er de beskrivelser jeg er kommet frem til indtil videre. De fleste burde være nogenlunde på rette spor, men jeg kan ikke garantere validiteten af alle ovenstående beskrivelser. Hvis du har indspark eller rettelser hører jeg meget gerne om det, så jeg, og andre der evt. læser med, kan blive lidt klogere.

    Leave a Comment

    Nordic Game Jam 2013 – Mine tanker

    Den foregående weekend valgte jeg at bruge alt min tid sammen med 470 andre spilinteresserede mennesker på Aalborg Universitet i København. Dette foregik i regi af dette års Nordic Game Jam, et weekendprojekt hvor en masse spilinteresserede mødes, og bruger en weekend på at lave et spil. Normalt er der fokus på computerspil, men i år var konceptet udvidet til også at indeholde en analogt spor.

    Årets tema var grotesk. Det var et ret spændende tema, da det er et koncept de fleste har en klar forestilling om hvad betyder, men når man begynder at dykke lidt ned i ordets definition og oprindelse viser det sig at være et noget bredere koncept end hvad man tænker over til daglig. Det dannede grundlag for nogle spændende diskussioner om hvordan konceptet skulle forstås, og hvordan denne forståelse kunne udtrykkes i spil.

    Jeg var selv på det digitale spor, hvor jeg i en gruppe bestående af 6 (plus 1/3 lydmand), hvor vi til sammen lavede spillet MonsterMash.

    Det var sjovt at prøve at deltage i et arrangement med så mange mennesker med en fælles interesse. Der var mange sjove folk imellem, og man endte hurtigt i nogle sjove og interessante diskussioner når man faldt i snak med mere eller mindre tilfældige mennesker man mødte i elevatoren, i køen til maden, eller i rygerområdet.

    Udover en sjov weekend betyder jammets afslutning også at jeg kan krydse første element af på min liste af mål for 2013.

    Deltage i enten en (gerne flere) hacker eller startup weekend, f.eks. Startup Weekend eller Hack4DK hvis der bliver holdt et lignende arrangement i år.

    Jeg synes dog stadig godt om jam-konceptet, så jeg håber stadig på at nå med til noget som Startup Weekend.

    Til sidst vil jeg gerne anbefale Nordic Game Jam til alle med interesse for udvikling af computerspil, også selvom det bare er noget du synes lyder sjovt. Jeg mødte selv op uden nogensinde at have arbejdet på computerspil før, så man behøver ikke at vide alting på forhånd, man bliver overrasket over hvor mange forskellige skills der kan bruges på sådan et udviklingshold:

    • Projektledelse
    • Ide generering / brainstorming (hvilket mest bare kræver en smule fantasi, og evnen til at sætte to idéer sammen til en ny idé)
    • Tegner/grafiker
    • Programmør
    • Historiefortæller/tekstskriver
    • Ukulelespiller (men venligst lad være med at gøre det i fælleslokalerne hvor du generer 30 andre der prøver at koncentrere sig!)
    • Ølkøber og kaffehenter (nogen skal jo sørge for at holdet holder sammen)

    Så der er plads til alle, og det er bare et spørgsmål om at tage afsted og deltage.

    Arrangørerne har desuden samlet en oversigt over alle tilmeldte spil, de fleste af spillene har vist mulighed for at man kan downloade dem eller spille dem online. Find alle spillene her.

    Leave a Comment

    Tillykke med de 100.000, Ubuntudanmark!

    Den 31. Oktober 2006 kl 21:06 blev det første indlæg posted på det danske Ubuntu supportforum. Det var den spæde start på et forum der siden har udviklet sig meget.

    Forummet har pt. over 5000 brugere, og i dag nåede de endnu en milepæl. Der er dags dato blevet skrevet ikke mindre end 100.000 indlæg! Det må jo betyde at de har gjort et eller andet rigtigt.

    Tillykke til de mange aktive brugere, og ikke mindst de dygtige supportere! Godt gået, og held og lykke med de næste 100.000! :-)

    Leave a Comment

    Teknikken bag en Facebook konkurrence

    I sidste uge lancere min arbejdsplads en konkurrence hvor man kan vinde en skiferie. For at sprede ordet valgte vi bl.a. at dele konkurrencen på Facebook. I forbindelse med Facebookdelen rendte jeg ind i et par problemer som jeg havde svært ved at finde dokumenteret online. Konkurrencen blev oprettet som en facebook page app, som den ses her.


    Facebooksiden i sig selv var ikke et stort problem. Jeg lavede en app på Facebook Developers siden. Dette giver en række muligheder, bl.a. muligheden for at vælge hvordan din app skal integreres med Facebook.

    For at kunne bruge applikationen som et element på en Facebook page, vælges “page tab”. Teknisk fungerer det ved at du selv hoster din app, som en almindelig html side, der så indlejres på din Facebook Page, i en iframe. En page tab har 4 indstillinger:

    • Page Tab Name – Den navn din app skal have i page menuen
    • Page Tab URL – Den side Facebook skal integrere i sin iframe
    • Secure Page Tab URL – En HTTPS-version af den side der skal vises på Facebook
    • Page Tab Edit URL – Link til din app’s admin modul. Jeg skippede dette, da mit projekt ikke havde behov for customization

    I følge Facebook selv har mere end 9.6mio brugere valgt kun at kunne tilgå Facebook via https. Hvis du ikke har tilføjet en HTTPS-version af din app vil alle de mennesker hverken kunne se eller bruge din app.

    Et af de problemer jeg kæmpede mest med, var at gøre det muligt for folk at dele appen med deres venner. Ikke fordi det var svært rent kodemæssigt, men jeg fandt ud af at det kræver at appen udover at være oprettet som ‘page tab’ som forklaret ovenfor, også kræver at den er lavet som en normal ‘app on facebook’ (se billede ovenfor). Når du vælger ‘app on facebook’ får du 2 indstillingsmuligheder. Canvas URL, og Secure Canvas URL. Et Facebook app canvas fungerer på samme måde som en Facebook page tab, bortset fra at det er en selvstændig app, og ikke tilknyttet en page. Da jeg ikke havde brug for en selvstændig app valgte jeg at lave mine canvas URLs pege på en tom side, der kun bestod af et JavaScript redirect, til min page tab.

    Selve appen

    Da opsætningen var på plads var der bare tilbage at lave selve appen. Det sker som nævnt tidligere vha. html, css og javascript, og der er altså ikke meget magi her. For at få adgang til Facebooks funktionalitet, skal Facebook SDK’et loades.


    js.src = d.location.protocol + "//";

    kan bruges til at styre hvilket sprog Facebooks ting skal vises på. Tilgængelige sprog kan findes i Facebook’s Locale XML.

    Nu er der adgang til Facebooks funktionalitet via. Javascript. I dette projekt blev det brug til 2 ting. Først skal der være mulighed for at folk kan dele appen med deres venner:

    function tellafriend() {
    		method: 'apprequests',
    		message: 'Hvilken besked skal folk sende til deres venner?',
    		title: 'Overskrift.'
    	}, function (response) {

    Den sidste del:

    function (response) {

    Sørger selvfølgelig for at funktionen poststory() kaldes så snart folk har valgt hvem af deres venner de gerne vil dele appen med. Det er også muligt at trykke cancel og på den måde ikke dele med nogen, poststory() vil dog stadig blive kaldt.
    Formålet med poststory() er at lade folk poste et link til appen på deres egen væg:

    function poststory() {
    		method: 'feed',
    		name: 'Overskrift på vægopslaget',
    		link: 'Link der skal deles',
    		picture: 'link til billede der skal inkluderes på opslaget',
    		caption: 'Billedetekst.',
    		description: 'Brødtekst på indlægget'
    	}, function(response) {

    Efter poststory() kaldes funktionen redirectuser(), som vha. et normalt Javascript redirect videresender brugeren til vores egen konkurrenceside.

    Jeg håber indlægget kan hjælpe med at komme udenom nogen af de små fælder jeg selv rendte ind i :-)
    Husk i forbindelse med konkurrencer at overholde Facebook’s egne regler for konkurrencer. Ellers kan det blive en kort fornøjelse. Kasper Blom har skrevet en god kort opsummering af konkurrencereglerne.


    WordPress Danmark og WordPress på dansk

    Som jeg nævnte i forrige indlæg havde vi en diskussion efter sidste weekends WordCamp, vedrørende WordPress Danmark, og hvad folk i communitiet mener der kan gøres for at forbedre WordPress Danmark.

    Som nævnt har jeg meldt mig som tovholder på oversættelsesteamet. Ikke i den forstand at jeg skal have hånd i hanke med hvad der oversættes og hvordan, slet ikke, men i den forstand at jeg skal se på mulighederne for at gøre det lettere at finde plugins og temaer der er oversat til dansk, samt gøre det lettere for folk at bidrage til oversættelserne.

    Jeg har ikke alle de rigtige svar, men jeg har selvfølgelig gjort mig nogle tanker om hvad der evt. kunne gøres.

    1. Gøre det lettere hjælpe
    2. Gøre det let at tilføje projekter til førnævnte GlotPress, så folk med interesse i et specifikt plugin eller let kan komme i gang med at oversætte netop det
    3. Gøre det muligt at søge efter oversatte plugins

    Første punkt kunne evt. klares ved at opsætte en GlotPress installation på, for at samle oversættelsesindsatsen, samt færdige oversættelser et sted. Det behøver selvfølgelig ikke nødvendigvis være GlotPress, men det kunne være et fornuftigt valgt, da det er anbefalede værktøj, og det bygger på BackPress, som er en fælles kodebase for WordPress relaterede projekter.

    Andet punkt kan hjælpes på vej ved evt. ved at se på muligheden for at kunne trække filer til oversættelse direkte fra’s plugin og theme repository, og evt. gøre det let for oversættere at tilføje nye projekter, til det software der blev diskuteret i punkt 1.

    Hvis de ovenstående 2 punkter bliver en succes, vil det selvfølgelig betyde at vi med tiden “automatisk” får opbygget en pæn samling oversatte plugins. Derudover vil det være relevant at kunne hooke ind i søgefunktionen på, for her i gennem at få adgang til de oversatte plugins og themes der allerede findes.
    Der er pt. ingen officielt dokumentation til søge API’et, men der kan findes nogle små optegnelser hos DD32. Desuden kan der jo søges både i plugins og themes direkte fra WordPress admin interfacet, hvilket betyder at findes fungerende kode i WordPress, som der kan rodes i.

    Har du andre forslag til hvordan det kan gøres lettere at finde danske plugins og themes, eller hvordan det kan gøres lettere for folk at hjælpe med at oversætte? Eller har du lyst til at hjælpe med at implementere ovenstående? Smid en kommentar herunder, eller endnu bedre, deltag i debatten på WordPress Danmark’s udviklingsblog.