Wednesday, May 21, 2008

IWA Performance consideration

IWA (Integrated Windows Authentication) is a cool thing where users need to authenticate again if their computer is already authenticated to the Windows network. However if you have users in remote locations they might experience significant performance degradation with IWA turned on. The reason for this is IWA requests the browser to send its NTLM authentication key. There will be 2 401 (Unauthorized) responses before the 200 (OK) response.

This article by Matthew Langston explains how IWA works: http://confluence.slac.stanford.edu/display/Gino/Integrated+Windows+Authentication?decorator=printable. So I don't need to explain it again here.

Since you can't eliminate the 2 401 errors (That's the way IWA works), you can improve on performance by cutting down the amount of data transfered over the network. By default IIS is configured to send the standard HTML file when a 401 error occurs. You need to change the setting in the "Custom Errors" tab (in IIS website properties) and set the 401 errors to send default text message instead of the HTML file. This will reduce amount of data transferred from around 2KB to about 83 bytes. You will see substantial improvement in performance.

This article explains how to change the "custom Errors" properties (Your website setting maybe slightly different): http://support.microsoft.com/kb/817322/en-us

Peace!

Thursday, May 8, 2008

Coding Standards and Guidelines

I was asked to create a coding standards document where I work. Oh yeah, I did not do it because I love to do this kind of work. So I outsourced by job to my best friend Google ;-) I got several hits. I compiled a coding standards and guidelines document with the help my buddy. I would like to give it back to from where I got. So here it is:

Coding Standards



1. Introduction


Application developers need to adhere to certain coding standards in order to
enhance the readability and maintainability of the application.

Well written software offers many advantages. It will contain fewer bugs and
will run more efficiently than poorly written programs. Since software has a
life cycle and much of which revolves around maintenance, it will be easier for
the original developer(s) and future keepers of the code to maintain and modify
the software as needed. This will lead to increased productivity of the
developer(s). The overall cost of the software is greatly reduced when the code
is developed and maintained according to software standards.

This guide makes a distinction between standards and guidelines. Standards are
rules which programmers are expected to follow. Guidelines can be viewed as
suggestions which can help programmers write better software and are optional,
but highly recommended.


2. Internal Documentation Standards


If done correctly, internal documentation improves the readability of a software
module. A file containing one of more software modules should have comment block
at its beginning containing the following basic information:



  • The name of the author who created the file
  • The date the file was created
  • The author’s development group
  • Description (overview of the purpose of the modules)

Note that a module is a method, function, or subroutine.

Each module contained within the source file should be preceded by a block of comments showing the following:



  • The name of the module
  • The name of the original author (if the module author is different than the author of the file.)
  • The date the module was created
  • A description of what the module does
  • A list of the calling arguments, their types, and brief explanations of what they do
  • A list of required files and/or database tables needed by the routine, indicating if the routine expects
    the database or files to be already opened
  • Return values
  • Error codes/exceptions


3. Coding Standards


3.1 Indentation:

Proper and consistent indentation is important in producing easy to read and
maintainable programs. Indentation should be used to:


  • Emphasize the body of a control statement such as a loop or a select statement
  • Emphasize the body of a conditional statement
  • Emphasize a new scope block


Tabs should be used for indentation.



Examples:

/* Indentation used in a loop construct. */

for (int i = 0; i < number_of_employees; ++i)

{

   
total_wages += employee[i].wages;

   
if (total_wages > 1,000,000)

   
{

       
System.out.println(“Over one million”);

   
}

}



// Indentation used in the body of a method.

package void get_vehicle_info ( )

{

   
System.out.println ( “VIN: “ + vin ) ;

   
System.out.println ( “Make: “ + make ) ;

   
System.out.println ( “Model: “ + model ) ;

   
System.out.println ( “Year: “ + year ) ;

}




3.2 Inline Comments

Inline comments explaining the functioning of the subroutine or key aspects of
the algorithm shall be frequently used.



Inline comments should be used to make the code clearer to a programmer trying
to read and understand it. Writing a well structured program lends much to its
readability even without inline comments. The bottom line is to use inline
comments where they are needed to explain complicated program behavior or
requirements. Use inline comments to generalize what a block of code,
conditional structure, or control structure is doing. Do not use overuse inline
comments to explain program details which are readily obvious to an
intermediately skilled programmer.



3.3 Structured Programming

Structured (or modular) programming techniques shall be used. GO TO statements
shall not be used as they lead to “spaghetti” code, which is hard to read and
maintain



3.4 Classes, Subroutines, Functions, and Methods

Keep subroutines, functions, and methods reasonably sized. This depends upon the
language being used. A good rule of thumb for module length is to constrain each
module to one function or action (i.e. each module should only do one “thing”).
If a module grows too large, it is usually because the programmer is trying to
accomplish too many actions at one time.



The names of the classes, subroutines, functions, and methods shall have verbs
in them. That is the names shall specify an action, e.g. “getName”, “computeStatistics”.



3.5 Source Files

The name of the source file or script shall represent its function. All of the
routines in a file shall have a common purpose.



3.6 Variable Names

