Tuesday, 23 August 2016

The Naming and Shaming of programming tightwads

Let the Shame List begin


Just like the News of the World when they published their list of paedophiles, nonces and kiddy fiddlers I am now creating my own list of shame which will publicly list the many people who have contacted me and done any of the following:

1. Asked for a new feature to be developed for one of my Wordpress plugins that only they required. Then once I have delivered the upgrade they don't even say "Thank You".

In fact 9 out of 10 times I don't even get the smallest of donations even when I have been promised them beforehand. I have lost count of the people who email me promising to donate me money if only I do this or that but when I do it they seem to forget how to click that big yellow DONATE button in the plugin admin page.

Do these people really think I live only to serve their useless coding skills by implementing features they themselves are too unskilled to develop or too tight to pay for? Is this really what people expect from Open Source code? I don't mind if you cannot code and add the feature or fix the bug yourself but if you can't then at least have the decency to donate some money for my time. Is that too much to ask for?

2. The other group of people (and there are many) are those who email me at stupid times throughout the morning 4am sometimes - demanding that I fix their site immediately due to my plugin "not working".

In fact 99 out 100 times it is usually the case that they have either been a numpty and not followed or understood the instructions, deleted all or some of the files or haven't set the relevant permissions up correctly.

Not only do I try and make all my Wordpress plugins easy to use for the non technical to use by outputting detailed error messages that explain what they must to do to fix the problem but most plugins have a "Test Configuration" button on them that will run all the necessary tests and then list any problems as well as fixes for them.

If these people cannot even read and understand error messages such as "Filepath does not exist at this location" because they have been silly enough to delete that file or folder then why should I offer free 24 hour support for them?

Here's an idea. If I email you back with steps to fix your incompetence - donate me some money.

Believe it or not I don't help people out for fun or offer free 24 hour support for FREE products.

You get what you pay for! 

If you are too tight to offer to pay me to develop your custom feature or too tight to even donate the smallest amount when demanding (as I have had on numerous occasions) that I do X Y or Z by next Tuesday then why should I bend over to help you?

3. Then there are those companies (even some that have been big multi-nationals) that email me asking for relevant licences to be added to my downloadable scripts so that they can use them in their own projects. Probably projects that they will be making lots of money from by re-selling my code. Yet they refuse to donate even the slightest amount to the cause.

4. Finally and most important are the SEO Scammers, which you can read about more in detail here. They are advertisers who offer you money to post articles on your site yet when you do they then tell you that you will be paid in 20+ days. Why so long for so little money I have no idea. Yet on multiple occasions now I have been SEO Scammed where they fail to pay me my money but despite this, and me taking the article down. They have gained from the link juice passed along in links without rel="nofollow" on them and the site/domain authority.

It is very surprising how long PR Link Juice and authority stays around after the fact. Experiments we did showed that when setting up a pyramid system with one site at the top with zero links, and 100 or so with PR 4-6 all linking to that sites homepage. The top site zoomed up Googles rankings and even when we stopped the experiment the referrals from these sites (despite there being no links), stayed around in Google Webmaster Tools reports for months and months afterwards.

In future I am going to name and shame every person and company who carries out one of these actions on my blog. There are many other places you can do this on the web, darkweb and even Facebook https://www.facebook.com/moaningkeepstheGPaway/. So it is worth checking these places for names, emails and company addresses before doing any work with them.

A basic tech review is also advised to see where the company is based with a WHOIS and DNS search.

It might help those other developers considering open source development to realise that it's a dead end that causes more hassle than it's worth. If you think your going to get rich developing scripts that can easily be stolen, downloaded, re-used and modified then you are living in a fantasy world.

Let the shaming begin.

Just to let you know, since I started this list I have had quite a few people donate money and I have removed their names from the list. I am not heartless and I don't want people searching Google for their own name to find this page first.

Therefore you know what to do, pay me the money you owe me or make a donation.


Sebastian Long - This was an advertiser who offered a measly £60 for putting up an article (not exactly much) on my racing site for the Goodwood Sussex Stakes held in July. I posted the exact article he wanted and even added extra SEO to help him but he didn't want any of that so I took it out. Once he was happy he said I would be paid within 20 days -it would have been nice for him to tell me this before hand but I am too trustworthy, although that is slowly diminishing.. It's so far been over 20 days (and 20 working days), and I have not been paid. I have contacted him multiple times and have now taken the article down. However his name and his company ellipticalcontent.com will remain on the numerous SEO / Advertiser blacklists that I put him on due to his lack of respect in honouring a very simple contract.

