Gallery
Software
Music
Programming
Archive
Friday, Mar 22 Week 12

NetStumbler NS1 file version 1,6,8,11 and 12

Read and write NetStumbler .ns1 file-format with Delphi.
Supports .ns1 file-versions: 12,11,8,6,1 (Used by NetStumbler & MiniStumbler)
Make a descendant class of the TNs1Object-object to exchange data to your list.

Download

netstumbler-ns1.zip
(242.15 Kb)
, Downloads: 99

NetStumblerNs1.zip contains:

NetStumblerNs1.pas NetStumblerNs1 unit (Source code)
Unit1.pas Example unit+form (Source code)
Project1.dpr Example project (Delphi project)
sample-ns1-filevs-01.ns1 Sample NS1 file NS1-v1 (NetStumbler 0.2)
sample-ns1-filevs-06.ns1 Sample NS1 file NS1-v6 (NetStumbler 0.3+)
sample-ns1-filevs-08.ns1 Sample NS1 file NS1-v8 (NetStumbler 0.3.30)
sample-ns1-filevs-11.ns1 Sample NS1 file NS1-v11 (NetStumbler 0.3.99)
sample-ns1-filevs-12.ns1 Sample NS1 file NS1-v12 (NetStumbler 0.4)
info.txt Information (Text file)
netstumbler.ico NetStumbler/NS1 icon (Icon file)
Delphi NS1, mortenbs.com.url A link back to this page (Internet shortcut)

How to use it

1. Make an inherited class of TNs1Object.
2. Override all virtual parameters for read.
3. Override all virtual parameters for write.
4. In readEntry, create your external object. (used for load)
5. In writeEntry, define from your external object. (used for save)
6. Call loadFile() or saveFile() to exchange data with your list.
7. When calling, the object runs all inherited procedures for defining parameters.
8. Finally free the object.
--- Or modify the object and put in your code as needed...
//mbs.

unit NetStumblerNs1; //updated 2016-09-24, mortenbs.com

//Read and write NetStumbler .ns1 file-format with Delphi.
//Supports .ns1 file-versions: 12,11,8,6,1 (Used by NetStumbler & MiniStumbler)
//Make a descendant class of the TNs1Object-object to exchange data to your list.
//http://www.mortenbs.com/delphi-netstumbler-ns1-files/

interface

uses
windows,sysUtils,classes;

