Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit f641c41

Browse files
committedDec 25, 2016
Moving post encryption into plugin.
1 parent 31b7e95 commit f641c41

File tree

3 files changed

+128
-65
lines changed

3 files changed

+128
-65
lines changed
 
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[Core]
2+
Name = post_encryption
3+
Module = post_encryption
4+
5+
[Documentation]
6+
Author = Roberto Alsina
7+
Version = 1.0
8+
Website = https://getnikola.com/
9+
Description = Encrypt posts with passwords
10+
11+
[Nikola]
12+
plugincategory = SignalHandler
+116
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
# -*- coding: utf-8 -*-
2+
3+
# Copyright © 2012-2016 Roberto Alsina and others.
4+
5+
# Permission is hereby granted, free of charge, to any
6+
# person obtaining a copy of this software and associated
7+
# documentation files (the "Software"), to deal in the
8+
# Software without restriction, including without limitation
9+
# the rights to use, copy, modify, merge, publish,
10+
# distribute, sublicense, and/or sell copies of the
11+
# Software, and to permit persons to whom the Software is
12+
# furnished to do so, subject to the following conditions:
13+
#
14+
# The above copyright notice and this permission notice
15+
# shall be included in all copies or substantial portions of
16+
# the Software.
17+
#
18+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
19+
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
20+
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
21+
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
22+
# OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23+
# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24+
# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25+
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26+
27+
"""Render the taxonomy overviews, classification pages and feeds."""
28+
29+
from __future__ import unicode_literals
30+
import blinker
31+
import io
32+
import string
33+
34+
from nikola.plugin_categories import SignalHandler
35+
from nikola import utils
36+
from nikola.rc4 import rc4
37+
38+
39+
class PostEncryption(SignalHandler):
40+
"""Render the tag/category pages and feeds."""
41+
42+
name = "post_encryption"
43+
44+
@staticmethod
45+
def wrap_encrypt(path, password):
46+
"""Wrap a post with encryption."""
47+
with io.open(path, 'r+', encoding='utf8') as inf:
48+
data = inf.read() + "<!--tail-->"
49+
data = CRYPT.substitute(data=rc4(password, data))
50+
with io.open(path, 'w+', encoding='utf8') as outf:
51+
outf.write(data)
52+
53+
def _handle_post_compiled(self, source, dest, post):
54+
"""Encrypt post if password is set."""
55+
if post.meta('password'):
56+
# TODO: get rid of this feature one day (v8?; warning added in v7.3.0.)
57+
utils.LOGGER.warn("The post {0} is using the `password` attribute, which may stop working in the future.")
58+
utils.LOGGER.warn("Please consider switching to a more secure method of encryption.")
59+
utils.LOGGER.warn("More details: https://github.com/getnikola/nikola/issues/1547")
60+
self.wrap_encrypt(dest, post.meta('password'))
61+
62+
def set_site(self, site):
63+
"""Set site, which is a Nikola instance."""
64+
super(PostEncryption, self).set_site(site)
65+
# Add hook for after post compilation
66+
blinker.signal("compiled").connect(self._handle_post_compiled)
67+
68+
69+
CRYPT = string.Template("""\
70+
<script>
71+
function rc4(key, str) {
72+
var s = [], j = 0, x, res = '';
73+
for (var i = 0; i < 256; i++) {
74+
s[i] = i;
75+
}
76+
for (i = 0; i < 256; i++) {
77+
j = (j + s[i] + key.charCodeAt(i % key.length)) % 256;
78+
x = s[i];
79+
s[i] = s[j];
80+
s[j] = x;
81+
}
82+
i = 0;
83+
j = 0;
84+
for (var y = 0; y < str.length; y++) {
85+
i = (i + 1) % 256;
86+
j = (j + s[i]) % 256;
87+
x = s[i];
88+
s[i] = s[j];
89+
s[j] = x;
90+
res += String.fromCharCode(str.charCodeAt(y) ^ s[(s[i] + s[j]) % 256]);
91+
}
92+
return res;
93+
}
94+
function decrypt() {
95+
key = $$("#key").val();
96+
crypt_div = $$("#encr")
97+
crypted = crypt_div.html();
98+
decrypted = rc4(key, window.atob(crypted));
99+
if (decrypted.substr(decrypted.length - 11) == "<!--tail-->"){
100+
crypt_div.html(decrypted);
101+
$$("#pwform").hide();
102+
crypt_div.show();
103+
} else { alert("Wrong password"); };
104+
}
105+
</script>
106+
107+
<div id="encr" style="display: none;">${data}</div>
108+
<div id="pwform">
109+
<form onsubmit="javascript:decrypt(); return false;" class="form-inline">
110+
<fieldset>
111+
<legend>This post is password-protected.</legend>
112+
<input type="password" id="key" placeholder="Type password here">
113+
<button type="submit" class="btn">Show Content</button>
114+
</fieldset>
115+
</form>
116+
</div>""")

