#include "copyright.h" #include "config.h" #include "db.h" #include "externs.h" #include "params.h" #ifdef COMPRESS #define alloc_compressed(x) dup_string(compress(x)) #else /* !COMPRESS */ #define alloc_compressed(x) dup_string(x) #endif /* COMPRESS */ char buf2[BUFSIZ], buf[BUFSIZ]; static propdir *freehead = NULL; propdir *new_propdir(void) { propdir *ret; if (freehead) { ret = freehead; freehead = freehead->next; } else { ret = (propdir *) malloc (sizeof(propdir)); } return ret; } void delete_propdir(propdir *p) { p->next = freehead; freehead = p; } char *unparse_perms(char perms) { static char perms_buf[9]; perms_buf[0] = (perms & PERMS_LOCKED) ? 'l' : '-'; perms_buf[1] = (perms & PERMS_HIDDEN) ? 'h' : '-'; perms_buf[2] = (perms & PERMS_COREAD) ? 'r' : '-'; perms_buf[3] = (perms & PERMS_COWRITE) ? 'w' : '-'; perms_buf[4] = (perms & PERMS_COSRCH) ? 's' : '-'; perms_buf[5] = (perms & PERMS_OTREAD) ? 'r' : '-'; perms_buf[6] = (perms & PERMS_OTWRITE) ? 'w' : '-'; perms_buf[7] = (perms & PERMS_OTSRCH) ? 's' : '-'; perms_buf[8] = '\0'; return perms_buf; } char parse_perms(char *perms) { char ret = 0; if (isdigit(*perms)) return (char)strtol(perms, NULL, 0); ret += (perms[0] == 'l') ? 0x80 : 0; ret += (perms[1] == 'h') ? 0x40 : 0; ret += (perms[2] == 'r') ? 0x20 : 0; ret += (perms[3] == 'w') ? 0x10 : 0; ret += (perms[4] == 's') ? 0x08 : 0; ret += (perms[5] == 'r') ? 0x04 : 0; ret += (perms[6] == 'w') ? 0x02 : 0; ret += (perms[7] == 's') ? 0x01 : 0; return ret; } char default_perms(char *line1) { switch (*line1) { case '.': return (PERMS_COREAD | PERMS_COWRITE | PERMS_COSRCH); case '_': return (PERMS_COREAD | PERMS_COWRITE | PERMS_COSRCH | PERMS_OTREAD | PERMS_OTSRCH); case '*': return (PERMS_COREAD | PERMS_COWRITE | PERMS_COSRCH | PERMS_HIDDEN); } return (PERMS_COREAD | PERMS_COWRITE | PERMS_COSRCH | PERMS_OTREAD | PERMS_OTWRITE | PERMS_OTSRCH); } char access_rights(dbref player, dbref obj, dbref program) { if (program != NOTHING) { if (FLAGS(program) & STICKY) player = OWNER(program); if ((FLAGS(program) & WIZARD) && (FLAGS(OWNER(program)) & WIZARD)) return ACCESS_WI; } else if (FLAGS(player) & WIZARD) return ACCESS_WI; if (controls(player, obj)) return ACCESS_CO; return ACCESS_OT; } int check_perms(char perms, char access, char type) { if (access & ACCESS_WI) return 1; if (access & ACCESS_CO) { switch(type) { case PT_SEE: return 1; case PT_CHANGE: return (!(perms & PERMS_LOCKED)); case PT_READ: return (perms & PERMS_COREAD); case PT_WRITE: return (perms & PERMS_COWRITE); case PT_SRCH: return (perms & PERMS_COSRCH); } } else { switch(type) { case PT_SEE: return (!(perms & PERMS_HIDDEN)); case PT_CHANGE: return 0; case PT_READ: return (perms & PERMS_OTREAD); case PT_WRITE: return (perms & PERMS_OTWRITE); case PT_SRCH: return (perms & PERMS_OTSRCH); } } return 0; } #define PERMS_DEFAULT_DIR PERMS_COREAD | PERMS_COWRITE | PERMS_COSRCH | \ PERMS_OTREAD | PERMS_OTSRCH propdir *setpropdir(propdir **p, char *name, char perms, char access) { propdir *tmp; for (tmp = *p; tmp && (string_compare(tmp->name, name)); tmp = tmp->next); if (tmp) { if (!check_perms(tmp->perms, access, PT_SRCH)) return NULL; } else { /* tmp = (propdir *)malloc(sizeof(propdir)); */ tmp = new_propdir(); tmp->name = dup_string(name); tmp->data = NULL; if (access & ACCESS_WI) tmp->perms = perms | PERMS_DEFAULT_DIR; else tmp->perms = perms | PERMS_DEFAULT_DIR & ~PERMS_LOCKED; tmp->next = *p; tmp->child = NULL; *p = tmp; } return tmp; } propdir *setpropelt(propdir **p, char *name, char *data, char perms, char access) { propdir *tmp; for (tmp = *p; tmp && (string_compare(tmp->name, name)); tmp = tmp->next); if (tmp) { if (!check_perms(tmp->perms, access, PT_WRITE)) return NULL; free (tmp->data); } else { /* tmp = (propdir *)malloc(sizeof(propdir)); */ tmp = new_propdir(); tmp->name = dup_string(name); /* tmp->name = alloc_compressed(name); */ if (access & ACCESS_WI) tmp->perms = perms; else tmp->perms = perms & ~PERMS_LOCKED; tmp->next = *p; tmp->child = NULL; *p = tmp; } /* tmp->data = dup_string(data); */ tmp->data = alloc_compressed(data); return tmp; } #define split(A,B) \ { \ A = B; \ while (*B && (*B != '/')) B++; \ if (*B) *B++ = '\0'; \ while (*B == '/') B++; \ } #define first(A) while (*A == '/') A++; propdir *set_propdir(propdir *p, char *name, char *data, char perms, char access) { propdir *tmp, *loop, *ptmp, *tmp2; char *word; ptmp = p; first(name); if (*name) { split(word, name); if (*name) loop = setpropdir(&ptmp, word, perms, access); else loop = setpropelt(&ptmp, word, data, perms, access); } else return ptmp; while (*name && loop) { split(word, name); /* can only create new properties if propdir is writeable */ if (check_perms(loop->perms, access, PT_WRITE)) { /* we can write to the propdir so let's do it! */ if (*name) tmp = setpropdir(&(loop->child), word, perms, access); else tmp = setpropelt(&(loop->child), word, data, perms, access); } else { for(tmp2 = loop->child; tmp2 && string_compare(tmp2->name, word); tmp2 = tmp2->next); /* if property exists, use the perms on the property not the dir */ if (tmp2) { if (*name) tmp = setpropdir(&(loop->child), word, perms, access); else tmp = setpropelt(&(loop->child), word, data, perms, access); } else return NULL; /* if not then can't create */ } loop = tmp; } if (*name) return NULL; if (!loop) return NULL; return ptmp; } int add_property(dbref obj, char *name, char *data, char perms, char access) { propdir *p; p = set_propdir(DBFETCHPROP(obj), name, data, perms, access); if (p) { DBSTOREPROP(obj, p); } return (int)p; } void burn_proptree(propdir *p) { if (p) { free(p->name); if(p->data) free(p->data); burn_proptree(p->child); burn_proptree(p->next); /* free(p) */ delete_propdir(p); } } propdir *burn_prop(propdir *p, char *name, int *status) { propdir *tmp, *loop; if (!p) { *status = 0; return NULL; } else *status = 1; if (string_compare(p->name, name)) { for (loop = p; loop->next && string_compare(loop->next->name, name); loop = loop->next); if (loop->next) { tmp = loop->next; loop->next = tmp->next; } else { *status = 0; return p; } } else { tmp = p; p = p->next; } free(tmp->name); free(tmp->data); burn_proptree(tmp->child); /* free(tmp); */ delete_propdir(tmp); return p; } /* returns 0 if successful, 1 if property not found, 2 if permission denied */ int remove_property(dbref obj, char *name, char access) { propdir *p, *tmp; char *word; int s; p = DBFETCHPROP(obj); /* forgot one Claudius! */ if (!name || !*name) { burn_proptree(p); DBSTOREPROP(obj, NULL); return 0; } first(name); split(word, name); if (*name) { while (p && string_compare(p->name, word)) p = p->next; if (!p) return 1; } else { tmp = burn_prop(p, word, &s); if (s) { DBSTOREPROP(obj, tmp); return 0; } else return 1; } split(word, name); while (*name && p->child) { if(check_perms(p->perms, access, PT_SRCH)) { for (p = p->child; p && string_compare(p->name, word); p = p->next); if (!p) return 1; split(word, name); } else return 2; } if (p->child) { if(check_perms(p->perms, access, PT_WRITE)) { tmp = burn_prop(p->child, word, &s); if (s) p->child = tmp; else return 1; } else return 2; } return 0; } /* checks if object has property, returning 1 if it or any of it's contents has the property stated */ int has_property(dbref obj, char *name, char *data, char access) { if (validate_property(obj, name, data, access)) return 1; for (obj = DBFETCH(obj)->contents; obj != NOTHING; obj = DBFETCH(obj)->next) if (validate_property(obj, name, data, access)) return 1; return 0; } propdir *find_property(dbref obj, char *name, char access) { propdir *tmp; char *word; tmp = DBFETCHPROP(obj); first(name); if (!*name) return NULL; while (*name) { split(word, name); while (tmp && string_compare(tmp->name, word)) tmp = tmp->next; if (*name) { if (tmp && check_perms(tmp->perms, access, PT_SRCH)) tmp = tmp->child; else return NULL; } } return tmp; } int validate_property(dbref obj, char *name, char *data, char access) { propdir *p; if ((p = find_property(obj, name, access)) && p->data && check_perms(p->perms, access, PT_READ)) { return (!string_compare(uncompress(p->data), data)); } return 0; } /* return class of property */ char *get_property_data(dbref obj, char *name, char access) { propdir *p; #ifdef MUSH if(!GoodObject(obj) || !name || !*name) return NULL; #endif if ((p = find_property(obj, name, access)) && (check_perms(p->perms, access, PT_READ))) return uncompress(p->data); return NULL; } propdir *dup_propdir(propdir *src, char access) { propdir *new = NULL; if (src && check_perms(src->perms, access, PT_READ)) { /* new = (propdir *)malloc(sizeof(propdir)); */ new = new_propdir(); new->name = dup_string(src->name); new->data = dup_string(src->data); if (check_perms(src->perms, access, PT_SRCH)) new->child = dup_propdir(src->child, access); new->next = dup_propdir(src->next, access); } return new; } /* copies properties */ void copy_prop(dbref obj, dbref dest, char access) { DBSTOREPROP(dest, dup_propdir(DBFETCHPROP(obj), access)); } /* return old gender values for pronoun substitution code */ int genderof(dbref player, char access) { if (validate_property(player, "sex", "male", access)) return GENDER_MALE; if (validate_property(player, "sex", "female", access)) return GENDER_FEMALE; if (validate_property(player, "sex", "neuter", access)) return GENDER_NEUTER; return GENDER_UNASSIGNED; } void notify_pdrecurse(dbref player, propdir *p, char *match, char access, char longform) { char *end; char *junk; char *tmp; char *mush=match; for(; p; p = p->next) { for (junk = match; (*junk != '/') && *junk; junk++); if (!stringn_compare(p->name, match, (int)(junk - match)) #ifdef MUSH || wild_match(mush, p->name) #endif ) { end = buf2 + strlen(buf2); if ((p->child) && check_perms(p->perms, access, PT_SRCH)) { if (*junk) { strcat(buf2, p->name); strcat(buf2, "/"); while (*junk == '/') junk++; notify_pdrecurse(player, p->child, junk, access, longform); *end = '\0'; } } if ((!(p->perms & PERMS_HIDDEN) || (access == ACCESS_WI))) { if (longform) { sprintf(buf, "%s:%s%s%s%s%s", unparse_perms(p->perms), buf2, p->name, p->child ? "/" : "", p->data ? ":" : "", check_perms(p->perms, access, PT_READ) ? p->data : "<<PERMISSION DENIED>>"); } else { tmp = p->data; /* sprintf(buf, "%s%s%s%s%s", buf2, p->name, */ sprintf(buf, "%s%s%s%s", buf2, p->name, p->child ? "/" : "", p->data ? ":" : ""); if(!check_perms(p->perms, access, PT_READ)) strcat(buf, "<<PERMISSION DENIED>>"); else if(p->data && *tmp) strcat(buf, p->data); } notify(player, player, buf); } *end = '\0'; } } } void notify_propdir(dbref player, dbref obj, char *match, char access, char longform) { if (DBFETCHPROP(obj)) notify_pdrecurse(player, DBFETCHPROP(obj), match, access, longform); } void change_perms(dbref obj, char *name, char perms, char access) { propdir *p; strcpy(buf, name); p = find_property(obj, buf, access); if (p && check_perms(p->perms, access, PT_CHANGE)) { if (access == ACCESS_WI) p->perms = perms; else p->perms = perms &= ~PERMS_LOCKED; } } propdir *find_see(propdir *p, char access) { while (p && !check_perms(p->perms, access, PT_SEE)) p = p->next; return p; } int nextprop(char *buffer, propdir *p, char *name, char sub, char access) { char *word; propdir *tmp; if(!p) return 0; split(word, name); for(tmp = p; tmp && string_compare(uncompress(tmp->name), word); tmp = tmp->next); if(tmp && name && *name) { if(nextprop(buffer, tmp->child, name, sub, access)) { strcpy(buf, uncompress(tmp->name)); strcat(buf, "/"); strcat(buf, buffer); strcpy(buffer, buf); } else { if(tmp = find_see(tmp->next, access)) strcpy(buffer, uncompress(tmp->name)); else return 0; } } else { if (!tmp) strcpy(buffer, uncompress(p->name)); else { if (sub) p = find_see(tmp->child, access); else p = NULL; if (p) { strcpy(buffer, uncompress(tmp->name)); strcat(buffer, "/"); tmp = p; } else { strcpy(buffer, ""); tmp = find_see(tmp->next, access); } if (tmp) strcat(buffer, uncompress(tmp->name)); else return 0; } } return 1; } void next_property(char *buffer, dbref obj, char *name, char access) { if (name != NULL) first(name); if (name != NULL && (DBFETCHPROP(obj))) nextprop(buffer, DBFETCHPROP(obj), name, name[strlen(name) - 1] == '/', access); else if (DBFETCHPROP(obj)) strcpy(buffer, DBFETCHPROP(obj)->name); else strcpy(buffer, ""); } int has_next_property(dbref obj, char *name, char access, int child) { propdir *p; if (!(p = find_property(obj, name, access))) return 0; return ((int)find_see(child ? p->child : p->next, access)); } void putproperties_recurse(FILE *f, propdir *p) { char *end; for (; p; p = p->next) { if (p->child) { end = buf2 + strlen(buf2); strcat(buf2, p->name); strcat(buf2, "/"); putproperties_recurse(f, p->child); *end = '\0'; } if (p->data) { sprintf (buf, "%s%s:%d:%s\n", buf2, p->name, p->perms, p->data); fputs(buf, f); } } } void putproperties(FILE *f, dbref obj) { strcpy(buf2, ""); putproperties_recurse(f, DBFETCHPROP(obj)); } void getproperties(FILE *f, dbref obj, char permflag) { char *data, *perms, getbuf[BUFSIZ]; propdir *p = NULL; /* get rid of first line */ fgets(getbuf, sizeof(getbuf), f); /* initialize first line stuff */ fgets(getbuf, sizeof(getbuf), f); while (strcmp(getbuf, "***Property list end ***\n")) { data = (char *)strchr(getbuf, PROP_DELIMITER); if (data) { *data++ = '\0'; if (permflag) /* permissions now stored in db... */ { perms = data; data = (char *)strchr(data, PROP_DELIMITER); if (!data) abort(); /* PARSE ERROR */ *data++ = '\0'; data[strlen(data) - 1] = '\0'; p = set_propdir(p, getbuf, data, atoi(perms), ACCESS_WI); } else { data[strlen(data) - 1] = '\0'; p = set_propdir(p, getbuf, data, default_perms(getbuf), ACCESS_WI); } } fgets(getbuf, sizeof(getbuf), f); } DBSTOREPROP(obj, p); } int is_propdir(dbref player, dbref object1, char *string, dbref program) { propdir *p = NULL; p = find_property(object1, string, access_rights(player, object1, program)); if(!p) return 0; if(!p->child) return 0; return 1; }