NetSurf
messages.c
Go to the documentation of this file.
1/*
2 * Copyright 2004 James Bursa <bursa@users.sourceforge.net>
3 * Copyright 2006 Rob Kendrick <rjek@rjek.com>
4 *
5 * This file is part of NetSurf, http://www.netsurf-browser.org/
6 *
7 * NetSurf 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; version 2 of the License.
10 *
11 * NetSurf is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20/**
21 * \file
22 * Localised message support implementation.
23 *
24 * Native language messages are loaded from a file and stored hashed by key for
25 * fast access.
26 */
27
28#include <stdlib.h>
29#include <assert.h>
30#include <errno.h>
31#include <stdio.h>
32#include <stdbool.h>
33#include <string.h>
34#include <zlib.h>
35#include <stdarg.h>
36
37#include "utils/log.h"
38#include "utils/messages.h"
39#include "utils/utils.h"
40#include "utils/hashtable.h"
41
42/** Messages are stored in a fixed-size hash table. */
43#define HASH_SIZE 101
44
45/**
46 * The hash table used to store the standard Messages file for the old API
47 */
48static struct hash_table *messages_hash = NULL;
49
50
51/**
52 * Create a message context
53 *
54 * generate a message context populated with english fallbacks for
55 * some formatted messages.
56 */
57static struct hash_table *messages_create_ctx(int hash_size)
58{
59 struct hash_table *nctx;
60 const struct {
61 const char *key;
62 const char *value;
63 } fallback[] = {
64 { "LoginDescription",
65 "The site %s is requesting your username and password. "
66 "The realm is \"%s\""},
67 { "PrivacyDescription",
68 "A privacy error occurred while communicating with %s this "
69 "may be a site configuration error or an attempt to steal "
70 "private information (passwords, messages or credit cards)"},
71 { "TimeoutDescription",
72 "A connection to %s could not be established. The site may "
73 "be temporarily unavailable or too busy to respond."},
74 { "FetchErrorDescription",
75 "An error occurred when connecting to %s"},
76 { NULL, NULL}
77 };
78 nctx = hash_create(hash_size);
79
80 if (nctx != NULL) {
81 int floop;
82 for (floop = 0; fallback[floop].key != NULL; floop++) {
83 hash_add(nctx,
84 fallback[floop].key,
85 fallback[floop].value);
86 }
87 }
88
89 return nctx;
90}
91
92/**
93 * Free memory used by a messages hash.
94 * The context will not be valid after this function returns.
95 *
96 * \param ctx context of messages file to free
97 */
98static void messages_destroy_ctx(struct hash_table *ctx)
99{
100 if (ctx == NULL)
101 return;
102
103 hash_destroy(ctx);
104}
105
106
107/**
108 * Read keys and values from messages file.
109 *
110 * \param path pathname of messages file
111 * \param ctx reference of hash table to merge with or NULL to create one.
112 * \return NSERROR_OK on sucess and ctx updated or error code on faliure.
113 */
114static nserror messages_load_ctx(const char *path, struct hash_table **ctx)
115{
116 struct hash_table *nctx; /* new context */
117 nserror res;
118
119 if (*ctx != NULL) {
120 /**
121 * \note The passed hash is not copied here so this
122 * updates in place.
123 */
124 return hash_add_file(*ctx, path);
125 }
126
128 if (nctx == NULL) {
129 NSLOG(netsurf, INFO,
130 "Unable to create hash table for messages file %s",
131 path);
132 return NSERROR_NOMEM;
133 }
134
135 res = hash_add_file(nctx, path);
136 if (res == NSERROR_OK) {
137 *ctx = nctx;
138 } else {
139 hash_destroy(nctx);
140 }
141
142 return res;
143}
144
145
146/**
147 * Fast lookup of a message by key.
148 *
149 * \param key key of message
150 * \param ctx context of messages file to look up in
151 * \return value of message, or key if not found
152 */
153static const char *
154messages_get_ctx(const char *key, struct hash_table *ctx)
155{
156 const char *r = NULL;
157
158 assert(key != NULL);
159
160 /* allow attempts to retrieve messages before context is set up. */
161 if (ctx != NULL) {
162 r = hash_get(ctx, key);
163 }
164
165 /* If called with no context or unable to retrive a value
166 * return the key.
167 */
168 if (r == NULL) {
169 r = key;
170 }
171
172 return r;
173}
174
175
176/* exported interface documented in messages.h */
178{
179 if (path == NULL) {
181 }
182
183 NSLOG(netsurf, INFO, "Loading Messages from '%s'", path);
184
186}
187
188
189/* exported interface documented in messages.h */
190nserror messages_add_from_inline(const uint8_t *data, size_t size)
191{
192 /* ensure the hash table is initialised */
193 if (messages_hash == NULL) {
195 }
196 if (messages_hash == NULL) {
197 NSLOG(netsurf, INFO, "Unable to create hash table");
198 return NSERROR_NOMEM;
199 }
200 return hash_add_inline(messages_hash, data, size);
201}
202
203
204/* exported interface documented in messages.h */
205char *messages_get_buff(const char *key, ...)
206{
207 const char *msg_fmt;
208 char *buff = NULL; /* formatted buffer to return */
209 int buff_len = 0;
210 va_list ap;
211
212 assert(key != NULL);
213
214 if (messages_hash == NULL) {
215 return NULL;
216 }
217
218 msg_fmt = hash_get(messages_hash, key);
219
220 if (msg_fmt == NULL) {
221 return NULL;
222 }
223
224 va_start(ap, key);
225 buff_len = vsnprintf(buff, buff_len, msg_fmt, ap);
226 va_end(ap);
227
228 buff = malloc(buff_len + 1);
229
230 if (buff != NULL) {
231 va_start(ap, key);
232 vsnprintf(buff, buff_len + 1, msg_fmt, ap);
233 va_end(ap);
234 }
235
236 return buff;
237}
238
239
240/* exported function documented in utils/messages.h */
241const char *messages_get(const char *key)
242{
243 return messages_get_ctx(key, messages_hash);
244}
245
246
247/* exported function documented in utils/messages.h */
249{
250 switch (code) {
251 case NSERROR_OK:
252 /* No error */
253 return messages_get_ctx("OK", messages_hash);
254
255 case NSERROR_NOMEM:
256 /* Memory exhaustion */
257 return messages_get_ctx("NoMemory", messages_hash);
258
260 /* No fetch handler for URL scheme */
261 return messages_get_ctx("NoHandler", messages_hash);
262
264 /* Requested item not found */
265 return messages_get_ctx("NotFound", messages_hash);
266
268 /* Missing directory */
269 return messages_get_ctx("NotDirectory", messages_hash);
270
272 /* Failed to save data */
273 return messages_get_ctx("SaveFailed", messages_hash);
274
276 /* Failed to clone handle */
277 return messages_get_ctx("CloneFailed", messages_hash);
278
280 /* Initialisation failed */
281 return messages_get_ctx("InitFailed", messages_hash);
282
284 /* A BMP error occurred */
285 return messages_get_ctx("BMPError", messages_hash);
286
288 /* A GIF error occurred */
289 return messages_get_ctx("GIFError", messages_hash);
290
292 /* A ICO error occurred */
293 return messages_get_ctx("ICOError", messages_hash);
294
296 /* A PNG error occurred */
297 return messages_get_ctx("PNGError", messages_hash);
298
300 /* A RISC OS Sprite error occurred */
301 return messages_get_ctx("SpriteError", messages_hash);
302
304 /* A SVG error occurred */
305 return messages_get_ctx("SVGError", messages_hash);
306
308 /* The character set is unknown */
309 return messages_get_ctx("BadEncoding", messages_hash);
310
312 /* More data needed */
313 return messages_get_ctx("NeedData", messages_hash);
314
316 /* The character set encoding change was unhandled */
317 return messages_get_ctx("EncodingChanged", messages_hash);
318
320 /* Bad Parameter */
321 return messages_get_ctx("BadParameter", messages_hash);
322
323 case NSERROR_INVALID:
324 /* Invalid data */
325 return messages_get_ctx("Invalid", messages_hash);
326
328 /* Box conversion failed */
329 return messages_get_ctx("BoxConvert", messages_hash);
330
331 case NSERROR_STOPPED:
332 /* Content conversion stopped */
333 return messages_get_ctx("Stopped", messages_hash);
334
335 case NSERROR_DOM:
336 /* DOM call returned error */
337 return messages_get_ctx("ParsingFail", messages_hash);
338
339 case NSERROR_CSS:
340 /* CSS call returned error */
341 return messages_get_ctx("CSSGeneric", messages_hash);
342
343 case NSERROR_CSS_BASE:
344 /* CSS base sheet failed */
345 return messages_get_ctx("CSSBase", messages_hash);
346
347 case NSERROR_BAD_URL:
348 /* Bad URL */
349 return messages_get_ctx("BadURL", messages_hash);
350
352 /* Bad Content */
353 return messages_get_ctx("BadContent", messages_hash);
354
356 /* Exceeded frame depth */
357 return messages_get_ctx("FrameDepth", messages_hash);
358
360 /* Permission error */
361 return messages_get_ctx("PermissionError", messages_hash);
362
363 case NSERROR_BAD_SIZE:
364 /* Bad size */
365 return messages_get_ctx("BadSize", messages_hash);
366
367 case NSERROR_NOSPACE:
368 /* Insufficient space */
369 return messages_get_ctx("NoSpace", messages_hash);
370
372 /* Functionality is not implemented */
373 return messages_get_ctx("NotImplemented", messages_hash);
374
375 case NSERROR_UNKNOWN:
376 /* Unknown error */
377 return messages_get_ctx("Unknown", messages_hash);
378
379 case NSERROR_BAD_AUTH:
380 /* Authentication required */
381 return messages_get_ctx("BadAuth", messages_hash);
382
384 /* To many redirects */
385 return messages_get_ctx("TooManyRedirects", messages_hash);
386
388 /* Certificate chain verification failure */
389 return messages_get_ctx("CertificateVerificationNeeded", messages_hash);
390
391 case NSERROR_TIMEOUT:
392 /* Operation timed out */
393 return messages_get_ctx("Timeout", messages_hash);
394 }
395
396 /* The switch has no default, so the compiler should tell us when we
397 * forget to add messages for new error codes. As such, we should
398 * never get here.
399 */
400 assert(0);
401 return messages_get_ctx("Unknown", messages_hash);
402}
403
404/* exported function documented in utils/messages.h */
406{
407 switch (code) {
408 case SSL_CERT_ERR_OK:
409 /* Nothing wrong with this certificate */
410 return messages_get_ctx("SSLCertErrOk", messages_hash);
411
413 /* Unknown error */
414 return messages_get_ctx("SSLCertErrUnknown", messages_hash);
415
417 /* Bad issuer */
418 return messages_get_ctx("SSLCertErrBadIssuer", messages_hash);
419
421 /* Bad signature on this certificate */
422 return messages_get_ctx("SSLCertErrBadSig", messages_hash);
423
425 /* This certificate is not yet valid */
426 return messages_get_ctx("SSLCertErrTooYoung", messages_hash);
427
429 /* This certificate is no longer valid */
430 return messages_get_ctx("SSLCertErrTooOld", messages_hash);
431
433 /* This certificate is self signed */
434 return messages_get_ctx("SSLCertErrSelfSigned", messages_hash);
435
437 /* This certificate chain is self signed */
438 return messages_get_ctx("SSLCertErrChainSelfSigned", messages_hash);
439
441 /* This certificate has been revoked */
442 return messages_get_ctx("SSLCertErrRevoked", messages_hash);
443
445 /* Common name is invalid */
446 return messages_get_ctx("SSLCertErrHostnameMismatch", messages_hash);
447
449 /* Common name is invalid */
450 return messages_get_ctx("SSLCertErrCertMissing", messages_hash);
451
452 }
453
454 /* The switch has no default, so the compiler should tell us when we
455 * forget to add messages for new error codes. As such, we should
456 * never get here.
457 */
458 assert(0);
459 return messages_get_ctx("Unknown", messages_hash);
460}
461
462/* exported function documented in utils/messages.h */
464{
466 messages_hash = NULL;
467}
nserror
Enumeration of error codes.
Definition: errors.h:29
@ NSERROR_TIMEOUT
Operation timed out.
Definition: errors.h:65
@ NSERROR_PERMISSION
Permission error.
Definition: errors.h:58
@ NSERROR_SAVE_FAILED
Failed to save data.
Definition: errors.h:36
@ NSERROR_CSS_BASE
CSS base sheet failed.
Definition: errors.h:54
@ NSERROR_BMP_ERROR
A BMP error occurred.
Definition: errors.h:39
@ NSERROR_SPRITE_ERROR
A RISC OS Sprite error occurred.
Definition: errors.h:43
@ NSERROR_NOSPACE
Insufficient space.
Definition: errors.h:59
@ NSERROR_NOT_FOUND
Requested item not found.
Definition: errors.h:34
@ NSERROR_INIT_FAILED
Initialisation failed.
Definition: errors.h:38
@ NSERROR_BAD_ENCODING
The character set is unknown.
Definition: errors.h:45
@ NSERROR_BAD_CONTENT
Bad Content.
Definition: errors.h:56
@ NSERROR_BOX_CONVERT
Box conversion failed.
Definition: errors.h:50
@ NSERROR_BAD_URL
Bad URL.
Definition: errors.h:55
@ NSERROR_DOM
DOM call returned error.
Definition: errors.h:52
@ NSERROR_ICO_ERROR
A ICO error occurred.
Definition: errors.h:41
@ NSERROR_GIF_ERROR
A GIF error occurred.
Definition: errors.h:40
@ NSERROR_BAD_AUTH
Fetch needs authentication data.
Definition: errors.h:63
@ NSERROR_NOT_IMPLEMENTED
Functionality is not implemented.
Definition: errors.h:61
@ NSERROR_BAD_PARAMETER
Bad Parameter.
Definition: errors.h:48
@ NSERROR_SVG_ERROR
A SVG error occurred.
Definition: errors.h:44
@ NSERROR_BAD_CERTS
Fetch needs certificate chain check.
Definition: errors.h:64
@ NSERROR_BAD_SIZE
Bad size.
Definition: errors.h:60
@ NSERROR_NO_FETCH_HANDLER
No fetch handler for URL scheme.
Definition: errors.h:33
@ NSERROR_PNG_ERROR
A PNG error occurred.
Definition: errors.h:42
@ NSERROR_NEED_DATA
More data needed.
Definition: errors.h:46
@ NSERROR_BAD_REDIRECT
Fetch encountered a bad redirect.
Definition: errors.h:62
@ NSERROR_FRAME_DEPTH
Exceeded frame depth.
Definition: errors.h:57
@ NSERROR_UNKNOWN
Unknown error - DO NOT USE.
Definition: errors.h:31
@ NSERROR_NOT_DIRECTORY
Missing directory.
Definition: errors.h:35
@ NSERROR_STOPPED
Content conversion stopped.
Definition: errors.h:51
@ NSERROR_ENCODING_CHANGE
The character changed.
Definition: errors.h:47
@ NSERROR_CSS
CSS call returned error.
Definition: errors.h:53
@ NSERROR_INVALID
Invalid data.
Definition: errors.h:49
@ NSERROR_NOMEM
Memory exhaustion.
Definition: errors.h:32
@ NSERROR_CLONE_FAILED
Failed to clone handle.
Definition: errors.h:37
@ NSERROR_OK
No error.
Definition: errors.h:30
struct hash_table * hash_create(unsigned int chains)
Create a new hash table.
Definition: hashtable.c:254
bool hash_add(struct hash_table *ht, const char *key, const char *value)
Adds a key/value pair to a hash table.
Definition: hashtable.c:303
nserror hash_add_inline(struct hash_table *ht, const uint8_t *data, size_t size)
Add key/value pairs to a hash table with data from a memory buffer.
Definition: hashtable.c:399
nserror hash_add_file(struct hash_table *ht, const char *path)
Add key/value pairs to a hash table with data from a file.
Definition: hashtable.c:363
void hash_destroy(struct hash_table *ht)
Destroys a hash table.
Definition: hashtable.c:278
const char * hash_get(struct hash_table *ht, const char *key)
Looks up a the value associated with with a key from a specific hash table.
Definition: hashtable.c:339
Interface to Write-Once hash table for string to string mapping.
#define NSLOG(catname, level, logmsg, args...)
Definition: log.h:116
nserror messages_add_from_inline(const uint8_t *data, size_t size)
Read keys and values from inline message data into the standard Messages hash.
Definition: messages.c:190
static nserror messages_load_ctx(const char *path, struct hash_table **ctx)
Read keys and values from messages file.
Definition: messages.c:114
nserror messages_add_from_file(const char *path)
Read keys and values from messages file into the standard Messages hash.
Definition: messages.c:177
const char * messages_get_errorcode(nserror code)
lookup of a message by errorcode from the standard Messages hash.
Definition: messages.c:248
const char * messages_get(const char *key)
Fast lookup of a message by key from the standard Messages hash.
Definition: messages.c:241
char * messages_get_buff(const char *key,...)
Formatted message from a key in the global message hash.
Definition: messages.c:205
static void messages_destroy_ctx(struct hash_table *ctx)
Free memory used by a messages hash.
Definition: messages.c:98
static struct hash_table * messages_hash
The hash table used to store the standard Messages file for the old API.
Definition: messages.c:48
void messages_destroy(void)
Free memory used by the standard Messages hash.
Definition: messages.c:463
static struct hash_table * messages_create_ctx(int hash_size)
Create a message context.
Definition: messages.c:57
#define HASH_SIZE
Messages are stored in a fixed-size hash table.
Definition: messages.c:43
static const char * messages_get_ctx(const char *key, struct hash_table *ctx)
Fast lookup of a message by key.
Definition: messages.c:154
const char * messages_get_sslcode(ssl_cert_err code)
lookup of a message by SSL error code from the standard Messages hash.
Definition: messages.c:405
Localised message support (interface).
ssl_cert_err
ssl certificate error status
Definition: ssl_certs.h:36
@ SSL_CERT_ERR_TOO_YOUNG
This certificate is not yet valid.
Definition: ssl_certs.h:41
@ SSL_CERT_ERR_BAD_SIG
Bad signature on this certificate.
Definition: ssl_certs.h:40
@ SSL_CERT_ERR_BAD_ISSUER
Bad issuer.
Definition: ssl_certs.h:39
@ SSL_CERT_ERR_SELF_SIGNED
This certificate (or the chain) is self signed.
Definition: ssl_certs.h:43
@ SSL_CERT_ERR_OK
Nothing wrong with this certificate.
Definition: ssl_certs.h:37
@ SSL_CERT_ERR_HOSTNAME_MISMATCH
This certificate host did not match the server.
Definition: ssl_certs.h:46
@ SSL_CERT_ERR_TOO_OLD
This certificate is no longer valid.
Definition: ssl_certs.h:42
@ SSL_CERT_ERR_REVOKED
This certificate has been revoked.
Definition: ssl_certs.h:45
@ SSL_CERT_ERR_CHAIN_SELF_SIGNED
This certificate chain is self signed.
Definition: ssl_certs.h:44
@ SSL_CERT_ERR_CERT_MISSING
This certificate was missing from the chain, its data is useless.
Definition: ssl_certs.h:47
@ SSL_CERT_ERR_UNKNOWN
Unknown error.
Definition: ssl_certs.h:38
Interface to utility string handling.
Interface to a number of general purpose functionality.
static nserror path(const struct redraw_context *ctx, const plot_style_t *pstyle, const float *p, unsigned int n, const float transform[6])
Plots a path.
Definition: plot.c:821