/** Return the first access rule that matches a host. * \param hname a host or user+host pattern. * \param who the player attempting access. * \param rulenum pointer to rule position. * \return pointer to first matching access rule or NULL. */ struct access * site_check_access(const char *hname, dbref who, int *rulenum) { struct access *ap; const char *p; *rulenum = 0; if (!hname || !*hname) return 0; if ((p = strchr(hname, '@'))) p++; for (ap = access_top; ap; ap = ap->next) { (*rulenum)++; if (ap->can & ACS_SITELOCK) continue; if (((ap->can & ACS_REGEXP) ? (qcomp_regexp_match(ap->re, hname) || (p && qcomp_regexp_match(ap->re, p))) : (quick_wild(ap->host, hname) || (p && quick_wild(ap->host, p)))) && (ap->who == AMBIGUOUS || ap->who == who)) { /* Got one */ return ap; } } return NULL; }
/** Decide if a host can access someway. * \param hname a host or user+host pattern. * \param flag the access type we're testing. * \param who the player attempting access. * \retval 1 access permitted. * \retval 0 access denied. * \verbatim * Given a hostname and a flag decide if the host can do it. * Here's how it works: * We run the linked list and take the first match. * (If the hostname is user@host, we try to match both user@host * and just host to each line in the file.) * If we make a match, and the line tells us whether the site can/can't * do the action, we're done. * Otherwise, we assume that the host can do any toggleable option * (can create, connect, guest), and don't have any special * flags (can't register, isn't suspect) * \endverbatim */ bool site_can_access(const char *hname, uint32_t flag, dbref who) { struct access *ap; acsflag *c; const char *p; if (!hname || !*hname) return 0; if ((p = strchr(hname, '@'))) p++; for (ap = access_top; ap; ap = ap->next) { if (ap->can & ACS_SITELOCK) continue; if ((ap->can & ACS_REGEXP) ? (qcomp_regexp_match(ap->re, hname) || (p && qcomp_regexp_match(ap->re, p))) : (quick_wild(ap->host, hname) || (p && quick_wild(ap->host, p))) && (ap->who == AMBIGUOUS || ap->who == who)) { /* Got one */ if (flag & ACS_CONNECT) { if ((ap->cant & ACS_GOD) && God(who)) /* God can't connect from here */ return 0; else if ((ap->cant & ACS_WIZARD) && Wizard(who)) /* Wiz can't connect from here */ return 0; else if ((ap->cant & ACS_ADMIN) && Hasprivs(who)) /* Wiz and roy can't connect from here */ return 0; } if (ap->cant && ((ap->cant & flag) == flag)) return 0; if (ap->can && (ap->can & flag)) return 1; /* Hmm. We don't know if we can or not, so continue */ break; } } /* Flag was neither set nor unset. If the flag was a toggle, * then the host can do it. If not, the host can't */ for (c = acslist; c->name; c++) { if (flag & c->flag) return c->toggle ? 1 : 0; } /* Should never reach here, but just in case */ return 1; }
/** Is a name in the forbidden names file? * \param name name to check. * \retval 1 name is forbidden. * \retval 0 name is not forbidden. */ int forbidden_name(const char *name) { char buf[BUFFER_LEN], *newlin, *ptr; FILE *fp; fp = fopen(NAMES_FILE, FOPEN_READ); if (!fp) return 0; while (fgets(buf, sizeof buf, fp)) { upcasestr(buf); /* step on the newline */ if ((newlin = strchr(buf, '\r'))) *newlin = '\0'; else if ((newlin = strchr(buf, '\n'))) *newlin = '\0'; ptr = buf; if (name && ptr && quick_wild(ptr, name)) { fclose(fp); return 1; } } fclose(fp); return 0; }
/** Decompile the standard attribute table, as per \@attribute/decompile * \param player The enactor * \param pattern Wildcard pattern of attrnames to decompile * \param retroactive Include the /retroactive switch? */ void do_decompile_attribs(dbref player, char *pattern, int retroactive) { ATTR *ap; const char *name; notify(player, T("@@ Standard Attributes:")); for (ap = ptab_firstentry_new(&ptab_attrib, &name); ap; ap = ptab_nextentry_new(&ptab_attrib, &name)) { if (strcmp(name, AL_NAME(ap))) continue; if (pattern && *pattern && !quick_wild(pattern, AL_NAME(ap))) continue; notify_format(player, "@attribute/access%s %s=%s", (retroactive ? "/retroactive" : ""), AL_NAME(ap), privs_to_string(attr_privs_view, AL_FLAGS(ap))); if (ap->flags & AF_RLIMIT) { notify_format(player, "@attribute/limit %s=%s", AL_NAME(ap), display_attr_limit(ap)); } else if (ap->flags & AF_ENUM) { notify_format(player, "@attribute/enum %s=%s", AL_NAME(ap), display_attr_limit(ap)); } } }
static void unsetq_walk(const char *cur, int count __attribute__ ((__unused__)), void *userdata) { struct st_unsetq_data *st_data = (struct st_unsetq_data *) userdata; /* If it matches the pattern, then set it to "" (blank / unset) */ if (!st_data->wild || quick_wild(st_data->wild, cur)) { PE_Setq(st_data->pe_info, cur, ""); } }
/** Return a string with all help entries that match a pattern */ static char * list_matching_entries(char *pattern, help_file *help_dat, const char *sep) { static char buff[BUFFER_LEN]; int offset; char *bp; size_t n; int len; bp = buff; if (help_dat->admin) offset = 1; /* To skip the leading & */ else offset = 0; if (!wildcard(pattern)) { /* Quick way out, use the other kind of matching */ char the_topic[LINE_SIZE + 2]; help_indx *entry = NULL; strcpy(the_topic, normalize_entry(help_dat, pattern)); if (!help_dat->indx || help_dat->entries == 0) return T("#-1 NO INDEX FOR FILE"); entry = help_find_entry(help_dat, the_topic); if (!entry) return (char *) ""; return (char *) (entry->topic + offset); } bp = buff; if (sep) len = strlen(sep); for (n = 0; n < help_dat->entries; n++) if (quick_wild(pattern, help_dat->indx[n].topic + offset)) { safe_str(help_dat->indx[n].topic + offset, buff, &bp); if (sep) safe_strl(sep, len, buff, &bp); } if (bp > buff) *(bp - len) = '\0'; else { *bp = '\0'; } return buff; }
static void listq_walk(const char *cur, int count __attribute__ ((__unused__)), void *userdata) { struct st_qreg_data *st_data = (struct st_qreg_data *) userdata; char *name; name = (char *) cur + 1; if (!st_data->wild || quick_wild(st_data->wild, name)) { if (st_data->count++) { safe_str(st_data->osep, st_data->buff, st_data->bp); } safe_str(name, st_data->buff, st_data->bp); } }
static void ReportMatchedTopics(dbref executor, const UTF8 *topic, CHashTable *htab) { bool matched = false; UTF8 *topic_list = NULL; UTF8 *buffp = NULL; struct help_entry *htab_entry; for (htab_entry = (struct help_entry *)hash_firstentry(htab); htab_entry != NULL; htab_entry = (struct help_entry *)hash_nextentry(htab)) { mudstate.wild_invk_ctr = 0; if ( htab_entry->key && quick_wild(topic, htab_entry->key)) { if (!matched) { matched = true; topic_list = alloc_lbuf("help_write"); buffp = topic_list; } safe_str(htab_entry->key, topic_list, &buffp); safe_chr(' ', topic_list, &buffp); safe_chr(' ', topic_list, &buffp); } } if (!matched) { notify(executor, tprintf(T("No entry for \xE2\x80\x98%s\xE2\x80\x99."), topic)); } else { notify(executor, tprintf(T("Here are the entries which match \xE2\x80\x98%s\xE2\x80\x99:"), topic)); *buffp = '\0'; notify(executor, topic_list); free_lbuf(topic_list); } }