The Pigstye

Where only the best pigs wallow.

For a project I was working on I needed a set of functions that would understand CIDR subnetting. This was on an Access Database and it needed to be very portable or I would have created a dll to do it. Access VBA has a serious limitation for this project, there is no unsigned long. To get around this limitation I converted all the decimal equivalents of ip to doubles and used the ascii representation of the binary to do the necessary masking operations. Here it is, hope it saves someone else the time of having to recreate this work.

‘==================================================
‘ Module: SubNetFunctions
‘ Author: Tom Willett
‘ Date: 9/6/2010
‘ License: GPL
‘ Description: This is a collection of subneting functions using cidr subnetting.
‘ The subnet functions are a cludge because vba does not have an unsigned long.
‘ All of the functions therefore, use the ascii representation of the binary numbers to do
‘ their calculations and store the decimal equivalent of the ip as a double.
‘ The functions available are:
‘ broadcastIP — given a subnet in cidr format returns the broadcastIP in dotted format
‘ cidr2mask — given a cidr returns the equivalent mask
‘ highestIP — given a subnet in cidr format returns the highest usable address in dotted format
‘ lowestIP — given a subnet in cidr format returns the first usable address in dotted format
‘ subnetID — given a subnet in cidr format returns the subnet id in dotted format
‘ —— helper functions ———-
‘ AbinAnd — binary ands two 8bit ascii binary numbers and returns the ascii binary result
‘ Bin2Dec — given a binary number as a string returns the decimal equivalent as a string
‘ Dec2Bin — given a decimal number as a string returns the binary equivalent as a string
‘ ip2long — given an ip in dotted format returns the long equivalent (actually double)
‘ long2ip — given a ip represented as a long (actually double) returns the ip in dotted format

‘ All of these functions have been tested on 64 and 32 bit versions of Access 2010 and 2007
‘=============================================================================================
Option Compare Database
Option Explicit

‘======================================================
‘ Bin2Dec

‘ Parameter BinNum — binary number as a string
‘ Return Decimal equivalent as a string
‘======================================================
Public Function Bin2Dec(ByVal BinNum As String) As String
Dim i As Integer
Dim DecNum As Long

On Error GoTo ErrorHandler

‘ Loop thru BinString
For i = Len(BinNum) To 1 Step -1
‘ Check the string for invalid characters
If Asc(Mid(BinNum, i, 1)) < 48 Or _
Asc(Mid(BinNum, i, 1)) > 49 Then
DecNum = “”
Err.Raise 1002, “BinToDec”, “Invalid Input”
End If
‘ If bit is 1 then raise 2^LoopCount and add it to DecNum
If Mid(BinNum, i, 1) And 1 Then
DecNum = DecNum + 2 ^ (Len(BinNum) – i)
End If
Next i
‘ Return DecNum as a String
Bin2Dec = CStr(DecNum)
ErrorHandler:
End Function

‘==============================================================
‘ Dec2Bin

‘ Parameter DecNum — decimal number as a string
‘ Return — Binary equivalent of DecNum as a string
‘===============================================================
Public Function Dec2Bin(ByVal DecNum As String) As String
Dim BinNum As String
Dim lDecNum As Long
Dim i As Integer

On Error GoTo ErrorHandler

‘ Check the string for invalid characters
For i = 1 To Len(DecNum)
If Asc(Mid(DecNum, i, 1)) < 48 Or _
Asc(Mid(DecNum, i, 1)) > 57 Then
BinNum = “”
Err.Raise 1010, “DecToBin”, “Invalid Input”
End If
Next i

i = 0
lDecNum = Val(DecNum)

Do
If lDecNum And 2 ^ i Then
BinNum = “1″ & BinNum
Else
BinNum = “0″ & BinNum
End If
i = i + 1
Loop Until 2 ^ i > lDecNum
‘ Return BinNum as a String
Dec2Bin = BinNum
ErrorHandler:
End Function

‘===============================================
‘ AbinAnd

‘ Parameters Bin1 and Bin2 are 8 bit binary numbers represented as strings
‘ Return A binary number as a string which is the result of doing a binary AND of Bin1 and Bin2
‘===============================================
Public Function AbinAnd(ByVal bin1 As String, ByVal bin2 As String) As String
‘ This function takes two binary numbers as strings and returns the string representration of the two anded together
Dim x As Byte
Dim nBin As String

