404 Error: /eyeblaster/addineyev2.html

While looking at the content access statistics in Google Analytics, I’ve noticed that a few of them access a page with the URL /eyeblaster/addineyev2.html. Since I was pretty sure I didn’t have such a page I first thought that my site might have been hacked and checked this page. It led me to the 404 error page. So this URL didn’t exist but some of my visitors were redirected to it. The traffic to this page was not so high (never more than 5 page views a day) but I could see that this added up to 25 page views since mid of February.

Next step was to find out where these visitors were coming from. The navigation summary in Google Analytics for this page looks like this:

Navigation Summary

So half of the visitors came from a previous page and half from outside. The distribution of previous pages was pretty random, so it is definitely not related to specific pages:

Previous Page Path

But actually the important most visitors leave my blog once redirected. Googling for this issue, I found a Google support page:

If you are trafficking an EyeBlaster Flash creative as a 3rd-party tag, you will need to put the addineyev2.html file to www.example.com/eyeblaster/addineyev2.html

The code for addinexev2.html can be found on adopstools.com. It’s basically just loading a JavaScript file:

<HTML>
<HEAD>
</HEAD>
<BODY style=margin:0;padding:0>
<SCRIPT src="http://ds.eyeblaster.com/BurstingScript/addineye.js">
</script>
</BODY>
</HTML>

If you add this HTML page, you should also make sense to prevent search engines from indexing it by adding the following to your robots.txt:

Disallow: /eyeblaster
Disallow: /addineyeV2.html

Or by adding the following metatag to the head section of this HTML page:

<meta name="robots" content="noindex" />

But since I didn’t feel confortable adding such a webpage to my site (especially since it’s just loading some JavaScript from a third party site), I looked for another solution. If the script was actually hosted by Google I might have trusted it but it’s not the case.

Looking at the referenced JavaScript file, I found out it seems to be related to the MediaMind ad network and googling for it also showed that Eyeblaster rebranded as MediaMind. So an alternative to adding the HTML file above to your website is to block ads from this network. Actually a network which forces you add files to your site (assuming you can add files at all) should actually be blocked by default by Google. But since they haven’t done it, we’ll have to do it manually.

To block this network, you have to go to Adsense, click on Allow & block ads, type “mediamind” in the search box. You’ll see something like this:

allow block MediaMind ad network

Then click on the left side button for each of these networks to block them:

block MediaMind ad network

Now you shouldn’t get these ads which end up redirecting your users to this non-existing HTML page and you’ll display ads from networks which behave better. I’m suspecting that other networks might also be using this script, so I’ll have to monitor this and find out which other ad networks I’ll have to block.

Visual Studio 2012: mspdb110.dll is missing when executing editbin.exe

I was having some issues using an OCX in an old application I had recompiled using Visual Studio 2012. One thing I found is that it might be related to a compatibility issue with Data Execution Prevention (DEP). Since I couldn’t recompile the OCX and didn’t have direct access to the linker settings, I went for using editbin.exe to apply a /NXCOMPAT:NO. But when I ran the following:

C:\Users\benohead>"c:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin\editbin.exe" /NXCOMPAT:NO myfile.exe

I got a system error from link.exe saying:

The program can’t start because mspdb110.dll is missing from your computer. Try reinstalling the program to fix this problem.

The cause for this error is that I executed the command in the wrong DOS prompt. Not the one where I had executed vcvars32.bat. So I just executed vcvars32.bat:

"c:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin\vcvars32.bat"

And gave it another try. Now no error message was displayed.

WordPress: Network-wide plugin settings

When developing a plugin, which will be used on single site, as well as multi-site, there are two ways of supporting multi-site deployments:

  1. The plugin is activated per site and provides per-site settings only.
  2. The plugin can be activated for the whole network and provides network-wide settings

I’m currently working on a plugin which needs to support both scenarios. The first scenario is pretty straight forward. But the second one is a little bit trickier.

  • Proper support of the network activation
  • Activation for new sites
  • Network-wide settings
  • Proper support of the network deactivation

Proper support of the network activation

To activate the plugin in a multisite environment, you’ll need go through all the blogs and activate them individually e.g.:

register_activation_hook( __FILE__, 'my_plugin_activate' );