Variable shall have mnemonic or meaningful names that convey to a casual
observer, the intent of its use. Variables shall be initialized prior to its
first use. Variable names shall be defined in Pascal Case (e.g. getUserInfo,
setMemberProfile).



3.7 Use of Braces

In some languages, braces are used to delimit the bodies of conditional
statements, control constructs, and blocks of scope. Programmers shall use the
following bracing style:



for (int i = 0 ; i < 100; i++)

{

   
/* Some work is done here. */

}




Braces shall be used even when there is only one statement in the control block.
For example:

Bad:

if (i <= 0)

printf (“Positive number required.\n”);



Better:

if (i <= 0)

{

   
printf (“Positive number required.\n”);

}





4. Coding Guidelines



General coding guidelines provide the programmer with a set of best practices
which can be used to make programs easier to read and maintain.

4.1 Line Length

It is considered good practice to keep the lengths of source code lines at or
below 80 characters. Lines longer than this may not be displayed properly on
some terminals and tools.

4.2 Spacing
The proper use of spaces within a line of code can enhance readability. Good
rules of thumb are as follows:

  • A keyword followed by a parenthesis should be separated by a space.
  • A blank space should appear after each comma in an argument list.
  • All binary operators except “.” should be separated from their operands by spaces. Blank spaces should never separate unary operators such as unary minus,
    increment (“++”), and decrement (“—“) from their operands.
  • Casts should be made followed by a blank space.



Example:
Bad:
cost=price+(price*sales_tax);
Better:
cost = price + ( price * sales_tax );



4.3 Wrapping Lines
When an expression will not fit on a single line, break it according to these
following principles:

  • Break after a comma

    Example:

    fprintf ( stdout , “\nThere are %d reasons to use standards\n” ,
    num_reasons ) ;

  • Break after an operator

    Example:

    long int total_apples = num_my_apples + num_his_apples +
    num_her_apples ;

  • Prefer higher-level breaks to lower-level breaks

    Example:

    Bad:

    longName1 = longName2 * (longName3 + LongName4 –
    longName5) + 4 * longName6 ;

    Better:
    longName1 = longName2 * (longName3 + LongName4 – LongName5)
    + 4 * longName6 ;

  • Align the new line with the beginning of the expression at the same level on the previous line.

    Example:
    total_windows = number_attic_windows + number_second_floor_windows +
    number_first_floor_windows ;




4.4 Program Statements
Program statements should be limited to one per line. Also, nested statements
should be avoided when possible.
Examples:
Bad:
number_of_names = names.length ; b = new JButton [ number_of_names ] ;


Better:
number_of_names = names.length ;
b = new JButton [ number_of_names ] ;


Bad:
strncpy ( city_name , string , strlen ( string ) ) ;

Better:
length = strlen ( string ) ;
strncpy ( city_name , string , length ) ;



4.5 Use of Parentheses
It is better to use parentheses liberally. Even in cases where operator
precedence unambiguously dictates the order of evaluation of an expression,
often it is beneficial from a readability point of view to include parentheses
anyway.
Example:

Acceptable:
total = 3 – 4 * 3 ;

Better:
total = 3 – ( 4 * 3 ) ;



4.6 Coding for Efficiency vs. Coding for Readability
There are many aspects to programming. These include writing software that runs
efficiently and writing software that is easy to maintain. These two goals often
collide with each other. Creating code that runs as efficiently as possible
often means writing code that uses tricky logic and complex algorithms, code
that can be hard to follow and maintain even with ample inline comments.

The programmer needs to carefully weigh efficiency gains versus program
complexity and readability. If a more complicated algorithm offers only small
gains in the speed of a program, the programmer should consider using a simpler
algorithm. Although slower, the simpler algorithm will be easier for other
programmers to understand.

4.7 Meaningful Error Messages
Error handling is an important aspect of computer programming. This not only
includes adding the necessary logic to test for and handle errors but also
involves making error messages meaningful. Error messages should also be stored
in way that makes them easy to review.


 





Secure Coding Guidelines


Protecting access to your data source is one of the most important goals when
working on the security of your application. To help limit access to your data
source it is imperative to keep connection information such as Username,
Password, data source name, etc. private.


1. Read Only DB User


Applications code must connect to the database as a database user who has read
only access to the data and can’t update or change any data or objects. Only
where necessary (such as admin pages that require update or insert) connect as
another user who has limited privileges to write to only the required database
objects. Also strongly consider using Windows Integrated Authentication to
access SQL Server in your code. If it can’t be used for any reason, avoid
storing clear text password instead store the password encrypted.



2. Validating Inputs


Before using the HTTP inputs provided by end users in a database query, validate
them using regular expressions or other means. For example, the following
ensures that a userid value is an 8-character alphanumeric string.



[Visual Basic] Copy Code

Public Static Function ValidateUserid(inString As String) As Boolean

   
Dim r As Regex = New Regex("^[A-Za-z0-9]{8}$")

   
Return r.IsMatch(inString)

End Function