nBin = String(8, “0″)
bin1 = Right(nBin & bin1, 8 )
bin2 = Right(nBin & bin2, 8 )
For x = 1 To 8
If Mid(bin1, x, 1) = “1″ And Mid(bin2, x, 1) = “1″ Then
Mid(nBin, x, 1) = “1″
End If
Next
AbinAnd = nBin
End Function

‘===========================================================
‘ cidr2mask

‘ Parameter — cidr as a string — decimal from 1 to 31
‘ Return the mask equivalent of the cidr in dotted format
‘===========================================================

Public Function cidr2mask(cidr As String) As String
‘converts the cidr bits to the subnet mask
Dim BuildBin As String
Dim octet(3) As String
Dim x, y As Byte
Dim cCtr As Byte

cCtr = CByte(cidr)
For x = 0 To 3
BuildBin = “”
For y = 1 To 8
If cCtr > 0 Then
BuildBin = BuildBin & “1″
Else
BuildBin = BuildBin & “0″
End If
If cCtr > 0 Then
cCtr = cCtr – 1
End If
Next
octet(x) = Bin2Dec(BuildBin)
Next

cidr2mask = Join(octet, “.”)
End Function

‘====================================================
‘ subnetID

‘Given a subnet address in cidr format return the subnetID in dotted format
‘====================================================
Public Function subnetID(subnet As String) As String
Dim BuildBin As String
Dim Parts As Variant
Dim octet As Variant
Dim Mask(3) As String
Dim x, y As Byte
Dim cCtr As Byte

‘split address and cidr
On Error Resume Next
Parts = Split(subnet, “/”)
octet = Split(Parts(0), “.”)
cCtr = CByte(Parts(1))
‘load mask octets
For x = 0 To 3
BuildBin = “”
For y = 1 To 8
If cCtr > 0 Then
BuildBin = BuildBin & “1″
Else
BuildBin = BuildBin & “0″
End If
If cCtr > 0 Then
cCtr = cCtr – 1
End If
Next
Mask(x) = BuildBin
Next
‘convert ip octets to binary string
For x = 0 To 3
octet(x) = Dec2Bin(octet(x))
Next

‘AND Binary Expressions.

For x = 0 To 3
octet(x) = Bin2Dec(AbinAnd(Mask(x), octet(x)))
Next

subnetID = Join(octet, “.”)
End Function

‘=======================================================
‘ broadcaseIP

‘given a subnet in cidr format return the broadcast address in dotted format
‘=======================================================
Public Function broadcastIP(subnet As String) As String
Dim BuildBin As String
Dim Parts As Variant
Dim octet As Variant
Dim Mask(3) As String
Dim IPBin As String
Dim x, y As Byte
Dim cCtr As Byte

‘split address and cidr
On Error Resume Next
Parts = Split(subnet, “/”)
octet = Split(Parts(0), “.”)
cCtr = CByte(Parts(1))
‘convert ip octets to binary string
For x = 0 To 3
octet(x) = Right(“00000000″ & Dec2Bin(octet(x)), 8 )
Next

‘Create Full IP as Binary
IPBin = Join(octet, “”)

BuildBin = “”
For x = 1 To 32
If x < = cCtr Then
BuildBin = BuildBin & Mid(IPBin, x, 1)
Else
BuildBin = BuildBin & "1"
End If
Next

Mask(0) = Bin2Dec(Mid(BuildBin, 1, 8 ))
Mask(1) = Bin2Dec(Mid(BuildBin, 9, 8 ))
Mask(2) = Bin2Dec(Mid(BuildBin, 17, 8 ))
Mask(3) = Bin2Dec(Mid(BuildBin, 25, 8 ))
broadcastIP = Join(Mask, ".")
End Function

'==================================================
' lowestIP
'
' Parameter subnet in cidr format as a string
' Return the lowest usable ip in a cidr range
'==================================================

Public Function lowestIP(subnet As String) As String
Dim BuildBin As String
Dim Parts As Variant
Dim octet As Variant
Dim Mask(3) As String
Dim x, y As Byte
Dim cCtr As Byte

'split address and cidr
Parts = Split(subnet, "/")
octet = Split(Parts(0), ".")
cCtr = CByte(Parts(1))
'load mask octets
For x = 0 To 3
BuildBin = ""
For y = 1 To 8
If cCtr > 0 Then
BuildBin = BuildBin & “1″
Else
BuildBin = BuildBin & “0″
End If
If cCtr > 0 Then
cCtr = cCtr – 1
End If
Next
Mask(x) = BuildBin
Next
‘convert ip octets to binary string
For x = 0 To 3
octet(x) = Dec2Bin(octet(x))
Next

