/*
** Copyright 2000-2004 University of Illinois Board of Trustees
** Copyright 2000-2004 Mark D. Roth
** All rights reserved.
**
** fields.c - libphclient code to parse server field data
**
** Mark D. Roth <roth@feep.net>
*/
#include <internal.h>
#include <errno.h>
#ifdef STDC_HEADERS
# include <stdlib.h>
# include <string.h>
#endif
#include <strings.h>
struct attriblist
{
char *name;
unsigned long value;
};
typedef struct attriblist attriblist_t;
static attriblist_t attributes[] = {
{ "Always", PH_ATTRIB_ALWAYS },
{ "Any", PH_ATTRIB_ANY },
{ "Change", PH_ATTRIB_CHANGE },
{ "Default", PH_ATTRIB_DEFAULT },
{ "Encrypt", PH_ATTRIB_ENCRYPT },
{ "ForcePub", PH_ATTRIB_FORCEPUB },
{ "Indexed", PH_ATTRIB_INDEXED },
{ "LocalPub", PH_ATTRIB_LOCALPUB },
{ "Lookup", PH_ATTRIB_LOOKUP },
{ "NoMeta", PH_ATTRIB_NOMETA },
{ "NoPeople", PH_ATTRIB_NOPEOPLE },
{ "Private", PH_ATTRIB_PRIVATE },
{ "Public", PH_ATTRIB_PUBLIC },
{ "Sacred", PH_ATTRIB_SACRED },
{ "Turn", PH_ATTRIB_TURN },
{ "Unique", PH_ATTRIB_UNIQUE },
{ "PrivLookup", PH_ATTRIB_PRIVLOOKUP },
{ "SacredPerson", PH_ATTRIB_SACREDPERSON },
{ NULL, 0 }
};
int
ph_is_fieldinfo_cached(PH *ph)
{
return (ph->ph_fieldlist != NULL ? 1 : 0);
}
/* ph_free_fieldlist() - free a field list generated by ph_field_list(). */
static void
ph_free_fieldlist(struct ph_fieldinfo *fi)
{
int i, j;
#ifdef DEBUG
printf("==> ph_free_fieldlist(fi=0x%lx)\n", fi);
#endif
for (i = 0; fi[i].pf_fnames != NULL; i++)
{
for (j = 0; fi[i].pf_fnames[j] != NULL; j++)
free(fi[i].pf_fnames[j]);
free(fi[i].pf_fnames);
if (fi[i].pf_description != NULL)
free(fi[i].pf_description);
}
free(fi);
}
/* maps an attribute string to the corresponding value */
static unsigned long
ph_field_attrib_value(char *buf)
{
int i;
for (i = 0; attributes[i].value != 0; i++)
if (strcasecmp(buf, attributes[i].name) == 0)
break;
return attributes[i].value;
}
/*
** returns bitmask representation for a space-delimited string of
** multiple attributes
*/
static unsigned long
ph_encode_field_attributes(char *buf)
{
char *attribp, *nextp;
unsigned long bitmask = 0;
for (nextp = buf; (attribp = strsep(&nextp, " ")) != NULL;)
{
if (*attribp == '\0')
continue;
BIT_SET(bitmask, ph_field_attrib_value(attribp));
}
return bitmask;
}
#if 0
/* maps an attribute value to the corresponding string */
static char *
ph_field_attrib_string(unsigned long attrib)
{
int i;
for (i = 0; attributes[i].value != 0; i++)
if (attributes[i].value == attrib)
break;
return attributes[i].name;
}
#endif
/*
** writes a string of space-delimited attribute names corresponding to
** the numeric bitmask
*/
void
ph_decode_field_attributes(unsigned long bitmask, char *buf, size_t bufsize)
{
int i;
size_t buflen = 0;
buf[0] = '\0';
for (i = 0; attributes[i].value != 0; i++)
if (BIT_ISSET(bitmask, attributes[i].value))
buflen += snprintf(buf + buflen, bufsize - buflen,
"%s ", attributes[i].name);
}
/*
** ph_retrieve_fieldinfo() - obtain a list of fields supported by the PH server.
** returns:
** 0 success
** -1 error (sets errno)
*/
int
ph_retrieve_fieldinfo(PH *ph)
{
int numfields = 0, numaliases = 0;
int i, code, id, save_errno;
char *fieldnames, *value, *name;
char buf[PH_BUF_SIZE];
void *ptr;
ph_memblock_t *blockp;
struct ph_fieldinfo *phfi;
#ifdef DEBUG
puts("==> ph_retrieve_fieldinfo()");
#endif
/* don't load if already cached */
if (ph_is_fieldinfo_cached(ph))
return 0;
/* tell the server to list field aliases, if supported */
ph_set_option(ph, "fieldaliases", NULL);
if (ph_mmgr_malloc(ph->ph_mmgr, ph_MMGR_ARRAY,
0, sizeof(struct ph_fieldinfo),
(ph_free_func_t)ph_free_fieldlist,
&blockp) == -1)
return -1;
phfi = (struct ph_fieldinfo *)ph_mmgr_ptr(blockp);
if (ph_send_command(ph, "fields") == -1)
return -1;
while ((i = ph_get_response(ph, &code, buf, sizeof(buf))) == 0)
{
#ifdef DEBUG
printf("ph_retrieve_fieldinfo(): code=%d buf=\"%s\"\n", code,
buf);
#endif
/* check the response code */
if (code < LR_OK && code > 0)
continue;
if (code == LR_OK)
{
ph->ph_fieldlist = phfi;
ph_mmgr_free(blockp, 0);
return 0;
}
if (code != -(LR_OK))
{
ph_mmgr_free(blockp, 1);
errno = EINVAL;
return -1;
}
/* parse line from server */
if (ph_parse_response(buf, &id, &fieldnames, &value) == -1)
{
ph_mmgr_free(blockp, 1);
errno = EINVAL;
return -1;
}
#ifdef DEBUG
printf("id=%d fieldnames=\"%s\" value=\"%s\"\n", id,
fieldnames, value);
#endif
/* allocate memory if it's a new entry */
if (numfields == 0
|| id != phfi[numfields - 1].pf_id)
{
#ifdef DEBUG
printf("allocating memory - numfields = %d\n",
numfields);
#endif
if (ph_mmgr_array_add(blockp, numfields + 2) == -1)
{
save_errno = errno;
ph_mmgr_free(blockp, 1);
errno = save_errno;
return -1;
}
phfi = (struct ph_fieldinfo *)ph_mmgr_ptr(blockp);
/* set field id */
phfi[numfields].pf_id = id;
/* set field names */
numaliases = 0;
while ((name = strsep(&fieldnames, " ,")) != NULL)
{
ptr = realloc(phfi[numfields].pf_fnames,
(numaliases + 2) * sizeof(char *));
if (ptr == NULL)
{
save_errno = errno;
ph_mmgr_free(blockp, 1);
errno = save_errno;
return -1;
}
phfi[numfields].pf_fnames = (char **)ptr;
phfi[numfields].pf_fnames[numaliases] = strdup(name);
phfi[numfields].pf_fnames[++numaliases] = NULL;
}
if (phfi[numfields].pf_fnames[0] == NULL)
{
save_errno = errno;
ph_mmgr_free(blockp, 1);
errno = save_errno;
return -1;
}
/* set max_size */
i = sscanf(value, "max %d",
&(phfi[numfields].pf_max_size));
if (i != 1)
{
ph_mmgr_free(blockp, 1);
errno = EINVAL;
return -1;
}
#ifdef DEBUG
printf("max_size = %d\n", phfi[numfields].pf_max_size);
#endif
/* extract the field attributes */
#ifdef DEBUG
printf("attributes = \"%s\"\n", value + 4);
#endif
phfi[numfields].pf_attrib = ph_encode_field_attributes(strchr(value + 4, ' '));
numfields++;
}
else /* second line for this field */
{
/* otherwise, extract the description */
#ifdef DEBUG
printf("description = \"%s\"\n", value);
#endif
phfi[numfields - 1].pf_description = strdup(value);
if (phfi[numfields - 1].pf_description == NULL)
{
save_errno = errno;
ph_mmgr_free(blockp, 1);
errno = save_errno;
return -1;
}
}
/* end of loop - call ph_get_response() again */
}
/* in case ph_get_response() returned an error */
save_errno = errno;
ph_mmgr_free(blockp, 1);
errno = save_errno;
return -1;
}
/*
** ph_get_fieldinfo() - return the description for a given field.
** returns:
** 0 success
** -1 error (sets errno)
** PH_ERR_DATAERR unknown field
*/
int
ph_get_fieldinfo(PH *ph, char *fieldname, struct ph_fieldinfo **fieldinfo)
{
int i, j;
if (!ph_is_fieldinfo_cached(ph)
&& ph_retrieve_fieldinfo(ph) == -1)
return -1;
for (i = 0; ph->ph_fieldlist[i].pf_fnames != NULL; i++)
for (j = 0; ph->ph_fieldlist[i].pf_fnames[j] != NULL; j++)
if (strcasecmp(ph->ph_fieldlist[i].pf_fnames[j],
fieldname) == 0)
{
*fieldinfo = &(ph->ph_fieldlist[i]);
return 0;
}
return PH_ERR_DATAERR;
}
/*
** ph_fieldinfo_iterate() - return the next field info structure.
** returns:
** 1 data returned
** 0 no more data
** -1 error (sets errno)
*/
int
ph_fieldinfo_iterate(PH *ph, struct ph_fieldinfo **fieldinfo)
{
if (!ph_is_fieldinfo_cached(ph)
&& ph_retrieve_fieldinfo(ph) == -1)
return -1;
/* first entry */
if (*fieldinfo == NULL)
{
*fieldinfo = &(ph->ph_fieldlist[0]);
return 1;
}
/* next element */
(*fieldinfo)++;
if ((*fieldinfo)->pf_fnames != NULL)
return 1;
/* end of list */
*fieldinfo = NULL;
return 0;
}
/*
** ph_free_fieldinfo() - free fieldlist associated with ph.
*/
void
ph_free_fieldinfo(PH *ph)
{
if (ph->ph_fieldlist != NULL)
ph_free_fieldlist(ph->ph_fieldlist);
ph->ph_fieldlist = NULL;
}
syntax highlighted by Code2HTML, v. 0.9.1