41b869574b6774f314d589dfcdbb8fc2cd0e9bcc
[jelmer/ctrlproxy.git] / src / isupport.c
1 /*
2         ctrlproxy: A modular IRC proxy
3         (c) 2005 Jelmer Vernooij <jelmer@nl.linux.org>
4
5         This program is free software; you can redistribute it and/or modify
6         it under the terms of the GNU General Public License as published by
7         the Free Software Foundation; either version 2 of the License, or
8         (at your option) any later version.
9
10         This program is distributed in the hope that it will be useful,
11         but WITHOUT ANY WARRANTY; without even the implied warranty of
12         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13         GNU General Public License for more details.
14
15         You should have received a copy of the GNU General Public License
16         along with this program; if not, write to the Free Software
17         Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 #include "internals.h"
21
22 #define DEFAULT_PREFIX          "(ov)@+"
23 #define DEFAULT_CHANTYPES       "#&"
24 #define DEFAULT_CHARSET         "iso8859-15"
25
26 void handle_005(struct network_state *s, struct line *l)
27 {
28         unsigned int i;
29         
30         g_assert(s);
31         g_assert(s->info);
32         g_assert(l);
33
34         g_assert(l->argc >= 1);
35
36         for(i = 3; i < l->argc-1; i++) {
37                 char *sep;
38                 char *key, *val;
39
40                 g_assert(l->args[i]);
41
42                 sep = strchr(l->args[i], '=');
43
44                 if (!sep) { 
45                         key = g_strdup(l->args[i]); 
46                         val = NULL; 
47                 } else {
48                         key = g_strndup(l->args[i], sep - l->args[i]);
49                         val = g_strdup(sep+1);
50                 }
51                 
52                 g_hash_table_replace(s->info->features, key, val);
53
54                 if(!g_strcasecmp(key, "CASEMAPPING")) {
55                         if(!g_strcasecmp(val, "rfc1459")) {
56                                 s->info->casemapping = CASEMAP_RFC1459;
57                         } else if(!g_strcasecmp(val, "strict-rfc1459")) {
58                                 s->info->casemapping = CASEMAP_STRICT_RFC1459;
59                         } else if(!g_strcasecmp(val, "ascii")) {
60                                 s->info->casemapping = CASEMAP_ASCII;
61                         } else {
62                                 s->info->casemapping = CASEMAP_UNKNOWN;
63                                 log_network_state(NULL, LOG_WARNING, s, "Unknown CASEMAPPING value '%s'", val);
64                         }
65                 } else if(!g_strcasecmp(key, "NETWORK")) {
66                         g_free(s->info->name);
67                         s->info->name = g_strdup(val);
68                 } 
69         }
70 }
71
72 gboolean network_supports(const struct network_info *n, const char *fe)
73 {
74         gpointer k, v;
75         g_assert(n);
76         g_assert(n->features);
77         return g_hash_table_lookup_extended (n->features, fe, &k, &v);
78 }
79
80 int irccmp(const struct network_info *n, const char *a, const char *b)
81 {
82         switch(n?n->casemapping:CASEMAP_UNKNOWN) {
83         default:
84         case CASEMAP_UNKNOWN:
85         case CASEMAP_RFC1459:
86                 return str_rfc1459cmp(a,b);
87         case CASEMAP_ASCII:
88                 return str_asciicmp(a,b);
89         case CASEMAP_STRICT_RFC1459:
90                 return str_strictrfc1459cmp(a,b);
91         }
92
93         return 0;
94 }
95
96 gboolean is_channelname(const char *name, const struct network_info *n)
97 {
98         const char *chantypes = NULL;
99
100         g_assert(name);
101
102         if (n != NULL) {
103                 g_assert(n->features);
104         
105                 chantypes = g_hash_table_lookup(n->features, "CHANTYPES");
106         }
107
108         if(chantypes == NULL) 
109                 chantypes = DEFAULT_CHANTYPES;
110         
111         if(strchr(chantypes, name[0])) 
112                 return TRUE;
113
114         return FALSE;
115 }
116
117 gboolean is_prefix(char p, const struct network_info *n)
118 {
119         const char *prefix = NULL;
120         const char *pref_end;
121         
122         if (n != NULL) {
123                 g_assert(n->features);
124                 prefix = g_hash_table_lookup(n->features, "PREFIX");
125         }
126         
127         if (prefix == NULL) 
128                 prefix = DEFAULT_PREFIX;
129
130         pref_end = strchr(prefix, ')');
131         if (!pref_end)pref_end = prefix; else pref_end++;
132
133         if(strchr(pref_end, p)) return TRUE;
134         return FALSE;
135 }
136
137 const char *get_charset(const struct network_info *n)
138 {
139         char *ret = g_hash_table_lookup(n->features, "CHARSET");
140
141         if (ret != NULL)
142                 return ret;
143
144         return DEFAULT_CHARSET;
145 }
146
147 char get_prefix_by_mode(char mode, const struct network_info *n)
148 {
149         const char *prefix = NULL;
150         int i;
151         char *pref_end;
152
153         if (n != NULL) {
154                 g_assert(n->features);
155
156                 prefix = g_hash_table_lookup(n->features, "PREFIX");
157         }
158
159         if (prefix == NULL) 
160                 prefix = DEFAULT_PREFIX;
161         
162         pref_end = strchr(prefix, ')');
163         if(prefix[0] != '(' || !pref_end) {
164                 log_global(NULL, LOG_WARNING, "Malformed PREFIX data `%s'", prefix);
165                 return ' ';
166         }
167         pref_end++;
168         prefix++;
169
170         for(i = 0; pref_end[i]; i++) {
171                 if(prefix[i] == mode) return pref_end[i];
172         }
173         return ' ';
174 }