X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=citadel%2Fuser_ops.c;h=99543f719c7e26efd640e939faa114eb15204707;hb=9ffea7c3315046ddcea2589656c13da5f5e0c076;hp=7f6ed1c15309ba3d8f7bde5efefbc77132968480;hpb=58c77aea1dda7b206b900bafb9278237456ef737;p=citadel.git diff --git a/citadel/user_ops.c b/citadel/user_ops.c index 7f6ed1c15..99543f719 100644 --- a/citadel/user_ops.c +++ b/citadel/user_ops.c @@ -31,6 +31,39 @@ int chkpwd_write_pipe[2]; int chkpwd_read_pipe[2]; +/* + * Trim a string down to the maximum username size and return the new length + */ +long cutusername(char *username) { + long len; + len = strlen(username); + if (len >= USERNAME_SIZE) + { + syslog(LOG_INFO, "Username too long: %s", username); + len = USERNAME_SIZE - 1; + username[len]='\0'; + } + return len; +} + + +/* + * makeuserkey() - convert a username into the format used as a database key + * (it's just the username converted into lower case) + */ +void makeuserkey(char *key, const char *username, long len) { + int i; + + if (len >= USERNAME_SIZE) + { + syslog(LOG_INFO, "Username too long: %s", username); + len = USERNAME_SIZE - 1; + } + for (i=0; i<=len; ++i) { + key[i] = tolower(username[i]); + } +} + /* * CtdlGetUser() retrieve named user into supplied buffer. @@ -40,7 +73,7 @@ int CtdlGetUser(struct ctdluser *usbuf, char *name) { char usernamekey[USERNAME_SIZE]; struct cdbdata *cdbus; - long len = cutuserkey(name); + long len = cutusername(name); if (usbuf != NULL) { memset(usbuf, 0, sizeof(struct ctdluser)); @@ -89,7 +122,7 @@ void CtdlPutUser(struct ctdluser *usbuf) { char usernamekey[USERNAME_SIZE]; - makeuserkey(usernamekey, usbuf->fullname, cutuserkey(usbuf->fullname)); + makeuserkey(usernamekey, usbuf->fullname, cutusername(usbuf->fullname)); usbuf->version = REV_LEVEL; cdb_store(CDB_USERS, usernamekey, strlen(usernamekey), usbuf, sizeof(struct ctdluser)); } @@ -125,8 +158,8 @@ int rename_user(char *oldname, char *newname) { char newnamekey[USERNAME_SIZE]; /* Create the database keys... */ - makeuserkey(oldnamekey, oldname, cutuserkey(oldname)); - makeuserkey(newnamekey, newname, cutuserkey(newname)); + makeuserkey(oldnamekey, oldname, cutusername(oldname)); + makeuserkey(newnamekey, newname, cutusername(newname)); /* Lock up and get going */ begin_critical_section(S_USERS); @@ -397,38 +430,12 @@ int CtdlGetUserByNumber(struct ctdluser *usbuf, long number) /* * Helper function for rebuild_usersbynumber() */ -void rebuild_ubn_for_user(struct ctdluser *usbuf, void *data) { - - struct ubnlist { - struct ubnlist *next; - char username[USERNAME_SIZE]; - long usernum; - }; +void rebuild_ubn_for_user(char *username, void *data) { + struct ctdluser u; - static struct ubnlist *u = NULL; - struct ubnlist *ptr = NULL; - - /* Lazy programming here. Call this function as a ForEachUser backend - * in order to queue up the room names, or call it with a null user - * to make it do the processing. - */ - if (usbuf != NULL) { - ptr = (struct ubnlist *) malloc(sizeof (struct ubnlist)); - if (ptr == NULL) return; - - ptr->usernum = usbuf->usernum; - safestrncpy(ptr->username, usbuf->fullname, sizeof ptr->username); - ptr->next = u; - u = ptr; - return; - } - - while (u != NULL) { - syslog(LOG_DEBUG, "user_ops: rebuilding usersbynumber index %10ld : %s", u->usernum, u->username); - cdb_store(CDB_USERSBYNUMBER, &u->usernum, sizeof(long), u->username, strlen(u->username)+1); - ptr = u; - u = u->next; - free(ptr); + syslog(LOG_DEBUG, "user_ops: rebuilding usersbynumber index for %s", username); + if (CtdlGetUser(&u, username) == 0) { + cdb_store(CDB_USERSBYNUMBER, &(u.usernum), sizeof(long), u.fullname, strlen(u.fullname)+1); } } @@ -439,7 +446,6 @@ void rebuild_ubn_for_user(struct ctdluser *usbuf, void *data) { void rebuild_usersbynumber(void) { cdb_trunc(CDB_USERSBYNUMBER); /* delete the old indices */ ForEachUser(rebuild_ubn_for_user, NULL); /* enumerate the users */ - rebuild_ubn_for_user(NULL, NULL); /* and index them */ } @@ -912,7 +918,7 @@ int purge_user(char pname[]) struct ctdluser usbuf; char usernamekey[USERNAME_SIZE]; - makeuserkey(usernamekey, pname, cutuserkey(pname)); + makeuserkey(usernamekey, pname, cutusername(pname)); /* If the name is empty we can't find them in the DB any way so just return */ if (IsEmptyStr(pname)) { @@ -1138,52 +1144,49 @@ int CtdlForgetThisRoom(void) { /* - * Traverse the user file... + * Traverse the user file and perform a callback for each user record. + * (New improved version that runs in two phases so that callbacks can perform writes without having a r/o cursor open) */ -void ForEachUser(void (*CallBack) (struct ctdluser * EachUser, void *out_data), - void *in_data) +void ForEachUser(void (*CallBack) (char *, void *out_data), void *in_data) { - struct ctdluser usbuf; + struct feu { + char username[USERNAME_SIZE]; + int version; + }; + struct cdbdata *cdbus; + struct ctdluser *usptr; + int i = 0; + struct feu *usernames = NULL; + int num_users = 0; + int num_users_alloc = 0; cdb_rewind(CDB_USERS); + // Phase 1 : load list of usernames while (cdbus = cdb_next_item(CDB_USERS), cdbus != NULL) { - memset(&usbuf, 0, sizeof(struct ctdluser)); - memcpy(&usbuf, cdbus->ptr, - ((cdbus->len > sizeof(struct ctdluser)) ? - sizeof(struct ctdluser) : cdbus->len)); - cdb_free(cdbus); - (*CallBack) (&usbuf, in_data); - } -} + usptr = (struct ctdluser *) cdbus->ptr; + if (strlen(usptr->fullname) > 0) { + ++num_users; + if (num_users > num_users_alloc) { + num_users_alloc = ((num_users_alloc == 0) ? 1 : (num_users_alloc * 2)); + usernames = realloc(usernames, num_users_alloc * sizeof(struct feu)); + } + strcpy(usernames[num_users-1].username, usptr->fullname); + usernames[num_users-1].version = usptr->version; + } + } -/* - * List one user (this works with cmd_list) - */ -void ListThisUser(struct ctdluser *usbuf, void *data) -{ - char *searchstring; - - searchstring = (char *)data; - if (bmstrcasestr(usbuf->fullname, searchstring) == NULL) { - return; - } - - if (usbuf->axlevel > AxDeleted) { - if ((CC->user.axlevel >= AxAideU) - || ((usbuf->flags & US_UNLISTED) == 0) - || ((CC->internal_pgm))) { - cprintf("%s|%d|%ld|%ld|%ld|%ld||\n", - usbuf->fullname, - usbuf->axlevel, - usbuf->usernum, - (long)usbuf->lastcall, - usbuf->timescalled, - usbuf->posted); + // Phase 2 : perform the callback for each username + for (i=0; i