~ubuntu-branches/ubuntu/trusty/rhash/trusty

« back to all changes in this revision

Viewing changes to bindings/ruby/rhash.c

  • Committer: Package Import Robot
  • Author(s): Aleksey Kravchenko
  • Date: 2013-09-16 19:48:55 UTC
  • mfrom: (1.2.1) (16.1.1 experimental)
  • Revision ID: package-import@ubuntu.com-20130916194855-sengvtinypyl41ld
Tags: 1.3.0-1
* New upstream release version 1.3.0
 - switched the package back to unstable

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Ruby Bindings for Librhash
3
 
 * Copyright (c) 2011-2012, Sergey Basalaev <sbasalaev@gmail.com>
4
 
 * Librhash is (c) 2011-2012, Aleksey Kravchenko <rhash.admin@gmail.com>
5
 
 * 
6
 
 * Permission is hereby granted, free of charge,  to any person obtaining a copy
7
 
 * of this software and associated documentation files (the "Software"), to deal
8
 
 * in the Software without restriction,  including without limitation the rights
9
 
 * to  use,  copy,  modify,  merge, publish, distribute, sublicense, and/or sell
10
 
 * copies  of  the Software,  and  to permit  persons  to whom  the Software  is
11
 
 * furnished to do so.
12
 
 * 
13
 
 * This library  is distributed  in the hope that it will be useful, but WITHOUT
14
 
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15
 
 * FOR A PARTICULAR PURPOSE. Use it at your own risk!
16
 
 */
17
 
 
18
 
#include <ruby.h>
19
 
#include <rhash/rhash.h>
20
 
 
21
 
/* RHash class. */
22
 
static VALUE cRHash;
23
 
 
24
 
static void rh_free(rhash ctx) {
25
 
        rhash_free(ctx);
26
 
}
27
 
 
28
 
/**
29
 
 * call-seq:
30
 
 *   rhash.update(data) -> RHash
31
 
 *   rhash << data      -> RHash
32
 
 *
33
 
 * Updates this <code>RHash</code> with new data chunk.
34
 
 */
35
 
static VALUE rh_update(VALUE self, VALUE msg) {
36
 
        rhash ctx;
37
 
        Data_Get_Struct(self, struct rhash_context, ctx);
38
 
 
39
 
        if (TYPE(msg) != T_STRING) {
40
 
                msg = rb_obj_as_string(msg); // convert to string
41
 
        }
42
 
 
43
 
        rhash_update(ctx, RSTRING_PTR(msg), RSTRING_LEN(msg));
44
 
        return self;
45
 
}
46
 
 
47
 
/**
48
 
 * call-seq:
49
 
 *   rhash.update_file(filename) -> RHash
50
 
 * 
51
 
 * Updates this <code>RHash</code> with data from given file.
52
 
 */
53
 
static VALUE rh_update_file(VALUE self, VALUE file) {
54
 
        // this function is actually implemented in pure Ruby below
55
 
        // this allows us to handle files in platform-independent way
56
 
        return self;
57
 
}
58
 
 
59
 
/**
60
 
 * call-seq:
61
 
 *   rhash.finish
62
 
 *
63
 
 * Finishes calculation for all data buffered by
64
 
 * <code>update</code> and stops calculation of hashes.
65
 
 */
66
 
static VALUE rh_finish(VALUE self) {
67
 
        rhash ctx;
68
 
        Data_Get_Struct(self, struct rhash_context, ctx);
69
 
        rhash_final(ctx, NULL);
70
 
        return self;
71
 
}
72
 
 
73
 
/**
74
 
 * call-seq:
75
 
 *   rhash.reset
76
 
 *
77
 
 * Resets this RHash to initial state.
78
 
 * The RHash becomes available to process
79
 
 * new data chunks.
80
 
 */
81
 
static VALUE rh_reset(VALUE self) {
82
 
        rhash ctx;
83
 
        Data_Get_Struct(self, struct rhash_context, ctx);
84
 
        rhash_reset(ctx);
85
 
        return self;
86
 
}
87
 
 
88
 
static VALUE rh_print(VALUE self, VALUE type, int flags) {
89
 
        char buf[130];
90
 
        rhash ctx;
91
 
        Data_Get_Struct(self, struct rhash_context, ctx);
92
 
        int len = rhash_print(buf, ctx, type == Qnil ? 0 : FIX2INT(type), flags);
93
 
        return rb_str_new(buf, len);
94
 
}
95
 
 
96
 
