+ if(!(new_owner_hi = modcmd_get_handle_info(user, argv[1])))
+ return 0;
+ if(new_owner_hi == user->handle_info)
+ {
+ reply("CSMSG_NO_TRANSFER_SELF");
+ return 0;
+ }
+ new_owner = GetChannelAccess(cData, new_owner_hi);
+ if(!new_owner)
+ {
+ if(force)
+ {
+ new_owner = add_channel_user(cData, new_owner_hi, UL_OWNER - 1, 0, NULL);
+ }
+ else
+ {
+ reply("CSMSG_NO_CHAN_USER", new_owner_hi->handle, channel->name);
+ return 0;
+ }
+ }
+ if((chanserv_get_owned_count(new_owner_hi) >= chanserv_conf.max_owned) && !force)
+ {
+ reply("CSMSG_OWN_TOO_MANY", new_owner_hi->handle, chanserv_conf.max_owned);
+ return 0;
+ }
+ if((dnr = chanserv_is_dnr(NULL, new_owner_hi)) && !force) {
+ if(!IsHelping(user))
+ reply("CSMSG_DNR_ACCOUNT", new_owner_hi->handle);
+ else
+ chanserv_show_dnrs(user, cmd, NULL, new_owner_hi->handle);
+ return 0;
+ }
+ invoker = GetChannelUser(cData, user->handle_info);
+ if(invoker->access <= UL_OWNER)
+ {
+ confirm = make_confirmation_string(curr_user);
+ if((argc < 3) || strcmp(argv[2], confirm))
+ {
+ reply("CSMSG_CONFIRM_GIVEOWNERSHIP", new_owner_hi->handle, confirm);
+ return 0;
+ }
+ }
+ new_owner_old_access = new_owner->access;
+ if(new_owner->access >= UL_COOWNER)
+ co_access = new_owner->access;
+ else
+ co_access = UL_COOWNER;
+ new_owner->access = UL_OWNER;
+ if(curr_user)
+ curr_user->access = co_access;
+ cData->ownerTransfer = now;
+ giveownership = calloc(1, sizeof(*giveownership));
+ giveownership->issued = now;
+ giveownership->old_owner = curr_user->handle->handle;
+ giveownership->target = new_owner_hi->handle;
+ giveownership->target_access = new_owner_old_access;
+ if(override)
+ {
+ if(argc > (2 + force))
+ {
+ unsplit_string(argv + 2 + force, argc - 2 - force, transfer_reason);
+ giveownership->reason = strdup(transfer_reason);
+ }
+ giveownership->staff_issuer = strdup(user->handle_info->handle);
+ }
+
+ giveownership->previous = channel->channel_info->giveownership;
+ channel->channel_info->giveownership = giveownership;
+ reply("CSMSG_OWNERSHIP_GIVEN", channel->name, new_owner_hi->handle);
+ sprintf(reason, "%s ownership transferred to %s by %s.", channel->name, new_owner_hi->handle, user->handle_info->handle);
+ global_message(MESSAGE_RECIPIENT_OPERS | MESSAGE_RECIPIENT_HELPERS, reason);
+ return 1;
+}
+
+static CHANSERV_FUNC(cmd_suspend)
+{
+ struct handle_info *hi;
+ struct userData *actor, *real_actor, *target;
+ unsigned int override = 0;
+
+ REQUIRE_PARAMS(2);
+ if(!(hi = modcmd_get_handle_info(user, argv[1]))) return 0;
+ actor = GetChannelUser(channel->channel_info, user->handle_info);
+ real_actor = GetChannelAccess(channel->channel_info, user->handle_info);
+ if(!(target = GetTrueChannelAccess(channel->channel_info, hi)))
+ {
+ reply("CSMSG_NO_CHAN_USER", hi->handle, channel->name);
+ return 0;
+ }
+ if(target->access >= actor->access)
+ {
+ reply("MSG_USER_OUTRANKED", hi->handle);
+ return 0;
+ }
+ if(target->flags & USER_SUSPENDED)
+ {
+ reply("CSMSG_ALREADY_SUSPENDED", hi->handle);
+ return 0;
+ }
+ if(target->present)
+ {
+ target->present = 0;
+ target->seen = now;
+ }
+ if(!real_actor || target->access >= real_actor->access)
+ override = CMD_LOG_OVERRIDE;
+ target->flags |= USER_SUSPENDED;
+ reply("CSMSG_USER_SUSPENDED", hi->handle, channel->name);
+ return 1 | override;
+}
+
+static CHANSERV_FUNC(cmd_unsuspend)
+{
+ struct handle_info *hi;
+ struct userData *actor, *real_actor, *target;
+ unsigned int override = 0;
+
+ REQUIRE_PARAMS(2);
+ if(!(hi = modcmd_get_handle_info(user, argv[1]))) return 0;
+ actor = GetChannelUser(channel->channel_info, user->handle_info);
+ real_actor = GetChannelAccess(channel->channel_info, user->handle_info);
+ if(!(target = GetTrueChannelAccess(channel->channel_info, hi)))
+ {
+ reply("CSMSG_NO_CHAN_USER", hi->handle, channel->name);
+ return 0;
+ }
+ if(target->access >= actor->access)
+ {
+ reply("MSG_USER_OUTRANKED", hi->handle);
+ return 0;
+ }
+ if(!(target->flags & USER_SUSPENDED))
+ {
+ reply("CSMSG_NOT_SUSPENDED", hi->handle);
+ return 0;
+ }
+ if(!real_actor || target->access >= real_actor->access)
+ override = CMD_LOG_OVERRIDE;
+ target->flags &= ~USER_SUSPENDED;
+ scan_user_presence(target, NULL);
+ reply("CSMSG_USER_UNSUSPENDED", hi->handle, channel->name);
+ return 1 | override;
+}
+
+static MODCMD_FUNC(cmd_deleteme)
+{
+ struct handle_info *hi;
+ struct userData *target;
+ const char *confirm_string;
+ unsigned short access_level;
+ char *channel_name;
+
+ hi = user->handle_info;
+ if(!(target = GetTrueChannelAccess(channel->channel_info, hi)))
+ {
+ reply("CSMSG_NO_CHAN_USER", hi->handle, channel->name);
+ return 0;
+ }
+ if(target->access == UL_OWNER)
+ {
+ reply("CSMSG_NO_OWNER_DELETEME", channel->name);
+ return 0;
+ }
+ confirm_string = make_confirmation_string(target);
+ if((argc < 2) || strcmp(argv[1], confirm_string))
+ {
+ reply("CSMSG_CONFIRM_DELETEME", confirm_string);
+ return 0;
+ }
+ access_level = target->access;
+ channel_name = strdup(channel->name);
+ del_channel_user(target, 1);
+ reply("CSMSG_DELETED_YOU", access_level, channel_name);
+ free(channel_name);
+ return 1;
+}
+
+static CHANSERV_FUNC(cmd_addvote)
+{
+ struct chanData *cData = channel->channel_info;
+ struct userData *uData, *target;
+ struct handle_info *hi;
+ if (!cData) return 0;
+ REQUIRE_PARAMS(2);
+ hi = user->handle_info;
+ if(!(target = GetTrueChannelAccess(channel->channel_info, hi)))
+ {
+ reply("CSMSG_NO_CHAN_USER", hi->handle, channel->name);
+ return 0;
+ }
+ if(target->access < 300) {
+ reply("CSMSG_NO_ACCESS");
+ return 0;
+ }
+ if (cData->vote) {
+ reply("CSMSG_ADDVOTE_FULL");
+ return 0;
+ }
+ char *msg;
+ msg = unsplit_string(argv + 1, argc - 1, NULL);
+ cData->vote = strdup(msg);
+ cData->vote_start=0;
+ dict_delete(cData->vote_options);
+ cData->vote_options = dict_new();
+ dict_set_free_data(cData->vote_options, free_vote_options);
+ for(uData = channel->channel_info->users; uData; uData = uData->next)
+ {
+ uData->voted = 0;
+ uData->votefor = 0;
+ }
+ reply("CSMSG_ADDVOTE_DONE");
+ return 1;
+}
+
+static CHANSERV_FUNC(cmd_delvote)
+{
+ struct chanData *cData = channel->channel_info;
+ struct userData *target;
+ struct handle_info *hi;
+ if (!cData) return 0;
+ hi = user->handle_info;
+ if(!(target = GetTrueChannelAccess(channel->channel_info, hi)))
+ {
+ reply("CSMSG_NO_CHAN_USER", hi->handle, channel->name);
+ return 0;
+ }
+ if(target->access < 300) {
+ reply("CSMSG_NO_ACCESS");
+ return 0;
+ }
+ if (!cData->vote) {
+ reply("CSMSG_NO_VOTE");
+ return 0;
+ }
+ free(cData->vote);
+ cData->vote = NULL;
+ reply("CSMSG_DELVOTE_DONE");
+ return 1;
+}
+
+static CHANSERV_FUNC(cmd_addoption)
+{
+ struct chanData *cData = channel->channel_info;
+ struct userData *target;
+ struct handle_info *hi;
+ if (!cData) return 0;
+ REQUIRE_PARAMS(2);
+ hi = user->handle_info;
+ if(!(target = GetTrueChannelAccess(channel->channel_info, hi)))
+ {
+ reply("CSMSG_NO_CHAN_USER", hi->handle, channel->name);
+ return 0;
+ }
+ if(target->access < 300) {
+ reply("CSMSG_NO_ACCESS");
+ return 0;
+ }
+ if (!cData->vote) {
+ reply("CSMSG_NO_VOTE");
+ return 0;
+ }
+
+ char *msg;
+
+ msg = unsplit_string(argv + 1, argc - 1, NULL);
+
+ dict_iterator_t it;
+ unsigned int lastid = 1;
+ for (it = dict_first(cData->vote_options); it; it = iter_next(it)) {
+ struct vote_option *cvOpt = iter_data(it);
+ if(cvOpt->option_id > lastid)
+ lastid = cvOpt->option_id;
+ }
+ struct vote_option *vOpt;
+ vOpt = calloc(1, sizeof(*vOpt));
+ vOpt->name = strdup(msg);
+ vOpt->option_id = (lastid + 1);
+ char str[50];
+ sprintf(str,"%i",(lastid + 1));
+ vOpt->option_str = strdup(str);
+ vOpt->voted = 0;
+ dict_insert(cData->vote_options,vOpt->option_str,vOpt);
+
+ reply("CSMSG_ADDOPTION_DONE",dict_size(cData->vote_options),lastid,(lastid + 1));
+ return 1;
+}
+
+static CHANSERV_FUNC(cmd_deloption)
+{
+ struct chanData *cData = channel->channel_info;
+ struct userData *uData, *target;
+ struct handle_info *hi;
+ if (!cData) return 0;
+ REQUIRE_PARAMS(2);
+ hi = user->handle_info;
+ if(!(target = GetTrueChannelAccess(channel->channel_info, hi)))
+ {
+ reply("CSMSG_NO_CHAN_USER", hi->handle, channel->name);
+ return 0;
+ }
+ if(target->access < 300) {
+ reply("CSMSG_NO_ACCESS");