From c156ae475c9fde2ade6ce14664aa63700f106900 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Juhani=20Krekel=C3=A4?=
Date: Wed, 14 Aug 2019 00:34:23 +0300
Subject: [PATCH] First commit
---
webed.py | 264 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 264 insertions(+)
create mode 100644 webed.py
diff --git a/webed.py b/webed.py
new file mode 100644
index 0000000..2633985
--- /dev/null
+++ b/webed.py
@@ -0,0 +1,264 @@
+#!/usr/bin/env python3
+
+# ------------------------------------------------------------------
+# CC0 1.0 Universal
+# #
+# Statement of Purpose
+#
+# The laws of most jurisdictions throughout the world automatically confer
+# exclusive Copyright and Related Rights (defined below) upon the creator and
+# subsequent owner(s) (each and all, an "owner") of an original work of
+# authorship and/or a database (each, a "Work").
+#
+# Certain owners wish to permanently relinquish those rights to a Work for the
+# purpose of contributing to a commons of creative, cultural and scientific
+# works ("Commons") that the public can reliably and without fear of later
+# claims of infringement build upon, modify, incorporate in other works, reuse
+# and redistribute as freely as possible in any form whatsoever and for any
+# purposes, including without limitation commercial purposes. These owners may
+# contribute to the Commons to promote the ideal of a free culture and the
+# further production of creative, cultural and scientific works, or to gain
+# reputation or greater distribution for their Work in part through the use and
+# efforts of others.
+#
+# For these and/or other purposes and motivations, and without any expectation
+# of additional consideration or compensation, the person associating CC0 with a
+# Work (the "Affirmer"), to the extent that he or she is an owner of Copyright
+# and Related Rights in the Work, voluntarily elects to apply CC0 to the Work
+# and publicly distribute the Work under its terms, with knowledge of his or her
+# Copyright and Related Rights in the Work and the meaning and intended legal
+# effect of CC0 on those rights.
+#
+# 1. Copyright and Related Rights. A Work made available under CC0 may be
+# protected by copyright and related or neighboring rights ("Copyright and
+# Related Rights"). Copyright and Related Rights include, but are not limited
+# to, the following:
+#
+# i. the right to reproduce, adapt, distribute, perform, display, communicate,
+# and translate a Work;
+#
+# ii. moral rights retained by the original author(s) and/or performer(s);
+#
+# iii. publicity and privacy rights pertaining to a person's image or likeness
+# depicted in a Work;
+#
+# iv. rights protecting against unfair competition in regards to a Work,
+# subject to the limitations in paragraph 4(a), below;
+#
+# v. rights protecting the extraction, dissemination, use and reuse of data in
+# a Work;
+#
+# vi. database rights (such as those arising under Directive 96/9/EC of the
+# European Parliament and of the Council of 11 March 1996 on the legal
+# protection of databases, and under any national implementation thereof,
+# including any amended or successor version of such directive); and
+#
+# vii. other similar, equivalent or corresponding rights throughout the world
+# based on applicable law or treaty, and any national implementations thereof.
+#
+# 2. Waiver. To the greatest extent permitted by, but not in contravention of,
+# applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and
+# unconditionally waives, abandons, and surrenders all of Affirmer's Copyright
+# and Related Rights and associated claims and causes of action, whether now
+# known or unknown (including existing as well as future claims and causes of
+# action), in the Work (i) in all territories worldwide, (ii) for the maximum
+# duration provided by applicable law or treaty (including future time
+# extensions), (iii) in any current or future medium and for any number of
+# copies, and (iv) for any purpose whatsoever, including without limitation
+# commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes
+# the Waiver for the benefit of each member of the public at large and to the
+# detriment of Affirmer's heirs and successors, fully intending that such Waiver
+# shall not be subject to revocation, rescission, cancellation, termination, or
+# any other legal or equitable action to disrupt the quiet enjoyment of the Work
+# by the public as contemplated by Affirmer's express Statement of Purpose.
+#
+# 3. Public License Fallback. Should any part of the Waiver for any reason be
+# judged legally invalid or ineffective under applicable law, then the Waiver
+# shall be preserved to the maximum extent permitted taking into account
+# Affirmer's express Statement of Purpose. In addition, to the extent the Waiver
+# is so judged Affirmer hereby grants to each affected person a royalty-free,
+# non transferable, non sublicensable, non exclusive, irrevocable and
+# unconditional license to exercise Affirmer's Copyright and Related Rights in
+# the Work (i) in all territories worldwide, (ii) for the maximum duration
+# provided by applicable law or treaty (including future time extensions), (iii)
+# in any current or future medium and for any number of copies, and (iv) for any
+# purpose whatsoever, including without limitation commercial, advertising or
+# promotional purposes (the "License"). The License shall be deemed effective as
+# of the date CC0 was applied by Affirmer to the Work. Should any part of the
+# License for any reason be judged legally invalid or ineffective under
+# applicable law, such partial invalidity or ineffectiveness shall not
+# invalidate the remainder of the License, and in such case Affirmer hereby
+# affirms that he or she will not (i) exercise any of his or her remaining
+# Copyright and Related Rights in the Work or (ii) assert any associated claims
+# and causes of action with respect to the Work, in either case contrary to
+# Affirmer's express Statement of Purpose.
+#
+# 4. Limitations and Disclaimers.
+#
+# a. No trademark or patent rights held by Affirmer are waived, abandoned,
+# surrendered, licensed or otherwise affected by this document.
+#
+# b. Affirmer offers the Work as-is and makes no representations or warranties
+# of any kind concerning the Work, express, implied, statutory or otherwise,
+# including without limitation warranties of title, merchantability, fitness
+# for a particular purpose, non infringement, or the absence of latent or
+# other defects, accuracy, or the present or absence of errors, whether or not
+# discoverable, all to the greatest extent permissible under applicable law.
+#
+# c. Affirmer disclaims responsibility for clearing rights of other persons
+# that may apply to the Work or any use thereof, including without limitation
+# any person's Copyright and Related Rights in the Work. Further, Affirmer
+# disclaims responsibility for obtaining any necessary consents, permissions
+# or other rights required for any use of the Work.
+#
+# d. Affirmer understands and acknowledges that Creative Commons is not a
+# party to this document and has no duty or obligation with respect to this
+# CC0 or use of the Work.
+#
+# For more information, please see
+#
+# ------------------------------------------------------------------
+
+import base64
+import html
+import http.server
+import os
+import sys
+import urllib.parse
+
+files = {}
+
+def gen_id():
+ return base64.urlsafe_b64encode(os.urandom(48 * 6 // 8)).decode()
+
+def process_file(file_id):
+ r = []
+ for line in files[file_id]:
+ r.append('%s
' % html.escape(line))
+
+ return '\n'.join(r)
+
+def run_command(keyvalues):
+ file_id = keyvalues['id'][-1]
+ cmd = keyvalues['cmd'][-1]
+ linenum = int(keyvalues['linenum'][-1])
+
+ assert cmd in ['append', 'delete']
+
+ if cmd == 'append':
+ line = keyvalues['line'][-1]
+ before = files[file_id][:linenum]
+ after = files[file_id][linenum:]
+ files[file_id] = before + [line] + after
+
+ elif cmd == 'delete':
+ assert 0 < linenum <= len(files[file_id])
+ del files[file_id][linenum - 1]
+
+class WebEd(http.server.BaseHTTPRequestHandler):
+ def redirect(self, path):
+ self.send_response(303)
+ self.send_header('Content-Type', 'text/plain; charset=utf-8')
+ self.send_header('Content-Length', 0)
+ self.send_header('Location', path)
+ self.end_headers()
+
+ def send_html(self, html, status_code = 200):
+ encoded = html.encode('utf-8')
+ length = len(encoded)
+
+ self.send_response(status_code)
+ self.send_header('Content-Type', 'text/html; charset=utf-8')
+ self.send_header('Content-Length', length)
+ self.end_headers()
+
+ self.wfile.write(encoded)
+
+ def do_GET(self):
+ url, _, keyvalues = self.path.partition('?')
+ keyvalues = urllib.parse.parse_qs(keyvalues)
+
+ if url == '/' and 'id' not in keyvalues:
+ # Generate new ID
+ file_id = gen_id()
+ self.redirect('%s?id=%s' % (url, file_id))
+
+ elif 'id' not in keyvalues:
+ self.send_html("""
+
+
+
+ 404 Not Found
+
+
+ 404 Not Found
+
+
+ """, 404)
+
+ else:
+ file_id = keyvalues['id'][-1]
+
+ if file_id not in files:
+ files[file_id] = []
+
+ if 'cmd' in keyvalues:
+ try:
+ run_command(keyvalues)
+
+ except Exception as err:
+ self.send_html("""
+
+
+
+ 400 Bad Request
+
+
+ 400 Bad Request
+
+
+ """, 400)
+ return
+
+ self.redirect('%s?id=%s' % (url, file_id))
+
+ self.send_html("""
+
+
+ WebEd
+
+
+
+
+
%s
+
+
+
+
+
+ """ % (process_file(file_id), file_id, len(files[file_id]), len(files[file_id])))
+
+def main():
+ http.server.HTTPServer(('', int(sys.argv[1])), WebEd).serve_forever()
+
+if __name__ == '__main__':
+ main()