Thursday, November 24, 2011

Perl CGI on IIS

This is just a note to myself, as I tend to forget how to do this...

Install the IIS CGI module: Control Panel, Programs and Features, Turn Windows Features On or Off...

Enable CGI in IIS:
  • Open IIS Manager
  • Select server
  • Double click ISAPI and CGI Restrictions
  • Click Edit Feature Settins...
  • Check Allow unspecified CGI modules (or enter the specific ones you want)
Set handler mappings:
  • Select site
  • Open Handler Mappings
  • request path: *.pl
  • executable: C:\strawberry\perl\bin\perl.exe "%s" %s
  • name: CGI script

Monday, October 17, 2011

WRVS4400N v2 VPN configuration

I have a WRVS4400N V2 Wireless-N Gigabit Security Router with VPN from Cisco Small Business.

This box has many features but they do not include an ADSL interface. For that I have a Linksys AG300 DSL Modem / Router.

What I couldn't find documentation on is how to configure these two devices to be able to establish a VPN connection from the Internet. But, after much trial and error I have it working.

The AG300 has been serving our office LAN for several years and I didn't want to disrupt any existing configuration or services.

I connected the WAN port of the WRVS4400N to a port on our LAN - via a switch to one of the AG300 LAN ports. The WRVS4400N WAN port picked up an IP on our LAN from the DHCP server on the AG300.

I set the WAN port MTU configuration to Manual (Setup, WAN) and MTU size to 1000. This on the basis that the VPN traffic will be tunnelled so the MTU better be less than 1500. 1000 is no doubt lower than necessary but I didn't want failure for the sake of a few bytes. I can tune it up later.

I set the timezone and enabled daylight savings time, with the default NTP server(s).

I set up the wireless network, though this is probably irrelevant at this point. My testing was all with wired systems. All I did was set an SSID Name for SSID1 (Wireless, Basic Settings), and set security mode to WPA2-Personal Mixed and a Shared Secret (Wireless, Security Settings).

IPSec VPN I left disabled (default).

I created one VPN Client Account: a username and password and left Allow User to Change Password at default: no.

I generated a certificate and exported for client.

I changed the admin account password.

I did all this from a laptop plugged into one of the LAN ports on the WRVS4400N. The laptop picked up an IP from the DHCP server on the WRVS4400N on the default 192.168.1.0/24 network.

I then downloaded and installed the QuickVPN client from http://www.cisco.com/en/US/prod/routers/quick_vpn.html. I was using a laptop running Windows 7 64bit for testing, so I downloaded WRVS4400N Wireless-N Gigabit Security Router - VPN V2.0. I ran setup as administrator and accepted all defaults. The laptop was in a workgroup, not a domain member on our LAN.