Kevin Clark - who did not know how to set up a sitemap - "press the build button" and wanted help "fixing" issues that were not broken which I duly gave out. No dontation received.

Raymond Peytors - who asked about the now non supported pings to ASK or Yahoo - these have not been supported for sitemaps for a long time now. No donation recieved.

Mike Shanley - who did not seem to know how to read the "Read Me" text that comes with Wordpress plugins. On all my plugins I add a "Test Set-up" button which runs through the setup and displays problems and solutions for the user. The Read Me guide also explains how to run the Test when installing the plugin. Donation? Not on your nelly.

Juergen Mueller - For sending me an error message related to another plugin that he thought somehow was related to my plugin. This was due to the memory limit of his server/site being reached by said plugin.
Despite that he had all the details within the error message to fix it he still decided to email me for help. Despite me explaining how to fix the problem and steps he should do in future to fix problems I did not get a donation.

Holder Heiss - who even though he had read my disclaimer that said I don't give away support for free still asked me and received free help. He tried to motivate me to solving his problem with the following sentence

 "I understand that you are cautious about giving free support for your free software. Anyway as I like using and would like to continue using the google sitemap plugin, maybe I can motivate you to have a look on this topic reported by several users:"

Even though he had not donated me any money I still checked the system, upgraded my software and looked for a problem that I could not find - probably related to another plugin. You get what you pay for and he got at least an hours worth of support for free!

Pedro Galvez Dextre - Who complained about the error message "Sitemap Build Aborted. The Server Load was 4.76 which is equal to or above your specified threshold of 0.9" and asked what was wrong????

Cindy Livengood - who couldn't be bothered to read the Readme.txt file as they "bored her" even though they contained an example post which would show if the plugin was working or not.

There have been many other people but I only have so much time to go through my inbox.

By the way if your name is on this list or appears on it in future and you would like it removed then you know what to do - a donate button is at the bottom of each plugin, on my website, on my blog and many other places.

Please remember people - I have had a serious illness and I am still in lots of pain. Therefore I have stopped supporting my Wordpress plugins for this reason PLUS the lack of donations I have received.

I work at a company where I am charged out at £700 a day therefore a donation of £10 is not going to make me work for a day or two on a plugin that is open-source and should be taken as such.

You get what you pay for and I wrote these plugins for myself not for anyone else.

I put them up on Wordpress to see if anyone else found them useful. If you do not like them then use another plugin.

If you want professional support then be prepared to pay for it. If not read on and follow these basic debugging steps and use Google. That's how I had to learn LINUX and WordPress!

As stated in my Readme.txt file of my Sitemap plugin: http://wordpress.org/extend/plugins/strictly-google-sitemap/faq/


I have an error - How to debug

If you have any error messages installing the plugin then please try the following to rule out conflicts with other plugins
-Disable all other plugins and then try to re-activate the Strictly Google Sitemap plugin
- some caching plugins can cause issues.
-If that worked, re-enable the plugins one by one to find the plugin causing the problem. Decide which plugin you want to use.
-If that didn't work check you have the latest version of the plugin software (from WordPress) and the latest version of WordPress installed
-Check you have Javascript and Cookies enabled.
-If you can code turn on the DEBUG constant and debug the code to find the problem otherwise contact me and offer me some money to fix the issue :)
-Please remember that you get what you pay for so you cannot expect 24 hour support for a free product. Please bear that in mind if you decide to email me.
A donation button is on my site and in the plugin admin page. 
-If you must email me and haven't chosen to donate even the smallest amount of money please read this >> http://blog.strictly-software.com/2011/10/naming-and-shaming-of-programming.html 
-If you don't want to pay for support then ask a question on the message board and hope someone else fixes the problem.

But I need this or that and your plugin doesn't do it

Sorry but tough luck.

I wrote this plugin for my own requirements not anyone else and if you have conflicts with other plugins or require extra work then offer to pay me to do the development or do the work yourself.

This is what Open Source programming should be about.

I wrote this plugin as other Sitemap plugins didn't do what I wanted them to and you should follow the same rules.

If you don't like this plugin or require a new feature you must remember that you have already bought a good amount of my time for the princely sum of £0.

Hopefully the starting of the shaming will stop the influx of emails I constantly receive asking for help without donations.

Remember every one of my plugins has a donate button at the bottom of it and you get what you pay for!

Tuesday, 9 August 2016

Fun with Dates! Web Server, SQL Server, IIS and ASP Classic - Problems and Solutions

Fun with Dates! Web Server, SQL Server, IIS and ASP Classic - Problems and Solutions


