summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rwxr-xr-xdev-django-admin.sh1
-rw-r--r--meetingtools.wsgi8
-rw-r--r--meetingtools/__init__.py0
-rw-r--r--meetingtools/ac/__init__.py0
-rw-r--r--meetingtools/ac/api.py66
-rw-r--r--meetingtools/apps/__init__.py0
-rw-r--r--meetingtools/apps/room/__init__.py0
-rw-r--r--meetingtools/apps/room/admin.py10
-rw-r--r--meetingtools/apps/room/models.py14
-rw-r--r--meetingtools/apps/room/views.py0
-rw-r--r--meetingtools/extensions/__init__.py0
-rw-r--r--meetingtools/manage.py11
-rw-r--r--meetingtools/settings.py96
-rw-r--r--meetingtools/site_logging.py10
-rw-r--r--meetingtools/urls.py16
-rw-r--r--site-media/img/RSS_mini.pngbin0 -> 634 bytes
-rw-r--r--site-media/img/act_bg.pngbin0 -> 2915 bytes
-rw-r--r--site-media/img/date_bg.jpgbin0 -> 12339 bytes
-rw-r--r--site-media/img/glob.jpgbin0 -> 25039 bytes
-rw-r--r--site-media/img/globe.jpgbin0 -> 9637 bytes
-rw-r--r--site-media/img/header.jpgbin0 -> 63437 bytes
-rw-r--r--site-media/img/logo.jpgbin0 -> 19292 bytes
-rw-r--r--site-media/img/sv_search.jpgbin0 -> 14148 bytes
-rw-r--r--site-media/site-media/css/reset.css49
-rw-r--r--site-media/site-media/css/sunet.css275
-rw-r--r--site-media/site-media/img/RSS_mini.pngbin0 -> 634 bytes
-rw-r--r--site-media/site-media/img/act_bg.pngbin0 -> 2915 bytes
-rw-r--r--site-media/site-media/img/date_bg.jpgbin0 -> 12339 bytes
-rw-r--r--site-media/site-media/img/glob.jpgbin0 -> 25039 bytes
-rw-r--r--site-media/site-media/img/globe.jpgbin0 -> 9637 bytes
-rw-r--r--site-media/site-media/img/header.jpgbin0 -> 63437 bytes
-rw-r--r--site-media/site-media/img/logo.jpgbin0 -> 19292 bytes
-rw-r--r--site-media/site-media/img/sv_search.jpgbin0 -> 14148 bytes
-rw-r--r--templates/base.html84
35 files changed, 643 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..07025ed
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+*.pyc
+*.db
+*.log
diff --git a/dev-django-admin.sh b/dev-django-admin.sh
new file mode 100755
index 0000000..4514ca6
--- /dev/null
+++ b/dev-django-admin.sh
@@ -0,0 +1 @@
+env PYTHONPATH=`pwd`:$PHTHONPATH DJANGO_SETTINGS_MODULE=meetingtools.settings django-admin.py $*
diff --git a/meetingtools.wsgi b/meetingtools.wsgi
new file mode 100644
index 0000000..5fa6ac1
--- /dev/null
+++ b/meetingtools.wsgi
@@ -0,0 +1,8 @@
+import os
+import sys
+
+os.environ['DJANGO_SETTINGS_MODULE'] = 'meetingtools.settings'
+
+sys.path.append('/var/www/meetingtools')
+import django.core.handlers.wsgi
+application = django.core.handlers.wsgi.WSGIHandler()
diff --git a/meetingtools/__init__.py b/meetingtools/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/meetingtools/__init__.py
diff --git a/meetingtools/ac/__init__.py b/meetingtools/ac/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/meetingtools/ac/__init__.py
diff --git a/meetingtools/ac/api.py b/meetingtools/ac/api.py
new file mode 100644
index 0000000..2631987
--- /dev/null
+++ b/meetingtools/ac/api.py
@@ -0,0 +1,66 @@
+'''
+Created on Jan 31, 2011
+
+@author: leifj
+'''
+
+from lxml import etree
+import httplib2
+from urllib import urlencode
+
+class ACPException(Exception):
+ def __init__(self, value):
+ self.value = value
+
+ def __str__(self):
+ return repr(self.value)
+
+class ACPResult():
+
+ def __init__(self,content):
+ self.et = etree.parse(content)
+ self.status = self.et.find('status')
+
+ def is_error(self):
+ return self.status.get('code') != 'ok'
+
+ def exception(self):
+ raise ACPException,self.status
+
+ def get_principal(self):
+ return self.et.find('principal')
+
+class ACPClient():
+
+ def __init__(self,url,username=None,password=None):
+ self.url = url
+ self.session = None
+ if username and password:
+ self.login(username,password)
+
+ def request(self,method,p={}):
+ url = self.url+"?"+"action=%s" % method
+ if self.session:
+ url = url + "&session=%s" % self.session
+ urlencode(dict([k,v.encode("iso-8859-1")] for (k,v) in p.items()))
+
+ h = httplib2.Http(".cache");
+ resp, content = h.request(url, "GET")
+ if resp.status != 200:
+ raise ACPException,resp.reason
+
+ if resp.has_key('set-cookie'):
+ cookie = resp['set-cookie']
+ if cookie:
+ avp = cookie.split(";")
+ if avp.len > 0:
+ av = avp[0].split('=')
+ self.session = av[1]
+
+ return ACPResult(content)
+
+ def login(self,username,password):
+ result = self.request('login',{'login':username,'password':password})
+ if result.is_error():
+ raise result.exception()
+ \ No newline at end of file
diff --git a/meetingtools/apps/__init__.py b/meetingtools/apps/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/meetingtools/apps/__init__.py
diff --git a/meetingtools/apps/room/__init__.py b/meetingtools/apps/room/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/meetingtools/apps/room/__init__.py
diff --git a/meetingtools/apps/room/admin.py b/meetingtools/apps/room/admin.py
new file mode 100644
index 0000000..13d80a8
--- /dev/null
+++ b/meetingtools/apps/room/admin.py
@@ -0,0 +1,10 @@
+'''
+Created on Jan 31, 2011
+
+@author: leifj
+'''
+
+from django.contrib import admin
+from meetingtools.apps.room.models import Room
+
+admin.site.register(Room) \ No newline at end of file
diff --git a/meetingtools/apps/room/models.py b/meetingtools/apps/room/models.py
new file mode 100644
index 0000000..f75478e
--- /dev/null
+++ b/meetingtools/apps/room/models.py
@@ -0,0 +1,14 @@
+'''
+Created on Jan 31, 2011
+
+@author: leifj
+'''
+
+from django.db import models
+from django.db.models.fields import CharField, BooleanField, URLField
+
+class Room(models.Model):
+ name = CharField(max_length=128)
+ group = CharField(max_length=128) # populate from entitlement held by creator
+ resetWhenEmpty = BooleanField()
+ meetingRoomUrl = URLField() \ No newline at end of file
diff --git a/meetingtools/apps/room/views.py b/meetingtools/apps/room/views.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/meetingtools/apps/room/views.py
diff --git a/meetingtools/extensions/__init__.py b/meetingtools/extensions/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/meetingtools/extensions/__init__.py
diff --git a/meetingtools/manage.py b/meetingtools/manage.py
new file mode 100644
index 0000000..5e78ea9
--- /dev/null
+++ b/meetingtools/manage.py
@@ -0,0 +1,11 @@
+#!/usr/bin/env python
+from django.core.management import execute_manager
+try:
+ import settings # Assumed to be in the same directory.
+except ImportError:
+ import sys
+ sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)
+ sys.exit(1)
+
+if __name__ == "__main__":
+ execute_manager(settings)
diff --git a/meetingtools/settings.py b/meetingtools/settings.py
new file mode 100644
index 0000000..3c43a57
--- /dev/null
+++ b/meetingtools/settings.py
@@ -0,0 +1,96 @@
+# Django settings for meetingtools project.
+
+import meetingtools.site_logging
+
+DEBUG = True
+TEMPLATE_DEBUG = DEBUG
+
+ADMINS = (
+ # ('Your Name', 'your_email@domain.com'),
+)
+
+BASE_DIR = '..'
+
+MANAGERS = ADMINS
+
+DATABASES = {
+ 'default': {
+ 'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
+ 'NAME': '%s/sqlite.db' % BASE_DIR, # Or path to database file if using sqlite3.
+ 'USER': '', # Not used with sqlite3.
+ 'PASSWORD': '', # Not used with sqlite3.
+ 'HOST': '', # Set to empty string for localhost. Not used with sqlite3.
+ 'PORT': '', # Set to empty string for default. Not used with sqlite3.
+ }
+}
+
+
+# Local time zone for this installation. Choices can be found here:
+# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
+# although not all choices may be available on all operating systems.
+# On Unix systems, a value of None will cause Django to use the same
+# timezone as the operating system.
+# If running in a Windows environment this must be set to the same as your
+# system time zone.
+TIME_ZONE = 'Europe/Stockholm'
+
+# Language code for this installation. All choices can be found here:
+# http://www.i18nguy.com/unicode/language-identifiers.html
+LANGUAGE_CODE = 'en-us'
+
+SITE_ID = 1
+
+# If you set this to False, Django will make some optimizations so as not
+# to load the internationalization machinery.
+USE_I18N = True
+
+# If you set this to False, Django will not format dates, numbers and
+# calendars according to the current locale
+USE_L10N = True
+
+MEDIA_ROOT = "%s/site-media" % BASE_DIR
+ADMIN_MEDIA_ROOT = "/usr/lib/pymodules/python2.5/django/contrib/admin/media"
+MEDIA_URL = '/site-media/'
+ADMIN_MEDIA_PREFIX = '/admin-media/'
+
+# Make this unique, and don't share it with anybody.
+SECRET_KEY = 'tz78l!c=cl2=jic5$2#(bq)7-4s1ivtm*a+q0w1yi0$)hrmc7l'
+
+# List of callables that know how to import templates from various sources.
+TEMPLATE_LOADERS = (
+ 'django.template.loaders.filesystem.Loader',
+ 'django.template.loaders.app_directories.Loader',
+# 'django.template.loaders.eggs.Loader',
+)
+
+MIDDLEWARE_CLASSES = (
+ 'django.middleware.common.CommonMiddleware',
+ 'django.contrib.sessions.middleware.SessionMiddleware',
+ 'django.contrib.auth.middleware.AuthenticationMiddleware',
+ 'coip.middleware.UserMappingMiddleware',
+ 'django.contrib.auth.middleware.RemoteUserMiddleware'
+)
+
+AUTHENTICATION_BACKENDS = (
+ 'django.contrib.auth.backends.RemoteUserBackend',
+ 'django.contrib.auth.backends.ModelBackend',
+)
+
+ROOT_URLCONF = 'meetingtools.urls'
+
+TEMPLATE_DIRS = (
+ # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
+ # Always use forward slashes, even on Windows.
+ # Don't forget to use absolute paths, not relative paths.
+ "%s/templates" % BASE_DIR
+)
+
+INSTALLED_APPS = (
+ 'django.contrib.auth',
+ 'django.contrib.contenttypes',
+ 'django.contrib.sessions',
+ 'django.contrib.sites',
+ 'django.contrib.admin',
+ 'django.contrib.humanize',
+ 'django_extensions'
+)
diff --git a/meetingtools/site_logging.py b/meetingtools/site_logging.py
new file mode 100644
index 0000000..cdbe3c2
--- /dev/null
+++ b/meetingtools/site_logging.py
@@ -0,0 +1,10 @@
+import logging
+import sys
+
+logger = logging.getLogger('')
+logger.setLevel(logging.DEBUG)
+handler = logging.StreamHandler(sys.stderr)
+handler.setLevel(logging.DEBUG)
+formatter = logging.Formatter('%(levelname)-8s %(message)s')
+handler.setFormatter(formatter)
+logger.addHandler(handler)
diff --git a/meetingtools/urls.py b/meetingtools/urls.py
new file mode 100644
index 0000000..69b4bf0
--- /dev/null
+++ b/meetingtools/urls.py
@@ -0,0 +1,16 @@
+from django.conf.urls.defaults import *
+
+# Uncomment the next two lines to enable the admin:
+# from django.contrib import admin
+# admin.autodiscover()
+
+urlpatterns = patterns('',
+ # Example:
+ # (r'^meetingtools/', include('meetingtools.foo.urls')),
+
+ # Uncomment the admin/doc line below to enable admin documentation:
+ # (r'^admin/doc/', include('django.contrib.admindocs.urls')),
+
+ # Uncomment the next line to enable the admin:
+ # (r'^admin/', include(admin.site.urls)),
+)
diff --git a/site-media/img/RSS_mini.png b/site-media/img/RSS_mini.png
new file mode 100644
index 0000000..24e8cd3
--- /dev/null
+++ b/site-media/img/RSS_mini.png
Binary files differ
diff --git a/site-media/img/act_bg.png b/site-media/img/act_bg.png
new file mode 100644
index 0000000..24b03bb
--- /dev/null
+++ b/site-media/img/act_bg.png
Binary files differ
diff --git a/site-media/img/date_bg.jpg b/site-media/img/date_bg.jpg
new file mode 100644
index 0000000..4533679
--- /dev/null
+++ b/site-media/img/date_bg.jpg
Binary files differ
diff --git a/site-media/img/glob.jpg b/site-media/img/glob.jpg
new file mode 100644
index 0000000..2756a5f
--- /dev/null
+++ b/site-media/img/glob.jpg
Binary files differ
diff --git a/site-media/img/globe.jpg b/site-media/img/globe.jpg
new file mode 100644
index 0000000..dae815f
--- /dev/null
+++ b/site-media/img/globe.jpg
Binary files differ
diff --git a/site-media/img/header.jpg b/site-media/img/header.jpg
new file mode 100644
index 0000000..a2af257
--- /dev/null
+++ b/site-media/img/header.jpg
Binary files differ
diff --git a/site-media/img/logo.jpg b/site-media/img/logo.jpg
new file mode 100644
index 0000000..b8a7c23
--- /dev/null
+++ b/site-media/img/logo.jpg
Binary files differ
diff --git a/site-media/img/sv_search.jpg b/site-media/img/sv_search.jpg
new file mode 100644
index 0000000..836d66f
--- /dev/null
+++ b/site-media/img/sv_search.jpg
Binary files differ
diff --git a/site-media/site-media/css/reset.css b/site-media/site-media/css/reset.css
new file mode 100644
index 0000000..69a1fa3
--- /dev/null
+++ b/site-media/site-media/css/reset.css
@@ -0,0 +1,49 @@
+/* Eric Meyer CSS Reset */
+
+html, body, div, span, applet, object, iframe,
+h1, h2, h3, h4, h5, h6, blockquote, pre,
+a, abbr, acronym, address, big, cite, code,
+del, dfn, em, font, img, ins, kbd, q, s, samp,
+small, strike, sub, sup, tt, var,
+dl, dt, dd, ol, ul, li,
+fieldset, form, label, legend,
+table, caption, tbody, tfoot, thead, tr, th, td {
+ margin: 0;
+ padding: 0;
+ border: 0;
+ outline: 0;
+ font-weight: inherit;
+ font-style: inherit;
+ font-size: 100%;
+ font-family: inherit;
+ vertical-align: top;
+}
+/* remember to define focus styles! */
+:focus {
+ outline: 0;
+}
+body {
+ line-height: 1;
+ color: black;
+ background: white;
+}
+ol, ul {
+ list-style: none;
+}
+/* tables still need 'cellspacing="0"' in the markup */
+table {
+ border-collapse: separate;
+ border-spacing: 0;
+}
+caption, th, td {
+ text-align: left;
+ font-weight: normal;
+}
+blockquote:before, blockquote:after,
+q:before, q:after {
+ content: "";
+}
+blockquote, q {
+ quotes: "" "";
+}
+
diff --git a/site-media/site-media/css/sunet.css b/site-media/site-media/css/sunet.css
new file mode 100644
index 0000000..fc01b2e
--- /dev/null
+++ b/site-media/site-media/css/sunet.css
@@ -0,0 +1,275 @@
+/*
+ * Structure
+ */
+* {
+ margin: 0;
+}
+html, body {
+ height: 100%;
+ background: url(/site-media/img/header.jpg) center top repeat-x;
+ width: 100%;
+}
+.wrapper {
+ min-height: 100%;
+ height: auto !important;
+ height: 100%;
+ margin: 0 auto -4em;
+ width: 100%;
+ margin: 0 auto;
+}
+.wCont {
+ width: 850px;
+ margin: 0 auto;
+}
+.header {
+ height: 191px;
+}
+ #logo {
+ display: block;
+ height: 145px;
+ width: 81px;
+ background: url(/site-media/img/logo.jpg) center no-repeat;
+ }
+.footer, .push {
+ height: 4em;
+}
+#menuContL {
+ width: 655px;
+ float: left;
+}
+#menuContR {
+ float: left;
+ padding-left: 15px;
+}
+.content {
+ padding-top: 12px;
+ clear: both;
+}
+.contL {
+ float: left;
+ width: 620px;
+ padding-right: 14px;
+ border-right: 1px solid #e5e5e5;
+}
+.contM {
+ float: left;
+ width: 420px;
+ padding-right: 14px;
+ border-right: 1px solid #e5e5e5;
+}
+.contMenu {
+ float: left;
+ width: 158px;
+ padding: 10px 14px 0 0;
+ margin-right: 20px;
+ border: 4px solid #c0c0c0;
+}
+.contR {
+ float: left;
+ width: 200px;
+ padding-left: 15px;
+
+}
+/*
+ * Pseudo
+ */
+.fl {
+ float: left;
+}
+.fr {
+ float: right;
+}
+.clr {
+ clear: both;
+}
+
+/*
+ * Menu
+ */
+.menu {
+ list-style: none;
+}
+.menu li {
+ display: inline-block;
+ list-style: none;
+ text-transform: uppercase;
+ height: 28px;
+ padding: 18px 8px 0 3px;
+}
+.selected {
+ background: url(../img/act_bg.png) repeat-x;
+}
+.menu li a {
+ color: #000;
+ font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;
+ font-size: 10px;
+}
+.breadcrumb li {
+ display: inline-block;
+ list-style: none;
+ text-transform: uppercase;
+ height: 12px;
+ padding: 0 3px 0 0;
+ font-size: 10px;
+}
+.breadcrumb li a, .breadcrumb li a:link, .breadcrumb li a:hover, .breadcrumb li a:visited {
+ color: #000;
+}
+.contMenu ul li {
+ border-bottom: 1px solid #D9D9D9;
+ padding: 3px 0 3px 11px;
+}
+.contMenu ul li a, .contMenu ul li a:link, .contMenu ul li a:hover, .contMenu ul li a:visited {
+ color: #000;
+ font-size: 10px;
+}
+/*
+ * Elements
+ */
+.search {
+ background: #fff;
+ margin: 11px 3px 0 0;
+ float: right;
+}
+.searchInput {
+ border: none;
+ font-size: 10px;
+ margin: 3px 0 0;
+}
+.footer {
+ background: #EFEFEF;
+ border-top: 2px solid #EBEBEB;
+ border-bottom: 2px solid #EBEBEB;
+}
+#footerText {
+ padding: 20px 0 0;
+ color: #999999;
+ font-size: 12px;
+}
+.blockCont {
+ border-top: 6px solid #c0c0c0;
+ padding-top: 15px;
+}
+.infoBlock {
+ float: left;
+ width: 30%;
+ margin-right: 15px;
+}
+.borderb2 {
+ border-bottom: 2px solid #e5e5e5;
+ border-top: 2px solid #e5e5e5;
+ height: 5px;
+}
+.borderb2_bold {
+ border-bottom: 3px solid #e5e5e5;
+ border-top: 3px solid #e5e5e5;
+ height: 2px;
+}
+
+/*
+ * Formatting
+ */
+body {
+ font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;
+ font-size: 14px;
+}
+a, a:hover, a:visited {
+ text-decoration: none;
+ color: #E37424;
+}
+h1, h1 a {
+ color: #E37424;
+ font-size: 36px;
+ padding-bottom: 15px;
+}
+h2, h2 a {
+ color: #E37424;
+ font-size: 14px;
+ padding-bottom: 15px;
+}
+.intro {
+ color: #000;
+ font-size: 14px;
+ line-height: 18px;
+ font-weight: bold;
+ padding-bottom: 15px;
+}
+.mb3 {
+ margin-bottom: 3px;
+}
+.pb15 {
+ padding-bottom: 15px;
+}
+.pt15 {
+ padding-top: 15px;
+}
+p {
+ color: #999999;
+ font-size: 12px;
+ padding-bottom: 15px;
+ line-height: 16px;
+}
+.blockCont .category {
+ text-transform: uppercase;
+ font-size: 10px;
+}
+.readmore {
+ font-size: 12px;
+}
+.addthis_button_compact {
+ font-size: 12px;
+ color: #000;
+}
+.contR .tag {
+ font-size: 10px;
+ color: #000;
+}
+.contR a img {
+ margin-top: 2px;
+}
+.contR .date {
+ background: url(../img/date_bg.jpg) no-repeat;
+ float: left;
+ width: 41px;
+ height: 66px;
+ padding: 7px 0;
+ color: #707070;
+}
+ .contR .date .day, .contR .date .month {
+ padding: 0 9px;
+ height: 18px;
+ font-size: 16px;
+ }
+ .contR .date .year {
+ font-size: 10px;
+ padding: 4px 0 0 5px;
+ }
+ .contR .entry {
+ float: left;
+ padding-left: 5px;
+ }
+ .contR .name {
+ padding: 15px 0 5px;
+ color: #999999;
+ font-size: 12px;
+ }
+ .contR .event {
+ padding-top: 5px;
+ }
+.ad {
+ background: #fff;
+ padding: 10px;
+ margin: 10px 0;
+ border: 1px solid #ccc;
+}
+.ad h2 {
+ font-size: 18px;
+ text-align: center;
+}
+.ad .imgCont {
+ width: 100%;
+ text-align: center;
+}
+#_atssh {
+ display: none;
+}
diff --git a/site-media/site-media/img/RSS_mini.png b/site-media/site-media/img/RSS_mini.png
new file mode 100644
index 0000000..24e8cd3
--- /dev/null
+++ b/site-media/site-media/img/RSS_mini.png
Binary files differ
diff --git a/site-media/site-media/img/act_bg.png b/site-media/site-media/img/act_bg.png
new file mode 100644
index 0000000..24b03bb
--- /dev/null
+++ b/site-media/site-media/img/act_bg.png
Binary files differ
diff --git a/site-media/site-media/img/date_bg.jpg b/site-media/site-media/img/date_bg.jpg
new file mode 100644
index 0000000..4533679
--- /dev/null
+++ b/site-media/site-media/img/date_bg.jpg
Binary files differ
diff --git a/site-media/site-media/img/glob.jpg b/site-media/site-media/img/glob.jpg
new file mode 100644
index 0000000..2756a5f
--- /dev/null
+++ b/site-media/site-media/img/glob.jpg
Binary files differ
diff --git a/site-media/site-media/img/globe.jpg b/site-media/site-media/img/globe.jpg
new file mode 100644
index 0000000..dae815f
--- /dev/null
+++ b/site-media/site-media/img/globe.jpg
Binary files differ
diff --git a/site-media/site-media/img/header.jpg b/site-media/site-media/img/header.jpg
new file mode 100644
index 0000000..a2af257
--- /dev/null
+++ b/site-media/site-media/img/header.jpg
Binary files differ
diff --git a/site-media/site-media/img/logo.jpg b/site-media/site-media/img/logo.jpg
new file mode 100644
index 0000000..b8a7c23
--- /dev/null
+++ b/site-media/site-media/img/logo.jpg
Binary files differ
diff --git a/site-media/site-media/img/sv_search.jpg b/site-media/site-media/img/sv_search.jpg
new file mode 100644
index 0000000..836d66f
--- /dev/null
+++ b/site-media/site-media/img/sv_search.jpg
Binary files differ
diff --git a/templates/base.html b/templates/base.html
new file mode 100644
index 0000000..66eb9a9
--- /dev/null
+++ b/templates/base.html
@@ -0,0 +1,84 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title>{{service_name}} Error</title>
+ <meta http-equiv="content-type"
+ content="text/html;charset=utf-8" />
+ <meta http-equiv="Content-Style-Type" content="text/css" />
+ <link href="/site-media/css/reset.css" rel="stylesheet" type="text/css" />
+ <link href="/site-media/css/sunet.css" rel="stylesheet" type="text/css" />
+
+<!--[if IE]>
+<link href="css/sunet-ie6.css" rel="stylesheet" type="text/css" />
+<![endif]-->
+<!--[if lt IE 8]>
+<style>
+.menu li {
+ display: inline;
+}
+</style>
+<![endif]-->
+<style media='all' type="text/css">
+
+div#gsfn_list_widget img { border: none; }
+div#gsfn_list_widget { font-size: 12px; width: 100%; border: 3px solid #DDD; padding: 10px; }
+div#gsfn_list_widget a.widget_title { color: #000; display: block; margin-bottom: 10px; font-weight: bold; }
+div#gsfn_list_widget .powered_by { margin-top: 8px; padding-top: 8px; border-top: 1px solid #DDD; }
+div#gsfn_list_widget .powered_by a { color: #333; font-size: 90%; }
+div#gsfn_list_widget div#gsfn_content { }
+div#gsfn_list_widget div#gsfn_content li { text-align:left; margin-bottom:6px; }
+div#gsfn_list_widget div#gsfn_content a.gsfn_link { line-height: 1; }
+div#gsfn_list_widget div#gsfn_content span.time { font-size: 90%; padding-left: 3px; }
+div#gsfn_list_widget div#gsfn_content p.gsfn_summary { margin-top: 2px }
+</style>
+
+<style media='all' type='text/css'>
+div#gsfn_search_widget img { border: none; }
+div#gsfn_search_widget { font-size: 12px; width: 100%; border: 3px solid #DDD; padding: 10px;}
+div#gsfn_search_widget a.widget_title { color: #000; display: block; margin-bottom: 10px; font-weight: bold; }
+div#gsfn_search_widget .powered_by { margin-top: 8px; padding-top: 8px; border-top: 1px solid #DDD; }
+div#gsfn_search_widget .powered_by a { color: #333; font-size: 90%; }
+div#gsfn_search_widget form { margin-bottom: 8px; }
+div#gsfn_search_widget form label { margin-bottom: 5px; display: block; }
+div#gsfn_search_widget form #gsfn_search_query { width: 60%; }
+div#gsfn_search_widget div.gsfn_content { }
+div#gsfn_search_widget div.gsfn_content li { text-align:left; margin-bottom:6px; }
+div#gsfn_search_widget div.gsfn_content a.gsfn_link { line-height: 1; }
+div#gsfn_search_widget div.gsfn_content span.time { font-size: 90%; padding-left: 3px; }
+div#gsfn_search_widget div.gsfn_content p.gsfn_summary { margin-top: 2px }
+</style>
+
+</head>
+
+<body>
+<div class="wrapper">
+ <div class="wCont">
+ <div class="header">
+ <a href="#" id="logo">&nbsp;</a>
+ <div id="menuContL">
+ </div>
+ <div id="menuContR">
+ </div>
+ </div>
+
+ <div class="content">
+ <div style="display:none;" class="contL"></div>
+ {% block main %}{% endblock %}
+ <div style="display:none;" class="blockCont"/>
+ <div style="display:none;" class="contR"></div>
+ <div class="clr"></div>
+ </div>
+ </div>
+ <div class="push"></div>
+</div>
+<div class="clr"></div>
+<div class="footer">
+ <div class="wCont">
+ <div id="footerText">
+ </div>
+ </div>
+</div>
+<!--</div>-->
+</body>
+</html>