diff --git a/100unix2web.conf b/100unix2web.conf
new file mode 100644
index 0000000..12dae2c
--- /dev/null
+++ b/100unix2web.conf
@@ -0,0 +1,11 @@
+
+ WSGIDaemonProcess app
+ WSGIScriptAlias / /var/www/unix2web/unix2web.wsgi
+
+
+ WSGIProcessGroup app
+ WSGIApplicationGroup %{GLOBAL}
+ Order deny,allow
+ Allow from all
+
+
\ No newline at end of file
diff --git a/README.rst b/README.rst
new file mode 100644
index 0000000..aef6184
--- /dev/null
+++ b/README.rst
@@ -0,0 +1,102 @@
+================
+unix2web
+================
+----------
+Expose a UNIX filter on a web page
+----------
+
+Purpose
+=============
+
+You have an UNIX filter that does one job and do it well. For example it converts a .doc file to PDF :
+ doc2pdf < file.doc >file.pdf
+
+This tool lets you host a nice web page where people can upload the input file and download the output file. This is
+useful if UNIX-disabled people need to use your filter.
+
+In a matter of minutes you can make an unix script available to the world on e.g. an AWS EC2 instance.
+
+Installation
+=============
+
+We assume you have a UNIX-like server where your filter works (this tool does not handle the installation of your filter
+or its dependencies).
+
+Clone the repo somewhere :
+
+ git clone https://github.com/edouardklein/unix2web/
+
+Change the index.html file to your liking (most notably the title and description).
+
+Modify unix2web.wsgi if you want the webapp to live somewhere else than /var/www/unix2web/ (not useful if you intend
+to only run one filter on the server).
+
+Same procedure for 100web2unix.conf
+
+Same procedure for unix2web.py
+
+Review the install.sh file, modify if necessary, then upload all the files on your server and run install.sh
+ scp -i private_key.pem *.* login@example.com:/tmp/
+ ssh -i private_key.pem login@example.com 'cd /tmp/ && sudo sh install.sh'
+
+
+Example use cases
+=========
+
+Converting .doc to .pdf from anywhere.
+
+Compiling LaTeX files.
+
+I'd be happy to hear about your uses. If you deploy this, please send me a word.
+
+Security
+========
+
+Security is hard, so we did not do it beyond the obvious (not using the user's filename).
+
+Easy to DDoS (just send a big file).
+
+No password protection.
+
+We advise to deploy this behind a hard-to-find, non-indexable URL and to share the link wisely.
+
+
+Bugs and Todo
+============
+
+Near future
+----------
+
+This probably scales badly (untested).
+
+The error output comes all at once, would be nice if, for long processes, it came as it appears server-side.
+
+Security is bad. At least we should check input size and kill long processes.
+
+Output files are not cleaned up (easily doable with a cron-job, though).
+
+Distant future
+-------------
+
+Parsing the --help string à la docopt and automatically creating an interface for the options would be wonderful.
+
+Author
+======
+See http://rdklein.fr
+
+License
+=======
+
+ unix2web is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Foobar is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with unix2web. If not, see .
+
diff --git a/index.css b/index.css
new file mode 100644
index 0000000..bcb1578
--- /dev/null
+++ b/index.css
@@ -0,0 +1,19 @@
+.btn-file {
+ position: relative;
+ overflow: hidden;
+ }
+.btn-file input[type=file] {
+ position: absolute;
+ top: 0;
+ right: 0;
+ min-width: 100%;
+ min-height: 100%;
+ font-size: 100px;
+ text-align: right;
+ filter: alpha(opacity=0);
+ opacity: 0;
+ outline: none;
+ background: white;
+ cursor: inherit;
+ display: block;
+ }
\ No newline at end of file
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..f3525b1
--- /dev/null
+++ b/index.html
@@ -0,0 +1,113 @@
+
+
+
+
+
+
+ Test unix2web page
+
+
+
+
+
+
+
+
+
unix2web
+
Make any UNIX filter accessible wia the web. For demo purposes we use a simple sed one liner that changes
+ all instances of "the web" to "UNIX" and echoes the date on stderr :
+ (date>&2; sed s/the web/UNIX/gI output.
+
+
+
+
+
+
+
+
+
+ Output file :
+
+
+
+
+ Output file :
+
+
+
+
+
\ No newline at end of file
diff --git a/install.sh b/install.sh
new file mode 100644
index 0000000..66c2947
--- /dev/null
+++ b/install.sh
@@ -0,0 +1,17 @@
+# This will install the web-app on a ubuntu server
+# intallation instructions follow recipe given here http://blog.garethdwyer.co.za/2013/07/getting-simple-flask-app-running-on.html . Thanks !
+
+APPNAME=unix2web
+INSTALLDIR=/var/www/$APPNAME
+sudo yes | apt-get install apache2 libapache2-mod-wsgi python-flask
+sudo mkdir -p $INSTALLDIR
+sudo mv /tmp/index.html $INSTALLDIR/
+sudo mv /tmp/index.css $INSTALLDIR/
+sudo mv /tmp/$APPNAME.py $INSTALLDIR/
+sudo mv /tmp/$APPNAME.wsgi $INSTALLDIR/
+sudo mv /tmp/100$APPNAME.conf /etc/apache2/sites-available
+sudo a2dissite 000-default
+sudo a2ensite 100$APPNAME
+sudo /etc/init.d/apache2 restart
+
+
diff --git a/unix2web.py b/unix2web.py
new file mode 100644
index 0000000..f42ca31
--- /dev/null
+++ b/unix2web.py
@@ -0,0 +1,151 @@
+from __future__ import print_function
+"""Run a UNIX filter on an uploaded file, download the result
+
+Code on https://github.com/edouardklein/unix2web/
+
+ This file is part of unix2web.
+
+ unix2web is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Foobar is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with unix2web. If not, see .
+"""
+__author__ = 'Edouard Klein '
+
+import os
+from flask import Flask, request, Response, jsonify
+import logging
+logging.basicConfig(filename='/tmp/debug.log', level=logging.DEBUG)
+from subprocess import Popen, PIPE
+
+app = Flask(__name__)
+
+# Back port of the with TemporaryDirectory()... syntax from
+# https://stackoverflow.com/questions/19296146/with-tempfile-temporarydirectory
+# Thanks.
+import warnings as _warnings
+import os as _os
+from tempfile import mkdtemp, mkstemp
+
+class TemporaryDirectory(object):
+ """Create and return a temporary directory. This has the same
+ behavior as mkdtemp but can be used as a context manager. For
+ example:
+
+ with TemporaryDirectory() as tmpdir:
+ ...
+
+ Upon exiting the context, the directory and everything contained
+ in it are removed.
+ """
+
+ def __init__(self, suffix="", prefix="tmp", dir=None):
+ self._closed = False
+ self.name = None # Handle mkdtemp raising an exception
+ self.name = mkdtemp(suffix, prefix, dir)
+
+ def __repr__(self):
+ return "<{} {!r}>".format(self.__class__.__name__, self.name)
+
+ def __enter__(self):
+ return self.name
+
+ def cleanup(self, _warn=False):
+ if self.name and not self._closed:
+ try:
+ self._rmtree(self.name)
+ except (TypeError, AttributeError) as ex:
+ # Issue #10188: Emit a warning on stderr
+ # if the directory could not be cleaned
+ # up due to missing globals
+ if "None" not in str(ex):
+ raise
+ print("ERROR: {!r} while cleaning up {!r}".format(ex, self,),file=_sys.stderr)
+ return
+ self._closed = True
+ if _warn:
+ self._warn("Implicitly cleaning up {!r}".format(self),
+ ResourceWarning)
+
+ def __exit__(self, exc, value, tb):
+ self.cleanup()
+
+ def __del__(self):
+ # Issue a ResourceWarning if implicit cleanup needed
+ self.cleanup(_warn=True)
+
+ # XXX (ncoghlan): The following code attempts to make
+ # this class tolerant of the module nulling out process
+ # that happens during CPython interpreter shutdown
+ # Alas, it doesn't actually manage it. See issue #10188
+ _listdir = staticmethod(_os.listdir)
+ _path_join = staticmethod(_os.path.join)
+ _isdir = staticmethod(_os.path.isdir)
+ _islink = staticmethod(_os.path.islink)
+ _remove = staticmethod(_os.remove)
+ _rmdir = staticmethod(_os.rmdir)
+ _warn = _warnings.warn
+
+ def _rmtree(self, path):
+ # Essentially a stripped down version of shutil.rmtree. We can't
+ # use globals because they may be None'ed out at shutdown.
+ for name in self._listdir(path):
+ fullname = self._path_join(path, name)
+ try:
+ isdir = self._isdir(fullname) and not self._islink(fullname)
+ except OSError:
+ isdir = False
+ if isdir:
+ self._rmtree(fullname)
+ else:
+ try:
+ self._remove(fullname)
+ except OSError:
+ pass
+ try:
+ self._rmdir(path)
+ except OSError:
+ pass
+#End of Backport
+
+
+@app.route('/tmp/')
+def get_output(file):
+ logging.debug('GET on file '+file)
+ return open('/tmp/'+file, 'r').read() # Not platform independent FIXME.
+
+@app.route('/', methods=['GET', 'POST'])
+def upload_file():
+ logging.debug('Request on /')
+ if request.method == 'POST':
+ logging.debug('POST')
+ file = request.files['file']
+ if file:
+ with TemporaryDirectory() as tmpdir:
+ logging.debug('saving on '+os.path.join(tmpdir, 'input'))
+ file.save(os.path.join(tmpdir, 'input'))
+ (_,output_file_name) = mkstemp()
+ p = Popen("(date>&2; sed s/the web/UNIX/gI "+output_file_name, shell=True, cwd=tmpdir, stderr=PIPE)
+ (_,stderr) = p.communicate()
+ logging.debug('Got stderr : '+stderr)
+ return jsonify(stderr=stderr, outputfile_url=output_file_name)
+ logging.debug('GET')
+ return open("/var/www/unix2web/index.html", 'r').read()
+
+@app.route('/index.css')
+def wrapper():
+ resp = Response(response=open('/var/www/unix2web/index.css', 'r').read(),
+ status=200,
+ mimetype="text/css")
+ return resp
+
+if __name__ == '__main__':
+ app.run()
diff --git a/unix2web.wsgi b/unix2web.wsgi
new file mode 100644
index 0000000..8620039
--- /dev/null
+++ b/unix2web.wsgi
@@ -0,0 +1,5 @@
+import sys
+sys.path.insert(0, '/var/www/unix2web')
+
+from unix2web import app as application
+