+static struct {
+ char *name;
+ unsigned int priv;
+} privtab[] = {
+#define P(priv) { #priv, PRIV_ ## priv }
+ P(CHAN_LIMIT), P(MODE_LCHAN), P(WALK_LCHAN), P(DEOP_LCHAN),
+ P(SHOW_INVIS), P(SHOW_ALL_INVIS), P(UNLIMIT_QUERY), P(KILL),
+ P(LOCAL_KILL), P(REHASH), P(RESTART), P(DIE),
+ P(GLINE), P(LOCAL_GLINE), P(JUPE), P(LOCAL_JUPE),
+ P(OPMODE), P(LOCAL_OPMODE), P(SET), P(WHOX),
+ P(BADCHAN), P(LOCAL_BADCHAN), P(SEE_CHAN), P(PROPAGATE),
+ P(DISPLAY), P(SEE_OPERS), P(WIDE_GLINE), P(FORCE_OPMODE),
+ P(FORCE_LOCAL_OPMODE), P(REMOTEREHASH), P(CHECK), P(SEE_SECRET_CHAN),
+ P(SHUN), P(LOCAL_SHUN), P(WIDE_SHUN), P(ZLINE),
+ P(LOCAL_ZLINE), P(WIDE_ZLINE), P(LIST_CHAN), P(WHOIS_NOTICE),
+ P(HIDE_IDLE), P(XTRAOP), P(HIDE_CHANNELS), P(DISPLAY_MODE),
+ P(FREEFORM), P(REMOVE), P(SPAMFILTER),
+#undef P
+ { 0, 0 }
+};
+
+char *client_report_privs(struct userNode *client)
+{
+ int i;
+
+ privbuf[0] = '\0';
+ for (i = 0; privtab[i].name; i++) {
+ if (HasPriv(client, privtab[i].priv)) {
+ strcat(privbuf, privtab[i].name);
+ strcat(privbuf, " ");
+ }
+ }
+
+ privbuf[strlen(privbuf)] = 0;
+
+ return privbuf;
+}
+
+int clear_privs(struct userNode *who) {
+ int i = 0;
+ assert(0 != who);
+
+ for (i = 0; privtab[i].name; i++)
+ RevokePriv(who, privtab[i].priv);
+
+ return 0;
+}
+
+int client_modify_priv_by_name(struct userNode *who, char *priv, int what) {
+ int i = 0;
+ assert(0 != priv);
+ assert(0 != who);
+
+ for (i = 0; privtab[i].name; i++) {
+ if (0 == strcmp(privtab[i].name, priv)) {
+ if (what == PRIV_ADD)
+ GrantPriv(who, privtab[i].priv);
+ else if (what == PRIV_DEL) {
+ RevokePriv(who, privtab[i].priv);
+ }
+ }
+ }
+ return 0;
+}
+
+int check_priv(char *priv)
+{
+ int i;
+
+ for (i = 0; privtab[i].name; i++) {
+ if (0 == strcmp(privtab[i].name, priv)) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+void
+irc_privs(struct userNode *target, char *flag, int add)
+{
+ client_modify_priv_by_name(target, flag, add);
+ putsock("%s " P10_PRIVS " %s %s%s", self->numeric, target->numeric, (add == PRIV_ADD) ? "+" : "-", flag);
+}
+
+void
+irc_raw_privs(struct userNode *target, const char *privs)
+{
+ putsock("%s " P10_PRIVS " %s %s", self->numeric, target->numeric, privs);
+}
+
+static CMD_FUNC(cmd_privs)
+{
+ char *tstr = NULL;
+ char buf[512] = "";
+ char *p = 0;
+ char *tmp;
+
+ int what = PRIV_ADD;
+ int type = 0;
+
+ unsigned int i;
+
+ struct server *sender;
+ struct userNode *user;
+
+
+ tstr = conf_get_data("server/type", RECDB_QSTRING);
+ if(tstr)
+ type = atoi(tstr);
+
+
+ if (!(sender = GetServerH(origin))) { /* from oper */
+ return 1; /* ignore as no services have privs set */
+ } else { /* from server */
+ if (type < 5)
+ return 1; /* silently ignore */
+
+ user = argc > 1 ? GetUserN(argv[1]) : NULL;
+
+ if (!user)
+ return 0;
+
+ for (i=1; i<argc; i++) {
+ strcat(buf, argv[i]);
+ strcat(buf, " ");
+ }
+
+ for (i = 2; i < argc; i++) {
+ if (*argv[i] == '+') { what = PRIV_ADD; argv[i]++; }
+ if (*argv[i] == '-') { what = PRIV_DEL; argv[i]++; }
+ for (tmp = x3_strtok(&p, argv[i], ","); tmp;
+ tmp = x3_strtok(&p, NULL, ",")) {
+ if (!strcmp(tmp, "PRIV_NONE")) {
+ if (now > user->timestamp+5)
+ clear_privs(user);
+ break;
+ } else
+ client_modify_priv_by_name(user, tmp, what);
+ }
+ }
+ }
+ return 1;
+}
+