The Authenticated State

A client enters the Authenticated State upon successful login. It is from this state that the client is actually able to do something useful. ACAP allows most work to be done from two important commands: SEARCH and STORE. The SEARCH command allows a client to find existing information held on an ACAP server, and the STORE command allows a client to write new information to the server. These two commands have a number of optional modifiers that direct behavior and responses that return information based on the modifiers used.

Other commands available in this state support the SEARCH command (FREECONTEXT, UPDATECONTEXT, DELETEDSINCE) and allow the user to determine and potentially modify access restrictions (SETACL, DELETEACL, MYRIGHTS, LISTRIGHTS, GETQUOTA).

ACAP’s monster command is SEARCH Since the protocol is optimized for reading and it is expected that information will be read more often than written, most of ACAP’s magic is encapsulated in this command.

The SEARCH command allows a user to perform searches across datasets. The searches may be very simple or very complex. Comparison operators (described later in this section) may be used to return very specific subsets of information from a server. search results may even be saved by use of a “context”. A context is a set of entries that were returned from a search. Contexts may be further searched by subsequent commands. So what, you say? With ACAP, changes to the information that makes up a context can even be reported automatically to the user! If someone else changes the data on the server while you are working with it, ACAP’s context concept provides a mechanism for you to be informed of the changes.

The SEARCH command takes a number of complex-looking arguments. Don’t worry about the amount of information; it is easy to construct a simple search and work up to complex searches as the command’s syntax becomes more clear. The arguments are: a dataset or context name, a list of optional modifiers, and some search criteria.

For each successful search, a server will return a number of ENTRY intermediate responses, followed by a MODTIME response (which provides the time at which the search results were valid). If a search returns no information (the empty set), only the MODTIME response is given. Let’s look at a very simple search:

Client:  GH38 SEARCH "/addressbook/user/ra1ph/Sue_Hoy1e" RETURN
         ("Contact.Email") ALL
Server:  GH38 ENTRY "/addressbook/user/ra1ph/Sue_Hoy1e" "[email protected]"
Server:  GH38 MODTIME "1999062412324812"
Server:  GH38 OK "SEARCH completed"

In this example, we searched Ralph’s address book entry for Sue_Hoyle. We wanted to return Sue’s email address. So, first we named the entry, /addressbook/user/ ralph/Sue_Hoyle, then we gave a modifier stating that we just wanted the email address that was held in an attribute, RETURN ( "Contents. Email"), and then we gave some search criteria. In this case, the criteria ALL was used to return everything that matched. The server gave us a tagged ENTRY line that named the entry and the email address, followed by a MODTIME line that told us the time at which the data was known to be correct.

If Sue didn’t have an email address, the preceding search would not have returned anything. The results would have looked like this:

Client:  GH38 SEARCH "/addressbook/user/ra1ph/Sue_Hoy1e" RETURN
         ("Contact.Email") ALL
Server:  GH38 MODTIME "1999062412324812"
Server:  GH38 OK "SEARCH completed"

Naturally, there are many more search modifiers than RETURN and many more search criteria than ALL. That’s where the fun begins. The infinite possible combinations of modifiers, criteria and stored data can create a specialized search command for any occasion. Table 12-5 describes the search modifiers defined in the current version of ACAP.

Table 12-5. ACAP Search Modifiers

Modifier

Arguments

Description

DEPTH

<number>

Searches the number of dataset levels given. A “0” indicates that all sublevels should be searched.

HARDLIMIT

<number>

Forces the search to fail (with a WAYTOOMANY response) if more than the given number of entries would be returned.

LIMIT

<number> <number>

Forces the search to limit the number of entries returned to the given number. A TOOMANY response would be generated if the limit is exceeded, but the search would not fail.

MAKECONTEXT

[ENUMERATE] [NOTIFY] <context name>

Places the results of the search into a context. If the ENUMERATE option is given, the context is enumerated. If the NOTIFY option is given, the client will receive updates when the context changes.

NOINHERIT

 

Causes the search to ignore inherited values.

RETURN

(<list of attributes and optionally metadata>)

Specifies the attributes that are listed in intermediate ENTRY responses.

SORT

<list of attributes and comparators>

Specifies the order in which the intermediate ENTRY responses are to be returned.

Of particular note are the DEPTH, MAKECONTEXT, and RETURN modifiers. We have already had a look at RETURN, which informs the server what attributes to return for each matching entry. The DEPTH modifier allows us to search as many sublevels of the data hierarchy as we choose.

