Tip

Exporting nsf objects - deep under the covers

This will dump internal Domino ojects out to disk file for detailed analysis. If you've ever wanted to see how Domino stores file attachments, what the ACL really looks like or the inside of a view collection then this script is for you!


'Untitled: 

Option Public
Option Declare
'Dump objects: 


Const VERSION = 1
Const LOWOBJ = 1 ' No lower than 1
' Just an arbitrary limit. This can be raised (and it is an unsigned value 

so "negative" values are also ok)
Const HIGHOBJ = 65535
Const MAXCHUNK = 32000 ' Domino prefers this size
Const SUCCESS = 0
Const NULLHANDLE = 0
Declare Function NSFDbOpen Lib "nnotes" (_
Byval PathName As Lmbcs String, _
rethDB As Long _
) As Integer

Declare Function NSFDbClose Lib "nnotes" (_
Byval hDB As Long _
) As Integer

Declare Function NSFDbSessionClose Lib "nnotes" (_
Byval hDB As Long _
) As Integer

Declare Function NSFDbGetObjectSize Lib "nnotes" (_
Byval hDB As Long, _
Byval ObjectID As Long, _
Byval ObjectType As Long, _
retSize As Long, _
retClass As Integer, _
retPrivileges As Integer _
) As Integer

Declare Function NSFDbReadObject Lib "nnotes" (_
Byval hDB As Long, _
Byval ObjectID As Long, _
Byval Offset As Long, _
Byval Length As Long, _
rethBuffer As Long _
) As Integer

Declare Function OSMemFree Lib "nnotes" Alias "OSMemFree" ( _
Byval hObject As Long _
) As Integer

Declare Function OSLockObject Lib "nnotes" Alias "OSLockObject" ( _
Byval hObject As Long _
) As Long

Declare Function OSUnlockObject Lib "nnotes" Alias "OSUnlockObject" ( _
Byval hObject As Long _
) As Integer

Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" ( _
Byval pDest As String, _
Byval pSource As Long, _
Byval dwLength As Long _
)


Sub Initialize
	Dim result As Long
	Dim hDB As Long
	Dim ObjectID As Long
	Dim ObjectType As Long
	Dim retSize As Long
	Dim retClass As Integer
	Dim retPrivileges As Integer
	Dim rethBuffer As Long
	
	Dim hLock As Long
	Dim PerlFileH As Long
	Dim BinFileH As Long
	Dim MapFileH As Long
	Dim DbPath As String
	Dim FilePath As String
	Dim Chunk As Long
	Dim Offset As Long
	Dim ObjStr As String
	
	Messagebox |This script will export information on the first 65535 

objects in a Domino database. There are three important things to keep in 

mind here. #1 The export path must be a directory. A map file, perl script 

and all the objects are placed into this directory. #2 This script scans 

through objects | & LOWOBJ & | to | & HIGHOBJ & |. If you need to change 

these boundaries then change the constants LOWOBJ and HIGHOBJ. I picked 

65535 as an initial default because I just wanted some basic information. 

#3 When LotusScript writes the object files, it pads every byte with 

another null byte (0x00). The perl script will strip that null byte out. 

If you don't have perl (the script will still work) then either you will 

need to strip the nulls yourself or just ignore them. Perl for Windows can 