function my_plugin_activate($network_wide)
{
	global $wpdb;

	if (function_exists('is_multisite') && is_multisite() && $network_wide) {
		$current_blog = $wpdb->blogid;
		$blogs = $wpdb->get_col("SELECT blog_id FROM $wpdb->blogs");
		foreach ($blogs as $blog) {
			switch_to_blog($blog);
			my_plugin_activate();
		}
		switch_to_blog($current_blog);
	} else {
		my_plugin_activate();
	}
}

If we are in a multisite environment but the plugin is only activated to for a blog, a normal activation is performed. Otherwise we fetch the list of all blogs and activate them one by one before reverting to the current blog.

Note that you should not use restore current blog() to get back to the original blog since it will revert to the blog active before the last switch_to_blog(). So if switch_to_blog() is called twice it will not revert to the blog which was active before this all started.

Activation for new sites

When a new blog is added, you’ll need to specifically activate the plugin for this blog since this blog was not present, when the activation occurred.

add_action( 'wpmu_new_blog', 'activate_new_blog' );
 
function activate_new_blog($blog_id) {
    global $wpdb;
 
    if (is_plugin_active_for_network('plugin_name/plugin_main_file.php')) {
	switch_to_blog($blog_id);
	my_plugin_activate();
	restore_current_blog();
    }
}

So first we check whether the plugin was activated for the whole network. If it is the case, we switch to the new blog, activate the plugin for this blog and switch back to the previous blog. Here it is fine to use restore_current_blog() since we only use one switch_to_blog().

Network-wide settings

In single site environment, you would use the functions get_option() and update_option() to respectively read and write your plugin settings. In a multi-site environment, you should rather use the get_site_option() and update_site_option() functions instead.

So instead of:

get_option('my_settings', array())
...
update_option( 'my_settings', $settings );

Use:

get_site_option('my_settings', array())
...
update_site_option( 'my_settings', $settings );

When registering your settings page, instead of using options-general.php as parent slug, when calling add_submenu_page, if your plugin has been network activated, you’ll need to add the submenu page using settings.php as parent slug.

Also when linking to your settings page (i.e. from the plugins list), in a single site environment, you’d do it this way:

<a href="options-general.php?page=my_settings">Settings</a>

But to link to the network settings page, you’ll need to use the following

<a href="settings.php?page=my_settings">Settings</a>

The hook for adding the link is also different. Instead of adding a filter for ‘plugin_action_links_pluginname_pluginfile’, you’ll have to add a filter for ‘network_admin_plugin_action_links_pluginname_pluginfile’.

Also the hook to use to call your registering function is different, instead of adding an action to the ‘admin_menu’ hook, you should add an action to the ‘network_admin_menu’ hook in a network activation scenario.

In your settings page, when in a single site environment, you can use the settings API and do not need to update your settings manually, by using options.php as form action:

<form method="post" action="options.php">

For network-wide settings it’s not so easy. There is no direct equivalent to options.php for such settings. You will need to direct to edit.php and provide an action name which will be linked to one of your functions where you will update the settings. Here the registration and definition of this function:

add_action('network_admin_edit_my_settings', __FILE__, 'update_network_setting');

function update_network_setting() {
	update_site_option( 'my_settings', $_POST[ 'my_settings' ] );
	wp_redirect( add_query_arg( array( 'page' => my_settings, 'updated' => 'true' ), network_admin_url( 'settings.php' ) ) );
	exit;
}

Of course instead of my_settings, you should use the name of your settings. The name of the action hook is network_admin_edit_ followed by an action name which will be used as parameter to edit.php in the form definition e.g.:

<form method="post" action="edit.php?action=my_settings">

Of course, since you want to support both the normal and the network activation scenarios, you’ll have to use is_plugin_active_for_network() to figure out in which scenario you are and trigger the appropriate logic.

Proper support of the network deactivation

For the deactivation, you need to do exactly the same you’ve already done for the activation i.e.:

register_deactivation_hook( __FILE__, 'my_plugin_deactivate' );

function my_plugin_deactivate($network_wide)
{
	global $wpdb;

	if (function_exists('is_multisite') && is_multisite() && $network_wide) {
		$current_blog = $wpdb->blogid;
		$blogs = $wpdb->get_col("SELECT blog_id FROM $wpdb->blogs");
		foreach ($blogs as $blog) {
			switch_to_blog($blog);
			my_plugin_deactivate();
		}
		switch_to_blog($current_blog);
	} else {
		my_plugin_deactivate();
	}
}