type
//--------------------------|---------------------|-----------------------|-------------------------<
uint8 = byte;
puint32 = ^uint32;
uint32 = longWord;
int32 = longInt;
float8 = double;
time_t = uint32;
pMacAddress = ^TMacAddress;
TMacAddress = array[0..5] of uint8;
//--------------------------|---------------------|-----------------------|-------------------------<
pNs1Header=^TNs1Header;
TNs1Header=record
Signature :array[0..3] of ansiChar; //File signature
Version :uint32; //File version
DataCount :uint32; //Data entries
end;
//--------------------------|---------------------|-----------------------|-------------------------<
pNs1GpsPos=^TNs1GpsPos;
TNs1GpsPos=record
Lat :float8; //Latitude
Long :float8; //Longitude
end;
//--------------------------|---------------------|-----------------------|-------------------------<
pNs1ApGpsData=^TNs1ApGpsData;
TNs1ApGpsData=record
Gps :TNs1GpsPos; //GPS-position
Altitude :float8; //Altitude
NumSats :uint32; //Satellites in view
Speed :float8; //Speed
Track :float8; //Track
MagVariation :float8; //Magnetic variation
Hdop :float8; //Hdop
end;
//--------------------------|---------------------|-----------------------|-------------------------<
pNs1String=^TNs1String;
TNs1String=record
Length :uint8; //Length
Value :array[0..0] of ansiChar; //Chars (Without NULL)
end;
//--------------------------|---------------------|-----------------------|-------------------------<
pNs1SignalInfo=^TNs1SignalInfo;
TNs1SignalInfo=record
MaxSignal :int32; //Max signal level (dBm)
MinNoise :int32; //Min noise level (dBm)
MaxSNR :int32; //Max signal-to-noise ratio (dB)
end;
//--------------------------|---------------------|-----------------------|-------------------------<
pNs1V1Params=^TNs1V1Params;
TNs1V1Params=record //(v1)
Flags :uint32; //Flags (802.11)
BeaconInterval :uint32; //Beacon Interval (Kµs)
FirstSeen :time_t; //First seen
LastSeen :time_t; //Last seen
end;
//--------------------------|---------------------|-----------------------|-------------------------<
pNs1V6Params=^TNs1V6Params;
TNs1V6Params=record //(v6+)
Flags :uint32; //Flags (802.11)
BeaconInterval :uint32; //Beacon Interval (Kµs)
FirstSeen :FILETIME; //First seen
LastSeen :FILETIME; //Last seen
end;
//--------------------------|---------------------|-----------------------|-------------------------<
pNs1V8Params=^TNs1V8Params;
TNs1V8Params=record //(v8+)
Channels :int64; //Channels
LastChannel :uint32; //Last channel
IPAddress :uint32; //IPv4 Address
end;
//--------------------------|---------------------|-----------------------|-------------------------<
pNs1V11Params=^TNs1V11Params;
TNs1V11Params=record //(v11+)
MinSignal :int32; //Min signal level (dBm)
MaxNoise :int32; //Max noise level (dBm)
DataRate :uint32; //Max data rate
IPSubnet :uint32; //IPv4 Subnet address
IPMask :uint32; //IPv4 Subnet mask
end;
//--------------------------|---------------------|-----------------------|-------------------------<
pNs1V12Params=^TNs1V12Params;
TNs1V12Params=record //(v12)
ApFlags :uint32; //Flags
IELength :uint32; //InfoElements size
InfoElements :array[0..0] of uint8; //802.11 Info
end;
//--------------------------|---------------------|-----------------------|-------------------------<
pNs1ApDataEntry=^TNs1ApDataEntry; //(v5+)
TNs1ApDataEntry=record
Time :FILETIME; //Time
Signal :int32; //Signal (dBm)
Noise :int32; //Noise (dBm)
LocationSource :int32; //(None=0, GPS=1)
//GpsData :TNs1ApGpsData; //Present if LocationSource<>0
end;
//--------------------------|---------------------|-----------------------|-------------------------<
pNs1ApDataEntries=^TNs1ApDataEntries;
TNs1ApDataEntries=record //(v5+)
Count :uint32; //Number of entries
Data :array[0..0] of TNs1ApDataEntry; //Entries
end;
//--------------------------|---------------------|-----------------------|-------------------------<

const
NS1_FILE_SIGNATURE = 'NetS';
NS1_SUPPORTED_VERSIONS = [1,6,8,11,12];