be installed from http://www.activestate.com for free.|
	
	DbPath = Inputbox("Enter the path to database. To specify a 

server, prepend <Server> followed by !!. For example, <Server>!!<Filepath> 

or just <Filepath>","Enter the database path", "<Server>!!<Filepath.nsf>")
	
	FilePath = Inputbox ("Enter directory to export data 

to","Directory","C:Objects")
	
	If Len(FilePath) > 0 And Not Right(FilePath,1) = "" Then
		FilePath = FilePath & ""
	End If
	Reset
	
%REM
Get a handle to the database
%ENDREM
	hDb = NULLHANDLE
	If Len(DbPath) > 0 Then
		result = NSFDbOpen(DbPath, hDB)
	End If
	If hDB = NULLHANDLE Then
		Messagebox "The database at " & DbPath & " was not opened"
		End
	End If
	
	
%REM
Write the null removing perl script out to the directory
%ENDREM
	PerlFileH = Freefile
	Open Filepath & "no.pl" For Output As PerlFileH
	Print #PerlFileH, |
use strict;
use warnings;
my $file_name = $ARGV[0];

undef $/;
open IN, $file_name or die "Can't open $file_name: $!";
my $data = <IN>;
close IN or die "Can't close $file_name: $!";

open OUT, ">$file_name" or die "Can't open $file_name: $!";
for (my $offset=0;
     $offset < length $data;
     $offset += 2 ) {
  print OUT substr $data, $offset, 1;
}
close OUT or die "Can't close $file_name: $!";
|
	Close PerlFileH
	
	
%REM
	|
	|
	|
Create a map file. This is a tab delimited file describing the attributes 

of each object. If the
object size is zero, then it will be noted in the log but no object file 

will be saved to disk.
%ENDREM
	MapFileH = Freefile
	Open Filepath & "Map.txt" For Output As MapFileH
	Print #MapFileH, "ObjectID	Size	Class	Privileges"
	
	ObjectID = 0
	Do
		' Get the object flags
		If Not SUCCESS = _
		NSFDbGetObjectSize(hDB, ObjectID, 65535, retSize, 

retClass, retPrivileges) Then
			Goto next_Obj
		End If
		
		' Save the information to the log if nessessary
		If retSize <> 0 Or _
		retClass <> 0 Or _
		retPrivileges <> 0 _
		Then
			Print #MapFileH, Hex(ObjectID) & "	" & 

Hex(retSize) & "	" & Hex(retClass) & "	" & Hex(retPrivileges)
			Print ObjectID & "	" & retSize & "	" & 

Hex(retClass) & "	" & Hex(retPrivileges)
		End If
		
		' If there is something to export, then do that.
		If retSize <> 0 Then
			
			' Read the object into memory with the handle in 

rethBuffer
			If Not SUCCESS = _
			NSFDbReadObject(hDB, ObjectID, 0, retSize, 

rethBuffer) Then
				Goto free_Obj
			End If
			
			' Lock the object in memory. hLock is now a memory 

address that can be used
			' to access the data
			hLock = OSLockObject (rethBuffeR)
			
			
			' Open the output file and write it in MAXCHUNK 

byte chunks
			' Domino appears to prefer this size chunk
			BinFileH = Freefile
			Open Filepath & Hex(ObjectID) & |.obj| For Binary 

Access Write As BinFileH
			Offset = 0
			While Offset < retSize
				Chunk = retSize - Offset
				If (retSize - Offset) > MAXCHUNK Then
					Chunk = MAXCHUNK
				End If
				
				ObjStr = String(Chunk, "X")
				CopyMemory ObjStr, hLock, Len(ObjStr)
				Put # BinFileH, ,ObjStr ' Remember, each 

byte is null padded
				
				hLock = hLock + Chunk
				Offset = Offset + Chunk
			Wend
			Close BinFileH
			
			' Launch the perl script and who cares if it 

succeeds. If perl is not
			' installed it won't really matter
			If 0 = Shell (|perl | & Filepath & |no.pl | & 

FilePath & Hex(ObjectID) & |.obj|) Then
			End If
			
			' Unlock the object. The memory is still 

allocated, it may be moved around if the OS wishes
			Call OSUnlockObject (retHBuffer)
free_Obj:
			' And now deallocate the memory.
			Call OSMemFree (rethBuffer)
			
		End If
		
next_Obj:
		ObjectID = ObjectID + 1
	Loop While ObjectID <= 65535
	
	Close MapFileH
	Reset
	
	' Close the handle
	result = NSFDbClose(hDB)
	
	Messagebox "Done"
End Sub

This was first published in September 2001

There are Comments. Add yours.

 
TIP: Want to include a code block in your comment? Use <pre> or <code> tags around the desired text. Ex: <code>insert code</code>

REGISTER or login:

Forgot Password?
By submitting you agree to receive email from TechTarget and its partners. If you reside outside of the United States, you consent to having your personal data transferred to and processed in the United States. Privacy
Sort by: OldestNewest

Forgot Password?

No problem! Submit your e-mail address below. We'll send you an email containing your password.

Your password has been sent to:

Disclaimer: Our Tips Exchange is a forum for you to share technical advice and expertise with your peers and to learn from other enterprise IT professionals. TechTarget provides the infrastructure to facilitate this sharing of information. However, we cannot guarantee the accuracy or validity of the material submitted. You agree that your use of the Ask The Expert services and your reliance on any questions, answers, information or other materials received through this Web site is at your own risk.