Setting Document Read Access
Chapter 9-3
Setting Document Read Access
Introduction
Notes versions prior to 3.0 used privilege levels to set the read access levels of documents in a database. Starting with Notes version 3.0, you can set the read access level of documents in a database using privilege levels (to maintain compatibility with earlier versions of Notes) and/or a name list.
The name list consists of people, servers, groups, and roles. Roles in the name list are enclosed in brackets. You use the Notes user interface to create the read access levels of documents as follows:
- When you are editing a document, select File - Document Properties and select the panel with the key icon on the tab.
- When you are designing a form and defining its properties, select the panel with the key icon on the tab.
In the latter case, when you use the Notes user interface to create a document with the form, the document inherits the form's read access list.
The SETPRIVS Sample Program
The sample program SETPRIVS allows you to set read access privilege levels or a name list; a command line argument specifies which the program is to set. If you specify privilege levels, the argument that follows determines the privilege levels to set. If you specify a name list, the arguments that follow determine the entries in the name list. You must enclose name list entries in brackets.
The program uses a privilege mask contained in the document to set the read access privilege levels and a text list field in the document to set the read access name list.
SETPRIVS first gets all the documents in a given view. It will set the read access privilege levels or name lists of these documents as specified on the command line.
SETPRIVS then opens a collection and uses NIFReadEntries to get a buffer of all the note handles in the collection.
setprivs.c: Get the documents whose read access will be modified |
typedef struct
{
WORD NumEntries;
char pReaderEntries;
} READER_LIST;
STATUS error;
char ViewName;
short SetReaderList;
READER_LIST ReaderList;
DBHANDLE hDB;
HCOLLECTION hCollection;
NOTEID ViewNoteID;
WORD NewPrivileges;
DWORD NumUpdated = 0;
DWORD NumNotUpdated = 0;
if (error = NIFFindView(hDB, ViewName, &ViewNoteID))
{
if (error == ERR_NOT_FOUND)
{
printf("View '%s' cannot be found\n", ViewName);
error = NOERROR;
}
goto Done;
}
/ Open the collection of notes in the view at the current time.
Return a handle to the collection to the variable hCollection. /
if (error = NIFOpenCollection(hDB, hDB, ViewNoteID,
0,
NULLHANDLE,
&hCollection,
NULL, NULL, NULL, NULL))
goto Done;
{
COLLECTIONPOSITION IndexPos;
DWORD EntriesReturned;
HANDLE hBuffer;
WORD SignalFlag; / signal and share warning flags /
IndexPos.Level = 0;
IndexPos.Tumbler[0] = 0;
/ Create a buffer of note IDs copied from the collection and store the
note IDs in a buffer with handle hBuffer. /
do
{
error = NIFReadEntries(hCollection,
&IndexPos,
NAVIGATE_NEXT, 1L,
NAVIGATE_NEXT, MAXDWORD,
READ_MASK_NOTEID,
&hBuffer, NULL,
NULL, &EntriesReturned, &SignalFlag);
/ processing of each note follows /
...
} while (SignalFlag & SIGNAL_MORE_TO_DO);
/ All note IDs have been captured, close the collection. */
NIFCloseCollection (hCollection);
}
Setting Read Access
The next section of code sets the read access for each note (document) found. It calls OSLock to lock the buffer of note IDs and then opens each note in turn. If you specified setting the read access name list on the command line, the code calls the routine UpdateReaderList. If you specified setting the read access privilege level, the code calls the routine UpdatePrivMask.
The read access name list is a special field in a document called $Readers. It is a field of type TYPE_TEXT_LIST with the ITEM_SUMMARY and ITEM_READERS flags set. In UpdateReaderList, if the $Readers text list field exists in this note, it is deleted. If you specified an empty text list entry on the command line, the note is updated. An empty text list entry clears the read access name list. If the text list from the command line is not empty, the code creates a $Readers text list field and adds the text list entries to the list. It then updates the note.
In UpdatePrivMask, the original privilege mask is saved and a new privilege mask is set. If the new privilege mask is different from the original privilege mask, the note is updated.
Finally, the code closes the note and unlocks and frees the memory.
setprivs.c: The loop that sets the read access |
if (hBuffer != NULLHANDLE)
{
char String[512];
DWORD i;
/ NIFReadEntries requires memory to be locked
(if hBuffer <> 0) /
NOTEID entry = OSLock(NOTEID, hBuffer);
/ process each individual noteID /
for (i=0; i < EntriesReturned; i++, entry++)
{
NOTEHANDLE hNote;
/ skip this noteID if it is for a category entry /
if (entry & NOTEID_CATEGORY)
continue;
/ open each note separately, follow each with
close of note /
if (error = NSFNoteOpen(hDB, entry, 0, &hNote))
{
OSLoadString(NULLHANDLE, ERR(error), String,
sizeof(String)-1);
printf("Error '%s' reading docment %#lX -- %s\n",
String, entry, " skipping it");
error = NOERROR;
continue;
}
if (SetReaderList)
error = UpdateReaderList (hNote, ReaderList,
&NumNotUpdated, &NumUpdated);
else
error = UpdatePrivMask (hNote, NewPrivileges,
&NumNotUpdated, &NumUpdated);
/ close each note /
NSFNoteClose(hNote)
if (error)
{
OSLoadString(NULLHANDLE, ERR(error), String,
sizeof(String)-1);
printf("Error '%s' writing document %#lX -- %s\n",
String, entry, "skipping it");
error = NOERROR;
continue;
}
} / for loop /
/ finished with all noteIDs, unlock memory and free it /
OSUnlockObject(hBuffer);
OSMemFree(hBuffer);
} / if (hBuffer != NULLHANDLE) */
setprivs.c: Updating the read access name list |
STATUS UpdateReaderList (NOTEHANDLE hNote, READER_LIST ReaderList,
DWORD pdwNumNotUpdated, DWORD pdwNumUpdated)
{
STATUS error = NOERROR;
HANDLE hList; / handle to privilege text list /
VOID pList; / pointer to the privilege text list /
WORD wListSize; / total size of text list structure /
WORD i;
char pTextEntry;
/ If the "$Readers" field exists, delete it. /
if (NSFItemIsPresent(hNote, DESIGN_READERS , (WORD) strlen(DESIGN_READERS)))
if (error = NSFItemDelete (hNote, DESIGN_READERS,
(WORD)strlen(DESIGN_READERS)))
return (error);
pTextEntry = (ReaderList.pReaderEntries);
if (pTextEntry[0] == '\0')
{
/ Just update the note - the $Readers field is deleted /
if (!(error = NSFNoteUpdate(hNote, UPDATE_NOCOMMIT)))
(pdwNumUpdated)++;
return (error);
}
/ Create an empty text list structure /
if (error = ListAllocate (0, 0, FALSE, &hList, &pList, &wListSize))
return (error);
OSUnlock(hList);
pList=NULL;
/ Add each text list entry /
for (i = 0; i < ReaderList.NumEntries; i++)
{
pTextEntry = (ReaderList.pReaderEntries + i);
if (error = ListAddEntry (hList, FALSE, &wListSize, i,
pTextEntry,(WORD)strlen(pTextEntry)))
{
OSMemFree(hList);
return (error);
}
} / for /
/ Add the completed field to the note. /
pList = OSLockObject (hList);
error = NSFItemAppend (hNote, ITEM_SUMMARY | ITEM_READERS,
DESIGN_READERS, (WORD)strlen (DESIGN_READERS),
TYPE_TEXT_LIST, pList, wListSize);
/ Unlock and free the buffer that was holding the text list field. /
OSUnlock(hList);
OSMemFree(hList);
if (error)
return (error);
/ Update the note /
if (!(error = NSFNoteUpdate(hNote, UPDATE_NOCOMMIT)))
(pdwNumUpdated)++;
return (error);
}
setprivs.c: Updating the read access privilege levels |
STATUS UpdatePrivMask (NOTEHANDLE hNote, WORD NewPrivMask,
DWORD pdwNumNotUpdated, DWORD pdwNumUpdated)
{
WORD OldPrivMask;
STATUS error = NOERROR;
/ get original privileges, check to see if different /
NSFNoteGetInfo(hNote, _NOTE_PRIVILEGES, &OldPrivMask);
if (OldPrivMask == NewPrivMask)
(pdwNumNotUpdated)++;
else
{
NSFNoteSetInfo (hNote, _NOTE_PRIVILEGES, &NewPrivMask);
if (!(error = NSFNoteUpdate(hNote, UPDATE_NOCOMMIT)))
(pdwNumUpdated)++;
}
return (error);
}
Viewing the Read Access Name List
In Notes, open the database and select a document. Select File - Document Properties and select the key tab. The read access name list is displayed in the text box.
Viewing the Read Access Privilege Levels
In Notes, open the database and select a document. Select File - Document Properties and select the key tab.
Encoding the Read Access Privilege Levels
Privilege levels are specified by the numbers 1 through 5. Each number refers to a specific bit in the WORD used in the third argument of NSFNoteSetInfo. The chart below shows the bits and their corresponding decimal values. To set multiple privilege levels, you must set multiple bits.
Privilege Bit Decimal
Level Number Value
------------------------------------------------------
1 0 1
2 1 2
3 2 4
4 3 8
5 4 16
The privilege code specified in the command line of SETPRIVS is passed as the third argument to NSFNoteSetInfo and is the sum of the desired privilege level decimal values. For example, to specify privilege 3 and privilege 4 on the command line, use 12 for the privilege code. Privilege level 3 has a decimal value of 4 and privilege level 4 has a decimal value of 8. The sum of the two decimal values is 12.