type
//--------------------------|---------------------|-----------------------|-------------------------<
TNs1Object=class
procedure reset;virtual;
function loadFile(aFileName:string):boolean;
function saveFile(aFileName:string;aDataCount:uint32;aFileVs:uint8=12):boolean;
private
procedure setVersion(n:uint8);
function readNs1String:ansiString;
procedure readNs1ApDataEntries;
function validNs1Sig(p:pointer):boolean;
protected
fVersion :uint8; //NS1 File Version
pBuffer,pStep :pAnsiChar;
nBufSz,nSize :uint32;
procedure step(n:uint32);
function readNs1Data:boolean;
function writeNs1Data(strm:TStream;aDataCount:uint32):boolean;
procedure readEntry(pSsid:pNs1String;pBssId:pMacAddress;pSignalInfo:pNs1SignalInfo);virtual; //For adding new entries, v1+ (all)
procedure readLastChannel(LastChannel:uint32);virtual; //v1 (only)
procedure readChannelActivity(ChannelActivity:uint32);virtual; //v6 (only)
procedure readGpsPos(pGps:pNs1GpsPos);virtual; //v6+
procedure readName(pName:pAnsiChar);virtual; //v6+
procedure readV1Params(pParams:pNs1V1Params);virtual; //v1 (only)
procedure readV6Params(pParams:pNs1V6Params);virtual; //v6+
procedure readV8Params(pParams:pNs1V8Params);virtual; //v8+
procedure readV11Params(pParams:pNs1V11Params);virtual; //v11+
procedure readV12Params(pParams:pNs1V12Params);virtual; //v12+
procedure readApDataEntry(pEntry:pNs1ApDataEntry;pGpsData:pNs1ApGpsData);virtual; //v6+
procedure writeEntry(id:int32;var ssid:ansiString;pBssId:pMacAddress;pSignalInfo:pNs1SignalInfo;var nItems:uint32);virtual; //For new entries, v1+ (all)
procedure writeLastChannel(var LastChannel:uint32);virtual; //v1 (only)
procedure writeChannelActivity(var ChannelActivity:uint32);virtual; //v6 (only)
procedure writeGpsPos(pGps:pNs1GpsPos);virtual; //v6+
procedure writeName(var name:ansiString);virtual; //v6+
procedure writeV1Params(pParams:pNs1V1Params);virtual; //v1 (only)
procedure writeV6Params(pParams:pNs1V6Params);virtual; //v6+
procedure writeV8Params(pParams:pNs1V8Params);virtual; //v8+
procedure writeV11Params(pParams:pNs1V11Params);virtual; //v11+
procedure writeV12Params(pParams:pNs1V12Params);virtual; //v12+
procedure writeApDataEntry(id:int32;pEntry:pNs1ApDataEntry;var pGpsData:pNs1ApGpsData);virtual; //v6+
public
constructor Create;virtual;
destructor Destroy;override;
property version :uint8 read fVersion; //readonly
end;
//--------------------------|---------------------|-----------------------|-------------------------<

function fileTimeToDateTime(ft:FILETIME):TDateTime;
function dateTimeToFileTime(dt:TDateTime):FILETIME;

implementation

function fileTimeToDateTime(ft:FILETIME):TDateTime;
var mt:FILETIME;st:TSystemTime;
begin
result:=0;
if (ft.dwLowDateTime<>0) or (ft.dwHighDateTime<>0) then try
fileTimeToLocalFileTime(ft,mt);
fileTimeToSystemTime(mt,st);
result:=SystemTimeToDateTime(st);
except result:=0 end;
end;

function dateTimeToFileTime(dt:TDateTime):FILETIME;
var lft:FILETIME;st:TSystemTime;
begin
pInt64(@result)^:=0;
dateTimeToSystemTime(dt,st);
systemTimeToFileTime(st,lft);
localFileTimeToFileTime(lft,result);
end;

//--------------------------------------------------------------------------------------------------
//TNs1Object:

constructor TNs1Object.Create;
begin
pBuffer := nil;
reset;
end;

destructor TNs1Object.Destroy;
begin
reset;
inherited Destroy;
end;

procedure TNs1Object.reset;
begin
fVersion := 0;
pStep := nil;
nSize := 0;
nBufSz := 0;
if pBuffer<>nil then begin dispose(pBuffer);pBuffer:=nil end;
end;

procedure TNs1Object.setVersion(n:uint8);
begin
if not (n in NS1_SUPPORTED_VERSIONS) then n:=0;
fVersion:=n;
end;

function TNs1Object.loadFile(aFileName:string):boolean;
var fs:TFileStream;n:uint32;
begin
result:=false;
reset;
try
fs := TFileStream.Create(aFileName,fmOpenRead or fmShareDenyWrite);
nBufSz := fs.size;
if nBufSz<>0 then try
getMem(pBuffer,nBufSz);
try
if windows.readFile(fs.handle,pBuffer^,nBufSz,n,nil) then begin
pStep := pBuffer;
nSize := nBufSz;
result := readNs1Data;
end;
except end;
except end;
fs.free;
except end;
reset;
end;

function TNs1Object.saveFile(aFileName:string;aDataCount:uint32;aFileVs:uint8=12):boolean;
var fs:TFileStream;
begin
result:=false;if aDataCount=0 then exit;
reset;
setVersion(aFileVs);
if fVersion<>0 then try
fs:=TFileStream.Create(aFileName,fmCreate);
try result:=writeNs1Data(fs,aDataCount) except result:=false end;
fs.free;
except end;
reset;
end;

