diff --git a/src/mra.py b/src/mra.py
index 7be7789b6629a869e7a48d8db321edef50e4188c..d88208cceb5253aff98b8becd4f72807940a57d9 100644
--- a/src/mra.py
+++ b/src/mra.py
@@ -877,6 +877,46 @@ class MRA(object):
     def pub_resource_path(self, path):
         return os.path.relpath(path, self.get_resource_path())
 
+    # Fonts:
+
+    def get_fontset_path(self, *args):
+        root = self.config["storage"].get("fontset",
+                    "/".join([self.get_resource_path("fonts"), "fonts.txt"]))
+        return self.get_resource_path(root, *args)
+
+    def list_fontset(self):
+        try:
+            return [line.split()[0] for line in open(self.get_fontset_path(), "r")]
+        except:
+            return []
+
+    def update_fontset(self):
+        fontset = open(self.get_fontset_path(), "w")
+        for font, path in self.list_fonts():
+            fontset.write("%s\t%s\n" % (font, path))
+        fontset.close
+
+    def get_font_path(self, *args):
+        root = self.config["storage"].get("fonts", self.get_resource_path("fonts"))
+        return self.get_resource_path(root, *args)
+
+    def create_font(self, name, data=None):
+        fp = self.mk_path(self.get_font_path(name))
+        with open(fp, "w") as f:
+            if data:
+                f.write(data)
+        return fp
+
+    def pub_font_path(self, path):
+        return os.path.relpath(path, self.get_font_path())
+
+    def list_fonts(self):
+        print self.get_font_path()
+        for (root, _, files) in os.walk(self.get_font_path()):
+            for f in files:
+                if f.endswith(".ttf") and not f.startswith("."):
+                    yield f[:-4], os.path.join(os.path.relpath(root, self.get_font_path()), f)
+
     # Styles:
 
     def get_style_path(self, *args):
diff --git a/src/mra.yaml.sample b/src/mra.yaml.sample
index b00c78dd49613ee4e9203c9ff871a6d601232e9e..1cbfb0d1b63e1ffac5f4f929e196a010ce292a5f 100644
--- a/src/mra.yaml.sample
+++ b/src/mra.yaml.sample
@@ -12,6 +12,7 @@ storage:
 
     ## Folowing the same principle, the folowing two directories will
     ## default to resources/sub_directory_name
+    # fonts: ""
     # styles: ""
     # data: ""
 
diff --git a/src/server.py b/src/server.py
index 0bb34b415497dad5439206d23da115d22454c34f..29a3affce374b1d28c4aef831f72ff8ce0b95490 100755
--- a/src/server.py
+++ b/src/server.py
@@ -45,6 +45,7 @@ import tools
 from tools import href, assert_is_empty
 from pyxml import Entries
 from extensions import plugins
+import mapscript
 
 # Some helper functions first.
 def get_workspace(ws_name):
@@ -66,9 +67,38 @@ class index(object):
             "layergroups": href("layergroups/"),
             "services/wms/settings": href("services/wms/settings"),
             "services/wcs/settings": href("services/wcs/settings"),
-            "services/wfs/settings": href("services/wfs/settings")
+            "services/wfs/settings": href("services/wfs/settings"),
+            "fonts": href("fonts"),
             }
 
+class fonts(object):
+    """Configure available fonts.
+
+    http://hostname/mra/fonts
+
+    """
+    @HTTPCompatible()
+    def GET(self, format):
+        """Returns the list of available fonts."""
+
+        return {"fonts": [f_name
+            for f_name in mra.list_fontset()]}
+
+    @HTTPCompatible()
+    def PUT(self, format):
+        """Uploads fonts from a local source."""
+
+        import zipfile
+        ctype = web.ctx.env.get("CONTENT_TYPE", None)
+        if ctype == "application/zip":
+            path = mra.create_font("archive.zip", data=web.data())
+            with zipfile.ZipFile(path, "r") as z:
+                z.extractall(mra.get_font_path())
+            os.remove(path)
+
+        mra.update_fontset()
+
+
 class workspaces(object):
     """Workspaces container.
 
@@ -1174,6 +1204,8 @@ class OWSGlobalSettings(object):
 
 # Index:
 urlmap(index, "")
+# Fonts:
+urlmap(fonts, "fonts")
 # Workspaces:
 urlmap(workspaces, "workspaces")
 urlmap(workspace, "workspaces", ())