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 */
205nserror messages_add_key_value(const char *key, const char *value)
206{
207 /* ensure the hash table is initialised */
208 if (messages_hash == NULL) {
210 }
211 if (messages_hash == NULL) {
212 NSLOG(netsurf, INFO, "Unable to create hash table");
213 return NSERROR_NOMEM;
214 }
215 return hash_add(messages_hash, key, value);
216}
217
218
219/* exported interface documented in messages.h */
220char *messages_get_buff(const char *key, ...)
221{
222 const char *msg_fmt;
223 char *buff = NULL; /* formatted buffer to return */
224 int buff_len = 0;
225 va_list ap;
226
227 assert(key != NULL);
228
229 if (messages_hash == NULL) {
230 return NULL;
231 }
232
233 msg_fmt = hash_get(messages_hash, key);
234
235 if (msg_fmt == NULL) {
236 return NULL;
237 }
238
239 va_start(ap, key);
240 buff_len = vsnprintf(buff, buff_len, msg_fmt, ap);
241 va_end(ap);
242
243 buff = malloc(buff_len + 1);
244
245 if (buff != NULL) {
246 va_start(ap, key);
247 vsnprintf(buff, buff_len + 1, msg_fmt, ap);
248 va_end(ap);
249 }
250
251 return buff;
252}
253
254
255/* exported function documented in utils/messages.h */
256const char *messages_get(const char *key)
257{
258 return messages_get_ctx(key, messages_hash);
259}
260
261
262/* exported function documented in utils/messages.h */
264{
265 switch (code) {
266 case NSERROR_OK:
267 /* No error */
268 return messages_get_ctx("OK", messages_hash);
269
270 case NSERROR_NOMEM:
271 /* Memory exhaustion */
272 return messages_get_ctx("NoMemory", messages_hash);
273
275 /* No fetch handler for URL scheme */
276 return messages_get_ctx("NoHandler", messages_hash);
277
279 /* Requested item not found */
280 return messages_get_ctx("NotFound", messages_hash);
281
283 /* Missing directory */
284 return messages_get_ctx("NotDirectory", messages_hash);
285
287 /* Failed to save data */
288 return messages_get_ctx("SaveFailed", messages_hash);
289
291 /* Failed to clone handle */
292 return messages_get_ctx("CloneFailed", messages_hash);
293
295 /* Initialisation failed */
296 return messages_get_ctx("InitFailed", messages_hash);
297
299 /* A BMP error occurred */
300 return messages_get_ctx("BMPError", messages_hash);
301
303 /* A GIF error occurred */
304 return messages_get_ctx("GIFError", messages_hash);
305
307 /* A ICO error occurred */
308 return messages_get_ctx("ICOError", messages_hash);
309
311 /* A PNG error occurred */
312 return messages_get_ctx("PNGError", messages_hash);
313
315 /* A RISC OS Sprite error occurred */
316 return messages_get_ctx("SpriteError", messages_hash);
317
319 /* A SVG error occurred */
320 return messages_get_ctx("SVGError", messages_hash);
321
323 /* The character set is unknown */
324 return messages_get_ctx("BadEncoding", messages_hash);
325
327 /* More data needed */
328 return messages_get_ctx("NeedData", messages_hash);
329
331 /* The character set encoding change was unhandled */
332 return messages_get_ctx("EncodingChanged", messages_hash);
333
335 /* Bad Parameter */
336 return messages_get_ctx("BadParameter", messages_hash);
337
338 case NSERROR_INVALID:
339 /* Invalid data */
340 return messages_get_ctx("Invalid", messages_hash);
341
343 /* Box conversion failed */
344 return messages_get_ctx("BoxConvert", messages_hash);
345
346 case NSERROR_STOPPED:
347 /* Content conversion stopped */
348 return messages_get_ctx("Stopped", messages_hash);
349
350 case NSERROR_DOM:
351 /* DOM call returned error */
352 return messages_get_ctx("ParsingFail", messages_hash);
353
354 case NSERROR_CSS:
355 /* CSS call returned error */
356 return messages_get_ctx("CSSGeneric", messages_hash);
357
358 case NSERROR_CSS_BASE:
359 /* CSS base sheet failed */
360 return messages_get_ctx("CSSBase", messages_hash);
361
362 case NSERROR_BAD_URL:
363 /* Bad URL */
364 return messages_get_ctx("BadURL", messages_hash);
365
367 /* Bad Content */
368 return messages_get_ctx("BadContent", messages_hash);
369
371 /* Exceeded frame depth */
372 return messages_get_ctx("FrameDepth", messages_hash);
373
375 /* Permission error */
376 return messages_get_ctx("PermissionError", messages_hash);
377
378 case NSERROR_BAD_SIZE:
379 /* Bad size */
380 return messages_get_ctx("BadSize", messages_hash);
381
382 case NSERROR_NOSPACE:
383 /* Insufficient space */
384 return messages_get_ctx("NoSpace", messages_hash);
385
387 /* Functionality is not implemented */
388 return messages_get_ctx("NotImplemented", messages_hash);
389
390 case NSERROR_UNKNOWN:
391 /* Unknown error */
392 return messages_get_ctx("Unknown", messages_hash);
393
394 case NSERROR_BAD_AUTH:
395 /* Authentication required */
396 return messages_get_ctx("BadAuth", messages_hash);
397
399 /* To many redirects */
400 return messages_get_ctx("TooManyRedirects", messages_hash);
401
403 /* Certificate chain verification failure */
404 return messages_get_ctx("CertificateVerificationNeeded", messages_hash);
405
406 case NSERROR_TIMEOUT:
407 /* Operation timed out */
408 return messages_get_ctx("Timeout", messages_hash);
409 }
410
411 /* The switch has no default, so the compiler should tell us when we
412 * forget to add messages for new error codes. As such, we should
413 * never get here.
414 */
415 assert(0);
416 return messages_get_ctx("Unknown", messages_hash);
417}
418
419/* exported function documented in utils/messages.h */
421{
422 switch (code) {
423 case SSL_CERT_ERR_OK:
424 /* Nothing wrong with this certificate */
425 return messages_get_ctx("SSLCertErrOk", messages_hash);
426
428 /* Unknown error */
429 return messages_get_ctx("SSLCertErrUnknown", messages_hash);
430
432 /* Bad issuer */
433 return messages_get_ctx("SSLCertErrBadIssuer", messages_hash);
434
436 /* Bad signature on this certificate */
437 return messages_get_ctx("SSLCertErrBadSig", messages_hash);
438
440 /* This certificate is not yet valid */
441 return messages_get_ctx("SSLCertErrTooYoung", messages_hash);
442
444 /* This certificate is no longer valid */
445 return messages_get_ctx("SSLCertErrTooOld", messages_hash);
446
448 /* This certificate is self signed */
449 return messages_get_ctx("SSLCertErrSelfSigned", messages_hash);
450
452 /* This certificate chain is self signed */
453 return messages_get_ctx("SSLCertErrChainSelfSigned", messages_hash);
454
456 /* This certificate has been revoked */
457 return messages_get_ctx("SSLCertErrRevoked", messages_hash);
458
460 /* Common name is invalid */
461 return messages_get_ctx("SSLCertErrHostnameMismatch", messages_hash);
462
464 /* Common name is invalid */
465 return messages_get_ctx("SSLCertErrCertMissing", messages_hash);
466
467 }
468
469 /* The switch has no default, so the compiler should tell us when we
470 * forget to add messages for new error codes. As such, we should
471 * never get here.
472 */
473 assert(0);
474 return messages_get_ctx("Unknown", messages_hash);
475}
476
477/* exported function documented in utils/messages.h */
479{
481 messages_hash = NULL;
482}
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:255
nserror hash_add(struct hash_table *ht, const char *key, const char *value)
Adds a key/value pair to a hash table.
Definition: hashtable.c:304
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:400
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:364
void hash_destroy(struct hash_table *ht)
Destroys a hash table.
Definition: hashtable.c:279
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:340
Interface to Write-Once hash table for string to string mapping.
#define NSLOG(catname, level, logmsg, args...)
Definition: log.h:116
nserror messages_add_key_value(const char *key, const char *value)
Add a single message.
Definition: messages.c:205
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:263
const char * messages_get(const char *key)
Fast lookup of a message by key from the standard Messages hash.
Definition: messages.c:256
char * messages_get_buff(const char *key,...)
Formatted message from a key in the global message hash.
Definition: messages.c:220
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:478
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:420
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