Files uploaded through Wordpress on Windows Server are missing permissions

When uploading files in Wordpress, PHP uses a temporary upload folder. By default PHP will use the C:\Windows\Temp when uploading files. If you install PHP and Wordpress onto your Windows server then you might notice that any files uploaded through Wordpress are not accessible on your site. This is down to PHP taking the folder permissions from the C:\Windows\Temp folder which does not have public access granted on it (for obvious security reasons!).

To work around this issue you need to create a new folder and give that folder the correct permissions for the uploaded files to be available to users who visit your site.

Step 1: Create a new folder. I decided to use a folder on the root level: C:\TempUploadedFiles

Step 2: Right click on this folder and grant enough permissions for the files to be viewed online. Typically you would add IIS_IUSR, Users and NetworkService users with read permissions.

Step 3: Now we need to tell PHP to use this new folder when uploading files. Open your PHP.ini file in notepad (usually in C:\Program Files (x86)\PHP) and locate the line with 'upload_tmp_dir'. Replace the whole line with this:
upload_tmp_dir = C:\TempUploadedFiles
(make sure there is no semi colon at the start of the line!)

Gotcha: Be sure to check that there is no other 'upload_tmp_dir' declared in the PHP.ini file. In the file I was using there was another instance of 'upload_tmp_dir' located at the end of the file and it was overwriting my values.

Step 4: Save your PHP.ini file and open IIS. Locate your website and click on restart for the new settings to take effect.

Step 5: Open Wordpress and upload your new file. PHP will use your new destination to handle the file during upload and when the file has fully uploaded it will transfer it to the correct location in your wp-content/public folder with the correct permissions.

You only need to make this change once as in future all PHP sites will use the new C:\TempUploadedFiles folder.

Need to do a word count from a Word, Excel, HTML, XML or PDF file?

Count Anything

I had to send on a word count to a customer recently. Nothing new there. Client's ask for word counts all the time, especially if they are getting content translated. Usually I copy the text into Word document and do a word count from there but this was proving too time consuming.

A quick search online and I stumbled onto a small program called 'Count Anything'. It's a free program for Windows users that allows you to drag any supported file onto it and it lets you know the number of words and characters in the document. Very handy!

I love finding programs like this. If you know of any other neat little programs you use day to day let me know.

Microsoft.ACE.OLEDB.12.0' provider is not registered on the local machine

I was working recently on an import script that would allow the end user upload an excel file, read it and import the data. Everything worked great on my own computer but when I ran the project on our Windows Server 2003 the project would fail when attempting to open the .xlsx file. The error returned to me was:

Microsoft.ACE.OLEDB.12.0' provider is not registered on the local machine

Obviously the server was missing the component required to read in a xlsx excel file. To solve this issue you need to download the 2007 Office System Driver: Data Connectivity Components onto your server. No server restart is required to install this tool and once it is installed everything will work as expected and your .net project will be allowed open and read .xlsx files.

RTE News Reader for Windows Phone gets a new update

Just a quick post to say that my RTE News Reader app for Windows Phone has been upgraded to version 1.6. This new version fixes a small bug that prevented users from re-read the same article after they returned to the article from IE. The big improvement for this version is that the app now displays the content from rte.ie within it. I don't open up the web browser in a separate window anymore.

This proved a little tricky to do as it meant I had to scrape the site and parse the HTML. I did this by using the excellent HTML Agility Pack for Windows Phone. The one gotcha here was that I had to make sure I encoded my web calls correctly. The default encoding was making Irish words or euro symbols come out all weird.

It's great to get another release of this app out the door. Hopefully you'll like it!

There is already an open DataReader associated with this Command which must be closed first

I was working on one of my Entity Framework Code First websites the other day when I noticed the following error being returned to me:

There is already an open DataReader associated with this Command which must be closed first

Doing a few searches online I could see some of the solutions were to include the parameter 'MultipleActiveResultSets=True' in your entity framework setting in the web.config. However, when I checked my web.config to look for this setting I noticed that I did actually have it all setup as expected.

Doing some more digging around I noticed that the cause for this issue is down to an issue with deferred execution in some of my queries.

The solution was to add a simple .ToList() at the end of my query.

A simple fix but one that drove me nuts for a while!

Workaround for the PDFSharp error: Cannot handle iref streams

[July 09 2012 Update] As some people have emailed and commented, another option to work around this solution is to plugin iTextSharp and use that for opening PDFs older than ver 5. The workaround can be found over on the PDFSharp forums http://forum.pdfsharp.net/viewtopic.php?f=2&t=693#p5855. I decided against this option myself as it would have required me to install and setup another third party library which I didn't want to do.

[Original Article]

I use PDFSharp with my ,net projects as a great way to produce invoices for our online stores. Some of our customers supply us with blank PDFs and we use these as templates when generating a new invoice.

I was given a PDF recently that was encoded using Adobe Acrobat 9. Normally we don't have any issues but this file was throwing the following error any time I wanted to open it:

cannot handle iref streams. the current implementation of pdfsharp cannot handle this pdf feature introduced with acrobat 6

It turns out that the encoding a PDF form above ver 5 gives PDFSharp a bit of a headache. The solution for us was to simply re-save the file with Adobe Reader v5 format. We were able to do this using Adobe Acrobat or Photoshop.

Apply a different ASP.NET runtime to your website without restarting IIS 6

If you have ever had to change the default asp.net runtime in IIS 6 you might have noticed that it warns you about restarting all of the other websites before it can be applied. On small servers with a handful of sites it's not a big deal. If you have a server that runs a lot of mission critical stuff it's more of a hassle.

