fastgeoip 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+ }