/**
97
 
 * call-seq:
98
 
 *   rhash.to_raw(id)
99
 
 *   rhash.to_raw
100
 
 *
101
 
 * Returns value of the RHash digest as raw bytes.
102
 
 * If RHash was created with a single hashing algorithm
103
 
 * then argument may be omitted.
104
 
 */
105
 
static VALUE rh_to_raw(int argc, VALUE* argv, VALUE self) {
106
 
        VALUE type;
107
 
        rb_scan_args(argc, argv, "01", &type);
108
 
        return rh_print(self, type, RHPR_RAW);
109
 
}
110
 
 
111
 
/**
112
 
 * call-seq:
113
 
 *   rhash.to_hex(id)
114
 
 *   rhash.to_hex
115
 
 *
116
 
 * Returns value of the RHash digest as hexadecimal string.
117
 
 * If RHash was created with a single hashing algorithm
118
 
 * then argument may be omitted.
119
 
 */
120
 
static VALUE rh_to_hex(int argc, VALUE* argv, VALUE self) {
121
 
        VALUE type;
122
 
        rb_scan_args(argc, argv, "01", &type);
123
 
        return rh_print(self, type, RHPR_HEX);
124
 
}
125
 
 
126
 
/**
127
 
 * call-seq:
128
 
 *   rhash.to_base32(id)
129
 
 *   rhash.to_base32
130
 
 *
131
 
 * Returns value of the RHash digest as base32 string.
132
 
 * If RHash was created with a single hashing algorithm
133
 
 * then argument may be omitted.
134
 
 */
135
 
static VALUE rh_to_base32(int argc, VALUE* argv, VALUE self) {
136
 
        VALUE type;
137
 
        rb_scan_args(argc, argv, "01", &type);
138
 
        return rh_print(self, type, RHPR_BASE32);
139
 
}
140
 
 
141
 
/**
142
 
 * call-seq:
143
 
 *   rhash.magnet(filepath)
144
 
 *   rhash.magnet
145
 
 *
146
 
 * Returns magnet link with all hashes computed by
147
 
 * the RHash object.
148
 
 * if filepath is specified, then it is url-encoded
149
 
 * and included into the resulting magnet link.
150
 
 */
151
 
static VALUE rh_magnet(int argc, VALUE* argv, VALUE self) {
152
 
        VALUE value;
153
 
        const char* filepath = 0;
154
 
        char* buf;
155
 
        size_t buf_size;
156
 
        rhash ctx;
157
 
 
158
 
        Data_Get_Struct(self, struct rhash_context, ctx);
159
 
 
160
 
        rb_scan_args(argc, argv, "01", &value);
161
 
        if (value != Qnil) {
162
 
                if (TYPE(value) != T_STRING) value = rb_obj_as_string(value);
163
 
                filepath = RSTRING_PTR(value);
164
 
        }
165
 
 
166
 
        buf_size = rhash_print_magnet(0, filepath, ctx, RHASH_ALL_HASHES, RHPR_FILESIZE);
167
 
        buf = (char*)malloc(buf_size);
168
 
        if (!buf) return Qnil;
169
 
 
170
 
        rhash_print_magnet(buf, filepath, ctx, RHASH_ALL_HASHES, RHPR_FILESIZE);
171
 
        value = rb_str_new2(buf);
172
 
        free(buf);
173
 
        return value;
174
 
}
175
 
 
176
 
/**
177
 
 * call-seq:
178
 
 *   rhash.to_base64(id)
179
 
 *   rhash.to_base64
180
 
 *
181
 
 * Returns value of the RHash digest as base64 string.
182
 
 * If RHash was created with a single hashing algorithm
183
 
 * then argument may be omitted.
184
 
 */
185
 
static VALUE rh_to_base64(int argc, VALUE* argv, VALUE self) {
186
 
        VALUE type;
187
 
        rb_scan_args(argc, argv, "01", &type);
188
 
        return rh_print(self, type, RHPR_BASE64);
189
 
}
190
 
 
191
 
/**
192
 
 * call-seq:
193
 
 *   rhash.to_s(id)
194
 
 *   rhash.to_s
195
 
 *
196
 
 * Returns value of the RHash digest for given algorithm
197
 
 * as string in default format. If RHash was created with
198
 
 * a single hashing algorithm then argument may be omitted.
199
 
 */
200
 
static VALUE rh_to_s(int argc, VALUE* argv, VALUE self) {
201
 
        VALUE type;
202
 
        rb_scan_args(argc, argv, "01", &type);
203
 
        return rh_print(self, type, 0);
204
 
}
205
 
 
206
 
