WSGIDaemonProcess stickynotes2modernpaste user=apache group=apache threads=5
WSGIScriptAlias /stickynotes2modernpaste /usr/share/stickynotes2modernpaste/stickynotes2modernpaste.wsgi
WSGISocketPrefix run/wsgi

# Grab a cup of coffee, a light snack, and turn on some classical music.
# You're in for a bit of a novel.
#
# The below rules are worthy of some comment so that later on when I (or
# heaven forbid anyone else) have to revisit them for some horrible reason,
# they can be referred to and maybe (but unlikely) useful.
#
# Chapter 1. Background.
#
# The rewrite rules exist solely for the purpose of continuing to support old
# `fpaste` (the CLI app). This is in the process of being rewritten, and one
# day we won't have to support it anymore. But for now, we do, because it's on
# live media (and, I believe, Desktop installs, by default), and when a user is
# having issues and asking for help in IRC, they need to be able to use
# `fpaste` to do so. So, that is why we care about `fpaste` in its current
# (F25-F26) form.
#
# You see, fpaste was written in such a way that it makes a lot of weird
# assumptions that don't hold anymore. I will not speculate on why it was
# written the way it was, but I _will_ briefly outline some of the intricacies
# of supporting it.
#
# First off the workflow is something like this:
#   1. User wants to paste some text. Who knows why they want to do this. Maybe
#      they are bored and want to see how broken our rewrite rules are. Maybe
#      they hate me and want to see me cry trying to fix them. Who knows?!
#
#   2. The fpaste client makes a POST on their behalf to /. This POST payload
#      includes the text of the paste and some other information (paste
#      language, etc).
#
#   3. The server sees the POST, matches it against our rules below, and
#      decides that it needs to redirect them to stickynotes2modernpaste, a
#      custom Flask app that I (relrod) wrote so that we could handle requests
#      that are in the form our old stickynotes pastebin accepted, and proxy
#      them to modernpaste.
#
#      Note that this matches the first set of crazy RewriteConds below. We
#      only want to send CLI users there, and only when they POST to /. At
#      this point, at least.
#
#   4. sn2mp says "okay cool," proxies the paste to modernpaste via its JSON
#      API, and returns back to fpaste a JSON blob that contains JSON with two
#      keys that fpaste requires exists. In our response, one of them is always
#      an empty string, and the other is the id of the paste, prefixed with
#      "paste/".
#
#   5. At this point, fpaste has enough information to return a URL to the
#      paste. However, things are not all okay in the world. You see, fpaste
#      wants to show a short-url too. Apparently people don't like typing or
#      something. To generate a short-url, the fpaste client sends another POST
#      to us, at the path "/paste/[the paste id]//". In the past, when it would
#      do this, stickynotes would return a JSON blob that included the
#      short-url. In fact, it would always include the short-url at the
#      third-line from the last in its JSON response, and the fpaste client
#      hardcoded that assumption. See Chapter 2 for information about the "//".
#
#   6. When we get this second POST, we again send the client to sn2mp. We add
#      a few more crazy RewriteConds to ensure that we only add this behavior
#      for fpaste and not most users. We know paste IDs are 22-24 characters
#      long (as per https://github.com/LINKIWI/modern-paste/pull/33) and that
#      the client will always POST to "/paste/[the paste id]//". So we match on
#      that. If we match, sn2mp will take everything after its name and append
#      it to the URL that ultimately gets shipped to da.gd for shortening. Then
#      it returns a (malformed) JSON blob that is written in exactly the way
#      fpaste expects.
#
#   7. Then fpaste shows the user both URLs, and all is okay.
#
# Chapter 2. Trailing slashes.
#
# The fpaste client defaults to private mode, but modernpaste doesn't support
# that, per se. You can password-protect pastes, but that's about it.
#
# However, they way stickynotes worked, it used /[paste id]/[secret] when a
# paste was private. Since modernpaste does things differently, sn2mp never
# returns the [secret] part of that URL. Or rather, it returns the empty string
# in its place. This means, by default (private mode = true), fpaste will
# both render, and internally use, a URL that has /[paste id]/[secret]. But
# since [secret] is the empty string, this is equivalent to /[paste id]/, with
# the trailing slash.
#
# To make matters worse, this little gem is found in the fpaste procedure for
# doing the second POST (#5 and 6 above):
#
#    eq = urllib.request.Request(url=long_url+'/', data=params.encode())
#
# Yep, it adds a '/' for the second POST. So we get POSTs to
# /paste/[paste id]// during the second POST.
#
# Our capture of the paste ID below (the ".{22,24}" part) will match the first
# trailing slash, but not the second (because of the /$ that comes after).
# Nevertheless sn2mp handles all three cases anyway, and will STRIP OFF
# trailing slashes if they occur 0, 1, or 2 times.
#
# Lastly, the long url that fpaste shows the user contains one trailing slash
# (due to the /[secret] part from how stickynotes worked). So we add one final
# rewrite that redirects users who go to that, to the non-slash version.
#
# If you have made it this far, you are a champion. You should get a badge.
#
# Warm regards and good luck,
#   relrod

RewriteEngine on
#LogLevel alert rewrite:trace6

{% if env != 'staging' %}
RewriteRule login / [L,R]
RewriteRule archive /login/ [L,R]
RewriteRule api/paste/recent /login/ [L,R]
RewriteRule api/paste/top /login/ [L,R]
{% endif %}

RewriteCond %{HTTP_USER_AGENT} ^fpaste\/0\.3.*$ [OR]
RewriteCond %{HTTP_USER_AGENT} ^Python\-urllib.*$
RewriteCond %{REQUEST_METHOD} POST
RewriteRule ^/$ /stickynotes2modernpaste/$1 [L,PT]

RewriteCond %{HTTP_USER_AGENT} ^fpaste\/0\.3.*$ [OR]
RewriteCond %{HTTP_USER_AGENT} ^Python\-urllib.*$
RewriteCond %{REQUEST_METHOD} POST
RewriteRule ^/paste/(.{22,24})/$ /stickynotes2modernpaste/paste/$1 [L,PT]

# Otherwise, if we're given a URL with a trailing slash, kill it.
RewriteRule ^/paste/([^/]{22,24})/$ /paste/$1 [R,L]

WSGIScriptAlias / /usr/share/modern-paste/modern_paste.wsgi

<Directory /usr/share/stickynotes2modernpaste>
    WSGIProcessGroup stickynotes2modernpaste
    WSGIApplicationGroup %{GLOBAL}
    WSGIScriptReloading On
    Order deny,allow
    Require all granted
</Directory>

<Directory /usr/share/modern-paste>
  Require all granted
</Directory>

DocumentRoot /usr/share/modern-paste
#ErrorLog logs/modern-paste-error.log
#CustomLog logs/modern-paste-access.log combined
#LogLevel info