By Strictly-Software

Dates can be a nightmare especially when moving servers.

A setup that ran perfectly on an old system can crumble up into a nightmare when the code and database is ported to a new server. I recently had this problem moving from a webserver connecting to database server to an all in one server based at the French hosting company OVH.

At first everything seemed okay then I started to notice the errors such as

1. Dates entered on a web page form as dd/mm/yyyy on submission coming back in US format e.g 22/08/2016 would come back as 8/22/2016 why there was no trailing zero I have no idea.

2. Primary Key / Index errors where the date was part of the key and it thought duplicates were being added into the system.

Good Practice

I always thought I ran good practice on my systems by doing the following but despite all these settings I was still getting US dates instead of UK dates shown on the website. However you should still do this as it limits the chances of error.

1. I ensure all Stored Procedures have SET DATEFORMAT YMD at the top and I store all dates as ISO format yyyy-mm-dd in the database.

2. All database logins used to pass information to the database are set to have "British English" as their "Default Language".

3. The database properties under options is set to British English.

4. The server properties under Advanced -> Default Language is set to British English.

5. On the website I always ask users and use client/server side validation to ensure they enter the dates as UK format dd/mm/yyyy.

6. I then convert that with a simple function into ISO format yyyy-mm-dd hh-mm-ss to pass to the stored procedure that saves the date. Having the SET DATEFORMAT YMD at the top of the stored procedure also helps to ensure SQL treats dates in that order Year - Month - Day etc.

I also always have on my site a Kill page which cleans out all session and application data e.g


<%
Application.Contents.RemoveAll()
Session.Contents.RemoveAll()
Session.Abandon()
%>


This is great if I need to wipe all stored info quickly especially as I have another page that gives me loads of Session, Application, Cookie and HTTP information. It also gives me much more including dates and times from the Web Server e.g NOW() and SQL Server e.g GETDATE() so I can check they are in sync.

I also show the default locale and currency formats. A simple version is below.


<%
response.write("<p>")
response.write("Default LCID is: " & Session.LCID & "<br>")
response.write("Date format is: " & date() & "<br>")
response.write("Currency format is: " & FormatCurrency(350))
%>


The LCID stands for the Server Locale and you can set it either in your Global.asa page if you use one or on the login page or in a global include that all pages use. English - United Kingdom has a value of 2057, the USA is 1033. You can read more about the locales here.

The result I got from my test page was

Default LCID is: 2057
Date format is: 09/08/2016
Currency format is: £350.00

This is all correct.

I have never had to resort to setting the Session.LCID on the website before and the Web Servers globalization settings were set the to the UK. This made it all the more stranger that I was getting US dates.

However I followed ALL of the steps below apart from the last step - which really is a last resort and it fixed the issue. It really is a shame that there isn't just one place where you can set your region and date formats that affects SQL and your Website but there just isn't.

Maybe a clever programmer could write something that would burrow away into all the servers settings and give you a report of what needs changing?

I already have a console .NET app that I run from a command prompt on any machine that tells me whether I can connect to the DB with specific ADO connection string params and LOCALHOST. It returns information about SQL logins, security such as access to extended stored procedures and any collation differences if there are any. It also shows me installed memory and disk space, used memory and disk space, all connected drives mapped drives and user logon history. Plus it attempts to send out an email using LOCALHOST as the mail relay using no ports and standard ports.

It also checks that it can access the outside world with a WebHTTP request to obtain the actual IP address of the machine before doing a PING to Google to test for speed. If I had the time I would probably love to delve into a project to solve the date issue as it's one that just keeps cropping up on new servers.


Debugging, Tests and Solutions

Apart from the good practices which I listed above and resorting to setting Session.LCID = 2057 at the top of your ASP pages there are some other things to try.

1. Test that your ISO dates are actually being stored as ISO NOT US e.g 2016-09-08 could be the 8th August in the UK (or ISO), or 9th of July if stored as US format. Do this with a simple SQL statement and login to your database using the connection string properties your website would not as an administrator.

This way you are using the properties of the users login and you can compare the results with you logged in as admin and if they are out of sync you should re-check your login properties again.


SELECT TOP(20) Racedate as ISODate,CONVERT(varchar, Racedate,103) as UKDate,datepart(day,Racedate) as DAYPart,datepart(month,Racedate) as MONTHPart,datepart(year,Racedate) as YEARPart
FROM   RACES
ORDER BY Racedate DESC


