Revision: 10275 http://pure-data.svn.sourceforge.net/pure-data/?rev=10275&view=rev Author: zmoelnig Date: 2008-09-03 09:34:50 +0000 (Wed, 03 Sep 2008)
Log Message: ----------- added stephen sinclairs "urloader"
Added Paths: ----------- trunk/externals/loaders/urloader/ trunk/externals/loaders/urloader/Makefile trunk/externals/loaders/urloader/another.pd trunk/externals/loaders/urloader/baseurl.c trunk/externals/loaders/urloader/baseurl.h trunk/externals/loaders/urloader/md5.c trunk/externals/loaders/urloader/md5.h trunk/externals/loaders/urloader/pd.index trunk/externals/loaders/urloader/test.pd trunk/externals/loaders/urloader/unknown.pd trunk/externals/loaders/urloader/urlloader.c
Added: trunk/externals/loaders/urloader/Makefile =================================================================== --- trunk/externals/loaders/urloader/Makefile (rev 0) +++ trunk/externals/loaders/urloader/Makefile 2008-09-03 09:34:50 UTC (rev 10275) @@ -0,0 +1,167 @@ +# Makefile +# based on hexloader Makefile (c) 2007 IOhannes m zm\xF6lnig + +# path to pd +## change this according to your setup! +PDROOT=../../../pd + +# here we find the sources of pd (and evtl. the pd.lib) +PDSRCDIR=$(PDROOT)/src +PDLIBDIR=$(PDROOT)/bin + +# this is the filename-extension +# people have to specify it at the cmdline: eg "make pd_linux" +EXTENSION=$(MAKECMDGOALS) + + +DEFINES=-DPD + +# if no filename-extension is supplied by the user +# try to guess one, based on what "uname" tells us +UNAME := $(shell uname -s) +ifeq ($(UNAME),Linux) + DEFAULTEXTENSION= pd_linux + DEFINES+=-DDL_OPEN +else + ifeq ($(UNAME),Darwin) + DEFAULTEXTENSION= pd_darwin + DEFINES+=-DDL_OPEN + else + ifeq (MINGW,$(findstring MINGW,$(UNAME))) + DEFAULTEXTENSION=pd_nt + else + ifeq ($(UNAME),IRIX) + UNAMEV := $(shell uname -R) + ifeq (6.,$(findstring 6.,$(UNAMEV))) + DEFAULTEXTENSION= pd_irix6 + DEFINES+=-DDL_OPEN + else + DEFAULTEXTENSION= pd_irix5 + DEFINES+=-DDL_OPEN + endif + else + DEFAULTEXTENSION=help + endif + endif + endif +endif + +# if no extension is given, call "make" again with a guessed extension +auto: + make $(DEFAULTEXTENSION) + +# just a stupid fallback +help: + @echo "choose one command: make pd_linux (linux), make pd_darwin (osX), make pd_irix5 (IRIX5), make pd_irix6 (IRIX6), make dll (MSVC), make pd_nt (MinWG)" + +# delete old build files +clean: + -rm -f *.dll *.pd_* *.o *.obj *~ + +# we want to compile all C-files we find in the current directory +SOURCES=$(sort $(filter %.c, $(wildcard *.c))) +# some C-files maps will become an external with the given filename-extension +TARGETS=urlloader.pd_linux baseurl.pd_linux + + +# ----------------------- Linux ----------------------- + +pd_linux: $(TARGETS) + +LINUXCFLAGS = $(DEFINES) -funroll-loops -fomit-frame-pointer -fPIC \ + -Wall -W -Wshadow -Wstrict-prototypes -Werror \ + -Wno-unused -Wno-parentheses -Wno-switch + +ifeq ($(DEBUG),1) +LINUXCFLAGS += -ggdb +else +LINUXCFLAGS += -O2 +endif + +LINUXLDFLAGS = -export_dynamic -shared -lc -lm +LINUXLIBS = -lcurl + +LINUXINCLUDE = -I$(PDSRCDIR) + +%.pd_linux: %.c + $(CC) $(LINUXLDFLAGS) $(LINUXCFLAGS) $(LINUXINCLUDE) -o $*.pd_linux $*.c $(LINUXLIBS) + strip --strip-unneeded $*.pd_linux + + + +# ----------------------- Mac OSX ----------------------- + +pd_darwin: $(TARGETS) + +DARWINCFLAGS = $(DEFINES) -O2 -Wall -W -Wshadow -Wstrict-prototypes \ + -Wno-unused -Wno-parentheses -Wno-switch + +DARWININCLUDE = -I$(PDSRCDIR) + +DARWINLDFLAGS = -bundle -undefined suppress -flat_namespace + +%.pd_darwin: %.c + $(CC) $(DARWINCFLAGS) $(DARWININCLUDE) $(DARWINLDFLAGS) -o $*.pd_darwin $*.c + + +# ----------------------- IRIX 5.x ----------------------- +pd_irix5: $(TARGETS) + +SGICFLAGS5 = -o32 $(DEFINES) -DSGI -O2 + +SGIINCLUDE = -I$(PDSRCDIR) + +SGILDFLAGS = -elf -shared -rdata_shared + +%.pd_irix5: %.c + $(CC) $(SGICFLAGS5) $(SGIINCLUDE) -o $*.o -c $*.c + $(LD) $(SGILDFLAGS) -o $*.pd_irix5 $*.o + rm $*.o + + +# ----------------------- IRIX 6.x ----------------------- +pd_irix6: $(TARGETS) + +SGICFLAGS6 = $(DEFINES) -DSGI -n32 \ + -OPT:roundoff=3 -OPT:IEEE_arithmetic=3 -OPT:cray_ivdep=true \ + -Ofast=ip32 + +%.pd_irix6: %.c + $(CC) $(SGICFLAGS6) $(SGIINCLUDE) -o $*.o -c $*.c + $(LD) $(SGILDFLAGS) -o $*.pd_irix6 $*.o + rm $*.o + + +# ----------------------- NT ----------------------- +dll: $(TARGETS) + +PDNTCFLAGS = /W3 /WX /DPD /DNT /D__WIN32__ /DMSW /nologo + +VC="C:\Programme\Microsoft Visual Studio\Vc98" + +PDNTINCLUDE = /I. /I$(PDROOT)\tcl\include /I$(PDSRCDIR)\src /I$(VC)\include + +PDNTLDIR = $(VC)\lib + +PDNTLIB = $(PDNTLDIR)\libc.lib \ + $(PDNTLDIR)\oldnames.lib \ + $(PDNTLDIR)\kernel32.lib \ + $(PDLIBDIR)\pd.lib + +%.dll: %.c + cl $(PDNTCFLAGS) $(PDNTINCLUDE) /c $*.c + link /dll /export:$*_setup $*.obj $(PDNTLIB) + + +pd_nt: $(TARGETS) + +MINGWCFLAGS = $(DEFINES) -O2 -funroll-loops -fomit-frame-pointer \ + -Wall -W -Wshadow -Wstrict-prototypes -Werror \ + -Wno-unused -Wno-parentheses -Wno-switch -mms-bitfields + +MINGWLDFLAGS = -export_dynamic -shared -lm -lkernel32 -lcoldname -lcrtdll -lpd -L$(PDLIBDIR) + +MINGWINCLUDE = -I$(PDSRCDIR) + +%.pd_nt: %.c + $(CC) $(MINGWLDFLAGS) $(MINGWCFLAGS) $(MINGWINCLUDE) -o $*.dll $*.c
Added: trunk/externals/loaders/urloader/another.pd =================================================================== --- trunk/externals/loaders/urloader/another.pd (rev 0) +++ trunk/externals/loaders/urloader/another.pd 2008-09-03 09:34:50 UTC (rev 10275) @@ -0,0 +1,7 @@ +#N canvas 1 44 450 300 10; +#X obj 35 50 inlet; +#X obj 35 96 outlet; +#X obj 35 73 * 2; +#X text 141 50 Another patch on the web.; +#X connect 0 0 2 0; +#X connect 2 0 1 0;
Added: trunk/externals/loaders/urloader/baseurl.c =================================================================== --- trunk/externals/loaders/urloader/baseurl.c (rev 0) +++ trunk/externals/loaders/urloader/baseurl.c 2008-09-03 09:34:50 UTC (rev 10275) @@ -0,0 +1,58 @@ +/* Copyright (c) 2008 Steve Sinclair radarsat1@gmail.com + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," that comes with Pd. + */ + +/* + * This code provides a canvas with a base URL to inform the baseurl + * where to look. + */ + + +#ifdef __WIN32__ +# define MSW +#endif + +#include "m_pd.h" + +#if (PD_MINOR_VERSION >= 40) + +#include "s_stuff.h" +#include "g_canvas.h" +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +#include "baseurl.h" + +typedef void (*t_baseurl_setup)(void); + +/* definitions taken from s_loader.c */ +typedef int (*loader_t)(t_canvas *canvas, char *classname); +void sys_register_loader(loader_t loader); +void class_set_extern_dir(t_symbol *s); + +/* ==================================================== */ + +static t_class *baseurl_class; + +static char *version = "0.0.1"; + +#endif /* PD_MINOR_VERSION>=40 */ + +static void*baseurl_new(t_symbol *s, int argc, t_atom *argv) +{ + t_baseurl *x = (t_baseurl*)pd_new(baseurl_class); + SETSYMBOL(&x->url, argv[0].a_w.w_symbol); + return (x); +} + +void baseurl_setup(void) +{ + post("baseurl %s",version); + post("\twritten by Steve Sinclair"); + post("\tcompiled on "__DATE__" at "__TIME__ " "); + post("\tcompiled against Pd version %d.%d.%d.%s", PD_MAJOR_VERSION, PD_MINOR_VERSION, PD_BUGFIX_VERSION, PD_TEST_VERSION); + + baseurl_class = class_new(gensym("baseurl"), (t_newmethod)baseurl_new, 0, sizeof(t_baseurl), CLASS_NOINLET, A_GIMME, 0); +}
Added: trunk/externals/loaders/urloader/baseurl.h =================================================================== --- trunk/externals/loaders/urloader/baseurl.h (rev 0) +++ trunk/externals/loaders/urloader/baseurl.h 2008-09-03 09:34:50 UTC (rev 10275) @@ -0,0 +1,15 @@ +/* Copyright (c) 2008 Steve Sinclair radarsat1@gmail.com + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," that comes with Pd. + */ + +#ifndef BASEURL_H +#define BASEURL_H + +typedef struct _baseurl +{ + t_object x_obj; + t_atom url; +} t_baseurl; + +#endif // BASEURL_H
Added: trunk/externals/loaders/urloader/md5.c =================================================================== --- trunk/externals/loaders/urloader/md5.c (rev 0) +++ trunk/externals/loaders/urloader/md5.c 2008-09-03 09:34:50 UTC (rev 10275) @@ -0,0 +1,452 @@ +/* md5.c - Functions to compute MD5 message digest of files or memory blocks + according to the definition of MD5 in RFC 1321 from April 1992. + Copyright (C) 1995, 1996, 2001, 2003, 2004, 2005 Free Software Foundation, Inc. + NOTE: The canonical source of this file is maintained with the GNU C + Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu. + + 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 Ulrich Drepper drepper@gnu.ai.mit.edu, 1995. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "md5.h" + +#include <stddef.h> +#include <string.h> + +#if USE_UNLOCKED_IO +# include "unlocked-io.h" +#endif + +#ifdef _LIBC +# include <endian.h> +# if __BYTE_ORDER == __BIG_ENDIAN +# define WORDS_BIGENDIAN 1 +# endif +/* We need to keep the namespace clean so define the MD5 function + protected using leading __ . */ +# define md5_init_ctx __md5_init_ctx +# define md5_process_block __md5_process_block +# define md5_process_bytes __md5_process_bytes +# define md5_finish_ctx __md5_finish_ctx +# define md5_read_ctx __md5_read_ctx +# define md5_stream __md5_stream +# define md5_buffer __md5_buffer +#endif + +#ifdef WORDS_BIGENDIAN +# define SWAP(n) \ + (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24)) +#else +# define SWAP(n) (n) +#endif + +#define BLOCKSIZE 4096 +#if BLOCKSIZE % 64 != 0 +# error "invalid BLOCKSIZE" +#endif + +/* This array contains the bytes used to pad the buffer to the next + 64-byte boundary. (RFC 1321, 3.1: Step 1) */ +static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ }; + + +/* Initialize structure containing state of computation. + (RFC 1321, 3.3: Step 3) */ +void +md5_init_ctx (struct md5_ctx *ctx) +{ + ctx->A = 0x67452301; + ctx->B = 0xefcdab89; + ctx->C = 0x98badcfe; + ctx->D = 0x10325476; + + ctx->total[0] = ctx->total[1] = 0; + ctx->buflen = 0; +} + +/* Put result from CTX in first 16 bytes following RESBUF. The result + must be in little endian byte order. + + IMPORTANT: On some systems it is required that RESBUF is correctly + aligned for a 32 bits value. */ +void * +md5_read_ctx (const struct md5_ctx *ctx, void *resbuf) +{ + ((md5_uint32 *) resbuf)[0] = SWAP (ctx->A); + ((md5_uint32 *) resbuf)[1] = SWAP (ctx->B); + ((md5_uint32 *) resbuf)[2] = SWAP (ctx->C); + ((md5_uint32 *) resbuf)[3] = SWAP (ctx->D); + + return resbuf; +} + +/* Process the remaining bytes in the internal buffer and the usual + prolog according to the standard and write the result to RESBUF. + + IMPORTANT: On some systems it is required that RESBUF is correctly + aligned for a 32 bits value. */ +void * +md5_finish_ctx (struct md5_ctx *ctx, void *resbuf) +{ + /* Take yet unprocessed bytes into account. */ + md5_uint32 bytes = ctx->buflen; + size_t pad; + + /* Now count remaining bytes. */ + ctx->total[0] += bytes; + if (ctx->total[0] < bytes) + ++ctx->total[1]; + + pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes; + memcpy (&ctx->buffer[bytes], fillbuf, pad); + + /* Put the 64-bit file length in *bits* at the end of the buffer. */ + *(md5_uint32 *) &ctx->buffer[bytes + pad] = SWAP (ctx->total[0] << 3); + *(md5_uint32 *) &ctx->buffer[bytes + pad + 4] = SWAP ((ctx->total[1] << 3) | + (ctx->total[0] >> 29)); + + /* Process last bytes. */ + md5_process_block (ctx->buffer, bytes + pad + 8, ctx); + + return md5_read_ctx (ctx, resbuf); +} + +/* Compute MD5 message digest for bytes read from STREAM. The + resulting message digest number will be written into the 16 bytes + beginning at RESBLOCK. */ +int +md5_stream (FILE *stream, void *resblock) +{ + struct md5_ctx ctx; + char buffer[BLOCKSIZE + 72]; + size_t sum; + + /* Initialize the computation context. */ + md5_init_ctx (&ctx); + + /* Iterate over full file contents. */ + while (1) + { + /* We read the file in blocks of BLOCKSIZE bytes. One call of the + computation function processes the whole buffer so that with the + next round of the loop another block can be read. */ + size_t n; + sum = 0; + + /* Read block. Take care for partial reads. */ + while (1) + { + n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream); + + sum += n; + + if (sum == BLOCKSIZE) + break; + + if (n == 0) + { + /* Check for the error flag IFF N == 0, so that we don't + exit the loop after a partial read due to e.g., EAGAIN + or EWOULDBLOCK. */ + if (ferror (stream)) + return 1; + goto process_partial_block; + } + + /* We've read at least one byte, so ignore errors. But always + check for EOF, since feof may be true even though N > 0. + Otherwise, we could end up calling fread after EOF. */ + if (feof (stream)) + goto process_partial_block; + } + + /* Process buffer with BLOCKSIZE bytes. Note that + BLOCKSIZE % 64 == 0 + */ + md5_process_block (buffer, BLOCKSIZE, &ctx); + } + + process_partial_block:; + + /* Process any remaining bytes. */ + if (sum > 0) + md5_process_bytes (buffer, sum, &ctx); + + /* Construct result in desired memory. */ + md5_finish_ctx (&ctx, resblock); + return 0; +} + +/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The + result is always in little endian byte order, so that a byte-wise + output yields to the wanted ASCII representation of the message + digest. */ +void * +md5_buffer (const char *buffer, size_t len, void *resblock) +{ + struct md5_ctx ctx; + + /* Initialize the computation context. */ + md5_init_ctx (&ctx); + + /* Process whole buffer but last len % 64 bytes. */ + md5_process_bytes (buffer, len, &ctx); + + /* Put result in desired memory area. */ + return md5_finish_ctx (&ctx, resblock); +} + + +void +md5_process_bytes (const void *buffer, size_t len, struct md5_ctx *ctx) +{ + /* When we already have some bits in our internal buffer concatenate + both inputs first. */ + if (ctx->buflen != 0) + { + size_t left_over = ctx->buflen; + size_t add = 128 - left_over > len ? len : 128 - left_over; + + memcpy (&ctx->buffer[left_over], buffer, add); + ctx->buflen += add; + + if (ctx->buflen > 64) + { + md5_process_block (ctx->buffer, ctx->buflen & ~63, ctx); + + ctx->buflen &= 63; + /* The regions in the following copy operation cannot overlap. */ + memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63], + ctx->buflen); + } + + buffer = (const char *) buffer + add; + len -= add; + } + + /* Process available complete blocks. */ + if (len >= 64) + { +#if !_STRING_ARCH_unaligned +# define alignof(type) offsetof (struct { char c; type x; }, x) +# define UNALIGNED_P(p) (((size_t) p) % alignof (md5_uint32) != 0) + if (UNALIGNED_P (buffer)) + while (len > 64) + { + md5_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx); + buffer = (const char *) buffer + 64; + len -= 64; + } + else +#endif + { + md5_process_block (buffer, len & ~63, ctx); + buffer = (const char *) buffer + (len & ~63); + len &= 63; + } + } + + /* Move remaining bytes in internal buffer. */ + if (len > 0) + { + size_t left_over = ctx->buflen; + + memcpy (&ctx->buffer[left_over], buffer, len); + left_over += len; + if (left_over >= 64) + { + md5_process_block (ctx->buffer, 64, ctx); + left_over -= 64; + memcpy (ctx->buffer, &ctx->buffer[64], left_over); + } + ctx->buflen = left_over; + } +} + + +/* These are the four functions used in the four steps of the MD5 algorithm + and defined in the RFC 1321. The first function is a little bit optimized + (as found in Colin Plumbs public domain implementation). */ +/* #define FF(b, c, d) ((b & c) | (~b & d)) */ +#define FF(b, c, d) (d ^ (b & (c ^ d))) +#define FG(b, c, d) FF (d, b, c) +#define FH(b, c, d) (b ^ c ^ d) +#define FI(b, c, d) (c ^ (b | ~d)) + +/* Process LEN bytes of BUFFER, accumulating context into CTX. + It is assumed that LEN % 64 == 0. */ + +void +md5_process_block (const void *buffer, size_t len, struct md5_ctx *ctx) +{ + md5_uint32 correct_words[16]; + const md5_uint32 *words = buffer; + size_t nwords = len / sizeof (md5_uint32); + const md5_uint32 *endp = words + nwords; + md5_uint32 A = ctx->A; + md5_uint32 B = ctx->B; + md5_uint32 C = ctx->C; + md5_uint32 D = ctx->D; + + /* First increment the byte count. RFC 1321 specifies the possible + length of the file up to 2^64 bits. Here we only compute the + number of bytes. Do a double word increment. */ + ctx->total[0] += len; + if (ctx->total[0] < len) + ++ctx->total[1]; + + /* Process all bytes in the buffer with 64 bytes in each round of + the loop. */ + while (words < endp) + { + md5_uint32 *cwp = correct_words; + md5_uint32 A_save = A; + md5_uint32 B_save = B; + md5_uint32 C_save = C; + md5_uint32 D_save = D; + + /* First round: using the given function, the context and a constant + the next context is computed. Because the algorithms processing + unit is a 32-bit word and it is determined to work on words in + little endian byte order we perhaps have to change the byte order + before the computation. To reduce the work for the next steps + we store the swapped words in the array CORRECT_WORDS. */ + +#define OP(a, b, c, d, s, T) \ + do \ + { \ + a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T; \ + ++words; \ + CYCLIC (a, s); \ + a += b; \ + } \ + while (0) + + /* It is unfortunate that C does not provide an operator for + cyclic rotation. Hope the C compiler is smart enough. */ +#define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s))) + + /* Before we start, one word to the strange constants. + They are defined in RFC 1321 as + + T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64 + + Here is an equivalent invocation using Perl: + + perl -e 'foreach(1..64){printf "0x%08x\n", int (4294967296 * abs (sin $_))}' + */ + + /* Round 1. */ + OP (A, B, C, D, 7, 0xd76aa478); + OP (D, A, B, C, 12, 0xe8c7b756); + OP (C, D, A, B, 17, 0x242070db); + OP (B, C, D, A, 22, 0xc1bdceee); + OP (A, B, C, D, 7, 0xf57c0faf); + OP (D, A, B, C, 12, 0x4787c62a); + OP (C, D, A, B, 17, 0xa8304613); + OP (B, C, D, A, 22, 0xfd469501); + OP (A, B, C, D, 7, 0x698098d8); + OP (D, A, B, C, 12, 0x8b44f7af); + OP (C, D, A, B, 17, 0xffff5bb1); + OP (B, C, D, A, 22, 0x895cd7be); + OP (A, B, C, D, 7, 0x6b901122); + OP (D, A, B, C, 12, 0xfd987193); + OP (C, D, A, B, 17, 0xa679438e); + OP (B, C, D, A, 22, 0x49b40821); + + /* For the second to fourth round we have the possibly swapped words + in CORRECT_WORDS. Redefine the macro to take an additional first + argument specifying the function to use. */ +#undef OP +#define OP(f, a, b, c, d, k, s, T) \ + do \ + { \ + a += f (b, c, d) + correct_words[k] + T; \ + CYCLIC (a, s); \ + a += b; \ + } \ + while (0) + + /* Round 2. */ + OP (FG, A, B, C, D, 1, 5, 0xf61e2562); + OP (FG, D, A, B, C, 6, 9, 0xc040b340); + OP (FG, C, D, A, B, 11, 14, 0x265e5a51); + OP (FG, B, C, D, A, 0, 20, 0xe9b6c7aa); + OP (FG, A, B, C, D, 5, 5, 0xd62f105d); + OP (FG, D, A, B, C, 10, 9, 0x02441453); + OP (FG, C, D, A, B, 15, 14, 0xd8a1e681); + OP (FG, B, C, D, A, 4, 20, 0xe7d3fbc8); + OP (FG, A, B, C, D, 9, 5, 0x21e1cde6); + OP (FG, D, A, B, C, 14, 9, 0xc33707d6); + OP (FG, C, D, A, B, 3, 14, 0xf4d50d87); + OP (FG, B, C, D, A, 8, 20, 0x455a14ed); + OP (FG, A, B, C, D, 13, 5, 0xa9e3e905); + OP (FG, D, A, B, C, 2, 9, 0xfcefa3f8); + OP (FG, C, D, A, B, 7, 14, 0x676f02d9); + OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a); + + /* Round 3. */ + OP (FH, A, B, C, D, 5, 4, 0xfffa3942); + OP (FH, D, A, B, C, 8, 11, 0x8771f681); + OP (FH, C, D, A, B, 11, 16, 0x6d9d6122); + OP (FH, B, C, D, A, 14, 23, 0xfde5380c); + OP (FH, A, B, C, D, 1, 4, 0xa4beea44); + OP (FH, D, A, B, C, 4, 11, 0x4bdecfa9); + OP (FH, C, D, A, B, 7, 16, 0xf6bb4b60); + OP (FH, B, C, D, A, 10, 23, 0xbebfbc70); + OP (FH, A, B, C, D, 13, 4, 0x289b7ec6); + OP (FH, D, A, B, C, 0, 11, 0xeaa127fa); + OP (FH, C, D, A, B, 3, 16, 0xd4ef3085); + OP (FH, B, C, D, A, 6, 23, 0x04881d05); + OP (FH, A, B, C, D, 9, 4, 0xd9d4d039); + OP (FH, D, A, B, C, 12, 11, 0xe6db99e5); + OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8); + OP (FH, B, C, D, A, 2, 23, 0xc4ac5665); + + /* Round 4. */ + OP (FI, A, B, C, D, 0, 6, 0xf4292244); + OP (FI, D, A, B, C, 7, 10, 0x432aff97); + OP (FI, C, D, A, B, 14, 15, 0xab9423a7); + OP (FI, B, C, D, A, 5, 21, 0xfc93a039); + OP (FI, A, B, C, D, 12, 6, 0x655b59c3); + OP (FI, D, A, B, C, 3, 10, 0x8f0ccc92); + OP (FI, C, D, A, B, 10, 15, 0xffeff47d); + OP (FI, B, C, D, A, 1, 21, 0x85845dd1); + OP (FI, A, B, C, D, 8, 6, 0x6fa87e4f); + OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0); + OP (FI, C, D, A, B, 6, 15, 0xa3014314); + OP (FI, B, C, D, A, 13, 21, 0x4e0811a1); + OP (FI, A, B, C, D, 4, 6, 0xf7537e82); + OP (FI, D, A, B, C, 11, 10, 0xbd3af235); + OP (FI, C, D, A, B, 2, 15, 0x2ad7d2bb); + OP (FI, B, C, D, A, 9, 21, 0xeb86d391); + + /* Add the starting values of the context. */ + A += A_save; + B += B_save; + C += C_save; + D += D_save; + } + + /* Put checksum in context given as argument. */ + ctx->A = A; + ctx->B = B; + ctx->C = C; + ctx->D = D; +}
Added: trunk/externals/loaders/urloader/md5.h =================================================================== --- trunk/externals/loaders/urloader/md5.h (rev 0) +++ trunk/externals/loaders/urloader/md5.h 2008-09-03 09:34:50 UTC (rev 10275) @@ -0,0 +1,136 @@ +/* Declaration of functions and data types used for MD5 sum computing + library functions. + Copyright (C) 1995-1997,1999-2005 Free Software Foundation, Inc. + + NOTE: The canonical source of this file is maintained with the GNU C + Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu. + + 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 _MD5_H +#define _MD5_H 1 + +#include <stdio.h> + +#if HAVE_INTTYPES_H +# include <inttypes.h> +#endif +#if HAVE_STDINT_H || _LIBC +# include <stdint.h> +#endif + +#ifndef __GNUC_PREREQ +# if defined __GNUC__ && defined __GNUC_MINOR__ +# define __GNUC_PREREQ(maj, min) \ + ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) +# else +# define __GNUC_PREREQ(maj, min) 0 +# endif +#endif + +#ifndef __THROW +# if defined __cplusplus && __GNUC_PREREQ (2,8) +# define __THROW throw () +# else +# define __THROW +# endif +#endif + +#ifndef __attribute__ +# if ! __GNUC_PREREQ (2,8) || __STRICT_ANSI__ +# define __attribute__(x) +# endif +#endif + +#ifndef _LIBC +# define __md5_buffer md5_buffer +# define __md5_finish_ctx md5_finish_ctx +# define __md5_init_ctx md5_init_ctx +# define __md5_process_block md5_process_block +# define __md5_process_bytes md5_process_bytes +# define __md5_read_ctx md5_read_ctx +# define __md5_stream md5_stream +#endif + +typedef uint32_t md5_uint32; + +/* Structure to save state of computation between the single steps. */ +struct md5_ctx +{ + md5_uint32 A; + md5_uint32 B; + md5_uint32 C; + md5_uint32 D; + + md5_uint32 total[2]; + md5_uint32 buflen; + char buffer[128] __attribute__ ((__aligned__ (__alignof__ (md5_uint32)))); +}; + +/* + * The following three functions are build up the low level used in + * the functions `md5_stream' and `md5_buffer'. + */ + +/* Initialize structure containing state of computation. + (RFC 1321, 3.3: Step 3) */ +extern void __md5_init_ctx (struct md5_ctx *ctx) __THROW; + +/* Starting with the result of former calls of this function (or the + initialization function update the context for the next LEN bytes + starting at BUFFER. + It is necessary that LEN is a multiple of 64!!! */ +extern void __md5_process_block (const void *buffer, size_t len, + struct md5_ctx *ctx) __THROW; + +/* Starting with the result of former calls of this function (or the + initialization function update the context for the next LEN bytes + starting at BUFFER. + It is NOT required that LEN is a multiple of 64. */ +extern void __md5_process_bytes (const void *buffer, size_t len, + struct md5_ctx *ctx) __THROW; + +/* Process the remaining bytes in the buffer and put result from CTX + in first 16 bytes following RESBUF. The result is always in little + endian byte order, so that a byte-wise output yields to the wanted + ASCII representation of the message digest. + + IMPORTANT: On some systems it is required that RESBUF be correctly + aligned for a 32 bits value. */ +extern void *__md5_finish_ctx (struct md5_ctx *ctx, void *resbuf) __THROW; + + +/* Put result from CTX in first 16 bytes following RESBUF. The result is + always in little endian byte order, so that a byte-wise output yields + to the wanted ASCII representation of the message digest. + + IMPORTANT: On some systems it is required that RESBUF is correctly + aligned for a 32 bits value. */ +extern void *__md5_read_ctx (const struct md5_ctx *ctx, void *resbuf) __THROW; + + +/* Compute MD5 message digest for bytes read from STREAM. The + resulting message digest number will be written into the 16 bytes + beginning at RESBLOCK. */ +extern int __md5_stream (FILE *stream, void *resblock) __THROW; + +/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The + result is always in little endian byte order, so that a byte-wise + output yields to the wanted ASCII representation of the message + digest. */ +extern void *__md5_buffer (const char *buffer, size_t len, + void *resblock) __THROW; + +#endif /* md5.h */
Added: trunk/externals/loaders/urloader/pd.index =================================================================== --- trunk/externals/loaders/urloader/pd.index (rev 0) +++ trunk/externals/loaders/urloader/pd.index 2008-09-03 09:34:50 UTC (rev 10275) @@ -0,0 +1,2 @@ +4a3a52f1d881ce91a6e8ba09671a6852 another.pd +b9faccc63257b5ced1f91f21ed8adfa3 unknown.pd
Added: trunk/externals/loaders/urloader/test.pd =================================================================== --- trunk/externals/loaders/urloader/test.pd (rev 0) +++ trunk/externals/loaders/urloader/test.pd 2008-09-03 09:34:50 UTC (rev 10275) @@ -0,0 +1,13 @@ +#N canvas 592 253 450 300 10; +#X text 28 24 Test for URL loader; +#X obj 28 56 baseurl http://localhost/pd; +#X obj 32 140 unknown; +#X floatatom 32 111 5 0 0 0 - - -; +#X floatatom 32 171 5 0 0 0 - - -; +#X obj 135 139 another; +#X floatatom 135 112 5 0 0 0 - - -; +#X floatatom 135 171 5 0 0 0 - - -; +#X connect 2 0 4 0; +#X connect 3 0 2 0; +#X connect 5 0 7 0; +#X connect 6 0 5 0;
Added: trunk/externals/loaders/urloader/unknown.pd =================================================================== --- trunk/externals/loaders/urloader/unknown.pd (rev 0) +++ trunk/externals/loaders/urloader/unknown.pd 2008-09-03 09:34:50 UTC (rev 10275) @@ -0,0 +1,5 @@ +#N canvas 1 44 450 300 10; +#X text 46 35 This is a PD patch.; +#X obj 210 36 inlet; +#X obj 210 89 outlet; +#X connect 1 0 2 0;
Added: trunk/externals/loaders/urloader/urlloader.c =================================================================== --- trunk/externals/loaders/urloader/urlloader.c (rev 0) +++ trunk/externals/loaders/urloader/urlloader.c 2008-09-03 09:34:50 UTC (rev 10275) @@ -0,0 +1,509 @@ +/* Copyright (c) 2008 Steve Sinclair radarsat1@gmail.com + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," that comes with Pd. + */ + +/* + * this code adds an external "loader" to Miller S. Puckette's "pure data", + * which allows the loading of libraries/externals from internet URLs + * + * the infrastructure of this file is based on hcsteiner's "libdir" loader + */ + + +#ifdef __WIN32__ +# define MSW +#endif + +#include "m_pd.h" + +#if (PD_MINOR_VERSION >= 40) + +#include "s_stuff.h" +#include "g_canvas.h" +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <stdlib.h> +#include <sys/stat.h> + +#include "baseurl.h" +#include <curl/curl.h> + +#include <stdint.h> +#include "md5.h" +#include "md5.c" + +typedef void (*t_urlloader_setup)(void); + +/* definitions taken from s_loader.c */ +typedef int (*loader_t)(t_canvas *canvas, char *classname); +void sys_register_loader(loader_t loader); +void class_set_extern_dir(t_symbol *s); + +/* taken from m_class.c */ +int pd_setloadingabstraction(t_symbol *sym); +void canvas_popabstraction(t_canvas *x); + +/* ==================================================== */ + +#define CACHE_TIMEOUT_SECONDS 100 + +typedef struct _urlloader +{ + t_object x_obj; +} t_urlloader; +static t_class *urlloader_class; + +static char *version = "0.0.1"; + +typedef struct _list +{ + struct _list *next; +} t_list; + +typedef struct _url_object +{ + t_list list; + t_symbol *name; + char md5[16]; +} t_url_object; + +typedef struct _url +{ + t_list list; + t_symbol *url; + t_url_object *objects; +} t_url; +static t_url *baseurl_list = NULL; + +char cachedir[MAXPDSTRING]=""; +#define FILEPERM (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) +#define DIRPERM (FILEPERM|S_IXUSR|S_IXGRP|S_IXOTH) +char *get_cache_dir(void) +{ + if (cachedir[0]==0) { + strcpy(cachedir, getenv("HOME")); + strcat(cachedir, "/.pd/cache"); + } + + return cachedir; +} + +FILE* create_and_open(const char *filename, const char *mode) +{ + char str[MAXPDSTRING], *ss=str; + const char *sf=filename; + struct stat st; + while (*sf) { + do { + *ss = *sf; + ss++; + sf++; + } while (*sf && *sf != '/'); + *ss = 0; + + if (stat(str, &st)<0) { + if (*sf) { + if (mkdir(str, DIRPERM)<0) { + post("[urlloader] Error creating %s", str); + return 0; + } + } + else + return fopen(str, mode); + } + else if (!*sf) + return fopen(str, mode); + } + + return 0; +} + +/** Return the full path to a filename in the cache */ +void cache_path(char path[MAXPDSTRING], t_url *u, const char *filename) +{ + char *s; + strncpy(path, get_cache_dir(), MAXPDSTRING); +#ifdef WIN32 + strncat(path, "\", MAXPDSTRING); +#else + strncat(path, "/", MAXPDSTRING); +#endif + s = path + strlen(path); + strncat(path, u->url->s_name, MAXPDSTRING); + while (*s) { + if (*s == '/') *s = '_'; + s++; + } +#ifdef WIN32 + strncat(path, "\", MAXPDSTRING); +#else + strncat(path, "/", MAXPDSTRING); +#endif + strncat(path, filename, MAXPDSTRING); +} + +/** Open a file from the cache or download it first if needed. */ +FILE* download_and_open_from_cache(t_url *u, const char *filename, const char *mode) +{ + char str_url[MAXPDSTRING]; + char cache_name[MAXPDSTRING]; + struct stat st; + + cache_path(cache_name, u, filename); + + if (stat(cache_name, &st)<0 + || ((time(NULL)-st.st_mtime) > CACHE_TIMEOUT_SECONDS)) + { + CURL *c = curl_easy_init(); + FILE *f=0; + if (!c) { + post("[urlloader] Error initializing curl."); + return 0; + } + + f = create_and_open(cache_name, "wb"); + if (!f) { + post("[urlloader] Error opening %s for write.", cache_name); + return 0; + } + + /* Download the index file */ + snprintf(str_url, MAXPDSTRING, "%s/%s", u->url->s_name, filename); + curl_easy_setopt(c, CURLOPT_URL, str_url); + curl_easy_setopt(c, CURLOPT_WRITEDATA, f); + if (curl_easy_perform(c)) { + post("[urlloader] Error downloading %s", str_url); + } + curl_easy_cleanup(c); + + post("[urlloader] Downloaded %s to %s", str_url, cache_name); + + fclose(f); + } + + if (mode) + return fopen(cache_name, mode); + else + // indicate success without opening the file + return (FILE*)1; +} + +/** Append an item to a struct beginning with a t_list. + * If allowdup is false (0), second item must be a t_symbol*. + * If duplicate, returns the item without modifying it. */ +void *list_append(void *list, void *item, int size, int allowdup) +{ + t_list** l = list; + t_symbol *s1, *s2; + if (!*l) { + *l = getbytes(size); + } + else { + while (*l) { + if (!allowdup) { + s1 = *(t_symbol**)(((char*)*l)+sizeof(t_list)); + s2 = *(t_symbol**)(((char*)item)+sizeof(t_list)); + if (s1==s2 || strcmp(s1->s_name, s2->s_name)==0) + return *l; + } + if (!(*l)->next) + break; + l = &(*l)->next; + } + (*l)->next = getbytes(size); + l = &(*l)->next; + } + + if (*l) { + memcpy(*l, item, size); + (*l)->next = 0; + } + + return *l; +} + +t_url *url_add(t_atom *url) +{ + t_url u; + u.url = url->a_w.w_symbol; + u.objects = 0; + return list_append(&baseurl_list, &u, sizeof(t_url), 0); +} + +void url_parse_index_line(t_url *u, char* line) +{ + char *s = line, *name, hex[3]; + int i=0; + t_url_object o; + while ((*s==' ' || *s=='\t') && *s) {s++;} /* skip whitespace */ + if (!*s) return; + while (!(*s==' ' || *s=='\t') && *s) { /* remember MD5 sum */ + hex[0] = *s; s++; + hex[1] = *s; s++; + hex[2] = 0; + o.md5[i++] = strtol(hex, 0, 16); + } + if (!*s) return; + while ((*s==' ' || *s=='\t') && *s) {s++;} /* skip whitespace */ + if (!*s) return; + name = s; + while (!(*s==' ' || *s=='\t') && *s) {s++;} /* skip md5sum for now */ + *s = 0; + + o.name = gensym(name); + list_append(&u->objects, &o, sizeof(t_url_object), 0); +} + +/** Download index for a given URL. */ +int url_update_index(t_url *u) +{ + char buffer[MAXPDSTRING], *line=buffer; + int bufpos=0; + + // open and read the downloaded or cached file. + FILE *f = download_and_open_from_cache(u, "pd.index", "rb"); + if (!f) { + post("[urlloader] Error opening index for %s", u->url->s_name); + return -1; + } + + post("[urlloader] Index for %s opened.", u->url->s_name); + while (!feof(f)) { + int sz = fread(buffer+bufpos, 1, 256, f); + int end = bufpos + sz; + while (bufpos < end) { + while (buffer[bufpos]!='\n' && buffer[bufpos]!='\r' + && bufpos < end) + ++bufpos; + if (bufpos < end || feof(f)) { + buffer[bufpos] = 0; + url_parse_index_line(u, line); + ++bufpos; + line = buffer+bufpos; + } + } + } + + fclose(f); + return 0; +} + +/** Download any indexes that are missing. */ +static int cache_update_index(void) +{ + t_url *u; + int rc; + + u = baseurl_list; + while (u) { + rc = 0; + if (u->objects == NULL) + rc = url_update_index(u); + if (rc) { + post("[urlloader] Error updating index for %s", u->url->s_name); + return rc; + } + u = (t_url*)u->list.next; + } + + return 0; +} + +/** Search all objects in the canvas and its owner for baseurl objects. + * Add the found object URLs to the global list of t_urls. + */ +static void canvas_find_baseurls(t_canvas *canvas) +{ + t_gobj *o = canvas->gl_list; + while (o) { + if (strcmp(class_getname(o->g_pd),"baseurl")==0) + url_add(&((t_baseurl*)o)->url); + o = o->g_next; + } + if (canvas->gl_owner) + canvas_find_baseurls(canvas->gl_owner); +} + +/** Find a given class name in the global t_url list. */ +static t_url* url_find_class(char *classname, t_url_object **object) +{ + t_url *u = baseurl_list; + t_url_object *o; + while (u) { + o = u->objects; + while (o) { + char *ext = strstr(o->name->s_name, ".pd"); + if (!ext) continue; + if (strncmp(o->name->s_name, classname, + ext - o->name->s_name)==0) + break; + o = (t_url_object*)o->list.next; + } + if (o) break; + u = (t_url*)u->list.next; + } + if (object) *object = o; + return u; +} + +/** Load an abstraction specified by an absolute path name. */ +int canvas_load_from_absolute_path(t_canvas *canvas, t_symbol *classname, + char *path, char *ext) +{ + char dirbuf[MAXPDSTRING], *nameptr; + t_pd *current = s__X.s_thing; + int fd=-1; + + fd = canvas_open(canvas, path, ext, + dirbuf, &nameptr, MAXPDSTRING, 0); + + if (fd < 0) + return 0; + + close(fd); + if (!pd_setloadingabstraction(classname)) { + canvas_setargs(0, 0); /* TODO argc, argv */ + binbuf_evalfile(gensym(nameptr), gensym(dirbuf)); + if (s__X.s_thing != current) + canvas_popabstraction((t_canvas *)(s__X.s_thing)); + canvas_setargs(0, 0); + } + else { + error("%s: can't load abstraction within itself\n", classname); + return 0; + } + + return 1; +} + +/** + * the loader + * + * @param canvas the context of the object to be created + * @param classname the name of the object (external, library) to be created + * @return 1 on success, 0 on failure + */ +static int urlloader_loader(t_canvas *canvas, char *classname) +{ + int result=0; + t_url *u; + t_url_object *o; + char class_filename[MAXPDSTRING]; + char class_cachepath[MAXPDSTRING]; + char tmpstr[MAXPDSTRING]; + FILE *f; + + static int already_loading=0; + if(already_loading)return 0; + already_loading=1; + + /* loader */ + post("[urlloader] Asked to load %s for canvas %s", classname, canvas->gl_name->s_name); + canvas_find_baseurls(canvas); + cache_update_index(); + + post("[urlloader] Known URLs:"); + u = baseurl_list; + while (u) { + post("[urlloader] %s", u->url->s_name); + o = u->objects; + while (o) { + post("[urlloader] - %s", o->name->s_name); + o = (t_url_object*)o->list.next; + } + u = (t_url*)u->list.next; + } + + u = url_find_class(classname, &o); + if (!(u && o)) { + already_loading=0; + return result; + } + + post("[urlloader] Found: %s.pd at %s", classname, u->url->s_name); + + snprintf(class_filename, MAXPDSTRING, "%s.pd", classname); + if (f=download_and_open_from_cache(u, class_filename, "rb")) + { + char resblock[16]; + int okay=1, i; + if (md5_stream(f, resblock)) { + post("[urlloader] Error generating MD5 sum for %s", class_filename); + result = 0; + already_loading = 0; + fclose(f); + return result; + } + fclose(f); + + for (i=0; i<16; i++) + okay &= (resblock[i]==o->md5[i]); + if (!okay) { + post("[urlloader] MD5 error for %s", class_filename); + result = 0; + already_loading = 0; + return result; + } + + // download GPG signature + snprintf(tmpstr, MAXPDSTRING, "%s.asc", class_filename); + if (!download_and_open_from_cache(u, tmpstr, 0)) { + post("[urlloader] Error downloading GPG signature for %s", + class_filename); + result = 0; + already_loading = 0; + return result; + } + + // check GPG signature + cache_path(class_cachepath, u, classname); + snprintf(tmpstr, MAXPDSTRING, "gpg --verify %s.pd.asc %s.pd", + class_cachepath, class_cachepath); + if (system(tmpstr)) { + post("[urlloader] Error verifying GPG signature for %s", + class_filename); + result = 0; + already_loading = 0; + return result; + } + + + // load pd patch + canvas_load_from_absolute_path(canvas, gensym(classname), + class_cachepath, ".pd"); + result = 1; + } + + already_loading=0; + return result; +} + +#endif /* PD_MINOR_VERSION>=40 */ + +static void*urlloader_new(t_symbol *s, int argc, t_atom *argv) +{ + t_urlloader*x = (t_urlloader*)pd_new(urlloader_class); + return (x); +} + +void urlloader_setup(void) +{ + /* relies on t.grill's loader functionality, fully added in 0.40 */ + post("url loader %s",version); + post("\twritten by Steve Sinclair"); + post("\tcompiled on "__DATE__" at "__TIME__ " "); + post("\tcompiled against Pd version %d.%d.%d.%s", PD_MAJOR_VERSION, PD_MINOR_VERSION, PD_BUGFIX_VERSION, PD_TEST_VERSION); + + curl_global_init(CURL_GLOBAL_ALL); + +#if (PD_MINOR_VERSION >= 40) + sys_register_loader(urlloader_loader); +#else + error("to function, this needs to be compiled against Pd 0.40 or higher,\n"); + error("\tor a version that has sys_register_loader()"); +#endif + + urlloader_class = class_new(gensym("urlloader"), (t_newmethod)urlloader_new, 0, sizeof(t_urlloader), CLASS_NOINLET, A_GIMME, 0); +}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.