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