00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef lint
00021 static const char rcsid[] = "$Id: channels.c,v 1.40 2008-10-17 15:57:43 sven Exp $";
00022 #endif
00023
00024 #include "server.h"
00025
00026 channel_t *channel_head = NULL;
00027 int nchannels = 0;
00028
00029 void channel_init()
00030 {
00031 channel_head = NULL;
00032 nchannels = 0;
00033 channel_load(server_config.chanfile);
00034 }
00035
00036
00037 void channel_reset()
00038 {
00039 channel_t *chan;
00040
00041
00042 for (chan = channel_head; chan; chan = chan->next) {
00043 channel_free_online(chan);
00044 }
00045 uhost_cache_reset();
00046 }
00047
00048 void channel_destroy()
00049 {
00050 channel_reset();
00051 channel_save(server_config.chanfile);
00052 }
00053
00054 void channel_free(channel_t *chan)
00055 {
00056
00057 channel_free_online(chan);
00058
00059
00060 if (chan->name) free(chan->name);
00061 if (chan->settings) xml_node_delete(chan->settings);
00062
00063
00064 if (chan->prev) chan->prev->next = chan->next;
00065 else channel_head = chan->next;
00066 if (chan->next) chan->next->prev = chan->prev;
00067 nchannels--;
00068 }
00069
00070
00071 channel_t *channel_probe(const char *chan_name, int create)
00072 {
00073 channel_t *chan, *prev;
00074
00075 prev = NULL;
00076 for (chan = channel_head; chan; chan = chan->next) {
00077 if (!strcasecmp(chan->name, chan_name)) return(chan);
00078 prev = chan;
00079 }
00080 if (!create) return(NULL);
00081
00082
00083 nchannels++;
00084 chan = calloc(1, sizeof(*chan));
00085 chan->name = strdup(chan_name);
00086 chan->settings = xml_node_new();
00087 chan->settings->name = strdup("settings");
00088
00089
00090 if (prev) prev->next = chan;
00091 else channel_head = chan;
00092 chan->prev = prev;
00093 return(chan);
00094 }
00095
00096
00097 channel_t *channel_lookup(const char *chan_name)
00098 {
00099 return channel_probe(chan_name, 0);
00100 }
00101
00102
00103 channel_t *channel_add(const char *name)
00104 {
00105 channel_t *chan;
00106
00107 chan = channel_probe(name, 1);
00108 chan->flags |= CHANNEL_STATIC;
00109 return(chan);
00110 }
00111
00112
00113 int channel_remove(const char *name)
00114 {
00115 channel_t *chan;
00116
00117 chan = channel_probe(name, 0);
00118 if (!chan) return(-1);
00119 chan->flags &= ~CHANNEL_STATIC;
00120 return(0);
00121 }
00122
00123 channel_mode_arg_t *channel_get_arg(channel_t *chan, int type)
00124 {
00125 int i;
00126 char *c;
00127 channel_mode_arg_t *arg;
00128
00129 if (!chan->args && (current_server.type2modes || current_server.type3modes)) {
00130 chan->nargs = strlen(current_server.type2modes) + strlen(current_server.type3modes);
00131 chan->args = calloc(chan->nargs, sizeof(*chan->args));
00132 for (arg = chan->args, c = current_server.type2modes; *c; arg++, c++) {
00133 arg->type = *c;
00134 }
00135 for (c = current_server.type3modes; *c; arg++, c++) {
00136 arg->type = *c;
00137 }
00138 }
00139 for (i = 0; i < chan->nargs; i++) {
00140 if (chan->args[i].type == type) return chan->args+i;
00141 }
00142 return(NULL);
00143 }
00144
00145 channel_mask_list_t *channel_get_mask_list(channel_t *chan, int type)
00146 {
00147 int i;
00148
00149 if (!chan->lists && current_server.type1modes) {
00150 chan->nlists = strlen(current_server.type1modes);
00151 chan->lists = calloc(chan->nlists, sizeof(*chan->lists));
00152 for (i = 0; i < chan->nlists; i++) {
00153 chan->lists[i] = calloc(1, sizeof(*chan->lists[i]));
00154 chan->lists[i]->type = current_server.type1modes[i];
00155 }
00156 }
00157
00158 for (i = 0; i < chan->nlists; i++) {
00159 if (chan->lists[i]->type == type) return(chan->lists[i]);
00160 }
00161 return(NULL);
00162 }
00163
00164 void channel_add_mask(channel_t *chan, char type, const char *mask, const char *set_by, int time)
00165 {
00166 channel_mask_list_t *l;
00167 channel_mask_t *m;
00168
00169 l = channel_get_mask_list(chan, type);
00170
00171 if (!l) return;
00172
00173 m = calloc(1, sizeof(*m));
00174 m->mask = strdup(mask);
00175 m->next = l->head;
00176 if (set_by) m->set_by = strdup(set_by);
00177 m->time = time;
00178 m->last_used = 0;
00179
00180 l->head = m;
00181 l->len++;
00182 }
00183
00184 void channel_del_mask(channel_t *chan, char type, const char *mask)
00185 {
00186 channel_mask_list_t *l;
00187 channel_mask_t *m, *prev;
00188
00189 l = channel_get_mask_list(chan, type);
00190 if (!l) return;
00191
00192 prev = NULL;
00193 for (m = l->head; m; m = m->next) {
00194 if (m->mask && !strcasecmp(m->mask, mask)) {
00195 free(m->mask);
00196 if (m->set_by) free(m->set_by);
00197 if (prev) prev->next = m->next;
00198 else l->head = m->next;
00199 l->len--;
00200 free(m);
00201 break;
00202 }
00203 prev = m;
00204 }
00205 }
00206
00207 int channel_mode(const char *chan_name, const char *nick, char *buf)
00208 {
00209 channel_t *chan;
00210 channel_member_t *m;
00211 flags_t *flags = NULL;
00212
00213 buf[0] = 0;
00214 chan = channel_probe(chan_name, 0);
00215 if (!chan) return(-1);
00216 if (!nick) flags = &chan->mode;
00217 else {
00218 for (m = chan->member_head; m; m = m->next) {
00219 if (!(current_server.strcmp)(nick, m->nick)) {
00220 flags = &m->mode;
00221 break;
00222 }
00223 }
00224 if (!flags) return(-2);
00225 }
00226 flag_to_str(flags, buf);
00227 return(0);
00228 }
00229
00230 int channel_mode_arg(const char *chan_name, int type, const char **value)
00231 {
00232 int i;
00233 channel_t *chan;
00234
00235 chan = channel_probe(chan_name, 0);
00236 if (!chan) return(-1);
00237 for (i = 0; i < chan->nargs; i++) {
00238 if (chan->args[i].type == type) {
00239 *value = chan->args[i].value;
00240 return(0);
00241 }
00242 }
00243 return(-2);
00244 }
00245
00246 int channel_set(channel_t *chan, const char *value, ...)
00247 {
00248 va_list args;
00249 xml_node_t *node;
00250 char *setting, *oldvalue;
00251 int r;
00252
00253 va_start(args, value);
00254 node = xml_node_vlookup(chan->settings, args, 1);
00255 va_end(args);
00256 setting = xml_node_fullname(node);
00257 xml_node_get_str(&oldvalue, node, NULL);
00258 r = bind_check(BT_chanset, NULL, setting, chan->name, setting, oldvalue, value);
00259 free(setting);
00260 if (!(r & BIND_RET_BREAK)) xml_node_set_str(value, node, NULL);
00261 return(0);
00262 }
00263
00264 int channel_get(channel_t *chan, char **strptr, ...)
00265 {
00266 va_list args;
00267 xml_node_t *node;
00268
00269 va_start(args, strptr);
00270 node = xml_node_vlookup(chan->settings, args, 0);
00271 va_end(args);
00272 return xml_node_get_str(strptr, node, NULL);
00273 }
00274
00275 int channel_get_int(channel_t *chan, int *intptr, ...)
00276 {
00277 va_list args;
00278 xml_node_t *node;
00279
00280 va_start(args, intptr);
00281 node = xml_node_vlookup(chan->settings, args, 0);
00282 va_end(args);
00283 return xml_node_get_int(intptr, node, NULL);
00284 }
00285
00286 xml_node_t *channel_get_node(channel_t *chan, ...)
00287 {
00288 va_list args;
00289 xml_node_t *node;
00290
00291 va_start(args, chan);
00292 node = xml_node_vlookup(chan->settings, args, 0);
00293 va_end(args);
00294 return(node);
00295 }
00296
00297 int channel_load(const char *fname)
00298 {
00299 xml_node_t *root = xml_parse_file(fname);
00300 xml_node_t *chan_node, *settings;
00301 channel_t *chan;
00302 char *name;
00303 int flags;
00304
00305 if (!root) {
00306 putlog(LOG_MISC, "*", "Could not load channel file '%s': %s", fname, xml_last_error());
00307 return(-1);
00308 }
00309
00310 chan_node = xml_node_lookup(root, 0, "channel", 0, 0);
00311 for (; chan_node; chan_node = chan_node->next_sibling) {
00312 xml_node_get_vars(chan_node, "sin", "name", &name, "flags", &flags, "settings", &settings);
00313 if (!name) continue;
00314 chan = channel_probe(name, 1);
00315 if (settings) {
00316 xml_node_unlink(settings);
00317 xml_node_delete(chan->settings);
00318 chan->settings = settings;
00319 }
00320 chan->flags = flags;
00321 }
00322 return(0);
00323 }
00324
00325 int channel_save(const char *fname)
00326 {
00327 xml_node_t *root = xml_node_new();
00328 xml_node_t *chan_node;
00329 channel_t *chan;
00330
00331 if (!fname) fname = "channels.xml";
00332 root->name = strdup("channels");
00333 for (chan = channel_head; chan; chan = chan->next) {
00334 if (!(chan->flags & CHANNEL_STATIC)) continue;
00335
00336 chan_node = xml_node_new();
00337 chan_node->name = strdup("channel");
00338 xml_node_set_str(chan->name, chan_node, "name", 0, 0);
00339 xml_node_set_int(chan->flags, chan_node, "flags", 0, 0);
00340 xml_node_append(chan_node, chan->settings);
00341 xml_node_append(root, chan_node);
00342 }
00343 xml_save_file(fname, root, XML_INDENT);
00344 for (chan = channel_head; chan; chan = chan->next) {
00345 if (chan->settings) xml_node_unlink(chan->settings);
00346 }
00347 xml_node_delete(root);
00348 return(0);
00349 }