素人がプログラミングを勉強していたブログ

プログラミング、セキュリティ、英語、Webなどのブログ since 2008

連絡先: twitter: @javascripter にどうぞ。

アダルトサイトをブロックするGreasemonkeyスクリプト


有害っぽいサイトにアクセスすると、
f:id:javascripter:20090319165309p:image
のようにぼかしをかけて見えなくする。未成年の僕は是非入れるといいですね。
インストールするとWebサイトを見るたび「調べる」ウェブサイトのカテゴリ登録を確認|ネットスター株式会社にアクセスするので、セッションID等の入ったURL等にアクセスしないよう気をつける必要がある。

// ==UserScript==
// @name           Harmful Site Filter
// @namespace      http://d.hatena.ne.jp/javascripter/
// @include        http*
// ==/UserScript==

function cacheManager(identifier) {
  var o = JSON.parse(GM_getValue(identifier, JSON.stringify({__proto__: null})));
  return {
    has: function (key) {
      return key in o;
    },
    get: function (key) {
      return o[key];
    },
    set: function (key, value) {
      o[key] = value;
      GM_setValue(identifier, JSON.stringify(o));
      return value;
    },
    remove: function (key) {
      delete o[key];
      GM_setValue(identifier, JSON.stringify(o));
    },
    clear: function () {
      GM_deleteValue(identifier);
    }
  };
}

var cache = cacheManager("cache");
GM_registerMenuCommand("Harmful Site Filter - Clear Cache", cache.clear);

function harmful(url, k) {
  const API_URL = "http://category.netstar-inc.com/check/res.php";
  function onload(res) {
    const EXTRACTOR = /大カテゴリ (.*?)<br>/;
    var html = res.responseText;
    var all = EXTRACTOR.exec(html);
    k(
      cache.set(url, all && all[1].trim() == "アダルト")
    );
  }
  var opt = {
    method: "post",
    headers: {
      "Content-Type": "application/x-www-form-urlencoded;"
    },
    url: API_URL,
    data: "url=" + encodeURI(url),
    onload: onload
  };
  if (cache.has(url))
    k(cache.get(url));
  else
    GM_xmlhttpRequest(opt);
}

harmful(location.href, function (isHarmful) {
  if (isHarmful)
    blur(document.body);
});

var isAppended = false;
function blur(element) {
  if (!isAppended) {
    document.documentElement.appendChild(
      E4XToDOM(
        <svg:svg xmlns:svg="http://www.w3.org/2000/svg" height="0">
          <svg:defs>
            <svg:filter id="blur">
              <svg:feGaussianBlur stdDeviation="3"/>
            </svg:filter>
            <svg:filter id="grayscale">
              <svg:feColorMatrix values="0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0"/>
            </svg:filter>
          </svg:defs>
        </svg:svg>
      )
    );
    isAppended = true;
  }
  element.style.cssText += 'filter: url("#blur");';
}

function E4XToDOM(xml) {
  return document.adoptNode(
    new DOMParser().parseFromString(xml.toXMLString(), "application/xml").documentElement
  );
}

SVGフィルタを動的にセットする場合、elem.style.filter = 'url("#xxx")';は何故か上手くいかない。また、setProperty等を使っても上手くいかない。elem.setAttribute("style", 'filter:url("#xxx");');や、上のコードのようにcssTextを使うと上手くいくので、おそらくバグだと思う。
SVGはCSS3: What's Now, What's New and What's Not? [Slide 25 of 26: SVG ‘filter’ on HTML]から貰いました。