Wednesday 31 October 2007

How to prevent browser and proxy caching of web pages

I ran into the issue of if the user presses the "BACK" button, the page does not refresh. So I placed the meta tag in the header:<meta equiv="CACHE-CONTROL" content="NO-CACHE">To attempt to resolve the issue. This fixed the issue for IE and other browsers. But firefox gave me a particular problem. They interpret this tag unlike the other browsers, thus not refreshing the page. After a bit of digging, I discovered this code: (Place in the OnInit block, prefereably)


Note, this is new code as of 8-31-06 Response.ClearHeaders();
Response.AppendHeader("Cache-Control", "no-cache"); //HTTP 1.1
Response.AppendHeader("Cache-Control", "private"); // HTTP 1.1
Response.AppendHeader("Cache-Control", "no-store"); // HTTP 1.1
Response.AppendHeader("Cache-Control", "must-revalidate"); // HTTP 1.1
Response.AppendHeader("Cache-Control", "max-stale=0"); // HTTP 1.1
Response.AppendHeader("Cache-Control", "post-check=0"); // HTTP 1.1
Response.AppendHeader("Cache-Control", "pre-check=0"); // HTTP 1.1
Response.AppendHeader("Pragma", "no-cache"); // HTTP 1.1
Response.AppendHeader("Keep-Alive", "timeout=3, max=993"); // HTTP 1.1
Response.AppendHeader("Expires", "Mon, 26 Jul 1997 05:00:00 GMT"); // HTTP 1.1 forces all browsers to grab new copies of the pages when the user pressed the BACK or FORWARD button on their browsers, which is quite annoying.

Parse delimited string in a Stored procedure

Sometimes we need to pass an array to the Stored Procrdure and split the array inside the stored proc. For example, lets say there is a datagrid displaying sales orders, each sales order associated with an orderid (PK in the Sales table). If the user needs to delete a bunch of sales orders ( say 10-15 etc)..it would be easier to concatenate all the orderid's into one string like 10-24-23-34-56-57-....etc and pass it to the sql server stored proc and inside the stored proc, split the string into individual ids and delete each sales order.
There can be plenty of other situations where passing a delimited string to the stored proc is faster than making n number of trips to the server.

CREATE PROCEDURE ParseArray (@Array VARCHAR(1000),@separator CHAR(1))
AS
BEGIN
SET NOCOUNT ON
-- @Array is the array we wish to parse
-- @Separator is the separator charactor such as a comma
DECLARE @separator_position INT -- This is used to locate each separator character
DECLARE @array_value VARCHAR(1000) -- this holds each array value as it is returned
-- For my loop to work I need an extra separator at the end. I always look to the
-- left of the separator character for each array value
SET @array = @array + @separator
-- Loop through the string searching for separtor characters
WHILE PATINDEX('%' + @separator + '%', @array) <> 0
BEGIN
-- patindex matches the a pattern against a string
SELECT @separator_position = PATINDEX('%' + @separator + '%',@array)
SELECT @array_value = LEFT(@array, @separator_position - 1)
-- This is where you process the values passed.
-- Replace this select statement with your processing
-- @array_value holds the value of this element of the array
SELECT Array_Value = @array_value
-- This replaces what we just processed with and empty string
SELECT @array = STUFF(@array, 1, @separator_position, '')
END
SET NOCOUNT OFF
END
GO


The credit for the above code : Mr Dinakar Nethi on his blog
http://weblogs.sqlteam.com/dinakar/archive/2007/03/28/60150.aspx

Thursday 25 October 2007

What is SQL injection attack?

"SQL Injection" is subset of the unverified/unsanitized user input vulnerability ("buffer overflows" are a different subset), and the idea is to convince the application to run SQL code that was not intended. If the application is creating SQL strings naively on the fly and then running them, it's straightforward to create some real surprises.

There have been instances of dropping a table, or displaying a list of users and their passwords, from the database using this kind of applications.

A simple example of such an attack, can be using a forget password page into a deadly display all records page.How? read ahead!

Usually the sites are used to generate SQL statements on the fly. So they will generate them as

SELECT fieldlist
FROM table
WHERE field = 'Textbox value';

Here the string that the user enters into the textbox of the page is substituted. So for a page that retrieves the password, the SQL statement would be:

SELECT password
FROM tblLogin
WHERE userid = 'txtUserID.Text.ToString()';

So if we enter abc into the text box, it is passed on to the server as

SELECT password
FROM tblLogin
WHERE userid = 'abc';

Now if we want to gain unauthorised access to the table all we have to do is enter some malicious code into the text box. Watch it now!

If we enter anything' OR 'x' = 'x what happens? The resultant query will be:

SELECT password
FROM tblLogin
WHERE userid = 'anything' OR 'x' = 'x'

Did you just say wow??? So next time you are designing some form, keep this thing in mind to check if the text input in the text boxes, does not complement any inbuilt sql query. You have been warned!

Wednesday 3 October 2007

Could not load type '****' from assembly'****, Version = 0.0.0.0, Culture=neutral, PublicKeyToken=null'

I was on a maintainence call this morning, and there was a minor problem to a certain page. I wont run into what the problem was, as it is out of context. After I was done with the bug, I swiftly published the project, and uploaded the project on to the live server. because I did not make any drastic changes to the project, out of habit, I just rolled the web.config file to the original settings, as to prevent typing the connection string for the database back again.

I made sure everything was working and in place and uploaded the project on to the live server! Bingo! Everthing was fine on the site and even for extended site testing on the links and database connection, it worked fine. The bug was resolved, and time to hit the next job!

Then towards the end of the day, I received a couple of mails regarding the web-parts section of the page is bugging up! I clicked the link on that page and it gave me this error:

Could not load type '****' from assembly'****, Version = 0.0.0.0, Culture=neutral, PublicKeyToken=null'

I could not figure out what exactly the problem was as, the version on the development server was still working smoothly. There was no other problem to the site, apart from web-parts. so what went wrong?

I tried to hit Google for the same topic, but to my amazement, there were many people out there who faced the same problem many a times, there was not a single solution, that explained the cause of the error. The closest I got was at www.dotnet247.com where the author said that there was some issue with app.config file, which he tried to reuse in another project. But I am not trying to reuse any file in a different project. It is necessarily the same project, with a couple of html and vbscript lines added to a page.

So in principle I am suppose to be able to update the project straight away! Me and my collegue, set on the journey to discover what is going wrong! I started doing all sort of permutations for the settings. After a while I had a thought, why not try to change the web.config file on the local copy and then publish the entire project to the live server, instead of replacing the web.config file!

I did that, and miracles do happen! The project started working at its best again. But the best thing was that instead of stopping after the problem was solved, I kept trying all the possible change, just to make sure, it was no fluke, and indeed it wasnt one.

So I figured out that even if there are minor changes to the site, do not recycle any files straight out of the pile. The second issue that has come to my mind now, is that if I can just change a single file from the published result! Will get back as soon as I have enough to write about that; till then happy programming!