[C#]

public static bool ValidateUserid(string inString)

{

   
Regex r = new Regex("^[A-Za-z0-9]{8}$");

   
return r.IsMatch(inString)

}




Validating whether the input data is per our expectation reduces the risk of SQL
injection attacks substantially.




3. Using Parameters (Prepared Statements)


Parameters provide a convenient method for organizing values passed with a SQL
statement or to a stored procedure. Additionally, parameters can guard against a
SQL Insertion attack by ensuring that values received from an external source
are passed as values only, and not part of the SQL statement. As a result, SQL
commands inserted into a value are not executed at the data source. Rather, the
values passed are treated as a parameter value only. The following code shows an
example of using a parameter to pass a value.



[Visual Basic] Copy Code

'Retrieve CustomerID to search for from external source.

Dim custID As String = GetCustomerID()



Dim selectString As String = "SELECT * FROM Customers

                              
WHERE CustomerID = @CustomerID"



Dim cmd As SqlCommand = New SqlCommand(selectString, conn)

cmd.Parameters.Add("@CustomerID", SqlDbType.VarChar, 5).Value = custID



conn.Open()

Dim myReader As SqlDataReader = cmd.ExecuteReader()

'Process results.

myReader.Close()

conn.Close()



[C#]

// Retrieve CustomerID to search for from external source.

string custID = GetCustomerID();



string selectString = @"SELECT * FROM Customers

                        
WHERE CustomerID = @CustomerID";



SqlCommand cmd = new SqlCommand(selectString, conn);

cmd.Parameters.Add("@CustomerID", SqlDbType.VarChar, 5).Value = custID;



conn.Open();

SqlDataReader myReader = cmd.ExecuteReader();

'Process results.

myReader.Close();

conn.Close();


4. Keep Exception / Server Error Information Private


Attackers often use information from an exception, such as the name of your
server, database, or table to mount a specific attack on your system. Because
exceptions can contain specific information about your application or data
source, you can help your application and data source better protected by only
exposing information to the client that is required.



Use friendly error messages such as “Database Connection failed. Please contact
the Customer Support at support@company.com”. Do not display the server errors
or the Exception stack to the end user in production environments.

 

Saturday, May 3, 2008

Simple Oracle Export script

Here is a simple script to export a Oracle schema or full database. Of course there are better ways to backup Oracle database these days. But some time we just need to KISS (keep it simple silly).

Set mm=%DATE:~4,2%
Set dd=%DATE:~7,2%
Set yyyy=%DATE:~10,4%
exp system/password file=DMP\sysadm-%yyyy%-%mm%-%dd%.dmp compress=y owner=schema1 consistent=y log=logs\sysadm-%yyyy%-%mm%-%dd%.log

This puts the dump file in a folder called DMP and a log file in the logs folder under the current folder where the script runs with a timestamp in the file name.

Now I know you will ask me how to delete older backups. This link: http://blogs.msdn.com/benjguin/archive/2006/12/01/delete-old-files-script.aspx gives you a script to delete old files based on your needs. Just in case the link doesn't work, here is the script again (Thanks Benjamin):

Delete Old Files script

This sample script (WHICH IS PROVIDED AS IS) may help purging files older than n days in a folder

Just copy the following code to a VBS file (DeleteOldFiles.vbs).

Sample call:

cscript DeleteOldFiles.vbs C:\Windows\Temp 90

The code is:

option explicit

Call DoTheJob()
WScript.Echo "--- end of script execution ---"

Sub DoTheJob
dim limitDate
dim formattedLimitDate
dim folder
dim strComputer
dim objWMIService
dim colFileList
dim objFile
dim nbFiles
dim totalFiles
dim nbErrors
dim result
dim nbDays

if WScript.Arguments.Count <> 2 then
WScript.Echo "usage : DeleteOldFiles.vbs "
WScript.Echo "sample: DeleteOldFiles.vbs C:\Windows\temp 90"
Exit Sub
end if

folder = WScript.Arguments(0)
nbDays = WScript.Arguments(1)

'calculate and format limit date
limitDate = DateAdd("d", -1 * nbDays , Date)

formattedLimitDate = DatePart("yyyy", limitDate)

if DatePart("m", limitDate) < formattedlimitdate =" formattedLimitDate" formattedlimitdate =" formattedLimitDate">

if DatePart("d", limitDate) < formattedlimitdate =" formattedLimitDate" formattedlimitdate =" formattedLimitDate">

'show what will be done
WScript.Echo "Will remove files from " & folder & " with a date older than " & formattedLimitDate & " (" & nbDays & " days ago)"


'Get the files and delete the old ones
strComputer = "."

Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")

Set colFileList = objWMIService.ExecQuery _
("ASSOCIATORS OF {Win32_Directory.Name='" & folder & "'} Where " _
& "ResultClass = CIM_DataFile")

nbFiles = 0
totalFiles = 0
nbErrors = 0

For Each objFile In colFileList
totalFiles = totalFiles + 1
if objFile.CreationDate < result =" objFile.Delete()" result =" 0" nbfiles =" nbFiles" nberrors =" nbErrors">

'Show the result
Wscript.Echo "Total files in folder: " & totalFiles
WScript.Echo "Deleted files: " & nbFiles
WScript.echo "Errors: " & nbErrors
End Sub