ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/src/numeric.c
Revision: 69
Committed: Tue Oct 4 16:09:51 2005 UTC (19 years, 10 months ago) by adx
Content type: text/x-csrc
File size: 5849 byte(s)
Log Message:
- splitted ircd/libio, all headers connected with libio sources have been
  moved for internal use only. To use libio interface, include "libio.h"
  (which is already done in "stdinc.h")


File Contents

# User Rev Content
1 adx 30 /*
2     * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3     * numeric.c: Numeric handling functions.
4     *
5     * Copyright (C) 2002 by the past and present ircd coders, and others.
6     *
7     * This program is free software; you can redistribute it and/or modify
8     * it under the terms of the GNU General Public License as published by
9     * the Free Software Foundation; either version 2 of the License, or
10     * (at your option) any later version.
11     *
12     * This program is distributed in the hope that it will be useful,
13     * but WITHOUT ANY WARRANTY; without even the implied warranty of
14     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     * GNU General Public License for more details.
16     *
17     * You should have received a copy of the GNU General Public License
18     * along with this program; if not, write to the Free Software
19     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20     * USA
21     *
22 knight 31 * $Id$
23 adx 30 */
24    
25     #include "stdinc.h"
26    
27     #include "numeric.h"
28     #include "common.h" /* NULL cripes */
29     #include "send.h"
30     #include "client.h"
31     #include "messages.tab"
32    
33     static char used_locale[LOCALE_LENGTH] = "standard";
34    
35     /*
36     * form_str
37     *
38     * inputs - numeric
39     * output - corresponding string
40     * side effects - NONE
41     */
42     const char* form_str(int numeric)
43     {
44     assert(-1 < numeric);
45     assert(numeric < ERR_LAST_ERR_MSG);
46    
47     if (numeric > ERR_LAST_ERR_MSG)
48     numeric = ERR_LAST_ERR_MSG;
49     if (numeric < 0)
50     numeric = ERR_LAST_ERR_MSG;
51    
52     assert(replies[numeric].standard != NULL);
53    
54     return (replies[numeric].translated != NULL ? replies[numeric].translated :
55     replies[numeric].standard);
56     }
57    
58     /* Attempts to change a numeric with index "reply" to "new_reply".
59     * Returns 1 if ok, 0 otherwise.
60     */
61     static int
62     change_reply(const char *locale, int linecnt, int reply, char *new_reply)
63     {
64     int found;
65     char *new = new_reply;
66     const char *old = replies[reply].standard;
67    
68     for (; *new; new++)
69     {
70     if (*new == '%')
71     {
72     if (!*++new) break;
73     if (*new != '%')
74     {
75     /* We've just found a format symbol. Check if it is the next format
76     * symbol in the original reply.
77     */
78     for (; *new >= '0' && *new <= '9'; new++); /* skip size prefix */
79     found = 0;
80     for (; *old; old++)
81     {
82     if (*old == '%')
83     {
84     if (!*++old) break; /* shouldn't happen */
85     if (*old != '%')
86     {
87     for (; *old >= '0' && *old <= '9'; old++); /* skip size prefix */
88     if (*new != *old++)
89     {
90     ilog(L_ERROR, "Incompatible format symbols (%s.lang, %d)",
91     locale, linecnt);
92     return 0;
93     }
94     found = 1;
95     break;
96     }
97     }
98     }
99     if (!found)
100     {
101     ilog(L_ERROR, "Too many format symbols (%s.lang, %d)", locale, linecnt);
102     return(0);
103     }
104     }
105     }
106     }
107    
108     MyFree(replies[reply].translated);
109     DupString(replies[reply].translated, new_reply);
110     return(1);
111     }
112    
113     /* Loads a language file. Errors are logged into the log file. */
114     void
115     set_locale(const char *locale)
116     {
117     int i, res = 1, linecnt = 0;
118     char buffer[IRCD_BUFSIZE + 1];
119     char *ident, *reply;
120     FBFILE *f;
121    
122     /* Restore standard replies */
123     for (i = 0; i <= ERR_LAST_ERR_MSG; i++) /* 0 isn't a magic number! ;> */
124     {
125     if (replies[i].translated != NULL)
126     {
127     MyFree(replies[i].translated);
128     replies[i].translated = NULL;
129     }
130     }
131    
132     if (strchr(locale, '/') != NULL)
133     {
134     strlcpy(used_locale, "standard", sizeof(used_locale)); /* XXX paranoid */
135     return;
136     }
137    
138     /* yes, I know - the slash isn't necessary. But I have to be sure
139     * that it'll work even if some lame admin won't put "/" at the end
140     * of MSGPATH.
141     */
142     snprintf(buffer, sizeof(buffer), "%s/%s.lang", MSGPATH, locale);
143     if ((f = fbopen(buffer, "r")) == NULL)
144     {
145     strlcpy(used_locale, "standard", sizeof(used_locale)); /* XXX */
146     return;
147     }
148    
149     /* Process the language file */
150     while (fbgets(buffer, sizeof(buffer), f))
151     {
152     ++linecnt;
153     if (buffer[0] == ';')
154     continue; /* that's a comment */
155    
156     if ((ident = strpbrk(buffer, "\r\n")) != NULL)
157     *ident = '\0';
158    
159     /* skip spaces if there are any */
160     for (ident = buffer; *ident == ' ' || *ident == '\t'; ident++)/* null */;
161     if (*ident == '\0')
162     continue; /* empty line */
163    
164     /* skip after the reply identificator */
165     for (reply = ident; *reply != ' ' && *reply != '\t' && *reply != ':';
166     reply++)
167     if (*reply == '\0') goto error;
168    
169     if (*reply == ' ' || *reply == '\t')
170     {
171     for (*reply++ = '\0'; *reply == ' ' || *reply == '\t'; reply++);
172     if (*reply != ':')
173     {
174     error:
175     ilog(L_ERROR, "Invalid line in language file (%s.lang, %d)",
176     locale, linecnt);
177     res = 0;
178     continue;
179     }
180     }
181     else
182     *reply++ = '\0';
183     if (*ident == '\0')
184     goto error;
185    
186     /* skip to the beginning of reply */
187     while (*reply == ' ' || *reply == '\t') reply++;
188     if (*reply == '\0')
189     goto error;
190    
191     for (i = 0; i <= ERR_LAST_ERR_MSG; i++)
192     {
193     if (replies[i].name != NULL)
194     {
195     if (irccmp(replies[i].name, ident) == 0)
196     {
197     if (!change_reply(locale, linecnt, i, reply)) res = 0;
198     i = -1;
199     break;
200     }
201     }
202     }
203     if (i != -1)
204     {
205     ilog(L_ERROR,
206     "Unknown numeric %s (%s.lang, %d)", ident, locale, linecnt);
207     res = 0;
208     }
209     }
210     fbclose(f);
211    
212     strlcpy(used_locale, locale, sizeof(used_locale));
213     if (!res)
214     sendto_realops_flags(UMODE_ALL, L_ADMIN, "Language file [%s] contains "
215     "errors, check server log file for more details",
216     used_locale);
217     }
218    
219     /* Returns the name of current locale. */
220     const char *
221     get_locale(void)
222     {
223     return used_locale;
224     }

Properties

Name Value
svn:eol-style native
svn:keywords Id Revision