This should show you how the date is stored as a string (as all dates are really floating point numbers that would make no sense in a select if you saw them), as well as how the database sees each part of the ISO date.

So the DAYPart column should be the right section of the ISODate and left section of the UKDate and the month should be in the middle.

2. Test that your database is using a British format to return data to the client by running this SQL.


SELECT name, alias, UPPER(dateformat) as DateFormat
FROM syslanguages
WHERE langid =
 (SELECT value FROM master..sysconfigures
 WHERE comment = 'default language')


If everything is setup correctly you should get results like below:

Name  - Alias  - Dateformat
British - British English - DMY

If you don't get your desired country format back then the issue could be purely on the SQL Server / Database so go back over the good practices to ensure the Server/Database and Logins all have British English (en-gb) as their Default Languages / Locales in any setting you can see.

If you know that dates were entered for today and they look like ISO Date format in the tables then run a simple SELECT with a DATEDIFF(DAY,Stamp,GETDATE())=0 clause to see if they are returned.

If they are then you know the dates are being stored in the DB correctly so the issue is probably due to the web server.

3. Some people say that you should store your dates in 6 columns, Year, Month, Day, Hour, Minute, Second but personally I don't think this level of normalization is necessary OR should be.

However if you only have a couple of places to change then it might offer a solution. However if you already have a big database with lots of dates being shown and entered it would be a lot of work to normalize like this.

4. Go into your web servers Control Panel and select Language. Then ensure all possible date formats, languages and locales are set to use your desired location e.g chose UK instead of US and ensure the date formats are dd/mm/yyyy not mm/dd/yyyy.

There should be an "Advanced" link on the left where you can set the order of preference related to languages there as well. You will need to restart the machine for these to take affect.

5. Follow these steps from your Control Panel so that all users get to use your own regional settings. It's just one more place regions and formats are set which should be looked at if you are having an issue.

  • Go to Control Panel.
  • Click Region and you will see a screen with 3 tabs (Formats, Location and Administrative).
  • Click Formats and choose the settings you prefer.
  • Click Additional settings.
  • Click Date tab.
  • Change Short date to desired format and confirm dialog. 
  • Click Location and choose the settings you prefer.
  • Click Administrative tab. 
  • For "Welcome screen and new user accounts", click copy settings. 
  • From the new window, click both checkboxes for "welcome screen and system accounts" and "new user accounts" (if you skip this step, you will still see the issue because IIS uses system account).
  • Approve all changes for Region by clicking OK on all open windows.
  • Open Command prompt, write iisreset and enter.
  • If you still don't see the changes try logoff and logon.
  • Or reboot.


6. Go into IIS and at Server level and Database level go into the .NET Globalization settings and change the options Culture and UI Culture to English (en). Even if you are using ASP classic it is still worth doing this.

7. Compare the webpages showing up the US dates in different browsers, FireFox, Chrome and IE for example. If there is a difference then it could be down to your browsers locale settings. You may have had an anti virus checker run and reset some browser properties without you knowing so it's worth a shot especially if you know that not everyone is seeing the same values as yourself.

8. If it really comes down to it and you cannot resolve the issue then you could wrap all your dates from any SQL returned to your web pages in a function that uses VBScript to split the day, month and year apart before putting them back together in the format you want.

An example is below. You can use the built in functions Day(val), Month(val), or Year(val) or DatePart("d",val) to get the part of the date out. This function also uses a quick easy way to append zeros onto single character numbers 1-9 become 01 or 09.

You will also see by this method whether or not the ASP code manages to select the correct part of the date out of the SQL column returned to you.

For example if you have a date of 12/08/2016 (where 12 is the day), and you use Datepart("d",dtDate), where dtDate is the variable holding 12/08/2016. Then you will see if you get back the correct value of 12 (UK) or 08 (US). If you get an issue like this then check all your web server settings.

Function CorrectDate(dtDate)
 Dim dDay, dMonth, dYear
 dDay = Datepart("d",dtDate)
 dMonth = Datepart("m",dtDate)
 dYear = Datepart("yyyy",dtDate)

 CorrectDate = QuickNoFormat(dDay) & "-" & QuickNoFormat(dMonth) & "-" & dYear
End Function



Function QuickNoFormat(intNo) 
 '* If the number is only 1 character long add a zero to the front e.g 8 becomes 08
 If IsNumeric(intNo) Then
  QuickNoFormat = Right(Cstr(Cint(intNo) + 100),2)
 Else
  QuickNoFormat = intNo
 End If
End Function

Hopefully by following the good practice guide you shouldn't run into problems but if you do the list of solutions should help you out. It did with my latest Windows 2012 server.