‘AND Binary Expressions.
‘convert octets to masked octets
For x = 0 To 3
octet(x) = Bin2Dec(AbinAnd(Mask(x), octet(x)))
Next

BuildBin = Right(“00000000″ & Dec2Bin(octet(3)), 8 )
Mid(BuildBin, 8, 1) = “1″
octet(3) = Bin2Dec(BuildBin)

lowestIP = Join(octet, “.”)

End Function

‘==============================================================
‘ highestIP

‘ Parameter subnet in cidr format as a string
‘ Return highest usable IP for given cidr
‘==============================================================
Public Function highestIP(subnet As String) As String
Dim BuildBin As String
Dim Parts As Variant
Dim octet As Variant
Dim Mask(3) As String
Dim IPBin As String
Dim x, y As Byte
Dim cCtr As Byte

‘split address and cidr
Parts = Split(subnet, “/”)
octet = Split(Parts(0), “.”)
cCtr = CByte(Parts(1))
‘load mask octets
For x = 0 To 3
BuildBin = “”
For y = 1 To 8
If cCtr > 0 Then
BuildBin = BuildBin & “1″
Else
BuildBin = BuildBin & “0″
End If
If cCtr > 0 Then
cCtr = cCtr – 1
End If
Next
Mask(x) = BuildBin
Next
‘convert ip octets to binary string
For x = 0 To 3
octet(x) = Dec2Bin(octet(x))
Next

‘AND Binary Expressions.
‘convert octets to masked octets
For x = 0 To 3
octet(x) = Right(“00000000″ & AbinAnd(Mask(x), octet(x)), 8 )
Next

IPBin = Join(octet, “”)
BuildBin = “”

cCtr = CByte(Parts(1))
For x = 1 To 32
If x < = cCtr Then
BuildBin = BuildBin & Mid(IPBin, x, 1)
Else
If x = 32 Then
BuildBin = BuildBin & "0"
Else
BuildBin = BuildBin & "1"
End If
End If
Next

Mask(0) = Bin2Dec(Mid(BuildBin, 1, 8 ))
Mask(1) = Bin2Dec(Mid(BuildBin, 9, 8 ))
Mask(2) = Bin2Dec(Mid(BuildBin, 17, 8 ))
Mask(3) = Bin2Dec(Mid(BuildBin, 25, 8 ))

highestIP = Join(Mask, ".")
End Function

'==================================================
' IP2Long
'
' Parameter -- IP in dotted format as a string
' Return - decimal equivalent as a double
' VBA does not have an unsigned long :(
'==================================================
Public Function IP2Long(ByVal IP As String) As Double
Dim IPLong As Double
Dim IPpart As Variant
Dim IPbyte(4) As Double
'IPpart(0).IPpart(1).IPpart(2).IPpart(3)

IPpart = Split(IP, ".")
Dim x As Byte
For x = 0 To 3
IPbyte(x) = CByte(IPpart(x))
Next
IPLong = ((IPbyte(0) * (256 ^ 3)) + (IPbyte(1) * (256 ^ 2)) + (IPbyte(2) * 256) + IPbyte(3))

IP2Long = IPLong
End Function

'=====================================================
' Long2IP
'
' Parameter Decimal value of the IP as a double
' Return dotted representation of the IP as a string
'=====================================================

Public Function Long2IP(ByVal LongIP As Double) As String
Dim ByteIP(4) As String
Dim x As Byte
Dim IP As String

If LongIP < 4294967296# And LongIP >= 0 Then
ByteIP(0) = Fix(LongIP / (256 ^ 3))
ByteIP(1) = Fix(((LongIP – (ByteIP(0) * (256 ^ 3))) / (256 ^ 2)))
ByteIP(2) = Fix(((LongIP – (ByteIP(0) * (256 ^ 3)) – (ByteIP(1) * (256 ^ 2))) / 256))
ByteIP(3) = ((LongIP – (ByteIP(0) * (256 ^ 3)) – (ByteIP(1) * (256 ^ 2)) – (ByteIP(2) * 256)))
IP = ByteIP(0) & “.” & ByteIP(1) & “.” & ByteIP(2) & “.” & ByteIP(3)
Long2IP = IP
Else
Long2IP = -1
End If
End Function

I looked around for a simple example of creating a print preview button/link on a webpage. I already had a print.css which handled the printing but my users could not seem to find the print and print preview links on their browsers. Sigh.

So I took what I could find and came up with the following method of doing this.