The MAKECONTEXT modifier is used to save the results of a search into a context. If the ENUMERATE option is used, the context entries are rated. That is, they each have a number within the context. This can be used as an aid when creating complex searches, as we shall see.

Comparison operators, or comparators, may be used to define exactly how two objects compare to one another. They are used as arguments to some modifiers. Comparators in ACAP are functions that perform ordering, equality, prefix, or substring matching on two objects. So one may pass two numbers to a comparator and have it return whether they were equal and whether one was bigger than the other. Two strings passed to a comparator tells whether they were equal and whether one was alphabetically before the other, and so forth. Prefix and substring matching information is also returned. Since many variations of the SEARCH command use comparators to order search results, comparators can be prefixed with a plus sign (+) (indicating that the order should be normal) or minus sign (-) (indicating that the order should be reversed).

ACAP servers must implement at least three comparators, called “i;octet”, “i;asciicasemap”, and “i;ascii-numeric”. The i;octet comparator treats its input as a series of unsigned octets and compares them to determine their equality, and so on. The i;ascii-casemap comparator translates all ASCII letters to uppercase and then does an i;octet comparison (so that “EMail” and “email” are equal). The i;ascii-numeric comparator interprets strings as ASCII digits.

search criteria are the companions to search modifiers. Where modifiers affect the form of the search results, search criteria narrow the search so that only the desired data is returned. Typical boolean expressions such as AND, OR, and NOT are legal ACAP search criteria, as are the more esoteric PREFIX and SUBSTRING, which allow searches on entries where only part of the value is being matched.

Take note of the RANGE criterion. If a context is enumerated, RANGE allows one to pull out specific ranges from it. This means, for example, that one may order a context as one sees fit (with the SORT modifier) and then return the top (or bottom) few entries using the RANGE criterion.

Table 12-6 shows each of the ACAP search criteria.

Table 12-6. ACAP Search Criteria

Operator

Arguments

Description

ALL

None

Causes every entry to be returned.

AND

<search key 1> <search key 2>

Returns entries that match both search keys.

COMPARE

<attribute> <comparator> <value>

Returns entries that contain the given attribute that compare to the given value (the same or later) in the manner specified by the comparator.

COMPAR-ESTRICT

<attribute> <comparator> <value>

Returns entries that contain the given attribute that compare to the given value (later only) in the manner specified by the comparator.

EQUAL

<attribute> <comparator> <value>

Returns entries that contain the given attribute that are equal to the given value.

NOT

<search key>

Returns entries that do not match the given search key.

OR

<search key 1> <search key 2>

Returns entries that match either of the search keys.

PREFIX

<attribute> <comparator> <value>

Returns entries that contain the given attribute that begins with the given value in the manner specified by the comparator.

RANGE

<start number> <end number> <modtime>

Returns entries from an enumerated context that have numbers between the two given numbers, as the context existed at the time given.

SUBSTRING

<attribute> <comparator> <value>

Returns entries that contain the given attribute that contains the given value in the manner specified by the comparator.

So, knowing a bit more about searching, our friend Ralph could search his address book for any entries that contained email addresses. The result might look like this:

Client:  GH39 SEARCH "/addressbook/user/ralph/" DEPTH 2 RETURN
         ("Contact. Email") NOT EQUAL "Contact.Email" "i; octet" NIL
Server:  GH39 ENTRY "/addressbook/user/ralph/Sue_Hoyle" "[email protected]"
Server:  GH39 ENTRY "/addressbook/user/ralph/Justin_Case" "justin_case@sun.
com"
Server:  GH39 ENTRY "/addressbook/user/ralph/Zelda_O'Brien" "[email protected]"
Server:  GH39 MODTIME "1999062412382399"
Server:  GH39 OK "SEARCH completed"

We have added a DEPTH modifier to make sure that entries one level down (two total levels) are searched. Also, the search criteria is more interesting. Here, we searched for only those entries that had an attribute called Email that was not empty.

The real power of ACAP searching takes place in the context of a context. How’s that for polymorphism? Contexts can be created by using the MAKECONTEXT modifier. If we wish to save the results of a search so that we can search again on the results, this is the way to do it. This is especially handy for searches that return many, many entries.

Suppose, for example, that we repeat our last search, but this time we save the results to a context. We will have to name the context, so we’ll call it “people_with_email”:

