X-Git-Url: http://gitweb.michael.orlitzky.com/?a=blobdiff_plain;f=lib%2Fwhatever-dl%2Fwebsites%2Fmegaporn.rb;fp=lib%2Fwhatever-dl%2Fwebsites%2Fmegaporn.rb;h=57a61a7e1332b86d5bce7cd8fa9f300989b7fcab;hb=6de408333ceb0d142f8fa0fef2571228e89c8fc1;hp=0000000000000000000000000000000000000000;hpb=8e886df259246365023322b78f58e4037cb536a4;p=dead%2Fwhatever-dl.git diff --git a/lib/whatever-dl/websites/megaporn.rb b/lib/whatever-dl/websites/megaporn.rb new file mode 100644 index 0000000..57a61a7 --- /dev/null +++ b/lib/whatever-dl/websites/megaporn.rb @@ -0,0 +1,171 @@ +# +# Copyright Michael Orlitzky +# +# http://michael.orlitzky.com/ +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# http://www.fsf.org/licensing/licenses/gpl.html +# + +require 'src/website' + +class Megaporn < Website + + VALID_MEGAPORN_URL_REGEX = /^(http:\/\/)?(www\.)?(megaporn|megavideo)\.com\/video\/\?v=[[:alnum:]]+$/ + + def self.owns_url?(url) + return url =~ VALID_MEGAPORN_URL_REGEX + end + + + def get_video_filename + # Just use the video id. + id_regex = /v=([[:alnum:]]+)/ + matches = id_regex.match(@url) + + if (matches.nil? || matches.length < 2) + return 'default.flv' + else + return (matches[1] + '.flv') + end + end + + + def get_video_url() + data = get_page_data(@url) + + # Megaporn attaches a numeric suffix to their 'www' + # hostname that (I suppose) is necessary to find the + # video file. The suffix is simply provided as a flash + # variable, though. + host_suffix = parse_flash_variable(data, 's') + + # There are also two or three keys, sent as Flash variables, + # that are used in the "decryption" routine. We get integers + # to be on the safe side. + key1 = parse_flash_variable(data, 'k1').to_i + key2 = parse_flash_variable(data, 'k2').to_i + + # This is a magic hex string, passed to the decryption + # routine along with key1 and key2. + seed = parse_flash_variable(data, 'un') + + secret_path = self.decrypt(seed, key1, key2) + + # Note that the path to the video file looks like a folder. + # We need to remember to save it as a file. + return "http://www#{host_suffix}.#{self.domain}/videos/#{secret_path}/" + end + + + protected + + def domain + # I'm guessing they serve videos from both of these domains. + if (@url.include?('megavideo.com')) + return 'megavideo.com' + else + return 'megaporn.com' + end + end + + + def parse_flash_variable(data, variable_name) + # The Flash variables differ only in name, so this method can + # parse them all. + var_regex = /flashvars\.#{variable_name} = \"(.+?)\"/ + matches = var_regex.match(data) + + if (matches.nil? || matches.length < 2) + raise StandardError.new("Could not parse Flash variable: #{variable_name}.") + end + + return matches[1] + end + + + def string_to_binary_array(target_string) + binary_array = [] + + target_string.each_char do |c| + binary_int = c.to_i(16).to_s(2).to_i + binary_char = sprintf('%04d', binary_int) + binary_char.each_char do |bc| + binary_array << bc + end + end + + return binary_array + end + + + def binary_words_to_hex(target_array) + hex = '' + + target_array.each do |word| + hex << word.to_i(2).to_s(16) + end + + return hex + end + + + def decrypt(seed, key1, key2) + # I reverse-engineered this one myself. Suck it, megaporn. + # + # Round 1. Convert the seed to its binary reprentation, + # storing each bit as an element of an array. + loc1 = string_to_binary_array(seed) + + # Round 2 + loc6 = [] + key1 = key1.to_i + key2 = key2.to_i + 0.upto(383) do |loc3| + key1 = (key1 * 11 + 77213) % 81371 + key2 = (key2 * 17 + 92717) % 192811 + loc6[loc3] = (key1 + key2) % 128 + end + + + # Round 3 + 256.downto(0) do |loc3| + loc5 = loc6[loc3] + loc4 = loc3 % 128 + loc8 = loc1[loc5] + loc1[loc5] = loc1[loc4] + loc1[loc4] = loc8 + end + + + # Round 4 + 0.upto(127) do |loc3| + loc1[loc3] = (loc1[loc3].to_i ^ loc6[loc3 + 256]) & 1 + end + + + # Round 5 + loc12 = loc1.to_s + offset = 0 + loc7 = [] + while (offset < loc12.length) + loc7 << loc12[offset, 4]; + offset += 4 + end + + + # Round 6 + return binary_words_to_hex(loc7) + end + + +end