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.
- data/.document +5 -0
- data/.gitignore +25 -0
- data/LICENSE +20 -0
- data/README.rdoc +11 -0
- data/Rakefile +55 -0
- data/VERSION +1 -0
- data/ext/GeoIP.c +1640 -0
- data/ext/GeoIP.h +252 -0
- data/ext/GeoIPCity.c +297 -0
- data/ext/GeoIPCity.h +72 -0
- data/ext/GeoIP_internal.h +19 -0
- data/ext/extconf.h +5 -0
- data/ext/extconf.rb +58 -0
- data/ext/fastgeoip.c +59 -0
- data/ext/global.h +32 -0
- data/ext/md5.c +326 -0
- data/ext/md5.h +40 -0
- data/ext/mkmf.log +24 -0
- data/ext/regionName.c +13518 -0
- data/ext/ruby_geoip.h +15 -0
- data/ext/timeZone.c +941 -0
- data/ext/types.h +140 -0
- data/fastgeoip.gemspec +66 -0
- data/lib/fastgeoip.rb +0 -0
- data/test/helper.rb +10 -0
- metadata +92 -0
data/ext/GeoIPCity.h
ADDED
@@ -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
|
data/ext/extconf.h
ADDED
data/ext/extconf.rb
ADDED
@@ -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'
|
data/ext/fastgeoip.c
ADDED
@@ -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
|
+
}
|
data/ext/global.h
ADDED
@@ -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
|
+
|
data/ext/md5.c
ADDED
@@ -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
|
+
}
|