]> gitweb.michael.orlitzky.com - dead/whatever-dl.git/blobdiff - 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
diff --git a/lib/whatever-dl/websites/megaporn.rb b/lib/whatever-dl/websites/megaporn.rb
new file mode 100644 (file)
index 0000000..57a61a7
--- /dev/null
@@ -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