netsurf: branch vince/disccache updated. release/3.0-1119-g16f6457
by NetSurf Browser Project
Gitweb links:
...log http://git.netsurf-browser.org/netsurf.git/shortlog/16f6457502da8f15c7a56...
...commit http://git.netsurf-browser.org/netsurf.git/commit/16f6457502da8f15c7a5633...
...tree http://git.netsurf-browser.org/netsurf.git/tree/16f6457502da8f15c7a56336e...
The branch, vince/disccache has been updated
via 16f6457502da8f15c7a56336ec23c4848fe3a9a9 (commit)
via a7f9dfe927b696491496095a2b713150d258c879 (commit)
via 9873af9b0e64b87a0c510d0020cb9a0bf13ae53c (commit)
from c940d69028064b5a3ffa38dfd67302ada9eaaaa2 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commitdiff http://git.netsurf-browser.org/netsurf.git/commit/?id=16f6457502da8f15c7a...
commit 16f6457502da8f15c7a56336ec23c4848fe3a9a9
Author: Vincent Sanders <vince(a)netsurf-browser.org>
Commit: Vincent Sanders <vince(a)netsurf-browser.org>
store and retrive cache data
diff --git a/gtk/llcache.c b/gtk/llcache.c
index f731cb5..46945ac 100644
--- a/gtk/llcache.c
+++ b/gtk/llcache.c
@@ -85,47 +85,87 @@ persist(nsurl *url, llcache_cache_control *cache_control, const uint8_t *data, c
size_t b64ulen;
char *fname;
FILE *file;
- nserror ret= NSERROR_OK;
LOG(("Writing cache file for url:%s", nsurl_access(url)));
b64u = base64url_encode(nsurl_access(url), strlen(nsurl_access(url)), &b64ulen);
- fname = malloc(SLEN("/tmp/ns/") + b64ulen + 1);
- snprintf(fname, SLEN("/tmp/ns/") + b64ulen + 1, "/tmp/ns/%s", b64u);
+ fname = malloc(SLEN("/tmp/ns/d/") + b64ulen + 1);
+ snprintf(fname, SLEN("/tmp/ns/d/") + b64ulen + 1, "/tmp/ns/d/%s", b64u);
- LOG(("Opening file %s",fname));
+ LOG(("Opening data file %s", fname));
file = fopen(fname, "wb");
- free(fname);
- if (file == NULL)
+ if (file == NULL) {
+ free(fname);
+ free(b64u);
return NSERROR_SAVE_FAILED;
+ }
LOG(("Writing %d bytes at %p to file", datalen, data));
if (fwrite(data, datalen, 1, file) != 1) {
- ret = NSERROR_SAVE_FAILED;
LOG(("did not return 1"));
+ fclose(file);
+ free(fname);
+ free(b64u);
+ return NSERROR_SAVE_FAILED;
}
fclose(file);
+
+ snprintf(fname, SLEN("/tmp/ns/i/") + b64ulen + 1, "/tmp/ns/i/%s", b64u);
+
+ LOG(("Opening info file %s", fname));
+ file = fopen(fname, "wb");
+
+ if (file == NULL) {
+ free(fname);
+ free(b64u);
+ return NSERROR_SAVE_FAILED;
+ }
+
+ fprintf(file,
+ "req_time:%lld\n"
+ "res_time:%lld\n"
+ "fin_time:%lld\n"
+ "date:%lld\n"
+ "expires:%lld\n"
+ "age:%d\n"
+ "max_age:%d\n"
+ "no_cache:%d\n"
+ "etag:%s\n"
+ "last_modified:%lld\n",
+ (long long)cache_control->req_time,
+ (long long)cache_control->res_time,
+ (long long)cache_control->fin_time,
+ (long long)cache_control->date,
+ (long long)cache_control->expires,
+ cache_control->age,
+ cache_control->max_age,
+ cache_control->no_cache,
+ cache_control->etag == NULL?"":cache_control->etag,
+ (long long)cache_control->last_modified);
+
+ fclose(file);
+
+ free(fname);
free(b64u);
- return ret;
+ return NSERROR_OK;
}
static nserror
-retrieve(nsurl *url, llcache_cache_control *cache_control, uint8_t **data_out, size_t *datalen_out)
+retrieve(nsurl *url,
+ llcache_cache_control *cache_control,
+ uint8_t **data_out,
+ size_t *datalen_out)
{
uint8_t *b64u;
size_t b64ulen;
char *fname;
FILE *file;
- nserror ret= NSERROR_OK;
uint8_t *data;
size_t datalen;
- if (cache_control != NULL) {
- return NSERROR_NOT_FOUND;
- }
data = *data_out;
datalen = *datalen_out;
@@ -135,8 +175,48 @@ retrieve(nsurl *url, llcache_cache_control *cache_control, uint8_t **data_out, s
strlen(nsurl_access(url)),
&b64ulen);
- fname = malloc(SLEN("/tmp/ns/") + b64ulen + 1);
- snprintf(fname, SLEN("/tmp/ns/") + b64ulen + 1, "/tmp/ns/%s", b64u);
+ fname = malloc(SLEN("/tmp/ns/d/") + b64ulen + 1);
+
+ /* retrive cache control info if necessary */
+ if (cache_control != NULL) {
+ snprintf(fname, SLEN("/tmp/ns/i/") + b64ulen + 1, "/tmp/ns/i/%s", b64u);
+
+ LOG(("Opening info file %s", fname));
+ file = fopen(fname, "rb");
+
+ if (file == NULL) {
+ free(fname);
+ free(b64u);
+ return NSERROR_NOT_FOUND;
+ }
+
+ fscanf(file,
+ "req_time:%lld\n"
+ "res_time:%lld\n"
+ "fin_time:%lld\n"
+ "date:%lld\n"
+ "expires:%lld\n"
+ "age:%d\n"
+ "max_age:%d\n"
+ "no_cache:%d\n"
+ "etag:%ms\n"
+ "last_modified:%lld\n",
+ (long long*)&cache_control->req_time,
+ (long long*)&cache_control->res_time,
+ (long long*)&cache_control->fin_time,
+ (long long*)&cache_control->date,
+ (long long*)&cache_control->expires,
+ &cache_control->age,
+ &cache_control->max_age,
+ (int *)&cache_control->no_cache,
+ &cache_control->etag,
+ (long long*)&cache_control->last_modified);
+
+ fclose(file);
+
+ }
+
+ snprintf(fname, SLEN("/tmp/ns/d/") + b64ulen + 1, "/tmp/ns/d/%s", b64u);
LOG(("Opening file %s",fname));
file = fopen(fname, "rb");
commitdiff http://git.netsurf-browser.org/netsurf.git/commit/?id=a7f9dfe927b69649149...
commit a7f9dfe927b696491496095a2b713150d258c879
Author: Vincent Sanders <vince(a)netsurf-browser.org>
Commit: Vincent Sanders <vince(a)netsurf-browser.org>
working basic persistant sorage for gtk frontend
diff --git a/content/llcache.c b/content/llcache.c
index 87e1692..ed42895 100644
--- a/content/llcache.c
+++ b/content/llcache.c
@@ -1030,7 +1030,7 @@ llcache_persist_retrieve(llcache_object *object)
/* Source data for the object may be in the persiatant store */
return guit->llcache->retrieve(object->url,
- &object->cache,
+ NULL,
&object->source_data,
&object->source_len);
}
@@ -1102,7 +1102,7 @@ llcache_object_retrieve_from_cache(nsurl *url,
llcache_object *obj, *newest = NULL;
#ifdef LLCACHE_TRACE
- LOG(("Searching cache for %s (%x %s %p)",
+ LOG(("Searching cache for %s flags:%x referer:%s post:%p",
nsurl_access(url), flags, referer==NULL?"":nsurl_access(referer), post));
#endif
diff --git a/gtk/llcache.c b/gtk/llcache.c
index e6bf7aa..f731cb5 100644
--- a/gtk/llcache.c
+++ b/gtk/llcache.c
@@ -20,24 +20,167 @@
* Low-level resource cache persistant storage implementation.
*/
+#include <string.h>
+
#include "utils/nsurl.h"
#include "utils/log.h"
+#include "utils/utils.h"
#include "desktop/gui.h"
#include "content/llcache_private.h"
#include "gtk/llcache.h"
+static uint8_t encoding_table[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
+ 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
+ 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
+ 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
+ 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
+ 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
+ 'w', 'x', 'y', 'z', '0', '1', '2', '3',
+ '4', '5', '6', '7', '8', '9', '-', '_'};
+static unsigned int mod_table[] = {0, 2, 1};
+
+
+static uint8_t *base64url_encode(const char *data,
+ size_t input_length,
+ size_t *output_length)
+{
+ uint8_t *encoded_data;
+ size_t i;
+ size_t j;
+
+ *output_length = 4 * ((input_length + 2) / 3);
+
+ encoded_data = malloc(*output_length + 1);
+ if (encoded_data == NULL) {
+ return NULL;
+ }
+
+ for (i = 0, j = 0; i < input_length;) {
+
+ uint32_t octet_a = i < input_length ? data[i++] : 0;
+ uint32_t octet_b = i < input_length ? data[i++] : 0;
+ uint32_t octet_c = i < input_length ? data[i++] : 0;
+
+ uint32_t triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c;
+
+ encoded_data[j++] = encoding_table[(triple >> 3 * 6) & 0x3F];
+ encoded_data[j++] = encoding_table[(triple >> 2 * 6) & 0x3F];
+ encoded_data[j++] = encoding_table[(triple >> 1 * 6) & 0x3F];
+ encoded_data[j++] = encoding_table[(triple >> 0 * 6) & 0x3F];
+ }
+
+ for (i = 0; i < mod_table[input_length % 3]; i++) {
+ encoded_data[*output_length - 1 - i] = 0;
+ (*output_length)--;
+ }
+
+ return encoded_data;
+}
+
static nserror
persist(nsurl *url, llcache_cache_control *cache_control, const uint8_t *data, const size_t datalen)
{
+ uint8_t *b64u;
+ size_t b64ulen;
+ char *fname;
+ FILE *file;
+ nserror ret= NSERROR_OK;
+
LOG(("Writing cache file for url:%s", nsurl_access(url)));
- return NSERROR_OK;
+ b64u = base64url_encode(nsurl_access(url), strlen(nsurl_access(url)), &b64ulen);
+
+ fname = malloc(SLEN("/tmp/ns/") + b64ulen + 1);
+ snprintf(fname, SLEN("/tmp/ns/") + b64ulen + 1, "/tmp/ns/%s", b64u);
+
+ LOG(("Opening file %s",fname));
+ file = fopen(fname, "wb");
+ free(fname);
+
+ if (file == NULL)
+ return NSERROR_SAVE_FAILED;
+
+ LOG(("Writing %d bytes at %p to file", datalen, data));
+ if (fwrite(data, datalen, 1, file) != 1) {
+ ret = NSERROR_SAVE_FAILED;
+ LOG(("did not return 1"));
+ }
+
+ fclose(file);
+ free(b64u);
+
+ return ret;
}
static nserror
retrieve(nsurl *url, llcache_cache_control *cache_control, uint8_t **data_out, size_t *datalen_out)
{
- return NSERROR_NOT_FOUND;
+ uint8_t *b64u;
+ size_t b64ulen;
+ char *fname;
+ FILE *file;
+ nserror ret= NSERROR_OK;
+ uint8_t *data;
+ size_t datalen;
+
+ if (cache_control != NULL) {
+ return NSERROR_NOT_FOUND;
+ }
+
+ data = *data_out;
+ datalen = *datalen_out;
+
+ LOG(("retriving cache file for url:%s", nsurl_access(url)));
+ b64u = base64url_encode(nsurl_access(url),
+ strlen(nsurl_access(url)),
+ &b64ulen);
+
+ fname = malloc(SLEN("/tmp/ns/") + b64ulen + 1);
+ snprintf(fname, SLEN("/tmp/ns/") + b64ulen + 1, "/tmp/ns/%s", b64u);
+
+ LOG(("Opening file %s",fname));
+ file = fopen(fname, "rb");
+ free(fname);
+ if (file == NULL) {
+ free(b64u);
+ return NSERROR_NOT_FOUND;
+ }
+
+ /* need to deal with buffers */
+ if (data == NULL) {
+ if (datalen == 0) {
+ /* caller did not know the files length */
+ fseek(file, 0L, SEEK_END);
+ datalen = ftell(file);
+ fseek(file, 0L, SEEK_SET);
+ }
+
+ data = malloc(datalen);
+ if (data == NULL) {
+ fclose(file);
+ free(b64u);
+ return NSERROR_NOMEM;
+ }
+ }
+
+ LOG(("Reading %d bytes into %p from file", datalen, data));
+ if (fread(data, datalen, 1, file) != 1) {
+ LOG(("did not return 1"));
+ fclose(file);
+ free(b64u);
+ if ((*data_out) == NULL) {
+ free(data);
+ }
+ return NSERROR_NOT_FOUND;
+ }
+
+ fclose(file);
+ free(b64u);
+
+ *data_out = data;
+ *datalen_out = datalen;
+
+ return NSERROR_OK;
}
static struct gui_llcache_table llcache_table = {
commitdiff http://git.netsurf-browser.org/netsurf.git/commit/?id=9873af9b0e64b87a0c5...
commit 9873af9b0e64b87a0c510d0020cb9a0bf13ae53c
Author: Vincent Sanders <vince(a)netsurf-browser.org>
Commit: Vincent Sanders <vince(a)netsurf-browser.org>
add sha1 implementation and tests
diff --git a/test/Makefile b/test/Makefile
index acf9d4e..825b582 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -2,6 +2,7 @@ CFLAGS := -std=c99 -g -O0 -D_BSD_SOURCE -D_POSIX_C_SOURCE -I.. \
$(shell pkg-config --cflags libcurl)
LDFLAGS := $(shell pkg-config --libs libcurl) -lz
+
llcache_CFLAGS := $(shell pkg-config --cflags libparserutils libwapcaplet libdom) -O2
llcache_LDFLAGS := $(shell pkg-config --libs libparserutils libwapcaplet libdom)
@@ -14,6 +15,7 @@ llcache_SRCS := content/fetch.c content/fetchers/curl.c \
utils/log.c utils/nsurl.c utils/messages.c utils/url.c \
utils/useragent.c utils/utils.c test/llcache.c
+
urldbtest_SRCS := content/urldb.c utils/url.c utils/utils.c utils/log.c \
desktop/options.c utils/messages.c utils/hashtable.c \
utils/filename.c utils/nsurl.c utils/corestrings.c \
@@ -22,16 +24,22 @@ urldbtest_SRCS := content/urldb.c utils/url.c utils/utils.c utils/log.c \
urldbtest_CFLAGS := $(shell pkg-config --cflags libwapcaplet libdom) -O2
urldbtest_LDFLAGS := $(shell pkg-config --libs libwapcaplet libdom)
+
nsurl_SRCS := utils/corestrings.c utils/log.c utils/nsurl.c test/nsurl.c
nsurl_CFLAGS := $(shell pkg-config --cflags libwapcaplet libdom)
nsurl_LDFLAGS := $(shell pkg-config --libs libwapcaplet libdom)
+
nsoption_SRCS := utils/log.c utils/nsoption.c test/nsoption.c
nsoption_CFLAGS := -Dnsgtk
+sha1_SRCS := utils/sha1.c utils/log.c test/sha1.c
+sha1_CFLAGS :=
+sha1_LDFLAGS :=
+
.PHONY: all
-all: llcache urldbtest nsurl nsoption
+all: llcache urldbtest nsurl nsoption sha1
llcache: $(addprefix ../,$(llcache_SRCS))
$(CC) $(CFLAGS) $(llcache_CFLAGS) $^ -o $@ $(LDFLAGS) $(llcache_LDFLAGS)
@@ -45,6 +53,9 @@ nsurl: $(addprefix ../,$(nsurl_SRCS))
nsoption: $(addprefix ../,$(nsoption_SRCS))
$(CC) $(CFLAGS) $(nsoption_CFLAGS) $^ -o $@ $(LDFLAGS) $(nsoption_LDFLAGS)
+sha1: $(addprefix ../,$(sha1_SRCS))
+ $(CC) $(CFLAGS) $(sha1_CFLAGS) $^ -o $@ $(LDFLAGS) $(sha1_LDFLAGS)
+
.PHONY: clean
clean:
diff --git a/test/sha1.c b/test/sha1.c
new file mode 100644
index 0000000..abfc25b
--- /dev/null
+++ b/test/sha1.c
@@ -0,0 +1,50 @@
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "utils/log.h"
+#include "utils/sha1.h"
+
+
+struct {
+ const char *text;
+ const uint8_t hash[NSSHA1_DIGEST_SIZE];
+} checks[] = {
+ {
+ "The quick brown fox jumps over the lazy dog",
+ { 0x2f, 0xd4, 0xe1, 0xc6, 0x7a, 0x2d, 0x28, 0xfc, 0xed, 0x84,
+ 0x9e, 0xe1, 0xbb, 0x76, 0xe7, 0x39, 0x1b, 0x93, 0xeb, 0x12 }
+ },
+ {
+ "The quick brown fox jumps over the lazy cog",
+ { 0xde, 0x9f, 0x2c, 0x7f, 0xd2, 0x5e, 0x1b, 0x3a, 0xfa, 0xd3,
+ 0xe8, 0x5a, 0x0b, 0xd1, 0x7d, 0x9b, 0x10, 0x0d, 0xb4, 0xb3 }
+ },
+ {
+ "",
+ { 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55,
+ 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09 }
+ },
+ { NULL, {0} },
+};
+
+int main(int argc, char **argv)
+{
+ uint8_t res[NSSHA1_DIGEST_SIZE];
+ int chk_loop = 0;
+
+ verbose_log = true;
+
+ while (checks[chk_loop].text != NULL) {
+
+ NSSHA1(checks[chk_loop].text, strlen(checks[chk_loop].text), res);
+ if (memcmp(res, &checks[chk_loop].hash, NSSHA1_DIGEST_SIZE) == 0) {
+ LOG(("Test %d: PASS", chk_loop));
+ } else {
+ LOG(("Test %d: FAIL", chk_loop));
+ }
+ chk_loop++;
+ }
+}
diff --git a/utils/Makefile b/utils/Makefile
index aef5799..48bba98 100644
--- a/utils/Makefile
+++ b/utils/Makefile
@@ -2,6 +2,6 @@
S_UTILS := base64.c corestrings.c filename.c filepath.c hashtable.c \
libdom.c locale.c log.c messages.c nsurl.c talloc.c url.c \
- utf8.c utils.c useragent.c bloom.c nsoption.c
+ utf8.c utils.c useragent.c bloom.c nsoption.c sha1.c
S_UTILS := $(addprefix utils/,$(S_UTILS))
diff --git a/utils/sha1.c b/utils/sha1.c
new file mode 100644
index 0000000..882f2b9
--- /dev/null
+++ b/utils/sha1.c
@@ -0,0 +1,264 @@
+/*
+ SHA-1 in C
+ By Steve Reid <sreid(a)sea-to-sky.net>
+ 100% Public Domain
+
+ -----------------
+ Modified 7/98
+ By James H. Brown <jbrown(a)burgoyne.com>
+ Still 100% Public Domain
+
+ Corrected a problem which generated improper hash values on 16 bit machines
+ Routine SHA1Update changed from
+ void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int
+ len)
+ to
+ void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned
+ long len)
+
+ The 'len' parameter was declared an int which works fine on 32 bit machines.
+ However, on 16 bit machines an int is too small for the shifts being done
+ against
+ it. This caused the hash function to generate incorrect values if len was
+ greater than 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update().
+
+ Since the file IO in main() reads 16K at a time, any file 8K or larger would
+ be guaranteed to generate the wrong hash (e.g. Test Vector #3, a million
+ "a"s).
+
+ I also changed the declaration of variables i & j in SHA1Update to
+ unsigned long from unsigned int for the same reason.
+
+ These changes should make no difference to any 32 bit implementations since
+ an
+ int and a long are the same size in those environments.
+
+ --
+ I also corrected a few compiler warnings generated by Borland C.
+ 1. Added #include <process.h> for exit() prototype
+ 2. Removed unused variable 'j' in SHA1Final
+ 3. Changed exit(0) to return(0) at end of main.
+
+ ALL changes I made can be located by searching for comments containing 'JHB'
+ -----------------
+ Modified 8/98
+ By Steve Reid <sreid(a)sea-to-sky.net>
+ Still 100% public domain
+
+ 1- Removed #include <process.h> and used return() instead of exit()
+ 2- Fixed overwriting of finalcount in SHA1Final() (discovered by Chris Hall)
+ 3- Changed email address from steve(a)edmweb.com to sreid(a)sea-to-sky.net
+
+ -----------------
+ Modified 4/01
+ By Saul Kravitz <Saul.Kravitz(a)celera.com>
+ Still 100% PD
+ Modified to run on Compaq Alpha hardware.
+
+ -----------------
+ Modified 07/2002
+ By Ralph Giles <giles(a)ghostscript.com>
+ Still 100% public domain
+ modified for use with stdint types, autoconf
+ code cleanup, removed attribution comments
+ switched SHA1Final() argument order for consistency
+ use SHA1_ prefix for public api
+ move public api to sha1.h
+*/
+
+/** \file
+ * steve reid's public domain SHA-1 implementation.
+ *
+ * Modified by Vincent Sanders <vince(a)netsurf-browser.org>
+ *
+ * This is a sligly modified version of this public domain
+ * implementation changes were made to:
+ * - introduce suitable prefixes to avoid namespace conflicts.
+ * - make the context structure self contained.
+ * - make the function signatures more suitable for this use case
+ */
+
+
+/* see https://en.wikipedia.org/wiki/SHA-1 */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "utils/errors.h"
+#include "utils/sha1.h"
+
+struct nssha1_ctx {
+ uint32_t state[5];
+ uint32_t count[2];
+ uint8_t buffer[64];
+} ;
+
+#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
+
+/* blk0() and blk() perform the initial expand. */
+/* I got the idea of expanding during the round function from SSLeay */
+/* FIXME: can we do this in an endian-proof way? */
+#ifdef WORDS_BIGENDIAN
+#define blk0(i) block->l[i]
+#else
+#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
+ |(rol(block->l[i],8)&0x00FF00FF))
+#endif
+#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
+ ^block->l[(i+2)&15]^block->l[i&15],1))
+
+/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
+#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
+#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
+#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
+
+
+
+/* Hash a single 512-bit block. This is the core of the algorithm. */
+static void SHA1_Transform(uint32_t state[5], const uint8_t buffer[64])
+{
+ uint32_t a, b, c, d, e;
+ typedef union {
+ uint8_t c[64];
+ uint32_t l[16];
+ } CHAR64LONG16;
+ CHAR64LONG16* block;
+
+ block = (CHAR64LONG16*)buffer;
+
+ /* Copy context->state[] to working vars */
+ a = state[0];
+ b = state[1];
+ c = state[2];
+ d = state[3];
+ e = state[4];
+
+ /* 4 rounds of 20 operations each. Loop unrolled. */
+ R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
+ R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
+ R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
+ R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
+ R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
+ R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
+ R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
+ R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
+ R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
+ R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
+ R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
+ R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
+ R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
+ R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
+ R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
+ R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
+ R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
+ R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
+ R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
+ R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
+
+ /* Add the working vars back into context.state[] */
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+ state[4] += e;
+
+ /* Wipe variables */
+ a = b = c = d = e = 0;
+}
+
+
+/* SHA1Init - Initialize new context */
+nserror
+NSSHA1_Init(struct nssha1_ctx **ret_ctx)
+{
+ struct nssha1_ctx *context;
+
+ context = calloc(1, sizeof(struct nssha1_ctx));
+ if (context == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ /* SHA1 initialization constants */
+ context->state[0] = 0x67452301;
+ context->state[1] = 0xEFCDAB89;
+ context->state[2] = 0x98BADCFE;
+ context->state[3] = 0x10325476;
+ context->state[4] = 0xC3D2E1F0;
+ context->count[0] = context->count[1] = 0;
+
+ *ret_ctx = context;
+
+ return NSERROR_OK;
+}
+
+
+/* Run your data through this. */
+nserror
+NSSHA1_Update(struct nssha1_ctx *context, const uint8_t *data, const size_t len)
+{
+ size_t i, j;
+
+ j = (context->count[0] >> 3) & 63;
+ if ((context->count[0] += len << 3) < (len << 3)) {
+ context->count[1]++;
+ }
+ context->count[1] += (len >> 29);
+ if ((j + len) > 63) {
+ memcpy(&context->buffer[j], data, (i = 64-j));
+ SHA1_Transform(context->state, context->buffer);
+ for ( ; i + 63 < len; i += 64) {
+ SHA1_Transform(context->state, data + i);
+ }
+ j = 0;
+ } else {
+ i = 0;
+ }
+ memcpy(&context->buffer[j], &data[i], len - i);
+
+ return NSERROR_OK;
+}
+
+
+/* Add padding and return the message digest. */
+nserror
+NSSHA1_Final(struct nssha1_ctx *context, uint8_t digest[NSSHA1_DIGEST_SIZE])
+{
+ uint32_t i;
+ uint8_t finalcount[8];
+
+ for (i = 0; i < 8; i++) {
+ finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
+ }
+ NSSHA1_Update(context, (uint8_t *)"\200", 1);
+ while ((context->count[0] & 504) != 448) {
+ NSSHA1_Update(context, (uint8_t *)"\0", 1);
+ }
+ NSSHA1_Update(context, finalcount, 8); /* Should cause a SHA1_Transform() */
+ for (i = 0; i < NSSHA1_DIGEST_SIZE; i++) {
+ digest[i] = (uint8_t)
+ ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
+ }
+
+ free(context);
+
+ return NSERROR_OK;
+}
+
+nserror
+NSSHA1(const uint8_t *data, const size_t len, uint8_t digest[NSSHA1_DIGEST_SIZE])
+{
+ struct nssha1_ctx *context;
+ nserror error;
+
+ error = NSSHA1_Init(&context);
+ if (error != NSERROR_OK)
+ return error;
+ NSSHA1_Update(context, data, len);
+ NSSHA1_Final(context, digest);
+
+ return NSERROR_OK;
+}
diff --git a/utils/sha1.h b/utils/sha1.h
new file mode 100644
index 0000000..e9f930c
--- /dev/null
+++ b/utils/sha1.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2014 vincent Sanders <vince(a)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
+ * interface for steve reid's public domain SHA-1 implementation.
+ *
+ * The exposed API makes only minimal changes to the public domain
+ * implementation, mainly adding a prefix so this implementation is
+ * not confused with any other similarly named version that might be
+ * linked.
+ */
+
+#ifndef _NETSURF_UTILS_SHA1_H_
+#define _NETSURF_UTILS_SHA1_H_
+
+struct nssha1_ctx;
+
+#define NSSHA1_DIGEST_SIZE 20
+
+/**
+ * Initialise a SHA1 context ready to take updates
+ *
+ * The context is allocated by this routine and destroyed by the finaliser.
+ *
+ * @param context receives an initialised SHA1 context.
+ * @return NSERROR_OK and \a context updated on sucess or
+ * NSERROR_NOMEM on memory exhaustion.
+ */
+nserror NSSHA1_Init(struct nssha1_ctx **context);
+
+/**
+ * Update an SHA1 context with additional data.
+ *
+ * @param context The context created by NSSHA1_Init
+ * @param data The data to hash.
+ * @param len The length of data to hash.
+ * @return NSERROR_OK
+ */
+nserror NSSHA1_Update(struct nssha1_ctx *context, const uint8_t *data, const size_t len);
+
+/**
+ * Finalise a SHA1 hash.
+ *
+ * Frees the context.
+ *
+ * @param context The context created by NSSHA1_Init
+ * @param digest a buffer to store the results in.
+ * @return NSERROR_OK
+ */
+nserror NSSHA1_Final(struct nssha1_ctx *context, uint8_t digest[NSSHA1_DIGEST_SIZE]);
+
+/**
+ * Generate SHA1 of some data
+ */
+nserror NSSHA1(const uint8_t *data, const size_t len, uint8_t digest[NSSHA1_DIGEST_SIZE]);
+
+#endif
-----------------------------------------------------------------------
Summary of changes:
content/llcache.c | 4 +-
gtk/llcache.c | 227 +++++++++++++++++++++++++++++++++++++++++++++-
test/Makefile | 13 +++-
test/sha1.c | 50 ++++++++++
utils/Makefile | 2 +-
utils/sha1.c | 264 +++++++++++++++++++++++++++++++++++++++++++++++++++++
utils/sha1.h | 72 +++++++++++++++
7 files changed, 626 insertions(+), 6 deletions(-)
create mode 100644 test/sha1.c
create mode 100644 utils/sha1.c
create mode 100644 utils/sha1.h
diff --git a/content/llcache.c b/content/llcache.c
index 87e1692..ed42895 100644
--- a/content/llcache.c
+++ b/content/llcache.c
@@ -1030,7 +1030,7 @@ llcache_persist_retrieve(llcache_object *object)
/* Source data for the object may be in the persiatant store */
return guit->llcache->retrieve(object->url,
- &object->cache,
+ NULL,
&object->source_data,
&object->source_len);
}
@@ -1102,7 +1102,7 @@ llcache_object_retrieve_from_cache(nsurl *url,
llcache_object *obj, *newest = NULL;
#ifdef LLCACHE_TRACE
- LOG(("Searching cache for %s (%x %s %p)",
+ LOG(("Searching cache for %s flags:%x referer:%s post:%p",
nsurl_access(url), flags, referer==NULL?"":nsurl_access(referer), post));
#endif
diff --git a/gtk/llcache.c b/gtk/llcache.c
index e6bf7aa..46945ac 100644
--- a/gtk/llcache.c
+++ b/gtk/llcache.c
@@ -20,24 +20,247 @@
* Low-level resource cache persistant storage implementation.
*/
+#include <string.h>
+
#include "utils/nsurl.h"
#include "utils/log.h"
+#include "utils/utils.h"
#include "desktop/gui.h"
#include "content/llcache_private.h"
#include "gtk/llcache.h"
+static uint8_t encoding_table[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
+ 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
+ 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
+ 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
+ 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
+ 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
+ 'w', 'x', 'y', 'z', '0', '1', '2', '3',
+ '4', '5', '6', '7', '8', '9', '-', '_'};
+static unsigned int mod_table[] = {0, 2, 1};
+
+
+static uint8_t *base64url_encode(const char *data,
+ size_t input_length,
+ size_t *output_length)
+{
+ uint8_t *encoded_data;
+ size_t i;
+ size_t j;
+
+ *output_length = 4 * ((input_length + 2) / 3);
+
+ encoded_data = malloc(*output_length + 1);
+ if (encoded_data == NULL) {
+ return NULL;
+ }
+
+ for (i = 0, j = 0; i < input_length;) {
+
+ uint32_t octet_a = i < input_length ? data[i++] : 0;
+ uint32_t octet_b = i < input_length ? data[i++] : 0;
+ uint32_t octet_c = i < input_length ? data[i++] : 0;
+
+ uint32_t triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c;
+
+ encoded_data[j++] = encoding_table[(triple >> 3 * 6) & 0x3F];
+ encoded_data[j++] = encoding_table[(triple >> 2 * 6) & 0x3F];
+ encoded_data[j++] = encoding_table[(triple >> 1 * 6) & 0x3F];
+ encoded_data[j++] = encoding_table[(triple >> 0 * 6) & 0x3F];
+ }
+
+ for (i = 0; i < mod_table[input_length % 3]; i++) {
+ encoded_data[*output_length - 1 - i] = 0;
+ (*output_length)--;
+ }
+
+ return encoded_data;
+}
+
static nserror
persist(nsurl *url, llcache_cache_control *cache_control, const uint8_t *data, const size_t datalen)
{
+ uint8_t *b64u;
+ size_t b64ulen;
+ char *fname;
+ FILE *file;
+
LOG(("Writing cache file for url:%s", nsurl_access(url)));
+ b64u = base64url_encode(nsurl_access(url), strlen(nsurl_access(url)), &b64ulen);
+
+ fname = malloc(SLEN("/tmp/ns/d/") + b64ulen + 1);
+ snprintf(fname, SLEN("/tmp/ns/d/") + b64ulen + 1, "/tmp/ns/d/%s", b64u);
+
+ LOG(("Opening data file %s", fname));
+ file = fopen(fname, "wb");
+
+ if (file == NULL) {
+ free(fname);
+ free(b64u);
+ return NSERROR_SAVE_FAILED;
+ }
+
+ LOG(("Writing %d bytes at %p to file", datalen, data));
+ if (fwrite(data, datalen, 1, file) != 1) {
+ LOG(("did not return 1"));
+ fclose(file);
+ free(fname);
+ free(b64u);
+ return NSERROR_SAVE_FAILED;
+ }
+
+ fclose(file);
+
+ snprintf(fname, SLEN("/tmp/ns/i/") + b64ulen + 1, "/tmp/ns/i/%s", b64u);
+
+ LOG(("Opening info file %s", fname));
+ file = fopen(fname, "wb");
+
+ if (file == NULL) {
+ free(fname);
+ free(b64u);
+ return NSERROR_SAVE_FAILED;
+ }
+
+ fprintf(file,
+ "req_time:%lld\n"
+ "res_time:%lld\n"
+ "fin_time:%lld\n"
+ "date:%lld\n"
+ "expires:%lld\n"
+ "age:%d\n"
+ "max_age:%d\n"
+ "no_cache:%d\n"
+ "etag:%s\n"
+ "last_modified:%lld\n",
+ (long long)cache_control->req_time,
+ (long long)cache_control->res_time,
+ (long long)cache_control->fin_time,
+ (long long)cache_control->date,
+ (long long)cache_control->expires,
+ cache_control->age,
+ cache_control->max_age,
+ cache_control->no_cache,
+ cache_control->etag == NULL?"":cache_control->etag,
+ (long long)cache_control->last_modified);
+
+ fclose(file);
+
+ free(fname);
+ free(b64u);
+
return NSERROR_OK;
}
static nserror
-retrieve(nsurl *url, llcache_cache_control *cache_control, uint8_t **data_out, size_t *datalen_out)
+retrieve(nsurl *url,
+ llcache_cache_control *cache_control,
+ uint8_t **data_out,
+ size_t *datalen_out)
{
- return NSERROR_NOT_FOUND;
+ uint8_t *b64u;
+ size_t b64ulen;
+ char *fname;
+ FILE *file;
+ uint8_t *data;
+ size_t datalen;
+
+
+ data = *data_out;
+ datalen = *datalen_out;
+
+ LOG(("retriving cache file for url:%s", nsurl_access(url)));
+ b64u = base64url_encode(nsurl_access(url),
+ strlen(nsurl_access(url)),
+ &b64ulen);
+
+ fname = malloc(SLEN("/tmp/ns/d/") + b64ulen + 1);
+
+ /* retrive cache control info if necessary */
+ if (cache_control != NULL) {
+ snprintf(fname, SLEN("/tmp/ns/i/") + b64ulen + 1, "/tmp/ns/i/%s", b64u);
+
+ LOG(("Opening info file %s", fname));
+ file = fopen(fname, "rb");
+
+ if (file == NULL) {
+ free(fname);
+ free(b64u);
+ return NSERROR_NOT_FOUND;
+ }
+
+ fscanf(file,
+ "req_time:%lld\n"
+ "res_time:%lld\n"
+ "fin_time:%lld\n"
+ "date:%lld\n"
+ "expires:%lld\n"
+ "age:%d\n"
+ "max_age:%d\n"
+ "no_cache:%d\n"
+ "etag:%ms\n"
+ "last_modified:%lld\n",
+ (long long*)&cache_control->req_time,
+ (long long*)&cache_control->res_time,
+ (long long*)&cache_control->fin_time,
+ (long long*)&cache_control->date,
+ (long long*)&cache_control->expires,
+ &cache_control->age,
+ &cache_control->max_age,
+ (int *)&cache_control->no_cache,
+ &cache_control->etag,
+ (long long*)&cache_control->last_modified);
+
+ fclose(file);
+
+ }
+
+ snprintf(fname, SLEN("/tmp/ns/d/") + b64ulen + 1, "/tmp/ns/d/%s", b64u);
+
+ LOG(("Opening file %s",fname));
+ file = fopen(fname, "rb");
+ free(fname);
+ if (file == NULL) {
+ free(b64u);
+ return NSERROR_NOT_FOUND;
+ }
+
+ /* need to deal with buffers */
+ if (data == NULL) {
+ if (datalen == 0) {
+ /* caller did not know the files length */
+ fseek(file, 0L, SEEK_END);
+ datalen = ftell(file);
+ fseek(file, 0L, SEEK_SET);
+ }
+
+ data = malloc(datalen);
+ if (data == NULL) {
+ fclose(file);
+ free(b64u);
+ return NSERROR_NOMEM;
+ }
+ }
+
+ LOG(("Reading %d bytes into %p from file", datalen, data));
+ if (fread(data, datalen, 1, file) != 1) {
+ LOG(("did not return 1"));
+ fclose(file);
+ free(b64u);
+ if ((*data_out) == NULL) {
+ free(data);
+ }
+ return NSERROR_NOT_FOUND;
+ }
+
+ fclose(file);
+ free(b64u);
+
+ *data_out = data;
+ *datalen_out = datalen;
+
+ return NSERROR_OK;
}
static struct gui_llcache_table llcache_table = {
diff --git a/test/Makefile b/test/Makefile
index acf9d4e..825b582 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -2,6 +2,7 @@ CFLAGS := -std=c99 -g -O0 -D_BSD_SOURCE -D_POSIX_C_SOURCE -I.. \
$(shell pkg-config --cflags libcurl)
LDFLAGS := $(shell pkg-config --libs libcurl) -lz
+
llcache_CFLAGS := $(shell pkg-config --cflags libparserutils libwapcaplet libdom) -O2
llcache_LDFLAGS := $(shell pkg-config --libs libparserutils libwapcaplet libdom)
@@ -14,6 +15,7 @@ llcache_SRCS := content/fetch.c content/fetchers/curl.c \
utils/log.c utils/nsurl.c utils/messages.c utils/url.c \
utils/useragent.c utils/utils.c test/llcache.c
+
urldbtest_SRCS := content/urldb.c utils/url.c utils/utils.c utils/log.c \
desktop/options.c utils/messages.c utils/hashtable.c \
utils/filename.c utils/nsurl.c utils/corestrings.c \
@@ -22,16 +24,22 @@ urldbtest_SRCS := content/urldb.c utils/url.c utils/utils.c utils/log.c \
urldbtest_CFLAGS := $(shell pkg-config --cflags libwapcaplet libdom) -O2
urldbtest_LDFLAGS := $(shell pkg-config --libs libwapcaplet libdom)
+
nsurl_SRCS := utils/corestrings.c utils/log.c utils/nsurl.c test/nsurl.c
nsurl_CFLAGS := $(shell pkg-config --cflags libwapcaplet libdom)
nsurl_LDFLAGS := $(shell pkg-config --libs libwapcaplet libdom)
+
nsoption_SRCS := utils/log.c utils/nsoption.c test/nsoption.c
nsoption_CFLAGS := -Dnsgtk
+sha1_SRCS := utils/sha1.c utils/log.c test/sha1.c
+sha1_CFLAGS :=
+sha1_LDFLAGS :=
+
.PHONY: all
-all: llcache urldbtest nsurl nsoption
+all: llcache urldbtest nsurl nsoption sha1
llcache: $(addprefix ../,$(llcache_SRCS))
$(CC) $(CFLAGS) $(llcache_CFLAGS) $^ -o $@ $(LDFLAGS) $(llcache_LDFLAGS)
@@ -45,6 +53,9 @@ nsurl: $(addprefix ../,$(nsurl_SRCS))
nsoption: $(addprefix ../,$(nsoption_SRCS))
$(CC) $(CFLAGS) $(nsoption_CFLAGS) $^ -o $@ $(LDFLAGS) $(nsoption_LDFLAGS)
+sha1: $(addprefix ../,$(sha1_SRCS))
+ $(CC) $(CFLAGS) $(sha1_CFLAGS) $^ -o $@ $(LDFLAGS) $(sha1_LDFLAGS)
+
.PHONY: clean
clean:
diff --git a/test/sha1.c b/test/sha1.c
new file mode 100644
index 0000000..abfc25b
--- /dev/null
+++ b/test/sha1.c
@@ -0,0 +1,50 @@
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "utils/log.h"
+#include "utils/sha1.h"
+
+
+struct {
+ const char *text;
+ const uint8_t hash[NSSHA1_DIGEST_SIZE];
+} checks[] = {
+ {
+ "The quick brown fox jumps over the lazy dog",
+ { 0x2f, 0xd4, 0xe1, 0xc6, 0x7a, 0x2d, 0x28, 0xfc, 0xed, 0x84,
+ 0x9e, 0xe1, 0xbb, 0x76, 0xe7, 0x39, 0x1b, 0x93, 0xeb, 0x12 }
+ },
+ {
+ "The quick brown fox jumps over the lazy cog",
+ { 0xde, 0x9f, 0x2c, 0x7f, 0xd2, 0x5e, 0x1b, 0x3a, 0xfa, 0xd3,
+ 0xe8, 0x5a, 0x0b, 0xd1, 0x7d, 0x9b, 0x10, 0x0d, 0xb4, 0xb3 }
+ },
+ {
+ "",
+ { 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55,
+ 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09 }
+ },
+ { NULL, {0} },
+};
+
+int main(int argc, char **argv)
+{
+ uint8_t res[NSSHA1_DIGEST_SIZE];
+ int chk_loop = 0;
+
+ verbose_log = true;
+
+ while (checks[chk_loop].text != NULL) {
+
+ NSSHA1(checks[chk_loop].text, strlen(checks[chk_loop].text), res);
+ if (memcmp(res, &checks[chk_loop].hash, NSSHA1_DIGEST_SIZE) == 0) {
+ LOG(("Test %d: PASS", chk_loop));
+ } else {
+ LOG(("Test %d: FAIL", chk_loop));
+ }
+ chk_loop++;
+ }
+}
diff --git a/utils/Makefile b/utils/Makefile
index aef5799..48bba98 100644
--- a/utils/Makefile
+++ b/utils/Makefile
@@ -2,6 +2,6 @@
S_UTILS := base64.c corestrings.c filename.c filepath.c hashtable.c \
libdom.c locale.c log.c messages.c nsurl.c talloc.c url.c \
- utf8.c utils.c useragent.c bloom.c nsoption.c
+ utf8.c utils.c useragent.c bloom.c nsoption.c sha1.c
S_UTILS := $(addprefix utils/,$(S_UTILS))
diff --git a/utils/sha1.c b/utils/sha1.c
new file mode 100644
index 0000000..882f2b9
--- /dev/null
+++ b/utils/sha1.c
@@ -0,0 +1,264 @@
+/*
+ SHA-1 in C
+ By Steve Reid <sreid(a)sea-to-sky.net>
+ 100% Public Domain
+
+ -----------------
+ Modified 7/98
+ By James H. Brown <jbrown(a)burgoyne.com>
+ Still 100% Public Domain
+
+ Corrected a problem which generated improper hash values on 16 bit machines
+ Routine SHA1Update changed from
+ void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int
+ len)
+ to
+ void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned
+ long len)
+
+ The 'len' parameter was declared an int which works fine on 32 bit machines.
+ However, on 16 bit machines an int is too small for the shifts being done
+ against
+ it. This caused the hash function to generate incorrect values if len was
+ greater than 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update().
+
+ Since the file IO in main() reads 16K at a time, any file 8K or larger would
+ be guaranteed to generate the wrong hash (e.g. Test Vector #3, a million
+ "a"s).
+
+ I also changed the declaration of variables i & j in SHA1Update to
+ unsigned long from unsigned int for the same reason.
+
+ These changes should make no difference to any 32 bit implementations since
+ an
+ int and a long are the same size in those environments.
+
+ --
+ I also corrected a few compiler warnings generated by Borland C.
+ 1. Added #include <process.h> for exit() prototype
+ 2. Removed unused variable 'j' in SHA1Final
+ 3. Changed exit(0) to return(0) at end of main.
+
+ ALL changes I made can be located by searching for comments containing 'JHB'
+ -----------------
+ Modified 8/98
+ By Steve Reid <sreid(a)sea-to-sky.net>
+ Still 100% public domain
+
+ 1- Removed #include <process.h> and used return() instead of exit()
+ 2- Fixed overwriting of finalcount in SHA1Final() (discovered by Chris Hall)
+ 3- Changed email address from steve(a)edmweb.com to sreid(a)sea-to-sky.net
+
+ -----------------
+ Modified 4/01
+ By Saul Kravitz <Saul.Kravitz(a)celera.com>
+ Still 100% PD
+ Modified to run on Compaq Alpha hardware.
+
+ -----------------
+ Modified 07/2002
+ By Ralph Giles <giles(a)ghostscript.com>
+ Still 100% public domain
+ modified for use with stdint types, autoconf
+ code cleanup, removed attribution comments
+ switched SHA1Final() argument order for consistency
+ use SHA1_ prefix for public api
+ move public api to sha1.h
+*/
+
+/** \file
+ * steve reid's public domain SHA-1 implementation.
+ *
+ * Modified by Vincent Sanders <vince(a)netsurf-browser.org>
+ *
+ * This is a sligly modified version of this public domain
+ * implementation changes were made to:
+ * - introduce suitable prefixes to avoid namespace conflicts.
+ * - make the context structure self contained.
+ * - make the function signatures more suitable for this use case
+ */
+
+
+/* see https://en.wikipedia.org/wiki/SHA-1 */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "utils/errors.h"
+#include "utils/sha1.h"
+
+struct nssha1_ctx {
+ uint32_t state[5];
+ uint32_t count[2];
+ uint8_t buffer[64];
+} ;
+
+#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
+
+/* blk0() and blk() perform the initial expand. */
+/* I got the idea of expanding during the round function from SSLeay */
+/* FIXME: can we do this in an endian-proof way? */
+#ifdef WORDS_BIGENDIAN
+#define blk0(i) block->l[i]
+#else
+#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
+ |(rol(block->l[i],8)&0x00FF00FF))
+#endif
+#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
+ ^block->l[(i+2)&15]^block->l[i&15],1))
+
+/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
+#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
+#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
+#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
+
+
+
+/* Hash a single 512-bit block. This is the core of the algorithm. */
+static void SHA1_Transform(uint32_t state[5], const uint8_t buffer[64])
+{
+ uint32_t a, b, c, d, e;
+ typedef union {
+ uint8_t c[64];
+ uint32_t l[16];
+ } CHAR64LONG16;
+ CHAR64LONG16* block;
+
+ block = (CHAR64LONG16*)buffer;
+
+ /* Copy context->state[] to working vars */
+ a = state[0];
+ b = state[1];
+ c = state[2];
+ d = state[3];
+ e = state[4];
+
+ /* 4 rounds of 20 operations each. Loop unrolled. */
+ R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
+ R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
+ R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
+ R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
+ R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
+ R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
+ R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
+ R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
+ R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
+ R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
+ R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
+ R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
+ R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
+ R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
+ R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
+ R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
+ R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
+ R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
+ R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
+ R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
+
+ /* Add the working vars back into context.state[] */
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+ state[4] += e;
+
+ /* Wipe variables */
+ a = b = c = d = e = 0;
+}
+
+
+/* SHA1Init - Initialize new context */
+nserror
+NSSHA1_Init(struct nssha1_ctx **ret_ctx)
+{
+ struct nssha1_ctx *context;
+
+ context = calloc(1, sizeof(struct nssha1_ctx));
+ if (context == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ /* SHA1 initialization constants */
+ context->state[0] = 0x67452301;
+ context->state[1] = 0xEFCDAB89;
+ context->state[2] = 0x98BADCFE;
+ context->state[3] = 0x10325476;
+ context->state[4] = 0xC3D2E1F0;
+ context->count[0] = context->count[1] = 0;
+
+ *ret_ctx = context;
+
+ return NSERROR_OK;
+}
+
+
+/* Run your data through this. */
+nserror
+NSSHA1_Update(struct nssha1_ctx *context, const uint8_t *data, const size_t len)
+{
+ size_t i, j;
+
+ j = (context->count[0] >> 3) & 63;
+ if ((context->count[0] += len << 3) < (len << 3)) {
+ context->count[1]++;
+ }
+ context->count[1] += (len >> 29);
+ if ((j + len) > 63) {
+ memcpy(&context->buffer[j], data, (i = 64-j));
+ SHA1_Transform(context->state, context->buffer);
+ for ( ; i + 63 < len; i += 64) {
+ SHA1_Transform(context->state, data + i);
+ }
+ j = 0;
+ } else {
+ i = 0;
+ }
+ memcpy(&context->buffer[j], &data[i], len - i);
+
+ return NSERROR_OK;
+}
+
+
+/* Add padding and return the message digest. */
+nserror
+NSSHA1_Final(struct nssha1_ctx *context, uint8_t digest[NSSHA1_DIGEST_SIZE])
+{
+ uint32_t i;
+ uint8_t finalcount[8];
+
+ for (i = 0; i < 8; i++) {
+ finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
+ }
+ NSSHA1_Update(context, (uint8_t *)"\200", 1);
+ while ((context->count[0] & 504) != 448) {
+ NSSHA1_Update(context, (uint8_t *)"\0", 1);
+ }
+ NSSHA1_Update(context, finalcount, 8); /* Should cause a SHA1_Transform() */
+ for (i = 0; i < NSSHA1_DIGEST_SIZE; i++) {
+ digest[i] = (uint8_t)
+ ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
+ }
+
+ free(context);
+
+ return NSERROR_OK;
+}
+
+nserror
+NSSHA1(const uint8_t *data, const size_t len, uint8_t digest[NSSHA1_DIGEST_SIZE])
+{
+ struct nssha1_ctx *context;
+ nserror error;
+
+ error = NSSHA1_Init(&context);
+ if (error != NSERROR_OK)
+ return error;
+ NSSHA1_Update(context, data, len);
+ NSSHA1_Final(context, digest);
+
+ return NSERROR_OK;
+}
diff --git a/utils/sha1.h b/utils/sha1.h
new file mode 100644
index 0000000..e9f930c
--- /dev/null
+++ b/utils/sha1.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2014 vincent Sanders <vince(a)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
+ * interface for steve reid's public domain SHA-1 implementation.
+ *
+ * The exposed API makes only minimal changes to the public domain
+ * implementation, mainly adding a prefix so this implementation is
+ * not confused with any other similarly named version that might be
+ * linked.
+ */
+
+#ifndef _NETSURF_UTILS_SHA1_H_
+#define _NETSURF_UTILS_SHA1_H_
+
+struct nssha1_ctx;
+
+#define NSSHA1_DIGEST_SIZE 20
+
+/**
+ * Initialise a SHA1 context ready to take updates
+ *
+ * The context is allocated by this routine and destroyed by the finaliser.
+ *
+ * @param context receives an initialised SHA1 context.
+ * @return NSERROR_OK and \a context updated on sucess or
+ * NSERROR_NOMEM on memory exhaustion.
+ */
+nserror NSSHA1_Init(struct nssha1_ctx **context);
+
+/**
+ * Update an SHA1 context with additional data.
+ *
+ * @param context The context created by NSSHA1_Init
+ * @param data The data to hash.
+ * @param len The length of data to hash.
+ * @return NSERROR_OK
+ */
+nserror NSSHA1_Update(struct nssha1_ctx *context, const uint8_t *data, const size_t len);
+
+/**
+ * Finalise a SHA1 hash.
+ *
+ * Frees the context.
+ *
+ * @param context The context created by NSSHA1_Init
+ * @param digest a buffer to store the results in.
+ * @return NSERROR_OK
+ */
+nserror NSSHA1_Final(struct nssha1_ctx *context, uint8_t digest[NSSHA1_DIGEST_SIZE]);
+
+/**
+ * Generate SHA1 of some data
+ */
+nserror NSSHA1(const uint8_t *data, const size_t len, uint8_t digest[NSSHA1_DIGEST_SIZE]);
+
+#endif
--
NetSurf Browser