Wow, it's been a LONG time since I've looked at any of this code, but since Meg had to go and blame me for it I figured I should take a look

The bans are actually handled by use of the built-in ban system (banid, writeid) because, at least when I was working on it, they would trigger well before Lua had a chance to in the player join sequence. However the default system only stores permanent bans, so temp bans were all lost any time the server restarted (and I believe even between map loads at one point...) I believe one of the other requirements we set was that you should still be able to unban someone with the default server commands.
So as part of ULib's initialization it first reads in the ULib specific ban file to ULib.bans. Then it reads the default bans file and adds any that aren't in the ULib bans file to ULib.bans with only the steamid and unban time filled in. We then loop over everything in ULib.bans, if the unban time is greater than the current time then we have a temporary ban and we call banid with the time remaining, else if the unban time is 0 then we have a permanent ban and we check and remove it from the ULib file
only if it's not in the default bans file, else we have an expired temporary ban and we remove it from the file.
So with this system, to keep all the permanent bans you need to keep BOTH the ulib bans.txt file AND the banned_users.cfg file. As for why we are removing permanent bans that aren't in the default file, I believe it was actually Megiddo who complained to me about permanent bans being recreated after removing them from the default file, though as I said that was a long time so I can't be 100% sure.
As for the issue of invalid characters in names and such, the KeyValues parsing code is ALL Megiddo