I took the basic method and javascript code from Paul Sowden’s article at A List Apart and mixed in my own specifics. Consult this article if you don’t understand what I am doing. You should also look at Eric Meyers article at A list Apart on print style sheets if you don’t understand creating a print stylesheet.

So here is what I did:

First I added this little javascript function to the application javascript library. You could just as easily add it to the page header.

function setActiveStyleSheet(title) {
   var i, a, main;
   for(i=0; (a = document.getElementsByTagName("link")[i]); i++) {
     if(a.getAttribute("rel").indexOf("style") != -1
        && a.getAttribute("title")) {
       a.disabled = true;
       if(a.getAttribute("title") == title) a.disabled = false;
     }
   }
}

In the website header used on all pages I put a link to three different stylesheets.

<link href=”default.css” media=”all” rel=”stylesheet” type=”text/css” title=”default” />
<link href=”print-preview.css” media=”all” rel=”alternate stylesheet” type=”text/css” title=”printcss” />
<link href=”print-preview.css” media=”print” rel=”stylesheet” type=”text/css” />

The first link is the default style sheet. The last link is to the print style sheet and the middle link is to an alternate screen stylesheet. In all three style sheets I have a class called print-preview. In both the default style sheet and the print style sheet the class definition looks like this:

.print-preview {
  display: none;
}

The print-preview style sheet is identical to the print style sheet except the display on the .print-preview is set to block so it will display.

Again in the common header just after the beginning element I added:

<div class='print-preview'>
<a href='#' onclick="javascript: window.print();setActiveStyleSheet('default');">
<img src='/images/print.png' /></a>
<a href='#' onclick="javascript: setActiveStyleSheet('default');"></a>
<img src='/images/arrow-previous.png" /></a>
<hr /></div>

This displays a header on the print preview page that has a printer icon and a back button. Since the display is set to none on both the normal css and the print css it only displays in print-preview view.

Now on the page I just add a link to Print Preview like this:

<a href="#" onclick="javascript:setActiveStyleSheet('print-preview');">Print Preview</a>

It all works like this:
When a user clicks the Print Preview link the active style sheet is changed to the alternate print-preview style sheet so the page looks just like it would printed with the addition of the printer icon and back icon at the top.
If the user presses the printer icon, window.print() is called so the print dialog is displayed. Then the default style sheet is restored, so the page reverts to the normal display. If the user presses the back icon, the default style sheet is restored so the normal display is restored.

Since the print style sheet is used for all printing, if the user uses the print preview link on the page or chooses print from the browser menus, then the same thing is printed out.

The other day I moved a bunch of files from a windows server to a linux server. The files and directories on the windows server had spaces in them. Linux does not really like spaces in directory and file names.

I went looking around the net and could not find exactly what I wanted, so I took what I could find and modified it. At this point I cannot remember where I got the pieces, but the main brains for this script is not mine. Anyway here it is:

#!/usr/bin/perl -w
# nospace /this/dir /that/dir /those/too

use File::Find;
use strict;
die "usage: nospace dir[s]\n" unless @ARGV;

my %ext;

find(\&remspaces, @ARGV);

sub remspaces {
return if ($_ eq '.');
return if ($_ eq '..');
(my $new = $_) =~ tr/a-zA-Z0-9_.-/_/c;
my $duplicate = ($new ne $_ and -e $new);
my $try = $new;

$ext{"$File::Find::dir/$try"}++ if $duplicate;

while (my $count = $ext{"$File::Find::dir/$new"}++) {
(my $with_num = $new) =~ s/(?=\.|$)/_$count/;
$new = $with_num, last if not -e $with_num;
}

$ext{"$File::Find::dir/$try"}-- if $duplicate;

rename $_ => $new
or warn "can't rename $_ to $new: $!";
}

Copy above into a new file, save it as nospace, make it executable and run it by giving it a directory to work on. Thus if your files were in a directory called music call it with:

nospace music

Worked for me.

How do you set up auto-login with ssh keys? Every time I set up a new server I have to look this up. So here I will write it down.

Step 1 — Generate the DSA key pair

ssh-keygen -t dsa

Step 2 — Copy key to remote server

cd
scp .ssh/id_dsa.pub user@server:/

Step 3 — Logon to remove server and append key to authorized_keys

ssh server
cat id_dsa.pub >> .ssh/authorized_keys

That’s It

Hello Again

Comments off

Starting over again. It seems every few years its time to clean out the old blog and start over.

Powered by WordPress Web Design by SRS Solutions © 2014 The Pigstye Design by SRS Solutions