Tuesday, June 20, 2006

getting the current date in a particular format in Windows XP/2003

I needed to get the current date, in the format 'yyyy-MM-dd', and use that value multiple times within a batch file.

The command 'DATE /T' returns a date like this:
Tue 06/20/2006

But I needed:
2006-06-20

Now, this would have been extraordinarily easy, if I could use 4nt, cygwin, nclip, or any number of other tools. However, my options were limited on the machine that I needed to run this on, as it is a production web application server. So, I had to come up with a way to do this using the tools I had available to me:
- Windows 2003 Server (assumed to be a default installation, or more minimal than that)
- Sybase ASE 12.5.x
- Java

I probably could have just written a simple java application to do this, but where's the fun in THAT? :)

So, I consulted with my good friend, Jeff Scanlon, as I usually do when I have an interesting tech challenge, and together we came up with this batch file [NOTE: you can download it here, if the code gets too munged with the blogger html/css]:

------ BEGIN BATCH FILE -------

@echo off
REM generate SQL script to get date in correct format:
echo select 'set my_date=' + str_replace(convert(char(20),getdate(),102),'.','-') >%TEMP%\getDate_yyyy-MM-dd.sql
echo go >>%TEMP%\getDate_yyyy-MM-dd.sql

REM run the SQL script to generate a simple, temporary batch file:
isql -U username -P password -i %TEMP%\getDate_yyyy-MM-dd.sql | findstr set >%TEMP%\set_my_date.bat

REM run the temporary batch file, which will set an environment variable, 'MY_DATE', to contain the date:
call %TEMP%\set_my_date.bat

REM clean up
del /q %TEMP%\set_my_date.bat
del /q %TEMP%\getDate_yyyy-MM-dd.sql

REM this is where you'd actually put code that uses the date, like:
REM md c:\backup\%MY_DATE%
REM copy c:\mystuff\*.* c:\backup\%MY_DATE%

------ END BATCH FILE -------

Thursday, May 04, 2006

How to list duplicate lines in a text file, with counts next to each unique line

At some point, last year (it's been in my 'toblog' file all this time), I needed to analyze the lines in a text file, removing duplicate lines, while counting how many times each duplicated line occurred within the file, and sorting from most common to least common.

For example, using a text file called 'dupetest.txt', containing:

foo bar baz
foo qux corge
spugbrap likes bacon
foo qux corge
spugbrap likes bacon
foo bar baz
oatmeal cookies are good
oatmeal cookies are good
foo bar baz
foo qux corge
foo bar baz

The output I want is:
4 foo bar baz
3 foo qux corge
2 spugbrap likes bacon
2 oatmeal cookies are good


I knew there had to be a simple way of doing this by just stringing together a few unix commands (in cygwin), but finding the right combination of commands took me some effort. Here's what I came up with:

sort dupetest.txt | uniq -c -d | sort -n -r

Friday, April 28, 2006

Talking over SSL from Java

For the first time in this blog, I'm pleased to present to you a
guest post from my good friend, Jeff Scanlon:


Talking over SSL from Java
--------------------------

When using SSLFactory to talk SSL with a server, or using
the URL class to open an https connection, an error you
might encounter is:

sun.security.validator.ValidatorException: PKIX path building failed:
sun.security.provider.certpath.SunCertPathBuilderException:
unable to find valid certification path to requested target

One solution that worked for me is to add the server certificate
to the cacerts file in the appropriate Java runtime.

Steps:
  1. You must have the server certificate. If you don't have this
    handy, navigate to the secure website, click on the lock icon
    (in Internet Explorer). Click on "Details" tab and then click
    the "Copy to File..." button. Export the certificate to a DER
    encoded binary X.509 (.CER) file. Let's say you chose the
    filename example.cer

  2. Copy example.cer to the jre/lib/security directory in the Java
    runtime you are using. If you're on Windows and the JDK/JRE
    is in C:\jdk1.5.0_04, then the full path is:
    C:\jdk1.5.0_04\jre\lib\security

  3. Import the certificate into the cacerts file by using the
    following command [editor's note: this is all one command, broken
    into multiple lines for blogging
    ]:

    keytool -import -storepass changeit -file
      example.cer -keystore cacerts
      -alias example

    'changeit' is the default password to the cacerts keystore
    'example.cer' is the filename you used in step #1
    'example' is an arbitrary alias you choose for the certificate

  4. Now try your code and see if it can establish the SSL
    connection. If you get an error like 'HTTPS hostname
    wrong: should be ____', then add this code:

    import javax.net.ssl.HostnameVerifier;
    import javax.net.ssl.HttpsURLConnection;
    import javax.net.ssl.SSLSession;

    // -------------------------------------------------

    HostnameVerifier hv = new HostnameVerifier() {
        public boolean verify(String hostName,
                              SSLSession session)
        {
            System.out.println(
              "hostName is [" + hostName +
              "] and session peer host is [" +
              session.getPeerHost() + "]");
            return(true);
        }
    };

    HttpsURLConnection.setDefaultHostnameVerifier(hv);

    The above code provides a hostname verifier replacement that
    will cause hostname verification to succeed (by always
    returning true). Be aware that using this code does have
    security implications. However, this simplistic verify
    replacement should solve SSL communication problems and
    provide a starting point for implementing a custom verify
    that maintains security.

Jeff has been a good friend of mine for about 16 years, now.
He has been published several times (such as here,
here, and here), and is usually the first person I turn
to for ideas/advice on any programming/computer-related topic. He will definitely be contributing to this blog again in the future.