procedure TNs1Object.step(n:uint32);
begin
inc(pStep,n);
dec(nSize,n);
end;

function TNs1Object.validNs1Sig(p:pointer):boolean;
begin
result:=puint32(p)^=puint32(pAnsiChar(NS1_FILE_SIGNATURE))^;
end;

function TNs1Object.writeNs1Data(strm:TStream;aDataCount:uint32):boolean;
var
nItems,k :uint32;
n,c :int32;
header :TNs1Header;
ssid :ansiString;
bssId :TMacAddress;
signalInfo :TNs1SignalInfo;
LastChannel :uint32;
ChannelActivity :uint32;
v1Params :TNs1V1Params;
v6Params :TNs1V6Params;
v8Params :TNs1V8Params;
v11Params :TNs1V11Params;
v12Params :TNs1V12Params;
gpsPos :TNs1GpsPos;
name :ansiString;
dataEntry :TNs1ApDataEntry;
gpsData :TNs1ApGpsData;
pGpsData :pNs1ApGpsData;
begin
result:=false;if (fVersion=0) or (aDataCount=0) then exit;
header.Signature := NS1_FILE_SIGNATURE;
header.Version := fVersion;
header.DataCount := aDataCount;
strm.write(header,sizeOf(TNs1Header));
try
for n:=0 to aDataCount-1 do begin
nItems:=0;
ssid:='';
writeEntry(n,ssid,@bssId,@signalInfo,nItems); //For new entries
k:=length(ssid);strm.write(k,1);
if k<>0 then strm.write(pAnsiChar(ssid)^,k); //SSID:TNs1String
strm.write(pByte(@bssid)^,6); //BSSID:TMacAddress
strm.write(signalInfo,sizeOf(TNs1SignalInfo)); //TNs1SignalInfo
if fVersion=1 then begin
LastChannel:=0;
writeLastChannel(LastChannel);strm.write(LastChannel,4); //Last channel
writeV1Params(@v1Params);strm.write(v1Params,sizeOf(TNs1V1Params)); //TNs1V1Params
end else
if fVersion=6 then begin
ChannelActivity:=0;
writeChannelActivity(ChannelActivity);strm.write(ChannelActivity,4); //Channel activity
end;
if fVersion>5 then begin
writeV6Params(@v6Params);strm.write(v6Params,sizeOf(TNs1V6Params)); //TNs1V6Params
writeGpsPos(@gpsPos);strm.write(gpsPos,sizeOf(TNs1GpsPos)); //TNs1GpsPos
strm.write(nItems,4);
for c:=0 to nItems-1 do begin //TNs1ApDataEntries
fillChar(dataEntry,sizeOf(TNs1ApDataEntry),0); //TNs1ApDataEntry
fillChar(gpsData,sizeOf(TNs1ApGpsData),0); //TNs1ApGpsData
pGpsData:=@gpsData;
writeApDataEntry(c,@dataEntry,pGpsData);
strm.write(dataEntry,sizeOf(TNs1ApDataEntry));
if pGpsData<>nil then strm.write(pGpsData^,sizeOf(TNs1ApGpsData));
end;
name:='';
writeName(name); //Name:TNs1String
k:=length(name);strm.write(k,1);
if k<>0 then strm.write(pAnsiChar(name)^,k);
end;
if fVersion>7 then begin
writeV8Params(@v8Params);strm.write(v8Params,sizeOf(TNs1V8Params)); //TNs1V8Params
end;
if fVersion>10 then begin
writeV11Params(@v11Params);strm.write(v11Params,sizeOf(TNs1V11Params)); //TNs1V11Params
end;
if fVersion>11 then begin //TNs1V12Params
writeV12Params(@v12Params);
strm.write(v12Params.ApFlags,4);
strm.write(v12Params.IELength,4);
k:=0;
for c:=1 to v12Params.IELength do strm.Write(k,1); //InfoElements
end;
end;
except exit end;
result:=true;
end;

