/* ************************************************************* RWhois Software Copyright (c) 1994 Scott Williamson and Mark Kosters Copyright (c) 1996-1998 Network Solutions, Inc. See the file LICENSE for conditions of use and distribution. **************************************************************** */ /* * referral.c: file containing function to parse and chase referrals. */ #include #include "rwhois.h" #include "rwhois_internal.h" #include rw_referral_group_struct * rwhois_find_referral_group(dl_list_type *referral_group_list, char *group_name) { int not_done; dl_node_type *saved_position; rw_referral_group_struct *group; assert(referral_group_list); if (NOT_STR_EXISTS(group_name)) { return NULL; } saved_position = dl_list_get_pos(referral_group_list); not_done = dl_list_first(referral_group_list); while (not_done) { group = (rw_referral_group_struct *) dl_list_value(referral_group_list); if (group->group_name && STR_EQ(group_name, group->group_name)) { dl_list_put_pos(referral_group_list, saved_position); return group; } not_done = dl_list_next(referral_group_list); } dl_list_put_pos(referral_group_list, saved_position); return NULL; } int rwhois_add_referral_to_group(dl_list_type *referral_group_list, rw_referral_struct *referral) { rw_referral_group_struct *group; char *group_name; assert(referral_group_list); assert(referral); /* referrals without schemes are broken, so we don't add them. */ if (NOT_STR_EXISTS(referral->scheme)) { return -1; } if (! STR_EQ(referral->scheme, "rwhois")) { group_name = EXT_REFERRALS_GROUP_NAME; } else if (STR_EXISTS(referral->authority_area)) { group_name = referral->authority_area; } else { group_name = ROOT_GROUP_NAME; } group = rwhois_find_referral_group(referral_group_list, group_name); /* if we didn't find a group, create it */ if (! group) { group = (rw_referral_group_struct *) CALLOC(1, sizeof(*group)); group->group_name = STRDUP(group_name); group->referrals = dl_list_create(destroy_rw_referral_struct); dl_list_append(referral_group_list, group); } dl_list_append(group->referrals, referral); return TRUE; } dl_list_type * rwhois_get_all_referrals(dl_list_type *record_list, dl_list_type *referral_group_list) { int not_done; rw_record_struct *rec; assert(record_list); if (dl_list_empty(record_list)) { return NULL; } /* allocate the group list */ if (!referral_group_list) { referral_group_list = dl_list_create(destroy_rw_referral_group_struct); } not_done = dl_list_first(record_list); while (not_done) { rec = (rw_record_struct *) dl_list_value(record_list); /* skip if the record is bad, it has no referral, or it has a bad referral */ if (!rec || !rec->referral || NOT_STR_EXISTS(rec->referral->scheme)) { not_done = dl_list_next(record_list); continue; } /* otherwise, add the referral to group list, and remove the record from the record list, transferring ownership of the referral structure to the referral group list */ rwhois_add_referral_to_group(referral_group_list, rec->referral); rec->referral = NULL; /* deleting the node will normally advance our position in the list, unless we are already at the end */ if (dl_list_at_tail(record_list)) { not_done = FALSE; } else { not_done = TRUE; } dl_list_delete(record_list); } return referral_group_list; } rw_referral_struct * rwhois_find_referral_in_group(rw_referral_group_struct *ref_group, char *host, int port, char *other) { int not_done; dl_list_type *ref_list; rw_referral_struct *ref; assert(ref_group); if (!ref_group->referrals) { return NULL; } ref_list = ref_group->referrals; not_done = dl_list_first(ref_list); while (not_done) { ref = (rw_referral_struct *) dl_list_value(ref_list); if (!ref || (STR_EXISTS(host) && !STR_EQ(ref->host, host)) || (port > 0 && port != ref->port) || (STR_EXISTS(other) && !STR_EQ(ref->authority_area, other))) { not_done = dl_list_next(ref_list); } else { return ref; } } return NULL; } int rwhois_merge_referral_groups(rw_referral_group_struct *dest_group, rw_referral_group_struct *source_group) { int not_done; dl_list_type *ref_list; rw_referral_struct *ref; assert(dest_group); assert(source_group); /* the group names should match */ if (! STR_EQ(dest_group->group_name, source_group->group_name)) { return RW_ERROR; } if (!source_group->referrals) { return RW_OK; } if (!dest_group->referrals) { dest_group->referrals = source_group->referrals; return RW_OK; } ref_list = source_group->referrals; not_done = dl_list_first(ref_list); while (not_done) { ref = (rw_referral_struct *) dl_list_value(ref_list); if (rwhois_find_referral_in_group(dest_group, ref->host, ref->port, ref->authority_area) != NULL) { not_done = dl_list_next(ref_list); continue; } /* otherwise, the current referral isn't in the dest list, so move it from the source list to the dest list */ dl_list_append(dest_group->referrals, ref); if (dl_list_at_tail(ref_list)) { not_done = FALSE; } else { not_done = TRUE; } /* this will advance us to the next node */ dl_list_delete_node(ref_list); } return RW_OK; } int destroy_rw_referral_struct(rw_referral_struct *ref) { if (!ref) return TRUE; if (ref->scheme) FREE(ref->scheme); if (ref->host) FREE(ref->host); if (ref->authority_area) FREE(ref->authority_area); if (ref->url) FREE(ref->url); if (ref->old_style_line) FREE(ref->old_style_line); FREE(ref); return TRUE; } int destroy_rw_referral_group_struct(rw_referral_group_struct *group) { if (!group) return TRUE; if (STR_EXISTS(group->group_name)) FREE(group->group_name); dl_list_destroy(group->referrals); free(group); return TRUE; }