I copied the WRVS4400N certificate to the QuickVPN folder (C:\Program Files (x86)\Cisco Small Business\QuickVPN Client.

I connected the test client (with QuickVPN) to our internal LAN and configured a QuickVPN profile to access the WRVS4400N directly (ie at its internal WAN port address, thus not traversing our Internet DSL modem / router). This connected successfully and I was able to RDP to a test system on the LAN side of the WRVS4400N - success!!! of a sort.

Next I created a new QuickVPN profile, the same as the first except for specifying the external address of the AG300 (i.e. our public / Internet IP address). I tried to connect and this failed.

The failure wasn't too surprising. There was nothing on the AG300 that would allow the connection attempts to reach the WRVS4400N WAN port. Unfortunately, the WRVS4400N documentation said nothing other than to configure our DSL router / modem according to instructions from our ISP and our ISP knows nothing of the WRVS4400N, VPNs or anything else they don't supply and almost nothing about what they do supply, so I didn't even bother calling them.

After some searching I found a post (https://supportforums.cisco.com/thread/2108785) indicating that some ports should be opened on the DSL modem / router and that this sometimes works, though it is an unsupported configuration (cryptic comment about there should only be one gateway). Anyway, I added ports 443, 500, 4500 and 60443, all TCP, to the port forwarding list on the AG300, all forwarded to the WRVS4400N WAN interface, but still no luck.

Then I got out the sniffer and compared the successful internal connection with the failing external connection and noted that the internal connection had an exchange on UDP port 500 and the failing one had inbound packets to that port but no replies. So, I forwarded UDP port 500 as well and finally got a VPN connection via the external interface of the AG300. Success at last!! I had almost given up.

Saturday, May 21, 2011

Doc Watson - Deep River Blues

I'm trying to learn Deep River Blues, as played by Doc Watson and others. There are lots of great videos on YouTube, including:

http://www.youtube.com/watch?v=cE2swkx9WXE&feature=related

http://www.folkways.si.edu/albumdetails.aspx?itemid=3105

Sunday, May 15, 2011

Ewan Dobson is awesome

I just stumbled on YouTube videos of Ewan Dobson - fingerpicking acoustic guitar. worth a listen if you haven't heard him.

Saturday, April 16, 2011

Competitiveness Vs Productivity

I was reading a series of articles on competitiveness, with a focus on declining US competitiveness: America's tech decline: A reading guide, and it occurred to me that a focus on competitiveness may be misguided, and that a focus on productivity might provide better guidance.


The focus on competitiveness identifies winners and losers. It creates a context in which local relative advantage is preferred over global absolute advantage. Monopolies are favoured, to capture benefit locally, despite their reducing the total benefit obtained from the set of resources monopolized. Actions which decrease the competitiveness as others are promoted as legitimate means to "win" the competition.

A focus on productivity, on the other hand, would admit the possibility that we can all be winners. Decreasing productivity in other areas would, generally, not increase local productivity. Therefore, there would be less incentive to use resources sub-optimally.

There are ample and inevitable reasons for competition. World population is increasing rapidly while the supply of many primary resources is limited. Without increases in global productivity, global population growth cannot be supported. Current trends suggest a deteriorating situation for most people, with only those who are ruthlessly competitive being able to improve their situation. There is no shortage of people who are so competitive, and there is no morality in large corporate bodies - the corporations are far more ruthless and competitive than any of the individuals.

A focus on productivity would suggest curbing some of the more immoral behaviours of large organizations and promote an effective balance between socialism and central control on the one hand, and individualism, capitalism and free markets on the other hand. Extremes in either direction have been unstable and ultimately undesired in the long run, with all the best societies having a mixture of capitalism and socialism, personal liberty and central management.

If we can't have sufficient for everyone, we are destined for strife and conflict, potentially and, as resources become more limited, almost certainly brutal. If we can have ample for everyone, then there will be no compelling need for competition, and only our basic character (competitiveness, greed and envy are very common traits) to cause such strife. To have ample for everyone, we must increase productivity and distribute what is produced so everyone has a sufficient (ample) share.

Promoting competitiveness and making others lose may yield fantastic local benefits in the short term, but in the long run it may not be the best strategy.

Thursday, March 24, 2011

Render SQL Server Reporting Services report as a PDF file

We have various reports developed using SQL Server Reporting Services. In some cases we want to provide our users with PDF versions of the reports without them having to navigate the Report Server website. For these purposes, it is convenient to produce a PDF file and send it by email or save it to a share.

I thought it would be easy, but it wasn't so. It took many hours to get a program working that would access our report server and save a report to disk as a PDF file. The following program worked:

Module Module1



    Sub Main()

        Dim format As String = "PDF"

        Dim fileName As String = "C:\temp\test.pdf"

        Dim reportPath As String = "/Project1/Report1"



        ' Prepare Render arguments



        Dim myCredentials As New NetworkCredential(userName:="USER", password:="password")



        Dim rs As ReportExecutionService = New ReportExecutionService()

        rs.Credentials = System.Net.CredentialCache.DefaultCredentials



        Dim historyID As String = Nothing

        Dim deviceInfo As String = Nothing

        Dim extension As String = Nothing

        Dim encoding As String = Nothing

        Dim mimeType As String = Nothing

        Dim warnings() As Warning = Nothing

        Dim streamIDs() As String = Nothing

        Dim results() As Byte





        rs.LoadReport(reportPath, historyID)



        results = rs.Render(format, deviceInfo, extension, _

         mimeType, encoding, warnings, streamIDs)



        ' Open a file stream and write out the report

        Dim stream As FileStream = File.OpenWrite(fileName)

        stream.Write(results, 0, results.Length)

        stream.Close()

    End Sub



End Module


I compiled this program using Visual Studio 2010 Express edition. The report server is part of SQL Server 2008 Enterprise Edition.

Within Visual Studio I had to create a reference to a web resource. This is a bit tricky... I don't have VS in front of me now, but I opened the project settings, selected resources (or something like that) and drilled down through advanced settings until, way at the bottom of one of the pop-up screens, there was an "Add Web Resource" button (or something like that). There I entered the name of our report server. Something like:

http://server/reportserver/reportexecution2005.asmx?wsdl
I don't know if the "?wsdl" is necessary. Some posts said it was and this is the URL I was using when I finally got it working. More to test, if I wasn't already many hours behind schedule.

This (reportexecution2005.asmx) works despite the server being SQL Server 2008 and Visual Studio being 2010. All the sample VB code I could find used something called "rs" without declaring or initializing it. None of those posts said anything about where it came from or what versions of tools the code worked with. I stumbled upon ReportExecutionService() quite by accident, and cobbled together working declaration and initialization by trial and error and by following a few hints here and there on the Internet.

There is lots left to learn and understand, but in the mean time, the above is working for me.

Friday, February 18, 2011

perl/tk mega-widget configuration

perldoc Tk::ConfigSpec says if where is set to SELF then "apply configure to the core widget" but it doesn't explain how to make it work. I started with a skeleton widget:
package Tk::Test;

use strict;
use warnings;

use base 'Tk::Frame';
Tk::Widget->Construct('Test');

sub ClassInit {
    my ($class,$mw) = @_;
    $class->SUPER::ClassInit($mw);
}

sub Populate {
    my ($self, $args) = @_;

    $self->SUPER::Populate($args);

    $self->ConfigSpecs(
        -xxx    => [ 'SELF', 'xxx', 'Xxx', 'x' ],
    );
}

1;
But when I created one, setting option -xxx, I got the following error:

Tk::Error: Can't set -xxx to `XX' for Tk::Test=HASH(0x93d5420): unknown option "-xxx" at /usr/lib/perl5/Tk/Configure.pm line 47.
Eventually I figured out that I need a configure subroutine in my widget. It gets called after Populate has run, passed the -xxx option and its value. My initial widget was inheriting its configure subroutine from Tk::Frame and that configure didn't accept the -xxx option (and why wouldn't it).

I added a configure subroutine...

package Tk::Test;

use strict;
use warnings;
use Data::Dumper;

use base 'Tk::Frame';
Tk::Widget->Construct('Test');

sub ClassInit {
    my ($class,$mw) = @_;
    $class->SUPER::ClassInit($mw);
}

sub Populate {
    my ($self, $args) = @_;

    $self->SUPER::Populate($args);

    $self->ConfigSpecs(
        -xxx    => [ 'SELF', 'xxx', 'Xxx', 'x' ],
    );
}

sub configure {
    my ($self, @args) = @_;

    print "configure: " . Dumper(\@args);
}

1;
With this, the error was gone. Now all I have to do is learn how to write a configure sub properly.

Labels