How to disable IPv6 for Exim4 that comes with Vesta Panel

I had a server which has both IPv4 and IPv6 and they were working perfectly fine. I had installed Vesta CP which is an amazing control panel application and it was working just great. But there was only one problem with Exim4. It was not sending emails properly to Gmail. Mails sent to gmail were bounced. I checked the log and the message was

message does not meet IPv6 sending guidelines regarding PTR records

Ok, that is pretty straight forward. The server’s IPv6 didn’t have a reverse DNS or PTR. To fix this problem I had to set it up. But then I was thinking how to tell Exim not touse IPv6 but IPv4. The problem begins

Exim in this server came with Vesta Panel, and in most forums people suggested to add a new entry as disable_ipv6=true in the /etc/exim4/update-exim4.conf.con file. I’ve added that and restarted exmi4, but there were no changes. Netstat shows that exim is still listening on port 25 against the IPv6 address.

netstat -tulpn | grep :25
tcp        0      0    *               LISTEN      7013/exim4      
tcp        0      0  *               LISTEN      7013/exim4      
tcp6       0      0 :::25                   :::*                    LISTEN      7013/exim4      
tcp6       0      0 :::2525                 :::*                    LISTEN      7013/exim4 

Some people in different forum suggested that dc_local_interfaces should be set to but it still didn’t make any change in exim.

Finally, finally, I noticed that there is a configuration template file /etc/exim4/exim4.conf.template. Curiously, I’ve added disable_ipv6=true directive over there, restarted exim and voila! It started working :)

netstat -tulpn | grep :25
tcp        0      0    *               LISTEN      8110/exim4      
tcp        0      0  *               LISTEN      8110/exim4  

I hope you will find this article useful, and save some time when you run into similar problem with exim and vesta panel.

How to prevent someone or some role from accessing the WordPress admin panel

It might be required sometime to prevent a user or all users with a specific role from accessing the WordPress admin panel. It’s not tough. Let’s think that we want that all users with author role will not be able to access the admin panel. All you have to do is just add the following code in your functions.php and you’re done

