From 6aff183b54d0af4c6cf2a97a8a16047100f16e1c Mon Sep 17 00:00:00 2001
From: James Vasile
Date: Thu, 1 Dec 2011 09:18:44 -0500
Subject: [PATCH 01/31] move to sqlite3 + json dict storage for users
---
Makefile | 7 ++++++-
cfg.py | 1 +
data/users.sqlite3.distrib | Bin 0 -> 3072 bytes
modules/installed/lib/user_store.py | 13 ++++++++++++-
plinth.py | 9 +++++++--
5 files changed, 26 insertions(+), 4 deletions(-)
create mode 100644 data/users.sqlite3.distrib
diff --git a/Makefile b/Makefile
index 70bc7ad3d..35086eb87 100644
--- a/Makefile
+++ b/Makefile
@@ -8,9 +8,14 @@ COMPRESSED_CSS := $(patsubst %.css,%.tiny.css,$(CSS))
PWD=`pwd`
## Catch-all tagets
-default: cherrypy.config dirs template css docs
+default: cherrypy.config dirs template css docs dbs
all: default
+dbs: data/users.sqlite3
+
+data/users.sqlite3: data/users.sqlite3.distrib
+ cp data/users.sqlite3.distrib data/users.sqlite3
+
dirs:
@mkdir -p data/cherrypy_sessions
diff --git a/cfg.py b/cfg.py
index db237fc40..0f98be007 100644
--- a/cfg.py
+++ b/cfg.py
@@ -4,6 +4,7 @@ import os
file_root = os.path.dirname(os.path.realpath(__file__))
data_dir = os.path.join(file_root, "data")
store_file = os.path.join(data_dir, "store.sqlite3")
+user_db = os.path.join(data_dir, "users")
status_log_file = os.path.join(data_dir, "status.log")
access_log_file = os.path.join(data_dir, "access.log")
users_dir = os.path.join(data_dir, "users")
diff --git a/data/users.sqlite3.distrib b/data/users.sqlite3.distrib
new file mode 100644
index 0000000000000000000000000000000000000000..2d805a1537d2501e6dddf3302a83dd69935d620c
GIT binary patch
literal 3072
zcmeHH!Ab)$5KT6vV4>%|#`R*M!dkUjL9l9Xy{Ns3l(ajwi@TdP$!bMBh{t}Nzu-rB
z@?etfLMiwKX2>L&H}fXsL2`TDj}_1f7b#Qp096pi=$ul7kf)t!FAeLB@zU1!CAPVG
zXzy#gPJWO_mWV9L=VpP6odQk)tH2em`o522#YPE8#YHiBmp8rcphpMYi++zjT!21AK{Er
Date: Thu, 1 Dec 2011 09:20:26 -0500
Subject: [PATCH 02/31] add TODO: at exit, commit db
---
modules/installed/lib/user_store.py | 2 ++
1 file changed, 2 insertions(+)
diff --git a/modules/installed/lib/user_store.py b/modules/installed/lib/user_store.py
index c3fb0e17e..01a3e7724 100644
--- a/modules/installed/lib/user_store.py
+++ b/modules/installed/lib/user_store.py
@@ -15,6 +15,8 @@ class UserStore(UserStoreModule, sqlite_db):
def close(self):
self.__exit__()
+ #TODO: at exit, commit db
+
class UserStoreOld():
#class UserStore(UserStoreModule):
"""The user storage is on disk. Rather than slurp the entire
From df140feb52a5736c42bd66e54df9bdc9a6ea52f0 Mon Sep 17 00:00:00 2001
From: James Vasile
Date: Thu, 1 Dec 2011 09:31:10 -0500
Subject: [PATCH 03/31] autocommit
---
modules/installed/lib/user_store.py | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/modules/installed/lib/user_store.py b/modules/installed/lib/user_store.py
index 01a3e7724..3466555fa 100644
--- a/modules/installed/lib/user_store.py
+++ b/modules/installed/lib/user_store.py
@@ -10,13 +10,11 @@ class UserStore(UserStoreModule, sqlite_db):
def __init__(self):
self.data_dir = cfg.users_dir
self.db_file = cfg.user_db
- sqlite_db.__init__(self, self.db_file)
+ sqlite_db.__init__(self, self.db_file, autocommit=True)
self.__enter__()
def close(self):
self.__exit__()
- #TODO: at exit, commit db
-
class UserStoreOld():
#class UserStore(UserStoreModule):
"""The user storage is on disk. Rather than slurp the entire
From 69856fdbbdb8e30e96971a7a58239881263a6c82 Mon Sep 17 00:00:00 2001
From: James Vasile
Date: Thu, 1 Dec 2011 10:04:46 -0500
Subject: [PATCH 04/31] complete the transition to sqlite
---
modules/installed/lib/auth.py | 2 +-
modules/installed/lib/user_store.py | 2 ++
modules/installed/router/router.py | 2 +-
modules/installed/system/users.py | 14 +++++++-------
4 files changed, 11 insertions(+), 9 deletions(-)
diff --git a/modules/installed/lib/auth.py b/modules/installed/lib/auth.py
index 4b0f22973..988f8dd9d 100644
--- a/modules/installed/lib/auth.py
+++ b/modules/installed/lib/auth.py
@@ -18,7 +18,7 @@ def check_credentials(username, passphrase):
"""Verifies credentials for username and passphrase.
Returns None on success or a string describing the error on failure"""
- u = cfg.users.get(username)
+ u = cfg.users[username]
if u is None:
cfg.log("Unknown user: %s" % username)
return u"Username %s is unknown to me." % username
diff --git a/modules/installed/lib/user_store.py b/modules/installed/lib/user_store.py
index 3466555fa..a4042c102 100644
--- a/modules/installed/lib/user_store.py
+++ b/modules/installed/lib/user_store.py
@@ -14,6 +14,8 @@ class UserStore(UserStoreModule, sqlite_db):
self.__enter__()
def close(self):
self.__exit__()
+ def expert(self):
+ return False
class UserStoreOld():
#class UserStore(UserStoreModule):
diff --git a/modules/installed/router/router.py b/modules/installed/router/router.py
index 764d43c4d..0d12c875e 100644
--- a/modules/installed/router/router.py
+++ b/modules/installed/router/router.py
@@ -60,7 +60,7 @@ router does. With the addition of some extra modules, its abilities
can rival those of high-end routers costing hundreds of dollars.
""" % cfg.box_name + parts['sidebar_right']
if not cfg.users.expert():
- main += """
In basic mode, you don't need to do any
+ parts['main'] += """
In basic mode, you don't need to do any
router setup before you can go online. Just plug your
%(product)s in to your cable or DSL modem and the router
will try to get you on the internet using DHCP.
diff --git a/modules/installed/system/users.py b/modules/installed/system/users.py
index ce99f6417..669183c69 100644
--- a/modules/installed/system/users.py
+++ b/modules/installed/system/users.py
@@ -51,11 +51,11 @@ class add(FormPlugin, PagePlugin):
if not username: msg = add_message(msg, _("Must specify a username!"))
if not md5_password: msg = add_message(msg, _("Must specify a password!"))
- if cfg.users.get(username):
+ if username in cfg.users:
msg = add_message(msg, _("User already exists!"))
else:
try:
- cfg.users.set(User(dict={'username':username, 'name':name, 'email':email, 'password':md5_password}))
+ cfg.users[username]= User(dict={'username':username, 'name':name, 'email':email, 'password':md5_password})
except:
msg = add_message(msg, _("Error storing user!"))
@@ -77,7 +77,7 @@ class edit(FormPlugin, PagePlugin):
system.
Deleting users is permanent!
""" % (cfg.product_name, cfg.box_name))
def main(self, msg=''):
- users = cfg.users.get_all()
+ users = cfg.users.keys()
add_form = Form(title=_("Edit or Delete User"), action="/sys/users/edit", message=msg)
add_form.html('Delete ')
for uname in sorted(users.keys()):
@@ -95,12 +95,12 @@ class edit(FormPlugin, PagePlugin):
cfg.log.info("%s asked to delete %s" % (cherrypy.session.get(cfg.session_key), usernames))
if usernames:
for username in usernames:
- if cfg.users.exists(username):
+ if username in cfg.users:
try:
- cfg.users.remove(username)
+ del cfg.users[username]
msg.add(_("Deleted user %s." % username))
except IOError, e:
- if cfg.users.get('username', reload=True):
+ if 'username' in cfg.users:
m = _("Error on deletion, user %s not fully deleted: %s" % (username, e))
cfg.log.error(m)
msg.add(m)
@@ -117,7 +117,7 @@ class edit(FormPlugin, PagePlugin):
return self.fill_template(title="", main=main, sidebar_left=self.sidebar_left, sidebar_right=self.sidebar_right)
sidebar_right = ''
- u = cfg.users.get(kwargs['username'])
+ u = cfg.users[kwargs['username']]
if not u:
main = _("
Could not find a user with username of %s!
" % kwargs['username'])
return self.fill_template(template="err", title=_("Unnown User"), main=main,
From 2ec8608585f4fcfaa1f297bac43c40e041ecca6f Mon Sep 17 00:00:00 2001
From: James Vasile
Date: Thu, 1 Dec 2011 10:05:42 -0500
Subject: [PATCH 05/31] move away from importing all of util
---
plugin_mount.py | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/plugin_mount.py b/plugin_mount.py
index d8b7022d3..5ad414a8b 100644
--- a/plugin_mount.py
+++ b/plugin_mount.py
@@ -2,6 +2,7 @@ import cherrypy
from modules.auth import require
import cfg
from util import *
+import util as u
class PluginMount(type):
"""See http://martyalchin.com/2008/jan/10/simple-plugin-framework/ for documentation"""
@@ -72,7 +73,7 @@ class PagePlugin:
cfg.log.info("Registering page: %s" % url)
exec "cfg.html_root.%s = self" % (url)
def fill_template(self, *args, **kwargs):
- return page_template(*args, **kwargs)
+ return u.page_template(*args, **kwargs)
def forms(self, url, *args, **kwargs):
for form in cfg.forms:
@@ -152,7 +153,7 @@ class FormPlugin():
except AttributeError:
pass
cfg.log("%%%%%%%%%%% %s" % kwargs)
- return page_template(*args, **kwargs)
+ return u.page_template(*args, **kwargs)
class UserStoreModule:
"""
From d728cb1cd58ce7ecadb453d7777020a8b89ac4bb Mon Sep 17 00:00:00 2001
From: James Vasile
Date: Thu, 1 Dec 2011 10:06:49 -0500
Subject: [PATCH 06/31] add withsqlite
---
vendor/withsqlite/__init__.py | 0
vendor/withsqlite/withsqlite.py | 197 ++++++++++++++++++++++++++++++++
2 files changed, 197 insertions(+)
create mode 100644 vendor/withsqlite/__init__.py
create mode 100644 vendor/withsqlite/withsqlite.py
diff --git a/vendor/withsqlite/__init__.py b/vendor/withsqlite/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/vendor/withsqlite/withsqlite.py b/vendor/withsqlite/withsqlite.py
new file mode 100644
index 000000000..40aaa8812
--- /dev/null
+++ b/vendor/withsqlite/withsqlite.py
@@ -0,0 +1,197 @@
+#!/usr/bin/env python
+
+"""
+withsqlite - uses an sqlite db as a back end for a dict-like object,
+kind of like shelve but with json and sqlite3.
+
+Copyright 2011 James Vasile
+Released under the GNU General Public License, version 3 or later.
+See https://www.gnu.org/licenses/gpl-3.0.html for terms.
+
+Repo is at . Patches welcome!
+
+This file was developed as part of planeteria
+
+"""
+import os, sys, sqlite3, time
+import simplejson as json
+
+def to_json(python_object):
+ if isinstance(python_object, time.struct_time):
+ return {'__class__': 'time.asctime',
+ '__value__': time.asctime(python_object)}
+
+ return {'__class__': 'basestring',
+ '__value__': str(python_object)}
+
+class sqlite_db():
+ """
+Backends a dict on an sqlite db. This class aims to present like a
+dict wherever it can.
+
+USE:
+import sqlite_db from withsqlite
+with sqlite_db("filename") as db:
+ db['aaa'] = {'test':'ok'}
+ print db.items()
+
+BUGS:
+
+vals are json serialized before being written, so if you can't
+serialize it, you can't put it in the dict.
+
+Unimplemented mapping API:
+a.copy() a (shallow) copy of a
+a.update([b]) updates a with key/value pairs from b, overwriting existing keys, returns None
+a.fromkeys(seq[, value]) Creates a new dictionary with keys from seq and values set to value
+a.setdefault(k[, x]) a[k] if k in a, else x (also setting it)
+a.pop(k[, x]) a[k] if k in a, else x (and remove k)
+a.popitem() remove and return an arbitrary (key, value) pair
+a.iteritems() return an iterator over (key, value) pairs
+a.iterkeys() return an iterator over the mapping's keys
+a.itervalues() return an iterator over the mapping's values
+
+>>> with sqlite_db("test") as db:
+... db.clear()
+... db.items()
+...
+[]
+>>> with sqlite_db("test") as db:
+... db['a']="test"
+... db.items()
+...
+[(u'a', u'test')]
+>>> with sqlite_db("test") as db:
+... db['as']="test"
+... db.items()
+...
+[(u'a', u'test'), (u'as', u'test')]
+>>> with sqlite_db("test") as db:
+... db['b']=[1,2,3,4,5]
+... del db['b']
+...
+>>> with sqlite_db("test") as db:
+... db.items()
+... len(db)
+...
+[(u'a', u'test'), (u'as', u'test')]
+2
+>>> with sqlite_db("test") as db:
+... db.keys()
+...
+[u'a', u'as']
+>>> with sqlite_db("test") as db:
+... db.values()
+...
+[u'test', u'test']
+>>> with sqlite_db("test") as db:
+... db.get('b',5)
+...
+5
+>>> with sqlite_db("test") as db:
+... db.get('b')
+...
+>>> with sqlite_db("test") as db:
+... db.get('c',5)
+...
+5
+>>> with sqlite_db("test") as db:
+... 'as' in db
+...
+True
+>>> with sqlite_db("test") as db:
+... 'asdf' not in db
+...
+True
+>>> with sqlite_db("test") as db:
+... db.has_key('as')
+...
+True
+>>>
+"""
+
+ def __init__(self, fname, autocommit=False, check_same_thread=False):
+ self.fname = fname + ".sqlite3"
+ self.autocomit = autocommit
+ self.check_same_thread = check_same_thread
+ def __enter__(self):
+ if not os.path.exists(self.fname):
+ self.make_db()
+ self.conn = sqlite3.connect(self.fname, check_same_thread = self.check_same_thread)
+ self.crsr = self.conn.cursor()
+ return self
+ def __exit__(self, type, value, traceback):
+ self.conn.commit()
+ self.crsr.close()
+ def make_db(self):
+ conn = sqlite3.connect(self.fname)
+ c = conn.cursor()
+ c.execute('''create table store (key text unique, val text)''')
+ conn.commit()
+ c.close()
+ def __delitem__(self, key):
+ """del a[k] remove a[k] from a"""
+ self.crsr.execute("delete from store where key=?", [key])
+ def jsonize(self,val):
+ "If it's just a string, serialize it ourselves"
+ if isinstance(val, basestring):
+ return '"%s"' % val
+ return json.dumps(val, default=to_json, sort_keys=True, indent=3)
+ def __setitem__(self, key, val):
+ """a[k] = v set a[k] to v """
+
+ try:
+ if val == self.__getitem__(key):
+ return
+ self.crsr.execute("update or fail store set val=? where key==?", [self.jsonize(val), key])
+ except KeyError:
+ self.crsr.execute("insert into store values (?, ?)", [key, self.jsonize(val)])
+
+ if self.autocommit: self.commit()
+ def __getitem__(self, key):
+ """a[k] the item of a with key k (1), (10)"""
+ self.crsr.execute('select val from store where key=?', [key])
+ try:
+ f = self.crsr.fetchone()[0]
+ except TypeError:
+ raise KeyError, key
+ return json.loads(f)
+ def __contains__(self, key):
+ """k in a True if a has a key k, else False
+ k not in a Equivalent to not k in a"""
+ self.crsr.execute("select COUNT(*) from store where key=?", [key])
+ return self.crsr.fetchone()[0] != 0
+ def has_key(self, key):
+ return self.__contains__(key)
+ def __len__(self):
+ """len(a) the number of items in a"""
+ self.crsr.execute("select COUNT(*) from store")
+ return self.crsr.fetchone()[0]
+ def keys(self):
+ """a.keys() a copy of a's list of keys"""
+ self.crsr.execute("select key from store")
+ return [f[0] for f in self.crsr.fetchall()]
+ def values(self):
+ """a.values() a copy of a's list of values"""
+ self.crsr.execute("select val from store")
+ return [json.loads(f[0]) for f in self.crsr.fetchall()]
+ def items(self):
+ """a.items() a copy of a's list of (key, value) pairs"""
+ self.crsr.execute("select * from store")
+ return [(f[0], json.loads(f[1])) for f in self.crsr.fetchall()]
+ def get(self, k, x=None):
+ """a.get(k[, x]) a[k] if k in a, else x """
+ try:
+ return self.__getitem__(k)
+ except KeyError:
+ return x
+ def commit(self):
+ self.conn.commit()
+ def clear(self):
+ """a.clear() remove all items from a"""
+ self.crsr.execute("delete from store")
+ if self.autocommit: self.commit()
+
+if __name__=="__main__":
+ import doctest
+ doctest.testmod()
From de840a566a6865c8a95167f541114735c2e193bb Mon Sep 17 00:00:00 2001
From: James Vasile
Date: Thu, 15 Dec 2011 15:40:06 -0500
Subject: [PATCH 07/31] cfg.py shouldn't overwrite local config on update
---
cfg.py => cfg.sample.py | 0
1 file changed, 0 insertions(+), 0 deletions(-)
rename cfg.py => cfg.sample.py (100%)
diff --git a/cfg.py b/cfg.sample.py
similarity index 100%
rename from cfg.py
rename to cfg.sample.py
From d641d884bf85028cfa28d723690cdfb36534b42d Mon Sep 17 00:00:00 2001
From: James Vasile
Date: Thu, 15 Dec 2011 15:52:39 -0500
Subject: [PATCH 08/31] cfg.py shouldn't overwrite local config on update
---
Makefile | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/Makefile b/Makefile
index 35086eb87..3afdbcfb0 100644
--- a/Makefile
+++ b/Makefile
@@ -1,3 +1,4 @@
+#SHELL := /bin/bash
MAKE=make
#TODO: add install target
@@ -8,7 +9,7 @@ COMPRESSED_CSS := $(patsubst %.css,%.tiny.css,$(CSS))
PWD=`pwd`
## Catch-all tagets
-default: cherrypy.config dirs template css docs dbs
+default: cfg cherrypy.config dirs template css docs dbs
all: default
dbs: data/users.sqlite3
@@ -19,6 +20,9 @@ data/users.sqlite3: data/users.sqlite3.distrib
dirs:
@mkdir -p data/cherrypy_sessions
+cfg: Makefile
+ test -f cfg.py || cp cfg.sample.py cfg.py
+
cherrypy.config: Makefile
@echo [global]\\n\
server.socket_host = \'0.0.0.0\'\\n\
From cbc452d86cfb41d0273b07943e266fc86c50cae3 Mon Sep 17 00:00:00 2001
From: James Vasile
Date: Thu, 15 Dec 2011 17:52:15 -0500
Subject: [PATCH 09/31] start to make proxy
---
share/apache2/plinth.conf | 1 +
1 file changed, 1 insertion(+)
create mode 100644 share/apache2/plinth.conf
diff --git a/share/apache2/plinth.conf b/share/apache2/plinth.conf
new file mode 100644
index 000000000..c25e39840
--- /dev/null
+++ b/share/apache2/plinth.conf
@@ -0,0 +1 @@
+ProxyPass /plinth/ http://localhost:8000/
From 62efdd96b5f91a2e13948c31625fb950cbf13603 Mon Sep 17 00:00:00 2001
From: James Vasile
Date: Fri, 16 Dec 2011 20:54:01 -0500
Subject: [PATCH 10/31] daemonize
---
plinth.py | 24 ++++++++++++++++++++++--
share/init.d/plinth | 38 ++++++++++++++++++++++++++++++++++++++
2 files changed, 60 insertions(+), 2 deletions(-)
create mode 100755 share/init.d/plinth
diff --git a/plinth.py b/plinth.py
index 6f350097c..7a60adcda 100755
--- a/plinth.py
+++ b/plinth.py
@@ -1,7 +1,6 @@
#!/usr/bin/env python
-# Start listener, just for testing
-import os, sys
+import os, sys, argparse
#import logging
from gettext import gettext as _
import cfg
@@ -9,6 +8,10 @@ if not os.path.join(cfg.file_root, "vendor") in sys.path:
sys.path.append(os.path.join(cfg.file_root, "vendor"))
import cherrypy
+from cherrypy import _cpserver
+from cherrypy.process.plugins import Daemonizer
+Daemonizer(cherrypy.engine).subscribe()
+
import plugin_mount
from util import *
from logger import Logger
@@ -96,7 +99,24 @@ tools.staticfile.on = True
tools.staticfile.filename = "{fileroot}/static/theme/favicon.ico"
""".format(fileroot=cfg.file_root))
+def parse_arguments():
+ parser = argparse.ArgumentParser(description='Plinht web interface for the FreedomBox.')
+ parser.add_argument('--pidfile', default="",
+ help='specify a file in which the server may write its pid')
+ args=parser.parse_args()
+ if args.pidfile:
+ cfg.pidfile = args.pidfile
+
def setup():
+ parse_arguments()
+
+ try:
+ if cfg.pidfile:
+ from cherrypy.process.plugins import PIDFile
+ PIDFile(cherrypy.engine, cfg.pidfile).subscribe()
+ except AttributeError:
+ pass
+
os.chdir(cfg.file_root)
cherrypy.config.update({'error_page.404': error_page_404})
cherrypy.config.update({'error_page.500': error_page_500})
diff --git a/share/init.d/plinth b/share/init.d/plinth
new file mode 100755
index 000000000..f5df9b712
--- /dev/null
+++ b/share/init.d/plinth
@@ -0,0 +1,38 @@
+#!/bin/bash
+# This file is /etc/init.d/plinth
+DAEMON=/usr/bin/plinth.py
+PID_FILE=/var/run/plinth.pid
+
+start_plinth (){
+ if [ -f $PID_FILE ]; then
+ echo Already running with a pid of `cat $PID_FILE`.
+ else
+ $DAEMON --pidfile=$PID_FILE
+ fi
+}
+
+stop_plinth () {
+ if [ -f $PID_FILE ]; then
+ kill -15 `cat $PID_FILE`
+ rm -rf $PID_FILE
+ else
+ echo "No pid file at $PID_FILE suggests plinth is not running."
+ fi
+}
+
+test -x $DAEMON || exit 0
+case "$1" in
+ start)
+ echo "Starting Plinth."
+ start_plinth
+ ;;
+ stop)
+ echo "Stoping Plinth."
+ stop_plinth
+ ;;
+ restart)
+ $0 stop
+ $0 start
+ ;;
+
+esac
From d8c1a051c2db12b5e6e798cdbd1ff17886dae108 Mon Sep 17 00:00:00 2001
From: James Vasile
Date: Fri, 16 Dec 2011 23:42:18 -0500
Subject: [PATCH 11/31] move port to cfg
---
cfg.sample.py | 3 +++
plinth.py | 10 +++++-----
2 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/cfg.sample.py b/cfg.sample.py
index 0f98be007..34ca0231d 100644
--- a/cfg.sample.py
+++ b/cfg.sample.py
@@ -12,6 +12,9 @@ users_dir = os.path.join(data_dir, "users")
product_name = "Plinth"
box_name = "Freedom Plug"
+port = 8000
+
+## Do not edit below this line ##
html_root = None
main_menu = Menu()
diff --git a/plinth.py b/plinth.py
index 7a60adcda..f630ccd28 100755
--- a/plinth.py
+++ b/plinth.py
@@ -81,14 +81,14 @@ def write_cherrypy_config():
[global]
server.socket_host = '0.0.0.0'
-server.socket_port = 8000
+server.socket_port = %(port)s
server.thread_pool = 10
-tools.staticdir.root = "{fileroot}"
+tools.staticdir.root = "%(fileroot)s"
tools.sessions.on = True
tools.auth.on = True
tools.sessions.storage_type = "file"
tools.sessions.timeout = 90
-tools.sessions.storage_path = "{fileroot}/data/cherrypy_sessions"
+tools.sessions.storage_path = "%(fileroot)s/data/cherrypy_sessions"
[/static]
tools.staticdir.on = True
@@ -96,8 +96,8 @@ tools.staticdir.dir = "static"
[/favicon.ico]
tools.staticfile.on = True
-tools.staticfile.filename = "{fileroot}/static/theme/favicon.ico"
-""".format(fileroot=cfg.file_root))
+tools.staticfile.filename = "%(fileroot)s/static/theme/favicon.ico"
+""" % {'port':cfg.port, 'fileroot':cfg.file_root})
def parse_arguments():
parser = argparse.ArgumentParser(description='Plinht web interface for the FreedomBox.')
From 1a00c3adb743b313fb44f9833139f25027136c7b Mon Sep 17 00:00:00 2001
From: James Vasile
Date: Fri, 16 Dec 2011 23:42:29 -0500
Subject: [PATCH 12/31] mkdir
---
util.py | 20 +++++++++++++++++++-
1 file changed, 19 insertions(+), 1 deletion(-)
diff --git a/util.py b/util.py
index 11bb647e0..e43af8371 100644
--- a/util.py
+++ b/util.py
@@ -1,9 +1,27 @@
-import sys
+import os, sys
import cherrypy
import cfg
import sqlite3
from filedict import FileDict
+def mkdir(newdir):
+ """works the way a good mkdir should :)
+ - already exists, silently complete
+ - regular file in the way, raise an exception
+ - parent directory(ies) does not exist, make them as well
+ """
+ if os.path.isdir(newdir):
+ pass
+ elif os.path.isfile(newdir):
+ raise OSError("a file with the same name as the desired " \
+ "dir, '%s', already exists." % newdir)
+ else:
+ head, tail = os.path.split(newdir)
+ if head and not os.path.isdir(head):
+ mkdir(head)
+ #print "mkdir %s" % repr(newdir)
+ if tail:
+ os.mkdir(newdir)
def is_string(obj):
isinstance(obj, basestring)
def is_ascii(s):
From 69f3375a4f02986e11c4e86b8c0b153a1a5683ce Mon Sep 17 00:00:00 2001
From: James Vasile
Date: Fri, 16 Dec 2011 23:43:30 -0500
Subject: [PATCH 13/31] start adding base_href
---
cfg.sample.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/cfg.sample.py b/cfg.sample.py
index 34ca0231d..186f48729 100644
--- a/cfg.sample.py
+++ b/cfg.sample.py
@@ -3,6 +3,7 @@ import os
file_root = os.path.dirname(os.path.realpath(__file__))
data_dir = os.path.join(file_root, "data")
+base_href=""
store_file = os.path.join(data_dir, "store.sqlite3")
user_db = os.path.join(data_dir, "users")
status_log_file = os.path.join(data_dir, "status.log")
From 9eada7d59640a4c418de127432efc20847896085 Mon Sep 17 00:00:00 2001
From: James Vasile
Date: Fri, 16 Dec 2011 23:44:13 -0500
Subject: [PATCH 14/31] update withsqlite.py
---
vendor/withsqlite/withsqlite.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/vendor/withsqlite/withsqlite.py b/vendor/withsqlite/withsqlite.py
index 40aaa8812..45d66c17b 100644
--- a/vendor/withsqlite/withsqlite.py
+++ b/vendor/withsqlite/withsqlite.py
@@ -112,7 +112,7 @@ True
def __init__(self, fname, autocommit=False, check_same_thread=False):
self.fname = fname + ".sqlite3"
- self.autocomit = autocommit
+ self.autocommit = autocommit
self.check_same_thread = check_same_thread
def __enter__(self):
if not os.path.exists(self.fname):
From fa89070e011fc205529073ed18d962f98ea3efd4 Mon Sep 17 00:00:00 2001
From: James Vasile
Date: Fri, 16 Dec 2011 23:44:54 -0500
Subject: [PATCH 15/31] add order to privacy page plugin
---
modules/installed/privacy/privacy.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/modules/installed/privacy/privacy.py b/modules/installed/privacy/privacy.py
index b62ba5d2e..8eee56524 100644
--- a/modules/installed/privacy/privacy.py
+++ b/modules/installed/privacy/privacy.py
@@ -5,6 +5,7 @@ from modules.auth import require
import cfg
class Privacy(PagePlugin):
+ order = 20 # order of running init in PagePlugins
def __init__(self, *args, **kwargs):
PagePlugin.__init__(self, *args, **kwargs)
self.register_page("privacy")
From c5d647018356cf0bc24cacc43e3c04abb4a7c381 Mon Sep 17 00:00:00 2001
From: James Vasile
Date: Fri, 16 Dec 2011 23:45:23 -0500
Subject: [PATCH 16/31] start second server
---
plinth.py | 36 ++++++++++++++++++++++++++++++++++--
1 file changed, 34 insertions(+), 2 deletions(-)
diff --git a/plinth.py b/plinth.py
index f630ccd28..7edbf1062 100755
--- a/plinth.py
+++ b/plinth.py
@@ -129,11 +129,43 @@ def setup():
cfg.log("Loaded %d page plugins" % len(cfg.page_plugins))
cfg.forms = plugin_mount.FormPlugin.get_plugins()
+ # Add an extra server
+ server = _cpserver.Server()
+ server.socket_host = '127.0.0.1'
+ server.socket_port = 52854
+ server.subscribe()
+
+ # Configure default server
+ cherrypy.config.update({'server.socket_host': '0.0.0.0',
+ 'server.socket_port': cfg.port,
+ 'server.thread_pool':10,
+ 'tools.staticdir.root': cfg.file_root,
+ 'tools.sessions.on':True,
+ 'tools.auth.on':True,
+ 'tools.sessions.storage_type':"file",
+ 'tools.sessions.timeout':90,
+ 'tools.sessions.storage_path':"%s/data/cherrypy_sessions" % cfg.file_root,
+
+ })
+
+ config = {'/': {'tools.staticdir.root': '%s/static' % cfg.file_root},
+ '/static': {'tools.staticdir.on': True,
+ 'tools.staticdir.dir':"."},
+ '/favicon.ico':{'tools.staticfile.on':True,
+ 'tools.staticfile.filename': "%s/static/theme/favicon.ico" % cfg.file_root}
+ }
+ cherrypy.tree.mount(cfg.html_root, '/', config=config)
+
+
+ cherrypy.engine.signal_handler.subscribe()
+
+
def main():
setup()
- cherrypy.quickstart(cfg.html_root, script_name='/', config="cherrypy.config")
-
+ print "localhost %d" % cfg.port
+ cherrypy.engine.start()
+ cherrypy.engine.block()
if __name__ == '__main__':
main()
From 515b133c4c51cbd80bcf98f090d770711f97b16e Mon Sep 17 00:00:00 2001
From: James Vasile
Date: Sat, 17 Dec 2011 14:02:37 -0500
Subject: [PATCH 17/31] rm old code
---
plinth.py | 33 ---------------------------------
1 file changed, 33 deletions(-)
diff --git a/plinth.py b/plinth.py
index 7edbf1062..954cb2cc0 100755
--- a/plinth.py
+++ b/plinth.py
@@ -67,38 +67,6 @@ def load_modules():
else:
cfg.log("skipping %s" % name)
-def write_cherrypy_config():
- """Write the cherrpy.config file.
-
- We could just make a dict instead of writing a data file and then
- reading it back, but I like the output for debugging purposes.
- Future versions might do the more efficient thing.
- """
-
- with open(os.path.join(cfg.file_root, "cherrypy.config"), 'w') as OUTF:
- OUTF.write(
-"""### Generated file, do not edit! ###
-
-[global]
-server.socket_host = '0.0.0.0'
-server.socket_port = %(port)s
-server.thread_pool = 10
-tools.staticdir.root = "%(fileroot)s"
-tools.sessions.on = True
-tools.auth.on = True
-tools.sessions.storage_type = "file"
-tools.sessions.timeout = 90
-tools.sessions.storage_path = "%(fileroot)s/data/cherrypy_sessions"
-
-[/static]
-tools.staticdir.on = True
-tools.staticdir.dir = "static"
-
-[/favicon.ico]
-tools.staticfile.on = True
-tools.staticfile.filename = "%(fileroot)s/static/theme/favicon.ico"
-""" % {'port':cfg.port, 'fileroot':cfg.file_root})
-
def parse_arguments():
parser = argparse.ArgumentParser(description='Plinht web interface for the FreedomBox.')
parser.add_argument('--pidfile', default="",
@@ -120,7 +88,6 @@ def setup():
os.chdir(cfg.file_root)
cherrypy.config.update({'error_page.404': error_page_404})
cherrypy.config.update({'error_page.500': error_page_500})
- write_cherrypy_config()
cfg.log = Logger()
load_modules()
cfg.html_root = Root()
From ca9f8e31243427dadd064e1a6934397e804b664e Mon Sep 17 00:00:00 2001
From: James Vasile
Date: Mon, 19 Dec 2011 09:04:29 -0500
Subject: [PATCH 18/31] redirect / and /plinth to /plinth/
---
share/apache2/plinth.conf | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/share/apache2/plinth.conf b/share/apache2/plinth.conf
index c25e39840..7046b10d9 100644
--- a/share/apache2/plinth.conf
+++ b/share/apache2/plinth.conf
@@ -1 +1,11 @@
ProxyPass /plinth/ http://localhost:8000/
+
+
+Options Indexes FollowSymLinks
+
+RewriteEngine on
+RewriteRule [^/]*/plinth$ plinth/ [R]
+RewriteRule [^/]*/$ plinth/ [R]
+#RewriteRule ^$ plinth/ [R]
+
+
From c9863bc0f8270ec16f05c6edb614ca285feaa890 Mon Sep 17 00:00:00 2001
From: James Vasile
Date: Tue, 20 Dec 2011 20:50:58 -0500
Subject: [PATCH 19/31] subdomain for plinth
---
share/apache2/plinth.conf | 40 +++++++++++++++++++++++++++++++--------
static/static | 1 +
2 files changed, 33 insertions(+), 8 deletions(-)
create mode 120000 static/static
diff --git a/share/apache2/plinth.conf b/share/apache2/plinth.conf
index 7046b10d9..6f0612f6a 100644
--- a/share/apache2/plinth.conf
+++ b/share/apache2/plinth.conf
@@ -1,11 +1,35 @@
-ProxyPass /plinth/ http://localhost:8000/
-
-Options Indexes FollowSymLinks
+
+ DocumentRoot /dev/null
+ ServerName plinth
-RewriteEngine on
-RewriteRule [^/]*/plinth$ plinth/ [R]
-RewriteRule [^/]*/$ plinth/ [R]
-#RewriteRule ^$ plinth/ [R]
+ ## Force ssl
+ RewriteEngine on
+ ReWriteCond %{SERVER_PORT} !^443$
+ RewriteRule ^/(.*) https://%{HTTP_HOST}/$1 [NC,R,L]
+
+
+
+
+ DocumentRoot /home/james/src/plinth/static
+ ServerName plinth
+
+ SSLEngine on
+ SSLCertificateFile /etc/apache2/ssl/apache.pem
+
+ ## Use a rule like this to hang plinth off a subdir
+ #RewriteEngine on
+ #RewriteRule ^/plinth/(.*)$ http://localhost:8000/$1 [P,L]
+ #Use the following to debug rewrite rules
+ #RewriteLog "/var/log/apache2/rewrite.log"
+ #RewriteLogLevel 9
+
+ ## Use proxy directives to hand plinth off a domain or subdomain
+ ProxyPass /static !
+ ProxyPass / http://localhost:8000/
+ ProxyPassReverse / http://localhost:8000/
+
+ allow from all
+
+
-
diff --git a/static/static b/static/static
new file mode 120000
index 000000000..945c9b46d
--- /dev/null
+++ b/static/static
@@ -0,0 +1 @@
+.
\ No newline at end of file
From 51a74abc82d005a49c52e86ef499acf03b3d8a74 Mon Sep 17 00:00:00 2001
From: James Vasile
Date: Tue, 20 Dec 2011 21:22:36 -0500
Subject: [PATCH 20/31] listen locally only, proxy to the outside world
---
plinth.py | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/plinth.py b/plinth.py
index 954cb2cc0..b8afa7582 100755
--- a/plinth.py
+++ b/plinth.py
@@ -103,8 +103,8 @@ def setup():
server.subscribe()
# Configure default server
- cherrypy.config.update({'server.socket_host': '0.0.0.0',
- 'server.socket_port': cfg.port,
+ cherrypy.config.update({'server.socket_host': '127.0.0.1',
+ 'server.socket_port': cfg.port,
'server.thread_pool':10,
'tools.staticdir.root': cfg.file_root,
'tools.sessions.on':True,
@@ -115,15 +115,14 @@ def setup():
})
- config = {'/': {'tools.staticdir.root': '%s/static' % cfg.file_root},
+ config = {'/': {'tools.staticdir.root': '%s/static' % cfg.file_root,
+ 'tools.proxy.on':True,},
'/static': {'tools.staticdir.on': True,
'tools.staticdir.dir':"."},
'/favicon.ico':{'tools.staticfile.on':True,
'tools.staticfile.filename': "%s/static/theme/favicon.ico" % cfg.file_root}
}
cherrypy.tree.mount(cfg.html_root, '/', config=config)
-
-
cherrypy.engine.signal_handler.subscribe()
From 873709794cd36267d76fabed45e0cb7768e73406 Mon Sep 17 00:00:00 2001
From: James Vasile
Date: Tue, 20 Dec 2011 21:25:20 -0500
Subject: [PATCH 21/31] move basehref
---
cfg.sample.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/cfg.sample.py b/cfg.sample.py
index 186f48729..2c8a8adf1 100644
--- a/cfg.sample.py
+++ b/cfg.sample.py
@@ -3,7 +3,6 @@ import os
file_root = os.path.dirname(os.path.realpath(__file__))
data_dir = os.path.join(file_root, "data")
-base_href=""
store_file = os.path.join(data_dir, "store.sqlite3")
user_db = os.path.join(data_dir, "users")
status_log_file = os.path.join(data_dir, "status.log")
@@ -18,4 +17,5 @@ port = 8000
## Do not edit below this line ##
html_root = None
main_menu = Menu()
+base_href = ""
From 3605889eeb9253f7a3f550b3cae62adfdf901f1f Mon Sep 17 00:00:00 2001
From: James Vasile
Date: Tue, 20 Dec 2011 21:26:03 -0500
Subject: [PATCH 22/31] ignore backups
---
.gitignore | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/.gitignore b/.gitignore
index f5dbc143c..2088e658a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,4 +18,5 @@ doc/oneline.txt
doc/plinth.1
templates/*.py
TODO
-\#*
\ No newline at end of file
+\#*
+.#*
From 157d522bf69cfdacadb382d8a4227b691478743a Mon Sep 17 00:00:00 2001
From: James Vasile
Date: Tue, 20 Dec 2011 21:26:51 -0500
Subject: [PATCH 23/31] plinth is in local
---
share/init.d/plinth | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/share/init.d/plinth b/share/init.d/plinth
index f5df9b712..46bc36933 100755
--- a/share/init.d/plinth
+++ b/share/init.d/plinth
@@ -1,6 +1,6 @@
#!/bin/bash
# This file is /etc/init.d/plinth
-DAEMON=/usr/bin/plinth.py
+DAEMON=/usr/local/bin/plinth.py
PID_FILE=/var/run/plinth.pid
start_plinth (){
From 7007a013ad6fd7bd1e76b30f96fc6d98e1bc7d0b Mon Sep 17 00:00:00 2001
From: James Vasile
Date: Tue, 20 Dec 2011 21:28:00 -0500
Subject: [PATCH 24/31] add base_href to templates
---
templates/base.tmpl | 18 +++++++++---------
templates/two_col.tmpl | 2 +-
2 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/templates/base.tmpl b/templates/base.tmpl
index f191589c9..10f0d4adf 100644
--- a/templates/base.tmpl
+++ b/templates/base.tmpl
@@ -13,11 +13,11 @@
-
-
+
+
$css
-
-
+
+
$js
$main_menu_js
$sub_menu_js
@@ -30,12 +30,12 @@
diff --git a/templates/two_col.tmpl b/templates/two_col.tmpl
index 0b559ade8..3acef6965 100644
--- a/templates/two_col.tmpl
+++ b/templates/two_col.tmpl
@@ -1,5 +1,5 @@
#extends templates.base
#def css
-
+
#end def
From 1bdf38f4704035d8cc14f0ea7aa0f73da9bbccb8 Mon Sep 17 00:00:00 2001
From: James Vasile
Date: Tue, 20 Dec 2011 21:28:26 -0500
Subject: [PATCH 25/31] base href defaults to blank
---
util.py | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/util.py b/util.py
index e43af8371..98fb18a3d 100644
--- a/util.py
+++ b/util.py
@@ -58,10 +58,12 @@ class Message():
self.text += " %s" % text
def page_template(template='base', **kwargs):
- for k in ['sidebar_left', 'sidebar_right', 'main', 'js', 'onload', 'nav', 'css', 'title']:
+ for k in ['sidebar_left', 'sidebar_right', 'main', 'js', 'onload', 'nav', 'css', 'title', 'basehref']:
if not k in kwargs:
kwargs[k] = ''
+ if kwargs['basehref'] == '':
+ kwargs['basehref'] = cfg.base_href
if template=='base' and kwargs['sidebar_right']=='':
template='two_col'
if isinstance(template, basestring):
From 130ca2e436075d550aa58d24e703e548d4b83438 Mon Sep 17 00:00:00 2001
From: James Vasile
Date: Tue, 20 Dec 2011 21:29:58 -0500
Subject: [PATCH 26/31] set documentroot to /dev/null
---
share/apache2/plinth.conf | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/share/apache2/plinth.conf b/share/apache2/plinth.conf
index 6f0612f6a..aab477fa1 100644
--- a/share/apache2/plinth.conf
+++ b/share/apache2/plinth.conf
@@ -1,5 +1,6 @@
+ # The DocumentRoot is set by fabric
DocumentRoot /dev/null
ServerName plinth
@@ -11,7 +12,8 @@
- DocumentRoot /home/james/src/plinth/static
+ # The DocumentRoot is set by fabric
+ DocumentRoot /dev/null
ServerName plinth
SSLEngine on
From d7d768308d849df7066f48700fcbc22df7163956 Mon Sep 17 00:00:00 2001
From: James Vasile
Date: Tue, 20 Dec 2011 21:30:21 -0500
Subject: [PATCH 27/31] menu can add base href automatically
---
menu.py | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/menu.py b/menu.py
index e0e376a5c..3e682e4b5 100644
--- a/menu.py
+++ b/menu.py
@@ -27,9 +27,15 @@ class Menu():
def sort_items(self):
"""Sort the items in self.items by order."""
self.items = sorted(self.items, key=lambda x: x.order, reverse=False)
- def add_item(self, label, url, order=50):
+ def add_item(self, label, url, order=50, basehref=True):
"""This method creates a menu item with the parameters, adds
- that menu item to this menu, and returns the item."""
+ that menu item to this menu, and returns the item.
+
+ If BASEHREF is true and url start with a slash, prepend the cfg.base_href to it"""
+
+ if basehref and url.startswith("/"):
+ url = cfg.base_href + url
+
item = Menu(label=label, url=url, order=order)
self.items.append(item)
self.sort_items()
From fbcb4f7753bd4d40c574561e71f3f70fb859c60b Mon Sep 17 00:00:00 2001
From: James Vasile
Date: Tue, 20 Dec 2011 22:42:21 -0500
Subject: [PATCH 28/31] starting santiago
---
modules/installed/santiago/santiago.py | 123 +++++++++++++++++++++++++
1 file changed, 123 insertions(+)
create mode 100644 modules/installed/santiago/santiago.py
diff --git a/modules/installed/santiago/santiago.py b/modules/installed/santiago/santiago.py
new file mode 100644
index 000000000..169e9d7e2
--- /dev/null
+++ b/modules/installed/santiago/santiago.py
@@ -0,0 +1,123 @@
+"""
+santiago is the interface that listens over a tor hidden service. It
+accepts json requests and responds with json data structures filled
+with information. There is authentication involved, although I
+haven't figured that one all the way through yet.
+"""
+
+import os
+import cherrypy
+import simplejson as json
+from gettext import gettext as _
+from plugin_mount import PagePlugin
+from modules.auth import require
+import cfg
+import util as u
+
+santiago_port = 52854
+
+import gnupg
+
+def check_sig(query, sig):
+ "Verify that the sig and the query match"
+ gpg = gnupg.GPG(gnupghome='/home/james/')
+ return True
+
+class Santiago(PagePlugin):
+ order = 90 # order of running init in PagePlugins
+ def __init__(self, *args, **kwargs):
+
+ self.register_page("santiago")
+ self.santiago_address = self.get_santiago_address() #TODO: multiple santiago ports
+ #set a listener on the santiago address
+
+ def get_santiago_address(self):
+ if 'santiago' in cfg.users['admin'] and 'address' in cfg.users['admin']['santiago']:
+ return cfg.users['admin']['santiago']['address']
+ else:
+ admin = cfg.users['admin']
+ admin['santiago'] = {}
+
+ with open ("/etc/tor/torrc", 'r') as INF:
+ rc = INF.read()
+
+ self.santiago_dir = os.path.join(cfg.file_root, "data", "santiago", "tor")
+ self.tor_dir = os.path.join(self.santiago_dir, "general")
+ u.mkdir(self.santiago_dir)
+ os.system( 'chmod a+w %s' % self.santiago_dir)
+ hidden_service_config = "HiddenServiceDir %s\nHiddenServicePort 80 127.0.0.1:%d" % (self.tor_dir, santiago_port)
+ if hidden_service_config in rc:
+ ## get info from dir (but how? we need perms)
+ ## just fake it for now
+ admin['santiago']['address'] = "b5wycujkfh2jxfdo.onion"
+ cfg.users['admin'] = admin
+ return cfg.users['admin']['santiago']['address']
+ print "Need to add these two lines to /etc/torrc:\n%s" % hidden_service_config
+ return ""
+
+ def check_for_hidden_service(self):
+ pass
+
+ @cherrypy.expose
+ def index(self, *args, **kw):
+
+ """
+ A request is a dict with some required keys:
+ req - this is the request. It is a dict that has keys of use to serving the request.
+ version - the version number of this description (currently 1)
+ entropy - a random string of at least 256 bytes.
+ signature - an optional signature
+ """
+ if (cherrypy.request.local.port != santiago_port
+ #or not check_sig(kw['q'], kw['sig'])
+
+ #or cherrypy.request.method.upper() != "POST"
+ ):
+ raise cherrypy.HTTPError(404)
+
+ return kw['q']
+ from pprint import pformat
+
+ #return str(cherrypy.request.params)
+
+ return '''
+CP Info
+
%s
+''' % pformat({
+ 'args': args,
+ 'kw': kw,
+ 'request': dict([(k, getattr(cherrypy.request, k))
+ for k in dir(cherrypy.request)
+ if not k.startswith('_')]),
+ })
+
+
+
+
+ #try:
+ # query = json.loads(q)
+ #except:
+ # raise cherrypy.HTTPError(404)
+
+ ## client requests proxy methods
+ ## we send back a list of proxy methods (complete with routes/IP addresses to connect to)
+
+
+ return str(cherrypy.request.local.port)
+ a = " ".join(dir(cherrypy.request))
+ a += cherrypy.request.query_string + "!!!!!!!!!!!!"
+ a += str(cherrypy.request.local.port)
+ return a
+ return "test " + cherrypy.request.method.upper() + " "+t
+
+## Plinth page to config santiago
+class santiago(PagePlugin):
+ def __init__(self, *args, **kwargs):
+ PagePlugin.__init__(self, *args, **kwargs)
+ self.menu = cfg.html_root.privacy.menu.add_item("Santiago", "/privacy/santiago", 10)
+ self.register_page("privacy.santiago")
+
+ @cherrypy.expose
+ @require()
+ def index(self):
+ return "Santiago's config goes here."
From caeb6bc7aa752b8f0f53ad769323644c07cebc68 Mon Sep 17 00:00:00 2001
From: James Vasile
Date: Wed, 21 Dec 2011 11:59:27 -0500
Subject: [PATCH 29/31] enable santiago
---
modules/santiago.py | 1 +
1 file changed, 1 insertion(+)
create mode 120000 modules/santiago.py
diff --git a/modules/santiago.py b/modules/santiago.py
new file mode 120000
index 000000000..ae4ef986e
--- /dev/null
+++ b/modules/santiago.py
@@ -0,0 +1 @@
+installed/santiago/santiago.py
\ No newline at end of file
From 1dc3d28a999e131c9bf6ed1382c2acad48574946 Mon Sep 17 00:00:00 2001
From: James Vasile
Date: Thu, 22 Dec 2011 17:07:27 -0500
Subject: [PATCH 30/31] tag init.d script
---
share/init.d/plinth | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/share/init.d/plinth b/share/init.d/plinth
index 46bc36933..e364fc123 100755
--- a/share/init.d/plinth
+++ b/share/init.d/plinth
@@ -1,4 +1,15 @@
#!/bin/bash
+### BEGIN INIT INFO
+# Provides: plinth
+# Required-Start: $syslog
+# Required-Stop: $syslog
+# Default-Start: 2 3 4 5
+# Default-Stop: 0 1 6
+# Short-Description: plinth web frontend
+# Description:
+#
+### END INIT INFO
+
# This file is /etc/init.d/plinth
DAEMON=/usr/local/bin/plinth.py
PID_FILE=/var/run/plinth.pid
From e648c05039dd4c5a0e636c0b91ff17eaad70712b Mon Sep 17 00:00:00 2001
From: James Vasile
Date: Sun, 19 Feb 2012 14:41:40 -0500
Subject: [PATCH 31/31] flesh out santiago and apache config a bit
---
modules/installed/santiago/santiago.py | 40 +++++++++++++-------------
share/apache2/plinth.conf | 2 ++
2 files changed, 22 insertions(+), 20 deletions(-)
diff --git a/modules/installed/santiago/santiago.py b/modules/installed/santiago/santiago.py
index 169e9d7e2..38e651206 100644
--- a/modules/installed/santiago/santiago.py
+++ b/modules/installed/santiago/santiago.py
@@ -5,7 +5,7 @@ with information. There is authentication involved, although I
haven't figured that one all the way through yet.
"""
-import os
+import os, sys
import cherrypy
import simplejson as json
from gettext import gettext as _
@@ -16,22 +16,22 @@ import util as u
santiago_port = 52854
-import gnupg
+#import gnupg
-def check_sig(query, sig):
- "Verify that the sig and the query match"
- gpg = gnupg.GPG(gnupghome='/home/james/')
- return True
+#def check_sig(query, sig):
+# "Verify that the sig and the query match"
+# gpg = gnupg.GPG(gnupghome='/home/james/')
+# return True
class Santiago(PagePlugin):
- order = 90 # order of running init in PagePlugins
- def __init__(self, *args, **kwargs):
+ order = 90 # order of running init in PagePlugins
+ def __init__(self, *args, **kwargs):
self.register_page("santiago")
self.santiago_address = self.get_santiago_address() #TODO: multiple santiago ports
#set a listener on the santiago address
- def get_santiago_address(self):
+ def get_santiago_address(self):
if 'santiago' in cfg.users['admin'] and 'address' in cfg.users['admin']['santiago']:
return cfg.users['admin']['santiago']['address']
else:
@@ -55,11 +55,11 @@ class Santiago(PagePlugin):
print "Need to add these two lines to /etc/torrc:\n%s" % hidden_service_config
return ""
- def check_for_hidden_service(self):
+ def check_for_hidden_service(self):
pass
- @cherrypy.expose
- def index(self, *args, **kw):
+ @cherrypy.expose
+ def index(self, *args, **kw):
"""
A request is a dict with some required keys:
@@ -112,12 +112,12 @@ class Santiago(PagePlugin):
## Plinth page to config santiago
class santiago(PagePlugin):
- def __init__(self, *args, **kwargs):
- PagePlugin.__init__(self, *args, **kwargs)
- self.menu = cfg.html_root.privacy.menu.add_item("Santiago", "/privacy/santiago", 10)
- self.register_page("privacy.santiago")
+ def __init__(self, *args, **kwargs):
+ PagePlugin.__init__(self, *args, **kwargs)
+ self.menu = cfg.html_root.privacy.menu.add_item("Santiago", "/privacy/santiago", 10)
+ self.register_page("privacy.santiago")
- @cherrypy.expose
- @require()
- def index(self):
- return "Santiago's config goes here."
+ @cherrypy.expose
+ @require()
+ def index(self):
+ return "Santiago's config goes here."
diff --git a/share/apache2/plinth.conf b/share/apache2/plinth.conf
index aab477fa1..8c45eb1d9 100644
--- a/share/apache2/plinth.conf
+++ b/share/apache2/plinth.conf
@@ -3,6 +3,7 @@
# The DocumentRoot is set by fabric
DocumentRoot /dev/null
ServerName plinth
+ ServerAlias plinth.*
## Force ssl
RewriteEngine on
@@ -15,6 +16,7 @@
# The DocumentRoot is set by fabric
DocumentRoot /dev/null
ServerName plinth
+ ServerAlias plinth.*
SSLEngine on
SSLCertificateFile /etc/apache2/ssl/apache.pem