‎nikola/post.py

-65
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@
6868
get_translation_candidate,
6969
unslugify,
7070
)
71-
from .rc4 import rc4
7271

7372
__all__ = ('Post',)
7473

@@ -527,14 +526,6 @@ def deps_uptodate(self, lang):
527526

528527
def compile(self, lang):
529528
"""Generate the cache/ file with the compiled post."""
530-
def wrap_encrypt(path, password):
531-
"""Wrap a post with encryption."""
532-
with io.open(path, 'r+', encoding='utf8') as inf:
533-
data = inf.read() + "<!--tail-->"
534-
data = CRYPT.substitute(data=rc4(password, data))
535-
with io.open(path, 'w+', encoding='utf8') as outf:
536-
outf.write(data)
537-
538529
dest = self.translated_base_path(lang)
539530
if not self.is_translation_available(lang) and not self.config['SHOW_UNTRANSLATED_POSTS']:
540531
return
@@ -554,12 +545,6 @@ def wrap_encrypt(path, password):
554545
'post': self,
555546
})
556547

557-
if self.meta('password'):
558-
# TODO: get rid of this feature one day (v8?; warning added in v7.3.0.)
559-
LOGGER.warn("The post {0} is using the `password` attribute, which may stop working in the future.")
560-
LOGGER.warn("Please consider switching to a more secure method of encryption.")
561-
LOGGER.warn("More details: https://github.com/getnikola/nikola/issues/1547")
562-
wrap_encrypt(dest, self.meta('password'))
563548
if self.publish_later:
564549
LOGGER.notice('{0} is scheduled to be published in the future ({1})'.format(
565550
self.source_path, self.date))
@@ -1200,53 +1185,3 @@ def insert_hyphens(node, hyphenator):
12001185

12011186
for child in node.iterchildren():
12021187
insert_hyphens(child, hyphenator)
1203-
1204-
1205-
CRYPT = string.Template("""\
1206-
<script>
1207-
function rc4(key, str) {
1208-
var s = [], j = 0, x, res = '';
1209-
for (var i = 0; i < 256; i++) {
1210-
s[i] = i;
1211-
}
1212-
for (i = 0; i < 256; i++) {
1213-
j = (j + s[i] + key.charCodeAt(i % key.length)) % 256;
1214-
x = s[i];
1215-
s[i] = s[j];
1216-
s[j] = x;
1217-
}
1218-
i = 0;
1219-
j = 0;
1220-
for (var y = 0; y < str.length; y++) {
1221-
i = (i + 1) % 256;
1222-
j = (j + s[i]) % 256;
1223-
x = s[i];
1224-
s[i] = s[j];
1225-
s[j] = x;
1226-
res += String.fromCharCode(str.charCodeAt(y) ^ s[(s[i] + s[j]) % 256]);
1227-
}
1228-
return res;
1229-
}
1230-
function decrypt() {
1231-
key = $$("#key").val();
1232-
crypt_div = $$("#encr")
1233-
crypted = crypt_div.html();
1234-
decrypted = rc4(key, window.atob(crypted));
1235-
if (decrypted.substr(decrypted.length - 11) == "<!--tail-->"){
1236-
crypt_div.html(decrypted);
1237-
$$("#pwform").hide();
1238-
crypt_div.show();
1239-
} else { alert("Wrong password"); };
1240-
}
1241-
</script>
1242-
1243-
<div id="encr" style="display: none;">${data}</div>
1244-
<div id="pwform">
1245-
<form onsubmit="javascript:decrypt(); return false;" class="form-inline">
1246-
<fieldset>
1247-
<legend>This post is password-protected.</legend>
1248-
<input type="password" id="key" placeholder="Type password here">
1249-
<button type="submit" class="btn">Show Content</button>
1250-
</fieldset>
1251-
</form>
1252-
</div>""")

0 commit comments

Comments
 (0)
Please sign in to comment.