fastgeoip 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,72 @@
1
+ /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 2 -*- */
2
+ /* GeoIPCity.h
3
+ *
4
+ * Copyright (C) 2006 MaxMind LLC
5
+ *
6
+ * This library is free software; you can redistribute it and/or
7
+ * modify it under the terms of the GNU Lesser General Public
8
+ * License as published by the Free Software Foundation; either
9
+ * version 2.1 of the License, or (at your option) any later version.
10
+ *
11
+ * This library is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
+ * Lesser General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public
17
+ * License along with this library; if not, write to the Free Software
18
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
+ */
20
+
21
+ #ifndef GEOIPCITY_H
22
+ #define GEOIPCITY_H
23
+
24
+ #include "GeoIP.h"
25
+
26
+ #ifdef __cplusplus
27
+ extern "C" {
28
+ #endif
29
+
30
+ typedef struct GeoIPRecordTag {
31
+ char *country_code;
32
+ char *country_code3;
33
+ char *country_name;
34
+ char *region;
35
+ char *city;
36
+ char *postal_code;
37
+ float latitude;
38
+ float longitude;
39
+ union {
40
+ int metro_code; /* metro_code is a alias for dma_code */
41
+ int dma_code;
42
+ };
43
+ int area_code;
44
+ int charset;
45
+ char *continent_code;
46
+ } GeoIPRecord;
47
+
48
+ GeoIPRecord * GeoIP_record_by_ipnum (GeoIP* gi, unsigned long ipnum);
49
+ GeoIPRecord * GeoIP_record_by_addr (GeoIP* gi, const char *addr);
50
+ GeoIPRecord * GeoIP_record_by_name (GeoIP* gi, const char *host);
51
+
52
+ GeoIPRecord * GeoIP_record_by_ipnum_v6 (GeoIP* gi, geoipv6_t ipnum);
53
+ GeoIPRecord * GeoIP_record_by_addr_v6 (GeoIP* gi, const char *addr);
54
+ GeoIPRecord * GeoIP_record_by_name_v6 (GeoIP* gi, const char *host);
55
+
56
+ int GeoIP_record_id_by_addr (GeoIP* gi, const char *addr);
57
+ int GeoIP_record_id_by_addr_v6 (GeoIP* gi, const char *addr);
58
+
59
+ int GeoIP_init_record_iter (GeoIP* gi);
60
+ /* returns 0 on success, 1 on failure */
61
+ int GeoIP_next_record (GeoIP* gi, GeoIPRecord **gir, int *record_iter);
62
+
63
+ void GeoIPRecord_delete (GeoIPRecord *gir);
64
+
65
+ /* NULL on failure otherwise a malloced string in utf8 */
66
+ char * _iso_8859_1__utf8(const char *);
67
+
68
+ #ifdef __cplusplus
69
+ }
70
+ #endif
71
+
72
+ #endif /* GEOIPCITY_H */
@@ -0,0 +1,19 @@
1
+ #ifndef GEOIP_INTERNAL_H
2
+ #define GEOIP_INTERNAL_H
3
+
4
+ #include "GeoIP.h"
5
+
6
+ GEOIP_API unsigned int _GeoIP_seek_record (GeoIP *gi, unsigned long ipnum);
7
+ GEOIP_API unsigned long _GeoIP_addr_to_num (const char *addr);
8
+
9
+ GEOIP_API unsigned int _GeoIP_seek_record_v6 (GeoIP *gi, geoipv6_t ipnum);
10
+ GEOIP_API geoipv6_t _GeoIP_addr_to_num_v6 (const char *addr);
11
+
12
+ GEOIP_API unsigned long _GeoIP_lookupaddress (const char *host);
13
+ GEOIP_API geoipv6_t _GeoIP_lookupaddress_v6 (const char *host);
14
+ GEOIP_API int __GEOIP_V6_IS_NULL(geoipv6_t v6);
15
+
16
+ GEOIP_API void _GeoIP_setup_dbfilename();
17
+ GEOIP_API char *_GeoIP_full_path_to(const char *file_name);
18
+
19
+ #endif
@@ -0,0 +1,5 @@
1
+ #ifndef EXTCONF_H
2
+ #define EXTCONF_H
3
+ #define HAVE_GEOIP_H 1
4
+ #define HAVE_GEOIPUPDATE_H 1
5
+ #endif
@@ -0,0 +1,58 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rbconfig'
4
+ require 'mkmf'
5
+
6
+
7
+ # $srcs = ['fastgeoip.c'] + Dir.glob(File.join(File.dirname(__FILE__),'/geoip/*.c'))
8
+
9
+ dir_config('libz')
10
+
11
+ # dir_config('geoip')
12
+ #$LIBPATH.push(Config::CONFIG['libdir'])
13
+ #$CFLAGS += " -I#{Config::CONFIG['includedir']}"
14
+
15
+ def crash(str)
16
+ printf(" extconf failure: %s\n", str)
17
+ exit 1
18
+ end
19
+
20
+
21
+ unless have_library('z','gzopen')
22
+ crash(<<EOL)
23
+ need libz.
24
+
25
+ Install libz or try passing some of the following options
26
+ to extconf.rb:
27
+
28
+ --with-libz-dir=/path/to/libz
29
+ --with-libz-lib=/path/to/libz/lib
30
+ --with-libz-include=/path/to/libz/include
31
+ EOL
32
+ end
33
+
34
+
35
+
36
+ # if !have_header('GeoIP.h') || !have_header('GeoIPUpdate.h') ||
37
+ # !have_library('GeoIP', 'GeoIP_new') ||
38
+ # !have_library('GeoIPUpdate', 'GeoIP_update_database')
39
+ # crash(<<EOL)
40
+ # need libGeoIP.
41
+ #
42
+ # Install the library or try passing one of the following
43
+ # options to extconf.rb:
44
+ #
45
+ # --with-geoip-dir=/path/to/geoip
46
+ # --with-geoip-lib=/path/to/geoip/lib
47
+ # --with-geoip-include=/path/to/geoip/include
48
+ #
49
+ # To obtain libGeoIP, yo ucan download it from:
50
+ #
51
+ # http://maxmind.com/geoip/api/c.shtml
52
+ # EOL
53
+ # end
54
+
55
+ $CFLAGS = ' -g -Wall ' + $CFLAGS
56
+
57
+ # create_header
58
+ create_makefile 'fastgeoip'
@@ -0,0 +1,59 @@
1
+ /* $Id: geoip.c,v 1.6 2002/11/19 21:21:38 sean Exp $ */
2
+
3
+ #include "ruby_geoip.h"
4
+ #include "GeoIP.h"
5
+
6
+ VALUE geoip_country_code_by_addr(VALUE self, VALUE addr) {
7
+ fast_geoip *fgi;
8
+ char *cc;
9
+
10
+ Check_Type(addr, T_STRING);
11
+ Data_Get_Struct(self, fast_geoip, fgi);
12
+ cc = (char *)GeoIP_country_code_by_addr(fgi->db, STR2CSTR(addr));
13
+ if (cc == NULL) {
14
+ return(Qnil);
15
+ } else {
16
+ return(rb_str_new2(cc));
17
+ }
18
+ }
19
+
20
+
21
+ void geoip_free(fast_geoip *fgi) {
22
+ if (fgi->db != NULL)
23
+ GeoIP_delete(fgi->db);
24
+ free(fgi);
25
+ }
26
+
27
+
28
+ VALUE geoip_open(int argc, VALUE *argv, VALUE class) {
29
+ fast_geoip *fgi;
30
+ VALUE filename;
31
+
32
+ if (argc == 1) {
33
+ rb_scan_args(argc, argv, "01", &filename);
34
+ Check_Type(filename, T_STRING);
35
+ } else
36
+ rb_raise(rb_eArgError, "wrong number of arguments (needs 1 : filename of db)");
37
+
38
+ fgi = ALLOC(fast_geoip);
39
+ fgi->db = GeoIP_open(STR2CSTR(filename), GEOIP_MEMORY_CACHE);
40
+ return(Data_Wrap_Struct(class, 0, geoip_free, fgi));
41
+ }
42
+
43
+
44
+ VALUE geoip_database_info(VALUE self) {
45
+ fast_geoip *fgi;
46
+ Data_Get_Struct(self, fast_geoip, fgi);
47
+ return(rb_str_new2(GeoIP_database_info(fgi->db)));
48
+ }
49
+
50
+
51
+ void Init_fastgeoip(void) {
52
+ cFastGeoIP = rb_define_class("FastGeoIp", rb_cObject);
53
+ eFastGeoIPError = rb_define_class_under(cFastGeoIP, "Error", rb_eException);
54
+
55
+ rb_define_singleton_method(cFastGeoIP, "open", geoip_open, -1);
56
+
57
+ rb_define_method(cFastGeoIP, "country_code_by_addr", geoip_country_code_by_addr, 1);
58
+ rb_define_method(cFastGeoIP, "database_info", geoip_database_info, 0);
59
+ }
@@ -0,0 +1,32 @@
1
+ /* GLOBAL.H - RSAREF types and constants
2
+ */
3
+
4
+ /* PROTOTYPES should be set to one if and only if the compiler supports
5
+ function argument prototyping.
6
+ The following makes PROTOTYPES default to 0 if it has not already
7
+
8
+ been defined with C compiler flags.
9
+ */
10
+ #ifndef PROTOTYPES
11
+ #define PROTOTYPES 0
12
+ #endif
13
+
14
+ /* POINTER defines a generic pointer type */
15
+ typedef unsigned char *POINTER;
16
+
17
+ /* UINT2 defines a two byte word */
18
+ typedef unsigned short int UINT2;
19
+
20
+ /* UINT4 defines a four byte word */
21
+ typedef unsigned long int UINT4;
22
+
23
+ /* PROTO_LIST is defined depending on how PROTOTYPES is defined above.
24
+ If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it
25
+ returns an empty list.
26
+ */
27
+ #if PROTOTYPES
28
+ #define PROTO_LIST(list) list
29
+ #else
30
+ #define PROTO_LIST(list) ()
31
+ #endif
32
+
@@ -0,0 +1,326 @@
1
+ /* md5.c - MD5 Message-Digest Algorithm
2
+ * Copyright (C) 1995, 1996, 1998, 1999,
3
+ * 2000, 2001 Free Software Foundation, Inc.
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify it
6
+ * under the terms of the GNU General Public License as published by the
7
+ * Free Software Foundation; either version 2, or (at your option) any
8
+ * later version.
9
+ *
10
+ * This program is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ * GNU General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU General Public License
16
+ * along with this program; if not, write to the Free Software Foundation,
17
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
+ *
19
+ * According to the definition of MD5 in RFC 1321 from April 1992.
20
+ * NOTE: This is *not* the same file as the one from glibc.
21
+ */
22
+ /* Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. */
23
+ /* Heavily modified for GnuPG by <wk@gnupg.org> */
24
+
25
+ #include <stdio.h>
26
+ #include <stdlib.h>
27
+ #include <string.h>
28
+ #include <assert.h>
29
+
30
+ #include "types.h"
31
+
32
+ #ifdef WORDS_BIGENDIAN
33
+ #define BIG_ENDIAN_HOST
34
+ #endif
35
+
36
+ //#define DIM(v) (sizeof(v)/sizeof((v)[0]))
37
+ #define wipememory2(_ptr,_set,_len) do { volatile char *_vptr=(volatile char *)(_ptr); size_t _vlen=(_len); while(_vlen) { *_vptr=(_set); _vptr++; _vlen--; } } while(0)
38
+ #define wipememory(_ptr,_len) wipememory2(_ptr,0,_len)
39
+ #define rol(x,n) ( ((x) << (n)) | ((x) >> (32-(n))) )
40
+
41
+ typedef struct {
42
+ u32 A,B,C,D; /* chaining variables */
43
+ u32 nblocks;
44
+ byte buf[64];
45
+ int count;
46
+ } MD5_CONTEXT;
47
+
48
+
49
+ void
50
+ md5_init( MD5_CONTEXT *ctx )
51
+ {
52
+ ctx->A = 0x67452301;
53
+ ctx->B = 0xefcdab89;
54
+ ctx->C = 0x98badcfe;
55
+ ctx->D = 0x10325476;
56
+
57
+ ctx->nblocks = 0;
58
+ ctx->count = 0;
59
+ }
60
+
61
+
62
+
63
+
64
+ /* These are the four functions used in the four steps of the MD5 algorithm
65
+ and defined in the RFC 1321. The first function is a little bit optimized
66
+ (as found in Colin Plumbs public domain implementation). */
67
+ /* #define FF(b, c, d) ((b & c) | (~b & d)) */
68
+ #define FF(b, c, d) (d ^ (b & (c ^ d)))
69
+ #define FG(b, c, d) FF (d, b, c)
70
+ #define FH(b, c, d) (b ^ c ^ d)
71
+ #define FI(b, c, d) (c ^ (b | ~d))
72
+
73
+ static void
74
+ burn_stack (int bytes)
75
+ {
76
+ char buf[128];
77
+
78
+ wipememory(buf,sizeof buf);
79
+ bytes -= sizeof buf;
80
+ if (bytes > 0)
81
+ burn_stack (bytes);
82
+ }
83
+
84
+
85
+
86
+ /****************
87
+ * transform n*64 bytes
88
+ */
89
+ static void
90
+ /*transform( MD5_CONTEXT *ctx, const void *buffer, size_t len )*/
91
+ transform( MD5_CONTEXT *ctx, byte *data )
92
+ {
93
+ u32 correct_words[16];
94
+ u32 A = ctx->A;
95
+ u32 B = ctx->B;
96
+ u32 C = ctx->C;
97
+ u32 D = ctx->D;
98
+ u32 *cwp = correct_words;
99
+
100
+ #ifdef BIG_ENDIAN_HOST
101
+ { int i;
102
+ byte *p2, *p1;
103
+ for(i=0, p1=data, p2=(byte*)correct_words; i < 16; i++, p2 += 4 ) {
104
+ p2[3] = *p1++;
105
+ p2[2] = *p1++;
106
+ p2[1] = *p1++;
107
+ p2[0] = *p1++;
108
+ }
109
+ }
110
+ #else
111
+ memcpy( correct_words, data, 64 );
112
+ #endif
113
+
114
+
115
+ #define OP(a, b, c, d, s, T) \
116
+ do \
117
+ { \
118
+ a += FF (b, c, d) + (*cwp++) + T; \
119
+ a = rol(a, s); \
120
+ a += b; \
121
+ } \
122
+ while (0)
123
+
124
+ /* Before we start, one word about the strange constants.
125
+ They are defined in RFC 1321 as
126
+
127
+ T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64
128
+ */
129
+
130
+ /* Round 1. */
131
+ OP (A, B, C, D, 7, 0xd76aa478);
132
+ OP (D, A, B, C, 12, 0xe8c7b756);
133
+ OP (C, D, A, B, 17, 0x242070db);
134
+ OP (B, C, D, A, 22, 0xc1bdceee);
135
+ OP (A, B, C, D, 7, 0xf57c0faf);
136
+ OP (D, A, B, C, 12, 0x4787c62a);
137
+ OP (C, D, A, B, 17, 0xa8304613);
138
+ OP (B, C, D, A, 22, 0xfd469501);
139
+ OP (A, B, C, D, 7, 0x698098d8);
140
+ OP (D, A, B, C, 12, 0x8b44f7af);
141
+ OP (C, D, A, B, 17, 0xffff5bb1);
142
+ OP (B, C, D, A, 22, 0x895cd7be);
143
+ OP (A, B, C, D, 7, 0x6b901122);
144
+ OP (D, A, B, C, 12, 0xfd987193);
145
+ OP (C, D, A, B, 17, 0xa679438e);
146
+ OP (B, C, D, A, 22, 0x49b40821);
147
+
148
+ #undef OP
149
+ #define OP(f, a, b, c, d, k, s, T) \
150
+ do \
151
+ { \
152
+ a += f (b, c, d) + correct_words[k] + T; \
153
+ a = rol(a, s); \
154
+ a += b; \
155
+ } \
156
+ while (0)
157
+
158
+ /* Round 2. */
159
+ OP (FG, A, B, C, D, 1, 5, 0xf61e2562);
160
+ OP (FG, D, A, B, C, 6, 9, 0xc040b340);
161
+ OP (FG, C, D, A, B, 11, 14, 0x265e5a51);
162
+ OP (FG, B, C, D, A, 0, 20, 0xe9b6c7aa);
163
+ OP (FG, A, B, C, D, 5, 5, 0xd62f105d);
164
+ OP (FG, D, A, B, C, 10, 9, 0x02441453);
165
+ OP (FG, C, D, A, B, 15, 14, 0xd8a1e681);
166
+ OP (FG, B, C, D, A, 4, 20, 0xe7d3fbc8);
167
+ OP (FG, A, B, C, D, 9, 5, 0x21e1cde6);
168
+ OP (FG, D, A, B, C, 14, 9, 0xc33707d6);
169
+ OP (FG, C, D, A, B, 3, 14, 0xf4d50d87);
170
+ OP (FG, B, C, D, A, 8, 20, 0x455a14ed);
171
+ OP (FG, A, B, C, D, 13, 5, 0xa9e3e905);
172
+ OP (FG, D, A, B, C, 2, 9, 0xfcefa3f8);
173
+ OP (FG, C, D, A, B, 7, 14, 0x676f02d9);
174
+ OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a);
175
+
176
+ /* Round 3. */
177
+ OP (FH, A, B, C, D, 5, 4, 0xfffa3942);
178
+ OP (FH, D, A, B, C, 8, 11, 0x8771f681);
179
+ OP (FH, C, D, A, B, 11, 16, 0x6d9d6122);
180
+ OP (FH, B, C, D, A, 14, 23, 0xfde5380c);
181
+ OP (FH, A, B, C, D, 1, 4, 0xa4beea44);
182
+ OP (FH, D, A, B, C, 4, 11, 0x4bdecfa9);
183
+ OP (FH, C, D, A, B, 7, 16, 0xf6bb4b60);
184
+ OP (FH, B, C, D, A, 10, 23, 0xbebfbc70);
185
+ OP (FH, A, B, C, D, 13, 4, 0x289b7ec6);
186
+ OP (FH, D, A, B, C, 0, 11, 0xeaa127fa);
187
+ OP (FH, C, D, A, B, 3, 16, 0xd4ef3085);
188
+ OP (FH, B, C, D, A, 6, 23, 0x04881d05);
189
+ OP (FH, A, B, C, D, 9, 4, 0xd9d4d039);
190
+ OP (FH, D, A, B, C, 12, 11, 0xe6db99e5);
191
+ OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8);
192
+ OP (FH, B, C, D, A, 2, 23, 0xc4ac5665);
193
+
194
+ /* Round 4. */
195
+ OP (FI, A, B, C, D, 0, 6, 0xf4292244);
196
+ OP (FI, D, A, B, C, 7, 10, 0x432aff97);
197
+ OP (FI, C, D, A, B, 14, 15, 0xab9423a7);
198
+ OP (FI, B, C, D, A, 5, 21, 0xfc93a039);
199
+ OP (FI, A, B, C, D, 12, 6, 0x655b59c3);
200
+ OP (FI, D, A, B, C, 3, 10, 0x8f0ccc92);
201
+ OP (FI, C, D, A, B, 10, 15, 0xffeff47d);
202
+ OP (FI, B, C, D, A, 1, 21, 0x85845dd1);
203
+ OP (FI, A, B, C, D, 8, 6, 0x6fa87e4f);
204
+ OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0);
205
+ OP (FI, C, D, A, B, 6, 15, 0xa3014314);
206
+ OP (FI, B, C, D, A, 13, 21, 0x4e0811a1);
207
+ OP (FI, A, B, C, D, 4, 6, 0xf7537e82);
208
+ OP (FI, D, A, B, C, 11, 10, 0xbd3af235);
209
+ OP (FI, C, D, A, B, 2, 15, 0x2ad7d2bb);
210
+ OP (FI, B, C, D, A, 9, 21, 0xeb86d391);
211
+
212
+ /* Put checksum in context given as argument. */
213
+ ctx->A += A;
214
+ ctx->B += B;
215
+ ctx->C += C;
216
+ ctx->D += D;
217
+ }
218
+
219
+
220
+
221
+ /* The routine updates the message-digest context to
222
+ * account for the presence of each of the characters inBuf[0..inLen-1]
223
+ * in the message whose digest is being computed.
224
+ */
225
+ void
226
+ md5_write( MD5_CONTEXT *hd, byte *inbuf, size_t inlen)
227
+ {
228
+ if( hd->count == 64 ) { /* flush the buffer */
229
+ transform( hd, hd->buf );
230
+ burn_stack (80+6*sizeof(void*));
231
+ hd->count = 0;
232
+ hd->nblocks++;
233
+ }
234
+ if( !inbuf )
235
+ return;
236
+ if( hd->count ) {
237
+ for( ; inlen && hd->count < 64; inlen-- )
238
+ hd->buf[hd->count++] = *inbuf++;
239
+ md5_write( hd, NULL, 0 );
240
+ if( !inlen )
241
+ return;
242
+ }
243
+
244
+ while( inlen >= 64 ) {
245
+ transform( hd, inbuf );
246
+ hd->count = 0;
247
+ hd->nblocks++;
248
+ inlen -= 64;
249
+ inbuf += 64;
250
+ }
251
+ burn_stack (80+6*sizeof(void*));
252
+ for( ; inlen && hd->count < 64; inlen-- )
253
+ hd->buf[hd->count++] = *inbuf++;
254
+ }
255
+ /* The routine final terminates the message-digest computation and
256
+ * ends with the desired message digest in mdContext->digest[0...15].
257
+ * The handle is prepared for a new MD5 cycle.
258
+ * Returns 16 bytes representing the digest.
259
+ */
260
+
261
+ void
262
+ md5_final( MD5_CONTEXT *hd )
263
+ {
264
+ u32 t, msb, lsb;
265
+ byte *p;
266
+
267
+ md5_write(hd, NULL, 0); /* flush */;
268
+
269
+ t = hd->nblocks;
270
+ /* multiply by 64 to make a byte count */
271
+ lsb = t << 6;
272
+ msb = t >> 26;
273
+ /* add the count */
274
+ t = lsb;
275
+ if( (lsb += hd->count) < t )
276
+ msb++;
277
+ /* multiply by 8 to make a bit count */
278
+ t = lsb;
279
+ lsb <<= 3;
280
+ msb <<= 3;
281
+ msb |= t >> 29;
282
+
283
+ if( hd->count < 56 ) { /* enough room */
284
+ hd->buf[hd->count++] = 0x80; /* pad */
285
+ while( hd->count < 56 )
286
+ hd->buf[hd->count++] = 0; /* pad */
287
+ }
288
+ else { /* need one extra block */
289
+ hd->buf[hd->count++] = 0x80; /* pad character */
290
+ while( hd->count < 64 )
291
+ hd->buf[hd->count++] = 0;
292
+ md5_write(hd, NULL, 0); /* flush */;
293
+ memset(hd->buf, 0, 56 ); /* fill next block with zeroes */
294
+ }
295
+ /* append the 64 bit count */
296
+ hd->buf[56] = lsb ;
297
+ hd->buf[57] = lsb >> 8;
298
+ hd->buf[58] = lsb >> 16;
299
+ hd->buf[59] = lsb >> 24;
300
+ hd->buf[60] = msb ;
301
+ hd->buf[61] = msb >> 8;
302
+ hd->buf[62] = msb >> 16;
303
+ hd->buf[63] = msb >> 24;
304
+ transform( hd, hd->buf );
305
+ burn_stack (80+6*sizeof(void*));
306
+
307
+ p = hd->buf;
308
+ #ifdef BIG_ENDIAN_HOST
309
+ #define X(a) do { *p++ = hd-> a ; *p++ = hd-> a >> 8; \
310
+ *p++ = hd-> a >> 16; *p++ = hd-> a >> 24; } while(0)
311
+ #else /* little endian */
312
+ #define X(a) do { *(u32*)p = hd-> a ; p += 4; } while(0)
313
+ #endif
314
+ X(A);
315
+ X(B);
316
+ X(C);
317
+ X(D);
318
+ #undef X
319
+
320
+ }
321
+
322
+ static byte *
323
+ md5_read( MD5_CONTEXT *hd )
324
+ {
325
+ return hd->buf;
326
+ }