function my_plugin_deactivate()
{
	//deactivate the plugin for the current blog
}

Of course in a network-wide deactivation scenario, you may want to add some additional cleanup after the plugin has been deactivated for all blogs.

Conclusion

So supporting all three scenarios (single site, multisite with per blog activation and multisite with network activation) is not so difficult. The only tricky part is handling network-wide settings. Unfortunately, the settings API does not help you much here. But once you’ve done it for a plugin, it’s just a matter of copy&paste.

Note that if you do not perform anything special as part of your activation, you do not need to handle the multisite activation since WordPress will activate the plugins appropriately. It is only required if your plugin does some additional magic since WordPress will not call you for each blog.

WordPress: Running multisite on different port

Since I’m maintaining a few WordPress plugins I wanted to have a local installation where I can also make sure that new versions of the plugins also behave well in a multisite environment (site network). Unfortunately, I cannot use ports 80 and 443 since I need them for some other projects I’m working on (using IIS). So my local apache server runs on ports 8080 (http) and 8443 (https).

The problem is that this is not supported by WordPress. You need to run on ports 80 and/or 443. Otherwise WordPress won’t let you create a site network and you’ll get a message saying:

You cannot install a network of sites with your server address.
You cannot use port numbers such as 8080.

A single site installation of WordPress works fine on port 8080 but for some reason, it isn’t support for WordPres Site Networks… Well, that’s not a reason not to use it :-)

Since it’s all PHP, you can easily just fix it. Of course, you need to keep in mind that any update of WordPress might remove the changes and you’ll need to do it all again. But since it’s just a test installation, it’s not a problem for me.

So, to find out how to fix it, we first need to find out where this message is displayed. Using grep, you can quickly find that it comes from the function network_step1 in wp-admin\network.php. The relevant piece of code looks like this:

if ( ( false !== $has_ports && ! in_array( $has_ports, array( ':80', ':443' ) ) ) ) {
	echo '<div class="error"><p><strong>' . __( 'ERROR:') . '</strong> ' . __( 'You cannot install a network of sites with your server address.' ) . '</p></div>';
	echo '<p>' . sprintf( __( 'You cannot use port numbers such as <code>%s</code>.' ), $has_ports ) . '</p>';
	echo '<a href="' . esc_url( admin_url() ) . '">' . __( 'Return to Dashboard' ) . '</a>';
	echo '</div>';
	include( ABSPATH . 'wp-admin/admin-footer.php' );
	die();
}

If you use an extra :80 or :443, WordPress will not complain but it will if it is another port number. So in order not to get this error message, you just need to add the ports you need to the list, replacing:

if ( ( false !== $has_ports && ! in_array( $has_ports, array( ':80', ':443' ) ) ) ) {

by:

if ( ( false !== $has_ports && ! in_array( $has_ports, array( ':80', ':443', ':8080', ':8443' ) ) ) ) {

Of course, I assumed there was a reason why only ports 80 and 443 were supported. So I searched in the code for 80 and 443 and found this in wp-includes\ms-settings.php:

if ( substr( $domain, -3 ) == ':80' ) {
	$domain = substr( $domain, 0, -3 );
	$_SERVER['HTTP_HOST'] = substr( $_SERVER['HTTP_HOST'], 0, -3 );
} elseif ( substr( $domain, -4 ) == ':443' ) {
	$domain = substr( $domain, 0, -4 );
	$_SERVER['HTTP_HOST'] = substr( $_SERVER['HTTP_HOST'], 0, -4 );
}

In a previous version of this post I was adding some code for ports 8080 and 8443 but I realized it was actually making things worse. The only purpose of this piece of code is to remove unnecessary port numbers which are not relevant for comparing domain names. But ports 8080 and 8443 are relevant (https://benohead.com:8443 doesn’t point to the same web server as https://benohead.com, but https://benohead.com:443 does).

With the changes above I could create the site network. But when I tried to login, I was redirected to the IIS, to http://localhost/wordpress/wp-login.php instead of http://localhost:8080/wordpress/wp-login.php. Since I couldn’t find anything in code which would explain this, I had a look at the wp_options. And saw that the siteurl option contained http://localhost/wordpress/ instead of http://localhost:8080/wordpress/. So I just updated it in MySQL using the following SQL statement:

UPDATE `my_wordpress_db`.`wp_options` SET `option_value` = 'http://localhost:8080/wordpress/' WHERE `wp_options`.`option_name` = 'siteurl';

And tried again. And this time I got to the right login page ! Remember to replace “my_wordpress_db” by the name of your WordPress database.

I then noticed that there were still some links pointing to http://localhost/wordpress. Finally I saw that the “home” option in wp_options was still pointing to the wrong URL. After fixing it, everything looked fine:

UPDATE `my_wordpress_db`.`wp_options` SET `option_value` = 'http://127.0.0.1:8080/wordpress/' WHERE `wp_options`.`option_name` = 'home';

So now everything was working fine, the admin page, the blog post/pages. But then I realized that when creating a new site, I saw “localhost:8080″ in the UI but it was saving localhost8080 instead. So something was removing the colon. And I found the following in the function wpmu_create_blog in wp-includes\ms-functions.php:

$domain = preg_replace( '/\s+/', '', sanitize_user( $domain, true ) );

With the second parameter is true, only alphanumeric characters plus these: _, space, ., -, *, and @ are returned. Of course, one solution would be to add colon to the list but then it would allow usernames to contain colons as well. So I ended up just setting the second parameter to false, or rather commenting it out, since false is the default:

$domain = preg_replace( '/\s+/', '', sanitize_user( $domain/*, true*/ ) );

Now everything seems to be working.

While looking for a solution, I did find a few links explaining how to do it in version prior to WordPress 3.7. But I needed it for WordPress 3.9.1. So I had to find a solution by myself. Of course I have only tested it on WP 3.9.1 and haven’t checked when was last time these pieces of code were changed. So it might work on WP 3.7 and WP 3.8 as well but I cannot guarantee anything.

Visual C++: module unsafe for SAFESEH image, unable to generate SAFESEH image

Using Visual Studio 2012, I was building from the command line a software which was built until now using an older version (guess it was Visual Studio 2005). There were of course many things I had to change in the code itself (so much for portability…). And of course I had to upgrade the project in the solutions to VS2012 (using the devenv /upgrade command).

After converting the projects and modifying the code, I got the following error messages on a few projects:

error LNK2026: module unsafe for SAFESEH image.

fatal error LNK1281: Unable to generate SAFESEH image.

This means that the linker was started with the option meaning /SAFESEH “image has safe exception handlers” (also note that we only got this because we’re still building 32bit targets). The error occurs because some input modules were not compatible with the safe exception handlers feature of the linker. In our case it was some third party lib files for which I did not have the source code. These lib files are not be compatible with safe exception handlers is because they were created with an older version of the Visual C++ compiler.

But this is easy to fix. You just need to tell the linker not to produce an image with a table of safe exceptions handlers even if it thinks that all modules are compatible with the safe exception handling feature.

If you work in the Visual Studio Editor, you can right-click on your DLL project, go to Properties > Linker > Advanced and set “image has safe exception handlers” to No.

If like me you’re working from the command line, you can edit the .vcxproj file by opening it and searching for the <link> tags. Add the following to each <link> tag (there will be one per target e.g. one for debug and one for release):

<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>

It doesn’t matter where exactly you add it, it just needs to be between <link> and </link>.

If you call the linker yourself, you can also add /SAFESEH:NO to the command line.

After making this change, you can build your project again and the error will be gone.

OleViewer: STG_E_FILENOTFOUND and IDataObject interface viewer only supports IID_IDataObject

I had some problems loading a type library (TLB file) when building a Visual C++ project, so I wanted to have a look at the TLB file using the OleViewer. So I started the OleViewer as Administrator from C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\x64. When opening the TLB file I got the following error message:

LoadTypeLib(my tlb file) failed.
STG_R_FILENOTFOUND ($80030002)

The issue here was that I started the 64bit version of the OleViewer. With the 32bit version (present directly in C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin), this error was gone, so it could actually load the file but I got another error message:

IDataObject interface viewer only supports IID_IDataObject

Solving this was easy but kind of confusing. I went to the View menu, unchecked “Expert Mode” then opened the TLB file. And the error message was gone. After that I checked it again but could still open the TLB file. Eveb after closing the OleViewer and opening it again, I was able to load the TLB file.

I’m still not 100% sure what happened here… Another thing I did after removing the Expert Mode and before reopening my TLB file was to open a few object classes in the tree on the left. At least of them was the Microsoft Web Browser (under Controls). So if unchecking the Expert Mode alone doesn’t help, you could try this.

It looks like the error message I got above means that iviewers.dll in-process server was not properly registered. The OleViewer uses iviewers.dll to parse the type library. Somehow after the things I’ve done above, the registration was fine. Of course if it still doesn’t work for you, you can try registering it yourself using regsvr32 iviewers.dll.

Somewhere inbetween I’ve also try using but also had a problem with the same TLB file (also it worked for others). After the problem was solved with OleViewer, OleWoo was also able to open the TLB file. So I guess OleWoo parses the TLB the same way OleViewer does.

And actually after that Visual Studio 2012 wasn’t complaining anymore about the TLB file. Before that I got the following error message on the line where I import the TLB file:

error C1084: Cannot read type library file: ‘my tlb file’: Error loading type library/DLL.

So it looks like Visual Studio had the same issue with iviewers.dll as OleViewer and OleWoo but unfortunately only said it couldn’t load the type library instead of giving me a more precise error message…

Even if I don’t really get what happend here, I’m glad it’s solved :-)

First and last matching child in CSS and with jQuery

I recently noticed a few problems in some code I had written a few months ago:

  1. I am displaying a grid containing an empty first column and an empty last column and want to remove them. This only happened for the first row and not for the others
  2. I display a left border on all columns and additionally a right border on the last column. This also didn’t work anymore, the right border was missing.

These two problems were due to using the selector (once in CSS and once with jQuery) which do not do what I would expect.

First let’s assume we have a table-like div structure:

<div class="table">
    <div class="tr">
        <div class="th"></div>
        ...
        <div class="th"></div>
    </div>
    <div class="tr">
        <div class="td"></div>
        ...
        <div class="td"></div>
    </div>
    ...
    <div class="tr">
        <div class="td"></div>
        ...
        <div class="td"></div>
    </div>
</div>

In CSS, I can set the style of the first cell and of the last cell of each row like this:

div.tr div:first-child { }

div.tr div:last-child { }

To select them with jQuery:

jQuery("div.tr div:first-child")

jQuery("div.tr div:last-child")

Easy, right ? So where’s the problem ?

Well the problem is that is that it only worked by chance and as soon as I extended the generated html code, it broke. I needed to add some additional divs at the end of every line in the grid but have them be invisible. So basically, since the new divs where invisbile, the current last div would still have to be styled in a special way although it wasn’t the last div child anymore. So I just modified my CSS and jQuery selectors like this:

div.tr div.td:last-child { }
jQuery("div.tr div.d:last-child")

And the same for th as well. But it doesn’t work. What happens is that div.tr div.td:last-child doesn’t mean select the last child of div.tr being a div.td. It means select the last child of div.tr if it is a div.td. So since the last child of div.tr was not a div.td anymore, it failed.

So what I needed was a selector like :last-child-of-type. Well actually there is a selector :last-of-type. Unfortunately, it also failed using it since this selector doesn’t work with classes i.e. you can use div:last-of-type as selector but not div.class:last-of-type. So :last-of-type is useful to select the second div in this case:

<article>
    <p></p>
    <div></div>
    <div></div>
    <div></div>
    <p></p>
</article>

But not in our case. So what can be done ? Well, the way I went for (which just involved replacing an append by a prepend) was to move the hidden divs to the beginning of the row. So now I could use :last-child again. And since I was selecting the first line only with jQuery, I used the following:

$(".tr.cell").each(function() {
    $(this).children(".td").first().remove();
    $(this).children(".td").last().remove();
});

So it’d be great if :last-of-type could support classes or if there was a :last-of-class. But until there is, you can work around it with jQuery using a loop. In CSS, unfortunately, there seems to be no way to do it. The only way to select this last element of a type using CSS selectors is to assign it a class with javascript or while generating the HTML code and then selecting this class using CSS.