phoenix_password 1.0.0 → 1.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.
@@ -0,0 +1,799 @@
1
+ require "./phoenix_password/version"
2
+ require_relative 'realistic'
3
+
4
+ class PhoenixPassword
5
+ prepend Realistic
6
+
7
+ def initialize(data={})
8
+ @rules=data[:rules]
9
+ @strictness=data[:strictness] ? data[:strictness] : 0
10
+ @own_rules=data[:own_rules] if data[:own_rules].is_a?(Array) && data[:own_rules][0].is_a?(Regexp)
11
+ end
12
+
13
+ def generate_combinations(data)
14
+ characters=data[:characters]
15
+ if !data[:extra_chars].nil?
16
+ characters.push(data[:extra_chars][data[:iteration]-1]) if data[:iteration] != 0
17
+ end
18
+ combination=Array.new(data[:cmb_length],data[:characters].first)
19
+ combination_length=combination.length
20
+ i=0
21
+ possible_combinations=characters.length**combination_length
22
+ chars_used=Array.new(data[:cmb_length],0)
23
+
24
+ while i < possible_combinations/characters.length
25
+ x=1
26
+ change_count=1
27
+ while x < combination_length
28
+ if chars_used[x] == characters.length
29
+ chars_used[x] = 0
30
+ end
31
+ if combination[x] == characters.last && combination[x+1] == characters.last
32
+ change_count +=1
33
+ if change_count == combination_length -1
34
+ chars_used[0] += 1
35
+ end
36
+ end
37
+ x +=1
38
+ end
39
+
40
+ y=0
41
+ until y == combination_length
42
+ combination[y]=characters[chars_used[y]]
43
+ y+=1
44
+ end
45
+
46
+ combinations=add_combinations({:combination=>combination,:extra_chars=>data[:extra_chars],
47
+ :characters=>characters,:cmb_length=>data[:cmb_length],:type=>data[:type]})
48
+ yield(combinations) if combinations.length >= 1
49
+
50
+ z=combination_length-1
51
+ while 1 < z
52
+ if z == combination_length-1
53
+ chars_used[z-1] +=1 if combination[z] == characters.last
54
+ else
55
+ diff=(combination_length-1)-z
56
+ last_chars=0
57
+ count_diff=1
58
+ while count_diff <= diff
59
+ if combination[z] == characters.last && combination[z+count_diff] == characters.last
60
+ last_chars +=1
61
+ end
62
+ count_diff +=1
63
+ end
64
+ if last_chars == (combination_length-1)-z
65
+ chars_used[z-1] +=1
66
+ end
67
+ end
68
+ z-=1
69
+ end
70
+ chars_used[combination_length-1] +=1
71
+ i+=1
72
+ end
73
+ return characters
74
+ end
75
+
76
+ def add_combinations(data)
77
+
78
+ combinations=[]
79
+ combination=data[:combination]
80
+ characters=data[:characters]
81
+ if data[:extra_chars].nil? || data[:iteration] == 0
82
+ if @rules
83
+ combinations.<<(combination.join()) if rules_pass?({:combination=>combination.join(),:cmb_length=>data[:cmb_length]})
84
+ else
85
+ combinations.<<(combination.join())
86
+ end
87
+ if combination.last != characters.first
88
+ reverse_comb=combination.reverse
89
+ if @rules
90
+ combinations.<<(reverse_comb.join()) if rules_pass?({:combination=>reverse_comb.join(),:cmb_length=>data[:cmb_length]-1})
91
+ else
92
+ combinations.<<(reverse_comb.join())
93
+ end
94
+ reverse_comb.pop
95
+ reverse_compare=reverse_comb
96
+ reverse_comb=reverse_comb.join()
97
+ check_match= matching_check({:combination=>reverse_comb,:match_limit=>data[:match_limit],:cap_limit=>data[:cap_limit]})
98
+ characters.each do |char|
99
+ next if char == characters.first
100
+ if data[:type] == "unique"
101
+ if @rules
102
+ combinations.<<("%s%s"%[reverse_comb,char]) if rules_pass?({:combination=>"%s%s"%[reverse_comb,char],:cmb_length=>data[:cmb_length]})
103
+ else
104
+ combinations.<<("%s%s"%[reverse_comb,char])
105
+ end
106
+ else
107
+ if check_match
108
+ if @rules
109
+ combinations.<<("%s%s"%[reverse_comb,char]) if rules_pass?({:combination=>"%s%s"%[reverse_comb,char],:cmb_length=>data[:cmb_length]})
110
+ else
111
+ combinations.<<("%s%s"%[reverse_comb,char])
112
+ end
113
+ else
114
+ if @rules
115
+ combinations.<<("%s%s"%[reverse_comb,char]) if char == reverse_compare.last && rules_pass?({:combination=>"%s%s"%[reverse_comb,char],:cmb_length=>data[:cmb_length]})
116
+ else
117
+ combinations.<<("%s%s"%[reverse_comb,char]) if char == reverse_compare.last
118
+ end
119
+ end
120
+ end
121
+ end
122
+ end
123
+
124
+ else
125
+ combinations << combination.join() if combination.include?(characters.last)
126
+ if combination.last != characters.first
127
+ reverse_comb=combination.reverse
128
+ reverse_comb.pop
129
+ reverse_compare=reverse_comb
130
+ reverse_comb=reverse_comb.join
131
+ if reverse_comb.include?(characters.last)
132
+ check_match= matching_check({:combination=>reverse_comb,:match_limit=>data[:match_limit],:cap_limit=>data[:cap_limit]}) if data[:type] == 'matching'
133
+ characters.each do |char|
134
+ if data[:type] == "unique"
135
+ combinations.<<("%s%s"%[reverse_comb,char])
136
+ elsif check_match
137
+ combinations.<<("%s%s"%[reverse_comb,char])
138
+ else
139
+ combinations.<<("%s%s"%[reverse_comb,char]) if char == reverse_compare.last
140
+ end
141
+ end
142
+ else
143
+ combinations.<<("%s%s"%[reverse_comb,characters.last])
144
+ end
145
+ end
146
+ end
147
+ return combinations
148
+ end
149
+
150
+ def matching_combinations(info)
151
+ data={:characters=>info[:characters],:cmb_length=>info[:cmb_length],:type=>info[:type]}
152
+ unless info[:extra_chars].nil?
153
+ data[:extra_chars]=info[:extra_chars]
154
+ end
155
+
156
+ matching_file=create_file(info) if !info[:piped]
157
+
158
+ char_sum=data[:characters].length
159
+ total_characters=data[:characters].length
160
+ unless data[:extra_chars].nil?
161
+ total_characters=data[:characters].length+data[:extra_chars].length
162
+ data[:iteration]=0
163
+ if info[:skip_first] || !info[:piped]
164
+ data[:iteration] +=1
165
+ char_sum +=1
166
+ end
167
+ end
168
+
169
+ matching=0
170
+ begin
171
+ generate_combinations(data) do |combinations|
172
+ combinations.each do |combination|
173
+ if matching_check({:combination=>combination,:match_limit=>info[:match_limit],:cap_limit=>info[:cap_limit]})
174
+ if info[:piped]
175
+ puts combination
176
+ else
177
+ matching_file.puts(combination)
178
+ end
179
+ matching +=1
180
+ end
181
+ end
182
+ end
183
+ data[:iteration]+=1 unless data[:iteration].nil?
184
+ char_sum +=1
185
+ rescue => e
186
+ raise
187
+ end while char_sum <= total_characters
188
+ matching_file.close unless matching_file.nil?
189
+ return matching
190
+ end
191
+
192
+ def matching_check(info)
193
+ combination=info[:combination]
194
+ if info[:cap_limit]
195
+ caps=combination.scan(/[A-Z]/)
196
+ return false if caps.length == 0 || caps.length > info[:cap_limit]
197
+ end
198
+ i=0
199
+ x=0
200
+ u=0
201
+ while i < (combination.length-1)
202
+ if combination[i] == combination[i+1]
203
+ return true if info[:match_limit].nil?
204
+ if i == 0
205
+ x +=1
206
+ elsif combination[i] == combination[i-1] || combination[i] == combination[i+info[:match_limit]]
207
+ x+=1
208
+ end
209
+ else
210
+ u +=1
211
+ end
212
+ if x == info[:match_limit] || u == combination.length-1
213
+ return false
214
+ end
215
+ i+=1
216
+ end
217
+ return true
218
+ end
219
+
220
+ def unique_combinations(info)
221
+ data={:characters=>info[:characters],:cmb_length=>info[:cmb_length],:type=>info[:type],:uniqueness_type=>info[:uniqueness_type]}
222
+ unless info[:extra_chars].nil?
223
+ data[:extra_chars]=info[:extra_chars]
224
+ end
225
+
226
+ unique_file=create_file(info) unless info[:piped]
227
+
228
+ total_characters=data[:characters].length
229
+ char_sum= data[:characters].length
230
+ unless data[:extra_chars].nil?
231
+ total_characters=data[:characters].length+data[:extra_chars].length
232
+ data[:iteration]=0
233
+ if info[:skip_first] || !info[:piped]
234
+ data[:iteration]+=1
235
+ char_sum +=1
236
+ end
237
+ end
238
+ unique_combs=0
239
+ uniqueness=info[:uniqueness_type]
240
+ begin
241
+ generate_combinations(data) do |combinations|
242
+ combinations.each do |combination|
243
+ unique_chars=check_uniqueness(combination,uniqueness,info[:cap_limit])
244
+ if unique_chars == combination.length-1
245
+ if info[:piped]
246
+ puts combination
247
+ else
248
+ unique_file.puts(combination)
249
+ end
250
+ unique_combs= unique_combs+1
251
+ end
252
+ end
253
+ end
254
+ data[:iteration] +=1 if !data[:iteration].nil?
255
+ char_sum +=1
256
+ rescue => e
257
+ raise
258
+ end while char_sum <= total_characters
259
+
260
+ unless unique_file.nil?
261
+ unique_file.close
262
+ end
263
+
264
+ return unique_combs
265
+ end
266
+
267
+ def check_uniqueness(combination,uniqueness,cap_limit)
268
+ if cap_limit
269
+ caps=combination.scan(/[A-Z]/)
270
+ return 0 if caps.length == 0 || caps.length > cap_limit
271
+ end
272
+ i=0
273
+ unique_chars=0
274
+ chars_check=[]
275
+ while i < (combination.length-1)
276
+ if combination[i] != combination[i+1]
277
+ if uniqueness.nil?
278
+ unique_chars+=1
279
+ elsif uniqueness == "single"
280
+ if i == 0
281
+ unique_chars+=1
282
+ chars_check.push(combination[i])
283
+ elsif !chars_check.include?(combination[i])
284
+ chars_check << combination[i]
285
+ if !chars_check.include?(combination[i+1])
286
+ unique_chars +=1
287
+ else
288
+ return 0
289
+ end
290
+ end
291
+ elsif uniqueness == "repeat"
292
+ if i == 0
293
+ unique_chars+=1
294
+ chars_check.push(combination[i])
295
+ elsif chars_check.include?(combination[i])
296
+ unique_chars+=1
297
+ elsif i == (combination.length-2)
298
+ #since in last iteration compare against the next character as well
299
+ unique_chars +=1 if chars_check.include?(combination[i]) || chars_check.include?(combination[i+1])
300
+ else
301
+ chars_check.push(combination[i])
302
+ end
303
+
304
+ return combination.length-1 if i == (combination.length-2) && unique_chars > 1
305
+ end
306
+ else
307
+ return 0
308
+ end
309
+ i+=1
310
+ end
311
+ return unique_chars
312
+ end
313
+
314
+ def get_single_combs(data)
315
+ i=0
316
+ single_combinations=0
317
+ extra_singe=0
318
+ extra_chars=data[:characters].length+data[:extra_chars].length if !data[:extra_chars].nil?
319
+ while i < data[:cmb_length]-1
320
+ if i == 0
321
+ single_combinations=(data[:characters].length-1)*data[:characters].length
322
+ extra_singe=extra_chars*(extra_chars-1) if !extra_chars.nil?
323
+ else
324
+ single_combinations=single_combinations*(data[:characters].length-(i+1))
325
+ extra_singe=extra_singe*(extra_chars-(i+1)) if !extra_chars.nil?
326
+ end
327
+ i+=1
328
+ end
329
+ return extra_singe - single_combinations if !data[:extra_chars].nil?
330
+ return single_combinations
331
+ end
332
+
333
+ def get_combinations(data)
334
+ if data[:extra_chars].nil?
335
+ base=data[:characters].length
336
+ else
337
+ old_base=data[:characters].length
338
+ old_combinations=old_base**data[:cmb_length]
339
+ x=0
340
+ post_matches=0
341
+ while x < data[:cmb_length]-1
342
+ if x == 0
343
+ post_matches=old_base
344
+ elsif x == 1
345
+ post_matches=(old_base**x)+(1*(old_base-1))
346
+ else
347
+ post_matches=(old_base**x)+(post_matches*(old_base-1))
348
+ end
349
+ x+=1
350
+ end
351
+ old_matches=old_base*post_matches
352
+ base=data[:characters].length+data[:extra_chars].length
353
+ end
354
+ previous_matches=0
355
+ i=0
356
+
357
+ while i < data[:cmb_length]-1
358
+ if i==0
359
+ previous_matches=base
360
+ elsif i== 1
361
+ previous_matches=(base**i)+(1*(base-1))
362
+ else
363
+ previous_matches=(base**i)+(previous_matches*(base-1))
364
+ end
365
+ i+=1
366
+ end
367
+ matches=base*previous_matches
368
+
369
+ if data[:type]=='unique'
370
+ possible_combinations=base**data[:cmb_length]
371
+ if data[:uniqueness_type].nil?
372
+ return (possible_combinations-matches)-(old_combinations-old_matches) if !data[:extra_chars].nil?
373
+ return possible_combinations-matches
374
+ else
375
+ single_combs=get_single_combs(data)
376
+ if data[:uniqueness_type]=="single"
377
+ return single_combs
378
+ elsif data[:uniqueness_type]=="repeat"
379
+ return ((possible_combinations-matches)-(old_combinations-old_matches))-single_combs if !data[:extra_chars].nil?
380
+ return (possible_combinations-matches)-single_combs
381
+ end
382
+ end
383
+ else
384
+ return matches-old_matches if !data[:extra_chars].nil?
385
+ return matches
386
+ end
387
+ return 0
388
+ end
389
+
390
+ def get_above_limit(data)
391
+ if data[:extra_chars].nil?
392
+ base=data[:characters].length
393
+ else
394
+ old_base=data[:characters].length
395
+ previous_matches=0
396
+ previous_mult=0
397
+ i=0
398
+ while i < (data[:cmb_length] -1)
399
+ if i == (data[:match_limit]-1)
400
+ previous_matches=old_base
401
+ old_matches=previous_matches
402
+ elsif i == data[:match_limit]
403
+ previous_matches=previous_matches+(1*(old_base-1))
404
+ previous_mult=1
405
+ else
406
+ temp_mult=previous_matches
407
+ previous_matches=(old_base**(i-1)+previous_mult*(old_base-1))+(previous_matches*(old_base-1))
408
+ previous_mult=temp_mult
409
+ end
410
+
411
+ i+=1
412
+ end
413
+
414
+ old_matches=old_base*previous_matches if data[:cmb_length] != (data[:match_limit]+1)
415
+ base=data[:characters].length+data[:extra_chars].length
416
+ end
417
+
418
+ previous_matches=0
419
+ previous_mult=0
420
+ i=1
421
+ while i < (data[:cmb_length] -1)
422
+ if i == (data[:match_limit]-1)
423
+ previous_matches=base
424
+ return previous_matches if data[:cmb_length] == (data[:match_limit]+i) && data[:extra_chars].nil?
425
+ elsif i == data[:match_limit]
426
+ previous_matches=previous_matches+(1*(base-1))
427
+ previous_mult=1
428
+ else
429
+ temp_mult=previous_matches
430
+ previous_matches=(base**(i-1))+(previous_mult*(base-1))+(previous_matches*(base-1))
431
+ previous_mult=temp_mult
432
+
433
+ end
434
+ i+=1
435
+ end
436
+
437
+ unless data[:extra_chars].nil?
438
+ return base-old_base if data[:cmb_length] == (data[:match_limit]+1)
439
+ return (base*previous_matches)-old_matches
440
+ else
441
+ return base*previous_matches
442
+ end
443
+ end
444
+
445
+ def cap_limit_matching(data)
446
+ cap_data={}
447
+ total_chars=data[:characters].join()
448
+ caps_matched= total_chars.scan(/[A-Z]/)
449
+ cap_data[:characters]=[]
450
+ data[:characters].each do |char|
451
+ next if caps_matched.include?(char)
452
+ cap_data[:characters].push(char)
453
+ end
454
+ base=cap_data[:characters].length
455
+ cap_matches=0
456
+ case data[:cmb_length]
457
+ when 3
458
+ cap_matches += base*2
459
+ when 4
460
+ cap_matches+=get_combinations({:characters=>cap_data[:characters],:cmb_length=>data[:cmb_length]-1})*2
461
+ cap_matches+=(base**2)*2
462
+ else
463
+ cap_matches+=get_combinations({:characters=>cap_data[:characters],:cmb_length=>data[:cmb_length]-1})*2
464
+ cap_matches+=(get_combinations({:characters=>cap_data[:characters],:cmb_length=>data[:cmb_length]-2})*base)*(data[:cmb_length]-2)
465
+ end
466
+
467
+ if !data[:extra_chars].nil?
468
+ all_chars=data[:characters]+data[:extra_chars]
469
+ new_cap_matches=cap_limit_matching({:cmb_length=>data[:cmb_length],:characters=>all_chars})
470
+ return new_cap_matches-(cap_matches*caps_matched.length)
471
+ else
472
+ return cap_matches*caps_matched.length
473
+ end
474
+
475
+ end
476
+
477
+ def cap_limit_matching_l(data)
478
+ cap_data={}
479
+ total_chars=data[:characters].join()
480
+ caps_matched= total_chars.scan(/[A-Z]/)
481
+ cap_data[:characters]=[]
482
+ data[:characters].each do |char|
483
+ next if caps_matched.include?(char)
484
+ cap_data[:characters].push(char)
485
+ end
486
+ base=cap_data[:characters].length
487
+ cap_matches=0
488
+ no_limit_matches=get_combinations({:characters=>cap_data[:characters],:cmb_length=>data[:cmb_length]-1})
489
+ case data[:cmb_length]
490
+ when 3
491
+ cap_matches += base*2
492
+ when 4
493
+ cap_matches+=(no_limit_matches-get_above_limit({:characters=>cap_data[:characters],:cmb_length=>data[:cmb_length]-1,:match_limit=>data[:match_limit]}))*2
494
+ cap_matches+=(base**2)*2
495
+ else
496
+
497
+ #XXA
498
+ cap_matches+=(no_limit_matches-get_above_limit({:characters=>cap_data[:characters],:cmb_length=>data[:cmb_length]-1,:match_limit=>data[:match_limit]}))*2
499
+ no_limit_matches=get_combinations({:characters=>cap_data[:characters],:cmb_length=>data[:cmb_length]-2})
500
+ #XAX
501
+ cap_matches+=((no_limit_matches-get_above_limit({:characters=>cap_data[:characters],:cmb_length=>data[:cmb_length]-2,:match_limit=>data[:match_limit]}))*base)*2
502
+ x=data[:cmb_length]-4
503
+ if x == 1
504
+ cap_matches +=get_combinations({:characters=>cap_data[:characters],:cmb_length=>data[:cmb_length]-2})*base
505
+ elsif x == 2
506
+ grt_half_no_limit=get_combinations({:characters=>cap_data[:characters],:cmb_length=>data[:cmb_length]-3})
507
+ grt_half_limit =grt_half_no_limit-get_above_limit({:characters=>cap_data[:characters],:match_limit=>data[:match_limit],:cmb_length=>data[:cmb_length]-3})
508
+ cap_matches +=(((grt_half_limit*base**2)+(base*base**3))-(grt_half_no_limit*base))*2
509
+ else
510
+ #AXX
511
+ i=3
512
+ p=0
513
+ l=0
514
+ begin
515
+ grt_half=get_combinations({:characters=>cap_data[:characters],:cmb_length=>data[:cmb_length]-(3+l)})
516
+ grt_half_limit =grt_half-get_above_limit({:characters=>cap_data[:characters],:match_limit=>data[:match_limit],:cmb_length=>data[:cmb_length]-(3+l)})
517
+ if i == 3
518
+ if data[:cmb_length] <=8
519
+ cap_matches +=(((grt_half_limit*base**2)+(base*base**(x+1)))-(grt_half*base))*2
520
+ else
521
+ cap_matches +=((grt_half_limit*((base**2)-base))+(base*base**(x+1)))*2
522
+
523
+ end
524
+ else
525
+ lsr_half=get_combinations({:characters=>cap_data[:characters],:cmb_length=>i-1})
526
+ lsr_half_limit=lsr_half-get_above_limit(:characters=>cap_data[:characters],:match_limit=>data[:match_limit],:cmb_length=>i-1)
527
+ cap_matches +=(((grt_half_limit*(base**(2+p)))+(lsr_half_limit*base**(x+1-p)))-(grt_half*lsr_half))*2
528
+
529
+ end
530
+ p+=1
531
+ l+=1
532
+ i+=1
533
+ end while i < (data[:cmb_length]/2.0).ceil
534
+
535
+
536
+
537
+ if x%2 == 1
538
+ no_limit_matches=get_combinations({:characters=>cap_data[:characters],:cmb_length=>x-(p-1)})
539
+ half_point=(((no_limit_matches-get_above_limit({:characters=>cap_data[:characters],:cmb_length=>x-(p-1),:match_limit=>data[:match_limit]})))*base**(x-(p-1)))*2
540
+ if data[:cmb_length] == 7
541
+ cap_matches+=half_point-((half_point/base))
542
+ else
543
+ half_no_limit=get_combinations(:characters=>cap_data[:characters],:cmb_length=>x-1)
544
+ half_no_limit_b=get_combinations(:characters=>cap_data[:characters],:cmb_length=>x-2)
545
+
546
+ if data[:cmb_length] >= 9 && data[:extra_chars].nil?
547
+ puts "!------Approximately less than------!"
548
+ end
549
+ cap_matches+=half_point-((half_point/base))
550
+
551
+ end
552
+
553
+ else
554
+ no_limit_matches_a=get_combinations({:characters=>cap_data[:characters],:cmb_length=>(x-l)+1})
555
+ greater_half=(((no_limit_matches_a-get_above_limit({:characters=>cap_data[:characters],:cmb_length=>(x-l)+1,:match_limit=>data[:match_limit]})))*base**(x-l))
556
+ no_limit_matches_b=get_combinations({:characters=>cap_data[:characters],:cmb_length=>(x-l)})
557
+ lesser_half=(((no_limit_matches_b-get_above_limit({:characters=>cap_data[:characters],:cmb_length=>(x-l),:match_limit=>data[:match_limit]})))*base**(x-l+1))
558
+
559
+ if data[:cmb_length] == 10 && data[:extra_chars].nil?
560
+ puts "!------Approximately less than------!"
561
+ elsif data[:cmb_length] == 12 && data[:extra_chars].nil?
562
+ puts "!------Approximately more than------!"
563
+ end
564
+ cap_matches+=((greater_half+lesser_half)-((no_limit_matches_a*no_limit_matches_b)-(no_limit_matches_b*base)))*2
565
+ end
566
+
567
+ end
568
+
569
+ end
570
+
571
+ if (cap_data[:characters].length <= 2 || data[:cmb_length] >= 13) && data[:extra_chars].nil?
572
+ puts "!!!----Inaccurate information----!!!"
573
+ end
574
+
575
+ if !data[:extra_chars].nil?
576
+ all_chars=data[:characters]+data[:extra_chars]
577
+ new_cap_matches=cap_limit_matching_l({:cmb_length=>data[:cmb_length],:characters=>all_chars,:match_limit=>data[:match_limit]})
578
+ return new_cap_matches-(cap_matches*caps_matched.length)
579
+ else
580
+ return cap_matches*caps_matched.length
581
+ end
582
+ end
583
+
584
+ def unique_cap_limit(data)
585
+ cap_data={}
586
+ total_chars=data[:characters].join()
587
+ caps_matched= total_chars.scan(/[A-Z]/)
588
+ cap_data[:characters]=[]
589
+ data[:characters].each do |char|
590
+ next if caps_matched.include?(char)
591
+ cap_data[:characters].push(char)
592
+ end
593
+ base=cap_data[:characters].length
594
+ unique_cap_limit=0
595
+ if data[:uniqueness_type] == 'single'
596
+ if data[:cmb_length] == 3
597
+ unique_cap_limit=(((base**2)-(base))*3)
598
+ else
599
+ previous_single=get_single_combs(:characters=>cap_data[:characters],:cmb_length=>data[:cmb_length]-1,:type=>"unique")
600
+ unique_cap_limit=previous_single*data[:cmb_length]
601
+ end
602
+ else
603
+ case data[:cmb_length]
604
+ when 3
605
+ if data[:uniqueness_type].nil?
606
+ unique_cap_limit=((base**2)*3)-(base*2)
607
+ else
608
+ unique_cap_limit=((base**2)*3)-(base*2)-(((base**2)-(base))*3)
609
+ end
610
+ when 4
611
+ previous_unique=get_combinations(:characters=>cap_data[:characters],:cmb_length=>data[:cmb_length]-1,:type=>"unique")
612
+ if data[:uniqueness_type].nil?
613
+ unique_cap_limit=(previous_unique*2)+((((base**2)-base)*base)*2)
614
+ else
615
+ previous_single=get_single_combs(:characters=>cap_data[:characters],:cmb_length=>data[:cmb_length]-1,:type=>"unique")
616
+ unique_cap_limit=(previous_unique*2)+((((base**2)-base)*base)*2)-(previous_single*data[:cmb_length])
617
+ end
618
+ else
619
+ previous_unique_a=get_combinations(:characters=>cap_data[:characters],:cmb_length=>data[:cmb_length]-1,:type=>"unique")
620
+ previous_unique_b=get_combinations(:characters=>cap_data[:characters],:cmb_length=>data[:cmb_length]-2,:type=>"unique")
621
+ if data[:uniqueness_type].nil?
622
+ unique_cap_limit=(previous_unique_a*2)+((previous_unique_b*base)*(data[:cmb_length]-2))
623
+ else
624
+ previous_single=get_single_combs(:characters=>cap_data[:characters],:cmb_length=>data[:cmb_length]-1,:type=>"unique")
625
+ unique_cap_limit=(previous_unique_a*2)+((previous_unique_b*base)*(data[:cmb_length]-2))-(previous_single*data[:cmb_length])
626
+ end
627
+ end
628
+ end
629
+
630
+ if !data[:extra_chars].nil?
631
+ all_chars=data[:characters]+data[:extra_chars]
632
+ new_unique_cap_limit=unique_cap_limit({:cmb_length=>data[:cmb_length],:characters=>all_chars,:uniqueness_type=>data[:uniqueness_type]})
633
+ return new_unique_cap_limit-(unique_cap_limit*caps_matched.length)
634
+ else
635
+ return unique_cap_limit*caps_matched.length
636
+ end
637
+
638
+ end
639
+
640
+ def cap_limit_combs(data,x=0)
641
+ if data[:type] == "matching"
642
+ if !data[:match_limit].nil?
643
+ puts "Combinations and file size may vary when using match_limit" if x == 0
644
+ cap_limit_matching_l(data)
645
+ else
646
+ cap_limit_matching(data)
647
+ end
648
+ else
649
+ unique_cap_limit(data)
650
+ end
651
+ end
652
+
653
+ def get_size(data)
654
+ bytes=data[:combinations]*(data[:cmb_length]+1)
655
+ kilo_bytes=bytes/1000.0
656
+ mega_bytes=kilo_bytes/1000.0
657
+ giga_bytes=mega_bytes/1000.0
658
+ tera_bytes=giga_bytes/1000.0
659
+ peta_bytes=tera_bytes/1000.0
660
+ all_sizes= {:bytes=>bytes,:kilo=>kilo_bytes,:mega=>mega_bytes,:giga=>giga_bytes,:tera=>tera_bytes,:peta=>peta_bytes}
661
+ return_sizes= {}
662
+ all_sizes.each do |key,value|
663
+ if kilo_bytes < 1
664
+ return_sizes[key]=value
665
+ break
666
+ end
667
+ return_sizes[key]=value if value > 0.01 && key != :bytes
668
+ end
669
+ yield(return_sizes) if block_given?
670
+ return return_sizes
671
+ end
672
+
673
+
674
+ def create_file(data)
675
+ continue=file_info(data)
676
+ case continue
677
+ when /(y|Y)/
678
+ if data[:file_append]
679
+ return File.open("#{data[:file_append]}.txt","a")
680
+ else
681
+ puts "Creating file"
682
+ print "Enter save file name:"
683
+ file_name=gets.chomp
684
+ data[:file_append]=file_name if !data[:file_append].nil?
685
+ return File.open("#{file_name}.txt","w")
686
+ end
687
+
688
+ when /(n|N)/
689
+ puts "Goodbye"
690
+ exit
691
+ else
692
+ puts "Invalid option"
693
+ exit
694
+ end
695
+ end
696
+
697
+ def file_info(data)
698
+ if data[:file_append].nil? || !data[:file_append]
699
+ if data[:write_cmbs].nil?
700
+ poss_combs=get_combinations(data)
701
+ if !data[:match_limit].nil?
702
+ if !data[:cap_limit].nil?
703
+ poss_combs=cap_limit_combs(data)
704
+ else
705
+ poss_combs -= get_above_limit(data)
706
+ end
707
+ elsif !data[:cap_limit].nil?
708
+ poss_combs=cap_limit_combs(data)
709
+ end
710
+ matching_file_size=get_size({:cmb_length=>data[:cmb_length],:combinations=>poss_combs})
711
+ else
712
+ poss_combs=0
713
+ matching_file_size={:bytes=>0,:kilo=>0,:mega=>0,:giga=>0,:tera=>0,:peta=>0}
714
+ dataB=data.clone
715
+ cmb_count=data[:write_cmbs].length if !data[:cap_limit].nil?
716
+ data[:write_cmbs].each do |n|
717
+ dataB[:cmb_length]=n
718
+ if data[:cap_limit].nil?
719
+ current_combs=get_combinations(dataB)
720
+ poss_combs +=current_combs
721
+ unless data[:match_limit].nil?
722
+ poss_combs -= get_above_limit(dataB)
723
+ current_combs -= get_above_limit(dataB)
724
+ end
725
+ else
726
+ current_combs=cap_limit_combs(dataB,cmb_count)
727
+ cmb_count -= 1
728
+ poss_combs +=cap_limit_combs(dataB,cmb_count)
729
+ end
730
+ get_size({:cmb_length=>n,:combinations=>current_combs})do |sizes|
731
+ sizes.each do |key,value|
732
+ matching_file_size[key] +=value
733
+ end
734
+ matching_file_size[:bytes]=0 if matching_file_size[:kilo] >= 1
735
+ end
736
+ end
737
+ end
738
+ puts "Possible #{data[:type]} combinations #{poss_combs}."
739
+ size_string="File size:"
740
+ matching_file_size.each do |key,value|
741
+ next if value == 0
742
+ size_string += " #{"%.2f"% value}#{key.capitalize}#{'Bytes' if key != :bytes}"
743
+ end
744
+ puts size_string
745
+ puts "Do you wish to continue ?"
746
+ puts "y|Y n|N"
747
+ return gets.chomp
748
+
749
+ elsif data[:file_append]
750
+ return "y"
751
+ end
752
+ end
753
+
754
+ def multi_length(data)
755
+ dataB=data.clone
756
+ i=0
757
+ while i < data[:cmb_length].length
758
+ dataB[:cmb_length] = data[:cmb_length][i]
759
+ dataB[:characters]=data[:characters].clone
760
+ if data[:type] == 'unique'
761
+ unique_combinations(dataB)
762
+ elsif data[:type] == 'matching'
763
+ matching_combinations(dataB)
764
+ end
765
+
766
+ i+=1
767
+ end
768
+ end
769
+
770
+ def combinations(data)
771
+ @type=data[:type]
772
+ puts "File size estimates are invalid when
773
+ using rules" if @rules && data[:piped]
774
+ case data[:type]
775
+ when "matching"
776
+ if data[:cmb_length].length == 1
777
+ data[:cmb_length]=data[:cmb_length][0]
778
+ matching_combinations(data)
779
+ else
780
+ data[:file_append]=false
781
+ data[:write_cmbs]=data[:cmb_length].clone
782
+ multi_length(data)
783
+ end
784
+
785
+ when "unique"
786
+ if data[:cmb_length].length == 1
787
+ data[:cmb_length]=data[:cmb_length].first
788
+ unique_combinations(data)
789
+ else
790
+ data[:file_append]=false
791
+ data[:write_cmbs]=data[:cmb_length].clone
792
+ multi_length(data)
793
+ end
794
+ else
795
+ puts "Invalid combination type"
796
+ exit
797
+ end
798
+ end
799
+ end