/**
207
 
 * call-seq:
208
 
 *   RHash.base32?(id) -> true or false
209
 
 *
210
 
 * Returns true if default format for given hash algorithm is
211
 
 * base32 and false if it is hexadecimal.
212
 
 */
213
 
static VALUE rh_is_base32(VALUE self, VALUE type) {
214
 
        return rhash_is_base32(FIX2INT(type)) ? Qtrue : Qfalse;
215
 
}
216
 
 
217
 
static VALUE rh_init(int argc, VALUE *argv, VALUE self) {
218
 
        return self;
219
 
}
220
 
 
221
 
/**
222
 
 * call-seq:
223
 
 *   RHash.new(id, ...)
224
 
 *
225
 
 * Creates RHash object to calculate hashes for given algorithms.
226
 
 * Parameters should be constants defined in this class.
227
 
 */
228
 
VALUE rh_new(int argc, VALUE* argv, VALUE clz) {
229
 
        int flags = 0, i;
230
 
        for (i=0; i<argc; i++) {
231
 
                flags |= FIX2INT(argv[i]);
232
 
        }
233
 
        if (!flags) flags = RHASH_ALL_HASHES;
234
 
        rhash ctx = rhash_init(flags);
235
 
        rhash_set_autofinal(ctx, 0);
236
 
        VALUE newobj = Data_Wrap_Struct(clz, NULL, rh_free, ctx);
237
 
        rb_obj_call_init(newobj, argc, argv);
238
 
        return newobj;
239
 
}
240
 
 
241
 
/**
242
 
 * Librhash is a library for computing and verifying hash sums
243
 
 * that supports many hashing algorithms. This module provides
244
 
 * class for incremental hashing that utilizes the library.
245
 
 * Sample usage of it you can see from the following example:
246
 
 * 
247
 
 *   hasher = RHash.new(RHash::CRC32, RHash::MD5)
248
 
 *   hasher.update('Hello, ')
249
 
 *   hasher << 'world' << '!'
250
 
 *   hasher.finish
251
 
 *   puts hasher.to_hex RHash::CRC32
252
 
 *   puts hasher.to_base32 RHash::MD5
253
 
 *
254
 
 * which produces
255
 
 *
256
 
 *   ebe6c6e6
257
 
 *   ntjvk3plbwsuxsqgbngdsr4yhe
258
 
 *
259
 
 * In this example <code>RHash</code> object is first created
260
 
 * for a set of hashing algorithms.
261
 
 *
262
 
 * Next, data for hashing is  given  in  chunks  with  methods
263
 
 * <code>update</code> and <code>update_file</code>. Finally,
264
 
 * call <code>finish</code> to end up all remaining calculations.
265
 
 *
266
 
 * To receive text represenation of the message digest use one
267
 
 * of methods <code>to_hex</code>, <code>to_base32</code> and
268
 
 * <code>to_base64</code>. Binary message digest may be obtained
269
 
 * with <code>to_raw</code>. All of these methods accept algorithm
270
 
 * value as argument. It may be omitted if <code>RHash</code> was
271
 
 * created to compute hash for only a single hashing algorithm.
272
 
 */
273
 
