ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/numeric.c
(Generate patch)

Comparing ircd-hybrid/trunk/src/numeric.c (file contents):
Revision 1833 by michael, Fri Apr 19 19:16:09 2013 UTC vs.
Revision 1834 by michael, Fri Apr 19 19:50:27 2013 UTC

# Line 30 | Line 30
30   #include "log.h"
31   #include "send.h"
32   #include "client.h"
33 + #include "messages.tab"
34 +
35 + static char used_locale[LOCALE_LENGTH] = "standard";
36 +
37 + /*
38 + * form_str
39 + *
40 + * inputs       - numeric
41 + * output       - corresponding string
42 + * side effects - NONE
43 + */
44 + const char* form_str(int numeric)
45 + {
46 +  assert(-1 < numeric);
47 +  assert(numeric < ERR_LAST_ERR_MSG);
48 +
49 +  if (numeric > ERR_LAST_ERR_MSG)
50 +    numeric = ERR_LAST_ERR_MSG;
51 +  if (numeric < 0)
52 +    numeric = ERR_LAST_ERR_MSG;
53 +
54 +  assert(replies[numeric].standard != NULL);
55 +
56 +  return (replies[numeric].translated != NULL ? replies[numeric].translated :
57 +                                                replies[numeric].standard);
58 + }
59 +
60 + /* Attempts to change a numeric with index "reply" to "new_reply".
61 + * Returns 1 if ok, 0 otherwise.
62 + */
63 + static int
64 + change_reply(const char *locale, int linecnt, int reply, char *new_reply)
65 + {
66 +  int found;
67 +  char *new = new_reply;
68 +  const char *old = replies[reply].standard;
69 +
70 +  for (; *new; new++)
71 +  {
72 +    if (*new == '%')
73 +    {
74 +      if (!*++new) break;
75 +      if (*new != '%')
76 +      {
77 +        /* We've just found a format symbol. Check if it is the next format
78 +         * symbol in the original reply.
79 +         */
80 +        for (; *new >= '0' && *new <= '9'; new++); /* skip size prefix */
81 +        found = 0;
82 +        for (; *old; old++)
83 +        {
84 +          if (*old == '%')
85 +          {
86 +            if (!*++old) break;  /* shouldn't happen */
87 +            if (*old != '%')
88 +            {
89 +              for (; *old >= '0' && *old <= '9'; old++); /* skip size prefix */
90 +              if (*new != *old++)
91 +              {
92 +                ilog(LOG_TYPE_IRCD, "Incompatible format symbols (%s.lang, %d)",
93 +                     locale, linecnt);
94 +                return 0;
95 +              }
96 +              found = 1;
97 +              break;
98 +            }
99 +          }
100 +        }
101 +        if (!found)
102 +        {
103 +          ilog(LOG_TYPE_IRCD, "Too many format symbols (%s.lang, %d)", locale, linecnt);
104 +          return(0);
105 +        }
106 +      }
107 +    }
108 +  }
109 +
110 +  MyFree(replies[reply].translated);
111 +  replies[reply].translated = xstrdup(new_reply);
112 +  return(1);
113 + }
114 +
115 + /* Loads a language file. Errors are logged into the log file. */
116 + void
117 + set_locale(const char *locale)
118 + {
119 +  int i, res = 1, linecnt = 0;
120 +  char buffer[IRCD_BUFSIZE + 1];
121 +  char *ident, *reply;
122 +  FILE *f;
123 +
124 +  /* Restore standard replies */
125 +  for (i = 0; i <= ERR_LAST_ERR_MSG; i++)   /* 0 isn't a magic number! ;> */
126 +  {
127 +    if (replies[i].translated != NULL)
128 +    {
129 +      MyFree(replies[i].translated);
130 +      replies[i].translated = NULL;
131 +    }
132 +  }
133 +
134 +  if (strchr(locale, '/') != NULL)
135 +  {
136 +    strlcpy(used_locale, "standard", sizeof(used_locale));  /* XXX paranoid */
137 +    return;
138 +  }
139 +
140 +  /* yes, I know - the slash isn't necessary. But I have to be sure
141 +   * that it'll work even if some lame admin won't put "/" at the end
142 +   * of MSGPATH.
143 +   */
144 +  snprintf(buffer, sizeof(buffer), "%s/%s.lang", MSGPATH, locale);
145 +  if ((f = fopen(buffer, "r")) == NULL)
146 +  {
147 +    strlcpy(used_locale, "standard", sizeof(used_locale));  /* XXX */
148 +    return;
149 +  }
150 +
151 +  /* Process the language file */
152 +  while (fgets(buffer, sizeof(buffer), f))
153 +  {
154 +    ++linecnt;
155 +    if (buffer[0] == ';')
156 +      continue;   /* that's a comment */
157 +
158 +    if ((ident = strpbrk(buffer, "\r\n")) != NULL)
159 +      *ident = '\0';
160 +
161 +    /* skip spaces if there are any */
162 +    for (ident = buffer; *ident == ' ' || *ident == '\t'; ident++)/* null */;
163 +    if (*ident == '\0')
164 +      continue;            /* empty line */
165 +
166 +    /* skip after the reply identificator */
167 +    for (reply = ident; *reply != ' ' && *reply != '\t' && *reply != ':';
168 +      reply++)
169 +      if (*reply == '\0') goto error;
170 +
171 +    if (*reply == ' ' || *reply == '\t')
172 +    {
173 +      for (*reply++ = '\0'; *reply == ' ' || *reply == '\t'; reply++);
174 +      if (*reply != ':')
175 +      {
176 +        error:
177 +        ilog(LOG_TYPE_IRCD, "Invalid line in language file (%s.lang, %d)",
178 +             locale, linecnt);
179 +        res = 0;
180 +        continue;
181 +      }
182 +    }
183 +    else
184 +      *reply++ = '\0';
185 +    if (*ident == '\0')
186 +      goto error;
187 +
188 +    /* skip to the beginning of reply */
189 +    while (*reply == ' ' || *reply == '\t') reply++;
190 +    if (*reply == '\0')
191 +      goto error;
192 +
193 +    for (i = 0; i <= ERR_LAST_ERR_MSG; i++)
194 +    {
195 +      if (replies[i].name != NULL)
196 +      {
197 +        if (irccmp(replies[i].name, ident) == 0)
198 +        {
199 +          if (!change_reply(locale, linecnt, i, reply)) res = 0;
200 +          i = -1;
201 +          break;
202 +        }
203 +      }
204 +    }
205 +    if (i != -1)
206 +    {
207 +      ilog(LOG_TYPE_IRCD,
208 +           "Unknown numeric %s (%s.lang, %d)", ident, locale, linecnt);
209 +      res = 0;
210 +    }
211 +  }
212 +  fclose(f);
213 +
214 +  strlcpy(used_locale, locale, sizeof(used_locale));
215 +  if (!res)
216 +    sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
217 +                         "Language file [%s] contains "
218 +                         "errors, check server log file for more details",
219 +                         used_locale);
220 + }
221 +
222 + /* Returns the name of current locale. */
223 + const char *
224 + get_locale(void)
225 + {
226 +  return used_locale;
227 + }

Diff Legend

Removed lines
+ Added lines
< Changed lines (old)
> Changed lines (new)