Client:  GH40 SEARCH "/addressbook/user/ralph/" DEPTH 2 RETURN
         ("Contact.Email") MAKECONTEXT ENUMERATE "people_with_email" NOT
         EQUAL "Contact.Email" "i;octet" NIL
Server:  GH40 ENTRY "/addressbook/user/ralph/Sue_Hoyle" "[email protected]"
Server:  GH40 ENTRY "/addressbook/user/ralph/Justin_Case" "justin_case@sun.
com"
Server:  GH40 ENTRY "/addressbook/user/ralph/Zelda_O'Brien" "[email protected]"
Server:  GH40 MODTIME "1999062412385473"
Server:  GH40 OK "Context 'people_with_email' created"

We now have a context, stored on the server, called “people_with_email”. It contains the entries shown in the results of the last example. The context was enumerated, so each of the entries have numbers that can be used in a later search. We could have also asked the server to tell us when updates to entries in the context occur (with the NOTIFY option to MAKECONTEXT), but we’ll leave that for now. Notifications of information of changing contexts are covered in the discussion of the UPDATECONTEXT command, later in this section.

If we now search our context, we can (for example) get just the first entry. For that, we use the RANGE modifier telling it to return from the first entry to the first entry:

Client:  GH41 SEARCH "people_with_email" RANGE 1 1 ALL
Server:  GH41 ENTRY "/addressbook/user/ralph/Sue_Hoyle" "[email protected]"
Server:  GH41 MODTIME "1999062412394812"
Server:  GH41 OK "SEARCH completed"

It was not necessary to give a RETURN modifier in this example because the context holds only the partial entries that were in the last results.

The FREECONTEXT command causes the server to remove context named as an argument. If the server is sending update notifications to a client (see UPDATECONTEXT, later in this section) for this context, they will cease. For example:

Client:  GH42 FREECONTEXT "people_without_email"
Server:  GH42 OK "FREECONTEXT completed"

The UPDATECONTEXT command may be used to cause a server to notify the client when any attributes within a context change. It takes a context name as an argument. This is a powerful concept: once a SEARCH command with a MAKECONTEXT modifier creates a context, a client can monitor the state of every entry in the context!

A client would request notifications for a context called “people_with_email” like this:

Client:  GH43 UPDATECONTEXT "people_with_email"
Server:  GH43 OK "UPDATECONTEXT completed"

From this point on, any changes to the context “people_with_email” will be sent to the client. The server can send these updates at any time. The only way to stop notifications from being sent is for the client to issue a FREECONTEXT command. Whenever an entry in the context changes, the server sends an untagged response to the client with the new information. The untagged server responses may be of these types:

ADDTO

Indicates that an entry has been added to the context

CHANGE

Indicates either that an entry’s position in the context has changed or that a watched attribute has changed within the entry

REMOVEFROM

Indicates that an entry has been deleted from the context

MODTIME

Indicates that the client has received all changes up to a given time

An ADDTO server response contains the context name, the entry name, the entry’s position in the context, and a list of metadata. An ADDTO response that informs a client that an entry called “Mary Ryan” had been added might look like this:

Server:  * ADDTO "people_with_email" "Mary Ryan" 4
         ("Contact.Telephone" "+61 7 3874 1583" "Contact. Email"
         "[email protected]")

In the preceding example, the entry is in the fourth position in the context. If the telephone number in the entry was now changed, the CHANGE response would be used. The CHANGE response lists the context name, the entry name, the entry’s old position in the context, the entry’s new position, and the metadata list.

Server:  * CHANGE "people_with_email" "Mary Ryan" 4 4
         ("Contact.Telephone" "+61 7 3876 8457")

If the preceding entry was now deleted, the client would get a message that looks like this:

Server:  * REMOVEFROM "people_with_email" "Mary Ryan" 4

The REMOVEFROM response shows the context name, the entry name, and the entry’s old position in the context.

At any time the server may send a MODTIME response, although this is generally only done when the client sends a new UPDATECONTEXT command. The MODTIME response is used to inform that client that it has all updates as of a certain time. Here is an example that shows the client issuing a new UPDATECONTEXT command:

Client:  GH43 UPDATECONTEXT "people_with_email"
Server:  * MODTIME "people_with_email" "19990624095600"
Server:  GH43 OK "UPDATECONTEXT completed"

Note that clients are not supposed to use the UPDATECONTEXT command to poll servers for updates; they should generally wait for the servers to send them in their own time. A client might issue a command like the preceding one on startup, however, or at similar times in order to ensure expected behavior.