void Init_rhash() {
274
 
        rhash_library_init();
275
 
        
276
 
        cRHash = rb_define_class("RHash", rb_cObject);
277
 
        
278
 
        rb_define_singleton_method(cRHash, "new", rh_new, -1);
279
 
        rb_define_singleton_method(cRHash, "base32?", rh_is_base32, 1);
280
 
        
281
 
        rb_define_method(cRHash, "initialize", rh_init,  -1);
282
 
        rb_define_method(cRHash, "update",     rh_update, 1);
283
 
        rb_define_method(cRHash, "<<",         rh_update, 1);
284
 
        rb_define_method(cRHash, "finish",     rh_finish, 0);
285
 
        rb_define_method(cRHash, "reset",      rh_reset,  0);
286
 
        rb_define_method(cRHash, "to_raw",     rh_to_raw, -1);
287
 
        rb_define_method(cRHash, "to_hex",     rh_to_hex, -1);
288
 
        rb_define_method(cRHash, "to_base32",  rh_to_base32, -1);
289
 
        rb_define_method(cRHash, "to_base64",  rh_to_base64, -1);
290
 
        rb_define_method(cRHash, "to_s",       rh_to_s, -1);
291
 
        rb_define_method(cRHash, "magnet",     rh_magnet, -1);
292
 
        
293
 
        rb_eval_string(
294
 
"class RHash \n\
295
 
  def update_file(filename) \n\
296
 
    f = File.open(filename, 'rb') \n\
297
 
    while block = f.read(4096) \n\
298
 
      self.update(block) \n\
299
 
    end \n\
300
 
    self \n\
301
 
  end \n\
302
 
end\n\
303
 
\n\
304
 
def RHash.hash_for_msg(msg, hash_id)\n\
305
 
  RHash.new(hash_id).update(msg).finish.to_s\n\
306
 
end\n\
307
 
\n\
308
 
def RHash.hash_for_file(filename, hash_id)\n\
309
 
  RHash.new(hash_id).update_file(filename).finish.to_s\n\
310
 
end\n\
311
 
\n\
312
 
def RHash.magnet_for_file(filename, *hash_ids)\n\
313
 
  RHash.new(*hash_ids).update_file(filename).finish.magnet(filename)\n\
314
 
end");
315
 
        
316
 
        /** CRC32 checksum. */
317
 
        rb_define_const(cRHash, "CRC32",     INT2FIX(RHASH_CRC32));
318
 
        /** MD4 hash. */
319
 
        rb_define_const(cRHash, "MD4",       INT2FIX(RHASH_MD4));
320
 
        /** MD5 hash. */
321
 
        rb_define_const(cRHash, "MD5",       INT2FIX(RHASH_MD5));
322
 
        /** SHA-1 hash. */
323
 
        rb_define_const(cRHash, "SHA1",      INT2FIX(RHASH_SHA1));
324
 
        /** Tiger hash. */
325
 
        rb_define_const(cRHash, "TIGER",     INT2FIX(RHASH_TIGER));
326
 
        /** Tiger tree hash */
327
 
        rb_define_const(cRHash, "TTH",       INT2FIX(RHASH_TTH));
328
 
        /** BitTorrent info hash. */
329
 
        rb_define_const(cRHash, "BTIH",      INT2FIX(RHASH_BTIH));
330
 
        /** EDonkey 2000 hash. */
331
 
        rb_define_const(cRHash, "ED2K",      INT2FIX(RHASH_ED2K));
332
 
        /** eMule AICH. */
333
 
        rb_define_const(cRHash, "AICH",      INT2FIX(RHASH_AICH));
334
 
        /** Whirlpool hash. */
335
 
        rb_define_const(cRHash, "WHIRLPOOL", INT2FIX(RHASH_WHIRLPOOL));
336
 
        /** RIPEMD-160 hash. */
337
 
        rb_define_const(cRHash, "RIPEMD160", INT2FIX(RHASH_RIPEMD160));
338
 
        /** GOST R 34.11-94. */
339
 
        rb_define_const(cRHash, "GOST",      INT2FIX(RHASH_GOST));
340
 
        /** GOST R 34.11-94. */
341
 
        rb_define_const(cRHash, "GOST_CRYPTOPRO", INT2FIX(RHASH_GOST_CRYPTOPRO));
342
 
        /** HAS-160 hash. */
343
 
        rb_define_const(cRHash, "HAS160",    INT2FIX(RHASH_HAS160));
344
 
        /** Snefru-128 hash. */
345
 
        rb_define_const(cRHash, "SNEFRU128", INT2FIX(RHASH_SNEFRU128));
346
 
        /** Snefru-256 hash. */
347
 
        rb_define_const(cRHash, "SNEFRU256", INT2FIX(RHASH_SNEFRU256));
348
 
        /** SHA-224 hash. */
349
 
        rb_define_const(cRHash, "SHA224",    INT2FIX(RHASH_SHA224));
350
 
        /** SHA-256 hash. */
351
 
        rb_define_const(cRHash, "SHA256",    INT2FIX(RHASH_SHA256));
352
 
        /** SHA-384 hash. */
353
 
        rb_define_const(cRHash, "SHA384",    INT2FIX(RHASH_SHA384));
354
 
        /** SHA-512 hash. */
355
 
        rb_define_const(cRHash, "SHA512",    INT2FIX(RHASH_SHA512));
356
 
        /** EDON-R 256. */
357
 
        rb_define_const(cRHash, "EDONR256",  INT2FIX(RHASH_EDONR256));
358
 
        /** EDON-R 512. */
359
 
        rb_define_const(cRHash, "EDONR512",  INT2FIX(RHASH_EDONR512));
360
 
        /** Create RHash with this parameter to compute hashes for all available algorithms. */
361
 
        rb_define_const(cRHash, "ALL",       INT2FIX(RHASH_ALL_HASHES));
362
 
}
363