Luckily there is an easy workaround for this. All you need to do it use the command line to specify the asp.net runtime you want to target and the IIS identifier you want to apply it to. So once you have setup your website in IIS open up the command prompt and type in:

C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis -s w3svc/123456789/root -norestart

Simply replace the 123456789 numbers with the identifier value for your website. Usually this value is on the same line as your domain name in IIS 6. If it's not you can add the Identifier column from View -> Add/Remove.

The line should make sense just by looking at it. The first part is specifying the asp.net runtime you want to target (asp.net 4 in this example) next up we have the IIS identifier followed by a no restart flag.

It's a shame that you even have to do this at all but at least the option is straightforward enough not to make it too much of a burden.

How to store additional details in your web session cookie

If you're using the ASP.NET membership you're probably aware that one of the things it usesto keep the user logged in can be a cookie. This cookie can be used to store additional details also to help you cut down on the database calls required for simple things like the user's name or email address.

You could write your own extension to handle the cookie creation and management but you might find it easier to use a third party library called FormsAuthenticationExtensions

This extension can be installed using Nuget: Install-Package FormsAuthenticationExtensions

Once installed you can use it very easily by adding the following code to your application where the user's is being logged in:

using FormsAuthenticationExtensions;

public bool Login(string userName, string password)
		{
            // handle your own logic to check the username and password and log in the user

            // if the login is successful, store some additional details into the session ticket
            if (User.Identity.IsAuthenticated)
            {
                var user = // make a database call to get this user's name and email address

                var ticketData = new NameValueCollection
                {
                    { "firstname", user.Firstname },
                    { "surname", user.Surname },
                    { "email", user.Email }
                };
                new FormsAuthentication().SetAuthCookie(userName, true, ticketData);
            }

            return loggedIn;
		}

As you can see the above code will take the user's email and name and store it along with the session cookie.

To read the values from the cookie in your MVC controller you can use something like this:

using FormsAuthenticationExtensions;

public ActionResult MyContactDetails()
        {
            // get the email from cookie
            var ticketData = ((FormsIdentity)User.Identity).Ticket.GetStructuredUserData();
            var emailFromCookie = ticketData["id"];

            return View();
        }

Or if you want to display the cookie details in your razor view you can do this:

@using FormsAuthenticationExtensions;
@{
    var ticketData = ((FormsIdentity)User.Identity).Ticket.GetStructuredUserData();
}

email : @ticketData["email"] 

Finally, if you need to update any of the details in the cookie (for example, if the user updates their email address) you can simply do something like this:

using FormsAuthenticationExtensions;

[HttpPost]
        public ActionResult MyContactDetails(ViewModel model)
        {
            // check cookie for data
            var ticketData = ((FormsIdentity)User.Identity).Ticket.GetStructuredUserData();

            if (ModelState.IsValid)
            {
                // update some of the cookie information with the new data
                ticketData = new NameValueCollection
                {
                    { "firstname", model.Firstname },
                    { "surname", model.Surname },
                    { "email", model.Email }
                };
                new FormsAuthentication().SetAuthCookie(model.Email, true, ticketData);

                return RedirectToAction("MyContactDetailsSuccess");
            }

            return View(model);
        }

As you can see it's very easy to use and a great way of storing small data in your app to help cut down on database calls. You need to be a little careful with this and ensure that you only store the bare minimum of information here. Cookies can't be too large so if you have anything more than 3-5 additional string data types and you might want to look at using a Session value instead. You should also avoid storing any complex data types in your cookies.

How to create a symlink or symbolic link on Windows Server 2008 to help share folders

A symlink or symbolic link can be easily created in Widows Server 2008 to share a common folders or files amongst projects. Lets assume you have a folder in domain1.com called CSS and you want to share this folder with domain2.com. You could just upload the CSS folder into domain2.com but then you need to FTP and update the CSS folder in 2 places. If both sites are using the exact same CSS this could cause you issues over time as you might forget to roll out updates from one site to another.

Using Windows Server 2008 you could create a symlink to solve this issue. Once you have the CSS folder created on domain1.com then you can run the following command from the command line on the server to create a symlink:

MKLINK /D C:\inetpub\wwwroot\domain2.com\CSS C:\inetpub\wwwroot\domain1.com\CSS

The format of the above is: MKLINK [new directory] [where to generate the new folder] [target folder you want the new link to go to]

If you're using Windows Server 2003 you can achieve something similar using:

fsutil hardlink create c:\foo.txt c:\bar.txt

There is a good answer on serverfault.com that covers this topic quite well - http://serverfault.com/questions/7109/how-do-i-create-a-symbolic-link-in-windows

How to import a large sql file using PHPMyAdmin on Windows Server 2008

By default you can import a sql file up to 2mb in size. Most of the time you will have a larger filesize due to all the content your website will be storing. There are 2 ways you can overcome this limitation. Either use the mysql command line (it really isn't that scary to use!) or increase the file upload limit in PHP.

First Option:

FTP up the sql file to the server.

Log into your server. Locate the file you just FTP'd and cut and paste it to the root level of your C:\.

Open MySQL command prompt by going to Start -> All Programs -> MySQL -> MySQL command prompt. A DOS like window will appear and as for the admin database password. Enter this and you will be logged into MySQL.

Now simply type: use databasename (where databasename is the name of the database you want to import into) and press enter

The prompt will let you know that you have switched to the database you entered.

Next type: source c:\filename.sql (where filename.sql is the name of the file you copied to the root level) and hit enter.

The database sql will now be imported by mySQL.

Second Option:

Use the steps in my PHP guide to increase the upload size allowed by PHP (about half way through the guide). This will let you upload larger files through the PHPMyAdmin panel.