function TNs1Object.readNs1Data:boolean;
var
n,tot :uint32;
pSsid :pNs1String;
pBssId :pMacAddress;
pSignalInfo :pNs1SignalInfo;
begin
result := false;if (nSize<12) or not validNs1Sig(pStep) then exit;step(4);
n := puint32(pStep)^;step(4);if n>12 then exit;
tot := puint32(pStep)^;step(4);setVersion(n);if fVersion=0 then exit;
try
while (tot<>0) and (nSize<>0) do begin dec(tot);
pSsid := pNs1String(pStep);step(pNs1String(pStep)^.Length+1); //SSID:TNs1String
pBssId := pMacAddress(pStep);step(6); //BSSID:TMacAddress
pSignalInfo := pNs1SignalInfo(pStep);step(sizeOf(TNs1SignalInfo)); //TNs1SignalInfo
readEntry(pSsid,pBssId,pSignalInfo); //-->NEW ENTRY<--
if fVersion=1 then begin
readLastChannel(puint32(pStep)^);step(4); //Last channel
readV1Params(pNs1V1Params(pStep));step(sizeOf(TNs1V1Params)); //TNs1V1Params
end else
if fVersion=6 then begin
readChannelActivity(puint32(pStep)^);step(4); //Channel activity
end;
if fVersion>5 then begin
readV6Params(pNs1V6Params(pStep));step(sizeOf(TNs1V6Params)); //TNs1V6Params
readGpsPos(pNs1GpsPos(pStep));step(sizeOf(TNs1GpsPos)); //TNs1GpsPos
readNs1ApDataEntries; //TNs1ApDataEntries
readName(pChar(readNs1String)); //Name:TNs1String
end;
if fVersion>7 then begin
readV8Params(pNs1V8Params(pStep));step(sizeOf(TNs1V8Params)); //TNs1V8Params
end;
if fVersion>10 then begin
readV11Params(pNs1V11Params(pStep));step(sizeOf(TNs1V11Params)); //TNs1V11Params
end;
if fVersion>11 then readV12Params(pNs1V12Params(pStep)); //TNs1V12Params
end;result:=true;
except end;
end;

function TNs1Object.readNs1String:ansiString;
begin
result:='';
with pNs1String(pStep)^ do begin
if Length<>0 then result:=copy(ansiString(@Value[0]),1,Length);
step(1+Length);
end;
end;

procedure TNs1Object.readNs1ApDataEntries;
var n:uint32;pEntry:pNs1ApDataEntry;pGpsData:pNs1ApGpsData;
begin
n:=puint32(pStep)^;step(4);
while n<>0 do begin dec(n);
pEntry := pNs1ApDataEntry(pStep);step(sizeOf(TNs1ApDataEntry));
pGpsData := nil;
if pEntry^.LocationSource>0 then begin
pGpsData:=pNs1ApGpsData(pStep);
step(sizeOf(TNs1ApGpsData));
end;
readApDataEntry(pEntry,pGpsData);
end;
end;

//READING DATA:

procedure TNs1Object.readEntry(pSsid:pNs1String;pBssId:pMacAddress;pSignalInfo:pNs1SignalInfo); //For adding new entries
begin
//-FOR DESCENDANT OBJECT-
//Add the new entry to your list here.
//Also set SSID, BSSID and SignalInfo parameters to your new entry here...
end;

procedure TNs1Object.readLastChannel(LastChannel:uint32); //v1 (only)
begin
//-FOR DESCENDANT OBJECT-
//Add "LastChannel"-parameter to your entry created in "notifyEntry"
end;

procedure TNs1Object.readChannelActivity(ChannelActivity:uint32); //v6 (only)
begin
//-FOR DESCENDANT OBJECT-
//Add "ChannelActivity"-parameter to your entry created in "notifyEntry"
end;

procedure TNs1Object.readGpsPos(pGps:pNs1GpsPos); //v6+
begin
//-FOR DESCENDANT OBJECT-
//Add "GPS-Position"-parameter to your entry created in "notifyEntry"
end;

