diff --git a/extensions/fablabchemnitz_airplanetypelinearcase.py b/extensions/fablabchemnitz_airplanetypelinearcase.py
index c8d1c9db..b1f8e224 100644
--- a/extensions/fablabchemnitz_airplanetypelinearcase.py
+++ b/extensions/fablabchemnitz_airplanetypelinearcase.py
@@ -1,5 +1,4 @@
-#! /usr/bin/env python
-# coding=utf-8
+#! /usr/bin/env python3
#
#
# Este script dibuja el perfil exterior de corte la caja en un solo
diff --git a/extensions/fablabchemnitz_apollonian.py b/extensions/fablabchemnitz_apollonian.py
index a6fc63f2..e7bc1200 100644
--- a/extensions/fablabchemnitz_apollonian.py
+++ b/extensions/fablabchemnitz_apollonian.py
@@ -1,4 +1,5 @@
#!/usr/bin/env python3
+
import inkex
import fablabchemnitz_apolloniangasket_func
from lxml import etree
diff --git a/extensions/fablabchemnitz_attributes_cleaner.inx b/extensions/fablabchemnitz_attributes_cleaner.inx
new file mode 100644
index 00000000..a6ec1ace
--- /dev/null
+++ b/extensions/fablabchemnitz_attributes_cleaner.inx
@@ -0,0 +1,18 @@
+
+
+ Remove Obsolete Attributes
+ fablabchemnitz.deattributes_cleaner
+ Remove attributes "sodipodi:absref", "sodipodi:docbase" and "sodipodi:docname" from all elements that contain them. These attributes contain absolute paths to resources which can pose a security issue.
+ true
+ true
+ true
+
+ all
+
+
+
+
+
+
\ No newline at end of file
diff --git a/extensions/fablabchemnitz_attributes_cleaner.py b/extensions/fablabchemnitz_attributes_cleaner.py
new file mode 100644
index 00000000..b3f0de52
--- /dev/null
+++ b/extensions/fablabchemnitz_attributes_cleaner.py
@@ -0,0 +1,44 @@
+#!/usr/bin/env python3
+
+"""
+Removes attributes sodipodi:absref, sodipodi:docbase and sodipodi:docname from all elements that contain them.
+
+full names of attributes
+sodipodi:absref
+{http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd}absref
+sodipodi:docbase
+{http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd}docbase
+sodipodi:docname
+{http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd}docname
+
+element.attrib.pop("{http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd}absref", None)
+"""
+
+import inkex
+import sys
+
+class AbsrefRemover(inkex.Effect):
+ def __init__(self):
+ inkex.Effect.__init__(self)
+ self.arg_parser.add_argument("-a", "--removeAbsref", type=inkex.Boolean, default=True, help="Remove sodipodi:absref")
+ self.arg_parser.add_argument("-b", "--removeDocbase", type=inkex.Boolean, default=True, help="Remove sodipodi:docbase")
+ self.arg_parser.add_argument("-n", "--removeDocname", type=inkex.Boolean, default=True, help="Remove sodipodi:docname")
+
+ def effect(self):
+ if self.options.removeAbsref:
+ elements = self.document.xpath("//*[@sodipodi:absref]", namespaces=inkex.NSS)
+ for element in elements:
+ element.attrib.pop("{http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd}absref", None)
+
+ if self.options.removeDocbase:
+ elements = self.document.xpath("//*[@sodipodi:docbase]", namespaces=inkex.NSS)
+ for element in elements:
+ element.attrib.pop("{http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd}docbase", None)
+
+ if self.options.removeDocname:
+ elements = self.document.xpath("//*[@sodipodi:docname]", namespaces=inkex.NSS)
+ for element in elements:
+ element.attrib.pop("{http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd}docname", None)
+
+if __name__ == "__main__":
+ AbsrefRemover().run()
\ No newline at end of file
diff --git a/extensions/fablabchemnitz_attributes_editor.inx b/extensions/fablabchemnitz_attributes_editor.inx
new file mode 100644
index 00000000..0fce802c
--- /dev/null
+++ b/extensions/fablabchemnitz_attributes_editor.inx
@@ -0,0 +1,25 @@
+
+
+ Edit Attributes
+ fablabchemnitz.de.attributes_editor
+ Edit value of attribute on selected elements.
+ For namespaces use {namespaceUrl}attributeName
+
+
+
+
+
+
+
+
+
+
+ all
+
+
+
+
+
+
\ No newline at end of file
diff --git a/extensions/fablabchemnitz_attributes_editor.py b/extensions/fablabchemnitz_attributes_editor.py
new file mode 100644
index 00000000..c868bec3
--- /dev/null
+++ b/extensions/fablabchemnitz_attributes_editor.py
@@ -0,0 +1,38 @@
+#!/usr/bin/env python3
+
+import inkex
+import sys
+
+class AttribEditor(inkex.Effect):
+ def __init__(self):
+ inkex.Effect.__init__(self)
+ self.arg_parser.add_argument("-a", "--attributeName", help="attribute name to set")
+ self.arg_parser.add_argument("-v", "--attributeValue", help="attribute value to set")
+ self.arg_parser.add_argument("-m", "--mode", default="set", help="mode of operation")
+
+ def effect(self):
+ if not self.options.attributeName: # if attributeName is not given
+ self.OptionParser.error("Attribute name not given")
+
+ elements = self.svg.selected.values()
+ for el in elements:
+ currentAtt = el.attrib.get(self.options.attributeName)
+ if currentAtt is None:
+ currentAtt = ""
+
+ if self.options.mode == "set":
+ el.attrib[self.options.attributeName] = self.options.attributeValue
+ elif self.options.mode == "append":
+ el.attrib[self.options.attributeName] = currentAtt + self.options.attributeValue
+ elif self.options.mode == "prefix":
+ el.attrib[self.options.attributeName] = self.options.attributeValue + currentAtt
+ elif self.options.mode == "subtract":
+ el.attrib[self.options.attributeName] = currentAtt.replace(self.options.attributeValue, "")
+ elif self.options.mode == "remove":
+ if self.options.attributeName in el.attrib:
+ del el.attrib[self.options.attributeName]
+ else:
+ inkex.errormsg(_("Invalid mode: " + self.options.mode))
+
+if __name__ == "__main__":
+ AttribEditor().run()
\ No newline at end of file
diff --git a/extensions/fablabchemnitz_attributes_import.inx b/extensions/fablabchemnitz_attributes_import.inx
new file mode 100644
index 00000000..13e59d81
--- /dev/null
+++ b/extensions/fablabchemnitz_attributes_import.inx
@@ -0,0 +1,18 @@
+
+
+ Import Attributes
+ fablabchemnitz.de.attributes_import
+ Uses lines in text file to edit attributes of elements.
+ <_param name="usage" type="description">Line: 'elementID,attributeName,attributeValue'.
+ For namespaces use {namespaceUrl}attributeName
+
+
+ all
+
+
+
+
+
+
\ No newline at end of file
diff --git a/extensions/fablabchemnitz_attributes_import.py b/extensions/fablabchemnitz_attributes_import.py
new file mode 100644
index 00000000..9a0d9f04
--- /dev/null
+++ b/extensions/fablabchemnitz_attributes_import.py
@@ -0,0 +1,30 @@
+#!/usr/bin/env python3
+
+import inkex
+
+class AttribImport(inkex.Effect):
+ def __init__(self):
+ inkex.Effect.__init__(self)
+ self.arg_parser.add_argument("--data", default="", help="data file")
+
+ def effect(self):
+ with open(self.options.data, 'r') as f:
+ lines = f.read().splitlines()
+ for line in lines:
+ #split on , max 2+1 = 3 items
+ parts = line.split(",", 2)
+ if len(parts) >= 3:
+ id = parts[0]
+ attribute = parts[1]
+ value = parts[2]
+ try:
+ node = self.svg.getElementById(id)
+ if node is not None:
+ try:
+ node.set(attribute, value)
+ except AttributeError:
+ inkex.utils.debug("Unknown Attribute")
+ except AttributeError:
+ inkex.utils.debug("element with id '" + id + "' not found in current selection.")
+if __name__ == '__main__':
+ AttribImport().run()
\ No newline at end of file