add_action( "init", "prevent_from_admin_panel" );
function prevent_from_admin_panel() {
    if ( ! current_user_can( "manage_categories" ) ) {
        if ( is_admin() && !defined( 'DOING_AJAX' ) ) {
            $pageurl = get_author_posts_url( get_current_user_id() );
            wp_redirect( $pageurl );

The code checks if the currently logged in user has the necessary capability manage_categories. This particular capability is only available to the users with Editor or higher roles, like an Administrator. So, if the current user doesn’t have it, he must be someone with an Author role. Now we will just get the url of his posts page and redirect him over there.

this particular code is_admin() && !defined( 'DOING_AJAX' ) makes sure that for ajax calls, we will not perform this redirection.

If you want to block a particular user from accessing the admin panel, then just get his id by using get_current_user_id() function. And then redirect him to homepage if it matches with the user id that you want to prevent.

That’s it. I hope you’ve enjoyed this article.

Changing Author Homepage URL Properly in WordPress

* Photo by Michael Fertig

Authors in WordPress have a homepage url like where all their posts are shown. And many of us who think it doesn’t look attractive want to change that url format. The middle part of that url, which says author, is called an author_base and it is possible to change this using some rewrite rules and filters. Let’s get our hand dirty :)

Modifying the permalink

To change the author base in permalink, you need to use the global $wp_rewrite class, like this

function change_author_base_in_permalink() {
    global $wp_rewrite;
    $wp_rewrite->author_base = "users";

Now, as soon as you visit you will see that it’s a 404. Good, eh? At the same time, this link will display all the posts for this particular user.

If you want to revert this change and go back to the old url structure, then all you have to do is comment that action, and then flush the permalink for once.

Other fixes

There is one small problem. Though the new permalink has been effective, but get_author_posts_url() still returns an url with the old format. So we need to fix that part too. Luckily, there is a filter :)

function fix_author_link($link){
        return str_replace("author","users",$link);

That’s mainly it. I hope you find this article useful.

Creating a slack bot using PHP to monitor your envato sales

Slack is awesome. Slack is the de-facto of modern team communication and I am pretty sure that this is not the first time you’re hearing something like this about slack. But if you’re really never used slack, oh boy, I feel pity for you :)

Anyway, in this article we’re going to make a slack bot that will monitor the sales in our envato account and notify from time to time as soon as someone purchased an item. Pretty useful, eh?


Considering you have a slack account, log into it and open a new channel, for example “#sales”. Now go to or just click on “Configure Integrations” from your slack app.

Continue reading Creating a slack bot using PHP to monitor your envato sales

Packaging thirdparty plugins with your WordPress theme using TGM Plugin Activation library

When you’re shipping your theme for sell, it’s often required to bundle the required plugins. Some people just keep these plugins like general vendor libraries inside their theme and load them using php’s require_once. However, if you’re following this style, your themes will fail to pass the theme check because these plugin files will be considered as a part of your theme, and it will prompt you that CPT functions and shortcodes should be a part of the plugin. Moreover, if someone deactivate your theme, those shortcodes and CPTs will be unavailable immediately.

This is why, along with many other developers, we use TGM Plugin Activation library. This tiny little lib can force or suggest installing the plugins which are required (or good to have) for making your WordPress theme work flawlessly.

TGM can work with plugins which are hosted in WordPress plugin repository, or in a github public repository. It can also work with plugins which are shipped with the theme as a separate zip file. In this article we’ll see all these three cases of plugin installation and activation process using TGM library.


Download the TGM library from After unzipping, keep the class-tgm-plugin-activation.php file inside vendors/tgm/ inside your theme. Then add the following code in your functions.php Continue reading Packaging thirdparty plugins with your WordPress theme using TGM Plugin Activation library

Generate Dummy Placeholder Images in the WordPress Export File Instantly

It’s a common problem for the theme developers who sell their themes in the marketplaces and ships a data file with it, that contains exported data from the demo WordPress site. The problem is, this content file contains links to the images used in the demo. And those images, which the author uses to decorate his demo sites, may not be freely distributable.

So, theme developers have to create another site with placeholder images and then export data from this site. It’s a double work. It’s a boring work as well.

To save from this pain, I’ve created a site called DimgX which is available at that can deliver placeholder images on the fly. Using this service is pretty straight forward. If your image url is all you have to do is add a at the end of the image domain, like

So if the url of the original image is which displays like this Artwork By Greg Christman

It’s placeholder image’s url will be and it will show like this – Tada! You don’t have to worry about the original image’s dimension or anything. Everything will be handled by DimgX on the fly.

Using this feature, DimgX allows you to upload the exported content file from your WordPress site, which has an xml extension, and then download a modified content file having all the attachment urls replaced using It’s pretty handy

DimgX replaces all the <guid> and <wp:attachment_url> in the export file, which contains links to the image files, and adds at the end of those domain names in those image urls.

While creating a placeholder image, DimgX needs to calculate the size of the original image, to properly draw a placeholder with the same dimension. And in PHP, you know the only way to do it using getImageSize() function. People usually download whole image and then calculate these dimensions but that’s is a pretty expensive process when you have to download lots of bigger images. Fortunately, all these popular image formats contains these dimension in the first few KB in their header. So DimX doesn’t download the whole image but only a chunk of it. And then it uses that chunk of the header data to calculate this size. It makes the whole process fast, and less resource extensive. And while doing this, it also saves a good amount of bandwidth. To feed your appetite, here’s a part of that routine

switch ($extension) {
    case "jpg" :
    case "jpeg" :
        $range = "0-50000";
    case "png":
        $range = "0-10000";
    case "gif":
        $range = "0-10";
        $range = "0-15000";

$ch = curl_init ($url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_BINARYTRANSFER,1);
curl_setopt($ch, CURLOPT_RANGE, $range);

And here is the regular expression pattern that gets this complex URL replacement job beautifully done

$pattern1 = "/<guid([^>]+)>http://([^/]+)/([S]+)(.jpg|png|gif)</guid>/";
$pattern2 = "/<wp:attachment_url>http://([^/]+)/([S]+)(.jpg|png|gif)</wp:attachment_url>/";
$new_data = preg_replace($pattern1,'<guid${1}>http://${2}${3}${4}</guid>',$data);
$new_data = preg_replace($pattern2,'<wp:attachment_url>http://${1}${2}${3}</wp:attachment_url>',$new_data);

Anyway, feel free to use DimgX at and let me know how you feel about this service. Right now, it can convert image urls that is served using http://, because wildcard SSLs are not cheap. But it’s in our roadmap. Stay tuned :)

[update] PHPStorm’s upcoming subscription based licensing model and why you’re fucked up

** I’ve added an update. Click here to read it **

JetBrains has sent me an email today, mentioning about the upcoming change in their licensing model. Right now all users can renew their license at $49 which is a 50% discount rate of the original rate. From this November 2nd, you will be able to renew it for $119. Or you can buy a new license for $199/yr or $19.90/mo. Now, if you want to do some simple math, the upcoming yearly cost will be a whooping 100% increased price. If you go for monthly subscription, it will be like 141% extra of the current price.

Moreover there will be pain if you don’t want to continue. If you start with, for example V8, and in the middle of a yearly subscription V9 is released, but you don’t want to continue after the end of your subscription – you will be given a perpetual license of V8. You read it right, you will have to continue with V8 – not V9. Even though V9 was released during your subscription, you will not be allowed to keep using it. Huh!

Well, either way you’re pretty much fucked up. If you’re an existing license holder then you may find it slightly profitable to stick for the first two years because they said that there will be a 40% discount and 2nd year will be on them.

I am using PHPStorm since it’s version 3 and I am not going to renew it this time, for sure. I’ve been experimenting with Atom lately and it is pretty nice. Anyway, I am going to miss PHPStorm because I consider their upcoming licensing model is a kinda ripping-off of their loyal customers. Dear Jetbrains, Adios!


Ok, it looks like I was comparing the pricing for company/organization instead of the personal licensing model. Their page content is pretty confusing, and it’s hard to get it right at the first sight. I’ve found the correct page with the pricing for personal/individual license and it’s not bad.

With this pricing, well, I think I don’t have any problem to renew it again. Thanks to @Gary Hockin and @Hadi Hariri from Jetbrains for clearing it up.