/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, ¶ms); |
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, ¶ms); |
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, ¶ms); |
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 |