Let me know if this is of any help for you.


By Strictly-Software

© 2016 Strictly-Software

Friday, 8 July 2016

ISAPI URL Rewriting for ASP Classic on IIS 8

ISAPI URL Rewriting for ASP Classic on IIS 8


By Strictly-Software

I recently had to setup a dedicated server for some sites that we had to move from in-house hosting and outsource.

It was a move from Windows 2003 to a Windows 2012 server with IIS 8. 

As usual the person setting up the system was as useful as a glass hammer and I had to spend ages learning things outside my job description just to get the system to work.

Not only was the web server side of things a pain but he copies databases with a backup/restore method which means having to re-link all the users and logins, re-create MS Agent jobs, set execute permissions, trustworthy settings and install CLR assemblies and handle collation conflicts etc. All things I could do without!

As everything is so costly for Windows Hosting, licences for everything, moving the Helicon ISAPI .httpd.ini file was a no no due to the fees. Luckily you can install for free the IIS URL Rewrite Module and use that to replicate any rules you may be using.

IIS 8 is a lot different from IIS 6.5 which I was working on before but once you get the IIS URL Rewrite 2.0 component installed from Microsofts website you will see it (after restarting IIS), in the bottom section of each site in your IIS panel.

You can then use the GUI interface to create the rules which is a bit cumbersome when you are used to just knocking out regular expressions in a text file.

However it does make it easier for people not as skilled at writing regular expressions as they can choose the type of expression from a drop down, rewrite or redirect or abort request, but you can use the "Test Pattern" tool to ensure your rule will work.

This article is a great guide for people wanting to set up rules using the interface and it shows you the output which is a web.config file placed in the root of your site. It doesn't matter if your site is .NET or ASP classic the web.config rule will work as long as .NET is installed and enabled in IIS.

This means you can easily open up the file and edit it when adding rules.

A simple example which shows you some of the rules you can do is below. Remember as it's an XML file you need to HTML Encode any characters that may malform the XML such as angled brackets. This is where using the GUI Tool is useful as it will auto encode everything for you and tell you if the XML is valid.

This example starts with a simple rewrite rule for SEO to make /promo go to the page /promo.asp and then it has an SQL injection example and an XSS injection example.

Obviously all input should be sanitised anyway but it doesn't harm to have multiple rings of security. At the end is a list of common HTTP libraries to ban. These are the sort of user-agent that scrapers and script kiddies use. They often download the tools off the web and don't know how to OR forget to change the user-agent.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <httpErrors errorMode="Detailed" />
        <rewrite>
            <rules>                
  <rule name="Promo SEO to Promo" stopProcessing="false">
                    <match url="^promo$" />
                    <action type="Rewrite" url="/promo.asp" />
                </rule>
  <rule name="Login Reminder SEO to Login" stopProcessing="false">
                    <match url="^loginreminder$" />
                    <action type="Rewrite" url="/logonreminder.asp" />
                </rule>
                <rule name="RequestBlockingRule1 SQL Injection" stopProcessing="true">
                    <match url=".*" />
                    <conditions>
                        <add input="{QUERY_STRING}" pattern=".*?sys\.?(?:objects|columns|tables)" />
                    </conditions>
                    <action type="AbortRequest" />
                </rule>
                <rule name="RequestBlockingRule1 XSS" stopProcessing="true">
                    <match url=".*" />
                    <conditions>
                        <add input="{QUERY_STRING}" pattern=".*?(<svg|alert\(|eval\(|onload=).*" />
                    </conditions>
                    <action type="AbortRequest" />
                </rule>                
                <rule name="RequestBlockingRule2" stopProcessing="true">
                    <match url=".*" />
                    <conditions>
                        <add input="{HTTP_USER_AGENT}" pattern=".*?(?:ColdFusion|libwww\-perl|Nutch|PycURL|Python|Snoopy|urllib|LWP|PECL|POE|WinHttp|curl|Wget).*" />
                    </conditions>
                    <action type="CustomResponse" statusCode="403" statusReason="Forbidden" statusDescription="Access Denied" />
                </rule>        
            </rules>
        </rewrite>
    </system.webServer>
</configuration>


As you can see I am aborting the requests for hackers and bad BOTs rather than returning a 403 status code in all but the last example, and I am just doing it there to show you how a 403 is carried out.

The syntax is slightly different from normal .htaccess rules due to being inside the XML file and the properties that are specified but in reality if you know regular expressions you won't go wrong.

By Strictly-Software

© 2016 Strictly-Software