Willem's...

{rue if I mellow}

  Home  |   Contact  |   Syndication    |   Login
  24 Posts | 0 Stories | 93 Comments | 78 Trackbacks

News

Archives

Post Categories

Businessware Architects

Sunday, October 30, 2005 #

An interesting adventure - if anyone is interested in how to do this contact me. We used the following devices:

  • SAGEM MSO-series fingerprint reader
  • pcPRox RFID reader
  • ADAM primarily, with some AD integration to hold the fingerprint-minutae data

    What made this interesting was writing the application entirely in 'Unmanaged' C++ and integrating the SAGEM SDK (MorphoSmart API) and the pcProxlib API SDK. Both these APIs are provided as native C++ DLLs and ultimately drove our decision to go the complete C++ route. Some useful techniques for using the ADSI ('ADs...') calls and the various AD/AM COM objects was (painfully) learnt.

    We are currently building a C#-interop wrapper for the various SDKs to make life a lot easier...


  • We needed to write an application that would automatically execute a time-out action, the time-out being a prescribed length of time that has expired without any user input occurring during that period.

    Not as easy as it sounds.  One way to do it is to setup a set of system-hooks using the message hook APIs provided by Win32.  I personally did not like this approach for the following reasons:

    • Using system-hooks is intrusive and reduces overall system performance.
    • Its more work, because the hooks provide callbacks for all the windows/processes running and they would have to be filtered.
    • There may be security and credentials constraints setting system-wide hooks while running the application as a user with certain permissions.

    I discovered a little gem: the Win32 (user.lib) GetLastInputInfo function which returns a data structure containing the system tick-count when the last user input was detected. User input is defined as any captured mouse event or application keyboard event.  One problem with this very easy to use function is that if specific inputs have to recognized, eg only mouse events, this function cannot be used.

    The following code-excerpt provides a means of detecting an application user-input idle timeout.  The example is an MFC application, and uses a timer event to periodically poll for the last user input time:

    void CMyWindow::OnTimer(UINT nIDEvent)
    {
        // timer event for polling for user-idle timeout.
        if(nIDEvent == TIMEOUT_TIMER_ID)
        {
            // Get the last input event info.
            LASTINPUTINFO li;
            li.cbSize = sizeof(LASTINPUTINFO);
            ::GetLastInputInfo(&li);
            // Calculate the time elapsed in seconds.
            DWORD te = ::GetTickCount();
            int elapsed = (te - li.dwTime) / 1000;
            // Test against a preset timeout period in
            // seconds.
            if(Application()->TimeOut() < elapsed)
            {
                // Call a function or set an application flag
                // that can be acted on outside this function.
                OnTimeout();
            }
        }
        ..
    }

    BTW, this API is only available in WIN 2000 onwards - correct your stdafx.h file as follows, to ensure correct compilation and linking:

    #define WINVER 0x0500
    #define _WIN32_WINNT 0x0500

    This means: forcing a page postback or redirect from a client browser without explicit user input.

    Why would you want to do that? The main reasons are:

    • Auto-redirecting to a new URL after a brief time period
    • Refreshing page information periodically
    • Maintaining a valid session state indefinitely
    • Forcing a specific process to run on the server when the client session has expired.

    The following methods are the constructs we have used in our web development projects:

    HTML header refresh tag

    The most common and best known way - a tag of the following format is placed in the HTML section of the page:

    <meta http-equiv="refresh" content="8;url=http://dotnet.org.za/">

    • where '8' refers to the number of seconds that will elapse before the page is refreshed;
    • 'url' is the new url redirect to. It can be excluded which means the current page will be reloaded.

    This construct is useful if you have one or two pages which have to auto-refresh, and works for any HTML content type forms.  The downside is the refresh interval cannot be set dynamically, and if you are testing for session timeouts on your site, you'll have to embed this construct in every page of the site.

    Response.AppendHeader method

    ASP.NET provides the AppendHeader method to the Response object. Typically the page refresh can be set as follows in an ASP.NET webform (in C#):

    this.Response.AppendHeader("Refresh",
        Convert.ToString(Session.Timeout * 60 + 5));

    Here the page refresh is set to 5 seconds after the client session timeout setting specified in the web.config file.

    This construct is useful as it can be placed in a base webform OnLoad() or Page_Load() response method. All derived webforms will then have the same page refresh setting when they are loaded. Obviously, if the timeout value is changed in the web.config file, no modification is required in this code and everything still works fine.

    Page OnLoad method script

    The same thing can be done by setting a script for the client-side HTML using the HtmlGenericControl.Attributes collection:

    string onload = "window.setTimeout(
        'window.location.href=window.location.href'," +
        Convert.ToString( (Session.Timeout * 60 + 5) * 1000) + ");";
    this.body.Attributes.Add("onload", onload);

    Unfortunately, to get this to work you need to add the following attribute to the tag in the HTML:

    runat="server"

    and the following member in the webform code-behind class:

    protected System.Web.UI.HtmlControls.HtmlGenericControl body;

    Hmmm - so why do this, if it means that we have to fiddle with the HTML?

    In our experience, certain ASP.NET controls in the webform actually kills the working of the previous two constructs - but this method always seems to work....regardless...in Internet Explorer...

    In future posts, I will look more closely at managing ASP.NET session timeouts with re-logins for secured sites.


    Recently I wanted to setup up an RSS feed reader and blog item display window on our website. In order to do something different (and because I'm inherently lazy), I thought it would be cool to use Microsoft's XSD.EXE tool to gen. the classes from an XML schema for RSS 2.0, write a bit of code around this and use it on our site. My primary interest was to consume the RSS feeds coming off various sites and use the blog channels I was interested in.

    So, the tasks that needed doing were:

    • Validate the feeds as RSS 2.0 conformant

      I found a useful website at http://feedvalidator.org/ that allows you to submit RSS feed url's and reports on their conformance. Except for some minor issues, the feeds from today's modern blog sites are usually conformant (phew)! 

    • Find an XSD that works

      This is an issue, as there appears to be more than one 'standard' for the RSS 2.0 XML format.  After plugging many of these XSD's into XMLSpy and validating against the rss feeds, I found an XSD that worked and against which the stream can be validated. The XSD can be downloaded here: http://www.thearchitect.co.uk/schemas/rss-2_0.xsd.

    • Generate the code classes and deserialize the RSS stream

      Also an issue. XSD.EXE generates code incorrectly when a choice-item includes an enumerated type. The XmlChoiceIdentifierAttribute serialization attribute causes the reflection of the classes to fail! So what appeared to be the easy way to read RSS streams was becoming more difficult. This was resolved (and could easily be the subject of a meaty article). You can download my working code here. The cool thing about this code is that it should be very easy to generate RSS 2.0 conformant XML streams without much added code.

    The working code contains both the original code-class file generated by XSD.EXE and the modified file (which works). The basis for these manual fixes can be found here:

    Implementing XML Key Management Services Using ASP.NET  ('The XKMS Object Model' section)

    Watch this space - I intend getting our CodeXS code generator working correctly with this schema and producing a fully-fledged RSS 2.0 serializer....(soon-ish!)


    [South African Specific]

     

    If you would like to check your SA Passport or ID application status, or your current official marital status, please click on the link below:



    An enigmatic quest indeed, with no definitive standards published by any SA government department known.  The following blogs show the basics for validating SA Identity numbers:

    http://www.vanjaarsveld.com/default.aspx
    http://codingsanity.blogspot.com/2004/10/id-validation.html
    http://www.powertrip.co.za/blog/archives/000007.html
    http://www.powertrip.co.za/blog/archives/000135.html

    Here's my interpretation and short code-excerpt for validating 'digit-13', the so-called 'check' digit:

    Format:
    {YYMMDD}{G}{SSS}{C}{A}{Z}
    YYMMDD : Date of birth.
    G  : Gender. 0-4 Female; 5-9 Male.
    SSS  : Sequence No. for DOB/G combination.
    C  : Citizenship. 0 SA; 1 Other.
    A  : Usually 8, or 9 [can be other values]
    Z  : Control digit calculated in the following section:
     
    Formula to calculate the check digit for a 13 digit identity number:

    According to the provisions of the Identification Amendment Act, 2000 (Act No. 28 of 2000,
    which was promulgated on 13 October 2000) all forms of identity documents other than the
    green bar-coded identity document are invalid. [my observation: the following algorithm appears to work for the older 'blue'-book id numbers as well].  In accordance with the legislation,
    the control figure which is the 13th digit of all identity numbers which have 08 and 09 is
    calculated as follows using ID Number 800101 5009 087 as an example:

    • Add all the digits in the odd positions (excluding last digit).
        8 + 0 + 0 + 5 + 0 + 0 = 13...................[1]
    • Move the even positions into a field and multiply the number by 2.
        011098 x 2 = 22196
    • Add the digits of the result in b).
        2 + 2 + 1 + 9 + 6 = 20.........................[2]
    • Add the answer in [2] to the answer in [1].
        13 + 20 = 33
    • Subtract the second digit (i.e. 3) from 10.  The number must tally with the last number in the ID Number. If the result is 2 digits, the last digit is used to compare against the last number in the ID Number.  If the answer differs, the ID number is invalid.

    Here's the digit-13 check C# code
    [Check below for a validator using a working version of this code]
    :

    // This method assumes that the 13-digit id number has
    // valid digits in position 0 through 12. 
    // Stored in a property 'ParseIdString'. 
    // Returns: the valid digit between 0 and 9, or 
    // -1 if the method fails. 
    private int GetControlDigit()
    {
      int d = -1;
      try
      {
        int a = 0;
        for(int i = 0; i < 6; i++)
        {
          a += int.Parse(this.ParsedIdString[2*i].ToString());
        }
        int b = 0;
        for(int i = 0; i < 6; i++)
        {
          b = b*10 + int.Parse(this.ParsedIdString[2*i+1].ToString());
        }
        b *= 2;
        int c = 0;
        do
        {
          c += b % 10;
          b = b / 10;
        }
        while(b > 0);
        c += a;
        d = 10 - (c % 10);
        if(d == 10) d = 0;
      }
      catch {/*ignore*/}
      return d;
    }

    SA ID Validator