The second of the two ACAP “magic” commands is STORE. It allows a client to write information to a server. This includes both creation or modification of datasets and their entries. Since the storing of a NIL value in an entry is the same as deleting it, STORE is also used to delete entries. Note that if any part of a STORE command fails, the entire request will fail; that is, nothing will be stored if an error occurs.

The arguments to the STORE command can look rather complex, but they are easily parsable. The proposed standard calls the arguments an entry store list. An entry store list begins with an entry path (a dataset or an attribute), followed by optional modifiers followed by attribute name-value pairs. Each of these is described in detail in this section.

STORE modifiers are either NOCREATE (which will generate an error if any of the attributes to be added do not already exist) and UNCHANGEDSINCE “<time>” (which will generate an error if any of the attributes to be added have been changed by someone else since the given time).

Attribute name-value pairs give a series of attribute names and the values to store in them. A value of NIL will cause the attribute to be deleted from the entry.

Setting the value of an “entry” attribute to NIL will cause the entry to be deleted from the dataset. Since a dataset is also an entry, setting the “entry” attribute of a dataset to NIL will cause the dataset to be deleted from its parent dataset. Setting an “entry” attribute value to DEFAULT effectively deletes all information held in the entry and then fills the entry with whatever it can inherit from its parent.

Let’s look at the address book example again. If we wish to delete an entry from the address book, it can be done like this:

Client:  GH44 STORE ("/addressbook/user/ralph/Sue_Hoyle" "entry" NIL)
Server:  GH44 OK "STORE completed"

A subsequent SEARCH for that entry would show that it no longer existed. If, on the other hand, we wished to add a new entry to the address book that held a person’s name and email address, we could do it like this:

Client:  GH45 STORE ("/addressbook/user/ralph/Phread_the_Terrorist"
         "Contact.CommonName" "Phread the Terrorist" "Contact. Email"
         "[email protected]" )
Server:  GH45 OK "STORE completed"

The DELETEDSINCE command may be used to list entries that have been deleted from a dataset. It takes a dataset name and a time as arguments. The entries that have been deleted since the given time are listed in intermediate DELETED lines by the server.

The time given is in the same format as modtime (YYYYMMDDHHMMSSFF in UTC).

If we wanted to see all of the entries that have been deleted from an address book since midnight on June 24, 1999, a client might issue a command like this:

Client:  GH46 DELETEDSINCE "/addressbook/user/ralph" 19990624000000
Server:  GH46 OK "DELETEDSINCE completed"

If the server doesn’t have a list of deleted entries that goes back to the time given, it will report an error like this using the TOOOLD server response code:

Client:  GH47 DELETEDSINCE "/addressbook/user/ralph" 19970101000000
Server:  GH47 NO (TOOOLD) "We trashed that data long ago"

The SETACL command may be used to change the ACL for a particular object. It takes an ACL object, an authentication identifier (e.g., username), and a list of access rights as arguments. The user issuing this command must have administer privileges on the given object.

If a user with the appropriate rights wanted to set the access control list for an address book in the dataset /addressbook/user/ralph so that anyone could read or write information in it, the client would do something like this:

Client:  GH48 SETACL ("/addressbook/user/ralph") "anyone" "rw"
Server:  GH48 OK "SETACL completed"

If the user does not have administer privileges, the SETACL will fail. Suppose the user “dwood” tried to modify the address book owned by “ralph”:

Client:  GH49 SETACL (" /addressbook/user/ralph") "anyone" "rw"
Server:  GH49 NO (PERMISSION  ("/addressbook/user/ralph" ))" dwood' not
         permitted to modify access rights for '/addressbook/user/ralph'"

Note that this example shows the PERMISSION server response code.

The DELETEACL command may be used to either delete an access control list for an object or to delete a particular user’s rights within an ACL. It takes an ACL object and (optionally) an authentication identifier. If an identifier is given, it deleted all rights for that user in the ACL. Otherwise, it deletes the entire ACL.

For example, if a user wanted to ensure that the user “ralph” had no rights at all on the address book /addressbook/user/margaret, a client might issue a command like this:

Client:  GH50 DELETEACL (" / addressbook/user/margaret" ) "ralph"
Server:  GH50 OK "DELETEACL completed"

You may recall from the discussion of ACLs that if an object doesn’t have an ACL, it inherits user rights from parent objects farther up the hierarchy. For this reason, one is not allowed to delete a default ACL for a dataset. Therefore, if the preceding example didn’t have the authentication identifier, it would have failed (because /addressbook/user/margaret is a dataset). If you tried to do that, it would look like this:

Client:  GH51 DELETEACL ("/addressbook/user/margaret" )
Server:  GH51 BAD "Can't delete ACL from dataset"

The MYRIGHTS command can be used to show what rights a user has been granted for a particular dataset or entry. It takes an ACL object as an argument. That is, the argument names a dataset or entry, but the server reads that dataset’s or entry’s ACL when processing the command. The MYRIGHTS tagged intermediate response is returned by the server, which lists the client’s rights for the given dataset. This command is related to the LISTRIGHTS command, described subsequently, which lists which rights the client may change for the given dataset.

We would expect to have at least read and administer rights for entries in personally created datasets. Here is an example of a MYRIGHTS command on a personal address book that shows that we have read, write, insert, and administer rights on it:

Client:  GH52 MYRIGHTS (" /addressbook/user/dwood")
Server:  GH52 MYRIGHTS "rwia"
Server:  GH52 OK "MYRIGHTS completed"

A similar request on a public, shared dataset (say, a dataset holding system-wide configuration information) may return more restricted rights. In this example, the client may only read the information:

Client:  GH53 MYRIGHTS ("/options/global/")
Server:  GH53 MYRIGHTS "r"
Server:  GH53 OK "MYRIGHTS completed"

The LISTRIGHTS command can be used to determine what rights a user can change for a certain dataset or entry. It takes both an ACL object and an authentication identifier (e.g., a username) as arguments. The server returns a tagged LISTRIGHTS response that lists the rights that will always be granted to that user for that object and the rights that the user currently may change. Rights in the response are not duplicated, so if read permission is always granted, it will not also appear in the user’s specific rights list.

For example, if a user “margaret” will always be granted implicit read and administer rights for personally created items and she also has permission to modify search and write rights on her personal address book, the command and response might look like this:

Client:  GH54 LISTRIGHTS ("/addressbook/user/margaret") "margaret"
Server:  GH54 LISTRIGHTS "ra" "x" "w"
Server:  GH54 OK "LISTRIGHTS completed"

This shows that Margaret is not allowed to give herself or anyone else insert rights. That is, she can change the data that is there but cannot create new entries. This is probably not realistic for a personal address book!

The GETQUOTA command can be used to determine how much storage space a user has available on a server. It takes a dataset as an argument and returns the client’s quota limit (in bytes) and usage for that dataset. For example:

Client:  GH55 GETQUOTA "/addressbook/user/dwood"
Server:  * QUOTA "/addressbook/user/dwood" 2097152 1808728
Server:  GH55 OK "GETQUOTA completed"

In this example, the client asked for quota information on a dataset representing a personal address book. The server responded with an untagged response that repeated the name of the dataset, then listed the client’s quota (2 MB in this case) and the amount of storage space the client is currently using (1.8 MB or so). The client can only store about 200 KB before running out of room.

Table 12-7 lists the ACAP commands that are valid in the Authenticated State.

Table 12-7. ACAP Commands Valid in the Authenticated State

Command

Arguments

Description

Response

SEARCH

dataset or context name, optional modifiers and search criteria

Returns a list of entries on a server that matches the search criteria.

Intermediate responses: ENTRY, MODTIME, REFER; untagged responses: ADDTO, REMOVEFROM, CHANGE, MODTIME

FREECONTEXT

context name

Requests that the server remove the named context. The context will no longer be searchable.

None

UPDATECONTEXT

list of context names

Requests that the server notify the client of any changes to the given contexts.

Untagged responses: ADDTO, REMOVEFROM, CHANGE, MODTIME

STORE

entry store list

Requests that the server create, modify or delete the given entries.

Intermediate response: ENTRY

DELETEDSINCE

dataset name and time

Requests that the server return a list of entries that have been deleted from the given dataset since the given time.

Intermediate response ENTRY

SETACL

ACL object, authentication identifier and access rights.

Requests a change in the access control list for the given object.

None

DELETEACL

ACL object and optional authentication identifier

Requests the removal of all or part of the access control list for the given object.

None

MYRIGHTS

ACL object

Requests the rights of the client on the given object.

Intermediate response: MYRIGHTS

LISTRIGHTS

ACL object, authentication identifier

Requests the rights that the client may change on the given object.

Untagged response: LISTRIGHTS

GETQUOTA

dataset

Requests the client’s quota limit and usage for the given dataset.

Untagged response: QUOTA

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
13.58.121.214