The popstore provides an application program interface (API). With this interface, sites may write their own code to directly create, manipulate, and delete user accounts as well as interface the popstore to billing utilities and other management interfaces.
12.1 Fundamentals
The popstore API is a re-entrant, thread-safe API. User and message
contexts are shared between API client code and the API so as to
facilitate the handling of multiple accounts and messages
simultaneously from either single or multi-threaded programs. Note that
writers of multi-threaded API client code should read Section 12.9 .
Access to the underlying profile and message files is controlled and coordinated by the API subroutines. Programs must not attempt to access those files directly. The contexts used by the API are not opaque: clients of the API are provided with structure definitions for those contexts and can view the individual data fields in them. However, these fields must be treated as read only data and must not be changed. Indeed, changes to them generally will not affect the actual on-disk data. To change the actual, underlying on-disk data, call the appropriate API subroutines to effect the desired change.
For C programmers, a C header file declaring basic constants, data
types, structures, and API subroutines in provided. This header file is
the popstore.h header file and is, on UNIX and NT
platforms, located in the /pmdf/include/ directory. On
OpenVMS platforms, it is located in the PMDF_COM:
directory.
In order to use the popstore API, you must first call the POPSTORE_init subroutine so as to initialize the API. When finished with the API, be sure to call POPSTORE_end. The Sections 12.2 --12.8 provide information and code examples for performing common tasks. Section 12.12 provides complete descriptions for each API subroutine. See Section 12.10 for information on linking programs against the API.
12.2 Creating accounts
There are two approaches to creating accounts: either create an account
from scratch with no default settings for fields in the account's
profile, or create the account by copying fields from another account
profile and then subsequently changing desired fields in the new
account. Either approach is acceptable; both methods are described
below. The advantage to the latter approach is that by copying the
default account, the site's default account settings are
used as an initial basis for the new account.
12.2.1 From scratch
The subroutines POPSTORE_user_create_set and POPSTORE_user_create are
used to create an account from scratch. With a variable of type
POPSTORE_user_context *user_contextinitialized to NULL, make successive calls to POPSTORE_user_create_set to set values for the account to be created. The username field must be set, and it is always a good idea to set a password too unless you genuinely want the account to require no password to access it. After setting the desired fields, call POPSTORE_user_create to actually create the account and dispose of the context created by the first call to POPSTORE_user_create_set. That call will write to disk the profile file for the account and create an entry in the user database. If the username for the account conflicts with another existing account, the account will not be created and a POPSTORE_USEREXISTS error will be returned.
Note that the POPSTORE_user_create_set subroutine will not allow the MANAGE usage flag to be set or cleared without first calling POPSTORE_manage to explicitly authorize such actions. (cleared). Note further that regardless of any value set for the last billing field, that field will be set to the current date and time when POPSTORE_user_create is called.
An example program which creates the profile
# pmdf popstore show joe Username: joe Owner: Joe User Group: staff Usage flags: Last connect: No time recorded Last disconnect: No time recorded Total connect time: 0 00:00:00 Total connections: 0 Past block days: 0 Last billing: Tue Jun 24 10:25:18 1997 Message count: 0 (0 total messages received) Quota used: 0.00 Kbytes Primary quota: 90.00 Kbytes Overdraft quota: 10.00 Kbytesis shown in
Examples
12-1 Creating a new account from
scratch
/******************************************************************
* *
* create_sample.c *
* Sample subroutine to create a popstore account from scratch. *
* *
******************************************************************/
#include <stdio.h>
#include <stdlib.h>
#ifdef __VMS
# include "pmdf_com:popstore.h"
#else
# include "/pmdf/include/popstore.h"
#endif
void check (int stat) (1)
{
if (stat == POPSTORE_SUCCESS) return;
fprintf (stderr, "Error %d: %s\n", stat, POPSTORE_error_to_text (stat));
(void) POPSTORE_end ();
exit (1);
}
main ()
{
POPSTORE_user_context *ctx;
/*
* Initialize the popstore
*/
check (POPSTORE_init (1, NULL, "create_sample", 13)); (2)
/*
* Set values for various fields
*/
ctx = NULL;
check (POPSTORE_user_create_set (&ctx, POPSTORE_SET_USERNAME, 3, "joe")); (3)
check (POPSTORE_user_create_set (&ctx, POPSTORE_SET_GROUP_NAME, 5, "staff"));
check (POPSTORE_user_create_set (&ctx, POPSTORE_SET_OWNER, 10, "Joe User"));
check (POPSTORE_user_create_set (&ctx, POPSTORE_SET_PASSWORD, 6, "secret"));
check (POPSTORE_user_create_set (&ctx, POPSTORE_SET_QUOTA, 1024*90));
check (POPSTORE_user_create_set (&ctx, POPSTORE_SET_OVERDRAFT, 1024*10));
/*
* Create the account
*/
check (POPSTORE_user_create (&ctx)); (4)
/*
* All done
*/
(void) POPSTORE_end (); (5)
}
12.2.2 By copying
New accounts may also be created by copying an old account with the
POPSTORE_user_copy_d subroutine and then changing the value of fields
with POPSTORE_user_update. For instance, both of the popstore
management interfaces create new accounts by copying the
default account to the new account and then changing the
requested fields in the new account.
Note that the POPSTORE_user_update subroutine will not allow the MANAGE usage flag may not be set or cleared without first calling POPSTORE_manage to explicitly authorize such actions.
The code in Examples
12-2 creates the account joe by first
copying the default account and then changing fields in
the newly created joe account with POPSTORE_user_update.
The account so created is identical to that created from scratch in
Examples
12-1 . The following items of note are identified with
callouts in the example program:
default
account except for the username and password fields.
Examples
12-2 Creating a new account by copying
thedefaultaccount
/****************************************************************
* *
* copy_sample.c *
* Sample subroutine to create a popstore account by copying *
* the default account. *
* *
****************************************************************/
#include <stdio.h>
#include <stdlib.h>
#ifdef __VMS
# include "pmdf_com:popstore.h"
#else
# include "/pmdf/include/popstore.h"
#endif
static POPSTORE_user_context *user_context = NULL;
void check (int stat) (1)
{
if (stat == POPSTORE_SUCCESS) return;
fprintf (stderr, "Error %d: %s\n", stat, POPSTORE_error_to_text (stat));
if (user_context) (void) POPSTORE_user_end (user_context);
(void) POPSTORE_end ();
exit (1);
}
#define PUSH(list,code,addr,len) \ (2)
list[item_index].item_code = (code); \
list[item_index].item_address = (addr); \
list[item_index++].item_length = (len);
main ()
{
POPSTORE_item_list item_list[5];
int item_index = 0;
char group[] = "staff";
char owner[] = "Joe User";
uint32 quota = 1024*90;
uint32 overdraft = 1024*10;
/*
* Initialize the popstore
*/
check (POPSTORE_init (1, NULL, "copy_sample", 11)); (3)
/*
* Build an item list describing the fields to set new values for
*/
PUSH (item_list, POPSTORE_SET_GROUP_NAME, group, strlen (group)); (4)
PUSH (item_list, POPSTORE_SET_OWNER, owner, strlen (owner));
PUSH (item_list, POPSTORE_SET_QUOTA, "a, 0);
PUSH (item_list, POPSTORE_SET_OVERDRAFT, &overdraft, 0);
PUSH (item_list, POPSTORE_SET_END, NULL, 0);
/*
* Create the new account as a duplicate of the default account but
* with the desired new username and password
*/
check (POPSTORE_user_copy_d (NULL, 0, "default", 7, (5)
NULL, 0, "joe", 3,
"secret", 6, 0));
/*
* Change the account settings
*/
check (POPSTORE_user_begin_d (NULL, 0, &user_context, "joe", 3,
POPSTORE_NOACCOUNTING, "copy_sample", 11));
check (POPSTORE_user_update (user_context, item_list)); (6)
check (POPSTORE_user_end (user_context));
user_context = NULL;
/*
* All done
*/
POPSTORE_end ();
}
12.3 Modifying accounts
Fields in an existing account may be modified using the
POPSTORE_user_update subroutine. This subroutine accepts as input a
user context created by POPSTORE_user_begin_d and an item list
describing the fields to change and the new values to use for those
fields. Before making any changes, the validity of the entries in the
item list is first determined. Only if the entries are all correct, are
any changes then made. The changes are made atomically: the profile is
locked, read, all changes made, written back to disk, and then
unlocked. In the event of an unexpected error, the old profile data is
restored if possible.
An example of using POPSTORE_user_update is given in Examples
12-2 .
When modifying accounts, keep the following notes in mind:
12.4 Deleting accounts
Accounts are deleted with POPSTORE_user_delete_d. When an account is
deleted, any unread messages for that account may optionally be
returned to their originators. Shown below is the call which would be
made to delete the account jdoe, returning any unread
messages to their originators:
stat = POPSTORE_user_delete_d ("jdoe", 4, 1);
12.5 Listing accounts
Formatted listings of accounts may be generated with the
POPSTORE_format_profiles_d procedure. Note that this same functionality
is provided at the command line with the POPSTORE utility; see
Chapter 9 for details. In order to use POPSTORE_format_profiles_d,
you must first decide upon a layout for the listing and then implement
that layout with a formatting file. See the description of the
POPSTORE_format_profiles_d subroutine for further details. Once a
formatting file has been developed, it may then be used to format
listings of user accounts. In the example code shown in Examples
12-4 ,
an actual formatting file used by the POPSTORE utility is used. That
formatting file, as can be seen in Examples
12-3 , lists for each
account the username, stored message count, and used quota.
Examples
12-3 Formatting file for account
listings
%first{ Message Quota used}
%first{ Username Count (kbytes)}
%first{ ------------------------------------------------------}
%flags_manage{ |*}%username{%-32s} %message_count{%7u} %quota_used_k{%8.2f}
%last{ ----------------------------------------------------------------}
%last{*Note: privileged users are flagged with an asterisk}
Examples
12-4 Generating account listings
/***************************************************************
* *
* format_sample.c *
* Sample subroutine to generate an account listing. *
* *
***************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef __VMS
# include "PMDF_COM:popstore.h"
#else
# include "/pmdf/include/popstore.h"
#endif
void check (int stat)
{
if (stat == POPSTORE_SUCCESS) return;
fprintf (stderr, "Error %d: %s\n", stat, POPSTORE_error_to_text (stat));
(void) POPSTORE_end ();
exit (1);
}
int output (void *ctx, char *line, int len, int eol, int literal)
{
if (!eol) printf ("%.*s", len, line);
else printf ("%.*s\n", len, line);
return (POPSTORE_SUCCESS);
}
main ()
{
POPSTORE_format_element *format;
/*
* Initialize the popstore
*/
check (POPSTORE_init (0, NULL, "format_sample", 13));
/*
* Read in the formatting file and get a formatting context
*/
check (POPSTORE_format_read (&format, "popmgr_profile_brief.txt", 24,
#ifdef __VMS
"PMDF_HTTP_POPSTORE:[000000]", 27));
#else
"/pmdf/www/popstore/", 19));
#endif
/*
* Display the profiles
*/
check (POPSTORE_format_profiles_d (format, NULL, 0, NULL, 0, NULL, 0, NULL,
NULL, output));
/*
* Dispose of the formatting context
*/
check (POPSTORE_format_dispose (format));
/*
* All done
*/
(void) POPSTORE_end ();
}
To generate a simple listing of accounts, the POPSTORE_user_list_d
subroutine may prove sufficient. That subroutine is primarily intended
for cases where a program needs to obtain one-by-one the usernames for
each account. Sample code using POPSTORE_user_list_d to list all
accounts and then the first account with a username starting with the
letter "z" is given in Examples
12-5 .
Examples
12-5 Simple account listing
/***************************************************************
* *
* list_sample.c *
* Sample subroutine to generate an account listing. *
* *
***************************************************************/
#include <stdio.h>
#ifdef __VMS
# include "PMDF_COM:popstore.h"
#else
# include "/pmdf/include/popstore.h"
#endif
main ()
{
POPSTORE_list_context *list_context;
int stat, userlen;
char user[POPSTORE_MAX_USER_LEN+1];
/*
* Initialize the popstore
*/
stat = POPSTORE_init (1, NULL, "list_sample", 11);
if (stat != POPSTORE_SUCCESS) exit (1);
/*
* List all accounts
*/
printf ("---- Listing of all accounts ----\n");
list_context = NULL;
stat = POPSTORE_SUCCESS;
while (stat == POPSTORE_SUCCESS) {
stat = POPSTORE_user_list_d (&list_context, "*", 1, NULL, 0, NULL, 0,
user, &userlen, POPSTORE_MAX_USER_LEN + 1);
if (stat == POPSTORE_SUCCESS) printf ("%s\n", user);
}
printf ("\n---- The first account starting with the letter \"z\" ----\n");
list_context = NULL;
stat = POPSTORE_user_list_d (&list_context, "z*", 2, NULL, 0, NULL, 0,
user, &userlen, POPSTORE_MAX_USER_LEN + 1);
if (stat == POPSTORE_SUCCESS) {
printf ("%s\n", user);
/* Done with this context; dispose of it now */
(void) POPSTORE_user_list_abort (&list_context);
}
else printf ("**** No accounts begin with the letter \"z\" ****\n");
/*
* All done
*/
(void) POPSTORE_end ();
}
12.6 Billing accounts
Sites who wish to bill users for usage should use the
POPSTORE_user_billing_d subroutine to perform atomic billing
operations. That subroutine locks a user profile, extracts billing
information, resets accounting fields, writes the user profile back to
disk, unlocks the profile, and then returns the extracted billing
information to the caller.
The billing period is the intervening time between when POPSTORE_user_billing_d was last called and the current billing time supplied to POPSTORE_user_billing_d. The time when POPSTORE_user_billing_d was last called is stored in each account's last billing profile field.¹
The extracted billing information includes the total connect time and past block days of message storage used during the billing period. After that information is extracted, those two fields are set to the value zero. In addition, the last billing time fields in the profile and message list are set to the new billing time supplied to POPSTORE_user_billing_d, and this data is then written out to the on-disk profile file.
Examples
12-6 shows sample code which uses POPSTORE_user_billing_d in
conjunction with POPSTORE_user_list_d to bill each account whose
associated username starts with the letter "a" and is in the
students management group.
Examples
12-6 Account billing operations
/***************************************************************
* *
* bill_sample.c *
* Sample subroutine to bill each popstore account. *
* *
***************************************************************/
#include <stdio.h>
#include <times.h>
#ifdef __VMS
# include "PMDF_COM:popstore.h"
#else
# include "/pmdf/include/popstore.h"
#endif
main ()
{
time_t billing_time;
POPSTORE_user_data data;
POPSTORE_list_context *list_context;
int stat, stat2, userlen;
char user[POPSTORE_MAX_USER_LEN + 1];
/*
* Initialize the popstore
*/
stat = POPSTORE_init (1, NULL, "list_sample", 11);
if (stat != POPSTORE_SUCCESS) exit (1);
/*
* Output a heading
*/
printf (" Connect Block\n");
printf ("Username Time Days\n");
printf ("-------------------------------- ------- -------\n");
/*
* Now, loop over each account and bill it
*/
billing_time = time (NULL);
list_context = NULL;
do {
stat = POPSTORE_user_list_d (&list_context, "a", 1, NULL, 0,
"students", 8, user, &userlen,
POPSTORE_MAX_USER_LEN + 1);
if (stat == POPSTORE_SUCCESS) {
stat2 = POPSTORE_user_billing_d (NULL, 0, user, userlen, billing_time,
&data);
if (stat2 == POPSTORE_SUCCESS) {
printf ("%-32s %7u %7u\n", user, data.total_connect,
data.past_block_days);
} else {
fprintf (stderr, "Unable to bill %.*s; error = %d\n", userlen, user,
stat2);
fprintf (stderr, "%s\n", POPSTORE_error_to_text (stat2));
}
}
} while (stat == POPSTORE_SUCCESS);
if (stat != POPSTORE_EOM) {
fprintf (stderr, "POPSTORE_user_list_d returned the error %d\n", stat);
fprintf (stderr, "%s\n", POPSTORE_error_to_text (stat));
}
/*
* All done
*/
(void) POPSTORE_end ();
}
To store a message into the message store, enqueue it as a mail message to PMDF with the desired popstore recipients given as the message's envelope To: recipients. See the PMDF Programmer's Reference Manual for information on using the PMDF API to enqueue messages to PMDF.
12.8 Accessing messages
A user's messages are accessed by first obtaining a user context,
user_context, with POPSTORE_user_begin_d. The list of
stored messages is the array of POPSTORE_message_ref
structures which start at the address
user_context->messagesand contain
user_context->profile->message_countarray elements. For example, the following code fragment counts the number of unread messages stored for the user
sue:
Examples
12-7 Message lists
int i, new_count, stat;
POPSTORE_message_ref *msg_ptr;
POPSTORE_user_context *user_context;
...
stat = POPSTORE_user_begin_d (&user_context, "sue", 3, POPSTORE_NOACCOUNTING,
"new message count", 17);
new_count = 0;
for (i = 0, msg_ptr = user_context->messages;
i < user_context->profile->message_count;
i++, msg_ptr++)
if (!(msg_ptr->flags & POPSTORE_MFLAGS_READ)) new_count++;
stat = POPSTORE_user_end (user_context);
printf ("Sue has %d new messages\n", new_count);
...
Individual messages are accessed and manipulated with the POPSTORE_message_ subroutines. When accessing or manipulating a message, the message is referenced using its "message index". The first message stored for a user has message index value 1, the second index value 2, the third index value 3, and so on.
The code shown in Examples
12-8 displays each new message for the user
sue, marking each message as read after displaying it.
Examples
12-8 Displaying new messages
/***************************************************************
* *
* read_sample.c *
* Sample subroutine to display new messages for an account. *
* *
***************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef __VMS
# include "pmdf_com:popstore.h"
#else
# include "/pmdf/include/popstore.h"
#endif
void check (int stat)
{
if (stat == POPSTORE_SUCCESS) return;
fprintf (stderr, "Error %d: %s\n", stat, POPSTORE_error_to_text (stat));
(void) POPSTORE_end ();
exit (1);
}
void display_message (POPSTORE_user_context *user_context, int msg_index)
{
char buffer[1024+1];
int len, message_context, stat;
printf ("=========================================================\n");
printf ("Message %d\n", msg_index);
printf ("=========================================================\n");
if (POPSTORE_SUCCESS !=
POPSTORE_message_begin (user_context, msg_index, &message_context,
NULL, 0, NULL, 0)) return;
do {
stat = POPSTORE_message_read (message_context, buffer, 1024, &len);
if (stat != POPSTORE_READERROR) {
buffer[len] = '\0';
printf ("%s", buffer);
}
} while (stat == POPSTORE_SUCCESS);
(void) POPSTORE_message_end (message_context);
printf ("=========================================================\n");
}
main ()
{
POPSTORE_message_ref *msg_ptr;
int i, stat;
POPSTORE_user_context *user_context;
/*
* Initialize the popstore
*/
check (POPSTORE_init (1, NULL, "read_sample", 11));
/*
* Access the popstore account
*/
check (POPSTORE_user_begin_d (NULL, 0, &user_context, "sue", 3,
POPSTORE_ACCOUNTING, "read_sample", 11));
/*
* Display the new messages
*/
msg_ptr = user_context->messages;
for (i = 0, msg_ptr = user_context->messages;
i < user_context->profile->message_count;
i++, msg_ptr++)
if (!(msg_ptr->flags & POPSTORE_MFLAGS_READ)) {
display_message (user_context, i+1);
(void) POPSTORE_message_mark_read (user_context, i+1);
}
/*
* Deaccess the account
*/
(void) POPSTORE_user_end (user_context);
/*
* And shut down the popstore
*/
(void) POPSTORE_end ();
}
12.9 Using the API from multi-threaded programs
Multi-threaded programs need to register mutex handling subroutines
with the PMDF API subroutine PMDF_set_mutex prior to initializing
either the PMDF or popstore APIs. In addition, when calling
POPSTORE_initialize, supply the address of the sleep subroutine
provided to PMDF_set_mutex.
12.10 Compiling and linking programs
OpenVMS systems
To declare the API subroutines, data structures, and constants, C
programs should use the PMDF_COM:popstore.h header file.
Linking programs to the popstore API is accomplished with a link command of the form
$ LINK program,PMDF_EXE:pmdfshr_link.opt/OPTwhere
program is the name of the object file to
link.
To declare the API subroutines, data structures, and constants, C
programs should use the /pmdf/include/popstore.h header
file.
Linking a C program to the API is accomplished with a link command of the form
% cc -Wl,-rpath,/pmdf/lib/ -L/pmdf/lib/ -o \
program program.c -lpmdf -lc -ldb -lldapv3
where program is the name of your program.
To declare the API subroutines, data structures, and constants, C
programs should use the /pmdf/include/popstore.h header
file.
Linking a C program to the API is accomplished with a link command of the form
% cc -R/pmdf/lib/ -L/pmdf/lib/ -o program program.c \
-lpmdf -lsocket -lintl -lnsl -lm -ldb -lldapv3
where program is the name of your program.
To declare the API subroutines, data structures, and constants, C
programs should use the C:\pmdf\include\popstore.h header
file.
When linking programs to the API with the Microsoft C/C++ compiler, use the switches
-mD -D_WIN32_WINNT=0x0400 C:\pmdf\lib\libpmdf.lib
12.11 Basic constants, types, and data structures
Basic constants and data types used by the popstore are listed in
Tables 12-1 and 12-2 . The data structures describing
a user profile, POPSTORE_user_data, and a message list,
POPSTORE_message_list, are shown in Sections 12.11.1
and Section 12.11.2 . A user context as obtained from the
POPSTORE_user_begin_d subroutine, is a pointer to a
POPSTORE_user_context structure and is described in
Section 12.11.3 . Fields in that structure point to data structures
containing the user's profile and message list. All of these constants,
data types, and structures are declared in the popstore.h
header file located in the /pmdf/include/ directory on
UNIX and NT platforms and the PMDF_COM: directory on
OpenVMS.
| Constant | Value | Description |
|---|---|---|
| ALFA_SIZE | 252 | A basic PMDF string size |
| BIGALFA_SIZE | 1024 | A basic PMDF string size |
| POPSTORE_FLAGS_DELETE | 16 | Bit mask for the DELETE usage flag bit |
| POPSTORE_FLAGS_DISMAIL | 2 | Bit mask for the DISMAIL usage flag bit |
| POPSTORE_FLAGS_DISUSER | 1 | Bit mask for the DISUSER usage flag bit |
| POPSTORE_FLAGS_LOCKPWD | 4 | Bit mask for the LOCKPWD usage flag bit |
| POPSTORE_FLAGS_MANAGE | 8 | Bit mask for the MANAGE usage flag bit |
| POPSTORE_FULL_UIDL_LEN | 23 | Length in bytes of a full message UIDL derived |
| POPSTORE_MAX_DOMAIN_LEN | 40 | Maximum length in bytes of a user domain name |
| POPSTORE_MAX_FILE_LEN | 1024 | Maximum length in bytes for full file paths |
| POPSTORE_MAX_GROUP_LEN | 16 | Maximum length in bytes of a management group name |
| POPSTORE_MAX_OWN_LEN | 40 | Maximum length in bytes for the profile owner field |
| POPSTORE_MAX_PRIV_LEN | 64 | Maximum length in bytes for the profile site-defined private data field |
| POPSTORE_MAX_PWD_LEN | 32 | Maximum length in bytes for the profile password field |
| POPSTORE_MAX_USER_LEN | 32 | Maximum length in bytes for the profile username field |
| POPSTORE_MFLAGS_READ | 1 | Bit mask for the READ message flag bit |
| POPSTORE_MSG_FILE_FORMAT_VERSION | 0 | Current value for message file format version |
| POPSTORE_MSG_NAME_LEN | 19 | Length in bytes of a message file name |
| POPSTORE_USERDATA_VERSION | 2 | Current value for the profile file format version |
| Type | Size (bytes) | Underlying data type |
|---|---|---|
| int32 | 4 | int |
| ubyte | 1 | unsigned char |
| uint32 | 4 | unsigned int |
| ushort | 2 | unsigned short int |
12.11.1 POPSTORE_user_data structure
User profile information is stored in a POPSTORE_user_data
structure of the form shown below. To change user profile information,
the POPSTORE_user_set or POPSTORE_user_update subroutines should be
used. The former is used when creating an account---an account which
does not yet exist. The latter is used to modify an existing account.
The profile information for an existing account is obtained with the
POPSTORE_user_begin_d subroutine. That subroutine returns a pointer to
a POPSTORE_user_context structure; the profile data is
pointed at by the profile field in that structure.
The layout of the POPSTORE_user_data structure is shown
below:
typedef struct {
ubyte version;
ubyte store_type;
ushort flags;
ubyte ulen;
ubyte plen;
ubyte olen;
ubyte slen;
char username[POPSTORE_MAX_USER_LEN];
char password[POPSTORE_MAX_PWD_LEN];
char owner[POPSTORE_MAX_OWN_LEN];
ubyte private[POPSTORE_MAX_PRIV_LEN];
uint32 quota;
uint32 return_after;
uint32 overdraft;
time_t last_billing;
uint32 total_conntections;
time_t last_connect;
uint32 reserved4;
time_t last_disconnect;
uint32 total_connect;
uint32 past_block_days;
uint32 past_block_days_remainder;
uint32 message_count;
uint32 quota_used;
uint32 received_messages;
uint32 received_bytes;
ubyte reserved5[3];
ubyte glen;
char group[POPSTORE_MAX_GROUP_LEN];
} POPSTORE_user_data;
The interpretation of these fields are as follows: Data structure version number. The current version number for the data structure is given by the POPSTORE_USERDATA_VERSION constant.
versionType of message store used for this profile. Value will typically be zero (POPSTORE_STORE_TYPE_POP).
store_typeBit masked field containing usage flag settings. The bits in this field may be tested with the POPSTORE_FLAGS_ constants.
flagsLength in bytes of the value stored in the username field.
ulenLength in bytes of the value stored in the password field. The value of this field is encrypted.
plenLength in bytes of the value stored in the owner field.
olenLength in bytes of the value stored in the private field.
slenThe account username. This field is not null terminated; the length of the value stored in this field is given by the value of the ulen field.
usernameThe account password. The value stored in this field is encrypted and is not null terminated. The encrypted value of the plen field gives the length of the value stored in this field.
passwordAccount owner information. This field is not null terminated; the length of the value stored in this field is given by the value of the olen field.
ownerSite-defined private data field. The length of the value stored in this field is given by the value of the slen field. This field is not null terminated.
privatePrimary message storage quota measured in units of bytes. A value of zero for this field conveys unlimited storage quota.
quotaField reserved for future use.
return_afterMessage overdraft storage quota.
overdraftTime of last billing as measured in seconds since 1 January 1970. This field is set to the current time when the account is first created.
last_billingCumulative count of connections made to the account sicne either the account was created or this field last cleared.
total_connectionsTime of last connection attempt as measured in seconds since 1 January 1970. This field is set for both successful and unsuccessful login attempts. The time is recorded when the user context is created with POPSTORE_user_begin_d and written to the profile when the context is disposed of with POPSTORE_user_end.
last_connectField reserved for future use.
reserved4Time of last disconnect as measured in seconds since 1 January 1970. This field is set for both successful and unsuccessful login attempts. The time is recorded when the user context is disposed of with POPSTORE_user_end.
last_disconnectTotal number of seconds spent connected since the account was created or this field last cleared.
total_connectCumulative block days for previously stored and since deleted or returned messages since the account was created or this field last cleared. The value of this field does not take into account messages currently held in the store.
past_block_daysRemainder field used in computation of block days. This field is measured in units of byte seconds.
past_block_days_remainderCount of messages currently stored for the account.
message_countNumber of bytes currently being consumed to store messages for the account. This value only takes into consideration the size of the underlying messages themselves and not the size of the actual container files.
quota_usedCumulative count of messages received and stored for the account since either the account was created or this field last cleared.
received_messagesCumulative count of message bytes received and stored for the account since either the account was created or this field last cleared.
received_bytesField reserved for future use.
reserved5Length in bytes of the value stored in the
glengroupfield.Name of the management group to which this account belongs.
group
12.11.2 POPSTORE_message_ref structure
A user's list of stored messages is stored as an array of zero or more
array elements each of type POPSTORE_message_ref. To
change information in the list (e.g., mark messages for
deletion), use the appropriate POPSTORE_message_ subroutine. The list
of an account's stored messages is obtained with the
POPSTORE_user_begin_d subroutine. That subroutine returns a pointer to
a POPSTORE_user_context structure; the message list is
pointed at by the messages field in that structure. The
count of stored messages, and hence the count of array elements in the
message list, is given by the user profile information also available
from the user context structure. See, for instance, Examples
12-7 .
The layout of the POPSTORE_message_ref structure is shown
below:
typedef struct {
uint32 size;
uint32 last_billing;
time_t created;
uint32 flags;
char uidl[4];
char filename[POPSTORE_MSG_NAME_LEN];
ubyte pad;
} POPSTORE_message_ref;
The interpretation of these fields are as follows: Size in bytes of the message. This size includes CRLF terminators but does not include any dots used for dot stuffing.
sizeTime at which usage billing was last done for the storage of this message. Measured as the count of seconds since 1 January 1970.
last_billingTime at which the message file was created. Measured as the count of seconds since 1 January 1970.
createdBit masked field containg message status flag bits. The bits in this field may be tested with the POPSTORE_MFLAGS_ constants. Currently, only one flag bit is stored in the message list: the read/unread bit accessed with the POPSTORE_MFLAGS_READ bit mask.
flagsThe message UIDL begins with this field and includes the
uidlfilenamefield. The length in bytes of the UIDL is given by POPSTORE_FULL_UIDL_LEN. This portion of the UIDL is unique for each recipient of the underlying message file.This field forms part of the message UIDL and is the same for all popstore recipients of this particular message. This field also is the name of the underlying file containing the message.
filenameA padding byte. The value of this byte is set to zero thus making the full UIDL accessible as a null terminated string.
pad
12.11.3 POPSTORE_user_context structure
Information about a popstore account is returned to callers of
POPSTORE_user_begin_d in the form of a pointer to a structure of type
POPSTORE_user_context---a "user context". Fields
in this structure must not be changed; use the appropriate API
subroutines to effect the needed changes. When through with a user
context, call POPSTORE_user_end to dispose of the context. Note that it
is important that that call be made: not only does it dispose of
allocated resources, it also updates accounting information for the
account and performs any requested message deletion operations.
The layout of the POPSTORE_user_context structure is shown
below:
typedef struct {
time_t connect;
uint32 log_subid;
int do_accounting;
uint32 block_days;
uint32 block_days_remainder;
POPSTORE_user_data *profile;
POPSTORE_message_ref *messages;
POPSTORE_string filespec;
char pad[3];
POPSTORE_userdb_data *userdb_data;
void *reserved0;
char domain[POPSTORE_MAX_DOMAIN_LEN];
int dlen;
} POPSTORE_user_context;
The interpretation of these fields are as follows: Time at which this context was established.
connectSub-identifier used for logging purposes.
log_subidFlag indicating whether or not accounting should be done for this context.
do_accountingAccumulated block days for messages deleted with this context.
block_daysAccumulated block days roundoff for messages deleted with this context.
block_days_remainderThe user's profile data. The value of this field is a pointer to the profile information for this user account.
profileThe user's list of stored messages. The value of this field is a pointer to an array of POPSTORE_message_ref elements. This array contains
messagesprofile->message_countelements.File specification for the underlying profile file.
filespecAlignment padding bytes.
padThis field will usually be NULL. It is a pointer to the account's user database record. That record is only obtained when the popstore is performing management operations and even then only seldom.
userdb_dataField reserved for future use.
reserved0User domain associated with this account.
domainLength in bytes of the user domain associated with this account. A length of zero indicates the
dlendefaultdomain.
12.12 Subroutine descriptions
This section documents the individual popstore API subroutines. A brief
description of each subroutine is given in Table 12-3 below.
| Subroutine name | Description |
|---|---|
| POPSTORE_command | Obsolete: use the POPSTORE_command_d subroutine |
| POPSTORE_command_d | Process a management command |
| POPSTORE_end | End usage of the API |
| POPSTORE_error_to_text | Convert a numerical error to a textual error message |
| POPSTORE_format_counters | Format PMDF channel counter information |
| POPSTORE_format_dispose | Dispose of a formatting context |
| POPSTORE_format_forwarding | Obsolete: use the POPSTORE_format_forwarding_d subroutine |
| POPSTORE_format_forwarding_d | Format forwarding information |
| POPSTORE_format_message | Format a stored message |
| POPSTORE_format_messages | Format a user's list of stored messages |
| POPSTORE_format_profile | Format a user profile |
| POPSTORE_format_profiles | Obsolete: use the POPSTORE_format_profiles_d subroutine |
| POPSTORE_format_profiles_d | Format a list of user profiles |
| POPSTORE_format_read | Read and parse a formatting file |
| POPSTORE_init | Initialize the API |
| POPSTORE_manage | Allow changing of the MANAGE usage flag |
| POPSTORE_message_begin | Access a stored message |
| POPSTORE_message_end | Deaccess a stored message |
| POPSTORE_message_mark_delete | Mark a user's message copy for deletion |
| POPSTORE_message_mark_nodelete | Mark a user's message to be retained |
| POPSTORE_message_mark_noread | Mark a user's message as being unread |
| POPSTORE_message_mark_read | Mark a user's message as read |
| POPSTORE_message_read | Sequentially read a message |
| POPSTORE_message_return | Return a message to its originator |
| POPSTORE_user_begin | Obsolete: use the POPSTORE_user_begin_d subroutine |
| POPSTORE_user_begin_d | Access a user account |
| POPSTORE_user_billing | Obsolete: use the POPSTORE_user_billing_d subroutine |
| POPSTORE_user_billing_d | Perform billing operations |
| POPSTORE_user_copy | Obsolete: use the POPSTORE_user_copy_d subroutine |
| POPSTORE_user_copy_d | Copy or rename an existing account |
| POPSTORE_user_create | Create a new account |
| POPSTORE_user_create_dispose | Abort creating a new account |
| POPSTORE_user_create_set | Set the value of a field for an account to be created with POPSTORE_user_create |
| POPSTORE_user_delete | Obsolete: use the POPSTORE_user_delete_d subroutine |
| POPSTORE_user_delete_d | Delete a user account |
| POPSTORE_user_end | Deaccess a user account |
| POPSTORE_user_exists | Obsolete: use the POPOPSTORE_user_exists_d subroutine |
| POPSTORE_user_exists_d | See if a username specifies a valid account |
| POPSTORE_user_list | Obsolete: use the POPSTORE_user_list_d subroutine |
| POPSTORE_user_list_abort | Prematurely dispose of a list |
| POPSTORE_user_list_d | Return the usernames associated with each account within an accounting group |
| POPSTORE_user_pw_change | Obsolete: use the POPSTORE_user_pw_change_d subroutine |
| POPSTORE_user_pw_change_d | Change a user's password |
| POPSTORE_user_pw_check | Perform an authentication check |
| POPSTORE_user_update | Update a field in an existing account |