zoome Downloader

By kurumigi Last update Feb 4, 2011 — Installed 2,267 times.

There are 5 previous versions of this script.

// ==UserScript==
// @name           zoome Downloader
// @namespace      http://d.hatena.ne.jp/kurumigi/
// @description    Download flv or mp4 files from http://zoome.jp/
// @include        http://zoome.jp/*/diary/*
// @include        http://circle.zoome.jp/*/media/*
// @version        0.5.1
// ==/UserScript==

(function () {
	// === GLOBAL PARAMETERS ===
	var DEBUG = false;
	var arc4Key = '72f27dae3d5ce9ceb803eaad50c3d657';
	var pageType = (location.host == 'zoome.jp') ? 'diary' : ((location.host == 'circle.zoome.jp') ? 'circle' : '');

	// === ARCFOUR DECODE ===
	// cf. http://www.mozilla.org/projects/security/pki/nss/draft-kaukonen-cipher-arcfour-03.txt
	function arc4(key, hexstring) {
		// 3.1.1
		var s = new Array(256);
		var s2 = new Array(256);
		var i, temp, crypt;

		// 3.1.2 and 3.1.3
		var keylen = key.length;
		for (i = 0; i < 256; i++) {
			s[i] = i;
			s2[i] = key.charCodeAt(i % keylen);
		}

		// 3.1.4
		var j = 0;
		for (i = 0; i < 256; i++) {
			j = (j + s[i] + s2[i]) % 256;
			temp = s[i];
			s[i] = s[j];
			s[j] = temp;
		}

		// 3.1.5
		i = 0;
		j = 0;

		// 3.2
		crypt = '';
		for (var k = 0; k < (hexstring.length / 2); k++) {
			i = (i + 1) % 256;
			j = (j + s[i]) % 256;
			temp = s[i];
			s[i] = s[j];
			s[j] = temp;
			crypt += String.fromCharCode(parseInt(hexstring.substr(k * 2, 2), 16) ^ (s[(s[i] + s[j]) % 256]));
		}

		return crypt;
	}

	// === XML CHECK ===
	function checkXml() {
		var xmlXPath = {
			diary  : '//input[@type="hidden"][@id="mypage_diary_xml"]/@value',
			circle : '//input[@type="hidden"][@id="circle_media_xml"]/@value',
		}
		if (DEBUG) { GM_log(document.evaluate(xmlXPath[pageType], document, null, XPathResult.STRING_TYPE, null).stringValue); }
		return (document.evaluate(xmlXPath[pageType], document, null, XPathResult.STRING_TYPE, null).stringValue != '');
	}

	// === GET XML URL ===
	function getXmlUrl() {
		var replaceStr = {
			diary  : '/data_movie?format=xml&diary_id=$1&filename=zpmmdian&dummy=1',
			circle : '/swf_media/$1?filename=zpmcmedn&dummy=1',
		}
		
		if (DEBUG) { GM_log(location.href.replace(/\/(?:diary|media)\/(\d+)\/?(?:\?no_bt=\d)?$/, replaceStr[pageType])); }
		return location.href.replace(/\/(?:diary|media)\/(\d+)\/?(?:\?no_bt=\d)?$/, replaceStr[pageType]);
	}

	// === GET MOVIE URL ===
	function getMovieUrl(responseXML) {
		var imgUrlXPath = {
			diary  : '//flv01//src',
			circle : '//url_movie',
		}
		if (DEBUG) { GM_log(arc4(arc4Key, responseXML.evaluate(imgUrlXPath[pageType], responseXML, null, XPathResult.STRING_TYPE, null).stringValue)) }
		return arc4(arc4Key, responseXML.evaluate(imgUrlXPath[pageType], responseXML, null, XPathResult.STRING_TYPE, null).stringValue);
	}

	// === DETECT FILE TYPE ===
	function detectFileType(responseXML) {
		var fileTypeXPath = {
			diary  : '//mp401/@encode_stat',
			circle : '//h264_encode_stat',
		}
		if (DEBUG) { GM_log(responseXML.evaluate('contains(' + fileTypeXPath[pageType] + ', "encoded")', responseXML, null, XPathResult.BOOLEAN_TYPE, null).booleanValue) }
		return responseXML.evaluate('contains(' + fileTypeXPath[pageType] + ', "encoded")', responseXML, null, XPathResult.BOOLEAN_TYPE, null).booleanValue;
	}

	// === DETECT MOVIE URL ===
	function detectMovieUrl(responseXML) {
		var movieUrl = getMovieUrl(responseXML);
		var fileType = detectFileType(responseXML);

		if (DEBUG) { GM_log(movieUrl.replace(/_m1_1\..*$/, '_m1_1.' + (fileType ? 'mp4' : 'flv'))) }
		return movieUrl.replace(/_m1_1\..*$/, '_m1_1.' + (fileType ? 'mp4' : 'flv'));
	}

	// === GET TITLE ===
	function getTitle() {
		return document.title.replace(/ - \u52D5\u753B\u5171\u6709\u30B5\u30A4\u30C8zoome$/,'');
	}

	// === INSERT LINK ===
	function insertLink() {
		if (checkXml()) {
			var req = new XMLHttpRequest();
			req.open('GET', getXmlUrl(), true);
			req.overrideMimeType('text/xml');
			req.onreadystatechange = function (aEvt) {
				if (req.readyState == 4) {
					if (req.status == 200) {
						var logo = document.getElementsByTagName('H1')[0].parentNode;
						
						var span = document.createElement('span');
						span.innerHTML = '\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9:';
						span.className = 'gnavi_s_sub';
						span.style.paddingLeft = '10px';
						
						var a = document.createElement('a');
						a.href = detectMovieUrl(req.responseXML);
						a.innerHTML = getTitle();
						
						span.appendChild(a);
						logo.parentNode.insertBefore(span, logo.nextSibling);
					}
				}
			};
			req.send(null);
		}
	}

	if (pageType != '') {
		insertLink();
	}

})();