Subversion Repositories Kolibri OS

Compare Revisions

No changes between revisions

Regard whitespace Rev 3584 → Rev 4364

/contrib/network/netsurf/netsurf/utils/base64.c
0,0 → 1,441
/* base64.c -- Encode binary data using printable characters.
Copyright (C) 1999, 2000, 2001, 2004, 2005, 2006 Free Software
Foundation, Inc.
 
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
 
/* Written by Simon Josefsson. Partially adapted from GNU MailUtils
* (mailbox/filter_trans.c, as of 2004-11-28). Improved by review
* from Paul Eggert, Bruno Haible, and Stepan Kasal.
*
* See also RFC 3548 <http://www.ietf.org/rfc/rfc3548.txt>.
*
* Be careful with error checking. Here is how you would typically
* use these functions:
*
* bool ok = base64_decode_alloc (in, inlen, &out, &outlen);
* if (!ok)
* FAIL: input was not valid base64
* if (out == NULL)
* FAIL: memory allocation error
* OK: data in OUT/OUTLEN
*
* size_t outlen = base64_encode_alloc (in, inlen, &out);
* if (out == NULL && outlen == 0 && inlen != 0)
* FAIL: input too long
* if (out == NULL)
* FAIL: memory allocation error
* OK: data in OUT/OUTLEN.
*
*/
 
/*#include <config.h>*/
 
/* Get prototype. */
#include "utils/base64.h"
 
/* Get malloc. */
#include <stdlib.h>
 
/* Get UCHAR_MAX. */
#include <limits.h>
 
/* C89 compliant way to cast 'char' to 'unsigned char'. */
static inline unsigned char
to_uchar (char ch)
{
return ch;
}
 
/* Base64 encode IN array of size INLEN into OUT array of size OUTLEN.
If OUTLEN is less than BASE64_LENGTH(INLEN), write as many bytes as
possible. If OUTLEN is larger than BASE64_LENGTH(INLEN), also zero
terminate the output buffer. */
void
base64_encode (const char * in, size_t inlen,
char * out, size_t outlen)
{
static const char b64str[64] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 
while (inlen && outlen)
{
*out++ = b64str[(to_uchar (in[0]) >> 2) & 0x3f];
if (!--outlen)
break;
*out++ = b64str[((to_uchar (in[0]) << 4)
+ (--inlen ? to_uchar (in[1]) >> 4 : 0))
& 0x3f];
if (!--outlen)
break;
*out++ =
(inlen
? b64str[((to_uchar (in[1]) << 2)
+ (--inlen ? to_uchar (in[2]) >> 6 : 0))
& 0x3f]
: '=');
if (!--outlen)
break;
*out++ = inlen ? b64str[to_uchar (in[2]) & 0x3f] : '=';
if (!--outlen)
break;
if (inlen)
inlen--;
if (inlen)
in += 3;
}
 
if (outlen)
*out = '\0';
}
 
/* Allocate a buffer and store zero terminated base64 encoded data
from array IN of size INLEN, returning BASE64_LENGTH(INLEN), i.e.,
the length of the encoded data, excluding the terminating zero. On
return, the OUT variable will hold a pointer to newly allocated
memory that must be deallocated by the caller. If output string
length would overflow, 0 is returned and OUT is set to NULL. If
memory allocation failed, OUT is set to NULL, and the return value
indicates length of the requested memory block, i.e.,
BASE64_LENGTH(inlen) + 1. */
size_t
base64_encode_alloc (const char *in, size_t inlen, char **out)
{
size_t outlen = 1 + BASE64_LENGTH (inlen);
 
/* Check for overflow in outlen computation.
*
* If there is no overflow, outlen >= inlen.
*
* If the operation (inlen + 2) overflows then it yields at most +1, so
* outlen is 0.
*
* If the multiplication overflows, we lose at least half of the
* correct value, so the result is < ((inlen + 2) / 3) * 2, which is
* less than (inlen + 2) * 0.66667, which is less than inlen as soon as
* (inlen > 4).
*/
if (inlen > outlen)
{
*out = NULL;
return 0;
}
 
*out = malloc (outlen);
if (!*out)
return outlen;
 
base64_encode (in, inlen, *out, outlen);
 
return outlen - 1;
}
 
/* With this approach this file works independent of the charset used
(think EBCDIC). However, it does assume that the characters in the
Base64 alphabet (A-Za-z0-9+/) are encoded in 0..255. POSIX
1003.1-2001 require that char and unsigned char are 8-bit
quantities, though, taking care of that problem. But this may be a
potential problem on non-POSIX C99 platforms.
 
IBM C V6 for AIX mishandles "#define B64(x) ...'x'...", so use "_"
as the formal parameter rather than "x". */
#define B64(_) \
((_) == 'A' ? 0 \
: (_) == 'B' ? 1 \
: (_) == 'C' ? 2 \
: (_) == 'D' ? 3 \
: (_) == 'E' ? 4 \
: (_) == 'F' ? 5 \
: (_) == 'G' ? 6 \
: (_) == 'H' ? 7 \
: (_) == 'I' ? 8 \
: (_) == 'J' ? 9 \
: (_) == 'K' ? 10 \
: (_) == 'L' ? 11 \
: (_) == 'M' ? 12 \
: (_) == 'N' ? 13 \
: (_) == 'O' ? 14 \
: (_) == 'P' ? 15 \
: (_) == 'Q' ? 16 \
: (_) == 'R' ? 17 \
: (_) == 'S' ? 18 \
: (_) == 'T' ? 19 \
: (_) == 'U' ? 20 \
: (_) == 'V' ? 21 \
: (_) == 'W' ? 22 \
: (_) == 'X' ? 23 \
: (_) == 'Y' ? 24 \
: (_) == 'Z' ? 25 \
: (_) == 'a' ? 26 \
: (_) == 'b' ? 27 \
: (_) == 'c' ? 28 \
: (_) == 'd' ? 29 \
: (_) == 'e' ? 30 \
: (_) == 'f' ? 31 \
: (_) == 'g' ? 32 \
: (_) == 'h' ? 33 \
: (_) == 'i' ? 34 \
: (_) == 'j' ? 35 \
: (_) == 'k' ? 36 \
: (_) == 'l' ? 37 \
: (_) == 'm' ? 38 \
: (_) == 'n' ? 39 \
: (_) == 'o' ? 40 \
: (_) == 'p' ? 41 \
: (_) == 'q' ? 42 \
: (_) == 'r' ? 43 \
: (_) == 's' ? 44 \
: (_) == 't' ? 45 \
: (_) == 'u' ? 46 \
: (_) == 'v' ? 47 \
: (_) == 'w' ? 48 \
: (_) == 'x' ? 49 \
: (_) == 'y' ? 50 \
: (_) == 'z' ? 51 \
: (_) == '0' ? 52 \
: (_) == '1' ? 53 \
: (_) == '2' ? 54 \
: (_) == '3' ? 55 \
: (_) == '4' ? 56 \
: (_) == '5' ? 57 \
: (_) == '6' ? 58 \
: (_) == '7' ? 59 \
: (_) == '8' ? 60 \
: (_) == '9' ? 61 \
: (_) == '+' ? 62 \
: (_) == '/' ? 63 \
: -1)
 
static const signed char b64[0x100] = {
B64 (0), B64 (1), B64 (2), B64 (3),
B64 (4), B64 (5), B64 (6), B64 (7),
B64 (8), B64 (9), B64 (10), B64 (11),
B64 (12), B64 (13), B64 (14), B64 (15),
B64 (16), B64 (17), B64 (18), B64 (19),
B64 (20), B64 (21), B64 (22), B64 (23),
B64 (24), B64 (25), B64 (26), B64 (27),
B64 (28), B64 (29), B64 (30), B64 (31),
B64 (32), B64 (33), B64 (34), B64 (35),
B64 (36), B64 (37), B64 (38), B64 (39),
B64 (40), B64 (41), B64 (42), B64 (43),
B64 (44), B64 (45), B64 (46), B64 (47),
B64 (48), B64 (49), B64 (50), B64 (51),
B64 (52), B64 (53), B64 (54), B64 (55),
B64 (56), B64 (57), B64 (58), B64 (59),
B64 (60), B64 (61), B64 (62), B64 (63),
B64 (64), B64 (65), B64 (66), B64 (67),
B64 (68), B64 (69), B64 (70), B64 (71),
B64 (72), B64 (73), B64 (74), B64 (75),
B64 (76), B64 (77), B64 (78), B64 (79),
B64 (80), B64 (81), B64 (82), B64 (83),
B64 (84), B64 (85), B64 (86), B64 (87),
B64 (88), B64 (89), B64 (90), B64 (91),
B64 (92), B64 (93), B64 (94), B64 (95),
B64 (96), B64 (97), B64 (98), B64 (99),
B64 (100), B64 (101), B64 (102), B64 (103),
B64 (104), B64 (105), B64 (106), B64 (107),
B64 (108), B64 (109), B64 (110), B64 (111),
B64 (112), B64 (113), B64 (114), B64 (115),
B64 (116), B64 (117), B64 (118), B64 (119),
B64 (120), B64 (121), B64 (122), B64 (123),
B64 (124), B64 (125), B64 (126), B64 (127),
B64 (128), B64 (129), B64 (130), B64 (131),
B64 (132), B64 (133), B64 (134), B64 (135),
B64 (136), B64 (137), B64 (138), B64 (139),
B64 (140), B64 (141), B64 (142), B64 (143),
B64 (144), B64 (145), B64 (146), B64 (147),
B64 (148), B64 (149), B64 (150), B64 (151),
B64 (152), B64 (153), B64 (154), B64 (155),
B64 (156), B64 (157), B64 (158), B64 (159),
B64 (160), B64 (161), B64 (162), B64 (163),
B64 (164), B64 (165), B64 (166), B64 (167),
B64 (168), B64 (169), B64 (170), B64 (171),
B64 (172), B64 (173), B64 (174), B64 (175),
B64 (176), B64 (177), B64 (178), B64 (179),
B64 (180), B64 (181), B64 (182), B64 (183),
B64 (184), B64 (185), B64 (186), B64 (187),
B64 (188), B64 (189), B64 (190), B64 (191),
B64 (192), B64 (193), B64 (194), B64 (195),
B64 (196), B64 (197), B64 (198), B64 (199),
B64 (200), B64 (201), B64 (202), B64 (203),
B64 (204), B64 (205), B64 (206), B64 (207),
B64 (208), B64 (209), B64 (210), B64 (211),
B64 (212), B64 (213), B64 (214), B64 (215),
B64 (216), B64 (217), B64 (218), B64 (219),
B64 (220), B64 (221), B64 (222), B64 (223),
B64 (224), B64 (225), B64 (226), B64 (227),
B64 (228), B64 (229), B64 (230), B64 (231),
B64 (232), B64 (233), B64 (234), B64 (235),
B64 (236), B64 (237), B64 (238), B64 (239),
B64 (240), B64 (241), B64 (242), B64 (243),
B64 (244), B64 (245), B64 (246), B64 (247),
B64 (248), B64 (249), B64 (250), B64 (251),
B64 (252), B64 (253), B64 (254), B64 (255)
};
 
#if UCHAR_MAX == 255
# define uchar_in_range(c) true
#else
# define uchar_in_range(c) ((c) <= 255)
#endif
 
/* Return true if CH is a character from the Base64 alphabet, and
false otherwise. Note that '=' is padding and not considered to be
part of the alphabet. */
bool
isbase64 (char ch)
{
return uchar_in_range (to_uchar (ch)) && 0 <= b64[to_uchar (ch)];
}
 
/* Decode base64 encoded input array IN of length INLEN to output
array OUT that can hold *OUTLEN bytes. Return true if decoding was
successful, i.e. if the input was valid base64 data, false
otherwise. If *OUTLEN is too small, as many bytes as possible will
be written to OUT. On return, *OUTLEN holds the length of decoded
bytes in OUT. Note that as soon as any non-alphabet characters are
encountered, decoding is stopped and false is returned. This means
that, when applicable, you must remove any line terminators that is
part of the data stream before calling this function. */
bool
base64_decode (const char * in, size_t inlen,
char * out, size_t *outlen)
{
size_t outleft = *outlen;
 
while (inlen >= 2)
{
if (!isbase64 (in[0]) || !isbase64 (in[1]))
break;
 
if (outleft)
{
*out++ = ((b64[to_uchar (in[0])] << 2)
| (b64[to_uchar (in[1])] >> 4));
outleft--;
}
 
if (inlen == 2)
break;
 
if (in[2] == '=')
{
if (inlen != 4)
break;
 
if (in[3] != '=')
break;
 
}
else
{
if (!isbase64 (in[2]))
break;
 
if (outleft)
{
*out++ = (((b64[to_uchar (in[1])] << 4) & 0xf0)
| (b64[to_uchar (in[2])] >> 2));
outleft--;
}
 
if (inlen == 3)
break;
 
if (in[3] == '=')
{
if (inlen != 4)
break;
}
else
{
if (!isbase64 (in[3]))
break;
 
if (outleft)
{
*out++ = (((b64[to_uchar (in[2])] << 6) & 0xc0)
| b64[to_uchar (in[3])]);
outleft--;
}
}
}
 
in += 4;
inlen -= 4;
}
 
*outlen -= outleft;
 
if (inlen != 0)
return false;
 
return true;
}
 
/* Allocate an output buffer in *OUT, and decode the base64 encoded
data stored in IN of size INLEN to the *OUT buffer. On return, the
size of the decoded data is stored in *OUTLEN. OUTLEN may be NULL,
if the caller is not interested in the decoded length. *OUT may be
NULL to indicate an out of memory error, in which case *OUTLEN
contains the size of the memory block needed. The function returns
true on successful decoding and memory allocation errors. (Use the
*OUT and *OUTLEN parameters to differentiate between successful
decoding and memory error.) The function returns false if the
input was invalid, in which case *OUT is NULL and *OUTLEN is
undefined. */
bool
base64_decode_alloc (const char *in, size_t inlen, char **out,
size_t *outlen)
{
/* This may allocate a few bytes too much, depending on input,
but it's not worth the extra CPU time to compute the exact amount.
The exact amount is 3 * inlen / 4, minus 1 if the input ends
with "=" and minus another 1 if the input ends with "==".
Dividing before multiplying avoids the possibility of overflow. */
size_t needlen = 3 * (inlen / 4) + 2;
 
*out = malloc (needlen);
if (!*out)
return true;
 
if (!base64_decode (in, inlen, *out, &needlen))
{
free (*out);
*out = NULL;
return false;
}
 
if (outlen)
*outlen = needlen;
 
return true;
}
 
#ifdef TEST_RIG
#include <stdio.h>
int main(int argc, char *argv[])
{
char *out = malloc(strlen(argv[1]));
size_t outz;
fprintf(stderr, "base64_decode output: %d\n",
base64_decode(argv[1], strlen(argv[1]), out, &outz));
fprintf(stderr, "bytes decoded: %d\n", outz);
fwrite(out, outz, 1, stdout);
return 0;
}
#endif
/contrib/network/netsurf/netsurf/utils/base64.h
0,0 → 1,45
/* base64.h -- Encode binary data using printable characters.
Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
Written by Simon Josefsson.
 
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
 
#ifndef BASE64_H
# define BASE64_H
 
/* Get size_t. */
# include <stddef.h>
 
/* Get bool. */
# include <stdbool.h>
 
/* This uses that the expression (n+(k-1))/k means the smallest
integer >= n/k, i.e., the ceiling of n/k. */
# define BASE64_LENGTH(inlen) ((((inlen) + 2) / 3) * 4)
 
extern bool isbase64 (char ch);
 
extern void base64_encode (const char * in, size_t inlen,
char * out, size_t outlen);
 
extern size_t base64_encode_alloc (const char *in, size_t inlen, char **out);
 
extern bool base64_decode (const char * in, size_t inlen,
char * out, size_t *outlen);
 
extern bool base64_decode_alloc (const char *in, size_t inlen,
char **out, size_t *outlen);
 
#endif /* BASE64_H */
/contrib/network/netsurf/netsurf/utils/config.h
0,0 → 1,120
/*
* Copyright 2003-7 John M Bell <jmb202@ecs.soton.ac.uk>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
#ifndef _NETSURF_UTILS_CONFIG_H_
#define _NETSURF_UTILS_CONFIG_H_
 
#include <stddef.h>
#include <dirent.h>
 
/* Try to detect which features the target OS supports */
 
#if (defined(_GNU_SOURCE) && !defined(__APPLE__) || defined(__HAIKU__))
#define HAVE_STRNDUP
#else
#undef HAVE_STRNDUP
char *strndup(const char *s, size_t n);
#endif
 
#if (defined(_GNU_SOURCE) || defined(__APPLE__) || defined(__HAIKU__))
#define HAVE_STRCASESTR
#else
#undef HAVE_STRCASESTR
char *strcasestr(const char *haystack, const char *needle);
#endif
 
typedef signed char int8_t;
typedef signed short int16_t;
typedef signed int int32_t;
 
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
 
 
 
/* For some reason, UnixLib defines this unconditionally.
* Assume we're using UnixLib if building for RISC OS. */
#if ((defined(_GNU_SOURCE) && !defined(__APPLE__)) || defined(riscos))
#define HAVE_STRCHRNUL
#else
#undef HAVE_STRCHRNUL
char *strchrnul(const char *s, int c);
#endif
 
#define HAVE_INETATON
#if (defined(_WIN32))
#undef HAVE_INETATON
#include <winsock2.h>
#define EAFNOSUPPORT WSAEAFNOSUPPORT
int inet_aton(const char *cp, struct in_addr *inp);
#else
#include <netinet/in.h>
#include <arpa/inet.h>
#endif
 
#define HAVE_INETPTON
#if (defined(_WIN32))
#undef HAVE_INETPTON
int inet_pton(int af, const char *src, void *dst);
#endif
 
#define HAVE_UTSNAME
#if (defined(_WIN32))
#undef HAVE_UTSNAME
#endif
 
#define HAVE_REALPATH
#if (defined(_WIN32))
#undef HAVE_REALPATH
char *realpath(const char *path, char *resolved_path);
#endif
 
#define HAVE_MKDIR
#if (defined(_WIN32))
#undef HAVE_MKDIR
#endif
 
#define HAVE_SIGPIPE
//#if (defined(_WIN32))
#undef HAVE_SIGPIPE
//#endif
 
#define HAVE_STDOUT
#if (defined(_WIN32))
#undef HAVE_STDOUT
#endif
 
//#define HAVE_MMAP
//#if (defined(_WIN32) || defined(riscos) || defined(__HAIKU__) || defined(__BEOS__) || defined(__amigaos4__) || defined(__AMIGA__) || defined(__MINT__))
#undef HAVE_MMAP
//#endif
 
/* This section toggles build options on and off.
* Simply undefine a symbol to turn the relevant feature off.
*
* IF ADDING A FEATURE HERE, ADD IT TO Docs/Doxyfile's "PREDEFINED" DEFINITION AS WELL.
*/
 
/* Platform specific features */
#include <inttypes.h>
 
/* gtk */
#define NO_IPV6
 
#endif
/contrib/network/netsurf/netsurf/utils/container.c
0,0 → 1,726
/*
* Copyright 2006 Rob Kendrick <rjek@rjek.com>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
/* To build a stand-alone command-line utility to create and dismantal
* these theme files, build this thusly:
*
* gcc -I../ -DNSTHEME -o themetool container.c
*
* [needs a c99 compiler]
*
* then for instance to create a theme file called mythemefilename
* ./themetool --verbose --create -n"My theme name" mythemefilename\
* --author "Myname" /path/to/directory/containing/theme/files/
*/
 
/** \file
* Container format handling for themes etc. */
 
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <sys/stat.h>
#include <arpa/inet.h>
#include "utils/config.h"
#include "utils/container.h"
#include "utils/log.h"
#include "utils/messages.h"
#include "utils/utils.h"
 
#ifdef WITH_MMAP
#include <sys/mman.h>
#endif
 
#ifdef NSTHEME
bool verbose_log = true;
#endif
 
struct container_dirent {
unsigned char filename[64];
u_int32_t startoffset;
u_int32_t len;
u_int32_t flags1;
u_int32_t flags2;
};
 
struct container_header {
u_int32_t magic; /* 0x4d54534e little endian */
u_int32_t parser;
unsigned char name[32];
unsigned char author[64];
u_int32_t diroffset;
};
 
struct container_ctx {
FILE *fh;
bool creating;
bool processed;
struct container_header header;
unsigned int entries;
unsigned char *data;
struct container_dirent *directory;
};
 
inline static size_t container_filelen(FILE *fd)
{
long o = ftell(fd);
long a;
 
fseek(fd, 0, SEEK_END);
a = ftell(fd);
fseek(fd, o, SEEK_SET);
if (a == -1) {
LOG(("could not ascertain size of file in theme container; omitting"));
return 0;
}
if (((unsigned long) a) > SIZE_MAX) {
LOG(("overlarge file in theme container; possible truncation"));
return SIZE_MAX;
}
return (size_t) a;
}
 
static void container_add_to_dir(struct container_ctx *ctx,
const unsigned char *entryname,
const u_int32_t offset,
const u_int32_t length)
{
struct container_dirent *temp;
temp = realloc(ctx->directory, ctx->entries *
sizeof(struct container_dirent));
if (temp == NULL) {
printf("error adding entry for %s to theme container\n", entryname);
return;
}
ctx->entries += 1;
ctx->directory = temp;
 
strncpy((char *)ctx->directory[ctx->entries - 1].filename,
(char *)entryname, sizeof(ctx->directory[
ctx->entries - 1].filename));
ctx->directory[ctx->entries - 1].startoffset = offset;
ctx->directory[ctx->entries - 1].len = length;
ctx->directory[ctx->entries - 1].flags1 = 0;
ctx->directory[ctx->entries - 1].flags2 = 0;
}
 
struct container_ctx *container_open(const char *filename)
{
size_t val;
struct container_ctx *ctx = calloc(sizeof(struct container_ctx), 1);
 
ctx->fh = fopen(filename, "rb");
 
if (ctx->fh == NULL) {
free(ctx);
return NULL;
}
 
/* we don't actually load any of the data (including directory)
* until we need to, such that _get_name and _get_author are as quick
* as possible. When we have, this gets set to true.
*/
ctx->processed = false;
 
val = fread(&ctx->header.magic, 4, 1, ctx->fh);
if (val == 0)
LOG(("empty read magic"));
ctx->header.magic = ntohl(ctx->header.magic);
 
val = fread(&ctx->header.parser, 4, 1, ctx->fh);
if (val == 0)
LOG(("empty read parser"));
ctx->header.parser = ntohl(ctx->header.parser);
 
val = fread(ctx->header.name, 32, 1, ctx->fh);
if (val == 0)
LOG(("empty read name"));
val = fread(ctx->header.author, 64, 1, ctx->fh);
if (val == 0)
LOG(("empty read author"));
 
val = fread(&ctx->header.diroffset, 4, 1, ctx->fh);
if (val == 0)
LOG(("empty read diroffset"));
ctx->header.diroffset = ntohl(ctx->header.diroffset);
 
if (ctx->header.magic != 0x4e53544d || ctx->header.parser != 3) {
fclose(ctx->fh);
free(ctx);
return NULL;
}
 
return ctx;
}
 
static void container_process(struct container_ctx *ctx)
{
size_t val;
unsigned char filename[64];
u_int32_t start, len, flags1, flags2;
 
#ifdef WITH_MMAP
ctx->data = mmap(NULL, ctx->header.diroffset, PROT_READ, MAP_PRIVATE,
fileno(ctx->fh), 0);
#else
ctx->data = malloc(ctx->header.diroffset);
fseek(ctx->fh, 0, SEEK_SET);
val = fread(ctx->data, ctx->header.diroffset, 1, ctx->fh);
if (val == 0)
LOG(("empty read diroffset"));
#endif
fseek(ctx->fh, ctx->header.diroffset, SEEK_SET);
/* now work through the directory structure taking it apart into
* our structure */
#define BEREAD(x) do { val = fread(&(x), 4, 1, ctx->fh); if (val == 0)\
LOG(("empty read"));(x) = ntohl((x)); } while (0)
do {
val = fread(filename, 64, 1, ctx->fh);
if (val == 0)
LOG(("empty read filename"));
BEREAD(start);
BEREAD(len);
BEREAD(flags1);
BEREAD(flags2);
if (filename[0] != '\0')
container_add_to_dir(ctx, filename, start, len);
} while (filename[0] != '\0');
#undef BEREAD
ctx->processed = true;
}
 
static const struct container_dirent *container_lookup(
struct container_ctx *ctx,
const unsigned char *entryname)
{
unsigned int i;
 
for (i = 1; i <= ctx->entries; i++) {
struct container_dirent *e = ctx->directory + i - 1;
if (strcmp((char *)e->filename, (char *)entryname) == 0)
return e;
}
 
return NULL;
}
 
const unsigned char *container_get(struct container_ctx *ctx,
const unsigned char *entryname,
u_int32_t *size)
{
const struct container_dirent *e;
 
if (ctx->processed == false)
container_process(ctx);
 
e = container_lookup(ctx, entryname);
 
if (e == NULL)
return NULL;
 
*size = e->len;
 
return &ctx->data[e->startoffset];
}
 
const unsigned char *container_iterate(struct container_ctx *ctx, int *state)
{
struct container_dirent *e;
unsigned char *r;
 
if (ctx->processed == false)
container_process(ctx);
 
e = ctx->directory + *state;
 
r = e->filename;
 
if (r == NULL || r[0] == '\0')
r = NULL;
 
*state += 1;
 
return r;
}
 
const unsigned char *container_get_name(struct container_ctx *ctx)
{
return ctx->header.name;
}
 
const unsigned char *container_get_author(struct container_ctx *ctx)
{
return ctx->header.author;
}
 
 
static void container_write_dir(struct container_ctx *ctx)
{
size_t val;
unsigned int i;
u_int32_t tmp;
#define BEWRITE(x) do {tmp = htonl((x)); val = fwrite(&tmp, 4, 1, ctx->fh);\
if (val == 0) LOG(("empty write")); } while(0)
for (i = 1; i <= ctx->entries; i++) {
struct container_dirent *e = ctx->directory + i - 1;
val = fwrite(e->filename, 64, 1, ctx->fh);
if (val == 0)
LOG(("empty write filename"));
BEWRITE(e->startoffset);
BEWRITE(e->len);
BEWRITE(e->flags1);
BEWRITE(e->flags2);
}
#undef BEWRITE
/* empty entry signifies end of directory */
tmp = 0;
val = fwrite(&tmp, 4, 8, ctx->fh);
if (val == 0)
LOG(("empty write end"));
}
 
struct container_ctx *container_create(const char *filename,
const unsigned char *name,
const unsigned char *author)
{
size_t val;
struct container_ctx *ctx = calloc(sizeof(struct container_ctx), 1);
 
ctx->fh = fopen(filename, "wb");
 
if (ctx->fh == NULL) {
free(ctx);
return NULL;
}
 
ctx->creating = true;
ctx->entries = 0;
ctx->directory = NULL;
ctx->header.parser = htonl(3);
strncpy((char *)ctx->header.name, (char *)name, 32);
strncpy((char *)ctx->header.author, (char *)author, 64);
 
val = fwrite("NSTM", 4, 1, ctx->fh);
if (val == 0)
LOG(("empty write NSTM"));
val = fwrite(&ctx->header.parser, 4, 1, ctx->fh);
if (val == 0)
LOG(("empty write parser"));
val = fwrite(ctx->header.name, 32, 1, ctx->fh);
if (val == 0)
LOG(("empty write name"));
val = fwrite(ctx->header.author, 64, 1, ctx->fh);
if (val == 0)
LOG(("empty write author"));
 
ctx->header.diroffset = 108;
 
/* skip over the directory offset for now, and fill it in later.
* we don't know where it'll be yet!
*/
 
fseek(ctx->fh, 108, SEEK_SET);
 
return ctx;
}
 
void container_add(struct container_ctx *ctx, const unsigned char *entryname,
const unsigned char *data,
const u_int32_t datalen)
{
size_t val;
container_add_to_dir(ctx, entryname, ftell(ctx->fh), datalen);
val = fwrite(data, datalen, 1, ctx->fh);
if (val == 0)
LOG(("empty write add file"));
}
 
void container_close(struct container_ctx *ctx)
{
if (ctx->creating == true) {
size_t flen, nflen, val;
 
/* discover where the directory's going to go. */
flen = container_filelen(ctx->fh);
flen = (flen + 3) & (~3); /* round up to nearest 4 bytes */
 
/* write this location to the header */
fseek(ctx->fh, 104, SEEK_SET);
nflen = htonl(flen);
val = fwrite(&nflen, 4, 1, ctx->fh);
if (val == 0)
LOG(("empty write directory location"));
 
/* seek to where the directory will be, and write it */
fseek(ctx->fh, flen, SEEK_SET);
container_write_dir(ctx);
 
} else if (ctx->processed) {
#ifdef WITH_MMAP
munmap(ctx->data, ctx->header.diroffset);
#else
free(ctx->data);
#endif
}
 
fclose(ctx->fh);
free(ctx);
}
 
#ifdef WITH_THEME_INSTALL
 
/**
* install theme from container
* \param themefile a file containing the containerized theme
* \param dirbasename a directory basename including trailing path sep; the
* full path of the theme is then a subdirectory of that
* caller owns reference to returned string, NULL for error
*/
 
char *container_extract_theme(const char *themefile, const char *dirbasename)
{
struct stat statbuf;
struct container_ctx *cctx;
FILE *fh;
size_t val;
const unsigned char *e, *d;
char *themename, *dirname;
char path[PATH_MAX];
int state = 0;
unsigned int i;
u_int32_t flen;
 
cctx = container_open(themefile);
if (cctx == NULL) {
warn_user("FileOpenError", themefile);
return NULL;
}
themename = strdup((const char *)container_get_name(cctx));
if (themename == NULL) {
warn_user("NoMemory", 0);
container_close(cctx);
return NULL;
}
LOG(("theme name: %s", themename));
LOG(("theme author: %s", container_get_author(cctx)));
dirname = malloc(strlen(dirbasename) + strlen(themename) + 2);
if (dirname == NULL) {
warn_user(messages_get("NoMemory"), 0);
free(themename);
container_close(cctx);
return NULL;
}
strcpy(dirname, dirbasename);
strcat(dirname, themename);
if (stat(dirname, &statbuf) != -1) {
warn_user("DirectoryError", dirname);
container_close(cctx);
free(dirname);
free(themename);
return NULL;
}
mkdir(dirname, S_IRWXU);
 
for (e = container_iterate(cctx, &state), i = 0; i < cctx->entries;
e = container_iterate(cctx, &state), i++) {
LOG(("extracting %s", e));
snprintf(path, PATH_MAX, "%s/%s", dirname, e);
fh = fopen(path, "wb");
if (fh == NULL) {
warn_user("FileOpenError", (char *)e);
} else {
d = container_get(cctx, e, &flen);
val = fwrite(d, flen, 1, fh);
if (val == 0)
LOG(("empty write"));
fclose(fh);
}
}
LOG(("theme container unpacked"));
container_close(cctx);
free(dirname);
return themename;
 
}
 
#endif
 
#ifdef TEST_RIG
int main(int argc, char *argv[])
{
struct container_ctx *ctx = container_create("test.theme", "Test theme",
"Rob Kendrick");
u_int32_t size;
int state = 0;
char *n;
 
container_add(ctx, "CHEESE", "This is a test of some cheese.", sizeof("This is a test of some cheese."));
container_add(ctx, "FOO", "This is a test of some cheese.", sizeof("This is a test of some cheese."));
 
container_close(ctx);
 
ctx = container_open("test.theme");
 
printf("Theme name: %s\n", container_get_name(ctx));
printf("Theme author: %s\n", container_get_author(ctx));
 
printf("Test string: %s\n", container_get(ctx, "CHEESE", &size));
printf("Length of text: %d\n", size);
 
while ( (n = container_iterate(ctx, &state)) ) {
printf("%s\n", n);
}
 
container_close(ctx);
 
exit(0);
}
#endif
 
#ifdef NSTHEME
/* code to implement a simple container creator/extractor */
#include <getopt.h>
#include <dirent.h>
#include <errno.h>
#include <unistd.h>
 
static bool verbose = false;
 
static void show_usage(const char *argv0)
{
fprintf(stderr, "%s [options] <theme file> <directory>\n", argv0);
fprintf(stderr, " --help This text\n");
fprintf(stderr, " --create Create theme file from directory\n");
fprintf(stderr, " --extract Extract theme file into directory\n");
fprintf(stderr, " --name x Set theme's name when creating\n");
fprintf(stderr, " --author x Set theme's author when creating\n");
fprintf(stderr, " --verbose Print progress information\n");
fprintf(stderr, "\nOne and only one of --create or --extract must be specified.\n");
}
 
static void extract_theme(const char *themefile, const char *dirname)
{
struct stat statbuf;
struct container_ctx *cctx;
FILE *fh;
const unsigned char *e, *d;
char path[PATH_MAX];
int i, state = 0;
u_int32_t flen;
 
 
if (stat(dirname, &statbuf) != -1) {
fprintf(stderr, "error: directory '%s' already exists.\n",
dirname);
exit(1);
}
 
mkdir(dirname, S_IRWXU);
 
cctx = container_open(themefile);
if (cctx == NULL) {
fprintf(stderr, "error: unable to open theme file '%s'\n",
themefile);
exit(1);
}
 
if (verbose == true) {
printf("theme name: %s\n", container_get_name(cctx));
printf("theme author: %s\n", container_get_author(cctx));
}
 
for (e = container_iterate(cctx, &state), i = 0; i < cctx->entries;
e = container_iterate(cctx, &state), i++) {
if (verbose == true)
printf("extracting %s\n", e);
snprintf(path, PATH_MAX, "%s/%s", dirname, e);
fh = fopen(path, "wb");
if (fh == NULL) {
perror("warning: unable to open file for output");
} else {
d = container_get(cctx, e, &flen);
fwrite(d, flen, 1, fh);
fclose(fh);
}
}
 
container_close(cctx);
 
}
 
static void create_theme(const char *themefile, const char *dirname,
const unsigned char *name,
const unsigned char *author)
{
DIR *dir = opendir(dirname);
FILE *fh;
struct dirent *e;
struct stat statbuf;
struct container_ctx *cctx;
unsigned char *data;
char path[PATH_MAX];
size_t flen;
int t;
 
if (dir == NULL) {
perror("error: unable to open directory");
exit(1);
}
 
cctx = container_create(themefile, name, author);
 
errno = 0; /* to distinguish between end of dir and err */
 
while ((e = readdir(dir)) != NULL) {
if (strcmp(e->d_name, ".") != 0 &&
strcmp(e->d_name, "..") != 0) {
/* not the metadirs, so we want to process this. */
if (verbose == true)
printf("adding %s\n", e->d_name);
if (strlen(e->d_name) > 63) {
fprintf(stderr,
"warning: name truncated to length 63.\n");
}
 
snprintf(path, PATH_MAX, "%s/%s", dirname, e->d_name);
 
stat(path, &statbuf);
if (S_ISDIR(statbuf.st_mode)) {
fprintf(stderr,
"warning: skipping directory '%s'\n",
e->d_name);
continue;
}
 
fh = fopen(path, "rb");
if (fh == NULL) {
fprintf(stderr,
"warning: unable to open, skipping.");
} else {
flen = statbuf.st_size;
data = malloc(flen);
t = fread(data, flen, 1, fh);
fclose(fh);
container_add(cctx, (unsigned char *)e->d_name,
data, flen);
free(data);
}
}
errno = 0;
}
 
if (errno != 0) {
perror("error: couldn't enumerate directory");
closedir(dir);
container_close(cctx);
exit(1);
}
 
closedir(dir);
container_close(cctx);
}
 
int main(int argc, char *argv[])
{
static struct option l_opts[] = {
{ "help", 0, 0, 'h' },
{ "create", 0, 0, 'c' },
{ "extract", 0, 0, 'x' },
{ "name", 1, 0, 'n' },
{ "author", 1, 0, 'a' },
{ "verbose", 0, 0, 'v' },
 
{ NULL, 0, 0, 0 }
};
 
static char *s_opts = "hcxn:a:v";
int optch, optidx;
bool creating = false, extracting = false;
unsigned char name[32] = { '\0' }, author[64] = { '\0' };
char *themefile, *dirname;
 
while ((optch = getopt_long(argc, argv, s_opts, l_opts, &optidx)) != -1)
switch (optch) {
case 'h':
show_usage(argv[0]);
exit(0);
break;
case 'c':
creating = true;
break;
case 'x':
extracting = true;
break;
case 'n':
strncpy((char *)name, optarg, 31);
if (strlen(optarg) > 32)
fprintf(stderr, "warning: theme name truncated to 32 characters.\n");
break;
case 'a':
strncpy((char *)author, optarg, 63);
if (strlen(optarg) > 64)
fprintf(stderr, "warning: theme author truncated to 64 characters.\n");
break;
case 'v':
verbose = true;
break;
default:
show_usage(argv[0]);
exit(1);
break;
}
 
if (creating == extracting) {
show_usage(argv[0]);
exit(1);
}
 
if ((argc - optind) < 2) {
show_usage(argv[0]);
exit(1);
}
 
if (creating == true &&
(strlen((char *)name) == 0 || strlen((char *)author) == 0)) {
fprintf(stderr, "No theme name and/or author specified.\n");
show_usage(argv[0]);
exit(1);
}
 
themefile = strdup(argv[optind]);
dirname = strdup(argv[optind + 1]);
 
if (verbose == true)
printf("%s '%s' %s directory '%s'\n",
creating ? "creating" : "extracting", themefile,
creating ? "from" : "to", dirname);
 
if (creating) {
if (verbose == true)
printf("name = %s, author = %s\n", name, author);
create_theme(themefile, dirname, name, author);
} else {
extract_theme(themefile, dirname);
}
 
return 0;
}
#endif
/contrib/network/netsurf/netsurf/utils/container.h
0,0 → 1,53
/*
* Copyright 2006 Rob Kendrick <rjek@rjek.com>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
/** \file
* Container format handling for themes etc. */
 
#ifndef __CONTAINER_H__
#define __CONTAINER_H__
 
#include <sys/types.h>
 
struct container_ctx;
 
/* reading interface */
struct container_ctx *container_open(const char *filename);
const unsigned char *container_get(struct container_ctx *ctx,
const unsigned char *entryname,
u_int32_t *size);
const unsigned char *container_get_name(struct container_ctx *ctx);
const unsigned char *container_get_author(struct container_ctx *ctx);
const unsigned char *container_iterate(struct container_ctx *ctx,
int *state);
 
/* creating interface */
struct container_ctx *container_create(const char *filename,
const unsigned char *name,
const unsigned char *author);
void container_add(struct container_ctx *ctx, const unsigned char *entryname,
const unsigned char *data,
const u_int32_t datalen);
 
/* common interface */
void container_close(struct container_ctx *ctx);
 
#ifdef WITH_THEME_INSTALL
char *container_extract_theme(const char *themefile, const char *dirbasename);
#endif
#endif /* __CONTAINER_H__ */
/contrib/network/netsurf/netsurf/utils/corestrings.c
0,0 → 1,731
/*
* Copyright 2012 Michael Drake <tlsa@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
/** \file
* Useful interned string pointers (implementation).
*/
 
#include <dom/dom.h>
 
#include "utils/corestrings.h"
#include "utils/utils.h"
 
/* lwc_string strings */
lwc_string *corestring_lwc_a;
lwc_string *corestring_lwc_abscenter;
lwc_string *corestring_lwc_absmiddle;
lwc_string *corestring_lwc_align;
lwc_string *corestring_lwc_applet;
lwc_string *corestring_lwc_base;
lwc_string *corestring_lwc_baseline;
lwc_string *corestring_lwc_body;
lwc_string *corestring_lwc_bottom;
lwc_string *corestring_lwc_button;
lwc_string *corestring_lwc_caption;
lwc_string *corestring_lwc_center;
lwc_string *corestring_lwc_checkbox;
lwc_string *corestring_lwc_circle;
lwc_string *corestring_lwc_col;
lwc_string *corestring_lwc_default;
lwc_string *corestring_lwc_div;
lwc_string *corestring_lwc_embed;
lwc_string *corestring_lwc_file;
lwc_string *corestring_lwc_font;
lwc_string *corestring_lwc_frame;
lwc_string *corestring_lwc_frameset;
lwc_string *corestring_lwc_h1;
lwc_string *corestring_lwc_h2;
lwc_string *corestring_lwc_h3;
lwc_string *corestring_lwc_h4;
lwc_string *corestring_lwc_h5;
lwc_string *corestring_lwc_h6;
lwc_string *corestring_lwc_head;
lwc_string *corestring_lwc_hidden;
lwc_string *corestring_lwc_hr;
lwc_string *corestring_lwc_html;
lwc_string *corestring_lwc_https;
lwc_string *corestring_lwc_iframe;
lwc_string *corestring_lwc_image;
lwc_string *corestring_lwc_img;
lwc_string *corestring_lwc_input;
lwc_string *corestring_lwc_justify;
lwc_string *corestring_lwc_left;
lwc_string *corestring_lwc_li;
lwc_string *corestring_lwc_link;
lwc_string *corestring_lwc_meta;
lwc_string *corestring_lwc_middle;
lwc_string *corestring_lwc_multipart_form_data;
lwc_string *corestring_lwc_no;
lwc_string *corestring_lwc_noscript;
lwc_string *corestring_lwc_object;
lwc_string *corestring_lwc_optgroup;
lwc_string *corestring_lwc_option;
lwc_string *corestring_lwc_p;
lwc_string *corestring_lwc_param;
lwc_string *corestring_lwc_password;
lwc_string *corestring_lwc_poly;
lwc_string *corestring_lwc_polygon;
lwc_string *corestring_lwc_post;
lwc_string *corestring_lwc_radio;
lwc_string *corestring_lwc_rect;
lwc_string *corestring_lwc_rectangle;
lwc_string *corestring_lwc_refresh;
lwc_string *corestring_lwc_reset;
lwc_string *corestring_lwc_right;
lwc_string *corestring_lwc_search;
lwc_string *corestring_lwc_select;
lwc_string *corestring_lwc_src;
lwc_string *corestring_lwc_style;
lwc_string *corestring_lwc_submit;
lwc_string *corestring_lwc_table;
lwc_string *corestring_lwc_tbody;
lwc_string *corestring_lwc_td;
lwc_string *corestring_lwc_text;
lwc_string *corestring_lwc_textarea;
lwc_string *corestring_lwc_texttop;
lwc_string *corestring_lwc_text_css;
lwc_string *corestring_lwc_tfoot;
lwc_string *corestring_lwc_th;
lwc_string *corestring_lwc_thead;
lwc_string *corestring_lwc_title;
lwc_string *corestring_lwc_top;
lwc_string *corestring_lwc_tr;
lwc_string *corestring_lwc_ul;
lwc_string *corestring_lwc_url;
lwc_string *corestring_lwc_yes;
lwc_string *corestring_lwc__blank;
lwc_string *corestring_lwc__parent;
lwc_string *corestring_lwc__self;
lwc_string *corestring_lwc__top;
 
/* dom_string strings */
dom_string *corestring_dom_a;
dom_string *corestring_dom_abort;
dom_string *corestring_dom_afterprint;
dom_string *corestring_dom_align;
dom_string *corestring_dom_area;
dom_string *corestring_dom_async;
dom_string *corestring_dom_background;
dom_string *corestring_dom_beforeprint;
dom_string *corestring_dom_beforeunload;
dom_string *corestring_dom_bgcolor;
dom_string *corestring_dom_blur;
dom_string *corestring_dom_border;
dom_string *corestring_dom_bordercolor;
dom_string *corestring_dom_cancel;
dom_string *corestring_dom_canplay;
dom_string *corestring_dom_canplaythrough;
dom_string *corestring_dom_cellpadding;
dom_string *corestring_dom_cellspacing;
dom_string *corestring_dom_change;
dom_string *corestring_dom_charset;
dom_string *corestring_dom_class;
dom_string *corestring_dom_click;
dom_string *corestring_dom_close;
dom_string *corestring_dom_color;
dom_string *corestring_dom_cols;
dom_string *corestring_dom_content;
dom_string *corestring_dom_contextmenu;
dom_string *corestring_dom_coords;
dom_string *corestring_dom_cuechange;
dom_string *corestring_dom_dblclick;
dom_string *corestring_dom_defer;
dom_string *corestring_dom_drag;
dom_string *corestring_dom_dragend;
dom_string *corestring_dom_dragenter;
dom_string *corestring_dom_dragleave;
dom_string *corestring_dom_dragover;
dom_string *corestring_dom_dragstart;
dom_string *corestring_dom_drop;
dom_string *corestring_dom_durationchange;
dom_string *corestring_dom_emptied;
dom_string *corestring_dom_ended;
dom_string *corestring_dom_error;
dom_string *corestring_dom_focus;
dom_string *corestring_dom_hashchange;
dom_string *corestring_dom_height;
dom_string *corestring_dom_href;
dom_string *corestring_dom_hreflang;
dom_string *corestring_dom_hspace;
dom_string *corestring_dom_http_equiv;
dom_string *corestring_dom_id;
dom_string *corestring_dom_input;
dom_string *corestring_dom_invalid;
dom_string *corestring_dom_keydown;
dom_string *corestring_dom_keypress;
dom_string *corestring_dom_keyup;
dom_string *corestring_dom_link;
dom_string *corestring_dom_load;
dom_string *corestring_dom_loadeddata;
dom_string *corestring_dom_loadedmetadata;
dom_string *corestring_dom_loadstart;
dom_string *corestring_dom_map;
dom_string *corestring_dom_media;
dom_string *corestring_dom_message;
dom_string *corestring_dom_mousedown;
dom_string *corestring_dom_mousemove;
dom_string *corestring_dom_mouseout;
dom_string *corestring_dom_mouseover;
dom_string *corestring_dom_mouseup;
dom_string *corestring_dom_mousewheel;
dom_string *corestring_dom_name;
dom_string *corestring_dom_nohref;
dom_string *corestring_dom_offline;
dom_string *corestring_dom_online;
dom_string *corestring_dom_pagehide;
dom_string *corestring_dom_pageshow;
dom_string *corestring_dom_pause;
dom_string *corestring_dom_play;
dom_string *corestring_dom_playing;
dom_string *corestring_dom_popstate;
dom_string *corestring_dom_progress;
dom_string *corestring_dom_ratechange;
dom_string *corestring_dom_readystatechange;
dom_string *corestring_dom_rect;
dom_string *corestring_dom_rel;
dom_string *corestring_dom_reset;
dom_string *corestring_dom_resize;
dom_string *corestring_dom_rows;
dom_string *corestring_dom_scroll;
dom_string *corestring_dom_seeked;
dom_string *corestring_dom_seeking;
dom_string *corestring_dom_select;
dom_string *corestring_dom_shape;
dom_string *corestring_dom_show;
dom_string *corestring_dom_size;
dom_string *corestring_dom_sizes;
dom_string *corestring_dom_src;
dom_string *corestring_dom_stalled;
dom_string *corestring_dom_storage;
dom_string *corestring_dom_submit;
dom_string *corestring_dom_suspend;
dom_string *corestring_dom_target;
dom_string *corestring_dom_text;
dom_string *corestring_dom_text_javascript;
dom_string *corestring_dom_timeupdate;
dom_string *corestring_dom_type;
dom_string *corestring_dom_unload;
dom_string *corestring_dom_valign;
dom_string *corestring_dom_vlink;
dom_string *corestring_dom_volumechange;
dom_string *corestring_dom_vspace;
dom_string *corestring_dom_waiting;
dom_string *corestring_dom_width;
 
 
/*
* Free the core strings
*/
void corestrings_fini(void)
{
#define CSS_LWC_STRING_UNREF(NAME) \
do { \
if (corestring_lwc_##NAME != NULL) { \
lwc_string_unref(corestring_lwc_##NAME); \
corestring_lwc_##NAME = NULL; \
} \
} while (0)
 
CSS_LWC_STRING_UNREF(a);
CSS_LWC_STRING_UNREF(abscenter);
CSS_LWC_STRING_UNREF(absmiddle);
CSS_LWC_STRING_UNREF(align);
CSS_LWC_STRING_UNREF(applet);
CSS_LWC_STRING_UNREF(base);
CSS_LWC_STRING_UNREF(baseline);
CSS_LWC_STRING_UNREF(body);
CSS_LWC_STRING_UNREF(bottom);
CSS_LWC_STRING_UNREF(button);
CSS_LWC_STRING_UNREF(caption);
CSS_LWC_STRING_UNREF(center);
CSS_LWC_STRING_UNREF(checkbox);
CSS_LWC_STRING_UNREF(circle);
CSS_LWC_STRING_UNREF(col);
CSS_LWC_STRING_UNREF(default);
CSS_LWC_STRING_UNREF(div);
CSS_LWC_STRING_UNREF(embed);
CSS_LWC_STRING_UNREF(file);
CSS_LWC_STRING_UNREF(font);
CSS_LWC_STRING_UNREF(frame);
CSS_LWC_STRING_UNREF(frameset);
CSS_LWC_STRING_UNREF(h1);
CSS_LWC_STRING_UNREF(h2);
CSS_LWC_STRING_UNREF(h3);
CSS_LWC_STRING_UNREF(h4);
CSS_LWC_STRING_UNREF(h5);
CSS_LWC_STRING_UNREF(h6);
CSS_LWC_STRING_UNREF(head);
CSS_LWC_STRING_UNREF(hidden);
CSS_LWC_STRING_UNREF(hr);
CSS_LWC_STRING_UNREF(html);
CSS_LWC_STRING_UNREF(https);
CSS_LWC_STRING_UNREF(iframe);
CSS_LWC_STRING_UNREF(image);
CSS_LWC_STRING_UNREF(img);
CSS_LWC_STRING_UNREF(input);
CSS_LWC_STRING_UNREF(justify);
CSS_LWC_STRING_UNREF(left);
CSS_LWC_STRING_UNREF(li);
CSS_LWC_STRING_UNREF(link);
CSS_LWC_STRING_UNREF(meta);
CSS_LWC_STRING_UNREF(middle);
CSS_LWC_STRING_UNREF(multipart_form_data);
CSS_LWC_STRING_UNREF(no);
CSS_LWC_STRING_UNREF(noscript);
CSS_LWC_STRING_UNREF(object);
CSS_LWC_STRING_UNREF(optgroup);
CSS_LWC_STRING_UNREF(option);
CSS_LWC_STRING_UNREF(p);
CSS_LWC_STRING_UNREF(param);
CSS_LWC_STRING_UNREF(password);
CSS_LWC_STRING_UNREF(poly);
CSS_LWC_STRING_UNREF(polygon);
CSS_LWC_STRING_UNREF(post);
CSS_LWC_STRING_UNREF(radio);
CSS_LWC_STRING_UNREF(rect);
CSS_LWC_STRING_UNREF(rectangle);
CSS_LWC_STRING_UNREF(refresh);
CSS_LWC_STRING_UNREF(reset);
CSS_LWC_STRING_UNREF(right);
CSS_LWC_STRING_UNREF(search);
CSS_LWC_STRING_UNREF(select);
CSS_LWC_STRING_UNREF(src);
CSS_LWC_STRING_UNREF(style);
CSS_LWC_STRING_UNREF(submit);
CSS_LWC_STRING_UNREF(table);
CSS_LWC_STRING_UNREF(tbody);
CSS_LWC_STRING_UNREF(td);
CSS_LWC_STRING_UNREF(text);
CSS_LWC_STRING_UNREF(textarea);
CSS_LWC_STRING_UNREF(texttop);
CSS_LWC_STRING_UNREF(text_css);
CSS_LWC_STRING_UNREF(tfoot);
CSS_LWC_STRING_UNREF(th);
CSS_LWC_STRING_UNREF(thead);
CSS_LWC_STRING_UNREF(title);
CSS_LWC_STRING_UNREF(top);
CSS_LWC_STRING_UNREF(tr);
CSS_LWC_STRING_UNREF(ul);
CSS_LWC_STRING_UNREF(url);
CSS_LWC_STRING_UNREF(yes);
CSS_LWC_STRING_UNREF(_blank);
CSS_LWC_STRING_UNREF(_parent);
CSS_LWC_STRING_UNREF(_self);
CSS_LWC_STRING_UNREF(_top);
 
#undef CSS_LWC_STRING_UNREF
 
#define CSS_DOM_STRING_UNREF(NAME) \
do { \
if (corestring_dom_##NAME != NULL) { \
dom_string_unref(corestring_dom_##NAME); \
corestring_dom_##NAME = NULL; \
} \
} while (0)
 
CSS_DOM_STRING_UNREF(a);
CSS_DOM_STRING_UNREF(abort);
CSS_DOM_STRING_UNREF(afterprint);
CSS_DOM_STRING_UNREF(align);
CSS_DOM_STRING_UNREF(area);
CSS_DOM_STRING_UNREF(async);
CSS_DOM_STRING_UNREF(background);
CSS_DOM_STRING_UNREF(beforeprint);
CSS_DOM_STRING_UNREF(beforeunload);
CSS_DOM_STRING_UNREF(bgcolor);
CSS_DOM_STRING_UNREF(blur);
CSS_DOM_STRING_UNREF(border);
CSS_DOM_STRING_UNREF(bordercolor);
CSS_DOM_STRING_UNREF(cancel);
CSS_DOM_STRING_UNREF(canplay);
CSS_DOM_STRING_UNREF(canplaythrough);
CSS_DOM_STRING_UNREF(cellpadding);
CSS_DOM_STRING_UNREF(cellspacing);
CSS_DOM_STRING_UNREF(change);
CSS_DOM_STRING_UNREF(charset);
CSS_DOM_STRING_UNREF(class);
CSS_DOM_STRING_UNREF(click);
CSS_DOM_STRING_UNREF(close);
CSS_DOM_STRING_UNREF(color);
CSS_DOM_STRING_UNREF(cols);
CSS_DOM_STRING_UNREF(content);
CSS_DOM_STRING_UNREF(contextmenu);
CSS_DOM_STRING_UNREF(coords);
CSS_DOM_STRING_UNREF(cuechange);
CSS_DOM_STRING_UNREF(dblclick);
CSS_DOM_STRING_UNREF(defer);
CSS_DOM_STRING_UNREF(drag);
CSS_DOM_STRING_UNREF(dragend);
CSS_DOM_STRING_UNREF(dragenter);
CSS_DOM_STRING_UNREF(dragleave);
CSS_DOM_STRING_UNREF(dragover);
CSS_DOM_STRING_UNREF(dragstart);
CSS_DOM_STRING_UNREF(drop);
CSS_DOM_STRING_UNREF(durationchange);
CSS_DOM_STRING_UNREF(emptied);
CSS_DOM_STRING_UNREF(ended);
CSS_DOM_STRING_UNREF(error);
CSS_DOM_STRING_UNREF(focus);
CSS_DOM_STRING_UNREF(hashchange);
CSS_DOM_STRING_UNREF(height);
CSS_DOM_STRING_UNREF(href);
CSS_DOM_STRING_UNREF(hreflang);
CSS_DOM_STRING_UNREF(hspace);
CSS_DOM_STRING_UNREF(http_equiv);
CSS_DOM_STRING_UNREF(id);
CSS_DOM_STRING_UNREF(input);
CSS_DOM_STRING_UNREF(invalid);
CSS_DOM_STRING_UNREF(keydown);
CSS_DOM_STRING_UNREF(keypress);
CSS_DOM_STRING_UNREF(keyup);
CSS_DOM_STRING_UNREF(link);
CSS_DOM_STRING_UNREF(load);
CSS_DOM_STRING_UNREF(loadeddata);
CSS_DOM_STRING_UNREF(loadedmetadata);
CSS_DOM_STRING_UNREF(loadstart);
CSS_DOM_STRING_UNREF(map);
CSS_DOM_STRING_UNREF(media);
CSS_DOM_STRING_UNREF(message);
CSS_DOM_STRING_UNREF(mousedown);
CSS_DOM_STRING_UNREF(mousemove);
CSS_DOM_STRING_UNREF(mouseout);
CSS_DOM_STRING_UNREF(mouseover);
CSS_DOM_STRING_UNREF(mouseup);
CSS_DOM_STRING_UNREF(mousewheel);
CSS_DOM_STRING_UNREF(name);
CSS_DOM_STRING_UNREF(nohref);
CSS_DOM_STRING_UNREF(offline);
CSS_DOM_STRING_UNREF(online);
CSS_DOM_STRING_UNREF(pagehide);
CSS_DOM_STRING_UNREF(pageshow);
CSS_DOM_STRING_UNREF(pause);
CSS_DOM_STRING_UNREF(play);
CSS_DOM_STRING_UNREF(playing);
CSS_DOM_STRING_UNREF(popstate);
CSS_DOM_STRING_UNREF(progress);
CSS_DOM_STRING_UNREF(ratechange);
CSS_DOM_STRING_UNREF(readystatechange);
CSS_DOM_STRING_UNREF(rect);
CSS_DOM_STRING_UNREF(rel);
CSS_DOM_STRING_UNREF(reset);
CSS_DOM_STRING_UNREF(resize);
CSS_DOM_STRING_UNREF(rows);
CSS_DOM_STRING_UNREF(scroll);
CSS_DOM_STRING_UNREF(seeked);
CSS_DOM_STRING_UNREF(seeking);
CSS_DOM_STRING_UNREF(select);
CSS_DOM_STRING_UNREF(shape);
CSS_DOM_STRING_UNREF(show);
CSS_DOM_STRING_UNREF(size);
CSS_DOM_STRING_UNREF(sizes);
CSS_DOM_STRING_UNREF(src);
CSS_DOM_STRING_UNREF(stalled);
CSS_DOM_STRING_UNREF(storage);
CSS_DOM_STRING_UNREF(submit);
CSS_DOM_STRING_UNREF(suspend);
CSS_DOM_STRING_UNREF(target);
CSS_DOM_STRING_UNREF(text);
CSS_DOM_STRING_UNREF(text_javascript);
CSS_DOM_STRING_UNREF(timeupdate);
CSS_DOM_STRING_UNREF(type);
CSS_DOM_STRING_UNREF(unload);
CSS_DOM_STRING_UNREF(valign);
CSS_DOM_STRING_UNREF(vlink);
CSS_DOM_STRING_UNREF(volumechange);
CSS_DOM_STRING_UNREF(vspace);
CSS_DOM_STRING_UNREF(waiting);
CSS_DOM_STRING_UNREF(width);
#undef CSS_DOM_STRING_UNREF
}
 
 
/*
* Create the core strings
*/
nserror corestrings_init(void)
{
lwc_error lerror;
nserror error;
dom_exception exc;
 
#define CSS_LWC_STRING_INTERN(NAME) \
do { \
lerror = lwc_intern_string( \
(const char *)#NAME, \
sizeof(#NAME) - 1, \
&corestring_lwc_##NAME ); \
if ((lerror != lwc_error_ok) || \
(corestring_lwc_##NAME == NULL)) { \
error = NSERROR_NOMEM; \
goto error; \
} \
} while(0)
 
CSS_LWC_STRING_INTERN(a);
CSS_LWC_STRING_INTERN(abscenter);
CSS_LWC_STRING_INTERN(absmiddle);
CSS_LWC_STRING_INTERN(align);
CSS_LWC_STRING_INTERN(applet);
CSS_LWC_STRING_INTERN(base);
CSS_LWC_STRING_INTERN(baseline);
CSS_LWC_STRING_INTERN(body);
CSS_LWC_STRING_INTERN(bottom);
CSS_LWC_STRING_INTERN(button);
CSS_LWC_STRING_INTERN(caption);
CSS_LWC_STRING_INTERN(center);
CSS_LWC_STRING_INTERN(checkbox);
CSS_LWC_STRING_INTERN(circle);
CSS_LWC_STRING_INTERN(col);
CSS_LWC_STRING_INTERN(default);
CSS_LWC_STRING_INTERN(div);
CSS_LWC_STRING_INTERN(embed);
CSS_LWC_STRING_INTERN(file);
CSS_LWC_STRING_INTERN(font);
CSS_LWC_STRING_INTERN(frame);
CSS_LWC_STRING_INTERN(frameset);
CSS_LWC_STRING_INTERN(h1);
CSS_LWC_STRING_INTERN(h2);
CSS_LWC_STRING_INTERN(h3);
CSS_LWC_STRING_INTERN(h4);
CSS_LWC_STRING_INTERN(h5);
CSS_LWC_STRING_INTERN(h6);
CSS_LWC_STRING_INTERN(head);
CSS_LWC_STRING_INTERN(hidden);
CSS_LWC_STRING_INTERN(hr);
CSS_LWC_STRING_INTERN(html);
CSS_LWC_STRING_INTERN(https);
CSS_LWC_STRING_INTERN(iframe);
CSS_LWC_STRING_INTERN(image);
CSS_LWC_STRING_INTERN(img);
CSS_LWC_STRING_INTERN(input);
CSS_LWC_STRING_INTERN(justify);
CSS_LWC_STRING_INTERN(left);
CSS_LWC_STRING_INTERN(li);
CSS_LWC_STRING_INTERN(link);
CSS_LWC_STRING_INTERN(meta);
CSS_LWC_STRING_INTERN(middle);
CSS_LWC_STRING_INTERN(no);
CSS_LWC_STRING_INTERN(noscript);
CSS_LWC_STRING_INTERN(object);
CSS_LWC_STRING_INTERN(optgroup);
CSS_LWC_STRING_INTERN(option);
CSS_LWC_STRING_INTERN(p);
CSS_LWC_STRING_INTERN(param);
CSS_LWC_STRING_INTERN(password);
CSS_LWC_STRING_INTERN(poly);
CSS_LWC_STRING_INTERN(polygon);
CSS_LWC_STRING_INTERN(post);
CSS_LWC_STRING_INTERN(radio);
CSS_LWC_STRING_INTERN(rect);
CSS_LWC_STRING_INTERN(rectangle);
CSS_LWC_STRING_INTERN(refresh);
CSS_LWC_STRING_INTERN(reset);
CSS_LWC_STRING_INTERN(right);
CSS_LWC_STRING_INTERN(search);
CSS_LWC_STRING_INTERN(select);
CSS_LWC_STRING_INTERN(src);
CSS_LWC_STRING_INTERN(style);
CSS_LWC_STRING_INTERN(submit);
CSS_LWC_STRING_INTERN(table);
CSS_LWC_STRING_INTERN(tbody);
CSS_LWC_STRING_INTERN(td);
CSS_LWC_STRING_INTERN(text);
CSS_LWC_STRING_INTERN(textarea);
CSS_LWC_STRING_INTERN(texttop);
CSS_LWC_STRING_INTERN(tfoot);
CSS_LWC_STRING_INTERN(th);
CSS_LWC_STRING_INTERN(thead);
CSS_LWC_STRING_INTERN(title);
CSS_LWC_STRING_INTERN(top);
CSS_LWC_STRING_INTERN(tr);
CSS_LWC_STRING_INTERN(ul);
CSS_LWC_STRING_INTERN(url);
CSS_LWC_STRING_INTERN(yes);
CSS_LWC_STRING_INTERN(_blank);
CSS_LWC_STRING_INTERN(_parent);
CSS_LWC_STRING_INTERN(_self);
CSS_LWC_STRING_INTERN(_top);
#undef CSS_LWC_STRING_INTERN
 
 
lerror = lwc_intern_string("multipart/form-data",
SLEN("multipart/form-data"),
&corestring_lwc_multipart_form_data);
if ((lerror != lwc_error_ok) ||
(corestring_lwc_multipart_form_data == NULL)) {
error = NSERROR_NOMEM;
goto error;
}
 
lerror = lwc_intern_string("text/css", SLEN("text/css"),
&corestring_lwc_text_css);
if ((lerror != lwc_error_ok) || (corestring_lwc_text_css == NULL)) {
error = NSERROR_NOMEM;
goto error;
}
 
 
#define CSS_DOM_STRING_INTERN(NAME) \
do { \
exc = dom_string_create_interned( \
(const uint8_t *)#NAME, \
sizeof(#NAME) - 1, \
&corestring_dom_##NAME ); \
if ((exc != DOM_NO_ERR) || \
(corestring_dom_##NAME == NULL)) { \
error = NSERROR_NOMEM; \
goto error; \
} \
} while(0)
 
CSS_DOM_STRING_INTERN(a);
CSS_DOM_STRING_INTERN(abort);
CSS_DOM_STRING_INTERN(afterprint);
CSS_DOM_STRING_INTERN(align);
CSS_DOM_STRING_INTERN(area);
CSS_DOM_STRING_INTERN(async);
CSS_DOM_STRING_INTERN(background);
CSS_DOM_STRING_INTERN(beforeprint);
CSS_DOM_STRING_INTERN(beforeunload);
CSS_DOM_STRING_INTERN(bgcolor);
CSS_DOM_STRING_INTERN(blur);
CSS_DOM_STRING_INTERN(border);
CSS_DOM_STRING_INTERN(bordercolor);
CSS_DOM_STRING_INTERN(cancel);
CSS_DOM_STRING_INTERN(canplay);
CSS_DOM_STRING_INTERN(canplaythrough);
CSS_DOM_STRING_INTERN(cellpadding);
CSS_DOM_STRING_INTERN(cellspacing);
CSS_DOM_STRING_INTERN(change);
CSS_DOM_STRING_INTERN(charset);
CSS_DOM_STRING_INTERN(class);
CSS_DOM_STRING_INTERN(click);
CSS_DOM_STRING_INTERN(close);
CSS_DOM_STRING_INTERN(color);
CSS_DOM_STRING_INTERN(cols);
CSS_DOM_STRING_INTERN(content);
CSS_DOM_STRING_INTERN(contextmenu);
CSS_DOM_STRING_INTERN(coords);
CSS_DOM_STRING_INTERN(cuechange);
CSS_DOM_STRING_INTERN(dblclick);
CSS_DOM_STRING_INTERN(defer);
CSS_DOM_STRING_INTERN(drag);
CSS_DOM_STRING_INTERN(dragend);
CSS_DOM_STRING_INTERN(dragenter);
CSS_DOM_STRING_INTERN(dragleave);
CSS_DOM_STRING_INTERN(dragover);
CSS_DOM_STRING_INTERN(dragstart);
CSS_DOM_STRING_INTERN(drop);
CSS_DOM_STRING_INTERN(durationchange);
CSS_DOM_STRING_INTERN(emptied);
CSS_DOM_STRING_INTERN(ended);
CSS_DOM_STRING_INTERN(error);
CSS_DOM_STRING_INTERN(focus);
CSS_DOM_STRING_INTERN(hashchange);
CSS_DOM_STRING_INTERN(height);
CSS_DOM_STRING_INTERN(href);
CSS_DOM_STRING_INTERN(hreflang);
CSS_DOM_STRING_INTERN(hspace);
/* http-equiv: see below */
CSS_DOM_STRING_INTERN(id);
CSS_DOM_STRING_INTERN(input);
CSS_DOM_STRING_INTERN(invalid);
CSS_DOM_STRING_INTERN(keydown);
CSS_DOM_STRING_INTERN(keypress);
CSS_DOM_STRING_INTERN(keyup);
CSS_DOM_STRING_INTERN(link);
CSS_DOM_STRING_INTERN(load);
CSS_DOM_STRING_INTERN(loadeddata);
CSS_DOM_STRING_INTERN(loadedmetadata);
CSS_DOM_STRING_INTERN(loadstart);
CSS_DOM_STRING_INTERN(map);
CSS_DOM_STRING_INTERN(media);
CSS_DOM_STRING_INTERN(message);
CSS_DOM_STRING_INTERN(mousedown);
CSS_DOM_STRING_INTERN(mousemove);
CSS_DOM_STRING_INTERN(mouseout);
CSS_DOM_STRING_INTERN(mouseover);
CSS_DOM_STRING_INTERN(mouseup);
CSS_DOM_STRING_INTERN(mousewheel);
CSS_DOM_STRING_INTERN(name);
CSS_DOM_STRING_INTERN(nohref);
CSS_DOM_STRING_INTERN(offline);
CSS_DOM_STRING_INTERN(online);
CSS_DOM_STRING_INTERN(pagehide);
CSS_DOM_STRING_INTERN(pageshow);
CSS_DOM_STRING_INTERN(pause);
CSS_DOM_STRING_INTERN(play);
CSS_DOM_STRING_INTERN(playing);
CSS_DOM_STRING_INTERN(popstate);
CSS_DOM_STRING_INTERN(progress);
CSS_DOM_STRING_INTERN(ratechange);
CSS_DOM_STRING_INTERN(readystatechange);
CSS_DOM_STRING_INTERN(rect);
CSS_DOM_STRING_INTERN(rel);
CSS_DOM_STRING_INTERN(reset);
CSS_DOM_STRING_INTERN(resize);
CSS_DOM_STRING_INTERN(rows);
CSS_DOM_STRING_INTERN(scroll);
CSS_DOM_STRING_INTERN(seeked);
CSS_DOM_STRING_INTERN(seeking);
CSS_DOM_STRING_INTERN(select);
CSS_DOM_STRING_INTERN(shape);
CSS_DOM_STRING_INTERN(show);
CSS_DOM_STRING_INTERN(size);
CSS_DOM_STRING_INTERN(sizes);
CSS_DOM_STRING_INTERN(src);
CSS_DOM_STRING_INTERN(stalled);
CSS_DOM_STRING_INTERN(storage);
CSS_DOM_STRING_INTERN(submit);
CSS_DOM_STRING_INTERN(suspend);
CSS_DOM_STRING_INTERN(target);
CSS_DOM_STRING_INTERN(text);
CSS_DOM_STRING_INTERN(timeupdate);
CSS_DOM_STRING_INTERN(type);
CSS_DOM_STRING_INTERN(unload);
CSS_DOM_STRING_INTERN(valign);
CSS_DOM_STRING_INTERN(vlink);
CSS_DOM_STRING_INTERN(volumechange);
CSS_DOM_STRING_INTERN(vspace);
CSS_DOM_STRING_INTERN(waiting);
CSS_DOM_STRING_INTERN(width);
#undef CSS_DOM_STRING_INTERN
 
exc = dom_string_create_interned((const uint8_t *) "text/javascript",
SLEN("text/javascript"),
&corestring_dom_text_javascript);
if ((exc != DOM_NO_ERR) || (corestring_dom_text_javascript == NULL)) {
error = NSERROR_NOMEM;
goto error;
}
 
exc = dom_string_create_interned((const uint8_t *) "http-equiv",
SLEN("http-equiv"),
&corestring_dom_http_equiv);
if ((exc != DOM_NO_ERR) || (corestring_dom_http_equiv == NULL)) {
error = NSERROR_NOMEM;
goto error;
}
 
return NSERROR_OK;
 
error:
corestrings_fini();
 
return error;
}
/contrib/network/netsurf/netsurf/utils/corestrings.h
0,0 → 1,237
/*
* Copyright 2012 Michael Drake <tlsa@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
/** \file
* Useful interned string pointers (interface).
*/
 
#ifndef NETSURF_UTILS_CORESTRINGS_H_
#define NETSURF_UTILS_CORESTRINGS_H_
 
#include <libwapcaplet/libwapcaplet.h>
#include "utils/errors.h"
 
nserror corestrings_init(void);
void corestrings_fini(void);
 
/* lwc_string strings */
extern lwc_string *corestring_lwc_a;
extern lwc_string *corestring_lwc_abscenter;
extern lwc_string *corestring_lwc_absmiddle;
extern lwc_string *corestring_lwc_align;
extern lwc_string *corestring_lwc_applet;
extern lwc_string *corestring_lwc_base;
extern lwc_string *corestring_lwc_baseline;
extern lwc_string *corestring_lwc_body;
extern lwc_string *corestring_lwc_bottom;
extern lwc_string *corestring_lwc_button;
extern lwc_string *corestring_lwc_caption;
extern lwc_string *corestring_lwc_center;
extern lwc_string *corestring_lwc_checkbox;
extern lwc_string *corestring_lwc_circle;
extern lwc_string *corestring_lwc_col;
extern lwc_string *corestring_lwc_default;
extern lwc_string *corestring_lwc_div;
extern lwc_string *corestring_lwc_embed;
extern lwc_string *corestring_lwc_file;
extern lwc_string *corestring_lwc_font;
extern lwc_string *corestring_lwc_frame;
extern lwc_string *corestring_lwc_frameset;
extern lwc_string *corestring_lwc_h1;
extern lwc_string *corestring_lwc_h2;
extern lwc_string *corestring_lwc_h3;
extern lwc_string *corestring_lwc_h4;
extern lwc_string *corestring_lwc_h5;
extern lwc_string *corestring_lwc_h6;
extern lwc_string *corestring_lwc_head;
extern lwc_string *corestring_lwc_hidden;
extern lwc_string *corestring_lwc_hr;
extern lwc_string *corestring_lwc_html;
extern lwc_string *corestring_lwc_https;
extern lwc_string *corestring_lwc_iframe;
extern lwc_string *corestring_lwc_image;
extern lwc_string *corestring_lwc_img;
extern lwc_string *corestring_lwc_input;
extern lwc_string *corestring_lwc_justify;
extern lwc_string *corestring_lwc_left;
extern lwc_string *corestring_lwc_li;
extern lwc_string *corestring_lwc_link;
extern lwc_string *corestring_lwc_meta;
extern lwc_string *corestring_lwc_middle;
extern lwc_string *corestring_lwc_multipart_form_data;
extern lwc_string *corestring_lwc_no;
extern lwc_string *corestring_lwc_noscript;
extern lwc_string *corestring_lwc_object;
extern lwc_string *corestring_lwc_optgroup;
extern lwc_string *corestring_lwc_option;
extern lwc_string *corestring_lwc_p;
extern lwc_string *corestring_lwc_param;
extern lwc_string *corestring_lwc_password;
extern lwc_string *corestring_lwc_poly;
extern lwc_string *corestring_lwc_polygon;
extern lwc_string *corestring_lwc_post;
extern lwc_string *corestring_lwc_radio;
extern lwc_string *corestring_lwc_rect;
extern lwc_string *corestring_lwc_rectangle;
extern lwc_string *corestring_lwc_refresh;
extern lwc_string *corestring_lwc_reset;
extern lwc_string *corestring_lwc_right;
extern lwc_string *corestring_lwc_search;
extern lwc_string *corestring_lwc_select;
extern lwc_string *corestring_lwc_src;
extern lwc_string *corestring_lwc_style;
extern lwc_string *corestring_lwc_submit;
extern lwc_string *corestring_lwc_table;
extern lwc_string *corestring_lwc_tbody;
extern lwc_string *corestring_lwc_td;
extern lwc_string *corestring_lwc_text;
extern lwc_string *corestring_lwc_textarea;
extern lwc_string *corestring_lwc_texttop;
extern lwc_string *corestring_lwc_text_css;
extern lwc_string *corestring_lwc_tfoot;
extern lwc_string *corestring_lwc_th;
extern lwc_string *corestring_lwc_thead;
extern lwc_string *corestring_lwc_title;
extern lwc_string *corestring_lwc_top;
extern lwc_string *corestring_lwc_tr;
extern lwc_string *corestring_lwc_ul;
extern lwc_string *corestring_lwc_url;
extern lwc_string *corestring_lwc_yes;
extern lwc_string *corestring_lwc__blank;
extern lwc_string *corestring_lwc__parent;
extern lwc_string *corestring_lwc__self;
extern lwc_string *corestring_lwc__top;
 
struct dom_string;
 
/* dom_string strings */
extern struct dom_string *corestring_dom_a;
extern struct dom_string *corestring_dom_abort;
extern struct dom_string *corestring_dom_afterprint;
extern struct dom_string *corestring_dom_align;
extern struct dom_string *corestring_dom_area;
extern struct dom_string *corestring_dom_async;
extern struct dom_string *corestring_dom_background;
extern struct dom_string *corestring_dom_beforeprint;
extern struct dom_string *corestring_dom_beforeunload;
extern struct dom_string *corestring_dom_bgcolor;
extern struct dom_string *corestring_dom_blur;
extern struct dom_string *corestring_dom_border;
extern struct dom_string *corestring_dom_bordercolor;
extern struct dom_string *corestring_dom_cancel;
extern struct dom_string *corestring_dom_canplay;
extern struct dom_string *corestring_dom_canplaythrough;
extern struct dom_string *corestring_dom_cellpadding;
extern struct dom_string *corestring_dom_cellspacing;
extern struct dom_string *corestring_dom_change;
extern struct dom_string *corestring_dom_charset;
extern struct dom_string *corestring_dom_class;
extern struct dom_string *corestring_dom_click;
extern struct dom_string *corestring_dom_close;
extern struct dom_string *corestring_dom_color;
extern struct dom_string *corestring_dom_cols;
extern struct dom_string *corestring_dom_content;
extern struct dom_string *corestring_dom_contextmenu;
extern struct dom_string *corestring_dom_coords;
extern struct dom_string *corestring_dom_cuechange;
extern struct dom_string *corestring_dom_dblclick;
extern struct dom_string *corestring_dom_defer;
extern struct dom_string *corestring_dom_drag;
extern struct dom_string *corestring_dom_dragend;
extern struct dom_string *corestring_dom_dragenter;
extern struct dom_string *corestring_dom_dragleave;
extern struct dom_string *corestring_dom_dragover;
extern struct dom_string *corestring_dom_dragstart;
extern struct dom_string *corestring_dom_drop;
extern struct dom_string *corestring_dom_durationchange;
extern struct dom_string *corestring_dom_emptied;
extern struct dom_string *corestring_dom_ended;
extern struct dom_string *corestring_dom_error;
extern struct dom_string *corestring_dom_focus;
extern struct dom_string *corestring_dom_hashchange;
extern struct dom_string *corestring_dom_height;
extern struct dom_string *corestring_dom_href;
extern struct dom_string *corestring_dom_hreflang;
extern struct dom_string *corestring_dom_hspace;
extern struct dom_string *corestring_dom_http_equiv;
extern struct dom_string *corestring_dom_id;
extern struct dom_string *corestring_dom_input;
extern struct dom_string *corestring_dom_invalid;
extern struct dom_string *corestring_dom_keydown;
extern struct dom_string *corestring_dom_keypress;
extern struct dom_string *corestring_dom_keyup;
extern struct dom_string *corestring_dom_link;
extern struct dom_string *corestring_dom_load;
extern struct dom_string *corestring_dom_loadeddata;
extern struct dom_string *corestring_dom_loadedmetadata;
extern struct dom_string *corestring_dom_loadstart;
extern struct dom_string *corestring_dom_map;
extern struct dom_string *corestring_dom_media;
extern struct dom_string *corestring_dom_message;
extern struct dom_string *corestring_dom_mousedown;
extern struct dom_string *corestring_dom_mousemove;
extern struct dom_string *corestring_dom_mouseout;
extern struct dom_string *corestring_dom_mouseover;
extern struct dom_string *corestring_dom_mouseup;
extern struct dom_string *corestring_dom_mousewheel;
extern struct dom_string *corestring_dom_name;
extern struct dom_string *corestring_dom_nohref;
extern struct dom_string *corestring_dom_offline;
extern struct dom_string *corestring_dom_online;
extern struct dom_string *corestring_dom_pagehide;
extern struct dom_string *corestring_dom_pageshow;
extern struct dom_string *corestring_dom_pause;
extern struct dom_string *corestring_dom_play;
extern struct dom_string *corestring_dom_playing;
extern struct dom_string *corestring_dom_popstate;
extern struct dom_string *corestring_dom_progress;
extern struct dom_string *corestring_dom_ratechange;
extern struct dom_string *corestring_dom_readystatechange;
extern struct dom_string *corestring_dom_rect;
extern struct dom_string *corestring_dom_rel;
extern struct dom_string *corestring_dom_reset;
extern struct dom_string *corestring_dom_resize;
extern struct dom_string *corestring_dom_rows;
extern struct dom_string *corestring_dom_scroll;
extern struct dom_string *corestring_dom_seeked;
extern struct dom_string *corestring_dom_seeking;
extern struct dom_string *corestring_dom_select;
extern struct dom_string *corestring_dom_shape;
extern struct dom_string *corestring_dom_show;
extern struct dom_string *corestring_dom_size;
extern struct dom_string *corestring_dom_sizes;
extern struct dom_string *corestring_dom_src;
extern struct dom_string *corestring_dom_stalled;
extern struct dom_string *corestring_dom_storage;
extern struct dom_string *corestring_dom_submit;
extern struct dom_string *corestring_dom_suspend;
extern struct dom_string *corestring_dom_target;
extern struct dom_string *corestring_dom_text;
extern struct dom_string *corestring_dom_text_javascript;
extern struct dom_string *corestring_dom_timeupdate;
extern struct dom_string *corestring_dom_type;
extern struct dom_string *corestring_dom_unload;
extern struct dom_string *corestring_dom_valign;
extern struct dom_string *corestring_dom_vlink;
extern struct dom_string *corestring_dom_volumechange;
extern struct dom_string *corestring_dom_vspace;
extern struct dom_string *corestring_dom_waiting;
extern struct dom_string *corestring_dom_width;
 
 
#endif
/contrib/network/netsurf/netsurf/utils/errors.h
0,0 → 1,72
/*
* Copyright 2009 John-Mark Bell <jmb@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
/** \file
* Error codes
*/
 
#ifndef NETSURF_UTILS_ERRORS_H_
#define NETSURF_UTILS_ERRORS_H_
 
/**
* Enumeration of error codes
*/
typedef enum {
NSERROR_OK, /**< No error */
 
NSERROR_UNKNOWN, /**< Unknown error - DO *NOT* USE */
 
NSERROR_NOMEM, /**< Memory exhaustion */
 
NSERROR_NO_FETCH_HANDLER, /**< No fetch handler for URL scheme */
 
NSERROR_NOT_FOUND, /**< Requested item not found */
 
NSERROR_SAVE_FAILED, /**< Failed to save data */
 
NSERROR_CLONE_FAILED, /**< Failed to clone handle */
 
NSERROR_INIT_FAILED, /**< Initialisation failed */
 
NSERROR_MNG_ERROR, /**< An MNG error occurred */
 
NSERROR_BAD_ENCODING, /**< The character set is unknown */
 
NSERROR_NEED_DATA, /**< More data needed */
 
NSERROR_ENCODING_CHANGE, /**< The character changed */
 
NSERROR_BAD_PARAMETER, /**< Bad Parameter */
 
NSERROR_INVALID, /**< Invalid data */
 
NSERROR_BOX_CONVERT, /**< Box conversion failed */
 
NSERROR_STOPPED, /**< Content conversion stopped */
 
NSERROR_DOM, /**< DOM call returned error */
 
NSERROR_CSS, /**< CSS call returned error */
 
NSERROR_CSS_BASE, /**< CSS base sheet failed */
 
NSERROR_BAD_URL /**< Bad URL */
} nserror;
 
#endif
 
/contrib/network/netsurf/netsurf/utils/filename.c
0,0 → 1,522
/*
* Copyright 2006 Richard Wilson <info@tinct.net>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
/** \file
* Provides a central method of obtaining unique filenames.
*
* A maximum of 2^24 files can be allocated at any point in time.
*/
 
#include <assert.h>
#include <sys/types.h>
#include <dirent.h>
#include <stdbool.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/stat.h>
#include <unistd.h>
 
#include "utils/config.h"
#include "utils/filename.h"
#include "utils/log.h"
#include "utils/utils.h"
 
#define FULL_WORD (unsigned int)0xffffffffu
#define START_PREFIX ('0' + '0' * 10)
 
struct directory {
int numeric_prefix; /** numeric representation of prefix */
char prefix[10]; /** directory prefix, eg '00/11/52/' */
unsigned int low_used; /** first 32 files, 1 bit per file */
unsigned int high_used; /** last 32 files, 1 bit per file */
struct directory *next; /** next directory (sorted by prefix) */
};
 
 
static struct directory *root = NULL;
static char filename_buffer[12];
static char filename_directory[256];
 
static struct directory *filename_create_directory(const char *prefix);
static bool filename_flush_directory(const char *folder, int depth);
static bool filename_delete_recursive(char *folder);
 
/**
* Request a new, unique, filename.
*
* \return a pointer to a shared buffer containing the new filename,
* NULL on failure
*/
const char *filename_request(void)
{
struct directory *dir;
int i = -1;
 
for (dir = root; dir; dir = dir->next) {
if ((dir->low_used & dir->high_used) != FULL_WORD) {
if (dir->low_used != FULL_WORD) {
for (i = 0; (dir->low_used & (1 << i)); i++);
} else {
for (i = 0; (dir->high_used & (1 << i)); i++);
i += 32;
}
break;
}
}
 
if (i == -1) {
/* no available slots - create a new directory */
dir = filename_create_directory(NULL);
if (dir == NULL) {
LOG(("Failed to create a new directory."));
return NULL;
}
i = 63;
}
 
if (i < 32)
dir->low_used |= (1 << i);
else
dir->high_used |= (1 << (i - 32));
 
sprintf(filename_buffer, "%s%.2i", dir->prefix, i);
 
return filename_buffer;
}
 
 
/**
* Claim a specific filename.
*
* \param filename the filename to claim
* \return whether the claim was successful
*/
bool filename_claim(const char *filename)
{
char dir_prefix[9];
int file;
struct directory *dir;
 
/* filename format is always '01/23/45/XX' */
strncpy(dir_prefix, filename, 9);
dir_prefix[8] = '\0';
file = (filename[10] + filename[9] * 10 - START_PREFIX);
 
/* create the directory */
dir = filename_create_directory(dir_prefix);
if (dir == NULL)
return false;
 
/* update the entry */
if (file < 32) {
if (dir->low_used & (1 << file))
return false;
dir->low_used |= (1 << file);
} else {
if (dir->high_used & (1 << (file - 32)))
return false;
dir->high_used |= (1 << (file - 32));
}
 
return true;
}
 
 
/**
* Releases a filename for future use.
*
* \param filename the filename to release
*/
void filename_release(const char *filename)
{
struct directory *dir;
int index, file;
 
/* filename format is always '01/23/45/XX' */
index = ((filename[7] + filename[6] * 10 - START_PREFIX) |
((filename[4] + filename[3] * 10 - START_PREFIX) << 6) |
((filename[1] + filename[0] * 10 - START_PREFIX) << 12));
file = (filename[10] + filename[9] * 10 - START_PREFIX);
 
/* modify the correct directory entry */
for (dir = root; dir; dir = dir->next) {
if (dir->numeric_prefix == index) {
if (file < 32)
dir->low_used &= ~(1 << file);
else
dir->high_used &= ~(1 << (file - 32));
return;
}
}
}
 
 
/**
* Initialise the filename provider.
*/
bool filename_initialise(void)
{
char *directory, *start;
 
directory = strdup(TEMP_FILENAME_PREFIX);
if (directory == NULL)
return false;
 
for (start = directory; *start != '\0'; start++) {
if (*start == '/') {
*start = '\0';
nsmkdir(directory, S_IRWXU);
*start = '/';
}
}
 
LOG(("Temporary directory location: %s", directory));
nsmkdir(directory, S_IRWXU);
 
free(directory);
 
return true;
}
 
 
/**
* Deletes all files in the cache directory that are not accounted for.
*/
void filename_flush(void)
{
while (filename_flush_directory(TEMP_FILENAME_PREFIX, 0));
}
 
 
/**
* Deletes some files in a directory that are not accounted for.
*
* A single call to this function may not delete all the files in
* a directory. It should be called until it returns false.
*
* \param folder the folder to search
* \param depth the folder depth
* \returns whether further calls may be needed
*/
bool filename_flush_directory(const char *folder, int depth)
{
DIR *parent;
struct dirent *entry;
bool changed = false;
bool del;
int number, i;
int prefix = 0;
unsigned int prefix_mask = (0x3f << 12);
char child[256];
const char *prefix_start = NULL;
struct directory *dir = NULL;
 
/* Maximum permissible depth is 3 */
assert(depth <= 3);
 
if (depth > 0) {
/* Not a top-level directory, so determine the prefix
* by removing the last /XX component */
prefix_start = folder + strlen(folder) - depth * 3 + 1;
}
 
/* Calculate the numeric prefix */
for (i = 0; i < depth; i++) {
number = prefix_start[1] + prefix_start[0] * 10 - START_PREFIX;
prefix |= (number << (12 - i * 6));
prefix_mask |= (0x3f << (12 - i * 6));
prefix_start += 3;
}
 
/* If we're flushing a leaf directory, find it in the list */
if (depth == 3) {
for (dir = root; dir; dir = dir->next) {
if (dir->numeric_prefix == prefix)
break;
}
 
if (dir == NULL)
return false;
}
 
parent = opendir(folder);
 
while ((entry = readdir(parent))) {
struct stat statbuf;
 
/* Ignore '.' and '..' */
if (strcmp(entry->d_name, ".") == 0 ||
strcmp(entry->d_name, "..") == 0)
continue;
 
snprintf(child, sizeof(child), "%s/%s", folder, entry->d_name);
child[sizeof(child) - 1] = '\0';
 
if (stat(child, &statbuf) == -1) {
LOG(("Unable to stat %s: %s", child, strerror(errno)));
continue;
}
 
/* first 3 depths are directories only, then files only */
if (depth < 3) {
/* Delete any unexpected files */
del = !S_ISDIR(statbuf.st_mode);
} else {
/* Delete any unexpected directories */
del = S_ISDIR(statbuf.st_mode);
}
 
/* check we are a file numbered '00' -> '63' */
if (del == false && (entry->d_name[0] >= '0') &&
(entry->d_name[0] <= '6') &&
(entry->d_name[1] >= '0') &&
(entry->d_name[1] <= '9') &&
(entry->d_name[2] == '\0')) {
number = atoi(entry->d_name);
 
if (number >= 0 && number <= 63) {
if (depth == 3) {
/* File: delete if not in bitfield */
if (number < 32)
del = !(dir->low_used &
(1 << number));
else
del = !(dir->high_used &
(1 << (number - 32)));
} else {
/* Directory: delete unless in list */
del = true;
 
/* Insert into numeric prefix */
prefix &= ~(0x3f << (12 - depth * 6));
prefix |= (number << (12 - depth * 6));
 
/* Find in dir list */
for (dir = root; dir; dir = dir->next) {
number = dir->numeric_prefix &
prefix_mask;
if (number == prefix) {
/* In list: retain */
del = false;
break;
}
}
}
} else {
/* Unexpected name: delete */
del = true;
}
} else {
/* Unexpected name: delete */
del = true;
}
 
/* continue if this is a file we want to retain */
if (del == false && (!S_ISDIR(statbuf.st_mode)))
continue;
 
/* delete or recurse */
if (del) {
if (S_ISDIR(statbuf.st_mode))
filename_delete_recursive(child);
 
if (remove(child))
LOG(("Failed to remove '%s'", child));
else
changed = true;
} else {
while (filename_flush_directory(child, depth + 1));
}
}
 
closedir(parent);
 
return changed;
}
 
 
/**
* Recursively deletes the contents of a directory
*
* \param directory the directory to delete
* \return true on success, false otherwise
*/
bool filename_delete_recursive(char *folder)
{
DIR *parent;
struct dirent *entry;
char child[256];
struct stat statbuf;
 
parent = opendir(folder);
 
while ((entry = readdir(parent))) {
/* Ignore '.' and '..' */
if (strcmp(entry->d_name, ".") == 0 ||
strcmp(entry->d_name, "..") == 0)
continue;
 
snprintf(child, sizeof(child), "%s/%s", folder, entry->d_name);
child[sizeof(child) - 1] = '\0';
 
if (stat(child, &statbuf) == -1) {
LOG(("Unable to stat %s: %s", child, strerror(errno)));
continue;
}
 
if (S_ISDIR(statbuf.st_mode)) {
if (!filename_delete_recursive(child)) {
closedir(parent);
return false;
}
}
 
if (remove(child)) {
LOG(("Failed to remove '%s'", child));
closedir(parent);
return false;
}
}
 
closedir(parent);
 
return true;
}
 
 
/**
* Creates a new directory.
*
* \param prefix the prefix to use, or NULL to allocate a new one
* \return a new directory structure, or NULL on memory exhaustion or
* creation failure
*
* Empty directories are never deleted, except by an explicit call to
* filename_flush().
*/
static struct directory *filename_create_directory(const char *prefix)
{
char *last_1, *last_2;
int index;
struct directory *old_dir, *new_dir, *prev_dir = NULL;
char dir_prefix[16];
int i;
 
/* get the lowest unique prefix, or use the provided one */
if (prefix == NULL) {
for (index = 0, old_dir = root; old_dir;
index++, old_dir = old_dir->next) {
if (old_dir->numeric_prefix != index)
break;
 
prev_dir = old_dir;
}
 
sprintf(dir_prefix, "%.2i/%.2i/%.2i/",
((index >> 12) & 63),
((index >> 6) & 63),
((index >> 0) & 63));
 
prefix = dir_prefix;
} else {
/* prefix format is always '01/23/45/' */
index = ((prefix[7] + prefix[6] * 10 - START_PREFIX) |
((prefix[4] + prefix[3] * 10 - START_PREFIX) << 6) |
((prefix[1] + prefix[0] * 10 - START_PREFIX) << 12));
 
for (old_dir = root; old_dir; old_dir = old_dir->next) {
if (old_dir->numeric_prefix == index)
return old_dir;
 
else if (old_dir->numeric_prefix > index)
break;
 
prev_dir = old_dir;
}
}
 
/* allocate a new directory */
new_dir = malloc(sizeof(struct directory));
if (new_dir == NULL) {
LOG(("No memory for malloc()"));
return NULL;
}
 
strncpy(new_dir->prefix, prefix, 9);
new_dir->prefix[9] = '\0';
new_dir->low_used = new_dir->high_used = 0;
new_dir->numeric_prefix = index;
 
if (prev_dir == NULL) {
new_dir->next = root;
root = new_dir;
} else {
new_dir->next = prev_dir->next;
prev_dir->next = new_dir;
}
 
/* if the previous directory has the same parent then we can simply
* create the child. */
if (prev_dir && strncmp(prev_dir->prefix, new_dir->prefix, 6) == 0) {
new_dir->prefix[8] = '\0';
sprintf(filename_directory, "%s/%s",
TEMP_FILENAME_PREFIX,
new_dir->prefix);
new_dir->prefix[8] = '/';
 
if (!is_dir(filename_directory)) {
if (!nsmkdir(filename_directory, S_IRWXU))
return new_dir;
 
/* the user has probably deleted the parent directory
* whilst we are running if there is an error, so we
* don't report this yet and try to create the
* structure normally. */
LOG(("Failed to create optimised structure '%s'",
filename_directory));
}
}
 
/* create the directory structure */
sprintf(filename_directory, "%s/", TEMP_FILENAME_PREFIX);
last_1 = filename_directory + SLEN(TEMP_FILENAME_PREFIX) + 1;
last_2 = new_dir->prefix;
 
/* create each subdirectory, up to the maximum depth of 3 */
for (i = 0; i < 3 && *last_2; i++) {
*last_1++ = *last_2++;
while (*last_2 && *last_2 != '/')
*last_1++ = *last_2++;
 
if (*last_2) {
last_1[0] = '\0';
 
if (!is_dir(filename_directory)) {
if (nsmkdir(filename_directory, S_IRWXU)) {
LOG(("Failed to create directory '%s'",
filename_directory));
return NULL;
}
}
}
}
 
return new_dir;
}
/contrib/network/netsurf/netsurf/utils/filename.h
0,0 → 1,36
/*
* Copyright 2006 Richard Wilson <info@tinct.net>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
#ifndef _NETSURF_UTILS_FILENAME_H_
#define _NETSURF_UTILS_FILENAME_H_
 
#include <stdbool.h>
 
#ifdef riscos
#define TEMP_FILENAME_PREFIX "<Wimp$ScrapDir>/WWW/NetSurf/Cache"
#else
#define TEMP_FILENAME_PREFIX "/tmp/WWW/NetSurf/Cache"
#endif
 
const char *filename_request(void);
bool filename_claim(const char *filename);
void filename_release(const char *filename);
bool filename_initialise(void);
void filename_flush(void);
 
#endif
/contrib/network/netsurf/netsurf/utils/filepath.c
0,0 → 1,323
/*
* Copyright 2010 Vincent Sanders <vince@kyllikki.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
/** \file
* Provides utility functions for finding readable files.
*
* These functions are intended to make finding resource files more straightforward.
*/
 
#include <sys/types.h>
#include <sys/stat.h>
#include <stdarg.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
 
#include "utils/config.h"
#include "utils/filepath.h"
 
/** maximum number of elements in the resource vector */
#define MAX_RESPATH 128
 
/* exported interface documented in filepath.h */
char *filepath_vsfindfile(char *str, const char *format, va_list ap)
{
char *realpathname;
char *pathname;
int len;
 
pathname = malloc(PATH_MAX);
if (pathname == NULL)
return NULL; /* unable to allocate memory */
 
len = vsnprintf(pathname, PATH_MAX, format, ap);
 
if ((len < 0) || (len >= PATH_MAX)) {
/* error or output exceeded PATH_MAX length so
* operation is doomed to fail.
*/
free(pathname);
return NULL;
}
 
realpathname = realpath(pathname, str);
free(pathname);
if (realpathname != NULL) {
/* sucessfully expanded pathname */
if (access(realpathname, R_OK) != 0) {
/* unable to read the file */
return NULL;
}
}
 
return realpathname;
}
 
/* exported interface documented in filepath.h */
char *filepath_sfindfile(char *str, const char *format, ...)
{
va_list ap;
char *ret;
 
va_start(ap, format);
ret = filepath_vsfindfile(str, format, ap);
va_end(ap);
 
return ret;
}
 
/* exported interface documented in filepath.h */
char *filepath_findfile(const char *format, ...)
{
char *str;
char *ret;
va_list ap;
 
str = malloc(PATH_MAX);
if (str == NULL)
return NULL; /* unable to allocate memory */
 
va_start(ap, format);
ret = filepath_vsfindfile(str, format, ap);
va_end(ap);
 
if (ret == NULL)
free(str);
 
return ret;
}
 
/* exported interface documented in filepath.h */
char *filepath_sfind(char **respathv, char *filepath, const char *filename)
{
int respathc = 0;
 
if ((respathv == NULL) || (respathv[0] == NULL) || (filepath == NULL))
return NULL;
 
while (respathv[respathc] != NULL) {
if (filepath_sfindfile(filepath, "%s/%s", respathv[respathc], filename) != NULL) {
return filepath;
}
 
respathc++;
}
 
return NULL;
}
 
/* exported interface documented in filepath.h */
char *filepath_find(char **respathv, const char *filename)
{
char *ret;
char *filepath;
 
if ((respathv == NULL) || (respathv[0] == NULL))
return NULL;
 
filepath = malloc(PATH_MAX);
if (filepath == NULL)
return NULL;
 
ret = filepath_sfind(respathv, filepath, filename);
 
if (ret == NULL)
free(filepath);
 
return ret;
}
 
/* exported interface documented in filepath.h */
char *filepath_sfinddef(char **respathv, char *filepath, const char *filename, const char *def)
{
char t[PATH_MAX];
char *ret;
 
if ((respathv == NULL) || (respathv[0] == NULL) || (filepath == NULL))
return NULL;
 
ret = filepath_sfind(respathv, filepath, filename);
 
if ((ret == NULL) && (def != NULL)) {
/* search failed, return the path specified */
ret = filepath;
if (def[0] == '~') {
snprintf(t, PATH_MAX, "%s/%s/%s", getenv("HOME"), def + 1, filename);
} else {
snprintf(t, PATH_MAX, "%s/%s", def, filename);
}
if (realpath(t, ret) == NULL) {
strcpy(ret, t);
}
 
}
return ret;
}
 
 
/* exported interface documented in filepath.h */
char **
filepath_generate(char * const *pathv, const char * const *langv)
{
char **respath; /* resource paths vector */
int pathc = 0;
int langc = 0;
int respathc = 0;
struct stat dstat;
char tmppath[PATH_MAX];
 
respath = calloc(MAX_RESPATH, sizeof(char *));
 
while (pathv[pathc] != NULL) {
if ((stat(pathv[pathc], &dstat) == 0) &&
S_ISDIR(dstat.st_mode)) {
/* path element exists and is a directory */
langc = 0;
while (langv[langc] != NULL) {
snprintf(tmppath, sizeof tmppath, "%s/%s", pathv[pathc],langv[langc]);
if ((stat(tmppath, &dstat) == 0) &&
S_ISDIR(dstat.st_mode)) {
/* path element exists and is a directory */
respath[respathc++] = strdup(tmppath);
}
langc++;
}
respath[respathc++] = strdup(pathv[pathc]);
}
pathc++;
}
 
return respath;
}
 
/* expand ${} in a string into environment variables */
static char *
expand_path(const char *path, int pathlen)
{
char *exp;
int explen;
int cstart = -1;
int cloop = 0;
char *envv;
int envlen;
int replen; /* length of replacement */
 
exp = malloc(pathlen + 1);
if (exp == NULL)
return NULL;
 
memcpy(exp, path, pathlen);
exp[pathlen] = 0;
 
explen = strlen(exp);
 
while (exp[cloop] != 0) {
if ((exp[cloop] == '$') &&
(exp[cloop + 1] == '{')) {
cstart = cloop;
cloop++;
}
if ((cstart != -1) &&
(exp[cloop] == '}')) {
replen = cloop - cstart;
exp[cloop] = 0;
envv = getenv(exp + cstart + 2);
if (envv == NULL) {
memmove(exp + cstart,
exp + cloop + 1,
explen - cloop);
explen -= replen;
} else {
envlen = strlen(envv);
exp = realloc(exp, explen + envlen - replen);
memmove(exp + cstart + envlen,
exp + cloop + 1,
explen - cloop );
memmove(exp + cstart, envv, envlen);
explen += envlen - replen;
}
cloop -= replen;
cstart = -1;
}
 
cloop++;
}
 
if (explen == 1) {
free(exp);
exp = NULL;
}
 
return exp;
}
 
/* exported interface documented in filepath.h */
char **
filepath_path_to_strvec(const char *path)
{
char **strvec;
int strc = 0;
const char *estart; /* path element start */
const char *eend; /* path element end */
int elen;
 
strvec = calloc(MAX_RESPATH, sizeof(char *));
if (strvec == NULL)
return NULL;
 
estart = eend = path;
 
while (strc < (MAX_RESPATH - 2)) {
while ( (*eend != 0) && (*eend != ':') )
eend++;
elen = eend - estart;
 
if (elen > 1) {
/* more than an empty colon */
strvec[strc] = expand_path(estart, elen);
if (strvec[strc] != NULL) {
/* successfully expanded an element */
strc++;
}
}
 
/* skip colons */
while (*eend == ':')
eend++;
 
/* check for termination */
if (*eend == 0)
break;
estart = eend;
}
return strvec;
}
 
/* exported interface documented in filepath.h */
void filepath_free_strvec(char **pathv)
{
free(pathv[0]);
free(pathv);
}
/contrib/network/netsurf/netsurf/utils/filepath.h
0,0 → 1,119
/*
* Copyright 2010 Vincent Sanders <vince@kyllikki.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
/**
* \file utils/filepath.h
* \brief Utility routines to obtain paths to file resources.
*/
 
#ifndef _NETSURF_UTILS_FILEPATH_H_
#define _NETSURF_UTILS_FILEPATH_H_
 
#include <stdarg.h>
 
 
/** Create a normalised file name.
*
* If the file described by the format exists and is accessible the
* normalised path is placed in str and a pointer to str returned
* otherwise NULL is returned. The string in str is always modified.
*
* @param str A buffer to contain the normalised file name must be at
* least PATH_MAX bytes long.
* @param format A printf format for the filename.
* @param ap The list of arguments for the format.
* @return A pointer to the expanded filename or NULL if the file is
* not present or accessible.
*/
char *filepath_vsfindfile(char *str, const char *format, va_list ap);
 
 
/** Create a normalised file name.
*
* Similar to vsfindfile but takes variadic (printf like) parameters
*/
char *filepath_sfindfile(char *str, const char *format, ...);
 
 
/** Create a normalised file name.
*
* Similar to sfindfile but allocates its own storage for the
* returned string. The caller must free this sorage.
*/
char *filepath_findfile(const char *format, ...);
 
 
/** Searches an array of resource paths for a file.
*
* Iterates through a vector of resource paths and returns the
* normalised file name of the first acessible file or NULL if no file
* can be found in any of the resource paths.
*
* @param respathv The resource path vector to iterate.
* @param filepath The buffer to place the result in.
* @param filename The filename of the resource to search for.
* @return A pointer to filepath if a target is found or NULL if not.
*/
char *filepath_sfind(char **respathv, char *filepath, const char *filename);
 
 
/** Searches an array of resource paths for a file.
*
* Similar to filepath_sfind except it allocates its own storage for
* the returned string. The caller must free this sorage.
*/
char *filepath_find(char **respathv, const char *filename);
 
 
/** Searches an array of resource paths for a file optionally forcing a default.
*
* Similar to filepath_sfind except if no resource is found the default
* is used as an additional path element to search, if that still
* fails the returned path is set to the concatination of the default
* path and the filename.
*/
char *filepath_sfinddef(char **respathv, char *filepath, const char *filename,
const char *def);
 
 
/** Merge two string vectors into a resource search path vector.
*
* @param pathv A string vector containing path elemets to scan.
* @param langv A string vector containing language names to enumerate.
* @return A pointer to a NULL terminated string vector of valid
* resource directories.
*/
char **filepath_generate(char * const *pathv, const char * const *langv);
 
 
/** Convert a colon separated list of path elements into a string vector.
*
* @param path A colon separated path.
* @return A pointer to a NULL terminated string vector of valid
* resource directories.
*/
char **filepath_path_to_strvec(const char *path);
 
 
/** Free a string vector
*
* Free a string vector allocated by filepath_path_to_strvec
*/
void filepath_free_strvec(char **pathv);
 
#endif /* _NETSURF_UTILS_FILEPATH_H_ */
/contrib/network/netsurf/netsurf/utils/git-testament.pl
0,0 → 1,226
#!/usr/bin/perl -w
 
use strict;
 
=head1
 
Generate a testament describing the current Git status. This gets written
out in a C form which can be used to construct the NetSurf Git testament
file for signon notification.
 
If there is no Git in place, the data is invented arbitrarily.
 
=cut
 
$ENV{LC_ALL} = 'C';
 
my $root = shift @ARGV;
my $targetfile = shift @ARGV;
 
my %gitinfo; # The Git information
 
$root .= "/" unless ($root =~ m@/$@);
 
my $git_present = 0;
if ( -d ".git" ) {
$git_present = 1;
}
 
sub compat_tmpnam {
# File::Temp was introduced in Perl 5.6.1
my $have_file_tmp = eval { require File::Temp };
 
if ( ! $have_file_tmp ) {
return "$$.gitt";
} else {
return File::Temp::tmpnam();
}
}
 
sub compat_md5_hex {
# Digest::MD5 was introduced in Perl 5.7.1
my $have_digest_md5 = eval { require Digest::MD5 };
my $have_md5 = eval { require MD5 };
my $data = shift;
 
if ( ! $have_digest_md5 ) {
return MD5->hexhash($data);
} else {
return Digest::MD5->new->add($data)->hexdigest;
}
}
 
sub gather_output {
my $cmd = shift;
my $tmpfile = compat_tmpnam();
local $/ = undef();
system("$cmd > $tmpfile");
open(my $CMDH, "<", $tmpfile);
my $ret = <$CMDH>;
close($CMDH);
unlink($tmpfile);
return $ret;
}
 
if ( $git_present ) {
my @bits = split /\s+/, `git config --get-regexp "^remote.*.url\$"`;
$gitinfo{url} = $bits[1];
chomp $gitinfo{url};
$gitinfo{revision} = `git rev-parse HEAD`;
chomp $gitinfo{revision};
$gitinfo{branch} = `git for-each-ref --format="\%(refname:short)" \$(git symbolic-ref HEAD 2>/dev/null || git show-ref -s HEAD)`;
chomp $gitinfo{branch};
@bits = split /\s+/, `git describe --tags --exact-match HEAD 2>/dev/null`;
$bits[0] = "" unless exists $bits[0];
$gitinfo{tag} = $bits[0];
} else {
$gitinfo{url} = "http://nowhere/tarball/";
$gitinfo{revision} = "unknown";
$gitinfo{branch} = "tarball";
$gitinfo{tag} = "";
}
 
my %gitstatus; # The Git status output
 
if ( $git_present ) {
foreach my $line (split(/\n/, gather_output("git status --porcelain"))) {
chomp $line;
my ($X, $Y, $fp) = ($line =~ /^(.)(.) (.+)$/);
my $fn = $fp;
$fn = ($fp =~ /(.+) ->/) if ($fp =~ / -> /);
next unless (care_about_file($fn));
# Normalise $X and $Y (WT and index) into a simple A/M/D etc
$gitstatus{$fn} = "$X$Y";
}
}
 
my %userinfo; # The information about the current user
 
{
my @pwent = getpwuid($<);
$userinfo{USERNAME} = $pwent[0];
my $gecos = $pwent[6];
$gecos =~ s/,.+//g;
$gecos =~ s/"/'/g;
$gecos =~ s/\\/\\\\/g;
$userinfo{GECOS} = $gecos;
}
 
# The current date, in AmigaOS version friendly format (dd.mm.yyyy)
 
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime();
my $compiledate = sprintf("%02d.%02d.%d",$mday,$mon+1,$year+1900);
chomp $compiledate;
 
# Spew the testament out
 
my $testament = "";
 
$testament .= "#define USERNAME \"$userinfo{USERNAME}\"\n";
$testament .= "#define GECOS \"$userinfo{GECOS}\"\n";
 
my $qroot = $root;
$qroot =~ s/"/\\"/g;
 
my $hostname = $ENV{HOSTNAME};
 
unless ( defined($hostname) && $hostname ne "") {
# Try hostname command if env-var empty
$hostname = gather_output("hostname");
chomp $hostname;
}
 
$hostname = "unknown-host" unless (defined($hostname) && $hostname ne "");
$hostname =~ s/"/\\"/g;
 
$testament .= "#define WT_ROOT \"$qroot\"\n";
$testament .= "#define WT_HOSTNAME \"$hostname\"\n";
$testament .= "#define WT_COMPILEDATE \"$compiledate\"\n";
 
my $cibuild = $ENV{CI_BUILD};
if (defined ($cibuild) && ($cibuild ne '')) {
$testament .= "#define CI_BUILD \"$cibuild\"\n";
}
 
$testament .= "#define WT_BRANCHPATH \"$gitinfo{branch}\"\n";
 
if ($gitinfo{branch} =~ m@^master$@) {
$testament .= "#define WT_BRANCHISMASTER 1\n";
}
if ($gitinfo{tag} =~ m@.@) {
$testament .= "#define WT_BRANCHISTAG 1\n";
$testament .= "#define WT_TAGIS \"$gitinfo{tag}\"\n";
}
if ($gitinfo{url} =~ m@/tarball/@) {
$testament .= "#define WT_NO_GIT 1\n";
}
$testament .= "#define WT_REVID \"$gitinfo{revision}\"\n";
$testament .= "#define WT_MODIFIED " . scalar(keys %gitstatus) . "\n";
$testament .= "#define WT_MODIFICATIONS {\\\n";
my $doneone = 0;
foreach my $filename (sort keys %gitstatus) {
if ($doneone) {
$testament .= ", \\\n";
}
$testament .= " { \"$filename\", \"$gitstatus{$filename}\" }";
$doneone = 1;
}
$testament .= " \\\n}\n";
 
my $oldcsum = "";
if ( -e $targetfile ) {
open(my $OLDVALUES, "<", $targetfile);
foreach my $line (readline($OLDVALUES)) {
if ($line =~ /MD5:([0-9a-f]+)/) {
$oldcsum = $1;
}
}
close($OLDVALUES);
}
 
my $newcsum = compat_md5_hex($testament);
 
if ($oldcsum ne $newcsum) {
print "TESTMENT: $targetfile\n";
open(my $NEWVALUES, ">", $targetfile) or die "$!";
print $NEWVALUES "/* ", $targetfile,"\n";
print $NEWVALUES <<'EOS';
*
* Revision testament.
*
* *WARNING* this file is automatically generated by git-testament.pl
*
* Copyright 2012 NetSurf Browser Project
*/
 
EOS
 
print $NEWVALUES "#ifndef NETSURF_REVISION_TESTAMENT\n";
print $NEWVALUES "#define NETSURF_REVISION_TESTAMENT \"$newcsum\"\n\n";
print $NEWVALUES "/* Revision testament checksum:\n";
print $NEWVALUES " * MD5:", $newcsum,"\n */\n\n";
print $NEWVALUES "/* Revision testament: */\n";
print $NEWVALUES $testament;
print $NEWVALUES "\n#endif\n";
close($NEWVALUES);
foreach my $unwanted (@ARGV) {
next unless(-e $unwanted);
print "TESTAMENT: Removing $unwanted\n";
system("rm", "-f", "--", $unwanted);
}
} else {
print "TESTMENT: unchanged\n";
}
 
exit 0;
 
sub care_about_file {
my ($fn) = @_;
return 0 if ($fn =~ /\.d$/); # Don't care for extraneous DEP files
return 0 if ($fn =~ /\.a$/); # Don't care for extraneous archive files
return 0 if ($fn =~ /\.md5$/); # Don't care for md5sum files
return 0 if ($fn =~ /\.map$/); # Don't care for map files
return 0 if ($fn =~ /\.gitt$/); # Don't care for testament temp files
return 1;
}
/contrib/network/netsurf/netsurf/utils/hashtable.c
0,0 → 1,334
/*
* Copyright 2006 Rob Kendrick <rjek@rjek.com>
* Copyright 2006 Richard Wilson <info@tinct.net>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
/** \file
* Write-Once hash table for string to string mappings */
 
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#ifdef TEST_RIG
#include <assert.h>
#include <stdio.h>
#endif
#include "utils/hashtable.h"
#include "utils/log.h"
 
 
struct hash_entry {
char *pairing; /**< block containing 'key\0value\0' */
unsigned int key_length; /**< length of key */
struct hash_entry *next; /**< next entry */
};
 
struct hash_table {
unsigned int nchains;
struct hash_entry **chain;
};
 
/**
* Hash a string, returning a 32bit value. The hash algorithm used is
* Fowler Noll Vo - a very fast and simple hash, ideal for short strings.
* See http://en.wikipedia.org/wiki/Fowler_Noll_Vo_hash for more details.
*
* \param datum The string to hash.
* \param len Pointer to unsigned integer to record datum's length in.
* \return The calculated hash value for the datum.
*/
 
static inline unsigned int hash_string_fnv(const char *datum, unsigned int *len)
{
unsigned int z = 0x811c9dc5;
const char *start = datum;
*len = 0;
 
if (datum == NULL)
return 0;
 
while (*datum) {
z *= 0x01000193;
z ^= *datum++;
}
*len = datum - start;
 
return z;
}
 
 
/**
* Create a new hash table, and return a context for it. The memory consumption
* of a hash table is approximately 8 + (nchains * 12) bytes if it is empty.
*
* \param chains Number of chains/buckets this hash table will have. This
* should be a prime number, and ideally a prime number just
* over a power of two, for best performance and distribution.
* \return struct hash_table containing the context of this hash table or NULL
* if there is insufficent memory to create it and its chains.
*/
 
struct hash_table *hash_create(unsigned int chains)
{
struct hash_table *r = malloc(sizeof(struct hash_table));
 
if (r == NULL) {
LOG(("Not enough memory for hash table."));
return NULL;
}
 
r->nchains = chains;
r->chain = calloc(chains, sizeof(struct hash_entry));
 
if (r->chain == NULL) {
LOG(("Not enough memory for %d hash table chains.", chains));
free(r);
return NULL;
}
 
return r;
}
 
/**
* Destroys a hash table, freeing all memory associated with it.
*
* \param ht Hash table to destroy. After the function returns, this
* will nolonger be valid.
*/
 
void hash_destroy(struct hash_table *ht)
{
unsigned int i;
 
if (ht == NULL)
return;
 
for (i = 0; i < ht->nchains; i++) {
if (ht->chain[i] != NULL) {
struct hash_entry *e = ht->chain[i];
while (e) {
struct hash_entry *n = e->next;
free(e->pairing);
free(e);
e = n;
}
}
}
 
free(ht->chain);
free(ht);
}
 
/**
* Adds a key/value pair to a hash table. If the key you're adding is already
* in the hash table, it does not replace it, but it does take precedent over
* it. The old key/value pair will be inaccessable but still in memory until
* hash_destroy() is called on the hash table.
*
* \param ht The hash table context to add the key/value pair to.
* \param key The key to associate the value with. A copy is made.
* \param value The value to associate the key with. A copy is made.
* \return true if the add succeeded, false otherwise. (Failure most likely
* indicates insufficent memory to make copies of the key and value.
*/
 
bool hash_add(struct hash_table *ht, const char *key, const char *value)
{
unsigned int h, c, v;
struct hash_entry *e;
 
if (ht == NULL || key == NULL || value == NULL)
return false;
 
e = malloc(sizeof(struct hash_entry));
if (e == NULL) {
LOG(("Not enough memory for hash entry."));
return false;
}
 
h = hash_string_fnv(key, &(e->key_length));
c = h % ht->nchains;
 
v = strlen(value) ;
e->pairing = malloc(v + e->key_length + 2);
if (e->pairing == NULL) {
LOG(("Not enough memory for string duplication."));
free(e);
return false;
}
memcpy(e->pairing, key, e->key_length + 1);
memcpy(e->pairing + e->key_length + 1, value, v + 1);
 
e->next = ht->chain[c];
ht->chain[c] = e;
 
return true;
}
 
/**
* Looks up a the value associated with with a key from a specific hash table.
*
* \param ht The hash table context to look up the key in.
* \param key The key to search for.
* \return The value associated with the key, or NULL if it was not found.
*/
 
const char *hash_get(struct hash_table *ht, const char *key)
{
unsigned int h, c, key_length;
struct hash_entry *e;
 
if (ht == NULL || key == NULL)
return NULL;
 
h = hash_string_fnv(key, &key_length);
c = h % ht->nchains;
 
for (e = ht->chain[c]; e; e = e->next)
if ((key_length == e->key_length) &&
(memcmp(key, e->pairing, key_length) == 0))
return e->pairing + key_length + 1;
 
return NULL;
}
 
/**
* Iterate through all available hash keys.
*
* \param ht The hash table context to iterate.
* \param c1 Pointer to first context
* \param c2 Pointer to second context (set to 0 on first call)
* \return The next hash key, or NULL for no more keys
*/
 
const char *hash_iterate(struct hash_table *ht, unsigned int *c1, unsigned int **c2) {
struct hash_entry **he = (struct hash_entry **)c2;
 
if (ht == NULL)
return NULL;
 
if (!*he)
*c1 = -1;
else
*he = (*he)->next;
 
if (*he)
return (*he)->pairing;
 
while (!*he) {
(*c1)++;
if (*c1 >= ht->nchains)
return NULL;
*he = ht->chain[*c1];
}
return (*he)->pairing;
}
 
/* A simple test rig. To compile, use:
* gcc -o hashtest -I../ -DTEST_RIG utils/hashtable.c
*
* If you make changes to this hash table implementation, please rerun this
* test, and if possible, through valgrind to make sure there are no memory
* leaks or invalid memory accesses. If you add new functionality, please
* include a test for it that has good coverage along side the other tests.
*/
 
#ifdef TEST_RIG
 
int main(int argc, char *argv[])
{
struct hash_table *a, *b;
FILE *dict;
char keybuf[BUFSIZ], valbuf[BUFSIZ];
int i;
 
a = hash_create(79);
assert(a != NULL);
 
b = hash_create(103);
assert(b != NULL);
 
hash_add(a, "cow", "moo");
hash_add(b, "moo", "cow");
 
hash_add(a, "pig", "oink");
hash_add(b, "oink", "pig");
 
hash_add(a, "chicken", "cluck");
hash_add(b, "cluck", "chicken");
 
hash_add(a, "dog", "woof");
hash_add(b, "woof", "dog");
 
hash_add(a, "cat", "meow");
hash_add(b, "meow", "cat");
 
#define MATCH(x,y) assert(!strcmp(hash_get(a, x), y)); assert(!strcmp(hash_get(b, y), x))
MATCH("cow", "moo");
MATCH("pig", "oink");
MATCH("chicken", "cluck");
MATCH("dog", "woof");
MATCH("cat", "meow");
 
hash_destroy(a);
hash_destroy(b);
 
/* this test requires /usr/share/dict/words - a large list of English
* words. We load the entire file - odd lines are used as keys, and
* even lines are used as the values for the previous line. we then
* work through it again making sure everything matches.
*
* We do this twice - once in a hash table with many chains, and once
* with a hash table with fewer chains.
*/
 
a = hash_create(1031);
b = hash_create(7919);
 
dict = fopen("/usr/share/dict/words", "r");
if (dict == NULL) {
fprintf(stderr, "Unable to open /usr/share/dict/words - extensive testing skipped.\n");
exit(0);
}
 
while (!feof(dict)) {
fscanf(dict, "%s", keybuf);
fscanf(dict, "%s", valbuf);
hash_add(a, keybuf, valbuf);
hash_add(b, keybuf, valbuf);
}
 
for (i = 0; i < 5; i++) {
fseek(dict, 0, SEEK_SET);
 
while (!feof(dict)) {
fscanf(dict, "%s", keybuf);
fscanf(dict, "%s", valbuf);
assert(strcmp(hash_get(a, keybuf), valbuf) == 0);
assert(strcmp(hash_get(b, keybuf), valbuf) == 0);
}
}
 
hash_destroy(a);
hash_destroy(b);
 
fclose(dict);
 
return 0;
}
 
#endif
/contrib/network/netsurf/netsurf/utils/hashtable.h
0,0 → 1,36
/*
* Copyright 2006 Rob Kendrick <rjek@rjek.com>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
/** \file
* Write-Once hash table for string to string mappings */
 
#ifndef _NETSURF_UTILS_HASHTABLE_H_
#define _NETSURF_UTILS_HASHTABLE_H_
 
#include <stdbool.h>
 
struct hash_table;
 
struct hash_table *hash_create(unsigned int chains);
void hash_destroy(struct hash_table *ht);
bool hash_add(struct hash_table *ht, const char *key, const char *value);
const char *hash_get(struct hash_table *ht, const char *key);
const char *hash_iterate(struct hash_table *ht, unsigned int *c1,
unsigned int **c2);
 
#endif
/contrib/network/netsurf/netsurf/utils/http/challenge.c
0,0 → 1,140
/*
* Copyright 2010 John-Mark Bell <jmb@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
#include <stdlib.h>
 
#include "utils/http.h"
 
#include "utils/http/challenge_internal.h"
#include "utils/http/generics.h"
#include "utils/http/parameter_internal.h"
#include "utils/http/primitives.h"
 
/**
* Representation of an HTTP challenge
*/
struct http_challenge {
http__item base;
 
lwc_string *scheme; /**< Challenge scheme */
http_parameter *params; /**< Challenge parameters */
};
 
/**
* Destroy an HTTP challenge
*
* \param self Challenge to destroy
*/
static void http_destroy_challenge(http_challenge *self)
{
lwc_string_unref(self->scheme);
http_parameter_list_destroy(self->params);
free(self);
}
 
/**
* Parse an HTTP challenge
*
* \param input Pointer to current input byte. Updated on exit.
* \param challenge Pointer to location to receive challenge
* \return NSERROR_OK on success,
* NSERROR_NOMEM on memory exhaustion,
* NSERROR_NOT_FOUND if no parameter could be parsed
*
* The returned challenge is owned by the caller.
*/
nserror http__parse_challenge(const char **input, http_challenge **challenge)
{
const char *pos = *input;
http_challenge *result;
lwc_string *scheme;
http_parameter *first = NULL;
http_parameter *params = NULL;
nserror error;
 
/* challenge = auth-scheme 1*SP 1#auth-param
* auth-scheme = token
* auth-param = parameter
*/
 
error = http__parse_token(&pos, &scheme);
if (error != NSERROR_OK)
return error;
 
if (*pos != ' ' && *pos != '\t') {
lwc_string_unref(scheme);
return NSERROR_NOT_FOUND;
}
 
http__skip_LWS(&pos);
 
error = http__parse_parameter(&pos, &first);
if (error != NSERROR_OK) {
lwc_string_unref(scheme);
return error;
}
 
http__skip_LWS(&pos);
 
if (*pos == ',') {
error = http__item_list_parse(&pos,
http__parse_parameter, first, &params);
if (error != NSERROR_OK && error != NSERROR_NOT_FOUND) {
lwc_string_unref(scheme);
return error;
}
} else {
params = first;
}
 
result = malloc(sizeof(*result));
if (result == NULL) {
http_parameter_list_destroy(params);
lwc_string_unref(scheme);
return NSERROR_NOMEM;
}
 
HTTP__ITEM_INIT(result, NULL, http_destroy_challenge);
result->scheme = scheme;
result->params = params;
 
*challenge = result;
*input = pos;
 
return NSERROR_OK;
}
 
/* See challenge.h for documentation */
const http_challenge *http_challenge_list_iterate(const http_challenge *cur,
lwc_string **scheme, http_parameter **parameters)
{
if (cur == NULL)
return NULL;
 
*scheme = lwc_string_ref(cur->scheme);
*parameters = cur->params;
 
return (http_challenge *) cur->base.next;
}
 
/* See challenge.h for documentation */
void http_challenge_list_destroy(http_challenge *list)
{
http__item_list_destroy(list);
}
 
/contrib/network/netsurf/netsurf/utils/http/challenge.h
0,0 → 1,47
/*
* Copyright 2010 John-Mark Bell <jmb@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
#ifndef NETSURF_UTILS_HTTP_CHALLENGE_H_
#define NETSURF_UTILS_HTTP_CHALLENGE_H_
 
#include <libwapcaplet/libwapcaplet.h>
 
#include "utils/http/parameter.h"
 
typedef struct http_challenge http_challenge;
 
/**
* Iterate over a challenge list
*
* \param cur Pointer to current iteration position, list head to start
* \param scheme Pointer to location to receive challenge scheme
* \param parameters Pointer to location to receive challenge parameters
* \return Pointer to next iteration position, or NULL for end of iteration
*/
const http_challenge *http_challenge_list_iterate(const http_challenge *cur,
lwc_string **scheme, http_parameter **parameters);
 
/**
* Destroy a list of HTTP challenges
*
* \param list List to destroy
*/
void http_challenge_list_destroy(http_challenge *list);
 
#endif
 
/contrib/network/netsurf/netsurf/utils/http/challenge_internal.h
0,0 → 1,27
/*
* Copyright 2010 John-Mark Bell <jmb@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
#ifndef NETSURF_UTILS_HTTP_CHALLENGE_INTERNAL_H_
#define NETSURF_UTILS_HTTP_CHALLENGE_INTERNAL_H_
 
#include "utils/errors.h"
#include "utils/http/challenge.h"
 
nserror http__parse_challenge(const char **input, http_challenge **parameter);
 
#endif
/contrib/network/netsurf/netsurf/utils/http/content-disposition.c
0,0 → 1,78
/*
* Copyright 2010 John-Mark Bell <jmb@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
#include <stdlib.h>
 
#include "utils/http.h"
 
#include "utils/http/generics.h"
#include "utils/http/parameter_internal.h"
#include "utils/http/primitives.h"
 
/* See content-disposition.h for documentation */
nserror http_parse_content_disposition(const char *header_value,
http_content_disposition **result)
{
const char *pos = header_value;
lwc_string *mtype;
http_parameter *params = NULL;
http_content_disposition *cd;
nserror error;
 
/* disposition-type *( ";" parameter ) */
 
http__skip_LWS(&pos);
 
error = http__parse_token(&pos, &mtype);
if (error != NSERROR_OK)
return error;
 
http__skip_LWS(&pos);
 
if (*pos == ';') {
error = http__item_list_parse(&pos,
http__parse_parameter, NULL, &params);
if (error != NSERROR_OK && error != NSERROR_NOT_FOUND) {
lwc_string_unref(mtype);
return error;
}
}
 
cd = malloc(sizeof(*cd));
if (cd == NULL) {
http_parameter_list_destroy(params);
lwc_string_unref(mtype);
return NSERROR_NOMEM;
}
 
cd->disposition_type = mtype;
cd->parameters = params;
 
*result = cd;
 
return NSERROR_OK;
}
 
/* See content-disposition.h for documentation */
void http_content_disposition_destroy(http_content_disposition *victim)
{
lwc_string_unref(victim->disposition_type);
http_parameter_list_destroy(victim->parameters);
free(victim);
}
 
/contrib/network/netsurf/netsurf/utils/http/content-disposition.h
0,0 → 1,49
/*
* Copyright 2010 John-Mark Bell <jmb@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
#ifndef NETSURF_UTILS_HTTP_CONTENT_DISPOSITION_H_
#define NETSURF_UTILS_HTTP_CONTENT_DISPOSITION_H_
 
#include <libwapcaplet/libwapcaplet.h>
 
#include "utils/http/parameter.h"
 
typedef struct http_content_disposition {
lwc_string *disposition_type;
http_parameter *parameters;
} http_content_disposition;
 
/**
* Parse an HTTP Content-Disposition header value
*
* \param header_value Header value to parse
* \param result Pointer to location to receive result
* \return NSERROR_OK on success,
* NSERROR_NOMEM on memory exhaustion
*/
nserror http_parse_content_disposition(const char *header_value,
http_content_disposition **result);
 
/**
* Destroy a content disposition object
*
* \param victim Object to destroy
*/
void http_content_disposition_destroy(http_content_disposition *victim);
 
#endif
/contrib/network/netsurf/netsurf/utils/http/content-type.c
0,0 → 1,128
/*
* Copyright 2010 John-Mark Bell <jmb@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#include "utils/http.h"
 
#include "utils/http/generics.h"
#include "utils/http/parameter_internal.h"
#include "utils/http/primitives.h"
 
/* See content-type.h for documentation */
nserror http_parse_content_type(const char *header_value,
http_content_type **result)
{
const char *pos = header_value;
lwc_string *type;
lwc_string *subtype = NULL;
http_parameter *params = NULL;
char *mime;
size_t mime_len;
lwc_string *imime;
http_content_type *ct;
nserror error;
 
/* type "/" subtype *( ";" parameter ) */
 
http__skip_LWS(&pos);
 
error = http__parse_token(&pos, &type);
if (error != NSERROR_OK)
return error;
 
http__skip_LWS(&pos);
 
if (*pos != '/') {
lwc_string_unref(type);
return NSERROR_NOT_FOUND;
}
 
pos++;
 
http__skip_LWS(&pos);
 
error = http__parse_token(&pos, &subtype);
if (error != NSERROR_OK) {
lwc_string_unref(type);
return error;
}
 
http__skip_LWS(&pos);
 
if (*pos == ';') {
error = http__item_list_parse(&pos,
http__parse_parameter, NULL, &params);
if (error != NSERROR_OK && error != NSERROR_NOT_FOUND) {
lwc_string_unref(subtype);
lwc_string_unref(type);
return error;
}
}
 
/* <type> + <subtype> + '/' */
mime_len = lwc_string_length(type) + lwc_string_length(subtype) + 1;
 
mime = malloc(mime_len + 1);
if (mime == NULL) {
http_parameter_list_destroy(params);
lwc_string_unref(subtype);
lwc_string_unref(type);
return NSERROR_NOMEM;
}
 
sprintf(mime, "%.*s/%.*s",
(int) lwc_string_length(type), lwc_string_data(type),
(int) lwc_string_length(subtype), lwc_string_data(subtype));
 
lwc_string_unref(subtype);
lwc_string_unref(type);
 
if (lwc_intern_string(mime, mime_len, &imime) != lwc_error_ok) {
http_parameter_list_destroy(params);
free(mime);
return NSERROR_NOMEM;
}
 
free(mime);
 
ct = malloc(sizeof(*ct));
if (ct == NULL) {
lwc_string_unref(imime);
http_parameter_list_destroy(params);
return NSERROR_NOMEM;
}
 
ct->media_type = imime;
ct->parameters = params;
 
*result = ct;
 
return NSERROR_OK;
}
 
/* See content-type.h for documentation */
void http_content_type_destroy(http_content_type *victim)
{
lwc_string_unref(victim->media_type);
http_parameter_list_destroy(victim->parameters);
free(victim);
}
 
/contrib/network/netsurf/netsurf/utils/http/content-type.h
0,0 → 1,49
/*
* Copyright 2010 John-Mark Bell <jmb@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
#ifndef NETSURF_UTILS_HTTP_CONTENT_TYPE_H_
#define NETSURF_UTILS_HTTP_CONTENT_TYPE_H_
 
#include <libwapcaplet/libwapcaplet.h>
 
#include "utils/http/parameter.h"
 
typedef struct http_content_type {
lwc_string *media_type;
http_parameter *parameters;
} http_content_type;
 
/**
* Parse an HTTP Content-Type header value
*
* \param header_value Header value to parse
* \param result Pointer to location to receive result
* \return NSERROR_OK on success,
* NSERROR_NOMEM on memory exhaustion
*/
nserror http_parse_content_type(const char *header_value,
http_content_type **result);
 
/**
* Destroy a content type object
*
* \param victim Object to destroy
*/
void http_content_type_destroy(http_content_type *victim);
 
#endif
/contrib/network/netsurf/netsurf/utils/http/generics.c
0,0 → 1,99
/*
* Copyright 2010 John-Mark Bell <jmb@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
#include <stdlib.h>
 
#include "utils/http/generics.h"
#include "utils/http/primitives.h"
 
/**
* Destructor for an item list
*
* \param list List to destroy
*/
void http___item_list_destroy(http__item *list)
{
while (list != NULL) {
http__item *victim = list;
 
list = victim->next;
 
victim->free(victim);
}
}
 
/**
* Parse a list of items
*
* \param input Pointer to current input byte. Updated on exit.
* \param itemparser Pointer to function to parse list items
* \param first Pointer to first item, or NULL.
* \param parameters Pointer to location to receive on-heap parameter list.
* \return NSERROR_OK on success,
* NSERROR_NOMEM on memory exhaustion,
* NSERROR_NOT_FOUND if no items could be parsed
*
* The returned list is owned by the caller
*
* \note Ownership of the \a first item is passed to this function.
*/
nserror http___item_list_parse(const char **input,
http__itemparser itemparser, http__item *first,
http__item **items)
{
const char *pos = *input;
const char separator = *pos;
http__item *item;
http__item *list = first;
nserror error = NSERROR_OK;
 
/* 1*( <separator> <item> ) */
 
while (*pos == separator) {
pos++;
 
http__skip_LWS(&pos);
 
error = itemparser(&pos, &item);
if (error == NSERROR_OK) {
if (list != NULL)
item->next = list;
 
list = item;
 
http__skip_LWS(&pos);
} else if (error != NSERROR_NOT_FOUND) {
/* Permit <separator> LWS <separator> */
break;
}
}
 
if (error != NSERROR_OK && error != NSERROR_NOT_FOUND) {
http__item_list_destroy(list);
} else if (list == NULL) {
error = NSERROR_NOT_FOUND;
} else {
error = NSERROR_OK;
*items = list;
*input = pos;
}
 
return error;
}
 
 
/contrib/network/netsurf/netsurf/utils/http/generics.h
0,0 → 1,56
/*
* Copyright 2010 John-Mark Bell <jmb@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
#ifndef NETSURF_UTILS_HTTP_GENERICS_H_
#define NETSURF_UTILS_HTTP_GENERICS_H_
 
#include "utils/errors.h"
 
/**
* Representation of an item
*/
typedef struct http__item {
struct http__item *next; /**< Next item in list, or NULL */
 
void (*free)(struct http__item *self); /**< Item destructor */
} http__item;
 
#define HTTP__ITEM_INIT(item, n, f) \
((http__item *) (item))->next = (http__item *) (n); \
((http__item *) (item))->free = (void (*)(http__item *)) (f)
 
/**
* Type of an item parser
*/
typedef nserror (*http__itemparser)(const char **input, http__item **item);
 
 
void http___item_list_destroy(http__item *list);
#define http__item_list_destroy(l) \
http___item_list_destroy((http__item *) (l))
 
nserror http___item_list_parse(const char **input,
http__itemparser itemparser, http__item *first,
http__item **items);
#define http__item_list_parse(i, p, f, r) \
http___item_list_parse((i), \
(http__itemparser) (p), \
(http__item *) (f), \
(http__item **) (void *) (r))
 
#endif
/contrib/network/netsurf/netsurf/utils/http/make.http
0,0 → 1,22
CFLAGS += -O2
NETSURF_FB_FRONTEND := sdl
NETSURF_FB_FONTLIB := internal
 
NETSURF_FRAMEBUFFER_BIN := $(PREFIX)/bin/
 
# Default resource install path
NETSURF_FRAMEBUFFER_RESOURCES := $(PREFIX)/share/netsurf/
 
# Default framebuffer search path
NETSURF_FB_RESPATH := $${HOME}/.netsurf/:$${NETSURFRES}:$(NETSURF_FRAMEBUFFER_RESOURCES):./framebuffer/res
 
# freetype compiled in font serch path
NETSURF_FB_FONTPATH := /usr/share/fonts/truetype/ttf-dejavu:/usr/share/fonts/truetype/msttcorefonts
OBJS := challenge.o generics.o primitives.o parameter.o \
content-disposition.o content-type.o www-authenticate.o
 
 
OUTFILE = TEST.o
CFLAGS += -I ../include/ -I ../ -I../../ -I./ -I/home/sourcerer/kos_src/newenginek/kolibri/include
include $(MENUETDEV)/makefiles/Makefile_for_o_lib
/contrib/network/netsurf/netsurf/utils/http/parameter.c
0,0 → 1,153
/*
* Copyright 2010 John-Mark Bell <jmb@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
#include <stdlib.h>
#include <string.h>
 
#include "utils/http.h"
 
#include "utils/http/generics.h"
#include "utils/http/parameter_internal.h"
#include "utils/http/primitives.h"
 
/**
* Representation of an HTTP parameter
*/
struct http_parameter {
http__item base;
 
lwc_string *name; /**< Parameter name */
lwc_string *value; /**< Parameter value */
};
 
/**
* Destructor for an HTTP parameter
*
* \param self Parameter to destroy
*/
static void http_destroy_parameter(http_parameter *self)
{
lwc_string_unref(self->name);
lwc_string_unref(self->value);
free(self);
}
 
/**
* Parse an HTTP parameter
*
* \param input Pointer to current input byte. Updated on exit.
* \param parameter Pointer to location to receive on-heap parameter.
* \return NSERROR_OK on success,
* NSERROR_NOMEM on memory exhaustion,
* NSERROR_NOT_FOUND if no parameter could be parsed
*
* The returned parameter is owned by the caller.
*/
nserror http__parse_parameter(const char **input, http_parameter **parameter)
{
const char *pos = *input;
lwc_string *name;
lwc_string *value;
http_parameter *param;
nserror error;
 
/* token "=" ( token | quoted-string ) */
 
error = http__parse_token(&pos, &name);
if (error != NSERROR_OK)
return error;
 
http__skip_LWS(&pos);
 
if (*pos != '=') {
lwc_string_unref(name);
return NSERROR_NOT_FOUND;
}
 
pos++;
 
http__skip_LWS(&pos);
 
if (*pos == '"')
error = http__parse_quoted_string(&pos, &value);
else
error = http__parse_token(&pos, &value);
 
if (error != NSERROR_OK) {
lwc_string_unref(name);
return error;
}
 
param = malloc(sizeof(*param));
if (param == NULL) {
lwc_string_unref(value);
lwc_string_unref(name);
return NSERROR_NOMEM;
}
 
HTTP__ITEM_INIT(param, NULL, http_destroy_parameter);
param->name = name;
param->value = value;
 
*parameter = param;
*input = pos;
 
return NSERROR_OK;
}
 
/* See parameter.h for documentation */
nserror http_parameter_list_find_item(const http_parameter *list,
lwc_string *name, lwc_string **value)
{
bool match;
 
while (list != NULL) {
if (lwc_string_caseless_isequal(name, list->name,
&match) == lwc_error_ok && match)
break;
 
list = (http_parameter *) list->base.next;
}
 
if (list == NULL)
return NSERROR_NOT_FOUND;
 
*value = lwc_string_ref(list->value);
 
return NSERROR_OK;
}
 
/* See parameter.h for documentation */
const http_parameter *http_parameter_list_iterate(const http_parameter *cur,
lwc_string **name, lwc_string **value)
{
if (cur == NULL)
return NULL;
 
*name = lwc_string_ref(cur->name);
*value = lwc_string_ref(cur->value);
 
return (http_parameter *) cur->base.next;
}
 
/* See parameter.h for documentation */
void http_parameter_list_destroy(http_parameter *list)
{
http__item_list_destroy(list);
}
 
/contrib/network/netsurf/netsurf/utils/http/parameter.h
0,0 → 1,59
/*
* Copyright 2010 John-Mark Bell <jmb@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
#ifndef NETSURF_UTILS_HTTP_PARAMETER_H_
#define NETSURF_UTILS_HTTP_PARAMETER_H_
 
#include <libwapcaplet/libwapcaplet.h>
 
#include "utils/errors.h"
 
typedef struct http_parameter http_parameter;
 
/**
* Find a named item in an HTTP parameter list
*
* \param list List to search
* \param name Name of item to search for
* \param value Pointer to location to receive value
* \return NSERROR_OK on success,
* NSERROR_NOT_FOUND if requested item does not exist
*/
nserror http_parameter_list_find_item(const http_parameter *list,
lwc_string *name, lwc_string **value);
 
/**
* Iterate over a parameter list
*
* \param cur Pointer to current iteration position, list head to start
* \param name Pointer to location to receive item name
* \param value Pointer to location to receive item value
* \return Pointer to next iteration position, or NULL for end of iteration
*/
const http_parameter *http_parameter_list_iterate(const http_parameter *cur,
lwc_string **name, lwc_string **value);
 
/**
* Destroy a list of HTTP parameters
*
* \param list List to destroy
*/
void http_parameter_list_destroy(http_parameter *list);
 
#endif
 
/contrib/network/netsurf/netsurf/utils/http/parameter_internal.h
0,0 → 1,27
/*
* Copyright 2010 John-Mark Bell <jmb@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
#ifndef NETSURF_UTILS_HTTP_PARAMETER_INTERNAL_H_
#define NETSURF_UTILS_HTTP_PARAMETER_INTERNAL_H_
 
#include "utils/errors.h"
#include "utils/http/parameter.h"
 
nserror http__parse_parameter(const char **input, http_parameter **parameter);
 
#endif
/contrib/network/netsurf/netsurf/utils/http/primitives.c
0,0 → 1,146
/*
* Copyright 2010 John-Mark Bell <jmb@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
#include <inttypes.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
 
#include "utils/http/primitives.h"
 
/**
* Skip past linear whitespace in input
*
* \param input Pointer to current input byte. Updated on exit.
*/
void http__skip_LWS(const char **input)
{
const char *pos = *input;
 
while (*pos == ' ' || *pos == '\t')
pos++;
 
*input = pos;
}
 
/**
* Determine if a character is valid for an HTTP token
*
* \param c Character to consider
* \return True if character is valid, false otherwise
*/
static bool http_is_token_char(uint8_t c)
{
/* [ 32 - 126 ] except ()<>@,;:\"/[]?={} SP HT */
 
if (c <= ' ' || 126 < c)
return false;
 
return (strchr("()<>@,;:\\\"/[]?={}", c) == NULL);
}
 
/**
* Parse an HTTP token
*
* \param input Pointer to current input byte. Updated on exit.
* \param value Pointer to location to receive on-heap token value.
* \return NSERROR_OK on success,
* NSERROR_NOMEM on memory exhaustion,
* NSERROR_NOT_FOUND if no token could be parsed
*
* The returned value is owned by the caller
*/
nserror http__parse_token(const char **input, lwc_string **value)
{
const uint8_t *start = (const uint8_t *) *input;
const uint8_t *end;
lwc_string *token;
 
end = start;
while (http_is_token_char(*end))
end++;
 
if (end == start)
return NSERROR_NOT_FOUND;
 
if (lwc_intern_string((const char *) start,
end - start, &token) != lwc_error_ok)
return NSERROR_NOMEM;
 
*value = token;
*input = (const char *) end;
 
return NSERROR_OK;
}
 
/**
* Parse an HTTP quoted-string
*
* \param input Pointer to current input byte. Updated on exit.
* \param value Pointer to location to receive on-heap string value.
* \return NSERROR_OK on success,
* NSERROR_NOMEM on memory exhaustion,
* NSERROR_NOT_FOUND if no string could be parsed
*
* The returned value is owned by the caller
*/
nserror http__parse_quoted_string(const char **input, lwc_string **value)
{
const uint8_t *start = (const uint8_t *) *input;
const uint8_t *end;
uint8_t c;
lwc_string *string_value;
 
/* <"> *( qdtext | quoted-pair ) <">
* qdtext = any TEXT except <">
* quoted-pair = "\" CHAR
* TEXT = [ HT, CR, LF, 32-126, 128-255 ]
* CHAR = [ 0 - 127 ]
*
* \todo TEXT may contain non 8859-1 chars encoded per RFC 2047
* \todo Support quoted-pairs
*/
 
if (*start != '"')
return NSERROR_NOT_FOUND;
 
end = start = start + 1;
 
c = *end;
while (c == '\t' || c == '\r' || c == '\n' ||
c == ' ' || c == '!' ||
('#' <= c && c <= 126) || c > 127) {
end++;
c = *end;
}
 
if (*end != '"')
return NSERROR_NOT_FOUND;
 
if (lwc_intern_string((const char *) start, end - start,
&string_value) != lwc_error_ok)
return NSERROR_NOMEM;
 
*value = string_value;
 
*input = (const char *) end + 1;
 
return NSERROR_OK;
}
 
 
/contrib/network/netsurf/netsurf/utils/http/primitives.h
0,0 → 1,32
/*
* Copyright 2010 John-Mark Bell <jmb@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
#ifndef NETSURF_UTILS_HTTP_PRIMITIVES_H_
#define NETSURF_UTILS_HTTP_PRIMITIVES_H_
 
#include <libwapcaplet/libwapcaplet.h>
 
#include "utils/errors.h"
 
void http__skip_LWS(const char **input);
 
nserror http__parse_token(const char **input, lwc_string **value);
 
nserror http__parse_quoted_string(const char **input, lwc_string **value);
 
#endif
/contrib/network/netsurf/netsurf/utils/http/www-authenticate.c
0,0 → 1,75
/*
* Copyright 2010 John-Mark Bell <jmb@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
#include <stdlib.h>
 
#include "utils/http/challenge_internal.h"
#include "utils/http/generics.h"
#include "utils/http/parameter_internal.h"
#include "utils/http/primitives.h"
#include "utils/http/www-authenticate.h"
 
/* See www-authenticate.h for documentation */
nserror http_parse_www_authenticate(const char *header_value,
http_www_authenticate **result)
{
const char *pos = header_value;
http_challenge *first = NULL;
http_challenge *list = NULL;
http_www_authenticate *wa;
nserror error;
 
/* 1#challenge */
 
http__skip_LWS(&pos);
 
error = http__parse_challenge(&pos, &first);
if (error != NSERROR_OK)
return error;
 
http__skip_LWS(&pos);
 
if (*pos == ',') {
error = http__item_list_parse(&pos,
http__parse_challenge, first, &list);
if (error != NSERROR_OK && error != NSERROR_NOT_FOUND)
return error;
} else {
list = first;
}
 
wa = malloc(sizeof(*wa));
if (wa == NULL) {
http_challenge_list_destroy(list);
return NSERROR_NOMEM;
}
 
wa->challenges = list;
 
*result = wa;
 
return NSERROR_OK;
}
 
/* See www-authenticate.h for documentation */
void http_www_authenticate_destroy(http_www_authenticate *victim)
{
http_challenge_list_destroy(victim->challenges);
free(victim);
}
 
/contrib/network/netsurf/netsurf/utils/http/www-authenticate.h
0,0 → 1,48
/*
* Copyright 2010 John-Mark Bell <jmb@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
#ifndef NETSURF_UTILS_HTTP_WWW_AUTHENTICATE_H_
#define NETSURF_UTILS_HTTP_WWW_AUTHENTICATE_H_
 
#include <libwapcaplet/libwapcaplet.h>
 
#include "utils/http/challenge.h"
 
typedef struct http_www_authenticate {
http_challenge *challenges;
} http_www_authenticate;
 
/**
* Parse an HTTP WWW-Authenticate header value
*
* \param header_value Header value to parse
* \param result Pointer to location to receive result
* \return NSERROR_OK on success,
* NSERROR_NOMEM on memory exhaustion
*/
nserror http_parse_www_authenticate(const char *header_value,
http_www_authenticate **result);
 
/**
* Destroy a www authenticate object
*
* \param victim Object to destroy
*/
void http_www_authenticate_destroy(http_www_authenticate *victim);
 
#endif
/contrib/network/netsurf/netsurf/utils/http.h
0,0 → 1,35
/*
* Copyright 2010 John-Mark Bell <jmb@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
/** \file
* HTTP header parsing functions
*/
 
#ifndef NETSURF_UTILS_HTTP_H_
#define NETSURF_UTILS_HTTP_H_
 
#include <libwapcaplet/libwapcaplet.h>
 
#include "utils/errors.h"
 
#include "utils/http/content-disposition.h"
#include "utils/http/content-type.h"
#include "utils/http/www-authenticate.h"
 
#endif
 
/contrib/network/netsurf/netsurf/utils/libdom.c
0,0 → 1,379
/*
* Copyright 2012 Vincent Sanders <vince@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
/** \file
* libdom utilities (implementation).
*/
 
#include <assert.h>
#include <dom/dom.h>
 
#include "utils/config.h"
#include "utils/log.h"
 
#include "utils/libdom.h"
 
/* exported interface documented in libdom.h */
bool libdom_treewalk(dom_node *root,
bool (*callback)(dom_node *node, dom_string *name, void *ctx),
void *ctx)
{
dom_node *node;
bool result = true;
 
node = dom_node_ref(root); /* tree root */
 
while (node != NULL) {
dom_node *next = NULL;
dom_node_type type;
dom_string *name;
dom_exception exc;
 
exc = dom_node_get_first_child(node, &next);
if (exc != DOM_NO_ERR) {
dom_node_unref(node);
break;
}
 
if (next != NULL) { /* 1. children */
dom_node_unref(node);
node = next;
} else {
exc = dom_node_get_next_sibling(node, &next);
if (exc != DOM_NO_ERR) {
dom_node_unref(node);
break;
}
 
if (next != NULL) { /* 2. siblings */
dom_node_unref(node);
node = next;
} else { /* 3. ancestor siblings */
while (node != NULL) {
exc = dom_node_get_next_sibling(node,
&next);
if (exc != DOM_NO_ERR) {
dom_node_unref(node);
node = NULL;
break;
}
 
if (next != NULL) {
dom_node_unref(next);
break;
}
 
exc = dom_node_get_parent_node(node,
&next);
if (exc != DOM_NO_ERR) {
dom_node_unref(node);
node = NULL;
break;
}
 
dom_node_unref(node);
node = next;
}
 
if (node == NULL)
break;
 
exc = dom_node_get_next_sibling(node, &next);
if (exc != DOM_NO_ERR) {
dom_node_unref(node);
break;
}
 
dom_node_unref(node);
node = next;
}
}
 
assert(node != NULL);
 
exc = dom_node_get_node_type(node, &type);
if ((exc != DOM_NO_ERR) || (type != DOM_ELEMENT_NODE))
continue;
 
exc = dom_node_get_node_name(node, &name);
if (exc != DOM_NO_ERR)
continue;
 
result = callback(node, name, ctx);
 
dom_string_unref(name);
 
if (result == false) {
break; /* callback caused early termination */
}
 
}
return result;
}
 
 
/* libdom_treewalk context for libdom_find_element */
struct find_element_ctx {
lwc_string *search;
dom_node *found;
};
 
/* libdom_treewalk callback for libdom_find_element */
static bool libdom_find_element_callback(dom_node *node, dom_string *name,
void *ctx)
{
struct find_element_ctx *data = ctx;
 
if (dom_string_caseless_lwc_isequal(name, data->search)) {
/* Found element */
data->found = node;
return false; /* Discontinue search */
}
 
return true; /* Continue search */
}
 
 
/* exported interface documented in libdom.h */
dom_node *libdom_find_element(dom_node *node, lwc_string *element_name)
{
struct find_element_ctx data;
 
assert(element_name != NULL);
 
if (node == NULL)
return NULL;
 
data.search = element_name;
data.found = NULL;
 
libdom_treewalk(node, libdom_find_element_callback, &data);
 
return data.found;
}
 
 
/* exported interface documented in libdom.h */
dom_node *libdom_find_first_element(dom_node *parent, lwc_string *element_name)
{
dom_node *element;
dom_exception exc;
dom_string *node_name = NULL;
dom_node_type node_type;
dom_node *next_node;
 
exc = dom_node_get_first_child(parent, &element);
if ((exc != DOM_NO_ERR) || (element == NULL)) {
return NULL;
}
 
/* find first node thats a element */
do {
exc = dom_node_get_node_type(element, &node_type);
 
if ((exc == DOM_NO_ERR) && (node_type == DOM_ELEMENT_NODE)) {
exc = dom_node_get_node_name(element, &node_name);
if ((exc == DOM_NO_ERR) && (node_name != NULL)) {
if (dom_string_caseless_lwc_isequal(node_name,
element_name)) {
dom_string_unref(node_name);
break;
}
dom_string_unref(node_name);
}
}
 
exc = dom_node_get_next_sibling(element, &next_node);
dom_node_unref(element);
if (exc == DOM_NO_ERR) {
element = next_node;
} else {
element = NULL;
}
} while (element != NULL);
 
return element;
}
 
/* exported interface documented in libdom.h */
void libdom_iterate_child_elements(dom_node *parent,
libdom_iterate_cb cb, void *ctx)
{
dom_nodelist *children;
uint32_t index, num_children;
dom_exception error;
 
error = dom_node_get_child_nodes(parent, &children);
if (error != DOM_NO_ERR || children == NULL)
return;
 
error = dom_nodelist_get_length(children, &num_children);
if (error != DOM_NO_ERR) {
dom_nodelist_unref(children);
return;
}
 
for (index = 0; index < num_children; index++) {
dom_node *child;
dom_node_type type;
 
error = dom_nodelist_item(children, index, &child);
if (error != DOM_NO_ERR) {
dom_nodelist_unref(children);
return;
}
 
error = dom_node_get_node_type(child, &type);
if (error == DOM_NO_ERR && type == DOM_ELEMENT_NODE) {
if (cb(child, ctx) == false) {
dom_node_unref(child);
dom_nodelist_unref(children);
return;
}
}
 
dom_node_unref(child);
}
 
dom_nodelist_unref(children);
}
 
/* exported interface documented in libdom.h */
nserror libdom_hubbub_error_to_nserror(dom_hubbub_error error)
{
switch (error) {
 
/* HUBBUB_REPROCESS is not handled here because it can
* never occur outside the hubbub treebuilder
*/
 
case DOM_HUBBUB_OK:
/* parsed ok */
return NSERROR_OK;
 
case (DOM_HUBBUB_HUBBUB_ERR | HUBBUB_PAUSED):
/* hubbub input paused */
return NSERROR_OK;
 
case DOM_HUBBUB_NOMEM:
/* out of memory error from DOM */
return NSERROR_NOMEM;
 
case DOM_HUBBUB_BADPARM:
/* Bad parameter passed to creation */
return NSERROR_BAD_PARAMETER;
 
case DOM_HUBBUB_DOM:
/* DOM call returned error */
return NSERROR_DOM;
 
case (DOM_HUBBUB_HUBBUB_ERR | HUBBUB_ENCODINGCHANGE):
/* encoding changed */
return NSERROR_ENCODING_CHANGE;
 
case (DOM_HUBBUB_HUBBUB_ERR | HUBBUB_NOMEM):
/* out of memory error from parser */
return NSERROR_NOMEM;
 
case (DOM_HUBBUB_HUBBUB_ERR | HUBBUB_BADPARM):
return NSERROR_BAD_PARAMETER;
 
case (DOM_HUBBUB_HUBBUB_ERR | HUBBUB_INVALID):
return NSERROR_INVALID;
 
case (DOM_HUBBUB_HUBBUB_ERR | HUBBUB_FILENOTFOUND):
return NSERROR_NOT_FOUND;
 
case (DOM_HUBBUB_HUBBUB_ERR | HUBBUB_NEEDDATA):
return NSERROR_NEED_DATA;
 
case (DOM_HUBBUB_HUBBUB_ERR | HUBBUB_BADENCODING):
return NSERROR_BAD_ENCODING;
 
case (DOM_HUBBUB_HUBBUB_ERR | HUBBUB_UNKNOWN):
/* currently only generated by the libdom hubbub binding */
return NSERROR_DOM;
default:
/* unknown error */
/** @todo better error handling and reporting */
return NSERROR_UNKNOWN;
}
return NSERROR_UNKNOWN;
}
 
 
static void ignore_dom_msg(uint32_t severity, void *ctx, const char *msg, ...)
{
}
 
/* exported interface documented in libdom.h */
nserror libdom_parse_file(const char *filename, const char *encoding, dom_document **doc)
{
dom_hubbub_parser_params parse_params;
dom_hubbub_error error;
dom_hubbub_parser *parser;
dom_document *document;
FILE *fp = NULL;
#define BUF_SIZE 512
uint8_t buf[BUF_SIZE];
 
fp = fopen(filename, "r");
if (fp == NULL) {
return NSERROR_NOT_FOUND;
}
 
parse_params.enc = encoding;
parse_params.fix_enc = false;
parse_params.enable_script = false;
parse_params.msg = ignore_dom_msg;
parse_params.script = NULL;
parse_params.ctx = NULL;
parse_params.daf = NULL;
 
error = dom_hubbub_parser_create(&parse_params, &parser, &document);
if (error != DOM_HUBBUB_OK) {
fclose(fp);
return libdom_hubbub_error_to_nserror(error);
}
 
while (feof(fp) == 0) {
size_t read = fread(buf, sizeof(buf[0]), BUF_SIZE, fp);
 
error = dom_hubbub_parser_parse_chunk(parser, buf, read);
if (error != DOM_HUBBUB_OK) {
dom_node_unref(document);
dom_hubbub_parser_destroy(parser);
fclose(fp);
return NSERROR_DOM;
}
}
 
error = dom_hubbub_parser_completed(parser);
if (error != DOM_HUBBUB_OK) {
dom_node_unref(document);
dom_hubbub_parser_destroy(parser);
fclose(fp);
return libdom_hubbub_error_to_nserror(error);
}
 
dom_hubbub_parser_destroy(parser);
fclose(fp);
 
*doc = document;
return NSERROR_OK;
}
/contrib/network/netsurf/netsurf/utils/libdom.h
0,0 → 1,80
/*
* Copyright 2011 John-Mark Bell <jmb@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
 
/** \file
* libdom utilities (implementation).
*/
 
#ifndef NETSURF_UTILS_LIBDOM_H_
#define NETSURF_UTILS_LIBDOM_H_
 
#include <stdbool.h>
 
#include <dom/dom.h>
 
#include <dom/bindings/hubbub/parser.h>
#include <dom/bindings/hubbub/errors.h>
 
/**
* depth-first walk the dom calling callback for each element
*
* \param root the dom node to use as the root of the tree walk
* \return true if all nodes were examined, false if the callback terminated
* the walk early.
*/
bool libdom_treewalk(dom_node *root,
bool (*callback)(dom_node *node, dom_string *name, void *ctx),
void *ctx);
 
/**
* Search the descendants of a node for an element.
*
* \param node dom_node to search children of, or NULL
* \param element_name name of element to find
* \return first child of node which is an element and matches name, or
* NULL if not found or parameter node is NULL
*/
dom_node *libdom_find_element(dom_node *node, lwc_string *element_name);
 
/**
* Search children of a node for first named element
* \param parent dom_node to search children of, or NULL
* \param element_name name of element to find
* \return first child of node which is an element and matches name, or
* NULL if not found or parameter node is NULL
*/
dom_node *libdom_find_first_element(dom_node *parent, lwc_string *element_name);
 
typedef bool (*libdom_iterate_cb)(dom_node *node, void *ctx);
 
void libdom_iterate_child_elements(dom_node *parent,
libdom_iterate_cb cb, void *ctx);
 
nserror libdom_parse_file(const char *filename, const char *encoding,
dom_document **doc);
 
/**
* Convert libdom hubbub binding errors to nserrors.
*
* \param error The hubbub binding error to convert
* \return The appropriate nserror
*/
nserror libdom_hubbub_error_to_nserror(dom_hubbub_error error);
 
#endif
/contrib/network/netsurf/netsurf/utils/locale.c
0,0 → 1,53
/*
* Copyright 2008 John-Mark Bell <jmb@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
/** \file
* Locale-specific variants of various routines (implementation)
*/
 
#include <ctype.h>
#include <locale.h>
 
#include "utils/locale.h"
 
/* <ctype.h> functions */
#define MAKELSCTYPE(x) int ls_##x(int c) \
{ \
int ret; \
setlocale(LC_ALL, ""); \
ret = x(c); \
setlocale(LC_ALL, "C"); \
return ret; \
}
 
MAKELSCTYPE(isalpha)
MAKELSCTYPE(isalnum)
MAKELSCTYPE(iscntrl)
MAKELSCTYPE(isdigit)
MAKELSCTYPE(isgraph)
MAKELSCTYPE(islower)
MAKELSCTYPE(isprint)
MAKELSCTYPE(ispunct)
MAKELSCTYPE(isspace)
MAKELSCTYPE(isupper)
MAKELSCTYPE(isxdigit)
MAKELSCTYPE(tolower)
MAKELSCTYPE(toupper)
 
#undef MAKELSCTYPE
 
/contrib/network/netsurf/netsurf/utils/locale.h
0,0 → 1,42
/*
* Copyright 2008 John-Mark Bell <jmb@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
/** \file
* Locale-specific variants of various routines (interface)
*/
 
#ifndef _NETSURF_UTILS_LOCALE_H_
#define _NETSURF_UTILS_LOCALE_H_
 
/* <ctype.h> functions */
int ls_isalpha(int c);
int ls_isalnum(int c);
int ls_iscntrl(int c);
int ls_isdigit(int c);
int ls_isgraph(int c);
int ls_islower(int c);
int ls_isprint(int c);
int ls_ispunct(int c);
int ls_isspace(int c);
int ls_isupper(int c);
int ls_isxdigit(int c);
int ls_tolower(int c);
int ls_toupper(int c);
 
#endif
 
/contrib/network/netsurf/netsurf/utils/log.c
0,0 → 1,122
/*
* Copyright 2007 Rob Kendrick <rjek@netsurf-browser.org>
* Copyright 2004-2007 James Bursa <bursa@users.sourceforge.net>
* Copyright 2003 Phil Mellor <monkeyson@users.sourceforge.net>
* Copyright 2003 John M Bell <jmb202@ecs.soton.ac.uk>
* Copyright 2004 John Tytgat <joty@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
#include <stdarg.h>
#include <stdio.h>
#include <sys/time.h>
#include "desktop/netsurf.h"
 
#include "utils/log.h"
 
nserror nslog_init(nslog_ensure_t *ensure, int *pargc, char **argv)
{
nserror ret = NSERROR_OK;
 
if (((*pargc) > 1) &&
(argv[1][0] == '-') &&
(argv[1][1] == 'v') &&
(argv[1][2] == 0)) {
int argcmv;
for (argcmv = 2; argcmv < (*pargc); argcmv++) {
argv[argcmv - 1] = argv[argcmv];
}
(*pargc)--;
 
/* ensure we actually show logging */
verbose_log = true;
/* ensure stderr is available */
if (ensure != NULL) {
if (ensure(stderr) == false) {
/* failed to ensure output */
ret = NSERROR_INIT_FAILED;
}
}
}
return ret;
}
 
#ifndef NDEBUG
 
/* Subtract the `struct timeval' values X and Y,
storing the result in RESULT.
Return 1 if the difference is negative, otherwise 0.
*/
 
static int
timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y)
{
/* Perform the carry for the later subtraction by updating y. */
if (x->tv_usec < y->tv_usec) {
int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
y->tv_usec -= 1000000 * nsec;
y->tv_sec += nsec;
}
if (x->tv_usec - y->tv_usec > 1000000) {
int nsec = (x->tv_usec - y->tv_usec) / 1000000;
y->tv_usec += 1000000 * nsec;
y->tv_sec -= nsec;
}
 
/* Compute the time remaining to wait.
tv_usec is certainly positive. */
result->tv_sec = x->tv_sec - y->tv_sec;
result->tv_usec = x->tv_usec - y->tv_usec;
 
/* Return 1 if result is negative. */
return x->tv_sec < y->tv_sec;
}
 
const char *nslog_gettime(void)
{
static struct timeval start_tv;
static char buff[32];
 
struct timeval tv;
struct timeval now_tv;
 
if (!timerisset(&start_tv)) {
gettimeofday(&start_tv, NULL);
}
gettimeofday(&now_tv, NULL);
 
timeval_subtract(&tv, &now_tv, &start_tv);
 
snprintf(buff, sizeof(buff),"(%ld.%06ld)",
(long)tv.tv_sec, (long)tv.tv_usec);
 
return buff;
}
 
void nslog_log(const char *format, ...)
{
va_list ap;
 
va_start(ap, format);
 
vfprintf(stderr, format, ap);
 
va_end(ap);
}
 
#endif
 
/contrib/network/netsurf/netsurf/utils/log.h
0,0 → 1,78
/*
* Copyright 2003 James Bursa <bursa@users.sourceforge.net>
* Copyright 2004 John Tytgat <joty@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
#ifndef _NETSURF_LOG_H_
#define _NETSURF_LOG_H_
 
#include <stdio.h>
#include "desktop/netsurf.h"
#include "utils/errors.h"
 
/**
* Ensures the FILE handle is available to write logging to.
*
* This is provided by the frontends if required
*/
typedef bool(nslog_ensure_t)(FILE *fptr);
 
/**
* Initialise the logging system.
*
* Sets up everything required for logging. Processes the argv passed
* to remove the -v switch for verbose logging. If necessary ensures
* the output file handle is available.
*/
extern nserror nslog_init(nslog_ensure_t *ensure, int *pargc, char **argv);
 
#ifdef NDEBUG
# define LOG(x) ((void) 0)
#else
 
/**
* Obtain a formatted string suitable for prepending to a log message
*
* \return formatted string of the time since first log call
*/
extern const char *nslog_gettime(void);
extern void nslog_log(const char *format, ...);
 
# ifdef __GNUC__
# define LOG_FN __PRETTY_FUNCTION__
# define LOG_LN __LINE__
# elif defined(__CC_NORCROFT)
# define LOG_FN __func__
# define LOG_LN __LINE__
# else
# define LOG_FN ""
# define LOG_LN __LINE__
# endif
 
#define LOG(x) \
do { \
if (verbose_log) { \
nslog_log("%s " __FILE__ " %s %i: ", \
nslog_gettime(), LOG_FN, LOG_LN); \
nslog_log x; \
nslog_log("\n"); \
} \
} while(0)
 
#endif
 
#endif
/contrib/network/netsurf/netsurf/utils/make.utils
0,0 → 1,23
CFLAGS += -O2
NETSURF_FB_FRONTEND := sdl
NETSURF_FB_FONTLIB := internal
 
NETSURF_FRAMEBUFFER_BIN := $(PREFIX)/bin/
 
# Default resource install path
NETSURF_FRAMEBUFFER_RESOURCES := $(PREFIX)/share/netsurf/
 
# Default framebuffer search path
NETSURF_FB_RESPATH := $${HOME}/.netsurf/:$${NETSURFRES}:$(NETSURF_FRAMEBUFFER_RESOURCES):./framebuffer/res
 
# freetype compiled in font serch path
NETSURF_FB_FONTPATH := /usr/share/fonts/truetype/ttf-dejavu:/usr/share/fonts/truetype/msttcorefonts
OBJS := base64.o corestrings.o filename.o filepath.o hashtable.o \
libdom.o locale.o log.o messages.o nsurl.o talloc.o url.o \
utf8.o utils.o useragent.o
 
 
OUTFILE = TEST.o
CFLAGS += -I ../include/ -I ../ -I../../ -I./ -I/home/sourcerer/kos_src/newenginek/kolibri/include
include $(MENUETDEV)/makefiles/Makefile_for_o_lib
/contrib/network/netsurf/netsurf/utils/memanalyze.pl
0,0 → 1,380
#!/usr/bin/env perl
#
# Example input:
#
# MEM mprintf.c:1094 malloc(32) = e5718
# MEM mprintf.c:1103 realloc(e5718, 64) = e6118
# MEM sendf.c:232 free(f6520)
 
my $mallocs=0;
my $callocs=0;
my $reallocs=0;
my $strdups=0;
my $showlimit;
 
while(1) {
if($ARGV[0] eq "-v") {
$verbose=1;
shift @ARGV;
}
elsif($ARGV[0] eq "-t") {
$trace=1;
shift @ARGV;
}
elsif($ARGV[0] eq "-l") {
# only show what alloc that caused a memlimit failure
$showlimit=1;
shift @ARGV;
}
else {
last;
}
}
 
my $maxmem;
 
sub newtotal {
my ($newtot)=@_;
# count a max here
 
if($newtot > $maxmem) {
$maxmem= $newtot;
}
}
 
my $file = $ARGV[0];
 
if(! -f $file) {
print "Usage: memanalyze.pl [options] <dump file>\n",
"Options:\n",
" -l memlimit failure displayed\n",
" -v Verbose\n",
" -t Trace\n";
exit;
}
 
open(FILE, "<$file");
 
if($showlimit) {
while(<FILE>) {
if(/^LIMIT.*memlimit$/) {
print $_;
last;
}
}
close(FILE);
exit;
}
 
 
 
while(<FILE>) {
chomp $_;
$line = $_;
 
if($line =~ /^LIMIT ([^ ]*):(\d*) (.*)/) {
# new memory limit test prefix
my $i = $3;
my ($source, $linenum) = ($1, $2);
if($trace && ($i =~ /([^ ]*) reached memlimit/)) {
print "LIMIT: $1 returned error at $source:$linenum\n";
}
}
elsif($line =~ /^MEM ([^ ]*):(\d*) (.*)/) {
# generic match for the filename+linenumber
$source = $1;
$linenum = $2;
$function = $3;
 
if($function =~ /free\(0x([0-9a-f]*)/) {
$addr = $1;
if(!exists $sizeataddr{$addr}) {
print "FREE ERROR: No memory allocated: $line\n";
}
elsif(-1 == $sizeataddr{$addr}) {
print "FREE ERROR: Memory freed twice: $line\n";
print "FREE ERROR: Previously freed at: ".$getmem{$addr}."\n";
}
else {
$totalmem -= $sizeataddr{$addr};
if($trace) {
print "FREE: malloc at ".$getmem{$addr}." is freed again at $source:$linenum\n";
printf("FREE: %d bytes freed, left allocated: $totalmem bytes\n", $sizeataddr{$addr});
}
 
newtotal($totalmem);
$frees++;
 
$sizeataddr{$addr}=-1; # set -1 to mark as freed
$getmem{$addr}="$source:$linenum";
 
}
}
elsif($function =~ /malloc\((\d*)\) = 0x([0-9a-f]*)/) {
$size = $1;
$addr = $2;
 
if($sizeataddr{$addr}>0) {
# this means weeeeeirdo
print "Mixed debug compile, rebuild curl now\n";
}
 
$sizeataddr{$addr}=$size;
$totalmem += $size;
 
if($trace) {
print "MALLOC: malloc($size) at $source:$linenum",
" makes totally $totalmem bytes\n";
}
 
newtotal($totalmem);
$mallocs++;
 
$getmem{$addr}="$source:$linenum";
}
elsif($function =~ /calloc\((\d*),(\d*)\) = 0x([0-9a-f]*)/) {
$size = $1*$2;
$addr = $3;
 
$arg1 = $1;
$arg2 = $2;
 
if($sizeataddr{$addr}>0) {
# this means weeeeeirdo
print "Mixed debug compile, rebuild curl now\n";
}
 
$sizeataddr{$addr}=$size;
$totalmem += $size;
 
if($trace) {
print "CALLOC: calloc($arg1,$arg2) at $source:$linenum",
" makes totally $totalmem bytes\n";
}
 
newtotal($totalmem);
$callocs++;
 
$getmem{$addr}="$source:$linenum";
}
elsif($function =~ /realloc\(0x([0-9a-f]*), (\d*)\) = 0x([0-9a-f]*)/) {
$oldaddr = $1;
$newsize = $2;
$newaddr = $3;
 
$totalmem -= $sizeataddr{$oldaddr};
if($trace) {
printf("REALLOC: %d less bytes and ", $sizeataddr{$oldaddr});
}
$sizeataddr{$oldaddr}=0;
 
$totalmem += $newsize;
$sizeataddr{$newaddr}=$newsize;
 
if($trace) {
printf("%d more bytes ($source:$linenum)\n", $newsize);
}
 
newtotal($totalmem);
$reallocs++;
 
$getmem{$oldaddr}="";
$getmem{$newaddr}="$source:$linenum";
}
elsif($function =~ /strdup\(0x([0-9a-f]*)\) \((\d*)\) = 0x([0-9a-f]*)/) {
# strdup(a5b50) (8) = df7c0
 
$dup = $1;
$size = $2;
$addr = $3;
$getmem{$addr}="$source:$linenum";
$sizeataddr{$addr}=$size;
 
$totalmem += $size;
 
if($trace) {
printf("STRDUP: $size bytes at %s, makes totally: %d bytes\n",
$getmem{$addr}, $totalmem);
}
 
newtotal($totalmem);
$strdups++;
}
elsif($function =~ /strndup\(0x([0-9a-f]*), (\d*)\) \((\d*)\) = 0x([0-9a-f]*)/) {
# strndup(a5b50, 20) (8) = df7c0
 
$dup = $1;
$limit = $2;
$size = $3;
$addr = $4;
$getmem{$addr}="$source:$linenum";
$sizeataddr{$addr}=$size;
 
$totalmem += $size;
 
if($trace) {
printf("STRDUP: $size bytes at %s, makes totally: %d bytes\n",
$getmem{$addr}, $totalmem);
}
 
newtotal($totalmem);
$strdups++;
}
else {
print "Not recognized input line: $function\n";
}
}
# FD url.c:1282 socket() = 5
elsif($_ =~ /^FD ([^ ]*):(\d*) (.*)/) {
# generic match for the filename+linenumber
$source = $1;
$linenum = $2;
$function = $3;
 
if($function =~ /socket\(\) = (\d*)/) {
$filedes{$1}=1;
$getfile{$1}="$source:$linenum";
$openfile++;
}
elsif($function =~ /accept\(\) = (\d*)/) {
$filedes{$1}=1;
$getfile{$1}="$source:$linenum";
$openfile++;
}
elsif($function =~ /sclose\((\d*)\)/) {
if($filedes{$1} != 1) {
print "Close without open: $line\n";
}
else {
$filedes{$1}=0; # closed now
$openfile--;
}
}
}
# FILE url.c:1282 fopen("blabla") = 0x5ddd
elsif($_ =~ /^FILE ([^ ]*):(\d*) (.*)/) {
# generic match for the filename+linenumber
$source = $1;
$linenum = $2;
$function = $3;
 
if($function =~ /fopen\(\"([^\"]*)\",\"([^\"]*)\"\) = (\(nil\)|0x([0-9a-f]*))/) {
if($3 eq "(nil)") {
;
}
else {
$fopen{$4}=1;
$fopenfile{$4}="$source:$linenum";
$fopens++;
}
}
# fclose(0x1026c8)
elsif($function =~ /fclose\(0x([0-9a-f]*)\)/) {
if(!$fopen{$1}) {
print "fclose() without fopen(): $line\n";
}
else {
$fopen{$1}=0;
$fopens--;
}
}
}
# GETNAME url.c:1901 getnameinfo()
elsif($_ =~ /^GETNAME ([^ ]*):(\d*) (.*)/) {
# not much to do
}
 
# ADDR url.c:1282 getaddrinfo() = 0x5ddd
elsif($_ =~ /^ADDR ([^ ]*):(\d*) (.*)/) {
# generic match for the filename+linenumber
$source = $1;
$linenum = $2;
$function = $3;
 
if($function =~ /getaddrinfo\(\) = (\(nil\)|0x([0-9a-f]*))/) {
my $add = $2;
if($add eq "(nil)") {
;
}
else {
$addrinfo{$add}=1;
$addrinfofile{$add}="$source:$linenum";
$addrinfos++;
}
}
# fclose(0x1026c8)
elsif($function =~ /freeaddrinfo\(0x([0-9a-f]*)\)/) {
if(!$addrinfo{$1}) {
print "freeaddrinfo() without getaddrinfo(): $line\n";
}
else {
$addrinfo{$1}=0;
$addrinfos--;
}
}
 
 
}
else {
print "Not recognized prefix line: $line\n";
}
}
close(FILE);
 
if($totalmem) {
print "Leak detected: memory still allocated: $totalmem bytes\n";
 
for(keys %sizeataddr) {
$addr = $_;
$size = $sizeataddr{$addr};
if($size > 0) {
print "At $addr, there's $size bytes.\t";
print " allocated by ".$getmem{$addr}."\n";
$allocs{$getmem{$addr}}++;
$amount{$getmem{$addr}} += $size;
}
}
 
print "Summary by location of allocation:\n";
print "Allocs\tBytes\tLocation\n";
for (sort { $amount{$b} <=> $amount{$a} } keys %allocs) {
print "$allocs{$_}\t$amount{$_}\t$_\n";
}
}
 
if($openfile) {
for(keys %filedes) {
if($filedes{$_} == 1) {
print "Open file descriptor created at ".$getfile{$_}."\n";
}
}
}
 
if($fopens) {
print "Open FILE handles left at:\n";
for(keys %fopen) {
if($fopen{$_} == 1) {
print "fopen() called at ".$fopenfile{$_}."\n";
}
}
}
 
if($addrinfos) {
print "IPv6-style name resolve data left at:\n";
for(keys %addrinfofile) {
if($addrinfo{$_} == 1) {
print "getaddrinfo() called at ".$addrinfofile{$_}."\n";
}
}
}
 
if($verbose) {
print "Mallocs: $mallocs\n",
"Reallocs: $reallocs\n",
"Callocs: $callocs\n",
"Strdups: $strdups\n",
"Frees: $frees\n",
"Allocations: ".($mallocs + $callocs + $reallocs + $strdups)."\n";
 
print "Maximum allocated: $maxmem\n";
}
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/contrib/network/netsurf/netsurf/utils/memdebug.c
0,0 → 1,381
/** \file
* Heap debugging functions (implementation).
*
* Based on memdebug.c from curl (see below), with the following modifications:
*
* - renamed functions from curl_ to memdebug_
* - added memdebug_strndup
* - added guard bytes before and after each block to help detect overflows
* - if a guard byte is corrupted during free, dumps the DA to file
*/
 
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* $Id: memdebug.c,v 1.1 2004/07/28 22:35:02 bursa Exp $
***************************************************************************/
 
#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#ifdef riscos
#include <unixlib/local.h>
 
#include "oslib/os.h"
#include "oslib/osfile.h"
#endif
 
#include "memdebug.h"
 
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
 
#define MAGIC 0x34343434
#define GUARD 0x34
 
#if defined(riscos) && !defined(__ELF__)
extern int __dynamic_num;
#endif
 
struct memdebug {
size_t size;
unsigned int magic;
double mem[1];
/* I'm hoping this is the thing with the strictest alignment
* requirements. That also means we waste some space :-( */
};
 
/*
* Note that these debug functions are very simple and they are meant to
* remain so. For advanced analysis, record a log file and write perl scripts
* to analyze them!
*
* Don't use these with multithreaded test programs!
*/
 
#define logfile memdebug_debuglogfile
FILE *memdebug_debuglogfile;
static bool memlimit; /* enable memory limit */
static long memsize; /* set number of mallocs allowed */
 
/* this sets the log file name */
void memdebug_memdebug(const char *logname)
{
if(logname)
logfile = fopen(logname, "w");
else
logfile = stderr;
}
 
/* This function sets the number of malloc() calls that should return
successfully! */
void memdebug_memlimit(long limit)
{
memlimit = true;
memsize = limit;
}
 
/* returns true if this isn't allowed! */
static bool countcheck(const char *func, int line, const char *source)
{
/* if source is NULL, then the call is made internally and this check
should not be made */
if(memlimit && source) {
if(!memsize) {
if(logfile && source)
fprintf(logfile, "LIMIT %s:%d %s reached memlimit\n",
source, line, func);
if(source)
fprintf(stderr, "LIMIT %s:%d %s reached memlimit\n",
source, line, func);
return true; /* RETURN ERROR! */
}
else
memsize--; /* countdown */
 
/* log the countdown */
if(logfile && source)
fprintf(logfile, "LIMIT %s:%d %ld ALLOCS left\n",
source, line, memsize);
 
}
 
return false; /* allow this */
}
 
void *memdebug_malloc(size_t wantedsize, int line, const char *source)
{
struct memdebug *mem;
size_t size;
 
if(countcheck("malloc", line, source))
return NULL;
 
/* alloc at least 64 bytes */
size = sizeof(struct memdebug)+wantedsize + 8;
 
mem=(struct memdebug *)(malloc)(size);
if(mem) {
unsigned int i;
/* fill memory with junk */
memset(mem->mem, 0xA5, wantedsize);
mem->size = wantedsize;
mem->magic = MAGIC;
for (i = 0; i != 8; i++)
((char *) mem->mem)[wantedsize + i] = GUARD;
}
 
if(logfile && source)
fprintf(logfile, "MEM %s:%d malloc(%zu) = %p\n",
source, line, wantedsize, mem ? mem->mem : 0);
return (mem ? mem->mem : NULL);
}
 
void *memdebug_calloc(size_t wanted_elements, size_t wanted_size,
int line, const char *source)
{
struct memdebug *mem;
size_t size, user_size;
 
if(countcheck("calloc", line, source))
return NULL;
 
/* alloc at least 64 bytes */
user_size = wanted_size * wanted_elements;
size = sizeof(struct memdebug) + user_size + 8;
 
mem = (struct memdebug *)(malloc)(size);
if(mem) {
unsigned int i;
/* fill memory with zeroes */
memset(mem->mem, 0, user_size);
mem->size = user_size;
mem->magic = MAGIC;
for (i = 0; i != 8; i++)
((char *) mem->mem)[mem->size + i] = GUARD;
}
 
if(logfile && source)
fprintf(logfile, "MEM %s:%d calloc(%zu,%zu) = %p\n",
source, line, wanted_elements, wanted_size, mem ? mem->mem : 0);
return (mem ? mem->mem : NULL);
}
 
char *memdebug_strdup(const char *str, int line, const char *source)
{
char *mem;
size_t len;
 
assert(str != NULL);
 
if(countcheck("strdup", line, source))
return NULL;
 
len=strlen(str)+1;
 
mem=memdebug_malloc(len, 0, NULL); /* NULL prevents logging */
if (mem)
memcpy(mem, str, len);
 
if(logfile)
fprintf(logfile, "MEM %s:%d strdup(%p) (%zu) = %p\n",
source, line, str, len, mem);
 
return mem;
}
 
char *memdebug_strndup(const char *str, size_t size, int line, const char *source)
{
char *mem;
size_t len;
 
assert(str != NULL);
 
if(countcheck("strndup", line, source))
return NULL;
 
len=strlen(str)+1;
if (size < len - 1)
len = size + 1;
 
mem=memdebug_malloc(len, 0, NULL); /* NULL prevents logging */
if (mem) {
memcpy(mem, str, len);
mem[len - 1] = 0;
}
 
if(logfile)
fprintf(logfile, "MEM %s:%d strndup(%p, %zd) (%zu) = %p\n",
source, line, str, size, len, mem);
 
return mem;
}
 
/* We provide a realloc() that accepts a NULL as pointer, which then
performs a malloc(). In order to work with ares. */
void *memdebug_realloc(void *ptr, size_t wantedsize,
int line, const char *source)
{
unsigned int i;
struct memdebug *mem=NULL;
 
size_t size = sizeof(struct memdebug)+wantedsize+8;
 
if(countcheck("realloc", line, source))
return NULL;
 
if(ptr) {
mem = (struct memdebug *)(void *)
((char *)ptr - offsetof(struct memdebug, mem));
}
 
if(logfile) {
if (mem && mem->magic != MAGIC)
fprintf(logfile, "MAGIC match failed!\n");
for (i = 0; mem && i != 8; i++)
if (((char *) mem->mem)[mem->size + i] != GUARD)
fprintf(logfile, "GUARD %u match failed!\n", i);
fprintf(logfile, "MEM %s:%d realloc(%p, %zu) = ",
source, line, ptr, wantedsize);
fflush(logfile);
}
 
mem=(struct memdebug *)(realloc)(mem, size);
if(logfile)
fprintf(logfile, "%p\n", mem?mem->mem:NULL);
 
if(mem) {
mem->size = wantedsize;
mem->magic = MAGIC;
for (i = 0; i != 8; i++)
((char *) mem->mem)[wantedsize + i] = GUARD;
return mem->mem;
}
 
return NULL;
}
 
void memdebug_free(void *ptr, int line, const char *source)
{
unsigned int i;
struct memdebug *mem;
 
if (!ptr)
return;
 
assert(ptr != NULL);
 
mem = (struct memdebug *)(void *)
((char *)ptr - offsetof(struct memdebug, mem));
if(logfile) {
fprintf(logfile, "MEM %s:%d free(%p)\n", source, line, ptr);
if (mem->magic != MAGIC) {
fprintf(logfile, "MAGIC match failed!\n");
#ifdef riscos
#ifndef __ELF__
if (__dynamic_num != -1) {
int size;
byte *base_address;
xosdynamicarea_read(__dynamic_num, &size, &base_address,
0, 0, 0, 0, 0);
fprintf(logfile, "saving DA %i %p %x\n", __dynamic_num, base_address,
size);
xosfile_save("core", (bits) base_address, 0, base_address,
base_address + size);
}
#else
__unixlib_write_coredump(NULL);
#endif
#endif
}
fflush(logfile);
for (i = 0; i != 8; i++)
if (((char *) mem->mem)[mem->size + i] != GUARD)
fprintf(logfile, "GUARD %u match failed!\n", i);
fflush(logfile);
}
 
/* destroy */
memset(mem->mem, 0x13, mem->size);
mem->magic = 0x13131313;
for (i = 0; i != 8; i++)
((char *) mem->mem)[mem->size + i] = 0x13;
 
/* free for real */
(free)(mem);
}
 
int memdebug_socket(int domain, int type, int protocol, int line,
const char *source)
{
int sockfd=(socket)(domain, type, protocol);
if(logfile && (sockfd!=-1))
fprintf(logfile, "FD %s:%d socket() = %d\n",
source, line, sockfd);
return sockfd;
}
 
int memdebug_accept(int s, void *saddr, void *saddrlen,
int line, const char *source)
{
struct sockaddr *addr = (struct sockaddr *)saddr;
socklen_t *addrlen = (socklen_t *)saddrlen;
int sockfd=(accept)(s, addr, addrlen);
if(logfile)
fprintf(logfile, "FD %s:%d accept() = %d\n",
source, line, sockfd);
return sockfd;
}
 
/* this is our own defined way to close sockets on *ALL* platforms */
int memdebug_sclose(int sockfd, int line, const char *source)
{
int res=sclose(sockfd);
if(logfile)
fprintf(logfile, "FD %s:%d sclose(%d)\n",
source, line, sockfd);
return res;
}
 
FILE *memdebug_fopen(const char *file, const char *mode,
int line, const char *source)
{
FILE *res=(fopen)(file, mode);
if(logfile)
fprintf(logfile, "FILE %s:%d fopen(\"%s\",\"%s\") = %p\n",
source, line, file, mode, res);
return res;
}
 
int memdebug_fclose(FILE *file, int line, const char *source)
{
int res;
 
assert(file != NULL);
 
res=(fclose)(file);
if(logfile)
fprintf(logfile, "FILE %s:%d fclose(%p)\n",
source, line, file);
return res;
}
/contrib/network/netsurf/netsurf/utils/memdebug.h
0,0 → 1,106
/** \file
* Heap debugging functions (interface).
*
* Based on memdebug.h from curl (see below), with the following modifications:
*
* - renamed functions from curl_ to memdebug_
* - added memdebug_strndup
* - added guard bytes before and after each block to help detect overflows
* - if a guard byte is corrupted during free, dumps the DA to file
*/
 
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* $Id: memdebug.h,v 1.1 2004/07/28 22:35:02 bursa Exp $
***************************************************************************/
 
#ifndef _MEMDEBUG_H_
#define _MEMDEBUG_H_
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
 
#define logfile memdebug_debuglogfile
 
extern FILE *logfile;
 
/* memory functions */
void *memdebug_malloc(size_t size, int line, const char *source);
void *memdebug_calloc(size_t elements, size_t size, int line, const char *source);
void *memdebug_realloc(void *ptr, size_t size, int line, const char *source);
void memdebug_free(void *ptr, int line, const char *source);
char *memdebug_strdup(const char *str, int line, const char *source);
char *memdebug_strndup(const char *str, size_t size, int line, const char *source);
void memdebug_memdebug(const char *logname);
void memdebug_memlimit(long limit);
 
/* file descriptor manipulators */
int memdebug_socket(int domain, int type, int protocol, int line , const char *);
int memdebug_sclose(int sockfd, int, const char *source);
int memdebug_accept(int s, void *addr, void *addrlen,
int line, const char *source);
 
/* FILE functions */
FILE *memdebug_fopen(const char *file, const char *mode, int line,
const char *source);
int memdebug_fclose(FILE *file, int line, const char *source);
 
#ifndef MEMDEBUG_NODEFINES
 
#undef strdup
#define strdup(ptr) memdebug_strdup(ptr, __LINE__, __FILE__)
#define strndup(ptr,size) memdebug_strndup(ptr, size, __LINE__, __FILE__)
#define malloc(size) memdebug_malloc(size, __LINE__, __FILE__)
#define calloc(nbelem,size) memdebug_calloc(nbelem, size, __LINE__, __FILE__)
#define realloc(ptr,size) memdebug_realloc(ptr, size, __LINE__, __FILE__)
#define free(ptr) memdebug_free(ptr, __LINE__, __FILE__)
 
#define socket(domain,type,protocol)\
memdebug_socket(domain,type,protocol,__LINE__,__FILE__)
#undef accept /* for those with accept as a macro */
#define accept(sock,addr,len)\
memdebug_accept(sock,addr,len,__LINE__,__FILE__)
 
#define getaddrinfo(host,serv,hint,res) \
memdebug_getaddrinfo(host,serv,hint,res,__LINE__,__FILE__)
#define getnameinfo(sa,salen,host,hostlen,serv,servlen,flags) \
memdebug_getnameinfo(sa,salen,host,hostlen,serv,servlen,flags, __LINE__, \
__FILE__)
#define freeaddrinfo(data) \
memdebug_freeaddrinfo(data,__LINE__,__FILE__)
 
/* sclose is probably already defined, redefine it! */
#undef sclose
#define sclose(sockfd) memdebug_sclose(sockfd,__LINE__,__FILE__)
/* ares-adjusted define: */
#undef closesocket
#define closesocket(sockfd) memdebug_sclose(sockfd,__LINE__,__FILE__)
 
#undef fopen
#define fopen(file,mode) memdebug_fopen(file,mode,__LINE__,__FILE__)
#define fclose(file) memdebug_fclose(file,__LINE__,__FILE__)
 
#endif /* MEMDEBUG_NODEFINES */
 
#endif
/contrib/network/netsurf/netsurf/utils/merge-messages.lua
0,0 → 1,83
#!/usr/bin/env lua5.1
 
local lfs = require "lfs"
 
local en_stat = assert(lfs.attributes "!NetSurf/Resources/en/Messages")
local language = { }
local sorted = { }
 
io.stderr:write("loading non-en languages...\n");
 
for dir in lfs.dir "!NetSurf/Resources" do
local path = "!NetSurf/Resources/" .. dir
if dir ~= "en" and lfs.attributes(path .. "/Messages") then
local f = io.open(path .. "/Messages", "r")
local c = 0
io.stderr:write(dir, ":")
language[dir] = { }
sorted[#sorted + 1] = dir
for l in f:lines() do
if l:sub(1, 1) ~= "#" then
local tag, msg = l:match "^([^:]*):(.*)$"
if tag then
language[dir][tag] = msg
c = c + 1
end
end
end
f:close()
io.stderr:write(tostring(c), " entries.\n")
end
end
 
table.sort(sorted)
 
io.stderr:write("working through en...\n")
 
local manipulators = {
{ "^(ami.*)", "ami.%1" },
{ "^(gtk.*)", "gtk.%1" },
{ "^(Help.*)", "ro.%1" },
{ "^(ARexx.*)", "ami.%1" },
 
{ "^(.*)$", "all.%1" } -- must be last
}
 
local function manipulate_tag(t)
for _, m in ipairs(manipulators) do
local r, s = t:gsub(m[1], m[2])
if s > 0 then return r end
end
return t
end
 
local f = io.open("!NetSurf/Resources/en/Messages", "r")
 
for l in f:lines() do
if l:sub(1,1) == "#" then
print(l)
else
local tag, msg = l:match "^([^:]*):(.*)$"
if not tag then
print(l)
else
local mtag = manipulate_tag(tag)
io.stdout:write("en.", mtag, ":", msg, "\n")
for _, langname in ipairs(sorted) do
local trans = language[langname][tag]
if not trans then
io.stderr:write("*** language ", langname, " lacks translation for ", mtag, "/", tag, "\n")
trans = msg
end
io.stdout:write(langname, ".", mtag, ":", trans, "\n")
language[langname][tag] = nil
end
end
end
end
 
for _, langname in ipairs(sorted) do
for tag in pairs(language[langname]) do
io.stderr:write("*** language ", langname, " contains orphan tag ", tag, "\n")
end
end
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/contrib/network/netsurf/netsurf/utils/messages.c
0,0 → 1,298
/*
* Copyright 2004 James Bursa <bursa@users.sourceforge.net>
* Copyright 2006 Rob Kendrick <rjek@rjek.com>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
/** \file
* Localised message support (implementation).
*
* Native language messages are loaded from a file and stored hashed by key for
* fast access.
*/
 
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <zlib.h>
#include <stdarg.h>
 
#include "utils/log.h"
#include "utils/messages.h"
#include "utils/utils.h"
#include "utils/hashtable.h"
 
/** We store the messages in a fixed-size hash table. */
#define HASH_SIZE 101
 
/** The hash table used to store the standard Messages file for the old API */
static struct hash_table *messages_hash = NULL;
 
/**
* Read keys and values from messages file.
*
* \param path pathname of messages file
* \param ctx struct hash_table to merge with, or NULL for a new one.
* \return struct hash_table containing the context or NULL in case of error.
*/
 
struct hash_table *messages_load_ctx(const char *path, struct hash_table *ctx)
{
char s[400];
gzFile fp;
 
assert(path != NULL);
 
ctx = (ctx != NULL) ? ctx : hash_create(HASH_SIZE);
 
if (ctx == NULL) {
LOG(("Unable to create hash table for messages file %s", path));
return NULL;
}
 
fp = gzopen(path, "r");
if (!fp) {
snprintf(s, sizeof s, "Unable to open messages file "
"\"%.100s\": %s", path, strerror(errno));
s[sizeof s - 1] = 0;
LOG(("%s", s));
hash_destroy(ctx);
return NULL;
}
 
while (gzgets(fp, s, sizeof s)) {
char *colon, *value;
 
if (s[0] == 0 || s[0] == '#')
continue;
 
s[strlen(s) - 1] = 0; /* remove \n at end */
colon = strchr(s, ':');
if (!colon)
continue;
*colon = 0; /* terminate key */
value = colon + 1;
 
if (hash_add(ctx, s, value) == false) {
LOG(("Unable to add %s:%s to hash table of %s",
s, value, path));
gzclose(fp);
hash_destroy(ctx);
return NULL;
}
}
 
gzclose(fp);
 
return ctx;
}
 
/**
* Read keys and values from messages file into the standard Messages hash.
*
* \param path pathname of messages file
*
* The messages are merged with any previously loaded messages. Any keys which
* are present already are replaced with the new value.
*
* Exits through die() in case of error.
*/
 
void messages_load(const char *path)
{
struct hash_table *m;
char s[400];
 
if (path == NULL)
return;
LOG(("Loading Messages from '%s'", path));
m = messages_load_ctx(path, messages_hash);
if (m == NULL) {
LOG(("Unable to open Messages file '%s'. Possible reason: %s",
path, strerror(errno)));
snprintf(s, sizeof s,
"Unable to open Messages file '%s'.", path);
die(s);
}
 
messages_hash = m;
}
 
/**
* Fast lookup of a message by key.
*
* \param key key of message
* \param ctx context of messages file to look up in
* \return value of message, or key if not found
*/
 
const char *messages_get_ctx(const char *key, struct hash_table *ctx)
{
const char *r;
 
assert(key != NULL);
 
/* If we're called with no context, it's nicer to return the
* key rather than explode - this allows attempts to get messages
* before messages_hash is set up to fail gracefully, for example */
if (ctx == NULL)
return key;
 
r = hash_get(ctx, key);
 
return r ? r : key;
}
 
/* exported interface documented in messages.h */
char *messages_get_buff(const char *key, ...)
{
const char *msg_fmt;
char *buff = NULL; /* formatted buffer to return */
int buff_len = 0;
va_list ap;
 
msg_fmt = messages_get_ctx(key, messages_hash);
 
va_start(ap, key);
buff_len = vsnprintf(buff, buff_len, msg_fmt, ap);
va_end(ap);
 
buff = malloc(buff_len + 1);
 
if (buff == NULL) {
LOG(("malloc failed"));
warn_user("NoMemory", 0);
} else {
va_start(ap, key);
vsnprintf(buff, buff_len + 1, msg_fmt, ap);
va_end(ap);
}
 
return buff;
}
 
 
/**
* Fast lookup of a message by key from the standard Messages hash.
*
* \param key key of message
* \return value of message, or key if not found
*/
 
const char *messages_get(const char *key)
{
return messages_get_ctx(key, messages_hash);
}
 
 
/**
* lookup of a message by errorcode from the standard Messages hash.
*
* \param code errorcode of message
* \return message text
*/
 
const char *messages_get_errorcode(nserror code)
{
switch (code) {
case NSERROR_OK:
/**< No error */
return messages_get_ctx("OK", messages_hash);
 
case NSERROR_NOMEM:
/**< Memory exhaustion */
return messages_get_ctx("NoMemory", messages_hash);
 
case NSERROR_NO_FETCH_HANDLER:
/**< No fetch handler for URL scheme */
return messages_get_ctx("NoHandler", messages_hash);
 
case NSERROR_NOT_FOUND:
/**< Requested item not found */
return messages_get_ctx("NotFound", messages_hash);
 
case NSERROR_SAVE_FAILED:
/**< Failed to save data */
return messages_get_ctx("SaveFailed", messages_hash);
 
case NSERROR_CLONE_FAILED:
/**< Failed to clone handle */
return messages_get_ctx("CloneFailed", messages_hash);
 
case NSERROR_INIT_FAILED:
/**< Initialisation failed */
return messages_get_ctx("InitFailed", messages_hash);
 
case NSERROR_MNG_ERROR:
/**< An MNG error occurred */
return messages_get_ctx("MNGError", messages_hash);
 
case NSERROR_BAD_ENCODING:
/**< The character set is unknown */
return messages_get_ctx("BadEncoding", messages_hash);
 
case NSERROR_NEED_DATA:
/**< More data needed */
return messages_get_ctx("NeedData", messages_hash);
 
case NSERROR_ENCODING_CHANGE:
/**< The character set encoding change was unhandled */
return messages_get_ctx("EncodingChanged", messages_hash);
 
case NSERROR_BAD_PARAMETER:
/**< Bad Parameter */
return messages_get_ctx("BadParameter", messages_hash);
 
case NSERROR_INVALID:
/**< Invalid data */
return messages_get_ctx("Invalid", messages_hash);
 
case NSERROR_BOX_CONVERT:
/**< Box conversion failed */
return messages_get_ctx("BoxConvert", messages_hash);
 
case NSERROR_STOPPED:
/**< Content conversion stopped */
return messages_get_ctx("Stopped", messages_hash);
 
case NSERROR_DOM:
/**< DOM call returned error */
return messages_get_ctx("ParsingFail", messages_hash);
 
case NSERROR_CSS:
/**< CSS call returned error */
return messages_get_ctx("CSSGeneric", messages_hash);
 
case NSERROR_CSS_BASE:
/**< CSS base sheet failed */
return messages_get_ctx("CSSBase", messages_hash);
 
case NSERROR_BAD_URL:
/**< Bad URL */
return messages_get_ctx("BadURL", messages_hash);
 
default:
case NSERROR_UNKNOWN:
break;
}
 
/**< Unknown error */
return messages_get_ctx("Unknown", messages_hash);
}
/contrib/network/netsurf/netsurf/utils/messages.h
0,0 → 1,64
/*
* Copyright 2004 James Bursa <bursa@users.sourceforge.net>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
/** \file
* Localised message support (interface).
*
* The messages module loads a file of keys and associated strings, and
* provides fast lookup by key. The messages file consists of key:value lines,
* comment lines starting with #, and other lines are ignored. Use
* messages_load() to read the file into memory. To lookup a key, use
* messages_get("key").
*
* It can also load additional messages files into different contexts and allow
* you to look up values in it independantly from the standard shared Messages
* file table. Use the _ctx versions of the functions to do this.
*/
 
#ifndef _NETSURF_UTILS_MESSAGES_H_
#define _NETSURF_UTILS_MESSAGES_H_
 
#include "utils/errors.h"
#include "utils/hashtable.h"
 
void messages_load(const char *path);
struct hash_table *messages_load_ctx(const char *path, struct hash_table *ctx);
const char *messages_get_ctx(const char *key, struct hash_table *ctx);
const char *messages_get(const char *key);
 
/**
* lookup of a message by errorcode from the standard Messages hash.
*
* \param code errorcode of message
* \return message text
*/
const char *messages_get_errorcode(nserror code);
 
/**
* Formatted message from a key in the global message hash.
*
* \param key key of message
* \param ... message parameters
* \return buffer containing formatted message text or NULL if memory
* is unavailable. The caller owns the returned buffer and is
* responsible for freeing it.
*/
 
char *messages_get_buff(const char *key, ...);
 
#endif
/contrib/network/netsurf/netsurf/utils/nsurl.c
0,0 → 1,2122
/*
* Copyright 2011 Michael Drake <tlsa@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
/** \file
* NetSurf URL handling (implementation).
*/
 
#include <assert.h>
#include <ctype.h>
#include <libwapcaplet/libwapcaplet.h>
#include <stdlib.h>
#include <string.h>
 
#include "utils/errors.h"
#include "utils/log.h"
#include "utils/nsurl.h"
#include "utils/utils.h"
 
 
/* Define to enable NSURL debugging */
#undef NSURL_DEBUG
 
static bool nsurl__is_unreserved(unsigned char c)
{
/* From RFC3986 section 2.3 (unreserved characters)
*
* unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
*
*/
static const bool unreserved[256] = {
false, false, false, false, false, false, false, false, /* 00 */
false, false, false, false, false, false, false, false, /* 08 */
false, false, false, false, false, false, false, false, /* 10 */
false, false, false, false, false, false, false, false, /* 18 */
false, false, false, false, false, false, false, false, /* 20 */
false, false, false, false, false, true, true, false, /* 28 */
true, true, true, true, true, true, true, true, /* 30 */
true, true, false, false, false, false, false, false, /* 38 */
false, true, true, true, true, true, true, true, /* 40 */
true, true, true, true, true, true, true, true, /* 48 */
true, true, true, true, true, true, true, true, /* 50 */
true, true, true, false, false, false, false, true, /* 58 */
false, true, true, true, true, true, true, true, /* 60 */
true, true, true, true, true, true, true, true, /* 68 */
true, true, true, true, true, true, true, true, /* 70 */
true, true, true, false, false, false, true, false, /* 78 */
false, false, false, false, false, false, false, false, /* 80 */
false, false, false, false, false, false, false, false, /* 88 */
false, false, false, false, false, false, false, false, /* 90 */
false, false, false, false, false, false, false, false, /* 98 */
false, false, false, false, false, false, false, false, /* A0 */
false, false, false, false, false, false, false, false, /* A8 */
false, false, false, false, false, false, false, false, /* B0 */
false, false, false, false, false, false, false, false, /* B8 */
false, false, false, false, false, false, false, false, /* C0 */
false, false, false, false, false, false, false, false, /* C8 */
false, false, false, false, false, false, false, false, /* D0 */
false, false, false, false, false, false, false, false, /* D8 */
false, false, false, false, false, false, false, false, /* E0 */
false, false, false, false, false, false, false, false, /* E8 */
false, false, false, false, false, false, false, false, /* F0 */
false, false, false, false, false, false, false, false /* F8 */
};
return unreserved[c];
}
 
/* The ASCII codes which should not be percent escaped */
static bool nsurl__is_no_escape(unsigned char c)
{
static const bool no_escape[256] = {
false, false, false, false, false, false, false, false, /* 00 */
false, false, false, false, false, false, false, false, /* 08 */
false, false, false, false, false, false, false, false, /* 10 */
false, false, false, false, false, false, false, false, /* 18 */
false, true, false, true, true, false, true, true, /* 20 */
true, true, true, true, true, true, true, true, /* 28 */
true, true, true, true, true, true, true, true, /* 30 */
true, true, true, true, false, true, false, true, /* 38 */
true, true, true, true, true, true, true, true, /* 40 */
true, true, true, true, true, true, true, true, /* 48 */
true, true, true, true, true, true, true, true, /* 50 */
true, true, true, true, false, true, false, true, /* 58 */
false, true, true, true, true, true, true, true, /* 60 */
true, true, true, true, true, true, true, true, /* 68 */
true, true, true, true, true, true, true, true, /* 70 */
true, true, true, false, true, false, true, false, /* 78 */
false, false, false, false, false, false, false, false, /* 80 */
false, false, false, false, false, false, false, false, /* 88 */
false, false, false, false, false, false, false, false, /* 90 */
false, false, false, false, false, false, false, false, /* 98 */
false, false, false, false, false, false, false, false, /* A0 */
false, false, false, false, false, false, false, false, /* A8 */
false, false, false, false, false, false, false, false, /* B0 */
false, false, false, false, false, false, false, false, /* B8 */
false, false, false, false, false, false, false, false, /* C0 */
false, false, false, false, false, false, false, false, /* C8 */
false, false, false, false, false, false, false, false, /* D0 */
false, false, false, false, false, false, false, false, /* D8 */
false, false, false, false, false, false, false, false, /* E0 */
false, false, false, false, false, false, false, false, /* E8 */
false, false, false, false, false, false, false, false, /* F0 */
false, false, false, false, false, false, false, false, /* F8 */
};
return no_escape[c];
}
 
 
/** nsurl scheme type */
enum scheme_type {
NSURL_SCHEME_OTHER,
NSURL_SCHEME_HTTP,
NSURL_SCHEME_HTTPS,
NSURL_SCHEME_FTP,
NSURL_SCHEME_MAILTO
};
 
 
/** nsurl components */
struct nsurl_components {
lwc_string *scheme;
lwc_string *username;
lwc_string *password;
lwc_string *host;
lwc_string *port;
lwc_string *path;
lwc_string *query;
lwc_string *fragment;
 
enum scheme_type scheme_type;
};
 
 
/**
* NetSurf URL object
*
* [scheme]://[username][:password]@[host]:[port][/path][?query][#fragment]
*/
struct nsurl {
struct nsurl_components components;
 
int count; /* Number of references to NetSurf URL object */
 
size_t length; /* Length of string */
char string[FLEX_ARRAY_LEN_DECL]; /* Full URL as a string */
};
 
 
/** Marker set, indicating positions of sections within a URL string */
struct url_markers {
size_t start; /** start of URL */
size_t scheme_end;
size_t authority;
 
size_t colon_first;
size_t at;
size_t colon_last;
 
size_t path;
size_t query;
size_t fragment;
 
size_t end; /** end of URL */
 
enum scheme_type scheme_type;
};
 
 
/** Marker set, indicating positions of sections within a URL string */
struct nsurl_component_lengths {
size_t scheme;
size_t username;
size_t password;
size_t host;
size_t port;
size_t path;
size_t query;
size_t fragment;
};
 
 
/** Flags indicating which parts of a URL string are required for a nsurl */
enum nsurl_string_flags {
NSURL_F_SCHEME = (1 << 0),
NSURL_F_SCHEME_PUNCTUATION = (1 << 1),
NSURL_F_AUTHORITY_PUNCTUATION = (1 << 2),
NSURL_F_USERNAME = (1 << 3),
NSURL_F_PASSWORD = (1 << 4),
NSURL_F_CREDENTIALS_PUNCTUATION = (1 << 5),
NSURL_F_HOST = (1 << 6),
NSURL_F_PORT = (1 << 7),
NSURL_F_AUTHORITY = (NSURL_F_USERNAME |
NSURL_F_PASSWORD |
NSURL_F_HOST |
NSURL_F_PORT),
NSURL_F_PATH = (1 << 8),
NSURL_F_QUERY = (1 << 9),
NSURL_F_FRAGMENT_PUNCTUATION = (1 << 10),
NSURL_F_FRAGMENT = (1 << 11)
};
 
 
/** Sections of a URL */
enum url_sections {
URL_SCHEME,
URL_CREDENTIALS,
URL_HOST,
URL_PATH,
URL_QUERY,
URL_FRAGMENT
};
 
 
#define nsurl__component_copy(c) (c == NULL) ? NULL : lwc_string_ref(c)
 
#define nsurl__component_compare(c1, c2, match) \
if (c1 && c2 && lwc_error_ok == \
lwc_string_isequal(c1, c2, match)) { \
/* do nothing */ \
} else if (c1 || c2) { \
*match = false; \
}
 
 
/**
* Obtains a set of markers delimiting sections in a URL string
*
* \param url_s URL string
* \param markers Updated to mark sections in the URL string
* \param joining True iff URL string is a relative URL for joining
*/
static void nsurl__get_string_markers(const char * const url_s,
struct url_markers *markers, bool joining)
{
const char *pos = url_s; /** current position in url_s */
bool is_http = false;
bool trailing_whitespace = false;
 
/* Initialise marker set */
struct url_markers marker = { 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, NSURL_SCHEME_OTHER };
 
/* Skip any leading whitespace in url_s */
while (isspace(*pos))
pos++;
 
/* Record start point */
marker.start = pos - url_s;
 
marker.scheme_end = marker.authority = marker.colon_first = marker.at =
marker.colon_last = marker.path = marker.start;
 
if (*pos == '\0') {
/* Nothing but whitespace, early exit */
marker.query = marker.fragment = marker.end = marker.path;
*markers = marker;
return;
}
 
/* Get scheme */
if (isalpha(*pos)) {
pos++;
 
while (*pos != ':' && *pos != '\0') {
if (!isalnum(*pos) && *pos != '+' &&
*pos != '-' && *pos != '.') {
/* This character is not valid in the
* scheme */
break;
}
pos++;
}
 
if (*pos == ':') {
/* This delimits the end of the scheme */
size_t off;
 
marker.scheme_end = pos - url_s;
 
off = marker.scheme_end - marker.start;
 
/* Detect http(s) and mailto for scheme specifc
* normalisation */
if (off == SLEN("http") &&
(((*(pos - off + 0) == 'h') ||
(*(pos - off + 0) == 'H')) &&
((*(pos - off + 1) == 't') ||
(*(pos - off + 1) == 'T')) &&
((*(pos - off + 2) == 't') ||
(*(pos - off + 2) == 'T')) &&
((*(pos - off + 3) == 'p') ||
(*(pos - off + 3) == 'P')))) {
marker.scheme_type = NSURL_SCHEME_HTTP;
is_http = true;
} else if (off == SLEN("https") &&
(((*(pos - off + 0) == 'h') ||
(*(pos - off + 0) == 'H')) &&
((*(pos - off + 1) == 't') ||
(*(pos - off + 1) == 'T')) &&
((*(pos - off + 2) == 't') ||
(*(pos - off + 2) == 'T')) &&
((*(pos - off + 3) == 'p') ||
(*(pos - off + 3) == 'P')) &&
((*(pos - off + 4) == 's') ||
(*(pos - off + 4) == 'S')))) {
marker.scheme_type = NSURL_SCHEME_HTTPS;
is_http = true;
} else if (off == SLEN("ftp") &&
(((*(pos - off + 0) == 'f') ||
(*(pos - off + 0) == 'F')) &&
((*(pos - off + 1) == 't') ||
(*(pos - off + 1) == 'T')) &&
((*(pos - off + 2) == 'p') ||
(*(pos - off + 2) == 'P')))) {
marker.scheme_type = NSURL_SCHEME_FTP;
} else if (off == SLEN("mailto") &&
(((*(pos - off + 0) == 'm') ||
(*(pos - off + 0) == 'M')) &&
((*(pos - off + 1) == 'a') ||
(*(pos - off + 1) == 'A')) &&
((*(pos - off + 2) == 'i') ||
(*(pos - off + 2) == 'I')) &&
((*(pos - off + 3) == 'l') ||
(*(pos - off + 3) == 'L')) &&
((*(pos - off + 4) == 't') ||
(*(pos - off + 4) == 'T')) &&
((*(pos - off + 5) == 'o') ||
(*(pos - off + 5) == 'O')))) {
marker.scheme_type = NSURL_SCHEME_MAILTO;
}
 
/* Skip over colon */
pos++;
 
/* Mark place as start of authority */
marker.authority = marker.colon_first = marker.at =
marker.colon_last = marker.path =
pos - url_s;
 
} else {
/* Not found a scheme */
if (joining == false) {
/* Assuming no scheme == http */
marker.scheme_type = NSURL_SCHEME_HTTP;
is_http = true;
}
}
}
 
/* Get authority
*
* Two slashes always indicates the start of an authority.
*
* We are more relaxed in the case of http:
* a. when joining, one or more slashes indicates start of authority
* b. when not joining, we assume authority if no scheme was present
* and in the case of mailto: when we assume there is an authority.
*/
if ((*pos == '/' && *(pos + 1) == '/') ||
(is_http && ((joining && *pos == '/') ||
(joining == false &&
marker.scheme_end != marker.start))) ||
marker.scheme_type == NSURL_SCHEME_MAILTO) {
 
/* Skip over leading slashes */
if (*pos == '/') {
if (is_http == false) {
if (*pos == '/') pos++;
if (*pos == '/') pos++;
} else {
while (*pos == '/')
pos++;
}
 
marker.authority = marker.colon_first = marker.at =
marker.colon_last = marker.path =
pos - url_s;
}
 
/* Need to get (or complete) the authority */
while (*pos != '\0') {
if (*pos == '/' || *pos == '?' || *pos == '#') {
/* End of the authority */
break;
 
} else if (*pos == ':' && marker.colon_first ==
marker.authority) {
/* could be username:password or host:port
* separator */
marker.colon_first = pos - url_s;
 
} else if (*pos == ':' && marker.colon_first !=
marker.authority) {
/* could be host:port separator */
marker.colon_last = pos - url_s;
 
} else if (*pos == '@' && marker.at ==
marker.authority) {
/* Credentials @ host separator */
marker.at = pos - url_s;
}
 
pos++;
}
 
marker.path = pos - url_s;
 
} else if ((*pos == '\0' || *pos == '/') &&
joining == false && is_http == true) {
marker.path = pos - url_s;
}
 
/* Get path
*
* Needs to start with '/' if there's no authority
*/
if (*pos == '/' || ((marker.path == marker.authority) &&
(*pos != '?') && (*pos != '#') && (*pos != '\0'))) {
while (*(++pos) != '\0') {
if (*pos == '?' || *pos == '#') {
/* End of the path */
break;
}
}
}
 
marker.query = pos - url_s;
 
/* Get query */
if (*pos == '?') {
while (*(++pos) != '\0') {
if (*pos == '#') {
/* End of the query */
break;
}
}
}
 
marker.fragment = pos - url_s;
 
/* Get fragment */
if (*pos == '#') {
while (*(++pos) != '\0')
;
}
 
/* We got to the end of url_s.
* Need to skip back over trailing whitespace to find end of URL */
pos--;
if (pos >= url_s && isspace(*pos)) {
trailing_whitespace = true;
while (pos >= url_s && isspace(*pos))
pos--;
}
 
marker.end = pos + 1 - url_s;
 
if (trailing_whitespace == true) {
/* Ensure last url section doesn't pass end */
if (marker.fragment > marker.end)
marker.fragment = marker.end;
if (marker.query > marker.end)
marker.query = marker.end;
if (marker.path > marker.end)
marker.path = marker.end;
if (marker.colon_last > marker.end)
marker.colon_last = marker.end;
if (marker.at > marker.end)
marker.at = marker.end;
if (marker.colon_last > marker.end)
marker.colon_last = marker.end;
if (marker.fragment > marker.end)
marker.fragment = marker.end;
}
 
/* Got all the URL components pegged out now */
*markers = marker;
}
 
 
/**
* Remove dot segments from a path, as per rfc 3986, 5.2.4
*
* \param path path to remove dot segments from ('\0' terminated)
* \param output path with dot segments removed
* \return size of output
*/
static size_t nsurl__remove_dot_segments(char *path, char *output)
{
char *path_pos = path;
char *output_pos = output;
 
while (*path_pos != '\0') {
#ifdef NSURL_DEBUG
LOG((" in:%s", path_pos));
LOG(("out:%.*s", output_pos - output, output));
#endif
if (*path_pos == '.') {
if (*(path_pos + 1) == '.' &&
*(path_pos + 2) == '/') {
/* Found prefix of "../" */
path_pos += SLEN("../");
continue;
 
} else if (*(path_pos + 1) == '/') {
/* Found prefix of "./" */
path_pos += SLEN("./");
continue;
}
} else if (*path_pos == '/' && *(path_pos + 1) == '.') {
if (*(path_pos + 2) == '/') {
/* Found prefix of "/./" */
path_pos += SLEN("/.");
continue;
 
} else if (*(path_pos + 2) == '\0') {
/* Found "/." at end of path */
*(output_pos++) = '/';
 
/* End of input path */
break;
 
} else if (*(path_pos + 2) == '.') {
if (*(path_pos + 3) == '/') {
/* Found prefix of "/../" */
path_pos += SLEN("/..");
 
if (output_pos > output)
output_pos--;
while (output_pos > output &&
*output_pos != '/')
output_pos--;
 
continue;
 
} else if (*(path_pos + 3) == '\0') {
/* Found "/.." at end of path */
 
while (output_pos > output &&
*(output_pos -1 ) !='/')
output_pos--;
 
/* End of input path */
break;
}
}
} else if (*path_pos == '.') {
if (*(path_pos + 1) == '\0') {
/* Found "." at end of path */
 
/* End of input path */
break;
 
} else if (*(path_pos + 1) == '.' &&
*(path_pos + 2) == '\0') {
/* Found ".." at end of path */
 
/* End of input path */
break;
}
}
/* Copy first character into output path */
*output_pos++ = *path_pos++;
 
/* Copy up to but not including next '/' */
while ((*path_pos != '/') && (*path_pos != '\0'))
*output_pos++ = *path_pos++;
}
 
return output_pos - output;
}
 
 
/**
* Get the length of the longest section
*
* \param m markers delimiting url sections in a string
* \return the length of the longest section
*/
static size_t nsurl__get_longest_section(struct url_markers *m)
{
size_t length = m->scheme_end - m->start; /* scheme */
 
if (length < m->at - m->authority) /* credentials */
length = m->at - m->authority;
 
if (length < m->path - m->at) /* host */
length = m->path - m->at;
 
if (length < m->query - m->path) /* path */
length = m->query - m->path;
 
if (length < m->fragment - m->query) /* query */
length = m->fragment - m->query;
 
if (length < m->end - m->fragment) /* fragment */
length = m->end - m->fragment;
 
return length;
}
 
 
/**
* Converts two hexadecimal digits to a single number
*
* \param c1 most significant hex digit
* \param c2 least significant hex digit
* \return the total value of the two digit hex number, or -ve if input not hex
*
* For unescaping url encoded characters.
*/
static inline int nsurl__get_ascii_offset(char c1, char c2)
{
int offset;
 
/* Use 1st char as most significant hex digit */
if (isdigit(c1))
offset = 16 * (c1 - '0');
else if (c1 >= 'a' && c1 <= 'f')
offset = 16 * (c1 - 'a' + 10);
else if (c1 >= 'A' && c1 <= 'F')
offset = 16 * (c1 - 'A' + 10);
else
/* Not valid hex */
return -1;
 
/* Use 2nd char as least significant hex digit and sum */
if (isdigit(c2))
offset += c2 - '0';
else if (c2 >= 'a' && c2 <= 'f')
offset += c2 - 'a' + 10;
else if (c2 >= 'A' && c2 <= 'F')
offset += c2 - 'A' + 10;
else
/* Not valid hex */
return -1;
 
return offset;
}
 
 
/**
* Create the components of a NetSurf URL object for a section of a URL string
*
* \param url_s URL string
* \param section Sets which section of URL string is to be normalised
* \param pegs Set of markers delimiting the URL string's sections
* \param pos_norm A buffer large enough for the normalised string (*3 + 1)
* \param url A NetSurf URL object, to which components may be added
* \return NSERROR_OK on success, appropriate error otherwise
*
* The section of url_s is normalised appropriately.
*/
static nserror nsurl__create_from_section(const char * const url_s,
const enum url_sections section,
const struct url_markers *pegs,
char *pos_norm,
struct nsurl_components *url)
{
int ascii_offset;
int start = 0;
int end = 0;
const char *pos;
const char *pos_url_s;
char *norm_start = pos_norm;
size_t copy_len;
size_t length;
enum {
NSURL_F_NO_PORT = (1 << 0)
} flags = 0;
 
switch (section) {
case URL_SCHEME:
start = pegs->start;
end = pegs->scheme_end;
break;
 
case URL_CREDENTIALS:
start = pegs->authority;
end = pegs->at;
break;
 
case URL_HOST:
start = (pegs->at == pegs->authority &&
*(url_s + pegs->at) != '@') ?
pegs->at :
pegs->at + 1;
end = pegs->path;
break;
 
case URL_PATH:
start = pegs->path;
end = pegs->query;
break;
 
case URL_QUERY:
start = pegs->query;
end = pegs->fragment;
break;
 
case URL_FRAGMENT:
start = (*(url_s + pegs->fragment) != '#') ?
pegs->fragment :
pegs->fragment + 1;
end = pegs->end;
break;
}
 
if (end < start)
end = start;
 
length = end - start;
 
/* Stage 1: Normalise the required section */
 
pos = pos_url_s = url_s + start;
copy_len = 0;
for (; pos < url_s + end; pos++) {
if (*pos == '%' && (pos + 2 < url_s + end)) {
/* Might be an escaped character needing unescaped */
 
/* Find which character which was escaped */
ascii_offset = nsurl__get_ascii_offset(*(pos + 1),
*(pos + 2));
 
if (ascii_offset < 0) {
/* % with invalid hex digits. */
copy_len++;
continue;
}
 
if (nsurl__is_unreserved(ascii_offset) == false) {
/* This character should be escaped after all,
* just let it get copied */
copy_len += 3;
pos += 2;
continue;
}
 
if (copy_len > 0) {
/* Copy up to here */
memcpy(pos_norm, pos_url_s, copy_len);
pos_norm += copy_len;
copy_len = 0;
}
 
/* Put the unescaped character in the normalised URL */
*(pos_norm++) = (char)ascii_offset;
pos += 2;
pos_url_s = pos + 1;
 
length -= 2;
 
} else if (nsurl__is_no_escape(*pos) == false) {
 
/* This needs to be escaped */
if (copy_len > 0) {
/* Copy up to here */
memcpy(pos_norm, pos_url_s, copy_len);
pos_norm += copy_len;
copy_len = 0;
}
 
/* escape */
*(pos_norm++) = '%';
*(pos_norm++) = digit2uppercase_hex(
((unsigned char)*pos) >> 4);
*(pos_norm++) = digit2uppercase_hex(
((unsigned char)*pos) & 0xf);
pos_url_s = pos + 1;
 
length += 2;
 
} else if ((section == URL_SCHEME || section == URL_HOST) &&
isupper(*pos)) {
/* Lower case this letter */
 
if (copy_len > 0) {
/* Copy up to here */
memcpy(pos_norm, pos_url_s, copy_len);
pos_norm += copy_len;
copy_len = 0;
}
/* Copy lower cased letter into normalised URL */
*(pos_norm++) = tolower(*pos);
pos_url_s = pos + 1;
 
} else {
/* This character is safe in normalised URL */
copy_len++;
}
}
 
if (copy_len > 0) {
/* Copy up to here */
memcpy(pos_norm, pos_url_s, copy_len);
pos_norm += copy_len;
}
 
/* Mark end of section */
(*pos_norm) = '\0';
 
/* Stage 2: Create the URL components for the required section */
switch (section) {
case URL_SCHEME:
if (length == 0) {
/* No scheme, assuming http, and add to URL */
if (lwc_intern_string("http", SLEN("http"),
&url->scheme) != lwc_error_ok) {
return NSERROR_NOMEM;
}
} else {
/* Add scheme to URL */
if (lwc_intern_string(norm_start, length,
&url->scheme) != lwc_error_ok) {
return NSERROR_NOMEM;
}
}
 
break;
 
case URL_CREDENTIALS:
url->username = NULL;
url->password = NULL;
 
if (length != 0 && *norm_start != ':') {
char *sec_start = norm_start;
if (pegs->colon_first != pegs->authority &&
pegs->at > pegs->colon_first + 1) {
/* there's a password */
sec_start += pegs->colon_first -
pegs->authority + 1;
if (lwc_intern_string(sec_start,
pegs->at - pegs->colon_first -1,
&url->password) !=
lwc_error_ok) {
return NSERROR_NOMEM;
}
 
/* update start pos and length for username */
sec_start = norm_start;
length -= pegs->at - pegs->colon_first;
} else if (pegs->colon_first != pegs->authority &&
pegs->at == pegs->colon_first + 1) {
/* strip username colon */
length--;
}
 
/* Username */
if (lwc_intern_string(sec_start, length,
&url->username) != lwc_error_ok) {
return NSERROR_NOMEM;
}
}
 
break;
 
case URL_HOST:
url->host = NULL;
url->port = NULL;
 
if (length != 0) {
size_t colon = 0;
char *sec_start = norm_start;
if (pegs->at < pegs->colon_first &&
pegs->colon_last == pegs->authority) {
/* There's one colon and it's after @ marker */
colon = pegs->colon_first;
} else if (pegs->colon_last != pegs->authority) {
/* There's more than one colon */
colon = pegs->colon_last;
} else {
/* There's no colon that could be a port
* separator */
flags |= NSURL_F_NO_PORT;
}
 
if (!(flags & NSURL_F_NO_PORT)) {
/* Determine whether colon is a port separator
*/
sec_start += colon - pegs->at;
while (++sec_start < norm_start + length) {
if (!isdigit(*sec_start)) {
/* Character after port isn't a
* digit; not a port separator
*/
flags |= NSURL_F_NO_PORT;
break;
}
}
}
 
if (!(flags & NSURL_F_NO_PORT)) {
/* There's a port */
size_t skip = (pegs->at == pegs->authority) ?
1 : 0;
sec_start = norm_start + colon - pegs->at +
skip;
if (url->scheme != NULL &&
url->scheme_type ==
NSURL_SCHEME_HTTP &&
length -
(colon - pegs->at + skip) == 2 &&
*sec_start == '8' &&
*(sec_start + 1) == '0') {
/* Scheme is http, and port is default
* (80) */
flags |= NSURL_F_NO_PORT;
}
 
if (length - (colon - pegs->at + skip) <= 0) {
/* No space for a port after the colon
*/
flags |= NSURL_F_NO_PORT;
}
 
/* Add non-redundant ports to NetSurf URL */
sec_start = norm_start + colon - pegs->at +
skip;
if (!(flags & NSURL_F_NO_PORT) &&
lwc_intern_string(sec_start,
length -
(colon - pegs->at + skip),
&url->port) != lwc_error_ok) {
return NSERROR_NOMEM;
}
 
/* update length for host */
skip = (pegs->at == pegs->authority) ? 0 : 1;
length = colon - pegs->at - skip;
}
 
/* host */
if (lwc_intern_string(norm_start, length,
&url->host) != lwc_error_ok) {
return NSERROR_NOMEM;
}
}
 
break;
 
case URL_PATH:
if (length != 0) {
if (lwc_intern_string(norm_start, length,
&url->path) != lwc_error_ok) {
return NSERROR_NOMEM;
}
} else if (url->host != NULL &&
url->scheme_type != NSURL_SCHEME_MAILTO) {
/* Set empty path to "/", if there's a host */
if (lwc_intern_string("/", SLEN("/"),
&url->path) != lwc_error_ok) {
return NSERROR_NOMEM;
}
} else {
url->path = NULL;
}
 
break;
 
case URL_QUERY:
if (length != 0) {
if (lwc_intern_string(norm_start, length,
&url->query) != lwc_error_ok) {
return NSERROR_NOMEM;
}
} else {
url->query = NULL;
}
 
break;
 
case URL_FRAGMENT:
if (length != 0) {
if (lwc_intern_string(norm_start, length,
&url->fragment) != lwc_error_ok) {
return NSERROR_NOMEM;
}
} else {
url->fragment = NULL;
}
 
break;
}
 
return NSERROR_OK;
}
 
 
/**
* Get nsurl string info; total length, component lengths, & components present
*
* \param url NetSurf URL components
* \param parts Which parts of the URL are required in the string
* \param url_l Updated to total string length
* \param lengths Updated with individual component lengths
* \param pflags Updated to contain relevant string flags
*/
static void nsurl__get_string_data(const struct nsurl_components *url,
nsurl_component parts, size_t *url_l,
struct nsurl_component_lengths *lengths,
enum nsurl_string_flags *pflags)
{
enum nsurl_string_flags flags = *pflags;
*url_l = 0;
 
/* Intersection of required parts and available parts gives
* the output parts */
if (url->scheme && parts & NSURL_SCHEME) {
flags |= NSURL_F_SCHEME;
 
lengths->scheme = lwc_string_length(url->scheme);
*url_l += lengths->scheme;
}
 
if (url->username && parts & NSURL_USERNAME) {
flags |= NSURL_F_USERNAME;
 
lengths->username = lwc_string_length(url->username);
*url_l += lengths->username;
}
 
if (url->password && parts & NSURL_PASSWORD) {
flags |= NSURL_F_PASSWORD;
 
lengths->password = lwc_string_length(url->password);
*url_l += SLEN(":") + lengths->password;
}
 
if (url->host && parts & NSURL_HOST) {
flags |= NSURL_F_HOST;
 
lengths->host = lwc_string_length(url->host);
*url_l += lengths->host;
}
 
if (url->port && parts & NSURL_PORT) {
flags |= NSURL_F_PORT;
 
lengths->port = lwc_string_length(url->port);
*url_l += SLEN(":") + lengths->port;
}
 
if (url->path && parts & NSURL_PATH) {
flags |= NSURL_F_PATH;
 
lengths->path = lwc_string_length(url->path);
*url_l += lengths->path;
}
 
if (url->query && parts & NSURL_QUERY) {
flags |= NSURL_F_QUERY;
 
lengths->query = lwc_string_length(url->query);
*url_l += lengths->query;
}
 
if (url->fragment && parts & NSURL_FRAGMENT) {
flags |= NSURL_F_FRAGMENT;
 
lengths->fragment = lwc_string_length(url->fragment);
*url_l += lengths->fragment;
}
 
/* Turn on any spanned punctuation */
if ((flags & NSURL_F_SCHEME) && (parts > NSURL_SCHEME)) {
flags |= NSURL_F_SCHEME_PUNCTUATION;
 
*url_l += SLEN(":");
}
 
if ((flags & NSURL_F_SCHEME) && (flags > NSURL_F_SCHEME) &&
url->path && lwc_string_data(url->path)[0] == '/') {
flags |= NSURL_F_AUTHORITY_PUNCTUATION;
 
*url_l += SLEN("//");
}
 
if ((flags & (NSURL_F_USERNAME | NSURL_F_PASSWORD)) &&
flags & NSURL_F_HOST) {
flags |= NSURL_F_CREDENTIALS_PUNCTUATION;
 
*url_l += SLEN("@");
}
 
if ((flags & ~NSURL_F_FRAGMENT) && (flags & NSURL_F_FRAGMENT)) {
flags |= NSURL_F_FRAGMENT_PUNCTUATION;
 
*url_l += SLEN("#");
}
 
*pflags = flags;
}
 
 
/**
* Get nsurl string info; total length, component lengths, & components present
*
* \param url NetSurf URL components
* \param url_s Updated to contain the string
* \param l Individual component lengths
* \param flags String flags
*/
static void nsurl_get_string(const struct nsurl_components *url, char *url_s,
struct nsurl_component_lengths *l,
enum nsurl_string_flags flags)
{
char *pos;
 
/* Copy the required parts into the url string */
pos = url_s;
 
if (flags & NSURL_F_SCHEME) {
memcpy(pos, lwc_string_data(url->scheme), l->scheme);
pos += l->scheme;
}
 
if (flags & NSURL_F_SCHEME_PUNCTUATION) {
*(pos++) = ':';
}
 
if (flags & NSURL_F_AUTHORITY_PUNCTUATION) {
*(pos++) = '/';
*(pos++) = '/';
}
 
if (flags & NSURL_F_USERNAME) {
memcpy(pos, lwc_string_data(url->username), l->username);
pos += l->username;
}
 
if (flags & NSURL_F_PASSWORD) {
*(pos++) = ':';
memcpy(pos, lwc_string_data(url->password), l->password);
pos += l->password;
}
 
if (flags & NSURL_F_CREDENTIALS_PUNCTUATION) {
*(pos++) = '@';
}
 
if (flags & NSURL_F_HOST) {
memcpy(pos, lwc_string_data(url->host), l->host);
pos += l->host;
}
 
if (flags & NSURL_F_PORT) {
*(pos++) = ':';
memcpy(pos, lwc_string_data(url->port), l->port);
pos += l->port;
}
 
if (flags & NSURL_F_PATH) {
memcpy(pos, lwc_string_data(url->path), l->path);
pos += l->path;
}
 
if (flags & NSURL_F_QUERY) {
memcpy(pos, lwc_string_data(url->query), l->query);
pos += l->query;
}
 
if (flags & NSURL_F_FRAGMENT) {
if (flags & NSURL_F_FRAGMENT_PUNCTUATION)
*(pos++) = '#';
memcpy(pos, lwc_string_data(url->fragment), l->fragment);
pos += l->fragment;
}
 
*pos = '\0';
}
 
 
#ifdef NSURL_DEBUG
/**
* Dump a NetSurf URL's internal components
*
* \param url The NetSurf URL to dump components of
*/
static void nsurl__dump(const nsurl *url)
{
if (url->components.scheme)
LOG((" Scheme: %s", lwc_string_data(url->components.scheme)));
 
if (url->components.username)
LOG(("Username: %s",
lwc_string_data(url->components.username)));
 
if (url->components.password)
LOG(("Password: %s",
lwc_string_data(url->components.password)));
 
if (url->components.host)
LOG((" Host: %s", lwc_string_data(url->components.host)));
 
if (url->components.port)
LOG((" Port: %s", lwc_string_data(url->components.port)));
 
if (url->components.path)
LOG((" Path: %s", lwc_string_data(url->components.path)));
 
if (url->components.query)
LOG((" Query: %s", lwc_string_data(url->components.query)));
 
if (url->components.fragment)
LOG(("Fragment: %s",
lwc_string_data(url->components.fragment)));
}
#endif
 
/******************************************************************************
* NetSurf URL Public API *
******************************************************************************/
 
/* exported interface, documented in nsurl.h */
nserror nsurl_create(const char * const url_s, nsurl **url)
{
struct url_markers m;
struct nsurl_components c;
size_t length;
char *buff;
struct nsurl_component_lengths str_len = { 0, 0, 0, 0, 0, 0, 0, 0 };
enum nsurl_string_flags str_flags = 0;
nserror e = NSERROR_OK;
 
assert(url_s != NULL);
 
/* Peg out the URL sections */
nsurl__get_string_markers(url_s, &m, false);
 
/* Get the length of the longest section */
length = nsurl__get_longest_section(&m);
 
/* Allocate enough memory to url escape the longest section */
buff = malloc(length * 3 + 1);
if (buff == NULL)
return NSERROR_NOMEM;
 
/* Set scheme type */
c.scheme_type = m.scheme_type;
 
/* Build NetSurf URL object from sections */
e |= nsurl__create_from_section(url_s, URL_SCHEME, &m, buff, &c);
e |= nsurl__create_from_section(url_s, URL_CREDENTIALS, &m, buff, &c);
e |= nsurl__create_from_section(url_s, URL_HOST, &m, buff, &c);
e |= nsurl__create_from_section(url_s, URL_PATH, &m, buff, &c);
e |= nsurl__create_from_section(url_s, URL_QUERY, &m, buff, &c);
e |= nsurl__create_from_section(url_s, URL_FRAGMENT, &m, buff, &c);
 
/* Finished with buffer */
free(buff);
 
if (e != NSERROR_OK)
return NSERROR_NOMEM;
 
/* Get the string length and find which parts of url are present */
nsurl__get_string_data(&c, NSURL_WITH_FRAGMENT, &length,
&str_len, &str_flags);
 
/* Create NetSurf URL object */
*url = malloc(sizeof(nsurl) + length + 1); /* Add 1 for \0 */
if (*url == NULL)
return NSERROR_NOMEM;
 
(*url)->components = c;
(*url)->length = length;
 
/* Fill out the url string */
nsurl_get_string(&c, (*url)->string, &str_len, str_flags);
 
/* Give the URL a reference */
(*url)->count = 1;
 
return NSERROR_OK;
}
 
 
/* exported interface, documented in nsurl.h */
nsurl *nsurl_ref(nsurl *url)
{
assert(url != NULL);
 
url->count++;
 
return url;
}
 
 
/* exported interface, documented in nsurl.h */
void nsurl_unref(nsurl *url)
{
assert(url != NULL);
assert(url->count > 0);
 
if (--url->count > 0)
return;
 
#ifdef NSURL_DEBUG
nsurl__dump(url);
#endif
 
/* Release lwc strings */
if (url->components.scheme)
lwc_string_unref(url->components.scheme);
 
if (url->components.username)
lwc_string_unref(url->components.username);
 
if (url->components.password)
lwc_string_unref(url->components.password);
 
if (url->components.host)
lwc_string_unref(url->components.host);
 
if (url->components.port)
lwc_string_unref(url->components.port);
 
if (url->components.path)
lwc_string_unref(url->components.path);
 
if (url->components.query)
lwc_string_unref(url->components.query);
 
if (url->components.fragment)
lwc_string_unref(url->components.fragment);
 
/* Free the NetSurf URL */
free(url);
}
 
 
/* exported interface, documented in nsurl.h */
bool nsurl_compare(const nsurl *url1, const nsurl *url2, nsurl_component parts)
{
bool match = true;
 
assert(url1 != NULL);
assert(url2 != NULL);
 
/* Compare URL components */
 
/* Path, host and query first, since they're most likely to differ */
 
if (parts & NSURL_PATH) {
nsurl__component_compare(url1->components.path,
url2->components.path, &match);
 
if (match == false)
return false;
}
 
if (parts & NSURL_HOST) {
nsurl__component_compare(url1->components.host,
url2->components.host, &match);
 
if (match == false)
return false;
}
 
if (parts & NSURL_QUERY) {
nsurl__component_compare(url1->components.query,
url2->components.query, &match);
 
if (match == false)
return false;
}
 
if (parts & NSURL_SCHEME) {
nsurl__component_compare(url1->components.scheme,
url2->components.scheme, &match);
 
if (match == false)
return false;
}
 
if (parts & NSURL_USERNAME) {
nsurl__component_compare(url1->components.username,
url2->components.username, &match);
 
if (match == false)
return false;
}
 
if (parts & NSURL_PASSWORD) {
nsurl__component_compare(url1->components.password,
url2->components.password, &match);
 
if (match == false)
return false;
}
 
if (parts & NSURL_PORT) {
nsurl__component_compare(url1->components.port,
url2->components.port, &match);
 
if (match == false)
return false;
}
 
if (parts & NSURL_FRAGMENT) {
nsurl__component_compare(url1->components.fragment,
url2->components.fragment, &match);
 
if (match == false)
return false;
}
 
return true;
}
 
 
/* exported interface, documented in nsurl.h */
nserror nsurl_get(const nsurl *url, nsurl_component parts,
char **url_s, size_t *url_l)
{
struct nsurl_component_lengths str_len = { 0, 0, 0, 0, 0, 0, 0, 0 };
enum nsurl_string_flags str_flags = 0;
 
/* Get the string length and find which parts of url need copied */
nsurl__get_string_data(&(url->components), parts, url_l,
&str_len, &str_flags);
 
if (*url_l == 0) {
return NSERROR_BAD_URL;
}
 
/* Allocate memory for url string */
*url_s = malloc(*url_l + 1); /* adding 1 for '\0' */
if (*url_s == NULL) {
return NSERROR_NOMEM;
}
 
/* Copy the required parts into the url string */
nsurl_get_string(&(url->components), *url_s, &str_len, str_flags);
 
return NSERROR_OK;
}
 
 
/* exported interface, documented in nsurl.h */
lwc_string *nsurl_get_component(const nsurl *url, nsurl_component part)
{
assert(url != NULL);
 
switch (part) {
case NSURL_SCHEME:
return (url->components.scheme != NULL) ?
lwc_string_ref(url->components.scheme) : NULL;
 
case NSURL_USERNAME:
return (url->components.username != NULL) ?
lwc_string_ref(url->components.username) : NULL;
 
case NSURL_PASSWORD:
return (url->components.password != NULL) ?
lwc_string_ref(url->components.password) : NULL;
 
case NSURL_HOST:
return (url->components.host != NULL) ?
lwc_string_ref(url->components.host) : NULL;
 
case NSURL_PORT:
return (url->components.port != NULL) ?
lwc_string_ref(url->components.port) : NULL;
 
case NSURL_PATH:
return (url->components.path != NULL) ?
lwc_string_ref(url->components.path) : NULL;
 
case NSURL_QUERY:
return (url->components.query != NULL) ?
lwc_string_ref(url->components.query) : NULL;
 
case NSURL_FRAGMENT:
return (url->components.fragment != NULL) ?
lwc_string_ref(url->components.fragment) : NULL;
 
default:
LOG(("Unsupported value passed to part param."));
assert(0);
}
 
return NULL;
}
 
 
/* exported interface, documented in nsurl.h */
bool nsurl_has_component(const nsurl *url, nsurl_component part)
{
assert(url != NULL);
 
switch (part) {
case NSURL_SCHEME:
if (url->components.scheme != NULL)
return true;
else
return false;
 
case NSURL_CREDENTIALS:
/* Only username required for credentials section */
/* Fall through */
case NSURL_USERNAME:
if (url->components.username != NULL)
return true;
else
return false;
 
case NSURL_PASSWORD:
if (url->components.password != NULL)
return true;
else
return false;
 
case NSURL_HOST:
if (url->components.host != NULL)
return true;
else
return false;
 
case NSURL_PORT:
if (url->components.port != NULL)
return true;
else
return false;
 
case NSURL_PATH:
if (url->components.path != NULL)
return true;
else
return false;
 
case NSURL_QUERY:
if (url->components.query != NULL)
return true;
else
return false;
 
case NSURL_FRAGMENT:
if (url->components.fragment != NULL)
return true;
else
return false;
 
default:
LOG(("Unsupported value passed to part param."));
assert(0);
}
 
return false;
}
 
 
/* exported interface, documented in nsurl.h */
const char *nsurl_access(const nsurl *url)
{
assert(url != NULL);
 
return url->string;
}
 
 
/* exported interface, documented in nsurl.h */
const char *nsurl_access_leaf(const nsurl *url)
{
size_t path_len;
const char *path;
const char *leaf;
 
if (url->components.path == NULL)
return "";
 
path = lwc_string_data(url->components.path);
path_len = lwc_string_length(url->components.path);
 
if (path_len == 0)
return "";
 
if (path_len == 1 && *path == '/')
return "/";
 
leaf = path + path_len;
 
do {
leaf--;
} while ((leaf != path) && (*leaf != '/'));
 
if (*leaf == '/')
leaf++;
 
return leaf;
}
 
 
/* exported interface, documented in nsurl.h */
size_t nsurl_length(const nsurl *url)
{
assert(url != NULL);
 
return url->length;
}
 
 
/* exported interface, documented in nsurl.h */
nserror nsurl_join(const nsurl *base, const char *rel, nsurl **joined)
{
struct url_markers m;
struct nsurl_components c;
size_t length;
char *buff;
char *buff_pos;
char *buff_start;
struct nsurl_component_lengths str_len = { 0, 0, 0, 0, 0, 0, 0, 0 };
enum nsurl_string_flags str_flags = 0;
nserror error = 0;
enum {
NSURL_F_REL = 0,
NSURL_F_BASE_SCHEME = (1 << 0),
NSURL_F_BASE_AUTHORITY = (1 << 1),
NSURL_F_BASE_PATH = (1 << 2),
NSURL_F_MERGED_PATH = (1 << 3),
NSURL_F_BASE_QUERY = (1 << 4)
} joined_parts;
 
assert(base != NULL);
assert(rel != NULL);
 
/* Peg out the URL sections */
nsurl__get_string_markers(rel, &m, true);
 
/* Get the length of the longest section */
length = nsurl__get_longest_section(&m);
 
/* Initially assume that the joined URL can be formed entierly from
* the relative URL. */
joined_parts = NSURL_F_REL;
 
/* Update joined_compnents to indicate any required parts from the
* base URL. */
if (m.scheme_end - m.start <= 0) {
/* The relative url has no scheme.
* Use base URL's scheme. */
joined_parts |= NSURL_F_BASE_SCHEME;
 
if (m.path - m.authority <= 0) {
/* The relative URL has no authority.
* Use base URL's authority. */
joined_parts |= NSURL_F_BASE_AUTHORITY;
 
if (m.query - m.path <= 0) {
/* The relative URL has no path.
* Use base URL's path. */
joined_parts |= NSURL_F_BASE_PATH;
 
if (m.fragment - m.query <= 0) {
/* The relative URL has no query.
* Use base URL's query. */
joined_parts |= NSURL_F_BASE_QUERY;
}
 
} else if (*(rel + m.path) != '/') {
/* Relative URL has relative path */
joined_parts |= NSURL_F_MERGED_PATH;
}
}
}
 
/* Allocate enough memory to url escape the longest section, plus
* space for path merging (if required). */
if (joined_parts & NSURL_F_MERGED_PATH) {
/* Need to merge paths */
length += (base->components.path != NULL) ?
lwc_string_length(base->components.path) : 0;
}
length *= 4;
/* Plus space for removing dots from path */
length += (m.query - m.path) + ((base->components.path != NULL) ?
lwc_string_length(base->components.path) : 0);
 
buff = malloc(length + 5);
if (buff == NULL)
return NSERROR_NOMEM;
 
buff_pos = buff;
 
/* Form joined URL from base or rel components, as appropriate */
 
if (joined_parts & NSURL_F_BASE_SCHEME) {
c.scheme_type = base->components.scheme_type;
 
c.scheme = nsurl__component_copy(base->components.scheme);
} else {
c.scheme_type = m.scheme_type;
 
error |= nsurl__create_from_section(rel, URL_SCHEME, &m,
buff, &c);
}
 
if (joined_parts & NSURL_F_BASE_AUTHORITY) {
c.username = nsurl__component_copy(base->components.username);
c.password = nsurl__component_copy(base->components.password);
c.host = nsurl__component_copy(base->components.host);
c.port = nsurl__component_copy(base->components.port);
} else {
error |= nsurl__create_from_section(rel, URL_CREDENTIALS, &m,
buff, &c);
error |= nsurl__create_from_section(rel, URL_HOST, &m,
buff, &c);
}
 
if (joined_parts & NSURL_F_BASE_PATH) {
c.path = nsurl__component_copy(base->components.path);
 
} else if (joined_parts & NSURL_F_MERGED_PATH) {
struct url_markers m_path;
size_t new_length;
 
if (base->components.host != NULL &&
base->components.path == NULL) {
/* Append relative path to "/". */
*(buff_pos++) = '/';
memcpy(buff_pos, rel + m.path, m.query - m.path);
buff_pos += m.query - m.path;
 
} else {
/* Append relative path to all but last segment of
* base path. */
size_t path_end = lwc_string_length(
base->components.path);
const char *path = lwc_string_data(
base->components.path);
 
while (*(path + path_end) != '/' &&
path_end != 0) {
path_end--;
}
if (*(path + path_end) == '/')
path_end++;
 
/* Copy the base part */
memcpy(buff_pos, path, path_end);
buff_pos += path_end;
 
/* Copy the relative part */
memcpy(buff_pos, rel + m.path, m.query - m.path);
buff_pos += m.query - m.path;
}
 
/* add termination to string */
*buff_pos++ = '\0';
 
new_length = nsurl__remove_dot_segments(buff, buff_pos);
 
m_path.path = 0;
m_path.query = new_length;
 
buff_start = buff_pos + new_length;
error |= nsurl__create_from_section(buff_pos, URL_PATH, &m_path,
buff_start, &c);
 
} else {
struct url_markers m_path;
size_t new_length;
 
memcpy(buff_pos, rel + m.path, m.query - m.path);
buff_pos += m.query - m.path;
*(buff_pos++) = '\0';
 
new_length = nsurl__remove_dot_segments(buff, buff_pos);
 
m_path.path = 0;
m_path.query = new_length;
 
buff_start = buff_pos + new_length;
error |= nsurl__create_from_section(buff_pos, URL_PATH, &m_path,
buff_start, &c);
}
 
if (joined_parts & NSURL_F_BASE_QUERY)
c.query = nsurl__component_copy(base->components.query);
else
error |= nsurl__create_from_section(rel, URL_QUERY, &m,
buff, &c);
 
error |= nsurl__create_from_section(rel, URL_FRAGMENT, &m,
buff, &c);
 
/* Free temporary buffer */
free(buff);
 
if (error != NSERROR_OK)
return NSERROR_NOMEM;
 
/* Get the string length and find which parts of url are present */
nsurl__get_string_data(&c, NSURL_WITH_FRAGMENT, &length,
&str_len, &str_flags);
 
/* Create NetSurf URL object */
*joined = malloc(sizeof(nsurl) + length + 1); /* Add 1 for \0 */
if (*joined == NULL)
return NSERROR_NOMEM;
 
(*joined)->components = c;
(*joined)->length = length;
 
/* Fill out the url string */
nsurl_get_string(&c, (*joined)->string, &str_len, str_flags);
 
/* Give the URL a reference */
(*joined)->count = 1;
 
return NSERROR_OK;
}
 
 
/* exported interface, documented in nsurl.h */
nserror nsurl_defragment(const nsurl *url, nsurl **no_frag)
{
size_t length;
char *pos;
 
/* Find the change in length from url to new_url */
length = url->length;
if (url->components.fragment != NULL) {
length -= 1 + lwc_string_length(url->components.fragment);
}
 
/* Create NetSurf URL object */
*no_frag = malloc(sizeof(nsurl) + length + 1); /* Add 1 for \0 */
if (*no_frag == NULL) {
return NSERROR_NOMEM;
}
 
/* Copy components */
(*no_frag)->components.scheme =
nsurl__component_copy(url->components.scheme);
(*no_frag)->components.username =
nsurl__component_copy(url->components.username);
(*no_frag)->components.password =
nsurl__component_copy(url->components.password);
(*no_frag)->components.host =
nsurl__component_copy(url->components.host);
(*no_frag)->components.port =
nsurl__component_copy(url->components.port);
(*no_frag)->components.path =
nsurl__component_copy(url->components.path);
(*no_frag)->components.query =
nsurl__component_copy(url->components.query);
(*no_frag)->components.fragment = NULL;
 
(*no_frag)->components.scheme_type = url->components.scheme_type;
 
(*no_frag)->length = length;
 
/* Fill out the url string */
pos = (*no_frag)->string;
memcpy(pos, url->string, length);
pos += length;
*pos = '\0';
 
/* Give the URL a reference */
(*no_frag)->count = 1;
 
return NSERROR_OK;
}
 
 
/* exported interface, documented in nsurl.h */
nserror nsurl_refragment(const nsurl *url, lwc_string *frag, nsurl **new_url)
{
int frag_len;
int base_len;
char *pos;
size_t len;
 
assert(url != NULL);
assert(frag != NULL);
 
/* Find the change in length from url to new_url */
base_len = url->length;
if (url->components.fragment != NULL) {
base_len -= 1 + lwc_string_length(url->components.fragment);
}
frag_len = lwc_string_length(frag);
 
/* Set new_url's length */
len = base_len + 1 /* # */ + frag_len;
 
/* Create NetSurf URL object */
*new_url = malloc(sizeof(nsurl) + len + 1); /* Add 1 for \0 */
if (*new_url == NULL) {
return NSERROR_NOMEM;
}
 
(*new_url)->length = len;
 
/* Set string */
pos = (*new_url)->string;
memcpy(pos, url->string, base_len);
pos += base_len;
*pos = '#';
memcpy(++pos, lwc_string_data(frag), frag_len);
pos += frag_len;
*pos = '\0';
 
/* Copy components */
(*new_url)->components.scheme =
nsurl__component_copy(url->components.scheme);
(*new_url)->components.username =
nsurl__component_copy(url->components.username);
(*new_url)->components.password =
nsurl__component_copy(url->components.password);
(*new_url)->components.host =
nsurl__component_copy(url->components.host);
(*new_url)->components.port =
nsurl__component_copy(url->components.port);
(*new_url)->components.path =
nsurl__component_copy(url->components.path);
(*new_url)->components.query =
nsurl__component_copy(url->components.query);
(*new_url)->components.fragment =
lwc_string_ref(frag);
 
(*new_url)->components.scheme_type = url->components.scheme_type;
 
/* Give the URL a reference */
(*new_url)->count = 1;
 
return NSERROR_OK;
}
 
 
/* exported interface, documented in nsurl.h */
nserror nsurl_replace_query(const nsurl *url, const char *query,
nsurl **new_url)
{
int query_len;
int base_len;
char *pos;
size_t len;
lwc_string *lwc_query;
 
assert(url != NULL);
assert(query != NULL);
assert(query[0] == '?');
 
/* Get the length of the new query */
query_len = strlen(query);
 
/* Find the change in length from url to new_url */
base_len = url->length;
if (url->components.query != NULL) {
base_len -= lwc_string_length(url->components.query);
}
if (url->components.fragment != NULL) {
base_len -= 1 + lwc_string_length(url->components.fragment);
}
 
/* Set new_url's length */
len = base_len + query_len;
 
/* Create NetSurf URL object */
*new_url = malloc(sizeof(nsurl) + len + 1); /* Add 1 for \0 */
if (*new_url == NULL) {
return NSERROR_NOMEM;
}
 
if (lwc_intern_string(query, query_len, &lwc_query) != lwc_error_ok) {
free(*new_url);
return NSERROR_NOMEM;
}
 
(*new_url)->length = len;
 
/* Set string */
pos = (*new_url)->string;
memcpy(pos, url->string, base_len);
pos += base_len;
memcpy(pos, query, query_len);
pos += query_len;
if (url->components.fragment != NULL) {
const char *frag = lwc_string_data(url->components.fragment);
size_t frag_len = lwc_string_length(url->components.fragment);
*pos = '#';
memcpy(++pos, frag, frag_len);
pos += frag_len;
}
*pos = '\0';
 
/* Copy components */
(*new_url)->components.scheme =
nsurl__component_copy(url->components.scheme);
(*new_url)->components.username =
nsurl__component_copy(url->components.username);
(*new_url)->components.password =
nsurl__component_copy(url->components.password);
(*new_url)->components.host =
nsurl__component_copy(url->components.host);
(*new_url)->components.port =
nsurl__component_copy(url->components.port);
(*new_url)->components.path =
nsurl__component_copy(url->components.path);
(*new_url)->components.query = lwc_query;
(*new_url)->components.fragment =
nsurl__component_copy(url->components.fragment);
 
(*new_url)->components.scheme_type = url->components.scheme_type;
 
/* Give the URL a reference */
(*new_url)->count = 1;
 
return NSERROR_OK;
}
 
 
/* exported interface, documented in nsurl.h */
nserror nsurl_parent(const nsurl *url, nsurl **new_url)
{
lwc_string *lwc_path;
size_t old_path_len, new_path_len;
size_t len;
const char* path = NULL;
char *pos;
 
assert(url != NULL);
 
old_path_len = (url->components.path == NULL) ? 0 :
lwc_string_length(url->components.path);
 
/* Find new path length */
if (old_path_len == 0) {
new_path_len = old_path_len;
} else {
path = lwc_string_data(url->components.path);
 
new_path_len = old_path_len;
if (old_path_len > 1) {
/* Skip over any trailing / */
if (path[new_path_len - 1] == '/')
new_path_len--;
 
/* Work back to next / */
while (new_path_len > 0 &&
path[new_path_len - 1] != '/')
new_path_len--;
}
}
 
/* Find the length of new_url */
len = url->length;
if (url->components.query != NULL) {
len -= lwc_string_length(url->components.query);
}
if (url->components.fragment != NULL) {
len -= 1; /* # */
len -= lwc_string_length(url->components.fragment);
}
len -= old_path_len - new_path_len;
 
/* Create NetSurf URL object */
*new_url = malloc(sizeof(nsurl) + len + 1); /* Add 1 for \0 */
if (*new_url == NULL) {
return NSERROR_NOMEM;
}
 
/* Make new path */
if (old_path_len == 0) {
lwc_path = NULL;
} else if (old_path_len == new_path_len) {
lwc_path = lwc_string_ref(url->components.path);
} else {
if (lwc_intern_string(path, old_path_len - new_path_len,
&lwc_path) != lwc_error_ok) {
free(*new_url);
return NSERROR_NOMEM;
}
}
 
(*new_url)->length = len;
 
/* Set string */
pos = (*new_url)->string;
memcpy(pos, url->string, len);
pos += len;
*pos = '\0';
 
/* Copy components */
(*new_url)->components.scheme =
nsurl__component_copy(url->components.scheme);
(*new_url)->components.username =
nsurl__component_copy(url->components.username);
(*new_url)->components.password =
nsurl__component_copy(url->components.password);
(*new_url)->components.host =
nsurl__component_copy(url->components.host);
(*new_url)->components.port =
nsurl__component_copy(url->components.port);
(*new_url)->components.path = lwc_path;
(*new_url)->components.query = NULL;
(*new_url)->components.fragment = NULL;
 
(*new_url)->components.scheme_type = url->components.scheme_type;
 
/* Give the URL a reference */
(*new_url)->count = 1;
 
return NSERROR_OK;
}
 
/contrib/network/netsurf/netsurf/utils/nsurl.h
0,0 → 1,294
/*
* Copyright 2011 Michael Drake <tlsa@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
/** \file
* NetSurf URL handling (interface).
*/
 
#ifndef _NETSURF_UTILS_NSURL_H_
#define _NETSURF_UTILS_NSURL_H_
 
#include <libwapcaplet/libwapcaplet.h>
#include "utils/errors.h"
 
 
/** NetSurf URL object */
typedef struct nsurl nsurl;
 
 
typedef enum nsurl_component {
NSURL_SCHEME = (1 << 0),
NSURL_USERNAME = (1 << 1),
NSURL_PASSWORD = (1 << 2),
NSURL_CREDENTIALS = NSURL_USERNAME | NSURL_PASSWORD,
NSURL_HOST = (1 << 3),
NSURL_PORT = (1 << 4),
NSURL_AUTHORITY = NSURL_CREDENTIALS | NSURL_HOST | NSURL_PORT,
NSURL_PATH = (1 << 5),
NSURL_QUERY = (1 << 6),
NSURL_COMPLETE = NSURL_SCHEME | NSURL_AUTHORITY |
NSURL_PATH | NSURL_QUERY,
NSURL_FRAGMENT = (1 << 7),
NSURL_WITH_FRAGMENT = NSURL_COMPLETE | NSURL_FRAGMENT
} nsurl_component;
 
 
/**
* Create a NetSurf URL object from a URL string
*
* \param url_s String to create NetSurf URL from
* \param url Returns a NetSurf URL
* \return NSERROR_OK on success, appropriate error otherwise
*
* If return value != NSERROR_OK, nothing will be returned in url.
*
* It is up to the client to call nsurl_destroy when they are finished with
* the created object.
*/
nserror nsurl_create(const char * const url_s, nsurl **url);
 
 
/**
* Increment the reference count to a NetSurf URL object
*
* \param url NetSurf URL to create another reference to
* \return The NetSurf URL pointer to use as the copy
*
* Use this when copying a NetSurf URL into a persistent data structure.
*/
nsurl *nsurl_ref(nsurl *url);
 
 
/**
* Drop a reference to a NetSurf URL object
*
* \param url NetSurf URL to drop reference to
*
* When the reference count reaches zero then the NetSurf URL will be destroyed
*/
void nsurl_unref(nsurl *url);
 
 
/**
* Compare two URLs
*
* \param url1 First NetSurf URL
* \param url2 Second NetSurf URL
* \param parts The URL components to be compared
* \param match Returns true if url1 and url2 matched, else false
* \return NSERROR_OK on success, appropriate error otherwise
*
* If return value != NSERROR_OK, match will be false.
*/
bool nsurl_compare(const nsurl *url1, const nsurl *url2, nsurl_component parts);
 
 
/**
* Get URL (section) as a string, from a NetSurf URL object
*
* \param url NetSurf URL
* \param parts The required URL components.
* \param url_s Returns a url string
* \param url_l Returns length of url_s
* \return NSERROR_OK on success, appropriate error otherwise
*
* If return value != NSERROR_OK, nothing will be returned in url_s or url_l.
*
* The string returned in url_s is owned by the client and it is up to them
* to free it. It includes a trailing '\0'.
*
* The length returned in url_l excludes the trailing '\0'.
*
* That the required URL components be consecutive is not enforced, however,
* non-consecutive URL components generally make no sense. The exception
* is removal of credentials from a URL, such as for display in browser
* window URL bar. 'NSURL_COMPLETE &~ NSURL_PASSWORD' would remove the
* password from a complete URL.
*/
nserror nsurl_get(const nsurl *url, nsurl_component parts,
char **url_s, size_t *url_l);
 
 
/**
* Get part of a URL as a lwc_string, from a NetSurf URL object
*
* \param url NetSurf URL object
* \param part The URL component required
* \return the required component as an lwc_string, or NULL
*
* The caller owns the returned lwc_string and should call lwc_string_unref
* when they are done with it.
*
* The valid values for the part parameter are:
* NSURL_SCHEME
* NSURL_USERNAME
* NSURL_PASSWORD
* NSURL_HOST
* NSURL_PORT
* NSURL_PATH
* NSURL_QUERY
* NSURL_FRAGMENT
*/
lwc_string *nsurl_get_component(const nsurl *url, nsurl_component part);
 
 
/**
* Enquire about the existence of componenets in a given URL
*
* \param url NetSurf URL object
* \param part The URL components confirm existence of
* \return true iff the component in question exists in url
*
* The valid values for the part parameter are:
* NSURL_SCHEME
* NSURL_USERNAME
* NSURL_PASSWORD
* NSURL_CREDENTIALS
* NSURL_HOST
* NSURL_PORT
* NSURL_PATH
* NSURL_QUERY
* NSURL_FRAGMENT
*/
bool nsurl_has_component(const nsurl *url, nsurl_component part);
 
 
/**
* Access a NetSurf URL object as a string
*
* \param url NetSurf URL to retrieve a string pointer for.
* \return the required string
*
* The returned string is owned by the NetSurf URL object. It will die
* with the NetSurf URL object. Keep a reference to the URL if you need it.
*
* The returned string has a trailing '\0'.
*/
const char *nsurl_access(const nsurl *url);
 
 
/**
* Access a URL's path leaf as a string
*
* \param url NetSurf URL to retrieve a string pointer for.
* \return the required string
*
* The returned string is owned by the NetSurf URL object. It will die
* with the NetSurf URL object. Keep a reference to the URL if you need it.
*
* The returned string has a trailing '\0'.
*/
const char *nsurl_access_leaf(const nsurl *url);
 
 
/**
* Find the length of a NetSurf URL object's URL, as returned by nsurl_access
*
* \param url NetSurf URL to find length of.
* \return the required string
*
* The returned length excludes the trailing '\0'.
*/
size_t nsurl_length(const nsurl *url);
 
 
/**
* Join a base url to a relative link part, creating a new NetSurf URL object
*
* \param base NetSurf URL containing the base to join rel to
* \param rel String containing the relative link part
* \param joined Returns joined NetSurf URL
* \return NSERROR_OK on success, appropriate error otherwise
*
* If return value != NSERROR_OK, nothing will be returned in join.
*
* It is up to the client to call nsurl_destroy when they are finished with
* the created object.
*/
nserror nsurl_join(const nsurl *base, const char *rel, nsurl **joined);
 
 
/**
* Create a NetSurf URL object without a fragment from a NetSurf URL
*
* \param url NetSurf URL to create new NetSurf URL from
* \param no_frag Returns new NetSurf URL without fragment
* \return NSERROR_OK on success, appropriate error otherwise
*
* If return value != NSERROR_OK, nothing will be returned in no_frag.
*
* It is up to the client to call nsurl_destroy when they are finished with
* the created object.
*/
nserror nsurl_defragment(const nsurl *url, nsurl **no_frag);
 
 
/**
* Create a NetSurf URL object, adding a fragment to an existing URL object
*
* \param url NetSurf URL to create new NetSurf URL from
* \param frag Fragment to add
* \param new_url Returns new NetSurf URL without fragment
* \return NSERROR_OK on success, appropriate error otherwise
*
* If return value != NSERROR_OK, nothing will be returned in new_url.
*
* It is up to the client to call nsurl_destroy when they are finished with
* the created object.
*
* Any fragment in url is replaced with frag in new_url.
*/
nserror nsurl_refragment(const nsurl *url, lwc_string *frag, nsurl **new_url);
 
 
/**
* Create a NetSurf URL object, with query string replaced
*
* \param url NetSurf URL to create new NetSurf URL from
* \param query Query string to use
* \param new_url Returns new NetSurf URL with query string provided
* \return NSERROR_OK on success, appropriate error otherwise
*
* If return value != NSERROR_OK, nothing will be returned in new_url.
*
* It is up to the client to call nsurl_destroy when they are finished with
* the created object.
*
* Any query component in url is replaced with query in new_url.
*/
nserror nsurl_replace_query(const nsurl *url, const char *query,
nsurl **new_url);
 
 
/**
* Create a NetSurf URL object for URL with parent location of an existing URL.
*
* \param url NetSurf URL to create new NetSurf URL from
* \param new_url Returns new NetSurf URL with parent URL path
* \return NSERROR_OK on success, appropriate error otherwise
*
* If return value != NSERROR_OK, nothing will be returned in new_url.
*
* It is up to the client to call nsurl_destroy when they are finished with
* the created object.
*
* As well as stripping top most path segment, query and fragments are stripped.
*/
nserror nsurl_parent(const nsurl *url, nsurl **new_url);
 
#endif
/contrib/network/netsurf/netsurf/utils/ring.h
0,0 → 1,174
/*
* Copyright 2006, 2007 Daniel Silverstone <dsilvers@digital-scurf.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
/** \file
* Ring list structure.
*
* Rings are structures which have an r_next pointer and an r_prev
* pointer which are always initialised and always point at the next
* or previous element respectively.
*
* The degenerate case of a single element in the ring simply points
* at itself in both directions. A zero element ring is NULL.
*
* Some of the ring functions are specific to the fetcher but may be
* of use to others and are thus included here.
*/
 
#ifndef _NETSURF_UTILS_RING_H_
#define _NETSURF_UTILS_RING_H_
 
 
/** Insert the given item into the specified ring.
* Assumes that the element is zeroed as appropriate.
*/
#define RING_INSERT(ring,element) \
/*LOG(("RING_INSERT(%s, %p(%s))", #ring, element, element->host));*/ \
if (ring) { \
element->r_next = ring; \
element->r_prev = ring->r_prev; \
ring->r_prev = element; \
element->r_prev->r_next = element; \
} else \
ring = element->r_prev = element->r_next = element
 
/** Remove the given element from the specified ring.
* Will zero the element as needed
*/
#define RING_REMOVE(ring, element) \
/*LOG(("RING_REMOVE(%s, %p(%s)", #ring, element, element->host));*/ \
if (element->r_next != element ) { \
/* Not the only thing in the ring */ \
element->r_next->r_prev = element->r_prev; \
element->r_prev->r_next = element->r_next; \
if (ring == element) ring = element->r_next; \
} else { \
/* Only thing in the ring */ \
ring = 0; \
} \
element->r_next = element->r_prev = 0
 
/** Find the element (by hostname) in the given ring, leave it in the
* provided element variable
*/
#define RING_FINDBYHOST(ring, element, hostname) \
/*LOG(("RING_FINDBYHOST(%s, %s)", #ring, hostname));*/ \
if (ring) { \
bool found = false; \
element = ring; \
do { \
if (strcasecmp(element->host, hostname) == 0) { \
found = true; \
break; \
} \
element = element->r_next; \
} while (element != ring); \
if (!found) element = 0; \
} else element = 0
 
/** Find the element (by hostname) in the given ring, leave it in the
* provided element variable
*/
#define RING_FINDBYLWCHOST(ring, element, lwc_hostname) \
/*LOG(("RING_FINDBYHOST(%s, %s)", #ring, hostname));*/ \
if (ring) { \
bool found = false; \
element = ring; \
do { \
if (lwc_string_isequal(element->host, lwc_hostname, \
&found) == lwc_error_ok && \
found == true) { \
break; \
} \
element = element->r_next; \
} while (element != ring); \
if (!found) element = 0; \
} else element = 0
 
/** Measure the size of a ring and put it in the supplied variable */
#define RING_GETSIZE(ringtype, ring, sizevar) \
/*LOG(("RING_GETSIZE(%s)", #ring));*/ \
if (ring) { \
ringtype *p = ring; \
sizevar = 0; \
do { \
sizevar++; \
p = p->r_next; \
} while (p != ring); \
} else sizevar = 0
 
/** Count the number of elements in the ring which match the provided hostname */
#define RING_COUNTBYHOST(ringtype, ring, sizevar, hostname) \
/*LOG(("RING_COUNTBYHOST(%s, %s)", #ring, hostname));*/ \
if (ring) { \
ringtype *p = ring; \
sizevar = 0; \
do { \
if (strcasecmp(p->host, hostname) == 0) \
sizevar++; \
p = p->r_next; \
} while (p != ring); \
} else sizevar = 0
 
/** Count the number of elements in the ring which match the provided lwc_hostname */
#define RING_COUNTBYLWCHOST(ringtype, ring, sizevar, lwc_hostname) \
/*LOG(("RING_COUNTBYHOST(%s, %s)", #ring, hostname));*/ \
if (ring) { \
ringtype *p = ring; \
sizevar = 0; \
do { \
bool matches = false; \
/* nsurl guarantees lowercase host */ \
if (lwc_string_isequal(p->host, lwc_hostname, \
&matches) == lwc_error_ok) \
if (matches) \
sizevar++; \
p = p->r_next; \
} while (p != ring); \
} else sizevar = 0
 
/*
* Ring iteration works as follows:
*
* RING_ITERATE_START(ringtype, ring, iteratorptr) {
* code_using(iteratorptr);
* } RING_ITERATE_END(ring, iteratorptr);
*
* If you want to stop iterating (e.g. you found your answer)
* RING_ITERATE_STOP(ring, iteratorptr);
* You *MUST* abort the iteration if you do something to modify
* the ring such as deleting or adding an element.
*/
 
#define RING_ITERATE_START(ringtype, ring, iteratorptr) \
if (ring != NULL) { \
ringtype *iteratorptr = ring; \
do { \
do { \
#define RING_ITERATE_STOP(ring, iteratorptr) \
goto iteration_end_ring##_##iteratorptr
 
#define RING_ITERATE_END(ring, iteratorptr) \
} while (false); \
iteratorptr = iteratorptr->r_next; \
} while (iteratorptr != ring); \
} \
iteration_end_ring##_##iteratorptr:
 
#endif
/contrib/network/netsurf/netsurf/utils/schedule.h
0,0 → 1,32
/*
* Copyright 2011 Daniel Silverstone <dsilvers@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
/** \file
* Job scheduler (interface).
*/
 
#ifndef _NETSURF_UTILS_SCHEDULE_H_
#define _NETSURF_UTILS_SCHEDULE_H_
 
/* In platform specific schedule.c. */
typedef void (*schedule_callback_fn)(void *p);
 
void schedule(int t, schedule_callback_fn callback, void *p);
void schedule_remove(schedule_callback_fn callback, void *p);
 
#endif
/contrib/network/netsurf/netsurf/utils/split-messages.pl
0,0 → 1,23
#!/usr/bin/perl -w
 
use strict;
 
die "usage: split-messages <langname> <platname> < FatMessages > ThinMessages" if ($#ARGV != 1);
 
my $langname = $ARGV[0];
my $platname = $ARGV[1];
 
my $allprefix = $langname . ".all.";
my $platprefix = $langname . "." . $platname . ".";
 
print "# This messages file is automatically generated from FatMessages\n";
print "# at build-time. Please go and edit that instead of this.\n\n";
 
foreach (<STDIN>) {
if (not /^#/ and not /^\s*$/) {
if (/^$allprefix/ or /^$platprefix/) {
s/^$langname\.(all|$platname)\.//;
print "$_";
}
}
}
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/contrib/network/netsurf/netsurf/utils/talloc.c
0,0 → 1,1435
/*
Samba Unix SMB/CIFS implementation.
 
Samba trivial allocation library - new interface
 
NOTE: Please read talloc_guide.txt for full documentation
 
Copyright (C) Andrew Tridgell 2004
Copyright (C) Stefan Metzmacher 2006
** NOTE! The following LGPL license applies to the talloc
** library. This does NOT imply that all of Samba is released
** under the LGPL
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
 
/*
inspired by http://swapped.cc/halloc/
*/
 
#ifdef _SAMBA_BUILD_
#include "version.h"
#if (SAMBA_VERSION_MAJOR<4)
#include "includes.h"
/* This is to circumvent SAMBA3's paranoid malloc checker. Here in this file
* we trust ourselves... */
#ifdef malloc
#undef malloc
#endif
#ifdef realloc
#undef realloc
#endif
#define _TALLOC_SAMBA3
#endif /* (SAMBA_VERSION_MAJOR<4) */
#endif /* _SAMBA_BUILD_ */
 
/* jmb -- allow this to build standalone */
#define STANDALONE
 
#ifndef _TALLOC_SAMBA3
#ifndef STANDALONE
#include "replace.h"
#else
#include <stdarg.h>
#if !defined(__BEOS__) && !defined(__HAIKU__) && __GNUC__ > 2
/* Assume we've got va_copy */
#define HAVE_VA_COPY
#include <string.h>
#endif
#endif
#include "talloc.h"
#endif /* not _TALLOC_SAMBA3 */
 
/* use this to force every realloc to change the pointer, to stress test
code that might not cope */
#define ALWAYS_REALLOC 0
 
 
#define MAX_TALLOC_SIZE 0x10000000
#define TALLOC_MAGIC 0xe814ec70
#define TALLOC_FLAG_FREE 0x01
#define TALLOC_FLAG_LOOP 0x02
#define TALLOC_MAGIC_REFERENCE ((const char *)1)
 
/* by default we abort when given a bad pointer (such as when talloc_free() is called
on a pointer that came from malloc() */
#ifndef TALLOC_ABORT
#define TALLOC_ABORT(reason) abort()
#endif
 
#ifndef discard_const_p
#if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
# define discard_const_p(type, ptr) ((type *)((intptr_t)(ptr)))
#else
# define discard_const_p(type, ptr) ((type *)(ptr))
#endif
#endif
 
/* these macros gain us a few percent of speed on gcc */
#if (__GNUC__ >= 3)
/* the strange !! is to ensure that __builtin_expect() takes either 0 or 1
as its first argument */
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
#else
#define likely(x) x
#define unlikely(x) x
#endif
 
/* this null_context is only used if talloc_enable_leak_report() or
talloc_enable_leak_report_full() is called, otherwise it remains
NULL
*/
static void *null_context;
static void *autofree_context;
 
struct talloc_reference_handle {
struct talloc_reference_handle *next, *prev;
void *ptr;
};
 
typedef int (*talloc_destructor_t)(void *);
 
struct talloc_chunk {
struct talloc_chunk *next, *prev;
struct talloc_chunk *parent, *child;
struct talloc_reference_handle *refs;
talloc_destructor_t destructor;
const char *name;
size_t size;
unsigned flags;
};
 
/* 16 byte alignment seems to keep everyone happy */
#define TC_HDR_SIZE ((sizeof(struct talloc_chunk)+15)&~15)
#define TC_PTR_FROM_CHUNK(tc) ((void *)(TC_HDR_SIZE + (char*)tc))
 
/* panic if we get a bad magic value */
static inline struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr)
{
const void *pp = ((const char *)ptr) - TC_HDR_SIZE;
struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, pp);
if (unlikely((tc->flags & (TALLOC_FLAG_FREE | ~0xF)) != TALLOC_MAGIC)) {
if (tc->flags & TALLOC_FLAG_FREE) {
TALLOC_ABORT("Bad talloc magic value - double free");
} else {
TALLOC_ABORT("Bad talloc magic value - unknown value");
}
}
return tc;
}
 
/* hook into the front of the list */
#define _TLIST_ADD(list, p) \
do { \
if (!(list)) { \
(list) = (p); \
(p)->next = (p)->prev = NULL; \
} else { \
(list)->prev = (p); \
(p)->next = (list); \
(p)->prev = NULL; \
(list) = (p); \
}\
} while (0)
 
/* remove an element from a list - element doesn't have to be in list. */
#define _TLIST_REMOVE(list, p) \
do { \
if ((p) == (list)) { \
(list) = (p)->next; \
if (list) (list)->prev = NULL; \
} else { \
if ((p)->prev) (p)->prev->next = (p)->next; \
if ((p)->next) (p)->next->prev = (p)->prev; \
} \
if ((p) && ((p) != (list))) (p)->next = (p)->prev = NULL; \
} while (0)
 
 
/*
return the parent chunk of a pointer
*/
static inline struct talloc_chunk *talloc_parent_chunk(const void *ptr)
{
struct talloc_chunk *tc;
 
if (unlikely(ptr == NULL)) {
return NULL;
}
 
tc = talloc_chunk_from_ptr(ptr);
while (tc->prev) tc=tc->prev;
 
return tc->parent;
}
 
void *talloc_parent(const void *ptr)
{
struct talloc_chunk *tc = talloc_parent_chunk(ptr);
return tc? TC_PTR_FROM_CHUNK(tc) : NULL;
}
 
/*
find parents name
*/
const char *talloc_parent_name(const void *ptr)
{
struct talloc_chunk *tc = talloc_parent_chunk(ptr);
return tc? tc->name : NULL;
}
 
/*
Allocate a bit of memory as a child of an existing pointer
*/
static inline void *__talloc(const void *context, size_t size)
{
struct talloc_chunk *tc;
 
if (unlikely(context == NULL)) {
context = null_context;
}
 
if (unlikely(size >= MAX_TALLOC_SIZE)) {
return NULL;
}
 
tc = (struct talloc_chunk *)malloc(TC_HDR_SIZE+size);
if (unlikely(tc == NULL)) return NULL;
 
tc->size = size;
tc->flags = TALLOC_MAGIC;
tc->destructor = NULL;
tc->child = NULL;
tc->name = NULL;
tc->refs = NULL;
 
if (likely(context)) {
struct talloc_chunk *parent = talloc_chunk_from_ptr(context);
 
if (parent->child) {
parent->child->parent = NULL;
tc->next = parent->child;
tc->next->prev = tc;
} else {
tc->next = NULL;
}
tc->parent = parent;
tc->prev = NULL;
parent->child = tc;
} else {
tc->next = tc->prev = tc->parent = NULL;
}
 
return TC_PTR_FROM_CHUNK(tc);
}
 
/*
setup a destructor to be called on free of a pointer
the destructor should return 0 on success, or -1 on failure.
if the destructor fails then the free is failed, and the memory can
be continued to be used
*/
void _talloc_set_destructor(const void *ptr, int (*destructor)(void *))
{
struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
tc->destructor = destructor;
}
 
/*
increase the reference count on a piece of memory.
*/
int talloc_increase_ref_count(const void *ptr)
{
if (unlikely(!talloc_reference(null_context, ptr))) {
return -1;
}
return 0;
}
 
/*
helper for talloc_reference()
 
this is referenced by a function pointer and should not be inline
*/
static int talloc_reference_destructor(struct talloc_reference_handle *handle)
{
struct talloc_chunk *ptr_tc = talloc_chunk_from_ptr(handle->ptr);
_TLIST_REMOVE(ptr_tc->refs, handle);
return 0;
}
 
/*
more efficient way to add a name to a pointer - the name must point to a
true string constant
*/
static inline void _talloc_set_name_const(const void *ptr, const char *name)
{
struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
tc->name = name;
}
 
/*
internal talloc_named_const()
*/
static inline void *_talloc_named_const(const void *context, size_t size, const char *name)
{
void *ptr;
 
ptr = __talloc(context, size);
if (unlikely(ptr == NULL)) {
return NULL;
}
 
_talloc_set_name_const(ptr, name);
 
return ptr;
}
 
/*
make a secondary reference to a pointer, hanging off the given context.
the pointer remains valid until both the original caller and this given
context are freed.
the major use for this is when two different structures need to reference the
same underlying data, and you want to be able to free the two instances separately,
and in either order
*/
void *_talloc_reference(const void *context, const void *ptr)
{
struct talloc_chunk *tc;
struct talloc_reference_handle *handle;
if (unlikely(ptr == NULL)) return NULL;
 
tc = talloc_chunk_from_ptr(ptr);
handle = (struct talloc_reference_handle *)_talloc_named_const(context,
sizeof(struct talloc_reference_handle),
TALLOC_MAGIC_REFERENCE);
if (unlikely(handle == NULL)) return NULL;
 
/* note that we hang the destructor off the handle, not the
main context as that allows the caller to still setup their
own destructor on the context if they want to */
talloc_set_destructor(handle, talloc_reference_destructor);
handle->ptr = discard_const_p(void, ptr);
_TLIST_ADD(tc->refs, handle);
return handle->ptr;
}
 
 
/*
internal talloc_free call
*/
static inline int _talloc_free(void *ptr)
{
struct talloc_chunk *tc;
 
if (unlikely(ptr == NULL)) {
return -1;
}
 
tc = talloc_chunk_from_ptr(ptr);
 
if (unlikely(tc->refs)) {
int is_child;
/* check this is a reference from a child or grantchild
* back to it's parent or grantparent
*
* in that case we need to remove the reference and
* call another instance of talloc_free() on the current
* pointer.
*/
is_child = talloc_is_parent(tc->refs, ptr);
_talloc_free(tc->refs);
if (is_child) {
return _talloc_free(ptr);
}
return -1;
}
 
if (unlikely(tc->flags & TALLOC_FLAG_LOOP)) {
/* we have a free loop - stop looping */
return 0;
}
 
if (unlikely(tc->destructor)) {
talloc_destructor_t d = tc->destructor;
if (d == (talloc_destructor_t)-1) {
return -1;
}
tc->destructor = (talloc_destructor_t)-1;
if (d(ptr) == -1) {
tc->destructor = d;
return -1;
}
tc->destructor = NULL;
}
 
if (tc->parent) {
_TLIST_REMOVE(tc->parent->child, tc);
if (tc->parent->child) {
tc->parent->child->parent = tc->parent;
}
} else {
if (tc->prev) tc->prev->next = tc->next;
if (tc->next) tc->next->prev = tc->prev;
}
 
tc->flags |= TALLOC_FLAG_LOOP;
 
while (tc->child) {
/* we need to work out who will own an abandoned child
if it cannot be freed. In priority order, the first
choice is owner of any remaining reference to this
pointer, the second choice is our parent, and the
final choice is the null context. */
void *child = TC_PTR_FROM_CHUNK(tc->child);
const void *new_parent = null_context;
if (unlikely(tc->child->refs)) {
struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
if (p) new_parent = TC_PTR_FROM_CHUNK(p);
}
if (unlikely(_talloc_free(child) == -1)) {
if (new_parent == null_context) {
struct talloc_chunk *p = talloc_parent_chunk(ptr);
if (p) new_parent = TC_PTR_FROM_CHUNK(p);
}
(void) talloc_steal(new_parent, child);
}
}
 
tc->flags |= TALLOC_FLAG_FREE;
free(tc);
return 0;
}
 
/*
move a lump of memory from one talloc context to another return the
ptr on success, or NULL if it could not be transferred.
passing NULL as ptr will always return NULL with no side effects.
*/
void *_talloc_steal(const void *new_ctx, const void *ptr)
{
struct talloc_chunk *tc, *new_tc;
 
if (unlikely(!ptr)) {
return NULL;
}
 
if (unlikely(new_ctx == NULL)) {
new_ctx = null_context;
}
 
tc = talloc_chunk_from_ptr(ptr);
 
if (unlikely(new_ctx == NULL)) {
if (tc->parent) {
_TLIST_REMOVE(tc->parent->child, tc);
if (tc->parent->child) {
tc->parent->child->parent = tc->parent;
}
} else {
if (tc->prev) tc->prev->next = tc->next;
if (tc->next) tc->next->prev = tc->prev;
}
tc->parent = tc->next = tc->prev = NULL;
return discard_const_p(void, ptr);
}
 
new_tc = talloc_chunk_from_ptr(new_ctx);
 
if (unlikely(tc == new_tc || tc->parent == new_tc)) {
return discard_const_p(void, ptr);
}
 
if (tc->parent) {
_TLIST_REMOVE(tc->parent->child, tc);
if (tc->parent->child) {
tc->parent->child->parent = tc->parent;
}
} else {
if (tc->prev) tc->prev->next = tc->next;
if (tc->next) tc->next->prev = tc->prev;
}
 
tc->parent = new_tc;
if (new_tc->child) new_tc->child->parent = NULL;
_TLIST_ADD(new_tc->child, tc);
 
return discard_const_p(void, ptr);
}
 
 
 
/*
remove a secondary reference to a pointer. This undo's what
talloc_reference() has done. The context and pointer arguments
must match those given to a talloc_reference()
*/
static inline int talloc_unreference(const void *context, const void *ptr)
{
struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
struct talloc_reference_handle *h;
 
if (unlikely(context == NULL)) {
context = null_context;
}
 
for (h=tc->refs;h;h=h->next) {
struct talloc_chunk *p = talloc_parent_chunk(h);
if (p == NULL) {
if (context == NULL) break;
} else if (TC_PTR_FROM_CHUNK(p) == context) {
break;
}
}
if (h == NULL) {
return -1;
}
 
return _talloc_free(h);
}
 
/*
remove a specific parent context from a pointer. This is a more
controlled varient of talloc_free()
*/
int talloc_unlink(const void *context, void *ptr)
{
struct talloc_chunk *tc_p, *new_p;
void *new_parent;
 
if (ptr == NULL) {
return -1;
}
 
if (context == NULL) {
context = null_context;
}
 
if (talloc_unreference(context, ptr) == 0) {
return 0;
}
 
if (context == NULL) {
if (talloc_parent_chunk(ptr) != NULL) {
return -1;
}
} else {
if (talloc_chunk_from_ptr(context) != talloc_parent_chunk(ptr)) {
return -1;
}
}
tc_p = talloc_chunk_from_ptr(ptr);
 
if (tc_p->refs == NULL) {
return _talloc_free(ptr);
}
 
new_p = talloc_parent_chunk(tc_p->refs);
if (new_p) {
new_parent = TC_PTR_FROM_CHUNK(new_p);
} else {
new_parent = NULL;
}
 
if (talloc_unreference(new_parent, ptr) != 0) {
return -1;
}
 
(void) talloc_steal(new_parent, ptr);
 
return 0;
}
 
/*
add a name to an existing pointer - va_list version
*/
static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
 
static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap)
{
struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
tc->name = talloc_vasprintf(ptr, fmt, ap);
if (likely(tc->name)) {
_talloc_set_name_const(tc->name, ".name");
}
return tc->name;
}
 
/*
add a name to an existing pointer
*/
const char *talloc_set_name(const void *ptr, const char *fmt, ...)
{
const char *name;
va_list ap;
va_start(ap, fmt);
name = talloc_set_name_v(ptr, fmt, ap);
va_end(ap);
return name;
}
 
 
/*
create a named talloc pointer. Any talloc pointer can be named, and
talloc_named() operates just like talloc() except that it allows you
to name the pointer.
*/
void *talloc_named(const void *context, size_t size, const char *fmt, ...)
{
va_list ap;
void *ptr;
const char *name;
 
ptr = __talloc(context, size);
if (unlikely(ptr == NULL)) return NULL;
 
va_start(ap, fmt);
name = talloc_set_name_v(ptr, fmt, ap);
va_end(ap);
 
if (unlikely(name == NULL)) {
_talloc_free(ptr);
return NULL;
}
 
return ptr;
}
 
/*
return the name of a talloc ptr, or "UNNAMED"
*/
const char *talloc_get_name(const void *ptr)
{
struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
if (unlikely(tc->name == TALLOC_MAGIC_REFERENCE)) {
return ".reference";
}
if (likely(tc->name)) {
return tc->name;
}
return "UNNAMED";
}
 
 
/*
check if a pointer has the given name. If it does, return the pointer,
otherwise return NULL
*/
void *talloc_check_name(const void *ptr, const char *name)
{
const char *pname;
if (unlikely(ptr == NULL)) return NULL;
pname = talloc_get_name(ptr);
if (likely(pname == name || strcmp(pname, name) == 0)) {
return discard_const_p(void, ptr);
}
return NULL;
}
 
 
/*
this is for compatibility with older versions of talloc
*/
void *talloc_init(const char *fmt, ...)
{
va_list ap;
void *ptr;
const char *name;
 
/*
* samba3 expects talloc_report_depth_cb(NULL, ...)
* reports all talloc'ed memory, so we need to enable
* null_tracking
*/
talloc_enable_null_tracking();
 
ptr = __talloc(NULL, 0);
if (unlikely(ptr == NULL)) return NULL;
 
va_start(ap, fmt);
name = talloc_set_name_v(ptr, fmt, ap);
va_end(ap);
 
if (unlikely(name == NULL)) {
_talloc_free(ptr);
return NULL;
}
 
return ptr;
}
 
/*
this is a replacement for the Samba3 talloc_destroy_pool functionality. It
should probably not be used in new code. It's in here to keep the talloc
code consistent across Samba 3 and 4.
*/
void talloc_free_children(void *ptr)
{
struct talloc_chunk *tc;
 
if (unlikely(ptr == NULL)) {
return;
}
 
tc = talloc_chunk_from_ptr(ptr);
 
while (tc->child) {
/* we need to work out who will own an abandoned child
if it cannot be freed. In priority order, the first
choice is owner of any remaining reference to this
pointer, the second choice is our parent, and the
final choice is the null context. */
void *child = TC_PTR_FROM_CHUNK(tc->child);
const void *new_parent = null_context;
if (unlikely(tc->child->refs)) {
struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
if (p) new_parent = TC_PTR_FROM_CHUNK(p);
}
if (unlikely(_talloc_free(child) == -1)) {
if (new_parent == null_context) {
struct talloc_chunk *p = talloc_parent_chunk(ptr);
if (p) new_parent = TC_PTR_FROM_CHUNK(p);
}
(void) talloc_steal(new_parent, child);
}
}
}
 
/*
Allocate a bit of memory as a child of an existing pointer
*/
void *_talloc(const void *context, size_t size)
{
return __talloc(context, size);
}
 
/*
externally callable talloc_set_name_const()
*/
void talloc_set_name_const(const void *ptr, const char *name)
{
_talloc_set_name_const(ptr, name);
}
 
/*
create a named talloc pointer. Any talloc pointer can be named, and
talloc_named() operates just like talloc() except that it allows you
to name the pointer.
*/
void *talloc_named_const(const void *context, size_t size, const char *name)
{
return _talloc_named_const(context, size, name);
}
 
/*
free a talloc pointer. This also frees all child pointers of this
pointer recursively
 
return 0 if the memory is actually freed, otherwise -1. The memory
will not be freed if the ref_count is > 1 or the destructor (if
any) returns non-zero
*/
int talloc_free(void *ptr)
{
return _talloc_free(ptr);
}
 
 
 
/*
A talloc version of realloc. The context argument is only used if
ptr is NULL
*/
void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name)
{
struct talloc_chunk *tc;
void *new_ptr;
 
/* size zero is equivalent to free() */
if (unlikely(size == 0)) {
_talloc_free(ptr);
return NULL;
}
 
if (unlikely(size >= MAX_TALLOC_SIZE)) {
return NULL;
}
 
/* realloc(NULL) is equivalent to malloc() */
if (ptr == NULL) {
return _talloc_named_const(context, size, name);
}
 
tc = talloc_chunk_from_ptr(ptr);
 
/* don't allow realloc on referenced pointers */
if (unlikely(tc->refs)) {
return NULL;
}
 
/* by resetting magic we catch users of the old memory */
tc->flags |= TALLOC_FLAG_FREE;
 
#if ALWAYS_REALLOC
new_ptr = malloc(size + TC_HDR_SIZE);
if (new_ptr) {
memcpy(new_ptr, tc, tc->size + TC_HDR_SIZE);
free(tc);
}
#else
new_ptr = realloc(tc, size + TC_HDR_SIZE);
#endif
if (unlikely(!new_ptr)) {
tc->flags &= ~TALLOC_FLAG_FREE;
return NULL;
}
 
tc = (struct talloc_chunk *)new_ptr;
tc->flags &= ~TALLOC_FLAG_FREE;
if (tc->parent) {
tc->parent->child = tc;
}
if (tc->child) {
tc->child->parent = tc;
}
 
if (tc->prev) {
tc->prev->next = tc;
}
if (tc->next) {
tc->next->prev = tc;
}
 
tc->size = size;
_talloc_set_name_const(TC_PTR_FROM_CHUNK(tc), name);
 
return TC_PTR_FROM_CHUNK(tc);
}
 
/*
a wrapper around talloc_steal() for situations where you are moving a pointer
between two structures, and want the old pointer to be set to NULL
*/
void *_talloc_move(const void *new_ctx, const void *_pptr)
{
const void **pptr = discard_const_p(const void *,_pptr);
void *ret = _talloc_steal(new_ctx, *pptr);
(*pptr) = NULL;
return ret;
}
 
/*
return the total size of a talloc pool (subtree)
*/
size_t talloc_total_size(const void *ptr)
{
size_t total = 0;
struct talloc_chunk *c, *tc;
 
if (ptr == NULL) {
ptr = null_context;
}
if (ptr == NULL) {
return 0;
}
 
tc = talloc_chunk_from_ptr(ptr);
 
if (tc->flags & TALLOC_FLAG_LOOP) {
return 0;
}
 
tc->flags |= TALLOC_FLAG_LOOP;
 
total = tc->size;
for (c=tc->child;c;c=c->next) {
total += talloc_total_size(TC_PTR_FROM_CHUNK(c));
}
 
tc->flags &= ~TALLOC_FLAG_LOOP;
 
return total;
}
 
/*
return the total number of blocks in a talloc pool (subtree)
*/
size_t talloc_total_blocks(const void *ptr)
{
size_t total = 0;
struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
 
if (tc->flags & TALLOC_FLAG_LOOP) {
return 0;
}
 
tc->flags |= TALLOC_FLAG_LOOP;
 
total++;
for (c=tc->child;c;c=c->next) {
total += talloc_total_blocks(TC_PTR_FROM_CHUNK(c));
}
 
tc->flags &= ~TALLOC_FLAG_LOOP;
 
return total;
}
 
/*
return the number of external references to a pointer
*/
size_t talloc_reference_count(const void *ptr)
{
struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
struct talloc_reference_handle *h;
size_t ret = 0;
 
for (h=tc->refs;h;h=h->next) {
ret++;
}
return ret;
}
 
/*
report on memory usage by all children of a pointer, giving a full tree view
*/
void talloc_report_depth_cb(const void *ptr, int depth, int max_depth,
void (*callback)(const void *ptr,
int depth, int max_depth,
int is_ref,
void *private_data),
void *private_data)
{
struct talloc_chunk *c, *tc;
 
if (ptr == NULL) {
ptr = null_context;
}
if (ptr == NULL) return;
 
tc = talloc_chunk_from_ptr(ptr);
 
if (tc->flags & TALLOC_FLAG_LOOP) {
return;
}
 
callback(ptr, depth, max_depth, 0, private_data);
 
if (max_depth >= 0 && depth >= max_depth) {
return;
}
 
tc->flags |= TALLOC_FLAG_LOOP;
for (c=tc->child;c;c=c->next) {
if (c->name == TALLOC_MAGIC_REFERENCE) {
struct talloc_reference_handle *h = (struct talloc_reference_handle *)TC_PTR_FROM_CHUNK(c);
callback(h->ptr, depth + 1, max_depth, 1, private_data);
} else {
talloc_report_depth_cb(TC_PTR_FROM_CHUNK(c), depth + 1, max_depth, callback, private_data);
}
}
tc->flags &= ~TALLOC_FLAG_LOOP;
}
 
static void talloc_report_depth_FILE_helper(const void *ptr, int depth, int max_depth, int is_ref, void *_f)
{
const char *name = talloc_get_name(ptr);
FILE *f = (FILE *)_f;
 
if (is_ref) {
fprintf(f, "%*sreference to: %s\n", depth*4, "", name);
return;
}
 
if (depth == 0) {
fprintf(f,"%stalloc report on '%s' (total %6lu bytes in %3lu blocks)\n",
(max_depth < 0 ? "full " :""), name,
(unsigned long)talloc_total_size(ptr),
(unsigned long)talloc_total_blocks(ptr));
return;
}
 
fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d) %p\n",
depth*4, "",
name,
(unsigned long)talloc_total_size(ptr),
(unsigned long)talloc_total_blocks(ptr),
(int)talloc_reference_count(ptr), ptr);
 
#if 0
fprintf(f, "content: ");
if (talloc_total_size(ptr)) {
int tot = talloc_total_size(ptr);
int i;
 
for (i = 0; i < tot; i++) {
if ((((char *)ptr)[i] > 31) && (((char *)ptr)[i] < 126)) {
fprintf(f, "%c", ((char *)ptr)[i]);
} else {
fprintf(f, "~%02x", ((char *)ptr)[i]);
}
}
}
fprintf(f, "\n");
#endif
}
 
/*
report on memory usage by all children of a pointer, giving a full tree view
*/
void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f)
{
talloc_report_depth_cb(ptr, depth, max_depth, talloc_report_depth_FILE_helper, f);
fflush(f);
}
 
/*
report on memory usage by all children of a pointer, giving a full tree view
*/
void talloc_report_full(const void *ptr, FILE *f)
{
talloc_report_depth_file(ptr, 0, -1, f);
}
 
/*
report on memory usage by all children of a pointer
*/
void talloc_report(const void *ptr, FILE *f)
{
talloc_report_depth_file(ptr, 0, 1, f);
}
 
/*
report on any memory hanging off the null context
*/
static void talloc_report_null(void)
{
if (talloc_total_size(null_context) != 0) {
talloc_report(null_context, stderr);
}
}
 
/*
report on any memory hanging off the null context
*/
static void talloc_report_null_full(void)
{
if (talloc_total_size(null_context) != 0) {
talloc_report_full(null_context, stderr);
}
}
 
/*
enable tracking of the NULL context
*/
void talloc_enable_null_tracking(void)
{
if (null_context == NULL) {
null_context = _talloc_named_const(NULL, 0, "null_context");
}
}
 
/*
disable tracking of the NULL context
*/
void talloc_disable_null_tracking(void)
{
_talloc_free(null_context);
null_context = NULL;
}
 
/*
enable leak reporting on exit
*/
void talloc_enable_leak_report(void)
{
talloc_enable_null_tracking();
atexit(talloc_report_null);
}
 
/*
enable full leak reporting on exit
*/
void talloc_enable_leak_report_full(void)
{
talloc_enable_null_tracking();
atexit(talloc_report_null_full);
}
 
/*
talloc and zero memory.
*/
void *_talloc_zero(const void *ctx, size_t size, const char *name)
{
void *p = _talloc_named_const(ctx, size, name);
 
if (p) {
memset(p, '\0', size);
}
 
return p;
}
 
/*
memdup with a talloc.
*/
void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name)
{
void *newp = _talloc_named_const(t, size, name);
 
if (likely(newp)) {
memcpy(newp, p, size);
}
 
return newp;
}
 
/*
strdup with a talloc
*/
char *talloc_strdup(const void *t, const char *p)
{
char *ret;
if (!p) {
return NULL;
}
ret = (char *)talloc_memdup(t, p, strlen(p) + 1);
if (likely(ret)) {
_talloc_set_name_const(ret, ret);
}
return ret;
}
 
/*
append to a talloced string
*/
char *talloc_append_string(const void *t, char *orig, const char *append)
{
char *ret;
size_t olen = strlen(orig);
size_t alenz;
 
if (!append)
return orig;
 
alenz = strlen(append) + 1;
 
ret = talloc_realloc(t, orig, char, olen + alenz);
if (!ret)
return NULL;
 
/* append the string with the trailing \0 */
memcpy(&ret[olen], append, alenz);
 
_talloc_set_name_const(ret, ret);
 
return ret;
}
 
/*
strndup with a talloc
*/
char *talloc_strndup(const void *t, const char *p, size_t n)
{
size_t len;
char *ret;
 
for (len=0; len<n && p[len]; len++) ;
 
ret = (char *)__talloc(t, len + 1);
if (!ret) { return NULL; }
memcpy(ret, p, len);
ret[len] = 0;
_talloc_set_name_const(ret, ret);
return ret;
}
 
#ifndef HAVE_VA_COPY
#ifdef HAVE___VA_COPY
#define va_copy(dest, src) __va_copy(dest, src)
#else
#define va_copy(dest, src) (dest) = (src)
#endif
#endif
 
char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
{
int len;
char *ret;
va_list ap2;
char c;
/* this call looks strange, but it makes it work on older solaris boxes */
va_copy(ap2, ap);
len = vsnprintf(&c, 1, fmt, ap2);
va_end(ap2);
if (len < 0) {
return NULL;
}
 
ret = (char *)__talloc(t, len+1);
if (ret) {
va_copy(ap2, ap);
vsnprintf(ret, len+1, fmt, ap2);
va_end(ap2);
_talloc_set_name_const(ret, ret);
}
 
return ret;
}
 
 
/*
Perform string formatting, and return a pointer to newly allocated
memory holding the result, inside a memory pool.
*/
char *talloc_asprintf(const void *t, const char *fmt, ...)
{
va_list ap;
char *ret;
 
va_start(ap, fmt);
ret = talloc_vasprintf(t, fmt, ap);
va_end(ap);
return ret;
}
 
 
/**
* Realloc @p s to append the formatted result of @p fmt and @p ap,
* and return @p s, which may have moved. Good for gradually
* accumulating output into a string buffer.
**/
char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
{
struct talloc_chunk *tc;
int len, s_len;
va_list ap2;
char c;
 
if (s == NULL) {
return talloc_vasprintf(NULL, fmt, ap);
}
 
tc = talloc_chunk_from_ptr(s);
 
s_len = tc->size - 1;
 
va_copy(ap2, ap);
len = vsnprintf(&c, 1, fmt, ap2);
va_end(ap2);
 
if (len <= 0) {
/* Either the vsnprintf failed or the format resulted in
* no characters being formatted. In the former case, we
* ought to return NULL, in the latter we ought to return
* the original string. Most current callers of this
* function expect it to never return NULL.
*/
return s;
}
 
s = talloc_realloc(NULL, s, char, s_len + len+1);
if (!s) return NULL;
 
va_copy(ap2, ap);
vsnprintf(s+s_len, len+1, fmt, ap2);
va_end(ap2);
_talloc_set_name_const(s, s);
 
return s;
}
 
/*
Realloc @p s to append the formatted result of @p fmt and return @p
s, which may have moved. Good for gradually accumulating output
into a string buffer.
*/
char *talloc_asprintf_append(char *s, const char *fmt, ...)
{
va_list ap;
 
va_start(ap, fmt);
s = talloc_vasprintf_append(s, fmt, ap);
va_end(ap);
return s;
}
 
/*
alloc an array, checking for integer overflow in the array size
*/
void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name)
{
if (count >= MAX_TALLOC_SIZE/el_size) {
return NULL;
}
return _talloc_named_const(ctx, el_size * count, name);
}
 
/*
alloc an zero array, checking for integer overflow in the array size
*/
void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name)
{
if (count >= MAX_TALLOC_SIZE/el_size) {
return NULL;
}
return _talloc_zero(ctx, el_size * count, name);
}
 
/*
realloc an array, checking for integer overflow in the array size
*/
void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name)
{
if (count >= MAX_TALLOC_SIZE/el_size) {
return NULL;
}
return _talloc_realloc(ctx, ptr, el_size * count, name);
}
 
/*
a function version of talloc_realloc(), so it can be passed as a function pointer
to libraries that want a realloc function (a realloc function encapsulates
all the basic capabilities of an allocation library, which is why this is useful)
*/
void *talloc_realloc_fn(const void *context, void *ptr, size_t size)
{
return _talloc_realloc(context, ptr, size, NULL);
}
 
 
static int talloc_autofree_destructor(void *ptr)
{
autofree_context = NULL;
return 0;
}
 
static void talloc_autofree(void)
{
_talloc_free(autofree_context);
}
 
/*
return a context which will be auto-freed on exit
this is useful for reducing the noise in leak reports
*/
void *talloc_autofree_context(void)
{
if (autofree_context == NULL) {
autofree_context = _talloc_named_const(NULL, 0, "autofree_context");
talloc_set_destructor(autofree_context, talloc_autofree_destructor);
atexit(talloc_autofree);
}
return autofree_context;
}
 
size_t talloc_get_size(const void *context)
{
struct talloc_chunk *tc;
 
if (context == NULL)
return 0;
 
tc = talloc_chunk_from_ptr(context);
 
return tc->size;
}
 
/*
find a parent of this context that has the given name, if any
*/
void *talloc_find_parent_byname(const void *context, const char *name)
{
struct talloc_chunk *tc;
 
if (context == NULL) {
return NULL;
}
 
tc = talloc_chunk_from_ptr(context);
while (tc) {
if (tc->name && strcmp(tc->name, name) == 0) {
return TC_PTR_FROM_CHUNK(tc);
}
while (tc && tc->prev) tc = tc->prev;
if (tc) {
tc = tc->parent;
}
}
return NULL;
}
 
/*
show the parentage of a context
*/
void talloc_show_parents(const void *context, FILE *file)
{
struct talloc_chunk *tc;
 
if (context == NULL) {
fprintf(file, "talloc no parents for NULL\n");
return;
}
 
tc = talloc_chunk_from_ptr(context);
fprintf(file, "talloc parents of '%s'\n", talloc_get_name(context));
while (tc) {
fprintf(file, "\t'%s'\n", talloc_get_name(TC_PTR_FROM_CHUNK(tc)));
while (tc && tc->prev) tc = tc->prev;
if (tc) {
tc = tc->parent;
}
}
fflush(file);
}
 
/*
return 1 if ptr is a parent of context
*/
int talloc_is_parent(const void *context, const void *ptr)
{
struct talloc_chunk *tc;
 
if (context == NULL) {
return 0;
}
 
tc = talloc_chunk_from_ptr(context);
while (tc) {
if (TC_PTR_FROM_CHUNK(tc) == ptr) return 1;
while (tc && tc->prev) tc = tc->prev;
if (tc) {
tc = tc->parent;
}
}
return 0;
}
/contrib/network/netsurf/netsurf/utils/talloc.h
0,0 → 1,173
#ifndef _TALLOC_H_
#define _TALLOC_H_
/*
Unix SMB/CIFS implementation.
Samba temporary memory allocation functions
 
Copyright (C) Andrew Tridgell 2004-2005
Copyright (C) Stefan Metzmacher 2006
** NOTE! The following LGPL license applies to the talloc
** library. This does NOT imply that all of Samba is released
** under the LGPL
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
 
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
 
/* this is only needed for compatibility with the old talloc */
typedef void TALLOC_CTX;
 
/*
this uses a little trick to allow __LINE__ to be stringified
*/
#ifndef __location__
#define __TALLOC_STRING_LINE1__(s) #s
#define __TALLOC_STRING_LINE2__(s) __TALLOC_STRING_LINE1__(s)
#define __TALLOC_STRING_LINE3__ __TALLOC_STRING_LINE2__(__LINE__)
#define __location__ __FILE__ ":" __TALLOC_STRING_LINE3__
#endif
 
#ifndef TALLOC_DEPRECATED
#define TALLOC_DEPRECATED 0
#endif
 
#ifndef PRINTF_ATTRIBUTE
#if (__GNUC__ >= 3)
/** Use gcc attribute to check printf fns. a1 is the 1-based index of
* the parameter containing the format, and a2 the index of the first
* argument. Note that some gcc 2.x versions don't handle this
* properly **/
#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2)))
#else
#define PRINTF_ATTRIBUTE(a1, a2)
#endif
#endif
 
/* try to make talloc_set_destructor() and talloc_steal() type safe,
if we have a recent gcc */
#if (__GNUC__ >= 3)
#define _TALLOC_TYPEOF(ptr) __typeof__(ptr)
#define talloc_set_destructor(ptr, function) \
do { \
int (*_talloc_destructor_fn)(_TALLOC_TYPEOF(ptr)) = (function); \
_talloc_set_destructor((ptr), (int (*)(void *))_talloc_destructor_fn); \
} while(0)
/* this extremely strange macro is to avoid some braindamaged warning
stupidity in gcc 4.1.x */
#define talloc_steal(ctx, ptr) ({ _TALLOC_TYPEOF(ptr) __talloc_steal_ret = (_TALLOC_TYPEOF(ptr))_talloc_steal((ctx),(ptr)); __talloc_steal_ret; })
#else
#define talloc_set_destructor(ptr, function) \
_talloc_set_destructor((ptr), (int (*)(void *))(function))
#define _TALLOC_TYPEOF(ptr) void *
#define talloc_steal(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_steal((ctx),(ptr))
#endif
 
#define talloc_reference(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_reference((ctx),(ptr))
#define talloc_move(ctx, ptr) (_TALLOC_TYPEOF(*(ptr)))_talloc_move((ctx),(void *)(ptr))
 
/* useful macros for creating type checked pointers */
#define talloc(ctx, type) (type *)talloc_named_const(ctx, sizeof(type), #type)
#define talloc_size(ctx, size) talloc_named_const(ctx, size, __location__)
#define talloc_ptrtype(ctx, ptr) (_TALLOC_TYPEOF(ptr))talloc_size(ctx, sizeof(*(ptr)))
 
#define talloc_new(ctx) talloc_named_const(ctx, 0, "talloc_new: " __location__)
 
#define talloc_zero(ctx, type) (type *)_talloc_zero(ctx, sizeof(type), #type)
#define talloc_zero_size(ctx, size) _talloc_zero(ctx, size, __location__)
 
#define talloc_zero_array(ctx, type, count) (type *)_talloc_zero_array(ctx, sizeof(type), count, #type)
#define talloc_array(ctx, type, count) (type *)_talloc_array(ctx, sizeof(type), count, #type)
#define talloc_array_size(ctx, size, count) _talloc_array(ctx, size, count, __location__)
#define talloc_array_ptrtype(ctx, ptr, count) (_TALLOC_TYPEOF(ptr))talloc_array_size(ctx, sizeof(*(ptr)), count)
 
#define talloc_realloc(ctx, p, type, count) (type *)_talloc_realloc_array(ctx, p, sizeof(type), count, #type)
#define talloc_realloc_size(ctx, ptr, size) _talloc_realloc(ctx, ptr, size, __location__)
 
#define talloc_memdup(t, p, size) _talloc_memdup(t, p, size, __location__)
 
#define talloc_set_type(ptr, type) talloc_set_name_const(ptr, #type)
#define talloc_get_type(ptr, type) (type *)talloc_check_name(ptr, #type)
 
#define talloc_find_parent_bytype(ptr, type) (type *)talloc_find_parent_byname(ptr, #type)
 
#if TALLOC_DEPRECATED
#define talloc_zero_p(ctx, type) talloc_zero(ctx, type)
#define talloc_p(ctx, type) talloc(ctx, type)
#define talloc_array_p(ctx, type, count) talloc_array(ctx, type, count)
#define talloc_realloc_p(ctx, p, type, count) talloc_realloc(ctx, p, type, count)
#define talloc_destroy(ctx) talloc_free(ctx)
#endif
 
/* The following definitions come from talloc.c */
void *_talloc(const void *context, size_t size);
void _talloc_set_destructor(const void *ptr, int (*destructor)(void *));
int talloc_increase_ref_count(const void *ptr);
size_t talloc_reference_count(const void *ptr);
void *_talloc_reference(const void *context, const void *ptr);
int talloc_unlink(const void *context, void *ptr);
const char *talloc_set_name(const void *ptr, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
void talloc_set_name_const(const void *ptr, const char *name);
void *talloc_named(const void *context, size_t size,
const char *fmt, ...) PRINTF_ATTRIBUTE(3,4);
void *talloc_named_const(const void *context, size_t size, const char *name);
const char *talloc_get_name(const void *ptr);
void *talloc_check_name(const void *ptr, const char *name);
void *talloc_parent(const void *ptr);
const char *talloc_parent_name(const void *ptr);
void *talloc_init(const char *fmt, ...) PRINTF_ATTRIBUTE(1,2);
int talloc_free(void *ptr);
void talloc_free_children(void *ptr);
void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name);
void *_talloc_steal(const void *new_ctx, const void *ptr);
void *_talloc_move(const void *new_ctx, const void *pptr);
size_t talloc_total_size(const void *ptr);
size_t talloc_total_blocks(const void *ptr);
void talloc_report_depth_cb(const void *ptr, int depth, int max_depth,
void (*callback)(const void *ptr,
int depth, int max_depth,
int is_ref,
void *private_data),
void *private_data);
void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f);
void talloc_report_full(const void *ptr, FILE *f);
void talloc_report(const void *ptr, FILE *f);
void talloc_enable_null_tracking(void);
void talloc_disable_null_tracking(void);
void talloc_enable_leak_report(void);
void talloc_enable_leak_report_full(void);
void *_talloc_zero(const void *ctx, size_t size, const char *name);
void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name);
char *talloc_strdup(const void *t, const char *p);
char *talloc_strndup(const void *t, const char *p, size_t n);
char *talloc_append_string(const void *t, char *orig, const char *append);
char *talloc_vasprintf(const void *t, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
char *talloc_asprintf(const void *t, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
char *talloc_asprintf_append(char *s, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name);
void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name);
void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name);
void *talloc_realloc_fn(const void *context, void *ptr, size_t size);
void *talloc_autofree_context(void);
size_t talloc_get_size(const void *ctx);
void *talloc_find_parent_byname(const void *ctx, const char *name);
void talloc_show_parents(const void *context, FILE *file);
int talloc_is_parent(const void *context, const void *ptr);
 
#endif
/contrib/network/netsurf/netsurf/utils/testament.h
0,0 → 1,41
/* utils/testament.h
*
* Revision testament.
*
* *WARNING* this file is automatically generated by git-testament.pl
*
* Copyright 2012 NetSurf Browser Project
*/
 
#ifndef NETSURF_REVISION_TESTAMENT
#define NETSURF_REVISION_TESTAMENT "178a6caf6b7896579100426d2e86272e"
 
/* Revision testament checksum:
* MD5:178a6caf6b7896579100426d2e86272e
*/
 
/* Revision testament: */
#define USERNAME "sourcerer"
#define GECOS "sourcerer"
#define WT_ROOT "/home/sourcerer/kos_src/netsurf/unix/netsurf/"
#define WT_HOSTNAME "debian"
#define WT_COMPILEDATE "04.02.2013"
#define WT_BRANCHPATH "master"
#define WT_BRANCHISMASTER 1
#define WT_REVID "43fe4490d3152ccecd7fd8065c09faaa893fb09e"
#define WT_MODIFIED 11
#define WT_MODIFICATIONS {\
{ "buildsystem/", "??" }, \
{ "libcss/", "??" }, \
{ "libdom/", "??" }, \
{ "libhubbub/", "??" }, \
{ "libmng-1.0.10/", "??" }, \
{ "libnsbmp/", "??" }, \
{ "libnsfb/", "??" }, \
{ "libnsgif/", "??" }, \
{ "libparserutils/", "??" }, \
{ "libwapcaplet/", "??" }, \
{ "nsgenbind", "??" } \
}
 
#endif
/contrib/network/netsurf/netsurf/utils/types.h
0,0 → 1,62
/*
* Copyright 2011 Michael Drake <tlsa@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
/** \file
* Core types.
*/
 
#ifndef _NETSURF_UTILS_TYPES_H_
#define _NETSURF_UTILS_TYPES_H_
 
struct plotter_table;
struct hlcache_handle;
 
/* Rectangle coordinates */
struct rect {
int x0, y0; /* Top left */
int x1, y1; /* Bottom right */
};
 
 
/* Redraw context */
struct redraw_context {
/** Redraw to show interactive features, such as active selections
* etc. Should be off for printing. */
bool interactive;
 
/** Render background images. May want it off for printing. */
bool background_images;
 
/** Current plotters, must be assigned before use. */
const struct plotter_table *plot;
};
 
 
/* Content located at a specific spatial location */
struct contextual_content {
const char *link_url;
struct hlcache_handle *object;
struct hlcache_handle *main;
enum {
CTX_FORM_NONE,
CTX_FORM_TEXT,
CTX_FORM_FILE
} form_features;
};
 
#endif
/contrib/network/netsurf/netsurf/utils/url.c
0,0 → 1,942
/*
* Copyright 2006 Richard Wilson <info@tinct.net>
* Copyright 2005 James Bursa <bursa@users.sourceforge.net>
* Copyright 2005 John M Bell <jmb202@ecs.soton.ac.uk>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
/** \file
* URL parsing and joining (implementation).
*/
 
#include <sys/types.h>
#include <assert.h>
#include <ctype.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
 
#include "curl/curl.h"
#include "utils/config.h"
#include "utils/log.h"
#include "utils/url.h"
#include "utils/utils.h"
 
struct url_components_internal {
char *buffer; /* buffer used for all the following data */
char *scheme;
char *authority;
char *path;
char *query;
char *fragment;
};
 
 
regex_t url_re, url_up_re;
 
/**
* Initialise URL routines.
*
* Compiles regular expressions required by the url_ functions.
*/
 
void url_init(void)
{
/* regex from RFC 2396 */
regcomp_wrapper(&url_re, "^[[:space:]]*"
#define URL_RE_SCHEME 2
"(([a-zA-Z][-a-zA-Z0-9+.]*):)?"
#define URL_RE_AUTHORITY 4
"(//([^/?#[:space:]]*))?"
#define URL_RE_PATH 5
"([^?#[:space:]]*)"
#define URL_RE_QUERY 7
"(\\?([^#[:space:]]*))?"
#define URL_RE_FRAGMENT 9
"(#([^[:space:]]*))?"
"[[:space:]]*$", REG_EXTENDED);
regcomp_wrapper(&url_up_re,
"/([^/]?|[.][^./]|[^./][.]|[^./][^./]|[^/][^/][^/]+)"
"/[.][.](/|$)",
REG_EXTENDED);
}
 
 
/**
* Check whether a host string is an IP address. It should support and
* detect IPv4 addresses (all of dotted-quad or subsets, decimal or
* hexadecimal notations) and IPv6 addresses (including those containing
* embedded IPv4 addresses.)
*
* \param host a hostname terminated by '\0'
* \return true if the hostname is an IP address, false otherwise
*/
bool url_host_is_ip_address(const char *host)
{
struct in_addr ipv4;
size_t host_len = strlen(host);
const char *sane_host;
const char *slash;
#ifndef NO_IPV6
struct in6_addr ipv6;
char ipv6_addr[64];
#endif
/* FIXME TODO: Some parts of urldb.c (and perhaps other parts of
* NetSurf) make confusions between hosts and "prefixes", we can
* sometimes be erroneously passed more than just a host. Sometimes
* we may be passed trailing slashes, or even whole path segments.
* A specific criminal in this class is urldb_iterate_partial, which
* takes a prefix to search for, but passes that prefix to functions
* that expect only hosts.
*
* For the time being, we will accept such calls; we check if there
* is a / in the host parameter, and if there is, we take a copy and
* replace the / with a \0. This is not a permanent solution; we
* should search through NetSurf and find all the callers that are
* in error and fix them. When doing this task, it might be wise
* to replace the hideousness below with code that doesn't have to do
* this, and add assert(strchr(host, '/') == NULL); somewhere.
* -- rjek - 2010-11-04
*/
 
slash = strchr(host, '/');
if (slash == NULL) {
sane_host = host;
} else {
char *c = strdup(host);
c[slash - host] = '\0';
sane_host = c;
host_len = slash - host - 1;
LOG(("WARNING: called with non-host '%s'", host));
}
 
if (strspn(sane_host, "0123456789abcdefABCDEF[].:") < host_len)
goto out_false;
 
if (inet_aton(sane_host, &ipv4) != 0) {
/* This can only be a sane IPv4 address if it contains 3 dots.
* Helpfully, inet_aton is happy to treat "a", "a.b", "a.b.c",
* and "a.b.c.d" as valid IPv4 address strings where we only
* support the full, dotted-quad, form.
*/
int num_dots = 0;
size_t index;
 
for (index = 0; index < host_len; index++) {
if (sane_host[index] == '.')
num_dots++;
}
 
if (num_dots == 3)
goto out_true;
else
goto out_false;
}
 
#ifndef NO_IPV6
if (sane_host[0] != '[' || sane_host[host_len] != ']')
goto out_false;
 
strncpy(ipv6_addr, sane_host + 1, sizeof(ipv6_addr));
ipv6_addr[sizeof(ipv6_addr) - 1] = '\0';
 
if (inet_pton(AF_INET6, ipv6_addr, &ipv6) == 1)
goto out_true;
#endif
 
out_false:
if (slash != NULL) free((void *)sane_host);
return false;
 
out_true:
if (slash != NULL) free((void *)sane_host);
return true;
}
 
/**
* Split a URL into separate components
*
* URLs passed to this function are assumed to be valid and no error checking
* or recovery is attempted.
*
* See RFC 3986 for reference.
*
* \param url a valid absolute or relative URL
* \param result pointer to buffer to hold components
* \return URL_FUNC_OK on success
*/
 
static url_func_result url_get_components(const char *url,
struct url_components *result)
{
int storage_length;
char *storage_end;
const char *scheme;
const char *authority;
const char *path;
const char *query;
const char *fragment;
struct url_components_internal *internal;
 
assert(url);
 
/* clear our return value */
internal = (struct url_components_internal *)result;
memset(result, 0x00, sizeof(struct url_components));
 
/* get enough storage space for a URL with termination at each node */
storage_length = strlen(url) + 8;
internal->buffer = malloc(storage_length);
if (!internal->buffer)
return URL_FUNC_NOMEM;
storage_end = internal->buffer;
 
/* look for a valid scheme */
scheme = url;
if (isalpha(*scheme)) {
for (scheme = url + 1;
((*scheme != ':') && (*scheme != '\0'));
scheme++) {
if (!isalnum(*scheme) && (*scheme != '+') &&
(*scheme != '-') && (*scheme != '.'))
break;
}
 
if (*scheme == ':') {
memcpy(storage_end, url, scheme - url);
storage_end[scheme - url] = '\0';
result->scheme = storage_end;
storage_end += scheme - url + 1;
scheme++;
} else {
scheme = url;
}
}
 
 
/* look for an authority */
authority = scheme;
if ((authority[0] == '/') && (authority[1] == '/')) {
authority = strpbrk(scheme + 2, "/?#");
if (!authority)
authority = scheme + strlen(scheme);
memcpy(storage_end, scheme + 2, authority - scheme - 2);
storage_end[authority - scheme - 2] = '\0';
result->authority = storage_end;
storage_end += authority - scheme - 1;
}
 
 
/* look for a path */
path = authority;
if ((*path != '?') && (*path != '#') && (*path != '\0')) {
path = strpbrk(path, "?#");
if (!path)
path = authority + strlen(authority);
memcpy(storage_end, authority, path - authority);
storage_end[path - authority] = '\0';
result->path = storage_end;
storage_end += path - authority + 1;
}
 
 
/* look for a query */
query = path;
if (*query == '?') {
query = strchr(query, '#');
if (!query)
query = path + strlen(path);
memcpy(storage_end, path + 1, query - path - 1);
storage_end[query - path - 1] = '\0';
result->query = storage_end;
storage_end += query - path;
}
 
 
/* look for a fragment */
fragment = query;
if (*fragment == '#') {
fragment = query + strlen(query);
 
/* make a copy of the result for the caller */
memcpy(storage_end, query + 1, fragment - query - 1);
storage_end[fragment - query - 1] = '\0';
result->fragment = storage_end;
storage_end += fragment - query;
}
 
assert((result->buffer + storage_length) >= storage_end);
return URL_FUNC_OK;
}
 
 
/**
* Reform a URL from separate components
*
* See RFC 3986 for reference.
*
* \param components the components to reform into a URL
* \return a new URL allocated on the heap, or NULL on failure
*/
 
static char *url_reform_components(const struct url_components *components)
{
int scheme_len = 0, authority_len = 0, path_len = 0, query_len = 0,
fragment_len = 0;
char *result, *url;
 
/* 5.3 */
if (components->scheme)
scheme_len = strlen(components->scheme) + 1;
if (components->authority)
authority_len = strlen(components->authority) + 2;
if (components->path)
path_len = strlen(components->path);
if (components->query)
query_len = strlen(components->query) + 1;
if (components->fragment)
fragment_len = strlen(components->fragment) + 1;
 
/* claim memory */
url = result = malloc(scheme_len + authority_len + path_len +
query_len + fragment_len + 1);
if (!url) {
LOG(("malloc failed"));
return NULL;
}
 
/* rebuild URL */
if (components->scheme) {
sprintf(url, "%s:", components->scheme);
url += scheme_len;
}
if (components->authority) {
sprintf(url, "//%s", components->authority);
url += authority_len;
}
if (components->path) {
sprintf(url, "%s", components->path);
url += path_len;
}
if (components->query) {
sprintf(url, "?%s", components->query);
url += query_len;
}
if (components->fragment)
sprintf(url, "#%s", components->fragment);
return result;
}
 
 
/**
* Release some url components from memory
*
* \param result pointer to buffer containing components
*/
static void url_destroy_components(const struct url_components *components)
{
const struct url_components_internal *internal;
 
assert(components);
 
internal = (const struct url_components_internal *)components;
if (internal->buffer)
free(internal->buffer);
}
 
 
/**
* Resolve a relative URL to absolute form.
*
* \param rel relative URL
* \param base base URL, must be absolute and cleaned as by nsurl_create()
* \param result pointer to pointer to buffer to hold absolute url
* \return URL_FUNC_OK on success
*/
 
url_func_result url_join(const char *rel, const char *base, char **result)
{
url_func_result status = URL_FUNC_NOMEM;
struct url_components_internal base_components = {0,0,0,0,0,0};
struct url_components_internal *base_ptr = &base_components;
struct url_components_internal rel_components = {0,0,0,0,0,0};
struct url_components_internal *rel_ptr = &rel_components;
struct url_components_internal merged_components = {0,0,0,0,0,0};
struct url_components_internal *merged_ptr = &merged_components;
char *merge_path = NULL, *split_point;
char *input, *output, *start = NULL;
int len, buf_len;
 
(*result) = 0;
 
assert(base);
assert(rel);
 
 
/* break down the relative URL (not cached, corruptable) */
status = url_get_components(rel, (struct url_components *) rel_ptr);
if (status != URL_FUNC_OK) {
LOG(("relative url '%s' failed to get components", rel));
return URL_FUNC_FAILED;
}
 
/* [1] relative URL is absolute, use it entirely */
merged_components = rel_components;
if (rel_components.scheme)
goto url_join_reform_url;
 
/* break down the base URL (possibly cached, not corruptable) */
status = url_get_components(base, (struct url_components *) base_ptr);
if (status != URL_FUNC_OK) {
url_destroy_components((struct url_components *) rel_ptr);
LOG(("base url '%s' failed to get components", base));
return URL_FUNC_FAILED;
}
 
/* [2] relative authority takes presidence */
merged_components.scheme = base_components.scheme;
if (rel_components.authority)
goto url_join_reform_url;
 
/* [3] handle empty paths */
merged_components.authority = base_components.authority;
if (!rel_components.path) {
merged_components.path = base_components.path;
if (!rel_components.query)
merged_components.query = base_components.query;
goto url_join_reform_url;
}
 
/* [4] handle valid paths */
if (rel_components.path[0] == '/')
merged_components.path = rel_components.path;
else {
/* 5.2.3 */
if ((base_components.authority) && (!base_components.path)) {
merge_path = malloc(strlen(rel_components.path) + 2);
if (!merge_path) {
LOG(("malloc failed"));
goto url_join_no_mem;
}
sprintf(merge_path, "/%s", rel_components.path);
merged_components.path = merge_path;
} else {
split_point = base_components.path ?
strrchr(base_components.path, '/') :
NULL;
if (!split_point) {
merged_components.path = rel_components.path;
} else {
len = ++split_point - base_components.path;
buf_len = len + 1 + strlen(rel_components.path);
merge_path = malloc(buf_len);
if (!merge_path) {
LOG(("malloc failed"));
goto url_join_no_mem;
}
memcpy(merge_path, base_components.path, len);
memcpy(merge_path + len, rel_components.path,
strlen(rel_components.path));
merge_path[buf_len - 1] = '\0';
merged_components.path = merge_path;
}
}
}
 
url_join_reform_url:
/* 5.2.4 */
input = merged_components.path;
if ((input) && (strchr(input, '.'))) {
/* [1] remove all dot references */
output = start = malloc(strlen(input) + 1);
if (!output) {
LOG(("malloc failed"));
goto url_join_no_mem;
}
merged_components.path = output;
*output = '\0';
 
while (*input != '\0') {
/* [2A] */
if (input[0] == '.') {
if (input[1] == '/') {
input = input + 2;
continue;
} else if ((input[1] == '.') &&
(input[2] == '/')) {
input = input + 3;
continue;
}
}
 
/* [2B] */
if ((input[0] == '/') && (input[1] == '.')) {
if (input[2] == '/') {
input = input + 2;
continue;
} else if (input[2] == '\0') {
input = input + 1;
*input = '/';
continue;
}
 
/* [2C] */
if ((input[2] == '.') && ((input[3] == '/') ||
(input[3] == '\0'))) {
if (input[3] == '/') {
input = input + 3;
} else {
input = input + 2;
*input = '/';
}
 
if ((output > start) &&
(output[-1] == '/'))
*--output = '\0';
split_point = strrchr(start, '/');
if (!split_point)
output = start;
else
output = split_point;
*output = '\0';
continue;
}
}
 
 
/* [2D] */
if (input[0] == '.') {
if (input[1] == '\0') {
input = input + 1;
continue;
} else if ((input[1] == '.') &&
(input[2] == '\0')) {
input = input + 2;
continue;
}
}
 
/* [2E] */
if (*input == '/')
*output++ = *input++;
while ((*input != '/') && (*input != '\0'))
*output++ = *input++;
*output = '\0';
}
/* [3] */
merged_components.path = start;
}
 
/* 5.3 */
*result = url_reform_components((struct url_components *) merged_ptr);
if (!(*result))
goto url_join_no_mem;
 
/* return success */
status = URL_FUNC_OK;
 
url_join_no_mem:
free(start);
free(merge_path);
url_destroy_components((struct url_components *) base_ptr);
url_destroy_components((struct url_components *) rel_ptr);
return status;
}
 
 
/**
* Return the host name from an URL.
*
* \param url an absolute URL
* \param result pointer to pointer to buffer to hold host name
* \return URL_FUNC_OK on success
*/
 
url_func_result url_host(const char *url, char **result)
{
url_func_result status;
struct url_components components;
const char *host_start, *host_end;
 
assert(url);
 
status = url_get_components(url, &components);
if (status == URL_FUNC_OK) {
if (!components.authority) {
url_destroy_components(&components);
return URL_FUNC_FAILED;
}
host_start = strchr(components.authority, '@');
host_start = host_start ? host_start + 1 : components.authority;
 
/* skip over an IPv6 address if there is one */
if (host_start[0] == '[') {
host_end = strchr(host_start, ']') + 1;
} else {
host_end = strchr(host_start, ':');
}
 
if (!host_end)
host_end = components.authority +
strlen(components.authority);
 
*result = malloc(host_end - host_start + 1);
if (!(*result)) {
url_destroy_components(&components);
return URL_FUNC_FAILED;
}
memcpy((*result), host_start, host_end - host_start);
(*result)[host_end - host_start] = '\0';
}
url_destroy_components(&components);
return status;
}
 
 
/**
* Return the scheme name from an URL.
*
* See RFC 3986, 3.1 for reference.
*
* \param url an absolute URL
* \param result pointer to pointer to buffer to hold scheme name
* \return URL_FUNC_OK on success
*/
 
url_func_result url_scheme(const char *url, char **result)
{
url_func_result status;
struct url_components components;
 
assert(url);
 
status = url_get_components(url, &components);
if (status == URL_FUNC_OK) {
if (!components.scheme) {
status = URL_FUNC_FAILED;
} else {
*result = strdup(components.scheme);
if (!(*result))
status = URL_FUNC_NOMEM;
}
}
url_destroy_components(&components);
return status;
}
 
 
/**
* Extract path segment from an URL
*
* \param url an absolute URL
* \param result pointer to pointer to buffer to hold result
* \return URL_FUNC_OK on success
*/
 
url_func_result url_path(const char *url, char **result)
{
url_func_result status;
struct url_components components;
 
assert(url);
 
status = url_get_components(url, &components);
if (status == URL_FUNC_OK) {
if (!components.path) {
status = URL_FUNC_FAILED;
} else {
*result = strdup(components.path);
if (!(*result))
status = URL_FUNC_NOMEM;
}
}
url_destroy_components(&components);
return status;
}
 
/**
* Attempt to find a nice filename for a URL.
*
* \param url an absolute URL
* \param result pointer to pointer to buffer to hold filename
* \param remove_extensions remove any extensions from the filename
* \return URL_FUNC_OK on success
*/
 
url_func_result url_nice(const char *url, char **result,
bool remove_extensions)
{
int m;
regmatch_t match[10];
regoff_t start, end;
size_t i;
char *dot;
 
*result = 0;
 
m = regexec(&url_re, url, 10, match, 0);
if (m) {
LOG(("url '%s' failed to match regex", url));
return URL_FUNC_FAILED;
}
 
/* extract the last component of the path, if possible */
if (match[URL_RE_PATH].rm_so == -1 || match[URL_RE_PATH].rm_so ==
match[URL_RE_PATH].rm_eo)
goto no_path; /* no path, or empty */
for (end = match[URL_RE_PATH].rm_eo - 1;
end != match[URL_RE_PATH].rm_so && url[end] == '/';
end--)
;
if (end == match[URL_RE_PATH].rm_so)
goto no_path; /* path is a string of '/' */
end++;
for (start = end - 1;
start != match[URL_RE_PATH].rm_so && url[start] != '/';
start--)
;
if (url[start] == '/')
start++;
 
if (!strncasecmp(url + start, "index.", 6) ||
!strncasecmp(url + start, "default.", 8)) {
/* try again */
if (start == match[URL_RE_PATH].rm_so)
goto no_path;
for (end = start - 1;
end != match[URL_RE_PATH].rm_so &&
url[end] == '/';
end--)
;
if (end == match[URL_RE_PATH].rm_so)
goto no_path;
end++;
for (start = end - 1;
start != match[URL_RE_PATH].rm_so &&
url[start] != '/';
start--)
;
if (url[start] == '/')
start++;
}
 
*result = malloc(end - start + 1);
if (!*result) {
LOG(("malloc failed"));
return URL_FUNC_NOMEM;
}
strncpy(*result, url + start, end - start);
(*result)[end - start] = 0;
 
if (remove_extensions) {
dot = strchr(*result, '.');
if (dot && dot != *result)
*dot = 0;
}
 
return URL_FUNC_OK;
 
no_path:
 
/* otherwise, use the host name, with '.' replaced by '_' */
if (match[URL_RE_AUTHORITY].rm_so != -1 &&
match[URL_RE_AUTHORITY].rm_so !=
match[URL_RE_AUTHORITY].rm_eo) {
*result = malloc(match[URL_RE_AUTHORITY].rm_eo -
match[URL_RE_AUTHORITY].rm_so + 1);
if (!*result) {
LOG(("malloc failed"));
return URL_FUNC_NOMEM;
}
strncpy(*result, url + match[URL_RE_AUTHORITY].rm_so,
match[URL_RE_AUTHORITY].rm_eo -
match[URL_RE_AUTHORITY].rm_so);
(*result)[match[URL_RE_AUTHORITY].rm_eo -
match[URL_RE_AUTHORITY].rm_so] = 0;
 
for (i = 0; (*result)[i]; i++)
if ((*result)[i] == '.')
(*result)[i] = '_';
 
return URL_FUNC_OK;
}
 
return URL_FUNC_FAILED;
}
 
/**
* Convert an escaped string to plain.
* \param result unescaped string owned by caller must be freed with free()
* \return URL_FUNC_OK on success
*/
url_func_result url_unescape(const char *str, char **result)
{
char *curlstr;
char *retstr;
 
curlstr = curl_unescape(str, 0);
if (curlstr == NULL) {
return URL_FUNC_NOMEM;
}
 
retstr = strdup(curlstr);
curl_free(curlstr);
 
if (retstr == NULL) {
return URL_FUNC_NOMEM;
}
 
*result = retstr;
return URL_FUNC_OK;
}
 
/**
* Escape a string suitable for inclusion in an URL.
*
* \param unescaped the unescaped string
* \param toskip number of bytes to skip in unescaped string
* \param sptoplus true iff spaces should be converted to +
* \param escexceptions NULL or a string of characters excluded to be escaped
* \param result pointer to pointer to buffer to hold escaped string
* \return URL_FUNC_OK on success
*/
 
url_func_result url_escape(const char *unescaped, size_t toskip,
bool sptoplus, const char *escexceptions, char **result)
{
size_t len;
char *escaped, *d, *tmpres;
const char *c;
 
if (!unescaped || !result)
return URL_FUNC_FAILED;
 
*result = NULL;
 
len = strlen(unescaped);
if (len < toskip)
return URL_FUNC_FAILED;
len -= toskip;
 
escaped = malloc(len * 3 + 1);
if (!escaped)
return URL_FUNC_NOMEM;
 
for (c = unescaped + toskip, d = escaped; *c; c++) {
/* Check if we should escape this byte.
* '~' is unreserved and should not be percent encoded, if
* you believe the spec; however, leaving it unescaped
* breaks a bunch of websites, so we escape it anyway. */
if (!isascii(*c)
|| (strchr(":/?#[]@" /* gen-delims */
"!$&'()*+,;=" /* sub-delims */
"<>%\"{}|\\^`~" /* others */, *c)
&& (!escexceptions || !strchr(escexceptions, *c)))
|| *c <= 0x20 || *c == 0x7f) {
if (*c == 0x20 && sptoplus) {
*d++ = '+';
} else {
*d++ = '%';
*d++ = "0123456789ABCDEF"[((*c >> 4) & 0xf)];
*d++ = "0123456789ABCDEF"[(*c & 0xf)];
}
} else {
/* unreserved characters: [a-zA-Z0-9-._] */
*d++ = *c;
}
}
*d++ = '\0';
 
tmpres = malloc(d - escaped + toskip);
if (!tmpres) {
free(escaped);
return URL_FUNC_NOMEM;
}
 
memcpy(tmpres, unescaped, toskip);
memcpy(tmpres + toskip, escaped, d - escaped);
*result = tmpres;
 
free(escaped);
 
return URL_FUNC_OK;
}
 
 
#ifdef TEST
 
int main(int argc, char *argv[])
{
int i;
url_func_result res;
char *s;
url_init();
for (i = 1; i != argc; i++) {
/* printf("==> '%s'\n", argv[i]);
res = url_normalize(argv[i], &s);
if (res == URL_FUNC_OK) {
printf("<== '%s'\n", s);
free(s);
}*/
/* printf("==> '%s'\n", argv[i]);
res = url_host(argv[i], &s);
if (res == URL_FUNC_OK) {
printf("<== '%s'\n", s);
free(s);
}*/
if (1 != i) {
res = url_join(argv[i], argv[1], &s);
if (res == URL_FUNC_OK) {
printf("'%s' + '%s' \t= '%s'\n", argv[1],
argv[i], s);
free(s);
}
}
/* printf("'%s' => ", argv[i]);
res = url_nice(argv[i], &s, true);
if (res == URL_FUNC_OK) {
printf("'%s', ", s);
free(s);
} else {
printf("failed %u, ", res);
}
res = url_nice(argv[i], &s, false);
if (res == URL_FUNC_OK) {
printf("'%s', ", s);
free(s);
} else {
printf("failed %u, ", res);
}
printf("\n");*/
}
return 0;
}
 
void regcomp_wrapper(regex_t *preg, const char *regex, int cflags)
{
char errbuf[200];
int r;
r = regcomp(preg, regex, cflags);
if (r) {
regerror(r, preg, errbuf, sizeof errbuf);
fprintf(stderr, "Failed to compile regexp '%s'\n", regex);
fprintf(stderr, "error: %s\n", errbuf);
exit(1);
}
}
 
#endif
/contrib/network/netsurf/netsurf/utils/url.h
0,0 → 1,64
/*
* Copyright 2005 James Bursa <bursa@users.sourceforge.net>
* Copyright 2005 John M Bell <jmb202@ecs.soton.ac.uk>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
/**
* \file utils/url.h
* \brief URL parsing and joining (interface).
*/
 
#ifndef _NETSURF_UTILS_URL_H_
#define _NETSURF_UTILS_URL_H_
 
/** File url prefix */
#define FILE_SCHEME_PREFIX "file:///"
/** File url prefix length */
#define FILE_SCHEME_PREFIX_LEN 8
 
/** URL utility function return codes */
typedef enum {
URL_FUNC_OK, /**< No error */
URL_FUNC_NOMEM, /**< Insufficient memory */
URL_FUNC_FAILED /**< Non fatal error (eg failed to match regex) */
} url_func_result;
 
struct url_components {
const char *buffer;
const char *scheme;
const char *authority;
const char *path;
const char *query;
const char *fragment;
};
 
void url_init(void);
bool url_host_is_ip_address(const char *host);
url_func_result url_join(const char *rel, const char *base, char **result);
url_func_result url_host(const char *url, char **result);
url_func_result url_scheme(const char *url, char **result);
url_func_result url_nice(const char *url, char **result,
bool remove_extensions);
url_func_result url_escape(const char *unescaped, size_t toskip,
bool sptoplus, const char *escexceptions, char **result);
url_func_result url_unescape(const char *str, char **result);
url_func_result url_path(const char *url, char **result);
 
char *path_to_url(const char *path);
char *url_to_path(const char *url);
 
#endif
/contrib/network/netsurf/netsurf/utils/useragent.c
0,0 → 1,79
/*
* Copyright 2007 Daniel Silverstone <dsilvers@digital-scurf.org>
* Copyright 2007 Rob Kendrick <rjek@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
#include <stdio.h>
#include <stdlib.h>
 
#include "utils/config.h"
#include "utils/utsname.h"
#include "desktop/netsurf.h"
#include "utils/log.h"
#include "utils/useragent.h"
 
static const char *core_user_agent_string = NULL;
 
#ifndef NETSURF_UA_FORMAT_STRING
#define NETSURF_UA_FORMAT_STRING "NetSurf/%d.%d (%s)"
#endif
 
/**
* Prepare core_user_agent_string with a string suitable for use as a
* user agent in HTTP requests.
*/
static void
user_agent_build_string(void)
{
struct utsname un;
const char *sysname = "Unknown";
char *ua_string;
int len;
 
if (uname(&un) >= 0) {
sysname = un.sysname;
}
 
len = snprintf(NULL, 0, NETSURF_UA_FORMAT_STRING,
netsurf_version_major,
netsurf_version_minor,
sysname);
ua_string = malloc(len + 1);
if (!ua_string) {
/** \todo this needs handling better */
return;
}
snprintf(ua_string, len + 1,
NETSURF_UA_FORMAT_STRING,
netsurf_version_major,
netsurf_version_minor,
sysname);
 
core_user_agent_string = ua_string;
 
LOG(("Built user agent \"%s\"", core_user_agent_string));
}
 
/* This is a function so that later we can override it trivially */
const char *
user_agent_string(void)
{
if (core_user_agent_string == NULL)
user_agent_build_string();
return core_user_agent_string;
}
 
/contrib/network/netsurf/netsurf/utils/useragent.h
0,0 → 1,30
/*
* Copyright 2007 Daniel Silverstone <dsilvers@digital-scurf.org>
* Copyright 2007 Rob Kendrick <rjek@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
#ifndef _NETSURF_UTILS_USERAGENT_H_
#define _NETSURF_UTILS_USERAGENT_H_
 
/** Retrieve the core user agent for this release.
*
* The string returned can be relied upon to exist for the duration of
* the execution of the program. There is no need to copy it.
*/
const char * user_agent_string(void);
 
#endif
/contrib/network/netsurf/netsurf/utils/utf8.c
0,0 → 1,484
/*
* Copyright 2005 John M Bell <jmb202@ecs.soton.ac.uk>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
/** \file
* UTF-8 manipulation functions (implementation).
*/
 
#include <assert.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <iconv.h>
 
typedef signed char int8_t;
typedef signed short int16_t;
typedef signed int int32_t;
 
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
 
#include <parserutils/charset/utf8.h>
 
#include "utils/config.h"
#include "utils/log.h"
#include "utils/utf8.h"
 
static utf8_convert_ret utf8_convert(const char *string, size_t len,
const char *from, const char *to, char **result);
 
/**
* Convert a UTF-8 multibyte sequence into a single UCS4 character
*
* Encoding of UCS values outside the UTF-16 plane has been removed from
* RFC3629. This function conforms to RFC2279, however.
*
* \param s_in The sequence to process
* \param l Length of sequence
* \return UCS4 character
*/
uint32_t utf8_to_ucs4(const char *s_in, size_t l)
{
uint32_t ucs4;
size_t len;
parserutils_error perror;
 
perror = parserutils_charset_utf8_to_ucs4((const uint8_t *) s_in, l,
&ucs4, &len);
if (perror != PARSERUTILS_OK)
ucs4 = 0xfffd;
 
return ucs4;
}
 
/**
* Convert a single UCS4 character into a UTF-8 multibyte sequence
*
* Encoding of UCS values outside the UTF-16 plane has been removed from
* RFC3629. This function conforms to RFC2279, however.
*
* \param c The character to process (0 <= c <= 0x7FFFFFFF)
* \param s Pointer to 6 byte long output buffer
* \return Length of multibyte sequence
*/
size_t utf8_from_ucs4(uint32_t c, char *s)
{
uint8_t *in = (uint8_t *) s;
size_t len = 6;
parserutils_error perror;
 
perror = parserutils_charset_utf8_from_ucs4(c, &in, &len);
if (perror != PARSERUTILS_OK) {
s[0] = 0xef;
s[1] = 0xbf;
s[2] = 0xbd;
return 3;
}
 
return 6 - len;
}
 
/**
* Calculate the length (in characters) of a NULL-terminated UTF-8 string
*
* \param s The string
* \return Length of string
*/
size_t utf8_length(const char *s)
{
return utf8_bounded_length(s, strlen(s));
}
 
/**
* Calculated the length (in characters) of a bounded UTF-8 string
*
* \param s The string
* \param l Maximum length of input (in bytes)
* \return Length of string, in characters
*/
size_t utf8_bounded_length(const char *s, size_t l)
{
size_t len;
parserutils_error perror;
 
perror = parserutils_charset_utf8_length((const uint8_t *) s, l, &len);
if (perror != PARSERUTILS_OK)
return 0;
 
return len;
}
 
/**
* Calculate the length (in bytes) of a UTF-8 character
*
* \param s Pointer to start of character
* \return Length of character, in bytes
*/
size_t utf8_char_byte_length(const char *s)
{
size_t len;
parserutils_error perror;
 
perror = parserutils_charset_utf8_char_byte_length((const uint8_t *) s,
&len);
assert(perror == PARSERUTILS_OK);
 
return len;
}
 
/**
* Find previous legal UTF-8 char in string
*
* \param s The string
* \param o Offset in the string to start at
* \return Offset of first byte of previous legal character
*/
size_t utf8_prev(const char *s, size_t o)
{
uint32_t prev;
parserutils_error perror;
 
perror = parserutils_charset_utf8_prev((const uint8_t *) s, o, &prev);
assert(perror == PARSERUTILS_OK);
 
return prev;
}
 
/**
* Find next legal UTF-8 char in string
*
* \param s The string
* \param l Maximum offset in string
* \param o Offset in the string to start at
* \return Offset of first byte of next legal character
*/
size_t utf8_next(const char *s, size_t l, size_t o)
{
uint32_t next;
parserutils_error perror;
 
perror = parserutils_charset_utf8_next((const uint8_t *) s, l, o,
&next);
assert(perror == PARSERUTILS_OK);
 
return next;
}
 
/* Cache of previous iconv conversion descriptor used by utf8_convert */
static struct {
char from[32]; /**< Encoding name to convert from */
char to[32]; /**< Encoding name to convert to */
iconv_t cd; /**< Iconv conversion descriptor */
} last_cd;
 
/**
* Finalise the UTF-8 library
*/
void utf8_finalise(void)
{
if (last_cd.cd != 0)
iconv_close(last_cd.cd);
 
/* paranoia follows */
last_cd.from[0] = '\0';
last_cd.to[0] = '\0';
last_cd.cd = 0;
}
 
/**
* Convert a UTF8 string into the named encoding
*
* \param string The NULL-terminated string to convert
* \param encname The encoding name (suitable for passing to iconv)
* \param len Length of input string to consider (in bytes), or 0
* \param result Pointer to location to store result (allocated on heap)
* \return Appropriate utf8_convert_ret value
*/
utf8_convert_ret utf8_to_enc(const char *string, const char *encname,
size_t len, char **result)
{
return utf8_convert(string, len, "UTF-8", encname, result);
}
 
/**
* Convert a string in the named encoding into a UTF-8 string
*
* \param string The NULL-terminated string to convert
* \param encname The encoding name (suitable for passing to iconv)
* \param len Length of input string to consider (in bytes), or 0
* \param result Pointer to location to store result (allocated on heap)
* \return Appropriate utf8_convert_ret value
*/
utf8_convert_ret utf8_from_enc(const char *string, const char *encname,
size_t len, char **result)
{
return utf8_convert(string, len, encname, "UTF-8", result);
}
 
/**
* Convert a string from one encoding to another
*
* \param string The NULL-terminated string to convert
* \param len Length of input string to consider (in bytes), or 0
* \param from The encoding name to convert from
* \param to The encoding name to convert to
* \param result Pointer to location in which to store result
* \return Appropriate utf8_convert_ret value
*/
utf8_convert_ret utf8_convert(const char *string, size_t len,
const char *from, const char *to, char **result)
{
iconv_t cd;
char *temp, *out, *in;
size_t slen, rlen;
 
assert(string && from && to && result);
 
if (string[0] == '\0') {
/* On AmigaOS, iconv() returns an error if we pass an
* empty string. This prevents iconv() being called as
* there is no conversion necessary anyway. */
*result = strdup("");
if (!(*result)) {
*result = NULL;
return UTF8_CONVERT_NOMEM;
}
 
return UTF8_CONVERT_OK;
}
 
if (strcasecmp(from, to) == 0) {
/* conversion from an encoding to itself == strdup */
slen = len ? len : strlen(string);
*(result) = strndup(string, slen);
if (!(*result)) {
*(result) = NULL;
return UTF8_CONVERT_NOMEM;
}
 
return UTF8_CONVERT_OK;
}
 
in = (char *)string;
 
/* we cache the last used conversion descriptor,
* so check if we're trying to use it here */
if (strncasecmp(last_cd.from, from, sizeof(last_cd.from)) == 0 &&
strncasecmp(last_cd.to, to, sizeof(last_cd.to)) == 0) {
cd = last_cd.cd;
}
else {
/* no match, so create a new cd */
cd = iconv_open(to, from);
if (cd == (iconv_t)-1) {
if (errno == EINVAL)
return UTF8_CONVERT_BADENC;
/* default to no memory */
return UTF8_CONVERT_NOMEM;
}
 
/* close the last cd - we don't care if this fails */
if (last_cd.cd)
iconv_close(last_cd.cd);
 
/* and copy the to/from/cd data into last_cd */
strncpy(last_cd.from, from, sizeof(last_cd.from));
strncpy(last_cd.to, to, sizeof(last_cd.to));
last_cd.cd = cd;
}
 
slen = len ? len : strlen(string);
/* Worst case = ASCII -> UCS4, so allocate an output buffer
* 4 times larger than the input buffer, and add 4 bytes at
* the end for the NULL terminator
*/
rlen = slen * 4 + 4;
 
temp = out = malloc(rlen);
if (!out)
return UTF8_CONVERT_NOMEM;
 
/* perform conversion */
if (iconv(cd, (void *) &in, &slen, &out, &rlen) == (size_t)-1) {
free(temp);
/* clear the cached conversion descriptor as it's invalid */
if (last_cd.cd)
iconv_close(last_cd.cd);
last_cd.from[0] = '\0';
last_cd.to[0] = '\0';
last_cd.cd = 0;
/** \todo handle the various cases properly
* There are 3 possible error cases:
* a) Insufficiently large output buffer
* b) Invalid input byte sequence
* c) Incomplete input sequence */
return UTF8_CONVERT_NOMEM;
}
 
*(result) = realloc(temp, out - temp + 4);
if (!(*result)) {
free(temp);
*(result) = NULL; /* for sanity's sake */
return UTF8_CONVERT_NOMEM;
}
 
/* NULL terminate - needs 4 characters as we may have
* converted to UTF-32 */
memset((*result) + (out - temp), 0, 4);
 
return UTF8_CONVERT_OK;
}
 
static utf8_convert_ret utf8_convert_html_chunk(iconv_t cd,
const char *chunk, size_t inlen,
char **out, size_t *outlen)
{
size_t ret, esclen;
uint32_t ucs4;
char *pescape, escape[11];
 
while (inlen > 0) {
ret = iconv(cd, (void *) &chunk, &inlen, (void *) out, outlen);
if (ret != (size_t) -1)
break;
 
if (errno != EILSEQ)
return UTF8_CONVERT_NOMEM;
 
ucs4 = utf8_to_ucs4(chunk, inlen);
esclen = snprintf(escape, sizeof(escape), "&#x%06x;", ucs4);
pescape = escape;
ret = iconv(cd, (void *) &pescape, &esclen,
(void *) out, outlen);
if (ret == (size_t) -1)
return UTF8_CONVERT_NOMEM;
 
esclen = utf8_next(chunk, inlen, 0);
chunk += esclen;
inlen -= esclen;
}
 
return UTF8_CONVERT_OK;
}
 
/**
* Convert a UTF-8 encoded string into a string of the given encoding,
* applying HTML escape sequences where necessary.
*
* \param string String to convert (NUL-terminated)
* \param encname Name of encoding to convert to
* \param len Length, in bytes, of the input string, or 0
* \param result Pointer to location to receive result
* \return Appropriate utf8_convert_ret value
*/
utf8_convert_ret utf8_to_html(const char *string, const char *encname,
size_t len, char **result)
{
iconv_t cd;
const char *in;
char *out, *origout;
size_t off, prev_off, inlen, outlen, origoutlen, esclen;
utf8_convert_ret ret;
char *pescape, escape[11];
 
if (len == 0)
len = strlen(string);
 
cd = iconv_open(encname, "UTF-8");
if (cd == (iconv_t) -1) {
if (errno == EINVAL)
return UTF8_CONVERT_BADENC;
/* default to no memory */
return UTF8_CONVERT_NOMEM;
}
 
/* Worst case is ASCII -> UCS4, with all characters escaped:
* "&#xYYYYYY;", thus each input character may become a string
* of 10 UCS4 characters, each 4 bytes in length */
origoutlen = outlen = len * 10 * 4;
origout = out = malloc(outlen);
if (out == NULL) {
iconv_close(cd);
return UTF8_CONVERT_NOMEM;
}
 
/* Process input in chunks between characters we must escape */
prev_off = off = 0;
while (off < len) {
/* Must escape '&', '<', and '>' */
if (string[off] == '&' || string[off] == '<' ||
string[off] == '>') {
if (off - prev_off > 0) {
/* Emit chunk */
in = string + prev_off;
inlen = off - prev_off;
ret = utf8_convert_html_chunk(cd, in, inlen,
&out, &outlen);
if (ret != UTF8_CONVERT_OK) {
free(origout);
iconv_close(cd);
return ret;
}
}
 
/* Emit mandatory escape */
esclen = snprintf(escape, sizeof(escape),
"&#x%06x;", string[off]);
pescape = escape;
ret = utf8_convert_html_chunk(cd, pescape, esclen,
&out, &outlen);
if (ret != UTF8_CONVERT_OK) {
free(origout);
iconv_close(cd);
return ret;
}
 
prev_off = off = utf8_next(string, len, off);
} else {
off = utf8_next(string, len, off);
}
}
 
/* Process final chunk */
if (prev_off < len) {
in = string + prev_off;
inlen = len - prev_off;
ret = utf8_convert_html_chunk(cd, in, inlen, &out, &outlen);
if (ret != UTF8_CONVERT_OK) {
free(origout);
iconv_close(cd);
return ret;
}
}
 
iconv_close(cd);
 
/* Shrink-wrap */
*result = realloc(origout, origoutlen - outlen + 4);
if (*result == NULL) {
free(origout);
return UTF8_CONVERT_NOMEM;
}
memset(*result + (origoutlen - outlen), 0, 4);
 
return UTF8_CONVERT_OK;
}
 
 
/contrib/network/netsurf/netsurf/utils/utf8.h
0,0 → 1,70
/*
* Copyright 2005 John M Bell <jmb202@ecs.soton.ac.uk>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
/** \file
* UTF-8 manipulation functions (interface).
*/
typedef signed char int8_t;
typedef signed short int16_t;
typedef signed int int32_t;
 
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
 
 
#ifndef _NETSURF_UTILS_UTF8_H_
#define _NETSURF_UTILS_UTF8_H_
 
#include <stdint.h>
 
typedef enum {
UTF8_CONVERT_OK,
UTF8_CONVERT_NOMEM,
UTF8_CONVERT_BADENC
} utf8_convert_ret;
 
uint32_t utf8_to_ucs4(const char *s, size_t l);
size_t utf8_from_ucs4(uint32_t c, char *s);
 
size_t utf8_length(const char *s);
size_t utf8_bounded_length(const char *s, size_t l);
 
size_t utf8_char_byte_length(const char *s);
 
size_t utf8_prev(const char *s, size_t o);
size_t utf8_next(const char *s, size_t l, size_t o);
 
utf8_convert_ret utf8_to_enc(const char *string, const char *encname,
size_t len, char **result);
utf8_convert_ret utf8_from_enc(const char *string, const char *encname,
size_t len, char **result);
 
utf8_convert_ret utf8_to_html(const char *string, const char *encname,
size_t len, char **result);
 
/* These two are platform specific */
utf8_convert_ret utf8_to_local_encoding(const char *string, size_t len,
char **result);
utf8_convert_ret utf8_from_local_encoding(const char *string, size_t len,
char **result);
 
void utf8_finalise(void);
 
#endif
/contrib/network/netsurf/netsurf/utils/utils.c
0,0 → 1,433
/*
* Copyright 2007 Rob Kendrick <rjek@netsurf-browser.org>
* Copyright 2004-2007 James Bursa <bursa@users.sourceforge.net>
* Copyright 2003 Phil Mellor <monkeyson@users.sourceforge.net>
* Copyright 2003 John M Bell <jmb202@ecs.soton.ac.uk>
* Copyright 2004 John Tytgat <joty@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
#include <assert.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <regex.h>
#include <time.h>
 
#include "utils/config.h"
#include "utils/messages.h"
#include "utils/utf8.h"
#include "utils/utils.h"
#include "utils/log.h"
 
void *
ns_realloc(void *ptr, size_t size, void *pw)
{
(void)pw;
if (ptr == NULL)
return size > 0 ? malloc(size) : NULL;
if (size == 0) {
free(ptr);
return NULL;
}
return realloc(ptr, size);
}
 
char * strip(char * const s)
{
size_t i;
for (i = strlen(s);
i != 0 && (s[i - 1] == ' ' || s[i - 1] == '\n' ||
s[i - 1] == '\r' || s[i - 1] == '\t');
i--)
;
s[i] = 0;
return s + strspn(s, " \t\r\n");
}
 
int whitespace(const char * str)
{
unsigned int i;
for (i = 0; i < strlen(str); i++)
if (!isspace(str[i]))
return 0;
return 1;
}
 
/**
* returns a string without its underscores
* \param replacespace true to insert a space where there was an underscore
*/
 
char *remove_underscores(const char *s, bool replacespace)
{
size_t i, ii, len;
char *ret;
len = strlen(s);
ret = malloc(len + 1);
if (ret == NULL)
return NULL;
for (i = 0, ii = 0; i < len; i++) {
if (s[i] != '_')
ret[ii++] = s[i];
else if (replacespace)
ret[ii++] = ' ';
}
ret[ii] = '\0';
return ret;
}
 
/**
* Replace consecutive whitespace with a single space.
*
* \param s source string
* \return heap allocated result, or 0 on memory exhaustion
*/
 
char * squash_whitespace(const char *s)
{
char *c = malloc(strlen(s) + 1);
int i = 0, j = 0;
if (!c)
return 0;
do {
if (s[i] == ' ' || s[i] == '\n' || s[i] == '\r' ||
s[i] == '\t') {
c[j++] = ' ';
while (s[i] == ' ' || s[i] == '\n' || s[i] == '\r' ||
s[i] == '\t')
i++;
}
c[j++] = s[i++];
} while (s[i - 1] != 0);
return c;
}
 
 
/**
* Converts NUL terminated UTF-8 encoded string s containing zero or more
* spaces (char 32) or TABs (char 9) to non-breaking spaces
* (0xC2 + 0xA0 in UTF-8 encoding).
*
* Caller needs to free() result. Returns NULL in case of error. No
* checking is done on validness of the UTF-8 input string.
*/
char *cnv_space2nbsp(const char *s)
{
const char *srcP;
char *d, *d0;
unsigned int numNBS;
/* Convert space & TAB into non breaking space character (0xA0) */
for (numNBS = 0, srcP = (const char *)s; *srcP != '\0'; ++srcP)
if (*srcP == ' ' || *srcP == '\t')
++numNBS;
if ((d = (char *)malloc((srcP - s) + numNBS + 1)) == NULL)
return NULL;
for (d0 = d, srcP = (const char *)s; *srcP != '\0'; ++srcP) {
if (*srcP == ' ' || *srcP == '\t') {
*d0++ = 0xC2;
*d0++ = 0xA0;
} else
*d0++ = *srcP;
}
*d0 = '\0';
return d;
}
 
/**
* Check if a directory exists.
*/
 
bool is_dir(const char *path)
{
struct stat s;
 
if (stat(path, &s))
return false;
 
return S_ISDIR(s.st_mode) ? true : false;
}
 
 
/**
* Compile a regular expression, handling errors.
*
* Parameters as for regcomp(), see man regex.
*/
 
void regcomp_wrapper(regex_t *preg, const char *regex, int cflags)
{
int r;
r = regcomp(preg, regex, cflags);
if (r) {
char errbuf[200];
regerror(r, preg, errbuf, sizeof errbuf);
fprintf(stderr, "Failed to compile regexp '%s'\n", regex);
die(errbuf);
}
}
 
/** We can have a fairly good estimate of how long the buffer needs to
* be. The unsigned long can store a value representing a maximum size
* of around 4 GB. Therefore the greatest space required is to
* represent 1023MB. Currently that would be represented as "1023MB" so 12
* including a null terminator.
* Ideally we would be able to know this value for sure, in the mean
* time the following should suffice.
**/
 
#define BYTESIZE_BUFFER_SIZE 20
 
/**
* Does a simple conversion which assumes the user speaks English. The buffer
* returned is one of three static ones so may change each time this call is
* made. Don't store the buffer for later use. It's done this way for
* convenience and to fight possible memory leaks, it is not necessarily pretty.
**/
 
char *human_friendly_bytesize(unsigned long bsize) {
static char buffer1[BYTESIZE_BUFFER_SIZE];
static char buffer2[BYTESIZE_BUFFER_SIZE];
static char buffer3[BYTESIZE_BUFFER_SIZE];
static char *curbuffer = buffer3;
enum {bytes, kilobytes, megabytes, gigabytes} unit = bytes;
static char units[][7] = {"Bytes", "kBytes", "MBytes", "GBytes"};
 
float bytesize = (float)bsize;
 
if (curbuffer == buffer1)
curbuffer = buffer2;
else if (curbuffer == buffer2)
curbuffer = buffer3;
else
curbuffer = buffer1;
 
if (bytesize > 1024) {
bytesize /= 1024;
unit = kilobytes;
}
 
if (bytesize > 1024) {
bytesize /= 1024;
unit = megabytes;
}
 
if (bytesize > 1024) {
bytesize /= 1024;
unit = gigabytes;
}
 
sprintf(curbuffer, "%3.2f%s", bytesize, messages_get(units[unit]));
 
return curbuffer;
}
 
/**
* Create an RFC 1123 compliant date string from a Unix timestamp
*
* \param t The timestamp to consider
* \return Pointer to buffer containing string - invalidated by next call.
*/
const char *rfc1123_date(time_t t)
{
static char ret[30];
 
struct tm *tm = gmtime(&t);
const char *days[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" },
*months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
 
snprintf(ret, sizeof ret, "%s, %02d %s %d %02d:%02d:%02d GMT",
days[tm->tm_wday], tm->tm_mday, months[tm->tm_mon],
tm->tm_year + 1900, tm->tm_hour, tm->tm_min,
tm->tm_sec);
 
return ret;
}
 
/**
* Returns a number of centiseconds, that increases in real time, for the
* purposes of measuring how long something takes in wall-clock terms. It uses
* gettimeofday() for this. Should the call to gettimeofday() fail, it returns
* zero.
*
* \return number of centiseconds that increases monotonically
*/
unsigned int wallclock(void)
{
struct timeval tv;
 
LOG(("WALLCLOCK IS HERE"));
if (gettimeofday(&tv, NULL) == -1)
{LOG(("And -1"));return 0;}
 
LOG(("And time"));
return ((tv.tv_sec * 100) + (tv.tv_usec / 10000));
}
 
#ifndef HAVE_STRCASESTR
 
/**
* Case insensitive strstr implementation
*
* \param haystack String to search in
* \param needle String to look for
* \return Pointer to start of found substring, or NULL if not found
*/
char *strcasestr(const char *haystack, const char *needle)
{
size_t needle_len = strlen(needle);
const char * last_start = haystack + (strlen(haystack) - needle_len);
 
while (haystack <= last_start) {
if (strncasecmp(haystack, needle, needle_len) == 0)
return (char *)haystack;
haystack++;
}
 
return NULL;
}
 
#endif
 
#ifndef HAVE_STRNDUP
 
/**
* Duplicate up to n characters of a string.
*/
 
char *strndup(const char *s, size_t n)
{
size_t len;
char *s2;
 
for (len = 0; len != n && s[len]; len++)
continue;
 
s2 = malloc(len + 1);
if (!s2)
return 0;
 
memcpy(s2, s, len);
s2[len] = 0;
return s2;
}
 
#endif
 
#ifndef HAVE_STRCHRNUL
 
/**
* Find the first occurrence of C in S or the final NUL byte.
*/
char *strchrnul (const char *s, int c_in)
{
const unsigned char *us = (const unsigned char *) s;
 
while (*us != c_in && *us != '\0')
us++;
 
return (void *) us;
}
 
#endif
 
#ifndef HAVE_UTSNAME
#include "utils/utsname.h"
 
int uname(struct utsname *buf) {
strcpy(buf->sysname,"windows");
strcpy(buf->nodename,"nodename");
strcpy(buf->release,"release");
strcpy(buf->version,"version");
strcpy(buf->machine,"pc");
return 0;
}
#endif
 
#ifndef HAVE_REALPATH
char *realpath(const char *path, char *resolved_path)
{
char *ret;
if (resolved_path == NULL) {
ret=strdup(path);
} else {
ret = resolved_path;
strcpy(resolved_path, path);
}
return ret;
}
 
#ifndef HAVE_INETATON
 
 
int inet_aton(const char *cp, struct in_addr *inp)
{
unsigned int b1, b2, b3, b4;
unsigned char c;
 
if (strspn(cp, "0123456789.") < strlen(cp))
return 0;
 
if (sscanf(cp, "%3u.%3u.%3u.%3u%c", &b1, &b2, &b3, &b4, &c) != 4)
return 0;
 
if ((b1 > 255) || (b2 > 255) || (b3 > 255) || (b4 > 255))
return 0;
 
inp->s_addr = b4 << 24 | b3 << 16 | b2 << 8 | b1;
 
return 1;
}
 
#endif
 
#ifndef HAVE_INETPTON
 
int inet_pton(int af, const char *src, void *dst)
{
int ret;
 
if (af == AF_INET) {
ret = inet_aton(src, dst);
}
#if !defined(NO_IPV6)
else if (af == AF_INET6) {
/* TODO: implement v6 address support */
ret = -1;
errno = EAFNOSUPPORT;
}
#endif
else {
ret = -1;
errno = EAFNOSUPPORT;
}
 
return ret;
}
 
#endif
 
 
#endif
/contrib/network/netsurf/netsurf/utils/utils.h
0,0 → 1,190
/*
* Copyright 2004-2007 James Bursa <bursa@users.sourceforge.net>
* Copyright 2004 John Tytgat <joty@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
#ifndef _NETSURF_UTILS_UTILS_H_
#define _NETSURF_UTILS_UTILS_H_
 
#include <inttypes.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/time.h>
#include <regex.h>
#include <assert.h>
 
#ifndef NOF_ELEMENTS
#define NOF_ELEMENTS(array) (sizeof(array)/sizeof(*(array)))
#endif
 
#ifndef ABS
#define ABS(x) (((x)>0)?(x):(-(x)))
#endif
 
#ifdef __MINT__ /* avoid using GCCs builtin min/max functions */
#undef min
#undef max
#endif
 
#ifndef min
#define min(x,y) (((x)<(y))?(x):(y))
#endif
 
#ifndef max
#define max(x,y) (((x)>(y))?(x):(y))
#endif
 
#ifndef PRIxPTR
#define PRIxPTR "x"
#endif
 
#ifndef PRId64
#define PRId64 "lld"
#endif
 
#if defined(_WIN32)
#define SSIZET_FMT "Iu"
#else
#define SSIZET_FMT "zd"
#endif
 
#if defined(__GNUC__) && (__GNUC__ < 3)
#define FLEX_ARRAY_LEN_DECL 0
#else
#define FLEX_ARRAY_LEN_DECL
#endif
 
#if defined(__HAIKU__) || defined(__BEOS__)
#define strtof(s,p) ((float)(strtod((s),(p))))
#endif
 
#if !defined(ceilf) && defined(__MINT__)
#define ceilf(x) (float)ceil((double)x)
#endif
 
/**
* Calculate length of constant C string.
*
* \param x a constant C string.
* \return the length of C string without its terminating NUL accounted.
*/
#define SLEN(x) (sizeof((x)) - 1)
 
enum query_response {
QUERY_CONTINUE,
QUERY_YES,
QUERY_NO,
QUERY_ESCAPE
};
 
typedef int query_id;
 
#define QUERY_INVALID ((query_id)-1)
 
typedef struct
{
void (*confirm)(query_id id, enum query_response res, void *pw);
void (*cancel)(query_id, enum query_response res, void *pw);
} query_callback;
 
#ifdef HAVE_MKDIR
#define nsmkdir(dir, mode) mkdir((dir), (mode))
#else
#define nsmkdir(dir, mode) mkdir((dir))
#endif
 
#ifndef timeradd
#define timeradd(a, aa, result) \
do { \
(result)->tv_sec = (a)->tv_sec + (aa)->tv_sec; \
(result)->tv_usec = (a)->tv_usec + (aa)->tv_usec; \
if ((result)->tv_usec >= 1000000) { \
++(result)->tv_sec; \
(result)->tv_usec -= 1000000; \
} \
} while (0)
#endif
 
#ifndef timersub
#define timersub(a, aa, result) \
do { \
(result)->tv_sec = (a)->tv_sec - (aa)->tv_sec; \
(result)->tv_usec = (a)->tv_usec - (aa)->tv_usec; \
if ((result)->tv_usec < 0) { \
--(result)->tv_sec; \
(result)->tv_usec += 1000000; \
} \
} while (0)
#endif
 
 
/**
* Private-word-capable realloc() implementation which
* behaves as most NS libraries expect in the face of
* realloc(ptr, 0) and realloc(NULL, size).
*
* \param ptr The pointer for reallocation
* \param size The number of bytes for the allocation
* \param pw A "private word" which we ignore.
* \return The new pointer (NULL on frees or errors)
*/
void *ns_realloc(void *ptr, size_t size, void *pw);
 
char * strip(char * const s);
int whitespace(const char * str);
char * squash_whitespace(const char * s);
char *remove_underscores(const char *s, bool replacespace);
char *cnv_space2nbsp(const char *s);
bool is_dir(const char *path);
void regcomp_wrapper(regex_t *preg, const char *regex, int cflags);
char *human_friendly_bytesize(unsigned long bytesize);
const char *rfc1123_date(time_t t);
unsigned int wallclock(void);
 
/**
* Return a hex digit for the given numerical value.
*
* \return character in range 0-9a-f
*/
inline static char digit2lowcase_hex(unsigned char digit) {
assert(digit < 16);
return "0123456789abcdef"[digit];
}
 
/**
* Return a hex digit for the given numerical value.
*
* \return character in range 0-9A-F
*/
inline static char digit2uppercase_hex(unsigned char digit) {
assert(digit < 16);
return "0123456789ABCDEF"[digit];
}
 
 
/* Platform specific functions */
void die(const char * const error);
void warn_user(const char *warning, const char *detail);
query_id query_user(const char *query, const char *detail,
const query_callback *cb, void *pw, const char *yes, const char *no);
void query_close(query_id);
void PDF_Password(char **owner_pass, char **user_pass, char *path);
char *filename_from_path(char *path);
bool path_add_part(char *path, int length, const char *newpart);
#endif
/contrib/network/netsurf/netsurf/utils/utsname.h
0,0 → 1,39
/*
* Copyright 2010 Vincent Sanders <vince@kyllikki.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
#ifndef _NETSURF_UTILS_UTSNAME_H_
#define _NETSURF_UTILS_UTSNAME_H_
 
#ifdef HAVE_UTSNAME
#include <sys/utsname.h>
#else
/* from posix spec */
struct utsname {
char sysname[65]; /* Operating system name (e.g., "Linux") */
char nodename[65]; /* Name within "some implementation-defined
network" */
char release[65]; /* OS release (e.g., "2.6.28") */
char version[65]; /* OS version */
char machine[65]; /* Hardware identifier */
};
 
int uname(struct utsname *buf);
 
#endif
 
#endif
/contrib/network/netsurf/netsurf/utils/valgrind.supp
0,0 → 1,14
# Valgrind suppression file for NetSurf
 
# Suppress a valgrind message about use of uninitialized memory in strchrnul().
# This use is OK because it provides only a speedup.
{
strchrnul-addr4
Memcheck:Addr4
fun:strchrnul
}
{
strchrnul-addr8
Memcheck:Addr8
fun:strchrnul
}
/contrib/network/netsurf/netsurf/utils/warning-blame.sh
0,0 → 1,64
#!/bin/sh
 
# Copyright 2007 Vincent Sanders <vince@debian.org>
# All rights reserved.
 
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. Neither the name of the Author nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
 
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
 
 
# where to store the processed list of warnings
WARNING_LIST=/tmp/warning-list
 
if [ $# -gt 1 ]; then
if [ -f $1 ]; then
cp $1 ${WARNING_LIST}
else
echo "Need a valid warning file"
exit 1
fi
else
make clean 2>&1 >/dev/null
make 2>&1 |grep "warning:" | sort | uniq > ${WARNING_LIST}
fi
 
for blamefile in $(cat ${WARNING_LIST} | cut -f 1 -d ':' | sort | uniq ); do
if [ -f ${blamefile} ]; then
svn blame ${blamefile} >/tmp/blame
 
cat ${WARNING_LIST} | grep "^${blamefile}" >/tmp/blame-warnings
 
while read warning; do
echo ${warning}
 
lineno=$(echo ${warning} | cut -f 2 -d ':' ; )
 
cat /tmp/blame | head -n ${lineno} | tail -n 1
 
done < /tmp/blame-warnings
rm /tmp/blame-warnings
else
echo "Unable to find ${blamefile}"
fi
done
Property changes:
Added: svn:executable
+*
\ No newline at end of property