procedure TNs1Object.readName(pName:pAnsiChar); //v6+
begin
//-FOR DESCENDANT OBJECT-
//Add "Name"-parameter to your entry created in "notifyEntry"
end;

procedure TNs1Object.readV1Params(pParams:pNs1V1Params); //v1 (only)
begin
//-FOR DESCENDANT OBJECT-
//Add parameters to your entry created in "notifyEntry"
end;

procedure TNs1Object.readV6Params(pParams:pNs1V6Params); //v6+
begin
//-FOR DESCENDANT OBJECT-
//Add parameters to your entry created in "notifyEntry"
end;

procedure TNs1Object.readV8Params(pParams:pNs1V8Params); //v8+
begin
//-FOR DESCENDANT OBJECT-
//Add parameters to your entry created in "notifyEntry"
end;

procedure TNs1Object.readV11Params(pParams:pNs1V11Params); //v11+
begin
//-FOR DESCENDANT OBJECT-
//Add parameters to your entry created in "notifyEntry"
end;

procedure TNs1Object.readV12Params(pParams:pNs1V12Params); //v12+
begin
//-FOR DESCENDANT OBJECT-
//Add parameters to your entry created in "notifyEntry"
end;

procedure TNs1Object.readApDataEntry(pEntry:pNs1ApDataEntry;pGpsData:pNs1ApGpsData); //v6+
begin
//-FOR DESCENDANT OBJECT-
//Add parameters to your entry created in "notifyEntry"
//"pGpsData" can be nil, if not present in the ns1-file.
end;

//WRITING DATA:

procedure TNs1Object.writeEntry(id:int32;var ssid:ansiString;pBssId:pMacAddress;pSignalInfo:pNs1SignalInfo;var nItems:uint32); //For new entries
begin
//-FOR DESCENDANT OBJECT-
//New entry
//Define SSID, BSSID and SignalInfo... (any file-version)
//Set "nItems" to the number of ApDataEntries contained...
end;

procedure TNs1Object.writeLastChannel(var LastChannel:uint32); //v1 (only)
begin
//-FOR DESCENDANT OBJECT-
//Define "LastChannel"-parameter
end;

procedure TNs1Object.writeChannelActivity(var ChannelActivity:uint32); //v6 (only)
begin
//-FOR DESCENDANT OBJECT-
//Define "ChannelActivity"-parameter
end;

procedure TNs1Object.writeGpsPos(pGps:pNs1GpsPos); //v6+
begin
//-FOR DESCENDANT OBJECT-
//Define "GPS-Position"-parameter
end;

procedure TNs1Object.writeName(var name:ansiString); //v6+
begin
//-FOR DESCENDANT OBJECT-
//Define "Name"-parameter
end;

procedure TNs1Object.writeV1Params(pParams:pNs1V1Params); //v1 (only)
begin
//-FOR DESCENDANT OBJECT-
//Define parameters
end;

procedure TNs1Object.writeV6Params(pParams:pNs1V6Params); //v6+
begin
//-FOR DESCENDANT OBJECT-
//Define parameters
end;

procedure TNs1Object.writeV8Params(pParams:pNs1V8Params); //v8+
begin
//-FOR DESCENDANT OBJECT-
//Define parameters
end;

procedure TNs1Object.writeV11Params(pParams:pNs1V11Params); //v11+
begin
//-FOR DESCENDANT OBJECT-
//Define parameters
end;

procedure TNs1Object.writeV12Params(pParams:pNs1V12Params); //v12+
begin
//-FOR DESCENDANT OBJECT-
//Define parameters
end;

procedure TNs1Object.writeApDataEntry(id:int32;pEntry:pNs1ApDataEntry;var pGpsData:pNs1ApGpsData); //v6+
begin
//-FOR DESCENDANT OBJECT-
//Define parameters
//Set "pGpsData" to nil, if not present...
end;


end.

References

How to read and write .NS1 files
Download NetStumbler

Related pages of NS1 NetStumbler files

WiFi console commands
Programming
Delphi programming