About This Code
Brief Description:
Exporting nsf objects - deep under the covers
Contributor:
Andrew Jones
Last Modified:
17 Jun 2002
OpenNTF Disclaimer
All of the program code and information presented in the OpenNTF.org Code Bin are provided "as-is", and should be used at your own risk. OpenNTF.org make no express or implied warranty about anything in the Code Bin, and OpenNTF.org will not be responsible or liable for any damage caused by the use or misuse of anything from this site. OpenNTF.org makes no guarantees about anything. Please thoroughly test all of the knowledge and code you find here before you attempt to use them in your production environment.
Code / Description
'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
Usage / Example