]> gitweb.michael.orlitzky.com - dead/whatever-dl.git/blob - src/websites/megaporn.rb
bbd55c273505580d39b1ecbe21d99c6360941634
[dead/whatever-dl.git] / src / websites / megaporn.rb
1 #
2 # Copyright Michael Orlitzky
3 #
4 # http://michael.orlitzky.com/
5 #
6 # This program is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
10 #
11 # This program 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
14 # GNU General Public License for more details.
15 #
16 # http://www.fsf.org/licensing/licenses/gpl.html
17 #
18
19 # jcode still needed for String.each_char in Ruby 1.8.6.
20 require 'jcode'
21 require 'src/website'
22
23 class Megaporn < Website
24
25 VALID_MEGAPORN_URL_REGEX = /^(http:\/\/)?(www\.)?(megaporn|megavideo)\.com\/video\/\?v=[[:alnum:]]+$/
26
27 def self.owns_url?(url)
28 return url =~ VALID_MEGAPORN_URL_REGEX
29 end
30
31
32 def get_video_filename
33 # Just use the video id.
34 id_regex = /v=([[:alnum:]]+)/
35 matches = id_regex.match(@url)
36
37 if (matches.nil? || matches.length < 2)
38 return 'default.flv'
39 else
40 return (matches[1] + '.flv')
41 end
42 end
43
44
45 def get_video_url()
46 data = get_page_data(@url)
47
48 # Megaporn attaches a numeric suffix to their 'www'
49 # hostname that (I suppose) is necessary to find the
50 # video file. The suffix is simply provided as a flash
51 # variable, though.
52 host_suffix = parse_flash_variable(data, 's')
53
54 # There are also two or three keys, sent as Flash variables,
55 # that are used in the "decryption" routine. We get integers
56 # to be on the safe side.
57 key1 = parse_flash_variable(data, 'k1').to_i
58 key2 = parse_flash_variable(data, 'k2').to_i
59
60 # This is a magic hex string, passed to the decryption
61 # routine along with key1 and key2.
62 seed = parse_flash_variable(data, 'un')
63
64 secret_path = self.decrypt(seed, key1, key2)
65
66 # Note that the path to the video file looks like a folder.
67 # We need to remember to save it as a file.
68 return "http://www#{host_suffix}.#{self.domain}/videos/#{secret_path}/"
69 end
70
71
72 protected
73
74 def domain
75 # I'm guessing they serve videos from both of these domains.
76 if (@url.include?('megavideo.com'))
77 return 'megavideo.com'
78 else
79 return 'megaporn.com'
80 end
81 end
82
83
84 def parse_flash_variable(data, variable_name)
85 # The Flash variables differ only in name, so this method can
86 # parse them all.
87 var_regex = /flashvars\.#{variable_name} = \"(.+?)\"/
88 matches = var_regex.match(data)
89
90 if (matches.nil? || matches.length < 2)
91 raise StandardError.new("Could not parse Flash variable: #{variable_name}.")
92 end
93
94 return matches[1]
95 end
96
97
98 def string_to_binary_array(target_string)
99 binary_array = []
100
101 target_string.each_char do |c|
102 binary_int = c.to_i(16).to_s(2).to_i
103 binary_char = sprintf('%04d', binary_int)
104 binary_char.each_char do |bc|
105 binary_array << bc
106 end
107 end
108
109 return binary_array
110 end
111
112
113 def binary_words_to_hex(target_array)
114 hex = ''
115
116 target_array.each do |word|
117 hex << word.to_i(2).to_s(16)
118 end
119
120 return hex
121 end
122
123
124 def decrypt(seed, key1, key2)
125 # I reverse-engineered this one myself. Suck it, megaporn.
126 #
127 # Round 1. Convert the seed to its binary reprentation,
128 # storing each bit as an element of an array.
129 loc1 = string_to_binary_array(seed)
130
131 # Round 2
132 loc6 = []
133 key1 = key1.to_i
134 key2 = key2.to_i
135 0.upto(383) do |loc3|
136 key1 = (key1 * 11 + 77213) % 81371
137 key2 = (key2 * 17 + 92717) % 192811
138 loc6[loc3] = (key1 + key2) % 128
139 end
140
141
142 # Round 3
143 256.downto(0) do |loc3|
144 loc5 = loc6[loc3]
145 loc4 = loc3 % 128
146 loc8 = loc1[loc5]
147 loc1[loc5] = loc1[loc4]
148 loc1[loc4] = loc8
149 end
150
151
152 # Round 4
153 0.upto(127) do |loc3|
154 loc1[loc3] = (loc1[loc3].to_i ^ loc6[loc3 + 256]) & 1
155 end
156
157
158 # Round 5
159 loc12 = loc1.to_s
160 offset = 0
161 loc7 = []
162 while (offset < loc12.length)
163 loc7 << loc12[offset, 4];
164 offset += 4
165 end
166
167
168 # Round 6
169 return binary_words_to_hex(loc7)
170 end
171
172
173 end