diff --git a/magneticow/magneticow/magneticow.py b/magneticow/magneticow/magneticow.py
index 229c03f..cbdb2b0 100644
--- a/magneticow/magneticow/magneticow.py
+++ b/magneticow/magneticow/magneticow.py
@@ -16,6 +16,7 @@ import collections
import functools
import datetime as dt
from datetime import datetime
+import hashlib
import logging
import sqlite3
import os
@@ -41,7 +42,7 @@ magneticod_db = None
# Adapted from: http://flask.pocoo.org/snippets/8/
# (c) Copyright 2010 - 2017 by Armin Ronacher
# BEGINNING OF THE COPYRIGHTED CONTENT
-def check_auth(supplied_username, supplied_password):
+def is_authorized(supplied_username, supplied_password):
""" This function is called to check if a username / password combination is valid. """
# Because we do monkey-patch! [in magneticow.__main__.py:main()]
for username, password in app.arguments.user: # pylint: disable=maybe-no-member
@@ -64,13 +65,24 @@ def requires_auth(f):
@functools.wraps(f)
def decorated(*args, **kwargs):
auth = flask.request.authorization
- if not auth or not check_auth(auth.username, auth.password):
+ if not auth or not is_authorized(auth.username, auth.password):
return authenticate()
return f(*args, **kwargs)
return decorated
# END OF THE COPYRIGHTED CONTENT
+def generate_feed_hash(username: str, password: str, filter_: str) -> str:
+ """
+ Deterministically generates the feed hash from given username, password, and filter.
+ Hash is the hex encoding of the SHA256 sum.
+ :param username:
+ :param password:
+ :param filter_:
+ :return:
+ """
+ return hashlib.sha256((username + "\0" + password + "\0" + filter_).encode()).digest().hex()
+
@app.route("/")
@requires_auth
def home_page():
@@ -128,6 +140,9 @@ def search_torrents():
else:
context["next_page_exists"] = True
+ username, password = flask.request.authorization.username, flask.request.authorization.password
+ context["subscription_url"] = "/feed?filter=%s&hash=%s" % (search, generate_feed_hash(username, password, search))
+
return flask.render_template("torrents.html", **context)
@@ -158,6 +173,9 @@ def newest_torrents():
else:
context["next_page_exists"] = True
+ username, password = flask.request.authorization.username, flask.request.authorization.password
+ context["subscription_url"] = "/feed?filter=&hash=%s" % (generate_feed_hash(username, password, ""),)
+
return flask.render_template("torrents.html", **context)
@@ -241,6 +259,56 @@ def statistics():
})
+@app.route("/feed")
+def feed():
+ filter_ = flask.request.args["filter"]
+ hash_ = flask.request.args["hash"]
+ # Check for all possible users who might be requesting.
+ # pylint disabled: because we do monkey-patch! [in magneticow.__main__.py:main()]
+ for username, password in app.arguments.user: # pylint: disable=maybe-no-member
+ if generate_feed_hash(username, password, filter_) == hash_:
+ break
+ else:
+ return flask.Response(
+ "Could not verify your access level for that URL (wrong hash).\n",
+ 401
+ )
+
+ context = {}
+
+ if filter_:
+ context["title"] = "`%s` - magneticow" % (filter_,)
+ with magneticod_db:
+ cur = magneticod_db.execute(
+ "SELECT "
+ " name, "
+ " info_hash "
+ "FROM torrents "
+ "INNER JOIN ("
+ " SELECT docid AS id, rank(matchinfo(fts_torrents, 'pcnxal')) AS rank "
+ " FROM fts_torrents "
+ " WHERE name MATCH ? "
+ " ORDER BY rank ASC"
+ " LIMIT 50"
+ ") AS ranktable USING(id);",
+ (filter_, )
+ )
+ context["items"] = [{"title": r[0], "info_hash": r[1].hex()} for r in cur]
+ else:
+ context["title"] = "The Newest Torrents - magneticow"
+ with magneticod_db:
+ cur = magneticod_db.execute(
+ "SELECT "
+ " name, "
+ " info_hash "
+ "FROM torrents "
+ "ORDER BY id DESC LIMIT 50"
+ )
+ context["items"] = [{"title": r[0], "info_hash": r[1].hex()} for r in cur]
+
+ return flask.render_template("feed.xml", **context), 200, {"Content-Type": "application/rss+xml; charset=utf-8"}
+
+
def initialize_magneticod_db() -> None:
global magneticod_db
diff --git a/magneticow/magneticow/static/styles/torrents.css b/magneticow/magneticow/static/styles/torrents.css
index 45d42cd..6cbe505 100644
--- a/magneticow/magneticow/static/styles/torrents.css
+++ b/magneticow/magneticow/static/styles/torrents.css
@@ -22,6 +22,7 @@ header form {
width: 100%;
margin-left: 0.5em;
+ margin-right: 0.5em;
}
diff --git a/magneticow/magneticow/templates/feed.xml b/magneticow/magneticow/templates/feed.xml
new file mode 100644
index 0000000..997210c
--- /dev/null
+++ b/magneticow/magneticow/templates/feed.xml
@@ -0,0 +1,13 @@
+
+