summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Franke <nobody@nowhere.ws>2013-03-12 06:12:24 +0100
committerChristian Franke <nobody@nowhere.ws>2013-03-12 06:22:17 +0100
commit8733f95d481d341a74d95cd97ecbef39a1f0609f (patch)
tree2862af920799e90da7ed9dd86e612ae6347f26d2
parent18d1778eeda305b5ee65d22500905640e2fbacc5 (diff)
World day against cyber censorship
-rw-r--r--public/css/sublab-2013-03-12.css (renamed from public/css/sublab-2012-09-16.css)20
-rw-r--r--public/inc/zensur.js169
-rw-r--r--template/template/template.html17
3 files changed, 205 insertions, 1 deletions
diff --git a/public/css/sublab-2012-09-16.css b/public/css/sublab-2013-03-12.css
index 9ad8eda..68a1a97 100644
--- a/public/css/sublab-2012-09-16.css
+++ b/public/css/sublab-2013-03-12.css
@@ -4,6 +4,26 @@
color: #ddd;
}
+.censored {
+ color: #ddd;
+ background-color: #ddd;
+}
+
+#zensurinfo {
+ padding: 0.5em;
+ position: absolute;
+ left: 0px;
+ top: 0px;
+ right: 0px;
+ font-size: 1.5em;
+ font-weight: bold;
+ color: white;
+ background-color: red;
+}
+#zensurinfo * { color: white }
+#zensurinfo .censored { color: white; background-color: grey; }
+#zensurinfo a, #zensurinfo a:hover, #zensurinfo a:visited { color: yellow }
+
iframe.youtube {
margin: 5px 15px 0px 15px;
width: 300px;
diff --git a/public/inc/zensur.js b/public/inc/zensur.js
new file mode 100644
index 0000000..d6b4d29
--- /dev/null
+++ b/public/inc/zensur.js
@@ -0,0 +1,169 @@
+(function() {
+ // states
+ // 0: uncensored
+ // 1: start_censor
+ // 2: censored
+ // state transition probabilities:
+ var p_trans = [
+ // x uncensored -> uncensored
+ 0.08, // uncensored -> start_censor
+ // 0 uncensored -> censored
+ // 0 start_censor -> uncensored
+ // 0 start_censor -> start_censor
+ // 1 start_censor -> censored
+ 0.55, // censored -> uncensored
+ // 0 censored -> start_censor
+ // x censored -> censored
+ ];
+ var censored_tag = "span";
+ var censored_class = "censored";
+ var start_censor = "<" + censored_tag + " class=\"" + censored_class + "\">";
+ var stop_censor = "</" + censored_tag + ">";
+ var re_censor = /[0-9A-Za-z]/;
+ var isCensored = true;
+ var censoredElements = [];
+
+ function splitWords(text) {
+ // some older IEs don't suppport capturing parentheses
+ // return text.split(/([\t\n\r ])/);
+ if (text.length === 0) {
+ return [""];
+ }
+ var words = [];
+ var last_i = 0;
+ for (var i = 0; i < text.length; i++) {
+ switch(text[i]) {
+ case '\t':
+ case '\n':
+ case '\r':
+ case ' ':
+ if (last_i !== i) {
+ words.push(text.slice(last_i, i));
+ }
+ words.push(text[i]);
+ last_i = i + 1;
+ }
+ }
+ if (last_i !== text.length) {
+ words.push(text.slice(last_i));
+ }
+ return words;
+ }
+
+ function censorWord(state, word) {
+ // ignore words not containing letters (may be spaces only)
+ if (!word.match(re_censor)) {
+ return word;
+ }
+
+ var r = Math.random();
+ var prefix = "";
+ var suffix = "";
+
+ if (state.s === 1) {
+ // start_censor -> censored
+ state.s = 2;
+ prefix = start_censor;
+ }
+
+ if (state.s === 0 && r < p_trans[0]) {
+ // uncensored -> start_censor
+ state.s = 1;
+ }
+ else if (state.s === 2 && r < p_trans[1]) {
+ // censored -> uncensored
+ state.s = 0;
+ suffix = stop_censor;
+ }
+
+ return prefix + word + suffix;
+ }
+
+ function censorTextNode(node) {
+ var state = { s: 0 };
+ if (Math.random() < p_trans[0]) {
+ // start_censor
+ state.s = 1;
+ }
+ var words = splitWords(node.nodeValue);
+ for (var i in words) {
+ words[i] = censorWord(state, words[i]);
+ }
+ if (state.s === 2) {
+ words[words.length-1] = words[words.length-1] + stop_censor;
+ }
+ var newnode = document.createElement(censored_tag);
+ newnode.innerHTML = words.join("");
+ return newnode;
+ }
+
+ function censorElement(element, on) {
+ var childs = element.childNodes;
+ var uncensored = false;
+ for (var i in childs) {
+
+ if (childs[i].nodeType === 1 &&
+ childs[i].nodeName !== "OPTION" &&
+ childs[i].nodeName !== "SCRIPT" &&
+ childs[i].nodeName !== "SELECT" &&
+ childs[i].nodeName !== "STYLE" &&
+ childs[i].nodeName !== "TEXTAREA" &&
+ childs[i].nodeName !== "TITLE")
+ {
+ if (!on &&
+ childs[i].nodeName === censored_tag.toUpperCase() &&
+ childs[i].className === censored_class &&
+ childs[i].childNodes.length === 1)
+ {
+ uncensored = true;
+ element.replaceChild(childs[i].childNodes[0], childs[i]);
+ }
+
+ var childUncensored = censorElement(childs[i], on);
+ if (!on && childUncensored)
+ {
+ var newnode = document.createTextNode("");
+ for (var j in childs[i].childNodes) {
+ if (!childs[i].childNodes[j].nodeType === 3) {
+ return;
+ }
+ if (childs[i].childNodes[j].nodeValue) {
+ newnode.nodeValue += childs[i].childNodes[j].nodeValue;
+ }
+ }
+ element.replaceChild(newnode, childs[i]);
+ }
+ }
+
+ else if (on &&
+ childs[i].nodeType === 3 &&
+ childs[i].nodeValue.match(re_censor))
+ {
+ element.replaceChild(censorTextNode(childs[i]), childs[i]);
+ }
+
+ }
+
+ return uncensored;
+ }
+
+ function doCensor(on) {
+ for (var i in censoredElements) {
+ censorElement(censoredElements[i], on);
+ }
+ }
+
+ window.zensurjs = function(arg) {
+ if (arg === undefined) {
+ isCensored = !isCensored;
+ doCensor(isCensored);
+ }
+ else {
+ censoredElements.push(arg);
+ if (isCensored) {
+ censorElement(arg, true);
+ }
+ }
+ return isCensored;
+ };
+})();
diff --git a/template/template/template.html b/template/template/template.html
index 3c8f053..66c8987 100644
--- a/template/template/template.html
+++ b/template/template/template.html
@@ -15,16 +15,31 @@
<meta name="description" lang="de" content="$template_desc_de">
<meta name="description" lang="en" content="$template_desc_en">
- <link rel="stylesheet" href="/css/sublab-2012-09-16.css" type="text/css">
+ <link rel="stylesheet" href="/css/sublab-2013-03-12.css" type="text/css">
<link rel="stylesheet" href="/css/taifun.status.css" type="text/css">
<link rel="stylesheet" href="/css/trieste.status.css" type="text/css">
<link rel="stylesheet" href="/css/nautilus.status.css" type="text/css">
<link rel="stylesheet" href="/css/sublab.status.css" type="text/css">
<link rel="shortcut icon" href="/img/favicon.png">
<link rel="space-api" href="/status.json" />
+
+ <script type="text/javascript" src="/inc/zensur.js"></script>
+ <script type="text/javascript">
+ window.onload = function() { zensurjs(document.body); };
+ function toggleZensur() {
+ var state = zensurjs();
+ document.getElementById("zensurstate").innerHTML={true: 'Diese Seite ist zensiert.', false: 'Diese Seite könnte zensiert sein.'}[state];
+ document.getElementById("zensurlink").innerHTML={true: 'Ich bin gegen Zensur!', false: 'Ich bin für Zensur!'}[state];
+ }
+ </script>
</head>
<body>
+ <div id="zensurinfo">
+ <span id="zensurstate">Diese Seite ist zensiert.</span>
+ <a href="https://march12.rsf.org/en/">Lies Warum!</a>
+ <small><a href="" id="zensurlink" onclick="toggleZensur(); return false;">Ich bin gegen Zensur!</a></small>
+ </div>
<div class="hiddenframe">
<div class="frame">