faststep 0.0.1
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/.gitignore +6 -0
- data/Gemfile +4 -0
- data/Rakefile +15 -0
- data/bench/standard_benchmark +178 -0
- data/ext/faststep/bson.c +687 -0
- data/ext/faststep/bson.h +225 -0
- data/ext/faststep/bson_ruby_conversion.c +44 -0
- data/ext/faststep/bson_ruby_conversion.h +10 -0
- data/ext/faststep/collection.c +187 -0
- data/ext/faststep/collection.h +24 -0
- data/ext/faststep/connection.c +85 -0
- data/ext/faststep/connection.h +17 -0
- data/ext/faststep/cursor.c +61 -0
- data/ext/faststep/cursor.h +10 -0
- data/ext/faststep/db.c +56 -0
- data/ext/faststep/db.h +8 -0
- data/ext/faststep/exceptions.c +7 -0
- data/ext/faststep/exceptions.h +5 -0
- data/ext/faststep/extconf.rb +3 -0
- data/ext/faststep/faststep.c +30 -0
- data/ext/faststep/faststep.h +4 -0
- data/ext/faststep/faststep_defines.h +11 -0
- data/ext/faststep/gridfs.c +799 -0
- data/ext/faststep/gridfs.h +278 -0
- data/ext/faststep/md5.c +381 -0
- data/ext/faststep/md5.h +91 -0
- data/ext/faststep/mongo.c +801 -0
- data/ext/faststep/mongo.h +188 -0
- data/ext/faststep/mongo_except.h +143 -0
- data/ext/faststep/numbers.c +127 -0
- data/ext/faststep/platform_hacks.h +93 -0
- data/ext/faststep/support.c +21 -0
- data/ext/faststep/support.h +6 -0
- data/faststep.gemspec +26 -0
- data/lib/faststep/collection.rb +21 -0
- data/lib/faststep/connection.rb +13 -0
- data/lib/faststep/cursor.rb +7 -0
- data/lib/faststep/db.rb +25 -0
- data/lib/faststep/version.rb +3 -0
- data/lib/faststep.rb +10 -0
- data/spec/collection_spec.rb +116 -0
- data/spec/connection_spec.rb +34 -0
- data/spec/cursor_spec.rb +24 -0
- data/spec/db_spec.rb +28 -0
- data/spec/spec_helper.rb +13 -0
- data/spec/support_spec.rb +14 -0
- metadata +181 -0
@@ -0,0 +1,278 @@
|
|
1
|
+
/*--------------------------------------------------------------------*/
|
2
|
+
/* gridfs.h */
|
3
|
+
/* Author: Christopher Triolo */
|
4
|
+
/*--------------------------------------------------------------------*/
|
5
|
+
|
6
|
+
#include "mongo.h"
|
7
|
+
#include "bson.h"
|
8
|
+
#include "platform_hacks.h"
|
9
|
+
#include <stdio.h>
|
10
|
+
#ifndef GRIDFS_INCLUDED
|
11
|
+
#define GRIDFS_INCLUDED
|
12
|
+
|
13
|
+
enum {DEFAULT_CHUNK_SIZE = 256 * 1024};
|
14
|
+
|
15
|
+
typedef uint64_t gridfs_offset;
|
16
|
+
|
17
|
+
/* A GridFS contains a db connection, a root database name, and an
|
18
|
+
optional prefix */
|
19
|
+
typedef struct {
|
20
|
+
/* The client to db-connection. */
|
21
|
+
mongo_connection* client;
|
22
|
+
/* The root database name */
|
23
|
+
const char* dbname;
|
24
|
+
/* The prefix of the GridFS's collections, default is NULL */
|
25
|
+
const char* prefix;
|
26
|
+
/* The namespace where the file's metadata is stored */
|
27
|
+
const char* files_ns;
|
28
|
+
/* The namespace where the files's data is stored in chunks */
|
29
|
+
const char* chunks_ns;
|
30
|
+
|
31
|
+
} gridfs;
|
32
|
+
|
33
|
+
/* The state of a gridfile. This is used for incrementally writing buffers
|
34
|
+
* to a single GridFS file.
|
35
|
+
*/
|
36
|
+
|
37
|
+
/* A GridFile contains the GridFS it is located in and the file
|
38
|
+
metadata */
|
39
|
+
typedef struct {
|
40
|
+
/* The GridFS where the GridFile is located */
|
41
|
+
gridfs* gfs;
|
42
|
+
/* The GridFile's bson object where all its metadata is located */
|
43
|
+
bson* meta;
|
44
|
+
/* The position is the offset in the file */
|
45
|
+
gridfs_offset pos;
|
46
|
+
/* The files_id of the gridfile */
|
47
|
+
bson_oid_t id;
|
48
|
+
/* The name of the gridfile as a string */
|
49
|
+
const char* remote_name;
|
50
|
+
/* The gridfile's content type */
|
51
|
+
const char* content_type;
|
52
|
+
/* The length of this gridfile */
|
53
|
+
gridfs_offset length;
|
54
|
+
/* The number of the current chunk being written to */
|
55
|
+
int chunk_num;
|
56
|
+
/* A buffer storing data still to be written to chunks */
|
57
|
+
char* pending_data;
|
58
|
+
/* Length of pending data */
|
59
|
+
int pending_len;
|
60
|
+
|
61
|
+
} gridfile;
|
62
|
+
|
63
|
+
/*--------------------------------------------------------------------*/
|
64
|
+
|
65
|
+
/** Initializes a GridFS object
|
66
|
+
* @param client - db connection
|
67
|
+
* @param dbname - database name
|
68
|
+
* @param prefix - collection prefix, default is fs if NULL or empty
|
69
|
+
* @param gfs - the GridFS object to initialize
|
70
|
+
* @return - 1 if successful, 0 otherwise
|
71
|
+
*/
|
72
|
+
int gridfs_init(mongo_connection* client, const char* dbname,
|
73
|
+
const char* prefix, gridfs* gfs);
|
74
|
+
|
75
|
+
/** Destroys a GridFS object
|
76
|
+
*/
|
77
|
+
void gridfs_destroy( gridfs* gfs );
|
78
|
+
|
79
|
+
/** Initializes a gridfile for writing incrementally with gridfs_write_buffer.
|
80
|
+
* Once initialized, you can write any number of buffers with gridfs_write_buffer.
|
81
|
+
* When done, you must call gridfs_writer_done to save the file metadata.
|
82
|
+
*
|
83
|
+
* @return - 1 if successful, 0 otherwise
|
84
|
+
*/
|
85
|
+
void gridfile_writer_init( gridfile* gfile, gridfs* gfs, const char* remote_name, const char* content_type );
|
86
|
+
|
87
|
+
/** Write to a GridFS file incrementally. You can call this function any number
|
88
|
+
* of times with a new buffer each time. This allows you to effectively
|
89
|
+
* stream to a GridFS file. When finished, be sure to call gridfs_writer_done.
|
90
|
+
*
|
91
|
+
* @return - 1 if successful, 0 otherwise
|
92
|
+
*/
|
93
|
+
void gridfile_write_buffer( gridfile* gfile, const char* data, gridfs_offset length );
|
94
|
+
|
95
|
+
/** Signal that writing of this gridfile is complete by
|
96
|
+
* writing any buffered chunks along with the entry in the
|
97
|
+
* files collection.
|
98
|
+
*
|
99
|
+
* @return - the file object if successful; otherwise 0.
|
100
|
+
*/
|
101
|
+
bson gridfile_writer_done( gridfile* gfile );
|
102
|
+
|
103
|
+
/** Store a buffer as a GridFS file.
|
104
|
+
* @param gfs - the working GridFS
|
105
|
+
* @param data - pointer to buffer to store in GridFS
|
106
|
+
* @param length - length of the buffer
|
107
|
+
* @param remotename - filename for use in the database
|
108
|
+
* @param contenttype - optional MIME type for this object
|
109
|
+
* @return - the file object
|
110
|
+
*/
|
111
|
+
bson gridfs_store_buffer(gridfs* gfs, const char* data, gridfs_offset length,
|
112
|
+
const char* remotename,
|
113
|
+
const char * contenttype);
|
114
|
+
|
115
|
+
/** Open the file referenced by filename and store it as a GridFS file.
|
116
|
+
* @param gfs - the working GridFS
|
117
|
+
* @param filename - local filename relative to the process
|
118
|
+
* @param remotename - optional filename for use in the database
|
119
|
+
* @param contenttype - optional MIME type for this object
|
120
|
+
* @return - the file object
|
121
|
+
*/
|
122
|
+
bson gridfs_store_file(gridfs* gfs, const char* filename,
|
123
|
+
const char* remotename, const char* contenttype);
|
124
|
+
|
125
|
+
/** Removes the files referenced by filename from the db
|
126
|
+
* @param gfs - the working GridFS
|
127
|
+
* @param filename - the filename of the file/s to be removed
|
128
|
+
*/
|
129
|
+
void gridfs_remove_filename(gridfs* gfs, const char* filename);
|
130
|
+
|
131
|
+
/** Find the first query within the GridFS and return it as a GridFile
|
132
|
+
* @param gfs - the working GridFS
|
133
|
+
* @param query - a pointer to the bson with the query data
|
134
|
+
* @param gfile - the output GridFile to be initialized
|
135
|
+
* @return 1 if successful, 0 otherwise
|
136
|
+
*/
|
137
|
+
int gridfs_find_query(gridfs* gfs, bson* query, gridfile* gfile );
|
138
|
+
|
139
|
+
/** Find the first file referenced by filename within the GridFS
|
140
|
+
* and return it as a GridFile
|
141
|
+
* @param gfs - the working GridFS
|
142
|
+
* @param filename - filename of the file to find
|
143
|
+
* @param gfile - the output GridFile to be intialized
|
144
|
+
* @return 1 if successful, 0 otherwise
|
145
|
+
*/
|
146
|
+
int gridfs_find_filename(gridfs* gfs, const char *filename,
|
147
|
+
gridfile* gfile);
|
148
|
+
|
149
|
+
/*--------------------------------------------------------------------*/
|
150
|
+
|
151
|
+
|
152
|
+
/** Initializes a GridFile containing the GridFS and file bson
|
153
|
+
* @param gfs - the GridFS where the GridFile is located
|
154
|
+
* @param meta - the file object
|
155
|
+
* @param gfile - the output GridFile that is being initialized
|
156
|
+
* @return 1 if successful, 0 otherwise
|
157
|
+
*/
|
158
|
+
int gridfile_init(gridfs* gfs, bson* meta, gridfile* gfile);
|
159
|
+
|
160
|
+
/** Destroys the GridFile
|
161
|
+
* @param oGridFIle - the GridFile being destroyed
|
162
|
+
*/
|
163
|
+
void gridfile_destroy(gridfile* gfile);
|
164
|
+
|
165
|
+
/** Returns whether or not the GridFile exists
|
166
|
+
* @param gfile - the GridFile being examined
|
167
|
+
*/
|
168
|
+
int gridfile_exists(gridfile* gfile);
|
169
|
+
|
170
|
+
/** Returns the filename of GridFile
|
171
|
+
* @param gfile - the working GridFile
|
172
|
+
* @return - the filename of the Gridfile
|
173
|
+
*/
|
174
|
+
const char * gridfile_get_filename(gridfile* gfile);
|
175
|
+
|
176
|
+
/** Returns the size of the chunks of the GridFile
|
177
|
+
* @param gfile - the working GridFile
|
178
|
+
* @return - the size of the chunks of the Gridfile
|
179
|
+
*/
|
180
|
+
int gridfile_get_chunksize(gridfile* gfile);
|
181
|
+
|
182
|
+
/** Returns the length of GridFile's data
|
183
|
+
* @param gfile - the working GridFile
|
184
|
+
* @return - the length of the Gridfile's data
|
185
|
+
*/
|
186
|
+
gridfs_offset gridfile_get_contentlength(gridfile* gfile);
|
187
|
+
|
188
|
+
/** Returns the MIME type of the GridFile
|
189
|
+
* @param gfile - the working GridFile
|
190
|
+
* @return - the MIME type of the Gridfile
|
191
|
+
* (NULL if no type specified)
|
192
|
+
*/
|
193
|
+
const char* gridfile_get_contenttype(gridfile* gfile);
|
194
|
+
|
195
|
+
/** Returns the upload date of GridFile
|
196
|
+
* @param gfile - the working GridFile
|
197
|
+
* @return - the upload date of the Gridfile
|
198
|
+
*/
|
199
|
+
bson_date_t gridfile_get_uploaddate(gridfile* gfile);
|
200
|
+
|
201
|
+
/** Returns the MD5 of GridFile
|
202
|
+
* @param gfile - the working GridFile
|
203
|
+
* @return - the MD5 of the Gridfile
|
204
|
+
*/
|
205
|
+
const char* gridfile_get_md5(gridfile* gfile);
|
206
|
+
|
207
|
+
/** Returns the field in GridFile specified by name
|
208
|
+
* @param gfile - the working GridFile
|
209
|
+
* @param name - the name of the field to be returned
|
210
|
+
* @return - the data of the field specified
|
211
|
+
* (NULL if none exists)
|
212
|
+
*/
|
213
|
+
const char *gridfile_get_field(gridfile* gfile,
|
214
|
+
const char* name);
|
215
|
+
|
216
|
+
/** Returns a boolean field in GridFile specified by name
|
217
|
+
* @param gfile - the working GridFile
|
218
|
+
* @param name - the name of the field to be returned
|
219
|
+
* @return - the boolean of the field specified
|
220
|
+
* (NULL if none exists)
|
221
|
+
*/
|
222
|
+
bson_bool_t gridfile_get_boolean(gridfile* gfile,
|
223
|
+
const char* name);
|
224
|
+
|
225
|
+
/** Returns the metadata of GridFile
|
226
|
+
* @param gfile - the working GridFile
|
227
|
+
* @return - the metadata of the Gridfile in a bson object
|
228
|
+
* (an empty bson is returned if none exists)
|
229
|
+
*/
|
230
|
+
bson gridfile_get_metadata(gridfile* gfile);
|
231
|
+
|
232
|
+
/** Returns the number of chunks in the GridFile
|
233
|
+
* @param gfile - the working GridFile
|
234
|
+
* @return - the number of chunks in the Gridfile
|
235
|
+
*/
|
236
|
+
int gridfile_get_numchunks(gridfile* gfile);
|
237
|
+
|
238
|
+
/** Returns chunk n of GridFile
|
239
|
+
* @param gfile - the working GridFile
|
240
|
+
* @return - the nth chunk of the Gridfile
|
241
|
+
*/
|
242
|
+
bson gridfile_get_chunk(gridfile* gfile, int n);
|
243
|
+
|
244
|
+
/** Returns a mongo_cursor of *size* chunks starting with chunk *start*
|
245
|
+
* @param gfile - the working GridFile
|
246
|
+
* @param start - the first chunk in the cursor
|
247
|
+
* @param size - the number of chunks to be returned
|
248
|
+
* @return - mongo_cursor of the chunks (must be destroyed after use)
|
249
|
+
*/
|
250
|
+
mongo_cursor* gridfile_get_chunks(gridfile* gfile, int start, int size);
|
251
|
+
|
252
|
+
/** Writes the GridFile to a stream
|
253
|
+
* @param gfile - the working GridFile
|
254
|
+
* @param stream - the file stream to write to
|
255
|
+
*/
|
256
|
+
gridfs_offset gridfile_write_file(gridfile* gfile, FILE* stream);
|
257
|
+
|
258
|
+
/** Reads length bytes from the GridFile to a buffer
|
259
|
+
* and updates the position in the file.
|
260
|
+
* (assumes the buffer is large enough)
|
261
|
+
* (if size is greater than EOF gridfile_read reads until EOF)
|
262
|
+
* @param gfile - the working GridFile
|
263
|
+
* @param size - the amount of bytes to be read
|
264
|
+
* @param buf - the buffer to read to
|
265
|
+
* @return - the number of bytes read
|
266
|
+
*/
|
267
|
+
gridfs_offset gridfile_read(gridfile* gfile, gridfs_offset size, char* buf);
|
268
|
+
|
269
|
+
/** Updates the position in the file
|
270
|
+
* (If the offset goes beyond the contentlength,
|
271
|
+
* the position is updated to the end of the file.)
|
272
|
+
* @param gfile - the working GridFile
|
273
|
+
* @param offset - the position to update to
|
274
|
+
* @return - resulting offset location
|
275
|
+
*/
|
276
|
+
gridfs_offset gridfile_seek(gridfile* gfile, gridfs_offset offset);
|
277
|
+
|
278
|
+
#endif
|
data/ext/faststep/md5.c
ADDED
@@ -0,0 +1,381 @@
|
|
1
|
+
/*
|
2
|
+
Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved.
|
3
|
+
|
4
|
+
This software is provided 'as-is', without any express or implied
|
5
|
+
warranty. In no event will the authors be held liable for any damages
|
6
|
+
arising from the use of this software.
|
7
|
+
|
8
|
+
Permission is granted to anyone to use this software for any purpose,
|
9
|
+
including commercial applications, and to alter it and redistribute it
|
10
|
+
freely, subject to the following restrictions:
|
11
|
+
|
12
|
+
1. The origin of this software must not be misrepresented; you must not
|
13
|
+
claim that you wrote the original software. If you use this software
|
14
|
+
in a product, an acknowledgment in the product documentation would be
|
15
|
+
appreciated but is not required.
|
16
|
+
2. Altered source versions must be plainly marked as such, and must not be
|
17
|
+
misrepresented as being the original software.
|
18
|
+
3. This notice may not be removed or altered from any source distribution.
|
19
|
+
|
20
|
+
L. Peter Deutsch
|
21
|
+
ghost@aladdin.com
|
22
|
+
|
23
|
+
*/
|
24
|
+
/* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */
|
25
|
+
/*
|
26
|
+
Independent implementation of MD5 (RFC 1321).
|
27
|
+
|
28
|
+
This code implements the MD5 Algorithm defined in RFC 1321, whose
|
29
|
+
text is available at
|
30
|
+
http://www.ietf.org/rfc/rfc1321.txt
|
31
|
+
The code is derived from the text of the RFC, including the test suite
|
32
|
+
(section A.5) but excluding the rest of Appendix A. It does not include
|
33
|
+
any code or documentation that is identified in the RFC as being
|
34
|
+
copyrighted.
|
35
|
+
|
36
|
+
The original and principal author of md5.c is L. Peter Deutsch
|
37
|
+
<ghost@aladdin.com>. Other authors are noted in the change history
|
38
|
+
that follows (in reverse chronological order):
|
39
|
+
|
40
|
+
2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
|
41
|
+
either statically or dynamically; added missing #include <string.h>
|
42
|
+
in library.
|
43
|
+
2002-03-11 lpd Corrected argument list for main(), and added int return
|
44
|
+
type, in test program and T value program.
|
45
|
+
2002-02-21 lpd Added missing #include <stdio.h> in test program.
|
46
|
+
2000-07-03 lpd Patched to eliminate warnings about "constant is
|
47
|
+
unsigned in ANSI C, signed in traditional"; made test program
|
48
|
+
self-checking.
|
49
|
+
1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
|
50
|
+
1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
|
51
|
+
1999-05-03 lpd Original version.
|
52
|
+
*/
|
53
|
+
|
54
|
+
#include "md5.h"
|
55
|
+
#include <string.h>
|
56
|
+
|
57
|
+
#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */
|
58
|
+
#ifdef MONGO_BIG_ENDIAN
|
59
|
+
# define BYTE_ORDER 1
|
60
|
+
#else
|
61
|
+
# define BYTE_ORDER -1
|
62
|
+
#endif
|
63
|
+
|
64
|
+
#define T_MASK ((mongo_md5_word_t)~0)
|
65
|
+
#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
|
66
|
+
#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
|
67
|
+
#define T3 0x242070db
|
68
|
+
#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
|
69
|
+
#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
|
70
|
+
#define T6 0x4787c62a
|
71
|
+
#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
|
72
|
+
#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
|
73
|
+
#define T9 0x698098d8
|
74
|
+
#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
|
75
|
+
#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
|
76
|
+
#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
|
77
|
+
#define T13 0x6b901122
|
78
|
+
#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
|
79
|
+
#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
|
80
|
+
#define T16 0x49b40821
|
81
|
+
#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
|
82
|
+
#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
|
83
|
+
#define T19 0x265e5a51
|
84
|
+
#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
|
85
|
+
#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
|
86
|
+
#define T22 0x02441453
|
87
|
+
#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
|
88
|
+
#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
|
89
|
+
#define T25 0x21e1cde6
|
90
|
+
#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
|
91
|
+
#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
|
92
|
+
#define T28 0x455a14ed
|
93
|
+
#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
|
94
|
+
#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
|
95
|
+
#define T31 0x676f02d9
|
96
|
+
#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
|
97
|
+
#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
|
98
|
+
#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
|
99
|
+
#define T35 0x6d9d6122
|
100
|
+
#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
|
101
|
+
#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
|
102
|
+
#define T38 0x4bdecfa9
|
103
|
+
#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
|
104
|
+
#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
|
105
|
+
#define T41 0x289b7ec6
|
106
|
+
#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
|
107
|
+
#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
|
108
|
+
#define T44 0x04881d05
|
109
|
+
#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
|
110
|
+
#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
|
111
|
+
#define T47 0x1fa27cf8
|
112
|
+
#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
|
113
|
+
#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
|
114
|
+
#define T50 0x432aff97
|
115
|
+
#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
|
116
|
+
#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
|
117
|
+
#define T53 0x655b59c3
|
118
|
+
#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
|
119
|
+
#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
|
120
|
+
#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
|
121
|
+
#define T57 0x6fa87e4f
|
122
|
+
#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
|
123
|
+
#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
|
124
|
+
#define T60 0x4e0811a1
|
125
|
+
#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
|
126
|
+
#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
|
127
|
+
#define T63 0x2ad7d2bb
|
128
|
+
#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
|
129
|
+
|
130
|
+
|
131
|
+
static void
|
132
|
+
mongo_md5_process(mongo_md5_state_t *pms, const mongo_md5_byte_t *data /*[64]*/)
|
133
|
+
{
|
134
|
+
mongo_md5_word_t
|
135
|
+
a = pms->abcd[0], b = pms->abcd[1],
|
136
|
+
c = pms->abcd[2], d = pms->abcd[3];
|
137
|
+
mongo_md5_word_t t;
|
138
|
+
#if BYTE_ORDER > 0
|
139
|
+
/* Define storage only for big-endian CPUs. */
|
140
|
+
mongo_md5_word_t X[16];
|
141
|
+
#else
|
142
|
+
/* Define storage for little-endian or both types of CPUs. */
|
143
|
+
mongo_md5_word_t xbuf[16];
|
144
|
+
const mongo_md5_word_t *X;
|
145
|
+
#endif
|
146
|
+
|
147
|
+
{
|
148
|
+
#if BYTE_ORDER == 0
|
149
|
+
/*
|
150
|
+
* Determine dynamically whether this is a big-endian or
|
151
|
+
* little-endian machine, since we can use a more efficient
|
152
|
+
* algorithm on the latter.
|
153
|
+
*/
|
154
|
+
static const int w = 1;
|
155
|
+
|
156
|
+
if (*((const mongo_md5_byte_t *)&w)) /* dynamic little-endian */
|
157
|
+
#endif
|
158
|
+
#if BYTE_ORDER <= 0 /* little-endian */
|
159
|
+
{
|
160
|
+
/*
|
161
|
+
* On little-endian machines, we can process properly aligned
|
162
|
+
* data without copying it.
|
163
|
+
*/
|
164
|
+
if (!((data - (const mongo_md5_byte_t *)0) & 3)) {
|
165
|
+
/* data are properly aligned */
|
166
|
+
X = (const mongo_md5_word_t *)data;
|
167
|
+
} else {
|
168
|
+
/* not aligned */
|
169
|
+
memcpy(xbuf, data, 64);
|
170
|
+
X = xbuf;
|
171
|
+
}
|
172
|
+
}
|
173
|
+
#endif
|
174
|
+
#if BYTE_ORDER == 0
|
175
|
+
else /* dynamic big-endian */
|
176
|
+
#endif
|
177
|
+
#if BYTE_ORDER >= 0 /* big-endian */
|
178
|
+
{
|
179
|
+
/*
|
180
|
+
* On big-endian machines, we must arrange the bytes in the
|
181
|
+
* right order.
|
182
|
+
*/
|
183
|
+
const mongo_md5_byte_t *xp = data;
|
184
|
+
int i;
|
185
|
+
|
186
|
+
# if BYTE_ORDER == 0
|
187
|
+
X = xbuf; /* (dynamic only) */
|
188
|
+
# else
|
189
|
+
# define xbuf X /* (static only) */
|
190
|
+
# endif
|
191
|
+
for (i = 0; i < 16; ++i, xp += 4)
|
192
|
+
xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
|
193
|
+
}
|
194
|
+
#endif
|
195
|
+
}
|
196
|
+
|
197
|
+
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
|
198
|
+
|
199
|
+
/* Round 1. */
|
200
|
+
/* Let [abcd k s i] denote the operation
|
201
|
+
a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
|
202
|
+
#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
|
203
|
+
#define SET(a, b, c, d, k, s, Ti)\
|
204
|
+
t = a + F(b,c,d) + X[k] + Ti;\
|
205
|
+
a = ROTATE_LEFT(t, s) + b
|
206
|
+
/* Do the following 16 operations. */
|
207
|
+
SET(a, b, c, d, 0, 7, T1);
|
208
|
+
SET(d, a, b, c, 1, 12, T2);
|
209
|
+
SET(c, d, a, b, 2, 17, T3);
|
210
|
+
SET(b, c, d, a, 3, 22, T4);
|
211
|
+
SET(a, b, c, d, 4, 7, T5);
|
212
|
+
SET(d, a, b, c, 5, 12, T6);
|
213
|
+
SET(c, d, a, b, 6, 17, T7);
|
214
|
+
SET(b, c, d, a, 7, 22, T8);
|
215
|
+
SET(a, b, c, d, 8, 7, T9);
|
216
|
+
SET(d, a, b, c, 9, 12, T10);
|
217
|
+
SET(c, d, a, b, 10, 17, T11);
|
218
|
+
SET(b, c, d, a, 11, 22, T12);
|
219
|
+
SET(a, b, c, d, 12, 7, T13);
|
220
|
+
SET(d, a, b, c, 13, 12, T14);
|
221
|
+
SET(c, d, a, b, 14, 17, T15);
|
222
|
+
SET(b, c, d, a, 15, 22, T16);
|
223
|
+
#undef SET
|
224
|
+
|
225
|
+
/* Round 2. */
|
226
|
+
/* Let [abcd k s i] denote the operation
|
227
|
+
a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
|
228
|
+
#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
|
229
|
+
#define SET(a, b, c, d, k, s, Ti)\
|
230
|
+
t = a + G(b,c,d) + X[k] + Ti;\
|
231
|
+
a = ROTATE_LEFT(t, s) + b
|
232
|
+
/* Do the following 16 operations. */
|
233
|
+
SET(a, b, c, d, 1, 5, T17);
|
234
|
+
SET(d, a, b, c, 6, 9, T18);
|
235
|
+
SET(c, d, a, b, 11, 14, T19);
|
236
|
+
SET(b, c, d, a, 0, 20, T20);
|
237
|
+
SET(a, b, c, d, 5, 5, T21);
|
238
|
+
SET(d, a, b, c, 10, 9, T22);
|
239
|
+
SET(c, d, a, b, 15, 14, T23);
|
240
|
+
SET(b, c, d, a, 4, 20, T24);
|
241
|
+
SET(a, b, c, d, 9, 5, T25);
|
242
|
+
SET(d, a, b, c, 14, 9, T26);
|
243
|
+
SET(c, d, a, b, 3, 14, T27);
|
244
|
+
SET(b, c, d, a, 8, 20, T28);
|
245
|
+
SET(a, b, c, d, 13, 5, T29);
|
246
|
+
SET(d, a, b, c, 2, 9, T30);
|
247
|
+
SET(c, d, a, b, 7, 14, T31);
|
248
|
+
SET(b, c, d, a, 12, 20, T32);
|
249
|
+
#undef SET
|
250
|
+
|
251
|
+
/* Round 3. */
|
252
|
+
/* Let [abcd k s t] denote the operation
|
253
|
+
a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
|
254
|
+
#define H(x, y, z) ((x) ^ (y) ^ (z))
|
255
|
+
#define SET(a, b, c, d, k, s, Ti)\
|
256
|
+
t = a + H(b,c,d) + X[k] + Ti;\
|
257
|
+
a = ROTATE_LEFT(t, s) + b
|
258
|
+
/* Do the following 16 operations. */
|
259
|
+
SET(a, b, c, d, 5, 4, T33);
|
260
|
+
SET(d, a, b, c, 8, 11, T34);
|
261
|
+
SET(c, d, a, b, 11, 16, T35);
|
262
|
+
SET(b, c, d, a, 14, 23, T36);
|
263
|
+
SET(a, b, c, d, 1, 4, T37);
|
264
|
+
SET(d, a, b, c, 4, 11, T38);
|
265
|
+
SET(c, d, a, b, 7, 16, T39);
|
266
|
+
SET(b, c, d, a, 10, 23, T40);
|
267
|
+
SET(a, b, c, d, 13, 4, T41);
|
268
|
+
SET(d, a, b, c, 0, 11, T42);
|
269
|
+
SET(c, d, a, b, 3, 16, T43);
|
270
|
+
SET(b, c, d, a, 6, 23, T44);
|
271
|
+
SET(a, b, c, d, 9, 4, T45);
|
272
|
+
SET(d, a, b, c, 12, 11, T46);
|
273
|
+
SET(c, d, a, b, 15, 16, T47);
|
274
|
+
SET(b, c, d, a, 2, 23, T48);
|
275
|
+
#undef SET
|
276
|
+
|
277
|
+
/* Round 4. */
|
278
|
+
/* Let [abcd k s t] denote the operation
|
279
|
+
a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
|
280
|
+
#define I(x, y, z) ((y) ^ ((x) | ~(z)))
|
281
|
+
#define SET(a, b, c, d, k, s, Ti)\
|
282
|
+
t = a + I(b,c,d) + X[k] + Ti;\
|
283
|
+
a = ROTATE_LEFT(t, s) + b
|
284
|
+
/* Do the following 16 operations. */
|
285
|
+
SET(a, b, c, d, 0, 6, T49);
|
286
|
+
SET(d, a, b, c, 7, 10, T50);
|
287
|
+
SET(c, d, a, b, 14, 15, T51);
|
288
|
+
SET(b, c, d, a, 5, 21, T52);
|
289
|
+
SET(a, b, c, d, 12, 6, T53);
|
290
|
+
SET(d, a, b, c, 3, 10, T54);
|
291
|
+
SET(c, d, a, b, 10, 15, T55);
|
292
|
+
SET(b, c, d, a, 1, 21, T56);
|
293
|
+
SET(a, b, c, d, 8, 6, T57);
|
294
|
+
SET(d, a, b, c, 15, 10, T58);
|
295
|
+
SET(c, d, a, b, 6, 15, T59);
|
296
|
+
SET(b, c, d, a, 13, 21, T60);
|
297
|
+
SET(a, b, c, d, 4, 6, T61);
|
298
|
+
SET(d, a, b, c, 11, 10, T62);
|
299
|
+
SET(c, d, a, b, 2, 15, T63);
|
300
|
+
SET(b, c, d, a, 9, 21, T64);
|
301
|
+
#undef SET
|
302
|
+
|
303
|
+
/* Then perform the following additions. (That is increment each
|
304
|
+
of the four registers by the value it had before this block
|
305
|
+
was started.) */
|
306
|
+
pms->abcd[0] += a;
|
307
|
+
pms->abcd[1] += b;
|
308
|
+
pms->abcd[2] += c;
|
309
|
+
pms->abcd[3] += d;
|
310
|
+
}
|
311
|
+
|
312
|
+
void
|
313
|
+
mongo_md5_init(mongo_md5_state_t *pms)
|
314
|
+
{
|
315
|
+
pms->count[0] = pms->count[1] = 0;
|
316
|
+
pms->abcd[0] = 0x67452301;
|
317
|
+
pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
|
318
|
+
pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
|
319
|
+
pms->abcd[3] = 0x10325476;
|
320
|
+
}
|
321
|
+
|
322
|
+
void
|
323
|
+
mongo_md5_append(mongo_md5_state_t *pms, const mongo_md5_byte_t *data, int nbytes)
|
324
|
+
{
|
325
|
+
const mongo_md5_byte_t *p = data;
|
326
|
+
int left = nbytes;
|
327
|
+
int offset = (pms->count[0] >> 3) & 63;
|
328
|
+
mongo_md5_word_t nbits = (mongo_md5_word_t)(nbytes << 3);
|
329
|
+
|
330
|
+
if (nbytes <= 0)
|
331
|
+
return;
|
332
|
+
|
333
|
+
/* Update the message length. */
|
334
|
+
pms->count[1] += nbytes >> 29;
|
335
|
+
pms->count[0] += nbits;
|
336
|
+
if (pms->count[0] < nbits)
|
337
|
+
pms->count[1]++;
|
338
|
+
|
339
|
+
/* Process an initial partial block. */
|
340
|
+
if (offset) {
|
341
|
+
int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
|
342
|
+
|
343
|
+
memcpy(pms->buf + offset, p, copy);
|
344
|
+
if (offset + copy < 64)
|
345
|
+
return;
|
346
|
+
p += copy;
|
347
|
+
left -= copy;
|
348
|
+
mongo_md5_process(pms, pms->buf);
|
349
|
+
}
|
350
|
+
|
351
|
+
/* Process full blocks. */
|
352
|
+
for (; left >= 64; p += 64, left -= 64)
|
353
|
+
mongo_md5_process(pms, p);
|
354
|
+
|
355
|
+
/* Process a final partial block. */
|
356
|
+
if (left)
|
357
|
+
memcpy(pms->buf, p, left);
|
358
|
+
}
|
359
|
+
|
360
|
+
void
|
361
|
+
mongo_md5_finish(mongo_md5_state_t *pms, mongo_md5_byte_t digest[16])
|
362
|
+
{
|
363
|
+
static const mongo_md5_byte_t pad[64] = {
|
364
|
+
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
365
|
+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
366
|
+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
367
|
+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
368
|
+
};
|
369
|
+
mongo_md5_byte_t data[8];
|
370
|
+
int i;
|
371
|
+
|
372
|
+
/* Save the length before padding. */
|
373
|
+
for (i = 0; i < 8; ++i)
|
374
|
+
data[i] = (mongo_md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
|
375
|
+
/* Pad to 56 bytes mod 64. */
|
376
|
+
mongo_md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
|
377
|
+
/* Append the length. */
|
378
|
+
mongo_md5_append(pms, data, 8);
|
379
|
+
for (i = 0; i < 16; ++i)
|
380
|
+
digest[i] = (mongo_md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
|
381
|
+
}
|