commit 9c1844ad4f6b859b812de245d421ee64b97a83d6 parent 2736670ab1368921ed4bd6338e1665c81f039cb2 Author: Christian Grothoff <christian@grothoff.org> Date: Tue, 12 Sep 2023 14:26:11 +0200 Merge branch 'master' of git+ssh://git.taler.net/docs Diffstat:
321 files changed, 19718 insertions(+), 15330 deletions(-)
diff --git a/.gitignore b/.gitignore @@ -2,4 +2,11 @@ _build *.pyc prebuilt .vscode -vtestenv/ -\ No newline at end of file +vtestenv/ + +# generated images +images/transaction-*.png +images/arch-api.png +images/coin.png +images/deposit.png +images/reserve.png diff --git a/AUTHORS b/AUTHORS @@ -3,3 +3,4 @@ Sree Harsha Totakura <sreeharsha@totakura.in> Florian Dold Christian Grothoff Benedikt Muller +Thien-Thi Nguyen (ttn)† diff --git a/Makefile b/Makefile @@ -50,17 +50,9 @@ help: clean: rm -rf $(BUILDDIR)/* - -arch-api.png: arch-api.dot - dot -Tpng arch-api.dot > arch-api.png -coin.png: coin.dot - dot -Tpng coin.dot > coin.png -deposit.png: deposit.dot - dot -Tpng deposit.dot > deposit.png -reserve.png: reserve.dot - dot -Tpng reserve.dot > reserve.png - -diagrams: arch-api.png coin.png +.PHONY: diagrams +diagrams: + $(MAKE) -C images/ # The html-linked builder does not support caching, so we @@ -115,25 +107,25 @@ devhelp: @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/neuro" @echo "# devhelp" -epub: +epub: diagrams $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub @echo @echo "Build finished. The epub file is in $(BUILDDIR)/epub." -latex: +latex: diagrams $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." @echo "Run \`make' in that directory to run these through (pdf)latex" \ "(use \`make latexpdf' here to do that automatically)." -latexpdf: +latexpdf: diagrams $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." $(MAKE) -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." -latexpdfja: +latexpdfja: diagrams $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through platex and dvipdfmx..." $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja diff --git a/README b/README @@ -4,6 +4,7 @@ To build things on a Debian (-based) system, install these packages: - make - python3-sphinx - python3-recommonmark + - python3-sphinx-book-theme - graphviz - texlive-latex-extra - dvipng diff --git a/_exts/taler_sphinx_theme/__init__.py b/_exts/taler_sphinx_theme/__init__.py @@ -1,166 +0,0 @@ -"""Sphinx Guzzle theme.""" - -import os -from os import path -import xml.etree.ElementTree as ET - -from docutils import nodes -from sphinx.locale import admonitionlabels -from sphinx.writers.html import HTMLTranslator as SphinxHTMLTranslator - -from pygments.style import Style -from pygments.token import Keyword, Name, Comment, String, Error, \ - Number, Operator, Generic, Whitespace, Punctuation, Other, Literal - - -def setup(app): - """Setup conntects events to the sitemap builder""" - app.connect('html-page-context', add_html_link) - app.connect('build-finished', create_sitemap) - app.set_translator('html', MyHTMLTranslator) - app.set_translator('html-linked', MyHTMLTranslator) - app.sitemap_links = [] - app.add_html_theme('taler_sphinx_theme', path.abspath(path.dirname(__file__) + "/guzzle_sphinx_theme")) - - -def add_html_link(app, pagename, templatename, context, doctree): - """As each page is built, collect page names for the sitemap""" - base_url = app.config['html_theme_options'].get('base_url', '') - if base_url: - app.sitemap_links.append(base_url + pagename + ".html") - - -def create_sitemap(app, exception): - """Generates the sitemap.xml from the collected HTML page links""" - if (not app.config['html_theme_options'].get('base_url', '') or - exception is not None or - not app.sitemap_links): - return - - filename = app.outdir + "/sitemap.xml" - print("Generating sitemap.xml in %s" % filename) - - root = ET.Element("urlset") - root.set("xmlns", "http://www.sitemaps.org/schemas/sitemap/0.9") - - for link in app.sitemap_links: - url = ET.SubElement(root, "url") - ET.SubElement(url, "loc").text = link - - ET.ElementTree(root).write(filename) - - -def html_theme_path(): - return [os.path.dirname(os.path.abspath(__file__))] - - -class MyHTMLTranslator(SphinxHTMLTranslator): - """ - Handle translating to bootstrap structure. - """ - def visit_table(self, node, name=''): - """ - Override docutils default table formatter to not include a border - and to use Bootstrap CSS - See: http://sourceforge.net/p/docutils/code/HEAD/tree/trunk/docutils/docutils/writers/html4css1/__init__.py#l1550 - """ - self.context.append(self.compact_p) - self.compact_p = True - classes = 'table table-bordered ' + self.settings.table_style - classes = classes.strip() - self.body.append( - self.starttag(node, 'table', CLASS=classes)) - - def depart_table(self, node): - """ - This needs overridin' too - """ - self.compact_p = self.context.pop() - self.body.append('</table>\n') - - def visit_field(self, node): - pass - - def depart_field(self, node): - pass - - def visit_field_name(self, node): - atts = {} - if self.in_docinfo: - atts['class'] = 'docinfo-name' - else: - atts['class'] = 'field-name' - self.context.append('') - self.body.append(self.starttag(node, 'dt', '', **atts)) - - def depart_field_name(self, node): - self.body.append('</dt>') - self.body.append(self.context.pop()) - - def visit_field_body(self, node): - self.body.append(self.starttag(node, 'dd', '', CLASS='field-body')) - self.set_class_on_child(node, 'first', 0) - field = node.parent - if (self.compact_field_list or - isinstance(field.parent, nodes.docinfo) or - field.parent.index(field) == len(field.parent) - 1): - # If we are in a compact list, the docinfo, or if this is - # the last field of the field list, do not add vertical - # space after last element. - self.set_class_on_child(node, 'last', -1) - - def depart_field_body(self, node): - self.body.append('</dd>\n') - - def visit_field_list(self, node): - self.context.append((self.compact_field_list, self.compact_p)) - self.compact_p = None - if 'compact' in node['classes']: - self.compact_field_list = True - elif (self.settings.compact_field_lists - and 'open' not in node['classes']): - self.compact_field_list = True - if self.compact_field_list: - for field in node: - field_body = field[-1] - assert isinstance(field_body, nodes.field_body) - children = [n for n in field_body - if not isinstance(n, nodes.Invisible)] - if not (len(children) == 0 or - len(children) == 1 and - isinstance(children[0], - (nodes.paragraph, nodes.line_block))): - self.compact_field_list = False - break - self.body.append(self.starttag(node, 'dl', frame='void', - rules='none', - CLASS='docutils field-list')) - - def depart_field_list(self, node): - self.body.append('</dl>\n') - self.compact_field_list, self.compact_p = self.context.pop() - - def visit_container(self, node): - self.body.append(self.starttag(node, 'div', CLASS='docutils')) - - def add_secnumber(self, node): - # type: (nodes.Element) -> None - if node.get('secnumber'): - numbers = list(map(str, node['secnumber'])) - if len(numbers) <= 3: - self.body.append('.'.join(numbers) + self.secnumber_suffix) - elif isinstance(node.parent, nodes.section): - if self.builder.name == 'singlehtml': - docname = self.docnames[-1] - anchorname = "%s/#%s" % (docname, node.parent['ids'][0]) - if anchorname not in self.builder.secnumbers: - anchorname = "%s/" % docname # try first heading which has no anchor - else: - anchorname = '#' + node.parent['ids'][0] - if anchorname not in self.builder.secnumbers: - anchorname = '' # try first heading which has no anchor - if self.builder.secnumbers.get(anchorname): - numbers = list(self.builder.secnumbers[anchorname]) - if len(numbers) <= 3: - self.body.append('.'.join(map(str, numbers)) + - self.secnumber_suffix) diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/comments.html b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/comments.html @@ -1,16 +0,0 @@ -{% if theme_disqus_comments_shortname %} -<div id="comments"> - <div id="disqus_thread"></div> - <script type="text/javascript"> - var disqus_shortname = '{{ theme_disqus_comments_shortname }}'; - var disqus_identifier = '{{ pagename }}'; - (function() { - var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true; - dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js'; - (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq); - })(); - </script> - <noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript> - <a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a> -</div> -{% endif %} diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/globaltoc.html b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/globaltoc.html @@ -1,14 +0,0 @@ - -<div class="sidebar-block"> - <div class="sidebar-wrapper"> - <h2>{{ _('Table Of Contents') }}</h2> - </div> - <div class="sidebar-toc"> - {% set toctree = toctree(maxdepth=theme_globaltoc_depth|toint, collapse=theme_globaltoc_collapse|tobool, includehidden=theme_globaltoc_includehidden|tobool) %} - {% if toctree %} - {{ toctree }} - {% else %} - {{ toc }} - {% endif %} - </div> -</div> diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/layout.html b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/layout.html @@ -1,172 +0,0 @@ -{%- extends "basic/layout.html" %} - -{# Do this so that bootstrap is included before the main css file #} -{%- block htmltitle %} - <!-- Licensed under the Apache 2.0 License --> - <link rel="stylesheet" type="text/css" href="{{ pathto('_static/fonts/open-sans/stylesheet.css', 1) }}" /> - <!-- Licensed under the SIL Open Font License --> - <link rel="stylesheet" type="text/css" href="{{ pathto('_static/fonts/source-serif-pro/source-serif-pro.css', 1) }}" /> - <link rel="stylesheet" type="text/css" href="{{ pathto('_static/css/bootstrap.min.css', 1) }}" /> - <link rel="stylesheet" type="text/css" href="{{ pathto('_static/css/bootstrap-theme.min.css', 1) }}" /> - <meta name="viewport" content="width=device-width, initial-scale=1.0"> - {{ super() }} -{%- endblock %} - -{%- block extrahead %} - {% if theme_touch_icon %} - <link rel="apple-touch-icon" href="{{ pathto('_static/' ~ theme_touch_icon, 1) }}" /> - {% endif %} - {{ super() }} -{% endblock %} - -{# Displays the URL for the homepage if it's set or the master_doc if it is not #} -{% macro homepage() -%} - {%- if theme_homepage %} - {%- if hasdoc(theme_homepage) %} - {{ pathto(theme_homepage) }} - {%- else %} - {{ theme_homepage }} - {%- endif %} - {%- else %} - {{ pathto(master_doc) }} - {%- endif %} -{%- endmacro %} - -{# Displays the URL for the tospage if it's set or falls back to homepage macro #} -{% macro tospage() -%} - {%- if theme_tospage %} - {%- if hasdoc(theme_tospage) %} - {{ pathto(theme_tospage) }} - {%- else %} - {{ theme_tospage }} - {%- endif %} - {%- else %} - {{ homepage() }} - {%- endif %} -{%- endmacro %} - -{# Displays the URL for the projectpage if it's set or falls back to homepage macro #} -{% macro projectlink() -%} - {%- if theme_projectlink %} - {%- if hasdoc(theme_projectlink) %} - {{ pathto(theme_projectlink) }} - {%- else %} - {{ theme_projectlink }} - {%- endif %} - {%- else %} - {{ homepage() }} - {%- endif %} -{%- endmacro %} - -{# Displays the next and previous links both before and after content #} -{% macro render_relations() -%} - {% if prev or next %} - <div class="footer-relations"> - {% if prev %} - <div class="pull-left"> - <a class="btn btn-default" href="{{ prev.link|e }}" title="{{ _('previous chapter')}} (use the left arrow)">{{ prev.title }}</a> - </div> - {% endif %} - {%- if next and next.title != '<no title>' %} - <div class="pull-right"> - <a class="btn btn-default" href="{{ next.link|e }}" title="{{ _('next chapter')}} (use the right arrow)">{{ next.title }}</a> - </div> - {%- endif %} - </div> - <div class="clearer"></div> - {% endif %} -{%- endmacro %} - -{%- macro guzzle_sidebar() %} - <div id="left-column"> - <div class="sphinxsidebar"> - {%- if sidebars != None %} - {#- new style sidebar: explicitly include/exclude templates #} - {%- for sidebartemplate in sidebars %} - {%- include sidebartemplate %} - {%- endfor %} - {% else %} - {% include "logo-text.html" %} - {% include "globaltoc.html" %} - {% include "searchbox.html" %} - {%- endif %} - </div> - </div> -{%- endmacro %} - -{%- block content %} - - {%- if pagename == 'index' and theme_index_template %} - {% include theme_index_template %} - {%- else %} - <div class="container-wrapper"> - - <div id="mobile-toggle"> - <a href="#"><span class="glyphicon glyphicon-align-justify" aria-hidden="true"></span></a> - </div> - - {%- block sidebar1 %}{{ guzzle_sidebar() }}{% endblock %} - - {%- block document_wrapper %} - {%- block document %} - <div id="right-column"> - {% block breadcrumbs %} - <div role="navigation" aria-label="breadcrumbs navigation"> - <ol class="breadcrumb"> - <li><a href="{{ pathto(master_doc) }}">Docs</a></li> - {% for doc in parents %} - <li><a href="{{ doc.link|e }}">{{ doc.title }}</a></li> - {% endfor %} - <li>{{ title }}</li> - </ol> - </div> - {% endblock %} - <div class="document clearer body" role="main"> - {% block body %} {% endblock %} - </div> - {%- block bottom_rel_links %} - {{ render_relations() }} - {%- endblock %} - </div> - <div class="clearfix"></div> - {%- endblock %} - {%- endblock %} - - {%- block comments -%} - {% if theme_disqus_comments_shortname %} - <div class="container comment-container"> - {% include "comments.html" %} - </div> - {% endif %} - {%- endblock %} - </div> - {%- endif %} - {%- endblock %} - -{%- block footer %} -<script type="text/javascript"> - $("#mobile-toggle a").click(function () { - $("#left-column").toggle(); - }); -</script> -<script type="text/javascript" src="{{ pathto('_static/js/bootstrap.js', 1)}}"></script> -{%- block footer_wrapper %} - <div class="footer"> - © Copyright {{ copyright }}. Created using <a href="http://sphinx.pocoo.org/">Sphinx</a>. - </div> -{%- endblock %} -{%- block ga %} - {%- if theme_google_analytics_account %} - <script type="text/javascript"> - var _gaq = _gaq || []; - _gaq.push(['_setAccount', '{{ theme_google_analytics_account }}']); - _gaq.push(['_trackPageview']); - (function() { - var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; - ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; - var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); - })(); - </script> - {%- endif %} -{%- endblock %} -{%- endblock %} diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/localtoc.html b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/localtoc.html @@ -1,10 +0,0 @@ -{%- if display_toc %} -<div class="sidebar-block"> - <div class="sidebar-wrapper"> - <h2>{{ _('Contents') }}</h2> - <div class="sidebar-localtoc"> - {{ toc }} - </div> - </div> -</div> -{%- endif %} diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/logo-text.html b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/logo-text.html @@ -1 +0,0 @@ -<a href="{{ homepage() }}" class="text-logo">{{ theme_project_nav_name or shorttitle }}</a> diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/search.html b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/search.html @@ -1,48 +0,0 @@ -{%- extends "basic/search.html" %} - -{% block body %} - <h1 id="search-documentation">{{ _('Search') }}</h1> - <div id="fallback" class="admonition warning"> - <script type="text/javascript">$('#fallback').hide();</script> - <p> - {% trans %}Please activate JavaScript to enable the search - functionality.{% endtrans %} - </p> - </div> - <p> - {% trans %}From here you can search these documents. Enter your search - words into the box below and click "search". Note that the search - function will automatically search for all of the words. Pages - containing fewer words won't appear in the result list.{% endtrans %} - </p> - - <div class="search-page-form"> - <form class="form-inline" action="{{ pathto('search') }}" method="GET" role="form"> - <div class="input-group"> - <input name="q" type="text" class="form-control" /> - <span class="input-group-btn"> - <button class="btn btn-default" type="button">{{ _('search') }}</button> - </span> - </div> - <span id="search-progress" style="padding-left: 10px"></span> - </form> - </div> - - {% if search_performed %} - <h2>{{ _('Search Results') }}</h2> - {% if not search_results %} - <p>{{ _('Your search did not match any documents. Please make sure that all words are spelled correctly and that you\'ve selected enough categories.') }}</p> - {% endif %} - {% endif %} - <div id="search-results"> - {% if search_results %} - <ul> - {% for href, caption, context in search_results %} - <li><a href="{{ pathto(item.href) }}">{{ caption }}</a> - <div class="context">{{ context|e }}</div> - </li> - {% endfor %} - </ul> - {% endif %} - </div> -{% endblock %} diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/searchbox.html b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/searchbox.html @@ -1,15 +0,0 @@ -{%- if pagename != "search" %} -<div class="sidebar-block"> - <div class="sidebar-wrapper"> - <div id="main-search"> - <form class="form-inline" action="{{ pathto('search') }}" method="GET" role="form"> - <div class="input-group"> - <input name="q" type="text" class="form-control" placeholder="Search..."> - </div> - <input type="hidden" name="check_keywords" value="yes" /> - <input type="hidden" name="area" value="default" /> - </form> - </div> - </div> -</div> -{%- endif %} diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/css/bootstrap-theme.min.css b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/css/bootstrap-theme.min.css @@ -1,7 +0,0 @@ -/*! - * Bootstrap v3.1.0 (http://getbootstrap.com) - * Copyright 2011-2014 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - */ - -.btn-default,.btn-primary,.btn-success,.btn-info,.btn-warning,.btn-danger{text-shadow:0 -1px 0 rgba(0,0,0,0.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 1px rgba(0,0,0,0.075)}.btn-default:active,.btn-primary:active,.btn-success:active,.btn-info:active,.btn-warning:active,.btn-danger:active,.btn-default.active,.btn-primary.active,.btn-success.active,.btn-info.active,.btn-warning.active,.btn-danger.active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn:active,.btn.active{background-image:none}.btn-default{background-image:-webkit-linear-gradient(top, #fff 0, #e0e0e0 100%);background-image:linear-gradient(to bottom, #fff 0, #e0e0e0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background-repeat:repeat-x;border-color:#dbdbdb;text-shadow:0 1px 0 #fff;border-color:#ccc}.btn-default:hover,.btn-default:focus{background-color:#e0e0e0;background-position:0 -15px}.btn-default:active,.btn-default.active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-primary{background-image:-webkit-linear-gradient(top, #428bca 0, #2d6ca2 100%);background-image:linear-gradient(to bottom, #428bca 0, #2d6ca2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff2d6ca2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background-repeat:repeat-x;border-color:#2b669a}.btn-primary:hover,.btn-primary:focus{background-color:#2d6ca2;background-position:0 -15px}.btn-primary:active,.btn-primary.active{background-color:#2d6ca2;border-color:#2b669a}.btn-success{background-image:-webkit-linear-gradient(top, #5cb85c 0, #419641 100%);background-image:linear-gradient(to bottom, #5cb85c 0, #419641 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background-repeat:repeat-x;border-color:#3e8f3e}.btn-success:hover,.btn-success:focus{background-color:#419641;background-position:0 -15px}.btn-success:active,.btn-success.active{background-color:#419641;border-color:#3e8f3e}.btn-info{background-image:-webkit-linear-gradient(top, #5bc0de 0, #2aabd2 100%);background-image:linear-gradient(to bottom, #5bc0de 0, #2aabd2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background-repeat:repeat-x;border-color:#28a4c9}.btn-info:hover,.btn-info:focus{background-color:#2aabd2;background-position:0 -15px}.btn-info:active,.btn-info.active{background-color:#2aabd2;border-color:#28a4c9}.btn-warning{background-image:-webkit-linear-gradient(top, #f0ad4e 0, #eb9316 100%);background-image:linear-gradient(to bottom, #f0ad4e 0, #eb9316 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background-repeat:repeat-x;border-color:#e38d13}.btn-warning:hover,.btn-warning:focus{background-color:#eb9316;background-position:0 -15px}.btn-warning:active,.btn-warning.active{background-color:#eb9316;border-color:#e38d13}.btn-danger{background-image:-webkit-linear-gradient(top, #d9534f 0, #c12e2a 100%);background-image:linear-gradient(to bottom, #d9534f 0, #c12e2a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background-repeat:repeat-x;border-color:#b92c28}.btn-danger:hover,.btn-danger:focus{background-color:#c12e2a;background-position:0 -15px}.btn-danger:active,.btn-danger.active{background-color:#c12e2a;border-color:#b92c28}.thumbnail,.img-thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.075);box-shadow:0 1px 2px rgba(0,0,0,0.075)}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{background-image:-webkit-linear-gradient(top, #f5f5f5 0, #e8e8e8 100%);background-image:linear-gradient(to bottom, #f5f5f5 0, #e8e8e8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-color:#e8e8e8}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{background-image:-webkit-linear-gradient(top, #428bca 0, #357ebd 100%);background-image:linear-gradient(to bottom, #428bca 0, #357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);background-color:#357ebd}.navbar-default{background-image:-webkit-linear-gradient(top, #fff 0, #f8f8f8 100%);background-image:linear-gradient(to bottom, #fff 0, #f8f8f8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 5px rgba(0,0,0,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 5px rgba(0,0,0,0.075)}.navbar-default .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top, #ebebeb 0, #f3f3f3 100%);background-image:linear-gradient(to bottom, #ebebeb 0, #f3f3f3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff3f3f3', GradientType=0);-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,0.075);box-shadow:inset 0 3px 9px rgba(0,0,0,0.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,0.25)}.navbar-inverse{background-image:-webkit-linear-gradient(top, #3c3c3c 0, #222 100%);background-image:linear-gradient(to bottom, #3c3c3c 0, #222 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false)}.navbar-inverse .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top, #222 0, #282828 100%);background-image:linear-gradient(to bottom, #222 0, #282828 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff282828', GradientType=0);-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,0.25);box-shadow:inset 0 3px 9px rgba(0,0,0,0.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.navbar-static-top,.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}.alert{text-shadow:0 1px 0 rgba(255,255,255,0.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.25),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 0 rgba(255,255,255,0.25),0 1px 2px rgba(0,0,0,0.05)}.alert-success{background-image:-webkit-linear-gradient(top, #dff0d8 0, #c8e5bc 100%);background-image:linear-gradient(to bottom, #dff0d8 0, #c8e5bc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);border-color:#b2dba1}.alert-info{background-image:-webkit-linear-gradient(top, #d9edf7 0, #b9def0 100%);background-image:linear-gradient(to bottom, #d9edf7 0, #b9def0 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);border-color:#9acfea}.alert-warning{background-image:-webkit-linear-gradient(top, #fcf8e3 0, #f8efc0 100%);background-image:linear-gradient(to bottom, #fcf8e3 0, #f8efc0 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);border-color:#f5e79e}.alert-danger{background-image:-webkit-linear-gradient(top, #f2dede 0, #e7c3c3 100%);background-image:linear-gradient(to bottom, #f2dede 0, #e7c3c3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);border-color:#dca7a7}.progress{background-image:-webkit-linear-gradient(top, #ebebeb 0, #f5f5f5 100%);background-image:linear-gradient(to bottom, #ebebeb 0, #f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0)}.progress-bar{background-image:-webkit-linear-gradient(top, #428bca 0, #3071a9 100%);background-image:linear-gradient(to bottom, #428bca 0, #3071a9 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0)}.progress-bar-success{background-image:-webkit-linear-gradient(top, #5cb85c 0, #449d44 100%);background-image:linear-gradient(to bottom, #5cb85c 0, #449d44 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0)}.progress-bar-info{background-image:-webkit-linear-gradient(top, #5bc0de 0, #31b0d5 100%);background-image:linear-gradient(to bottom, #5bc0de 0, #31b0d5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0)}.progress-bar-warning{background-image:-webkit-linear-gradient(top, #f0ad4e 0, #ec971f 100%);background-image:linear-gradient(to bottom, #f0ad4e 0, #ec971f 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0)}.progress-bar-danger{background-image:-webkit-linear-gradient(top, #d9534f 0, #c9302c 100%);background-image:linear-gradient(to bottom, #d9534f 0, #c9302c 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.075);box-shadow:0 1px 2px rgba(0,0,0,0.075)}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{text-shadow:0 -1px 0 #3071a9;background-image:-webkit-linear-gradient(top, #428bca 0, #3278b3 100%);background-image:linear-gradient(to bottom, #428bca 0, #3278b3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0);border-color:#3278b3}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.05);box-shadow:0 1px 2px rgba(0,0,0,0.05)}.panel-default>.panel-heading{background-image:-webkit-linear-gradient(top, #f5f5f5 0, #e8e8e8 100%);background-image:linear-gradient(to bottom, #f5f5f5 0, #e8e8e8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0)}.panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top, #428bca 0, #357ebd 100%);background-image:linear-gradient(to bottom, #428bca 0, #357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0)}.panel-success>.panel-heading{background-image:-webkit-linear-gradient(top, #dff0d8 0, #d0e9c6 100%);background-image:linear-gradient(to bottom, #dff0d8 0, #d0e9c6 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0)}.panel-info>.panel-heading{background-image:-webkit-linear-gradient(top, #d9edf7 0, #c4e3f3 100%);background-image:linear-gradient(to bottom, #d9edf7 0, #c4e3f3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0)}.panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top, #fcf8e3 0, #faf2cc 100%);background-image:linear-gradient(to bottom, #fcf8e3 0, #faf2cc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0)}.panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top, #f2dede 0, #ebcccc 100%);background-image:linear-gradient(to bottom, #f2dede 0, #ebcccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0)}.well{background-image:-webkit-linear-gradient(top, #e8e8e8 0, #f5f5f5 100%);background-image:linear-gradient(to bottom, #e8e8e8 0, #f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);border-color:#dcdcdc;-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,0.05),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 3px rgba(0,0,0,0.05),0 1px 0 rgba(255,255,255,0.1)} -\ No newline at end of file diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/css/bootstrap.min.css b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/css/bootstrap.min.css @@ -1,7 +0,0 @@ -/*! - * Bootstrap v3.1.0 (http://getbootstrap.com) - * Copyright 2011-2014 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - */ - -/*! normalize.css v3.0.0 | MIT License | git.io/normalize */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:0.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace, monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}@media print{*{text-shadow:none !important;color:#000 !important;background:transparent !important;box-shadow:none !important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}select{background:#fff !important}.navbar{display:none}.table td,.table th{background-color:#fff !important}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000 !important}.label{border:1px solid #000}.table{border-collapse:collapse !important}.table-bordered th,.table-bordered td{border:1px solid #ddd !important}}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}*:before,*:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:62.5%;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.428571429;color:#333;background-color:#fff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#428bca;text-decoration:none}a:hover,a:focus{color:#2a6496;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.img-responsive{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{padding:4px;line-height:1.428571429;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small,.h1 .small,.h2 .small,.h3 .small,.h4 .small,.h5 .small,.h6 .small{font-weight:normal;line-height:1;color:#999}h1,.h1,h2,.h2,h3,.h3{margin-top:20px;margin-bottom:10px}h1 small,.h1 small,h2 small,.h2 small,h3 small,.h3 small,h1 .small,.h1 .small,h2 .small,.h2 .small,h3 .small,.h3 .small{font-size:65%}h4,.h4,h5,.h5,h6,.h6{margin-top:10px;margin-bottom:10px}h4 small,.h4 small,h5 small,.h5 small,h6 small,.h6 small,h4 .small,.h4 .small,h5 .small,.h5 .small,h6 .small,.h6 .small{font-size:75%}h1,.h1{font-size:36px}h2,.h2{font-size:30px}h3,.h3{font-size:24px}h4,.h4{font-size:18px}h5,.h5{font-size:14px}h6,.h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:200;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}small,.small{font-size:85%}cite{font-style:normal}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-muted{color:#999}.text-primary{color:#428bca}a.text-primary:hover{color:#3071a9}.text-success{color:#3c763d}a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#428bca}a.bg-primary:hover{background-color:#3071a9}.bg-success{background-color:#dff0d8}a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ul,ol{margin-top:0;margin-bottom:10px}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline>li{display:inline-block;padding-left:5px;padding-right:5px}.list-inline>li:first-child{padding-left:0}dl{margin-top:0;margin-bottom:20px}dt,dd{line-height:1.428571429}dt{font-weight:bold}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote p:last-child,blockquote ul:last-child,blockquote ol:last-child{margin-bottom:0}blockquote footer,blockquote small,blockquote .small{display:block;font-size:80%;line-height:1.428571429;color:#999}blockquote footer:before,blockquote small:before,blockquote .small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0;text-align:right}.blockquote-reverse footer:before,blockquote.pull-right footer:before,.blockquote-reverse small:before,blockquote.pull-right small:before,.blockquote-reverse .small:before,blockquote.pull-right .small:before{content:''}.blockquote-reverse footer:after,blockquote.pull-right footer:after,.blockquote-reverse small:after,blockquote.pull-right small:after,.blockquote-reverse .small:after,blockquote.pull-right .small:after{content:'\00A0 \2014'}blockquote:before,blockquote:after{content:""}address{margin-bottom:20px;font-style:normal;line-height:1.428571429}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;white-space:nowrap;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;box-shadow:inset 0 -1px 0 rgba(0,0,0,0.25)}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.428571429;word-break:break-all;word-wrap:break-word;color:#333;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}.row{margin-left:-15px;margin-right:-15px}.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12{position:relative;min-height:1px;padding-left:15px;padding-right:15px}.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666666666666%}.col-xs-10{width:83.33333333333334%}.col-xs-9{width:75%}.col-xs-8{width:66.66666666666666%}.col-xs-7{width:58.333333333333336%}.col-xs-6{width:50%}.col-xs-5{width:41.66666666666667%}.col-xs-4{width:33.33333333333333%}.col-xs-3{width:25%}.col-xs-2{width:16.666666666666664%}.col-xs-1{width:8.333333333333332%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666666666666%}.col-xs-pull-10{right:83.33333333333334%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666666666666%}.col-xs-pull-7{right:58.333333333333336%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666666666667%}.col-xs-pull-4{right:33.33333333333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.666666666666664%}.col-xs-pull-1{right:8.333333333333332%}.col-xs-pull-0{right:0}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666666666666%}.col-xs-push-10{left:83.33333333333334%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666666666666%}.col-xs-push-7{left:58.333333333333336%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666666666667%}.col-xs-push-4{left:33.33333333333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.666666666666664%}.col-xs-push-1{left:8.333333333333332%}.col-xs-push-0{left:0}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666666666666%}.col-xs-offset-10{margin-left:83.33333333333334%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666666666666%}.col-xs-offset-7{margin-left:58.333333333333336%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666666666667%}.col-xs-offset-4{margin-left:33.33333333333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.666666666666664%}.col-xs-offset-1{margin-left:8.333333333333332%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666666666666%}.col-sm-10{width:83.33333333333334%}.col-sm-9{width:75%}.col-sm-8{width:66.66666666666666%}.col-sm-7{width:58.333333333333336%}.col-sm-6{width:50%}.col-sm-5{width:41.66666666666667%}.col-sm-4{width:33.33333333333333%}.col-sm-3{width:25%}.col-sm-2{width:16.666666666666664%}.col-sm-1{width:8.333333333333332%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666666666666%}.col-sm-pull-10{right:83.33333333333334%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666666666666%}.col-sm-pull-7{right:58.333333333333336%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666666666667%}.col-sm-pull-4{right:33.33333333333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.666666666666664%}.col-sm-pull-1{right:8.333333333333332%}.col-sm-pull-0{right:0}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666666666666%}.col-sm-push-10{left:83.33333333333334%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666666666666%}.col-sm-push-7{left:58.333333333333336%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666666666667%}.col-sm-push-4{left:33.33333333333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.666666666666664%}.col-sm-push-1{left:8.333333333333332%}.col-sm-push-0{left:0}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666666666666%}.col-sm-offset-10{margin-left:83.33333333333334%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666666666666%}.col-sm-offset-7{margin-left:58.333333333333336%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666666666667%}.col-sm-offset-4{margin-left:33.33333333333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.666666666666664%}.col-sm-offset-1{margin-left:8.333333333333332%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666666666666%}.col-md-10{width:83.33333333333334%}.col-md-9{width:75%}.col-md-8{width:66.66666666666666%}.col-md-7{width:58.333333333333336%}.col-md-6{width:50%}.col-md-5{width:41.66666666666667%}.col-md-4{width:33.33333333333333%}.col-md-3{width:25%}.col-md-2{width:16.666666666666664%}.col-md-1{width:8.333333333333332%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666666666666%}.col-md-pull-10{right:83.33333333333334%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666666666666%}.col-md-pull-7{right:58.333333333333336%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666666666667%}.col-md-pull-4{right:33.33333333333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.666666666666664%}.col-md-pull-1{right:8.333333333333332%}.col-md-pull-0{right:0}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666666666666%}.col-md-push-10{left:83.33333333333334%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666666666666%}.col-md-push-7{left:58.333333333333336%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666666666667%}.col-md-push-4{left:33.33333333333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.666666666666664%}.col-md-push-1{left:8.333333333333332%}.col-md-push-0{left:0}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666666666666%}.col-md-offset-10{margin-left:83.33333333333334%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666666666666%}.col-md-offset-7{margin-left:58.333333333333336%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666666666667%}.col-md-offset-4{margin-left:33.33333333333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.666666666666664%}.col-md-offset-1{margin-left:8.333333333333332%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666666666666%}.col-lg-10{width:83.33333333333334%}.col-lg-9{width:75%}.col-lg-8{width:66.66666666666666%}.col-lg-7{width:58.333333333333336%}.col-lg-6{width:50%}.col-lg-5{width:41.66666666666667%}.col-lg-4{width:33.33333333333333%}.col-lg-3{width:25%}.col-lg-2{width:16.666666666666664%}.col-lg-1{width:8.333333333333332%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666666666666%}.col-lg-pull-10{right:83.33333333333334%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666666666666%}.col-lg-pull-7{right:58.333333333333336%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666666666667%}.col-lg-pull-4{right:33.33333333333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.666666666666664%}.col-lg-pull-1{right:8.333333333333332%}.col-lg-pull-0{right:0}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666666666666%}.col-lg-push-10{left:83.33333333333334%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666666666666%}.col-lg-push-7{left:58.333333333333336%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666666666667%}.col-lg-push-4{left:33.33333333333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.666666666666664%}.col-lg-push-1{left:8.333333333333332%}.col-lg-push-0{left:0}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666666666666%}.col-lg-offset-10{margin-left:83.33333333333334%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666666666666%}.col-lg-offset-7{margin-left:58.333333333333336%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666666666667%}.col-lg-offset-4{margin-left:33.33333333333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.666666666666664%}.col-lg-offset-1{margin-left:8.333333333333332%}.col-lg-offset-0{margin-left:0}}table{max-width:100%;background-color:transparent}th{text-align:left}.table{width:100%;margin-bottom:20px}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{padding:8px;line-height:1.428571429;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>th,.table>caption+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>td,.table>thead:first-child>tr:first-child>td{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>thead>tr>th,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>tbody>tr>td,.table-condensed>tfoot>tr>td{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.table-striped>tbody>tr:nth-child(odd)>td,.table-striped>tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}.table-hover>tbody>tr:hover>td,.table-hover>tbody>tr:hover>th{background-color:#f5f5f5}table col[class*="col-"]{position:static;float:none;display:table-column}table td[class*="col-"],table th[class*="col-"]{position:static;float:none;display:table-cell}.table>thead>tr>td.active,.table>tbody>tr>td.active,.table>tfoot>tr>td.active,.table>thead>tr>th.active,.table>tbody>tr>th.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>tbody>tr.active>td,.table>tfoot>tr.active>td,.table>thead>tr.active>th,.table>tbody>tr.active>th,.table>tfoot>tr.active>th{background-color:#f5f5f5}.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover,.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th{background-color:#e8e8e8}.table>thead>tr>td.success,.table>tbody>tr>td.success,.table>tfoot>tr>td.success,.table>thead>tr>th.success,.table>tbody>tr>th.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>tbody>tr.success>td,.table>tfoot>tr.success>td,.table>thead>tr.success>th,.table>tbody>tr.success>th,.table>tfoot>tr.success>th{background-color:#dff0d8}.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover,.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th{background-color:#d0e9c6}.table>thead>tr>td.info,.table>tbody>tr>td.info,.table>tfoot>tr>td.info,.table>thead>tr>th.info,.table>tbody>tr>th.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>tbody>tr.info>td,.table>tfoot>tr.info>td,.table>thead>tr.info>th,.table>tbody>tr.info>th,.table>tfoot>tr.info>th{background-color:#d9edf7}.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover,.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th{background-color:#c4e3f3}.table>thead>tr>td.warning,.table>tbody>tr>td.warning,.table>tfoot>tr>td.warning,.table>thead>tr>th.warning,.table>tbody>tr>th.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>tbody>tr.warning>td,.table>tfoot>tr.warning>td,.table>thead>tr.warning>th,.table>tbody>tr.warning>th,.table>tfoot>tr.warning>th{background-color:#fcf8e3}.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover,.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th{background-color:#faf2cc}.table>thead>tr>td.danger,.table>tbody>tr>td.danger,.table>tfoot>tr>td.danger,.table>thead>tr>th.danger,.table>tbody>tr>th.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>tbody>tr.danger>td,.table>tfoot>tr.danger>td,.table>thead>tr.danger>th,.table>tbody>tr.danger>th,.table>tfoot>tr.danger>th{background-color:#f2dede}.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover,.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th{background-color:#ebcccc}@media (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;overflow-x:scroll;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd;-webkit-overflow-scrolling:touch}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>thead>tr>th,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>td{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}fieldset{padding:0;margin:0;border:0;min-width:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;margin-bottom:5px;font-weight:bold}input[type="search"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type="file"]{display:block}input[type="range"]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.428571429;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.428571429;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6)}.form-control:-moz-placeholder{color:#999}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{cursor:not-allowed;background-color:#eee;opacity:1}textarea.form-control{height:auto}input[type="date"]{line-height:34px}.form-group{margin-bottom:15px}.radio,.checkbox{display:block;min-height:20px;margin-top:10px;margin-bottom:10px;padding-left:20px}.radio label,.checkbox label{display:inline;font-weight:normal;cursor:pointer}.radio input[type="radio"],.radio-inline input[type="radio"],.checkbox input[type="checkbox"],.checkbox-inline input[type="checkbox"]{float:left;margin-left:-20px}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{display:inline-block;padding-left:20px;margin-bottom:0;vertical-align:middle;font-weight:normal;cursor:pointer}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}input[type="radio"][disabled],input[type="checkbox"][disabled],.radio[disabled],.radio-inline[disabled],.checkbox[disabled],.checkbox-inline[disabled],fieldset[disabled] input[type="radio"],fieldset[disabled] input[type="checkbox"],fieldset[disabled] .radio,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}textarea.input-sm,select[multiple].input-sm{height:auto}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-lg{height:46px;line-height:46px}textarea.input-lg,select[multiple].input-lg{height:auto}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.has-feedback .form-control-feedback{position:absolute;top:25px;right:0;display:block;width:34px;height:34px;line-height:34px;text-align:center}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;border-color:#3c763d;background-color:#dff0d8}.has-success .form-control-feedback{color:#3c763d}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;border-color:#8a6d3b;background-color:#fcf8e3}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;border-color:#a94442;background-color:#f2dede}.has-error .form-control-feedback{color:#a94442}.form-control-static{margin-bottom:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .radio,.form-inline .checkbox{display:inline-block;margin-top:0;margin-bottom:0;padding-left:0;vertical-align:middle}.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{float:none;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .control-label,.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{margin-top:0;margin-bottom:0;padding-top:7px}.form-horizontal .radio,.form-horizontal .checkbox{min-height:27px}.form-horizontal .form-group{margin-left:-15px;margin-right:-15px}.form-horizontal .form-control-static{padding-top:7px}@media (min-width:768px){.form-horizontal .control-label{text-align:right}}.form-horizontal .has-feedback .form-control-feedback{top:0;right:15px}.btn{display:inline-block;margin-bottom:0;font-weight:normal;text-align:center;vertical-align:middle;cursor:pointer;background-image:none;border:1px solid transparent;white-space:nowrap;padding:6px 12px;font-size:14px;line-height:1.428571429;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none}.btn:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus{color:#333;text-decoration:none}.btn:active,.btn.active{outline:0;background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;pointer-events:none;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default:hover,.btn-default:focus,.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{color:#333;background-color:#ebebeb;border-color:#adadad}.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default[disabled],fieldset[disabled] .btn-default,.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled:active,.btn-default[disabled]:active,fieldset[disabled] .btn-default:active,.btn-default.disabled.active,.btn-default[disabled].active,fieldset[disabled] .btn-default.active{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#428bca;border-color:#357ebd}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{color:#fff;background-color:#3276b1;border-color:#285e8e}.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary[disabled],fieldset[disabled] .btn-primary,.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled:active,.btn-primary[disabled]:active,fieldset[disabled] .btn-primary:active,.btn-primary.disabled.active,.btn-primary[disabled].active,fieldset[disabled] .btn-primary.active{background-color:#428bca;border-color:#357ebd}.btn-primary .badge{color:#428bca;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{color:#fff;background-color:#47a447;border-color:#398439}.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{background-image:none}.btn-success.disabled,.btn-success[disabled],fieldset[disabled] .btn-success,.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled:active,.btn-success[disabled]:active,fieldset[disabled] .btn-success:active,.btn-success.disabled.active,.btn-success[disabled].active,fieldset[disabled] .btn-success.active{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{color:#fff;background-color:#39b3d7;border-color:#269abc}.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{background-image:none}.btn-info.disabled,.btn-info[disabled],fieldset[disabled] .btn-info,.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled:active,.btn-info[disabled]:active,fieldset[disabled] .btn-info:active,.btn-info.disabled.active,.btn-info[disabled].active,fieldset[disabled] .btn-info.active{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{color:#fff;background-color:#ed9c28;border-color:#d58512}.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-warning,.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled:active,.btn-warning[disabled]:active,fieldset[disabled] .btn-warning:active,.btn-warning.disabled.active,.btn-warning[disabled].active,fieldset[disabled] .btn-warning.active{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{color:#fff;background-color:#d2322d;border-color:#ac2925}.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger[disabled],fieldset[disabled] .btn-danger,.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled:active,.btn-danger[disabled]:active,fieldset[disabled] .btn-danger:active,.btn-danger.disabled.active,.btn-danger[disabled].active,fieldset[disabled] .btn-danger.active{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{color:#428bca;font-weight:normal;cursor:pointer;border-radius:0}.btn-link,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#2a6496;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#999;text-decoration:none}.btn-lg{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%;padding-left:0;padding-right:0}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;transition:height .35s ease}@font-face{font-family:'Glyphicons Halflings';src:url('../fonts/glyphicons-halflings-regular.eot');src:url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'),url('../fonts/glyphicons-halflings-regular.woff') format('woff'),url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'),url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:normal;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\2a"}.glyphicon-plus:before{content:"\2b"}.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px solid;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;font-size:14px;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,0.175);box-shadow:0 6px 12px rgba(0,0,0,0.175);background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:1.428571429;color:#333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{text-decoration:none;color:#262626;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#fff;text-decoration:none;outline:0;background-color:#428bca}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#999}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);cursor:not-allowed}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{left:auto;right:0}.dropdown-menu-left{left:0;right:auto}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.428571429;color:#999}.dropdown-backdrop{position:fixed;left:0;right:0;bottom:0;top:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px solid;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}@media (min-width:768px){.navbar-right .dropdown-menu{left:auto;right:0}.navbar-right .dropdown-menu-left{left:0;right:auto}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;float:left}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover,.btn-group>.btn:focus,.btn-group-vertical>.btn:focus,.btn-group>.btn:active,.btn-group-vertical>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn.active{z-index:2}.btn-group>.btn:focus,.btn-group-vertical>.btn:focus{outline:none}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child>.btn:last-child,.btn-group>.btn-group:first-child>.dropdown-toggle{border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn-group:last-child>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group-xs>.btn{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-sm>.btn{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-lg>.btn{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.btn-group>.btn+.dropdown-toggle{padding-left:8px;padding-right:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-left:12px;padding-right:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-bottom-left-radius:4px;border-top-right-radius:0;border-top-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{float:none;display:table-cell;width:1%}.btn-group-justified>.btn-group .btn{width:100%}[data-toggle="buttons"]>.btn>input[type="radio"],[data-toggle="buttons"]>.btn>input[type="checkbox"]{display:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*="col-"]{float:none;padding-left:0;padding-right:0}.input-group .form-control{float:left;width:100%;margin-bottom:0}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn,select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn,select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn{height:auto}.input-group-addon,.input-group-btn,.input-group .form-control{display:table-cell}.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child),.input-group .form-control:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:normal;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type="radio"],.input-group-addon input[type="checkbox"]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group-btn:last-child>.btn-group:not(:last-child)>.btn{border-bottom-right-radius:0;border-top-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:first-child>.btn-group:not(:first-child)>.btn{border-bottom-left-radius:0;border-top-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:hover,.input-group-btn>.btn:focus,.input-group-btn>.btn:active{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{margin-left:-1px}.nav{margin-bottom:0;padding-left:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#999}.nav>li.disabled>a:hover,.nav>li.disabled>a:focus{color:#999;text-decoration:none;background-color:transparent;cursor:not-allowed}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background-color:#eee;border-color:#428bca}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.428571429;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{color:#555;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent;cursor:default}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:hover,.nav-pills>li.active>a:focus{color:#fff;background-color:#428bca}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-right-radius:0;border-top-left-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{max-height:340px;overflow-x:visible;padding-right:15px;padding-left:15px;border-top:1px solid transparent;box-shadow:inset 0 1px 0 rgba(255,255,255,0.1);-webkit-overflow-scrolling:touch}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;box-shadow:none}.navbar-collapse.collapse{display:block !important;height:auto !important;padding-bottom:0;overflow:visible !important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{padding-left:0;padding-right:0}}.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;padding:15px 15px;font-size:18px;line-height:20px;height:20px}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;margin-right:15px;padding:9px 10px;margin-top:8px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:none}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;box-shadow:none}.navbar-nav .open .dropdown-menu>li>a,.navbar-nav .open .dropdown-menu .dropdown-header{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:hover,.navbar-nav .open .dropdown-menu>li>a:focus{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}.navbar-nav.navbar-right:last-child{margin-right:-15px}}@media (min-width:768px){.navbar-left{float:left !important}.navbar-right{float:right !important}}.navbar-form{margin-left:-15px;margin-right:-15px;padding:10px 15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);margin-top:8px;margin-bottom:8px}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .radio,.navbar-form .checkbox{display:inline-block;margin-top:0;margin-bottom:0;padding-left:0;vertical-align:middle}.navbar-form .radio input[type="radio"],.navbar-form .checkbox input[type="checkbox"]{float:none;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}}@media (min-width:768px){.navbar-form{width:auto;border:0;margin-left:0;margin-right:0;padding-top:0;padding-bottom:0;-webkit-box-shadow:none;box-shadow:none}.navbar-form.navbar-right:last-child{margin-right:-15px}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-right-radius:0;border-top-left-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-left:15px;margin-right:15px}.navbar-text.navbar-right:last-child{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:hover,.navbar-default .navbar-brand:focus{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:hover,.navbar-default .navbar-nav>.disabled>a:focus{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:hover,.navbar-default .navbar-toggle:focus{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{background-color:#e7e7e7;color:#555}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#999}.navbar-inverse .navbar-brand:hover,.navbar-inverse .navbar-brand:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#999}.navbar-inverse .navbar-nav>li>a{color:#999}.navbar-inverse .navbar-nav>li>a:hover,.navbar-inverse .navbar-nav>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:hover,.navbar-inverse .navbar-nav>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:hover,.navbar-inverse .navbar-nav>.disabled>a:focus{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:hover,.navbar-inverse .navbar-toggle:focus{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:hover,.navbar-inverse .navbar-nav>.open>a:focus{background-color:#080808;color:#fff}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#999}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#999}.navbar-inverse .navbar-link:hover{color:#fff}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{content:"/\00a0";padding:0 5px;color:#ccc}.breadcrumb>.active{color:#999}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;line-height:1.428571429;text-decoration:none;color:#428bca;background-color:#fff;border:1px solid #ddd;margin-left:-1px}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-bottom-left-radius:4px;border-top-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-bottom-right-radius:4px;border-top-right-radius:4px}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{color:#2a6496;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>span,.pagination>.active>a:hover,.pagination>.active>span:hover,.pagination>.active>a:focus,.pagination>.active>span:focus{z-index:2;color:#fff;background-color:#428bca;border-color:#428bca;cursor:default}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#999;background-color:#fff;border-color:#ddd;cursor:not-allowed}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-bottom-left-radius:6px;border-top-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-bottom-right-radius:6px;border-top-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-bottom-left-radius:3px;border-top-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-bottom-right-radius:3px;border-top-right-radius:3px}.pager{padding-left:0;margin:20px 0;list-style:none;text-align:center}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#999;background-color:#fff;cursor:not-allowed}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:bold;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}.label[href]:hover,.label[href]:focus{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#999}.label-default[href]:hover,.label-default[href]:focus{background-color:#808080}.label-primary{background-color:#428bca}.label-primary[href]:hover,.label-primary[href]:focus{background-color:#3071a9}.label-success{background-color:#5cb85c}.label-success[href]:hover,.label-success[href]:focus{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:hover,.label-info[href]:focus{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:hover,.label-warning[href]:focus{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:hover,.label-danger[href]:focus{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:bold;color:#fff;line-height:1;vertical-align:baseline;white-space:nowrap;text-align:center;background-color:#999;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-xs .badge{top:0;padding:1px 5px}a.badge:hover,a.badge:focus{color:#fff;text-decoration:none;cursor:pointer}a.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#428bca;background-color:#fff}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron h1,.jumbotron .h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.container .jumbotron{border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron{padding-left:60px;padding-right:60px}.jumbotron h1,.jumbotron .h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.428571429;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.thumbnail>img,.thumbnail a>img{display:block;max-width:100%;height:auto;margin-left:auto;margin-right:auto}a.thumbnail:hover,a.thumbnail:focus,a.thumbnail.active{border-color:#428bca}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:bold}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable{padding-right:35px}.alert-dismissable .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{background-color:#dff0d8;border-color:#d6e9c6;color:#3c763d}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{background-color:#d9edf7;border-color:#bce8f1;color:#31708f}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{background-color:#fcf8e3;border-color:#faebcc;color:#8a6d3b}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{background-color:#f2dede;border-color:#ebccd1;color:#a94442}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{overflow:hidden;height:20px;margin-bottom:20px;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1)}.progress-bar{float:left;width:0%;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#428bca;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-transition:width .6s ease;transition:width .6s ease}.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-size:40px 40px}.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.media,.media-body{overflow:hidden;zoom:1}.media,.media .media{margin-top:15px}.media:first-child{margin-top:0}.media-object{display:block}.media-heading{margin:0 0 5px}.media>.pull-left{margin-right:10px}.media>.pull-right{margin-left:10px}.media-list{padding-left:0;list-style:none}.list-group{margin-bottom:20px;padding-left:0}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-right-radius:4px;border-top-left-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}a.list-group-item{color:#555}a.list-group-item .list-group-item-heading{color:#333}a.list-group-item:hover,a.list-group-item:focus{text-decoration:none;background-color:#f5f5f5}a.list-group-item.active,a.list-group-item.active:hover,a.list-group-item.active:focus{z-index:2;color:#fff;background-color:#428bca;border-color:#428bca}a.list-group-item.active .list-group-item-heading,a.list-group-item.active:hover .list-group-item-heading,a.list-group-item.active:focus .list-group-item-heading{color:inherit}a.list-group-item.active .list-group-item-text,a.list-group-item.active:hover .list-group-item-text,a.list-group-item.active:focus .list-group-item-text{color:#e1edf7}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:hover,a.list-group-item-success:focus{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:hover,a.list-group-item-success.active:focus{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:hover,a.list-group-item-info:focus{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:hover,a.list-group-item-info.active:focus{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:hover,a.list-group-item-warning:focus{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:hover,a.list-group-item-warning.active:focus{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:hover,a.list-group-item-danger:focus{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:hover,a.list-group-item-danger.active:focus{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,0.05);box-shadow:0 1px 1px rgba(0,0,0,0.05)}.panel-body{padding:15px}.panel>.list-group{margin-bottom:0}.panel>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group .list-group-item:first-child{border-top:0}.panel>.list-group .list-group-item:last-child{border-bottom:0}.panel>.list-group:first-child .list-group-item:first-child{border-top-right-radius:3px;border-top-left-radius:3px}.panel>.list-group:last-child .list-group-item:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child th,.panel>.table>tbody:first-child>tr:first-child td{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th,.panel>.table-bordered>tfoot>tr:first-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:first-child>th,.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>tfoot>tr:first-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:first-child>td{border-top:0}.panel>.table-bordered>thead>tr:last-child>th,.panel>.table-responsive>.table-bordered>thead>tr:last-child>th,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th,.panel>.table-bordered>thead>tr:last-child>td,.panel>.table-responsive>.table-bordered>thead>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}.panel>.table-responsive{border:0;margin-bottom:0}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-right-radius:3px;border-top-left-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px;overflow:hidden}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse .panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse .panel-body{border-top-color:#ddd}.panel-default>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#428bca}.panel-primary>.panel-heading{color:#fff;background-color:#428bca;border-color:#428bca}.panel-primary>.panel-heading+.panel-collapse .panel-body{border-top-color:#428bca}.panel-primary>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#428bca}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse .panel-body{border-top-color:#d6e9c6}.panel-success>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse .panel-body{border-top-color:#bce8f1}.panel-info>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse .panel-body{border-top-color:#faebcc}.panel-warning>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse .panel-body{border-top-color:#ebccd1}.panel-danger>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#ebccd1}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,0.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:bold;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;opacity:.5;filter:alpha(opacity=50)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.modal-open{overflow:hidden}.modal{display:none;overflow:auto;overflow-y:scroll;position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transform:translate(0, -25%);-ms-transform:translate(0, -25%);transform:translate(0, -25%);-webkit-transition:-webkit-transform 0.3s ease-out;-moz-transition:-moz-transform 0.3s ease-out;-o-transition:-o-transform 0.3s ease-out;transition:transform 0.3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0, 0);-ms-transform:translate(0, 0);transform:translate(0, 0)}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,0.2);border-radius:6px;-webkit-box-shadow:0 3px 9px rgba(0,0,0,0.5);box-shadow:0 3px 9px rgba(0,0,0,0.5);background-clip:padding-box;outline:none}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0;filter:alpha(opacity=0)}.modal-backdrop.in{opacity:.5;filter:alpha(opacity=50)}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5;min-height:16.428571429px}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.428571429}.modal-body{position:relative;padding:20px}.modal-footer{margin-top:15px;padding:19px 20px 20px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-left:5px;margin-bottom:0}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,0.5);box-shadow:0 5px 15px rgba(0,0,0,0.5)}.modal-sm{width:300px}.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1030;display:block;visibility:visible;font-size:12px;line-height:1.4;opacity:0;filter:alpha(opacity=0)}.tooltip.in{opacity:.9;filter:alpha(opacity=90)}.tooltip.top{margin-top:-3px;padding:5px 0}.tooltip.right{margin-left:3px;padding:0 5px}.tooltip.bottom{margin-top:3px;padding:5px 0}.tooltip.left{margin-left:-3px;padding:0 5px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{bottom:0;left:5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;right:5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;left:5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;right:5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1010;display:none;max-width:276px;padding:1px;text-align:left;background-color:#fff;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);white-space:normal}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{margin:0;padding:8px 14px;font-size:14px;font-weight:normal;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover .arrow,.popover .arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover .arrow{border-width:11px}.popover .arrow:after{border-width:10px;content:""}.popover.top .arrow{left:50%;margin-left:-11px;border-bottom-width:0;border-top-color:#999;border-top-color:rgba(0,0,0,0.25);bottom:-11px}.popover.top .arrow:after{content:" ";bottom:1px;margin-left:-10px;border-bottom-width:0;border-top-color:#fff}.popover.right .arrow{top:50%;left:-11px;margin-top:-11px;border-left-width:0;border-right-color:#999;border-right-color:rgba(0,0,0,0.25)}.popover.right .arrow:after{content:" ";left:1px;bottom:-10px;border-left-width:0;border-right-color:#fff}.popover.bottom .arrow{left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,0.25);top:-11px}.popover.bottom .arrow:after{content:" ";top:1px;margin-left:-10px;border-top-width:0;border-bottom-color:#fff}.popover.left .arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,0.25)}.popover.left .arrow:after{content:" ";right:1px;border-right-width:0;border-left-color:#fff;bottom:-10px}.carousel{position:relative}.carousel-inner{position:relative;overflow:hidden;width:100%}.carousel-inner>.item{display:none;position:relative;-webkit-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;max-width:100%;height:auto;line-height:1}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;left:0;bottom:0;width:15%;opacity:.5;filter:alpha(opacity=50);font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,0.6)}.carousel-control.left{background-image:-webkit-linear-gradient(left, color-stop(rgba(0,0,0,0.5) 0), color-stop(rgba(0,0,0,0.0001) 100%));background-image:linear-gradient(to right, rgba(0,0,0,0.5) 0, rgba(0,0,0,0.0001) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1)}.carousel-control.right{left:auto;right:0;background-image:-webkit-linear-gradient(left, color-stop(rgba(0,0,0,0.0001) 0), color-stop(rgba(0,0,0,0.5) 100%));background-image:linear-gradient(to right, rgba(0,0,0,0.0001) 0, rgba(0,0,0,0.5) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1)}.carousel-control:hover,.carousel-control:focus{outline:none;color:#fff;text-decoration:none;opacity:.9;filter:alpha(opacity=90)}.carousel-control .icon-prev,.carousel-control .icon-next,.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right{position:absolute;top:50%;z-index:5;display:inline-block}.carousel-control .icon-prev,.carousel-control .glyphicon-chevron-left{left:50%}.carousel-control .icon-next,.carousel-control .glyphicon-chevron-right{right:50%}.carousel-control .icon-prev,.carousel-control .icon-next{width:20px;height:20px;margin-top:-10px;margin-left:-10px;font-family:serif}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;margin-left:-30%;padding-left:0;list-style:none;text-align:center}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;border:1px solid #fff;border-radius:10px;cursor:pointer;background-color:#000 \9;background-color:rgba(0,0,0,0)}.carousel-indicators .active{margin:0;width:12px;height:12px;background-color:#fff}.carousel-caption{position:absolute;left:15%;right:15%;bottom:20px;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,0.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicons-chevron-left,.carousel-control .glyphicons-chevron-right,.carousel-control .icon-prev,.carousel-control .icon-next{width:30px;height:30px;margin-top:-15px;margin-left:-15px;font-size:30px}.carousel-caption{left:20%;right:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.clearfix:before,.clearfix:after,.container:before,.container:after,.container-fluid:before,.container-fluid:after,.row:before,.row:after,.form-horizontal .form-group:before,.form-horizontal .form-group:after,.btn-toolbar:before,.btn-toolbar:after,.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after,.nav:before,.nav:after,.navbar:before,.navbar:after,.navbar-header:before,.navbar-header:after,.navbar-collapse:before,.navbar-collapse:after,.pager:before,.pager:after,.panel-body:before,.panel-body:after,.modal-footer:before,.modal-footer:after{content:" ";display:table}.clearfix:after,.container:after,.container-fluid:after,.row:after,.form-horizontal .form-group:after,.btn-toolbar:after,.btn-group-vertical>.btn-group:after,.nav:after,.navbar:after,.navbar-header:after,.navbar-collapse:after,.pager:after,.panel-body:after,.modal-footer:after{clear:both}.center-block{display:block;margin-left:auto;margin-right:auto}.pull-right{float:right !important}.pull-left{float:left !important}.hide{display:none !important}.show{display:block !important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none !important;visibility:hidden !important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-xs,tr.visible-xs,th.visible-xs,td.visible-xs{display:none !important}@media (max-width:767px){.visible-xs{display:block !important}table.visible-xs{display:table}tr.visible-xs{display:table-row !important}th.visible-xs,td.visible-xs{display:table-cell !important}}.visible-sm,tr.visible-sm,th.visible-sm,td.visible-sm{display:none !important}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block !important}table.visible-sm{display:table}tr.visible-sm{display:table-row !important}th.visible-sm,td.visible-sm{display:table-cell !important}}.visible-md,tr.visible-md,th.visible-md,td.visible-md{display:none !important}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block !important}table.visible-md{display:table}tr.visible-md{display:table-row !important}th.visible-md,td.visible-md{display:table-cell !important}}.visible-lg,tr.visible-lg,th.visible-lg,td.visible-lg{display:none !important}@media (min-width:1200px){.visible-lg{display:block !important}table.visible-lg{display:table}tr.visible-lg{display:table-row !important}th.visible-lg,td.visible-lg{display:table-cell !important}}@media (max-width:767px){.hidden-xs,tr.hidden-xs,th.hidden-xs,td.hidden-xs{display:none !important}}@media (min-width:768px) and (max-width:991px){.hidden-sm,tr.hidden-sm,th.hidden-sm,td.hidden-sm{display:none !important}}@media (min-width:992px) and (max-width:1199px){.hidden-md,tr.hidden-md,th.hidden-md,td.hidden-md{display:none !important}}@media (min-width:1200px){.hidden-lg,tr.hidden-lg,th.hidden-lg,td.hidden-lg{display:none !important}}.visible-print,tr.visible-print,th.visible-print,td.visible-print{display:none !important}@media print{.visible-print{display:block !important}table.visible-print{display:table}tr.visible-print{display:table-row !important}th.visible-print,td.visible-print{display:table-cell !important}}@media print{.hidden-print,tr.hidden-print,th.hidden-print,td.hidden-print{display:none !important}} -\ No newline at end of file diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/glyphicons-halflings-regular.eot b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/glyphicons-halflings-regular.eot Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/glyphicons-halflings-regular.svg b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/glyphicons-halflings-regular.svg @@ -1,229 +0,0 @@ -<?xml version="1.0" standalone="no"?> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" > -<svg xmlns="http://www.w3.org/2000/svg"> -<metadata></metadata> -<defs> -<font id="glyphicons_halflingsregular" horiz-adv-x="1200" > -<font-face units-per-em="1200" ascent="960" descent="-240" /> -<missing-glyph horiz-adv-x="500" /> -<glyph /> -<glyph /> -<glyph unicode="
" /> -<glyph unicode=" " /> -<glyph unicode="*" d="M100 500v200h259l-183 183l141 141l183 -183v259h200v-259l183 183l141 -141l-183 -183h259v-200h-259l183 -183l-141 -141l-183 183v-259h-200v259l-183 -183l-141 141l183 183h-259z" /> -<glyph unicode="+" d="M0 400v300h400v400h300v-400h400v-300h-400v-400h-300v400h-400z" /> -<glyph unicode=" " /> -<glyph unicode=" " horiz-adv-x="652" /> -<glyph unicode=" " horiz-adv-x="1304" /> -<glyph unicode=" " horiz-adv-x="652" /> -<glyph unicode=" " horiz-adv-x="1304" /> -<glyph unicode=" " horiz-adv-x="434" /> -<glyph unicode=" " horiz-adv-x="326" /> -<glyph unicode=" " horiz-adv-x="217" /> -<glyph unicode=" " horiz-adv-x="217" /> -<glyph unicode=" " horiz-adv-x="163" /> -<glyph unicode=" " horiz-adv-x="260" /> -<glyph unicode=" " horiz-adv-x="72" /> -<glyph unicode=" " horiz-adv-x="260" /> -<glyph unicode=" " horiz-adv-x="326" /> -<glyph unicode="€" d="M100 500l100 100h113q0 47 5 100h-218l100 100h135q37 167 112 257q117 141 297 141q242 0 354 -189q60 -103 66 -209h-181q0 55 -25.5 99t-63.5 68t-75 36.5t-67 12.5q-24 0 -52.5 -10t-62.5 -32t-65.5 -67t-50.5 -107h379l-100 -100h-300q-6 -46 -6 -100h406l-100 -100 h-300q9 -74 33 -132t52.5 -91t62 -54.5t59 -29t46.5 -7.5q29 0 66 13t75 37t63.5 67.5t25.5 96.5h174q-31 -172 -128 -278q-107 -117 -274 -117q-205 0 -324 158q-36 46 -69 131.5t-45 205.5h-217z" /> -<glyph unicode="−" d="M200 400h900v300h-900v-300z" /> -<glyph unicode="☁" d="M-14 494q0 -80 56.5 -137t135.5 -57h750q120 0 205 86t85 208q0 120 -85 206.5t-205 86.5q-46 0 -90 -14q-44 97 -134.5 156.5t-200.5 59.5q-152 0 -260 -107.5t-108 -260.5q0 -25 2 -37q-66 -14 -108.5 -67.5t-42.5 -122.5z" /> -<glyph unicode="✉" d="M0 100l400 400l200 -200l200 200l400 -400h-1200zM0 300v600l300 -300zM0 1100l600 -603l600 603h-1200zM900 600l300 300v-600z" /> -<glyph unicode="✏" d="M-13 -13l333 112l-223 223zM187 403l214 -214l614 614l-214 214zM887 1103l214 -214l99 92q13 13 13 32.5t-13 33.5l-153 153q-15 13 -33 13t-33 -13z" /> -<glyph unicode="" horiz-adv-x="500" d="M0 0z" /> -<glyph unicode="" d="M0 1200h1200l-500 -550v-550h300v-100h-800v100h300v550z" /> -<glyph unicode="" d="M14 84q18 -55 86 -75.5t147 5.5q65 21 109 69t44 90v606l600 155v-521q-64 16 -138 -7q-79 -26 -122.5 -83t-25.5 -111q17 -55 85.5 -75.5t147.5 4.5q70 23 111.5 63.5t41.5 95.5v881q0 10 -7 15.5t-17 2.5l-752 -193q-10 -3 -17 -12.5t-7 -19.5v-689q-64 17 -138 -7 q-79 -25 -122.5 -82t-25.5 -112z" /> -<glyph unicode="" d="M23 693q0 200 142 342t342 142t342 -142t142 -342q0 -142 -78 -261l300 -300q7 -8 7 -18t-7 -18l-109 -109q-8 -7 -18 -7t-18 7l-300 300q-119 -78 -261 -78q-200 0 -342 142t-142 342zM176 693q0 -136 97 -233t234 -97t233.5 96.5t96.5 233.5t-96.5 233.5t-233.5 96.5 t-234 -97t-97 -233z" /> -<glyph unicode="" d="M100 784q0 64 28 123t73 100.5t104.5 64t119 20.5t120 -38.5t104.5 -104.5q48 69 109.5 105t121.5 38t118.5 -20.5t102.5 -64t71 -100.5t27 -123q0 -57 -33.5 -117.5t-94 -124.5t-126.5 -127.5t-150 -152.5t-146 -174q-62 85 -145.5 174t-149.5 152.5t-126.5 127.5 t-94 124.5t-33.5 117.5z" /> -<glyph unicode="" d="M-72 800h479l146 400h2l146 -400h472l-382 -278l145 -449l-384 275l-382 -275l146 447zM168 71l2 1z" /> -<glyph unicode="" d="M-72 800h479l146 400h2l146 -400h472l-382 -278l145 -449l-384 275l-382 -275l146 447zM168 71l2 1zM237 700l196 -142l-73 -226l192 140l195 -141l-74 229l193 140h-235l-77 211l-78 -211h-239z" /> -<glyph unicode="" d="M0 0v143l400 257v100q-37 0 -68.5 74.5t-31.5 125.5v200q0 124 88 212t212 88t212 -88t88 -212v-200q0 -51 -31.5 -125.5t-68.5 -74.5v-100l400 -257v-143h-1200z" /> -<glyph unicode="" d="M0 0v1100h1200v-1100h-1200zM100 100h100v100h-100v-100zM100 300h100v100h-100v-100zM100 500h100v100h-100v-100zM100 700h100v100h-100v-100zM100 900h100v100h-100v-100zM300 100h600v400h-600v-400zM300 600h600v400h-600v-400zM1000 100h100v100h-100v-100z M1000 300h100v100h-100v-100zM1000 500h100v100h-100v-100zM1000 700h100v100h-100v-100zM1000 900h100v100h-100v-100z" /> -<glyph unicode="" d="M0 50v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5zM0 650v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400 q-21 0 -35.5 14.5t-14.5 35.5zM600 50v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5zM600 650v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-400 q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5z" /> -<glyph unicode="" d="M0 50v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM0 450v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200 q-21 0 -35.5 14.5t-14.5 35.5zM0 850v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM400 50v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5 t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM400 450v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM400 850v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5 v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM800 50v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM800 450v200q0 21 14.5 35.5t35.5 14.5h200 q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM800 850v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5z" /> -<glyph unicode="" d="M0 50v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM0 450q0 -21 14.5 -35.5t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5v200q0 21 -14.5 35.5t-35.5 14.5h-200q-21 0 -35.5 -14.5 t-14.5 -35.5v-200zM0 850v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM400 50v200q0 21 14.5 35.5t35.5 14.5h700q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5 t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5zM400 450v200q0 21 14.5 35.5t35.5 14.5h700q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5zM400 850v200q0 21 14.5 35.5t35.5 14.5h700q21 0 35.5 -14.5t14.5 -35.5 v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5z" /> -<glyph unicode="" d="M29 454l419 -420l818 820l-212 212l-607 -607l-206 207z" /> -<glyph unicode="" d="M106 318l282 282l-282 282l212 212l282 -282l282 282l212 -212l-282 -282l282 -282l-212 -212l-282 282l-282 -282z" /> -<glyph unicode="" d="M23 693q0 200 142 342t342 142t342 -142t142 -342q0 -142 -78 -261l300 -300q7 -8 7 -18t-7 -18l-109 -109q-8 -7 -18 -7t-18 7l-300 300q-119 -78 -261 -78q-200 0 -342 142t-142 342zM176 693q0 -136 97 -233t234 -97t233.5 96.5t96.5 233.5t-96.5 233.5t-233.5 96.5 t-234 -97t-97 -233zM300 600v200h100v100h200v-100h100v-200h-100v-100h-200v100h-100z" /> -<glyph unicode="" d="M23 694q0 200 142 342t342 142t342 -142t142 -342q0 -141 -78 -262l300 -299q7 -7 7 -18t-7 -18l-109 -109q-8 -8 -18 -8t-18 8l-300 299q-120 -77 -261 -77q-200 0 -342 142t-142 342zM176 694q0 -136 97 -233t234 -97t233.5 97t96.5 233t-96.5 233t-233.5 97t-234 -97 t-97 -233zM300 601h400v200h-400v-200z" /> -<glyph unicode="" d="M23 600q0 183 105 331t272 210v-166q-103 -55 -165 -155t-62 -220q0 -177 125 -302t302 -125t302 125t125 302q0 120 -62 220t-165 155v166q167 -62 272 -210t105 -331q0 -118 -45.5 -224.5t-123 -184t-184 -123t-224.5 -45.5t-224.5 45.5t-184 123t-123 184t-45.5 224.5 zM500 750q0 -21 14.5 -35.5t35.5 -14.5h100q21 0 35.5 14.5t14.5 35.5v400q0 21 -14.5 35.5t-35.5 14.5h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-400z" /> -<glyph unicode="" d="M100 1h200v300h-200v-300zM400 1v500h200v-500h-200zM700 1v800h200v-800h-200zM1000 1v1200h200v-1200h-200z" /> -<glyph unicode="" d="M26 601q0 -33 6 -74l151 -38l2 -6q14 -49 38 -93l3 -5l-80 -134q45 -59 105 -105l133 81l5 -3q45 -26 94 -39l5 -2l38 -151q40 -5 74 -5q27 0 74 5l38 151l6 2q46 13 93 39l5 3l134 -81q56 44 104 105l-80 134l3 5q24 44 39 93l1 6l152 38q5 40 5 74q0 28 -5 73l-152 38 l-1 6q-16 51 -39 93l-3 5l80 134q-44 58 -104 105l-134 -81l-5 3q-45 25 -93 39l-6 1l-38 152q-40 5 -74 5q-27 0 -74 -5l-38 -152l-5 -1q-50 -14 -94 -39l-5 -3l-133 81q-59 -47 -105 -105l80 -134l-3 -5q-25 -47 -38 -93l-2 -6l-151 -38q-6 -48 -6 -73zM385 601 q0 88 63 151t152 63t152 -63t63 -151q0 -89 -63 -152t-152 -63t-152 63t-63 152z" /> -<glyph unicode="" d="M100 1025v50q0 10 7.5 17.5t17.5 7.5h275v100q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5v-100h275q10 0 17.5 -7.5t7.5 -17.5v-50q0 -11 -7 -18t-18 -7h-1050q-11 0 -18 7t-7 18zM200 100v800h900v-800q0 -41 -29.5 -71t-70.5 -30h-700q-41 0 -70.5 30 t-29.5 71zM300 100h100v700h-100v-700zM500 100h100v700h-100v-700zM500 1100h300v100h-300v-100zM700 100h100v700h-100v-700zM900 100h100v700h-100v-700z" /> -<glyph unicode="" d="M1 601l656 644l644 -644h-200v-600h-300v400h-300v-400h-300v600h-200z" /> -<glyph unicode="" d="M100 25v1150q0 11 7 18t18 7h475v-500h400v-675q0 -11 -7 -18t-18 -7h-850q-11 0 -18 7t-7 18zM700 800v300l300 -300h-300z" /> -<glyph unicode="" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM500 500v400h100 v-300h200v-100h-300z" /> -<glyph unicode="" d="M-100 0l431 1200h209l-21 -300h162l-20 300h208l431 -1200h-538l-41 400h-242l-40 -400h-539zM488 500h224l-27 300h-170z" /> -<glyph unicode="" d="M0 0v400h490l-290 300h200v500h300v-500h200l-290 -300h490v-400h-1100zM813 200h175v100h-175v-100z" /> -<glyph unicode="" d="M1 600q0 122 47.5 233t127.5 191t191 127.5t233 47.5t233 -47.5t191 -127.5t127.5 -191t47.5 -233t-47.5 -233t-127.5 -191t-191 -127.5t-233 -47.5t-233 47.5t-191 127.5t-127.5 191t-47.5 233zM188 600q0 -170 121 -291t291 -121t291 121t121 291t-121 291t-291 121 t-291 -121t-121 -291zM350 600h150v300h200v-300h150l-250 -300z" /> -<glyph unicode="" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM350 600l250 300 l250 -300h-150v-300h-200v300h-150z" /> -<glyph unicode="" d="M0 25v475l200 700h800q199 -700 200 -700v-475q0 -11 -7 -18t-18 -7h-1150q-11 0 -18 7t-7 18zM200 500h200l50 -200h300l50 200h200l-97 500h-606z" /> -<glyph unicode="" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -172 121.5 -293t292.5 -121t292.5 121t121.5 293q0 171 -121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM500 397v401 l297 -200z" /> -<glyph unicode="" d="M23 600q0 -118 45.5 -224.5t123 -184t184 -123t224.5 -45.5t224.5 45.5t184 123t123 184t45.5 224.5h-150q0 -177 -125 -302t-302 -125t-302 125t-125 302t125 302t302 125q136 0 246 -81l-146 -146h400v400l-145 -145q-157 122 -355 122q-118 0 -224.5 -45.5t-184 -123 t-123 -184t-45.5 -224.5z" /> -<glyph unicode="" d="M23 600q0 118 45.5 224.5t123 184t184 123t224.5 45.5q198 0 355 -122l145 145v-400h-400l147 147q-112 80 -247 80q-177 0 -302 -125t-125 -302h-150zM100 0v400h400l-147 -147q112 -80 247 -80q177 0 302 125t125 302h150q0 -118 -45.5 -224.5t-123 -184t-184 -123 t-224.5 -45.5q-198 0 -355 122z" /> -<glyph unicode="" d="M100 0h1100v1200h-1100v-1200zM200 100v900h900v-900h-900zM300 200v100h100v-100h-100zM300 400v100h100v-100h-100zM300 600v100h100v-100h-100zM300 800v100h100v-100h-100zM500 200h500v100h-500v-100zM500 400v100h500v-100h-500zM500 600v100h500v-100h-500z M500 800v100h500v-100h-500z" /> -<glyph unicode="" d="M0 100v600q0 41 29.5 70.5t70.5 29.5h100v200q0 82 59 141t141 59h300q82 0 141 -59t59 -141v-200h100q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-900q-41 0 -70.5 29.5t-29.5 70.5zM400 800h300v150q0 21 -14.5 35.5t-35.5 14.5h-200 q-21 0 -35.5 -14.5t-14.5 -35.5v-150z" /> -<glyph unicode="" d="M100 0v1100h100v-1100h-100zM300 400q60 60 127.5 84t127.5 17.5t122 -23t119 -30t110 -11t103 42t91 120.5v500q-40 -81 -101.5 -115.5t-127.5 -29.5t-138 25t-139.5 40t-125.5 25t-103 -29.5t-65 -115.5v-500z" /> -<glyph unicode="" d="M0 275q0 -11 7 -18t18 -7h50q11 0 18 7t7 18v300q0 127 70.5 231.5t184.5 161.5t245 57t245 -57t184.5 -161.5t70.5 -231.5v-300q0 -11 7 -18t18 -7h50q11 0 18 7t7 18v300q0 116 -49.5 227t-131 192.5t-192.5 131t-227 49.5t-227 -49.5t-192.5 -131t-131 -192.5 t-49.5 -227v-300zM200 20v460q0 8 6 14t14 6h160q8 0 14 -6t6 -14v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14zM800 20v460q0 8 6 14t14 6h160q8 0 14 -6t6 -14v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14z" /> -<glyph unicode="" d="M0 400h300l300 -200v800l-300 -200h-300v-400zM688 459l141 141l-141 141l71 71l141 -141l141 141l71 -71l-141 -141l141 -141l-71 -71l-141 141l-141 -141z" /> -<glyph unicode="" d="M0 400h300l300 -200v800l-300 -200h-300v-400zM700 857l69 53q111 -135 111 -310q0 -169 -106 -302l-67 54q86 110 86 248q0 146 -93 257z" /> -<glyph unicode="" d="M0 401v400h300l300 200v-800l-300 200h-300zM702 858l69 53q111 -135 111 -310q0 -170 -106 -303l-67 55q86 110 86 248q0 145 -93 257zM889 951l7 -8q123 -151 123 -344q0 -189 -119 -339l-7 -8l81 -66l6 8q142 178 142 405q0 230 -144 408l-6 8z" /> -<glyph unicode="" d="M0 0h500v500h-200v100h-100v-100h-200v-500zM0 600h100v100h400v100h100v100h-100v300h-500v-600zM100 100v300h300v-300h-300zM100 800v300h300v-300h-300zM200 200v100h100v-100h-100zM200 900h100v100h-100v-100zM500 500v100h300v-300h200v-100h-100v-100h-200v100 h-100v100h100v200h-200zM600 0v100h100v-100h-100zM600 1000h100v-300h200v-300h300v200h-200v100h200v500h-600v-200zM800 800v300h300v-300h-300zM900 0v100h300v-100h-300zM900 900v100h100v-100h-100zM1100 200v100h100v-100h-100z" /> -<glyph unicode="" d="M0 200h100v1000h-100v-1000zM100 0v100h300v-100h-300zM200 200v1000h100v-1000h-100zM500 0v91h100v-91h-100zM500 200v1000h200v-1000h-200zM700 0v91h100v-91h-100zM800 200v1000h100v-1000h-100zM900 0v91h200v-91h-200zM1000 200v1000h200v-1000h-200z" /> -<glyph unicode="" d="M1 700v475q0 10 7.5 17.5t17.5 7.5h474l700 -700l-500 -500zM148 953q0 -42 29 -71q30 -30 71.5 -30t71.5 30q29 29 29 71t-29 71q-30 30 -71.5 30t-71.5 -30q-29 -29 -29 -71z" /> -<glyph unicode="" d="M2 700v475q0 11 7 18t18 7h474l700 -700l-500 -500zM148 953q0 -42 30 -71q29 -30 71 -30t71 30q30 29 30 71t-30 71q-29 30 -71 30t-71 -30q-30 -29 -30 -71zM701 1200h100l700 -700l-500 -500l-50 50l450 450z" /> -<glyph unicode="" d="M100 0v1025l175 175h925v-1000l-100 -100v1000h-750l-100 -100h750v-1000h-900z" /> -<glyph unicode="" d="M200 0l450 444l450 -443v1150q0 20 -14.5 35t-35.5 15h-800q-21 0 -35.5 -15t-14.5 -35v-1151z" /> -<glyph unicode="" d="M0 100v700h200l100 -200h600l100 200h200v-700h-200v200h-800v-200h-200zM253 829l40 -124h592l62 124l-94 346q-2 11 -10 18t-18 7h-450q-10 0 -18 -7t-10 -18zM281 24l38 152q2 10 11.5 17t19.5 7h500q10 0 19.5 -7t11.5 -17l38 -152q2 -10 -3.5 -17t-15.5 -7h-600 q-10 0 -15.5 7t-3.5 17z" /> -<glyph unicode="" d="M0 200q0 -41 29.5 -70.5t70.5 -29.5h1000q41 0 70.5 29.5t29.5 70.5v600q0 41 -29.5 70.5t-70.5 29.5h-150q-4 8 -11.5 21.5t-33 48t-53 61t-69 48t-83.5 21.5h-200q-41 0 -82 -20.5t-70 -50t-52 -59t-34 -50.5l-12 -20h-150q-41 0 -70.5 -29.5t-29.5 -70.5v-600z M356 500q0 100 72 172t172 72t172 -72t72 -172t-72 -172t-172 -72t-172 72t-72 172zM494 500q0 -44 31 -75t75 -31t75 31t31 75t-31 75t-75 31t-75 -31t-31 -75zM900 700v100h100v-100h-100z" /> -<glyph unicode="" d="M53 0h365v66q-41 0 -72 11t-49 38t1 71l92 234h391l82 -222q16 -45 -5.5 -88.5t-74.5 -43.5v-66h417v66q-34 1 -74 43q-18 19 -33 42t-21 37l-6 13l-385 998h-93l-399 -1006q-24 -48 -52 -75q-12 -12 -33 -25t-36 -20l-15 -7v-66zM416 521l178 457l46 -140l116 -317h-340 z" /> -<glyph unicode="" d="M100 0v89q41 7 70.5 32.5t29.5 65.5v827q0 28 -1 39.5t-5.5 26t-15.5 21t-29 14t-49 14.5v70h471q120 0 213 -88t93 -228q0 -55 -11.5 -101.5t-28 -74t-33.5 -47.5t-28 -28l-12 -7q8 -3 21.5 -9t48 -31.5t60.5 -58t47.5 -91.5t21.5 -129q0 -84 -59 -156.5t-142 -111 t-162 -38.5h-500zM400 200h161q89 0 153 48.5t64 132.5q0 90 -62.5 154.5t-156.5 64.5h-159v-400zM400 700h139q76 0 130 61.5t54 138.5q0 82 -84 130.5t-239 48.5v-379z" /> -<glyph unicode="" d="M200 0v57q77 7 134.5 40.5t65.5 80.5l173 849q10 56 -10 74t-91 37q-6 1 -10.5 2.5t-9.5 2.5v57h425l2 -57q-33 -8 -62 -25.5t-46 -37t-29.5 -38t-17.5 -30.5l-5 -12l-128 -825q-10 -52 14 -82t95 -36v-57h-500z" /> -<glyph unicode="" d="M-75 200h75v800h-75l125 167l125 -167h-75v-800h75l-125 -167zM300 900v300h150h700h150v-300h-50q0 29 -8 48.5t-18.5 30t-33.5 15t-39.5 5.5t-50.5 1h-200v-850l100 -50v-100h-400v100l100 50v850h-200q-34 0 -50.5 -1t-40 -5.5t-33.5 -15t-18.5 -30t-8.5 -48.5h-49z " /> -<glyph unicode="" d="M33 51l167 125v-75h800v75l167 -125l-167 -125v75h-800v-75zM100 901v300h150h700h150v-300h-50q0 29 -8 48.5t-18 30t-33.5 15t-40 5.5t-50.5 1h-200v-650l100 -50v-100h-400v100l100 50v650h-200q-34 0 -50.5 -1t-39.5 -5.5t-33.5 -15t-18.5 -30t-8 -48.5h-50z" /> -<glyph unicode="" d="M0 50q0 -20 14.5 -35t35.5 -15h1100q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM0 350q0 -20 14.5 -35t35.5 -15h800q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-800q-21 0 -35.5 -14.5t-14.5 -35.5 v-100zM0 650q0 -20 14.5 -35t35.5 -15h1000q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-1000q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM0 950q0 -20 14.5 -35t35.5 -15h600q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-600q-21 0 -35.5 -14.5 t-14.5 -35.5v-100z" /> -<glyph unicode="" d="M0 50q0 -20 14.5 -35t35.5 -15h1100q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM0 650q0 -20 14.5 -35t35.5 -15h1100q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5 v-100zM200 350q0 -20 14.5 -35t35.5 -15h700q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-700q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM200 950q0 -20 14.5 -35t35.5 -15h700q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-700q-21 0 -35.5 -14.5 t-14.5 -35.5v-100z" /> -<glyph unicode="" d="M0 50v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15t-14.5 35zM100 650v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1000q-21 0 -35.5 15 t-14.5 35zM300 350v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800q-21 0 -35.5 15t-14.5 35zM500 950v100q0 21 14.5 35.5t35.5 14.5h600q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-600 q-21 0 -35.5 15t-14.5 35z" /> -<glyph unicode="" d="M0 50v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15t-14.5 35zM0 350v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15 t-14.5 35zM0 650v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15t-14.5 35zM0 950v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100 q-21 0 -35.5 15t-14.5 35z" /> -<glyph unicode="" d="M0 50v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15t-14.5 35zM0 350v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15 t-14.5 35zM0 650v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15t-14.5 35zM0 950v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15 t-14.5 35zM300 50v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800q-21 0 -35.5 15t-14.5 35zM300 350v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800 q-21 0 -35.5 15t-14.5 35zM300 650v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800q-21 0 -35.5 15t-14.5 35zM300 950v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15 h-800q-21 0 -35.5 15t-14.5 35z" /> -<glyph unicode="" d="M-101 500v100h201v75l166 -125l-166 -125v75h-201zM300 0h100v1100h-100v-1100zM500 50q0 -20 14.5 -35t35.5 -15h600q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-600q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM500 350q0 -20 14.5 -35t35.5 -15h300q20 0 35 15t15 35 v100q0 21 -15 35.5t-35 14.5h-300q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM500 650q0 -20 14.5 -35t35.5 -15h500q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM500 950q0 -20 14.5 -35t35.5 -15h100q20 0 35 15t15 35v100 q0 21 -15 35.5t-35 14.5h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-100z" /> -<glyph unicode="" d="M1 50q0 -20 14.5 -35t35.5 -15h600q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-600q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM1 350q0 -20 14.5 -35t35.5 -15h300q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-300q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM1 650 q0 -20 14.5 -35t35.5 -15h500q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM1 950q0 -20 14.5 -35t35.5 -15h100q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM801 0v1100h100v-1100 h-100zM934 550l167 -125v75h200v100h-200v75z" /> -<glyph unicode="" d="M0 275v650q0 31 22 53t53 22h750q31 0 53 -22t22 -53v-650q0 -31 -22 -53t-53 -22h-750q-31 0 -53 22t-22 53zM900 600l300 300v-600z" /> -<glyph unicode="" d="M0 44v1012q0 18 13 31t31 13h1112q19 0 31.5 -13t12.5 -31v-1012q0 -18 -12.5 -31t-31.5 -13h-1112q-18 0 -31 13t-13 31zM100 263l247 182l298 -131l-74 156l293 318l236 -288v500h-1000v-737zM208 750q0 56 39 95t95 39t95 -39t39 -95t-39 -95t-95 -39t-95 39t-39 95z " /> -<glyph unicode="" d="M148 745q0 124 60.5 231.5t165 172t226.5 64.5q123 0 227 -63t164.5 -169.5t60.5 -229.5t-73 -272q-73 -114 -166.5 -237t-150.5 -189l-57 -66q-10 9 -27 26t-66.5 70.5t-96 109t-104 135.5t-100.5 155q-63 139 -63 262zM342 772q0 -107 75.5 -182.5t181.5 -75.5 q107 0 182.5 75.5t75.5 182.5t-75.5 182t-182.5 75t-182 -75.5t-75 -181.5z" /> -<glyph unicode="" d="M1 600q0 122 47.5 233t127.5 191t191 127.5t233 47.5t233 -47.5t191 -127.5t127.5 -191t47.5 -233t-47.5 -233t-127.5 -191t-191 -127.5t-233 -47.5t-233 47.5t-191 127.5t-127.5 191t-47.5 233zM173 600q0 -177 125.5 -302t301.5 -125v854q-176 0 -301.5 -125 t-125.5 -302z" /> -<glyph unicode="" d="M117 406q0 94 34 186t88.5 172.5t112 159t115 177t87.5 194.5q21 -71 57.5 -142.5t76 -130.5t83 -118.5t82 -117t70 -116t50 -125.5t18.5 -136q0 -89 -39 -165.5t-102 -126.5t-140 -79.5t-156 -33.5q-114 6 -211.5 53t-161.5 138.5t-64 210.5zM243 414q14 -82 59.5 -136 t136.5 -80l16 98q-7 6 -18 17t-34 48t-33 77q-15 73 -14 143.5t10 122.5l9 51q-92 -110 -119.5 -185t-12.5 -156z" /> -<glyph unicode="" d="M0 400v300q0 165 117.5 282.5t282.5 117.5q366 -6 397 -14l-186 -186h-311q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v125l200 200v-225q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5 t-117.5 282.5zM436 341l161 50l412 412l-114 113l-405 -405zM995 1015l113 -113l113 113l-21 85l-92 28z" /> -<glyph unicode="" d="M0 400v300q0 165 117.5 282.5t282.5 117.5h261l2 -80q-133 -32 -218 -120h-145q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5l200 153v-53q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5 zM423 524q30 38 81.5 64t103 35.5t99 14t77.5 3.5l29 -1v-209l360 324l-359 318v-216q-7 0 -19 -1t-48 -8t-69.5 -18.5t-76.5 -37t-76.5 -59t-62 -88t-39.5 -121.5z" /> -<glyph unicode="" d="M0 400v300q0 165 117.5 282.5t282.5 117.5h300q60 0 127 -23l-178 -177h-349q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v69l200 200v-169q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5 t-117.5 282.5zM342 632l283 -284l566 567l-136 137l-430 -431l-147 147z" /> -<glyph unicode="" d="M0 603l300 296v-198h200v200h-200l300 300l295 -300h-195v-200h200v198l300 -296l-300 -300v198h-200v-200h195l-295 -300l-300 300h200v200h-200v-198z" /> -<glyph unicode="" d="M200 50v1000q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-437l500 487v-1100l-500 488v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5z" /> -<glyph unicode="" d="M0 50v1000q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-437l500 487v-487l500 487v-1100l-500 488v-488l-500 488v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5z" /> -<glyph unicode="" d="M136 550l564 550v-487l500 487v-1100l-500 488v-488z" /> -<glyph unicode="" d="M200 0l900 550l-900 550v-1100z" /> -<glyph unicode="" d="M200 150q0 -21 14.5 -35.5t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5v800q0 21 -14.5 35.5t-35.5 14.5h-200q-21 0 -35.5 -14.5t-14.5 -35.5v-800zM600 150q0 -21 14.5 -35.5t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5v800q0 21 -14.5 35.5t-35.5 14.5h-200 q-21 0 -35.5 -14.5t-14.5 -35.5v-800z" /> -<glyph unicode="" d="M200 150q0 -20 14.5 -35t35.5 -15h800q21 0 35.5 15t14.5 35v800q0 21 -14.5 35.5t-35.5 14.5h-800q-21 0 -35.5 -14.5t-14.5 -35.5v-800z" /> -<glyph unicode="" d="M0 0v1100l500 -487v487l564 -550l-564 -550v488z" /> -<glyph unicode="" d="M0 0v1100l500 -487v487l500 -487v437q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-1000q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v438l-500 -488v488z" /> -<glyph unicode="" d="M300 0v1100l500 -487v437q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-1000q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v438z" /> -<glyph unicode="" d="M100 250v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5zM100 500h1100l-550 564z" /> -<glyph unicode="" d="M185 599l592 -592l240 240l-353 353l353 353l-240 240z" /> -<glyph unicode="" d="M272 194l353 353l-353 353l241 240l572 -571l21 -22l-1 -1v-1l-592 -591z" /> -<glyph unicode="" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -300t-217.5 -218t-299.5 -80t-299.5 80t-217.5 218t-80 300zM300 500h200v-200h200v200h200v200h-200v200h-200v-200h-200v-200z" /> -<glyph unicode="" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -300t-217.5 -218t-299.5 -80t-299.5 80t-217.5 218t-80 300zM300 500h600v200h-600v-200z" /> -<glyph unicode="" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -300t-217.5 -218t-299.5 -80t-299.5 80t-217.5 218t-80 300zM246 459l213 -213l141 142l141 -142l213 213l-142 141l142 141l-213 212l-141 -141l-141 142l-212 -213l141 -141z" /> -<glyph unicode="" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM270 551l276 -277l411 411l-175 174l-236 -236l-102 102z" /> -<glyph unicode="" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -300t-217.5 -218t-299.5 -80t-299.5 80t-217.5 218t-80 300zM363 700h144q4 0 11.5 -1t11 -1t6.5 3t3 9t1 11t3.5 8.5t3.5 6t5.5 4t6.5 2.5t9 1.5t9 0.5h11.5h12.5q19 0 30 -10t11 -26 q0 -22 -4 -28t-27 -22q-5 -1 -12.5 -3t-27 -13.5t-34 -27t-26.5 -46t-11 -68.5h200q5 3 14 8t31.5 25.5t39.5 45.5t31 69t14 94q0 51 -17.5 89t-42 58t-58.5 32t-58.5 15t-51.5 3q-105 0 -172 -56t-67 -183zM500 300h200v100h-200v-100z" /> -<glyph unicode="" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -300t-217.5 -218t-299.5 -80t-299.5 80t-217.5 218t-80 300zM400 300h400v100h-100v300h-300v-100h100v-200h-100v-100zM500 800h200v100h-200v-100z" /> -<glyph unicode="" d="M0 500v200h194q15 60 36 104.5t55.5 86t88 69t126.5 40.5v200h200v-200q54 -20 113 -60t112.5 -105.5t71.5 -134.5h203v-200h-203q-25 -102 -116.5 -186t-180.5 -117v-197h-200v197q-140 27 -208 102.5t-98 200.5h-194zM290 500q24 -73 79.5 -127.5t130.5 -78.5v206h200 v-206q149 48 201 206h-201v200h200q-25 74 -76 127.5t-124 76.5v-204h-200v203q-75 -24 -130 -77.5t-79 -125.5h209v-200h-210z" /> -<glyph unicode="" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM356 465l135 135 l-135 135l109 109l135 -135l135 135l109 -109l-135 -135l135 -135l-109 -109l-135 135l-135 -135z" /> -<glyph unicode="" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM322 537l141 141 l87 -87l204 205l142 -142l-346 -345z" /> -<glyph unicode="" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -115 62 -215l568 567q-100 62 -216 62q-171 0 -292.5 -121.5t-121.5 -292.5zM391 245q97 -59 209 -59q171 0 292.5 121.5t121.5 292.5 q0 112 -59 209z" /> -<glyph unicode="" d="M0 547l600 453v-300h600v-300h-600v-301z" /> -<glyph unicode="" d="M0 400v300h600v300l600 -453l-600 -448v301h-600z" /> -<glyph unicode="" d="M204 600l450 600l444 -600h-298v-600h-300v600h-296z" /> -<glyph unicode="" d="M104 600h296v600h300v-600h298l-449 -600z" /> -<glyph unicode="" d="M0 200q6 132 41 238.5t103.5 193t184 138t271.5 59.5v271l600 -453l-600 -448v301q-95 -2 -183 -20t-170 -52t-147 -92.5t-100 -135.5z" /> -<glyph unicode="" d="M0 0v400l129 -129l294 294l142 -142l-294 -294l129 -129h-400zM635 777l142 -142l294 294l129 -129v400h-400l129 -129z" /> -<glyph unicode="" d="M34 176l295 295l-129 129h400v-400l-129 130l-295 -295zM600 600v400l129 -129l295 295l142 -141l-295 -295l129 -130h-400z" /> -<glyph unicode="" d="M23 600q0 118 45.5 224.5t123 184t184 123t224.5 45.5t224.5 -45.5t184 -123t123 -184t45.5 -224.5t-45.5 -224.5t-123 -184t-184 -123t-224.5 -45.5t-224.5 45.5t-184 123t-123 184t-45.5 224.5zM456 851l58 -302q4 -20 21.5 -34.5t37.5 -14.5h54q20 0 37.5 14.5 t21.5 34.5l58 302q4 20 -8 34.5t-33 14.5h-207q-20 0 -32 -14.5t-8 -34.5zM500 300h200v100h-200v-100z" /> -<glyph unicode="" d="M0 800h100v-200h400v300h200v-300h400v200h100v100h-111v6t-1 15t-3 18l-34 172q-11 39 -41.5 63t-69.5 24q-32 0 -61 -17l-239 -144q-22 -13 -40 -35q-19 24 -40 36l-238 144q-33 18 -62 18q-39 0 -69.5 -23t-40.5 -61l-35 -177q-2 -8 -3 -18t-1 -15v-6h-111v-100z M100 0h400v400h-400v-400zM200 900q-3 0 14 48t35 96l18 47l214 -191h-281zM700 0v400h400v-400h-400zM731 900l202 197q5 -12 12 -32.5t23 -64t25 -72t7 -28.5h-269z" /> -<glyph unicode="" d="M0 -22v143l216 193q-9 53 -13 83t-5.5 94t9 113t38.5 114t74 124q47 60 99.5 102.5t103 68t127.5 48t145.5 37.5t184.5 43.5t220 58.5q0 -189 -22 -343t-59 -258t-89 -181.5t-108.5 -120t-122 -68t-125.5 -30t-121.5 -1.5t-107.5 12.5t-87.5 17t-56.5 7.5l-99 -55z M238.5 300.5q19.5 -6.5 86.5 76.5q55 66 367 234q70 38 118.5 69.5t102 79t99 111.5t86.5 148q22 50 24 60t-6 19q-7 5 -17 5t-26.5 -14.5t-33.5 -39.5q-35 -51 -113.5 -108.5t-139.5 -89.5l-61 -32q-369 -197 -458 -401q-48 -111 -28.5 -117.5z" /> -<glyph unicode="" d="M111 408q0 -33 5 -63q9 -56 44 -119.5t105 -108.5q31 -21 64 -16t62 23.5t57 49.5t48 61.5t35 60.5q32 66 39 184.5t-13 157.5q79 -80 122 -164t26 -184q-5 -33 -20.5 -69.5t-37.5 -80.5q-10 -19 -14.5 -29t-12 -26t-9 -23.5t-3 -19t2.5 -15.5t11 -9.5t19.5 -5t30.5 2.5 t42 8q57 20 91 34t87.5 44.5t87 64t65.5 88.5t47 122q38 172 -44.5 341.5t-246.5 278.5q22 -44 43 -129q39 -159 -32 -154q-15 2 -33 9q-79 33 -120.5 100t-44 175.5t48.5 257.5q-13 -8 -34 -23.5t-72.5 -66.5t-88.5 -105.5t-60 -138t-8 -166.5q2 -12 8 -41.5t8 -43t6 -39.5 t3.5 -39.5t-1 -33.5t-6 -31.5t-13.5 -24t-21 -20.5t-31 -12q-38 -10 -67 13t-40.5 61.5t-15 81.5t10.5 75q-52 -46 -83.5 -101t-39 -107t-7.5 -85z" /> -<glyph unicode="" d="M-61 600l26 40q6 10 20 30t49 63.5t74.5 85.5t97 90t116.5 83.5t132.5 59t145.5 23.5t145.5 -23.5t132.5 -59t116.5 -83.5t97 -90t74.5 -85.5t49 -63.5t20 -30l26 -40l-26 -40q-6 -10 -20 -30t-49 -63.5t-74.5 -85.5t-97 -90t-116.5 -83.5t-132.5 -59t-145.5 -23.5 t-145.5 23.5t-132.5 59t-116.5 83.5t-97 90t-74.5 85.5t-49 63.5t-20 30zM120 600q7 -10 40.5 -58t56 -78.5t68 -77.5t87.5 -75t103 -49.5t125 -21.5t123.5 20t100.5 45.5t85.5 71.5t66.5 75.5t58 81.5t47 66q-1 1 -28.5 37.5t-42 55t-43.5 53t-57.5 63.5t-58.5 54 q49 -74 49 -163q0 -124 -88 -212t-212 -88t-212 88t-88 212q0 85 46 158q-102 -87 -226 -258zM377 656q49 -124 154 -191l105 105q-37 24 -75 72t-57 84l-20 36z" /> -<glyph unicode="" d="M-61 600l26 40q6 10 20 30t49 63.5t74.5 85.5t97 90t116.5 83.5t132.5 59t145.5 23.5q61 0 121 -17l37 142h148l-314 -1200h-148l37 143q-82 21 -165 71.5t-140 102t-109.5 112t-72 88.5t-29.5 43zM120 600q210 -282 393 -336l37 141q-107 18 -178.5 101.5t-71.5 193.5 q0 85 46 158q-102 -87 -226 -258zM377 656q49 -124 154 -191l47 47l23 87q-30 28 -59 69t-44 68l-14 26zM780 161l38 145q22 15 44.5 34t46 44t40.5 44t41 50.5t33.5 43.5t33 44t24.5 34q-97 127 -140 175l39 146q67 -54 131.5 -125.5t87.5 -103.5t36 -52l26 -40l-26 -40 q-7 -12 -25.5 -38t-63.5 -79.5t-95.5 -102.5t-124 -100t-146.5 -79z" /> -<glyph unicode="" d="M-97.5 34q13.5 -34 50.5 -34h1294q37 0 50.5 35.5t-7.5 67.5l-642 1056q-20 33 -48 36t-48 -29l-642 -1066q-21 -32 -7.5 -66zM155 200l445 723l445 -723h-345v100h-200v-100h-345zM500 600l100 -300l100 300v100h-200v-100z" /> -<glyph unicode="" d="M100 262v41q0 20 11 44.5t26 38.5l363 325v339q0 62 44 106t106 44t106 -44t44 -106v-339l363 -325q15 -14 26 -38.5t11 -44.5v-41q0 -20 -12 -26.5t-29 5.5l-359 249v-263q100 -91 100 -113v-64q0 -21 -13 -29t-32 1l-94 78h-222l-94 -78q-19 -9 -32 -1t-13 29v64 q0 22 100 113v263l-359 -249q-17 -12 -29 -5.5t-12 26.5z" /> -<glyph unicode="" d="M0 50q0 -20 14.5 -35t35.5 -15h1000q21 0 35.5 15t14.5 35v750h-1100v-750zM0 900h1100v150q0 21 -14.5 35.5t-35.5 14.5h-150v100h-100v-100h-500v100h-100v-100h-150q-21 0 -35.5 -14.5t-14.5 -35.5v-150zM100 100v100h100v-100h-100zM100 300v100h100v-100h-100z M100 500v100h100v-100h-100zM300 100v100h100v-100h-100zM300 300v100h100v-100h-100zM300 500v100h100v-100h-100zM500 100v100h100v-100h-100zM500 300v100h100v-100h-100zM500 500v100h100v-100h-100zM700 100v100h100v-100h-100zM700 300v100h100v-100h-100zM700 500 v100h100v-100h-100zM900 100v100h100v-100h-100zM900 300v100h100v-100h-100zM900 500v100h100v-100h-100z" /> -<glyph unicode="" d="M0 200v200h259l600 600h241v198l300 -295l-300 -300v197h-159l-600 -600h-341zM0 800h259l122 -122l141 142l-181 180h-341v-200zM678 381l141 142l122 -123h159v198l300 -295l-300 -300v197h-241z" /> -<glyph unicode="" d="M0 400v600q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-596l-304 -300v300h-100q-41 0 -70.5 29.5t-29.5 70.5z" /> -<glyph unicode="" d="M100 600v200h300v-250q0 -113 6 -145q17 -92 102 -117q39 -11 92 -11q37 0 66.5 5.5t50 15.5t36 24t24 31.5t14 37.5t7 42t2.5 45t0 47v25v250h300v-200q0 -42 -3 -83t-15 -104t-31.5 -116t-58 -109.5t-89 -96.5t-129 -65.5t-174.5 -25.5t-174.5 25.5t-129 65.5t-89 96.5 t-58 109.5t-31.5 116t-15 104t-3 83zM100 900v300h300v-300h-300zM800 900v300h300v-300h-300z" /> -<glyph unicode="" d="M-30 411l227 -227l352 353l353 -353l226 227l-578 579z" /> -<glyph unicode="" d="M70 797l580 -579l578 579l-226 227l-353 -353l-352 353z" /> -<glyph unicode="" d="M-198 700l299 283l300 -283h-203v-400h385l215 -200h-800v600h-196zM402 1000l215 -200h381v-400h-198l299 -283l299 283h-200v600h-796z" /> -<glyph unicode="" d="M18 939q-5 24 10 42q14 19 39 19h896l38 162q5 17 18.5 27.5t30.5 10.5h94q20 0 35 -14.5t15 -35.5t-15 -35.5t-35 -14.5h-54l-201 -961q-2 -4 -6 -10.5t-19 -17.5t-33 -11h-31v-50q0 -20 -14.5 -35t-35.5 -15t-35.5 15t-14.5 35v50h-300v-50q0 -20 -14.5 -35t-35.5 -15 t-35.5 15t-14.5 35v50h-50q-21 0 -35.5 15t-14.5 35q0 21 14.5 35.5t35.5 14.5h535l48 200h-633q-32 0 -54.5 21t-27.5 43z" /> -<glyph unicode="" d="M0 0v800h1200v-800h-1200zM0 900v100h200q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5h500v-100h-1200z" /> -<glyph unicode="" d="M1 0l300 700h1200l-300 -700h-1200zM1 400v600h200q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5h500v-200h-1000z" /> -<glyph unicode="" d="M302 300h198v600h-198l298 300l298 -300h-198v-600h198l-298 -300z" /> -<glyph unicode="" d="M0 600l300 298v-198h600v198l300 -298l-300 -297v197h-600v-197z" /> -<glyph unicode="" d="M0 100v100q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5zM31 400l172 739q5 22 23 41.5t38 19.5h672q19 0 37.5 -22.5t23.5 -45.5l172 -732h-1138zM800 100h100v100h-100v-100z M1000 100h100v100h-100v-100z" /> -<glyph unicode="" d="M-101 600v50q0 24 25 49t50 38l25 13v-250l-11 5.5t-24 14t-30 21.5t-24 27.5t-11 31.5zM99 500v250v5q0 13 0.5 18.5t2.5 13t8 10.5t15 3h200l675 250v-850l-675 200h-38l47 -276q2 -12 -3 -17.5t-11 -6t-21 -0.5h-8h-83q-20 0 -34.5 14t-18.5 35q-56 337 -56 351z M1100 200v850q0 21 14.5 35.5t35.5 14.5q20 0 35 -14.5t15 -35.5v-850q0 -20 -15 -35t-35 -15q-21 0 -35.5 15t-14.5 35z" /> -<glyph unicode="" d="M74 350q0 21 13.5 35.5t33.5 14.5h17l118 173l63 327q15 77 76 140t144 83l-18 32q-6 19 3 32t29 13h94q20 0 29 -10.5t3 -29.5l-18 -37q83 -19 144 -82.5t76 -140.5l63 -327l118 -173h17q20 0 33.5 -14.5t13.5 -35.5q0 -20 -13 -40t-31 -27q-22 -9 -63 -23t-167.5 -37 t-251.5 -23t-245.5 20.5t-178.5 41.5l-58 20q-18 7 -31 27.5t-13 40.5zM497 110q12 -49 40 -79.5t63 -30.5t63 30.5t39 79.5q-48 -6 -102 -6t-103 6z" /> -<glyph unicode="" d="M21 445l233 -45l-78 -224l224 78l45 -233l155 179l155 -179l45 233l224 -78l-78 224l234 45l-180 155l180 156l-234 44l78 225l-224 -78l-45 233l-155 -180l-155 180l-45 -233l-224 78l78 -225l-233 -44l179 -156z" /> -<glyph unicode="" d="M0 200h200v600h-200v-600zM300 275q0 -75 100 -75h61q123 -100 139 -100h250q46 0 83 57l238 344q29 31 29 74v100q0 44 -30.5 84.5t-69.5 40.5h-328q28 118 28 125v150q0 44 -30.5 84.5t-69.5 40.5h-50q-27 0 -51 -20t-38 -48l-96 -198l-145 -196q-20 -26 -20 -63v-400z M400 300v375l150 212l100 213h50v-175l-50 -225h450v-125l-250 -375h-214l-136 100h-100z" /> -<glyph unicode="" d="M0 400v600h200v-600h-200zM300 525v400q0 75 100 75h61q123 100 139 100h250q46 0 83 -57l238 -344q29 -31 29 -74v-100q0 -44 -30.5 -84.5t-69.5 -40.5h-328q28 -118 28 -125v-150q0 -44 -30.5 -84.5t-69.5 -40.5h-50q-27 0 -51 20t-38 48l-96 198l-145 196 q-20 26 -20 63zM400 525l150 -212l100 -213h50v175l-50 225h450v125l-250 375h-214l-136 -100h-100v-375z" /> -<glyph unicode="" d="M8 200v600h200v-600h-200zM308 275v525q0 17 14 35.5t28 28.5l14 9l362 230q14 6 25 6q17 0 29 -12l109 -112q14 -14 14 -34q0 -18 -11 -32l-85 -121h302q85 0 138.5 -38t53.5 -110t-54.5 -111t-138.5 -39h-107l-130 -339q-7 -22 -20.5 -41.5t-28.5 -19.5h-341 q-7 0 -90 81t-83 94zM408 289l100 -89h293l131 339q6 21 19.5 41t28.5 20h203q16 0 25 15t9 36q0 20 -9 34.5t-25 14.5h-457h-6.5h-7.5t-6.5 0.5t-6 1t-5 1.5t-5.5 2.5t-4 4t-4 5.5q-5 12 -5 20q0 14 10 27l147 183l-86 83l-339 -236v-503z" /> -<glyph unicode="" d="M-101 651q0 72 54 110t139 37h302l-85 121q-11 16 -11 32q0 21 14 34l109 113q13 12 29 12q11 0 25 -6l365 -230q7 -4 16.5 -10.5t26 -26t16.5 -36.5v-526q0 -13 -85.5 -93.5t-93.5 -80.5h-342q-15 0 -28.5 20t-19.5 41l-131 339h-106q-84 0 -139 39t-55 111zM-1 601h222 q15 0 28.5 -20.5t19.5 -40.5l131 -339h293l106 89v502l-342 237l-87 -83l145 -184q10 -11 10 -26q0 -11 -5 -20q-1 -3 -3.5 -5.5l-4 -4t-5 -2.5t-5.5 -1.5t-6.5 -1t-6.5 -0.5h-7.5h-6.5h-476v-100zM999 201v600h200v-600h-200z" /> -<glyph unicode="" d="M97 719l230 -363q4 -6 10.5 -15.5t26 -25t36.5 -15.5h525q13 0 94 83t81 90v342q0 15 -20 28.5t-41 19.5l-339 131v106q0 84 -39 139t-111 55t-110 -53.5t-38 -138.5v-302l-121 84q-15 12 -33.5 11.5t-32.5 -13.5l-112 -110q-22 -22 -6 -53zM172 739l83 86l183 -146 q22 -18 47 -5q3 1 5.5 3.5l4 4t2.5 5t1.5 5.5t1 6.5t0.5 6v7.5v7v456q0 22 25 31t50 -0.5t25 -30.5v-202q0 -16 20 -29.5t41 -19.5l339 -130v-294l-89 -100h-503zM400 0v200h600v-200h-600z" /> -<glyph unicode="" d="M1 585q-15 -31 7 -53l112 -110q13 -13 32 -13.5t34 10.5l121 85l-1 -302q0 -84 38.5 -138t110.5 -54t111 55t39 139v106l339 131q20 6 40.5 19.5t20.5 28.5v342q0 7 -81 90t-94 83h-525q-17 0 -35.5 -14t-28.5 -28l-10 -15zM76 565l237 339h503l89 -100v-294l-340 -130 q-20 -6 -40 -20t-20 -29v-202q0 -22 -25 -31t-50 0t-25 31v456v14.5t-1.5 11.5t-5 12t-9.5 7q-24 13 -46 -5l-184 -146zM305 1104v200h600v-200h-600z" /> -<glyph unicode="" d="M5 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5q162 0 299.5 -80t217.5 -218t80 -300t-80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5zM300 500h300l-2 -194l402 294l-402 298v-197h-298v-201z" /> -<glyph unicode="" d="M0 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t231.5 47.5q122 0 232.5 -47.5t190.5 -127.5t127.5 -190.5t47.5 -232.5q0 -162 -80 -299.5t-218 -217.5t-300 -80t-299.5 80t-217.5 217.5t-80 299.5zM200 600l400 -294v194h302v201h-300v197z" /> -<glyph unicode="" d="M5 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5q121 0 231.5 -47.5t190.5 -127.5t127.5 -190.5t47.5 -232.5q0 -162 -80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5zM300 600h200v-300h200v300h200l-300 400z" /> -<glyph unicode="" d="M5 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5q121 0 231.5 -47.5t190.5 -127.5t127.5 -190.5t47.5 -232.5q0 -162 -80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5zM300 600l300 -400l300 400h-200v300h-200v-300h-200z" /> -<glyph unicode="" d="M5 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5q121 0 231.5 -47.5t190.5 -127.5t127.5 -190.5t47.5 -232.5q0 -162 -80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5zM254 780q-8 -34 5.5 -93t7.5 -87q0 -9 17 -44t16 -60q12 0 23 -5.5 t23 -15t20 -13.5q20 -10 108 -42q22 -8 53 -31.5t59.5 -38.5t57.5 -11q8 -18 -15 -55.5t-20 -57.5q12 -21 22.5 -34.5t28 -27t36.5 -17.5q0 -6 -3 -15.5t-3.5 -14.5t4.5 -17q101 -2 221 111q31 30 47 48t34 49t21 62q-14 9 -37.5 9.5t-35.5 7.5q-14 7 -49 15t-52 19 q-9 0 -39.5 -0.5t-46.5 -1.5t-39 -6.5t-39 -16.5q-50 -35 -66 -12q-4 2 -3.5 25.5t0.5 25.5q-6 13 -26.5 17t-24.5 7q2 22 -2 41t-16.5 28t-38.5 -20q-23 -25 -42 4q-19 28 -8 58q8 16 22 22q6 -1 26 -1.5t33.5 -4.5t19.5 -13q12 -19 32 -37.5t34 -27.5l14 -8q0 3 9.5 39.5 t5.5 57.5q-4 23 14.5 44.5t22.5 31.5q5 14 10 35t8.5 31t15.5 22.5t34 21.5q-6 18 10 37q8 0 23.5 -1.5t24.5 -1.5t20.5 4.5t20.5 15.5q-10 23 -30.5 42.5t-38 30t-49 26.5t-43.5 23q11 41 1 44q31 -13 58.5 -14.5t39.5 3.5l11 4q6 36 -17 53.5t-64 28.5t-56 23 q-19 -3 -37 0q-15 -12 -36.5 -21t-34.5 -12t-44 -8t-39 -6q-15 -3 -46 0t-45 -3q-20 -6 -51.5 -25.5t-34.5 -34.5q-3 -11 6.5 -22.5t8.5 -18.5q-3 -34 -27.5 -91t-29.5 -79zM518 915q3 12 16 30.5t16 25.5q10 -10 18.5 -10t14 6t14.5 14.5t16 12.5q0 -18 8 -42.5t16.5 -44 t9.5 -23.5q-6 1 -39 5t-53.5 10t-36.5 16z" /> -<glyph unicode="" d="M0 164.5q0 21.5 15 37.5l600 599q-33 101 6 201.5t135 154.5q164 92 306 -9l-259 -138l145 -232l251 126q13 -175 -151 -267q-123 -70 -253 -23l-596 -596q-15 -16 -36.5 -16t-36.5 16l-111 110q-15 15 -15 36.5z" /> -<glyph unicode="" horiz-adv-x="1220" d="M0 196v100q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5zM0 596v100q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000 q-41 0 -70.5 29.5t-29.5 70.5zM0 996v100q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5zM600 596h500v100h-500v-100zM800 196h300v100h-300v-100zM900 996h200v100h-200v-100z" /> -<glyph unicode="" d="M100 1100v100h1000v-100h-1000zM150 1000h900l-350 -500v-300l-200 -200v500z" /> -<glyph unicode="" d="M0 200v200h1200v-200q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5zM0 500v400q0 41 29.5 70.5t70.5 29.5h300v100q0 41 29.5 70.5t70.5 29.5h200q41 0 70.5 -29.5t29.5 -70.5v-100h300q41 0 70.5 -29.5t29.5 -70.5v-400h-500v100h-200v-100h-500z M500 1000h200v100h-200v-100z" /> -<glyph unicode="" d="M0 0v400l129 -129l200 200l142 -142l-200 -200l129 -129h-400zM0 800l129 129l200 -200l142 142l-200 200l129 129h-400v-400zM729 329l142 142l200 -200l129 129v-400h-400l129 129zM729 871l200 200l-129 129h400v-400l-129 129l-200 -200z" /> -<glyph unicode="" d="M0 596q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM182 596q0 -172 121.5 -293t292.5 -121t292.5 121t121.5 293q0 171 -121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM291 655 q0 23 15.5 38.5t38.5 15.5t39 -16t16 -38q0 -23 -16 -39t-39 -16q-22 0 -38 16t-16 39zM400 850q0 22 16 38.5t39 16.5q22 0 38 -16t16 -39t-16 -39t-38 -16q-23 0 -39 16.5t-16 38.5zM513 609q0 32 21 56.5t52 29.5l122 126l1 1q-9 14 -9 28q0 22 16 38.5t39 16.5 q22 0 38 -16t16 -39t-16 -39t-38 -16q-16 0 -29 10l-55 -145q17 -22 17 -51q0 -36 -25.5 -61.5t-61.5 -25.5q-37 0 -62.5 25.5t-25.5 61.5zM800 655q0 22 16 38t39 16t38.5 -15.5t15.5 -38.5t-16 -39t-38 -16q-23 0 -39 16t-16 39z" /> -<glyph unicode="" d="M-40 375q-13 -95 35 -173q35 -57 94 -89t129 -32q63 0 119 28q33 16 65 40.5t52.5 45.5t59.5 64q40 44 57 61l394 394q35 35 47 84t-3 96q-27 87 -117 104q-20 2 -29 2q-46 0 -79.5 -17t-67.5 -51l-388 -396l-7 -7l69 -67l377 373q20 22 39 38q23 23 50 23q38 0 53 -36 q16 -39 -20 -75l-547 -547q-52 -52 -125 -52q-55 0 -100 33t-54 96q-5 35 2.5 66t31.5 63t42 50t56 54q24 21 44 41l348 348q52 52 82.5 79.5t84 54t107.5 26.5q25 0 48 -4q95 -17 154 -94.5t51 -175.5q-7 -101 -98 -192l-252 -249l-253 -256l7 -7l69 -60l517 511 q67 67 95 157t11 183q-16 87 -67 154t-130 103q-69 33 -152 33q-107 0 -197 -55q-40 -24 -111 -95l-512 -512q-68 -68 -81 -163z" /> -<glyph unicode="" d="M79 784q0 131 99 229.5t230 98.5q144 0 242 -129q103 129 245 129q130 0 227 -98.5t97 -229.5q0 -46 -17.5 -91t-61 -99t-77 -89.5t-104.5 -105.5q-197 -191 -293 -322l-17 -23l-16 23q-43 58 -100 122.5t-92 99.5t-101 100l-84.5 84.5t-68 74t-60 78t-33.5 70.5t-15 78z M250 784q0 -27 30.5 -70t61.5 -75.5t95 -94.5l22 -22q93 -90 190 -201q82 92 195 203l12 12q64 62 97.5 97t64.5 79t31 72q0 71 -48 119.5t-106 48.5q-73 0 -131 -83l-118 -171l-114 174q-51 80 -124 80q-59 0 -108.5 -49.5t-49.5 -118.5z" /> -<glyph unicode="" d="M57 353q0 -94 66 -160l141 -141q66 -66 159 -66q95 0 159 66l283 283q66 66 66 159t-66 159l-141 141q-12 12 -19 17l-105 -105l212 -212l-389 -389l-247 248l95 95l-18 18q-46 45 -75 101l-55 -55q-66 -66 -66 -159zM269 706q0 -93 66 -159l141 -141l19 -17l105 105 l-212 212l389 389l247 -247l-95 -96l18 -18q46 -46 77 -99l29 29q35 35 62.5 88t27.5 96q0 93 -66 159l-141 141q-66 66 -159 66q-95 0 -159 -66l-283 -283q-66 -64 -66 -159z" /> -<glyph unicode="" d="M200 100v953q0 21 30 46t81 48t129 38t163 15t162 -15t127 -38t79 -48t29 -46v-953q0 -41 -29.5 -70.5t-70.5 -29.5h-600q-41 0 -70.5 29.5t-29.5 70.5zM300 300h600v700h-600v-700zM496 150q0 -43 30.5 -73.5t73.5 -30.5t73.5 30.5t30.5 73.5t-30.5 73.5t-73.5 30.5 t-73.5 -30.5t-30.5 -73.5z" /> -<glyph unicode="" d="M0 0l303 380l207 208l-210 212h300l267 279l-35 36q-15 14 -15 35t15 35q14 15 35 15t35 -15l283 -282q15 -15 15 -36t-15 -35q-14 -15 -35 -15t-35 15l-36 35l-279 -267v-300l-212 210l-208 -207z" /> -<glyph unicode="" d="M295 433h139q5 -77 48.5 -126.5t117.5 -64.5v335l-27 7q-46 14 -79 26.5t-72 36t-62.5 52t-40 72.5t-16.5 99q0 92 44 159.5t109 101t144 40.5v78h100v-79q38 -4 72.5 -13.5t75.5 -31.5t71 -53.5t51.5 -84t24.5 -118.5h-159q-8 72 -35 109.5t-101 50.5v-307l64 -14 q34 -7 64 -16.5t70 -31.5t67.5 -52t47.5 -80.5t20 -112.5q0 -139 -89 -224t-244 -96v-77h-100v78q-152 17 -237 104q-40 40 -52.5 93.5t-15.5 139.5zM466 889q0 -29 8 -51t16.5 -34t29.5 -22.5t31 -13.5t38 -10q7 -2 11 -3v274q-61 -8 -97.5 -37.5t-36.5 -102.5zM700 237 q170 18 170 151q0 64 -44 99.5t-126 60.5v-311z" /> -<glyph unicode="" d="M100 600v100h166q-24 49 -44 104q-10 26 -14.5 55.5t-3 72.5t25 90t68.5 87q97 88 263 88q129 0 230 -89t101 -208h-153q0 52 -34 89.5t-74 51.5t-76 14q-37 0 -79 -14.5t-62 -35.5q-41 -44 -41 -101q0 -11 2.5 -24.5t5.5 -24t9.5 -26.5t10.5 -25t14 -27.5t14 -25.5 t15.5 -27t13.5 -24h242v-100h-197q8 -50 -2.5 -115t-31.5 -94q-41 -59 -99 -113q35 11 84 18t70 7q32 1 102 -16t104 -17q76 0 136 30l50 -147q-41 -25 -80.5 -36.5t-59 -13t-61.5 -1.5q-23 0 -128 33t-155 29q-39 -4 -82 -17t-66 -25l-24 -11l-55 145l16.5 11t15.5 10 t13.5 9.5t14.5 12t14.5 14t17.5 18.5q48 55 54 126.5t-30 142.5h-221z" /> -<glyph unicode="" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM602 900l298 300l298 -300h-198v-900h-200v900h-198z" /> -<glyph unicode="" d="M2 300h198v900h200v-900h198l-298 -300zM700 0v200h100v-100h200v-100h-300zM700 400v100h300v-200h-99v-100h-100v100h99v100h-200zM700 700v500h300v-500h-100v100h-100v-100h-100zM801 900h100v200h-100v-200z" /> -<glyph unicode="" d="M2 300h198v900h200v-900h198l-298 -300zM700 0v500h300v-500h-100v100h-100v-100h-100zM700 700v200h100v-100h200v-100h-300zM700 1100v100h300v-200h-99v-100h-100v100h99v100h-200zM801 200h100v200h-100v-200z" /> -<glyph unicode="" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM800 100v400h300v-500h-100v100h-200zM800 1100v100h200v-500h-100v400h-100zM901 200h100v200h-100v-200z" /> -<glyph unicode="" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM800 400v100h200v-500h-100v400h-100zM800 800v400h300v-500h-100v100h-200zM901 900h100v200h-100v-200z" /> -<glyph unicode="" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM700 100v200h500v-200h-500zM700 400v200h400v-200h-400zM700 700v200h300v-200h-300zM700 1000v200h200v-200h-200z" /> -<glyph unicode="" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM700 100v200h200v-200h-200zM700 400v200h300v-200h-300zM700 700v200h400v-200h-400zM700 1000v200h500v-200h-500z" /> -<glyph unicode="" d="M0 400v300q0 165 117.5 282.5t282.5 117.5h300q162 0 281 -118.5t119 -281.5v-300q0 -165 -118.5 -282.5t-281.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5zM200 300q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5 h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500z" /> -<glyph unicode="" d="M0 400v300q0 163 119 281.5t281 118.5h300q165 0 282.5 -117.5t117.5 -282.5v-300q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-163 0 -281.5 117.5t-118.5 282.5zM200 300q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5 h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500zM400 300l333 250l-333 250v-500z" /> -<glyph unicode="" d="M0 400v300q0 163 117.5 281.5t282.5 118.5h300q163 0 281.5 -119t118.5 -281v-300q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5zM200 300q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5 h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500zM300 700l250 -333l250 333h-500z" /> -<glyph unicode="" d="M0 400v300q0 165 117.5 282.5t282.5 117.5h300q165 0 282.5 -117.5t117.5 -282.5v-300q0 -162 -118.5 -281t-281.5 -119h-300q-165 0 -282.5 118.5t-117.5 281.5zM200 300q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5 h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500zM300 400h500l-250 333z" /> -<glyph unicode="" d="M0 400v300h300v200l400 -350l-400 -350v200h-300zM500 0v200h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5h-500v200h400q165 0 282.5 -117.5t117.5 -282.5v-300q0 -165 -117.5 -282.5t-282.5 -117.5h-400z" /> -<glyph unicode="" d="M216 519q10 -19 32 -19h302q-155 -438 -160 -458q-5 -21 4 -32l9 -8l9 -1q13 0 26 16l538 630q15 19 6 36q-8 18 -32 16h-300q1 4 78 219.5t79 227.5q2 17 -6 27l-8 8h-9q-16 0 -25 -15q-4 -5 -98.5 -111.5t-228 -257t-209.5 -238.5q-17 -19 -7 -40z" /> -<glyph unicode="" d="M0 400q0 -165 117.5 -282.5t282.5 -117.5h300q47 0 100 15v185h-500q-41 0 -70.5 29.5t-29.5 70.5v500q0 41 29.5 70.5t70.5 29.5h500v185q-14 4 -114 7.5t-193 5.5l-93 2q-165 0 -282.5 -117.5t-117.5 -282.5v-300zM600 400v300h300v200l400 -350l-400 -350v200h-300z " /> -<glyph unicode="" d="M0 400q0 -165 117.5 -282.5t282.5 -117.5h300q163 0 281.5 117.5t118.5 282.5v98l-78 73l-122 -123v-148q0 -41 -29.5 -70.5t-70.5 -29.5h-500q-41 0 -70.5 29.5t-29.5 70.5v500q0 41 29.5 70.5t70.5 29.5h156l118 122l-74 78h-100q-165 0 -282.5 -117.5t-117.5 -282.5 v-300zM496 709l353 342l-149 149h500v-500l-149 149l-342 -353z" /> -<glyph unicode="" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM406 600 q0 80 57 137t137 57t137 -57t57 -137t-57 -137t-137 -57t-137 57t-57 137z" /> -<glyph unicode="" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM100 800l445 -500l450 500h-295v400h-300v-400h-300zM900 150h100v50h-100v-50z" /> -<glyph unicode="" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM100 700h300v-300h300v300h295l-445 500zM900 150h100v50h-100v-50z" /> -<glyph unicode="" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM100 705l305 -305l596 596l-154 155l-442 -442l-150 151zM900 150h100v50h-100v-50z" /> -<glyph unicode="" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM100 988l97 -98l212 213l-97 97zM200 401h700v699l-250 -239l-149 149l-212 -212l149 -149zM900 150h100v50h-100v-50z" /> -<glyph unicode="" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM200 612l212 -212l98 97l-213 212zM300 1200l239 -250l-149 -149l212 -212l149 148l248 -237v700h-699zM900 150h100v50h-100v-50z" /> -<glyph unicode="" d="M23 415l1177 784v-1079l-475 272l-310 -393v416h-392zM494 210l672 938l-672 -712v-226z" /> -<glyph unicode="" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-850q0 -21 -15 -35.5t-35 -14.5h-150v400h-700v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM600 1000h100v200h-100v-200z" /> -<glyph unicode="" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-218l-276 -275l-120 120l-126 -127h-378v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM581 306l123 123l120 -120l353 352l123 -123l-475 -476zM600 1000h100v200h-100v-200z" /> -<glyph unicode="" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-269l-103 -103l-170 170l-298 -298h-329v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM600 1000h100v200h-100v-200zM700 133l170 170l-170 170l127 127l170 -170l170 170l127 -128l-170 -169l170 -170 l-127 -127l-170 170l-170 -170z" /> -<glyph unicode="" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-300h-400v-200h-500v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM600 300l300 -300l300 300h-200v300h-200v-300h-200zM600 1000v200h100v-200h-100z" /> -<glyph unicode="" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-402l-200 200l-298 -298h-402v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM600 300h200v-300h200v300h200l-300 300zM600 1000v200h100v-200h-100z" /> -<glyph unicode="" d="M0 250q0 -21 14.5 -35.5t35.5 -14.5h1100q21 0 35.5 14.5t14.5 35.5v550h-1200v-550zM0 900h1200v150q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5v-150zM100 300v200h400v-200h-400z" /> -<glyph unicode="" d="M0 400l300 298v-198h400v-200h-400v-198zM100 800v200h100v-200h-100zM300 800v200h100v-200h-100zM500 800v200h400v198l300 -298l-300 -298v198h-400zM800 300v200h100v-200h-100zM1000 300h100v200h-100v-200z" /> -<glyph unicode="" d="M100 700v400l50 100l50 -100v-300h100v300l50 100l50 -100v-300h100v300l50 100l50 -100v-400l-100 -203v-447q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v447zM800 597q0 -29 10.5 -55.5t25 -43t29 -28.5t25.5 -18l10 -5v-397q0 -21 14.5 -35.5 t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5v1106q0 31 -18 40.5t-44 -7.5l-276 -117q-25 -16 -43.5 -50.5t-18.5 -65.5v-359z" /> -<glyph unicode="" d="M100 0h400v56q-75 0 -87.5 6t-12.5 44v394h500v-394q0 -38 -12.5 -44t-87.5 -6v-56h400v56q-4 0 -11 0.5t-24 3t-30 7t-24 15t-11 24.5v888q0 22 25 34.5t50 13.5l25 2v56h-400v-56q75 0 87.5 -6t12.5 -44v-394h-500v394q0 38 12.5 44t87.5 6v56h-400v-56q4 0 11 -0.5 t24 -3t30 -7t24 -15t11 -24.5v-888q0 -22 -25 -34.5t-50 -13.5l-25 -2v-56z" /> -<glyph unicode="" d="M0 300q0 -41 29.5 -70.5t70.5 -29.5h300q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5h-300q-41 0 -70.5 -29.5t-29.5 -70.5v-500zM100 100h400l200 200h105l295 98v-298h-425l-100 -100h-375zM100 300v200h300v-200h-300zM100 600v200h300v-200h-300z M100 1000h400l200 -200v-98l295 98h105v200h-425l-100 100h-375zM700 402v163l400 133v-163z" /> -<glyph unicode="" d="M16.5 974.5q0.5 -21.5 16 -90t46.5 -140t104 -177.5t175 -208q103 -103 207.5 -176t180 -103.5t137 -47t92.5 -16.5l31 1l163 162q16 17 13 40.5t-22 37.5l-192 136q-19 14 -45 12t-42 -19l-119 -118q-143 103 -267 227q-126 126 -227 268l118 118q17 17 20 41.5 t-11 44.5l-139 194q-14 19 -36.5 22t-40.5 -14l-162 -162q-1 -11 -0.5 -32.5z" /> -<glyph unicode="" d="M0 50v212q0 20 10.5 45.5t24.5 39.5l365 303v50q0 4 1 10.5t12 22.5t30 28.5t60 23t97 10.5t97 -10t60 -23.5t30 -27.5t12 -24l1 -10v-50l365 -303q14 -14 24.5 -39.5t10.5 -45.5v-212q0 -21 -15 -35.5t-35 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5zM0 712 q0 -21 14.5 -33.5t34.5 -8.5l202 33q20 4 34.5 21t14.5 38v146q141 24 300 24t300 -24v-146q0 -21 14.5 -38t34.5 -21l202 -33q20 -4 34.5 8.5t14.5 33.5v200q-6 8 -19 20.5t-63 45t-112 57t-171 45t-235 20.5q-92 0 -175 -10.5t-141.5 -27t-108.5 -36.5t-81.5 -40 t-53.5 -36.5t-31 -27.5l-9 -10v-200z" /> -<glyph unicode="" d="M100 0v100h1100v-100h-1100zM175 200h950l-125 150v250l100 100v400h-100v-200h-100v200h-200v-200h-100v200h-200v-200h-100v200h-100v-400l100 -100v-250z" /> -<glyph unicode="" d="M100 0h300v400q0 41 -29.5 70.5t-70.5 29.5h-100q-41 0 -70.5 -29.5t-29.5 -70.5v-400zM500 0v1000q0 41 29.5 70.5t70.5 29.5h100q41 0 70.5 -29.5t29.5 -70.5v-1000h-300zM900 0v700q0 41 29.5 70.5t70.5 29.5h100q41 0 70.5 -29.5t29.5 -70.5v-700h-300z" /> -<glyph unicode="" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h300v300h-200v100h200v100h-300v-300h200v-100h-200v-100zM600 300h200v100h100v300h-100v100h-200v-500 zM700 400v300h100v-300h-100z" /> -<glyph unicode="" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h100v200h100v-200h100v500h-100v-200h-100v200h-100v-500zM600 300h200v100h100v300h-100v100h-200v-500 zM700 400v300h100v-300h-100z" /> -<glyph unicode="" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h300v100h-200v300h200v100h-300v-500zM600 300h300v100h-200v300h200v100h-300v-500z" /> -<glyph unicode="" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 550l300 -150v300zM600 400l300 150l-300 150v-300z" /> -<glyph unicode="" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300v500h700v-500h-700zM300 400h130q41 0 68 42t27 107t-28.5 108t-66.5 43h-130v-300zM575 549 q0 -65 27 -107t68 -42h130v300h-130q-38 0 -66.5 -43t-28.5 -108z" /> -<glyph unicode="" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h300v300h-200v100h200v100h-300v-300h200v-100h-200v-100zM601 300h100v100h-100v-100zM700 700h100 v-400h100v500h-200v-100z" /> -<glyph unicode="" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h300v400h-200v100h-100v-500zM301 400v200h100v-200h-100zM601 300h100v100h-100v-100zM700 700h100 v-400h100v500h-200v-100z" /> -<glyph unicode="" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 700v100h300v-300h-99v-100h-100v100h99v200h-200zM201 300v100h100v-100h-100zM601 300v100h100v-100h-100z M700 700v100h200v-500h-100v400h-100z" /> -<glyph unicode="" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM400 500v200 l100 100h300v-100h-300v-200h300v-100h-300z" /> -<glyph unicode="" d="M0 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM182 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM400 400v400h300 l100 -100v-100h-100v100h-200v-100h200v-100h-200v-100h-100zM700 400v100h100v-100h-100z" /> -<glyph unicode="" d="M-14 494q0 -80 56.5 -137t135.5 -57h222v300h400v-300h128q120 0 205 86t85 208q0 120 -85 206.5t-205 86.5q-46 0 -90 -14q-44 97 -134.5 156.5t-200.5 59.5q-152 0 -260 -107.5t-108 -260.5q0 -25 2 -37q-66 -14 -108.5 -67.5t-42.5 -122.5zM300 200h200v300h200v-300 h200l-300 -300z" /> -<glyph unicode="" d="M-14 494q0 -80 56.5 -137t135.5 -57h8l414 414l403 -403q94 26 154.5 104t60.5 178q0 121 -85 207.5t-205 86.5q-46 0 -90 -14q-44 97 -134.5 156.5t-200.5 59.5q-152 0 -260 -107.5t-108 -260.5q0 -25 2 -37q-66 -14 -108.5 -67.5t-42.5 -122.5zM300 200l300 300 l300 -300h-200v-300h-200v300h-200z" /> -<glyph unicode="" d="M100 200h400v-155l-75 -45h350l-75 45v155h400l-270 300h170l-270 300h170l-300 333l-300 -333h170l-270 -300h170z" /> -<glyph unicode="" d="M121 700q0 -53 28.5 -97t75.5 -65q-4 -16 -4 -38q0 -74 52.5 -126.5t126.5 -52.5q56 0 100 30v-306l-75 -45h350l-75 45v306q46 -30 100 -30q74 0 126.5 52.5t52.5 126.5q0 24 -9 55q50 32 79.5 83t29.5 112q0 90 -61.5 155.5t-150.5 71.5q-26 89 -99.5 145.5 t-167.5 56.5q-116 0 -197.5 -81.5t-81.5 -197.5q0 -4 1 -12t1 -11q-14 2 -23 2q-74 0 -126.5 -52.5t-52.5 -126.5z" /> -</font> -</defs></svg> -\ No newline at end of file diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/glyphicons-halflings-regular.ttf b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/glyphicons-halflings-regular.ttf Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/glyphicons-halflings-regular.woff b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/glyphicons-halflings-regular.woff Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-Bold-webfont.eot b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-Bold-webfont.eot Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-Bold-webfont.svg b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-Bold-webfont.svg @@ -1,251 +0,0 @@ -<?xml version="1.0" standalone="no"?> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" > -<svg xmlns="http://www.w3.org/2000/svg"> -<metadata> -This is a custom SVG webfont generated by Font Squirrel. -Copyright : Digitized data copyright 20102011 Google Corporation -Foundry : Ascender Corporation -Foundry URL : httpwwwascendercorpcom -</metadata> -<defs> -<font id="OpenSansBold" horiz-adv-x="1169" > -<font-face units-per-em="2048" ascent="1638" descent="-410" /> -<missing-glyph horiz-adv-x="532" /> -<glyph unicode=" " horiz-adv-x="532" /> -<glyph unicode="	" horiz-adv-x="532" /> -<glyph unicode=" " horiz-adv-x="532" /> -<glyph unicode="!" horiz-adv-x="586" d="M117 143q0 84 45 127t131 43q83 0 128.5 -44t45.5 -126q0 -79 -46 -124.5t-128 -45.5q-84 0 -130 44.5t-46 125.5zM121 1462h346l-51 -977h-244z" /> -<glyph unicode=""" horiz-adv-x="967" d="M133 1462h279l-41 -528h-197zM555 1462h279l-41 -528h-197z" /> -<glyph unicode="#" horiz-adv-x="1323" d="M45 406v206h277l47 232h-252v209h289l77 407h219l-77 -407h198l78 407h215l-78 -407h240v-209h-279l-47 -232h258v-206h-297l-77 -406h-220l78 406h-194l-76 -406h-215l74 406h-238zM539 612h196l47 232h-196z" /> -<glyph unicode="$" d="M88 1049q0 145 113.5 238.5t316.5 113.5v153h137v-149q229 -10 414 -92l-94 -234q-156 64 -320 78v-295q195 -75 277.5 -130t121 -121t38.5 -154q0 -159 -115 -255.5t-322 -115.5v-205h-137v201q-244 5 -428 86v264q87 -43 209.5 -76t218.5 -39v310l-67 26 q-198 78 -280.5 169.5t-82.5 226.5zM389 1049q0 -44 30.5 -72.5t98.5 -58.5v235q-129 -19 -129 -104zM655 324q136 23 136 118q0 42 -34 71t-102 60v-249z" /> -<glyph unicode="%" horiz-adv-x="1845" d="M63 1026q0 457 345 457q169 0 259.5 -118.5t90.5 -338.5q0 -230 -89 -345.5t-261 -115.5q-165 0 -255 118.5t-90 342.5zM315 1024q0 -127 22.5 -189.5t72.5 -62.5q96 0 96 252q0 250 -96 250q-50 0 -72.5 -61.5t-22.5 -188.5zM395 0l811 1462h240l-811 -1462h-240z M1087 442q0 457 345 457q169 0 259.5 -118.5t90.5 -338.5q0 -229 -89 -344.5t-261 -115.5q-165 0 -255 118.5t-90 341.5zM1339 440q0 -127 22.5 -189.5t72.5 -62.5q96 0 96 252q0 250 -96 250q-50 0 -72.5 -61.5t-22.5 -188.5z" /> -<glyph unicode="&" horiz-adv-x="1536" d="M82 395q0 137 60.5 233.5t207.5 180.5q-75 86 -109 164.5t-34 171.5q0 152 116.5 245t311.5 93q186 0 297.5 -86.5t111.5 -231.5q0 -119 -69 -217.5t-223 -187.5l284 -277q71 117 123 301h318q-36 -135 -99 -263.5t-143 -227.5l301 -293h-377l-115 113 q-191 -133 -432 -133q-244 0 -387 112t-143 303zM403 424q0 -86 64.5 -137t165.5 -51q126 0 227 61l-332 330q-58 -44 -91.5 -92t-33.5 -111zM489 1124q0 -88 95 -194q86 48 132 94.5t46 108.5q0 53 -36 83.5t-93 30.5q-67 0 -105.5 -32t-38.5 -91z" /> -<glyph unicode="'" horiz-adv-x="545" d="M133 1462h279l-41 -528h-197z" /> -<glyph unicode="(" horiz-adv-x="694" d="M82 561q0 265 77.5 496t223.5 405h250q-141 -193 -213 -424t-72 -475q0 -245 73.5 -473.5t209.5 -413.5h-248q-147 170 -224 397t-77 488z" /> -<glyph unicode=")" horiz-adv-x="694" d="M61 1462h250q147 -175 224 -406.5t77 -494.5t-77.5 -490t-223.5 -395h-248q135 184 209 412.5t74 474.5q0 244 -72 475t-213 424z" /> -<glyph unicode="*" horiz-adv-x="1116" d="M63 1042l39 250l365 -104l-41 368h262l-41 -368l373 104l33 -252l-340 -24l223 -297l-227 -121l-156 313l-137 -311l-236 119l221 297z" /> -<glyph unicode="+" d="M88 612v219h387v390h219v-390h387v-219h-387v-385h-219v385h-387z" /> -<glyph unicode="," horiz-adv-x="594" d="M63 -264q65 266 101 502h280l15 -23q-52 -202 -176 -479h-220z" /> -<glyph unicode="-" horiz-adv-x="659" d="M61 424v250h537v-250h-537z" /> -<glyph unicode="." horiz-adv-x="584" d="M117 143q0 84 45 127t131 43q83 0 128.5 -44t45.5 -126q0 -79 -46 -124.5t-128 -45.5q-84 0 -130 44.5t-46 125.5z" /> -<glyph unicode="/" horiz-adv-x="846" d="M14 0l545 1462h277l-545 -1462h-277z" /> -<glyph unicode="0" d="M74 731q0 387 125 570.5t385 183.5q253 0 382.5 -192t129.5 -562q0 -383 -125.5 -567t-386.5 -184q-253 0 -381.5 190t-128.5 561zM381 731q0 -269 46.5 -385.5t156.5 -116.5q108 0 156 118t48 384q0 269 -48.5 386.5t-155.5 117.5q-109 0 -156 -117.5t-47 -386.5z" /> -<glyph unicode="1" d="M121 1087l471 375h254v-1462h-309v846l3 139l5 152q-77 -77 -107 -101l-168 -135z" /> -<glyph unicode="2" d="M78 1274q108 92 179 130t155 58.5t188 20.5q137 0 242 -50t163 -140t58 -206q0 -101 -35.5 -189.5t-110 -181.5t-262.5 -265l-188 -177v-14h637v-260h-1022v215l367 371q163 167 213 231.5t72 119.5t22 114q0 88 -48.5 131t-129.5 43q-85 0 -165 -39t-167 -111z" /> -<glyph unicode="3" d="M78 59v263q85 -43 187 -70t202 -27q153 0 226 52t73 167q0 103 -84 146t-268 43h-111v237h113q170 0 248.5 44.5t78.5 152.5q0 166 -208 166q-72 0 -146.5 -24t-165.5 -83l-143 213q200 144 477 144q227 0 358.5 -92t131.5 -256q0 -137 -83 -233t-233 -132v-6 q177 -22 268 -107.5t91 -230.5q0 -211 -153 -328.5t-437 -117.5q-238 0 -422 79z" /> -<glyph unicode="4" d="M35 303v215l641 944h285v-919h176v-240h-176v-303h-302v303h-624zM307 543h352v248q0 62 5 180t8 137h-8q-37 -82 -89 -160z" /> -<glyph unicode="5" d="M100 59v267q79 -42 184 -68.5t199 -26.5q283 0 283 232q0 221 -293 221q-53 0 -117 -10.5t-104 -22.5l-123 66l55 745h793v-262h-522l-27 -287l35 7q61 14 151 14q212 0 337.5 -119t125.5 -326q0 -245 -151 -377t-432 -132q-244 0 -394 79z" /> -<glyph unicode="6" d="M72 621q0 434 183.5 646t549.5 212q125 0 196 -15v-247q-89 20 -176 20q-159 0 -259.5 -48t-150.5 -142t-59 -267h13q99 170 317 170q196 0 307 -123t111 -340q0 -234 -132 -370.5t-366 -136.5q-162 0 -282.5 75t-186 219t-65.5 347zM379 510q0 -119 62.5 -201t158.5 -82 q99 0 152 66.5t53 189.5q0 107 -49.5 168.5t-149.5 61.5q-94 0 -160.5 -61t-66.5 -142z" /> -<glyph unicode="7" d="M55 1200v260h1049v-194l-553 -1266h-324l549 1200h-721z" /> -<glyph unicode="8" d="M72 371q0 125 66.5 222t213.5 171q-125 79 -180 169t-55 197q0 157 130 254t339 97q210 0 338.5 -95.5t128.5 -257.5q0 -112 -62 -199.5t-200 -156.5q164 -88 235.5 -183.5t71.5 -209.5q0 -180 -141 -289.5t-371 -109.5q-240 0 -377 102t-137 289zM358 389q0 -86 60 -134 t164 -48q115 0 172 49.5t57 130.5q0 67 -56.5 125.5t-183.5 124.5q-213 -98 -213 -248zM408 1106q0 -60 38.5 -107.5t139.5 -97.5q98 46 137 94t39 111q0 69 -50 109t-128 40q-79 0 -127.5 -40.5t-48.5 -108.5z" /> -<glyph unicode="9" d="M66 971q0 235 133.5 371.5t363.5 136.5q162 0 283.5 -76t186.5 -220.5t65 -344.5q0 -432 -182 -645t-551 -213q-130 0 -197 14v248q84 -21 176 -21q155 0 255 45.5t153 143t61 268.5h-12q-58 -94 -134 -132t-190 -38q-191 0 -301 122.5t-110 340.5zM365 975 q0 -106 49 -168t149 -62q94 0 161 61.5t67 141.5q0 119 -62.5 201t-159.5 82q-96 0 -150 -66t-54 -190z" /> -<glyph unicode=":" horiz-adv-x="584" d="M117 143q0 84 45 127t131 43q83 0 128.5 -44t45.5 -126q0 -79 -46 -124.5t-128 -45.5q-84 0 -130 44.5t-46 125.5zM117 969q0 84 45 127t131 43q83 0 128.5 -44t45.5 -126q0 -81 -46.5 -125.5t-127.5 -44.5q-84 0 -130 44t-46 126z" /> -<glyph unicode=";" horiz-adv-x="594" d="M63 -264q65 266 101 502h280l15 -23q-52 -202 -176 -479h-220zM117 969q0 84 45 127t131 43q83 0 128.5 -44t45.5 -126q0 -81 -46.5 -125.5t-127.5 -44.5q-84 0 -130 44t-46 126z" /> -<glyph unicode="<" d="M88 641v143l993 496v-240l-684 -317l684 -281v-239z" /> -<glyph unicode="=" d="M88 418v219h993v-219h-993zM88 805v219h993v-219h-993z" /> -<glyph unicode=">" d="M88 203v239l684 281l-684 317v240l993 -496v-143z" /> -<glyph unicode="?" horiz-adv-x="977" d="M6 1358q223 125 473 125q206 0 327.5 -99t121.5 -264q0 -110 -50 -190t-190 -180q-96 -71 -121.5 -108t-25.5 -97v-60h-265v74q0 96 41 167t150 151q105 75 138.5 122t33.5 105q0 65 -48 99t-134 34q-150 0 -342 -98zM244 143q0 84 45 127t131 43q83 0 128.5 -44 t45.5 -126q0 -79 -46 -124.5t-128 -45.5q-84 0 -130 44.5t-46 125.5z" /> -<glyph unicode="@" horiz-adv-x="1837" d="M102 602q0 247 108.5 448.5t309 316t461.5 114.5q220 0 393 -90t267 -256t94 -383q0 -144 -46 -263.5t-130 -187.5t-195 -68q-74 0 -131 35.5t-82 93.5h-16q-108 -129 -275 -129q-177 0 -279 106.5t-102 291.5q0 211 134 340t350 129q86 0 189.5 -16.5t170.5 -39.5 l-23 -489q0 -139 76 -139q64 0 102 93.5t38 244.5q0 161 -67 284.5t-188.5 188.5t-277.5 65q-202 0 -351 -83t-228.5 -239.5t-79.5 -361.5q0 -276 147.5 -423.5t427.5 -147.5q106 0 233 23.5t250 68.5v-192q-214 -91 -475 -91q-380 0 -592.5 200t-212.5 556zM711 627 q0 -211 172 -211q90 0 137 63.5t57 206.5l13 221q-51 11 -115 11q-125 0 -194.5 -78t-69.5 -213z" /> -<glyph unicode="A" horiz-adv-x="1413" d="M0 0l516 1468h379l518 -1468h-334l-106 348h-533l-106 -348h-334zM518 608h381q-147 473 -165.5 535t-26.5 98q-33 -128 -189 -633z" /> -<glyph unicode="B" horiz-adv-x="1376" d="M184 0v1462h455q311 0 451.5 -88.5t140.5 -281.5q0 -131 -61.5 -215t-163.5 -101v-10q139 -31 200.5 -116t61.5 -226q0 -200 -144.5 -312t-392.5 -112h-547zM494 256h202q128 0 189 49t61 150q0 182 -260 182h-192v-381zM494 883h180q126 0 182.5 39t56.5 129 q0 84 -61.5 120.5t-194.5 36.5h-163v-325z" /> -<glyph unicode="C" horiz-adv-x="1305" d="M119 729q0 228 83 399.5t238.5 263t364.5 91.5q213 0 428 -103l-100 -252q-82 39 -165 68t-163 29q-175 0 -271 -131.5t-96 -366.5q0 -489 367 -489q154 0 373 77v-260q-180 -75 -402 -75q-319 0 -488 193.5t-169 555.5z" /> -<glyph unicode="D" horiz-adv-x="1516" d="M184 0v1462h459q358 0 556 -189t198 -528q0 -361 -205.5 -553t-593.5 -192h-414zM494 256h133q448 0 448 481q0 471 -416 471h-165v-952z" /> -<glyph unicode="E" horiz-adv-x="1147" d="M184 0v1462h842v-254h-532v-321h495v-254h-495v-377h532v-256h-842z" /> -<glyph unicode="F" horiz-adv-x="1124" d="M184 0v1462h838v-254h-533v-377h496v-253h-496v-578h-305z" /> -<glyph unicode="G" horiz-adv-x="1483" d="M119 733q0 354 202.5 552t561.5 198q225 0 434 -90l-103 -248q-160 80 -333 80q-201 0 -322 -135t-121 -363q0 -238 97.5 -363.5t283.5 -125.5q97 0 197 20v305h-277v258h580v-758q-141 -46 -265.5 -64.5t-254.5 -18.5q-331 0 -505.5 194.5t-174.5 558.5z" /> -<glyph unicode="H" horiz-adv-x="1567" d="M184 0v1462h310v-573h579v573h309v-1462h-309v631h-579v-631h-310z" /> -<glyph unicode="I" horiz-adv-x="678" d="M184 0v1462h310v-1462h-310z" /> -<glyph unicode="J" horiz-adv-x="678" d="M-152 -150q80 -20 146 -20q102 0 146 63.5t44 198.5v1370h310v-1368q0 -256 -117 -390t-346 -134q-105 0 -183 22v258z" /> -<glyph unicode="K" horiz-adv-x="1360" d="M184 0v1462h310v-669l122 172l396 497h344l-510 -647l514 -815h-352l-383 616l-131 -94v-522h-310z" /> -<glyph unicode="L" horiz-adv-x="1157" d="M184 0v1462h310v-1206h593v-256h-903z" /> -<glyph unicode="M" horiz-adv-x="1931" d="M184 0v1462h422l346 -1118h6l367 1118h422v-1462h-289v692q0 49 1.5 113t13.5 340h-9l-377 -1145h-284l-352 1147h-9q19 -350 19 -467v-680h-277z" /> -<glyph unicode="N" horiz-adv-x="1665" d="M184 0v1462h391l635 -1095h7q-15 285 -15 403v692h279v-1462h-394l-636 1106h-9q19 -293 19 -418v-688h-277z" /> -<glyph unicode="O" horiz-adv-x="1630" d="M119 735q0 365 180.5 557.5t517.5 192.5t515.5 -194t178.5 -558q0 -363 -180 -558t-516 -195t-516 195t-180 560zM444 733q0 -245 93 -369t278 -124q371 0 371 493q0 494 -369 494q-185 0 -279 -124.5t-94 -369.5z" /> -<glyph unicode="P" horiz-adv-x="1286" d="M184 0v1462h467q266 0 404.5 -114.5t138.5 -341.5q0 -236 -147.5 -361t-419.5 -125h-133v-520h-310zM494 774h102q143 0 214 56.5t71 164.5q0 109 -59.5 161t-186.5 52h-141v-434z" /> -<glyph unicode="Q" horiz-adv-x="1630" d="M119 735q0 365 180.5 557.5t517.5 192.5t515.5 -194t178.5 -558q0 -258 -91.5 -432.5t-268.5 -255.5l352 -393h-397l-268 328h-23q-336 0 -516 195t-180 560zM444 733q0 -245 93 -369t278 -124q371 0 371 493q0 494 -369 494q-185 0 -279 -124.5t-94 -369.5z" /> -<glyph unicode="R" horiz-adv-x="1352" d="M184 0v1462h426q298 0 441 -108.5t143 -329.5q0 -129 -71 -229.5t-201 -157.5q330 -493 430 -637h-344l-349 561h-165v-561h-310zM494 813h100q147 0 217 49t70 154q0 104 -71.5 148t-221.5 44h-94v-395z" /> -<glyph unicode="S" horiz-adv-x="1128" d="M94 68v288q148 -66 250.5 -93t187.5 -27q102 0 156.5 39t54.5 116q0 43 -24 76.5t-70.5 64.5t-189.5 99q-134 63 -201 121t-107 135t-40 180q0 194 131.5 305t363.5 111q114 0 217.5 -27t216.5 -76l-100 -241q-117 48 -193.5 67t-150.5 19q-88 0 -135 -41t-47 -107 q0 -41 19 -71.5t60.5 -59t196.5 -102.5q205 -98 281 -196.5t76 -241.5q0 -198 -142.5 -312t-396.5 -114q-234 0 -414 88z" /> -<glyph unicode="T" horiz-adv-x="1186" d="M41 1204v258h1104v-258h-397v-1204h-310v1204h-397z" /> -<glyph unicode="U" horiz-adv-x="1548" d="M174 520v942h309v-895q0 -169 68 -248t225 -79q152 0 220.5 79.5t68.5 249.5v893h309v-946q0 -162 -72.5 -284t-209.5 -187t-324 -65q-282 0 -438 144.5t-156 395.5z" /> -<glyph unicode="V" horiz-adv-x="1331" d="M0 1462h313l275 -870q23 -77 47.5 -179.5t30.5 -142.5q11 92 75 322l277 870h313l-497 -1462h-338z" /> -<glyph unicode="W" horiz-adv-x="1980" d="M0 1462h305l187 -798q49 -221 71 -383q6 57 27.5 176.5t40.5 185.5l213 819h293l213 -819q14 -55 35 -168t32 -194q10 78 32 194.5t40 188.5l186 798h305l-372 -1462h-353l-198 768q-11 41 -37.5 169.5t-30.5 172.5q-6 -54 -30 -173.5t-37 -170.5l-197 -766h-352z" /> -<glyph unicode="X" horiz-adv-x="1366" d="M0 0l485 754l-454 708h342l315 -526l309 526h334l-459 -725l494 -737h-354l-340 553l-340 -553h-332z" /> -<glyph unicode="Y" horiz-adv-x="1278" d="M0 1462h336l303 -602l305 602h334l-485 -893v-569h-308v559z" /> -<glyph unicode="Z" horiz-adv-x="1186" d="M49 0v201l701 1005h-682v256h1050v-200l-700 -1006h719v-256h-1088z" /> -<glyph unicode="[" horiz-adv-x="678" d="M143 -324v1786h484v-211h-224v-1364h224v-211h-484z" /> -<glyph unicode="\" horiz-adv-x="846" d="M12 1462h277l545 -1462h-277z" /> -<glyph unicode="]" horiz-adv-x="678" d="M51 -113h223v1364h-223v211h484v-1786h-484v211z" /> -<glyph unicode="^" horiz-adv-x="1090" d="M8 520l438 950h144l495 -950h-239l-322 643l-280 -643h-236z" /> -<glyph unicode="_" horiz-adv-x="842" d="M-4 -184h850v-140h-850v140z" /> -<glyph unicode="`" horiz-adv-x="1243" d="M332 1548v21h342q63 -101 235 -301v-27h-202q-63 44 -185 142.5t-190 164.5z" /> -<glyph unicode="a" horiz-adv-x="1237" d="M86 334q0 178 124.5 262.5t375.5 93.5l194 6v49q0 170 -174 170q-134 0 -315 -81l-101 206q193 101 428 101q225 0 345 -98t120 -298v-745h-213l-59 152h-8q-77 -97 -158.5 -134.5t-212.5 -37.5q-161 0 -253.5 92t-92.5 262zM399 332q0 -129 148 -129q106 0 169.5 61 t63.5 162v92l-118 -4q-133 -4 -198 -48t-65 -134z" /> -<glyph unicode="b" horiz-adv-x="1296" d="M160 0v1556h305v-362q0 -69 -12 -221h12q107 166 317 166q198 0 310 -154.5t112 -423.5q0 -277 -115.5 -429t-314.5 -152q-197 0 -309 143h-21l-51 -123h-233zM465 563q0 -180 53.5 -258t169.5 -78q94 0 149.5 86.5t55.5 251.5t-56 247.5t-153 82.5q-113 0 -165 -69.5 t-54 -229.5v-33z" /> -<glyph unicode="c" horiz-adv-x="1053" d="M92 553q0 285 142 435.5t407 150.5q194 0 348 -76l-90 -236q-72 29 -134 47.5t-124 18.5q-238 0 -238 -338q0 -328 238 -328q88 0 163 23.5t150 73.5v-261q-74 -47 -149.5 -65t-190.5 -18q-522 0 -522 573z" /> -<glyph unicode="d" horiz-adv-x="1296" d="M92 557q0 275 114.5 428.5t315.5 153.5q211 0 322 -164h10q-23 125 -23 223v358h306v-1556h-234l-59 145h-13q-104 -165 -317 -165q-197 0 -309.5 153t-112.5 424zM401 553q0 -165 57 -247.5t163 -82.5q117 0 171.5 68t59.5 231v33q0 180 -55.5 258t-180.5 78 q-102 0 -158.5 -86.5t-56.5 -251.5z" /> -<glyph unicode="e" horiz-adv-x="1210" d="M92 551q0 281 140.5 434.5t388.5 153.5q237 0 369 -135t132 -373v-148h-721q5 -130 77 -203t202 -73q101 0 191 21t188 67v-236q-80 -40 -171 -59.5t-222 -19.5q-270 0 -422 149t-152 422zM408 686h428q-2 113 -59 174.5t-154 61.5t-152 -61.5t-63 -174.5z" /> -<glyph unicode="f" horiz-adv-x="793" d="M41 889v147l168 82v82q0 191 94 279t301 88q158 0 281 -47l-78 -224q-92 29 -170 29q-65 0 -94 -38.5t-29 -98.5v-70h264v-229h-264v-889h-305v889h-168z" /> -<glyph unicode="g" horiz-adv-x="1157" d="M6 -182q0 101 63 169t185 97q-47 20 -82 65.5t-35 96.5q0 64 37 106.5t107 83.5q-88 38 -139.5 122t-51.5 198q0 183 119 283t340 100q47 0 111.5 -8.5t82.5 -12.5h390v-155l-175 -45q48 -75 48 -168q0 -180 -125.5 -280.5t-348.5 -100.5l-55 3l-45 5q-47 -36 -47 -80 q0 -66 168 -66h190q184 0 280.5 -79t96.5 -232q0 -196 -163.5 -304t-469.5 -108q-234 0 -357.5 81.5t-123.5 228.5zM270 -158q0 -63 60.5 -99t169.5 -36q164 0 257 45t93 123q0 63 -55 87t-170 24h-158q-84 0 -140.5 -39.5t-56.5 -104.5zM381 752q0 -91 41.5 -144t126.5 -53 q86 0 126 53t40 144q0 202 -166 202q-168 0 -168 -202z" /> -<glyph unicode="h" horiz-adv-x="1346" d="M160 0v1556h305v-317q0 -37 -7 -174l-7 -90h16q102 164 324 164q197 0 299 -106t102 -304v-729h-305v653q0 242 -180 242q-128 0 -185 -87t-57 -282v-526h-305z" /> -<glyph unicode="i" horiz-adv-x="625" d="M147 1407q0 149 166 149t166 -149q0 -71 -41.5 -110.5t-124.5 -39.5q-166 0 -166 150zM160 0v1118h305v-1118h-305z" /> -<glyph unicode="j" horiz-adv-x="625" d="M-131 -227q70 -19 143 -19q77 0 112.5 43t35.5 127v1194h305v-1239q0 -178 -103 -274.5t-292 -96.5q-117 0 -201 25v240zM147 1407q0 149 166 149t166 -149q0 -71 -41.5 -110.5t-124.5 -39.5q-166 0 -166 150z" /> -<glyph unicode="k" horiz-adv-x="1270" d="M160 0v1556h305v-694l-16 -254h4l133 170l313 340h344l-444 -485l471 -633h-352l-322 453l-131 -105v-348h-305z" /> -<glyph unicode="l" horiz-adv-x="625" d="M160 0v1556h305v-1556h-305z" /> -<glyph unicode="m" horiz-adv-x="2011" d="M160 0v1118h233l41 -143h17q45 77 130 120.5t195 43.5q251 0 340 -164h27q45 78 132.5 121t197.5 43q190 0 287.5 -97.5t97.5 -312.5v-729h-306v653q0 121 -40.5 181.5t-127.5 60.5q-112 0 -167.5 -80t-55.5 -254v-561h-305v653q0 121 -40.5 181.5t-127.5 60.5 q-117 0 -170 -86t-53 -283v-526h-305z" /> -<glyph unicode="n" horiz-adv-x="1346" d="M160 0v1118h233l41 -143h17q51 81 140.5 122.5t203.5 41.5q195 0 296 -105.5t101 -304.5v-729h-305v653q0 121 -43 181.5t-137 60.5q-128 0 -185 -85.5t-57 -283.5v-526h-305z" /> -<glyph unicode="o" horiz-adv-x="1268" d="M92 561q0 274 143 426t402 152q161 0 284 -70t189 -201t66 -307q0 -273 -144 -427t-401 -154q-161 0 -284 70.5t-189 202.5t-66 308zM403 561q0 -166 54.5 -251t177.5 -85q122 0 175.5 84.5t53.5 251.5q0 166 -54 249t-177 83q-122 0 -176 -82.5t-54 -249.5z" /> -<glyph unicode="p" horiz-adv-x="1296" d="M160 -492v1610h248l43 -145h14q107 166 317 166q198 0 310 -153t112 -425q0 -179 -52.5 -311t-149.5 -201t-228 -69q-197 0 -309 143h-16q16 -140 16 -162v-453h-305zM465 563q0 -180 53.5 -258t169.5 -78q205 0 205 338q0 165 -50.5 247.5t-158.5 82.5 q-113 0 -165 -69.5t-54 -229.5v-33z" /> -<glyph unicode="q" horiz-adv-x="1296" d="M92 557q0 274 114.5 428t313.5 154q106 0 185 -40t139 -124h8l27 143h258v-1610h-306v469q0 61 13 168h-13q-49 -81 -130 -123t-187 -42q-198 0 -310 152.5t-112 424.5zM403 553q0 -168 53.5 -251t166.5 -83q116 0 170 66.5t59 232.5v37q0 180 -55.5 258t-178.5 78 q-215 0 -215 -338z" /> -<glyph unicode="r" horiz-adv-x="930" d="M160 0v1118h231l45 -188h15q52 94 140.5 151.5t192.5 57.5q62 0 103 -9l-23 -286q-37 10 -90 10q-146 0 -227.5 -75t-81.5 -210v-569h-305z" /> -<glyph unicode="s" horiz-adv-x="1018" d="M92 827q0 149 115.5 230.5t327.5 81.5q202 0 393 -88l-92 -220q-84 36 -157 59t-149 23q-135 0 -135 -73q0 -41 43.5 -71t190.5 -89q131 -53 192 -99t90 -106t29 -143q0 -172 -119.5 -262t-357.5 -90q-122 0 -208 16.5t-161 48.5v252q85 -40 191.5 -67t187.5 -27 q166 0 166 96q0 36 -22 58.5t-76 51t-144 66.5q-129 54 -189.5 100t-88 105.5t-27.5 146.5z" /> -<glyph unicode="t" horiz-adv-x="889" d="M47 889v129l168 102l88 236h195v-238h313v-229h-313v-539q0 -65 36.5 -96t96.5 -31q80 0 192 35v-227q-114 -51 -280 -51q-183 0 -266.5 92.5t-83.5 277.5v539h-146z" /> -<glyph unicode="u" horiz-adv-x="1346" d="M154 389v729h305v-653q0 -121 43 -181.5t137 -60.5q128 0 185 85.5t57 283.5v526h305v-1118h-234l-41 143h-16q-49 -78 -139 -120.5t-205 -42.5q-197 0 -297 105.5t-100 303.5z" /> -<glyph unicode="v" horiz-adv-x="1165" d="M0 1118h319l216 -637q36 -121 45 -229h6q5 96 45 229l215 637h319l-426 -1118h-313z" /> -<glyph unicode="w" horiz-adv-x="1753" d="M20 1118h304l129 -495q31 -133 63 -367h6q4 76 35 241l16 85l138 536h336l131 -536q4 -22 12.5 -65t16.5 -91.5t14.5 -95t7.5 -74.5h6q9 72 32 197.5t33 169.5l134 495h299l-322 -1118h-332l-86 391l-116 494h-7l-204 -885h-328z" /> -<glyph unicode="x" horiz-adv-x="1184" d="M10 0l379 571l-360 547h346l217 -356l219 356h346l-364 -547l381 -571h-347l-235 383l-236 -383h-346z" /> -<glyph unicode="y" horiz-adv-x="1165" d="M0 1118h334l211 -629q27 -82 37 -194h6q11 103 43 194l207 629h327l-473 -1261q-65 -175 -185.5 -262t-281.5 -87q-79 0 -155 17v242q55 -13 120 -13q81 0 141.5 49.5t94.5 149.5l18 55z" /> -<glyph unicode="z" horiz-adv-x="999" d="M55 0v180l518 705h-487v233h834v-198l-504 -687h522v-233h-883z" /> -<glyph unicode="{" horiz-adv-x="807" d="M31 449v239q126 0 191 44t65 126v8v318q0 153 97 215.5t341 62.5v-225q-99 -3 -136.5 -38t-37.5 -103v-299q-6 -188 -234 -222v-12q234 -35 234 -212v-9v-299q0 -68 37 -103t137 -38v-226q-244 0 -341 62.5t-97 216.5v315q0 87 -65.5 133t-190.5 46z" /> -<glyph unicode="|" horiz-adv-x="1128" d="M455 -465v2015h219v-2015h-219z" /> -<glyph unicode="}" horiz-adv-x="807" d="M82 -98q99 2 136.5 36t37.5 105v299v11q0 86 59 139.5t174 70.5v12q-227 34 -233 222v299q0 70 -37 104t-137 37v225q167 0 262 -26.5t135.5 -84t40.5 -167.5v-318v-10q0 -84 61.5 -126t194.5 -42v-239q-125 0 -190.5 -41t-65.5 -138v-315q0 -112 -41 -169t-135.5 -83.5 t-261.5 -26.5v226z" /> -<glyph unicode="~" d="M88 551v231q103 109 256 109q73 0 137.5 -16t139.5 -48q129 -55 227 -55q53 0 116 32t117 89v-231q-101 -109 -256 -109q-66 0 -126 13t-150 50q-131 56 -227 56q-55 0 -117.5 -33.5t-116.5 -87.5z" /> -<glyph unicode="¡" horiz-adv-x="586" d="M117 -369l51 975h244l51 -975h-346zM117 948q0 81 46.5 125.5t127.5 44.5q84 0 130 -44t46 -126q0 -84 -45 -127t-131 -43q-83 0 -128.5 44t-45.5 126z" /> -<glyph unicode="¢" d="M143 741q0 261 104.5 403t315.5 173v166h178v-158q166 -9 299 -74l-90 -235q-72 29 -134 47t-124 18q-121 0 -179 -83.5t-58 -254.5q0 -327 237 -327q82 0 148 15.5t166 60.5v-254q-127 -61 -265 -70v-188h-178v196q-420 59 -420 565z" /> -<glyph unicode="£" d="M82 0v248q103 44 141.5 101t38.5 157v145h-178v219h178v195q0 201 114.5 309.5t323.5 108.5q195 0 390 -82l-93 -230q-157 64 -272 64q-78 0 -120 -44.5t-42 -127.5v-193h375v-219h-375v-143q0 -170 -151 -248h718v-260h-1048z" /> -<glyph unicode="¤" d="M113 1047l147 147l127 -127q91 53 197 53q105 0 196 -55l127 129l150 -143l-129 -129q53 -89 53 -199q0 -107 -53 -199l125 -125l-146 -145l-127 125q-95 -51 -196 -51q-115 0 -199 51l-125 -123l-145 145l127 125q-54 93 -54 197q0 102 54 197zM395 723 q0 -77 54.5 -132.5t134.5 -55.5q81 0 136.5 55t55.5 133q0 80 -56.5 135t-135.5 55q-78 0 -133.5 -56t-55.5 -134z" /> -<glyph unicode="¥" d="M6 1462h316l262 -602l264 602h313l-383 -747h195v-178h-246v-138h246v-178h-246v-221h-287v221h-247v178h247v138h-247v178h190z" /> -<glyph unicode="¦" horiz-adv-x="1128" d="M455 350h219v-815h-219v815zM455 735v815h219v-815h-219z" /> -<glyph unicode="§" horiz-adv-x="995" d="M106 59v207q81 -41 180 -69.5t169 -28.5q194 0 194 117q0 39 -18.5 63t-63.5 49.5t-125 59.5q-183 74 -252 152.5t-69 195.5q0 79 36 144.5t97 105.5q-133 84 -133 233q0 131 111.5 210t293.5 79q170 0 363 -84l-82 -190q-68 32 -138.5 57.5t-148.5 25.5q-81 0 -118 -23 t-37 -71q0 -49 49.5 -86t163.5 -82q163 -64 240 -148.5t77 -193.5q0 -177 -125 -260q62 -40 93.5 -92.5t31.5 -126.5q0 -148 -119.5 -235.5t-320.5 -87.5q-203 0 -349 79zM344 827q0 -67 65 -119t181 -98q78 57 78 146q0 68 -50.5 115t-183.5 96q-37 -14 -63.5 -53.5 t-26.5 -86.5z" /> -<glyph unicode="¨" horiz-adv-x="1243" d="M279 1405q0 65 37.5 100t101.5 35q66 0 103.5 -37t37.5 -98q0 -60 -38 -96.5t-103 -36.5q-64 0 -101.5 35t-37.5 98zM682 1405q0 70 40.5 102.5t100.5 32.5q65 0 103.5 -36t38.5 -99q0 -61 -39 -97t-103 -36q-60 0 -100.5 32.5t-40.5 100.5z" /> -<glyph unicode="©" horiz-adv-x="1704" d="M100 731q0 200 100 375t275 276t377 101q200 0 375 -100t276 -275t101 -377q0 -197 -97 -370t-272 -277t-383 -104q-207 0 -382 103.5t-272.5 276.5t-97.5 371zM242 731q0 -164 82 -305.5t224 -223t304 -81.5q164 0 305.5 82t223 224t81.5 304q0 164 -82 305.5t-224 223 t-304 81.5q-164 0 -305.5 -82t-223 -224t-81.5 -304zM461 733q0 220 110.5 342.5t309.5 122.5q149 0 305 -78l-74 -168q-113 58 -217 58q-97 0 -150 -74t-53 -205q0 -280 203 -280q57 0 123 15t123 44v-191q-120 -57 -252 -57q-204 0 -316 125t-112 346z" /> -<glyph unicode="ª" horiz-adv-x="784" d="M47 975q0 109 82.5 163.5t267.5 63.5l99 4q0 117 -127 117q-81 0 -217 -61l-66 135q66 32 145.5 57t178.5 25q137 0 211.5 -71t74.5 -202v-442h-135l-31 110q-43 -58 -105 -90t-136 -32q-117 0 -179.5 58.5t-62.5 164.5zM252 977q0 -38 23 -56t55 -18q77 0 121.5 41.5 t44.5 106.5v36l-99 -6q-145 -10 -145 -104z" /> -<glyph unicode="«" horiz-adv-x="1260" d="M82 547v26l371 455l219 -119l-279 -348l279 -348l-219 -119zM588 547v26l370 455l220 -119l-279 -348l279 -348l-220 -119z" /> -<glyph unicode="¬" d="M88 612v219h993v-583h-219v364h-774z" /> -<glyph unicode="­" horiz-adv-x="659" d="M61 424v250h537v-250h-537z" /> -<glyph unicode="®" horiz-adv-x="1704" d="M100 731q0 200 100 375t275 276t377 101q200 0 375 -100t276 -275t101 -377q0 -197 -97 -370t-272 -277t-383 -104q-207 0 -382 103.5t-272.5 276.5t-97.5 371zM242 731q0 -164 82 -305.5t224 -223t304 -81.5q164 0 305.5 82t223 224t81.5 304q0 164 -82 305.5t-224 223 t-304 81.5q-164 0 -305.5 -82t-223 -224t-81.5 -304zM543 272v916h264q181 0 265.5 -70t84.5 -213q0 -170 -143 -233l237 -400h-254l-178 338h-47v-338h-229zM772 778h31q66 0 94.5 28.5t28.5 94.5q0 65 -28 92t-97 27h-29v-242z" /> -<glyph unicode="¯" horiz-adv-x="1024" d="M-6 1556v201h1036v-201h-1036z" /> -<glyph unicode="°" horiz-adv-x="877" d="M92 1137q0 92 46 172t126 127t174 47q92 0 172.5 -46t127 -127t46.5 -173q0 -93 -46.5 -173.5t-126.5 -125.5t-173 -45q-145 0 -245.5 99.5t-100.5 244.5zM283 1137q0 -64 44.5 -109t110.5 -45t111 46t45 108q0 63 -45.5 110t-110.5 47q-64 0 -109.5 -46t-45.5 -111z" /> -<glyph unicode="±" d="M88 0v219h993v-219h-993zM88 674v219h387v389h219v-389h387v-219h-387v-385h-219v385h-387z" /> -<glyph unicode="²" horiz-adv-x="776" d="M47 1354q147 129 336 129q137 0 216 -66.5t79 -183.5q0 -85 -47 -160t-176 -192l-105 -95h352v-200h-647v168l224 219q102 100 130.5 144.5t28.5 94.5q0 38 -24 58t-64 20q-81 0 -180 -88z" /> -<glyph unicode="³" horiz-adv-x="776" d="M59 639v190q148 -90 271 -90q143 0 143 107q0 53 -44 79.5t-122 26.5h-112v160h92q83 0 123.5 26t40.5 83q0 38 -25 63t-76 25q-47 0 -89 -19t-99 -59l-101 141q62 47 137.5 78t178.5 31q127 0 208 -64t81 -168q0 -143 -170 -198v-13q94 -20 146 -75t52 -134 q0 -121 -88 -190.5t-274 -69.5q-143 0 -273 70z" /> -<glyph unicode="´" horiz-adv-x="1243" d="M332 1241v27q172 200 235 301h342v-21q-52 -52 -177.5 -154.5t-196.5 -152.5h-203z" /> -<glyph unicode="µ" horiz-adv-x="1352" d="M160 -492v1610h305v-653q0 -121 44 -181.5t138 -60.5q126 0 183 86.5t57 282.5v526h305v-1118h-231l-43 150h-15q-42 -85 -102 -127.5t-148 -42.5q-62 0 -114 23t-84 67l5 -85l5 -157v-320h-305z" /> -<glyph unicode="¶" horiz-adv-x="1341" d="M113 1042q0 260 109 387t341 127h604v-1816h-161v1616h-166v-1616h-162v819q-62 -18 -146 -18q-216 0 -317.5 125t-101.5 376z" /> -<glyph unicode="·" horiz-adv-x="584" d="M117 723q0 84 45 127t131 43q83 0 128.5 -44t45.5 -126q0 -81 -46.5 -125.5t-127.5 -44.5q-84 0 -130 44t-46 126z" /> -<glyph unicode="¸" horiz-adv-x="420" d="M-37 -303q27 -7 72.5 -14t70.5 -7q72 0 72 62q0 83 -166 108l78 154h193l-27 -61q74 -24 118 -74.5t44 -114.5q0 -128 -75.5 -185t-233.5 -57q-78 0 -146 21v168z" /> -<glyph unicode="¹" horiz-adv-x="776" d="M92 1227l301 235h191v-876h-238v446l3 112l5 95q-27 -36 -75 -78l-78 -61z" /> -<glyph unicode="º" horiz-adv-x="795" d="M57 1116q0 169 89.5 266t252.5 97q152 0 245 -98.5t93 -264.5q0 -171 -91.5 -267.5t-250.5 -96.5q-153 0 -245.5 98.5t-92.5 265.5zM260 1116q0 -100 32.5 -150.5t104.5 -50.5t103.5 50.5t31.5 150.5t-31.5 149.5t-103.5 49.5t-104.5 -49.5t-32.5 -149.5z" /> -<glyph unicode="»" horiz-adv-x="1260" d="M82 213l278 348l-278 348l219 119l371 -455v-26l-371 -453zM588 213l278 348l-278 348l219 119l371 -455v-26l-371 -453z" /> -<glyph unicode="¼" horiz-adv-x="1804" d="M46 1227l301 235h191v-876h-238v446l3 112l5 95q-27 -36 -75 -78l-78 -61zM320 0l811 1462h239l-811 -1462h-239zM936 152v154l385 577h236v-563h125v-168h-125v-151h-238v151h-383zM1121 320h198v164q0 86 6 184q-9 -26 -35.5 -80t-41.5 -77z" /> -<glyph unicode="½" horiz-adv-x="1804" d="M46 1227l301 235h191v-876h-238v446l3 112l5 95q-27 -36 -75 -78l-78 -61zM320 0l811 1462h239l-811 -1462h-239zM1061 769q147 129 336 129q137 0 216 -66.5t79 -183.5q0 -85 -47 -160t-176 -192l-105 -95h352v-200h-647v168l224 219q102 100 130.5 144.5t28.5 94.5 q0 38 -24 58t-64 20q-81 0 -180 -88z" /> -<glyph unicode="¾" horiz-adv-x="1804" d="M90 639v190q148 -90 271 -90q143 0 143 107q0 53 -44 79.5t-122 26.5h-112v160h92q83 0 123.5 26t40.5 83q0 38 -25 63t-76 25q-47 0 -89 -19t-99 -59l-101 141q62 47 137.5 78t178.5 31q127 0 208 -64t81 -168q0 -143 -170 -198v-13q94 -20 146 -75t52 -134 q0 -121 -88 -190.5t-274 -69.5q-143 0 -273 70zM391 0l811 1462h239l-811 -1462h-239zM966 152v154l385 577h236v-563h125v-168h-125v-151h-238v151h-383zM1151 320h198v164q0 86 6 184q-9 -26 -35.5 -80t-41.5 -77z" /> -<glyph unicode="¿" horiz-adv-x="977" d="M61 -29q0 108 48.5 187t191.5 184q95 70 121.5 107t26.5 98v59h264v-74q0 -98 -44.5 -169t-152.5 -148q-109 -78 -137.5 -122t-28.5 -107q0 -57 43.5 -94t132.5 -37q79 0 169 29t186 71l102 -221q-98 -56 -221.5 -90.5t-229.5 -34.5q-220 0 -345.5 96.5t-125.5 265.5z M395 948q0 81 46.5 125.5t127.5 44.5q84 0 130 -44t46 -126q0 -84 -45 -127t-131 -43q-83 0 -128.5 44t-45.5 126z" /> -<glyph unicode="À" horiz-adv-x="1413" d="M0 0l516 1468h379l518 -1468h-334l-106 348h-533l-106 -348h-334zM518 608h381q-147 473 -165.5 535t-26.5 98q-33 -128 -189 -633zM338 1886v21h342q63 -101 235 -301v-27h-202q-63 44 -185 142.5t-190 164.5z" /> -<glyph unicode="Á" horiz-adv-x="1413" d="M0 0l516 1468h379l518 -1468h-334l-106 348h-533l-106 -348h-334zM518 608h381q-147 473 -165.5 535t-26.5 98q-33 -128 -189 -633zM541 1579v27q172 200 235 301h342v-21q-52 -52 -177.5 -154.5t-196.5 -152.5h-203z" /> -<glyph unicode="Â" horiz-adv-x="1413" d="M0 0l516 1468h379l518 -1468h-334l-106 348h-533l-106 -348h-334zM518 608h381q-147 473 -165.5 535t-26.5 98q-33 -128 -189 -633zM272 1579v27q189 189 256 301h357q31 -52 107.5 -141.5t148.5 -159.5v-27h-203q-157 93 -234 176q-78 -81 -229 -176h-203z" /> -<glyph unicode="Ã" horiz-adv-x="1413" d="M0 0l516 1468h379l518 -1468h-334l-106 348h-533l-106 -348h-334zM518 608h381q-147 473 -165.5 535t-26.5 98q-33 -128 -189 -633zM293 1577q11 145 82.5 227t189.5 82q41 0 80.5 -16.5t78 -36t75.5 -35.5t73 -16q31 0 59.5 26t41.5 80h149q-11 -145 -83.5 -227 t-188.5 -82q-41 0 -80.5 16.5t-78 36t-75.5 36t-73 16.5q-31 0 -59.5 -26.5t-41.5 -80.5h-149z" /> -<glyph unicode="Ä" horiz-adv-x="1413" d="M0 0l516 1468h379l518 -1468h-334l-106 348h-533l-106 -348h-334zM518 608h381q-147 473 -165.5 535t-26.5 98q-33 -128 -189 -633zM365 1743q0 65 37.5 100t101.5 35q66 0 103.5 -37t37.5 -98q0 -60 -38 -96.5t-103 -36.5q-64 0 -101.5 35t-37.5 98zM768 1743 q0 70 40.5 102.5t100.5 32.5q65 0 103.5 -36t38.5 -99q0 -61 -39 -97t-103 -36q-60 0 -100.5 32.5t-40.5 100.5z" /> -<glyph unicode="Å" horiz-adv-x="1413" d="M0 0l516 1468h379l518 -1468h-334l-106 348h-533l-106 -348h-334zM518 608h381q-147 473 -165.5 535t-26.5 98q-33 -128 -189 -633zM457 1565q0 108 67.5 172.5t180.5 64.5q110 0 182 -66t72 -169q0 -108 -71 -174t-183 -66t-180 64t-68 174zM609 1565q0 -45 24 -71 t72 -26q42 0 69 26t27 71t-27 70.5t-69 25.5t-69 -25.5t-27 -70.5z" /> -<glyph unicode="Æ" horiz-adv-x="1950" d="M0 0l655 1462h1174v-254h-563v-321h526v-254h-526v-377h563v-256h-873v348h-491l-150 -348h-315zM578 608h378v590h-127z" /> -<glyph unicode="Ç" horiz-adv-x="1305" d="M119 729q0 228 83 399.5t238.5 263t364.5 91.5q213 0 428 -103l-100 -252q-82 39 -165 68t-163 29q-175 0 -271 -131.5t-96 -366.5q0 -489 367 -489q154 0 373 77v-260q-180 -75 -402 -75q-319 0 -488 193.5t-169 555.5zM504 -303q27 -7 72.5 -14t70.5 -7q72 0 72 62 q0 83 -166 108l78 154h193l-27 -61q74 -24 118 -74.5t44 -114.5q0 -128 -75.5 -185t-233.5 -57q-78 0 -146 21v168z" /> -<glyph unicode="È" horiz-adv-x="1147" d="M184 0v1462h842v-254h-532v-321h495v-254h-495v-377h532v-256h-842zM259 1886v21h342q63 -101 235 -301v-27h-202q-63 44 -185 142.5t-190 164.5z" /> -<glyph unicode="É" horiz-adv-x="1147" d="M184 0v1462h842v-254h-532v-321h495v-254h-495v-377h532v-256h-842zM424 1579v27q172 200 235 301h342v-21q-52 -52 -177.5 -154.5t-196.5 -152.5h-203z" /> -<glyph unicode="Ê" horiz-adv-x="1147" d="M184 0v1462h842v-254h-532v-321h495v-254h-495v-377h532v-256h-842zM175 1579v27q189 189 256 301h357q31 -52 107.5 -141.5t148.5 -159.5v-27h-203q-157 93 -234 176q-78 -81 -229 -176h-203z" /> -<glyph unicode="Ë" horiz-adv-x="1147" d="M184 0v1462h842v-254h-532v-321h495v-254h-495v-377h532v-256h-842zM272 1743q0 65 37.5 100t101.5 35q66 0 103.5 -37t37.5 -98q0 -60 -38 -96.5t-103 -36.5q-64 0 -101.5 35t-37.5 98zM675 1743q0 70 40.5 102.5t100.5 32.5q65 0 103.5 -36t38.5 -99q0 -61 -39 -97 t-103 -36q-60 0 -100.5 32.5t-40.5 100.5z" /> -<glyph unicode="Ì" horiz-adv-x="678" d="M184 0v1462h310v-1462h-310zM-58 1886v21h342q63 -101 235 -301v-27h-202q-63 44 -185 142.5t-190 164.5z" /> -<glyph unicode="Í" horiz-adv-x="678" d="M184 0v1462h310v-1462h-310zM167 1579v27q172 200 235 301h342v-21q-52 -52 -177.5 -154.5t-196.5 -152.5h-203z" /> -<glyph unicode="Î" horiz-adv-x="678" d="M184 0v1462h310v-1462h-310zM-96 1579v27q189 189 256 301h357q31 -52 107.5 -141.5t148.5 -159.5v-27h-203q-157 93 -234 176q-78 -81 -229 -176h-203z" /> -<glyph unicode="Ï" horiz-adv-x="678" d="M184 0v1462h310v-1462h-310zM-3 1743q0 65 37.5 100t101.5 35q66 0 103.5 -37t37.5 -98q0 -60 -38 -96.5t-103 -36.5q-64 0 -101.5 35t-37.5 98zM400 1743q0 70 40.5 102.5t100.5 32.5q65 0 103.5 -36t38.5 -99q0 -61 -39 -97t-103 -36q-60 0 -100.5 32.5t-40.5 100.5z " /> -<glyph unicode="Ð" horiz-adv-x="1516" d="M47 596v254h137v612h459q358 0 556 -189t198 -528q0 -361 -205.5 -553t-593.5 -192h-414v596h-137zM494 256h131q450 0 450 481q0 232 -104 351.5t-314 119.5h-163v-358h237v-254h-237v-340z" /> -<glyph unicode="Ñ" horiz-adv-x="1665" d="M184 0v1462h391l635 -1095h7q-15 285 -15 403v692h279v-1462h-394l-636 1106h-9q19 -293 19 -418v-688h-277zM418 1577q11 145 82.5 227t189.5 82q41 0 80.5 -16.5t78 -36t75.5 -35.5t73 -16q31 0 59.5 26t41.5 80h149q-11 -145 -83.5 -227t-188.5 -82q-41 0 -80.5 16.5 t-78 36t-75.5 36t-73 16.5q-31 0 -59.5 -26.5t-41.5 -80.5h-149z" /> -<glyph unicode="Ò" horiz-adv-x="1630" d="M119 735q0 365 180.5 557.5t517.5 192.5t515.5 -194t178.5 -558q0 -363 -180 -558t-516 -195t-516 195t-180 560zM444 733q0 -245 93 -369t278 -124q371 0 371 493q0 494 -369 494q-185 0 -279 -124.5t-94 -369.5zM449 1886v21h342q63 -101 235 -301v-27h-202 q-63 44 -185 142.5t-190 164.5z" /> -<glyph unicode="Ó" horiz-adv-x="1630" d="M119 735q0 365 180.5 557.5t517.5 192.5t515.5 -194t178.5 -558q0 -363 -180 -558t-516 -195t-516 195t-180 560zM444 733q0 -245 93 -369t278 -124q371 0 371 493q0 494 -369 494q-185 0 -279 -124.5t-94 -369.5zM658 1579v27q172 200 235 301h342v-21 q-52 -52 -177.5 -154.5t-196.5 -152.5h-203z" /> -<glyph unicode="Ô" horiz-adv-x="1630" d="M119 735q0 365 180.5 557.5t517.5 192.5t515.5 -194t178.5 -558q0 -363 -180 -558t-516 -195t-516 195t-180 560zM444 733q0 -245 93 -369t278 -124q371 0 371 493q0 494 -369 494q-185 0 -279 -124.5t-94 -369.5zM381 1579v27q189 189 256 301h357q31 -52 107.5 -141.5 t148.5 -159.5v-27h-203q-157 93 -234 176q-78 -81 -229 -176h-203z" /> -<glyph unicode="Õ" horiz-adv-x="1630" d="M119 735q0 365 180.5 557.5t517.5 192.5t515.5 -194t178.5 -558q0 -363 -180 -558t-516 -195t-516 195t-180 560zM444 733q0 -245 93 -369t278 -124q371 0 371 493q0 494 -369 494q-185 0 -279 -124.5t-94 -369.5zM402 1577q11 145 82.5 227t189.5 82q41 0 80.5 -16.5 t78 -36t75.5 -35.5t73 -16q31 0 59.5 26t41.5 80h149q-11 -145 -83.5 -227t-188.5 -82q-41 0 -80.5 16.5t-78 36t-75.5 36t-73 16.5q-31 0 -59.5 -26.5t-41.5 -80.5h-149z" /> -<glyph unicode="Ö" horiz-adv-x="1630" d="M119 735q0 365 180.5 557.5t517.5 192.5t515.5 -194t178.5 -558q0 -363 -180 -558t-516 -195t-516 195t-180 560zM444 733q0 -245 93 -369t278 -124q371 0 371 493q0 494 -369 494q-185 0 -279 -124.5t-94 -369.5zM474 1743q0 65 37.5 100t101.5 35q66 0 103.5 -37 t37.5 -98q0 -60 -38 -96.5t-103 -36.5q-64 0 -101.5 35t-37.5 98zM877 1743q0 70 40.5 102.5t100.5 32.5q65 0 103.5 -36t38.5 -99q0 -61 -39 -97t-103 -36q-60 0 -100.5 32.5t-40.5 100.5z" /> -<glyph unicode="×" d="M129 1024l152 154l301 -299l305 299l153 -150l-305 -305l301 -303l-149 -152l-305 301l-301 -299l-150 152l297 301z" /> -<glyph unicode="Ø" horiz-adv-x="1630" d="M119 735q0 365 180.5 557.5t517.5 192.5q198 0 344 -70l84 125l160 -104l-88 -131q194 -194 194 -572q0 -363 -180 -558t-516 -195q-197 0 -336 65l-90 -135l-162 108l90 136q-198 194 -198 581zM444 733q0 -191 56 -307l506 756q-84 45 -189 45q-185 0 -279 -124.5 t-94 -369.5zM635 279q76 -39 180 -39q371 0 371 493q0 180 -51 297z" /> -<glyph unicode="Ù" horiz-adv-x="1548" d="M174 520v942h309v-895q0 -169 68 -248t225 -79q152 0 220.5 79.5t68.5 249.5v893h309v-946q0 -162 -72.5 -284t-209.5 -187t-324 -65q-282 0 -438 144.5t-156 395.5zM375 1886v21h342q63 -101 235 -301v-27h-202q-63 44 -185 142.5t-190 164.5z" /> -<glyph unicode="Ú" horiz-adv-x="1548" d="M174 520v942h309v-895q0 -169 68 -248t225 -79q152 0 220.5 79.5t68.5 249.5v893h309v-946q0 -162 -72.5 -284t-209.5 -187t-324 -65q-282 0 -438 144.5t-156 395.5zM602 1579v27q172 200 235 301h342v-21q-52 -52 -177.5 -154.5t-196.5 -152.5h-203z" /> -<glyph unicode="Û" horiz-adv-x="1548" d="M174 520v942h309v-895q0 -169 68 -248t225 -79q152 0 220.5 79.5t68.5 249.5v893h309v-946q0 -162 -72.5 -284t-209.5 -187t-324 -65q-282 0 -438 144.5t-156 395.5zM340 1579v27q189 189 256 301h357q31 -52 107.5 -141.5t148.5 -159.5v-27h-203q-157 93 -234 176 q-78 -81 -229 -176h-203z" /> -<glyph unicode="Ü" horiz-adv-x="1548" d="M174 520v942h309v-895q0 -169 68 -248t225 -79q152 0 220.5 79.5t68.5 249.5v893h309v-946q0 -162 -72.5 -284t-209.5 -187t-324 -65q-282 0 -438 144.5t-156 395.5zM433 1743q0 65 37.5 100t101.5 35q66 0 103.5 -37t37.5 -98q0 -60 -38 -96.5t-103 -36.5 q-64 0 -101.5 35t-37.5 98zM836 1743q0 70 40.5 102.5t100.5 32.5q65 0 103.5 -36t38.5 -99q0 -61 -39 -97t-103 -36q-60 0 -100.5 32.5t-40.5 100.5z" /> -<glyph unicode="Ý" horiz-adv-x="1278" d="M0 1462h336l303 -602l305 602h334l-485 -893v-569h-308v559zM461 1579v27q172 200 235 301h342v-21q-52 -52 -177.5 -154.5t-196.5 -152.5h-203z" /> -<glyph unicode="Þ" horiz-adv-x="1286" d="M184 0v1462h310v-229h178q254 0 388 -119t134 -344q0 -229 -142.5 -353t-404.5 -124h-153v-293h-310zM494 543h100q145 0 216 52.5t71 174.5q0 107 -63.5 159t-199.5 52h-124v-438z" /> -<glyph unicode="ß" horiz-adv-x="1456" d="M160 0v1139q0 201 146.5 314.5t404.5 113.5q244 0 391 -88.5t147 -237.5q0 -64 -21 -112.5t-53 -86.5t-69 -67t-69 -53t-53 -45t-21 -43q0 -27 26.5 -53t92.5 -66q146 -91 198.5 -140t78 -110t25.5 -139q0 -172 -116.5 -259t-343.5 -87q-99 0 -171 14.5t-132 48.5v242 q53 -36 135.5 -61t146.5 -25q168 0 168 123q0 41 -16 66.5t-57 55.5t-115 72q-126 72 -175 131.5t-49 140.5q0 64 35 117t105 102q77 55 108 95t31 86q0 60 -63.5 100.5t-163.5 40.5q-116 0 -181 -52.5t-65 -148.5v-1128h-305z" /> -<glyph unicode="à" horiz-adv-x="1237" d="M86 334q0 178 124.5 262.5t375.5 93.5l194 6v49q0 170 -174 170q-134 0 -315 -81l-101 206q193 101 428 101q225 0 345 -98t120 -298v-745h-213l-59 152h-8q-77 -97 -158.5 -134.5t-212.5 -37.5q-161 0 -253.5 92t-92.5 262zM399 332q0 -129 148 -129q106 0 169.5 61 t63.5 162v92l-118 -4q-133 -4 -198 -48t-65 -134zM239 1548v21h342q63 -101 235 -301v-27h-202q-63 44 -185 142.5t-190 164.5z" /> -<glyph unicode="á" horiz-adv-x="1237" d="M86 334q0 178 124.5 262.5t375.5 93.5l194 6v49q0 170 -174 170q-134 0 -315 -81l-101 206q193 101 428 101q225 0 345 -98t120 -298v-745h-213l-59 152h-8q-77 -97 -158.5 -134.5t-212.5 -37.5q-161 0 -253.5 92t-92.5 262zM399 332q0 -129 148 -129q106 0 169.5 61 t63.5 162v92l-118 -4q-133 -4 -198 -48t-65 -134zM441 1241v27q172 200 235 301h342v-21q-52 -52 -177.5 -154.5t-196.5 -152.5h-203z" /> -<glyph unicode="â" horiz-adv-x="1237" d="M86 334q0 178 124.5 262.5t375.5 93.5l194 6v49q0 170 -174 170q-134 0 -315 -81l-101 206q193 101 428 101q225 0 345 -98t120 -298v-745h-213l-59 152h-8q-77 -97 -158.5 -134.5t-212.5 -37.5q-161 0 -253.5 92t-92.5 262zM399 332q0 -129 148 -129q106 0 169.5 61 t63.5 162v92l-118 -4q-133 -4 -198 -48t-65 -134zM177 1240v27q189 189 256 301h357q31 -52 107.5 -141.5t148.5 -159.5v-27h-203q-157 93 -234 176q-78 -81 -229 -176h-203z" /> -<glyph unicode="ã" horiz-adv-x="1237" d="M86 334q0 178 124.5 262.5t375.5 93.5l194 6v49q0 170 -174 170q-134 0 -315 -81l-101 206q193 101 428 101q225 0 345 -98t120 -298v-745h-213l-59 152h-8q-77 -97 -158.5 -134.5t-212.5 -37.5q-161 0 -253.5 92t-92.5 262zM399 332q0 -129 148 -129q106 0 169.5 61 t63.5 162v92l-118 -4q-133 -4 -198 -48t-65 -134zM217 1239q11 145 82.5 227t189.5 82q41 0 80.5 -16.5t78 -36t75.5 -35.5t73 -16q31 0 59.5 26t41.5 80h149q-11 -145 -83.5 -227t-188.5 -82q-41 0 -80.5 16.5t-78 36t-75.5 36t-73 16.5q-31 0 -59.5 -26.5t-41.5 -80.5 h-149z" /> -<glyph unicode="ä" horiz-adv-x="1237" d="M86 334q0 178 124.5 262.5t375.5 93.5l194 6v49q0 170 -174 170q-134 0 -315 -81l-101 206q193 101 428 101q225 0 345 -98t120 -298v-745h-213l-59 152h-8q-77 -97 -158.5 -134.5t-212.5 -37.5q-161 0 -253.5 92t-92.5 262zM399 332q0 -129 148 -129q106 0 169.5 61 t63.5 162v92l-118 -4q-133 -4 -198 -48t-65 -134zM285 1405q0 65 37.5 100t101.5 35q66 0 103.5 -37t37.5 -98q0 -60 -38 -96.5t-103 -36.5q-64 0 -101.5 35t-37.5 98zM688 1405q0 70 40.5 102.5t100.5 32.5q65 0 103.5 -36t38.5 -99q0 -61 -39 -97t-103 -36 q-60 0 -100.5 32.5t-40.5 100.5z" /> -<glyph unicode="å" horiz-adv-x="1237" d="M86 334q0 178 124.5 262.5t375.5 93.5l194 6v49q0 170 -174 170q-134 0 -315 -81l-101 206q193 101 428 101q225 0 345 -98t120 -298v-745h-213l-59 152h-8q-77 -97 -158.5 -134.5t-212.5 -37.5q-161 0 -253.5 92t-92.5 262zM399 332q0 -129 148 -129q106 0 169.5 61 t63.5 162v92l-118 -4q-133 -4 -198 -48t-65 -134zM381 1477q0 108 67.5 172.5t180.5 64.5q110 0 182 -66t72 -169q0 -108 -71 -174t-183 -66t-180 64t-68 174zM533 1477q0 -45 24 -71t72 -26q42 0 69 26t27 71t-27 70.5t-69 25.5t-69 -25.5t-27 -70.5z" /> -<glyph unicode="æ" horiz-adv-x="1878" d="M86 334q0 178 121 262.5t362 93.5l191 6v84q0 69 -44.5 102t-121.5 33q-140 0 -305 -77l-99 202q189 101 422 101q227 0 342 -131q66 64 152.5 96.5t206.5 32.5q221 0 349 -137.5t128 -370.5v-148h-723q5 -130 77 -203t202 -73q196 0 380 88v-236q-79 -39 -171 -59 t-226 -20q-137 0 -249.5 50.5t-184.5 155.5q-98 -117 -196.5 -161.5t-256.5 -44.5q-161 0 -258.5 94.5t-97.5 259.5zM399 332q0 -129 140 -129q101 0 161 61t60 162v92l-113 -4q-124 -4 -186 -47.5t-62 -134.5zM1073 686h430q-2 112 -55 174t-141 62q-217 0 -234 -236z" /> -<glyph unicode="ç" horiz-adv-x="1053" d="M92 553q0 285 142 435.5t407 150.5q194 0 348 -76l-90 -236q-72 29 -134 47.5t-124 18.5q-238 0 -238 -338q0 -328 238 -328q88 0 163 23.5t150 73.5v-261q-74 -47 -149.5 -65t-190.5 -18q-522 0 -522 573zM350 -303q27 -7 72.5 -14t70.5 -7q72 0 72 62q0 83 -166 108 l78 154h193l-27 -61q74 -24 118 -74.5t44 -114.5q0 -128 -75.5 -185t-233.5 -57q-78 0 -146 21v168z" /> -<glyph unicode="è" horiz-adv-x="1210" d="M92 551q0 281 140.5 434.5t388.5 153.5q237 0 369 -135t132 -373v-148h-721q5 -130 77 -203t202 -73q101 0 191 21t188 67v-236q-80 -40 -171 -59.5t-222 -19.5q-270 0 -422 149t-152 422zM408 686h428q-2 113 -59 174.5t-154 61.5t-152 -61.5t-63 -174.5zM245 1548v21 h342q63 -101 235 -301v-27h-202q-63 44 -185 142.5t-190 164.5z" /> -<glyph unicode="é" horiz-adv-x="1210" d="M92 551q0 281 140.5 434.5t388.5 153.5q237 0 369 -135t132 -373v-148h-721q5 -130 77 -203t202 -73q101 0 191 21t188 67v-236q-80 -40 -171 -59.5t-222 -19.5q-270 0 -422 149t-152 422zM408 686h428q-2 113 -59 174.5t-154 61.5t-152 -61.5t-63 -174.5zM447 1241v27 q172 200 235 301h342v-21q-52 -52 -177.5 -154.5t-196.5 -152.5h-203z" /> -<glyph unicode="ê" horiz-adv-x="1210" d="M92 551q0 281 140.5 434.5t388.5 153.5q237 0 369 -135t132 -373v-148h-721q5 -130 77 -203t202 -73q101 0 191 21t188 67v-236q-80 -40 -171 -59.5t-222 -19.5q-270 0 -422 149t-152 422zM408 686h428q-2 113 -59 174.5t-154 61.5t-152 -61.5t-63 -174.5zM194 1241v27 q189 189 256 301h357q31 -52 107.5 -141.5t148.5 -159.5v-27h-203q-157 93 -234 176q-78 -81 -229 -176h-203z" /> -<glyph unicode="ë" horiz-adv-x="1210" d="M92 551q0 281 140.5 434.5t388.5 153.5q237 0 369 -135t132 -373v-148h-721q5 -130 77 -203t202 -73q101 0 191 21t188 67v-236q-80 -40 -171 -59.5t-222 -19.5q-270 0 -422 149t-152 422zM408 686h428q-2 113 -59 174.5t-154 61.5t-152 -61.5t-63 -174.5zM297 1405 q0 65 37.5 100t101.5 35q66 0 103.5 -37t37.5 -98q0 -60 -38 -96.5t-103 -36.5q-64 0 -101.5 35t-37.5 98zM700 1405q0 70 40.5 102.5t100.5 32.5q65 0 103.5 -36t38.5 -99q0 -61 -39 -97t-103 -36q-60 0 -100.5 32.5t-40.5 100.5z" /> -<glyph unicode="ì" horiz-adv-x="625" d="M160 0v1118h305v-1118h-305zM-101 1548v21h342q63 -101 235 -301v-27h-202q-63 44 -185 142.5t-190 164.5z" /> -<glyph unicode="í" horiz-adv-x="625" d="M160 0v1118h305v-1118h-305zM145 1241v27q172 200 235 301h342v-21q-52 -52 -177.5 -154.5t-196.5 -152.5h-203z" /> -<glyph unicode="î" horiz-adv-x="625" d="M160 0v1118h305v-1118h-305zM-122 1241v27q189 189 256 301h357q31 -52 107.5 -141.5t148.5 -159.5v-27h-203q-157 93 -234 176q-78 -81 -229 -176h-203z" /> -<glyph unicode="ï" horiz-adv-x="625" d="M160 0v1118h305v-1118h-305zM-29 1405q0 65 37.5 100t101.5 35q66 0 103.5 -37t37.5 -98q0 -60 -38 -96.5t-103 -36.5q-64 0 -101.5 35t-37.5 98zM374 1405q0 70 40.5 102.5t100.5 32.5q65 0 103.5 -36t38.5 -99q0 -61 -39 -97t-103 -36q-60 0 -100.5 32.5t-40.5 100.5z " /> -<glyph unicode="ð" horiz-adv-x="1268" d="M92 489q0 233 130 369.5t351 136.5q205 0 275 -98l8 4q-67 162 -192 281l-230 -142l-100 156l176 107q-80 53 -152 92l101 176q144 -65 258 -141l225 139l100 -154l-170 -104q156 -143 230 -324.5t74 -413.5q0 -280 -145 -436.5t-400 -156.5q-245 0 -392 137t-147 372z M403 487q0 -140 60 -211t172 -71q123 0 176 82t53 245q0 108 -61 173t-168 65q-121 0 -176.5 -68.5t-55.5 -214.5z" /> -<glyph unicode="ñ" horiz-adv-x="1346" d="M160 0v1118h233l41 -143h17q51 81 140.5 122.5t203.5 41.5q195 0 296 -105.5t101 -304.5v-729h-305v653q0 121 -43 181.5t-137 60.5q-128 0 -185 -85.5t-57 -283.5v-526h-305zM258 1239q11 145 82.5 227t189.5 82q41 0 80.5 -16.5t78 -36t75.5 -35.5t73 -16q31 0 59.5 26 t41.5 80h149q-11 -145 -83.5 -227t-188.5 -82q-41 0 -80.5 16.5t-78 36t-75.5 36t-73 16.5q-31 0 -59.5 -26.5t-41.5 -80.5h-149z" /> -<glyph unicode="ò" horiz-adv-x="1268" d="M92 561q0 274 143 426t402 152q161 0 284 -70t189 -201t66 -307q0 -273 -144 -427t-401 -154q-161 0 -284 70.5t-189 202.5t-66 308zM403 561q0 -166 54.5 -251t177.5 -85q122 0 175.5 84.5t53.5 251.5q0 166 -54 249t-177 83q-122 0 -176 -82.5t-54 -249.5zM237 1548v21 h342q63 -101 235 -301v-27h-202q-63 44 -185 142.5t-190 164.5z" /> -<glyph unicode="ó" horiz-adv-x="1268" d="M92 561q0 274 143 426t402 152q161 0 284 -70t189 -201t66 -307q0 -273 -144 -427t-401 -154q-161 0 -284 70.5t-189 202.5t-66 308zM403 561q0 -166 54.5 -251t177.5 -85q122 0 175.5 84.5t53.5 251.5q0 166 -54 249t-177 83q-122 0 -176 -82.5t-54 -249.5zM467 1241v27 q172 200 235 301h342v-21q-52 -52 -177.5 -154.5t-196.5 -152.5h-203z" /> -<glyph unicode="ô" horiz-adv-x="1268" d="M92 561q0 274 143 426t402 152q161 0 284 -70t189 -201t66 -307q0 -273 -144 -427t-401 -154q-161 0 -284 70.5t-189 202.5t-66 308zM403 561q0 -166 54.5 -251t177.5 -85q122 0 175.5 84.5t53.5 251.5q0 166 -54 249t-177 83q-122 0 -176 -82.5t-54 -249.5zM198 1241v27 q189 189 256 301h357q31 -52 107.5 -141.5t148.5 -159.5v-27h-203q-157 93 -234 176q-78 -81 -229 -176h-203z" /> -<glyph unicode="õ" horiz-adv-x="1268" d="M92 561q0 274 143 426t402 152q161 0 284 -70t189 -201t66 -307q0 -273 -144 -427t-401 -154q-161 0 -284 70.5t-189 202.5t-66 308zM403 561q0 -166 54.5 -251t177.5 -85q122 0 175.5 84.5t53.5 251.5q0 166 -54 249t-177 83q-122 0 -176 -82.5t-54 -249.5zM219 1239 q11 145 82.5 227t189.5 82q41 0 80.5 -16.5t78 -36t75.5 -35.5t73 -16q31 0 59.5 26t41.5 80h149q-11 -145 -83.5 -227t-188.5 -82q-41 0 -80.5 16.5t-78 36t-75.5 36t-73 16.5q-31 0 -59.5 -26.5t-41.5 -80.5h-149z" /> -<glyph unicode="ö" horiz-adv-x="1268" d="M92 561q0 274 143 426t402 152q161 0 284 -70t189 -201t66 -307q0 -273 -144 -427t-401 -154q-161 0 -284 70.5t-189 202.5t-66 308zM403 561q0 -166 54.5 -251t177.5 -85q122 0 175.5 84.5t53.5 251.5q0 166 -54 249t-177 83q-122 0 -176 -82.5t-54 -249.5zM291 1405 q0 65 37.5 100t101.5 35q66 0 103.5 -37t37.5 -98q0 -60 -38 -96.5t-103 -36.5q-64 0 -101.5 35t-37.5 98zM694 1405q0 70 40.5 102.5t100.5 32.5q65 0 103.5 -36t38.5 -99q0 -61 -39 -97t-103 -36q-60 0 -100.5 32.5t-40.5 100.5z" /> -<glyph unicode="÷" d="M88 612v219h993v-219h-993zM444 373q0 76 37 113.5t103 37.5t102.5 -39t36.5 -112q0 -70 -37 -111t-102 -41t-102.5 39t-37.5 113zM444 1071q0 75 37 113.5t103 38.5q67 0 103 -40.5t36 -111.5q0 -70 -37 -110.5t-102 -40.5t-102.5 39t-37.5 112z" /> -<glyph unicode="ø" horiz-adv-x="1268" d="M92 561q0 274 143 426t402 152q132 0 248 -52l55 82l152 -108l-58 -84q142 -155 142 -416q0 -273 -144 -427t-401 -154q-126 0 -234 45l-67 -101l-154 105l68 100q-152 156 -152 432zM403 561q0 -94 19 -166l317 475q-43 23 -106 23q-122 0 -176 -82.5t-54 -249.5z M543 240q38 -15 92 -15q122 0 175.5 84.5t53.5 251.5q0 81 -12 141z" /> -<glyph unicode="ù" horiz-adv-x="1346" d="M154 389v729h305v-653q0 -121 43 -181.5t137 -60.5q128 0 185 85.5t57 283.5v526h305v-1118h-234l-41 143h-16q-49 -78 -139 -120.5t-205 -42.5q-197 0 -297 105.5t-100 303.5zM245 1548v21h342q63 -101 235 -301v-27h-202q-63 44 -185 142.5t-190 164.5z" /> -<glyph unicode="ú" horiz-adv-x="1346" d="M154 389v729h305v-653q0 -121 43 -181.5t137 -60.5q128 0 185 85.5t57 283.5v526h305v-1118h-234l-41 143h-16q-49 -78 -139 -120.5t-205 -42.5q-197 0 -297 105.5t-100 303.5zM498 1241v27q172 200 235 301h342v-21q-52 -52 -177.5 -154.5t-196.5 -152.5h-203z" /> -<glyph unicode="û" horiz-adv-x="1346" d="M154 389v729h305v-653q0 -121 43 -181.5t137 -60.5q128 0 185 85.5t57 283.5v526h305v-1118h-234l-41 143h-16q-49 -78 -139 -120.5t-205 -42.5q-197 0 -297 105.5t-100 303.5zM235 1241v27q189 189 256 301h357q31 -52 107.5 -141.5t148.5 -159.5v-27h-203 q-157 93 -234 176q-78 -81 -229 -176h-203z" /> -<glyph unicode="ü" horiz-adv-x="1346" d="M154 389v729h305v-653q0 -121 43 -181.5t137 -60.5q128 0 185 85.5t57 283.5v526h305v-1118h-234l-41 143h-16q-49 -78 -139 -120.5t-205 -42.5q-197 0 -297 105.5t-100 303.5zM326 1405q0 65 37.5 100t101.5 35q66 0 103.5 -37t37.5 -98q0 -60 -38 -96.5t-103 -36.5 q-64 0 -101.5 35t-37.5 98zM729 1405q0 70 40.5 102.5t100.5 32.5q65 0 103.5 -36t38.5 -99q0 -61 -39 -97t-103 -36q-60 0 -100.5 32.5t-40.5 100.5z" /> -<glyph unicode="ý" horiz-adv-x="1165" d="M0 1118h334l211 -629q27 -82 37 -194h6q11 103 43 194l207 629h327l-473 -1261q-65 -175 -185.5 -262t-281.5 -87q-79 0 -155 17v242q55 -13 120 -13q81 0 141.5 49.5t94.5 149.5l18 55zM393 1241v27q172 200 235 301h342v-21q-52 -52 -177.5 -154.5t-196.5 -152.5h-203z " /> -<glyph unicode="þ" horiz-adv-x="1296" d="M160 -492v2048h305v-391l-7 -120l-7 -72h14q50 81 131 123.5t186 42.5q198 0 310 -154.5t112 -423.5q0 -273 -111.5 -427t-310.5 -154q-213 0 -317 137h-14l7 -62l7 -94v-453h-305zM465 563q0 -180 53.5 -258t169.5 -78q205 0 205 338q0 165 -50.5 247.5t-158.5 82.5 q-113 0 -165 -69.5t-54 -229.5v-33z" /> -<glyph unicode="ÿ" horiz-adv-x="1165" d="M0 1118h334l211 -629q27 -82 37 -194h6q11 103 43 194l207 629h327l-473 -1261q-65 -175 -185.5 -262t-281.5 -87q-79 0 -155 17v242q55 -13 120 -13q81 0 141.5 49.5t94.5 149.5l18 55zM243 1405q0 65 37.5 100t101.5 35q66 0 103.5 -37t37.5 -98q0 -60 -38 -96.5 t-103 -36.5q-64 0 -101.5 35t-37.5 98zM646 1405q0 70 40.5 102.5t100.5 32.5q65 0 103.5 -36t38.5 -99q0 -61 -39 -97t-103 -36q-60 0 -100.5 32.5t-40.5 100.5z" /> -<glyph unicode="ı" horiz-adv-x="625" d="M160 0v1118h305v-1118h-305z" /> -<glyph unicode="Œ" horiz-adv-x="1993" d="M119 735q0 363 169.5 556.5t487.5 193.5q61 0 127 -7t101 -16h868v-254h-563v-321h526v-254h-526v-377h563v-256h-873q-38 -9 -109 -14.5t-116 -5.5q-319 0 -487 197t-168 558zM438 733q0 -244 86 -368.5t250 -124.5q65 0 126 10.5t99 28.5v907q-35 19 -101.5 30 t-121.5 11q-166 0 -252 -125.5t-86 -368.5z" /> -<glyph unicode="œ" horiz-adv-x="2003" d="M92 561q0 277 141.5 427.5t399.5 150.5q112 0 212 -39.5t171 -116.5q144 156 383 156q244 0 380 -135t136 -373v-148h-746v-8q7 -127 81.5 -197.5t207.5 -70.5q107 0 200 21t193 67v-236q-81 -39 -175.5 -59t-229.5 -20q-271 0 -420 155q-141 -155 -391 -155 q-162 0 -286 70t-190.5 202t-66.5 309zM403 561q0 -166 54.5 -251t177.5 -85q122 0 175.5 84.5t53.5 251.5q0 166 -54 249t-177 83q-122 0 -176 -82.5t-54 -249.5zM1178 686h450q-2 111 -60.5 173.5t-162.5 62.5q-94 0 -156 -57.5t-71 -178.5z" /> -<glyph unicode="Ÿ" horiz-adv-x="1278" d="M0 1462h336l303 -602l305 602h334l-485 -893v-569h-308v559zM297 1743q0 65 37.5 100t101.5 35q66 0 103.5 -37t37.5 -98q0 -60 -38 -96.5t-103 -36.5q-64 0 -101.5 35t-37.5 98zM700 1743q0 70 40.5 102.5t100.5 32.5q65 0 103.5 -36t38.5 -99q0 -61 -39 -97t-103 -36 q-60 0 -100.5 32.5t-40.5 100.5z" /> -<glyph unicode="ˆ" horiz-adv-x="1243" d="M186 1241v27q189 189 256 301h357q31 -52 107.5 -141.5t148.5 -159.5v-27h-203q-157 93 -234 176q-78 -81 -229 -176h-203z" /> -<glyph unicode="˚" horiz-adv-x="1182" d="M340 1477q0 108 67.5 172.5t180.5 64.5q110 0 182 -66t72 -169q0 -108 -71 -174t-183 -66t-180 64t-68 174zM492 1477q0 -45 24 -71t72 -26q42 0 69 26t27 71t-27 70.5t-69 25.5t-69 -25.5t-27 -70.5z" /> -<glyph unicode="˜" horiz-adv-x="1243" d="M207 1239q11 145 82.5 227t189.5 82q41 0 80.5 -16.5t78 -36t75.5 -35.5t73 -16q31 0 59.5 26t41.5 80h149q-11 -145 -83.5 -227t-188.5 -82q-41 0 -80.5 16.5t-78 36t-75.5 36t-73 16.5q-31 0 -59.5 -26.5t-41.5 -80.5h-149z" /> -<glyph unicode=" " horiz-adv-x="953" /> -<glyph unicode=" " horiz-adv-x="1907" /> -<glyph unicode=" " horiz-adv-x="953" /> -<glyph unicode=" " horiz-adv-x="1907" /> -<glyph unicode=" " horiz-adv-x="635" /> -<glyph unicode=" " horiz-adv-x="476" /> -<glyph unicode=" " horiz-adv-x="317" /> -<glyph unicode=" " horiz-adv-x="317" /> -<glyph unicode=" " horiz-adv-x="238" /> -<glyph unicode=" " horiz-adv-x="381" /> -<glyph unicode=" " horiz-adv-x="105" /> -<glyph unicode="‐" horiz-adv-x="659" d="M61 424v250h537v-250h-537z" /> -<glyph unicode="‑" horiz-adv-x="659" d="M61 424v250h537v-250h-537z" /> -<glyph unicode="‒" horiz-adv-x="659" d="M61 424v250h537v-250h-537z" /> -<glyph unicode="–" horiz-adv-x="1024" d="M82 436v230h860v-230h-860z" /> -<glyph unicode="—" horiz-adv-x="2048" d="M82 436v230h1884v-230h-1884z" /> -<glyph unicode="‘" horiz-adv-x="444" d="M25 983q22 91 72.5 228.5t103.5 250.5h219q-66 -267 -101 -501h-280z" /> -<glyph unicode="’" horiz-adv-x="444" d="M25 961q69 296 100 501h281l14 -22q-50 -197 -176 -479h-219z" /> -<glyph unicode="‚" horiz-adv-x="596" d="M63 -264q65 266 101 502h280l15 -23q-52 -202 -176 -479h-220z" /> -<glyph unicode="“" horiz-adv-x="911" d="M25 983q22 91 72.5 228.5t103.5 250.5h219q-66 -267 -101 -501h-280zM492 983q22 91 72.5 228.5t103.5 250.5h219q-66 -267 -101 -501h-280z" /> -<glyph unicode="”" horiz-adv-x="911" d="M25 961q69 296 100 501h281l14 -22q-50 -197 -176 -479h-219zM492 961q69 296 100 501h280l15 -22q-50 -197 -176 -479h-219z" /> -<glyph unicode="„" horiz-adv-x="1061" d="M63 -264q65 266 101 502h280l15 -23q-52 -202 -176 -479h-220zM530 -264q65 266 101 502h280l15 -23q-52 -202 -176 -479h-220z" /> -<glyph unicode="•" horiz-adv-x="770" d="M98 748q0 154 74 235.5t213 81.5q137 0 212 -82t75 -235q0 -152 -75.5 -235t-211.5 -83q-138 0 -212.5 83t-74.5 235z" /> -<glyph unicode="…" horiz-adv-x="1751" d="M117 143q0 84 45 127t131 43q83 0 128.5 -44t45.5 -126q0 -79 -46 -124.5t-128 -45.5q-84 0 -130 44.5t-46 125.5zM700 143q0 84 45 127t132 43q83 0 128.5 -44t45.5 -126q0 -79 -46 -124.5t-128 -45.5q-85 0 -131 44.5t-46 125.5zM1284 143q0 84 45 127t131 43 q83 0 128.5 -44t45.5 -126q0 -79 -46 -124.5t-128 -45.5q-84 0 -130 44.5t-46 125.5z" /> -<glyph unicode=" " horiz-adv-x="381" /> -<glyph unicode="‹" horiz-adv-x="754" d="M82 547v26l371 455l219 -119l-279 -348l279 -348l-219 -119z" /> -<glyph unicode="›" horiz-adv-x="754" d="M82 213l278 348l-278 348l219 119l371 -455v-26l-371 -453z" /> -<glyph unicode="⁄" horiz-adv-x="266" d="M-393 0l811 1462h239l-811 -1462h-239z" /> -<glyph unicode=" " horiz-adv-x="476" /> -<glyph unicode="⁴" horiz-adv-x="776" d="M12 737v154l385 577h236v-563h125v-168h-125v-151h-238v151h-383zM197 905h198v164q0 86 6 184q-9 -26 -35.5 -80t-41.5 -77z" /> -<glyph unicode="€" d="M66 481v178h118q-4 23 -4 62l2 53h-116v176h133q37 242 199 382.5t405 140.5q188 0 352 -82l-98 -232q-69 31 -129 48.5t-125 17.5q-122 0 -201 -70.5t-102 -204.5h403v-176h-418l-2 -35v-47l2 -33h355v-178h-338q51 -243 321 -243q143 0 275 57v-256q-116 -59 -293 -59 q-245 0 -403 133t-199 368h-137z" /> -<glyph unicode="™" horiz-adv-x="1534" d="M16 1313v149h564v-149h-199v-572h-168v572h-197zM625 741v721h247l160 -510l170 510h240v-721h-168v408l4 121h-6l-174 -529h-142l-165 529h-7l4 -111v-418h-163z" /> -<glyph unicode="" horiz-adv-x="1120" d="M0 1120h1120v-1120h-1120v1120z" /> -<glyph unicode="fi" horiz-adv-x="1417" d="M41 889v147l168 82v82q0 191 94 279t301 88q158 0 281 -47l-78 -224q-92 29 -170 29q-65 0 -94 -38.5t-29 -98.5v-70h264v-229h-264v-889h-305v889h-168zM940 1407q0 149 166 149t166 -149q0 -71 -41.5 -110.5t-124.5 -39.5q-166 0 -166 150zM953 0v1118h305v-1118h-305z " /> -<glyph unicode="fl" horiz-adv-x="1417" d="M41 889v147l168 82v82q0 191 94 279t301 88q158 0 281 -47l-78 -224q-92 29 -170 29q-65 0 -94 -38.5t-29 -98.5v-70h264v-229h-264v-889h-305v889h-168zM953 0v1556h305v-1556h-305z" /> -<glyph unicode="ffi" horiz-adv-x="2208" d="M41 889v147l168 82v82q0 191 94 279t301 88q158 0 281 -47l-78 -224q-92 29 -170 29q-65 0 -94 -38.5t-29 -98.5v-70h264v-229h-264v-889h-305v889h-168zM834 889v147l168 82v82q0 191 94 279t301 88q158 0 281 -47l-78 -224q-92 29 -170 29q-65 0 -94 -38.5t-29 -98.5 v-70h264v-229h-264v-889h-305v889h-168zM1730 1407q0 149 166 149t166 -149q0 -71 -41.5 -110.5t-124.5 -39.5q-166 0 -166 150zM1743 0v1118h305v-1118h-305z" /> -<glyph unicode="ffl" horiz-adv-x="2208" d="M41 889v147l168 82v82q0 191 94 279t301 88q158 0 281 -47l-78 -224q-92 29 -170 29q-65 0 -94 -38.5t-29 -98.5v-70h264v-229h-264v-889h-305v889h-168zM834 889v147l168 82v82q0 191 94 279t301 88q158 0 281 -47l-78 -224q-92 29 -170 29q-65 0 -94 -38.5t-29 -98.5 v-70h264v-229h-264v-889h-305v889h-168zM1743 0v1556h305v-1556h-305z" /> -</font> -</defs></svg> -\ No newline at end of file diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-Bold-webfont.ttf b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-Bold-webfont.ttf Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-Bold-webfont.woff b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-Bold-webfont.woff Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-BoldItalic-webfont.eot b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-BoldItalic-webfont.eot Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-BoldItalic-webfont.svg b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-BoldItalic-webfont.svg @@ -1,251 +0,0 @@ -<?xml version="1.0" standalone="no"?> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" > -<svg xmlns="http://www.w3.org/2000/svg"> -<metadata> -This is a custom SVG webfont generated by Font Squirrel. -Copyright : Digitized data copyright 20102011 Google Corporation -Foundry : Ascender Corporation -Foundry URL : httpwwwascendercorpcom -</metadata> -<defs> -<font id="OpenSansBoldItalic" horiz-adv-x="1128" > -<font-face units-per-em="2048" ascent="1638" descent="-410" /> -<missing-glyph horiz-adv-x="532" /> -<glyph unicode=" " horiz-adv-x="532" /> -<glyph unicode="	" horiz-adv-x="532" /> -<glyph unicode=" " horiz-adv-x="532" /> -<glyph unicode="!" horiz-adv-x="586" d="M25 115q0 90 53.5 144t150.5 54q68 0 109 -38t41 -107q0 -87 -55 -141t-144 -54q-73 0 -114 37.5t-41 104.5zM150 485l157 977h340l-256 -977h-241z" /> -<glyph unicode=""" horiz-adv-x="928" d="M201 934l71 528h277l-152 -528h-196zM604 934l74 528h276l-151 -528h-199z" /> -<glyph unicode="#" horiz-adv-x="1323" d="M41 408l18 206h277l70 232h-252l18 209h289l119 407h217l-117 -407h199l116 407h215l-116 -407h239l-18 -209h-279l-69 -232h258l-19 -206h-297l-116 -408h-220l117 408h-194l-115 -408h-215l113 408h-238zM553 614h197l69 232h-196z" /> -<glyph unicode="$" d="M51 168v266q198 -107 404 -117l71 322q-163 61 -241 151t-78 214q0 173 127 279.5t350 121.5l35 151h139l-33 -151q166 -22 295 -90l-106 -232q-132 65 -242 74l-63 -299q131 -51 195 -99.5t97 -113t33 -149.5q0 -184 -125.5 -291.5t-367.5 -124.5l-39 -199h-140l44 201 q-209 12 -355 86zM502 1022q0 -79 80 -111l51 246q-62 -7 -96.5 -41t-34.5 -94zM594 322q63 9 102 45t39 98q0 46 -24.5 75.5t-59.5 43.5z" /> -<glyph unicode="%" horiz-adv-x="1753" d="M115 885q0 169 55.5 311.5t148.5 214.5t216 72q137 0 211.5 -80t74.5 -238q0 -166 -56 -310t-151 -217t-217 -73q-139 0 -210.5 83.5t-71.5 236.5zM231 0l1088 1462h235l-1083 -1462h-240zM360 868q0 -96 56 -96q65 0 112 131t47 275q0 96 -57 96q-63 0 -110.5 -128.5 t-47.5 -277.5zM973 283q0 177 53 322.5t148 219.5t219 74q137 0 211.5 -78.5t74.5 -230.5q0 -167 -54 -313.5t-148 -220.5t-215 -74q-144 0 -216.5 78.5t-72.5 222.5zM1219 285q0 -97 55 -97q41 0 77 55t59.5 154.5t23.5 196.5q0 96 -58 96q-39 0 -75 -56t-59 -154t-23 -195 z" /> -<glyph unicode="&" horiz-adv-x="1450" d="M68 358q0 145 78.5 248.5t273.5 200.5q-76 130 -76 258q0 195 117.5 307.5t316.5 112.5q169 0 266 -82.5t97 -224.5q0 -280 -365 -426l195 -263q44 57 80.5 121.5t78.5 173.5h300q-133 -313 -310 -497l205 -287h-350l-72 98q-175 -118 -403 -118q-209 0 -320.5 97.5 t-111.5 280.5zM383 387q0 -65 45.5 -108t116.5 -43q115 0 221 59l-225 328q-88 -51 -123 -104.5t-35 -131.5zM621 1085q0 -46 12 -92t29 -73q113 59 155.5 111t42.5 112q0 57 -30 82.5t-70 25.5q-66 0 -102.5 -46.5t-36.5 -119.5z" /> -<glyph unicode="'" horiz-adv-x="522" d="M201 934l71 528h277l-152 -528h-196z" /> -<glyph unicode="(" horiz-adv-x="694" d="M74 281q0 339 122.5 626.5t381.5 554.5h262q-255 -278 -377.5 -573.5t-122.5 -618.5q0 -308 117 -594h-234q-149 266 -149 605z" /> -<glyph unicode=")" horiz-adv-x="694" d="M-147 -324q499 545 499 1192q0 307 -116 594h233q149 -264 149 -604q0 -342 -124 -630.5t-379 -551.5h-262z" /> -<glyph unicode="*" horiz-adv-x="1116" d="M172 1141l86 237l338 -174l33 369l256 -51l-113 -353l387 29l-18 -254l-338 43l160 -336l-246 -73l-90 337l-197 -278l-207 164l275 248z" /> -<glyph unicode="+" d="M109 612v219h366v369h219v-369h367v-219h-367v-364h-219v364h-366z" /> -<glyph unicode="," horiz-adv-x="569" d="M-102 -264q74 167 194 502h285l8 -23q-118 -255 -262 -479h-225z" /> -<glyph unicode="-" horiz-adv-x="659" d="M41 424l53 250h524l-53 -250h-524z" /> -<glyph unicode="." horiz-adv-x="584" d="M25 115q0 90 53.5 144t150.5 54q68 0 109 -38t41 -107q0 -87 -55 -141t-144 -54q-73 0 -114 37.5t-41 104.5z" /> -<glyph unicode="/" horiz-adv-x="862" d="M-90 0l809 1462h295l-809 -1462h-295z" /> -<glyph unicode="0" d="M66 467q0 297 84 537t228 360.5t333 120.5q399 0 399 -473q0 -470 -168.5 -751t-472.5 -281q-198 0 -300.5 122t-102.5 365zM369 461q0 -115 27.5 -173.5t97.5 -58.5q81 0 150.5 106t116 301t46.5 386q0 111 -30.5 162t-92.5 51q-80 0 -149.5 -104t-117.5 -302t-48 -368z " /> -<glyph unicode="1" d="M182 1114l566 348h249l-309 -1462h-305l180 829q35 152 76 287q-9 -8 -61.5 -47t-262.5 -170z" /> -<glyph unicode="2" d="M-49 0l43 213l477 424q180 159 248.5 254.5t68.5 179.5q0 75 -41 114.5t-110 39.5q-66 0 -135.5 -33.5t-171.5 -118.5l-146 203q132 112 252 159.5t250 47.5q190 0 301 -98t111 -259q0 -107 -41 -201t-122.5 -188t-266.5 -245l-269 -222v-10h568l-54 -260h-962z" /> -<glyph unicode="3" d="M14 59v267q84 -50 182 -75.5t191 -25.5q158 0 243 63.5t85 176.5q0 172 -258 172h-138l46 221h73q167 0 263 62t96 172q0 67 -43 104t-121 37q-134 0 -287 -100l-127 204q124 81 232.5 113.5t246.5 32.5q190 0 298 -90.5t108 -243.5q0 -156 -94.5 -262t-261.5 -135v-4 q131 -26 198.5 -106.5t67.5 -201.5q0 -133 -74 -238t-212 -163.5t-327 -58.5q-239 0 -387 79z" /> -<glyph unicode="4" d="M-25 303l48 234l770 925h311l-195 -919h170l-51 -240h-170l-63 -303h-293l63 303h-590zM305 543h311l58 248q12 58 40 164t42 141h-6q-35 -63 -132 -181z" /> -<glyph unicode="5" d="M27 61v269q174 -99 352 -99q154 0 241 71t87 194q0 94 -57.5 141t-166.5 47q-102 0 -213 -33l-104 78l207 733h755l-55 -262h-489l-88 -293q72 15 127 15q183 0 289 -103t106 -287q0 -167 -71.5 -292t-208.5 -192.5t-330 -67.5q-117 0 -218.5 23t-162.5 58z" /> -<glyph unicode="6" d="M88 469q0 202 61 395.5t167.5 335t256.5 213.5t357 72q125 0 223 -27l-51 -246q-84 25 -191 25q-194 0 -313.5 -108t-185.5 -345h4q115 166 311 166q157 0 242.5 -97t85.5 -273q0 -169 -71 -313.5t-190.5 -215.5t-277.5 -71q-212 0 -320 127t-108 362zM383 422 q0 -91 40 -143t107 -52q99 0 161.5 94t62.5 236q0 71 -33.5 113.5t-102.5 42.5q-60 0 -114.5 -35.5t-87.5 -95.5t-33 -160z" /> -<glyph unicode="7" d="M78 0l737 1202h-629l56 260h975l-41 -194l-752 -1268h-346z" /> -<glyph unicode="8" d="M55 350q0 298 348 426q-165 132 -165 299q0 119 58 212.5t168 145.5t257 52q123 0 215.5 -42t141 -118t48.5 -174q0 -134 -80.5 -233.5t-230.5 -151.5q217 -141 217 -365q0 -122 -63.5 -218.5t-181 -149.5t-273.5 -53q-214 0 -336.5 100t-122.5 270zM352 383 q0 -81 50 -128.5t135 -47.5q93 0 147.5 53.5t54.5 138.5q0 73 -36.5 131.5t-120.5 112.5q-116 -45 -173 -107t-57 -153zM528 1094q0 -132 123 -201q185 72 185 221q0 68 -39.5 107t-102.5 39q-76 0 -121 -46.5t-45 -119.5z" /> -<glyph unicode="9" d="M86 12v256q111 -41 227 -41q121 0 207.5 49t144 138.5t99.5 257.5h-4q-111 -158 -295 -158q-163 0 -252.5 103.5t-89.5 285.5q0 166 73 305.5t196 208t286 68.5q203 0 308.5 -123t105.5 -361q0 -280 -99 -533t-264 -370.5t-403 -117.5q-128 0 -240 32zM424 928 q0 -87 37.5 -131.5t105.5 -44.5q60 0 111.5 36.5t82 100t30.5 158.5q0 84 -35.5 137t-110.5 53q-65 0 -115.5 -42t-78 -114t-27.5 -153z" /> -<glyph unicode=":" horiz-adv-x="584" d="M25 115q0 90 53.5 144t150.5 54q68 0 109 -38t41 -107q0 -87 -55 -141t-144 -54q-73 0 -114 37.5t-41 104.5zM207 940q0 92 55.5 145.5t149.5 53.5q68 0 108.5 -38.5t40.5 -107.5q0 -86 -54.5 -140t-144.5 -54q-72 0 -113.5 36.5t-41.5 104.5z" /> -<glyph unicode=";" horiz-adv-x="584" d="M-102 -264q74 167 194 502h285l8 -23q-118 -255 -262 -479h-225zM207 940q0 92 55.5 145.5t149.5 53.5q68 0 108.5 -38.5t40.5 -107.5q0 -86 -54.5 -140t-144.5 -54q-72 0 -113.5 36.5t-41.5 104.5z" /> -<glyph unicode="<" d="M109 641v143l952 496v-240l-643 -317l643 -281v-239z" /> -<glyph unicode="=" d="M109 418v219h952v-219h-952zM109 807v217h952v-217h-952z" /> -<glyph unicode=">" d="M109 203v239l643 281l-643 317v240l952 -496v-143z" /> -<glyph unicode="?" horiz-adv-x="940" d="M166 115q0 91 55 144.5t150 53.5q68 0 108.5 -38t40.5 -107q0 -87 -55 -141t-143 -54q-74 0 -115 38t-41 104zM178 1358q230 125 445 125q177 0 280 -87.5t103 -244.5q0 -83 -28.5 -149.5t-82.5 -123t-190 -147.5q-64 -43 -96.5 -73t-52.5 -64.5t-38 -108.5h-258l14 78 q19 103 73.5 177t172.5 155q124 84 157.5 127t33.5 96q0 119 -133 119q-50 0 -106.5 -16t-201.5 -84z" /> -<glyph unicode="@" horiz-adv-x="1753" d="M92 500q0 279 120.5 497t343 341.5t497.5 123.5q318 0 499 -163.5t181 -458.5q0 -173 -64 -321t-177.5 -231t-254.5 -83q-88 0 -144.5 38.5t-72.5 108.5h-6q-50 -77 -113 -112t-147 -35q-127 0 -198 79.5t-71 229.5q0 147 67.5 276.5t187.5 205t268 75.5q185 0 327 -55 l-106 -420q-11 -44 -19 -76.5t-8 -64.5q0 -68 58 -68q66 0 124 64t92.5 171t34.5 214q0 213 -123.5 325.5t-359.5 112.5q-203 0 -366.5 -94t-255 -266t-91.5 -392q0 -243 134 -380.5t376 -137.5q117 0 219.5 20t221.5 66v-186q-230 -90 -465 -90q-217 0 -378 85.5 t-246 241.5t-85 359zM713 526q0 -65 24.5 -102t69.5 -37q141 0 213 270l57 222q-36 10 -82 10q-82 0 -145.5 -51.5t-100 -137t-36.5 -174.5z" /> -<glyph unicode="A" horiz-adv-x="1286" d="M-123 0l766 1468h373l147 -1468h-297l-24 348h-473l-172 -348h-320zM494 608h333l-26 350q-10 131 -10 253v36q-44 -120 -109 -254z" /> -<glyph unicode="B" horiz-adv-x="1270" d="M53 0l309 1462h426q229 0 346 -81.5t117 -243.5q0 -150 -83 -247.5t-236 -129.5v-6q100 -26 159.5 -96.5t59.5 -180.5q0 -229 -153 -353t-423 -124h-522zM412 256h180q117 0 183.5 58t66.5 161q0 162 -183 162h-165zM545 883h149q121 0 181.5 48.5t60.5 139.5 q0 137 -170 137h-152z" /> -<glyph unicode="C" horiz-adv-x="1253" d="M123 553q0 262 104 482.5t278 335t400 114.5q125 0 222 -22.5t208 -82.5l-118 -250q-106 59 -175 78t-137 19q-132 0 -237.5 -81t-169.5 -238.5t-64 -338.5q0 -167 68.5 -248t218.5 -81q146 0 338 77v-260q-199 -77 -400 -77q-254 0 -395 149.5t-141 423.5z" /> -<glyph unicode="D" horiz-adv-x="1386" d="M53 0l309 1462h396q270 0 417.5 -143t147.5 -410q0 -280 -98 -486.5t-283.5 -314.5t-437.5 -108h-451zM412 256h106q148 0 258 76t172 223.5t62 337.5q0 154 -72.5 234.5t-208.5 80.5h-115z" /> -<glyph unicode="E" horiz-adv-x="1110" d="M53 0l309 1462h818l-54 -254h-512l-67 -321h477l-55 -254h-477l-80 -377h512l-54 -256h-817z" /> -<glyph unicode="F" horiz-adv-x="1087" d="M53 0l309 1462h814l-54 -254h-508l-79 -377h473l-56 -253h-473l-121 -578h-305z" /> -<glyph unicode="G" horiz-adv-x="1413" d="M123 549q0 268 107 484.5t301 334t448 117.5q218 0 410 -99l-115 -251q-74 40 -148 64t-161 24q-153 0 -273.5 -83t-189 -236.5t-68.5 -330.5q0 -172 72.5 -252.5t222.5 -80.5q76 0 170 24l66 299h-267l56 258h563l-162 -762q-134 -46 -248.5 -62.5t-242.5 -16.5 q-259 0 -400 147t-141 422z" /> -<glyph unicode="H" horiz-adv-x="1434" d="M53 0l309 1462h306l-121 -573h471l121 573h305l-309 -1462h-306l134 631h-471l-134 -631h-305z" /> -<glyph unicode="I" horiz-adv-x="659" d="M53 0l312 1462h305l-312 -1462h-305z" /> -<glyph unicode="J" horiz-adv-x="678" d="M-322 -150q88 -20 164 -20q99 0 160.5 60.5t89.5 191.5l293 1380h305l-303 -1423q-52 -245 -175.5 -357t-346.5 -112q-94 0 -187 27v253z" /> -<glyph unicode="K" horiz-adv-x="1255" d="M53 0l309 1462h306l-152 -702l158 205l409 497h361l-594 -700l291 -762h-338l-211 592l-125 -70l-109 -522h-305z" /> -<glyph unicode="L" horiz-adv-x="1061" d="M53 0l309 1462h306l-256 -1206h512l-54 -256h-817z" /> -<glyph unicode="M" horiz-adv-x="1802" d="M53 0l309 1462h404l68 -1093h4l551 1093h423l-309 -1462h-280l145 692q53 247 105 441h-5l-569 -1133h-281l-61 1133h-4q-11 -88 -38 -231t-187 -902h-275z" /> -<glyph unicode="N" horiz-adv-x="1546" d="M53 0l309 1462h357l340 -1077h4q12 76 39 217t180 860h274l-309 -1462h-342l-356 1106h-6l-4 -32q-32 -216 -66 -386l-145 -688h-275z" /> -<glyph unicode="O" horiz-adv-x="1495" d="M123 537q0 265 99 487.5t273 341.5t402 119q255 0 395 -144t140 -403q0 -283 -99 -506.5t-271 -337.5t-396 -114q-256 0 -399.5 147.5t-143.5 409.5zM434 537q0 -147 66.5 -222t187.5 -75t220.5 87t155.5 246t56 357q0 142 -65 219.5t-183 77.5q-121 0 -222 -91.5 t-158.5 -251.5t-57.5 -347z" /> -<glyph unicode="P" horiz-adv-x="1188" d="M53 0l309 1462h338q242 0 366 -106.5t124 -319.5q0 -241 -169.5 -378.5t-467.5 -137.5h-86l-109 -520h-305zM522 774h56q142 0 223.5 69t81.5 185q0 180 -195 180h-74z" /> -<glyph unicode="Q" horiz-adv-x="1495" d="M123 537q0 265 99 487.5t273 341.5t402 119q255 0 395 -144t140 -403q0 -316 -122.5 -555.5t-334.5 -337.5l254 -393h-359l-178 328h-26q-256 0 -399.5 147.5t-143.5 409.5zM434 537q0 -147 66.5 -222t187.5 -75t220.5 87t155.5 246t56 357q0 142 -65 219.5t-183 77.5 q-121 0 -222 -91.5t-158.5 -251.5t-57.5 -347z" /> -<glyph unicode="R" horiz-adv-x="1247" d="M53 0l309 1462h359q237 0 356 -102t119 -299q0 -158 -83 -271.5t-239 -168.5l261 -621h-332l-207 561h-119l-119 -561h-305zM530 813h78q131 0 204 57t73 174q0 82 -47.5 123t-149.5 41h-74z" /> -<glyph unicode="S" horiz-adv-x="1085" d="M41 70v274q193 -108 358 -108q112 0 175 42.5t63 116.5q0 43 -13.5 75.5t-38.5 60.5t-124 102q-138 99 -194 196t-56 209q0 129 62 230.5t176.5 158t263.5 56.5q217 0 397 -99l-109 -233q-156 74 -288 74q-83 0 -136 -45t-53 -119q0 -61 33 -106.5t148 -120.5 q121 -80 181 -176.5t60 -225.5q0 -209 -148 -330.5t-401 -121.5q-221 0 -356 90z" /> -<glyph unicode="T" horiz-adv-x="1087" d="M168 1204l55 258h1010l-55 -258h-353l-254 -1204h-305l254 1204h-352z" /> -<glyph unicode="U" horiz-adv-x="1415" d="M141 401q0 72 15 138l196 923h305l-194 -919q-17 -74 -17 -125q0 -178 189 -178q123 0 195 76.5t104 228.5l194 917h306l-201 -946q-57 -266 -218 -401t-419 -135q-212 0 -333.5 113.5t-121.5 307.5z" /> -<glyph unicode="V" horiz-adv-x="1208" d="M184 1462h295l51 -880q4 -45 4 -133q-2 -103 -6 -150h7q78 221 110 283l432 880h316l-748 -1462h-334z" /> -<glyph unicode="W" horiz-adv-x="1831" d="M184 1462h287l6 -798q0 -52 -4 -173t-10 -174h6q22 64 67 180.5t60 145.5l369 819h270l21 -873q0 -146 -9 -272h6q43 129 131 349l330 796h309l-647 -1462h-346l-22 721l-2 139q0 88 4 158h-4q-46 -146 -115 -299l-324 -719h-338z" /> -<glyph unicode="X" horiz-adv-x="1241" d="M-117 0l576 764l-238 698h320l153 -518l363 518h344l-545 -725l268 -737h-331l-172 543l-396 -543h-342z" /> -<glyph unicode="Y" horiz-adv-x="1155" d="M186 1462h312l129 -592l374 592h342l-618 -903l-119 -559h-303l119 559z" /> -<glyph unicode="Z" horiz-adv-x="1098" d="M-61 0l38 201l777 1005h-543l53 256h936l-41 -202l-782 -1004h596l-53 -256h-981z" /> -<glyph unicode="[" horiz-adv-x="678" d="M-37 -324l381 1786h473l-45 -211h-215l-291 -1364h215l-45 -211h-473z" /> -<glyph unicode="\" horiz-adv-x="862" d="M221 1462h260l224 -1462h-267z" /> -<glyph unicode="]" horiz-adv-x="678" d="M-137 -324l45 211h213l291 1364h-215l45 211h473l-381 -1786h-471z" /> -<glyph unicode="^" horiz-adv-x="1081" d="M20 520l619 950h147l277 -950h-223l-174 633l-402 -633h-244z" /> -<glyph unicode="_" horiz-adv-x="819" d="M-186 -324l30 140h822l-31 -140h-821z" /> -<glyph unicode="`" horiz-adv-x="1135" d="M508 1548v21h311q36 -148 115 -303v-25h-184q-71 69 -138.5 153.5t-103.5 153.5z" /> -<glyph unicode="a" horiz-adv-x="1217" d="M90 385q0 198 72 377.5t189 278t257 98.5q97 0 167.5 -42t109.5 -122h8l57 143h232l-238 -1118h-229l14 145h-4q-134 -165 -319 -165q-147 0 -231.5 106.5t-84.5 298.5zM395 399q0 -88 33.5 -132t95.5 -44q69 0 133 67t103 181.5t39 259.5q0 71 -38.5 117.5t-101.5 46.5 q-68 0 -129.5 -72t-98 -190t-36.5 -234z" /> -<glyph unicode="b" horiz-adv-x="1219" d="M37 0l330 1556h301l-62 -288q-41 -182 -84 -299h8q78 98 142.5 134t140.5 36q146 0 230.5 -108t84.5 -298t-68 -367.5t-187 -281.5t-263 -104q-194 0 -276 163h-8l-58 -143h-231zM420 399q0 -80 37 -128t102 -48q67 0 128 69t98.5 189.5t37.5 237.5q0 176 -131 176 q-68 0 -130 -65t-102 -180.5t-40 -250.5z" /> -<glyph unicode="c" horiz-adv-x="989" d="M90 391q0 212 74.5 385.5t209.5 268t308 94.5q182 0 328 -72l-92 -229q-54 23 -106 40t-118 17q-85 0 -153.5 -64t-107 -175.5t-38.5 -239.5q0 -96 45.5 -144.5t126.5 -48.5q76 0 141 23.5t134 58.5v-246q-152 -79 -336 -79q-201 0 -308.5 107.5t-107.5 303.5z" /> -<glyph unicode="d" horiz-adv-x="1217" d="M90 387q0 196 71.5 374.5t188.5 278t258 99.5q82 0 141.5 -37t112.5 -127h8l2 28q6 110 25 195l76 358h301l-330 -1556h-229l14 145h-4q-71 -87 -148.5 -126t-170.5 -39q-147 0 -231.5 107t-84.5 300zM395 399q0 -176 137 -176q66 0 128.5 68.5t100.5 182.5t38 245 q0 80 -37.5 128t-102.5 48q-68 0 -129.5 -72t-98 -190t-36.5 -234z" /> -<glyph unicode="e" horiz-adv-x="1141" d="M90 412q0 207 82.5 377.5t223.5 260t319 89.5q177 0 276 -81.5t99 -223.5q0 -187 -167 -288.5t-477 -101.5h-51l-2 -21v-20q0 -91 51.5 -143.5t147.5 -52.5q87 0 158 19t172 67v-227q-172 -86 -390 -86q-210 0 -326 113t-116 319zM428 647h45q155 0 241.5 48.5 t86.5 131.5q0 95 -105 95q-88 0 -166 -80t-102 -195z" /> -<glyph unicode="f" horiz-adv-x="764" d="M-219 -225q61 -21 115 -21q61 0 107 40t65 130l204 965h-163l30 145l183 84l18 84q41 190 138.5 277.5t273.5 87.5q131 0 235 -49l-80 -224q-69 31 -133 31q-57 0 -92 -40t-47 -105l-12 -62h219l-49 -229h-220l-215 -1010q-77 -371 -403 -371q-104 0 -174 25v242z" /> -<glyph unicode="g" horiz-adv-x="1108" d="M-115 -209q0 102 68.5 175.5t214.5 121.5q-74 47 -74 133q0 71 44.5 122.5t146.5 98.5q-65 49 -96 112t-31 153q0 199 125.5 315.5t341.5 116.5q83 0 166 -23h395l-35 -166l-174 -41q16 -52 16 -118q0 -195 -121 -308.5t-329 -113.5q-59 0 -99 10q-84 -27 -84 -78 q0 -34 30 -49t89 -23l137 -18q163 -21 237.5 -84.5t74.5 -183.5q0 -211 -156 -323t-446 -112q-208 0 -324.5 75.5t-116.5 207.5zM150 -172q0 -115 194 -115q151 0 228 45t77 127q0 39 -32.5 60t-137.5 35l-114 14q-106 -14 -160.5 -57t-54.5 -109zM442 680q0 -119 103 -119 q75 0 121.5 76.5t46.5 193.5t-99 117q-77 0 -124.5 -76.5t-47.5 -191.5z" /> -<glyph unicode="h" horiz-adv-x="1237" d="M37 0l330 1556h301q-39 -181 -60 -278t-86 -309h8q62 77 138 123.5t176 46.5q138 0 213.5 -83.5t75.5 -238.5q0 -73 -23 -180l-133 -637h-301l137 653q16 68 16 119q0 123 -108 123q-92 0 -167 -114t-118 -318l-98 -463h-301z" /> -<glyph unicode="i" horiz-adv-x="608" d="M37 0l237 1118h301l-237 -1118h-301zM322 1380q0 87 47.5 131.5t134.5 44.5q73 0 111 -31t38 -89q0 -80 -44 -129.5t-136 -49.5q-151 0 -151 123z" /> -<glyph unicode="j" horiz-adv-x="608" d="M-264 -225q61 -21 114 -21q137 0 173 170l253 1194h302l-265 -1239q-77 -371 -403 -371q-104 0 -174 25v242zM324 1380q0 87 47.5 131.5t134.5 44.5q73 0 111 -31t38 -89q0 -80 -44 -129.5t-136 -49.5q-151 0 -151 123z" /> -<glyph unicode="k" horiz-adv-x="1163" d="M37 0l330 1556h301l-148 -694q-8 -41 -29 -117l-28 -102h4l453 475h344l-498 -504l285 -614h-336l-183 420l-120 -72l-74 -348h-301z" /> -<glyph unicode="l" horiz-adv-x="608" d="M37 0l330 1556h301l-330 -1556h-301z" /> -<glyph unicode="m" horiz-adv-x="1853" d="M37 0l237 1118h230l-21 -207h6q146 228 355 228q219 0 262 -228h6q68 110 160.5 169t197.5 59q136 0 207.5 -85t71.5 -237q0 -76 -23 -180l-133 -637h-301l138 653q16 68 16 119q0 123 -98 123q-92 0 -166.5 -112t-118.5 -318l-96 -465h-301l137 653q16 68 16 119 q0 123 -98 123q-92 0 -167 -114t-118 -318l-98 -463h-301z" /> -<glyph unicode="n" horiz-adv-x="1237" d="M37 0l237 1118h230l-21 -207h6q146 228 355 228q138 0 213.5 -83.5t75.5 -238.5q0 -73 -23 -180l-133 -637h-301l137 653q16 68 16 119q0 123 -108 123q-92 0 -167 -114t-118 -318l-98 -463h-301z" /> -<glyph unicode="o" horiz-adv-x="1198" d="M90 410q0 213 71.5 379.5t206.5 258t316 91.5q196 0 310 -118t114 -325q0 -211 -70.5 -374t-203.5 -252.5t-316 -89.5q-195 0 -311.5 117.5t-116.5 312.5zM393 410q0 -185 150 -185q75 0 135 61.5t93.5 171t33.5 238.5q0 197 -143 197q-75 0 -134.5 -61t-97 -179 t-37.5 -243z" /> -<glyph unicode="p" horiz-adv-x="1219" d="M-68 -492l342 1610h230l-17 -170h9q138 191 317 191q146 0 230.5 -107.5t84.5 -300.5q0 -191 -68.5 -367.5t-187.5 -280t-262 -103.5q-83 0 -143 37t-111 126h-8q-12 -159 -43 -295l-72 -340h-301zM420 399q0 -80 37 -128t102 -48q67 0 128 69t98.5 189.5t37.5 237.5 q0 176 -131 176q-68 0 -131.5 -67.5t-102 -180t-38.5 -248.5z" /> -<glyph unicode="q" horiz-adv-x="1217" d="M90 385q0 198 72 377.5t189 278t257 98.5q86 0 152.5 -37.5t124.5 -126.5h8l57 143h232l-342 -1610h-301q47 218 73 337.5t84 304.5h-8q-72 -94 -143 -132t-154 -38q-88 0 -156 47.5t-106.5 138.5t-38.5 219zM395 399q0 -88 36.5 -132t103.5 -44q64 0 127.5 70t100 181 t36.5 245q0 80 -37.5 128t-102.5 48q-68 0 -129.5 -72t-98 -190t-36.5 -234z" /> -<glyph unicode="r" horiz-adv-x="862" d="M37 0l237 1118h230l-21 -207h6q147 228 353 228q59 0 96 -11l-66 -290q-45 16 -100 16q-116 0 -203.5 -91.5t-124.5 -262.5l-106 -500h-301z" /> -<glyph unicode="s" horiz-adv-x="969" d="M23 45v248q157 -90 319 -90q80 0 131 32.5t51 88.5q0 43 -37 77t-131 86q-121 68 -169 135.5t-48 159.5q0 170 110.5 263.5t315.5 93.5q201 0 363 -95l-99 -215q-140 84 -258 84q-57 0 -92 -25.5t-35 -68.5q0 -39 32 -68.5t120 -74.5q123 -63 178 -137t55 -170 q0 -188 -124.5 -288.5t-346.5 -100.5q-107 0 -186.5 15t-148.5 50z" /> -<glyph unicode="t" horiz-adv-x="840" d="M94 889l29 147l196 84l132 236h194l-49 -238h283l-50 -229h-282l-115 -539q-6 -30 -6 -53q0 -74 88 -74q65 0 162 35v-225q-111 -53 -266 -53q-150 0 -220.5 63t-70.5 195q0 50 12 112l115 539h-152z" /> -<glyph unicode="u" horiz-adv-x="1237" d="M111 301q0 93 24 213l127 604h301l-137 -653q-16 -68 -16 -119q0 -123 108 -123q92 0 167 114t118 318l98 463h301l-237 -1118h-230l21 207h-6q-145 -227 -355 -227q-138 0 -211 82.5t-73 238.5z" /> -<glyph unicode="v" horiz-adv-x="1049" d="M102 1118h295l45 -586q7 -133 7 -231h6q55 153 92 223l297 594h323l-604 -1118h-323z" /> -<glyph unicode="w" horiz-adv-x="1614" d="M125 1118h281l4 -495l-4 -167l-7 -171h4q6 20 14 41.5t51 136.5t46 119l231 536h328v-536q0 -142 -10 -297h6l28 80q73 208 95 258l219 495h307l-530 -1118h-330l-6 520q0 155 10 340h-6q-62 -178 -123 -319l-233 -541h-324z" /> -<glyph unicode="x" horiz-adv-x="1087" d="M-100 0l479 573l-225 545h321l115 -334l244 334h354l-467 -561l244 -557h-326l-125 342l-264 -342h-350z" /> -<glyph unicode="y" horiz-adv-x="1063" d="M-141 -233q68 -13 116 -13q84 0 147.5 48t117.5 149l26 49l-164 1118h295l56 -518q14 -122 14 -293h6q20 51 44 119.5t65 153.5l260 538h327l-680 -1278q-177 -332 -483 -332q-90 0 -147 19v240z" /> -<glyph unicode="z" horiz-adv-x="932" d="M-47 0l35 180l575 705h-397l51 233h750l-43 -200l-566 -685h439l-49 -233h-795z" /> -<glyph unicode="{" horiz-adv-x="727" d="M-8 459l45 229q122 0 192.5 41.5t92.5 138.5l61 285q38 170 131 239.5t270 69.5h84l-49 -225q-90 -2 -130.5 -34.5t-55.5 -106.5l-66 -297q-45 -207 -276 -236v-8q85 -26 126.5 -82.5t41.5 -134.5q0 -44 -15 -113l-36 -178q-7 -28 -7 -51q0 -54 33.5 -74t91.5 -20v-226 h-53q-167 0 -253.5 63.5t-86.5 184.5q0 57 14 125l39 184q15 69 15 86q0 140 -209 140z" /> -<glyph unicode="|" d="M455 -465v2015h219v-2015h-219z" /> -<glyph unicode="}" horiz-adv-x="727" d="M-100 -98q93 3 137 35.5t59 105.5l66 297q25 111 95 166t181 69v9q-168 51 -168 217q0 43 15 112l37 179q6 30 6 51q0 54 -36.5 74t-109.5 20l41 225h33q340 0 340 -248q0 -56 -14 -124l-39 -185q-15 -69 -15 -86q0 -139 209 -139l-45 -229q-122 0 -192.5 -42t-91.5 -139 l-62 -284q-37 -170 -130.5 -240t-270.5 -70h-45v226z" /> -<glyph unicode="~" d="M109 551v231q101 109 256 109q64 0 117 -14t139 -50q64 -27 111 -41t95 -14q51 0 112 30.5t122 90.5v-231q-103 -109 -256 -109q-59 0 -109 11.5t-147 51.5q-89 38 -127 47t-80 9q-54 0 -116.5 -33t-116.5 -88z" /> -<glyph unicode="¡" horiz-adv-x="586" d="M-74 -371l256 977h242l-158 -977h-340zM195 924q0 85 54 139.5t144 54.5q73 0 114.5 -37t41.5 -104q0 -92 -55.5 -145.5t-149.5 -53.5q-68 0 -108.5 38t-40.5 108z" /> -<glyph unicode="¢" d="M164 584q0 193 62.5 355t178 262.5t267.5 123.5l33 158h188l-35 -158q118 -14 225 -65l-92 -230q-53 23 -105 40t-118 17q-133 0 -216 -143t-83 -336q0 -96 45 -144t127 -48q75 0 140 23.5t134 58.5v-246q-136 -71 -299 -80l-41 -192h-188l49 210q-134 36 -203 136 t-69 258z" /> -<glyph unicode="£" d="M-12 0l49 246q196 48 244 264l22 104h-192l45 220h192l49 247q41 197 162 300.5t313 103.5q195 0 369 -86l-113 -232q-141 68 -237 68q-75 0 -123 -39.5t-68 -132.5l-47 -229h299l-45 -220h-299l-18 -84q-42 -195 -209 -270h655l-55 -260h-993z" /> -<glyph unicode="¤" d="M115 1047l147 147l127 -127q91 53 197 53q105 0 196 -55l127 129l150 -143l-129 -129q53 -89 53 -199q0 -107 -53 -199l125 -125l-146 -145l-127 125q-95 -51 -196 -51q-115 0 -199 51l-125 -123l-145 145l127 125q-54 93 -54 197q0 102 54 197zM397 723 q0 -77 54.5 -132.5t134.5 -55.5q81 0 136.5 55t55.5 133q0 80 -56.5 135t-135.5 55q-78 0 -133.5 -56t-55.5 -134z" /> -<glyph unicode="¥" d="M88 221l37 178h252l29 138h-252l39 178h196l-192 747h297l114 -590l371 590h311l-506 -747h203l-39 -178h-252l-28 -138h252l-37 -178h-252l-47 -221h-291l47 221h-252z" /> -<glyph unicode="¦" d="M455 350h219v-815h-219v815zM455 735v815h219v-815h-219z" /> -<glyph unicode="§" horiz-adv-x="995" d="M20 55v224q172 -105 345 -105q99 0 144.5 35t45.5 92q0 39 -33 72.5t-127 79.5q-117 57 -181 131t-64 176q0 89 47.5 163t154.5 142q-42 34 -70 84.5t-28 107.5q0 149 117 234.5t313 85.5q172 0 344 -88l-82 -193q-147 84 -282 84q-144 0 -144 -106q0 -43 40.5 -76 t127.5 -72q242 -106 242 -303q0 -188 -193 -303q38 -35 64 -85.5t26 -108.5q0 -161 -126 -253.5t-345 -92.5q-204 0 -336 75zM393 797q0 -54 43.5 -96.5t143.5 -88.5q49 31 75.5 78.5t26.5 95.5q0 109 -176 181q-51 -25 -82 -70.5t-31 -99.5z" /> -<glyph unicode="¨" horiz-adv-x="1135" d="M397 1382q0 78 42.5 118t119.5 40q133 0 133 -108q0 -73 -39 -116.5t-121 -43.5q-135 0 -135 110zM799 1382q0 78 42 118t120 40q65 0 99 -28t34 -80q0 -73 -39.5 -116.5t-120.5 -43.5q-135 0 -135 110z" /> -<glyph unicode="©" horiz-adv-x="1704" d="M125 731q0 200 100 375t275 276t377 101q199 0 373.5 -99t276 -275.5t101.5 -377.5q0 -199 -98.5 -373t-272.5 -276t-380 -102q-207 0 -382 103.5t-272.5 276.5t-97.5 371zM266 731q0 -164 81.5 -305t224 -223t305.5 -82q167 0 308 83t221.5 223.5t80.5 303.5 t-80.5 303.5t-222 223.5t-307.5 83q-164 0 -306.5 -82.5t-223.5 -223.5t-81 -304zM485 721q0 225 117.5 351t325.5 126q142 0 284 -72l-75 -174q-114 58 -205 58q-111 0 -163 -73t-52 -214q0 -134 55.5 -203t159.5 -69q43 0 108.5 15.5t124.5 43.5v-191q-131 -57 -262 -57 q-196 0 -307 122.5t-111 336.5z" /> -<glyph unicode="ª" horiz-adv-x="772" d="M152 1020q0 117 46 228t123 171t177 60q120 0 180 -103h6l39 90h154l-158 -702h-154l8 92h-2q-80 -104 -202 -104q-103 0 -160 70t-57 198zM356 1014q0 -111 86 -111q45 0 84 41.5t65.5 120t26.5 154.5q0 106 -88 106q-73 0 -123.5 -96t-50.5 -215z" /> -<glyph unicode="«" horiz-adv-x="1151" d="M72 551v18l401 463l191 -155l-279 -334l135 -350l-246 -103zM559 551v18l402 463l190 -155l-279 -334l136 -350l-246 -103z" /> -<glyph unicode="¬" d="M109 612v219h952v-583h-219v364h-733z" /> -<glyph unicode="­" horiz-adv-x="659" d="M41 424l53 250h524l-53 -250h-524z" /> -<glyph unicode="®" horiz-adv-x="1704" d="M125 731q0 200 100 375t275 276t377 101q199 0 373.5 -99t276 -275.5t101.5 -377.5q0 -199 -98.5 -373t-272.5 -276t-380 -102q-207 0 -382 103.5t-272.5 276.5t-97.5 371zM266 731q0 -164 81.5 -305t224 -223t305.5 -82q167 0 308 83t221.5 223.5t80.5 303.5 t-80.5 303.5t-222 223.5t-307.5 83q-164 0 -306.5 -82.5t-223.5 -223.5t-81 -304zM571 293v874h308q173 0 265.5 -67.5t92.5 -200.5q0 -86 -44 -149.5t-130 -96.5l197 -360h-254l-138 297h-67v-297h-230zM801 758h51q72 0 113 31t41 92q0 59 -35.5 88.5t-116.5 29.5h-53 v-241z" /> -<glyph unicode="¯" horiz-adv-x="1024" d="M-6 1556l45 201h1036l-45 -201h-1036z" /> -<glyph unicode="°" horiz-adv-x="877" d="M164 1137q0 93 46.5 173.5t127.5 126.5t172 46q93 0 173.5 -47t126.5 -127t46 -172q0 -93 -46 -173t-126 -125.5t-174 -45.5q-93 0 -173 45t-126.5 125t-46.5 174zM354 1137q0 -63 45.5 -108.5t110.5 -45.5q66 0 111 46t45 108q0 63 -45.5 110t-110.5 47t-110.5 -47.5 t-45.5 -109.5z" /> -<glyph unicode="±" d="M109 0v219h952v-219h-952zM109 674v219h366v369h219v-369h367v-219h-367v-365h-219v365h-366z" /> -<glyph unicode="²" horiz-adv-x="776" d="M59 586l35 166l273 219q111 91 141 122t44.5 59t14.5 56q0 42 -25.5 62t-60.5 20q-86 0 -188 -82l-100 158q74 57 156 87t192 30q123 0 196.5 -63t73.5 -160q0 -70 -22 -123t-70 -103.5t-189 -152.5l-129 -95h347l-41 -200h-648z" /> -<glyph unicode="³" horiz-adv-x="776" d="M92 625v192q125 -72 254 -72q76 0 125 30.5t49 88.5q0 37 -26 62.5t-88 25.5h-127l34 160h90q84 0 132.5 28t48.5 85q0 40 -26 60t-71 20q-86 0 -188 -66l-82 150q142 92 313 92q130 0 206.5 -55.5t76.5 -155.5q0 -87 -51 -145.5t-166 -88.5v-4q154 -33 154 -176 q0 -131 -107 -209t-285 -78q-75 0 -145.5 15.5t-120.5 40.5z" /> -<glyph unicode="´" horiz-adv-x="1135" d="M483 1241v25q79 88 222 303h335v-17q-46 -56 -154 -152.5t-194 -158.5h-209z" /> -<glyph unicode="µ" horiz-adv-x="1249" d="M-68 -492l342 1610h301l-135 -645q-16 -70 -16 -125q0 -60 31.5 -92.5t79.5 -32.5q90 0 162.5 106.5t117.5 319.5l98 469h301l-237 -1118h-229l18 176h-6q-117 -196 -266 -196q-51 0 -89.5 19.5t-58.5 47.5h-6q-8 -66 -21.5 -139t-82.5 -400h-304z" /> -<glyph unicode="¶" horiz-adv-x="1341" d="M147 1042q0 256 107.5 385t343.5 129h604v-1816h-162v1616h-166v-1616h-161v819q-62 -18 -146 -18q-216 0 -318 125t-102 376z" /> -<glyph unicode="·" horiz-adv-x="584" d="M131 695q0 90 53.5 144t150.5 54q68 0 109 -38t41 -107q0 -87 -55 -141t-144 -54q-73 0 -114 37.5t-41 104.5z" /> -<glyph unicode="¸" horiz-adv-x="420" d="M-207 -301q63 -23 125 -23q102 0 102 82q0 34 -31 56.5t-110 31.5l96 154h185l-39 -72q141 -49 141 -178q0 -116 -83 -179t-234 -63q-86 0 -152 23v168z" /> -<glyph unicode="¹" horiz-adv-x="776" d="M129 1214l399 248h207l-186 -876h-246l84 397q24 109 55 207q-16 -15 -80 -60l-131 -81z" /> -<glyph unicode="º" horiz-adv-x="754" d="M162 1038q0 197 104 319t277 122q129 0 197.5 -73.5t68.5 -211.5q0 -128 -48.5 -232.5t-132.5 -157t-196 -52.5q-134 0 -202 75t-68 211zM371 1026q0 -111 80 -111q63 0 105 85.5t42 207.5q0 107 -76 107q-64 0 -107.5 -89.5t-43.5 -199.5z" /> -<glyph unicode="»" horiz-adv-x="1151" d="M0 227l279 334l-136 350l246 103l203 -461v-18l-402 -463zM487 227l279 334l-135 350l246 103l202 -461v-18l-401 -463z" /> -<glyph unicode="¼" horiz-adv-x="1804" d="M177 0l1087 1462h236l-1084 -1462h-239zM97 1214l399 248h207l-186 -876h-246l84 397q24 109 55 207q-16 -15 -80 -60l-131 -81zM844 152l31 174l475 557h260l-121 -563h119l-35 -168h-119l-32 -151h-238l33 151h-373zM1078 320h174l58 231l22 74q-13 -20 -43 -58 t-211 -247z" /> -<glyph unicode="½" horiz-adv-x="1804" d="M940 1l35 166l273 219q111 91 141 122t44.5 59t14.5 56q0 42 -25.5 62t-60.5 20q-86 0 -188 -82l-100 158q74 57 156 87t192 30q123 0 196.5 -63t73.5 -160q0 -70 -22 -123t-70 -103.5t-189 -152.5l-129 -95h347l-41 -200h-648zM97 1214l399 248h207l-186 -876h-246 l84 397q24 109 55 207q-16 -15 -80 -60l-131 -81zM177 0l1087 1462h236l-1084 -1462h-239z" /> -<glyph unicode="¾" horiz-adv-x="1804" d="M310 0l1087 1462h236l-1084 -1462h-239zM905 152l31 174l475 557h260l-121 -563h119l-35 -168h-119l-32 -151h-238l33 151h-373zM1139 320h174l58 231l22 74q-13 -20 -43 -58t-211 -247zM133 625v192q125 -72 254 -72q76 0 125 30.5t49 88.5q0 37 -26 62.5t-88 25.5h-127 l34 160h90q84 0 132.5 28t48.5 85q0 40 -26 60t-71 20q-86 0 -188 -66l-82 150q142 92 313 92q130 0 206.5 -55.5t76.5 -155.5q0 -87 -51 -145.5t-166 -88.5v-4q154 -33 154 -176q0 -131 -107 -209t-285 -78q-75 0 -145.5 15.5t-120.5 40.5z" /> -<glyph unicode="¿" horiz-adv-x="940" d="M-68 -59q0 82 28.5 148.5t83.5 124t189 146.5q93 62 128 106.5t51 106.5l8 33h258l-14 -78q-19 -105 -76.5 -180t-169.5 -151q-122 -83 -156.5 -126t-34.5 -98q0 -118 133 -118q50 0 106.5 16t201.5 84l92 -221q-221 -125 -445 -125q-177 0 -280 87.5t-103 244.5z M418 924q0 86 54.5 140t143.5 54q73 0 114.5 -37t41.5 -104q0 -92 -55.5 -145.5t-149.5 -53.5q-68 0 -108.5 38t-40.5 108z" /> -<glyph unicode="À" horiz-adv-x="1286" d="M-123 0l766 1468h373l147 -1468h-297l-24 348h-473l-172 -348h-320zM494 608h333l-26 350q-10 131 -10 253v36q-44 -120 -109 -254zM539 1886v21h311q36 -148 115 -303v-25h-184q-71 69 -138.5 153.5t-103.5 153.5z" /> -<glyph unicode="Á" horiz-adv-x="1286" d="M-123 0l766 1468h373l147 -1468h-297l-24 348h-473l-172 -348h-320zM494 608h333l-26 350q-10 131 -10 253v36q-44 -120 -109 -254zM735 1579v25q79 88 222 303h335v-17q-46 -56 -154 -152.5t-194 -158.5h-209z" /> -<glyph unicode="Â" horiz-adv-x="1286" d="M-123 0l766 1468h373l147 -1468h-297l-24 348h-473l-172 -348h-320zM494 608h333l-26 350q-10 131 -10 253v36q-44 -120 -109 -254zM426 1579v25q63 57 153 147t142 156h338q22 -54 74 -142.5t102 -160.5v-25h-198q-63 53 -162 168q-105 -88 -232 -168h-217z" /> -<glyph unicode="Ã" horiz-adv-x="1286" d="M-123 0l766 1468h373l147 -1468h-297l-24 348h-473l-172 -348h-320zM494 608h333l-26 350q-10 131 -10 253v36q-44 -120 -109 -254zM448 1577q59 309 281 309q49 0 87.5 -16.5t71.5 -36t62 -35.5t60 -16q34 0 58 25.5t46 80.5h172q-66 -309 -287 -309q-49 0 -86.5 16.5 t-69.5 36t-61.5 36t-62.5 16.5q-31 0 -55.5 -28t-38.5 -79h-177z" /> -<glyph unicode="Ä" horiz-adv-x="1286" d="M-123 0l766 1468h373l147 -1468h-297l-24 348h-473l-172 -348h-320zM494 608h333l-26 350q-10 131 -10 253v36q-44 -120 -109 -254zM516 1720q0 78 42.5 118t119.5 40q133 0 133 -108q0 -73 -39 -116.5t-121 -43.5q-135 0 -135 110zM918 1720q0 78 42 118t120 40 q65 0 99 -28t34 -80q0 -73 -39.5 -116.5t-120.5 -43.5q-135 0 -135 110z" /> -<glyph unicode="Å" horiz-adv-x="1286" d="M-123 0l766 1468h373l147 -1468h-297l-24 348h-473l-172 -348h-320zM494 608h333l-26 350q-10 131 -10 253v36q-44 -120 -109 -254zM585 1565q0 109 68.5 173t179.5 64q110 0 182 -65t72 -170q0 -107 -70 -173.5t-184 -66.5q-110 0 -179 63.5t-69 174.5zM737 1565 q0 -45 24 -71t72 -26q42 0 69.5 26t27.5 71t-27.5 70.5t-69.5 25.5t-69 -25.5t-27 -70.5z" /> -<glyph unicode="Æ" horiz-adv-x="1833" d="M-123 0l922 1462h1104l-54 -254h-512l-67 -321h477l-55 -254h-478l-79 -377h512l-54 -256h-817l74 348h-426l-219 -348h-328zM588 608h317l127 600h-80z" /> -<glyph unicode="Ç" horiz-adv-x="1253" d="M123 553q0 262 104 482.5t278 335t400 114.5q125 0 222 -22.5t208 -82.5l-118 -250q-106 59 -175 78t-137 19q-132 0 -237.5 -81t-169.5 -238.5t-64 -338.5q0 -167 68.5 -248t218.5 -81q146 0 338 77v-260q-199 -77 -400 -77q-254 0 -395 149.5t-141 423.5zM356 -301 q63 -23 125 -23q102 0 102 82q0 34 -31 56.5t-110 31.5l96 154h185l-39 -72q141 -49 141 -178q0 -116 -83 -179t-234 -63q-86 0 -152 23v168z" /> -<glyph unicode="È" horiz-adv-x="1110" d="M53 0l309 1462h818l-54 -254h-512l-67 -321h477l-55 -254h-477l-80 -377h512l-54 -256h-817zM480 1886v21h311q36 -148 115 -303v-25h-184q-71 69 -138.5 153.5t-103.5 153.5z" /> -<glyph unicode="É" horiz-adv-x="1110" d="M53 0l309 1462h818l-54 -254h-512l-67 -321h477l-55 -254h-477l-80 -377h512l-54 -256h-817zM608 1579v25q79 88 222 303h335v-17q-46 -56 -154 -152.5t-194 -158.5h-209z" /> -<glyph unicode="Ê" horiz-adv-x="1110" d="M53 0l309 1462h818l-54 -254h-512l-67 -321h477l-55 -254h-477l-80 -377h512l-54 -256h-817zM368 1579v25q63 57 153 147t142 156h338q22 -54 74 -142.5t102 -160.5v-25h-198q-63 53 -162 168q-105 -88 -232 -168h-217z" /> -<glyph unicode="Ë" horiz-adv-x="1110" d="M53 0l309 1462h818l-54 -254h-512l-67 -321h477l-55 -254h-477l-80 -377h512l-54 -256h-817zM438 1720q0 78 42.5 118t119.5 40q133 0 133 -108q0 -73 -39 -116.5t-121 -43.5q-135 0 -135 110zM840 1720q0 78 42 118t120 40q65 0 99 -28t34 -80q0 -73 -39.5 -116.5 t-120.5 -43.5q-135 0 -135 110z" /> -<glyph unicode="Ì" horiz-adv-x="659" d="M53 0l312 1462h305l-312 -1462h-305zM241 1886v21h311q36 -148 115 -303v-25h-184q-71 69 -138.5 153.5t-103.5 153.5z" /> -<glyph unicode="Í" horiz-adv-x="659" d="M53 0l312 1462h305l-312 -1462h-305zM414 1579v25q79 88 222 303h335v-17q-46 -56 -154 -152.5t-194 -158.5h-209z" /> -<glyph unicode="Î" horiz-adv-x="659" d="M53 0l312 1462h305l-312 -1462h-305zM128 1579v25q63 57 153 147t142 156h338q22 -54 74 -142.5t102 -160.5v-25h-198q-63 53 -162 168q-105 -88 -232 -168h-217z" /> -<glyph unicode="Ï" horiz-adv-x="659" d="M53 0l312 1462h305l-312 -1462h-305zM222 1720q0 78 42.5 118t119.5 40q133 0 133 -108q0 -73 -39 -116.5t-121 -43.5q-135 0 -135 110zM624 1720q0 78 42 118t120 40q65 0 99 -28t34 -80q0 -73 -39.5 -116.5t-120.5 -43.5q-135 0 -135 110z" /> -<glyph unicode="Ð" horiz-adv-x="1386" d="M37 596l55 254h139l131 612h396q270 0 417.5 -143t147.5 -410q0 -280 -98 -486.5t-283.5 -314.5t-437.5 -108h-451l125 596h-141zM412 256h106q148 0 258 76t172 223.5t62 337.5q0 154 -72.5 234.5t-208.5 80.5h-115l-75 -358h237l-55 -254h-238z" /> -<glyph unicode="Ñ" horiz-adv-x="1546" d="M53 0l309 1462h357l340 -1077h4q12 76 39 217t180 860h274l-309 -1462h-342l-356 1106h-6l-4 -32q-32 -216 -66 -386l-145 -688h-275zM563 1577q59 309 281 309q49 0 87.5 -16.5t71.5 -36t62 -35.5t60 -16q34 0 58 25.5t46 80.5h172q-66 -309 -287 -309q-49 0 -86.5 16.5 t-69.5 36t-61.5 36t-62.5 16.5q-31 0 -55.5 -28t-38.5 -79h-177z" /> -<glyph unicode="Ò" horiz-adv-x="1495" d="M123 537q0 265 99 487.5t273 341.5t402 119q255 0 395 -144t140 -403q0 -283 -99 -506.5t-271 -337.5t-396 -114q-256 0 -399.5 147.5t-143.5 409.5zM434 537q0 -147 66.5 -222t187.5 -75t220.5 87t155.5 246t56 357q0 142 -65 219.5t-183 77.5q-121 0 -222 -91.5 t-158.5 -251.5t-57.5 -347zM627 1886v21h311q36 -148 115 -303v-25h-184q-71 69 -138.5 153.5t-103.5 153.5z" /> -<glyph unicode="Ó" horiz-adv-x="1495" d="M123 537q0 265 99 487.5t273 341.5t402 119q255 0 395 -144t140 -403q0 -283 -99 -506.5t-271 -337.5t-396 -114q-256 0 -399.5 147.5t-143.5 409.5zM434 537q0 -147 66.5 -222t187.5 -75t220.5 87t155.5 246t56 357q0 142 -65 219.5t-183 77.5q-121 0 -222 -91.5 t-158.5 -251.5t-57.5 -347zM753 1579v25q79 88 222 303h335v-17q-46 -56 -154 -152.5t-194 -158.5h-209z" /> -<glyph unicode="Ô" horiz-adv-x="1495" d="M123 537q0 265 99 487.5t273 341.5t402 119q255 0 395 -144t140 -403q0 -283 -99 -506.5t-271 -337.5t-396 -114q-256 0 -399.5 147.5t-143.5 409.5zM434 537q0 -147 66.5 -222t187.5 -75t220.5 87t155.5 246t56 357q0 142 -65 219.5t-183 77.5q-121 0 -222 -91.5 t-158.5 -251.5t-57.5 -347zM499 1579v25q63 57 153 147t142 156h338q22 -54 74 -142.5t102 -160.5v-25h-198q-63 53 -162 168q-105 -88 -232 -168h-217z" /> -<glyph unicode="Õ" horiz-adv-x="1495" d="M123 537q0 265 99 487.5t273 341.5t402 119q255 0 395 -144t140 -403q0 -283 -99 -506.5t-271 -337.5t-396 -114q-256 0 -399.5 147.5t-143.5 409.5zM434 537q0 -147 66.5 -222t187.5 -75t220.5 87t155.5 246t56 357q0 142 -65 219.5t-183 77.5q-121 0 -222 -91.5 t-158.5 -251.5t-57.5 -347zM520 1577q59 309 281 309q49 0 87.5 -16.5t71.5 -36t62 -35.5t60 -16q34 0 58 25.5t46 80.5h172q-66 -309 -287 -309q-49 0 -86.5 16.5t-69.5 36t-61.5 36t-62.5 16.5q-31 0 -55.5 -28t-38.5 -79h-177z" /> -<glyph unicode="Ö" horiz-adv-x="1495" d="M123 537q0 265 99 487.5t273 341.5t402 119q255 0 395 -144t140 -403q0 -283 -99 -506.5t-271 -337.5t-396 -114q-256 0 -399.5 147.5t-143.5 409.5zM434 537q0 -147 66.5 -222t187.5 -75t220.5 87t155.5 246t56 357q0 142 -65 219.5t-183 77.5q-121 0 -222 -91.5 t-158.5 -251.5t-57.5 -347zM585 1720q0 78 42.5 118t119.5 40q133 0 133 -108q0 -73 -39 -116.5t-121 -43.5q-135 0 -135 110zM987 1720q0 78 42 118t120 40q65 0 99 -28t34 -80q0 -73 -39.5 -116.5t-120.5 -43.5q-135 0 -135 110z" /> -<glyph unicode="×" d="M129 1024l152 154l301 -299l305 299l153 -150l-305 -305l301 -303l-149 -152l-305 301l-301 -299l-150 152l297 301z" /> -<glyph unicode="Ø" horiz-adv-x="1495" d="M100 29l121 151q-98 138 -98 357q0 265 99 487.5t273 341.5t402 119q182 0 305 -76l105 131l151 -117l-117 -145q91 -134 91 -340q0 -283 -99 -506.5t-271 -337.5t-396 -114q-180 0 -304 71l-108 -137zM424 537q0 -32 8 -101l596 754q-69 43 -158 43q-126 0 -229 -91.5 t-160 -252.5t-57 -352zM539 270q59 -37 153 -37q124 0 226 89t158.5 247.5t56.5 360.5l-5 80z" /> -<glyph unicode="Ù" horiz-adv-x="1415" d="M141 401q0 72 15 138l196 923h305l-194 -919q-17 -74 -17 -125q0 -178 189 -178q123 0 195 76.5t104 228.5l194 917h306l-201 -946q-57 -266 -218 -401t-419 -135q-212 0 -333.5 113.5t-121.5 307.5zM576 1886v21h311q36 -148 115 -303v-25h-184q-71 69 -138.5 153.5 t-103.5 153.5z" /> -<glyph unicode="Ú" horiz-adv-x="1415" d="M141 401q0 72 15 138l196 923h305l-194 -919q-17 -74 -17 -125q0 -178 189 -178q123 0 195 76.5t104 228.5l194 917h306l-201 -946q-57 -266 -218 -401t-419 -135q-212 0 -333.5 113.5t-121.5 307.5zM757 1579v25q79 88 222 303h335v-17q-46 -56 -154 -152.5t-194 -158.5 h-209z" /> -<glyph unicode="Û" horiz-adv-x="1415" d="M141 401q0 72 15 138l196 923h305l-194 -919q-17 -74 -17 -125q0 -178 189 -178q123 0 195 76.5t104 228.5l194 917h306l-201 -946q-57 -266 -218 -401t-419 -135q-212 0 -333.5 113.5t-121.5 307.5zM475 1579v25q63 57 153 147t142 156h338q22 -54 74 -142.5t102 -160.5 v-25h-198q-63 53 -162 168q-105 -88 -232 -168h-217z" /> -<glyph unicode="Ü" horiz-adv-x="1415" d="M141 401q0 72 15 138l196 923h305l-194 -919q-17 -74 -17 -125q0 -178 189 -178q123 0 195 76.5t104 228.5l194 917h306l-201 -946q-57 -266 -218 -401t-419 -135q-212 0 -333.5 113.5t-121.5 307.5zM565 1720q0 78 42.5 118t119.5 40q133 0 133 -108q0 -73 -39 -116.5 t-121 -43.5q-135 0 -135 110zM967 1720q0 78 42 118t120 40q65 0 99 -28t34 -80q0 -73 -39.5 -116.5t-120.5 -43.5q-135 0 -135 110z" /> -<glyph unicode="Ý" horiz-adv-x="1155" d="M186 1462h312l129 -592l374 592h342l-618 -903l-119 -559h-303l119 559zM606 1579v25q79 88 222 303h335v-17q-46 -56 -154 -152.5t-194 -158.5h-209z" /> -<glyph unicode="Þ" horiz-adv-x="1188" d="M53 0l309 1462h306l-50 -229h35q242 0 366 -106.5t124 -319.5q0 -243 -170.5 -378.5t-466.5 -135.5h-86l-62 -293h-305zM475 547h55q139 0 222.5 66.5t83.5 185.5q0 180 -195 180h-74z" /> -<glyph unicode="ß" horiz-adv-x="1350" d="M-260 -225q61 -21 115 -21q133 0 170 178l254 1207q47 224 182 326t385 102q208 0 331 -90t123 -240q0 -114 -49 -192t-178 -152q-73 -42 -96 -68.5t-23 -54.5q0 -23 22 -49.5t79 -69.5q107 -83 144.5 -150.5t37.5 -150.5q0 -170 -123.5 -270t-337.5 -100q-187 0 -297 61 v240q128 -78 258 -78q101 0 148 33t47 86q0 40 -26.5 75t-108.5 97q-94 72 -129 130t-35 126q0 84 45 145t162 127q66 37 104.5 76t38.5 96q0 62 -39.5 98.5t-124.5 36.5q-96 0 -156 -51.5t-85 -171.5l-254 -1219q-43 -198 -147 -288.5t-277 -90.5q-90 0 -160 25v242z" /> -<glyph unicode="à" horiz-adv-x="1217" d="M90 385q0 198 72 377.5t189 278t257 98.5q97 0 167.5 -42t109.5 -122h8l57 143h232l-238 -1118h-229l14 145h-4q-134 -165 -319 -165q-147 0 -231.5 106.5t-84.5 298.5zM395 399q0 -88 33.5 -132t95.5 -44q69 0 133 67t103 181.5t39 259.5q0 71 -38.5 117.5t-101.5 46.5 q-68 0 -129.5 -72t-98 -190t-36.5 -234zM443 1548v21h311q36 -148 115 -303v-25h-184q-71 69 -138.5 153.5t-103.5 153.5z" /> -<glyph unicode="á" horiz-adv-x="1217" d="M90 385q0 198 72 377.5t189 278t257 98.5q97 0 167.5 -42t109.5 -122h8l57 143h232l-238 -1118h-229l14 145h-4q-134 -165 -319 -165q-147 0 -231.5 106.5t-84.5 298.5zM395 399q0 -88 33.5 -132t95.5 -44q69 0 133 67t103 181.5t39 259.5q0 71 -38.5 117.5t-101.5 46.5 q-68 0 -129.5 -72t-98 -190t-36.5 -234zM598 1241v25q79 88 222 303h335v-17q-46 -56 -154 -152.5t-194 -158.5h-209z" /> -<glyph unicode="â" horiz-adv-x="1217" d="M90 385q0 198 72 377.5t189 278t257 98.5q97 0 167.5 -42t109.5 -122h8l57 143h232l-238 -1118h-229l14 145h-4q-134 -165 -319 -165q-147 0 -231.5 106.5t-84.5 298.5zM395 399q0 -88 33.5 -132t95.5 -44q69 0 133 67t103 181.5t39 259.5q0 71 -38.5 117.5t-101.5 46.5 q-68 0 -129.5 -72t-98 -190t-36.5 -234zM311 1240v25q63 57 153 147t142 156h338q22 -54 74 -142.5t102 -160.5v-25h-198q-63 53 -162 168q-105 -88 -232 -168h-217z" /> -<glyph unicode="ã" horiz-adv-x="1217" d="M90 385q0 198 72 377.5t189 278t257 98.5q97 0 167.5 -42t109.5 -122h8l57 143h232l-238 -1118h-229l14 145h-4q-134 -165 -319 -165q-147 0 -231.5 106.5t-84.5 298.5zM395 399q0 -88 33.5 -132t95.5 -44q69 0 133 67t103 181.5t39 259.5q0 71 -38.5 117.5t-101.5 46.5 q-68 0 -129.5 -72t-98 -190t-36.5 -234zM333 1239q59 309 281 309q49 0 87.5 -16.5t71.5 -36t62 -35.5t60 -16q34 0 58 25.5t46 80.5h172q-66 -309 -287 -309q-49 0 -86.5 16.5t-69.5 36t-61.5 36t-62.5 16.5q-31 0 -55.5 -28t-38.5 -79h-177z" /> -<glyph unicode="ä" horiz-adv-x="1217" d="M90 385q0 198 72 377.5t189 278t257 98.5q97 0 167.5 -42t109.5 -122h8l57 143h232l-238 -1118h-229l14 145h-4q-134 -165 -319 -165q-147 0 -231.5 106.5t-84.5 298.5zM395 399q0 -88 33.5 -132t95.5 -44q69 0 133 67t103 181.5t39 259.5q0 71 -38.5 117.5t-101.5 46.5 q-68 0 -129.5 -72t-98 -190t-36.5 -234zM397 1382q0 78 42.5 118t119.5 40q133 0 133 -108q0 -73 -39 -116.5t-121 -43.5q-135 0 -135 110zM799 1382q0 78 42 118t120 40q65 0 99 -28t34 -80q0 -73 -39.5 -116.5t-120.5 -43.5q-135 0 -135 110z" /> -<glyph unicode="å" horiz-adv-x="1217" d="M90 385q0 198 72 377.5t189 278t257 98.5q97 0 167.5 -42t109.5 -122h8l57 143h232l-238 -1118h-229l14 145h-4q-134 -165 -319 -165q-147 0 -231.5 106.5t-84.5 298.5zM395 399q0 -88 33.5 -132t95.5 -44q69 0 133 67t103 181.5t39 259.5q0 71 -38.5 117.5t-101.5 46.5 q-68 0 -129.5 -72t-98 -190t-36.5 -234zM521 1477q0 109 68.5 173t179.5 64q110 0 182 -65t72 -170q0 -107 -70 -173.5t-184 -66.5q-110 0 -179 63.5t-69 174.5zM673 1477q0 -45 24 -71t72 -26q42 0 69.5 26t27.5 71t-27.5 70.5t-69.5 25.5t-69 -25.5t-27 -70.5z" /> -<glyph unicode="æ" horiz-adv-x="1786" d="M90 385q0 200 68.5 375.5t185 277t258.5 101.5q96 0 160.5 -38.5t114.5 -125.5h6l57 143h188l-18 -90q44 49 120.5 80t168.5 31q157 0 246.5 -83.5t89.5 -221.5q0 -187 -167 -288.5t-476 -101.5h-52l-2 -19v-19q0 -96 55.5 -147.5t159.5 -51.5q66 0 152 23t162 63v-227 q-179 -86 -361 -86q-109 0 -179.5 27t-117.5 87l-16 -94h-188l14 145h-6q-71 -88 -146.5 -126.5t-167.5 -38.5q-146 0 -227.5 109t-81.5 296zM395 399q0 -84 32.5 -130t90.5 -46q72 0 134 68t99 184.5t37 243.5q0 80 -33 128t-102 48q-68 0 -128 -69t-95 -185.5t-35 -241.5z M1073 647h45q155 0 241.5 48.5t86.5 131.5q0 95 -105 95q-88 0 -166 -80t-102 -195z" /> -<glyph unicode="ç" horiz-adv-x="989" d="M90 391q0 212 74.5 385.5t209.5 268t308 94.5q182 0 328 -72l-92 -229q-54 23 -106 40t-118 17q-85 0 -153.5 -64t-107 -175.5t-38.5 -239.5q0 -96 45.5 -144.5t126.5 -48.5q76 0 141 23.5t134 58.5v-246q-152 -79 -336 -79q-201 0 -308.5 107.5t-107.5 303.5zM184 -301 q63 -23 125 -23q102 0 102 82q0 34 -31 56.5t-110 31.5l96 154h185l-39 -72q141 -49 141 -178q0 -116 -83 -179t-234 -63q-86 0 -152 23v168z" /> -<glyph unicode="è" horiz-adv-x="1141" d="M90 412q0 207 82.5 377.5t223.5 260t319 89.5q177 0 276 -81.5t99 -223.5q0 -187 -167 -288.5t-477 -101.5h-51l-2 -21v-20q0 -91 51.5 -143.5t147.5 -52.5q87 0 158 19t172 67v-227q-172 -86 -390 -86q-210 0 -326 113t-116 319zM428 647h45q155 0 241.5 48.5 t86.5 131.5q0 95 -105 95q-88 0 -166 -80t-102 -195zM423 1548v21h311q36 -148 115 -303v-25h-184q-71 69 -138.5 153.5t-103.5 153.5z" /> -<glyph unicode="é" horiz-adv-x="1141" d="M90 412q0 207 82.5 377.5t223.5 260t319 89.5q177 0 276 -81.5t99 -223.5q0 -187 -167 -288.5t-477 -101.5h-51l-2 -21v-20q0 -91 51.5 -143.5t147.5 -52.5q87 0 158 19t172 67v-227q-172 -86 -390 -86q-210 0 -326 113t-116 319zM428 647h45q155 0 241.5 48.5 t86.5 131.5q0 95 -105 95q-88 0 -166 -80t-102 -195zM528 1241v25q79 88 222 303h335v-17q-46 -56 -154 -152.5t-194 -158.5h-209z" /> -<glyph unicode="ê" horiz-adv-x="1141" d="M90 412q0 207 82.5 377.5t223.5 260t319 89.5q177 0 276 -81.5t99 -223.5q0 -187 -167 -288.5t-477 -101.5h-51l-2 -21v-20q0 -91 51.5 -143.5t147.5 -52.5q87 0 158 19t172 67v-227q-172 -86 -390 -86q-210 0 -326 113t-116 319zM428 647h45q155 0 241.5 48.5 t86.5 131.5q0 95 -105 95q-88 0 -166 -80t-102 -195zM292 1241v25q63 57 153 147t142 156h338q22 -54 74 -142.5t102 -160.5v-25h-198q-63 53 -162 168q-105 -88 -232 -168h-217z" /> -<glyph unicode="ë" horiz-adv-x="1141" d="M90 412q0 207 82.5 377.5t223.5 260t319 89.5q177 0 276 -81.5t99 -223.5q0 -187 -167 -288.5t-477 -101.5h-51l-2 -21v-20q0 -91 51.5 -143.5t147.5 -52.5q87 0 158 19t172 67v-227q-172 -86 -390 -86q-210 0 -326 113t-116 319zM428 647h45q155 0 241.5 48.5 t86.5 131.5q0 95 -105 95q-88 0 -166 -80t-102 -195zM365 1382q0 78 42.5 118t119.5 40q133 0 133 -108q0 -73 -39 -116.5t-121 -43.5q-135 0 -135 110zM767 1382q0 78 42 118t120 40q65 0 99 -28t34 -80q0 -73 -39.5 -116.5t-120.5 -43.5q-135 0 -135 110z" /> -<glyph unicode="ì" horiz-adv-x="608" d="M37 0l237 1118h301l-237 -1118h-301zM153 1548v21h311q36 -148 115 -303v-25h-184q-71 69 -138.5 153.5t-103.5 153.5z" /> -<glyph unicode="í" horiz-adv-x="608" d="M37 0l237 1118h301l-237 -1118h-301zM291 1241v25q79 88 222 303h335v-17q-46 -56 -154 -152.5t-194 -158.5h-209z" /> -<glyph unicode="î" horiz-adv-x="608" d="M37 0l237 1118h301l-237 -1118h-301zM36 1241v25q63 57 153 147t142 156h338q22 -54 74 -142.5t102 -160.5v-25h-198q-63 53 -162 168q-105 -88 -232 -168h-217z" /> -<glyph unicode="ï" horiz-adv-x="608" d="M37 0l237 1118h301l-237 -1118h-301zM126 1382q0 78 42.5 118t119.5 40q133 0 133 -108q0 -73 -39 -116.5t-121 -43.5q-135 0 -135 110zM528 1382q0 78 42 118t120 40q65 0 99 -28t34 -80q0 -73 -39.5 -116.5t-120.5 -43.5q-135 0 -135 110z" /> -<glyph unicode="ð" horiz-adv-x="1182" d="M72 406q0 165 64.5 301t180.5 212t265 76q83 0 151.5 -31t114.5 -94h6q-20 213 -117 310l-231 -131l-88 147l200 113q-34 34 -124 80l118 186q134 -61 232 -139l237 131l76 -152l-192 -106q81 -107 113 -235t32 -279q0 -249 -69.5 -432.5t-203.5 -283t-323 -99.5 q-216 0 -329 110t-113 316zM375 377q0 -81 39 -126.5t114 -45.5q66 0 122.5 55.5t89 148.5t32.5 193q0 77 -38.5 122.5t-108.5 45.5q-73 0 -130 -53t-88.5 -143t-31.5 -197z" /> -<glyph unicode="ñ" horiz-adv-x="1237" d="M37 0l237 1118h230l-21 -207h6q146 228 355 228q138 0 213.5 -83.5t75.5 -238.5q0 -73 -23 -180l-133 -637h-301l137 653q16 68 16 119q0 123 -108 123q-92 0 -167 -114t-118 -318l-98 -463h-301zM358 1239q59 309 281 309q49 0 87.5 -16.5t71.5 -36t62 -35.5t60 -16 q34 0 58 25.5t46 80.5h172q-66 -309 -287 -309q-49 0 -86.5 16.5t-69.5 36t-61.5 36t-62.5 16.5q-31 0 -55.5 -28t-38.5 -79h-177z" /> -<glyph unicode="ò" horiz-adv-x="1198" d="M90 410q0 213 71.5 379.5t206.5 258t316 91.5q196 0 310 -118t114 -325q0 -211 -70.5 -374t-203.5 -252.5t-316 -89.5q-195 0 -311.5 117.5t-116.5 312.5zM393 410q0 -185 150 -185q75 0 135 61.5t93.5 171t33.5 238.5q0 197 -143 197q-75 0 -134.5 -61t-97 -179 t-37.5 -243zM419 1548v21h311q36 -148 115 -303v-25h-184q-71 69 -138.5 153.5t-103.5 153.5z" /> -<glyph unicode="ó" horiz-adv-x="1198" d="M90 410q0 213 71.5 379.5t206.5 258t316 91.5q196 0 310 -118t114 -325q0 -211 -70.5 -374t-203.5 -252.5t-316 -89.5q-195 0 -311.5 117.5t-116.5 312.5zM393 410q0 -185 150 -185q75 0 135 61.5t93.5 171t33.5 238.5q0 197 -143 197q-75 0 -134.5 -61t-97 -179 t-37.5 -243zM571 1241v25q79 88 222 303h335v-17q-46 -56 -154 -152.5t-194 -158.5h-209z" /> -<glyph unicode="ô" horiz-adv-x="1198" d="M90 410q0 213 71.5 379.5t206.5 258t316 91.5q196 0 310 -118t114 -325q0 -211 -70.5 -374t-203.5 -252.5t-316 -89.5q-195 0 -311.5 117.5t-116.5 312.5zM393 410q0 -185 150 -185q75 0 135 61.5t93.5 171t33.5 238.5q0 197 -143 197q-75 0 -134.5 -61t-97 -179 t-37.5 -243zM300 1241v25q63 57 153 147t142 156h338q22 -54 74 -142.5t102 -160.5v-25h-198q-63 53 -162 168q-105 -88 -232 -168h-217z" /> -<glyph unicode="õ" horiz-adv-x="1198" d="M90 410q0 213 71.5 379.5t206.5 258t316 91.5q196 0 310 -118t114 -325q0 -211 -70.5 -374t-203.5 -252.5t-316 -89.5q-195 0 -311.5 117.5t-116.5 312.5zM393 410q0 -185 150 -185q75 0 135 61.5t93.5 171t33.5 238.5q0 197 -143 197q-75 0 -134.5 -61t-97 -179 t-37.5 -243zM314 1239q59 309 281 309q49 0 87.5 -16.5t71.5 -36t62 -35.5t60 -16q34 0 58 25.5t46 80.5h172q-66 -309 -287 -309q-49 0 -86.5 16.5t-69.5 36t-61.5 36t-62.5 16.5q-31 0 -55.5 -28t-38.5 -79h-177z" /> -<glyph unicode="ö" horiz-adv-x="1198" d="M90 410q0 213 71.5 379.5t206.5 258t316 91.5q196 0 310 -118t114 -325q0 -211 -70.5 -374t-203.5 -252.5t-316 -89.5q-195 0 -311.5 117.5t-116.5 312.5zM393 410q0 -185 150 -185q75 0 135 61.5t93.5 171t33.5 238.5q0 197 -143 197q-75 0 -134.5 -61t-97 -179 t-37.5 -243zM386 1382q0 78 42.5 118t119.5 40q133 0 133 -108q0 -73 -39 -116.5t-121 -43.5q-135 0 -135 110zM788 1382q0 78 42 118t120 40q65 0 99 -28t34 -80q0 -73 -39.5 -116.5t-120.5 -43.5q-135 0 -135 110z" /> -<glyph unicode="÷" d="M109 612v219h952v-219h-952zM444 373q0 76 37 113.5t103 37.5t102.5 -39t36.5 -112q0 -70 -37 -111t-102 -41t-102.5 39t-37.5 113zM444 1071q0 75 37 113.5t103 38.5q67 0 103 -40.5t36 -111.5q0 -70 -37 -110.5t-102 -40.5t-102.5 39t-37.5 112z" /> -<glyph unicode="ø" horiz-adv-x="1198" d="M43 6l119 148q-72 107 -72 256q0 213 71.5 379.5t206.5 258t316 91.5q131 0 227 -56l70 88l145 -110l-84 -105q66 -107 66 -260q0 -211 -70.5 -374t-203.5 -252.5t-316 -89.5q-123 0 -225 53l-109 -135zM385 426l365 453q-35 24 -88 24q-81 0 -144.5 -62.5t-98 -169.5 t-34.5 -233v-12zM457 238q11 -8 35.5 -15.5t50.5 -7.5q114 0 193 133t79 318v16z" /> -<glyph unicode="ù" horiz-adv-x="1237" d="M111 301q0 93 24 213l127 604h301l-137 -653q-16 -68 -16 -119q0 -123 108 -123q92 0 167 114t118 318l98 463h301l-237 -1118h-230l21 207h-6q-145 -227 -355 -227q-138 0 -211 82.5t-73 238.5zM419 1548v21h311q36 -148 115 -303v-25h-184q-71 69 -138.5 153.5 t-103.5 153.5z" /> -<glyph unicode="ú" horiz-adv-x="1237" d="M111 301q0 93 24 213l127 604h301l-137 -653q-16 -68 -16 -119q0 -123 108 -123q92 0 167 114t118 318l98 463h301l-237 -1118h-230l21 207h-6q-145 -227 -355 -227q-138 0 -211 82.5t-73 238.5zM610 1241v25q79 88 222 303h335v-17q-46 -56 -154 -152.5t-194 -158.5 h-209z" /> -<glyph unicode="û" horiz-adv-x="1237" d="M111 301q0 93 24 213l127 604h301l-137 -653q-16 -68 -16 -119q0 -123 108 -123q92 0 167 114t118 318l98 463h301l-237 -1118h-230l21 207h-6q-145 -227 -355 -227q-138 0 -211 82.5t-73 238.5zM334 1241v25q63 57 153 147t142 156h338q22 -54 74 -142.5t102 -160.5v-25 h-198q-63 53 -162 168q-105 -88 -232 -168h-217z" /> -<glyph unicode="ü" horiz-adv-x="1237" d="M111 301q0 93 24 213l127 604h301l-137 -653q-16 -68 -16 -119q0 -123 108 -123q92 0 167 114t118 318l98 463h301l-237 -1118h-230l21 207h-6q-145 -227 -355 -227q-138 0 -211 82.5t-73 238.5zM411 1382q0 78 42.5 118t119.5 40q133 0 133 -108q0 -73 -39 -116.5 t-121 -43.5q-135 0 -135 110zM813 1382q0 78 42 118t120 40q65 0 99 -28t34 -80q0 -73 -39.5 -116.5t-120.5 -43.5q-135 0 -135 110z" /> -<glyph unicode="ý" horiz-adv-x="1063" d="M-141 -233q68 -13 116 -13q84 0 147.5 48t117.5 149l26 49l-164 1118h295l56 -518q14 -122 14 -293h6q20 51 44 119.5t65 153.5l260 538h327l-680 -1278q-177 -332 -483 -332q-90 0 -147 19v240zM497 1241v25q79 88 222 303h335v-17q-46 -56 -154 -152.5t-194 -158.5 h-209z" /> -<glyph unicode="þ" horiz-adv-x="1219" d="M-68 -492l435 2048h301l-66 -307q-29 -131 -80 -280h8q131 170 283 170q150 0 232.5 -106.5t82.5 -301.5q0 -199 -69 -381t-182 -276t-250 -94q-178 0 -271 163h-8q-12 -159 -43 -295l-72 -340h-301zM420 399q0 -80 33.5 -128t105.5 -48q69 0 129 65t97.5 183.5 t37.5 247.5q0 88 -37.5 132t-103.5 44q-71 0 -130 -65t-95.5 -184.5t-36.5 -246.5z" /> -<glyph unicode="ÿ" horiz-adv-x="1063" d="M-141 -233q68 -13 116 -13q84 0 147.5 48t117.5 149l26 49l-164 1118h295l56 -518q14 -122 14 -293h6q20 51 44 119.5t65 153.5l260 538h327l-680 -1278q-177 -332 -483 -332q-90 0 -147 19v240zM310 1382q0 78 42.5 118t119.5 40q133 0 133 -108q0 -73 -39 -116.5 t-121 -43.5q-135 0 -135 110zM712 1382q0 78 42 118t120 40q65 0 99 -28t34 -80q0 -73 -39.5 -116.5t-120.5 -43.5q-135 0 -135 110z" /> -<glyph unicode="ı" horiz-adv-x="608" d="M37 0l237 1118h301l-237 -1118h-301z" /> -<glyph unicode="Œ" horiz-adv-x="1845" d="M123 537q0 265 99 487.5t273 341.5t402 119q140 0 209 -23h809l-53 -254h-512l-68 -321h477l-55 -254h-477l-80 -377h512l-53 -256h-760q-93 -20 -180 -20q-256 0 -399.5 147.5t-143.5 409.5zM434 537q0 -147 66.5 -222t187.5 -75q88 0 158 32l194 916q-62 39 -168 39 q-121 0 -222 -91.5t-158.5 -251.5t-57.5 -347z" /> -<glyph unicode="œ" horiz-adv-x="1806" d="M90 414q0 216 69 380.5t200 254.5t309 90q209 0 313 -160q154 160 399 160q177 0 276 -81.5t99 -223.5q0 -187 -167 -288.5t-476 -101.5h-51l-2 -21v-20q0 -91 51 -143.5t147 -52.5q87 0 158 19t172 67v-227q-93 -46 -185.5 -66t-203.5 -20q-116 0 -208 38.5t-138 106.5 q-63 -68 -147 -106.5t-207 -38.5q-187 0 -297.5 117t-110.5 317zM393 414q0 -91 36.5 -140t109.5 -49q109 0 179 134.5t70 336.5q0 96 -37 146.5t-106 50.5q-71 0 -127 -60.5t-90.5 -176.5t-34.5 -242zM1094 647h45q155 0 241 48.5t86 131.5q0 95 -104 95 q-88 0 -165.5 -78.5t-102.5 -196.5z" /> -<glyph unicode="Ÿ" horiz-adv-x="1155" d="M186 1462h312l129 -592l374 592h342l-618 -903l-119 -559h-303l119 559zM432 1720q0 78 42.5 118t119.5 40q133 0 133 -108q0 -73 -39 -116.5t-121 -43.5q-135 0 -135 110zM834 1720q0 78 42 118t120 40q65 0 99 -28t34 -80q0 -73 -39.5 -116.5t-120.5 -43.5 q-135 0 -135 110z" /> -<glyph unicode="ˆ" horiz-adv-x="1135" d="M311 1241v25q63 57 153 147t142 156h338q22 -54 74 -142.5t102 -160.5v-25h-198q-63 53 -162 168q-105 -88 -232 -168h-217z" /> -<glyph unicode="˚" horiz-adv-x="1182" d="M532 1477q0 109 68.5 173t179.5 64q110 0 182 -65t72 -170q0 -107 -70 -173.5t-184 -66.5q-110 0 -179 63.5t-69 174.5zM684 1477q0 -45 24 -71t72 -26q42 0 69.5 26t27.5 71t-27.5 70.5t-69.5 25.5t-69 -25.5t-27 -70.5z" /> -<glyph unicode="˜" horiz-adv-x="1135" d="M315 1239q59 309 281 309q49 0 87.5 -16.5t71.5 -36t62 -35.5t60 -16q34 0 58 25.5t46 80.5h172q-66 -309 -287 -309q-49 0 -86.5 16.5t-69.5 36t-61.5 36t-62.5 16.5q-31 0 -55.5 -28t-38.5 -79h-177z" /> -<glyph unicode=" " horiz-adv-x="953" /> -<glyph unicode=" " horiz-adv-x="1907" /> -<glyph unicode=" " horiz-adv-x="953" /> -<glyph unicode=" " horiz-adv-x="1907" /> -<glyph unicode=" " horiz-adv-x="635" /> -<glyph unicode=" " horiz-adv-x="476" /> -<glyph unicode=" " horiz-adv-x="317" /> -<glyph unicode=" " horiz-adv-x="317" /> -<glyph unicode=" " horiz-adv-x="238" /> -<glyph unicode=" " horiz-adv-x="381" /> -<glyph unicode=" " horiz-adv-x="105" /> -<glyph unicode="‐" horiz-adv-x="659" d="M41 424l53 250h524l-53 -250h-524z" /> -<glyph unicode="‑" horiz-adv-x="659" d="M41 424l53 250h524l-53 -250h-524z" /> -<glyph unicode="‒" horiz-adv-x="659" d="M41 424l53 250h524l-53 -250h-524z" /> -<glyph unicode="–" horiz-adv-x="983" d="M41 436l49 230h852l-49 -230h-852z" /> -<glyph unicode="—" horiz-adv-x="1966" d="M41 436l49 230h1835l-49 -230h-1835z" /> -<glyph unicode="‘" horiz-adv-x="440" d="M115 983q103 227 262 479h225q-91 -213 -194 -501h-285z" /> -<glyph unicode="’" horiz-adv-x="440" d="M106 961q89 206 195 501h285l8 -22q-103 -227 -262 -479h-226z" /> -<glyph unicode="‚" horiz-adv-x="569" d="M-102 -264q88 207 194 502h285l8 -23q-103 -227 -262 -479h-225z" /> -<glyph unicode="“" horiz-adv-x="887" d="M115 983q103 227 262 479h225q-91 -213 -194 -501h-285zM561 983q103 227 262 479h226q-97 -227 -195 -501h-285z" /> -<glyph unicode="”" horiz-adv-x="887" d="M106 961q89 206 195 501h285l8 -22q-103 -227 -262 -479h-226zM553 961q23 53 46.5 111t148.5 390h284l8 -22q-103 -227 -262 -479h-225z" /> -<glyph unicode="„" horiz-adv-x="1018" d="M-102 -264q88 207 194 502h285l8 -23q-103 -227 -262 -479h-225zM346 -264q24 57 49 118.5t146 383.5h284l9 -23q-100 -221 -263 -479h-225z" /> -<glyph unicode="•" horiz-adv-x="739" d="M104 686q0 106 42.5 194t120 136.5t182.5 48.5q120 0 182.5 -67t62.5 -191q0 -177 -91.5 -277t-248.5 -100q-117 0 -183.5 67t-66.5 189z" /> -<glyph unicode="…" horiz-adv-x="1706" d="M25 115q0 90 53.5 144t150.5 54q68 0 109 -38t41 -107q0 -87 -55 -141t-144 -54q-73 0 -114 37.5t-41 104.5zM586 115q0 90 53.5 144t150.5 54q68 0 109 -38t41 -107q0 -87 -55 -141t-144 -54q-73 0 -114 37.5t-41 104.5zM1147 115q0 90 53.5 144t150.5 54q68 0 109 -38 t41 -107q0 -87 -55 -141t-144 -54q-73 0 -114 37.5t-41 104.5z" /> -<glyph unicode=" " horiz-adv-x="381" /> -<glyph unicode="‹" horiz-adv-x="664" d="M72 551v18l401 463l191 -155l-279 -334l135 -350l-246 -103z" /> -<glyph unicode="›" horiz-adv-x="664" d="M0 227l279 334l-136 350l246 103l203 -461v-18l-402 -463z" /> -<glyph unicode="⁄" horiz-adv-x="256" d="M-532 0l1087 1462h236l-1084 -1462h-239z" /> -<glyph unicode=" " horiz-adv-x="476" /> -<glyph unicode="⁴" horiz-adv-x="776" d="M47 737l31 174l475 557h260l-121 -563h119l-35 -168h-119l-32 -151h-238l33 151h-373zM281 905h174l58 231l22 74q-13 -20 -43 -58t-211 -247z" /> -<glyph unicode="€" d="M41 481l37 178h127q9 67 22 115h-125l39 176h135q87 252 250.5 393.5t374.5 141.5q100 0 179 -23t165 -80l-125 -223q-87 49 -131 63.5t-90 14.5q-97 0 -176 -74.5t-135 -212.5h348l-39 -176h-360q-11 -34 -25 -115h299l-37 -178h-280q0 -120 44.5 -181.5t147.5 -61.5 q133 0 283 63v-258q-126 -63 -330 -63q-446 0 -446 501h-152z" /> -<glyph unicode="™" horiz-adv-x="1534" d="M106 1313v149h564v-149h-199v-572h-168v572h-197zM715 741v721h248l159 -510l170 510h240v-721h-168v408l4 121h-6l-174 -529h-141l-166 529h-7l5 -111v-418h-164z" /> -<glyph unicode="" horiz-adv-x="1120" d="M0 1120h1120v-1120h-1120v1120z" /> -<glyph unicode="fi" horiz-adv-x="1352" d="M-219 -225q61 -21 115 -21q61 0 107 40t65 130l204 965h-163l30 145l183 84l18 84q41 190 138.5 277.5t273.5 87.5q131 0 235 -49l-80 -224q-69 31 -133 31q-57 0 -92 -40t-47 -105l-12 -62h219l-49 -229h-220l-215 -1010q-77 -371 -403 -371q-104 0 -174 25v242zM780 0 l237 1118h301l-237 -1118h-301zM1065 1380q0 87 47.5 131.5t134.5 44.5q73 0 111 -31t38 -89q0 -80 -44 -129.5t-136 -49.5q-151 0 -151 123z" /> -<glyph unicode="fl" horiz-adv-x="1352" d="M-219 -225q61 -21 115 -21q61 0 107 40t65 130l204 965h-163l30 145l183 84l18 84q41 190 138.5 277.5t273.5 87.5q131 0 235 -49l-80 -224q-69 31 -133 31q-57 0 -92 -40t-47 -105l-12 -62h219l-49 -229h-220l-215 -1010q-77 -371 -403 -371q-104 0 -174 25v242zM780 0 l330 1556h301l-330 -1556h-301z" /> -<glyph unicode="ffi" horiz-adv-x="2048" d="M-219 -225q61 -21 115 -21q61 0 107 40t65 130l204 965h-163l30 145l183 84l18 84q41 190 138.5 277.5t273.5 87.5q131 0 235 -49l-80 -224q-69 31 -133 31q-57 0 -92 -40t-47 -105l-12 -62h395l18 84q41 190 138.5 277.5t273.5 87.5q131 0 235 -49l-79 -224 q-69 31 -134 31q-57 0 -91.5 -40t-47.5 -105l-12 -62h219l-49 -229h-219l-215 -1010q-77 -371 -404 -371q-104 0 -174 25v242q61 -21 115 -21q136 0 172 170l205 965h-396l-215 -1010q-77 -371 -403 -371q-104 0 -174 25v242zM1477 0l237 1118h301l-237 -1118h-301z M1761 1380q0 87 48 131.5t135 44.5q73 0 111 -31t38 -89q0 -80 -44 -129.5t-136 -49.5q-152 0 -152 123z" /> -<glyph unicode="ffl" horiz-adv-x="2048" d="M-219 -225q61 -21 115 -21q61 0 107 40t65 130l204 965h-163l30 145l183 84l18 84q41 190 138.5 277.5t273.5 87.5q131 0 235 -49l-80 -224q-69 31 -133 31q-57 0 -92 -40t-47 -105l-12 -62h395l18 84q41 190 138.5 277.5t273.5 87.5q131 0 235 -49l-79 -224 q-69 31 -134 31q-57 0 -91.5 -40t-47.5 -105l-12 -62h219l-49 -229h-219l-215 -1010q-77 -371 -404 -371q-104 0 -174 25v242q61 -21 115 -21q136 0 172 170l205 965h-396l-215 -1010q-77 -371 -403 -371q-104 0 -174 25v242zM1477 0l329 1556h301l-329 -1556h-301z" /> -</font> -</defs></svg> -\ No newline at end of file diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-BoldItalic-webfont.ttf b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-BoldItalic-webfont.ttf Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-BoldItalic-webfont.woff b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-BoldItalic-webfont.woff Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-ExtraBold-webfont.eot b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-ExtraBold-webfont.eot Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-ExtraBold-webfont.svg b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-ExtraBold-webfont.svg @@ -1,251 +0,0 @@ -<?xml version="1.0" standalone="no"?> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" > -<svg xmlns="http://www.w3.org/2000/svg"> -<metadata> -This is a custom SVG webfont generated by Font Squirrel. -Copyright : Digitized data copyright 2011 Google Corporation -Foundry : Ascender Corporation -Foundry URL : httpwwwascendercorpcom -</metadata> -<defs> -<font id="OpenSansExtrabold" horiz-adv-x="1200" > -<font-face units-per-em="2048" ascent="1638" descent="-410" /> -<missing-glyph horiz-adv-x="532" /> -<glyph unicode=" " horiz-adv-x="532" /> -<glyph unicode="	" horiz-adv-x="532" /> -<glyph unicode=" " horiz-adv-x="532" /> -<glyph unicode="!" horiz-adv-x="594" d="M82 1462h432l-51 -946h-330zM86 166q0 91 54 141.5t157 50.5q102 0 154.5 -50.5t52.5 -141.5q0 -90 -54.5 -140.5t-152.5 -50.5q-99 0 -155 50.5t-56 140.5z" /> -<glyph unicode=""" horiz-adv-x="1073" d="M121 1462h356l-41 -528h-274zM596 1462h356l-41 -528h-274z" /> -<glyph unicode="#" horiz-adv-x="1356" d="M37 391v254h274l31 168h-238v260h287l72 389h268l-74 -389h166l72 389h268l-73 -389h229v-260h-277l-30 -168h243v-254h-290l-74 -391h-268l73 391h-168l-71 -391h-267l72 391h-225zM578 645h165l31 168h-166z" /> -<glyph unicode="$" d="M80 1044q0 165 106 258t318 115v137h207v-135q199 -11 401 -98l-119 -285q-209 94 -377 94q-80 0 -112.5 -19.5t-32.5 -57.5q0 -33 23.5 -54.5t81.5 -48t161 -61.5q209 -74 300 -168.5t91 -243.5q0 -168 -106.5 -273t-310.5 -130v-193h-207v187q-219 10 -422 98v332 q116 -59 252 -98.5t239 -39.5q85 0 124.5 20.5t39.5 68.5q0 33 -28.5 56t-95 52t-179.5 70q-127 47 -205 105.5t-113.5 131t-35.5 180.5zM613 1462z" /> -<glyph unicode="%" horiz-adv-x="1942" d="M37 1026q0 220 98 338.5t275 118.5q175 0 278 -123t103 -334q0 -220 -99 -340.5t-282 -120.5q-172 0 -272.5 124.5t-100.5 336.5zM338 1022q0 -115 19 -166t57 -51t56.5 50t18.5 167q0 115 -18.5 166t-56.5 51q-39 0 -57.5 -52t-18.5 -165zM412 0l811 1462h297 l-811 -1462h-297zM1149 444q0 220 98 338.5t275 118.5q175 0 278 -123t103 -334q0 -219 -99.5 -339.5t-281.5 -120.5q-172 0 -272.5 124.5t-100.5 335.5zM1450 440q0 -115 19 -166t57 -51q43 0 59.5 58.5t16.5 158.5t-16.5 158.5t-59.5 58.5q-39 0 -57.5 -52t-18.5 -165z " /> -<glyph unicode="&" horiz-adv-x="1636" d="M72 406q0 262 272 401q-62 70 -96.5 148.5t-34.5 177.5q0 160 123.5 254t339.5 94q211 0 328.5 -93.5t117.5 -254.5q0 -111 -63.5 -205.5t-200.5 -177.5l199 -189q75 115 104 260h406q-30 -138 -94.5 -276.5t-145.5 -237.5l320 -307h-506l-99 102q-90 -57 -147.5 -78.5 t-129 -32.5t-163.5 -11q-158 0 -279.5 54t-186 151t-64.5 221zM475 434q0 -63 45 -103t119 -40q57 0 100 15t66 34l-248 252q-82 -61 -82 -158zM565 1120q0 -75 88 -155q57 32 87 76.5t30 91.5q0 49 -28.5 70.5t-71.5 21.5q-42 0 -73.5 -25t-31.5 -80z" /> -<glyph unicode="'" horiz-adv-x="598" d="M121 1462h356l-41 -528h-274z" /> -<glyph unicode="(" horiz-adv-x="735" d="M74 582q0 290 71 523t209 398h326q-126 -175 -194 -412t-68 -507q0 -261 66 -495.5t194 -412.5h-324q-137 158 -208.5 388t-71.5 518zM493 1485z" /> -<glyph unicode=")" horiz-adv-x="735" d="M55 1503h326q139 -166 210 -402t71 -519t-71.5 -514.5t-209.5 -391.5h-324q126 172 193 408.5t67 499.5q0 265 -66 501.5t-196 417.5zM247 1485z" /> -<glyph unicode="*" horiz-adv-x="1100" d="M45 1014l45 291l348 -101l-39 352h303l-38 -352l356 101l37 -295l-314 -21l207 -278l-260 -138l-143 283l-123 -281l-272 136l206 278z" /> -<glyph unicode="+" horiz-adv-x="1159" d="M72 588v268h372v367h269v-367h372v-268h-372v-361h-269v361h-372z" /> -<glyph unicode="," horiz-adv-x="633" d="M57 -285q29 138 58.5 309.5t40.5 274.5h342l14 -23q-97 -381 -176 -561h-279z" /> -<glyph unicode="-" horiz-adv-x="651" d="M43 393v312h565v-312h-565z" /> -<glyph unicode="." horiz-adv-x="592" d="M86 166q0 92 54.5 142t158.5 50q99 0 152 -50t53 -142q0 -90 -54.5 -140.5t-150.5 -50.5q-99 0 -156 50t-57 141z" /> -<glyph unicode="/" horiz-adv-x="905" d="M10 -20l545 1503h346l-545 -1503h-346z" /> -<glyph unicode="0" d="M72 729q0 390 130 572t398 182q261 0 394.5 -189.5t133.5 -564.5q0 -388 -130 -568.5t-398 -180.5q-262 0 -395 188.5t-133 560.5zM465 729q0 -248 31 -341t104 -93q74 0 104.5 96t30.5 338q0 243 -31 340.5t-104 97.5t-104 -94t-31 -344z" /> -<glyph unicode="1" d="M84 1053l502 409h356v-1462h-401v774q0 141 6 258q-37 -45 -92 -94l-166 -137z" /> -<glyph unicode="2" d="M45 1249q113 101 190 144.5t167.5 66.5t203.5 23q142 0 253.5 -50t173 -142.5t61.5 -207.5q0 -86 -21.5 -159t-66.5 -143.5t-119.5 -148.5t-317.5 -296v-10h553v-326h-1061v260l357 361q153 160 200 218.5t65.5 100.5t18.5 88q0 57 -37 90t-104 33q-69 0 -139.5 -39.5 t-159.5 -116.5z" /> -<glyph unicode="3" d="M70 59v328q96 -49 195.5 -72.5t183.5 -23.5q130 0 189.5 36.5t59.5 114.5q0 60 -31 92.5t-100 49t-180 16.5h-90v297h92q301 0 301 154q0 58 -44.5 86t-119.5 28q-140 0 -290 -94l-164 264q116 80 237.5 114t278.5 34q227 0 356 -90t129 -248q0 -136 -83 -233.5 t-240 -141.5v-6q366 -46 366 -346q0 -204 -161.5 -321t-448.5 -117q-118 0 -218.5 17t-217.5 62z" /> -<glyph unicode="4" d="M35 283v290l608 889h365v-884h161v-295h-161v-283h-390v283h-583zM377 578h241v170q0 48 3.5 129.5t5.5 85.5h-11q-34 -77 -77 -144z" /> -<glyph unicode="5" d="M94 59v324q87 -40 196.5 -66t188.5 -26q110 0 169 46.5t59 137.5q0 84 -60 131t-182 47q-93 0 -201 -35l-145 72l55 772h834v-329h-498l-18 -193q78 15 111 16.5t61 1.5q126 0 227.5 -58.5t158 -165.5t56.5 -247q0 -245 -147.5 -376t-446.5 -131q-256 0 -418 79z" /> -<glyph unicode="6" d="M70 618q0 306 87.5 495.5t258 279.5t420.5 90q89 0 208 -17v-309q-100 19 -217 19q-198 0 -295 -87t-106 -284h12q90 170 289 170q195 0 302.5 -125.5t107.5 -349.5q0 -241 -136 -380.5t-380 -139.5q-259 0 -405 168t-146 470zM463 512q0 -96 41 -157.5t108 -61.5 q63 0 102.5 47.5t39.5 151.5q0 178 -138 178q-68 0 -110.5 -46t-42.5 -112z" /> -<glyph unicode="7" d="M78 1133v327h1055v-233l-515 -1227h-409l502 1133h-633z" /> -<glyph unicode="8" d="M68 385q0 127 61 216.5t205 162.5q-116 78 -169.5 167.5t-53.5 196.5q0 168 131 261.5t362 93.5t359.5 -93t128.5 -264q0 -116 -60.5 -203.5t-191.5 -152.5q162 -92 228.5 -183.5t66.5 -197.5q0 -195 -141 -302t-394 -107q-258 0 -395 104.5t-137 300.5zM430 401 q0 -62 44 -99.5t122 -37.5q176 0 176 129q0 49 -38.5 96.5t-137.5 106.5q-89 -47 -127.5 -94.5t-38.5 -100.5zM481 1092q0 -86 117 -152q71 41 97 75t26 77q0 48 -35 77t-84 29q-51 0 -86 -29.5t-35 -76.5z" /> -<glyph unicode="9" d="M53 958q0 243 138.5 381t379.5 138q268 0 415 -178t147 -506q0 -429 -185 -621t-592 -192q-134 0 -204 10v313q86 -16 172 -16q212 0 327 87.5t125 276.5h-12q-39 -72 -77 -104t-93 -49t-137 -17q-190 0 -297 127t-107 350zM436 963q0 -82 35 -130.5t107 -48.5 q65 0 113 47t48 113q0 89 -44.5 153t-112.5 64q-65 0 -105.5 -47t-40.5 -151z" /> -<glyph unicode=":" horiz-adv-x="592" d="M86 166q0 92 54.5 142t158.5 50q99 0 152 -50t53 -142q0 -90 -54.5 -140.5t-150.5 -50.5q-99 0 -156 50t-57 141zM86 956q0 91 55 141t158 50q99 0 152 -50t53 -141q0 -90 -54 -141t-151 -51q-102 0 -157.5 51t-55.5 141z" /> -<glyph unicode=";" horiz-adv-x="608" d="M57 -285q29 138 58.5 309.5t40.5 274.5h342l14 -23q-97 -381 -176 -561h-279zM92 956q0 91 53.5 141t157.5 50q100 0 153.5 -50.5t53.5 -140.5t-54 -141t-153 -51q-102 0 -156.5 50.5t-54.5 141.5z" /> -<glyph unicode="<" horiz-adv-x="1159" d="M72 627v172l1011 506v-297l-620 -283l620 -252v-295z" /> -<glyph unicode="=" horiz-adv-x="1159" d="M72 358v271h1015v-271h-1015zM72 815v268h1015v-268h-1015z" /> -<glyph unicode=">" horiz-adv-x="1159" d="M72 178v295l620 252l-620 283v297l1011 -506v-172z" /> -<glyph unicode="?" horiz-adv-x="1034" d="M0 1341q249 142 520 142q223 0 350 -98t127 -267q0 -121 -56.5 -209.5t-180.5 -167.5q-105 -68 -131.5 -99.5t-26.5 -74.5v-51h-307v86q0 98 40 165.5t142 131.5q81 51 116.5 92t35.5 94q0 42 -38 66.5t-99 24.5q-151 0 -353 -107zM252 166q0 92 53.5 142t157.5 50 q100 0 153.5 -50.5t53.5 -141.5t-55.5 -141t-151.5 -50q-99 0 -155 49.5t-56 141.5z" /> -<glyph unicode="@" horiz-adv-x="1837" d="M82 610q0 253 114.5 453.5t316 309t456.5 108.5q234 0 413.5 -89t276 -253.5t96.5 -382.5q0 -141 -48.5 -263t-134.5 -191t-196 -69q-79 0 -143 31.5t-100 87.5h-15q-107 -119 -260 -119q-183 0 -281 107t-98 299q0 141 62 249.5t179 167t271 58.5q81 0 178.5 -16.5 t178.5 -44.5l-21 -422l-2 -94q0 -86 49 -86q52 0 84.5 87t32.5 220q0 239 -135 369t-383 130q-190 0 -330.5 -79t-214.5 -226.5t-74 -345.5q0 -255 142.5 -393.5t402.5 -138.5q116 0 250.5 25t263.5 71v-229q-224 -95 -500 -95q-388 0 -609.5 202.5t-221.5 561.5zM760 641 q0 -100 36.5 -145t96.5 -45q77 0 113 62t47 220l10 156q-40 6 -68 6q-108 0 -171.5 -67t-63.5 -187z" /> -<glyph unicode="A" horiz-adv-x="1487" d="M0 0l477 1468h527l483 -1468h-432l-72 274h-475l-74 -274h-434zM590 598h311l-63 240q-22 80 -53.5 207t-41.5 182q-9 -51 -35.5 -168t-117.5 -461z" /> -<glyph unicode="B" horiz-adv-x="1380" d="M158 0v1462h510q298 0 442.5 -88.5t144.5 -275.5q0 -123 -63 -210t-166 -112v-10q136 -36 197 -120t61 -218q0 -199 -149.5 -313.5t-407.5 -114.5h-569zM553 305h139q185 0 185 156q0 73 -49.5 112t-143.5 39h-131v-307zM553 901h119q85 0 131.5 35t46.5 104 q0 123 -186 123h-111v-262z" /> -<glyph unicode="C" horiz-adv-x="1329" d="M104 727q0 227 85.5 399t246 264.5t377.5 92.5q237 0 453 -103l-121 -311q-81 38 -162 64t-174 26q-141 0 -220 -115.5t-79 -318.5q0 -422 321 -422q97 0 188 27t183 65v-334q-183 -81 -414 -81q-331 0 -507.5 192t-176.5 555z" /> -<glyph unicode="D" horiz-adv-x="1503" d="M158 0v1462h506q352 0 543.5 -180t191.5 -520q0 -366 -201.5 -564t-566.5 -198h-473zM553 324h88q180 0 264 104.5t84 319.5q0 201 -79.5 298t-241.5 97h-115v-819z" /> -<glyph unicode="E" horiz-adv-x="1124" d="M158 0v1462h868v-317h-473v-230h438v-317h-438v-276h473v-322h-868z" /> -<glyph unicode="F" horiz-adv-x="1104" d="M158 0v1462h864v-317h-475v-279h438v-317h-438v-549h-389z" /> -<glyph unicode="G" horiz-adv-x="1516" d="M104 735q0 354 202 551t566 197q138 0 260.5 -26t213.5 -66l-125 -310q-158 78 -347 78q-173 0 -267.5 -112.5t-94.5 -321.5q0 -205 85.5 -312.5t246.5 -107.5q88 0 162 17v229h-261v305h631v-788q-257 -88 -565 -88q-338 0 -522.5 196t-184.5 559z" /> -<glyph unicode="H" horiz-adv-x="1569" d="M158 0v1462h397v-542h459v542h397v-1462h-397v596h-459v-596h-397z" /> -<glyph unicode="I" horiz-adv-x="713" d="M158 0v1462h397v-1462h-397z" /> -<glyph unicode="J" horiz-adv-x="721" d="M-162 -131q32 -6 68 -13.5t78 -7.5q98 0 140 59t42 202v1353h397v-1319q0 -297 -130 -449.5t-390 -152.5q-108 0 -205 21v307z" /> -<glyph unicode="K" horiz-adv-x="1407" d="M158 0v1462h397v-635q30 59 121 187l307 448h432l-461 -655l453 -807h-446l-289 559l-117 -70v-489h-397z" /> -<glyph unicode="L" horiz-adv-x="1192" d="M158 0v1462h395v-1143h563v-319h-958z" /> -<glyph unicode="M" horiz-adv-x="1980" d="M158 0v1462h526l305 -1038h8l299 1038h527v-1462h-363v641q0 50 1.5 111t13.5 299h-9l-295 -1051h-376l-299 1053h-9q21 -269 21 -418v-635h-350z" /> -<glyph unicode="N" horiz-adv-x="1708" d="M158 0v1462h516l532 -1016h6q-14 221 -14 355v661h352v-1462h-518l-534 1030h-9q19 -243 19 -371v-659h-350z" /> -<glyph unicode="O" horiz-adv-x="1632" d="M104 735q0 365 182.5 557.5t530.5 192.5q349 0 529 -191t180 -561q0 -369 -181 -561t-530 -192q-344 0 -527.5 193t-183.5 562zM520 733q0 -424 295 -424q150 0 222.5 103t72.5 321q0 219 -73.5 323.5t-219.5 104.5q-297 0 -297 -428z" /> -<glyph unicode="P" horiz-adv-x="1294" d="M158 0v1462h506q277 0 416 -121t139 -344q0 -245 -144.5 -378.5t-410.5 -133.5h-111v-485h-395zM553 807h72q89 0 141.5 50t52.5 138q0 148 -164 148h-102v-336z" /> -<glyph unicode="Q" horiz-adv-x="1632" d="M104 735q0 365 182.5 557.5t530.5 192.5q349 0 529 -191t180 -561q0 -497 -316 -670l357 -411h-492l-258 325l-1 1v1l-1 1q-344 0 -527.5 193t-183.5 562zM520 733q0 -424 295 -424q150 0 222.5 103t72.5 321q0 219 -73.5 323.5t-219.5 104.5q-297 0 -297 -428z" /> -<glyph unicode="R" horiz-adv-x="1386" d="M158 0v1462h479q596 0 596 -432q0 -254 -248 -393l426 -637h-448l-310 532h-100v-532h-395zM553 829h74q207 0 207 183q0 151 -203 151h-78v-334z" /> -<glyph unicode="S" horiz-adv-x="1182" d="M90 72v352q113 -58 235 -90.5t224 -32.5q88 0 129 30.5t41 78.5q0 30 -16.5 52.5t-53 45.5t-194.5 94q-143 65 -214.5 126t-106 140t-34.5 187q0 202 147 315t404 113q227 0 463 -105l-121 -305q-205 94 -354 94q-77 0 -112 -27t-35 -67q0 -43 44.5 -77t241.5 -124 q189 -85 262.5 -182.5t73.5 -245.5q0 -136 -69 -241.5t-199 -164t-305 -58.5q-146 0 -245 20.5t-206 71.5z" /> -<glyph unicode="T" horiz-adv-x="1210" d="M51 1139v323h1108v-323h-356v-1139h-395v1139h-357z" /> -<glyph unicode="U" horiz-adv-x="1550" d="M150 573v889h397v-858q0 -155 58 -225t171 -70q121 0 175.5 69.5t54.5 227.5v856h395v-880q0 -287 -162.5 -444.5t-468.5 -157.5q-299 0 -459.5 153t-160.5 440z" /> -<glyph unicode="V" horiz-adv-x="1421" d="M0 1462h444l199 -741q62 -247 68 -344q7 70 28 175t37 165l203 745h442l-479 -1462h-465z" /> -<glyph unicode="W" horiz-adv-x="2128" d="M31 1462h381l159 -733q54 -243 74 -387q13 102 46.5 277t62.5 290l129 553h366l125 -553q32 -133 65 -307t44 -260q13 111 71 385l162 735h381l-360 -1462h-467l-140 637q-10 40 -31.5 159t-31.5 199q-8 -65 -26 -161.5t-35.5 -177.5t-145.5 -656h-467z" /> -<glyph unicode="X" horiz-adv-x="1481" d="M4 0l485 748l-456 714h438l264 -452l254 452h451l-463 -745l498 -717h-457l-285 457l-282 -457h-447z" /> -<glyph unicode="Y" horiz-adv-x="1360" d="M0 1462h430l250 -542l252 542h428l-481 -891v-571h-398v559z" /> -<glyph unicode="Z" horiz-adv-x="1251" d="M61 0v244l633 899h-618v319h1108v-243l-633 -900h649v-319h-1139z" /> -<glyph unicode="[" horiz-adv-x="664" d="M117 -344v1847h499v-254h-182v-1339h182v-254h-499zM355 1485z" /> -<glyph unicode="\" horiz-adv-x="905" d="M6 1483h346l545 -1503h-346z" /> -<glyph unicode="]" horiz-adv-x="664" d="M47 -90h182v1339h-182v254h500v-1847h-500v254zM317 1485z" /> -<glyph unicode="^" horiz-adv-x="1075" d="M-16 502l440 966h170l508 -966h-295l-289 577l-124 -291l-124 -286h-286z" /> -<glyph unicode="_" horiz-adv-x="1024" d="M-4 -133h1032v-246h-1032v246z" /> -<glyph unicode="`" horiz-adv-x="1225" d="M264 1548v21h430q52 -70 203 -233l59 -66v-29h-260q-69 44 -203.5 138.5t-228.5 168.5z" /> -<glyph unicode="a" horiz-adv-x="1276" d="M74 346q0 181 126 269.5t365 99.5l189 6v16q0 140 -138 140q-124 0 -315 -84l-113 258q198 102 500 102q218 0 337.5 -108t119.5 -302v-743h-271l-75 150h-8q-79 -98 -161 -134t-212 -36q-160 0 -252 96t-92 270zM473 360q0 -104 111 -104q71 0 121.5 45t50.5 117v88 l-90 -4q-193 -7 -193 -142z" /> -<glyph unicode="b" horiz-adv-x="1317" d="M135 0v1556h391v-352q0 -63 -14 -217h14q57 88 131.5 127t169.5 39q185 0 293.5 -155t108.5 -429q0 -276 -109.5 -432.5t-304.5 -156.5q-63 0 -112 13.5t-87.5 37.5t-89.5 80h-24l-62 -111h-305zM526 555q0 -139 38 -199.5t124 -60.5q69 0 106 70.5t37 207.5 q0 273 -147 273q-82 0 -120 -57t-38 -179v-55z" /> -<glyph unicode="c" horiz-adv-x="1104" d="M86 561q0 282 155 437t441 155q197 0 371 -86l-115 -289q-71 31 -131 49.5t-125 18.5q-95 0 -147 -74t-52 -209q0 -272 201 -272q172 0 330 100v-311q-151 -100 -363 -100q-278 0 -421.5 150t-143.5 431z" /> -<glyph unicode="d" horiz-adv-x="1317" d="M86 565q0 276 111 432t305 156q95 0 166.5 -38t130.5 -128h8q-19 133 -19 266v303h394v-1556h-295l-84 143h-15q-101 -163 -301 -163q-121 0 -211.5 69t-140 203t-49.5 313zM481 559q0 -132 43 -201t123 -69q94 0 132.5 59t41.5 182v31q0 150 -43 213.5t-135 63.5 q-77 0 -119.5 -72.5t-42.5 -206.5z" /> -<glyph unicode="e" horiz-adv-x="1266" d="M86 559q0 287 145 440.5t414 153.5q256 0 395.5 -133.5t139.5 -384.5v-174h-699q4 -95 69.5 -149t178.5 -54q103 0 189.5 19.5t187.5 66.5v-281q-92 -47 -190 -65t-234 -18q-283 0 -439.5 150.5t-156.5 428.5zM489 707h336q-2 82 -46.5 131t-119.5 49q-69 0 -115.5 -43.5 t-54.5 -136.5z" /> -<glyph unicode="f" horiz-adv-x="846" d="M45 840v192l158 96v19q0 224 91.5 322t293.5 98q78 0 147.5 -12t161.5 -42l-84 -253q-72 20 -141 20q-45 0 -65.5 -27.5t-20.5 -89.5v-30h241v-293h-241v-840h-391v840h-150z" /> -<glyph unicode="g" horiz-adv-x="1241" d="M20 -180q0 203 252 262q-52 22 -90.5 71t-38.5 97q0 53 29 93.5t121 96.5q-88 39 -138.5 122t-50.5 202q0 185 126 287t360 102q31 0 107 -7t112 -13h395v-189l-155 -57q32 -58 32 -135q0 -183 -128.5 -284t-383.5 -101q-63 0 -100 8q-14 -26 -14 -49q0 -29 47 -44.5 t123 -15.5h188q381 0 381 -321q0 -207 -176.5 -322t-495.5 -115q-241 0 -371.5 80.5t-130.5 231.5zM350 -141q0 -48 52 -77.5t139 -29.5q142 0 227.5 35.5t85.5 91.5q0 45 -52 63.5t-149 18.5h-153q-63 0 -106.5 -29.5t-43.5 -72.5zM473 762q0 -174 121 -174q56 0 86.5 43 t30.5 129q0 176 -117 176q-121 0 -121 -174z" /> -<glyph unicode="h" horiz-adv-x="1372" d="M135 0v1556h391v-221q0 -150 -16 -342h18q56 88 133 124t179 36q190 0 295.5 -109.5t105.5 -306.5v-737h-393v618q0 228 -135 228q-96 0 -141.5 -80.5t-45.5 -267.5v-498h-391z" /> -<glyph unicode="i" horiz-adv-x="666" d="M127 1415q0 88 49 131t158 43t159 -44t50 -130q0 -172 -209 -172q-207 0 -207 172zM137 0v1133h391v-1133h-391z" /> -<glyph unicode="j" horiz-adv-x="664" d="M-104 -162q64 -18 120 -18q119 0 119 170v1143h391v-1225q0 -187 -109.5 -293.5t-310.5 -106.5q-48 0 -110.5 7.5t-99.5 17.5v305zM125 1415q0 88 49 131t158 43t159 -44t50 -130q0 -172 -209 -172q-207 0 -207 172z" /> -<glyph unicode="k" horiz-adv-x="1350" d="M135 0v1556h393v-612q0 -157 -22 -307h8q71 113 121 176l254 320h436l-393 -482l418 -651h-447l-248 406l-127 -97v-309h-393z" /> -<glyph unicode="l" horiz-adv-x="662" d="M135 0v1556h391v-1556h-391z" /> -<glyph unicode="m" horiz-adv-x="2048" d="M135 0v1133h295l49 -140h23q45 78 130.5 119t194.5 41q245 0 344 -149h31q48 70 133.5 109.5t188.5 39.5q201 0 297 -103t96 -313v-737h-391v616q0 115 -31.5 172.5t-99.5 57.5q-90 0 -132 -77t-42 -241v-528h-392v616q0 115 -30 172.5t-97 57.5q-92 0 -134 -82t-42 -268 v-496h-391z" /> -<glyph unicode="n" horiz-adv-x="1372" d="M135 0v1133h295l49 -140h23q50 80 138.5 120t203.5 40q188 0 292.5 -109t104.5 -307v-737h-391v618q0 113 -32.5 170.5t-104.5 57.5q-99 0 -143 -79t-44 -271v-496h-391z" /> -<glyph unicode="o" horiz-adv-x="1305" d="M86 569q0 277 149.5 430.5t419.5 153.5q167 0 295 -71t197.5 -203.5t69.5 -309.5q0 -278 -149.5 -433.5t-418.5 -155.5q-258 0 -410.5 159t-152.5 430zM483 569q0 -146 39 -222.5t131 -76.5q91 0 128.5 76.5t37.5 222.5q0 145 -38 219t-130 74q-90 0 -129 -73.5 t-39 -219.5z" /> -<glyph unicode="p" horiz-adv-x="1317" d="M135 -492v1625h318l55 -144h18q109 164 301 164q188 0 295 -156t107 -428q0 -274 -111.5 -431.5t-302.5 -157.5q-86 0 -154 28.5t-135 102.5h-18q18 -119 18 -148v-455h-391zM526 571q0 -146 39 -211t123 -65q75 0 109 64.5t34 213.5q0 146 -34 209.5t-113 63.5 q-86 0 -120.5 -61.5t-37.5 -182.5v-31z" /> -<glyph unicode="q" horiz-adv-x="1317" d="M86 565q0 276 110.5 432t301.5 156q205 0 309 -160h8l29 140h338v-1625h-391v469q0 34 12 166h-12q-96 -163 -299 -163q-190 0 -298 156t-108 429zM483 559q0 -148 41 -212t127 -64q89 0 129.5 55t40.5 186v47q0 150 -41 214.5t-135 64.5q-162 0 -162 -291z" /> -<glyph unicode="r" horiz-adv-x="961" d="M135 0v1133h291l61 -181h19q49 90 136.5 145.5t176.5 55.5q51 0 97 -8l22 -4l-35 -369q-48 12 -133 12q-128 0 -186 -58.5t-58 -168.5v-557h-391z" /> -<glyph unicode="s" horiz-adv-x="1092" d="M119 819q0 158 122 246t345 88q112 0 210.5 -24.5t204.5 -71.5l-106 -252q-78 35 -165 59.5t-142 24.5q-96 0 -96 -47q0 -29 33.5 -49.5t193.5 -83.5q119 -49 177.5 -96t86 -110.5t27.5 -154.5q0 -182 -124 -275t-356 -93q-126 0 -219 13.5t-190 49.5v313 q91 -40 199.5 -66t193.5 -26q127 0 127 58q0 30 -35.5 53.5t-206.5 91.5q-156 64 -218 145.5t-62 206.5z" /> -<glyph unicode="t" horiz-adv-x="942" d="M53 840v159l174 123l101 238h256v-227h278v-293h-278v-441q0 -110 106 -110q79 0 189 39v-285q-79 -34 -150.5 -48.5t-167.5 -14.5q-197 0 -284 96.5t-87 296.5v467h-137z" /> -<glyph unicode="u" horiz-adv-x="1372" d="M133 395v738h391v-619q0 -111 31.5 -168t103.5 -57q101 0 144 79.5t43 268.5v496h391v-1133h-295l-49 141h-23q-49 -78 -136.5 -119.5t-205.5 -41.5q-187 0 -291 108.5t-104 306.5z" /> -<glyph unicode="v" horiz-adv-x="1251" d="M0 1133h408l192 -670q1 -5 4 -17t6 -28.5t5.5 -35t2.5 -34.5h7q0 52 18 113l201 672h407l-432 -1133h-387z" /> -<glyph unicode="w" horiz-adv-x="1864" d="M25 1133h385l92 -435q44 -224 51 -372h6q3 92 55 350l105 457h432l96 -463q46 -221 58 -344h6q6 76 20 189.5t31 182.5l100 435h377l-311 -1133h-418l-128 540l-30 163l-20 131h-6q-49 -280 -66 -353l-115 -481h-411z" /> -<glyph unicode="x" horiz-adv-x="1290" d="M10 0l365 578l-346 555h444l172 -318l176 318h445l-355 -555l369 -578h-444l-191 344l-190 -344h-445z" /> -<glyph unicode="y" horiz-adv-x="1249" d="M-2 1133h412l192 -650q14 -51 19 -123h8q8 69 24 121l197 652h399l-448 -1205q-86 -230 -211.5 -325t-327.5 -95q-78 0 -160 17v307q53 -12 121 -12q52 0 91 20t68 56.5t62 119.5z" /> -<glyph unicode="z" horiz-adv-x="1038" d="M49 0v223l469 611h-442v299h889v-242l-449 -592h471v-299h-938z" /> -<glyph unicode="{" horiz-adv-x="887" d="M61 418v301q115 0 180.5 44.5t65.5 125.5v254q0 139 49 208t159.5 100.5t305.5 31.5v-279q-89 -3 -120.5 -13.5t-50.5 -32.5t-19 -60v-271q0 -113 -56.5 -173.5t-183.5 -78.5v-12q128 -20 184 -79t56 -167v-276q0 -39 21 -61t56 -32.5t113 -13.5v-278q-197 0 -307 32 t-158.5 101.5t-48.5 210.5v248q0 80 -67 125t-179 45z" /> -<glyph unicode="|" horiz-adv-x="1042" d="M387 -446v2002h268v-2002h-268z" /> -<glyph unicode="}" horiz-adv-x="887" d="M66 -66q108 4 149 29.5t41 77.5v276q0 108 56 167t184 79v12q-127 18 -183.5 78.5t-56.5 173.5v271q0 39 -19.5 60.5t-50 32t-120.5 13.5v279q196 0 306 -31.5t159 -100.5t49 -208v-254q0 -81 65 -125.5t180 -44.5v-301q-111 0 -178 -45t-67 -125v-248q0 -140 -49 -210 t-159 -102t-306 -32v278z" /> -<glyph unicode="~" horiz-adv-x="1159" d="M72 526v281q104 108 264 108q69 0 130 -13.5t150 -49.5q131 -55 238 -55q50 0 112.5 32t118.5 89v-281q-105 -109 -264 -109q-71 0 -133.5 15t-146.5 49q-131 55 -236 55q-110 0 -233 -121z" /> -<glyph unicode="¡" horiz-adv-x="594" d="M82 -334l51 946h330l51 -946h-432zM92 963q0 90 54 140t153 50q101 0 156 -50.5t55 -139.5q0 -91 -53.5 -142t-157.5 -51q-102 0 -154.5 50.5t-52.5 142.5z" /> -<glyph unicode="¢" d="M129 739q0 240 113 388.5t323 189.5v166h207v-154q171 -9 324 -84l-115 -289q-71 31 -131 49.5t-125 18.5q-95 0 -147 -74t-52 -209q0 -272 201 -272q172 0 330 100v-311q-127 -82 -285 -98v-180h-207v186q-212 31 -324 176t-112 397z" /> -<glyph unicode="£" d="M102 649v277h166v118q0 215 117 328t338 113q210 0 405 -82l-110 -289q-148 55 -252 55q-58 0 -85.5 -33t-27.5 -104v-106h344v-277h-344v-96q0 -150 -159 -227h671v-326h-1061v313q81 47 109.5 76.5t41.5 67.5t13 94v98h-166z" /> -<glyph unicode="¤" horiz-adv-x="1159" d="M96 1018l180 182l123 -123q84 41 172 41q91 0 177 -45l120 127l185 -174l-127 -125q41 -76 41 -178q0 -94 -41 -176l121 -119l-179 -178l-120 119q-89 -39 -177 -39q-100 0 -176 37l-119 -115l-178 178l123 119q-41 82 -41 174q0 89 41 176zM436 723q0 -56 40.5 -95.5 t94.5 -39.5q58 0 100 38.5t42 96.5t-42 97.5t-100 39.5q-56 0 -95.5 -40.5t-39.5 -96.5z" /> -<glyph unicode="¥" d="M8 1462h400l192 -504l193 504h399l-363 -712h195v-211h-242v-117h242v-209h-242v-213h-364v213h-246v209h246v117h-246v211h190z" /> -<glyph unicode="¦" horiz-adv-x="1042" d="M387 393h268v-839h-268v839zM387 717v839h268v-839h-268z" /> -<glyph unicode="§" horiz-adv-x="1024" d="M106 803q0 64 43 125t121 108q-141 102 -141 246q0 137 111 216t295 79q191 0 370 -86l-98 -221q-73 40 -146.5 63t-128.5 23q-108 0 -108 -74q0 -43 45.5 -79t128.5 -70q175 -71 252.5 -152t77.5 -178q0 -77 -32 -137.5t-116 -120.5q125 -94 125 -244 q0 -149 -116.5 -237.5t-319.5 -88.5q-204 0 -352 86v244q79 -44 182 -76t172 -32q139 0 139 96q0 42 -31 72.5t-139 78.5q-141 63 -205.5 112t-96.5 108t-32 139zM397 834q0 -51 44 -91t155 -98q41 47 41 107q0 57 -42 100t-140 84q-58 -32 -58 -102z" /> -<glyph unicode="¨" horiz-adv-x="1233" d="M223 1413q0 75 46 116.5t124 41.5q79 0 125.5 -42.5t46.5 -115.5q0 -71 -46.5 -113.5t-125.5 -42.5q-78 0 -124 41t-46 115zM702 1413q0 75 46 116.5t126 41.5t126.5 -43t46.5 -115q0 -71 -46.5 -113.5t-126.5 -42.5q-81 0 -126.5 41.5t-45.5 114.5z" /> -<glyph unicode="©" horiz-adv-x="1688" d="M92 731q0 200 100 375t275 276t377 101q197 0 370 -97t277 -272t104 -383q0 -204 -100.5 -376.5t-273 -273.5t-377.5 -101q-207 0 -382 103.5t-272.5 276.5t-97.5 371zM256 731q0 -158 79.5 -295.5t215.5 -215t293 -77.5q158 0 294 78.5t215 215t79 294.5 q0 157 -77.5 293t-214 215.5t-296.5 79.5q-158 0 -294.5 -78.5t-215 -215t-78.5 -294.5zM434 735q0 217 113 340t321 123q166 0 322 -78l-92 -205q-106 56 -211 56q-81 0 -126.5 -61t-45.5 -179q0 -128 43.5 -185t134.5 -57q138 0 258 68v-231q-126 -64 -272 -64 q-212 0 -328.5 124t-116.5 349z" /> -<glyph unicode="ª" horiz-adv-x="813" d="M49 967q0 116 77 171t267 64l88 4v6q0 41 -25.5 58.5t-76.5 17.5q-57 0 -107.5 -15t-103.5 -40l-76 166q108 51 180.5 65.5t163.5 14.5q139 0 218 -75.5t79 -213.5v-449h-162l-45 127q-48 -76 -104.5 -107.5t-138.5 -31.5q-109 0 -171.5 63.5t-62.5 174.5zM301 979 q0 -32 18 -50t52 -18q50 0 80 38.5t30 97.5v22l-84 -6q-96 -6 -96 -84z" /> -<glyph unicode="«" horiz-adv-x="1395" d="M74 561v27l389 483l280 -149l-272 -347l272 -348l-280 -147zM649 561v27l387 483l283 -149l-275 -347l275 -348l-283 -147z" /> -<glyph unicode="¬" horiz-adv-x="1159" d="M72 588v268h1013v-618h-270v350h-743z" /> -<glyph unicode="­" horiz-adv-x="651" d="M43 393v312h565v-312h-565z" /> -<glyph unicode="®" horiz-adv-x="1688" d="M92 731q0 200 100 375t275 276t377 101q197 0 370 -97t277 -272t104 -383q0 -204 -100.5 -376.5t-273 -273.5t-377.5 -101q-207 0 -382 103.5t-272.5 276.5t-97.5 371zM256 731q0 -158 79.5 -295.5t215.5 -215t293 -77.5q158 0 294 78.5t215 215t79 294.5 q0 157 -77.5 293t-214 215.5t-296.5 79.5q-158 0 -294.5 -78.5t-215 -215t-78.5 -294.5zM506 313v875h291q407 0 407 -270q0 -87 -33 -146.5t-108 -95.5l194 -363h-290l-146 320h-35v-320h-280zM786 809h11q58 0 91.5 21.5t33.5 76.5q0 47 -27.5 66.5t-95.5 19.5h-13v-184z " /> -<glyph unicode="¯" horiz-adv-x="1024" d="M-6 1556v246h1036v-246h-1036z" /> -<glyph unicode="°" horiz-adv-x="864" d="M63 1114q0 97 49 182.5t135 136t185 50.5t185 -50.5t135 -135.5t49 -183q0 -97 -48.5 -181t-134 -133.5t-186.5 -49.5q-99 0 -185 49t-135 133t-49 182zM301 1114q0 -50 38.5 -88.5t92.5 -38.5t92.5 39t38.5 88q0 52 -37.5 92.5t-93.5 40.5t-93.5 -40.5t-37.5 -92.5z" /> -<glyph unicode="±" horiz-adv-x="1159" d="M72 0v268h1013v-268h-1013zM72 684v268h372v367h269v-367h372v-268h-372v-360h-269v360h-372z" /> -<glyph unicode="²" horiz-adv-x="817" d="M61 1350q80 73 167.5 104t203.5 31q142 0 219.5 -63t77.5 -175q0 -46 -13 -87t-40.5 -84.5t-74.5 -91t-198 -173.5h347v-225h-674v207l215 213q84 84 116.5 129t32.5 79q0 58 -65 58q-81 0 -172 -88z" /> -<glyph unicode="³" horiz-adv-x="817" d="M63 1366q149 115 343 115q146 0 232.5 -57.5t86.5 -157.5q0 -78 -37 -132.5t-125 -86.5v-9q97 -24 144 -76t47 -139q0 -120 -98 -187t-277 -67q-185 0 -309 70v233q117 -81 297 -81q116 0 116 67q0 41 -32.5 56.5t-102.5 15.5h-104v194h80q71 0 105 18.5t34 59.5 q0 25 -21 46.5t-71 21.5t-94 -17t-97 -57z" /> -<glyph unicode="´" horiz-adv-x="1225" d="M264 1241v29q154 165 195.5 213t68.5 86h428v-21q-80 -64 -220 -163t-212 -144h-260z" /> -<glyph unicode="µ" horiz-adv-x="1376" d="M135 -492v1625h391v-615q0 -115 33.5 -172t112.5 -57q93 0 134.5 83t41.5 265v496h393v-1133h-293l-53 152h-16q-34 -88 -90.5 -130t-122.5 -42q-56 0 -90 20t-62 63q12 -90 12 -235v-320h-391z" /> -<glyph unicode="¶" horiz-adv-x="1317" d="M102 1042q0 256 107.5 385t343.5 129h633v-1816h-191v1587h-157v-1587h-191v819q-54 -18 -125 -18q-216 0 -318 125t-102 376z" /> -<glyph unicode="·" horiz-adv-x="592" d="M86 723q0 92 54.5 142t158.5 50q99 0 152 -50t53 -142q0 -90 -54.5 -141.5t-150.5 -51.5q-100 0 -156.5 51t-56.5 142z" /> -<glyph unicode="¸" horiz-adv-x="383" d="M-90 -258q83 -27 147 -27q52 0 52 47q0 33 -41 58.5t-107 40.5l72 139h203l-9 -29q96 -39 133 -92.5t37 -130.5q0 -109 -75 -174.5t-199 -65.5q-136 0 -213 29v205z" /> -<glyph unicode="¹" horiz-adv-x="817" d="M57 1188l340 274h219v-876h-282v356q0 35 3.5 118t6.5 99q-9 -19 -31.5 -43t-109.5 -98z" /> -<glyph unicode="º" horiz-adv-x="803" d="M49 1104q0 177 94.5 276t259.5 99q157 0 255 -103t98 -272q0 -174 -95.5 -274.5t-261.5 -100.5q-159 0 -254.5 102.5t-95.5 272.5zM301 1104q0 -87 24 -129.5t76 -42.5q99 0 99 172q0 174 -99 174q-100 0 -100 -174z" /> -<glyph unicode="»" horiz-adv-x="1395" d="M76 227l272 348l-272 347l282 149l387 -483v-27l-387 -481zM649 227l275 348l-275 347l285 149l387 -483v-27l-387 -481z" /> -<glyph unicode="¼" horiz-adv-x="1919" d="M1028 140v188l350 555h295v-542h125v-201h-125v-139h-275v139h-370zM1241 341h157v166q0 69 7 135q-40 -100 -62 -133zM357 0l753 1462h302l-754 -1462h-301zM-12 1188l340 274h219v-876h-282v356q0 35 3.5 118t6.5 99q-9 -19 -31.5 -43t-109.5 -98z" /> -<glyph unicode="½" horiz-adv-x="1921" d="M1140 765q80 73 167.5 104t203.5 31q142 0 219.5 -63t77.5 -175q0 -46 -13 -87t-40.5 -84.5t-74.5 -91t-198 -173.5h347v-225h-674v207l215 213q84 84 116.5 129t32.5 79q0 58 -65 58q-81 0 -172 -88zM381 0l753 1462h302l-754 -1462h-301zM-12 1188l340 274h219v-876 h-282v356q0 35 3.5 118t6.5 99q-9 -19 -31.5 -43t-109.5 -98z" /> -<glyph unicode="¾" horiz-adv-x="1921" d="M1100 140v188l350 555h295v-542h125v-201h-125v-139h-275v139h-370zM1313 341h157v166q0 69 7 135q-40 -100 -62 -133zM83 1366q149 115 343 115q146 0 232.5 -57.5t86.5 -157.5q0 -78 -37 -132.5t-125 -86.5v-9q97 -24 144 -76t47 -139q0 -120 -98 -187t-277 -67 q-185 0 -309 70v233q117 -81 297 -81q116 0 116 67q0 41 -32.5 56.5t-102.5 15.5h-104v194h80q71 0 105 18.5t34 59.5q0 25 -21 46.5t-71 21.5t-94 -17t-97 -57zM465 0l753 1462h302l-754 -1462h-301z" /> -<glyph unicode="¿" horiz-adv-x="1034" d="M37 10q0 120 55 208t182 169q100 64 129 97t29 77v51h307v-86q0 -98 -40 -165.5t-142 -131.5q-57 -36 -90 -66t-47 -55.5t-14 -64.5q0 -42 37.5 -66t99.5 -24q148 0 352 106l139 -272q-243 -141 -520 -141q-223 0 -350 98t-127 266zM365 963q0 90 54 140t152 50 q101 0 156 -49.5t55 -140.5q0 -93 -53 -143t-158 -50q-101 0 -153.5 50t-52.5 143z" /> -<glyph unicode="À" horiz-adv-x="1487" d="M0 0l477 1468h527l483 -1468h-432l-72 274h-475l-74 -274h-434zM590 598h311l-63 240q-22 80 -53.5 207t-41.5 182q-9 -51 -35.5 -168t-117.5 -461zM272 1886v21h430q52 -70 203 -233l59 -66v-29h-260q-69 44 -203.5 138.5t-228.5 168.5z" /> -<glyph unicode="Á" horiz-adv-x="1487" d="M0 0l477 1468h527l483 -1468h-432l-72 274h-475l-74 -274h-434zM590 598h311l-63 240q-22 80 -53.5 207t-41.5 182q-9 -51 -35.5 -168t-117.5 -461zM532 1579v29q154 165 195.5 213t68.5 86h428v-21q-80 -64 -220 -163t-212 -144h-260z" /> -<glyph unicode="Â" horiz-adv-x="1487" d="M0 0l477 1468h527l483 -1468h-432l-72 274h-475l-74 -274h-434zM590 598h311l-63 240q-22 80 -53.5 207t-41.5 182q-9 -51 -35.5 -168t-117.5 -461zM295 1579v29q69 65 144.5 153t113.5 146h393q94 -137 256 -299v-29h-254q-84 48 -201 150q-125 -107 -194 -150h-258z " /> -<glyph unicode="Ã" horiz-adv-x="1487" d="M0 0l477 1468h527l483 -1468h-432l-72 274h-475l-74 -274h-434zM590 598h311l-63 240q-22 80 -53.5 207t-41.5 182q-9 -51 -35.5 -168t-117.5 -461zM330 1575q11 175 72 258.5t180 83.5q38 0 81 -15t87 -33t87 -33t81 -15q29 0 46 25t26 73h182q-11 -167 -74 -254.5 t-172 -87.5q-45 0 -90.5 15t-89.5 33t-85.5 33t-78.5 15q-54 0 -72 -98h-180z" /> -<glyph unicode="Ä" horiz-adv-x="1487" d="M0 0l477 1468h527l483 -1468h-432l-72 274h-475l-74 -274h-434zM590 598h311l-63 240q-22 80 -53.5 207t-41.5 182q-9 -51 -35.5 -168t-117.5 -461zM352 1751q0 75 46 116.5t124 41.5q79 0 125.5 -42.5t46.5 -115.5q0 -71 -46.5 -113.5t-125.5 -42.5q-78 0 -124 41 t-46 115zM831 1751q0 75 46 116.5t126 41.5t126.5 -43t46.5 -115q0 -71 -46.5 -113.5t-126.5 -42.5q-81 0 -126.5 41.5t-45.5 114.5z" /> -<glyph unicode="Å" horiz-adv-x="1487" d="M0 0l477 1468h527l483 -1468h-432l-72 274h-475l-74 -274h-434zM590 598h311l-63 240q-22 80 -53.5 207t-41.5 182q-9 -51 -35.5 -168t-117.5 -461zM475 1614q0 116 71.5 185t192.5 69q118 0 195 -70t77 -182q0 -113 -76 -183.5t-196 -70.5q-121 0 -192.5 68.5 t-71.5 183.5zM655 1614q0 -37 21 -60.5t63 -23.5q35 0 59.5 23.5t24.5 60.5q0 38 -24.5 61t-59.5 23t-59.5 -23t-24.5 -61z" /> -<glyph unicode="Æ" horiz-adv-x="1937" d="M-10 0l628 1462h1221v-317h-473v-230h438v-317h-438v-276h473v-322h-870v274h-437l-100 -274h-442zM653 602h316v526h-111z" /> -<glyph unicode="Ç" horiz-adv-x="1329" d="M104 727q0 227 85.5 399t246 264.5t377.5 92.5q237 0 453 -103l-121 -311q-81 38 -162 64t-174 26q-141 0 -220 -115.5t-79 -318.5q0 -422 321 -422q97 0 188 27t183 65v-334q-183 -81 -414 -81q-331 0 -507.5 192t-176.5 555zM477 -258q83 -27 147 -27q52 0 52 47 q0 33 -41 58.5t-107 40.5l72 139h203l-9 -29q96 -39 133 -92.5t37 -130.5q0 -109 -75 -174.5t-199 -65.5q-136 0 -213 29v205z" /> -<glyph unicode="È" horiz-adv-x="1124" d="M158 0v1462h868v-317h-473v-230h438v-317h-438v-276h473v-322h-868zM154 1886v21h430q52 -70 203 -233l59 -66v-29h-260q-69 44 -203.5 138.5t-228.5 168.5z" /> -<glyph unicode="É" horiz-adv-x="1124" d="M158 0v1462h868v-317h-473v-230h438v-317h-438v-276h473v-322h-868zM362 1579v29q154 165 195.5 213t68.5 86h428v-21q-80 -64 -220 -163t-212 -144h-260z" /> -<glyph unicode="Ê" horiz-adv-x="1124" d="M158 0v1462h868v-317h-473v-230h438v-317h-438v-276h473v-322h-868zM151 1579v29q69 65 144.5 153t113.5 146h393q94 -137 256 -299v-29h-254q-84 48 -201 150q-125 -107 -194 -150h-258z" /> -<glyph unicode="Ë" horiz-adv-x="1124" d="M158 0v1462h868v-317h-473v-230h438v-317h-438v-276h473v-322h-868zM187 1751q0 75 46 116.5t124 41.5q79 0 125.5 -42.5t46.5 -115.5q0 -71 -46.5 -113.5t-125.5 -42.5q-78 0 -124 41t-46 115zM666 1751q0 75 46 116.5t126 41.5t126.5 -43t46.5 -115q0 -71 -46.5 -113.5 t-126.5 -42.5q-81 0 -126.5 41.5t-45.5 114.5z" /> -<glyph unicode="Ì" horiz-adv-x="713" d="M158 0v1462h397v-1462h-397zM-116 1886v21h430q52 -70 203 -233l59 -66v-29h-260q-69 44 -203.5 138.5t-228.5 168.5z" /> -<glyph unicode="Í" horiz-adv-x="713" d="M158 0v1462h397v-1462h-397zM156 1579v29q154 165 195.5 213t68.5 86h428v-21q-80 -64 -220 -163t-212 -144h-260z" /> -<glyph unicode="Î" horiz-adv-x="713" d="M158 0v1462h397v-1462h-397zM-95 1579v29q69 65 144.5 153t113.5 146h393q94 -137 256 -299v-29h-254q-84 48 -201 150q-125 -107 -194 -150h-258z" /> -<glyph unicode="Ï" horiz-adv-x="713" d="M158 0v1462h397v-1462h-397zM-55 1751q0 75 46 116.5t124 41.5q79 0 125.5 -42.5t46.5 -115.5q0 -71 -46.5 -113.5t-125.5 -42.5q-78 0 -124 41t-46 115zM424 1751q0 75 46 116.5t126 41.5t126.5 -43t46.5 -115q0 -71 -46.5 -113.5t-126.5 -42.5q-81 0 -126.5 41.5 t-45.5 114.5z" /> -<glyph unicode="Ð" horiz-adv-x="1503" d="M31 563v320h127v579h506q352 0 543.5 -180t191.5 -520q0 -366 -201.5 -564t-566.5 -198h-473v563h-127zM553 324h88q180 0 264 104.5t84 319.5q0 201 -79.5 298t-241.5 97h-115v-260h211v-320h-211v-239z" /> -<glyph unicode="Ñ" horiz-adv-x="1708" d="M158 0v1462h516l532 -1016h6q-14 221 -14 355v661h352v-1462h-518l-534 1030h-9q19 -243 19 -371v-659h-350zM434 1575q11 175 72 258.5t180 83.5q38 0 81 -15t87 -33t87 -33t81 -15q29 0 46 25t26 73h182q-11 -167 -74 -254.5t-172 -87.5q-45 0 -90.5 15t-89.5 33 t-85.5 33t-78.5 15q-54 0 -72 -98h-180z" /> -<glyph unicode="Ò" horiz-adv-x="1632" d="M104 735q0 365 182.5 557.5t530.5 192.5q349 0 529 -191t180 -561q0 -369 -181 -561t-530 -192q-344 0 -527.5 193t-183.5 562zM520 733q0 -424 295 -424q150 0 222.5 103t72.5 321q0 219 -73.5 323.5t-219.5 104.5q-297 0 -297 -428zM397 1886v21h430q52 -70 203 -233 l59 -66v-29h-260q-69 44 -203.5 138.5t-228.5 168.5z" /> -<glyph unicode="Ó" horiz-adv-x="1632" d="M104 735q0 365 182.5 557.5t530.5 192.5q349 0 529 -191t180 -561q0 -369 -181 -561t-530 -192q-344 0 -527.5 193t-183.5 562zM520 733q0 -424 295 -424q150 0 222.5 103t72.5 321q0 219 -73.5 323.5t-219.5 104.5q-297 0 -297 -428zM583 1579v29q154 165 195.5 213 t68.5 86h428v-21q-80 -64 -220 -163t-212 -144h-260z" /> -<glyph unicode="Ô" horiz-adv-x="1632" d="M104 735q0 365 182.5 557.5t530.5 192.5q349 0 529 -191t180 -561q0 -369 -181 -561t-530 -192q-344 0 -527.5 193t-183.5 562zM520 733q0 -424 295 -424q150 0 222.5 103t72.5 321q0 219 -73.5 323.5t-219.5 104.5q-297 0 -297 -428zM363 1579v29q69 65 144.5 153 t113.5 146h393q94 -137 256 -299v-29h-254q-84 48 -201 150q-125 -107 -194 -150h-258z" /> -<glyph unicode="Õ" horiz-adv-x="1632" d="M104 735q0 365 182.5 557.5t530.5 192.5q349 0 529 -191t180 -561q0 -369 -181 -561t-530 -192q-344 0 -527.5 193t-183.5 562zM520 733q0 -424 295 -424q150 0 222.5 103t72.5 321q0 219 -73.5 323.5t-219.5 104.5q-297 0 -297 -428zM401 1575q11 175 72 258.5t180 83.5 q38 0 81 -15t87 -33t87 -33t81 -15q29 0 46 25t26 73h182q-11 -167 -74 -254.5t-172 -87.5q-45 0 -90.5 15t-89.5 33t-85.5 33t-78.5 15q-54 0 -72 -98h-180z" /> -<glyph unicode="Ö" horiz-adv-x="1632" d="M104 735q0 365 182.5 557.5t530.5 192.5q349 0 529 -191t180 -561q0 -369 -181 -561t-530 -192q-344 0 -527.5 193t-183.5 562zM520 733q0 -424 295 -424q150 0 222.5 103t72.5 321q0 219 -73.5 323.5t-219.5 104.5q-297 0 -297 -428zM403 1751q0 75 46 116.5t124 41.5 q79 0 125.5 -42.5t46.5 -115.5q0 -71 -46.5 -113.5t-125.5 -42.5q-78 0 -124 41t-46 115zM882 1751q0 75 46 116.5t126 41.5t126.5 -43t46.5 -115q0 -71 -46.5 -113.5t-126.5 -42.5q-81 0 -126.5 41.5t-45.5 114.5z" /> -<glyph unicode="×" horiz-adv-x="1159" d="M121 991l182 189l270 -267l275 267l188 -183l-274 -274l270 -272l-184 -185l-275 271l-270 -269l-180 187l264 268z" /> -<glyph unicode="Ø" horiz-adv-x="1632" d="M104 735q0 365 182.5 557.5t530.5 192.5q191 0 330 -55l76 118l190 -114l-82 -125q195 -189 195 -576q0 -369 -181 -561t-530 -192q-177 0 -307 43l-84 -132l-193 125l84 125q-211 194 -211 594zM520 733q0 -155 29 -239l403 639q-68 28 -135 28q-297 0 -297 -428z M698 324q54 -15 117 -15q150 0 222.5 103t72.5 321q0 125 -18 211z" /> -<glyph unicode="Ù" horiz-adv-x="1550" d="M150 573v889h397v-858q0 -155 58 -225t171 -70q121 0 175.5 69.5t54.5 227.5v856h395v-880q0 -287 -162.5 -444.5t-468.5 -157.5q-299 0 -459.5 153t-160.5 440zM280 1886v21h430q52 -70 203 -233l59 -66v-29h-260q-69 44 -203.5 138.5t-228.5 168.5z" /> -<glyph unicode="Ú" horiz-adv-x="1550" d="M150 573v889h397v-858q0 -155 58 -225t171 -70q121 0 175.5 69.5t54.5 227.5v856h395v-880q0 -287 -162.5 -444.5t-468.5 -157.5q-299 0 -459.5 153t-160.5 440zM561 1579v29q154 165 195.5 213t68.5 86h428v-21q-80 -64 -220 -163t-212 -144h-260z" /> -<glyph unicode="Û" horiz-adv-x="1550" d="M150 573v889h397v-858q0 -155 58 -225t171 -70q121 0 175.5 69.5t54.5 227.5v856h395v-880q0 -287 -162.5 -444.5t-468.5 -157.5q-299 0 -459.5 153t-160.5 440zM322 1579v29q69 65 144.5 153t113.5 146h393q94 -137 256 -299v-29h-254q-84 48 -201 150 q-125 -107 -194 -150h-258z" /> -<glyph unicode="Ü" horiz-adv-x="1550" d="M150 573v889h397v-858q0 -155 58 -225t171 -70q121 0 175.5 69.5t54.5 227.5v856h395v-880q0 -287 -162.5 -444.5t-468.5 -157.5q-299 0 -459.5 153t-160.5 440zM362 1751q0 75 46 116.5t124 41.5q79 0 125.5 -42.5t46.5 -115.5q0 -71 -46.5 -113.5t-125.5 -42.5 q-78 0 -124 41t-46 115zM841 1751q0 75 46 116.5t126 41.5t126.5 -43t46.5 -115q0 -71 -46.5 -113.5t-126.5 -42.5q-81 0 -126.5 41.5t-45.5 114.5z" /> -<glyph unicode="Ý" horiz-adv-x="1360" d="M0 1462h430l250 -542l252 542h428l-481 -891v-571h-398v559zM471 1579v29q154 165 195.5 213t68.5 86h428v-21q-80 -64 -220 -163t-212 -144h-260z" /> -<glyph unicode="Þ" horiz-adv-x="1284" d="M158 0v1462h395v-213h111q277 0 416 -121t139 -344q0 -245 -144.5 -378.5t-410.5 -133.5h-111v-272h-395zM553 594h72q89 0 141.5 50t52.5 138q0 148 -164 148h-102v-336z" /> -<glyph unicode="ß" horiz-adv-x="1536" d="M135 0v1100q0 215 167 341t446 126q276 0 433.5 -99.5t157.5 -277.5q0 -57 -20 -103.5t-49.5 -84t-64.5 -66.5t-64.5 -52t-49.5 -41t-20 -32q0 -23 24.5 -44t93.5 -58q169 -95 228.5 -173t59.5 -202q0 -174 -115 -264t-338 -90q-136 0 -221.5 12.5t-149.5 46.5v291 q49 -30 131.5 -55t147.5 -25q61 0 99 23.5t38 62.5q0 28 -14.5 47t-50.5 42.5t-121 68.5q-126 67 -175 124.5t-49 137.5q0 122 140 218q75 52 107 91.5t32 83.5q0 51 -49.5 85t-140.5 34q-222 0 -222 -209v-1059h-391z" /> -<glyph unicode="à" horiz-adv-x="1276" d="M74 346q0 181 126 269.5t365 99.5l189 6v16q0 140 -138 140q-124 0 -315 -84l-113 258q198 102 500 102q218 0 337.5 -108t119.5 -302v-743h-271l-75 150h-8q-79 -98 -161 -134t-212 -36q-160 0 -252 96t-92 270zM473 360q0 -104 111 -104q71 0 121.5 45t50.5 117v88 l-90 -4q-193 -7 -193 -142zM204 1548v21h430q52 -70 203 -233l59 -66v-29h-260q-69 44 -203.5 138.5t-228.5 168.5z" /> -<glyph unicode="á" horiz-adv-x="1276" d="M74 346q0 181 126 269.5t365 99.5l189 6v16q0 140 -138 140q-124 0 -315 -84l-113 258q198 102 500 102q218 0 337.5 -108t119.5 -302v-743h-271l-75 150h-8q-79 -98 -161 -134t-212 -36q-160 0 -252 96t-92 270zM473 360q0 -104 111 -104q71 0 121.5 45t50.5 117v88 l-90 -4q-193 -7 -193 -142zM434 1241v29q154 165 195.5 213t68.5 86h428v-21q-80 -64 -220 -163t-212 -144h-260z" /> -<glyph unicode="â" horiz-adv-x="1276" d="M74 346q0 181 126 269.5t365 99.5l189 6v16q0 140 -138 140q-124 0 -315 -84l-113 258q198 102 500 102q218 0 337.5 -108t119.5 -302v-743h-271l-75 150h-8q-79 -98 -161 -134t-212 -36q-160 0 -252 96t-92 270zM473 360q0 -104 111 -104q71 0 121.5 45t50.5 117v88 l-90 -4q-193 -7 -193 -142zM197 1238v29q69 65 144.5 153t113.5 146h393q94 -137 256 -299v-29h-254q-84 48 -201 150q-125 -107 -194 -150h-258z" /> -<glyph unicode="ã" horiz-adv-x="1276" d="M74 346q0 181 126 269.5t365 99.5l189 6v16q0 140 -138 140q-124 0 -315 -84l-113 258q198 102 500 102q218 0 337.5 -108t119.5 -302v-743h-271l-75 150h-8q-79 -98 -161 -134t-212 -36q-160 0 -252 96t-92 270zM473 360q0 -104 111 -104q71 0 121.5 45t50.5 117v88 l-90 -4q-193 -7 -193 -142zM244 1237q11 175 72 258.5t180 83.5q38 0 81 -15t87 -33t87 -33t81 -15q29 0 46 25t26 73h182q-11 -167 -74 -254.5t-172 -87.5q-45 0 -90.5 15t-89.5 33t-85.5 33t-78.5 15q-54 0 -72 -98h-180z" /> -<glyph unicode="ä" horiz-adv-x="1276" d="M74 346q0 181 126 269.5t365 99.5l189 6v16q0 140 -138 140q-124 0 -315 -84l-113 258q198 102 500 102q218 0 337.5 -108t119.5 -302v-743h-271l-75 150h-8q-79 -98 -161 -134t-212 -36q-160 0 -252 96t-92 270zM473 360q0 -104 111 -104q71 0 121.5 45t50.5 117v88 l-90 -4q-193 -7 -193 -142zM268 1413q0 75 46 116.5t124 41.5q79 0 125.5 -42.5t46.5 -115.5q0 -71 -46.5 -113.5t-125.5 -42.5q-78 0 -124 41t-46 115zM747 1413q0 75 46 116.5t126 41.5t126.5 -43t46.5 -115q0 -71 -46.5 -113.5t-126.5 -42.5q-81 0 -126.5 41.5 t-45.5 114.5z" /> -<glyph unicode="å" horiz-adv-x="1276" d="M74 346q0 181 126 269.5t365 99.5l189 6v16q0 140 -138 140q-124 0 -315 -84l-113 258q198 102 500 102q218 0 337.5 -108t119.5 -302v-743h-271l-75 150h-8q-79 -98 -161 -134t-212 -36q-160 0 -252 96t-92 270zM473 360q0 -104 111 -104q71 0 121.5 45t50.5 117v88 l-90 -4q-193 -7 -193 -142zM389 1489q0 116 71.5 185t192.5 69q118 0 195 -70t77 -182q0 -113 -76 -183.5t-196 -70.5q-121 0 -192.5 68.5t-71.5 183.5zM569 1489q0 -37 21 -60.5t63 -23.5q35 0 59.5 23.5t24.5 60.5q0 38 -24.5 61t-59.5 23t-59.5 -23t-24.5 -61z" /> -<glyph unicode="æ" horiz-adv-x="1915" d="M74 352q0 345 497 363l183 6v18q0 138 -136 138q-138 0 -313 -80l-110 256q190 100 454 100q201 0 336 -94q70 49 153 71.5t199 22.5q229 0 360.5 -136.5t131.5 -383.5v-172h-696q4 -90 74 -146.5t186 -56.5q194 0 364 86v-281q-94 -48 -191 -65.5t-225 -17.5 q-280 0 -430 190q-80 -83 -141.5 -120.5t-138.5 -53.5t-197 -16q-162 0 -261 101.5t-99 270.5zM473 356q0 -100 113 -100q69 0 119.5 45t50.5 117v88l-84 -4q-106 -4 -152.5 -38.5t-46.5 -107.5zM1139 707h340q-2 82 -48 131t-116 49q-162 0 -176 -180z" /> -<glyph unicode="ç" horiz-adv-x="1104" d="M86 561q0 282 155 437t441 155q197 0 371 -86l-115 -289q-71 31 -131 49.5t-125 18.5q-95 0 -147 -74t-52 -209q0 -272 201 -272q172 0 330 100v-311q-151 -100 -363 -100q-278 0 -421.5 150t-143.5 431zM361 -258q83 -27 147 -27q52 0 52 47q0 33 -41 58.5t-107 40.5 l72 139h203l-9 -29q96 -39 133 -92.5t37 -130.5q0 -109 -75 -174.5t-199 -65.5q-136 0 -213 29v205z" /> -<glyph unicode="è" horiz-adv-x="1266" d="M86 559q0 287 145 440.5t414 153.5q256 0 395.5 -133.5t139.5 -384.5v-174h-699q4 -95 69.5 -149t178.5 -54q103 0 189.5 19.5t187.5 66.5v-281q-92 -47 -190 -65t-234 -18q-283 0 -439.5 150.5t-156.5 428.5zM489 707h336q-2 82 -46.5 131t-119.5 49q-69 0 -115.5 -43.5 t-54.5 -136.5zM189 1548v21h430q52 -70 203 -233l59 -66v-29h-260q-69 44 -203.5 138.5t-228.5 168.5z" /> -<glyph unicode="é" horiz-adv-x="1266" d="M86 559q0 287 145 440.5t414 153.5q256 0 395.5 -133.5t139.5 -384.5v-174h-699q4 -95 69.5 -149t178.5 -54q103 0 189.5 19.5t187.5 66.5v-281q-92 -47 -190 -65t-234 -18q-283 0 -439.5 150.5t-156.5 428.5zM489 707h336q-2 82 -46.5 131t-119.5 49q-69 0 -115.5 -43.5 t-54.5 -136.5zM471 1241v29q154 165 195.5 213t68.5 86h428v-21q-80 -64 -220 -163t-212 -144h-260z" /> -<glyph unicode="ê" horiz-adv-x="1266" d="M86 559q0 287 145 440.5t414 153.5q256 0 395.5 -133.5t139.5 -384.5v-174h-699q4 -95 69.5 -149t178.5 -54q103 0 189.5 19.5t187.5 66.5v-281q-92 -47 -190 -65t-234 -18q-283 0 -439.5 150.5t-156.5 428.5zM489 707h336q-2 82 -46.5 131t-119.5 49q-69 0 -115.5 -43.5 t-54.5 -136.5zM205 1241v29q69 65 144.5 153t113.5 146h393q94 -137 256 -299v-29h-254q-84 48 -201 150q-125 -107 -194 -150h-258z" /> -<glyph unicode="ë" horiz-adv-x="1266" d="M86 559q0 287 145 440.5t414 153.5q256 0 395.5 -133.5t139.5 -384.5v-174h-699q4 -95 69.5 -149t178.5 -54q103 0 189.5 19.5t187.5 66.5v-281q-92 -47 -190 -65t-234 -18q-283 0 -439.5 150.5t-156.5 428.5zM489 707h336q-2 82 -46.5 131t-119.5 49q-69 0 -115.5 -43.5 t-54.5 -136.5zM252 1413q0 75 46 116.5t124 41.5q79 0 125.5 -42.5t46.5 -115.5q0 -71 -46.5 -113.5t-125.5 -42.5q-78 0 -124 41t-46 115zM731 1413q0 75 46 116.5t126 41.5t126.5 -43t46.5 -115q0 -71 -46.5 -113.5t-126.5 -42.5q-81 0 -126.5 41.5t-45.5 114.5z" /> -<glyph unicode="ì" horiz-adv-x="666" d="M137 0v1133h391v-1133h-391zM-130 1548v21h430q52 -70 203 -233l59 -66v-29h-260q-69 44 -203.5 138.5t-228.5 168.5z" /> -<glyph unicode="í" horiz-adv-x="666" d="M137 0v1133h391v-1133h-391zM107 1241v29q154 165 195.5 213t68.5 86h428v-21q-80 -64 -220 -163t-212 -144h-260z" /> -<glyph unicode="î" horiz-adv-x="666" d="M137 0v1133h391v-1133h-391zM-120 1241v29q69 65 144.5 153t113.5 146h393q94 -137 256 -299v-29h-254q-84 48 -201 150q-125 -107 -194 -150h-258z" /> -<glyph unicode="ï" horiz-adv-x="666" d="M137 0v1133h391v-1133h-391zM-61 1413q0 75 46 116.5t124 41.5q79 0 125.5 -42.5t46.5 -115.5q0 -71 -46.5 -113.5t-125.5 -42.5q-78 0 -124 41t-46 115zM418 1413q0 75 46 116.5t126 41.5t126.5 -43t46.5 -115q0 -71 -46.5 -113.5t-126.5 -42.5q-81 0 -126.5 41.5 t-45.5 114.5z" /> -<glyph unicode="ð" horiz-adv-x="1313" d="M88 498q0 239 130.5 377.5t348.5 138.5q192 0 244 -84l8 4q-67 130 -143 207l-182 -119l-117 184l143 92l-149 93l108 182q174 -73 266 -135l209 137l115 -182l-145 -97q159 -157 226 -327.5t67 -388.5q0 -275 -152.5 -437.5t-415.5 -162.5q-259 0 -410 139t-151 379z M489 500q0 -242 164 -242q91 0 127.5 71t36.5 216q0 84 -45 136t-119 52q-92 0 -128 -56t-36 -177z" /> -<glyph unicode="ñ" horiz-adv-x="1372" d="M135 0v1133h295l49 -140h23q50 80 138.5 120t203.5 40q188 0 292.5 -109t104.5 -307v-737h-391v618q0 113 -32.5 170.5t-104.5 57.5q-99 0 -143 -79t-44 -271v-496h-391zM274 1237q11 175 72 258.5t180 83.5q38 0 81 -15t87 -33t87 -33t81 -15q29 0 46 25t26 73h182 q-11 -167 -74 -254.5t-172 -87.5q-45 0 -90.5 15t-89.5 33t-85.5 33t-78.5 15q-54 0 -72 -98h-180z" /> -<glyph unicode="ò" horiz-adv-x="1305" d="M86 569q0 277 149.5 430.5t419.5 153.5q167 0 295 -71t197.5 -203.5t69.5 -309.5q0 -278 -149.5 -433.5t-418.5 -155.5q-258 0 -410.5 159t-152.5 430zM483 569q0 -146 39 -222.5t131 -76.5q91 0 128.5 76.5t37.5 222.5q0 145 -38 219t-130 74q-90 0 -129 -73.5 t-39 -219.5zM175 1548v21h430q52 -70 203 -233l59 -66v-29h-260q-69 44 -203.5 138.5t-228.5 168.5z" /> -<glyph unicode="ó" horiz-adv-x="1305" d="M86 569q0 277 149.5 430.5t419.5 153.5q167 0 295 -71t197.5 -203.5t69.5 -309.5q0 -278 -149.5 -433.5t-418.5 -155.5q-258 0 -410.5 159t-152.5 430zM483 569q0 -146 39 -222.5t131 -76.5q91 0 128.5 76.5t37.5 222.5q0 145 -38 219t-130 74q-90 0 -129 -73.5 t-39 -219.5zM416 1241v29q154 165 195.5 213t68.5 86h428v-21q-80 -64 -220 -163t-212 -144h-260z" /> -<glyph unicode="ô" horiz-adv-x="1305" d="M86 569q0 277 149.5 430.5t419.5 153.5q167 0 295 -71t197.5 -203.5t69.5 -309.5q0 -278 -149.5 -433.5t-418.5 -155.5q-258 0 -410.5 159t-152.5 430zM483 569q0 -146 39 -222.5t131 -76.5q91 0 128.5 76.5t37.5 222.5q0 145 -38 219t-130 74q-90 0 -129 -73.5 t-39 -219.5zM199 1241v29q69 65 144.5 153t113.5 146h393q94 -137 256 -299v-29h-254q-84 48 -201 150q-125 -107 -194 -150h-258z" /> -<glyph unicode="õ" horiz-adv-x="1305" d="M86 569q0 277 149.5 430.5t419.5 153.5q167 0 295 -71t197.5 -203.5t69.5 -309.5q0 -278 -149.5 -433.5t-418.5 -155.5q-258 0 -410.5 159t-152.5 430zM483 569q0 -146 39 -222.5t131 -76.5q91 0 128.5 76.5t37.5 222.5q0 145 -38 219t-130 74q-90 0 -129 -73.5 t-39 -219.5zM231 1237q11 175 72 258.5t180 83.5q38 0 81 -15t87 -33t87 -33t81 -15q29 0 46 25t26 73h182q-11 -167 -74 -254.5t-172 -87.5q-45 0 -90.5 15t-89.5 33t-85.5 33t-78.5 15q-54 0 -72 -98h-180z" /> -<glyph unicode="ö" horiz-adv-x="1305" d="M86 569q0 277 149.5 430.5t419.5 153.5q167 0 295 -71t197.5 -203.5t69.5 -309.5q0 -278 -149.5 -433.5t-418.5 -155.5q-258 0 -410.5 159t-152.5 430zM483 569q0 -146 39 -222.5t131 -76.5q91 0 128.5 76.5t37.5 222.5q0 145 -38 219t-130 74q-90 0 -129 -73.5 t-39 -219.5zM239 1413q0 75 46 116.5t124 41.5q79 0 125.5 -42.5t46.5 -115.5q0 -71 -46.5 -113.5t-125.5 -42.5q-78 0 -124 41t-46 115zM718 1413q0 75 46 116.5t126 41.5t126.5 -43t46.5 -115q0 -71 -46.5 -113.5t-126.5 -42.5q-81 0 -126.5 41.5t-45.5 114.5z" /> -<glyph unicode="÷" horiz-adv-x="1159" d="M72 588v268h1013v-268h-1013zM422 332q0 82 39.5 126t116.5 44q75 0 116 -43.5t41 -126.5q0 -80 -43.5 -125t-113.5 -45q-71 0 -113.5 44t-42.5 126zM422 1112q0 82 39.5 126t116.5 44q75 0 116 -43.5t41 -126.5q0 -80 -43.5 -125t-113.5 -45q-71 0 -113.5 44t-42.5 126z " /> -<glyph unicode="ø" horiz-adv-x="1362" d="M86 569q0 277 157 430.5t441 153.5q125 0 234 -39l71 111l168 -105l-67 -104q184 -158 184 -447q0 -280 -156.5 -434.5t-439.5 -154.5q-125 0 -229 34l-84 -131l-170 107l79 123q-188 158 -188 456zM461 569q0 -99 12 -147l289 448q-36 13 -82 13q-114 0 -166.5 -74 t-52.5 -240zM606 258q27 -8 76 -8q114 0 165.5 73t51.5 246q0 86 -10 131z" /> -<glyph unicode="ù" horiz-adv-x="1372" d="M133 395v738h391v-619q0 -111 31.5 -168t103.5 -57q101 0 144 79.5t43 268.5v496h391v-1133h-295l-49 141h-23q-49 -78 -136.5 -119.5t-205.5 -41.5q-187 0 -291 108.5t-104 306.5zM175 1548v21h430q52 -70 203 -233l59 -66v-29h-260q-69 44 -203.5 138.5t-228.5 168.5z " /> -<glyph unicode="ú" horiz-adv-x="1372" d="M133 395v738h391v-619q0 -111 31.5 -168t103.5 -57q101 0 144 79.5t43 268.5v496h391v-1133h-295l-49 141h-23q-49 -78 -136.5 -119.5t-205.5 -41.5q-187 0 -291 108.5t-104 306.5zM471 1241v29q154 165 195.5 213t68.5 86h428v-21q-80 -64 -220 -163t-212 -144h-260z " /> -<glyph unicode="û" horiz-adv-x="1372" d="M133 395v738h391v-619q0 -111 31.5 -168t103.5 -57q101 0 144 79.5t43 268.5v496h391v-1133h-295l-49 141h-23q-49 -78 -136.5 -119.5t-205.5 -41.5q-187 0 -291 108.5t-104 306.5zM230 1241v29q69 65 144.5 153t113.5 146h393q94 -137 256 -299v-29h-254 q-84 48 -201 150q-125 -107 -194 -150h-258z" /> -<glyph unicode="ü" horiz-adv-x="1372" d="M133 395v738h391v-619q0 -111 31.5 -168t103.5 -57q101 0 144 79.5t43 268.5v496h391v-1133h-295l-49 141h-23q-49 -78 -136.5 -119.5t-205.5 -41.5q-187 0 -291 108.5t-104 306.5zM272 1413q0 75 46 116.5t124 41.5q79 0 125.5 -42.5t46.5 -115.5q0 -71 -46.5 -113.5 t-125.5 -42.5q-78 0 -124 41t-46 115zM751 1413q0 75 46 116.5t126 41.5t126.5 -43t46.5 -115q0 -71 -46.5 -113.5t-126.5 -42.5q-81 0 -126.5 41.5t-45.5 114.5z" /> -<glyph unicode="ý" horiz-adv-x="1249" d="M-2 1133h412l192 -650q14 -51 19 -123h8q8 69 24 121l197 652h399l-448 -1205q-86 -230 -211.5 -325t-327.5 -95q-78 0 -160 17v307q53 -12 121 -12q52 0 91 20t68 56.5t62 119.5zM401 1241v29q154 165 195.5 213t68.5 86h428v-21q-80 -64 -220 -163t-212 -144h-260z" /> -<glyph unicode="þ" horiz-adv-x="1317" d="M135 -492v2048h391v-344q0 -106 -18 -225h18q43 78 122 122t179 44q185 0 293.5 -154t108.5 -430q0 -271 -111.5 -430t-304.5 -159q-173 0 -287 129h-14l7 -60l7 -92v-449h-391zM526 571q0 -146 39 -211t123 -65q80 0 111.5 70.5t31.5 207.5q0 134 -33 203.5t-116 69.5 q-85 0 -119 -61.5t-37 -184.5v-29z" /> -<glyph unicode="ÿ" horiz-adv-x="1249" d="M-2 1133h412l192 -650q14 -51 19 -123h8q8 69 24 121l197 652h399l-448 -1205q-86 -230 -211.5 -325t-327.5 -95q-78 0 -160 17v307q53 -12 121 -12q52 0 91 20t68 56.5t62 119.5zM216 1413q0 75 46 116.5t124 41.5q79 0 125.5 -42.5t46.5 -115.5q0 -71 -46.5 -113.5 t-125.5 -42.5q-78 0 -124 41t-46 115zM695 1413q0 75 46 116.5t126 41.5t126.5 -43t46.5 -115q0 -71 -46.5 -113.5t-126.5 -42.5q-81 0 -126.5 41.5t-45.5 114.5z" /> -<glyph unicode="ı" horiz-adv-x="666" d="M137 0v1133h391v-1133h-391z" /> -<glyph unicode="Œ" horiz-adv-x="1960" d="M104 735q0 359 175 554.5t497 195.5q67 0 143.5 -7t106.5 -16h836v-317h-473v-230h436v-317h-436v-276h473v-322h-844q-34 -8 -110.5 -14t-133.5 -6q-319 0 -494.5 200t-175.5 555zM520 733q0 -205 64.5 -314.5t191.5 -109.5q141 0 217 43v760q-34 23 -93 36t-122 13 q-125 0 -191.5 -109.5t-66.5 -318.5z" /> -<glyph unicode="œ" horiz-adv-x="2007" d="M86 569q0 277 149.5 430.5t419.5 153.5q226 0 375 -127q155 127 400 127q227 0 359 -136t132 -384v-172h-696q4 -90 74 -146.5t186 -56.5q194 0 364 86v-281q-92 -47 -187 -65t-228 -18q-238 0 -383 137q-151 -137 -402 -137q-258 0 -410.5 159t-152.5 430zM485 569 q0 -146 38 -222.5t130 -76.5q91 0 128.5 76.5t37.5 222.5q0 145 -38 219t-130 74q-89 0 -127.5 -74t-38.5 -219zM1231 707h340q-2 82 -48 131t-116 49q-162 0 -176 -180z" /> -<glyph unicode="Ÿ" horiz-adv-x="1360" d="M0 1462h430l250 -542l252 542h428l-481 -891v-571h-398v559zM268 1751q0 75 46 116.5t124 41.5q79 0 125.5 -42.5t46.5 -115.5q0 -71 -46.5 -113.5t-125.5 -42.5q-78 0 -124 41t-46 115zM747 1751q0 75 46 116.5t126 41.5t126.5 -43t46.5 -115q0 -71 -46.5 -113.5 t-126.5 -42.5q-81 0 -126.5 41.5t-45.5 114.5z" /> -<glyph unicode="ˆ" horiz-adv-x="1237" d="M164 1241v29q69 65 144.5 153t113.5 146h393q94 -137 256 -299v-29h-254q-84 48 -201 150q-125 -107 -194 -150h-258z" /> -<glyph unicode="˚" horiz-adv-x="1120" d="M293 1489q0 116 71.5 185t192.5 69q118 0 195 -70t77 -182q0 -113 -76 -183.5t-196 -70.5q-121 0 -192.5 68.5t-71.5 183.5zM473 1489q0 -37 21 -60.5t63 -23.5q35 0 59.5 23.5t24.5 60.5q0 38 -24.5 61t-59.5 23t-59.5 -23t-24.5 -61z" /> -<glyph unicode="˜" horiz-adv-x="1225" d="M176 1237q11 175 72 258.5t180 83.5q38 0 81 -15t87 -33t87 -33t81 -15q29 0 46 25t26 73h182q-11 -167 -74 -254.5t-172 -87.5q-45 0 -90.5 15t-89.5 33t-85.5 33t-78.5 15q-54 0 -72 -98h-180z" /> -<glyph unicode=" " horiz-adv-x="959" /> -<glyph unicode=" " horiz-adv-x="1919" /> -<glyph unicode=" " horiz-adv-x="959" /> -<glyph unicode=" " horiz-adv-x="1919" /> -<glyph unicode=" " horiz-adv-x="639" /> -<glyph unicode=" " horiz-adv-x="479" /> -<glyph unicode=" " horiz-adv-x="319" /> -<glyph unicode=" " horiz-adv-x="319" /> -<glyph unicode=" " horiz-adv-x="239" /> -<glyph unicode=" " horiz-adv-x="383" /> -<glyph unicode=" " horiz-adv-x="106" /> -<glyph unicode="‐" horiz-adv-x="651" d="M43 393v312h565v-312h-565z" /> -<glyph unicode="‑" horiz-adv-x="651" d="M43 393v312h565v-312h-565z" /> -<glyph unicode="‒" horiz-adv-x="651" d="M43 393v312h565v-312h-565z" /> -<glyph unicode="–" horiz-adv-x="1024" d="M74 414v276h876v-276h-876z" /> -<glyph unicode="—" horiz-adv-x="2048" d="M74 414v276h1896v-276h-1896z" /> -<glyph unicode="‘" horiz-adv-x="512" d="M20 899q100 391 177 561h278q-67 -312 -98 -583h-342z" /> -<glyph unicode="’" horiz-adv-x="512" d="M37 877q68 317 98 583h342l15 -22q-92 -366 -177 -561h-278z" /> -<glyph unicode="‚" horiz-adv-x="633" d="M57 -285q29 138 58.5 309.5t40.5 274.5h342l14 -23q-97 -381 -176 -561h-279z" /> -<glyph unicode="“" horiz-adv-x="1022" d="M20 899q100 391 177 561h278q-67 -312 -98 -583h-342zM530 899q100 391 177 561h278q-67 -312 -98 -583h-342z" /> -<glyph unicode="”" horiz-adv-x="1022" d="M37 877q68 317 98 583h342l15 -22q-92 -366 -177 -561h-278zM547 877q68 317 98 583h342l14 -22q-93 -371 -176 -561h-278z" /> -<glyph unicode="„" horiz-adv-x="1143" d="M57 -285q29 138 58.5 309.5t40.5 274.5h342l14 -23q-97 -381 -176 -561h-279zM567 -285q29 138 58.5 309.5t40.5 274.5h342l14 -23q-97 -381 -176 -561h-279z" /> -<glyph unicode="•" horiz-adv-x="803" d="M74 748q0 174 84.5 267t242.5 93t243 -94.5t85 -265.5q0 -172 -87 -266.5t-241 -94.5q-155 0 -241 93t-86 268zM668 1133z" /> -<glyph unicode="…" horiz-adv-x="1776" d="M86 166q0 92 54.5 142t158.5 50q99 0 152 -50t53 -142q0 -90 -54.5 -140.5t-150.5 -50.5q-99 0 -156 50t-57 141zM678 166q0 92 54.5 142t158.5 50q99 0 152 -50t53 -142q0 -90 -54.5 -140.5t-150.5 -50.5q-99 0 -156 50t-57 141zM1270 166q0 92 54.5 142t158.5 50 q99 0 152 -50t53 -142q0 -90 -54.5 -140.5t-150.5 -50.5q-99 0 -156 50t-57 141z" /> -<glyph unicode=" " horiz-adv-x="383" /> -<glyph unicode="‹" horiz-adv-x="819" d="M74 561v27l389 483l280 -149l-272 -347l272 -348l-280 -147z" /> -<glyph unicode="›" horiz-adv-x="819" d="M76 227l272 348l-272 347l282 149l387 -483v-27l-387 -481z" /> -<glyph unicode="⁄" horiz-adv-x="188" d="M-434 0l753 1462h302l-754 -1462h-301z" /> -<glyph unicode=" " horiz-adv-x="479" /> -<glyph unicode="⁴" horiz-adv-x="817" d="M29 725v188l350 555h295v-542h125v-201h-125v-139h-275v139h-370zM242 926h157v166q0 69 7 135q-40 -100 -62 -133z" /> -<glyph unicode="€" d="M55 467v205h129l-2 21v22l2 43h-129v205h148q51 255 212.5 387.5t413.5 132.5q180 0 349 -76l-119 -299q-120 51 -230 51q-112 0 -171.5 -53.5t-71.5 -142.5h338v-205h-353l-2 -29v-14l2 -44v1h287v-205h-264q33 -164 260 -164q145 0 266 55v-323q-102 -55 -291 -55 q-253 0 -412 126t-206 361h-156z" /> -<glyph unicode="™" horiz-adv-x="1577" d="M37 1286v176h536v-176h-170v-545h-196v545h-170zM645 741v721h287l137 -479l150 479h276v-721h-195v400q0 68 7 110h-9l-151 -510h-164l-143 510h-9q7 -56 7 -110v-400h-193z" /> -<glyph unicode="" horiz-adv-x="1135" d="M0 1135h1135v-1135h-1135v1135z" /> -<glyph unicode="fi" horiz-adv-x="1511" d="M973 1415q0 88 49 131t158 43t159 -44t50 -130q0 -172 -209 -172q-207 0 -207 172zM983 0v1133h391v-1133h-391zM45 840v192l158 96v19q0 224 91.5 322t293.5 98q78 0 147.5 -12t161.5 -42l-84 -253q-72 20 -141 20q-45 0 -65.5 -27.5t-20.5 -89.5v-30h241v-293h-241 v-840h-391v840h-150z" /> -<glyph unicode="fl" horiz-adv-x="1507" d="M981 0v1556h391v-1556h-391zM45 840v192l158 96v19q0 224 91.5 322t293.5 98q78 0 147.5 -12t161.5 -42l-84 -253q-72 20 -141 20q-45 0 -65.5 -27.5t-20.5 -89.5v-30h241v-293h-241v-840h-391v840h-150z" /> -<glyph unicode="ffi" horiz-adv-x="2357" d="M45 840v192l158 96v19q0 224 91.5 322t293.5 98q78 0 147.5 -12t161.5 -42l-84 -253q-72 20 -141 20q-45 0 -65.5 -27.5t-20.5 -89.5v-30h241v-293h-241v-840h-391v840h-150zM891 840v192l158 96v19q0 224 91.5 322t293.5 98q78 0 147.5 -12t161.5 -42l-84 -253 q-72 20 -141 20q-45 0 -65.5 -27.5t-20.5 -89.5v-30h241v-293h-241v-840h-391v840h-150zM1819 1415q0 88 49 131t158 43t159 -44t50 -130q0 -172 -209 -172q-207 0 -207 172zM1829 0v1133h391v-1133h-391z" /> -<glyph unicode="ffl" horiz-adv-x="2353" d="M45 840v192l158 96v19q0 224 91.5 322t293.5 98q78 0 147.5 -12t161.5 -42l-84 -253q-72 20 -141 20q-45 0 -65.5 -27.5t-20.5 -89.5v-30h241v-293h-241v-840h-391v840h-150zM891 840v192l158 96v19q0 224 91.5 322t293.5 98q78 0 147.5 -12t161.5 -42l-84 -253 q-72 20 -141 20q-45 0 -65.5 -27.5t-20.5 -89.5v-30h241v-293h-241v-840h-391v840h-150zM1827 0v1556h391v-1556h-391z" /> -</font> -</defs></svg> -\ No newline at end of file diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-ExtraBold-webfont.ttf b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-ExtraBold-webfont.ttf Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-ExtraBold-webfont.woff b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-ExtraBold-webfont.woff Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-ExtraBoldItalic-webfont.eot b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-ExtraBoldItalic-webfont.eot Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-ExtraBoldItalic-webfont.svg b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-ExtraBoldItalic-webfont.svg @@ -1,251 +0,0 @@ -<?xml version="1.0" standalone="no"?> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" > -<svg xmlns="http://www.w3.org/2000/svg"> -<metadata> -This is a custom SVG webfont generated by Font Squirrel. -Copyright : Digitized data copyright 20102011 Google Corporation -Foundry : Ascender Corporation -Foundry URL : httpwwwascendercorpcom -</metadata> -<defs> -<font id="OpenSansExtraboldItalic" horiz-adv-x="1243" > -<font-face units-per-em="2048" ascent="1638" descent="-410" /> -<missing-glyph horiz-adv-x="532" /> -<glyph unicode=" " horiz-adv-x="532" /> -<glyph unicode="	" horiz-adv-x="532" /> -<glyph unicode=" " horiz-adv-x="532" /> -<glyph unicode="!" horiz-adv-x="623" d="M12 127q0 107 65 170t179 63q87 0 133.5 -40.5t46.5 -114.5q0 -110 -63.5 -170t-173.5 -60q-88 0 -137.5 38.5t-49.5 113.5zM125 516l156 946h426l-254 -946h-328z" /> -<glyph unicode=""" horiz-adv-x="930" d="M182 934l72 528h342l-158 -528h-256zM623 934l73 528h342l-157 -528h-258z" /> -<glyph unicode="#" horiz-adv-x="1323" d="M14 393l21 238h266l57 200h-235l20 242h285l111 389h270l-111 -389h168l111 389h270l-110 -389h221l-21 -242h-270l-57 -200h243l-20 -238h-293l-111 -393h-270l113 393h-168l-113 -393h-270l112 393h-219zM571 631h168l58 200h-168z" /> -<glyph unicode="$" horiz-adv-x="1188" d="M61 162v311q126 -59 228 -86t203 -27q174 0 174 105q0 40 -32.5 72.5t-139.5 83.5q-139 62 -214 160t-75 227q0 176 133.5 288t357.5 127l29 133h168l-31 -137q161 -15 314 -90l-140 -270q-158 71 -295 71q-66 0 -103.5 -28t-37.5 -68q0 -53 39 -89.5t158 -94.5 q140 -68 205 -155.5t65 -213.5q0 -178 -133 -290t-361 -125l-38 -187h-168l41 191q-221 16 -347 92z" /> -<glyph unicode="%" horiz-adv-x="1878" d="M80 887q0 173 54 309.5t154.5 211.5t237.5 75q147 0 231.5 -85t84.5 -237q0 -165 -56.5 -303t-158 -215.5t-230.5 -77.5q-159 0 -238 83.5t-79 238.5zM252 0l1089 1462h289l-1081 -1462h-297zM371 891q0 -84 53 -84q52 0 89.5 110.5t37.5 239.5q0 43 -12 63.5t-41 20.5 q-50 0 -88.5 -110t-38.5 -240zM1057 301q0 173 54 309.5t154.5 211.5t237.5 75q147 0 231.5 -85t84.5 -237q0 -164 -56 -302t-158 -215.5t-231 -77.5q-159 0 -238 83t-79 238zM1348 305q0 -84 53 -84q52 0 89.5 110.5t37.5 239.5q0 44 -12 64t-41 20q-50 0 -88.5 -110 t-38.5 -240z" /> -<glyph unicode="&" horiz-adv-x="1501" d="M8 385q0 159 87.5 264.5t271.5 165.5q-37 46 -60.5 118.5t-23.5 131.5q0 197 126 308.5t355 111.5q189 0 302.5 -88t113.5 -236q0 -130 -80 -233t-262 -197l129 -186q36 36 75.5 114.5t63.5 161.5h383q-46 -161 -128.5 -305.5t-189.5 -253.5l191 -262h-442l-43 61 q-155 -81 -349 -81q-244 0 -382 106.5t-138 298.5zM399 424q0 -62 47.5 -99.5t124.5 -37.5t138 26l-193 279q-117 -52 -117 -168zM635 1092q0 -76 51 -144q72 31 106.5 79.5t34.5 107.5q0 35 -22 60.5t-60 25.5q-49 0 -79.5 -34.5t-30.5 -94.5z" /> -<glyph unicode="'" horiz-adv-x="487" d="M182 934l72 528h342l-158 -528h-256z" /> -<glyph unicode="(" horiz-adv-x="766" d="M68 326q0 330 124.5 619t387.5 558h323q-260 -281 -384 -576t-124 -618q0 -150 32.5 -326t84.5 -307h-293q-67 120 -109 299t-42 351zM720 1485z" /> -<glyph unicode=")" horiz-adv-x="766" d="M-133 -324q256 277 378 571.5t122 622.5q0 150 -32.5 322.5t-86.5 310.5h295q71 -124 111 -298t40 -351q0 -341 -123 -628t-378 -550h-326zM420 1485z" /> -<glyph unicode="*" horiz-adv-x="1110" d="M152 1108l100 278l319 -165l31 350l307 -62l-116 -331l368 30l-22 -301l-310 41l148 -311l-285 -86l-80 303l-166 -244l-249 185l254 229z" /> -<glyph unicode="+" horiz-adv-x="1159" d="M102 586v272h353v352h270v-352h352v-272h-352v-348h-270v348h-353z" /> -<glyph unicode="," horiz-adv-x="627" d="M-104 -264q53 121 147 387l41 115h348l8 -23q-116 -262 -256 -479h-288z" /> -<glyph unicode="-" horiz-adv-x="674" d="M23 393l63 312h553l-64 -312h-552z" /> -<glyph unicode="." horiz-adv-x="627" d="M0 127q0 109 65 171t179 62q84 0 132 -40t48 -115q0 -118 -60 -174t-190 -56q-78 0 -126 37t-48 115z" /> -<glyph unicode="/" horiz-adv-x="956" d="M-90 -20l838 1503h344l-838 -1503h-344z" /> -<glyph unicode="0" horiz-adv-x="1188" d="M63 465q0 295 85 533.5t235 362.5t348 124q135 0 230.5 -62.5t145.5 -174.5t50 -265q0 -298 -85 -529.5t-235 -352.5t-348 -121q-210 0 -318 126t-108 359zM453 457q0 -84 15 -123t60 -39q58 0 111.5 94.5t91 265.5t37.5 336q0 85 -18.5 131.5t-63.5 46.5 q-55 0 -110 -111t-89 -282t-34 -319z" /> -<glyph unicode="1" horiz-adv-x="1188" d="M150 1079l620 383h311l-307 -1462h-389l174 799q28 132 76 256q-78 -68 -131 -103l-203 -125z" /> -<glyph unicode="2" horiz-adv-x="1188" d="M-57 0l53 256l483 436q248 221 248 361q0 49 -26 73.5t-66 24.5q-120 0 -281 -147l-186 258q234 221 541 221q183 0 295 -99.5t112 -269.5q0 -152 -87 -285t-298 -315l-205 -176v-12h490l-68 -326h-1005z" /> -<glyph unicode="3" horiz-adv-x="1188" d="M14 59v332q167 -100 377 -100q138 0 206.5 46.5t68.5 133.5q0 54 -27 81t-86 39.5t-166 12.5h-84l53 291h78q147 0 229 46.5t82 127.5q0 46 -36 74t-99 28q-117 0 -270 -84l-158 248q126 81 243.5 114.5t258.5 33.5q201 0 321.5 -93t120.5 -253q0 -148 -89.5 -245 t-252.5 -130v-8q129 -25 202 -111.5t73 -212.5q0 -216 -178 -333t-482 -117q-116 0 -217.5 20.5t-167.5 58.5z" /> -<glyph unicode="4" horiz-adv-x="1188" d="M-10 283l51 256l762 923h360l-186 -884h149l-61 -295h-150l-59 -283h-377l60 283h-549zM391 578h209l49 194q29 107 60 211h-9q-51 -97 -114 -172z" /> -<glyph unicode="5" horiz-adv-x="1188" d="M20 63v324q79 -45 181 -70.5t184 -25.5q277 0 277 192q0 76 -50.5 123t-136.5 47q-53 0 -111 -10t-92 -22l-122 92l215 749h813l-68 -323h-471l-59 -185q35 4 75 4q181 0 293.5 -117.5t112.5 -316.5q0 -261 -161 -402.5t-466 -141.5q-129 0 -244.5 22t-169.5 61z" /> -<glyph unicode="6" horiz-adv-x="1188" d="M78 471q0 105 26 254q85 392 298.5 575t568.5 183q102 0 233 -31l-63 -303q-95 25 -183 25q-145 0 -237 -34t-151.5 -108.5t-106.5 -224.5h8q106 170 307 170q160 0 244 -103t84 -299q0 -175 -68.5 -311.5t-197 -210t-297.5 -73.5q-225 0 -345 124t-120 367zM463 420 q0 -66 26.5 -99.5t71.5 -33.5q66 0 109 76.5t43 181.5q0 129 -92 129q-68 0 -113 -73t-45 -181z" /> -<glyph unicode="7" horiz-adv-x="1188" d="M35 0l717 1135h-574l70 327h1030l-51 -231l-744 -1231h-448z" /> -<glyph unicode="8" horiz-adv-x="1188" d="M49 338q0 301 332 418q-156 121 -156 309q0 121 60.5 216.5t174 149.5t265.5 54q200 0 316 -92.5t116 -241.5q0 -128 -77.5 -228.5t-202.5 -140.5q92 -71 140 -158t48 -204q0 -206 -141 -323t-387 -117q-225 0 -356.5 99t-131.5 259zM414 385q0 -54 36.5 -88.5 t96.5 -34.5q70 0 112.5 42t42.5 110q0 115 -118 194q-170 -90 -170 -223zM588 1065q0 -38 23.5 -77t62.5 -58q58 22 92.5 71t34.5 103q0 49 -28.5 73.5t-65.5 24.5q-48 0 -83.5 -39.5t-35.5 -97.5z" /> -<glyph unicode="9" horiz-adv-x="1188" d="M106 10v314q92 -37 203 -37q187 0 291.5 87t144.5 281h-8q-59 -95 -132 -134.5t-169 -39.5q-151 0 -239 110t-88 296q0 176 65.5 310.5t190 210t297.5 75.5q230 0 352.5 -137.5t122.5 -393.5q0 -293 -103 -519.5t-285.5 -339.5t-431.5 -113q-115 0 -211 30zM502 932 q0 -144 92 -144q74 0 125 70.5t51 171.5q0 66 -27.5 106t-70.5 40q-73 0 -121.5 -71t-48.5 -173z" /> -<glyph unicode=":" horiz-adv-x="627" d="M0 127q0 109 65 171t179 62q84 0 132 -40t48 -115q0 -118 -60 -174t-190 -56q-78 0 -126 37t-48 115zM195 915q0 110 65 171t176 61q82 0 132 -37.5t50 -116.5q0 -119 -59 -175t-190 -56q-79 0 -126.5 37.5t-47.5 115.5z" /> -<glyph unicode=";" horiz-adv-x="627" d="M-117 -264q65 147 148 387l41 115h348l8 -23q-116 -262 -256 -479h-289zM195 915q0 110 65 171t176 61q82 0 132 -37.5t50 -116.5q0 -119 -59 -175t-190 -56q-79 0 -126.5 37.5t-47.5 115.5z" /> -<glyph unicode="<" horiz-adv-x="1159" d="M88 627v172l973 508v-299l-576 -283l576 -252v-297z" /> -<glyph unicode="=" horiz-adv-x="1159" d="M102 399v271h975v-271h-975zM102 774v266h975v-266h-975z" /> -<glyph unicode=">" horiz-adv-x="1159" d="M109 176v297l575 252l-575 283v299l972 -508v-172z" /> -<glyph unicode="?" horiz-adv-x="999" d="M162 1348q231 135 461 135q201 0 319.5 -90t118.5 -248q0 -89 -27.5 -156t-79 -120.5t-170.5 -125.5q-100 -60 -142.5 -100t-55.5 -84l-15 -43h-315l12 64q15 80 42 138t71 104t141 110q89 58 125.5 95t36.5 77q0 70 -90 70q-126 0 -313 -109zM176 127q0 107 65 170 t179 63q87 0 133.5 -40.5t46.5 -114.5q0 -110 -63.5 -170t-174.5 -60q-87 0 -136.5 39t-49.5 113z" /> -<glyph unicode="@" horiz-adv-x="1837" d="M82 500q0 288 117 511t335.5 347.5t485.5 124.5q355 0 554.5 -174t199.5 -482q0 -170 -69.5 -314t-191 -225t-266.5 -81q-170 0 -219 129h-10q-48 -65 -111.5 -97t-156.5 -32q-117 0 -191 83.5t-74 221.5q0 156 74 294.5t196.5 211t276.5 72.5q155 0 336 -70l-100 -414 q-23 -94 -23 -137q0 -41 39 -41q64 0 116 48.5t81.5 138.5t29.5 206q0 213 -133.5 322.5t-382.5 109.5q-187 0 -336.5 -91.5t-232 -258t-82.5 -379.5q0 -145 55 -254t153.5 -168t223.5 -59q103 0 234 24.5t245 69.5v-225q-90 -43 -223.5 -70.5t-251.5 -27.5 q-209 0 -367.5 83.5t-244.5 240t-86 362.5zM764 532q0 -104 78 -104q61 0 99.5 51.5t74.5 188.5l47 190q-23 10 -51 10q-73 0 -128.5 -47.5t-87.5 -127t-32 -161.5z" /> -<glyph unicode="A" horiz-adv-x="1384" d="M-121 0l744 1462h503l123 -1462h-381l-10 274h-448l-125 -274h-406zM553 586h293l-17 424l-2 86q0 75 4 131q-24 -86 -61 -166z" /> -<glyph unicode="B" horiz-adv-x="1298" d="M33 0l309 1462h487q217 0 329 -82.5t112 -236.5q0 -288 -297 -377v-8q88 -29 140 -101.5t52 -177.5q0 -229 -152.5 -354t-432.5 -125h-547zM489 305h82q86 0 143.5 48.5t57.5 121.5q0 69 -33 103t-116 34h-68zM614 901h72q88 0 133 38t45 122q0 102 -127 102h-63z" /> -<glyph unicode="C" horiz-adv-x="1290" d="M104 549q0 266 101.5 488t276 335t399.5 113q265 0 481 -131l-148 -305q-93 55 -171 82.5t-162 27.5q-108 0 -195 -78t-136.5 -215t-49.5 -297q0 -134 56 -200t161 -66q83 0 168 20.5t200 69.5v-323q-203 -90 -440 -90q-260 0 -400.5 148.5t-140.5 420.5z" /> -<glyph unicode="D" horiz-adv-x="1401" d="M33 0l309 1462h416q276 0 427.5 -144.5t151.5 -408.5q0 -280 -99 -485.5t-287.5 -314.5t-446.5 -109h-471zM494 324h69q110 0 196.5 70t134.5 199.5t48 295.5q0 125 -54 189.5t-151 64.5h-71z" /> -<glyph unicode="E" horiz-adv-x="1151" d="M33 0l309 1462h868l-65 -317h-477l-47 -230h444l-72 -317h-444l-57 -276h477l-68 -322h-868z" /> -<glyph unicode="F" horiz-adv-x="1165" d="M33 0l309 1462h862l-67 -317h-471l-58 -279h436l-69 -319h-438l-113 -547h-391z" /> -<glyph unicode="G" horiz-adv-x="1430" d="M104 563q0 267 110 482t301.5 327.5t445.5 112.5q266 0 448 -107l-147 -309q-153 90 -306 90q-132 0 -233.5 -72.5t-162 -214.5t-60.5 -303q0 -264 209 -264q63 0 133 14l51 232h-229l67 305h610l-167 -795q-250 -81 -521 -81q-261 0 -405 152t-144 431z" /> -<glyph unicode="H" horiz-adv-x="1462" d="M33 0l309 1462h391l-112 -542h348l112 542h392l-310 -1462h-391l125 596h-346l-127 -596h-391z" /> -<glyph unicode="I" horiz-adv-x="727" d="M31 0l309 1462h397l-309 -1462h-397z" /> -<glyph unicode="J" horiz-adv-x="764" d="M-328 -113q99 -24 174 -24q107 0 162 59t84 195l289 1345h391l-299 -1394q-43 -200 -113 -312.5t-182.5 -164.5t-292.5 -52q-106 0 -213 29v319z" /> -<glyph unicode="K" horiz-adv-x="1370" d="M33 0l309 1462h391l-135 -624l38 59q88 143 130 195l297 370h459l-551 -674l270 -788h-438l-174 578l-97 -56l-108 -522h-391z" /> -<glyph unicode="L" horiz-adv-x="1079" d="M33 0l309 1462h391l-241 -1143h477l-68 -319h-868z" /> -<glyph unicode="M" horiz-adv-x="1862" d="M33 0l309 1462h518v-1038h8l478 1038h526l-313 -1462h-351l117 549q50 228 108 436l15 64h-8l-482 -1049h-370v1049h-8q-67 -417 -86 -512l-113 -537h-348z" /> -<glyph unicode="N" horiz-adv-x="1618" d="M33 0l309 1462h455l286 -983h9q29 236 57 371l131 612h348l-309 -1462h-455l-289 1028h-8q-29 -291 -57 -418l-129 -610h-348z" /> -<glyph unicode="O" horiz-adv-x="1509" d="M104 543q0 265 103 487t280.5 338.5t409.5 116.5q260 0 404.5 -148.5t144.5 -414.5t-99.5 -486.5t-274.5 -338t-406 -117.5q-269 0 -415.5 149t-146.5 414zM500 545q0 -242 200 -242q95 0 176.5 83t128 224t46.5 308q0 114 -48 178.5t-139 64.5q-99 0 -182 -84 t-132.5 -231t-49.5 -301z" /> -<glyph unicode="P" horiz-adv-x="1276" d="M33 0l309 1462h373q259 0 397.5 -113.5t138.5 -324.5q0 -252 -171.5 -395.5t-469.5 -143.5h-86l-100 -485h-391zM594 805h63q91 0 147 58.5t56 148.5q0 59 -36 95t-99 36h-59z" /> -<glyph unicode="Q" horiz-adv-x="1509" d="M104 543q0 265 102.5 486t282 338.5t414.5 117.5q258 0 400.5 -149.5t142.5 -413.5q0 -280 -114 -509t-310 -339l238 -422h-439l-162 328h-12q-258 0 -400.5 149.5t-142.5 413.5zM500 539q0 -115 47.5 -172.5t134.5 -57.5q102 0 186.5 81t133.5 224.5t49 311.5 q0 114 -47 172.5t-134 58.5q-103 0 -188.5 -83t-133.5 -226t-48 -309z" /> -<glyph unicode="R" horiz-adv-x="1331" d="M33 0l309 1462h387q252 0 386 -100t134 -301q0 -156 -71 -272t-211 -177l224 -516l40 -96h-426l-195 532h-73l-113 -532h-391zM600 829h51q95 0 151 54.5t56 152.5q0 62 -34.5 94.5t-100.5 32.5h-53z" /> -<glyph unicode="S" horiz-adv-x="1122" d="M43 76v350q84 -53 192.5 -89t196.5 -36q74 0 112 31t38 88q0 27 -12 50.5t-34 47t-118 103.5q-117 94 -170 192t-53 215q0 131 65.5 235.5t185 162t267.5 57.5q239 0 430 -107l-135 -297q-171 88 -291 88q-64 0 -98.5 -28t-34.5 -82q0 -49 33.5 -91.5t127.5 -113.5 q118 -87 175 -183t57 -220q0 -222 -147 -345.5t-410 -123.5q-110 0 -208 24.5t-169 71.5z" /> -<glyph unicode="T" horiz-adv-x="1130" d="M156 1139l69 323h1028l-71 -323h-318l-237 -1139h-391l237 1139h-317z" /> -<glyph unicode="U" horiz-adv-x="1436" d="M125 410q0 64 12 129l199 923h391l-195 -913q-14 -68 -14 -115q0 -127 121 -127q94 0 147.5 64.5t81.5 197.5l191 893h391l-199 -932q-59 -281 -225 -415.5t-451 -134.5q-134 0 -236.5 55t-158 154t-55.5 221z" /> -<glyph unicode="V" horiz-adv-x="1264" d="M150 1462h382l27 -801v-51q0 -144 -16 -256h8q14 64 44.5 157.5t55.5 145.5l350 805h414l-725 -1462h-436z" /> -<glyph unicode="W" horiz-adv-x="1915" d="M152 1462h370l-10 -733q-6 -267 -25 -375l40 104l94 232l335 772h336v-792q0 -156 -26 -316q10 28 133 346l303 762h387l-635 -1462h-461v620q0 155 13 324q-33 -133 -118 -349l-253 -595h-434z" /> -<glyph unicode="X" horiz-adv-x="1358" d="M-125 0l563 776l-223 686h416l123 -469l309 469h448l-538 -725l262 -737h-432l-146 498l-338 -498h-444z" /> -<glyph unicode="Y" horiz-adv-x="1237" d="M164 1462h403l90 -542l312 542h436l-612 -895l-121 -567h-391l120 567z" /> -<glyph unicode="Z" horiz-adv-x="1104" d="M-92 0l47 242l690 901h-479l67 319h986l-52 -245l-700 -898h543l-68 -319h-1034z" /> -<glyph unicode="[" horiz-adv-x="737" d="M-53 -344l393 1847h530l-55 -254h-215l-285 -1339h215l-53 -254h-530zM182 -324zM491 1485z" /> -<glyph unicode="\" horiz-adv-x="956" d="M221 1483h309l248 -1503h-319z" /> -<glyph unicode="]" horiz-adv-x="737" d="M-133 -344l53 254h213l285 1339h-215l55 254h528l-393 -1847h-526zM65 -324zM533 1485z" /> -<glyph unicode="^" horiz-adv-x="1096" d="M-6 502l631 960h172l284 -960h-274l-156 569l-360 -569h-297z" /> -<glyph unicode="_" horiz-adv-x="922" d="M-184 -379l57 246h930l-58 -246h-929z" /> -<glyph unicode="`" horiz-adv-x="1135" d="M485 1548v21h396q29 -157 94 -303v-25h-236q-82 75 -152 159t-102 148z" /> -<glyph unicode="a" d="M84 412q0 179 73 365t184.5 281t246.5 95q84 0 148 -37.5t114 -122.5h8l53 140h310l-240 -1133h-309l10 123h-8q-56 -78 -121 -110.5t-147 -32.5q-158 0 -240 111.5t-82 320.5zM479 434q0 -143 86 -143q50 0 95.5 58.5t72.5 156.5t27 192q0 65 -20 104.5t-62 39.5 q-76 0 -137.5 -126.5t-61.5 -281.5z" /> -<glyph unicode="b" d="M23 0l329 1556h387l-49 -231q-38 -175 -90 -301h8q48 59 77.5 81.5t66.5 35t86 12.5q155 0 238 -111.5t83 -320.5q0 -178 -70.5 -362t-182.5 -281.5t-249 -97.5q-83 0 -145 32t-125 113h-8l-49 -125h-307zM485 434q0 -65 19 -104t59 -39q49 0 96 59t76 156t29 192 q0 144 -86 144q-50 0 -95 -57t-71.5 -154t-26.5 -197z" /> -<glyph unicode="c" horiz-adv-x="1032" d="M84 442q0 201 76.5 364.5t215 255t314.5 91.5q195 0 367 -80l-123 -287q-133 60 -225 60q-62 0 -115 -48t-87 -143.5t-34 -187.5q0 -91 30 -133.5t95 -42.5q72 0 139.5 23t143.5 63v-307q-80 -44 -168.5 -67t-206.5 -23q-199 0 -310.5 120.5t-111.5 341.5z" /> -<glyph unicode="d" horiz-adv-x="1237" d="M84 412q0 178 71.5 363t183.5 281.5t247 96.5q75 0 126 -30.5t111 -121.5h8l2 37q7 138 25 217l62 301h391l-330 -1556h-309l10 123h-8q-57 -79 -120 -111t-148 -32q-158 0 -240 111.5t-82 320.5zM479 434q0 -143 86 -143q50 0 95.5 58.5t72.5 156.5t27 192 q0 144 -80 144q-49 0 -96 -59t-76 -155.5t-29 -193.5z" /> -<glyph unicode="e" horiz-adv-x="1186" d="M84 428q0 211 83.5 380.5t229 257t336.5 87.5q190 0 299 -86t109 -229q0 -201 -156.5 -308.5t-452.5 -107.5h-59v-16q0 -148 164 -148q79 0 155 23.5t173 74.5v-274q-112 -57 -209 -79.5t-224 -22.5q-212 0 -330 118.5t-118 329.5zM512 664h29q109 0 171 41.5t62 109.5 q0 32 -20 54t-64 22q-61 0 -114 -69.5t-64 -157.5z" /> -<glyph unicode="f" horiz-adv-x="840" d="M-209 -162q63 -18 117 -18q74 0 112 30t52 95l190 897h-166l43 190l189 96l16 74q43 192 146.5 278.5t275.5 86.5q80 0 155 -16t128 -42l-99 -264q-64 31 -129 31q-35 0 -59.5 -18.5t-32.5 -53.5l-16 -71h211l-66 -291h-209l-205 -959q-43 -192 -153.5 -283.5 t-292.5 -91.5q-110 0 -207 27v303z" /> -<glyph unicode="g" horiz-adv-x="1145" d="M-133 -207q0 98 68 169t212 118q-37 23 -60.5 60t-23.5 79q0 71 51 126t152 101q-131 103 -131 281q0 196 136 311t368 115q51 0 107.5 -6t89.5 -14h399l-41 -207l-160 -52q10 -40 10 -94q0 -191 -130 -308.5t-339 -117.5q-76 0 -124 13q-20 -11 -34 -22t-14 -30 q0 -43 111 -59l137 -18q174 -25 250 -91.5t76 -189.5q0 -215 -168.5 -332t-478.5 -117q-212 0 -337.5 75.5t-125.5 209.5zM197 -152q0 -86 170 -86q125 0 190.5 29t65.5 82q0 36 -33 54.5t-115 27.5l-115 12q-78 -11 -120.5 -41.5t-42.5 -77.5zM500 692q0 -94 67 -94 q52 0 85.5 68.5t33.5 158.5q0 95 -61 95q-38 0 -66 -33.5t-43.5 -87.5t-15.5 -107z" /> -<glyph unicode="h" horiz-adv-x="1274" d="M23 0l329 1556h387l-53 -249q-35 -158 -88 -283h8q101 129 273 129q141 0 220 -85.5t79 -236.5q0 -106 -25 -229l-127 -602h-387l129 618q18 78 18 142q0 43 -22 64.5t-53 21.5q-125 0 -185 -293l-116 -553h-387z" /> -<glyph unicode="i" horiz-adv-x="666" d="M23 0l239 1133h389l-241 -1133h-387zM309 1382q0 103 59.5 156t166.5 53q91 0 140.5 -36.5t49.5 -104.5q0 -100 -58 -154.5t-167 -54.5q-191 0 -191 141z" /> -<glyph unicode="j" horiz-adv-x="666" d="M-264 -162q56 -18 112 -18q142 0 175 147l247 1166h387l-260 -1227q-40 -193 -157 -295.5t-297 -102.5q-110 0 -207 27v303zM317 1382q0 103 59.5 156t166.5 53q91 0 140.5 -36.5t49.5 -104.5q0 -94 -55 -151.5t-170 -57.5q-191 0 -191 141z" /> -<glyph unicode="k" horiz-adv-x="1264" d="M23 0l325 1556h387l-139 -663q-17 -77 -68 -223h9q84 127 153 200l242 263h442l-491 -512l274 -621h-438l-139 391l-101 -53l-69 -338h-387z" /> -<glyph unicode="l" horiz-adv-x="666" d="M23 0l329 1556h387l-329 -1556h-387z" /> -<glyph unicode="m" horiz-adv-x="1896" d="M23 0l239 1133h309l-16 -187h8q61 114 137 160.5t191 46.5q117 0 180.5 -53.5t89.5 -153.5h8q65 106 149 156.5t195 50.5q141 0 214 -84.5t73 -249.5q0 -97 -22 -205l-125 -614h-387l129 631q14 56 14 133q0 40 -19 61t-51 21q-74 0 -119.5 -76t-76.5 -227l-111 -543 h-387l131 631q15 90 15 121q0 94 -72 94q-68 0 -113.5 -74.5t-77.5 -220.5l-118 -551h-387z" /> -<glyph unicode="n" horiz-adv-x="1274" d="M23 0l239 1133h309l-12 -158h8q55 95 129.5 136.5t182.5 41.5q141 0 220 -85.5t79 -236.5q0 -106 -25 -229l-127 -602h-387l129 618q18 78 18 142q0 43 -22 64.5t-53 21.5q-57 0 -105.5 -71t-79.5 -222l-116 -553h-387z" /> -<glyph unicode="o" d="M84 416q0 210 79.5 379.5t223.5 263.5t336 94q209 0 322.5 -113t113.5 -323t-79.5 -379.5t-223.5 -263.5t-336 -94q-209 0 -322.5 113t-113.5 323zM479 403q0 -133 84 -133q81 0 141 139t60 320q0 66 -23 99.5t-63 33.5q-82 0 -140.5 -139.5t-58.5 -319.5z" /> -<glyph unicode="p" d="M-82 -492l344 1625h309l-12 -127h8q96 147 258 147q156 0 245 -111.5t89 -306.5q0 -203 -70 -382.5t-185.5 -276t-252.5 -96.5q-143 0 -231 145h-8q-12 -166 -56 -371l-51 -246h-387zM485 434q0 -65 23 -104t65 -39q48 0 92 57t71.5 153t27.5 197q0 144 -86 144 q-50 0 -95 -57t-71.5 -154t-26.5 -197z" /> -<glyph unicode="q" d="M84 408q0 181 71.5 366.5t183 282t247.5 96.5q89 0 145.5 -33t118.5 -127h8l53 140h310l-344 -1625h-392l68 293q25 116 90 310h-8q-55 -74 -114 -102.5t-134 -28.5q-89 0 -158 50.5t-107 148t-38 229.5zM479 434q0 -143 86 -143q50 0 95.5 58.5t72.5 156.5t27 192 q0 144 -80 144q-49 0 -96 -59t-76 -155.5t-29 -193.5z" /> -<glyph unicode="r" horiz-adv-x="895" d="M23 0l239 1133h309l-18 -189h8q65 112 141 160.5t199 48.5q56 0 80 -8l-84 -383q-54 22 -123 22q-103 0 -164.5 -70.5t-93.5 -215.5l-106 -498h-387z" /> -<glyph unicode="s" horiz-adv-x="1028" d="M31 43v311q92 -50 171 -70t160 -20q68 0 102 18.5t34 51.5q0 35 -26 60.5t-130 84.5q-106 58 -154.5 133t-48.5 183q0 172 121 265t344 93q112 0 204 -26t179 -80l-121 -252q-66 43 -136.5 68.5t-121.5 25.5q-76 0 -76 -68q0 -29 31.5 -51t102.5 -57q225 -112 225 -320 q0 -199 -130 -306t-374 -107q-222 0 -356 63z" /> -<glyph unicode="t" horiz-adv-x="936" d="M63 842l41 190l218 88l137 240h258l-49 -227h288l-63 -291h-289l-84 -383q-16 -77 -16 -105q0 -63 63 -63q66 0 183 47v-291q-136 -67 -340 -67q-148 0 -224.5 63.5t-76.5 208.5q0 76 24 188l84 402h-154z" /> -<glyph unicode="u" horiz-adv-x="1274" d="M96 301q0 106 25 229l127 603h387l-129 -617q-19 -82 -19 -141q0 -44 22.5 -65t53.5 -21q59 0 107.5 78.5t77.5 214.5l116 551h387l-239 -1133h-310l13 158h-8q-54 -93 -128.5 -135.5t-183.5 -42.5q-141 0 -220 85.5t-79 235.5z" /> -<glyph unicode="v" horiz-adv-x="1114" d="M88 1133h385l27 -603q0 -73 -8 -118h8q1 14 18 63t36 90t265 568h414l-612 -1133h-388z" /> -<glyph unicode="w" horiz-adv-x="1686" d="M102 1133h365v-512q0 -182 -8 -259h8q46 177 88 295l172 476h428l-20 -476q-9 -129 -33 -295h8q7 22 15.5 47.5t48.5 140t241 583.5h385l-538 -1133h-422l20 449q2 73 11.5 209t21.5 219h-8q-60 -233 -121 -390l-189 -487h-407z" /> -<glyph unicode="x" horiz-adv-x="1159" d="M-119 0l473 578l-207 555h422l76 -314l186 314h459l-465 -576l228 -557h-428l-80 328l-211 -328h-453z" /> -<glyph unicode="y" horiz-adv-x="1114" d="M-129 -168q46 -12 109 -12q87 0 142.5 36.5t98.5 114.5l23 41l-162 1121h389l43 -562l2 -62v-87h8q37 132 50 165.5t239 545.5h416l-670 -1276q-96 -185 -223 -267t-311 -82q-92 0 -154 17v307z" /> -<glyph unicode="z" horiz-adv-x="993" d="M-41 0l43 221l502 613h-348l67 299h811l-53 -242l-496 -592h383l-65 -299h-844z" /> -<glyph unicode="{" horiz-adv-x="735" d="M-16 434l53 287q119 0 175 38.5t77 133.5l55 246q28 124 76.5 190t130 99.5t203.5 33.5h129l-62 -280q-81 -2 -120 -29.5t-56 -99.5l-53 -258q-20 -96 -85.5 -151.5t-193.5 -70.5v-8q90 -29 130 -87t40 -146q0 -17 -10 -74l-35 -164q-6 -30 -6 -49q0 -88 113 -88v-281 h-82q-183 0 -272 68.5t-89 208.5q0 63 15 127l37 174q6 24 6 43q0 75 -42 106t-134 31z" /> -<glyph unicode="|" horiz-adv-x="1159" d="M442 -465v2013h271v-2013h-271z" /> -<glyph unicode="}" horiz-adv-x="735" d="M-123 -43q73 3 109 13.5t54 33.5t30 82l53 258q21 99 88 154t190 67v8q-170 55 -170 234q0 12 11 74l34 163q7 29 7 50q0 88 -136 88l54 280h61q168 0 259 -70.5t91 -203.5q0 -69 -14 -129l-37 -174q-6 -26 -6 -43q0 -66 44.5 -100.5t148.5 -34.5l-58 -287 q-121 0 -182.5 -40.5t-81.5 -133.5l-55 -246q-37 -171 -137.5 -247.5t-282.5 -76.5h-74v281z" /> -<glyph unicode="~" horiz-adv-x="1159" d="M96 524v285q107 109 262 109q61 0 110.5 -11.5t152.5 -52.5q67 -28 114 -41.5t99 -13.5q51 0 115.5 32t121.5 89v-285q-107 -109 -262 -109q-62 0 -113.5 12.5t-148.5 51.5q-75 31 -118.5 43t-92.5 12q-52 0 -114.5 -30t-125.5 -91z" /> -<glyph unicode="¡" horiz-adv-x="623" d="M-109 -338l254 946h328l-156 -946h-426zM107 -324zM162 924q0 109 64 169t173 60q89 0 138 -39.5t49 -112.5q0 -107 -65 -170t-179 -63q-87 0 -133.5 40.5t-46.5 115.5z" /> -<glyph unicode="¢" horiz-adv-x="1188" d="M154 586q0 306 140.5 510t371.5 239l32 148h230l-33 -150q122 -19 231 -76l-122 -286q-79 37 -128 48t-98 11q-63 0 -115 -49.5t-84 -146.5t-32 -207q0 -79 31 -113.5t90 -34.5q72 0 140 25t142 65v-311q-145 -78 -307 -90l-41 -188h-229l51 208q-270 74 -270 398z" /> -<glyph unicode="£" horiz-adv-x="1188" d="M-18 0l63 313q76 21 120.5 49t69 69.5t41.5 123.5l21 96h-188l57 279h188l23 129q26 149 85 243t150.5 137.5t237.5 43.5q89 0 177 -19t196 -67l-144 -299q-66 31 -114 47t-99 16q-35 0 -56.5 -24.5t-35.5 -92.5l-24 -114h251l-57 -279h-252l-20 -94 q-16 -74 -69.5 -133.5t-133.5 -93.5h604l-72 -330h-1019z" /> -<glyph unicode="¤" horiz-adv-x="1188" d="M106 1032l185 185l127 -125q96 43 182 43q96 0 184 -48l125 130l189 -179l-129 -129q43 -82 43 -186q0 -94 -43 -186l123 -123l-183 -183l-125 123q-96 -41 -184 -41q-108 0 -186 39l-123 -119l-182 183l127 123q-46 90 -46 184q0 92 46 184zM451 723q0 -64 43 -108 t106 -44q65 0 110.5 44.5t45.5 107.5q0 61 -44.5 106t-111.5 45q-64 0 -106.5 -44t-42.5 -107z" /> -<glyph unicode="¥" horiz-adv-x="1188" d="M76 190l43 205h227l25 129h-226l45 205h179l-187 733h385l72 -487l293 487h393l-489 -733h184l-45 -205h-223l-27 -129h223l-43 -205h-223l-41 -190h-379l41 190h-227z" /> -<glyph unicode="¦" horiz-adv-x="1159" d="M444 395h271v-839h-271v839zM444 705v841h271v-841h-271z" /> -<glyph unicode="§" horiz-adv-x="1036" d="M37 70v249q85 -52 173 -86t185 -34q69 0 109.5 28.5t40.5 75.5q0 38 -31 70.5t-104 72.5q-130 71 -191 152t-61 178q0 84 46 156t132 125q-38 38 -59 89.5t-21 102.5q0 160 116 244t339 84q184 0 360 -102l-100 -224q-91 58 -159.5 79.5t-133.5 21.5q-60 0 -85.5 -22.5 t-25.5 -51.5q0 -33 14 -53.5t46.5 -43t89.5 -48.5q244 -113 244 -312q0 -99 -38 -171t-130 -124q32 -38 50.5 -90.5t18.5 -109.5q0 -170 -127 -260.5t-358 -90.5q-110 0 -197 25.5t-143 69.5zM442 817q0 -43 37 -84t125 -90q74 51 74 127q0 54 -36.5 95t-117.5 75 q-37 -19 -59.5 -54t-22.5 -69z" /> -<glyph unicode="¨" horiz-adv-x="1135" d="M336 1384q0 187 201 187q170 0 170 -125q0 -189 -201 -189q-88 0 -129 31t-41 96zM823 1384q0 187 201 187q168 0 168 -125q0 -97 -49.5 -143t-149.5 -46q-88 0 -129 31t-41 96z" /> -<glyph unicode="©" horiz-adv-x="1688" d="M113 731q0 202 101.5 378t275.5 275t374 99t375 -100t276 -275t101 -377q0 -197 -97 -370t-272 -277t-383 -104q-206 0 -380 102.5t-272.5 276.5t-98.5 372zM276 731q0 -158 78.5 -294t215 -215t294.5 -79q157 0 293 77.5t215.5 214t79.5 296.5q0 158 -78.5 294.5 t-215 215t-294.5 78.5t-295.5 -79.5t-215 -215.5t-77.5 -293zM461 735q0 220 113.5 341.5t320.5 121.5q166 0 332 -82l-92 -205q-114 60 -222 60q-80 0 -126 -61t-46 -179q0 -128 44 -185t135 -57q138 0 258 68v-231q-126 -64 -273 -64q-213 0 -328.5 125t-115.5 348z" /> -<glyph unicode="ª" horiz-adv-x="827" d="M139 1001q0 120 45 232t123 177t176 65q64 0 111.5 -20t101.5 -79h9l36 86h199l-170 -721h-195l9 86h-9q-89 -98 -223 -98q-60 0 -108 31.5t-76.5 91.5t-28.5 149zM412 1012q0 -48 19 -74.5t50 -26.5q46 0 79 38.5t51 100t18 128.5q0 53 -19.5 83.5t-52.5 30.5 q-39 0 -72.5 -40.5t-53 -107.5t-19.5 -132z" /> -<glyph unicode="«" horiz-adv-x="1276" d="M61 553v10l408 518l264 -204l-266 -334l111 -330l-334 -137zM608 582v10l424 495l260 -210l-278 -306l123 -358l-334 -137z" /> -<glyph unicode="¬" horiz-adv-x="1159" d="M82 586v272h975v-620h-271v348h-704z" /> -<glyph unicode="­" horiz-adv-x="674" d="M23 393l63 312h553l-64 -312h-552z" /> -<glyph unicode="®" horiz-adv-x="1688" d="M113 731q0 202 101.5 378t275.5 275t374 99t375 -100t276 -275t101 -377q0 -197 -97 -370t-272 -277t-383 -104q-206 0 -380 102.5t-272.5 276.5t-98.5 372zM276 731q0 -158 78.5 -294t215 -215t294.5 -79q157 0 293 77.5t215.5 214t79.5 296.5q0 158 -78.5 294.5 t-215 215t-294.5 78.5t-295.5 -79.5t-215 -215.5t-77.5 -293zM535 313v875h290q214 0 317 -70.5t103 -199.5q0 -91 -44.5 -153t-139.5 -97l211 -355h-285l-160 320h-12v-320h-280zM815 809h10q78 0 108 22t30 76t-35.5 70t-104.5 16h-8v-184z" /> -<glyph unicode="¯" horiz-adv-x="922" d="M183 1554l57 246h930l-58 -246h-929z" /> -<glyph unicode="°" horiz-adv-x="864" d="M166 1114q0 97 49 182.5t135 136t185 50.5q98 0 184 -50t135 -136.5t49 -182.5q0 -98 -49.5 -183t-135.5 -133t-183 -48q-99 0 -185 49t-135 133t-49 182zM403 1114q0 -51 39.5 -89t92.5 -38q52 0 91.5 38t39.5 89q0 53 -38.5 93t-92.5 40q-55 0 -93.5 -39.5t-38.5 -93.5 z" /> -<glyph unicode="±" horiz-adv-x="1159" d="M102 0v270h975v-270h-975zM102 694v271h353v352h270v-352h352v-271h-352v-350h-270v350h-353z" /> -<glyph unicode="²" horiz-adv-x="848" d="M23 584l43 204l276 211q108 83 144 124t36 75q0 51 -63 51q-35 0 -85 -18t-104 -62l-118 191q84 65 172.5 94t216.5 29q134 0 218.5 -61t84.5 -156q0 -70 -31.5 -129.5t-102 -121t-251.5 -175.5h319l-51 -256h-704z" /> -<glyph unicode="³" horiz-adv-x="848" d="M66 639v225q63 -43 131.5 -62.5t124.5 -19.5q151 0 151 80q0 68 -113 68h-120l43 194h96q71 0 114.5 21.5t43.5 66.5q0 28 -22 43t-54 15q-79 0 -185 -66l-100 182q83 52 161 73.5t181 21.5q137 0 220 -57t83 -152q0 -91 -55.5 -146t-175.5 -84v-8q92 -23 129 -69.5 t37 -112.5q0 -127 -104 -205t-275 -78q-106 0 -177.5 16t-133.5 54z" /> -<glyph unicode="´" horiz-adv-x="1135" d="M453 1241v23q123 102 282 305h439v-15q-45 -54 -191.5 -157t-245.5 -156h-284z" /> -<glyph unicode="µ" horiz-adv-x="1288" d="M-82 -492l344 1625h387l-129 -617q-18 -78 -18 -141q0 -44 22.5 -65t53.5 -21q52 0 82.5 26t53.5 87t48 180l117 551h387l-240 -1133h-289l6 123h-8q-68 -143 -190 -143q-102 0 -131 77h-8q-10 -134 -48 -303l-53 -246h-387z" /> -<glyph unicode="¶" horiz-adv-x="1317" d="M102 1042q0 256 107.5 385t343.5 129h633v-1816h-191v1587h-157v-1587h-191v819q-54 -18 -125 -18q-216 0 -318 125t-102 376z" /> -<glyph unicode="·" horiz-adv-x="627" d="M115 684q0 106 65 168.5t178 62.5q82 0 131.5 -40.5t49.5 -114.5q0 -117 -65.5 -173.5t-178.5 -56.5q-86 0 -133 40t-47 114z" /> -<glyph unicode="¸" horiz-adv-x="383" d="M-221 -258q30 -9 78.5 -18t72.5 -9q68 0 68 49q0 73 -145 101l75 135h205l-24 -41q178 -37 178 -195q0 -121 -82.5 -188.5t-233.5 -67.5q-115 0 -192 29v205z" /> -<glyph unicode="¹" horiz-adv-x="848" d="M115 1202l426 260h252l-187 -878h-317l82 364q21 102 55 207l-74 -59l-119 -78z" /> -<glyph unicode="º" horiz-adv-x="817" d="M139 1004q0 213 116.5 344t317.5 131q143 0 222 -79t79 -218q0 -134 -51 -237t-149.5 -160.5t-231.5 -57.5q-144 0 -223.5 75.5t-79.5 201.5zM412 1016q0 -84 55 -84q59 0 97 70.5t38 179.5q0 45 -11.5 68.5t-43.5 23.5q-60 0 -97.5 -73t-37.5 -185z" /> -<glyph unicode="»" horiz-adv-x="1276" d="M-14 248l276 305l-121 358l332 138l195 -506v-11l-424 -497zM543 248l266 334l-111 329l334 138l182 -478v-10l-407 -518z" /> -<glyph unicode="¼" horiz-adv-x="1991" d="M921 122l31 178l490 577h325l-119 -557h113l-41 -198h-113l-26 -123h-289l27 123h-398zM1198 320h162q62 239 73 274t15 44q-13 -18 -35 -48.5t-215 -269.5zM195 0l1089 1462h291l-1083 -1462h-297zM79 1202l426 260h252l-187 -878h-317l82 364q21 102 55 207l-74 -59 l-119 -78z" /> -<glyph unicode="½" horiz-adv-x="1991" d="M1002 -1l43 204l276 211q108 83 144 124t36 75q0 51 -63 51q-35 0 -85 -18t-104 -62l-118 191q84 65 172.5 94t216.5 29q134 0 218.5 -61t84.5 -156q0 -70 -31.5 -129.5t-102 -121t-251.5 -175.5h319l-51 -256h-704zM104 1202l426 260h252l-187 -878h-317l82 364 q21 102 55 207l-74 -59l-119 -78zM219 0l1089 1462h291l-1083 -1462h-297z" /> -<glyph unicode="¾" horiz-adv-x="1991" d="M968 122l31 178l490 577h325l-119 -557h113l-41 -198h-113l-26 -123h-289l27 123h-398zM1245 320h162q62 239 73 274t15 44q-13 -18 -35 -48.5t-215 -269.5zM195 639v225q63 -43 131.5 -62.5t124.5 -19.5q151 0 151 80q0 68 -113 68h-120l43 194h96q71 0 114.5 21.5 t43.5 66.5q0 28 -22 43t-54 15q-79 0 -185 -66l-100 182q83 52 161 73.5t181 21.5q137 0 220 -57t83 -152q0 -91 -55.5 -146t-175.5 -84v-8q92 -23 129 -69.5t37 -112.5q0 -127 -104 -205t-275 -78q-106 0 -177.5 16t-133.5 54zM363 0l1089 1462h291l-1083 -1462h-297z" /> -<glyph unicode="¿" horiz-adv-x="999" d="M-84 -16q0 89 27.5 155.5t77.5 119t172 126.5q100 60 142.5 101t55.5 83l15 43h315l-12 -63q-15 -82 -43 -140t-72.5 -104.5t-138.5 -107.5q-89 -58 -125.5 -95t-36.5 -77q0 -37 22.5 -53.5t67.5 -16.5q124 0 313 108l119 -282q-227 -135 -461 -135q-201 0 -319.5 90 t-118.5 248zM285 -324zM377 924q0 109 64 169t173 60q89 0 138 -39.5t49 -112.5q0 -107 -65 -170t-179 -63q-87 0 -133.5 40.5t-46.5 115.5z" /> -<glyph unicode="À" horiz-adv-x="1384" d="M-121 0l744 1462h503l123 -1462h-381l-10 274h-448l-125 -274h-406zM553 586h293l-17 424l-2 86q0 75 4 131q-24 -86 -61 -166zM551 1886v21h396q29 -157 94 -303v-25h-236q-82 75 -152 159t-102 148z" /> -<glyph unicode="Á" horiz-adv-x="1384" d="M-121 0l744 1462h503l123 -1462h-381l-10 274h-448l-125 -274h-406zM553 586h293l-17 424l-2 86q0 75 4 131q-24 -86 -61 -166zM709 1579v23q123 102 282 305h439v-15q-45 -54 -191.5 -157t-245.5 -156h-284z" /> -<glyph unicode="Â" horiz-adv-x="1384" d="M-121 0l744 1462h503l123 -1462h-381l-10 274h-448l-125 -274h-406zM553 586h293l-17 424l-2 86q0 75 4 131q-24 -86 -61 -166zM399 1579v23q79 72 170 162.5t139 142.5h447q26 -59 78 -149.5t102 -155.5v-23h-266q-46 41 -156 174q-140 -110 -240 -174h-274z" /> -<glyph unicode="Ã" horiz-adv-x="1384" d="M-121 0l744 1462h503l123 -1462h-381l-10 274h-448l-125 -274h-406zM553 586h293l-17 424l-2 86q0 75 4 131q-24 -86 -61 -166zM459 1575q32 172 108.5 257t204.5 85q34 0 59.5 -6.5t94.5 -42.5q31 -17 66 -33t67 -16q78 0 115 100h190q-34 -172 -112.5 -257t-208.5 -85 q-33 0 -65 8t-61 22t-46 23q-73 45 -127 45q-31 0 -60.5 -27t-36.5 -73h-188z" /> -<glyph unicode="Ä" horiz-adv-x="1384" d="M-121 0l744 1462h503l123 -1462h-381l-10 274h-448l-125 -274h-406zM553 586h293l-17 424l-2 86q0 75 4 131q-24 -86 -61 -166zM502 1722q0 187 201 187q170 0 170 -125q0 -189 -201 -189q-88 0 -129 31t-41 96zM989 1722q0 187 201 187q168 0 168 -125q0 -97 -49.5 -143 t-149.5 -46q-88 0 -129 31t-41 96z" /> -<glyph unicode="Å" horiz-adv-x="1384" d="M-121 0l744 1462h503l123 -1462h-381l-10 274h-448l-125 -274h-406zM553 586h293l-17 424l-2 86q0 75 4 131q-24 -86 -61 -166zM608 1550q0 114 73.5 184t195.5 70q118 0 193 -70.5t75 -181.5q0 -113 -74.5 -183.5t-193.5 -70.5q-121 0 -195 68.5t-74 183.5zM788 1550 q0 -37 23.5 -60.5t65.5 -23.5q39 0 63.5 25t24.5 59q0 38 -26.5 62t-61.5 24q-36 0 -62.5 -24t-26.5 -62z" /> -<glyph unicode="Æ" horiz-adv-x="1937" d="M-125 0l909 1462h1213l-66 -317h-477l-47 -230h444l-71 -317h-445l-57 -276h477l-67 -322h-869l58 274h-418l-170 -274h-414zM662 602h286l113 543h-68z" /> -<glyph unicode="Ç" horiz-adv-x="1290" d="M104 549q0 266 101.5 488t276 335t399.5 113q265 0 481 -131l-148 -305q-93 55 -171 82.5t-162 27.5q-108 0 -195 -78t-136.5 -215t-49.5 -297q0 -134 56 -200t161 -66q83 0 168 20.5t200 69.5v-323q-203 -90 -440 -90q-260 0 -400.5 148.5t-140.5 420.5zM305 -258 q30 -9 78.5 -18t72.5 -9q68 0 68 49q0 73 -145 101l75 135h205l-24 -41q178 -37 178 -195q0 -121 -82.5 -188.5t-233.5 -67.5q-115 0 -192 29v205z" /> -<glyph unicode="È" horiz-adv-x="1151" d="M33 0l309 1462h868l-65 -317h-477l-47 -230h444l-72 -317h-444l-57 -276h477l-68 -322h-868zM443 1886v21h396q29 -157 94 -303v-25h-236q-82 75 -152 159t-102 148z" /> -<glyph unicode="É" horiz-adv-x="1151" d="M33 0l309 1462h868l-65 -317h-477l-47 -230h444l-72 -317h-444l-57 -276h477l-68 -322h-868zM578 1579v23q123 102 282 305h439v-15q-45 -54 -191.5 -157t-245.5 -156h-284z" /> -<glyph unicode="Ê" horiz-adv-x="1151" d="M33 0l309 1462h868l-65 -317h-477l-47 -230h444l-72 -317h-444l-57 -276h477l-68 -322h-868zM303 1579v23q79 72 170 162.5t139 142.5h447q26 -59 78 -149.5t102 -155.5v-23h-266q-46 41 -156 174q-140 -110 -240 -174h-274z" /> -<glyph unicode="Ë" horiz-adv-x="1151" d="M33 0l309 1462h868l-65 -317h-477l-47 -230h444l-72 -317h-444l-57 -276h477l-68 -322h-868zM383 1722q0 187 201 187q170 0 170 -125q0 -189 -201 -189q-88 0 -129 31t-41 96zM870 1722q0 187 201 187q168 0 168 -125q0 -97 -49.5 -143t-149.5 -46q-88 0 -129 31t-41 96 z" /> -<glyph unicode="Ì" horiz-adv-x="727" d="M31 0l309 1462h397l-309 -1462h-397zM259 1886v21h396q29 -157 94 -303v-25h-236q-82 75 -152 159t-102 148z" /> -<glyph unicode="Í" horiz-adv-x="727" d="M31 0l309 1462h397l-309 -1462h-397zM345 1579v23q123 102 282 305h439v-15q-45 -54 -191.5 -157t-245.5 -156h-284z" /> -<glyph unicode="Î" horiz-adv-x="727" d="M31 0l309 1462h397l-309 -1462h-397zM79 1579v23q79 72 170 162.5t139 142.5h447q26 -59 78 -149.5t102 -155.5v-23h-266q-46 41 -156 174q-140 -110 -240 -174h-274z" /> -<glyph unicode="Ï" horiz-adv-x="727" d="M31 0l309 1462h397l-309 -1462h-397zM159 1722q0 187 201 187q170 0 170 -125q0 -189 -201 -189q-88 0 -129 31t-41 96zM646 1722q0 187 201 187q168 0 168 -125q0 -97 -49.5 -143t-149.5 -46q-88 0 -129 31t-41 96z" /> -<glyph unicode="Ð" horiz-adv-x="1401" d="M10 563l70 320h139l123 579h430q271 0 418 -143.5t147 -409.5q0 -434 -213 -671.5t-598 -237.5h-493l119 563h-142zM494 324h69q111 0 198 71.5t134 204t47 301.5q0 116 -54 179t-151 63h-71l-56 -260h178l-69 -320h-176z" /> -<glyph unicode="Ñ" horiz-adv-x="1618" d="M33 0l309 1462h455l286 -983h9q29 236 57 371l131 612h348l-309 -1462h-455l-289 1028h-8q-29 -291 -57 -418l-129 -610h-348zM553 1575q32 172 108.5 257t204.5 85q34 0 59.5 -6.5t94.5 -42.5q31 -17 66 -33t67 -16q78 0 115 100h190q-34 -172 -112.5 -257t-208.5 -85 q-33 0 -65 8t-61 22t-46 23q-73 45 -127 45q-31 0 -60.5 -27t-36.5 -73h-188z" /> -<glyph unicode="Ò" horiz-adv-x="1509" d="M104 543q0 265 103 487t280.5 338.5t409.5 116.5q260 0 404.5 -148.5t144.5 -414.5t-99.5 -486.5t-274.5 -338t-406 -117.5q-269 0 -415.5 149t-146.5 414zM500 545q0 -242 200 -242q95 0 176.5 83t128 224t46.5 308q0 114 -48 178.5t-139 64.5q-99 0 -182 -84 t-132.5 -231t-49.5 -301zM612 1886v21h396q29 -157 94 -303v-25h-236q-82 75 -152 159t-102 148z" /> -<glyph unicode="Ó" horiz-adv-x="1509" d="M104 543q0 265 103 487t280.5 338.5t409.5 116.5q260 0 404.5 -148.5t144.5 -414.5t-99.5 -486.5t-274.5 -338t-406 -117.5q-269 0 -415.5 149t-146.5 414zM500 545q0 -242 200 -242q95 0 176.5 83t128 224t46.5 308q0 114 -48 178.5t-139 64.5q-99 0 -182 -84 t-132.5 -231t-49.5 -301zM717 1579v23q123 102 282 305h439v-15q-45 -54 -191.5 -157t-245.5 -156h-284z" /> -<glyph unicode="Ô" horiz-adv-x="1509" d="M104 543q0 265 103 487t280.5 338.5t409.5 116.5q260 0 404.5 -148.5t144.5 -414.5t-99.5 -486.5t-274.5 -338t-406 -117.5q-269 0 -415.5 149t-146.5 414zM500 545q0 -242 200 -242q95 0 176.5 83t128 224t46.5 308q0 114 -48 178.5t-139 64.5q-99 0 -182 -84 t-132.5 -231t-49.5 -301zM432 1579v23q79 72 170 162.5t139 142.5h447q26 -59 78 -149.5t102 -155.5v-23h-266q-46 41 -156 174q-140 -110 -240 -174h-274z" /> -<glyph unicode="Õ" horiz-adv-x="1509" d="M104 543q0 265 103 487t280.5 338.5t409.5 116.5q260 0 404.5 -148.5t144.5 -414.5t-99.5 -486.5t-274.5 -338t-406 -117.5q-269 0 -415.5 149t-146.5 414zM500 545q0 -242 200 -242q95 0 176.5 83t128 224t46.5 308q0 114 -48 178.5t-139 64.5q-99 0 -182 -84 t-132.5 -231t-49.5 -301zM489 1575q32 172 108.5 257t204.5 85q34 0 59.5 -6.5t94.5 -42.5q31 -17 66 -33t67 -16q78 0 115 100h190q-34 -172 -112.5 -257t-208.5 -85q-33 0 -65 8t-61 22t-46 23q-73 45 -127 45q-31 0 -60.5 -27t-36.5 -73h-188z" /> -<glyph unicode="Ö" horiz-adv-x="1509" d="M104 543q0 265 103 487t280.5 338.5t409.5 116.5q260 0 404.5 -148.5t144.5 -414.5t-99.5 -486.5t-274.5 -338t-406 -117.5q-269 0 -415.5 149t-146.5 414zM500 545q0 -242 200 -242q95 0 176.5 83t128 224t46.5 308q0 114 -48 178.5t-139 64.5q-99 0 -182 -84 t-132.5 -231t-49.5 -301zM512 1722q0 187 201 187q170 0 170 -125q0 -189 -201 -189q-88 0 -129 31t-41 96zM999 1722q0 187 201 187q168 0 168 -125q0 -97 -49.5 -143t-149.5 -46q-88 0 -129 31t-41 96z" /> -<glyph unicode="×" horiz-adv-x="1159" d="M102 1010l187 190l289 -285l292 285l191 -184l-293 -293l287 -291l-185 -188l-292 288l-289 -286l-185 188l283 289z" /> -<glyph unicode="Ø" horiz-adv-x="1509" d="M94 31l117 145q-107 141 -107 367q0 262 101 484.5t275.5 340t398.5 117.5q182 0 315 -72l92 115l156 -119l-99 -125q103 -143 103 -362q0 -258 -98.5 -480.5t-271 -342t-392.5 -119.5q-192 0 -324 69l-106 -135zM500 539l467 589q-45 33 -115 33q-94 0 -175 -82 t-129 -224t-48 -306v-10zM586 332q46 -29 114 -29q95 0 176 81.5t128 222.5t47 308z" /> -<glyph unicode="Ù" horiz-adv-x="1436" d="M125 410q0 64 12 129l199 923h391l-195 -913q-14 -68 -14 -115q0 -127 121 -127q94 0 147.5 64.5t81.5 197.5l191 893h391l-199 -932q-59 -281 -225 -415.5t-451 -134.5q-134 0 -236.5 55t-158 154t-55.5 221zM555 1886v21h396q29 -157 94 -303v-25h-236q-82 75 -152 159 t-102 148z" /> -<glyph unicode="Ú" horiz-adv-x="1436" d="M125 410q0 64 12 129l199 923h391l-195 -913q-14 -68 -14 -115q0 -127 121 -127q94 0 147.5 64.5t81.5 197.5l191 893h391l-199 -932q-59 -281 -225 -415.5t-451 -134.5q-134 0 -236.5 55t-158 154t-55.5 221zM725 1579v23q123 102 282 305h439v-15q-45 -54 -191.5 -157 t-245.5 -156h-284z" /> -<glyph unicode="Û" horiz-adv-x="1436" d="M125 410q0 64 12 129l199 923h391l-195 -913q-14 -68 -14 -115q0 -127 121 -127q94 0 147.5 64.5t81.5 197.5l191 893h391l-199 -932q-59 -281 -225 -415.5t-451 -134.5q-134 0 -236.5 55t-158 154t-55.5 221zM440 1579v23q79 72 170 162.5t139 142.5h447 q26 -59 78 -149.5t102 -155.5v-23h-266q-46 41 -156 174q-140 -110 -240 -174h-274z" /> -<glyph unicode="Ü" horiz-adv-x="1436" d="M125 410q0 64 12 129l199 923h391l-195 -913q-14 -68 -14 -115q0 -127 121 -127q94 0 147.5 64.5t81.5 197.5l191 893h391l-199 -932q-59 -281 -225 -415.5t-451 -134.5q-134 0 -236.5 55t-158 154t-55.5 221zM533 1722q0 187 201 187q170 0 170 -125q0 -189 -201 -189 q-88 0 -129 31t-41 96zM1020 1722q0 187 201 187q168 0 168 -125q0 -97 -49.5 -143t-149.5 -46q-88 0 -129 31t-41 96z" /> -<glyph unicode="Ý" horiz-adv-x="1237" d="M164 1462h403l90 -542l312 542h436l-612 -895l-121 -567h-391l120 567zM615 1579v23q123 102 282 305h439v-15q-45 -54 -191.5 -157t-245.5 -156h-284z" /> -<glyph unicode="Þ" horiz-adv-x="1276" d="M33 0l309 1462h391l-45 -211q251 0 385.5 -114t134.5 -326q0 -250 -170.5 -393.5t-470.5 -143.5h-86l-57 -274h-391zM551 594h63q94 0 148.5 49t54.5 156q0 58 -41.5 95.5t-107.5 37.5h-45z" /> -<glyph unicode="ß" horiz-adv-x="1460" d="M-260 -162q63 -18 117 -18q74 0 111.5 30t51.5 95l244 1151q53 249 201.5 360t417.5 111q243 0 379.5 -99t136.5 -274q0 -118 -51 -198t-162 -132q-117 -56 -117 -102q0 -29 20.5 -50.5t87.5 -56.5q95 -51 140 -118t45 -164q0 -117 -58.5 -205.5t-170 -138t-271.5 -49.5 q-161 0 -274 45v299q59 -29 136.5 -45.5t133.5 -16.5q59 0 87 22t28 50q0 32 -19.5 53.5t-113.5 83.5q-88 56 -127 111.5t-39 130.5q0 92 42 150.5t165 125.5q71 40 100 76t29 80q0 58 -41.5 88.5t-116.5 30.5q-78 0 -132.5 -50t-74.5 -147l-252 -1184 q-43 -192 -153.5 -283.5t-292.5 -91.5q-110 0 -207 27v303z" /> -<glyph unicode="à" d="M84 412q0 179 73 365t184.5 281t246.5 95q84 0 148 -37.5t114 -122.5h8l53 140h310l-240 -1133h-309l10 123h-8q-56 -78 -121 -110.5t-147 -32.5q-158 0 -240 111.5t-82 320.5zM479 434q0 -143 86 -143q50 0 95.5 58.5t72.5 156.5t27 192q0 65 -20 104.5t-62 39.5 q-76 0 -137.5 -126.5t-61.5 -281.5zM400 1548v21h396q29 -157 94 -303v-25h-236q-82 75 -152 159t-102 148z" /> -<glyph unicode="á" d="M84 412q0 179 73 365t184.5 281t246.5 95q84 0 148 -37.5t114 -122.5h8l53 140h310l-240 -1133h-309l10 123h-8q-56 -78 -121 -110.5t-147 -32.5q-158 0 -240 111.5t-82 320.5zM479 434q0 -143 86 -143q50 0 95.5 58.5t72.5 156.5t27 192q0 65 -20 104.5t-62 39.5 q-76 0 -137.5 -126.5t-61.5 -281.5zM531 1241v23q123 102 282 305h439v-15q-45 -54 -191.5 -157t-245.5 -156h-284z" /> -<glyph unicode="â" d="M84 412q0 179 73 365t184.5 281t246.5 95q84 0 148 -37.5t114 -122.5h8l53 140h310l-240 -1133h-309l10 123h-8q-56 -78 -121 -110.5t-147 -32.5q-158 0 -240 111.5t-82 320.5zM479 434q0 -143 86 -143q50 0 95.5 58.5t72.5 156.5t27 192q0 65 -20 104.5t-62 39.5 q-76 0 -137.5 -126.5t-61.5 -281.5zM262 1238v23q79 72 170 162.5t139 142.5h447q26 -59 78 -149.5t102 -155.5v-23h-266q-46 41 -156 174q-140 -110 -240 -174h-274z" /> -<glyph unicode="ã" d="M84 412q0 179 73 365t184.5 281t246.5 95q84 0 148 -37.5t114 -122.5h8l53 140h310l-240 -1133h-309l10 123h-8q-56 -78 -121 -110.5t-147 -32.5q-158 0 -240 111.5t-82 320.5zM479 434q0 -143 86 -143q50 0 95.5 58.5t72.5 156.5t27 192q0 65 -20 104.5t-62 39.5 q-76 0 -137.5 -126.5t-61.5 -281.5zM301 1237q32 172 108.5 257t204.5 85q34 0 59.5 -6.5t94.5 -42.5q31 -17 66 -33t67 -16q78 0 115 100h190q-34 -172 -112.5 -257t-208.5 -85q-33 0 -65 8t-61 22t-46 23q-73 45 -127 45q-31 0 -60.5 -27t-36.5 -73h-188z" /> -<glyph unicode="ä" d="M84 412q0 179 73 365t184.5 281t246.5 95q84 0 148 -37.5t114 -122.5h8l53 140h310l-240 -1133h-309l10 123h-8q-56 -78 -121 -110.5t-147 -32.5q-158 0 -240 111.5t-82 320.5zM479 434q0 -143 86 -143q50 0 95.5 58.5t72.5 156.5t27 192q0 65 -20 104.5t-62 39.5 q-76 0 -137.5 -126.5t-61.5 -281.5zM331 1384q0 187 201 187q170 0 170 -125q0 -189 -201 -189q-88 0 -129 31t-41 96zM818 1384q0 187 201 187q168 0 168 -125q0 -97 -49.5 -143t-149.5 -46q-88 0 -129 31t-41 96z" /> -<glyph unicode="å" d="M84 412q0 179 73 365t184.5 281t246.5 95q84 0 148 -37.5t114 -122.5h8l53 140h310l-240 -1133h-309l10 123h-8q-56 -78 -121 -110.5t-147 -32.5q-158 0 -240 111.5t-82 320.5zM479 434q0 -143 86 -143q50 0 95.5 58.5t72.5 156.5t27 192q0 65 -20 104.5t-62 39.5 q-76 0 -137.5 -126.5t-61.5 -281.5zM488 1489q0 114 73.5 184t195.5 70q118 0 193 -70.5t75 -181.5q0 -113 -74.5 -183.5t-193.5 -70.5q-121 0 -195 68.5t-74 183.5zM668 1489q0 -37 23.5 -60.5t65.5 -23.5q39 0 63.5 25t24.5 59q0 38 -26.5 62t-61.5 24q-36 0 -62.5 -24 t-26.5 -62z" /> -<glyph unicode="æ" horiz-adv-x="1788" d="M84 412q0 179 73 365t184.5 281t246.5 95q92 0 152 -38t110 -122h8l53 140h207v-95q58 56 132.5 85.5t146.5 29.5q157 0 251.5 -86.5t94.5 -228.5q0 -201 -157 -308.5t-451 -107.5h-60v-16q0 -148 164 -148q79 0 155 23.5t173 74.5v-274q-99 -58 -182.5 -80t-192.5 -22 q-179 0 -262 112l-31 -92h-227l10 123h-8q-56 -78 -121 -110.5t-147 -32.5q-158 0 -240 111.5t-82 320.5zM479 434q0 -143 86 -143q76 0 134.5 123t58.5 284q0 65 -23 104.5t-65 39.5q-49 0 -93 -57.5t-71 -155t-27 -195.5zM1114 664h29q109 0 171 41.5t62 109.5 q0 32 -20 54t-64 22q-61 0 -114 -69.5t-64 -157.5z" /> -<glyph unicode="ç" horiz-adv-x="1032" d="M84 442q0 201 76.5 364.5t215 255t314.5 91.5q195 0 367 -80l-123 -287q-133 60 -225 60q-62 0 -115 -48t-87 -143.5t-34 -187.5q0 -91 30 -133.5t95 -42.5q72 0 139.5 23t143.5 63v-307q-80 -44 -168.5 -67t-206.5 -23q-199 0 -310.5 120.5t-111.5 341.5zM176 -258 q30 -9 78.5 -18t72.5 -9q68 0 68 49q0 73 -145 101l75 135h205l-24 -41q178 -37 178 -195q0 -121 -82.5 -188.5t-233.5 -67.5q-115 0 -192 29v205z" /> -<glyph unicode="è" horiz-adv-x="1186" d="M84 428q0 211 83.5 380.5t229 257t336.5 87.5q190 0 299 -86t109 -229q0 -201 -156.5 -308.5t-452.5 -107.5h-59v-16q0 -148 164 -148q79 0 155 23.5t173 74.5v-274q-112 -57 -209 -79.5t-224 -22.5q-212 0 -330 118.5t-118 329.5zM512 664h29q109 0 171 41.5t62 109.5 q0 32 -20 54t-64 22q-61 0 -114 -69.5t-64 -157.5zM429 1548v21h396q29 -157 94 -303v-25h-236q-82 75 -152 159t-102 148z" /> -<glyph unicode="é" horiz-adv-x="1186" d="M84 428q0 211 83.5 380.5t229 257t336.5 87.5q190 0 299 -86t109 -229q0 -201 -156.5 -308.5t-452.5 -107.5h-59v-16q0 -148 164 -148q79 0 155 23.5t173 74.5v-274q-112 -57 -209 -79.5t-224 -22.5q-212 0 -330 118.5t-118 329.5zM512 664h29q109 0 171 41.5t62 109.5 q0 32 -20 54t-64 22q-61 0 -114 -69.5t-64 -157.5zM523 1241v23q123 102 282 305h439v-15q-45 -54 -191.5 -157t-245.5 -156h-284z" /> -<glyph unicode="ê" horiz-adv-x="1186" d="M84 428q0 211 83.5 380.5t229 257t336.5 87.5q190 0 299 -86t109 -229q0 -201 -156.5 -308.5t-452.5 -107.5h-59v-16q0 -148 164 -148q79 0 155 23.5t173 74.5v-274q-112 -57 -209 -79.5t-224 -22.5q-212 0 -330 118.5t-118 329.5zM512 664h29q109 0 171 41.5t62 109.5 q0 32 -20 54t-64 22q-61 0 -114 -69.5t-64 -157.5zM277 1241v23q79 72 170 162.5t139 142.5h447q26 -59 78 -149.5t102 -155.5v-23h-266q-46 41 -156 174q-140 -110 -240 -174h-274z" /> -<glyph unicode="ë" horiz-adv-x="1186" d="M84 428q0 211 83.5 380.5t229 257t336.5 87.5q190 0 299 -86t109 -229q0 -201 -156.5 -308.5t-452.5 -107.5h-59v-16q0 -148 164 -148q79 0 155 23.5t173 74.5v-274q-112 -57 -209 -79.5t-224 -22.5q-212 0 -330 118.5t-118 329.5zM512 664h29q109 0 171 41.5t62 109.5 q0 32 -20 54t-64 22q-61 0 -114 -69.5t-64 -157.5zM336 1384q0 187 201 187q170 0 170 -125q0 -189 -201 -189q-88 0 -129 31t-41 96zM823 1384q0 187 201 187q168 0 168 -125q0 -97 -49.5 -143t-149.5 -46q-88 0 -129 31t-41 96z" /> -<glyph unicode="ì" horiz-adv-x="666" d="M23 0l239 1133h389l-241 -1133h-387zM167 1548v21h396q29 -157 94 -303v-25h-236q-82 75 -152 159t-102 148z" /> -<glyph unicode="í" horiz-adv-x="666" d="M23 0l239 1133h389l-241 -1133h-387zM294 1241v23q123 102 282 305h439v-15q-45 -54 -191.5 -157t-245.5 -156h-284z" /> -<glyph unicode="î" horiz-adv-x="666" d="M23 0l239 1133h389l-241 -1133h-387zM-7 1241v23q79 72 170 162.5t139 142.5h447q26 -59 78 -149.5t102 -155.5v-23h-266q-46 41 -156 174q-140 -110 -240 -174h-274z" /> -<glyph unicode="ï" horiz-adv-x="666" d="M23 0l239 1133h389l-241 -1133h-387zM91 1384q0 187 201 187q170 0 170 -125q0 -189 -201 -189q-88 0 -129 31t-41 96zM578 1384q0 187 201 187q168 0 168 -125q0 -97 -49.5 -143t-149.5 -46q-88 0 -129 31t-41 96z" /> -<glyph unicode="ð" horiz-adv-x="1155" d="M84 426q0 170 62.5 305t178.5 209t267 74q130 0 203 -88l10 4q-19 142 -90 246l-273 -127l-82 168l220 102q-29 25 -95 74l115 180q136 -61 231 -137l238 110l82 -166l-184 -90q71 -88 114 -249t43 -324q0 -360 -154.5 -548.5t-449.5 -188.5q-201 0 -318.5 119 t-117.5 327zM471 408q0 -148 84 -148q53 0 93 44.5t63.5 119t23.5 147.5q0 76 -18.5 119t-65.5 43q-81 0 -130.5 -101t-49.5 -224z" /> -<glyph unicode="ñ" horiz-adv-x="1274" d="M23 0l239 1133h309l-12 -158h8q55 95 129.5 136.5t182.5 41.5q141 0 220 -85.5t79 -236.5q0 -106 -25 -229l-127 -602h-387l129 618q18 78 18 142q0 43 -22 64.5t-53 21.5q-57 0 -105.5 -71t-79.5 -222l-116 -553h-387zM319 1237q32 172 108.5 257t204.5 85 q34 0 59.5 -6.5t94.5 -42.5q31 -17 66 -33t67 -16q78 0 115 100h190q-34 -172 -112.5 -257t-208.5 -85q-33 0 -65 8t-61 22t-46 23q-73 45 -127 45q-31 0 -60.5 -27t-36.5 -73h-188z" /> -<glyph unicode="ò" d="M84 416q0 210 79.5 379.5t223.5 263.5t336 94q209 0 322.5 -113t113.5 -323t-79.5 -379.5t-223.5 -263.5t-336 -94q-209 0 -322.5 113t-113.5 323zM479 403q0 -133 84 -133q81 0 141 139t60 320q0 66 -23 99.5t-63 33.5q-82 0 -140.5 -139.5t-58.5 -319.5zM404 1548v21 h396q29 -157 94 -303v-25h-236q-82 75 -152 159t-102 148z" /> -<glyph unicode="ó" d="M84 416q0 210 79.5 379.5t223.5 263.5t336 94q209 0 322.5 -113t113.5 -323t-79.5 -379.5t-223.5 -263.5t-336 -94q-209 0 -322.5 113t-113.5 323zM479 403q0 -133 84 -133q81 0 141 139t60 320q0 66 -23 99.5t-63 33.5q-82 0 -140.5 -139.5t-58.5 -319.5zM533 1241v23 q123 102 282 305h439v-15q-45 -54 -191.5 -157t-245.5 -156h-284z" /> -<glyph unicode="ô" d="M84 416q0 210 79.5 379.5t223.5 263.5t336 94q209 0 322.5 -113t113.5 -323t-79.5 -379.5t-223.5 -263.5t-336 -94q-209 0 -322.5 113t-113.5 323zM479 403q0 -133 84 -133q81 0 141 139t60 320q0 66 -23 99.5t-63 33.5q-82 0 -140.5 -139.5t-58.5 -319.5zM247 1241v23 q79 72 170 162.5t139 142.5h447q26 -59 78 -149.5t102 -155.5v-23h-266q-46 41 -156 174q-140 -110 -240 -174h-274z" /> -<glyph unicode="õ" d="M84 416q0 210 79.5 379.5t223.5 263.5t336 94q209 0 322.5 -113t113.5 -323t-79.5 -379.5t-223.5 -263.5t-336 -94q-209 0 -322.5 113t-113.5 323zM479 403q0 -133 84 -133q81 0 141 139t60 320q0 66 -23 99.5t-63 33.5q-82 0 -140.5 -139.5t-58.5 -319.5zM277 1237 q32 172 108.5 257t204.5 85q34 0 59.5 -6.5t94.5 -42.5q31 -17 66 -33t67 -16q78 0 115 100h190q-34 -172 -112.5 -257t-208.5 -85q-33 0 -65 8t-61 22t-46 23q-73 45 -127 45q-31 0 -60.5 -27t-36.5 -73h-188z" /> -<glyph unicode="ö" d="M84 416q0 210 79.5 379.5t223.5 263.5t336 94q209 0 322.5 -113t113.5 -323t-79.5 -379.5t-223.5 -263.5t-336 -94q-209 0 -322.5 113t-113.5 323zM479 403q0 -133 84 -133q81 0 141 139t60 320q0 66 -23 99.5t-63 33.5q-82 0 -140.5 -139.5t-58.5 -319.5zM317 1384 q0 187 201 187q170 0 170 -125q0 -189 -201 -189q-88 0 -129 31t-41 96zM804 1384q0 187 201 187q168 0 168 -125q0 -97 -49.5 -143t-149.5 -46q-88 0 -129 31t-41 96z" /> -<glyph unicode="÷" horiz-adv-x="1159" d="M102 586v272h975v-272h-975zM432 373q0 83 41 127.5t117 44.5q74 0 114.5 -44.5t40.5 -127.5q0 -81 -41.5 -126.5t-113.5 -45.5q-74 0 -116 46t-42 126zM432 1071q0 83 41 127.5t117 44.5q74 0 114.5 -44.5t40.5 -127.5q0 -81 -41.5 -126.5t-113.5 -45.5q-74 0 -116 46 t-42 126z" /> -<glyph unicode="ø" horiz-adv-x="1286" d="M66 -2l112 131q-94 117 -94 287q0 207 81.5 377.5t230.5 265t347 94.5q136 0 250 -57l105 121l127 -109l-105 -123q82 -114 82 -268q0 -208 -81 -377.5t-229 -264.5t-343 -95q-127 0 -238 49l-118 -140zM449 451l335 397q-35 29 -82 29q-67 0 -125 -55t-92 -153t-36 -218 zM518 274q29 -14 72 -14q107 0 172 101.5t74 287.5z" /> -<glyph unicode="ù" horiz-adv-x="1274" d="M96 301q0 106 25 229l127 603h387l-129 -617q-19 -82 -19 -141q0 -44 22.5 -65t53.5 -21q59 0 107.5 78.5t77.5 214.5l116 551h387l-239 -1133h-310l13 158h-8q-54 -93 -128.5 -135.5t-183.5 -42.5q-141 0 -220 85.5t-79 235.5zM412 1548v21h396q29 -157 94 -303v-25 h-236q-82 75 -152 159t-102 148z" /> -<glyph unicode="ú" horiz-adv-x="1274" d="M96 301q0 106 25 229l127 603h387l-129 -617q-19 -82 -19 -141q0 -44 22.5 -65t53.5 -21q59 0 107.5 78.5t77.5 214.5l116 551h387l-239 -1133h-310l13 158h-8q-54 -93 -128.5 -135.5t-183.5 -42.5q-141 0 -220 85.5t-79 235.5zM584 1241v23q123 102 282 305h439v-15 q-45 -54 -191.5 -157t-245.5 -156h-284z" /> -<glyph unicode="û" horiz-adv-x="1274" d="M96 301q0 106 25 229l127 603h387l-129 -617q-19 -82 -19 -141q0 -44 22.5 -65t53.5 -21q59 0 107.5 78.5t77.5 214.5l116 551h387l-239 -1133h-310l13 158h-8q-54 -93 -128.5 -135.5t-183.5 -42.5q-141 0 -220 85.5t-79 235.5zM285 1241v23q79 72 170 162.5t139 142.5 h447q26 -59 78 -149.5t102 -155.5v-23h-266q-46 41 -156 174q-140 -110 -240 -174h-274z" /> -<glyph unicode="ü" horiz-adv-x="1274" d="M96 301q0 106 25 229l127 603h387l-129 -617q-19 -82 -19 -141q0 -44 22.5 -65t53.5 -21q59 0 107.5 78.5t77.5 214.5l116 551h387l-239 -1133h-310l13 158h-8q-54 -93 -128.5 -135.5t-183.5 -42.5q-141 0 -220 85.5t-79 235.5zM371 1384q0 187 201 187q170 0 170 -125 q0 -189 -201 -189q-88 0 -129 31t-41 96zM858 1384q0 187 201 187q168 0 168 -125q0 -97 -49.5 -143t-149.5 -46q-88 0 -129 31t-41 96z" /> -<glyph unicode="ý" horiz-adv-x="1114" d="M-129 -168q46 -12 109 -12q87 0 142.5 36.5t98.5 114.5l23 41l-162 1121h389l43 -562l2 -62v-87h8q37 132 50 165.5t239 545.5h416l-670 -1276q-96 -185 -223 -267t-311 -82q-92 0 -154 17v307zM492 1241v23q123 102 282 305h439v-15q-45 -54 -191.5 -157t-245.5 -156 h-284z" /> -<glyph unicode="þ" d="M-82 -492l434 2048h387l-49 -231q-38 -175 -90 -301h8q44 59 96.5 94t131.5 35q151 0 237 -112t86 -306q0 -203 -70 -382.5t-185.5 -276t-252.5 -96.5q-143 0 -231 145h-8q-12 -166 -56 -371l-51 -246h-387zM485 434q0 -65 23 -104t65 -39q48 0 92 57t71.5 153t27.5 197 q0 144 -86 144q-50 0 -95 -57t-71.5 -154t-26.5 -197z" /> -<glyph unicode="ÿ" horiz-adv-x="1114" d="M-129 -168q46 -12 109 -12q87 0 142.5 36.5t98.5 114.5l23 41l-162 1121h389l43 -562l2 -62v-87h8q37 132 50 165.5t239 545.5h416l-670 -1276q-96 -185 -223 -267t-311 -82q-92 0 -154 17v307zM259 1384q0 187 201 187q170 0 170 -125q0 -189 -201 -189q-88 0 -129 31 t-41 96zM746 1384q0 187 201 187q168 0 168 -125q0 -97 -49.5 -143t-149.5 -46q-88 0 -129 31t-41 96z" /> -<glyph unicode="ı" horiz-adv-x="666" d="M23 0l239 1133h389l-241 -1133h-387z" /> -<glyph unicode="Œ" horiz-adv-x="1909" d="M104 528q0 196 58.5 379t164.5 313t252.5 197.5t323.5 67.5q94 0 191 -23h874l-67 -319h-478l-47 -225h445l-72 -322h-444l-58 -272h477l-65 -324h-815q-104 -20 -197 -20q-256 0 -399.5 146.5t-143.5 401.5zM500 526q0 -217 182 -217q96 0 180 41l162 762 q-53 49 -154 49q-96 0 -182.5 -88t-137 -235t-50.5 -312z" /> -<glyph unicode="œ" horiz-adv-x="1802" d="M84 416q0 209 79 380t217.5 264t319.5 93q187 0 277 -125q144 125 373 125q188 0 297.5 -86t109.5 -229q0 -203 -157 -309.5t-451 -106.5h-59v-16q0 -148 163 -148q79 0 155 23.5t173 74.5v-274q-114 -58 -210.5 -80t-221.5 -22q-203 0 -295 112q-124 -112 -334 -112 q-209 0 -322.5 113t-113.5 323zM479 403q0 -133 84 -133q81 0 141 139t60 320q0 66 -23 99.5t-63 33.5q-82 0 -140.5 -139.5t-58.5 -319.5zM1128 664h29q110 0 172 41t62 110q0 32 -20.5 54t-63.5 22q-60 0 -112.5 -68t-66.5 -159z" /> -<glyph unicode="Ÿ" horiz-adv-x="1237" d="M164 1462h403l90 -542l312 542h436l-612 -895l-121 -567h-391l120 567zM397 1722q0 187 201 187q170 0 170 -125q0 -189 -201 -189q-88 0 -129 31t-41 96zM884 1722q0 187 201 187q168 0 168 -125q0 -97 -49.5 -143t-149.5 -46q-88 0 -129 31t-41 96z" /> -<glyph unicode="ˆ" horiz-adv-x="1135" d="M254 1241v23q79 72 170 162.5t139 142.5h447q26 -59 78 -149.5t102 -155.5v-23h-266q-46 41 -156 174q-140 -110 -240 -174h-274z" /> -<glyph unicode="˚" horiz-adv-x="1182" d="M522 1489q0 114 73.5 184t195.5 70q118 0 193 -70.5t75 -181.5q0 -113 -74.5 -183.5t-193.5 -70.5q-121 0 -195 68.5t-74 183.5zM702 1489q0 -37 23.5 -60.5t65.5 -23.5q39 0 63.5 25t24.5 59q0 38 -26.5 62t-61.5 24q-36 0 -62.5 -24t-26.5 -62z" /> -<glyph unicode="˜" horiz-adv-x="1135" d="M301 1237q32 172 108.5 257t204.5 85q34 0 59.5 -6.5t94.5 -42.5q31 -17 66 -33t67 -16q78 0 115 100h190q-34 -172 -112.5 -257t-208.5 -85q-33 0 -65 8t-61 22t-46 23q-73 45 -127 45q-31 0 -60.5 -27t-36.5 -73h-188z" /> -<glyph unicode=" " horiz-adv-x="959" /> -<glyph unicode=" " horiz-adv-x="1919" /> -<glyph unicode=" " horiz-adv-x="959" /> -<glyph unicode=" " horiz-adv-x="1919" /> -<glyph unicode=" " horiz-adv-x="639" /> -<glyph unicode=" " horiz-adv-x="479" /> -<glyph unicode=" " horiz-adv-x="319" /> -<glyph unicode=" " horiz-adv-x="319" /> -<glyph unicode=" " horiz-adv-x="239" /> -<glyph unicode=" " horiz-adv-x="383" /> -<glyph unicode=" " horiz-adv-x="106" /> -<glyph unicode="‐" horiz-adv-x="674" d="M23 393l63 312h553l-64 -312h-552z" /> -<glyph unicode="‑" horiz-adv-x="674" d="M23 393l63 312h553l-64 -312h-552z" /> -<glyph unicode="‒" horiz-adv-x="674" d="M23 393l63 312h553l-64 -312h-552z" /> -<glyph unicode="–" horiz-adv-x="983" d="M33 416l57 274h871l-60 -274h-868z" /> -<glyph unicode="—" horiz-adv-x="1966" d="M33 416l57 274h1854l-60 -274h-1851z" /> -<glyph unicode="‘" horiz-adv-x="500" d="M109 983q104 235 258 479h288q-26 -62 -53 -131t-135 -370h-348z" /> -<glyph unicode="’" horiz-adv-x="500" d="M94 961q34 81 67.5 167.5t121.5 333.5h348l8 -22q-92 -212 -256 -479h-289z" /> -<glyph unicode="‚" horiz-adv-x="621" d="M-104 -264q25 59 50 123t138 379h348l8 -23q-94 -223 -256 -479h-288z" /> -<glyph unicode="“" horiz-adv-x="997" d="M109 983q104 235 258 479h288q-26 -62 -53 -131t-135 -370h-348zM606 983q109 246 256 479h289q-49 -115 -100 -258l-88 -243h-349z" /> -<glyph unicode="”" horiz-adv-x="997" d="M94 961q49 117 100 258l89 243h348l8 -22q-92 -212 -256 -479h-289zM592 961q41 98 99 258l89 243h348l7 -22q-39 -91 -110 -226t-144 -253h-289z" /> -<glyph unicode="„" horiz-adv-x="1122" d="M-104 -264q25 59 50 123t138 379h348l8 -23q-94 -223 -256 -479h-288zM397 -264q61 148 147 387l42 115h348l8 -23q-51 -116 -124.5 -251t-133.5 -228h-287z" /> -<glyph unicode="•" horiz-adv-x="803" d="M86 688q0 118 47 214t133.5 150t200.5 54q148 0 221.5 -77.5t73.5 -223.5q0 -194 -101.5 -305t-281.5 -111q-137 0 -215 80t-78 219zM594 1133z" /> -<glyph unicode="…" horiz-adv-x="1800" d="M12 127q0 109 65 171t179 62q84 0 132 -40t48 -115q0 -118 -60 -174t-190 -56q-78 0 -126 37t-48 115zM600 127q0 109 65 171t179 62q84 0 132 -40t48 -115q0 -118 -60 -174t-190 -56q-78 0 -126 37t-48 115zM1186 127q0 109 65 171t179 62q84 0 132 -40t48 -115 q0 -118 -60 -174t-190 -56q-78 0 -126 37t-48 115z" /> -<glyph unicode=" " horiz-adv-x="383" /> -<glyph unicode="‹" horiz-adv-x="719" d="M61 553v10l408 518l264 -204l-266 -334l111 -330l-334 -137z" /> -<glyph unicode="›" horiz-adv-x="719" d="M-14 248l266 334l-111 329l332 138l184 -478v-10l-407 -518z" /> -<glyph unicode="⁄" horiz-adv-x="248" d="M-563 0l1089 1462h291l-1083 -1462h-297z" /> -<glyph unicode=" " horiz-adv-x="479" /> -<glyph unicode="⁴" horiz-adv-x="848" d="M16 707l31 178l490 577h325l-119 -557h113l-41 -198h-113l-26 -123h-289l27 123h-398zM293 905h162q62 239 73 274t15 44q-13 -18 -35 -48.5t-215 -269.5z" /> -<glyph unicode="€" horiz-adv-x="1188" d="M53 451l43 204h109l22 123h-106l47 205h117q84 243 243 373.5t377 130.5q115 0 202 -25t173 -80l-154 -282q-120 78 -221 78q-142 0 -219 -195h297l-45 -205h-309q-18 -59 -25 -123h246l-43 -204h-227q0 -82 27.5 -113t105.5 -31q75 0 145 18.5t148 49.5v-330 q-126 -65 -355 -65q-231 0 -341.5 114t-116.5 357h-140z" /> -<glyph unicode="™" horiz-adv-x="1577" d="M102 1286v176h537v-176h-170v-545h-197v545h-170zM711 741v721h286l138 -479l149 479h277v-721h-195v400q0 74 6 110h-8l-152 -510h-163l-144 510h-8q6 -64 6 -110v-400h-192z" /> -<glyph unicode="" horiz-adv-x="1135" d="M0 1135h1135v-1135h-1135v1135z" /> -<glyph unicode="fi" horiz-adv-x="1505" d="M-209 -162q63 -18 117 -18q74 0 112 30t52 95l190 897h-166l43 190l189 96l16 74q43 192 146.5 278.5t275.5 86.5q80 0 155 -16t128 -42l-99 -264q-64 31 -129 31q-35 0 -59.5 -18.5t-32.5 -53.5l-16 -71h211l-66 -291h-209l-205 -959q-43 -192 -153.5 -283.5 t-292.5 -91.5q-110 0 -207 27v303zM863 0l239 1133h389l-241 -1133h-387zM1149 1382q0 103 59.5 156t166.5 53q91 0 140.5 -36.5t49.5 -104.5q0 -100 -58 -154.5t-167 -54.5q-191 0 -191 141z" /> -<glyph unicode="fl" horiz-adv-x="1505" d="M-209 -162q63 -18 117 -18q74 0 112 30t52 95l190 897h-166l43 190l189 96l16 74q43 192 146.5 278.5t275.5 86.5q80 0 155 -16t128 -42l-99 -264q-64 31 -129 31q-35 0 -59.5 -18.5t-32.5 -53.5l-16 -71h211l-66 -291h-209l-205 -959q-43 -192 -153.5 -283.5 t-292.5 -91.5q-110 0 -207 27v303zM863 0l329 1556h387l-329 -1556h-387z" /> -<glyph unicode="ffi" horiz-adv-x="2163" d="M-209 -162q63 -18 117 -18q74 0 112 30t52 95l190 897h-166l43 190l189 96l16 74q43 192 146.5 278.5t275.5 86.5q80 0 155 -16t128 -42l-99 -264q-64 31 -129 31q-35 0 -59.5 -18.5t-32.5 -53.5l-16 -71h331l17 69q41 185 142.5 275t279.5 90q80 0 155 -16t127 -42 l-98 -264q-64 31 -129 31q-35 0 -59.5 -18.5t-32.5 -53.5l-16 -71h210l-65 -291h-209l-205 -959q-43 -192 -153.5 -283.5t-292.5 -91.5q-110 0 -207 27v303q63 -18 117 -18q74 0 111.5 30t51.5 95l191 897h-330l-205 -959q-43 -192 -153.5 -283.5t-292.5 -91.5 q-110 0 -207 27v303zM1520 0l239 1133h389l-241 -1133h-387zM1806 1382q0 103 59.5 156t166.5 53q91 0 140.5 -36.5t49.5 -104.5q0 -100 -58 -154.5t-167 -54.5q-191 0 -191 141z" /> -<glyph unicode="ffl" horiz-adv-x="2159" d="M-209 -162q63 -18 117 -18q74 0 112 30t52 95l190 897h-166l43 190l189 96l16 74q43 192 146.5 278.5t275.5 86.5q80 0 155 -16t128 -42l-99 -264q-64 31 -129 31q-35 0 -59.5 -18.5t-32.5 -53.5l-16 -71h331l17 69q41 185 142.5 275t279.5 90q80 0 155 -16t127 -42 l-98 -264q-64 31 -129 31q-35 0 -59.5 -18.5t-32.5 -53.5l-16 -71h210l-65 -291h-209l-205 -959q-43 -192 -153.5 -283.5t-292.5 -91.5q-110 0 -207 27v303q63 -18 117 -18q74 0 111.5 30t51.5 95l191 897h-330l-205 -959q-43 -192 -153.5 -283.5t-292.5 -91.5 q-110 0 -207 27v303zM1516 0l329 1556h387l-329 -1556h-387z" /> -</font> -</defs></svg> -\ No newline at end of file diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-ExtraBoldItalic-webfont.ttf b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-ExtraBoldItalic-webfont.ttf Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-ExtraBoldItalic-webfont.woff b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-ExtraBoldItalic-webfont.woff Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-Italic-webfont.eot b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-Italic-webfont.eot Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-Italic-webfont.svg b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-Italic-webfont.svg @@ -1,251 +0,0 @@ -<?xml version="1.0" standalone="no"?> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" > -<svg xmlns="http://www.w3.org/2000/svg"> -<metadata> -This is a custom SVG webfont generated by Font Squirrel. -Copyright : Digitized data copyright 20102011 Google Corporation -Foundry : Ascender Corporation -Foundry URL : httpwwwascendercorpcom -</metadata> -<defs> -<font id="OpenSansItalic" horiz-adv-x="1128" > -<font-face units-per-em="2048" ascent="1638" descent="-410" /> -<missing-glyph horiz-adv-x="532" /> -<glyph unicode=" " horiz-adv-x="532" /> -<glyph unicode="	" horiz-adv-x="532" /> -<glyph unicode=" " horiz-adv-x="532" /> -<glyph unicode="!" horiz-adv-x="530" d="M43 78q0 76 39.5 120t107.5 44q45 0 73 -27.5t28 -81.5q0 -68 -39 -115t-105 -47q-49 0 -76.5 28t-27.5 79zM172 403q49 307 176 1059h207l-274 -1059h-109z" /> -<glyph unicode=""" horiz-adv-x="791" d="M225 934l72 528h188l-153 -528h-107zM573 934l72 528h189l-154 -528h-107z" /> -<glyph unicode="#" horiz-adv-x="1323" d="M63 430l13 129h284l101 340h-277l13 127h301l123 436h139l-125 -436h305l127 436h133l-125 -436h264l-12 -127h-291l-98 -340h285l-13 -129h-309l-125 -430h-139l129 430h-303l-127 -430h-133l121 430h-261zM500 559h303l96 340h-303z" /> -<glyph unicode="$" d="M72 176v154q82 -41 175.5 -63.5t166.5 -22.5l98 452q-139 49 -201.5 123.5t-62.5 188.5q0 159 108 255t299 113l39 176h133l-39 -178q159 -12 283 -76l-63 -135q-121 63 -248 72l-94 -440q149 -55 212.5 -125t63.5 -178q0 -162 -112.5 -263t-309.5 -123l-49 -225h-133 l49 223q-195 14 -315 72zM401 1010q0 -53 34.5 -97.5t107.5 -70.5l84 393q-108 -11 -167 -69t-59 -156zM549 250q107 13 170 75t63 154q0 54 -33 96t-114 74z" /> -<glyph unicode="%" horiz-adv-x="1624" d="M168 860q0 166 50.5 318.5t136.5 228.5t200 76q116 0 176 -72t60 -205q0 -108 -32 -237.5t-82.5 -217.5t-120.5 -137t-157 -49q-109 0 -170 75t-61 220zM231 0l1086 1462h151l-1085 -1462h-152zM307 864q0 -172 107 -172q52 0 94 39.5t73.5 114t50.5 175t19 171.5 q0 166 -108 166q-66 0 -119 -63t-85 -187.5t-32 -243.5zM909 274q0 166 50.5 318.5t136.5 228.5t200 76q116 0 176 -71.5t60 -204.5q0 -107 -31.5 -236t-82 -217.5t-121 -138t-156.5 -49.5q-110 0 -171 74.5t-61 219.5zM1049 279q0 -173 106 -173q65 0 117 65t86.5 198.5 t34.5 236.5q0 166 -109 166q-67 0 -119.5 -64.5t-84 -188.5t-31.5 -240z" /> -<glyph unicode="&" horiz-adv-x="1372" d="M66 342q0 148 90 257.5t303 211.5q-103 165 -103 309q0 164 106 264.5t281 100.5q149 0 236.5 -79t87.5 -212q0 -78 -32.5 -137t-87.5 -108t-127.5 -90t-153.5 -83l278 -389q127 110 199 295h168q-101 -236 -283 -412l203 -270h-201l-117 166q-120 -100 -230 -143 t-247 -43q-168 0 -269 96t-101 266zM229 354q0 -106 66.5 -170.5t175.5 -64.5q87 0 168 33t195 124l-306 433q-128 -67 -184 -116t-85.5 -107.5t-29.5 -131.5zM516 1118q0 -120 82 -235q139 71 191 110t83 85t31 104q0 77 -42.5 121.5t-123.5 44.5q-105 0 -163 -60t-58 -170 z" /> -<glyph unicode="'" horiz-adv-x="444" d="M225 934l72 528h188l-153 -528h-107z" /> -<glyph unicode="(" horiz-adv-x="584" d="M82 272q0 339 120 627t384 563h157q-246 -270 -371.5 -570t-125.5 -618q0 -339 114 -598h-131q-147 266 -147 596z" /> -<glyph unicode=")" horiz-adv-x="584" d="M-160 -324q496 551 496 1188q0 341 -113 598h131q146 -269 146 -598q0 -341 -121.5 -629.5t-382.5 -558.5h-156z" /> -<glyph unicode="*" horiz-adv-x="1130" d="M215 1194l55 154l371 -185l41 400l172 -35l-123 -383l422 18l-8 -157l-393 47l180 -383l-166 -52l-113 406l-258 -344l-116 121l309 284z" /> -<glyph unicode="+" d="M127 651v142h389v391h141v-391h390v-142h-390v-387h-141v387h-389z" /> -<glyph unicode="," horiz-adv-x="492" d="M-100 -264q126 286 204 502h187l8 -23q-113 -235 -270 -479h-129z" /> -<glyph unicode="-" horiz-adv-x="639" d="M55 469l35 158h479l-34 -158h-480z" /> -<glyph unicode="." horiz-adv-x="518" d="M43 74q0 77 40.5 122.5t111.5 45.5q43 0 69.5 -26t26.5 -79q0 -71 -40 -118.5t-108 -47.5q-46 0 -73 26t-27 77z" /> -<glyph unicode="/" horiz-adv-x="717" d="M-94 0l813 1462h174l-813 -1462h-174z" /> -<glyph unicode="0" d="M121 477q0 270 82 514.5t216.5 369t307.5 124.5q365 0 365 -471q0 -295 -78.5 -539t-214 -369.5t-314.5 -125.5q-176 0 -270 127.5t-94 369.5zM293 479q0 -172 50 -264t161 -92q115 0 209 114t150.5 328t56.5 453q0 323 -203 323q-113 0 -209 -115.5t-155.5 -323 t-59.5 -423.5z" /> -<glyph unicode="1" d="M303 1178l449 284h149l-313 -1462h-172l196 913q59 261 88 359q-50 -53 -139 -111l-178 -110z" /> -<glyph unicode="2" d="M12 0l31 147l465 420q102 93 176.5 163.5t123 133t72 124t23.5 136.5q0 99 -60 157t-163 58q-77 0 -150.5 -28.5t-162.5 -96.5l-82 115q191 154 413 154q176 0 278.5 -88.5t102.5 -243.5q0 -111 -39.5 -204t-131 -197t-294.5 -281l-352 -307v-8h678l-29 -154h-899z" /> -<glyph unicode="3" d="M47 59v164q94 -49 199 -75.5t190 -26.5q162 0 252 79.5t90 217.5q0 131 -79 198.5t-220 67.5h-131l31 143h139q165 0 274 87t109 227q0 92 -58 146t-157 54q-80 0 -157 -27t-175 -93l-80 118q195 144 424 144q179 0 277 -87t98 -237q0 -156 -101 -264.5t-280 -140.5v-9 q124 -23 195 -106.5t71 -208.5q0 -133 -62 -234.5t-181 -158.5t-283 -57q-210 0 -385 79z" /> -<glyph unicode="4" d="M16 334l29 158l834 978h196l-207 -983h232l-33 -153h-233l-72 -334h-164l74 334h-656zM219 487h486q46 220 78 373t116 445h-8q-17 -29 -66.5 -96.5t-72.5 -96.5z" /> -<glyph unicode="5" d="M80 59v164q164 -102 334 -102q191 0 298 96t107 268q0 126 -73.5 199.5t-204.5 73.5q-48 0 -97 -6.5t-139 -30.5l-74 57l197 684h668l-33 -153h-522l-127 -439q87 23 184 23q182 0 289.5 -104.5t107.5 -282.5q0 -161 -73 -283t-204 -182.5t-308 -60.5q-193 0 -330 79z " /> -<glyph unicode="6" d="M133 424q0 209 60.5 415t163.5 351.5t246 219t327 73.5q111 0 184 -23l-35 -145q-68 22 -170 22q-212 0 -356.5 -149t-212.5 -443h8q59 79 146.5 126t193.5 47q154 0 244 -98.5t90 -270.5q0 -161 -66.5 -294.5t-180.5 -204t-261 -70.5q-182 0 -281.5 115t-99.5 329z M299 416q0 -137 60.5 -216t172.5 -79q94 0 167.5 54t114 149t40.5 208q0 248 -221 248q-66 0 -128 -28.5t-110 -76t-72 -104.5t-24 -155z" /> -<glyph unicode="7" d="M174 0l768 1313h-719l31 149h891l-27 -139l-764 -1323h-180z" /> -<glyph unicode="8" d="M96 346q0 148 95 256t296 184q-95 69 -135.5 144.5t-40.5 171.5q0 111 54.5 198.5t153.5 136t222 48.5q174 0 271.5 -86.5t97.5 -235.5q0 -129 -78 -225t-266 -176q127 -78 180 -165t53 -202q0 -122 -60 -217.5t-172.5 -146.5t-264.5 -51q-190 0 -298 98.5t-108 267.5z M270 354q0 -107 69 -170t181 -63q139 0 222 74t83 196q0 99 -52 174t-165 135q-185 -60 -261.5 -143.5t-76.5 -202.5zM479 1100q0 -82 39 -144t127 -116q161 60 228 131.5t67 173.5q0 90 -57.5 143t-153.5 53q-114 0 -182 -65.5t-68 -175.5z" /> -<glyph unicode="9" d="M98 14v158q134 -47 246 -47q202 0 327 141t189 441h-10q-51 -75 -132.5 -118.5t-180.5 -43.5q-169 0 -261 98.5t-92 288.5q0 153 64.5 280.5t180 199t259.5 71.5q180 0 279.5 -114.5t99.5 -334.5q0 -194 -56 -406.5t-147.5 -360t-221.5 -217.5t-302 -70q-136 0 -242 34z M350 938q0 -124 54.5 -190t162.5 -66q76 0 140 28.5t108.5 81.5t65 114t20.5 151q0 131 -59 207.5t-160 76.5q-150 0 -241 -113t-91 -290z" /> -<glyph unicode=":" horiz-adv-x="518" d="M43 74q0 77 40.5 122.5t111.5 45.5q43 0 69.5 -26t26.5 -79q0 -71 -40 -118.5t-108 -47.5q-46 0 -73 26t-27 77zM203 956q0 77 40 122.5t111 45.5q97 0 97 -104q0 -73 -41.5 -119.5t-106.5 -46.5q-46 0 -73 26.5t-27 75.5z" /> -<glyph unicode=";" horiz-adv-x="518" d="M-100 -264q126 286 204 502h187l8 -23q-113 -235 -270 -479h-129zM203 956q0 77 40 122.5t111 45.5q97 0 97 -104q0 -73 -41.5 -119.5t-106.5 -46.5q-46 0 -73 26.5t-27 75.5z" /> -<glyph unicode="<" d="M121 664v98l919 479v-149l-747 -371l747 -328v-151z" /> -<glyph unicode="=" d="M127 444v142h920v-142h-920zM127 858v139h920v-139h-920z" /> -<glyph unicode=">" d="M121 242v151l745 328l-745 371v149l919 -479v-98z" /> -<glyph unicode="?" horiz-adv-x="874" d="M158 74q0 77 40 122.5t111 45.5q44 0 70.5 -26t26.5 -79q0 -73 -41.5 -119.5t-106.5 -46.5q-46 0 -73 26t-27 77zM197 1382q92 51 192 76t182 25q167 0 259 -84t92 -238q0 -123 -65.5 -226.5t-225.5 -223.5q-125 -91 -169 -147.5t-67 -160.5h-135q22 130 72.5 213.5 t165.5 174.5q128 100 168 144t63 94t23 112q0 93 -51.5 143.5t-147.5 50.5q-81 0 -155 -25.5t-140 -56.5z" /> -<glyph unicode="@" horiz-adv-x="1735" d="M111 504q0 261 126.5 485.5t343.5 347.5t486 123q191 0 329 -75.5t210.5 -213.5t72.5 -319q0 -179 -55 -324t-155 -227t-222 -82q-197 0 -213 184h-8q-111 -184 -291 -184q-115 0 -180.5 75.5t-65.5 209.5q0 157 68 284t188.5 199t260.5 72q65 0 127.5 -12t150.5 -48 q-64 -242 -98 -368t-31 -172q0 -117 102 -117q78 0 141.5 67t100.5 183.5t37 243.5q0 239 -128 367t-370 128q-228 0 -406.5 -107t-277 -295.5t-98.5 -416.5q0 -270 143.5 -418.5t409.5 -148.5q197 0 420 86v-127q-219 -90 -443 -90q-314 0 -494.5 184.5t-180.5 505.5z M639 518q0 -93 33 -134.5t98 -41.5q187 0 272 315l70 258q-63 23 -127 23q-94 0 -174 -55t-126 -153t-46 -212z" /> -<glyph unicode="A" horiz-adv-x="1137" d="M-117 0l799 1462h174l184 -1462h-170l-57 465h-496l-245 -465h-189zM401 621h394l-35 299q-24 179 -29 350q-37 -88 -80.5 -175t-249.5 -474z" /> -<glyph unicode="B" horiz-adv-x="1225" d="M86 0l309 1462h375q432 0 432 -336q0 -141 -87 -238t-245 -126v-10q115 -32 176.5 -110.5t61.5 -188.5q0 -212 -152 -332.5t-407 -120.5h-463zM287 145h266q181 0 278 80.5t97 227.5q0 116 -74.5 177.5t-214.5 61.5h-236zM434 836h248q156 0 249 73t93 199 q0 104 -66.5 155.5t-209.5 51.5h-211z" /> -<glyph unicode="C" horiz-adv-x="1198" d="M150 537q0 261 105.5 485.5t283.5 342.5t403 118q197 0 348 -80l-69 -141q-138 69 -279 69q-174 0 -311.5 -97t-218 -284.5t-80.5 -408.5q0 -187 97.5 -298.5t268.5 -111.5q139 0 322 57v-149q-86 -31 -164 -45t-188 -14q-242 0 -380 149.5t-138 407.5z" /> -<glyph unicode="D" horiz-adv-x="1364" d="M86 0l309 1462h342q276 0 419.5 -149.5t143.5 -435.5q0 -261 -105 -461t-300 -308t-457 -108h-352zM287 147h162q202 0 355 91.5t234.5 258.5t81.5 382t-103 325.5t-302 110.5h-178z" /> -<glyph unicode="E" horiz-adv-x="1047" d="M86 0l309 1462h735l-32 -153h-566l-98 -469h527l-29 -152h-529l-114 -536h565l-33 -152h-735z" /> -<glyph unicode="F" horiz-adv-x="967" d="M86 0l309 1462h735l-30 -153h-568l-110 -533h528l-32 -153h-529l-131 -623h-172z" /> -<glyph unicode="G" horiz-adv-x="1386" d="M150 528q0 269 101.5 489.5t281.5 343t399 122.5q117 0 219.5 -20t206.5 -64l-66 -152q-77 34 -165.5 59t-194.5 25q-169 0 -307.5 -101.5t-215.5 -283.5t-77 -407q0 -190 102.5 -299t286.5 -109q154 0 260 39l96 444h-289l33 152h459l-154 -711q-216 -75 -419 -75 q-264 0 -410.5 144.5t-146.5 403.5z" /> -<glyph unicode="H" horiz-adv-x="1389" d="M86 0l309 1462h170l-131 -622h660l133 622h168l-310 -1462h-167l143 688h-660l-145 -688h-170z" /> -<glyph unicode="I" horiz-adv-x="559" d="M86 0l311 1462h168l-311 -1462h-168z" /> -<glyph unicode="J" horiz-adv-x="547" d="M-319 -360l6 147q69 -20 145 -20q100 0 165.5 62.5t90.5 182.5l307 1450h170l-309 -1468q-79 -379 -422 -379q-105 0 -153 25z" /> -<glyph unicode="K" horiz-adv-x="1141" d="M86 0l309 1462h170l-151 -710l700 710h209l-639 -637l350 -825h-186q-72 181 -146.5 359.5t-146.5 361.5l-174 -131l-125 -590h-170z" /> -<glyph unicode="L" horiz-adv-x="971" d="M86 0l309 1462h170l-276 -1308h565l-33 -154h-735z" /> -<glyph unicode="M" horiz-adv-x="1714" d="M84 0l309 1462h244l149 -1204h9l659 1204h266l-303 -1462h-174q126 590 193 905.5t94 392.5h-6l-717 -1298h-131l-166 1296h-8q-7 -72 -28.5 -197.5t-37.5 -199.5l-190 -899h-162z" /> -<glyph unicode="N" horiz-adv-x="1438" d="M84 0l309 1462h180l459 -1220h6q30 224 72 405l174 815h164l-309 -1462h-181l-460 1223h-6q-32 -221 -74 -418l-172 -805h-162z" /> -<glyph unicode="O" horiz-adv-x="1475" d="M150 549q0 264 96 482t263.5 336t377.5 118q244 0 384 -154t140 -424q0 -269 -88 -481.5t-252 -329t-379 -116.5q-256 0 -399 149.5t-143 419.5zM332 553q0 -199 98 -310.5t266 -111.5q152 0 272.5 97.5t190.5 279.5t70 403q0 199 -94 310.5t-261 111.5q-157 0 -281 -101 t-192.5 -281t-68.5 -398z" /> -<glyph unicode="P" horiz-adv-x="1159" d="M86 0l309 1462h330q214 0 324 -94.5t110 -282.5q0 -248 -164 -379t-481 -131h-135l-123 -575h-170zM410 721h133q216 0 328 91t112 267q0 125 -69.5 180.5t-213.5 55.5h-163z" /> -<glyph unicode="Q" horiz-adv-x="1475" d="M150 549q0 264 96 482t263.5 336t377.5 118q244 0 384 -154t140 -424q0 -333 -139 -576t-375 -321l274 -358h-219l-227 330l-17 -2h-16q-256 0 -399 149.5t-143 419.5zM332 553q0 -199 98 -310.5t266 -111.5q158 0 279 100t187.5 280.5t66.5 399.5q0 199 -94 310.5 t-261 111.5q-157 0 -281 -101t-192.5 -281t-68.5 -398z" /> -<glyph unicode="R" horiz-adv-x="1165" d="M86 0l309 1462h320q446 0 446 -366q0 -348 -368 -449l239 -647h-186l-209 608h-252l-129 -608h-170zM416 754h168q193 0 297 85t104 244q0 121 -67.5 175.5t-219.5 54.5h-166q-102 -494 -116 -559z" /> -<glyph unicode="S" horiz-adv-x="1028" d="M39 43v170q162 -84 340 -84q162 0 257 75.5t95 207.5q0 78 -52.5 137.5t-195.5 140.5q-151 85 -209.5 170t-58.5 201q0 187 132 304.5t347 117.5q99 0 184.5 -19t180.5 -65l-66 -150q-66 38 -148 60t-151 22q-134 0 -215.5 -69.5t-81.5 -188.5q0 -54 17 -92.5t54 -72.5 t142 -95q147 -88 198.5 -138t78 -110.5t26.5 -140.5q0 -211 -140.5 -327.5t-395.5 -116.5q-106 0 -186.5 14.5t-151.5 48.5z" /> -<glyph unicode="T" horiz-adv-x="1020" d="M186 1311l33 151h985l-30 -151h-408l-279 -1311h-172l277 1311h-406z" /> -<glyph unicode="U" horiz-adv-x="1384" d="M164 383q0 81 24 201l189 878h170l-191 -891q-22 -106 -22 -188q0 -117 73 -184.5t218 -67.5q172 0 267.5 87.5t139.5 289.5l205 954h170l-205 -966q-55 -263 -197.5 -389.5t-388.5 -126.5q-230 0 -341 104t-111 299z" /> -<glyph unicode="V" horiz-adv-x="1122" d="M188 1462h170l97 -930q20 -196 20 -335h4q61 144 162 338l479 927h191l-781 -1462h-180z" /> -<glyph unicode="W" horiz-adv-x="1745" d="M223 1462h170l31 -901l2 -88q0 -98 -10 -258h6q89 243 156 383l405 864h178l43 -860q9 -153 9 -304l-1 -83h9q75 224 131 354l387 893h182l-664 -1462h-170l-49 965q-8 136 -8 282h-6q-25 -72 -61 -154.5t-504 -1092.5h-174z" /> -<glyph unicode="X" horiz-adv-x="1063" d="M-104 0l596 776l-263 686h172l203 -563l443 563h186l-555 -694l278 -768h-180l-213 641l-481 -641h-186z" /> -<glyph unicode="Y" horiz-adv-x="1030" d="M188 1462h170l179 -747l489 747h193l-627 -921l-113 -541h-172l119 549z" /> -<glyph unicode="Z" horiz-adv-x="1087" d="M-16 0l28 137l924 1170h-655l32 155h858l-26 -139l-924 -1169h697l-33 -154h-901z" /> -<glyph unicode="[" horiz-adv-x="586" d="M-16 -324l381 1786h387l-31 -141h-227l-318 -1503h227l-32 -142h-387z" /> -<glyph unicode="\" horiz-adv-x="717" d="M221 1462h154l217 -1462h-154z" /> -<glyph unicode="]" horiz-adv-x="586" d="M-150 -324l31 142h225l320 1503h-227l30 141h389l-380 -1786h-388z" /> -<glyph unicode="^" horiz-adv-x="1059" d="M53 553l598 920h109l266 -920h-145l-201 747l-467 -747h-160z" /> -<glyph unicode="_" horiz-adv-x="807" d="M-188 -324l30 140h811l-30 -140h-811z" /> -<glyph unicode="`" horiz-adv-x="1135" d="M575 1548v21h181q43 -136 147 -303v-25h-104q-61 61 -128.5 154t-95.5 153z" /> -<glyph unicode="a" horiz-adv-x="1157" d="M98 350q0 208 71 386t196 279t274 101q92 0 164 -49.5t112 -142.5h11l67 172h127l-233 -1096h-133l26 209h-8q-179 -229 -377 -229q-139 0 -218 99t-79 271zM270 346q0 -114 47 -170.5t132 -56.5q97 0 193 92.5t156 241t60 297.5q0 103 -56 164t-147 61 q-104 0 -193.5 -86t-140.5 -233t-51 -310z" /> -<glyph unicode="b" horiz-adv-x="1182" d="M59 0l330 1556h168q-51 -242 -78.5 -370.5t-75.5 -300.5h9q93 118 183.5 173.5t186.5 55.5q141 0 220 -99t79 -272q0 -209 -68.5 -386.5t-191 -277t-276.5 -99.5q-97 0 -170.5 51t-110.5 139h-10l-70 -170h-125zM319 346q0 -110 55.5 -168.5t160.5 -58.5q99 0 184.5 81 t137.5 230.5t52 317.5q0 227 -178 227q-96 0 -195.5 -95t-158 -239t-58.5 -295z" /> -<glyph unicode="c" horiz-adv-x="922" d="M98 389q0 200 74 369t204.5 263.5t293.5 94.5q137 0 268 -51l-47 -141q-120 51 -219 51q-112 0 -204.5 -76.5t-145 -213t-52.5 -296.5q0 -128 66.5 -199t183.5 -71q72 0 136 20t126 47v-143q-124 -63 -276 -63q-194 0 -301 107t-107 302z" /> -<glyph unicode="d" horiz-adv-x="1182" d="M98 350q0 214 72 392t194.5 275t274.5 97q194 0 281 -190h10q17 155 45 274l78 358h166l-330 -1556h-139l22 209h-8q-101 -125 -189 -177t-182 -52q-139 0 -217 98t-78 272zM270 346q0 -227 179 -227q94 0 194 93.5t158.5 239t58.5 296.5q0 111 -54 169t-157 58 q-101 0 -187.5 -82.5t-139 -232t-52.5 -314.5z" /> -<glyph unicode="e" horiz-adv-x="1010" d="M98 391q0 188 74.5 360.5t197.5 268.5t271 96q153 0 230 -66.5t77 -185.5q0 -180 -166 -282.5t-475 -102.5h-33l-4 -80q0 -131 61.5 -204.5t190.5 -73.5q63 0 129.5 18t165.5 66v-146q-94 -44 -166 -61.5t-159 -17.5q-184 0 -289 109t-105 302zM299 618h12 q228 0 349.5 59.5t121.5 172.5q0 53 -36.5 88t-114.5 35q-103 0 -193.5 -94t-138.5 -261z" /> -<glyph unicode="f" horiz-adv-x="641" d="M-229 -330q64 -22 112 -22q76 0 117 62t66 177l227 1082h-193l13 67l206 66l23 100q46 200 127.5 282.5t241.5 82.5q40 0 98 -11.5t90 -25.5l-43 -129q-76 29 -137 29q-87 0 -133.5 -48.5t-75.5 -177.5l-25 -108h238l-25 -127h-237l-232 -1098q-39 -189 -120 -276 t-213 -87q-69 0 -125 21v141z" /> -<glyph unicode="g" horiz-adv-x="1026" d="M-127 -211q0 105 72 182t233 131q-78 41 -78 121q0 69 51 118.5t142 92.5q-63 32 -103 94.5t-40 145.5q0 194 119.5 318t305.5 124q78 0 154 -20h371l-25 -107l-211 -24q41 -62 41 -158q0 -191 -116.5 -304.5t-311.5 -113.5q-55 0 -84 8q-139 -53 -139 -131 q0 -41 33 -54.5t96 -21.5l117 -14q181 -22 262.5 -88t81.5 -194q0 -184 -146 -285t-411 -101q-194 0 -304 73.5t-110 207.5zM35 -195q0 -77 65 -122t193 -45q182 0 284.5 63.5t102.5 179.5q0 62 -54 98t-184 50l-159 16q-120 -25 -184 -88t-64 -152zM313 680 q0 -85 45 -129.5t125 -44.5q79 0 138 42t90.5 115.5t31.5 159.5q0 82 -44 125t-126 43q-78 0 -136.5 -40.5t-91 -113t-32.5 -157.5z" /> -<glyph unicode="h" horiz-adv-x="1182" d="M59 0l330 1556h168q-18 -82 -34.5 -159t-34 -156.5t-38 -166.5t-47.5 -189h11q94 123 185.5 176t191.5 53q131 0 202.5 -72t71.5 -204q0 -62 -23 -166q-39 -193 -145 -672h-168l148 692q18 94 18 135q0 148 -147 148q-89 0 -173.5 -59t-149 -171.5t-97.5 -271.5 l-101 -473h-168z" /> -<glyph unicode="i" horiz-adv-x="520" d="M59 0l234 1096h168l-234 -1096h-168zM340 1376q0 56 32 91.5t83 35.5q88 0 88 -90q0 -55 -33.5 -93t-77.5 -38q-40 0 -66 24.5t-26 69.5z" /> -<glyph unicode="j" horiz-adv-x="520" d="M-258 -330q61 -22 119 -22q125 0 168 205l264 1243h166l-266 -1258q-36 -171 -114.5 -250.5t-213.5 -79.5q-69 0 -123 21v141zM340 1376q0 56 32 91.5t83 35.5q86 0 86 -90q0 -55 -33.5 -93t-77.5 -38q-38 0 -64 24.5t-26 69.5z" /> -<glyph unicode="k" horiz-adv-x="999" d="M57 0l330 1556h170l-129 -602q-57 -266 -102 -395h4l526 537h201l-469 -467l295 -629h-187l-235 524l-152 -123l-82 -401h-170z" /> -<glyph unicode="l" horiz-adv-x="520" d="M57 0l332 1556h168l-332 -1556h-168z" /> -<glyph unicode="m" horiz-adv-x="1786" d="M59 0l234 1096h139l-22 -203h10q87 119 173.5 171t178.5 52q113 0 174 -65t72 -181h8q86 125 183 185.5t196 60.5q127 0 196.5 -68t69.5 -198q0 -68 -22 -178l-144 -672h-170l148 692q20 104 20 146q0 62 -34.5 99.5t-108.5 37.5q-81 0 -160 -58t-138.5 -164.5 t-90.5 -252.5l-107 -500h-168l148 692q18 94 18 135q0 70 -31 109t-106 39q-84 0 -163.5 -60t-140 -171.5t-93.5 -268.5l-101 -475h-168z" /> -<glyph unicode="n" horiz-adv-x="1182" d="M59 0l234 1096h139l-22 -203h10q96 122 185.5 172.5t185.5 50.5q127 0 200.5 -69.5t73.5 -194.5q0 -79 -23 -180l-143 -672h-170l148 692q20 104 20 144q0 63 -35.5 101t-113.5 38q-89 0 -173.5 -60t-149 -171t-97.5 -269l-101 -475h-168z" /> -<glyph unicode="o" horiz-adv-x="1149" d="M98 406q0 190 73 357.5t197 257t275 89.5q190 0 300 -112.5t110 -309.5q0 -188 -72 -355t-195 -258t-278 -91q-192 0 -301 113t-109 309zM270 397q0 -131 63.5 -202.5t182.5 -71.5q104 0 187 73t129.5 207.5t46.5 307.5q0 115 -62.5 186.5t-169.5 71.5q-109 0 -195.5 -74 t-134 -205.5t-47.5 -292.5z" /> -<glyph unicode="p" horiz-adv-x="1182" d="M-43 -492l336 1588h139l-26 -209h8q179 227 372 227q137 0 216 -97.5t79 -273.5q0 -212 -69 -389t-191 -275.5t-276 -98.5q-97 0 -170 50t-113 140h-10l-4 -38q-3 -25 -10.5 -70t-114.5 -554h-166zM319 346q0 -110 55.5 -168.5t160.5 -58.5q99 0 184.5 81t137.5 230.5 t52 317.5q0 227 -178 227q-96 0 -195.5 -95t-158 -239t-58.5 -295z" /> -<glyph unicode="q" horiz-adv-x="1182" d="M98 350q0 212 72.5 392t196 277t274.5 97q94 0 165.5 -50.5t108.5 -141.5h13l67 172h125l-336 -1588h-166l101 480q9 45 57 221h-8q-95 -121 -185 -175t-186 -54q-140 0 -219.5 97.5t-79.5 272.5zM270 346q0 -227 179 -227q92 0 190 92t158.5 237t60.5 300 q0 105 -54.5 166t-152.5 61q-101 0 -189 -84.5t-140 -233t-52 -311.5z" /> -<glyph unicode="r" horiz-adv-x="811" d="M59 0l234 1096h139l-22 -203h10q72 95 119 136.5t98.5 64t114.5 22.5q69 0 120 -14l-36 -150q-53 13 -105 13q-91 0 -170.5 -60t-139 -166.5t-87.5 -236.5l-107 -502h-168z" /> -<glyph unicode="s" horiz-adv-x="877" d="M8 49v158q70 -42 151 -65t150 -23q126 0 190 50t64 128q0 57 -35 96t-151 107q-130 73 -184 143t-54 166q0 138 101 222.5t266 84.5q171 0 330 -74l-54 -137l-56 25q-101 43 -220 43q-93 0 -146 -43.5t-53 -112.5q0 -56 35.5 -96t146.5 -103q107 -60 153.5 -103 t69.5 -92.5t23 -111.5q0 -156 -110.5 -243.5t-311.5 -87.5q-169 0 -305 69z" /> -<glyph unicode="t" horiz-adv-x="664" d="M90 969l14 73l185 78l125 228h98l-55 -252h274l-26 -127h-273l-129 -604q-18 -87 -18 -132q0 -56 29 -86t81 -30q55 0 144 26v-129q-34 -14 -84 -24t-80 -10q-125 0 -191.5 59.5t-66.5 177.5q0 66 18 150l127 602h-172z" /> -<glyph unicode="u" horiz-adv-x="1182" d="M113 248q0 62 22 172l146 676h170l-150 -695q-18 -89 -18 -139q0 -143 147 -143q88 0 173 60t150 172t99 270l100 475h166l-231 -1096h-139l22 203h-12q-98 -125 -187 -174t-184 -49q-128 0 -201 69.5t-73 198.5z" /> -<glyph unicode="v" horiz-adv-x="946" d="M98 1096h168l64 -613q24 -258 24 -362h6q127 275 179 371l325 604h178l-591 -1096h-228z" /> -<glyph unicode="w" horiz-adv-x="1468" d="M117 1096h164l18 -594v-88q0 -147 -8 -269h6q47 124 137 322l295 629h182l37 -594q6 -168 6 -262v-53l-2 -42h6q28 86 83 218.5t323 732.5h178l-506 -1096h-205l-32 602q-4 94 -4 172v156h-9l-50 -118l-83 -189l-291 -623h-202z" /> -<glyph unicode="x" horiz-adv-x="979" d="M-74 0l475 565l-239 531h170l174 -412l330 412h194l-455 -539l252 -557h-168l-192 434l-346 -434h-195z" /> -<glyph unicode="y" horiz-adv-x="946" d="M-197 -336q63 -18 131 -18q82 0 140.5 50.5t113.5 149.5l76 136l-166 1114h168l74 -545q10 -69 19.5 -203.5t9.5 -216.5h6q35 87 87 200t77 156l325 609h178l-696 -1282q-93 -172 -184 -239t-219 -67q-72 0 -140 21v135z" /> -<glyph unicode="z" horiz-adv-x="909" d="M-29 0l23 117l694 854h-479l27 125h657l-29 -140l-680 -831h531l-25 -125h-719z" /> -<glyph unicode="{" horiz-adv-x="715" d="M27 514l32 143q118 0 189.5 43.5t93.5 147.5l68 326q34 160 117.5 224t254.5 64h33l-31 -141q-105 0 -151 -36.5t-66 -123.5l-71 -321q-28 -123 -91 -184t-167 -78v-5q151 -41 151 -213q0 -59 -18 -131l-47 -211q-15 -58 -15 -98q0 -53 36.5 -77.5t119.5 -24.5v-142h-23 q-141 0 -216.5 52.5t-75.5 171.5q0 52 20 141q33 146 51.5 227.5t14.5 102.5q0 143 -209 143z" /> -<glyph unicode="|" d="M541 -496v2052h139v-2052h-139z" /> -<glyph unicode="}" horiz-adv-x="715" d="M-74 -182q115 0 167 36t71 123l72 322q25 117 88 179.5t170 80.5v6q-150 42 -150 211q0 59 18 131l50 213q14 65 14 99q0 53 -40.5 77.5t-139.5 24.5l28 141h11q144 0 220.5 -52.5t76.5 -170.5q0 -48 -21 -141l-49 -219q-16 -68 -16 -111q0 -143 209 -143l-33 -144 q-119 0 -190 -43t-93 -147l-67 -326q-36 -164 -119 -226.5t-264 -62.5h-13v142z" /> -<glyph unicode="~" d="M115 592v151q98 109 243 109q69 0 127 -14.5t144 -51.5q64 -27 112.5 -41t98.5 -14q55 0 119.5 33t115.5 88v-150q-100 -110 -244 -110q-72 0 -135 16.5t-135 48.5q-75 32 -120 44t-93 12q-54 0 -118.5 -34.5t-114.5 -86.5z" /> -<glyph unicode="¡" horiz-adv-x="530" d="M-14 -373l274 1057h109l-176 -1057h-207zM250 950q0 76 40.5 122t110.5 46q44 0 70.5 -26t26.5 -80q0 -71 -40.5 -117.5t-105.5 -46.5q-48 0 -75 25.5t-27 76.5z" /> -<glyph unicode="¢" d="M225 590q0 185 63.5 344t178.5 258.5t260 120.5l35 170h123l-37 -168q119 -9 217 -49l-47 -142q-109 52 -219 52q-112 0 -204.5 -76.5t-145 -213t-52.5 -296.5q0 -125 66 -198t184 -73q72 0 136 20t126 48v-143q-123 -62 -286 -66l-41 -198h-125l43 215 q-132 34 -203.5 137.5t-71.5 257.5z" /> -<glyph unicode="£" d="M-23 0l27 141q205 46 258 289l47 221h-200l26 127h201l76 350q75 353 430 353q184 0 336 -86l-66 -133q-146 79 -278 79q-213 0 -263 -237l-69 -326h370l-26 -127h-371l-47 -219q-22 -98 -66 -166.5t-124 -111.5h725l-33 -154h-953z" /> -<glyph unicode="¤" d="M168 1067l92 92l127 -129q103 70 217 70t215 -70l129 129l92 -90l-129 -129q70 -104 70 -217q0 -119 -70 -217l127 -127l-90 -90l-129 127q-98 -68 -215 -68q-119 0 -217 70l-127 -127l-90 90l127 127q-68 96 -68 215q0 117 68 215zM358 723q0 -103 71.5 -174.5 t174.5 -71.5q104 0 177 71.5t73 174.5q0 104 -73 177t-177 73q-102 0 -174 -72.5t-72 -177.5z" /> -<glyph unicode="¥" d="M127 266l29 133h290l33 160h-291l29 133h225l-202 770h163l179 -747l491 747h187l-533 -770h231l-28 -133h-297l-33 -160h297l-29 -133h-295l-57 -266h-154l56 266h-291z" /> -<glyph unicode="¦" d="M541 281h139v-777h-139v777zM541 780v776h139v-776h-139z" /> -<glyph unicode="§" horiz-adv-x="995" d="M59 53v148q56 -34 136.5 -56t156.5 -22q133 0 204 44.5t71 129.5q0 48 -50.5 89t-152.5 87q-138 61 -194 130.5t-56 166.5q0 201 238 307q-119 70 -119 203q0 127 103.5 206t279.5 79q189 0 321 -68l-53 -123q-148 60 -266 60q-102 0 -162.5 -40.5t-60.5 -109.5 q0 -49 38 -83.5t162 -90.5q100 -44 149 -83.5t75 -89.5t26 -114q0 -97 -61 -180t-172 -139q114 -71 114 -189q0 -152 -114 -237.5t-318 -85.5q-176 0 -295 61zM326 791q0 -70 50.5 -117t198.5 -111q80 44 127.5 107t47.5 131q0 60 -49.5 105.5t-186.5 103.5 q-82 -26 -135 -87.5t-53 -131.5z" /> -<glyph unicode="¨" horiz-adv-x="1135" d="M457 1378q0 46 28 79.5t74 33.5q78 0 78 -80q0 -49 -29.5 -83t-68.5 -34q-35 0 -58.5 22t-23.5 62zM821 1378q0 46 28 79.5t75 33.5q77 0 77 -80q0 -49 -29.5 -83t-68.5 -34q-35 0 -58.5 22t-23.5 62z" /> -<glyph unicode="©" horiz-adv-x="1704" d="M139 731q0 200 100 375t275 276t377 101q197 0 370 -97t277 -272t104 -383q0 -204 -100.5 -376.5t-273 -273.5t-377.5 -101q-207 0 -382 103.5t-272.5 276.5t-97.5 371zM244 731q0 -173 87 -323.5t237.5 -237t322.5 -86.5q174 0 323 87t236.5 235.5t87.5 324.5 q0 174 -87 323t-235.5 236.5t-324.5 87.5q-174 0 -323 -87t-236.5 -235.5t-87.5 -324.5zM520 733q0 208 110 330.5t300 122.5q130 0 248 -60l-60 -120q-106 53 -190 53q-125 0 -191.5 -87t-66.5 -241q0 -169 65 -249.5t193 -80.5q82 0 211 43v-122q-66 -28 -113 -38 t-104 -10q-192 0 -297 119.5t-105 339.5z" /> -<glyph unicode="ª" horiz-adv-x="686" d="M170 1014q0 127 41.5 234.5t116.5 169t170 61.5q114 0 153 -103h6l37 90h86l-139 -665h-92l14 117h-4q-40 -56 -90 -93t-123 -37q-77 0 -126.5 60t-49.5 166zM283 1030q0 -139 98 -139q61 0 112.5 49t86 137.5t34.5 167.5q0 62 -28.5 96.5t-85.5 34.5q-92 0 -154.5 -103 t-62.5 -243z" /> -<glyph unicode="«" horiz-adv-x="958" d="M88 555v29l391 374l78 -81l-297 -328l172 -387l-113 -49zM483 510v31l367 405l86 -69l-283 -365l158 -350l-113 -49z" /> -<glyph unicode="¬" d="M127 651v142h920v-529h-140v387h-780z" /> -<glyph unicode="­" horiz-adv-x="639" d="M55 469l35 158h479l-34 -158h-480z" /> -<glyph unicode="®" horiz-adv-x="1704" d="M139 731q0 200 100 375t275 276t377 101q197 0 370 -97t277 -272t104 -383q0 -204 -100.5 -376.5t-273 -273.5t-377.5 -101q-207 0 -382 103.5t-272.5 276.5t-97.5 371zM244 731q0 -173 87 -323.5t237.5 -237t322.5 -86.5q174 0 323 87t236.5 235.5t87.5 324.5 q0 174 -87 323t-235.5 236.5t-324.5 87.5q-174 0 -323 -87t-236.5 -235.5t-87.5 -324.5zM645 291v880h229q163 0 241.5 -63t78.5 -193q0 -78 -47.5 -141t-132.5 -98l227 -385h-149l-207 352h-113v-352h-127zM772 762h92q195 0 195 149q0 76 -47.5 107t-149.5 31h-90v-287z " /> -<glyph unicode="¯" horiz-adv-x="782" d="M227 1556l33 132h787l-35 -132h-785z" /> -<glyph unicode="°" horiz-adv-x="877" d="M215 1171q0 128 90.5 220t220.5 92q83 0 155.5 -41.5t114.5 -114t42 -156.5q0 -128 -90.5 -218.5t-221.5 -90.5t-221 90.5t-90 218.5zM328 1171q0 -80 58 -138t140 -58q83 0 140 58.5t57 137.5q0 82 -57.5 140.5t-139.5 58.5q-80 0 -139 -58.5t-59 -140.5z" /> -<glyph unicode="±" d="M127 0v141h920v-141h-920zM127 643v141h389v392h141v-392h390v-141h-390v-387h-141v387h-389z" /> -<glyph unicode="²" horiz-adv-x="717" d="M96 586l23 106l264 228q115 100 158.5 149.5t63.5 93t20 90.5q0 53 -31 85t-90 32q-90 0 -195 -80l-59 90q125 101 274 101q109 0 171.5 -56.5t62.5 -150.5q0 -99 -52.5 -179.5t-197.5 -205.5l-221 -187h395l-25 -116h-561z" /> -<glyph unicode="³" horiz-adv-x="717" d="M119 625v127q125 -72 239 -72q205 0 205 170q0 137 -178 137h-90l22 107h95q97 0 155 41t58 112q0 60 -34.5 90.5t-93.5 30.5q-102 0 -196 -68l-55 93q109 88 268 88q114 0 178 -56t64 -151q0 -180 -207 -234v-4q69 -17 108 -68t39 -120q0 -132 -91 -205.5t-253 -73.5 q-125 0 -233 56z" /> -<glyph unicode="´" horiz-adv-x="1135" d="M532 1241v27q56 60 125.5 151.5t106.5 149.5h190v-21q-38 -49 -140 -151t-177 -156h-105z" /> -<glyph unicode="µ" horiz-adv-x="1194" d="M-43 -492l336 1588h168l-148 -695q-18 -92 -18 -135q0 -147 147 -147q89 0 172 59t148.5 171t99.5 269l105 478h163l-233 -1096h-139l24 205h-12q-93 -121 -183 -173t-188 -52q-112 0 -163 96h-9q-11 -78 -22.5 -148t-83.5 -420h-164z" /> -<glyph unicode="¶" horiz-adv-x="1341" d="M199 1042q0 260 109 387t341 127h557v-1816h-114v1661h-213v-1661h-115v819q-62 -18 -146 -18q-216 0 -317.5 125t-101.5 376z" /> -<glyph unicode="·" horiz-adv-x="518" d="M170 690q0 77 40.5 122.5t111.5 45.5q43 0 69.5 -26t26.5 -79q0 -71 -40 -118.5t-108 -47.5q-46 0 -73 26t-27 77z" /> -<glyph unicode="¸" horiz-adv-x="420" d="M-170 -383q38 -6 68 -6q174 0 174 110q0 46 -39 67.5t-99 29.5l101 182h106l-61 -121q131 -38 131 -155q0 -98 -81 -157t-214 -59q-41 0 -86 9v100z" /> -<glyph unicode="¹" horiz-adv-x="717" d="M258 1280l279 182h118l-186 -876h-135l112 526q25 103 58 225q-25 -25 -50 -46.5t-145 -100.5z" /> -<glyph unicode="º" horiz-adv-x="688" d="M168 1055q0 117 42 215.5t117.5 153.5t174.5 55q117 0 180 -67t63 -193q0 -191 -88.5 -311t-240.5 -120q-113 0 -180.5 71t-67.5 196zM281 1059q0 -85 38 -127.5t107 -42.5q94 0 152.5 88.5t58.5 232.5q0 166 -137 166q-102 0 -160.5 -87.5t-58.5 -229.5z" /> -<glyph unicode="»" horiz-adv-x="958" d="M23 197l282 360l-158 354l113 50l217 -402v-31l-368 -401zM401 197l297 323l-172 391l113 50l233 -447v-29l-393 -370z" /> -<glyph unicode="¼" horiz-adv-x="1518" d="M123 0l1085 1462h154l-1086 -1462h-153zM204 1280l279 182h118l-186 -876h-135l112 526q25 103 58 225q-25 -25 -50 -46.5t-145 -100.5zM706 203l23 101l481 579h133l-121 -563h127l-22 -117h-129l-43 -202h-127l43 202h-365zM870 320h225q69 322 90 395 q-20 -36 -110 -149z" /> -<glyph unicode="½" horiz-adv-x="1518" d="M148 1280l279 182h118l-186 -876h-135l112 526q25 103 58 225q-25 -25 -50 -46.5t-145 -100.5zM66 0l1085 1462h154l-1086 -1462h-153zM782 1l23 106l264 228q115 100 158.5 149.5t63.5 93t20 90.5q0 53 -31 85t-90 32q-90 0 -195 -80l-59 90q125 101 274 101 q109 0 171.5 -56.5t62.5 -150.5q0 -99 -52.5 -179.5t-197.5 -205.5l-221 -187h395l-25 -116h-561z" /> -<glyph unicode="¾" horiz-adv-x="1565" d="M87 625v127q125 -72 239 -72q205 0 205 170q0 137 -178 137h-90l22 107h95q97 0 155 41t58 112q0 60 -34.5 90.5t-93.5 30.5q-102 0 -196 -68l-55 93q109 88 268 88q114 0 178 -56t64 -151q0 -180 -207 -234v-4q69 -17 108 -68t39 -120q0 -132 -91 -205.5t-253 -73.5 q-125 0 -233 56zM273 0l1085 1462h154l-1086 -1462h-153zM856 203l23 101l481 579h133l-121 -563h127l-22 -117h-129l-43 -202h-127l43 202h-365zM1020 320h225q69 322 90 395q-20 -36 -110 -149z" /> -<glyph unicode="¿" horiz-adv-x="874" d="M-4 -78q0 124 66 228t225 223q132 98 172.5 152.5t62.5 154.5h135q-22 -130 -72 -212t-165 -175l-95 -75q-159 -127 -159 -275q0 -93 51.5 -144t147.5 -51q80 0 154 25.5t140 56.5l62 -129q-90 -48 -189 -74t-186 -26q-168 0 -259 83.5t-91 237.5zM512 946q0 71 40 118.5 t107 47.5q47 0 74 -25.5t27 -76.5q0 -77 -40.5 -122.5t-111.5 -45.5q-43 0 -69.5 26t-26.5 78z" /> -<glyph unicode="À" horiz-adv-x="1137" d="M-117 0l799 1462h174l184 -1462h-170l-57 465h-496l-245 -465h-189zM401 621h394l-35 299q-24 179 -29 350q-37 -88 -80.5 -175t-249.5 -474zM535 1886v21h181q43 -136 147 -303v-25h-104q-61 61 -128.5 154t-95.5 153z" /> -<glyph unicode="Á" horiz-adv-x="1137" d="M-117 0l799 1462h174l184 -1462h-170l-57 465h-496l-245 -465h-189zM401 621h394l-35 299q-24 179 -29 350q-37 -88 -80.5 -175t-249.5 -474zM679 1579v27q56 60 125.5 151.5t106.5 149.5h190v-21q-38 -49 -140 -151t-177 -156h-105z" /> -<glyph unicode="Â" horiz-adv-x="1137" d="M-117 0l799 1462h174l184 -1462h-170l-57 465h-496l-245 -465h-189zM401 621h394l-35 299q-24 179 -29 350q-37 -88 -80.5 -175t-249.5 -474zM465 1579v27q145 133 204.5 197.5t82.5 103.5h158q37 -99 128 -235l42 -66v-27h-103q-57 48 -161 189q-134 -119 -242 -189 h-109z" /> -<glyph unicode="Ã" horiz-adv-x="1137" d="M-117 0l799 1462h174l184 -1462h-170l-57 465h-496l-245 -465h-189zM401 621h394l-35 299q-24 179 -29 350q-37 -88 -80.5 -175t-249.5 -474zM432 1579q58 258 231 258q44 0 83.5 -18t75 -39.5t66.5 -39.5t58 -18q44 0 69.5 27t51.5 90h100q-66 -258 -233 -258 q-40 0 -77.5 17.5t-73 39t-69 39t-65.5 17.5q-44 0 -69.5 -28.5t-47.5 -86.5h-100z" /> -<glyph unicode="Ä" horiz-adv-x="1137" d="M-117 0l799 1462h174l184 -1462h-170l-57 465h-496l-245 -465h-189zM401 621h394l-35 299q-24 179 -29 350q-37 -88 -80.5 -175t-249.5 -474zM523 1716q0 46 28 79.5t74 33.5q78 0 78 -80q0 -49 -29.5 -83t-68.5 -34q-35 0 -58.5 22t-23.5 62zM887 1716q0 46 28 79.5 t75 33.5q77 0 77 -80q0 -49 -29.5 -83t-68.5 -34q-35 0 -58.5 22t-23.5 62z" /> -<glyph unicode="Å" horiz-adv-x="1137" d="M-117 0l799 1462h174l184 -1462h-170l-57 465h-496l-245 -465h-189zM401 621h394l-35 299q-24 179 -29 350q-37 -88 -80.5 -175t-249.5 -474zM553 1583q0 94 62 152.5t157 58.5q101 0 160 -57t59 -152q0 -99 -60 -157t-159 -58q-101 0 -160 57.5t-59 155.5zM657 1583 q0 -54 29.5 -84.5t85.5 -30.5q51 0 83 30.5t32 84.5q0 53 -32 84t-83 31q-49 0 -82 -31t-33 -84z" /> -<glyph unicode="Æ" horiz-adv-x="1673" d="M-119 0l938 1462h938l-33 -153h-565l-100 -469h528l-28 -150h-529l-115 -538h566l-33 -152h-737l98 465h-438l-293 -465h-197zM469 621h371l147 688h-84z" /> -<glyph unicode="Ç" horiz-adv-x="1198" d="M150 537q0 261 105.5 485.5t283.5 342.5t403 118q197 0 348 -80l-69 -141q-138 69 -279 69q-174 0 -311.5 -97t-218 -284.5t-80.5 -408.5q0 -187 97.5 -298.5t268.5 -111.5q139 0 322 57v-149q-86 -31 -164 -45t-188 -14q-242 0 -380 149.5t-138 407.5zM377 -383 q38 -6 68 -6q174 0 174 110q0 46 -39 67.5t-99 29.5l101 182h106l-61 -121q131 -38 131 -155q0 -98 -81 -157t-214 -59q-41 0 -86 9v100z" /> -<glyph unicode="È" horiz-adv-x="1047" d="M86 0l309 1462h735l-32 -153h-566l-98 -469h527l-29 -152h-529l-114 -536h565l-33 -152h-735zM570 1886v21h181q43 -136 147 -303v-25h-104q-61 61 -128.5 154t-95.5 153z" /> -<glyph unicode="É" horiz-adv-x="1047" d="M86 0l309 1462h735l-32 -153h-566l-98 -469h527l-29 -152h-529l-114 -536h565l-33 -152h-735zM657 1579v27q56 60 125.5 151.5t106.5 149.5h190v-21q-38 -49 -140 -151t-177 -156h-105z" /> -<glyph unicode="Ê" horiz-adv-x="1047" d="M86 0l309 1462h735l-32 -153h-566l-98 -469h527l-29 -152h-529l-114 -536h565l-33 -152h-735zM469 1579v27q145 133 204.5 197.5t82.5 103.5h158q37 -99 128 -235l42 -66v-27h-103q-57 48 -161 189q-134 -119 -242 -189h-109z" /> -<glyph unicode="Ë" horiz-adv-x="1047" d="M86 0l309 1462h735l-32 -153h-566l-98 -469h527l-29 -152h-529l-114 -536h565l-33 -152h-735zM523 1716q0 46 28 79.5t74 33.5q78 0 78 -80q0 -49 -29.5 -83t-68.5 -34q-35 0 -58.5 22t-23.5 62zM887 1716q0 46 28 79.5t75 33.5q77 0 77 -80q0 -49 -29.5 -83t-68.5 -34 q-35 0 -58.5 22t-23.5 62z" /> -<glyph unicode="Ì" horiz-adv-x="559" d="M86 0l311 1462h168l-311 -1462h-168zM265 1886v21h181q43 -136 147 -303v-25h-104q-61 61 -128.5 154t-95.5 153z" /> -<glyph unicode="Í" horiz-adv-x="559" d="M86 0l311 1462h168l-311 -1462h-168zM412 1579v27q56 60 125.5 151.5t106.5 149.5h190v-21q-38 -49 -140 -151t-177 -156h-105z" /> -<glyph unicode="Î" horiz-adv-x="559" d="M86 0l311 1462h168l-311 -1462h-168zM193 1579v27q145 133 204.5 197.5t82.5 103.5h158q37 -99 128 -235l42 -66v-27h-103q-57 48 -161 189q-134 -119 -242 -189h-109z" /> -<glyph unicode="Ï" horiz-adv-x="559" d="M86 0l311 1462h168l-311 -1462h-168zM265 1716q0 46 28 79.5t74 33.5q78 0 78 -80q0 -49 -29.5 -83t-68.5 -34q-35 0 -58.5 22t-23.5 62zM629 1716q0 46 28 79.5t75 33.5q77 0 77 -80q0 -49 -29.5 -83t-68.5 -34q-35 0 -58.5 22t-23.5 62z" /> -<glyph unicode="Ð" horiz-adv-x="1364" d="M72 649l32 150h150l141 663h342q276 0 419.5 -149.5t143.5 -435.5q0 -261 -105 -461t-300 -308t-457 -108h-352l135 649h-149zM287 147h162q202 0 355 91.5t234.5 258.5t81.5 382t-103 325.5t-302 110.5h-178l-111 -516h330l-33 -150h-330z" /> -<glyph unicode="Ñ" horiz-adv-x="1438" d="M84 0l309 1462h180l459 -1220h6q30 224 72 405l174 815h164l-309 -1462h-181l-460 1223h-6q-32 -221 -74 -418l-172 -805h-162zM600 1579q58 258 231 258q44 0 83.5 -18t75 -39.5t66.5 -39.5t58 -18q44 0 69.5 27t51.5 90h100q-66 -258 -233 -258q-40 0 -77.5 17.5 t-73 39t-69 39t-65.5 17.5q-44 0 -69.5 -28.5t-47.5 -86.5h-100z" /> -<glyph unicode="Ò" horiz-adv-x="1475" d="M150 549q0 264 96 482t263.5 336t377.5 118q244 0 384 -154t140 -424q0 -269 -88 -481.5t-252 -329t-379 -116.5q-256 0 -399 149.5t-143 419.5zM332 553q0 -199 98 -310.5t266 -111.5q152 0 272.5 97.5t190.5 279.5t70 403q0 199 -94 310.5t-261 111.5q-157 0 -281 -101 t-192.5 -281t-68.5 -398zM679 1886v21h181q43 -136 147 -303v-25h-104q-61 61 -128.5 154t-95.5 153z" /> -<glyph unicode="Ó" horiz-adv-x="1475" d="M150 549q0 264 96 482t263.5 336t377.5 118q244 0 384 -154t140 -424q0 -269 -88 -481.5t-252 -329t-379 -116.5q-256 0 -399 149.5t-143 419.5zM332 553q0 -199 98 -310.5t266 -111.5q152 0 272.5 97.5t190.5 279.5t70 403q0 199 -94 310.5t-261 111.5q-157 0 -281 -101 t-192.5 -281t-68.5 -398zM821 1579v27q56 60 125.5 151.5t106.5 149.5h190v-21q-38 -49 -140 -151t-177 -156h-105z" /> -<glyph unicode="Ô" horiz-adv-x="1475" d="M150 549q0 264 96 482t263.5 336t377.5 118q244 0 384 -154t140 -424q0 -269 -88 -481.5t-252 -329t-379 -116.5q-256 0 -399 149.5t-143 419.5zM332 553q0 -199 98 -310.5t266 -111.5q152 0 272.5 97.5t190.5 279.5t70 403q0 199 -94 310.5t-261 111.5q-157 0 -281 -101 t-192.5 -281t-68.5 -398zM612 1579v27q145 133 204.5 197.5t82.5 103.5h158q37 -99 128 -235l42 -66v-27h-103q-57 48 -161 189q-134 -119 -242 -189h-109z" /> -<glyph unicode="Õ" horiz-adv-x="1475" d="M150 549q0 264 96 482t263.5 336t377.5 118q244 0 384 -154t140 -424q0 -269 -88 -481.5t-252 -329t-379 -116.5q-256 0 -399 149.5t-143 419.5zM332 553q0 -199 98 -310.5t266 -111.5q152 0 272.5 97.5t190.5 279.5t70 403q0 199 -94 310.5t-261 111.5q-157 0 -281 -101 t-192.5 -281t-68.5 -398zM565 1579q58 258 231 258q44 0 83.5 -18t75 -39.5t66.5 -39.5t58 -18q44 0 69.5 27t51.5 90h100q-66 -258 -233 -258q-40 0 -77.5 17.5t-73 39t-69 39t-65.5 17.5q-44 0 -69.5 -28.5t-47.5 -86.5h-100z" /> -<glyph unicode="Ö" horiz-adv-x="1475" d="M150 549q0 264 96 482t263.5 336t377.5 118q244 0 384 -154t140 -424q0 -269 -88 -481.5t-252 -329t-379 -116.5q-256 0 -399 149.5t-143 419.5zM332 553q0 -199 98 -310.5t266 -111.5q152 0 272.5 97.5t190.5 279.5t70 403q0 199 -94 310.5t-261 111.5q-157 0 -281 -101 t-192.5 -281t-68.5 -398zM664 1716q0 46 28 79.5t74 33.5q78 0 78 -80q0 -49 -29.5 -83t-68.5 -34q-35 0 -58.5 22t-23.5 62zM1028 1716q0 46 28 79.5t75 33.5q77 0 77 -80q0 -49 -29.5 -83t-68.5 -34q-35 0 -58.5 22t-23.5 62z" /> -<glyph unicode="×" d="M168 1044l98 99l320 -320l323 320l99 -96l-324 -324l322 -322l-97 -96l-323 320l-320 -318l-96 96l317 320z" /> -<glyph unicode="Ø" horiz-adv-x="1475" d="M119 8l137 170q-106 136 -106 371q0 264 96 482t263.5 336t377.5 118q99 0 178.5 -27t151.5 -84l131 166l114 -92l-149 -184q48 -62 73 -156t25 -201q0 -269 -88 -481.5t-252 -329t-379 -116.5q-200 0 -332 96l-129 -160zM332 553q0 -135 41 -227l737 919q-90 88 -236 88 q-157 0 -281 -101t-192.5 -281t-68.5 -398zM463 205q91 -74 233 -74q152 0 272.5 97.5t190.5 279.5t70 403q0 118 -33 205z" /> -<glyph unicode="Ù" horiz-adv-x="1384" d="M164 383q0 81 24 201l189 878h170l-191 -891q-22 -106 -22 -188q0 -117 73 -184.5t218 -67.5q172 0 267.5 87.5t139.5 289.5l205 954h170l-205 -966q-55 -263 -197.5 -389.5t-388.5 -126.5q-230 0 -341 104t-111 299zM663 1886v21h181q43 -136 147 -303v-25h-104 q-61 61 -128.5 154t-95.5 153z" /> -<glyph unicode="Ú" horiz-adv-x="1384" d="M164 383q0 81 24 201l189 878h170l-191 -891q-22 -106 -22 -188q0 -117 73 -184.5t218 -67.5q172 0 267.5 87.5t139.5 289.5l205 954h170l-205 -966q-55 -263 -197.5 -389.5t-388.5 -126.5q-230 0 -341 104t-111 299zM823 1579v27q56 60 125.5 151.5t106.5 149.5h190v-21 q-38 -49 -140 -151t-177 -156h-105z" /> -<glyph unicode="Û" horiz-adv-x="1384" d="M164 383q0 81 24 201l189 878h170l-191 -891q-22 -106 -22 -188q0 -117 73 -184.5t218 -67.5q172 0 267.5 87.5t139.5 289.5l205 954h170l-205 -966q-55 -263 -197.5 -389.5t-388.5 -126.5q-230 0 -341 104t-111 299zM602 1579v27q145 133 204.5 197.5t82.5 103.5h158 q37 -99 128 -235l42 -66v-27h-103q-57 48 -161 189q-134 -119 -242 -189h-109z" /> -<glyph unicode="Ü" horiz-adv-x="1384" d="M164 383q0 81 24 201l189 878h170l-191 -891q-22 -106 -22 -188q0 -117 73 -184.5t218 -67.5q172 0 267.5 87.5t139.5 289.5l205 954h170l-205 -966q-55 -263 -197.5 -389.5t-388.5 -126.5q-230 0 -341 104t-111 299zM643 1716q0 46 28 79.5t74 33.5q78 0 78 -80 q0 -49 -29.5 -83t-68.5 -34q-35 0 -58.5 22t-23.5 62zM1007 1716q0 46 28 79.5t75 33.5q77 0 77 -80q0 -49 -29.5 -83t-68.5 -34q-35 0 -58.5 22t-23.5 62z" /> -<glyph unicode="Ý" horiz-adv-x="1030" d="M188 1462h170l179 -747l489 747h193l-627 -921l-113 -541h-172l119 549zM616 1579v27q56 60 125.5 151.5t106.5 149.5h190v-21q-38 -49 -140 -151t-177 -156h-105z" /> -<glyph unicode="Þ" horiz-adv-x="1159" d="M86 0l309 1462h170l-53 -256h160q213 0 323.5 -95t110.5 -282q0 -248 -164 -379t-483 -131h-133l-70 -319h-170zM354 465h135q215 0 328 91t113 267q0 126 -70 181t-215 55h-166z" /> -<glyph unicode="ß" horiz-adv-x="1182" d="M-256 -328q61 -22 111 -22q65 0 107 47.5t65 157.5l280 1314q43 200 156 299t307 99q162 0 252 -71t90 -196q0 -57 -21 -106.5t-61.5 -95t-178.5 -150.5q-110 -83 -110 -151q0 -56 95 -122q47 -34 101 -87.5t79.5 -110t25.5 -123.5q0 -175 -108.5 -274.5t-292.5 -99.5 q-175 0 -268 71v160q51 -41 118.5 -66.5t129.5 -25.5q113 0 181 58t68 159q0 40 -10.5 71t-33.5 59t-89 83q-88 69 -122.5 124t-34.5 115q0 53 18.5 96t49.5 78.5t124 104.5q80 56 111 87.5t48 65t17 70.5q0 64 -52.5 100.5t-141.5 36.5q-119 0 -186 -62.5t-95 -190.5 l-274 -1303q-40 -189 -121 -276t-211 -87q-69 0 -123 21v143z" /> -<glyph unicode="à" horiz-adv-x="1157" d="M98 350q0 208 71 386t196 279t274 101q92 0 164 -49.5t112 -142.5h11l67 172h127l-233 -1096h-133l26 209h-8q-179 -229 -377 -229q-139 0 -218 99t-79 271zM270 346q0 -114 47 -170.5t132 -56.5q97 0 193 92.5t156 241t60 297.5q0 103 -56 164t-147 61 q-104 0 -193.5 -86t-140.5 -233t-51 -310zM496 1548v21h181q43 -136 147 -303v-25h-104q-61 61 -128.5 154t-95.5 153z" /> -<glyph unicode="á" horiz-adv-x="1157" d="M98 350q0 208 71 386t196 279t274 101q92 0 164 -49.5t112 -142.5h11l67 172h127l-233 -1096h-133l26 209h-8q-179 -229 -377 -229q-139 0 -218 99t-79 271zM270 346q0 -114 47 -170.5t132 -56.5q97 0 193 92.5t156 241t60 297.5q0 103 -56 164t-147 61 q-104 0 -193.5 -86t-140.5 -233t-51 -310zM600 1241v27q56 60 125.5 151.5t106.5 149.5h190v-21q-38 -49 -140 -151t-177 -156h-105z" /> -<glyph unicode="â" horiz-adv-x="1157" d="M98 350q0 208 71 386t196 279t274 101q92 0 164 -49.5t112 -142.5h11l67 172h127l-233 -1096h-133l26 209h-8q-179 -229 -377 -229q-139 0 -218 99t-79 271zM270 346q0 -114 47 -170.5t132 -56.5q97 0 193 92.5t156 241t60 297.5q0 103 -56 164t-147 61 q-104 0 -193.5 -86t-140.5 -233t-51 -310zM390 1241v27q145 133 204.5 197.5t82.5 103.5h158q37 -99 128 -235l42 -66v-27h-103q-57 48 -161 189q-134 -119 -242 -189h-109z" /> -<glyph unicode="ã" horiz-adv-x="1157" d="M98 350q0 208 71 386t196 279t274 101q92 0 164 -49.5t112 -142.5h11l67 172h127l-233 -1096h-133l26 209h-8q-179 -229 -377 -229q-139 0 -218 99t-79 271zM270 346q0 -114 47 -170.5t132 -56.5q97 0 193 92.5t156 241t60 297.5q0 103 -56 164t-147 61 q-104 0 -193.5 -86t-140.5 -233t-51 -310zM354 1241q58 258 231 258q44 0 83.5 -18t75 -39.5t66.5 -39.5t58 -18q44 0 69.5 27t51.5 90h100q-66 -258 -233 -258q-40 0 -77.5 17.5t-73 39t-69 39t-65.5 17.5q-44 0 -69.5 -28.5t-47.5 -86.5h-100z" /> -<glyph unicode="ä" horiz-adv-x="1157" d="M98 350q0 208 71 386t196 279t274 101q92 0 164 -49.5t112 -142.5h11l67 172h127l-233 -1096h-133l26 209h-8q-179 -229 -377 -229q-139 0 -218 99t-79 271zM270 346q0 -114 47 -170.5t132 -56.5q97 0 193 92.5t156 241t60 297.5q0 103 -56 164t-147 61 q-104 0 -193.5 -86t-140.5 -233t-51 -310zM454 1378q0 46 28 79.5t74 33.5q78 0 78 -80q0 -49 -29.5 -83t-68.5 -34q-35 0 -58.5 22t-23.5 62zM818 1378q0 46 28 79.5t75 33.5q77 0 77 -80q0 -49 -29.5 -83t-68.5 -34q-35 0 -58.5 22t-23.5 62z" /> -<glyph unicode="å" horiz-adv-x="1157" d="M98 350q0 208 71 386t196 279t274 101q92 0 164 -49.5t112 -142.5h11l67 172h127l-233 -1096h-133l26 209h-8q-179 -229 -377 -229q-139 0 -218 99t-79 271zM270 346q0 -114 47 -170.5t132 -56.5q97 0 193 92.5t156 241t60 297.5q0 103 -56 164t-147 61 q-104 0 -193.5 -86t-140.5 -233t-51 -310zM513 1454q0 94 62 152.5t157 58.5q101 0 160 -57t59 -152q0 -99 -60 -157t-159 -58q-101 0 -160 57.5t-59 155.5zM617 1454q0 -54 29.5 -84.5t85.5 -30.5q51 0 83 30.5t32 84.5q0 53 -32 84t-83 31q-49 0 -82 -31t-33 -84z" /> -<glyph unicode="æ" horiz-adv-x="1669" d="M98 348q0 206 70.5 385t191.5 281t263 102q82 0 145 -48.5t102 -143.5h11l67 172h109l-31 -146q123 166 332 166q119 0 192.5 -68t73.5 -184q0 -182 -166.5 -283.5t-472.5 -101.5h-39l-4 -80q0 -131 62.5 -204.5t193.5 -73.5q55 0 116.5 16.5t178.5 67.5v-150 q-164 -75 -328 -75q-108 0 -189.5 39.5t-121.5 119.5l-31 -139h-114l26 209h-8q-109 -132 -191.5 -180.5t-177.5 -48.5q-122 0 -191 99t-69 269zM270 348q0 -114 37 -171.5t105 -57.5q95 0 188.5 91.5t153 240.5t59.5 299q0 103 -45.5 164t-122.5 61q-99 0 -187 -86.5 t-138 -231.5t-50 -309zM973 618h14q226 0 348.5 58.5t122.5 169.5q0 61 -35 94t-98 33q-117 0 -211 -94.5t-141 -260.5z" /> -<glyph unicode="ç" horiz-adv-x="922" d="M98 389q0 200 74 369t204.5 263.5t293.5 94.5q137 0 268 -51l-47 -141q-120 51 -219 51q-112 0 -204.5 -76.5t-145 -213t-52.5 -296.5q0 -128 66.5 -199t183.5 -71q72 0 136 20t126 47v-143q-124 -63 -276 -63q-194 0 -301 107t-107 302zM211 -383q38 -6 68 -6 q174 0 174 110q0 46 -39 67.5t-99 29.5l101 182h106l-61 -121q131 -38 131 -155q0 -98 -81 -157t-214 -59q-41 0 -86 9v100z" /> -<glyph unicode="è" horiz-adv-x="1010" d="M98 391q0 188 74.5 360.5t197.5 268.5t271 96q153 0 230 -66.5t77 -185.5q0 -180 -166 -282.5t-475 -102.5h-33l-4 -80q0 -131 61.5 -204.5t190.5 -73.5q63 0 129.5 18t165.5 66v-146q-94 -44 -166 -61.5t-159 -17.5q-184 0 -289 109t-105 302zM299 618h12 q228 0 349.5 59.5t121.5 172.5q0 53 -36.5 88t-114.5 35q-103 0 -193.5 -94t-138.5 -261zM449 1548v21h181q43 -136 147 -303v-25h-104q-61 61 -128.5 154t-95.5 153z" /> -<glyph unicode="é" horiz-adv-x="1010" d="M98 391q0 188 74.5 360.5t197.5 268.5t271 96q153 0 230 -66.5t77 -185.5q0 -180 -166 -282.5t-475 -102.5h-33l-4 -80q0 -131 61.5 -204.5t190.5 -73.5q63 0 129.5 18t165.5 66v-146q-94 -44 -166 -61.5t-159 -17.5q-184 0 -289 109t-105 302zM299 618h12 q228 0 349.5 59.5t121.5 172.5q0 53 -36.5 88t-114.5 35q-103 0 -193.5 -94t-138.5 -261zM585 1241v27q56 60 125.5 151.5t106.5 149.5h190v-21q-38 -49 -140 -151t-177 -156h-105z" /> -<glyph unicode="ê" horiz-adv-x="1010" d="M98 391q0 188 74.5 360.5t197.5 268.5t271 96q153 0 230 -66.5t77 -185.5q0 -180 -166 -282.5t-475 -102.5h-33l-4 -80q0 -131 61.5 -204.5t190.5 -73.5q63 0 129.5 18t165.5 66v-146q-94 -44 -166 -61.5t-159 -17.5q-184 0 -289 109t-105 302zM299 618h12 q228 0 349.5 59.5t121.5 172.5q0 53 -36.5 88t-114.5 35q-103 0 -193.5 -94t-138.5 -261zM351 1241v27q145 133 204.5 197.5t82.5 103.5h158q37 -99 128 -235l42 -66v-27h-103q-57 48 -161 189q-134 -119 -242 -189h-109z" /> -<glyph unicode="ë" horiz-adv-x="1010" d="M98 391q0 188 74.5 360.5t197.5 268.5t271 96q153 0 230 -66.5t77 -185.5q0 -180 -166 -282.5t-475 -102.5h-33l-4 -80q0 -131 61.5 -204.5t190.5 -73.5q63 0 129.5 18t165.5 66v-146q-94 -44 -166 -61.5t-159 -17.5q-184 0 -289 109t-105 302zM299 618h12 q228 0 349.5 59.5t121.5 172.5q0 53 -36.5 88t-114.5 35q-103 0 -193.5 -94t-138.5 -261zM413 1378q0 46 28 79.5t74 33.5q78 0 78 -80q0 -49 -29.5 -83t-68.5 -34q-35 0 -58.5 22t-23.5 62zM777 1378q0 46 28 79.5t75 33.5q77 0 77 -80q0 -49 -29.5 -83t-68.5 -34 q-35 0 -58.5 22t-23.5 62z" /> -<glyph unicode="ì" horiz-adv-x="520" d="M59 0l234 1096h168l-234 -1096h-168zM164 1548v21h181q43 -136 147 -303v-25h-104q-61 61 -128.5 154t-95.5 153z" /> -<glyph unicode="í" horiz-adv-x="520" d="M59 0l234 1096h168l-234 -1096h-168zM324 1241v27q56 60 125.5 151.5t106.5 149.5h190v-21q-38 -49 -140 -151t-177 -156h-105z" /> -<glyph unicode="î" horiz-adv-x="520" d="M59 0l234 1096h168l-234 -1096h-168zM93 1241v27q145 133 204.5 197.5t82.5 103.5h158q37 -99 128 -235l42 -66v-27h-103q-57 48 -161 189q-134 -119 -242 -189h-109z" /> -<glyph unicode="ï" horiz-adv-x="520" d="M59 0l234 1096h168l-234 -1096h-168zM161 1378q0 46 28 79.5t74 33.5q78 0 78 -80q0 -49 -29.5 -83t-68.5 -34q-35 0 -58.5 22t-23.5 62zM525 1378q0 46 28 79.5t75 33.5q77 0 77 -80q0 -49 -29.5 -83t-68.5 -34q-35 0 -58.5 22t-23.5 62z" /> -<glyph unicode="ð" horiz-adv-x="1165" d="M90 373q0 160 67.5 298t187 217t267.5 79q105 0 181.5 -45.5t111.5 -124.5l6 2v17q0 136 -36.5 240t-110.5 197l-270 -149l-56 108l238 131q-66 58 -146 113l95 117q118 -84 188 -154l260 146l64 -105l-240 -133q87 -115 126.5 -240.5t39.5 -269.5q0 -253 -71.5 -447 t-203 -292t-311.5 -98q-182 0 -284.5 104t-102.5 289zM262 377q0 -126 57.5 -191t167.5 -65q107 0 190 56t134 168t51 226q0 118 -65.5 187t-178.5 69q-109 0 -189 -57.5t-123.5 -161t-43.5 -231.5z" /> -<glyph unicode="ñ" horiz-adv-x="1182" d="M59 0l234 1096h139l-22 -203h10q96 122 185.5 172.5t185.5 50.5q127 0 200.5 -69.5t73.5 -194.5q0 -79 -23 -180l-143 -672h-170l148 692q20 104 20 144q0 63 -35.5 101t-113.5 38q-89 0 -173.5 -60t-149 -171t-97.5 -269l-101 -475h-168zM369 1241q58 258 231 258 q44 0 83.5 -18t75 -39.5t66.5 -39.5t58 -18q44 0 69.5 27t51.5 90h100q-66 -258 -233 -258q-40 0 -77.5 17.5t-73 39t-69 39t-65.5 17.5q-44 0 -69.5 -28.5t-47.5 -86.5h-100z" /> -<glyph unicode="ò" horiz-adv-x="1149" d="M98 406q0 190 73 357.5t197 257t275 89.5q190 0 300 -112.5t110 -309.5q0 -188 -72 -355t-195 -258t-278 -91q-192 0 -301 113t-109 309zM270 397q0 -131 63.5 -202.5t182.5 -71.5q104 0 187 73t129.5 207.5t46.5 307.5q0 115 -62.5 186.5t-169.5 71.5q-109 0 -195.5 -74 t-134 -205.5t-47.5 -292.5zM470 1548v21h181q43 -136 147 -303v-25h-104q-61 61 -128.5 154t-95.5 153z" /> -<glyph unicode="ó" horiz-adv-x="1149" d="M98 406q0 190 73 357.5t197 257t275 89.5q190 0 300 -112.5t110 -309.5q0 -188 -72 -355t-195 -258t-278 -91q-192 0 -301 113t-109 309zM270 397q0 -131 63.5 -202.5t182.5 -71.5q104 0 187 73t129.5 207.5t46.5 307.5q0 115 -62.5 186.5t-169.5 71.5q-109 0 -195.5 -74 t-134 -205.5t-47.5 -292.5zM589 1241v27q56 60 125.5 151.5t106.5 149.5h190v-21q-38 -49 -140 -151t-177 -156h-105z" /> -<glyph unicode="ô" horiz-adv-x="1149" d="M98 406q0 190 73 357.5t197 257t275 89.5q190 0 300 -112.5t110 -309.5q0 -188 -72 -355t-195 -258t-278 -91q-192 0 -301 113t-109 309zM270 397q0 -131 63.5 -202.5t182.5 -71.5q104 0 187 73t129.5 207.5t46.5 307.5q0 115 -62.5 186.5t-169.5 71.5q-109 0 -195.5 -74 t-134 -205.5t-47.5 -292.5zM382 1241v27q145 133 204.5 197.5t82.5 103.5h158q37 -99 128 -235l42 -66v-27h-103q-57 48 -161 189q-134 -119 -242 -189h-109z" /> -<glyph unicode="õ" horiz-adv-x="1149" d="M98 406q0 190 73 357.5t197 257t275 89.5q190 0 300 -112.5t110 -309.5q0 -188 -72 -355t-195 -258t-278 -91q-192 0 -301 113t-109 309zM270 397q0 -131 63.5 -202.5t182.5 -71.5q104 0 187 73t129.5 207.5t46.5 307.5q0 115 -62.5 186.5t-169.5 71.5q-109 0 -195.5 -74 t-134 -205.5t-47.5 -292.5zM342 1241q58 258 231 258q44 0 83.5 -18t75 -39.5t66.5 -39.5t58 -18q44 0 69.5 27t51.5 90h100q-66 -258 -233 -258q-40 0 -77.5 17.5t-73 39t-69 39t-65.5 17.5q-44 0 -69.5 -28.5t-47.5 -86.5h-100z" /> -<glyph unicode="ö" horiz-adv-x="1149" d="M98 406q0 190 73 357.5t197 257t275 89.5q190 0 300 -112.5t110 -309.5q0 -188 -72 -355t-195 -258t-278 -91q-192 0 -301 113t-109 309zM270 397q0 -131 63.5 -202.5t182.5 -71.5q104 0 187 73t129.5 207.5t46.5 307.5q0 115 -62.5 186.5t-169.5 71.5q-109 0 -195.5 -74 t-134 -205.5t-47.5 -292.5zM433 1378q0 46 28 79.5t74 33.5q78 0 78 -80q0 -49 -29.5 -83t-68.5 -34q-35 0 -58.5 22t-23.5 62zM797 1378q0 46 28 79.5t75 33.5q77 0 77 -80q0 -49 -29.5 -83t-68.5 -34q-35 0 -58.5 22t-23.5 62z" /> -<glyph unicode="÷" d="M127 651v142h920v-142h-920zM475 373q0 121 111 121q53 0 82.5 -30.5t29.5 -90.5q0 -58 -30 -89.5t-82 -31.5t-81.5 31t-29.5 90zM475 1071q0 121 111 121q53 0 82.5 -30.5t29.5 -90.5q0 -58 -30 -89.5t-82 -31.5t-81.5 31t-29.5 90z" /> -<glyph unicode="ø" horiz-adv-x="1149" d="M61 6l109 135q-68 103 -68 265q0 194 73.5 361t195.5 255t272 88q146 0 252 -68l104 129l105 -79l-119 -129q62 -97 62 -258q0 -189 -69.5 -360t-191.5 -266t-276 -95q-146 0 -246 65l-98 -125zM264 416q0 -92 17 -137l518 645q-54 47 -152 47q-108 0 -195.5 -73 t-137.5 -202t-50 -280zM358 166q57 -45 158 -45q103 0 188.5 71.5t133 200.5t47.5 295q0 84 -13 119z" /> -<glyph unicode="ù" horiz-adv-x="1182" d="M113 248q0 62 22 172l146 676h170l-150 -695q-18 -89 -18 -139q0 -143 147 -143q88 0 173 60t150 172t99 270l100 475h166l-231 -1096h-139l22 203h-12q-98 -125 -187 -174t-184 -49q-128 0 -201 69.5t-73 198.5zM472 1548v21h181q43 -136 147 -303v-25h-104 q-61 61 -128.5 154t-95.5 153z" /> -<glyph unicode="ú" horiz-adv-x="1182" d="M113 248q0 62 22 172l146 676h170l-150 -695q-18 -89 -18 -139q0 -143 147 -143q88 0 173 60t150 172t99 270l100 475h166l-231 -1096h-139l22 203h-12q-98 -125 -187 -174t-184 -49q-128 0 -201 69.5t-73 198.5zM636 1241v27q56 60 125.5 151.5t106.5 149.5h190v-21 q-38 -49 -140 -151t-177 -156h-105z" /> -<glyph unicode="û" horiz-adv-x="1182" d="M113 248q0 62 22 172l146 676h170l-150 -695q-18 -89 -18 -139q0 -143 147 -143q88 0 173 60t150 172t99 270l100 475h166l-231 -1096h-139l22 203h-12q-98 -125 -187 -174t-184 -49q-128 0 -201 69.5t-73 198.5zM409 1241v27q145 133 204.5 197.5t82.5 103.5h158 q37 -99 128 -235l42 -66v-27h-103q-57 48 -161 189q-134 -119 -242 -189h-109z" /> -<glyph unicode="ü" horiz-adv-x="1182" d="M113 248q0 62 22 172l146 676h170l-150 -695q-18 -89 -18 -139q0 -143 147 -143q88 0 173 60t150 172t99 270l100 475h166l-231 -1096h-139l22 203h-12q-98 -125 -187 -174t-184 -49q-128 0 -201 69.5t-73 198.5zM457 1378q0 46 28 79.5t74 33.5q78 0 78 -80 q0 -49 -29.5 -83t-68.5 -34q-35 0 -58.5 22t-23.5 62zM821 1378q0 46 28 79.5t75 33.5q77 0 77 -80q0 -49 -29.5 -83t-68.5 -34q-35 0 -58.5 22t-23.5 62z" /> -<glyph unicode="ý" horiz-adv-x="946" d="M-197 -336q63 -18 131 -18q82 0 140.5 50.5t113.5 149.5l76 136l-166 1114h168l74 -545q10 -69 19.5 -203.5t9.5 -216.5h6q35 87 87 200t77 156l325 609h178l-696 -1282q-93 -172 -184 -239t-219 -67q-72 0 -140 21v135zM500 1241v27q56 60 125.5 151.5t106.5 149.5h190 v-21q-38 -49 -140 -151t-177 -156h-105z" /> -<glyph unicode="þ" horiz-adv-x="1182" d="M-43 -492l432 2048h168q-95 -441 -115 -522t-39 -149h9q101 125 189 177t183 52q139 0 218 -97.5t79 -273.5q0 -212 -69 -389t-191 -275.5t-276 -98.5q-98 0 -172 51t-113 139h-10q-8 -104 -25 -176l-102 -486h-166zM319 346q0 -110 55.5 -168.5t160.5 -58.5 q99 0 184.5 81t137.5 230.5t52 317.5q0 227 -178 227q-96 0 -195.5 -95t-158 -239t-58.5 -295z" /> -<glyph unicode="ÿ" horiz-adv-x="946" d="M-197 -336q63 -18 131 -18q82 0 140.5 50.5t113.5 149.5l76 136l-166 1114h168l74 -545q10 -69 19.5 -203.5t9.5 -216.5h6q35 87 87 200t77 156l325 609h178l-696 -1282q-93 -172 -184 -239t-219 -67q-72 0 -140 21v135zM335 1378q0 46 28 79.5t74 33.5q78 0 78 -80 q0 -49 -29.5 -83t-68.5 -34q-35 0 -58.5 22t-23.5 62zM699 1378q0 46 28 79.5t75 33.5q77 0 77 -80q0 -49 -29.5 -83t-68.5 -34q-35 0 -58.5 22t-23.5 62z" /> -<glyph unicode="ı" horiz-adv-x="520" d="M59 0l234 1096h168l-234 -1096h-168z" /> -<glyph unicode="Œ" horiz-adv-x="1751" d="M150 549q0 264 96 482t263.5 336t377.5 118q152 0 237 -23h709l-31 -153h-565l-100 -469h528l-31 -150h-528l-115 -538h565l-32 -152h-674q-78 -20 -158 -20q-256 0 -399 149.5t-143 419.5zM332 553q0 -199 98 -310.5t266 -111.5q69 0 123 19l246 1161q-76 22 -191 22 q-157 0 -281 -101t-192.5 -281t-68.5 -398z" /> -<glyph unicode="œ" horiz-adv-x="1769" d="M98 406q0 193 75 360t201 255.5t281 88.5q270 0 359 -225q75 109 177.5 170t221.5 61q139 0 217 -65.5t78 -186.5q0 -183 -164.5 -284t-468.5 -101h-41l-4 -80q0 -131 61.5 -204.5t190.5 -73.5q75 0 145 24.5t150 59.5v-150q-162 -75 -326 -75q-270 0 -356 225 q-69 -107 -171.5 -164t-225.5 -57q-184 0 -292 114t-108 308zM270 410q0 -141 62 -214t172 -73q177 0 278 160.5t101 427.5q0 124 -59.5 191t-174.5 67q-109 0 -196 -73t-135 -202t-48 -284zM1053 618h18q231 0 351 61t120 177q0 48 -32 82.5t-97 34.5q-125 0 -220.5 -94.5 t-139.5 -260.5z" /> -<glyph unicode="Ÿ" horiz-adv-x="1030" d="M188 1462h170l179 -747l489 747h193l-627 -921l-113 -541h-172l119 549zM452 1716q0 46 28 79.5t74 33.5q78 0 78 -80q0 -49 -29.5 -83t-68.5 -34q-35 0 -58.5 22t-23.5 62zM816 1716q0 46 28 79.5t75 33.5q77 0 77 -80q0 -49 -29.5 -83t-68.5 -34q-35 0 -58.5 22 t-23.5 62z" /> -<glyph unicode="ˆ" horiz-adv-x="1135" d="M399 1241v27q145 133 204.5 197.5t82.5 103.5h158q37 -99 128 -235l42 -66v-27h-103q-57 48 -161 189q-134 -119 -242 -189h-109z" /> -<glyph unicode="˚" horiz-adv-x="1182" d="M551 1454q0 94 62 152.5t157 58.5q101 0 160 -57t59 -152q0 -99 -60 -157t-159 -58q-101 0 -160 57.5t-59 155.5zM655 1454q0 -54 29.5 -84.5t85.5 -30.5q51 0 83 30.5t32 84.5q0 53 -32 84t-83 31q-49 0 -82 -31t-33 -84z" /> -<glyph unicode="˜" horiz-adv-x="1135" d="M336 1241q58 258 231 258q44 0 83.5 -18t75 -39.5t66.5 -39.5t58 -18q44 0 69.5 27t51.5 90h100q-66 -258 -233 -258q-40 0 -77.5 17.5t-73 39t-69 39t-65.5 17.5q-44 0 -69.5 -28.5t-47.5 -86.5h-100z" /> -<glyph unicode=" " horiz-adv-x="953" /> -<glyph unicode=" " horiz-adv-x="1907" /> -<glyph unicode=" " horiz-adv-x="953" /> -<glyph unicode=" " horiz-adv-x="1907" /> -<glyph unicode=" " horiz-adv-x="635" /> -<glyph unicode=" " horiz-adv-x="476" /> -<glyph unicode=" " horiz-adv-x="317" /> -<glyph unicode=" " horiz-adv-x="317" /> -<glyph unicode=" " horiz-adv-x="238" /> -<glyph unicode=" " horiz-adv-x="381" /> -<glyph unicode=" " horiz-adv-x="105" /> -<glyph unicode="‐" horiz-adv-x="639" d="M55 469l35 158h479l-34 -158h-480z" /> -<glyph unicode="‑" horiz-adv-x="639" d="M55 469l35 158h479l-34 -158h-480z" /> -<glyph unicode="‒" horiz-adv-x="639" d="M55 469l35 158h479l-34 -158h-480z" /> -<glyph unicode="–" horiz-adv-x="983" d="M55 469l35 160h823l-34 -160h-824z" /> -<glyph unicode="—" horiz-adv-x="1966" d="M55 469l35 160h1806l-34 -160h-1807z" /> -<glyph unicode="‘" horiz-adv-x="348" d="M123 983q98 211 270 479h127q-147 -345 -203 -501h-188z" /> -<glyph unicode="’" horiz-adv-x="348" d="M125 961q134 298 203 501h188l8 -22q-40 -91 -111 -218.5t-159 -260.5h-129z" /> -<glyph unicode="‚" horiz-adv-x="492" d="M-100 -264q126 286 204 502h187l8 -23q-113 -235 -270 -479h-129z" /> -<glyph unicode="“" horiz-adv-x="719" d="M123 983q98 211 270 479h127q-147 -345 -203 -501h-188zM492 983q80 181 272 479h127q-162 -379 -203 -501h-188z" /> -<glyph unicode="”" horiz-adv-x="719" d="M125 961q134 298 203 501h188l8 -22q-40 -91 -111 -218.5t-159 -260.5h-129zM494 961q57 126 115.5 272.5t86.5 228.5h189l10 -22q-94 -206 -274 -479h-127z" /> -<glyph unicode="„" horiz-adv-x="858" d="M-100 -264q126 286 204 502h187l8 -23q-113 -235 -270 -479h-129zM268 -264q140 316 203 502h188l9 -23q-95 -205 -271 -479h-129z" /> -<glyph unicode="•" horiz-adv-x="774" d="M199 684q0 145 73.5 231t198.5 86q92 0 139 -49t47 -141q0 -141 -74 -230t-202 -89q-89 0 -135.5 49.5t-46.5 142.5z" /> -<glyph unicode="…" horiz-adv-x="1563" d="M563 74q0 77 40.5 122.5t111.5 45.5q43 0 69.5 -26t26.5 -79q0 -71 -40 -118.5t-108 -47.5q-46 0 -73 26t-27 77zM1085 74q0 77 40.5 122.5t111.5 45.5q43 0 69.5 -26t26.5 -79q0 -71 -40 -118.5t-108 -47.5q-46 0 -73 26t-27 77zM43 74q0 77 40.5 122.5t111.5 45.5 q43 0 69.5 -26t26.5 -79q0 -71 -40 -118.5t-108 -47.5q-46 0 -73 26t-27 77z" /> -<glyph unicode=" " horiz-adv-x="381" /> -<glyph unicode="‹" horiz-adv-x="580" d="M88 549v29l391 380l78 -81l-297 -334l172 -381l-113 -49z" /> -<glyph unicode="›" horiz-adv-x="580" d="M23 197l296 333l-172 381l113 50l232 -437v-28l-392 -381z" /> -<glyph unicode="⁄" horiz-adv-x="268" d="M-487 0l1085 1462h154l-1086 -1462h-153z" /> -<glyph unicode=" " horiz-adv-x="476" /> -<glyph unicode="⁴" horiz-adv-x="717" d="M92 788l23 101l481 579h133l-121 -563h127l-22 -117h-129l-43 -202h-127l43 202h-365zM256 905h225q69 322 90 395q-20 -36 -110 -149z" /> -<glyph unicode="€" d="M63 504l27 131h154q8 80 30 164h-151l27 133h159q97 267 259.5 408t369.5 141q89 0 160 -21.5t141 -70.5l-80 -138q-113 78 -231 78q-140 0 -254 -99t-189 -298h426l-26 -133h-441q-21 -65 -32 -164h381l-29 -131h-361q0 -373 297 -373q123 0 256 55v-147 q-127 -59 -278 -59q-212 0 -328.5 133.5t-116.5 378.5v12h-170z" /> -<glyph unicode="™" horiz-adv-x="1534" d="M121 1358v104h516v-104h-199v-617h-121v617h-196zM705 741v721h180l182 -557l193 557h170v-721h-121v430q0 73 4 121h-6l-197 -551h-96l-189 551h-6q4 -52 4 -121v-430h-118z" /> -<glyph unicode="" horiz-adv-x="1095" d="M0 1095h1095v-1095h-1095v1095z" /> -<glyph unicode="fi" horiz-adv-x="1165" d="M-229 -330q64 -22 112 -22q76 0 117 62t66 177l227 1082h-193l13 67l206 66l23 100q46 200 127.5 282.5t241.5 82.5q40 0 98 -11.5t90 -25.5l-43 -129q-76 29 -137 29q-87 0 -133.5 -48.5t-75.5 -177.5l-25 -108h238l-25 -127h-237l-232 -1098q-39 -189 -120 -276 t-213 -87q-69 0 -125 21v141zM702 0l234 1096h168l-234 -1096h-168zM983 1376q0 56 32 91.5t83 35.5q88 0 88 -90q0 -55 -33.5 -93t-77.5 -38q-40 0 -66 24.5t-26 69.5z" /> -<glyph unicode="fl" horiz-adv-x="1165" d="M-229 -330q64 -22 112 -22q76 0 117 62t66 177l227 1082h-193l13 67l206 66l23 100q46 200 127.5 282.5t241.5 82.5q40 0 98 -11.5t90 -25.5l-43 -129q-76 29 -137 29q-87 0 -133.5 -48.5t-75.5 -177.5l-25 -108h238l-25 -127h-237l-232 -1098q-39 -189 -120 -276 t-213 -87q-69 0 -125 21v141zM700 0l332 1556h168l-332 -1556h-168z" /> -<glyph unicode="ffi" horiz-adv-x="1815" d="M-229 -330q64 -22 112 -22q70 0 114 58t69 181l227 1082h-193l13 67l206 66l23 100q46 200 127.5 282.5t241.5 82.5q40 0 98 -11.5t90 -25.5l-43 -129q-76 29 -137 29q-87 0 -133.5 -48.5t-75.5 -177.5l-25 -108h482l24 108q45 197 126 280t243 83q41 0 97.5 -11 t92.5 -26l-45 -129q-76 29 -137 29q-89 0 -135 -51t-74 -175l-24 -108h239l-26 -127h-238l-231 -1098q-43 -195 -123.5 -279t-210.5 -84q-71 0 -125 21v141q61 -22 115 -22q68 0 111 57.5t69 181.5l227 1082h-481l-232 -1098q-39 -189 -120 -276t-213 -87q-69 0 -125 21v141 zM1354 0l233 1096h168l-233 -1096h-168zM1634 1376q0 54 32 90.5t83 36.5q88 0 88 -90q0 -55 -33.5 -93t-77.5 -38q-38 0 -65 24.5t-27 69.5z" /> -<glyph unicode="ffl" horiz-adv-x="1815" d="M-229 -330q64 -22 112 -22q70 0 114 58t69 181l227 1082h-193l13 67l206 66l23 100q46 200 127.5 282.5t241.5 82.5q40 0 98 -11.5t90 -25.5l-43 -129q-76 29 -137 29q-87 0 -133.5 -48.5t-75.5 -177.5l-25 -108h482l24 108q45 197 126 280t243 83q41 0 97.5 -11 t92.5 -26l-45 -129q-76 29 -137 29q-89 0 -135 -51t-74 -175l-24 -108h239l-26 -127h-238l-231 -1098q-43 -195 -123.5 -279t-210.5 -84q-71 0 -125 21v141q61 -22 115 -22q68 0 111 57.5t69 181.5l227 1082h-481l-232 -1098q-39 -189 -120 -276t-213 -87q-69 0 -125 21v141 zM1352 0l331 1556h168l-331 -1556h-168z" /> -</font> -</defs></svg> -\ No newline at end of file diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-Italic-webfont.ttf b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-Italic-webfont.ttf Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-Italic-webfont.woff b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-Italic-webfont.woff Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-Light-webfont.eot b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-Light-webfont.eot Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-Light-webfont.svg b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-Light-webfont.svg @@ -1,252 +0,0 @@ -<?xml version="1.0" standalone="no"?> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" > -<svg xmlns="http://www.w3.org/2000/svg"> -<metadata> -This is a custom SVG webfont generated by Font Squirrel. -Copyright : Digitized data copyright 20102011 Google Corporation -Foundry : Ascender Corporation -Foundry URL : httpwwwascendercorpcom -</metadata> -<defs> -<font id="OpenSansLight" horiz-adv-x="1169" > -<font-face units-per-em="2048" ascent="1638" descent="-410" /> -<missing-glyph horiz-adv-x="532" /> -<glyph unicode=" " horiz-adv-x="532" /> -<glyph unicode="	" horiz-adv-x="532" /> -<glyph unicode=" " horiz-adv-x="532" /> -<glyph unicode="!" horiz-adv-x="492" d="M164 78q0 98 80 98q82 0 82 -98t-82 -98q-80 0 -80 98zM186 1462h119l-29 -1085h-61z" /> -<glyph unicode=""" horiz-adv-x="723" d="M133 1462h127l-33 -528h-61zM463 1462h127l-33 -528h-61z" /> -<glyph unicode="#" horiz-adv-x="1323" d="M55 451v79h299l76 398h-297v80h311l86 454h91l-89 -454h365l88 454h86l-88 -454h285v-80h-301l-76 -398h303v-79h-320l-86 -451h-90l88 451h-360l-86 -451h-88l86 451h-283zM440 530h363l78 398h-363z" /> -<glyph unicode="$" d="M164 186v103q75 -36 179.5 -61t193.5 -25v508q-145 44 -215 88t-102 104t-32 146q0 124 94.5 208.5t254.5 104.5v192h81v-190q197 -9 351 -72l-33 -90q-141 62 -318 72v-486q213 -66 293 -144t80 -204q0 -133 -99 -217t-274 -106v-236h-81v232q-92 2 -200.5 22.5 t-172.5 50.5zM297 1049q0 -86 57 -141t183 -93v453q-119 -16 -179.5 -76t-60.5 -143zM618 209q122 13 192.5 75t70.5 160q0 85 -63 140.5t-200 95.5v-471z" /> -<glyph unicode="%" horiz-adv-x="1653" d="M113 1026q0 223 72 340t212 117q139 0 215 -120.5t76 -336.5q0 -226 -75 -343.5t-216 -117.5q-133 0 -208.5 120.5t-75.5 340.5zM211 1026q0 -186 45 -279.5t141 -93.5q193 0 193 373q0 184 -49.5 276.5t-143.5 92.5q-96 0 -141 -92.5t-45 -276.5zM373 0l811 1462h96 l-811 -1462h-96zM965 438q0 225 73.5 341t212.5 116q137 0 213 -120t76 -337q0 -226 -74 -343.5t-215 -117.5q-136 0 -211 121.5t-75 339.5zM1063 438q0 -185 45 -277.5t141 -92.5q193 0 193 370q0 369 -193 369q-96 0 -141 -91.5t-45 -277.5z" /> -<glyph unicode="&" horiz-adv-x="1460" d="M123 371q0 138 73.5 235t274.5 205l-75 82q-66 71 -98 139t-32 142q0 143 95.5 227t256.5 84q155 0 245.5 -81t90.5 -224q0 -105 -70 -192.5t-253 -194.5l452 -457q61 72 104 157t75 201h96q-63 -246 -209 -426l266 -268h-135l-193 197q-92 -90 -164 -131.5t-157.5 -63.5 t-194.5 -22q-209 0 -328.5 103t-119.5 288zM227 375q0 -143 93 -224t258 -81q128 0 234.5 43.5t209.5 146.5l-483 485q-136 -72 -196.5 -122.5t-88 -109.5t-27.5 -138zM373 1176q0 -79 40 -146t152 -174q159 85 221 159t62 169q0 94 -62 152.5t-168 58.5q-114 0 -179.5 -58 t-65.5 -161z" /> -<glyph unicode="'" horiz-adv-x="393" d="M133 1462h127l-33 -528h-61z" /> -<glyph unicode="(" horiz-adv-x="557" d="M82 561q0 265 77.5 496t223.5 405h113q-148 -182 -227 -412.5t-79 -486.5q0 -483 304 -887h-111q-147 170 -224 397t-77 488z" /> -<glyph unicode=")" horiz-adv-x="557" d="M61 1462h113q147 -175 224 -406.5t77 -494.5t-77.5 -490t-223.5 -395h-111q304 404 304 887q0 257 -79 487.5t-227 411.5z" /> -<glyph unicode="*" horiz-adv-x="1128" d="M104 1124l19 131l401 -104l-39 405h146l-37 -405l405 104l21 -131l-395 -39l247 -340l-124 -71l-191 379l-180 -379l-125 71l242 340z" /> -<glyph unicode="+" d="M111 682v82h432v434h82v-434h434v-82h-434v-432h-82v432h-432z" /> -<glyph unicode="," horiz-adv-x="440" d="M68 -264q77 275 110 502h117l12 -21q-75 -265 -174 -481h-65z" /> -<glyph unicode="-" horiz-adv-x="659" d="M92 512v82h475v-82h-475z" /> -<glyph unicode="." horiz-adv-x="487" d="M162 78q0 98 80 98q82 0 82 -98t-82 -98q-80 0 -80 98z" /> -<glyph unicode="/" horiz-adv-x="698" d="M25 0l544 1462h105l-545 -1462h-104z" /> -<glyph unicode="0" d="M115 735q0 382 115.5 566t351.5 184q231 0 352 -190.5t121 -559.5q0 -385 -117.5 -570t-355.5 -185q-229 0 -348 190.5t-119 564.5zM223 735q0 -340 89 -502.5t270 -162.5q189 0 275.5 168t86.5 497q0 324 -86.5 492t-275.5 168t-274 -168t-85 -492z" /> -<glyph unicode="1" d="M199 1165l397 297h86v-1462h-98v1065q0 145 12 301q-15 -15 -31 -29t-309 -243z" /> -<glyph unicode="2" d="M113 0v88l389 406q164 170 230 260t97 172t31 172q0 131 -86 213t-223 82q-183 0 -350 -133l-54 69q183 154 406 154q191 0 300.5 -102t109.5 -281q0 -145 -73.5 -280.5t-268.5 -334.5l-375 -385v-4h782v-96h-915z" /> -<glyph unicode="3" d="M94 63v99q84 -44 188.5 -69t196.5 -25q221 0 332 89.5t111 252.5q0 145 -113.5 223t-333.5 78h-158v96h160q182 0 288.5 86.5t106.5 234.5q0 122 -86.5 195.5t-226.5 73.5q-109 0 -199 -30.5t-202 -104.5l-49 67q85 71 205 112.5t243 41.5q202 0 312 -95.5t110 -269.5 q0 -136 -85.5 -229t-229.5 -119v-6q176 -22 268 -112t92 -242q0 -205 -139.5 -317.5t-401.5 -112.5q-223 0 -389 83z" /> -<glyph unicode="4" d="M43 373v67l725 1030h121v-1011h252v-86h-252v-373h-94v373h-752zM162 459h633v418q0 302 14 507h-8q-20 -37 -123 -188z" /> -<glyph unicode="5" d="M143 63v103q108 -55 192 -76.5t179 -21.5q192 0 308 101.5t116 274.5q0 163 -113 256t-307 93q-130 0 -272 -39l-60 39l58 669h704v-96h-610l-45 -516q156 29 244 29q234 0 368.5 -113t134.5 -311q0 -225 -140 -350t-386 -125q-109 0 -207 21.5t-164 61.5z" /> -<glyph unicode="6" d="M131 623q0 285 77.5 479.5t220 288.5t343.5 94q94 0 172 -23v-88q-73 27 -176 27q-247 0 -384.5 -178t-154.5 -518h13q76 98 174 148t207 50q205 0 320.5 -117t115.5 -323q0 -224 -121.5 -353.5t-327.5 -129.5q-222 0 -350.5 169.5t-128.5 473.5zM240 504 q0 -111 49.5 -213.5t134 -162.5t186.5 -60q164 0 255 103t91 294q0 168 -90 262t-245 94q-102 0 -189.5 -45t-139.5 -119.5t-52 -152.5z" /> -<glyph unicode="7" d="M109 1366v96h946v-73l-604 -1389h-117l602 1366h-827z" /> -<glyph unicode="8" d="M121 375q0 131 83 230t257 169q-161 76 -227 160.5t-66 202.5q0 105 53 184.5t148.5 122.5t212.5 43q186 0 299.5 -95t113.5 -257q0 -112 -70.5 -198t-228.5 -159q192 -79 270 -173t78 -228q0 -181 -126.5 -289t-339.5 -108q-221 0 -339 101t-118 294zM223 360 q0 -138 93.5 -214t261.5 -76q164 0 264 80.5t100 218.5q0 124 -78.5 201.5t-302.5 162.5q-184 -71 -261 -157t-77 -216zM268 1137q0 -70 31.5 -123.5t91 -97t199.5 -101.5q163 63 234 139t71 183q0 120 -84.5 190t-230.5 70q-141 0 -226.5 -69.5t-85.5 -190.5z" /> -<glyph unicode="9" d="M111 993q0 220 124.5 356t323.5 136q144 0 252 -75.5t166.5 -221.5t58.5 -346q0 -288 -75.5 -482t-220 -287t-349.5 -93q-104 0 -192 26v86q43 -14 103.5 -21.5t92.5 -7.5q247 0 387 178.5t156 520.5h-12q-73 -96 -174 -147.5t-211 -51.5q-203 0 -316.5 112t-113.5 318z M213 999q0 -174 87 -264t249 -90q101 0 188.5 45t139 119.5t51.5 151.5q0 117 -46.5 219t-130 159.5t-192.5 57.5q-158 0 -252 -106.5t-94 -291.5z" /> -<glyph unicode=":" horiz-adv-x="487" d="M162 78q0 98 80 98q82 0 82 -98t-82 -98q-80 0 -80 98zM162 971q0 98 80 98q82 0 82 -98q0 -53 -23.5 -76t-58.5 -23q-34 0 -57 23t-23 76z" /> -<glyph unicode=";" horiz-adv-x="487" d="M76 -264q29 97 62 245.5t48 256.5h117l12 -21q-75 -265 -174 -481h-65zM162 971q0 98 80 98q82 0 82 -98q0 -53 -23.5 -76t-58.5 -23q-34 0 -57 23t-23 76z" /> -<glyph unicode="<" d="M111 682v61l948 474v-95l-823 -405l823 -355v-96z" /> -<glyph unicode="=" d="M111 477v82h948v-82h-948zM111 885v82h948v-82h-948z" /> -<glyph unicode=">" d="M111 266v96l823 355l-823 405v95l948 -474v-61z" /> -<glyph unicode="?" horiz-adv-x="862" d="M57 1403q110 48 184.5 64t153.5 16q183 0 288 -98.5t105 -270.5q0 -68 -18 -119t-50.5 -94.5t-78.5 -84t-102 -87.5q-64 -54 -98.5 -98.5t-50 -93.5t-15.5 -146v-14h-82v37q0 123 37.5 201t138.5 167l91 79q72 61 103 121t31 138q0 127 -83.5 202t-219.5 75 q-79 0 -148 -17.5t-149 -56.5zM260 78q0 98 80 98q82 0 82 -98t-82 -98q-80 0 -80 98z" /> -<glyph unicode="@" horiz-adv-x="1815" d="M113 561q0 256 108.5 460.5t307 317.5t448.5 113q215 0 380.5 -89t255 -254.5t89.5 -383.5q0 -228 -90.5 -366t-245.5 -138q-89 0 -144.5 54t-64.5 147h-4q-43 -100 -124 -150.5t-189 -50.5q-148 0 -229 96.5t-81 270.5q0 202 120.5 330.5t314.5 128.5q138 0 286 -41 l-22 -464v-30q0 -104 35 -156.5t116 -52.5q103 0 168.5 116.5t65.5 303.5q0 194 -79 340t-225.5 224.5t-334.5 78.5q-230 0 -405.5 -99.5t-270 -281.5t-94.5 -418q0 -322 167 -497.5t474 -175.5q93 0 188.5 18t231.5 70v-99q-203 -80 -414 -80q-349 0 -544 200.5t-195 557.5 zM633 590q0 -143 55 -215t174 -72q255 0 273 346l16 291q-79 27 -193 27q-149 0 -237 -102.5t-88 -274.5z" /> -<glyph unicode="A" horiz-adv-x="1229" d="M0 0l588 1468h65l576 -1468h-115l-203 516h-594l-204 -516h-113zM354 608h523l-199 527q-25 62 -60 172q-27 -96 -59 -174z" /> -<glyph unicode="B" horiz-adv-x="1284" d="M207 0v1462h401q271 0 398 -92t127 -278q0 -127 -77.5 -211.5t-226.5 -108.5v-6q175 -26 257.5 -110.5t82.5 -235.5q0 -202 -134 -311t-380 -109h-448zM309 90h344q406 0 406 330q0 301 -428 301h-322v-631zM309 811h322q206 0 299.5 68.5t93.5 214.5t-105.5 212 t-314.5 66h-295v-561z" /> -<glyph unicode="C" horiz-adv-x="1272" d="M129 735q0 223 84.5 393t243 262.5t368.5 92.5q214 0 383 -80l-41 -92q-160 80 -336 80q-275 0 -433 -176t-158 -482q0 -313 149 -486t426 -173q184 0 338 47v-90q-145 -51 -362 -51q-308 0 -485 199t-177 556z" /> -<glyph unicode="D" horiz-adv-x="1446" d="M207 0v1462h395q350 0 532.5 -183t182.5 -534q0 -368 -193 -556.5t-567 -188.5h-350zM309 90h242q655 0 655 651q0 314 -159.5 472.5t-468.5 158.5h-269v-1282z" /> -<glyph unicode="E" horiz-adv-x="1130" d="M207 0v1462h799v-94h-697v-553h658v-94h-658v-627h697v-94h-799z" /> -<glyph unicode="F" horiz-adv-x="1028" d="M207 0v1462h801v-94h-699v-620h660v-95h-660v-653h-102z" /> -<glyph unicode="G" horiz-adv-x="1481" d="M129 729q0 223 91.5 395.5t262 266.5t391.5 94q239 0 429 -88l-41 -92q-190 88 -394 88q-289 0 -458.5 -178.5t-169.5 -481.5q0 -330 161 -496.5t473 -166.5q202 0 343 57v514h-435v96h539v-667q-212 -90 -477 -90q-346 0 -530.5 195.5t-184.5 553.5z" /> -<glyph unicode="H" horiz-adv-x="1473" d="M207 0v1462h102v-649h854v649h103v-1462h-103v719h-854v-719h-102z" /> -<glyph unicode="I" horiz-adv-x="516" d="M207 0v1462h102v-1462h-102z" /> -<glyph unicode="J" horiz-adv-x="506" d="M-184 -254q78 -20 149 -20q242 0 242 264v1472h102v-1462q0 -369 -342 -369q-92 0 -151 27v88z" /> -<glyph unicode="K" horiz-adv-x="1190" d="M207 0v1462h102v-760l162 162l573 598h130l-599 -618l615 -844h-125l-561 772l-195 -172v-600h-102z" /> -<glyph unicode="L" horiz-adv-x="1051" d="M207 0v1462h102v-1366h697v-96h-799z" /> -<glyph unicode="M" horiz-adv-x="1767" d="M207 0v1462h158l518 -1286h6l518 1286h154v-1462h-103v1108q0 116 12 240h-8l-547 -1348h-65l-545 1350h-8q8 -124 8 -254v-1096h-98z" /> -<glyph unicode="N" horiz-adv-x="1477" d="M207 0v1462h102l865 -1296h6q-9 180 -9 342v954h99v-1462h-103l-866 1298h-8q12 -232 12 -350v-948h-98z" /> -<glyph unicode="O" horiz-adv-x="1565" d="M129 735q0 349 175.5 549.5t479.5 200.5q306 0 479 -201.5t173 -550.5q0 -348 -174 -550.5t-480 -202.5q-305 0 -479 202.5t-174 552.5zM240 733q0 -314 140 -485.5t402 -171.5q264 0 403.5 170t139.5 487q0 316 -139.5 484.5t-401.5 168.5q-261 0 -402.5 -170 t-141.5 -483z" /> -<glyph unicode="P" horiz-adv-x="1198" d="M207 0v1462h358q522 0 522 -420q0 -212 -144 -325t-408 -113h-226v-604h-102zM309 692h201q247 0 357 81.5t110 264.5q0 169 -104 250.5t-322 81.5h-242v-678z" /> -<glyph unicode="Q" horiz-adv-x="1565" d="M129 735q0 349 175.5 549.5t479.5 200.5q306 0 479 -201.5t173 -550.5q0 -294 -126 -486.5t-349 -246.5l333 -348h-166l-282 330l-33 -2h-31q-305 0 -479 202.5t-174 552.5zM240 733q0 -314 140 -485.5t402 -171.5q264 0 403.5 170t139.5 487q0 316 -139.5 484.5 t-401.5 168.5q-261 0 -402.5 -170t-141.5 -483z" /> -<glyph unicode="R" horiz-adv-x="1217" d="M207 0v1462h348q272 0 402 -100.5t130 -302.5q0 -147 -77.5 -248t-235.5 -145l397 -666h-122l-377 637h-363v-637h-102zM309 725h279q185 0 287 82.5t102 243.5q0 167 -100 243t-326 76h-242v-645z" /> -<glyph unicode="S" horiz-adv-x="1116" d="M111 39v102q158 -67 403 -67q180 0 285.5 82.5t105.5 216.5q0 83 -35 137.5t-114 99.5t-232 97q-224 77 -309.5 166.5t-85.5 238.5q0 164 128.5 267.5t330.5 103.5q206 0 387 -78l-37 -88q-182 76 -348 76q-162 0 -258 -75t-96 -204q0 -81 29.5 -133t96.5 -93.5 t230 -99.5q171 -59 257 -114.5t125.5 -126t39.5 -170.5q0 -183 -134.5 -290t-357.5 -107q-268 0 -411 59z" /> -<glyph unicode="T" horiz-adv-x="1073" d="M10 1366v96h1053v-96h-475v-1366h-103v1366h-475z" /> -<glyph unicode="U" horiz-adv-x="1473" d="M190 520v942h103v-946q0 -211 117 -328.5t331 -117.5q209 0 324 115.5t115 320.5v956h102v-946q0 -252 -146 -394t-407 -142q-254 0 -396.5 142.5t-142.5 397.5z" /> -<glyph unicode="V" horiz-adv-x="1182" d="M0 1462h109l368 -995q84 -225 113 -338q20 75 79 233l402 1100h111l-547 -1462h-90z" /> -<glyph unicode="W" horiz-adv-x="1827" d="M51 1462h107l256 -942q15 -57 28 -105.5t23.5 -91t19 -82t15.5 -79.5q24 136 102 413l250 887h113l293 -1018q51 -176 73 -284q13 72 33.5 153t308.5 1149h103l-404 -1462h-84l-321 1128q-40 139 -60 228q-16 -87 -45.5 -200t-322.5 -1156h-86z" /> -<glyph unicode="X" horiz-adv-x="1102" d="M0 0l492 762l-447 700h115l395 -626l401 626h109l-453 -698l490 -764h-117l-432 682l-440 -682h-113z" /> -<glyph unicode="Y" horiz-adv-x="1081" d="M0 1462h117l426 -800l428 800h110l-487 -897v-565h-105v557z" /> -<glyph unicode="Z" horiz-adv-x="1180" d="M82 0v76l856 1290h-817v96h954v-76l-858 -1290h881v-96h-1016z" /> -<glyph unicode="[" horiz-adv-x="653" d="M174 -324v1786h428v-94h-330v-1597h330v-95h-428z" /> -<glyph unicode="\" horiz-adv-x="698" d="M25 1462h102l547 -1462h-103z" /> -<glyph unicode="]" horiz-adv-x="653" d="M51 -229h330v1597h-330v94h428v-1786h-428v95z" /> -<glyph unicode="^" d="M88 561l465 912h68l460 -912h-100l-395 791l-398 -791h-100z" /> -<glyph unicode="_" horiz-adv-x="842" d="M-4 -184h850v-82h-850v82z" /> -<glyph unicode="`" horiz-adv-x="1182" d="M393 1552v17h142q26 -48 98.5 -142t142.5 -170v-16h-69q-96 79 -188.5 171.5t-125.5 139.5z" /> -<glyph unicode="a" horiz-adv-x="1085" d="M98 289q0 159 132.5 247t383.5 93l207 6v72q0 155 -63 234t-203 79q-151 0 -313 -84l-37 86q179 84 354 84q179 0 267.5 -93t88.5 -290v-723h-73l-25 172h-8q-82 -105 -168.5 -148.5t-204.5 -43.5q-160 0 -249 82t-89 227zM203 285q0 -102 62.5 -158.5t176.5 -56.5 q174 0 274.5 99.5t100.5 276.5v107l-190 -8q-229 -11 -326.5 -71.5t-97.5 -188.5z" /> -<glyph unicode="b" horiz-adv-x="1219" d="M182 0v1556h99v-391q0 -88 -4 -162l-3 -85h7q62 98 149.5 144t210.5 46q228 0 343.5 -143.5t115.5 -419.5q0 -271 -121.5 -418t-341.5 -147q-116 0 -209 48t-147 136h-9l-28 -164h-62zM281 528q0 -246 86.5 -353t269.5 -107q178 0 268 124.5t90 354.5q0 471 -356 471 q-192 0 -275 -110t-83 -363v-17z" /> -<glyph unicode="c" horiz-adv-x="973" d="M119 537q0 270 137 420.5t375 150.5q141 0 270 -49l-27 -88q-141 47 -245 47q-200 0 -303 -123.5t-103 -355.5q0 -220 103 -344.5t288 -124.5q148 0 275 53v-92q-104 -51 -273 -51q-233 0 -365 147t-132 410z" /> -<glyph unicode="d" horiz-adv-x="1219" d="M119 528q0 282 118 431t343 149q118 0 204 -43t154 -147h6q-6 126 -6 247v391h98v-1556h-65l-25 166h-8q-124 -186 -356 -186q-225 0 -344 140t-119 408zM223 530q0 -462 359 -462q184 0 270 107t86 353v17q0 252 -84.5 362.5t-273.5 110.5q-178 0 -267.5 -125 t-89.5 -363z" /> -<glyph unicode="e" horiz-adv-x="1124" d="M119 535q0 260 128 416.5t345 156.5q192 0 303 -134t111 -364v-80h-783q2 -224 104.5 -342t293.5 -118q93 0 163.5 13t178.5 56v-90q-92 -40 -170 -54.5t-172 -14.5q-237 0 -369.5 146t-132.5 409zM229 618h672q0 189 -82 295.5t-227 106.5q-157 0 -252 -103.5 t-111 -298.5z" /> -<glyph unicode="f" horiz-adv-x="614" d="M29 1001v58l202 37v84q0 200 73.5 293.5t240.5 93.5q90 0 180 -27l-23 -86q-80 25 -159 25q-116 0 -164.5 -68.5t-48.5 -222.5v-101h256v-86h-256v-1001h-99v1001h-202z" /> -<glyph unicode="g" horiz-adv-x="1071" d="M45 -193q0 112 69.5 186t188.5 101q-49 21 -78.5 59.5t-29.5 88.5q0 109 139 192q-95 39 -148 122.5t-53 191.5q0 163 103.5 261.5t279.5 98.5q107 0 166 -21h348v-69l-225 -14q90 -112 90 -246q0 -157 -104.5 -254.5t-280.5 -97.5q-74 0 -104 6q-59 -31 -90 -73t-31 -89 q0 -52 39.5 -76t132.5 -24h190q177 0 271 -71.5t94 -211.5q0 -172 -139.5 -265.5t-397.5 -93.5q-205 0 -317.5 79t-112.5 220zM150 -184q0 -224 333 -224q428 0 428 273q0 98 -67 142t-217 44h-178q-299 0 -299 -235zM233 748q0 -126 76.5 -195.5t204.5 -69.5 q136 0 208.5 69t72.5 200q0 139 -74.5 208.5t-208.5 69.5q-130 0 -204.5 -74.5t-74.5 -207.5z" /> -<glyph unicode="h" horiz-adv-x="1208" d="M182 0v1556h99v-495l-5 -139h7q61 98 154 142t231 44q370 0 370 -397v-711h-98v705q0 164 -69 238.5t-214 74.5q-195 0 -285.5 -98.5t-90.5 -319.5v-600h-99z" /> -<glyph unicode="i" horiz-adv-x="463" d="M168 1389q0 96 63 96q31 0 48.5 -25t17.5 -71q0 -45 -17.5 -71t-48.5 -26q-63 0 -63 97zM182 0v1087h99v-1087h-99z" /> -<glyph unicode="j" horiz-adv-x="463" d="M-98 -381q69 -20 129 -20q151 0 151 176v1312h99v-1298q0 -135 -63.5 -208t-180.5 -73q-80 0 -135 25v86zM168 1389q0 96 63 96q31 0 48.5 -25t17.5 -71q0 -45 -17.5 -71t-48.5 -26q-63 0 -63 97z" /> -<glyph unicode="k" horiz-adv-x="991" d="M182 0v1556h99v-780l-7 -299h5l555 610h120l-428 -464l465 -623h-119l-413 549l-178 -162v-387h-99z" /> -<glyph unicode="l" horiz-adv-x="463" d="M182 0v1556h99v-1556h-99z" /> -<glyph unicode="m" horiz-adv-x="1808" d="M182 0v1087h82l21 -149h6q45 81 128 125.5t183 44.5q257 0 330 -193h4q53 93 142.5 143t203.5 50q178 0 267 -95t89 -302v-711h-98v713q0 159 -62 232t-190 73q-167 0 -247 -92t-80 -289v-637h-101v743q0 275 -252 275q-171 0 -249 -99.5t-78 -318.5v-600h-99z" /> -<glyph unicode="n" horiz-adv-x="1208" d="M182 0v1087h84l19 -149h6q106 170 377 170q370 0 370 -397v-711h-98v705q0 164 -69 238.5t-214 74.5q-195 0 -285.5 -98.5t-90.5 -319.5v-600h-99z" /> -<glyph unicode="o" horiz-adv-x="1200" d="M119 545q0 266 129 414.5t354 148.5q224 0 351.5 -150.5t127.5 -412.5q0 -266 -129 -415.5t-356 -149.5q-143 0 -252 69t-167 198t-58 298zM223 545q0 -224 98.5 -349.5t278.5 -125.5t278.5 125.5t98.5 349.5q0 225 -99.5 349t-279.5 124t-277.5 -123.5t-97.5 -349.5z " /> -<glyph unicode="p" horiz-adv-x="1219" d="M182 -492v1579h84l19 -155h6q112 176 358 176q220 0 335.5 -144.5t115.5 -420.5q0 -268 -121.5 -415.5t-331.5 -147.5q-251 0 -366 188h-7l3 -84q4 -74 4 -162v-414h-99zM281 541q0 -255 85.5 -364t278.5 -109q167 0 258.5 124t91.5 347q0 479 -346 479 q-190 0 -279 -104.5t-89 -340.5v-32z" /> -<glyph unicode="q" horiz-adv-x="1219" d="M119 532q0 275 118 425.5t338 150.5q236 0 353 -174h6l18 153h84v-1579h-98v414q0 122 6 248h-6q-118 -190 -369 -190q-214 0 -332 142t-118 410zM223 530q0 -229 89.5 -345.5t258.5 -116.5q198 0 282.5 109t84.5 366v12q0 245 -85 354t-271 109q-176 0 -267.5 -124 t-91.5 -364z" /> -<glyph unicode="r" horiz-adv-x="797" d="M182 0v1087h84l10 -196h7q67 120 143 168.5t184 48.5q69 0 148 -14l-19 -95q-68 17 -141 17q-139 0 -228 -118t-89 -298v-600h-99z" /> -<glyph unicode="s" horiz-adv-x="954" d="M84 47v107q164 -82 346 -82q161 0 244.5 53.5t83.5 142.5q0 82 -66.5 138t-218.5 110q-163 59 -229 101.5t-99.5 96t-33.5 130.5q0 122 102.5 193t286.5 71q176 0 334 -66l-37 -90q-160 66 -297 66q-133 0 -211 -44t-78 -122q0 -85 60.5 -136t236.5 -114 q147 -53 214 -95.5t100.5 -96.5t33.5 -127q0 -146 -111 -224.5t-315 -78.5q-218 0 -346 67z" /> -<glyph unicode="t" horiz-adv-x="686" d="M25 1001v58l161 45l50 246h51v-263h319v-86h-319v-688q0 -125 44 -185t138 -60t164 16v-80q-72 -24 -166 -24q-144 0 -212.5 77t-68.5 242v702h-161z" /> -<glyph unicode="u" horiz-adv-x="1208" d="M170 377v710h98v-704q0 -164 69 -238.5t214 -74.5q194 0 285.5 98t91.5 319v600h98v-1087h-84l-18 150h-6q-106 -170 -377 -170q-371 0 -371 397z" /> -<glyph unicode="v" horiz-adv-x="940" d="M0 1087h102l281 -739q56 -142 84 -248h6q41 136 84 250l281 737h102l-420 -1087h-100z" /> -<glyph unicode="w" horiz-adv-x="1481" d="M31 1087h106l174 -630q61 -234 80 -344h6q59 234 86 311l224 663h90l213 -661q72 -235 88 -311h6q8 65 80 348l166 624h100l-295 -1087h-104l-238 727q-23 74 -59 217h-6l-21 -74l-45 -145l-242 -725h-98z" /> -<glyph unicode="x" horiz-adv-x="1020" d="M55 0l394 559l-379 528h114l324 -458l321 458h109l-373 -528l400 -559h-115l-342 485l-344 -485h-109z" /> -<glyph unicode="y" horiz-adv-x="940" d="M0 1087h102l230 -610q105 -281 133 -379h6q42 129 137 385l230 604h102l-487 -1263q-59 -154 -99 -208t-93.5 -81t-129.5 -27q-57 0 -127 21v86q58 -16 125 -16q51 0 90 24t70.5 74.5t73 160t53.5 142.5z" /> -<glyph unicode="z" horiz-adv-x="944" d="M82 0v63l645 936h-598v88h727v-63l-649 -936h651v-88h-776z" /> -<glyph unicode="{" horiz-adv-x="723" d="M61 528v80q122 2 176 51t54 148v350q0 299 360 305v-90q-138 -5 -200 -58t-62 -157v-305q0 -130 -44 -194t-142 -85v-8q97 -20 141.5 -83.5t44.5 -186.5v-322q0 -102 59.5 -152.5t202.5 -53.5v-91q-195 0 -277.5 75t-82.5 231v337q0 205 -230 209z" /> -<glyph unicode="|" horiz-adv-x="1108" d="M508 -506v2067h92v-2067h-92z" /> -<glyph unicode="}" horiz-adv-x="723" d="M72 -233q141 2 201.5 52.5t60.5 153.5v322q0 123 44.5 186.5t141.5 83.5v8q-97 20 -141.5 84t-44.5 195v305q0 103 -61.5 156.5t-200.5 58.5v90q174 0 267 -77.5t93 -227.5v-350q0 -100 54.5 -148.5t175.5 -50.5v-80q-230 -4 -230 -209v-337q0 -155 -82.5 -230.5 t-277.5 -75.5v91z" /> -<glyph unicode="~" d="M111 625v94q108 110 233 110q61 0 115 -13.5t155 -57.5q126 -58 220 -58q56 0 109.5 30.5t115.5 94.5v-96q-48 -49 -104.5 -81t-129.5 -32q-116 0 -270 72q-124 57 -221 57q-49 0 -108 -30.5t-115 -89.5z" /> -<glyph unicode="¡" horiz-adv-x="492" d="M166 1010q0 98 80 98q82 0 82 -98q0 -53 -23.5 -76t-58.5 -23q-34 0 -57 23t-23 76zM186 -375l29 1086h61l29 -1086h-119z" /> -<glyph unicode="¢" d="M211 745q0 232 102.5 381.5t288.5 182.5v174h82v-166h14q131 0 275 -55l-31 -84q-134 51 -237 51q-187 0 -288.5 -122.5t-101.5 -358.5q0 -225 100.5 -349.5t280.5 -124.5q131 0 267 58v-92q-110 -56 -267 -56h-12v-204h-82v210q-186 30 -288.5 175t-102.5 380z" /> -<glyph unicode="£" d="M78 0v84q110 21 171.5 110t61.5 224v258h-211v82h211v297q0 204 98 315t281 111q175 0 330 -68l-35 -86q-157 66 -295 66q-141 0 -209.5 -81t-68.5 -253v-301h411v-82h-411v-256q0 -116 -35 -196t-113 -128h809v-96h-995z" /> -<glyph unicode="¤" d="M127 326l139 141q-90 106 -90 256q0 147 90 258l-139 141l59 60l138 -142q103 93 260 93q155 0 260 -93l137 142l59 -60l-139 -141q90 -111 90 -258q0 -151 -90 -256l139 -141l-59 -60l-137 142q-110 -93 -260 -93q-153 0 -260 93l-138 -142zM260 723q0 -136 94.5 -232 t229.5 -96q134 0 228.5 95.5t94.5 232.5q0 136 -95 233t-228 97q-134 0 -229 -97t-95 -233z" /> -<glyph unicode="¥" d="M43 1462h117l426 -796l428 796h110l-432 -788h283v-82h-338v-205h338v-82h-338v-305h-105v305h-337v82h337v205h-337v82h278z" /> -<glyph unicode="¦" horiz-adv-x="1108" d="M508 258h92v-764h-92v764zM508 797v764h92v-764h-92z" /> -<glyph unicode="§" horiz-adv-x="1057" d="M129 63v95q182 -78 332 -78q162 0 247 49.5t85 140.5q0 55 -25 87.5t-88.5 65.5t-190.5 79q-200 73 -272 141.5t-72 169.5q0 83 50.5 152.5t138.5 107.5q-86 47 -125 102t-39 136q0 117 101.5 183.5t275.5 66.5q175 0 336 -64l-35 -80q-91 34 -158.5 47t-144.5 13 q-134 0 -205.5 -44.5t-71.5 -119.5q0 -54 25.5 -88.5t85.5 -65.5t188 -74q192 -64 264 -132.5t72 -170.5q0 -173 -186 -274q86 -42 129 -96t43 -136q0 -135 -113 -207.5t-311 -72.5q-92 0 -171 15t-165 52zM246 825q0 -65 31.5 -104t105.5 -75t250 -99q82 41 126 98t44 121 q0 62 -32 102t-108.5 77t-236.5 87q-81 -23 -130.5 -79t-49.5 -128z" /> -<glyph unicode="¨" horiz-adv-x="1182" d="M336 1389q0 46 15.5 66t47.5 20q64 0 64 -86t-64 -86q-63 0 -63 86zM717 1389q0 46 15.5 66t47.5 20q64 0 64 -86t-64 -86q-63 0 -63 86z" /> -<glyph unicode="©" horiz-adv-x="1704" d="M100 731q0 200 100 375t275 276t377 101q200 0 375 -100t276 -275t101 -377q0 -197 -97 -370t-272 -277t-383 -104q-207 0 -382 103.5t-272.5 276.5t-97.5 371zM193 731q0 -178 88.5 -329.5t240.5 -240.5t330 -89t329.5 88.5t240.5 240.5t89 330q0 174 -85.5 325 t-239 243t-334.5 92q-176 0 -328.5 -88.5t-241.5 -242.5t-89 -329zM489 725q0 208 111 332.5t297 124.5q119 0 227 -52l-37 -83q-98 45 -190 45q-142 0 -222.5 -94.5t-80.5 -264.5q0 -186 74.5 -275t220.5 -89q84 0 198 43v-88q-102 -45 -208 -45q-187 0 -288.5 115 t-101.5 331z" /> -<glyph unicode="ª" horiz-adv-x="686" d="M78 989q0 100 80 151.5t241 59.5l95 4v43q0 77 -38 114.5t-106 37.5q-87 0 -196 -49l-33 73q117 56 231 56q228 0 228 -215v-451h-68l-25 72q-84 -84 -202 -84q-95 0 -151 49t-56 139zM168 993q0 -54 35 -85t96 -31q90 0 142.5 50t52.5 142v64l-88 -5q-116 -6 -177 -36.5 t-61 -98.5z" /> -<glyph unicode="«" horiz-adv-x="885" d="M82 516v27l309 393l62 -43l-254 -363l254 -362l-62 -43zM442 516v27l310 393l61 -43l-254 -363l254 -362l-61 -43z" /> -<glyph unicode="¬" d="M111 682v82h927v-494h-82v412h-845z" /> -<glyph unicode="­" horiz-adv-x="659" d="M92 512v82h475v-82h-475z" /> -<glyph unicode="®" horiz-adv-x="1704" d="M100 731q0 200 100 375t275 276t377 101q200 0 375 -100t276 -275t101 -377q0 -197 -97 -370t-272 -277t-383 -104q-207 0 -382 103.5t-272.5 276.5t-97.5 371zM193 731q0 -178 88.5 -329.5t240.5 -240.5t330 -89t329.5 88.5t240.5 240.5t89 330q0 174 -85.5 325 t-239 243t-334.5 92q-176 0 -328.5 -88.5t-241.5 -242.5t-89 -329zM608 291v880h211q143 0 222 -62t79 -191q0 -79 -38.5 -139.5t-110.5 -94.5l237 -393h-121l-210 360h-168v-360h-101zM709 731h112q91 0 143 46.5t52 135.5q0 172 -197 172h-110v-354z" /> -<glyph unicode="¯" horiz-adv-x="1024" d="M-6 1556v82h1036v-82h-1036z" /> -<glyph unicode="°" horiz-adv-x="877" d="M139 1184q0 132 86.5 215.5t212.5 83.5t212.5 -83.5t86.5 -215.5t-86.5 -215.5t-212.5 -83.5q-130 0 -214.5 83t-84.5 216zM229 1184q0 -91 61 -154t148 -63q86 0 147.5 62t61.5 155q0 92 -60 154.5t-149 62.5q-90 0 -149.5 -64t-59.5 -153z" /> -<glyph unicode="±" d="M111 1v82h948v-82h-948zM111 682v82h432v434h82v-434h434v-82h-434v-432h-82v432h-432z" /> -<glyph unicode="²" horiz-adv-x="688" d="M53 586v78l242 237q125 121 172 193t47 149q0 71 -46.5 112.5t-123.5 41.5q-108 0 -217 -82l-49 65q119 103 270 103q124 0 194 -63.5t70 -174.5q0 -47 -13 -89t-40 -85.5t-68.5 -90t-308.5 -306.5h447v-88h-576z" /> -<glyph unicode="³" horiz-adv-x="688" d="M41 629v88q136 -62 266 -62q115 0 174.5 49t59.5 136q0 83 -59.5 122t-178.5 39h-131v84h135q105 0 158 43.5t53 120.5q0 67 -47 107.5t-127 40.5q-128 0 -246 -78l-47 70q130 94 293 94q127 0 199.5 -60t72.5 -163q0 -78 -44 -131.5t-117 -75.5q186 -45 186 -211 q0 -130 -88.5 -201.5t-247.5 -71.5q-144 0 -264 60z" /> -<glyph unicode="´" horiz-adv-x="1182" d="M393 1241v16q73 79 144.5 171.5t97.5 140.5h141v-17q-36 -52 -122.5 -138t-190.5 -173h-70z" /> -<glyph unicode="µ" horiz-adv-x="1221" d="M182 -492v1579h99v-704q0 -164 69 -238.5t213 -74.5q194 0 285.5 98t91.5 319v600h98v-1087h-84l-18 150h-6q-50 -77 -150 -123.5t-217 -46.5q-99 0 -167.5 27.5t-119.5 84.5q5 -92 5 -170v-414h-99z" /> -<glyph unicode="¶" horiz-adv-x="1341" d="M113 1042q0 260 109 387t341 127h543v-1816h-100v1722h-228v-1722h-100v819q-64 -18 -146 -18q-216 0 -317.5 125t-101.5 376z" /> -<glyph unicode="·" horiz-adv-x="487" d="M162 721q0 98 80 98q82 0 82 -98t-82 -98q-80 0 -80 98z" /> -<glyph unicode="¸" horiz-adv-x="420" d="M43 -393q30 -10 92 -10q78 0 119 28t41 80q0 94 -193 121l93 174h96l-66 -117q168 -37 168 -174q0 -100 -67.5 -150.5t-188.5 -50.5q-68 0 -94 11v88z" /> -<glyph unicode="¹" horiz-adv-x="688" d="M76 1298l274 164h92v-876h-98v547q0 99 12 233q-26 -23 -233 -145z" /> -<glyph unicode="º" horiz-adv-x="739" d="M70 1141q0 162 78 250t223 88q142 0 220.5 -87t78.5 -251q0 -161 -80 -250.5t-223 -89.5t-220 86t-77 254zM160 1141q0 -264 209 -264t209 264q0 131 -50 194.5t-159 63.5t-159 -63.5t-50 -194.5z" /> -<glyph unicode="»" horiz-adv-x="885" d="M72 168l254 362l-254 363l61 43l309 -391v-27l-309 -393zM432 168l254 362l-254 363l62 43l309 -391v-27l-309 -393z" /> -<glyph unicode="¼" horiz-adv-x="1516" d="M59 1298l274 164h92v-876h-98v547q0 99 12 233q-26 -23 -233 -145zM243 0l811 1462h94l-811 -1462h-94zM760 242v60l407 581h96v-563h129v-78h-129v-241h-90v241h-413zM864 320h309v221q0 132 8 232q-6 -12 -21.5 -35.5t-295.5 -417.5z" /> -<glyph unicode="½" horiz-adv-x="1516" d="M11 1298l274 164h92v-876h-98v547q0 99 12 233q-26 -23 -233 -145zM168 0l811 1462h94l-811 -1462h-94zM827 1v78l242 237q125 121 172 193t47 149q0 71 -46.5 112.5t-123.5 41.5q-108 0 -217 -82l-49 65q119 103 270 103q124 0 194 -63.5t70 -174.5q0 -47 -13 -89 t-40 -85.5t-68.5 -90t-308.5 -306.5h447v-88h-576z" /> -<glyph unicode="¾" horiz-adv-x="1516" d="M41 629v88q136 -62 266 -62q115 0 174.5 49t59.5 136q0 83 -59.5 122t-178.5 39h-131v84h135q105 0 158 43.5t53 120.5q0 67 -47 107.5t-127 40.5q-128 0 -246 -78l-47 70q130 94 293 94q127 0 199.5 -60t72.5 -163q0 -78 -44 -131.5t-117 -75.5q186 -45 186 -211 q0 -130 -88.5 -201.5t-247.5 -71.5q-144 0 -264 60zM395 0l811 1462h94l-811 -1462h-94zM863 242v60l407 581h96v-563h129v-78h-129v-241h-90v241h-413zM967 320h309v221q0 132 8 232q-6 -12 -21.5 -35.5t-295.5 -417.5z" /> -<glyph unicode="¿" horiz-adv-x="862" d="M74 -27q0 70 20 124t58.5 102t171.5 159q64 53 98.5 98.5t49.5 94t15 145.5v15h82v-37q0 -125 -39.5 -204.5t-136.5 -164.5l-90 -79q-73 -61 -104 -120.5t-31 -138.5q0 -124 82 -200t221 -76q125 0 233 46l64 27l37 -79q-111 -48 -185.5 -64t-152.5 -16q-184 0 -288.5 99 t-104.5 269zM440 1010q0 98 80 98q82 0 82 -98q0 -53 -23.5 -76t-58.5 -23q-34 0 -57 23t-23 76z" /> -<glyph unicode="À" horiz-adv-x="1229" d="M0 0l588 1468h65l576 -1468h-115l-203 516h-594l-204 -516h-113zM354 608h523l-199 527q-25 62 -60 172q-27 -96 -59 -174zM337 1890v17h142q26 -48 98.5 -142t142.5 -170v-16h-69q-96 79 -188.5 171.5t-125.5 139.5z" /> -<glyph unicode="Á" horiz-adv-x="1229" d="M0 0l588 1468h65l576 -1468h-115l-203 516h-594l-204 -516h-113zM354 608h523l-199 527q-25 62 -60 172q-27 -96 -59 -174zM504 1579v16q73 79 144.5 171.5t97.5 140.5h141v-17q-36 -52 -122.5 -138t-190.5 -173h-70z" /> -<glyph unicode="Â" horiz-adv-x="1229" d="M0 0l588 1468h65l576 -1468h-115l-203 516h-594l-204 -516h-113zM354 608h523l-199 527q-25 62 -60 172q-27 -96 -59 -174zM328 1579v16q62 67 131.5 156t110.5 156h98q68 -120 242 -312v-16h-70q-122 101 -221 207q-108 -114 -221 -207h-70z" /> -<glyph unicode="Ã" horiz-adv-x="1229" d="M0 0l588 1468h65l576 -1468h-115l-203 516h-594l-204 -516h-113zM354 608h523l-199 527q-25 62 -60 172q-27 -96 -59 -174zM287 1581q10 111 63 174.5t137 63.5q48 0 88 -25t82 -59q34 -28 66 -50t61 -22q46 0 77 36.5t48 119.5h76q-16 -116 -69 -177t-132 -61 q-36 0 -75 18.5t-101 71.5q-32 26 -62.5 46t-62.5 20q-45 0 -75 -34.5t-48 -121.5h-73z" /> -<glyph unicode="Ä" horiz-adv-x="1229" d="M0 0l588 1468h65l576 -1468h-115l-203 516h-594l-204 -516h-113zM354 608h523l-199 527q-25 62 -60 172q-27 -96 -59 -174zM367 1727q0 46 15.5 66t47.5 20q64 0 64 -86t-64 -86q-63 0 -63 86zM748 1727q0 46 15.5 66t47.5 20q64 0 64 -86t-64 -86q-63 0 -63 86z" /> -<glyph unicode="Å" horiz-adv-x="1229" d="M0 0l588 1468h65l576 -1468h-115l-203 516h-594l-204 -516h-113zM354 608h523l-199 527q-25 62 -60 172q-27 -96 -59 -174zM402 1610q0 94 60 152.5t157 58.5t157 -59t60 -152q0 -97 -60 -155t-157 -58t-157 58t-60 155zM482 1610q0 -66 37.5 -103.5t99.5 -37.5 t99.5 37.5t37.5 103.5q0 64 -39 101.5t-98 37.5q-62 0 -99.5 -38t-37.5 -101z" /> -<glyph unicode="Æ" horiz-adv-x="1653" d="M-2 0l653 1462h877v-94h-615v-553h576v-94h-576v-627h615v-94h-717v516h-475l-227 -516h-111zM377 608h434v760h-100z" /> -<glyph unicode="Ç" horiz-adv-x="1272" d="M129 735q0 223 84.5 393t243 262.5t368.5 92.5q214 0 383 -80l-41 -92q-160 80 -336 80q-275 0 -433 -176t-158 -482q0 -313 149 -486t426 -173q184 0 338 47v-90q-145 -51 -362 -51q-308 0 -485 199t-177 556zM561 -393q30 -10 92 -10q78 0 119 28t41 80q0 94 -193 121 l93 174h96l-66 -117q168 -37 168 -174q0 -100 -67.5 -150.5t-188.5 -50.5q-68 0 -94 11v88z" /> -<glyph unicode="È" horiz-adv-x="1130" d="M207 0v1462h799v-94h-697v-553h658v-94h-658v-627h697v-94h-799zM314 1890v17h142q26 -48 98.5 -142t142.5 -170v-16h-69q-96 79 -188.5 171.5t-125.5 139.5z" /> -<glyph unicode="É" horiz-adv-x="1130" d="M207 0v1462h799v-94h-697v-553h658v-94h-658v-627h697v-94h-799zM463 1579v16q73 79 144.5 171.5t97.5 140.5h141v-17q-36 -52 -122.5 -138t-190.5 -173h-70z" /> -<glyph unicode="Ê" horiz-adv-x="1130" d="M207 0v1462h799v-94h-697v-553h658v-94h-658v-627h697v-94h-799zM315 1579v16q62 67 131.5 156t110.5 156h98q68 -120 242 -312v-16h-70q-122 101 -221 207q-108 -114 -221 -207h-70z" /> -<glyph unicode="Ë" horiz-adv-x="1130" d="M207 0v1462h799v-94h-697v-553h658v-94h-658v-627h697v-94h-799zM354 1727q0 46 15.5 66t47.5 20q64 0 64 -86t-64 -86q-63 0 -63 86zM735 1727q0 46 15.5 66t47.5 20q64 0 64 -86t-64 -86q-63 0 -63 86z" /> -<glyph unicode="Ì" horiz-adv-x="516" d="M207 0v1462h102v-1462h-102zM-63 1890v17h142q26 -48 98.5 -142t142.5 -170v-16h-69q-96 79 -188.5 171.5t-125.5 139.5z" /> -<glyph unicode="Í" horiz-adv-x="516" d="M207 0v1462h102v-1462h-102zM191 1579v16q73 79 144.5 171.5t97.5 140.5h141v-17q-36 -52 -122.5 -138t-190.5 -173h-70z" /> -<glyph unicode="Î" horiz-adv-x="516" d="M207 0v1462h102v-1462h-102zM-32 1579v16q62 67 131.5 156t110.5 156h98q68 -120 242 -312v-16h-70q-122 101 -221 207q-108 -114 -221 -207h-70z" /> -<glyph unicode="Ï" horiz-adv-x="516" d="M207 0v1462h102v-1462h-102zM5 1727q0 46 15.5 66t47.5 20q64 0 64 -86t-64 -86q-63 0 -63 86zM386 1727q0 46 15.5 66t47.5 20q64 0 64 -86t-64 -86q-63 0 -63 86z" /> -<glyph unicode="Ð" horiz-adv-x="1466" d="M47 678v94h160v690h395q350 0 532.5 -183t182.5 -534q0 -368 -193 -556.5t-567 -188.5h-350v678h-160zM309 90h242q655 0 655 651q0 314 -159.5 472.5t-468.5 158.5h-269v-600h406v-94h-406v-588z" /> -<glyph unicode="Ñ" horiz-adv-x="1477" d="M207 0v1462h102l865 -1296h6q-9 180 -9 342v954h99v-1462h-103l-866 1298h-8q12 -232 12 -350v-948h-98zM400 1581q10 111 63 174.5t137 63.5q48 0 88 -25t82 -59q34 -28 66 -50t61 -22q46 0 77 36.5t48 119.5h76q-16 -116 -69 -177t-132 -61q-36 0 -75 18.5t-101 71.5 q-32 26 -62.5 46t-62.5 20q-45 0 -75 -34.5t-48 -121.5h-73z" /> -<glyph unicode="Ò" horiz-adv-x="1565" d="M129 735q0 349 175.5 549.5t479.5 200.5q306 0 479 -201.5t173 -550.5q0 -348 -174 -550.5t-480 -202.5q-305 0 -479 202.5t-174 552.5zM240 733q0 -314 140 -485.5t402 -171.5q264 0 403.5 170t139.5 487q0 316 -139.5 484.5t-401.5 168.5q-261 0 -402.5 -170 t-141.5 -483zM502 1890v17h142q26 -48 98.5 -142t142.5 -170v-16h-69q-96 79 -188.5 171.5t-125.5 139.5z" /> -<glyph unicode="Ó" horiz-adv-x="1565" d="M129 735q0 349 175.5 549.5t479.5 200.5q306 0 479 -201.5t173 -550.5q0 -348 -174 -550.5t-480 -202.5q-305 0 -479 202.5t-174 552.5zM240 733q0 -314 140 -485.5t402 -171.5q264 0 403.5 170t139.5 487q0 316 -139.5 484.5t-401.5 168.5q-261 0 -402.5 -170 t-141.5 -483zM686 1579v16q73 79 144.5 171.5t97.5 140.5h141v-17q-36 -52 -122.5 -138t-190.5 -173h-70z" /> -<glyph unicode="Ô" horiz-adv-x="1565" d="M129 735q0 349 175.5 549.5t479.5 200.5q306 0 479 -201.5t173 -550.5q0 -348 -174 -550.5t-480 -202.5q-305 0 -479 202.5t-174 552.5zM240 733q0 -314 140 -485.5t402 -171.5q264 0 403.5 170t139.5 487q0 316 -139.5 484.5t-401.5 168.5q-261 0 -402.5 -170 t-141.5 -483zM492 1579v16q62 67 131.5 156t110.5 156h98q68 -120 242 -312v-16h-70q-122 101 -221 207q-108 -114 -221 -207h-70z" /> -<glyph unicode="Õ" horiz-adv-x="1565" d="M129 735q0 349 175.5 549.5t479.5 200.5q306 0 479 -201.5t173 -550.5q0 -348 -174 -550.5t-480 -202.5q-305 0 -479 202.5t-174 552.5zM240 733q0 -314 140 -485.5t402 -171.5q264 0 403.5 170t139.5 487q0 316 -139.5 484.5t-401.5 168.5q-261 0 -402.5 -170 t-141.5 -483zM443 1581q10 111 63 174.5t137 63.5q48 0 88 -25t82 -59q34 -28 66 -50t61 -22q46 0 77 36.5t48 119.5h76q-16 -116 -69 -177t-132 -61q-36 0 -75 18.5t-101 71.5q-32 26 -62.5 46t-62.5 20q-45 0 -75 -34.5t-48 -121.5h-73z" /> -<glyph unicode="Ö" horiz-adv-x="1565" d="M129 735q0 349 175.5 549.5t479.5 200.5q306 0 479 -201.5t173 -550.5q0 -348 -174 -550.5t-480 -202.5q-305 0 -479 202.5t-174 552.5zM240 733q0 -314 140 -485.5t402 -171.5q264 0 403.5 170t139.5 487q0 316 -139.5 484.5t-401.5 168.5q-261 0 -402.5 -170 t-141.5 -483zM529 1727q0 46 15.5 66t47.5 20q64 0 64 -86t-64 -86q-63 0 -63 86zM910 1727q0 46 15.5 66t47.5 20q64 0 64 -86t-64 -86q-63 0 -63 86z" /> -<glyph unicode="×" d="M119 1130l57 58l408 -408l409 408l58 -58l-408 -407l406 -408l-58 -57l-407 408l-406 -408l-57 57l405 408z" /> -<glyph unicode="Ø" horiz-adv-x="1565" d="M129 735q0 349 175.5 549.5t479.5 200.5q232 0 392 -121l108 152l72 -60l-111 -153q191 -207 191 -570q0 -348 -174 -550.5t-480 -202.5q-236 0 -395 120l-86 -120l-74 59l90 127q-188 200 -188 569zM240 733q0 -312 139 -483l739 1034q-133 102 -334 102 q-261 0 -402.5 -170t-141.5 -483zM444 182q133 -106 338 -106q264 0 403.5 170t139.5 487q0 315 -139 486z" /> -<glyph unicode="Ù" horiz-adv-x="1473" d="M190 520v942h103v-946q0 -211 117 -328.5t331 -117.5q209 0 324 115.5t115 320.5v956h102v-946q0 -252 -146 -394t-407 -142q-254 0 -396.5 142.5t-142.5 397.5zM450 1890v17h142q26 -48 98.5 -142t142.5 -170v-16h-69q-96 79 -188.5 171.5t-125.5 139.5z" /> -<glyph unicode="Ú" horiz-adv-x="1473" d="M190 520v942h103v-946q0 -211 117 -328.5t331 -117.5q209 0 324 115.5t115 320.5v956h102v-946q0 -252 -146 -394t-407 -142q-254 0 -396.5 142.5t-142.5 397.5zM633 1579v16q73 79 144.5 171.5t97.5 140.5h141v-17q-36 -52 -122.5 -138t-190.5 -173h-70z" /> -<glyph unicode="Û" horiz-adv-x="1473" d="M190 520v942h103v-946q0 -211 117 -328.5t331 -117.5q209 0 324 115.5t115 320.5v956h102v-946q0 -252 -146 -394t-407 -142q-254 0 -396.5 142.5t-142.5 397.5zM444 1579v16q62 67 131.5 156t110.5 156h98q68 -120 242 -312v-16h-70q-122 101 -221 207 q-108 -114 -221 -207h-70z" /> -<glyph unicode="Ü" horiz-adv-x="1473" d="M190 520v942h103v-946q0 -211 117 -328.5t331 -117.5q209 0 324 115.5t115 320.5v956h102v-946q0 -252 -146 -394t-407 -142q-254 0 -396.5 142.5t-142.5 397.5zM481 1727q0 46 15.5 66t47.5 20q64 0 64 -86t-64 -86q-63 0 -63 86zM862 1727q0 46 15.5 66t47.5 20 q64 0 64 -86t-64 -86q-63 0 -63 86z" /> -<glyph unicode="Ý" horiz-adv-x="1081" d="M0 1462h117l426 -800l428 800h110l-487 -897v-565h-105v557zM434 1579v16q73 79 144.5 171.5t97.5 140.5h141v-17q-36 -52 -122.5 -138t-190.5 -173h-70z" /> -<glyph unicode="Þ" horiz-adv-x="1198" d="M207 0v1462h102v-264h256q522 0 522 -420q0 -212 -144 -325t-408 -113h-226v-340h-102zM309 428h201q247 0 357 81.5t110 264.5q0 169 -104 250.5t-322 81.5h-242v-678z" /> -<glyph unicode="ß" horiz-adv-x="1194" d="M182 0v1206q0 173 103.5 267t292.5 94q188 0 285.5 -72.5t97.5 -210.5q0 -139 -139 -250q-81 -64 -110.5 -100.5t-29.5 -75.5q0 -44 14.5 -68t51.5 -57t102 -78q106 -75 151.5 -124.5t68 -103t22.5 -120.5q0 -156 -88 -241.5t-246 -85.5q-95 0 -174.5 18.5t-126.5 48.5 v107q65 -38 148.5 -62t152.5 -24q114 0 174.5 54.5t60.5 160.5q0 83 -39 144t-149 136q-127 87 -175 147t-48 146q0 60 32.5 110t106.5 108q74 57 106.5 105.5t32.5 106.5q0 93 -70 143t-202 50q-145 0 -226 -69t-81 -196v-1214h-99z" /> -<glyph unicode="à" horiz-adv-x="1085" d="M98 289q0 159 132.5 247t383.5 93l207 6v72q0 155 -63 234t-203 79q-151 0 -313 -84l-37 86q179 84 354 84q179 0 267.5 -93t88.5 -290v-723h-73l-25 172h-8q-82 -105 -168.5 -148.5t-204.5 -43.5q-160 0 -249 82t-89 227zM203 285q0 -102 62.5 -158.5t176.5 -56.5 q174 0 274.5 99.5t100.5 276.5v107l-190 -8q-229 -11 -326.5 -71.5t-97.5 -188.5zM255 1552v17h142q26 -48 98.5 -142t142.5 -170v-16h-69q-96 79 -188.5 171.5t-125.5 139.5z" /> -<glyph unicode="á" horiz-adv-x="1085" d="M98 289q0 159 132.5 247t383.5 93l207 6v72q0 155 -63 234t-203 79q-151 0 -313 -84l-37 86q179 84 354 84q179 0 267.5 -93t88.5 -290v-723h-73l-25 172h-8q-82 -105 -168.5 -148.5t-204.5 -43.5q-160 0 -249 82t-89 227zM203 285q0 -102 62.5 -158.5t176.5 -56.5 q174 0 274.5 99.5t100.5 276.5v107l-190 -8q-229 -11 -326.5 -71.5t-97.5 -188.5zM422 1241v16q73 79 144.5 171.5t97.5 140.5h141v-17q-36 -52 -122.5 -138t-190.5 -173h-70z" /> -<glyph unicode="â" horiz-adv-x="1085" d="M98 289q0 159 132.5 247t383.5 93l207 6v72q0 155 -63 234t-203 79q-151 0 -313 -84l-37 86q179 84 354 84q179 0 267.5 -93t88.5 -290v-723h-73l-25 172h-8q-82 -105 -168.5 -148.5t-204.5 -43.5q-160 0 -249 82t-89 227zM203 285q0 -102 62.5 -158.5t176.5 -56.5 q174 0 274.5 99.5t100.5 276.5v107l-190 -8q-229 -11 -326.5 -71.5t-97.5 -188.5zM251 1241v16q62 67 131.5 156t110.5 156h98q68 -120 242 -312v-16h-70q-122 101 -221 207q-108 -114 -221 -207h-70z" /> -<glyph unicode="ã" horiz-adv-x="1085" d="M98 289q0 159 132.5 247t383.5 93l207 6v72q0 155 -63 234t-203 79q-151 0 -313 -84l-37 86q179 84 354 84q179 0 267.5 -93t88.5 -290v-723h-73l-25 172h-8q-82 -105 -168.5 -148.5t-204.5 -43.5q-160 0 -249 82t-89 227zM203 285q0 -102 62.5 -158.5t176.5 -56.5 q174 0 274.5 99.5t100.5 276.5v107l-190 -8q-229 -11 -326.5 -71.5t-97.5 -188.5zM200 1243q10 111 63 174.5t137 63.5q48 0 88 -25t82 -59q34 -28 66 -50t61 -22q46 0 77 36.5t48 119.5h76q-16 -116 -69 -177t-132 -61q-36 0 -75 18.5t-101 71.5q-32 26 -62.5 46t-62.5 20 q-45 0 -75 -34.5t-48 -121.5h-73z" /> -<glyph unicode="ä" horiz-adv-x="1085" d="M98 289q0 159 132.5 247t383.5 93l207 6v72q0 155 -63 234t-203 79q-151 0 -313 -84l-37 86q179 84 354 84q179 0 267.5 -93t88.5 -290v-723h-73l-25 172h-8q-82 -105 -168.5 -148.5t-204.5 -43.5q-160 0 -249 82t-89 227zM203 285q0 -102 62.5 -158.5t176.5 -56.5 q174 0 274.5 99.5t100.5 276.5v107l-190 -8q-229 -11 -326.5 -71.5t-97.5 -188.5zM282 1389q0 46 15.5 66t47.5 20q64 0 64 -86t-64 -86q-63 0 -63 86zM663 1389q0 46 15.5 66t47.5 20q64 0 64 -86t-64 -86q-63 0 -63 86z" /> -<glyph unicode="å" horiz-adv-x="1085" d="M98 289q0 159 132.5 247t383.5 93l207 6v72q0 155 -63 234t-203 79q-151 0 -313 -84l-37 86q179 84 354 84q179 0 267.5 -93t88.5 -290v-723h-73l-25 172h-8q-82 -105 -168.5 -148.5t-204.5 -43.5q-160 0 -249 82t-89 227zM203 285q0 -102 62.5 -158.5t176.5 -56.5 q174 0 274.5 99.5t100.5 276.5v107l-190 -8q-229 -11 -326.5 -71.5t-97.5 -188.5zM325 1456q0 94 60 152.5t157 58.5t157 -59t60 -152q0 -97 -60 -155t-157 -58t-157 58t-60 155zM405 1456q0 -66 37.5 -103.5t99.5 -37.5t99.5 37.5t37.5 103.5q0 64 -39 101.5t-98 37.5 q-62 0 -99.5 -38t-37.5 -101z" /> -<glyph unicode="æ" horiz-adv-x="1731" d="M98 289q0 154 125 243t377 97l201 6v72q0 155 -61.5 234t-198.5 79q-148 0 -305 -84l-37 86q173 84 346 84q261 0 325 -211q111 213 347 213q184 0 289.5 -134.5t105.5 -363.5v-80h-715q0 -460 348 -460q85 0 150 12t174 57v-90q-92 -41 -165 -55t-161 -14 q-295 0 -397 256q-68 -133 -168 -194.5t-252 -61.5q-156 0 -242 82.5t-86 226.5zM203 285q0 -102 61 -158.5t170 -56.5q169 0 266 99.5t97 276.5v107l-187 -8q-219 -11 -313 -71.5t-94 -188.5zM903 618h604q0 188 -77.5 295t-212.5 107q-284 0 -314 -402z" /> -<glyph unicode="ç" horiz-adv-x="973" d="M119 537q0 270 137 420.5t375 150.5q141 0 270 -49l-27 -88q-141 47 -245 47q-200 0 -303 -123.5t-103 -355.5q0 -220 103 -344.5t288 -124.5q148 0 275 53v-92q-104 -51 -273 -51q-233 0 -365 147t-132 410zM373 -393q30 -10 92 -10q78 0 119 28t41 80q0 94 -193 121 l93 174h96l-66 -117q168 -37 168 -174q0 -100 -67.5 -150.5t-188.5 -50.5q-68 0 -94 11v88z" /> -<glyph unicode="è" horiz-adv-x="1124" d="M119 535q0 260 128 416.5t345 156.5q192 0 303 -134t111 -364v-80h-783q2 -224 104.5 -342t293.5 -118q93 0 163.5 13t178.5 56v-90q-92 -40 -170 -54.5t-172 -14.5q-237 0 -369.5 146t-132.5 409zM229 618h672q0 189 -82 295.5t-227 106.5q-157 0 -252 -103.5 t-111 -298.5zM302 1552v17h142q26 -48 98.5 -142t142.5 -170v-16h-69q-96 79 -188.5 171.5t-125.5 139.5z" /> -<glyph unicode="é" horiz-adv-x="1124" d="M119 535q0 260 128 416.5t345 156.5q192 0 303 -134t111 -364v-80h-783q2 -224 104.5 -342t293.5 -118q93 0 163.5 13t178.5 56v-90q-92 -40 -170 -54.5t-172 -14.5q-237 0 -369.5 146t-132.5 409zM229 618h672q0 189 -82 295.5t-227 106.5q-157 0 -252 -103.5 t-111 -298.5zM452 1241v16q73 79 144.5 171.5t97.5 140.5h141v-17q-36 -52 -122.5 -138t-190.5 -173h-70z" /> -<glyph unicode="ê" horiz-adv-x="1124" d="M119 535q0 260 128 416.5t345 156.5q192 0 303 -134t111 -364v-80h-783q2 -224 104.5 -342t293.5 -118q93 0 163.5 13t178.5 56v-90q-92 -40 -170 -54.5t-172 -14.5q-237 0 -369.5 146t-132.5 409zM229 618h672q0 189 -82 295.5t-227 106.5q-157 0 -252 -103.5 t-111 -298.5zM290 1241v16q62 67 131.5 156t110.5 156h98q68 -120 242 -312v-16h-70q-122 101 -221 207q-108 -114 -221 -207h-70z" /> -<glyph unicode="ë" horiz-adv-x="1124" d="M119 535q0 260 128 416.5t345 156.5q192 0 303 -134t111 -364v-80h-783q2 -224 104.5 -342t293.5 -118q93 0 163.5 13t178.5 56v-90q-92 -40 -170 -54.5t-172 -14.5q-237 0 -369.5 146t-132.5 409zM229 618h672q0 189 -82 295.5t-227 106.5q-157 0 -252 -103.5 t-111 -298.5zM331 1389q0 46 15.5 66t47.5 20q64 0 64 -86t-64 -86q-63 0 -63 86zM712 1389q0 46 15.5 66t47.5 20q64 0 64 -86t-64 -86q-63 0 -63 86z" /> -<glyph unicode="ì" horiz-adv-x="463" d="M182 0v1087h99v-1087h-99zM-34 1552v17h142q26 -48 98.5 -142t142.5 -170v-16h-69q-96 79 -188.5 171.5t-125.5 139.5z" /> -<glyph unicode="í" horiz-adv-x="463" d="M182 0v1087h99v-1087h-99zM107 1241v16q73 79 144.5 171.5t97.5 140.5h141v-17q-36 -52 -122.5 -138t-190.5 -173h-70z" /> -<glyph unicode="î" horiz-adv-x="463" d="M182 0v1087h99v-1087h-99zM-58 1241v16q62 67 131.5 156t110.5 156h98q68 -120 242 -312v-16h-70q-122 101 -221 207q-108 -114 -221 -207h-70z" /> -<glyph unicode="ï" horiz-adv-x="463" d="M182 0v1087h99v-1087h-99zM-21 1389q0 46 15.5 66t47.5 20q64 0 64 -86t-64 -86q-63 0 -63 86zM360 1389q0 46 15.5 66t47.5 20q64 0 64 -86t-64 -86q-63 0 -63 86z" /> -<glyph unicode="ð" horiz-adv-x="1174" d="M117 471q0 228 126.5 357.5t342.5 129.5q108 0 187.5 -33t148.5 -96l4 2q-64 270 -269 459l-270 -157l-49 77l244 146q-86 62 -199 119l45 81q147 -69 248 -145l225 137l49 -84l-202 -121q154 -151 230.5 -353t76.5 -431q0 -276 -124 -427.5t-349 -151.5 q-214 0 -339.5 130t-125.5 361zM221 463q0 -186 94.5 -289.5t268.5 -103.5q179 0 272.5 123t93.5 364q0 146 -97 228.5t-267 82.5q-185 0 -275 -100.5t-90 -304.5z" /> -<glyph unicode="ñ" horiz-adv-x="1208" d="M182 0v1087h84l19 -149h6q106 170 377 170q370 0 370 -397v-711h-98v705q0 164 -69 238.5t-214 74.5q-195 0 -285.5 -98.5t-90.5 -319.5v-600h-99zM282 1243q10 111 63 174.5t137 63.5q48 0 88 -25t82 -59q34 -28 66 -50t61 -22q46 0 77 36.5t48 119.5h76 q-16 -116 -69 -177t-132 -61q-36 0 -75 18.5t-101 71.5q-32 26 -62.5 46t-62.5 20q-45 0 -75 -34.5t-48 -121.5h-73z" /> -<glyph unicode="ò" horiz-adv-x="1200" d="M119 545q0 266 129 414.5t354 148.5q224 0 351.5 -150.5t127.5 -412.5q0 -266 -129 -415.5t-356 -149.5q-143 0 -252 69t-167 198t-58 298zM223 545q0 -224 98.5 -349.5t278.5 -125.5t278.5 125.5t98.5 349.5q0 225 -99.5 349t-279.5 124t-277.5 -123.5t-97.5 -349.5z M335 1552v17h142q26 -48 98.5 -142t142.5 -170v-16h-69q-96 79 -188.5 171.5t-125.5 139.5z" /> -<glyph unicode="ó" horiz-adv-x="1200" d="M119 545q0 266 129 414.5t354 148.5q224 0 351.5 -150.5t127.5 -412.5q0 -266 -129 -415.5t-356 -149.5q-143 0 -252 69t-167 198t-58 298zM223 545q0 -224 98.5 -349.5t278.5 -125.5t278.5 125.5t98.5 349.5q0 225 -99.5 349t-279.5 124t-277.5 -123.5t-97.5 -349.5z M499 1241v16q73 79 144.5 171.5t97.5 140.5h141v-17q-36 -52 -122.5 -138t-190.5 -173h-70z" /> -<glyph unicode="ô" horiz-adv-x="1200" d="M119 545q0 266 129 414.5t354 148.5q224 0 351.5 -150.5t127.5 -412.5q0 -266 -129 -415.5t-356 -149.5q-143 0 -252 69t-167 198t-58 298zM223 545q0 -224 98.5 -349.5t278.5 -125.5t278.5 125.5t98.5 349.5q0 225 -99.5 349t-279.5 124t-277.5 -123.5t-97.5 -349.5z M309 1241v16q62 67 131.5 156t110.5 156h98q68 -120 242 -312v-16h-70q-122 101 -221 207q-108 -114 -221 -207h-70z" /> -<glyph unicode="õ" horiz-adv-x="1200" d="M119 545q0 266 129 414.5t354 148.5q224 0 351.5 -150.5t127.5 -412.5q0 -266 -129 -415.5t-356 -149.5q-143 0 -252 69t-167 198t-58 298zM223 545q0 -224 98.5 -349.5t278.5 -125.5t278.5 125.5t98.5 349.5q0 225 -99.5 349t-279.5 124t-277.5 -123.5t-97.5 -349.5z M264 1243q10 111 63 174.5t137 63.5q48 0 88 -25t82 -59q34 -28 66 -50t61 -22q46 0 77 36.5t48 119.5h76q-16 -116 -69 -177t-132 -61q-36 0 -75 18.5t-101 71.5q-32 26 -62.5 46t-62.5 20q-45 0 -75 -34.5t-48 -121.5h-73z" /> -<glyph unicode="ö" horiz-adv-x="1200" d="M119 545q0 266 129 414.5t354 148.5q224 0 351.5 -150.5t127.5 -412.5q0 -266 -129 -415.5t-356 -149.5q-143 0 -252 69t-167 198t-58 298zM223 545q0 -224 98.5 -349.5t278.5 -125.5t278.5 125.5t98.5 349.5q0 225 -99.5 349t-279.5 124t-277.5 -123.5t-97.5 -349.5z M346 1389q0 46 15.5 66t47.5 20q64 0 64 -86t-64 -86q-63 0 -63 86zM727 1389q0 46 15.5 66t47.5 20q64 0 64 -86t-64 -86q-63 0 -63 86z" /> -<glyph unicode="÷" d="M111 682v82h948v-82h-948zM504 371q0 98 80 98q82 0 82 -98q0 -53 -23.5 -76t-58.5 -23q-34 0 -57 23t-23 76zM504 1075q0 99 80 99q82 0 82 -99q0 -52 -23.5 -75t-58.5 -23q-34 0 -57 23t-23 75z" /> -<glyph unicode="ø" horiz-adv-x="1200" d="M119 545q0 266 129 414.5t354 148.5q179 0 301 -104l96 124l74 -55l-104 -137q112 -147 112 -391q0 -266 -129 -415.5t-356 -149.5q-173 0 -291 98l-86 -113l-72 58l93 120q-121 153 -121 402zM223 545q0 -200 78 -322l543 705q-98 90 -246 90q-180 0 -277.5 -123.5 t-97.5 -349.5zM362 152q94 -82 238 -82q180 0 278.5 125.5t98.5 349.5q0 190 -72 309z" /> -<glyph unicode="ù" horiz-adv-x="1208" d="M170 377v710h98v-704q0 -164 69 -238.5t214 -74.5q194 0 285.5 98t91.5 319v600h98v-1087h-84l-18 150h-6q-106 -170 -377 -170q-371 0 -371 397zM304 1552v17h142q26 -48 98.5 -142t142.5 -170v-16h-69q-96 79 -188.5 171.5t-125.5 139.5z" /> -<glyph unicode="ú" horiz-adv-x="1208" d="M170 377v710h98v-704q0 -164 69 -238.5t214 -74.5q194 0 285.5 98t91.5 319v600h98v-1087h-84l-18 150h-6q-106 -170 -377 -170q-371 0 -371 397zM495 1241v16q73 79 144.5 171.5t97.5 140.5h141v-17q-36 -52 -122.5 -138t-190.5 -173h-70z" /> -<glyph unicode="û" horiz-adv-x="1208" d="M170 377v710h98v-704q0 -164 69 -238.5t214 -74.5q194 0 285.5 98t91.5 319v600h98v-1087h-84l-18 150h-6q-106 -170 -377 -170q-371 0 -371 397zM313 1241v16q62 67 131.5 156t110.5 156h98q68 -120 242 -312v-16h-70q-122 101 -221 207q-108 -114 -221 -207h-70z" /> -<glyph unicode="ü" horiz-adv-x="1208" d="M170 377v710h98v-704q0 -164 69 -238.5t214 -74.5q194 0 285.5 98t91.5 319v600h98v-1087h-84l-18 150h-6q-106 -170 -377 -170q-371 0 -371 397zM350 1389q0 46 15.5 66t47.5 20q64 0 64 -86t-64 -86q-63 0 -63 86zM731 1389q0 46 15.5 66t47.5 20q64 0 64 -86t-64 -86 q-63 0 -63 86z" /> -<glyph unicode="ý" horiz-adv-x="940" d="M0 1087h102l230 -610q105 -281 133 -379h6q42 129 137 385l230 604h102l-487 -1263q-59 -154 -99 -208t-93.5 -81t-129.5 -27q-57 0 -127 21v86q58 -16 125 -16q51 0 90 24t70.5 74.5t73 160t53.5 142.5zM361 1241v16q73 79 144.5 171.5t97.5 140.5h141v-17 q-36 -52 -122.5 -138t-190.5 -173h-70z" /> -<glyph unicode="þ" horiz-adv-x="1219" d="M182 -492v2048h99v-391l-7 -247h7q114 190 368 190q220 0 335.5 -144.5t115.5 -420.5q0 -268 -121.5 -415.5t-331.5 -147.5q-251 0 -366 188h-7l3 -84q4 -74 4 -162v-414h-99zM281 541q0 -255 85.5 -364t278.5 -109q167 0 258.5 124t91.5 347q0 479 -348 479 q-193 0 -279.5 -105t-86.5 -354v-18z" /> -<glyph unicode="ÿ" horiz-adv-x="940" d="M0 1087h102l230 -610q105 -281 133 -379h6q42 129 137 385l230 604h102l-487 -1263q-59 -154 -99 -208t-93.5 -81t-129.5 -27q-57 0 -127 21v86q58 -16 125 -16q51 0 90 24t70.5 74.5t73 160t53.5 142.5zM214 1389q0 46 15.5 66t47.5 20q64 0 64 -86t-64 -86 q-63 0 -63 86zM595 1389q0 46 15.5 66t47.5 20q64 0 64 -86t-64 -86q-63 0 -63 86z" /> -<glyph unicode="ı" horiz-adv-x="463" d="M182 0v1087h99v-1087h-99z" /> -<glyph unicode="Œ" horiz-adv-x="1839" d="M129 735q0 347 174.5 545.5t480.5 198.5q78 0 183 -17h747v-94h-655v-553h616v-94h-616v-627h655v-94h-756q-76 -16 -176 -16q-305 0 -479 200t-174 551zM240 733q0 -315 140.5 -484t401.5 -169q109 0 174 18v1266q-62 16 -172 16q-262 0 -403 -167.5t-141 -479.5z" /> -<glyph unicode="œ" horiz-adv-x="1942" d="M119 545q0 266 129 414.5t354 148.5q151 0 251 -70t157 -209q110 279 399 279q192 0 303 -134t111 -364v-80h-762q2 -230 100.5 -345t276.5 -115q93 0 163.5 13t178.5 56v-90q-92 -40 -170 -54.5t-172 -14.5q-156 0 -266.5 67.5t-165.5 198.5q-59 -128 -158 -197 t-252 -69q-143 0 -252 69t-167 198t-58 298zM223 545q0 -224 98.5 -349.5t278.5 -125.5q174 0 265 122.5t91 352.5q0 224 -93 348.5t-265 124.5q-180 0 -277.5 -123.5t-97.5 -349.5zM1065 618h653q0 189 -82 295.5t-227 106.5q-155 0 -242 -104t-102 -298z" /> -<glyph unicode="Ÿ" horiz-adv-x="1081" d="M0 1462h117l426 -800l428 800h110l-487 -897v-565h-105v557zM288 1727q0 46 15.5 66t47.5 20q64 0 64 -86t-64 -86q-63 0 -63 86zM669 1727q0 46 15.5 66t47.5 20q64 0 64 -86t-64 -86q-63 0 -63 86z" /> -<glyph unicode="ˆ" horiz-adv-x="1182" d="M299 1241v16q62 67 131.5 156t110.5 156h98q68 -120 242 -312v-16h-70q-122 101 -221 207q-108 -114 -221 -207h-70z" /> -<glyph unicode="˚" horiz-adv-x="1182" d="M371 1456q0 94 60 152.5t157 58.5t157 -59t60 -152q0 -97 -60 -155t-157 -58t-157 58t-60 155zM451 1456q0 -66 37.5 -103.5t99.5 -37.5t99.5 37.5t37.5 103.5q0 64 -39 101.5t-98 37.5q-62 0 -99.5 -38t-37.5 -101z" /> -<glyph unicode="˜" horiz-adv-x="1182" d="M283 1243q10 111 63 174.5t137 63.5q48 0 88 -25t82 -59q34 -28 66 -50t61 -22q46 0 77 36.5t48 119.5h76q-16 -116 -69 -177t-132 -61q-36 0 -75 18.5t-101 71.5q-32 26 -62.5 46t-62.5 20q-45 0 -75 -34.5t-48 -121.5h-73z" /> -<glyph unicode=" " horiz-adv-x="953" /> -<glyph unicode=" " horiz-adv-x="1907" /> -<glyph unicode=" " horiz-adv-x="953" /> -<glyph unicode=" " horiz-adv-x="1907" /> -<glyph unicode=" " horiz-adv-x="635" /> -<glyph unicode=" " horiz-adv-x="476" /> -<glyph unicode=" " horiz-adv-x="317" /> -<glyph unicode=" " horiz-adv-x="317" /> -<glyph unicode=" " horiz-adv-x="238" /> -<glyph unicode=" " horiz-adv-x="381" /> -<glyph unicode=" " horiz-adv-x="105" /> -<glyph unicode="‐" horiz-adv-x="659" d="M92 512v82h475v-82h-475z" /> -<glyph unicode="‑" horiz-adv-x="659" d="M92 512v82h475v-82h-475z" /> -<glyph unicode="‒" horiz-adv-x="659" d="M92 512v82h475v-82h-475z" /> -<glyph unicode="–" horiz-adv-x="1024" d="M82 512v82h860v-82h-860z" /> -<glyph unicode="—" horiz-adv-x="2048" d="M82 512v82h1884v-82h-1884z" /> -<glyph unicode="‘" horiz-adv-x="297" d="M29 981q32 112 81.5 251t92.5 230h65q-30 -101 -64.5 -257t-45.5 -244h-117z" /> -<glyph unicode="’" horiz-adv-x="297" d="M29 961q29 96 61 241.5t49 259.5h117l12 -20q-75 -265 -174 -481h-65z" /> -<glyph unicode="‚" horiz-adv-x="451" d="M68 -263q29 96 61 241.5t49 259.5h117l12 -20q-75 -265 -174 -481h-65z" /> -<glyph unicode="“" horiz-adv-x="614" d="M29 981q32 112 81.5 251t92.5 230h65q-30 -101 -64.5 -257t-45.5 -244h-117zM346 981q34 120 83 255t91 226h66q-30 -98 -63 -248.5t-48 -252.5h-117z" /> -<glyph unicode="”" horiz-adv-x="614" d="M29 961q29 96 61 241.5t49 259.5h117l12 -20q-75 -265 -174 -481h-65zM346 961q30 98 63 248.5t48 252.5h116l13 -20q-36 -128 -85 -261t-89 -220h-66z" /> -<glyph unicode="„" horiz-adv-x="768" d="M68 -263q29 96 61 241.5t49 259.5h117l12 -20q-75 -265 -174 -481h-65zM385 -263q30 98 63 248.5t48 252.5h116l13 -20q-36 -128 -85 -261t-89 -220h-66z" /> -<glyph unicode="•" horiz-adv-x="770" d="M231 748q0 89 40.5 134.5t113.5 45.5t113.5 -47t40.5 -133q0 -85 -41 -133t-113 -48t-113 47t-41 134z" /> -<glyph unicode="…" horiz-adv-x="1466" d="M162 78q0 98 80 98q82 0 82 -98t-82 -98q-80 0 -80 98zM651 78q0 98 80 98q82 0 82 -98t-82 -98q-80 0 -80 98zM1141 78q0 98 80 98q82 0 82 -98t-82 -98q-80 0 -80 98z" /> -<glyph unicode=" " horiz-adv-x="381" /> -<glyph unicode="‹" horiz-adv-x="524" d="M82 516v27l309 393l62 -43l-254 -363l254 -362l-62 -43z" /> -<glyph unicode="›" horiz-adv-x="524" d="M72 168l254 362l-254 363l61 43l309 -391v-27l-309 -393z" /> -<glyph unicode="⁄" horiz-adv-x="246" d="M-332 0l811 1462h94l-811 -1462h-94z" /> -<glyph unicode=" " horiz-adv-x="476" /> -<glyph unicode="⁴" horiz-adv-x="688" d="M25 827v60l407 581h96v-563h129v-78h-129v-241h-90v241h-413zM129 905h309v221q0 132 8 232q-6 -12 -21.5 -35.5t-295.5 -417.5z" /> -<glyph unicode="€" d="M74 528v82h172q-4 38 -4 113l4 102h-172v82h184q39 272 183 425t362 153q88 0 161 -17t148 -57l-39 -86q-132 72 -270 72q-174 0 -288 -125.5t-155 -364.5h502v-82h-510l-4 -104v-24q0 -65 4 -87h449v-82h-443q30 -217 147.5 -338.5t301.5 -121.5q148 0 287 65v-94 q-81 -34 -150.5 -46.5t-140.5 -12.5q-228 0 -367.5 140t-181.5 408h-180z" /> -<glyph unicode="™" horiz-adv-x="1485" d="M10 1384v78h522v-78h-219v-643h-86v643h-217zM608 741v721h125l221 -606l224 606h125v-721h-86v398l4 207h-7l-227 -605h-74l-221 609h-6l4 -201v-408h-82z" /> -<glyph unicode="−" d="M111 682v82h948v-82h-948z" /> -<glyph unicode="" horiz-adv-x="1085" d="M0 1085h1085v-1085h-1085v1085z" /> -<glyph unicode="fi" horiz-adv-x="1077" d="M29 1001v58l202 37v84q0 200 73.5 293.5t240.5 93.5q90 0 180 -27l-23 -86q-80 25 -159 25q-116 0 -164.5 -68.5t-48.5 -222.5v-101h256v-86h-256v-1001h-99v1001h-202zM782 1389q0 96 63 96q31 0 48.5 -25t17.5 -71q0 -45 -17.5 -71t-48.5 -26q-63 0 -63 97zM796 0v1087 h99v-1087h-99z" /> -<glyph unicode="fl" horiz-adv-x="1077" d="M29 1001v58l202 37v84q0 200 73.5 293.5t240.5 93.5q90 0 180 -27l-23 -86q-80 25 -159 25q-116 0 -164.5 -68.5t-48.5 -222.5v-101h256v-86h-256v-1001h-99v1001h-202zM796 0v1556h99v-1556h-99z" /> -<glyph unicode="ffi" horiz-adv-x="1692" d="M29 1001v58l202 37v84q0 200 73.5 293.5t240.5 93.5q90 0 180 -27l-23 -86q-80 25 -159 25q-116 0 -164.5 -68.5t-48.5 -222.5v-101h256v-86h-256v-1001h-99v1001h-202zM643 1001v58l202 37v84q0 200 73.5 293.5t240.5 93.5q90 0 180 -27l-23 -86q-80 25 -159 25 q-116 0 -164.5 -68.5t-48.5 -222.5v-101h256v-86h-256v-1001h-99v1001h-202zM1397 1389q0 96 63 96q31 0 48.5 -25t17.5 -71q0 -45 -17.5 -71t-48.5 -26q-63 0 -63 97zM1411 0v1087h99v-1087h-99z" /> -<glyph unicode="ffl" horiz-adv-x="1692" d="M29 1001v58l202 37v84q0 200 73.5 293.5t240.5 93.5q90 0 180 -27l-23 -86q-80 25 -159 25q-116 0 -164.5 -68.5t-48.5 -222.5v-101h256v-86h-256v-1001h-99v1001h-202zM643 1001v58l202 37v84q0 200 73.5 293.5t240.5 93.5q90 0 180 -27l-23 -86q-80 25 -159 25 q-116 0 -164.5 -68.5t-48.5 -222.5v-101h256v-86h-256v-1001h-99v1001h-202zM1411 0v1556h99v-1556h-99z" /> -</font> -</defs></svg> -\ No newline at end of file diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-Light-webfont.ttf b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-Light-webfont.ttf Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-Light-webfont.woff b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-Light-webfont.woff Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-LightItalic-webfont.eot b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-LightItalic-webfont.eot Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-LightItalic-webfont.svg b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-LightItalic-webfont.svg @@ -1,252 +0,0 @@ -<?xml version="1.0" standalone="no"?> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" > -<svg xmlns="http://www.w3.org/2000/svg"> -<metadata> -This is a custom SVG webfont generated by Font Squirrel. -Copyright : Digitized data copyright 20102011 Google Corporation -Foundry : Ascender Corporation -Foundry URL : httpwwwascendercorpcom -</metadata> -<defs> -<font id="OpenSansLightItalic" horiz-adv-x="1128" > -<font-face units-per-em="2048" ascent="1638" descent="-410" /> -<missing-glyph horiz-adv-x="532" /> -<glyph unicode=" " horiz-adv-x="532" /> -<glyph unicode="	" horiz-adv-x="532" /> -<glyph unicode=" " horiz-adv-x="532" /> -<glyph unicode="!" horiz-adv-x="502" d="M80 57q0 56 25 88.5t69 32.5q66 0 66 -72q0 -53 -25 -87.5t-68 -34.5q-67 0 -67 73zM186 377l203 1085h119l-260 -1085h-62z" /> -<glyph unicode=""" horiz-adv-x="721" d="M248 934l80 528h127l-146 -528h-61zM578 934l79 528h127l-145 -528h-61z" /> -<glyph unicode="#" horiz-adv-x="1323" d="M82 451l8 79h299l119 398h-297l8 80h311l134 454h90l-136 -454h365l135 454h86l-135 -454h285l-8 -80h-302l-118 -398h303l-8 -79h-320l-133 -451h-90l135 451h-360l-134 -451h-88l134 451h-283zM475 530h363l120 398h-362z" /> -<glyph unicode="$" d="M141 182v94q65 -34 153.5 -53.5t160.5 -19.5l110 512q-110 53 -153 91t-66.5 87.5t-23.5 116.5q0 155 105.5 250.5t272.5 99.5l41 192h80l-41 -192q149 -5 277 -68l-35 -78q-110 61 -256 70l-109 -514q124 -60 172.5 -99.5t73.5 -88.5t25 -115q0 -151 -110.5 -243 t-297.5 -103l-53 -240h-82l51 240q-79 2 -158 18t-137 43zM410 1018q0 -78 37 -128.5t137 -96.5l102 491q-134 -9 -205 -80t-71 -186zM537 203q142 7 223.5 74.5t81.5 183.5q0 76 -48 129.5t-157 97.5z" /> -<glyph unicode="%" horiz-adv-x="1556" d="M145 862q0 160 52 312t138 229.5t193 77.5q232 0 232 -283q0 -175 -50 -327t-136 -230t-197 -78q-112 0 -172 75.5t-60 223.5zM213 0l1135 1462h110l-1139 -1462h-106zM231 868q0 -115 41 -173t113 -58q84 0 148.5 72t102.5 204t38 277q0 109 -36 163t-114 54 q-79 0 -145 -71.5t-107 -203t-41 -264.5zM905 276q0 160 52 312t138 229.5t193 77.5q121 0 176.5 -71.5t55.5 -211.5q0 -175 -50 -327t-136 -230t-197 -78q-112 0 -172 75.5t-60 223.5zM991 283q0 -116 41 -174t113 -58q130 0 209.5 166.5t79.5 386.5q0 109 -36 163t-114 54 q-80 0 -146.5 -72.5t-106.5 -202.5t-40 -263z" /> -<glyph unicode="&" horiz-adv-x="1331" d="M78 324q0 162 99 277.5t325 215.5l-41 67q-78 128 -78 251q0 157 101 253.5t264 96.5q145 0 227 -76.5t82 -206.5q0 -85 -41 -154t-121 -128t-256 -138l330 -463q73 75 135.5 176.5t91.5 186.5h111q-102 -247 -285 -436l184 -246h-123l-131 184q-121 -108 -242 -156 t-266 -48q-167 0 -266.5 94t-99.5 250zM176 328q0 -119 78 -192t211 -73q108 0 211.5 42.5t222.5 146.5l-352 493q-164 -79 -232 -134.5t-103.5 -124t-35.5 -158.5zM485 1135q0 -132 109 -281q203 89 279.5 163.5t76.5 182.5q0 91 -56.5 143t-145.5 52q-125 0 -194 -68 t-69 -192z" /> -<glyph unicode="'" horiz-adv-x="403" d="M254 934l80 528h127l-146 -528h-61z" /> -<glyph unicode="(" horiz-adv-x="526" d="M104 270q0 343 122 633t382 559h105q-259 -276 -384.5 -568t-125.5 -618q0 -317 127 -600h-80q-146 262 -146 594z" /> -<glyph unicode=")" horiz-adv-x="526" d="M-156 -324q257 274 383.5 566.5t126.5 619.5q0 148 -28.5 294t-98.5 306h80q146 -262 146 -594q0 -345 -123.5 -636t-380.5 -556h-105z" /> -<glyph unicode="*" horiz-adv-x="1137" d="M233 1217l39 102l394 -168l47 408l121 -19l-109 -405l438 8l-8 -107l-416 29l181 -401l-115 -37l-135 417l-285 -348l-78 78l318 318z" /> -<glyph unicode="+" d="M162 672v100h401v404h101v-404h401v-100h-401v-400h-101v400h-401z" /> -<glyph unicode="," horiz-adv-x="451" d="M-90 -264q79 132 141 271t88 231h111l8 -23q-34 -92 -114 -233.5t-160 -245.5h-74z" /> -<glyph unicode="-" horiz-adv-x="629" d="M82 502l18 90h457l-16 -90h-459z" /> -<glyph unicode="." horiz-adv-x="485" d="M82 55q0 56 25 88.5t69 32.5q66 0 66 -72q0 -53 -25 -87.5t-67 -34.5q-68 0 -68 73z" /> -<glyph unicode="/" horiz-adv-x="641" d="M-100 0l815 1462h112l-817 -1462h-110z" /> -<glyph unicode="0" d="M139 494q0 186 44.5 381.5t124 334t187 207t240.5 68.5q340 0 340 -469q0 -201 -41 -405t-116.5 -346t-183.5 -213.5t-242 -71.5q-176 0 -264.5 126.5t-88.5 387.5zM242 504q0 -222 62.5 -329t197.5 -107q139 0 244 112t166 337t61 489q0 199 -59.5 295t-190.5 96 q-134 0 -241.5 -113t-173.5 -329t-66 -451z" /> -<glyph unicode="1" d="M354 1204l406 258h90l-313 -1462h-105l225 1055q19 92 74 293q-42 -36 -75.5 -61t-249.5 -161z" /> -<glyph unicode="2" d="M39 0l22 104l449 402q198 177 284 276.5t126.5 186.5t40.5 180q0 112 -66 178t-197 66q-176 0 -333 -129l-54 73q180 146 394 146q173 0 268.5 -85t95.5 -237q0 -110 -43.5 -208.5t-141.5 -211.5t-311 -303l-383 -338v-4h736l-17 -96h-870z" /> -<glyph unicode="3" d="M55 53v101q172 -86 344 -86q197 0 303.5 89.5t106.5 252.5q0 145 -89 223t-247 78h-117l21 96h110q209 0 333 95.5t124 258.5q0 114 -63.5 175t-188.5 61q-167 0 -344 -131l-49 75q84 67 188 104.5t218 37.5q161 0 252.5 -82.5t91.5 -226.5q0 -162 -106 -275t-286 -143 v-4q117 -24 185.5 -115.5t68.5 -226.5q0 -134 -64 -233t-179.5 -148t-274.5 -49q-96 0 -184.5 20.5t-153.5 52.5z" /> -<glyph unicode="4" d="M23 371l20 96l881 1010h118l-215 -1018h265l-21 -88h-264l-80 -371h-96l80 371h-688zM150 459h579q79 369 119 558.5t86 354.5h-4q-66 -91 -129 -166z" /> -<glyph unicode="5" d="M88 51v107q170 -90 340 -90q208 0 328.5 114.5t120.5 313.5q0 140 -85 219.5t-225 79.5q-133 0 -243 -41l-66 49l193 659h624l-18 -96h-541l-149 -516q98 29 215 29q188 0 292.5 -102t104.5 -279q0 -237 -148 -377.5t-407 -140.5q-84 0 -177.5 20t-158.5 51z" /> -<glyph unicode="6" d="M170 428q0 283 105 544.5t269.5 385t383.5 123.5q123 0 182 -21l-18 -90q-86 23 -170 23q-233 0 -393.5 -174t-233.5 -502h8q68 94 164 143t211 49q161 0 250.5 -100.5t89.5 -282.5q0 -156 -60 -281t-171 -195t-257 -70q-171 0 -265.5 119t-94.5 329zM270 414 q0 -164 72.5 -255t200.5 -91q112 0 196.5 58.5t130 162t45.5 229.5q0 146 -67 224.5t-195 78.5q-81 0 -154 -31.5t-129 -87t-78 -115t-22 -173.5z" /> -<glyph unicode="7" d="M244 0l796 1366h-766l23 96h858l-20 -110l-779 -1352h-112z" /> -<glyph unicode="8" d="M98 326q0 159 100.5 268.5t321.5 187.5q-100 72 -144 152t-44 180q0 159 114 265t291 106q163 0 258 -85t95 -229q0 -138 -84 -234.5t-285 -172.5q130 -78 190 -170.5t60 -208.5t-58 -208t-165.5 -144.5t-260.5 -52.5q-178 0 -283.5 92.5t-105.5 253.5zM201 340 q0 -136 77.5 -206.5t219.5 -70.5q168 0 270 91t102 233q0 104 -62 189t-198 157q-218 -73 -313.5 -167.5t-95.5 -225.5zM428 1114q0 -91 41.5 -159t157.5 -142q192 62 279 144t87 206q0 109 -70.5 172.5t-195.5 63.5q-130 0 -214.5 -82t-84.5 -203z" /> -<glyph unicode="9" d="M115 2v90q87 -29 192 -29q474 0 627 674h-8q-140 -192 -367 -192q-162 0 -255 105t-93 284q0 155 59.5 281t170.5 196t257 70q174 0 267.5 -115.5t93.5 -333.5q0 -288 -101.5 -548t-263.5 -382t-393 -122q-114 0 -186 22zM313 942q0 -145 67.5 -225t192.5 -80 q83 0 157.5 32.5t129 87.5t76.5 114t22 176q0 166 -71 256t-201 90q-112 0 -197.5 -58.5t-130.5 -162.5t-45 -230z" /> -<glyph unicode=":" horiz-adv-x="485" d="M102 55q0 56 25.5 88.5t69.5 32.5q65 0 65 -72q0 -55 -25.5 -88.5t-66.5 -33.5q-68 0 -68 73zM260 989q0 57 25.5 89t68.5 32q66 0 66 -72q0 -55 -25 -89t-67 -34q-68 0 -68 74z" /> -<glyph unicode=";" horiz-adv-x="485" d="M-53 -264q79 132 141 271t88 231h111l8 -23q-35 -96 -118.5 -242t-156.5 -237h-73zM266 989q0 57 25.5 89t68.5 32q66 0 66 -72q0 -55 -25 -89t-67 -34q-68 0 -68 74z" /> -<glyph unicode="<" d="M137 676v74l914 471v-103l-801 -399l801 -350v-107z" /> -<glyph unicode="=" d="M168 461v98h903v-98h-903zM168 885v100h903v-100h-903z" /> -<glyph unicode=">" d="M170 262v107l801 350l-801 399v103l915 -471v-74z" /> -<glyph unicode="?" horiz-adv-x="799" d="M170 59q0 56 25 88.5t69 32.5q66 0 66 -71q0 -54 -24.5 -88.5t-67.5 -34.5q-68 0 -68 73zM182 1376q85 49 171.5 78t187.5 29q159 0 250.5 -84.5t91.5 -229.5q0 -127 -66 -234t-231 -226q-85 -61 -132.5 -108.5t-73 -95t-46.5 -143.5h-92l6 29q29 132 82 206.5t157 147.5 q118 84 175 145.5t86.5 127.5t29.5 141q0 108 -67.5 170t-182.5 62q-139 0 -307 -101z" /> -<glyph unicode="@" horiz-adv-x="1724" d="M125 508q0 276 121.5 493.5t337 337t473.5 119.5q189 0 330.5 -72.5t221 -213t79.5 -314.5q0 -179 -56 -323.5t-154.5 -227t-211.5 -82.5q-98 0 -154.5 55t-56.5 144h-4q-54 -97 -132.5 -148t-168.5 -51q-112 0 -178 73t-66 202q0 156 63 283t178 198.5t261 71.5 q122 0 252 -52l-84 -315q-39 -140 -39 -221q0 -71 34.5 -111.5t100.5 -40.5q86 0 160 73.5t117.5 198t43.5 251.5q0 156 -65 277t-187 188t-292 67q-235 0 -424.5 -108.5t-295.5 -304t-106 -439.5q0 -288 155 -449t435 -161q207 0 420 82v-90q-210 -82 -428 -82 q-203 0 -357.5 82.5t-238.5 239t-84 370.5zM610 506q0 -92 40.5 -142.5t113.5 -50.5q101 0 180.5 89t124.5 255l78 289q-66 23 -139 23q-113 0 -204.5 -59t-142.5 -165.5t-51 -238.5z" /> -<glyph unicode="A" horiz-adv-x="1059" d="M-111 0l822 1468h67l201 -1468h-105l-69 520h-512l-287 -520h-117zM344 612h449l-39 291q-31 242 -39 402q-30 -63 -64.5 -130t-306.5 -563z" /> -<glyph unicode="B" horiz-adv-x="1202" d="M102 0l310 1462h379q190 0 290.5 -84t100.5 -241q0 -153 -90 -249t-254 -124v-4q125 -31 188.5 -113.5t63.5 -204.5q0 -205 -140.5 -323.5t-390.5 -118.5h-457zM223 90h342q201 0 309.5 87.5t108.5 256.5q0 145 -90 216t-275 71h-260zM377 811h278q206 0 313 81t107 238 q0 119 -78 180.5t-229 61.5h-272z" /> -<glyph unicode="C" horiz-adv-x="1169" d="M170 535q0 266 104.5 488t284.5 341t402 119q177 0 307 -68l-45 -90q-55 30 -124.5 47t-137.5 17q-197 0 -351.5 -104.5t-245 -304.5t-90.5 -441q0 -225 110.5 -346t317.5 -121q140 0 304 51v-94q-156 -49 -316 -49q-252 0 -386 145t-134 410z" /> -<glyph unicode="D" horiz-adv-x="1350" d="M102 0l310 1462h305q282 0 426.5 -147.5t144.5 -435.5q0 -253 -109.5 -461.5t-300.5 -313t-446 -104.5h-330zM221 90h209q226 0 394.5 94.5t261 275.5t92.5 412q0 498 -476 498h-206z" /> -<glyph unicode="E" horiz-adv-x="1067" d="M102 0l310 1462h727l-21 -94h-624l-117 -553h590l-21 -94h-588l-135 -627h627l-21 -94h-727z" /> -<glyph unicode="F" horiz-adv-x="981" d="M102 0l310 1462h708l-20 -94h-604l-134 -620h570l-21 -95h-569l-137 -653h-103z" /> -<glyph unicode="G" horiz-adv-x="1374" d="M170 547q0 265 105 483.5t283.5 335.5t395.5 117q113 0 203 -19t184 -59l-38 -94q-110 46 -189.5 62t-167.5 16q-184 0 -339 -107.5t-244 -301.5t-89 -433q0 -229 114.5 -352t326.5 -123q155 0 309 47l117 526h-303l18 90h406l-150 -682q-211 -73 -405 -73 q-257 0 -397 146t-140 421z" /> -<glyph unicode="H" horiz-adv-x="1366" d="M102 0l310 1462h102l-139 -649h760l137 649h100l-309 -1462h-100l151 719h-760l-149 -719h-103z" /> -<glyph unicode="I" horiz-adv-x="504" d="M102 0l310 1462h98l-309 -1462h-99z" /> -<glyph unicode="J" horiz-adv-x="477" d="M-324 -336l11 92q57 -20 137 -20q213 0 262 241l309 1485h105l-314 -1491q-35 -170 -125 -250.5t-241 -80.5q-48 0 -88 8t-56 16z" /> -<glyph unicode="K" horiz-adv-x="1122" d="M102 0l310 1462h102l-158 -723l133 121l680 602h138l-699 -610l371 -852h-111l-342 788l-190 -153l-131 -635h-103z" /> -<glyph unicode="L" horiz-adv-x="938" d="M102 0l310 1462h102l-289 -1366h621l-23 -96h-721z" /> -<glyph unicode="M" horiz-adv-x="1669" d="M109 0l309 1462h143l205 -1257h6l733 1257h150l-301 -1462h-101l191 901q79 369 100 447h-6l-780 -1348h-51l-222 1348h-6q-20 -154 -78 -426l-196 -922h-96z" /> -<glyph unicode="N" horiz-adv-x="1372" d="M102 0l310 1462h80l522 -1294h8q23 176 74 416l188 878h94l-309 -1462h-86l-516 1284h-8q-23 -149 -48 -273t-214 -1011h-95z" /> -<glyph unicode="O" horiz-adv-x="1464" d="M172 559q0 262 93 477.5t255 331t373 115.5q247 0 378.5 -148.5t131.5 -423.5q0 -255 -94 -481.5t-252 -338t-365 -111.5q-250 0 -385 149t-135 430zM276 573q0 -245 109.5 -373t319.5 -128q169 0 300 98.5t210 300t79 430.5q0 240 -104.5 364t-310.5 124 q-174 0 -308.5 -101t-214.5 -298t-80 -417z" /> -<glyph unicode="P" horiz-adv-x="1145" d="M102 0l310 1462h315q202 0 310 -92.5t108 -267.5q0 -500 -610 -500h-201l-129 -602h-103zM350 694h191q252 0 373.5 96.5t121.5 305.5q0 274 -329 274h-211z" /> -<glyph unicode="Q" horiz-adv-x="1464" d="M172 559q0 262 93 477.5t255 331t373 115.5q247 0 378.5 -148.5t131.5 -423.5q0 -216 -70 -418t-186.5 -324t-274.5 -167l267 -350h-142l-231 332l-74 -4q-250 0 -385 149t-135 430zM276 573q0 -245 109.5 -373t319.5 -128q169 0 300 98.5t210 300t79 430.5 q0 240 -104.5 364t-310.5 124q-174 0 -308.5 -101t-214.5 -298t-80 -417z" /> -<glyph unicode="R" horiz-adv-x="1145" d="M102 0l310 1462h303q430 0 430 -360q0 -182 -103.5 -303t-281.5 -152q201 -591 221 -647h-111l-211 633h-323l-131 -633h-103zM358 725h252q208 0 317 95.5t109 281.5q0 268 -329 268h-211z" /> -<glyph unicode="S" horiz-adv-x="1020" d="M37 55v109q163 -92 348 -92q188 0 295.5 86.5t107.5 232.5q0 61 -17 104.5t-52.5 78.5t-91 68t-131.5 75q-150 76 -209.5 164t-59.5 206t59 207.5t165 139t237 49.5q99 0 180 -17.5t168 -60.5l-32 -94q-66 40 -151.5 63t-164.5 23q-163 0 -259.5 -82.5t-96.5 -218.5 q0 -103 49 -170t182 -133q154 -79 213.5 -130t89 -113t29.5 -147q0 -126 -65.5 -224.5t-179.5 -148.5t-269 -50q-88 0 -172.5 17t-171.5 58z" /> -<glyph unicode="T" horiz-adv-x="985" d="M193 1368l20 94h973l-19 -94h-440l-289 -1368h-102l289 1368h-432z" /> -<glyph unicode="U" horiz-adv-x="1370" d="M176 381q0 83 27 201l186 880h103l-193 -899q-20 -89 -20 -184q0 -309 342 -309q195 0 307.5 96.5t158.5 318.5l207 977h101l-207 -977q-58 -270 -197 -387.5t-375 -117.5q-440 0 -440 401z" /> -<glyph unicode="V" horiz-adv-x="1079" d="M201 1462h100l117 -950q26 -217 35 -365h4q51 111 124 247l572 1068h117l-799 -1462h-88z" /> -<glyph unicode="W" horiz-adv-x="1702" d="M238 1462h100l47 -1031l4 -165l-2 -86h6q85 226 170 398l434 884h105l61 -878q19 -266 19 -410h6q30 86 61.5 163t493.5 1125h108q-169 -365 -330.5 -731t-328.5 -731h-78l-78 1075q-11 142 -11 219l1 47h-8q-27 -76 -62 -153.5t-563 -1187.5h-82z" /> -<glyph unicode="X" horiz-adv-x="971" d="M-135 0l608 766l-272 696h106l240 -626l483 626h119l-555 -719l285 -743h-107l-254 678l-526 -678h-127z" /> -<glyph unicode="Y" horiz-adv-x="965" d="M193 1462h100l201 -817l544 817h117l-631 -932l-108 -530h-105l119 545z" /> -<glyph unicode="Z" d="M-12 0l22 92l1069 1276h-764l23 94h887l-19 -88l-1069 -1280h799l-23 -94h-925z" /> -<glyph unicode="[" horiz-adv-x="537" d="M-57 -324l376 1786h429l-19 -90h-330l-340 -1605h330l-20 -91h-426z" /> -<glyph unicode="\" horiz-adv-x="641" d="M209 1462h86l242 -1462h-82z" /> -<glyph unicode="]" horiz-adv-x="537" d="M-176 -324l18 91h330l340 1605h-330l21 90h426l-377 -1786h-428z" /> -<glyph unicode="^" horiz-adv-x="1047" d="M70 569l587 906h91l260 -906h-105l-217 809l-500 -809h-116z" /> -<glyph unicode="_" horiz-adv-x="801" d="M-182 -291l18 86h807l-18 -86h-807z" /> -<glyph unicode="`" horiz-adv-x="1135" d="M487 1548v21h115q46 -129 164 -303v-25h-66q-50 52 -114 144.5t-99 162.5z" /> -<glyph unicode="a" horiz-adv-x="1133" d="M102 354q0 197 75 376t200.5 276.5t277.5 97.5q232 0 279 -219h6l59 202h80l-229 -1087h-82l45 274h-6q-84 -142 -187 -218t-237 -76q-281 0 -281 374zM205 365q0 -152 50 -223.5t151 -71.5q89 0 177.5 62t159 166t107.5 230t37 213q0 79 -26 141.5t-77 99t-127 36.5 q-124 0 -224 -82t-164 -245.5t-64 -325.5z" /> -<glyph unicode="b" horiz-adv-x="1151" d="M76 0l327 1556h95q-131 -628 -162 -751h6q93 156 199 229.5t231 73.5q281 0 281 -375q0 -203 -76 -380t-201 -273t-276 -96q-113 0 -186 59t-97 166h-6l-55 -209h-80zM268 346q0 -129 64 -202.5t166 -73.5q124 0 224 83t164 245t64 325q0 152 -49 223.5t-151 71.5 q-91 0 -180 -61.5t-160.5 -169.5t-106.5 -235t-35 -206z" /> -<glyph unicode="c" horiz-adv-x="887" d="M102 397q0 193 73.5 361.5t198.5 257t290 88.5q134 0 241 -43l-28 -90q-107 47 -218 47q-129 0 -232.5 -77t-162.5 -222t-59 -320q0 -158 73.5 -243.5t208.5 -85.5q71 0 131.5 13t131.5 46v-92q-116 -57 -273 -57q-174 0 -274.5 110.5t-100.5 306.5z" /> -<glyph unicode="d" horiz-adv-x="1133" d="M102 354q0 193 71.5 370t197.5 278.5t284 101.5q230 0 279 -219h4q12 66 143 671h99l-330 -1556h-82l45 274h-6q-173 -294 -424 -294q-281 0 -281 374zM205 365q0 -295 201 -295q89 0 178.5 62.5t160 168t106.5 231t36 209.5q0 126 -61.5 201.5t-168.5 75.5 q-124 0 -224 -83t-164 -242.5t-64 -327.5z" /> -<glyph unicode="e" horiz-adv-x="928" d="M102 395q0 181 71 347t195.5 264t274.5 98q114 0 182 -61t68 -166q0 -181 -163.5 -276t-485.5 -95h-33q-6 -44 -6 -98q0 -165 74 -251.5t213 -86.5q132 0 276 73v-94q-140 -69 -299 -69q-173 0 -270 109.5t-97 305.5zM225 594h49q517 0 517 270q0 67 -43.5 110.5 t-116.5 43.5q-131 0 -243.5 -115.5t-162.5 -308.5z" /> -<glyph unicode="f" horiz-adv-x="578" d="M-233 -383q53 -16 100 -16q88 0 134 53t75 186l246 1166h-205l14 67l205 14l35 160q35 168 116.5 244t227.5 76q73 0 166 -31l-25 -80q-87 27 -147 27q-96 0 -153.5 -53.5t-84.5 -178.5l-35 -164h248l-16 -81h-248l-252 -1190q-33 -161 -104 -234.5t-195 -73.5 q-48 0 -102 19v90z" /> -<glyph unicode="g" horiz-adv-x="1040" d="M-88 -217q0 236 309 334q-78 42 -78 123q0 123 191 202q-71 36 -110.5 105.5t-39.5 157.5q0 111 53.5 204t148 146t206.5 53q69 0 147 -21h361l-17 -79l-243 -11q26 -28 43.5 -84t17.5 -114q0 -109 -54.5 -206.5t-148 -145.5t-213.5 -48q-63 0 -77 9q-80 -33 -124 -73 t-44 -81t31.5 -64.5t113.5 -31.5l121 -11q346 -31 346 -264q0 -112 -65 -197.5t-187 -131.5t-291 -46q-186 0 -291.5 72t-105.5 203zM14 -207q0 -101 81 -150t224 -49q203 0 317 74.5t114 204.5q0 85 -62.5 130.5t-218.5 57.5l-160 15q-157 -45 -226 -114.5t-69 -168.5z M285 711q0 -112 58.5 -170t164.5 -58q88 0 154 37t102.5 114t36.5 169q0 104 -56 161.5t-157 57.5q-93 0 -161 -43t-105 -116t-37 -152z" /> -<glyph unicode="h" horiz-adv-x="1143" d="M76 0l332 1556h96l-86 -411q-44 -200 -66 -279h6q78 113 186.5 175.5t229.5 62.5q124 0 192 -65t68 -183q0 -70 -24 -182l-148 -674h-98l149 692q21 92 21 156q0 80 -43.5 125t-134.5 45q-112 0 -210.5 -67t-166 -188t-103.5 -286l-102 -477h-98z" /> -<glyph unicode="i" horiz-adv-x="475" d="M76 0l231 1087h96l-229 -1087h-98zM350 1366q0 55 22 88t60 33q57 0 57 -72q0 -57 -22 -90t-57 -33q-29 0 -44.5 19.5t-15.5 54.5z" /> -<glyph unicode="j" horiz-adv-x="475" d="M-279 -381q47 -22 113 -22q82 0 128.5 51.5t72.5 177.5l266 1261h96l-268 -1271q-35 -165 -106.5 -236.5t-188.5 -71.5q-62 0 -113 19v92zM350 1366q0 55 22 88t60 33q57 0 57 -72q0 -57 -22 -90t-57 -33q-29 0 -44.5 19.5t-15.5 54.5z" /> -<glyph unicode="k" horiz-adv-x="944" d="M76 0l330 1556h96l-166 -780l-70 -299h4l609 610h125l-474 -469l297 -618h-106l-264 559l-205 -188l-80 -371h-96z" /> -<glyph unicode="l" horiz-adv-x="475" d="M76 0l334 1556h94l-334 -1556h-94z" /> -<glyph unicode="m" horiz-adv-x="1751" d="M72 0l231 1087h80l-33 -210h6q80 113 181.5 170t212.5 57q106 0 163 -67t60 -195h6q77 129 181 195.5t222 66.5q117 0 182.5 -61.5t65.5 -176.5q0 -29 -2.5 -56.5t-19.5 -119.5l-152 -690h-100l149 680q25 120 25 176q0 77 -43 119.5t-119 42.5q-157 0 -277.5 -137.5 t-168.5 -362.5l-109 -518h-102l147 674q25 125 25 162q0 182 -154 182q-106 0 -200 -67.5t-159 -188.5t-100 -287l-100 -475h-98z" /> -<glyph unicode="n" horiz-adv-x="1143" d="M76 0l231 1087h82l-37 -221h6q164 238 416 238q130 0 195 -64t65 -184q0 -70 -24 -182l-148 -674h-98l149 692q21 92 21 156q0 80 -43.5 125t-134.5 45q-112 0 -210.5 -67t-166 -187.5t-103.5 -286.5l-102 -477h-98z" /> -<glyph unicode="o" horiz-adv-x="1124" d="M98 403q0 191 73 358t197 257t281 90q180 0 278.5 -108.5t98.5 -299.5q0 -197 -71.5 -368.5t-195.5 -261.5t-286 -90q-184 0 -279.5 109.5t-95.5 313.5zM201 408q0 -342 282 -342q127 0 225.5 77.5t157 228t58.5 330.5q0 154 -73 237t-210 83q-124 0 -223 -78.5 t-158 -225t-59 -310.5z" /> -<glyph unicode="p" horiz-adv-x="1149" d="M-33 -492l336 1579h82l-45 -274h6q91 153 195.5 224t228.5 71q135 0 208 -92.5t73 -282.5q0 -195 -72 -371t-197.5 -277t-283.5 -101q-230 0 -279 219h-4q-13 -72 -149 -695h-99zM266 346q0 -125 61.5 -200.5t168.5 -75.5q124 0 225 84t164 243.5t63 325.5 q0 295 -200 295q-87 0 -174 -58.5t-161.5 -167.5t-110.5 -237.5t-36 -208.5z" /> -<glyph unicode="q" horiz-adv-x="1157" d="M98 354q0 201 75.5 379t200.5 274.5t277 96.5q109 0 183.5 -58t99.5 -167h6l55 208h80l-327 -1556h-95l98 470l64 282h-6q-93 -156 -199 -229.5t-231 -73.5q-281 0 -281 374zM201 365q0 -143 45.5 -219t154.5 -76q92 0 182 62.5t160.5 171.5t105 236.5t34.5 200.5 q0 130 -63.5 203.5t-166.5 73.5q-124 0 -224 -83t-164 -245t-64 -325z" /> -<glyph unicode="r" horiz-adv-x="752" d="M72 0l231 1087h80l-29 -204h6q73 94 123 135.5t106.5 64.5t123.5 23q69 0 123 -14l-21 -93q-47 15 -113 15q-94 0 -179 -64t-153 -192t-100 -277l-100 -481h-98z" /> -<glyph unicode="s" horiz-adv-x="827" d="M25 55v107q74 -46 153 -71t148 -25q138 0 211 57.5t73 163.5q0 42 -15.5 74t-50 61.5t-132.5 85.5q-148 80 -200 145.5t-52 159.5q0 128 98.5 209.5t259.5 81.5q75 0 158.5 -17.5t140.5 -46.5l-35 -88q-136 64 -264 64q-116 0 -186 -53t-70 -138q0 -55 17 -88t60.5 -68.5 t119.5 -76.5q114 -63 161.5 -103.5t70 -86.5t22.5 -107q0 -144 -103 -229.5t-280 -85.5q-173 0 -305 75z" /> -<glyph unicode="t" horiz-adv-x="616" d="M113 1006l14 67l184 17l97 253h55l-55 -256h286l-18 -81h-283l-135 -635q-22 -99 -22 -164q0 -139 126 -139q68 0 152 26v-86q-101 -28 -170 -28q-99 0 -153 54.5t-54 158.5q0 73 29 206l129 607h-182z" /> -<glyph unicode="u" horiz-adv-x="1143" d="M109 227q0 60 22 170l150 690h100l-152 -698q-22 -106 -22 -158q0 -74 47.5 -117.5t138.5 -43.5q110 0 207.5 65.5t164 187t99.5 279.5l105 485h98l-231 -1087h-80l28 205h-6q-167 -221 -403 -221q-131 0 -198.5 62t-67.5 181z" /> -<glyph unicode="v" horiz-adv-x="895" d="M104 1087h101l108 -735q26 -165 33 -254h6q51 115 129 256l406 733h102l-600 -1087h-113z" /> -<glyph unicode="w" horiz-adv-x="1393" d="M121 1087h92l13 -821l-3 -157h6q61 134 150 297l373 681h77l64 -681q14 -147 14 -297h6l24 61l101 236l320 681h96l-508 -1087h-108l-60 686q-14 224 -14 266h-6q-34 -92 -144 -290l-356 -662h-117z" /> -<glyph unicode="x" horiz-adv-x="922" d="M-72 0l471 559l-245 528h100l207 -462l373 462h120l-448 -534l258 -553h-98l-224 483l-393 -483h-121z" /> -<glyph unicode="y" horiz-adv-x="920" d="M-217 -379q71 -27 137 -27q80 0 147 49.5t130 164.5t100 184l-174 1095h100l82 -548q51 -351 55 -449h11q43 105 186 367l348 630h103l-713 -1290q-72 -127 -122.5 -178t-114 -81t-146.5 -30q-68 0 -129 21v92z" /> -<glyph unicode="z" horiz-adv-x="887" d="M-29 0l15 72l776 932h-543l17 83h659l-18 -83l-762 -920h602l-17 -84h-729z" /> -<glyph unicode="{" horiz-adv-x="709" d="M59 528l21 78q126 0 191 49t89 158l89 393q30 135 106 195.5t215 60.5h29l-17 -86q-86 -2 -129 -20.5t-69.5 -61.5t-44.5 -120l-74 -338q-30 -134 -91.5 -194.5t-164.5 -78.5v-4q68 -18 105.5 -68.5t37.5 -121.5q0 -52 -24 -164l-47 -225q-13 -58 -13 -101 q0 -61 37.5 -89t138.5 -28v-86h-20q-256 0 -256 199q0 45 16 115l56 252q18 90 18 127q0 159 -199 159z" /> -<glyph unicode="|" d="M584 -510v2071h100v-2071h-100z" /> -<glyph unicode="}" horiz-adv-x="709" d="M-41 -238q96 2 138 21t68.5 61t43.5 121l74 338q27 126 87.5 189.5t168.5 82.5v5q-75 20 -109.5 72.5t-34.5 117.5q0 55 18 131l54 258q12 61 12 101q0 44 -18 69t-54 36t-116 11l20 86h21q131 0 189.5 -51t58.5 -147q0 -41 -17 -115l-55 -252q-19 -95 -19 -127 q0 -77 49.5 -118.5t149.5 -41.5l-20 -78q-125 0 -191 -48.5t-90 -157.5l-88 -394q-32 -139 -108.5 -197.5t-213.5 -58.5h-18v86z" /> -<glyph unicode="~" d="M127 625v94q108 110 233 110q61 0 115 -13.5t156 -57.5q126 -58 219 -58q54 0 107.5 29t117.5 96v-96q-111 -113 -233 -113q-117 0 -271 72q-62 29 -112.5 43t-108.5 14q-49 0 -108 -30.5t-115 -89.5z" /> -<glyph unicode="¡" horiz-adv-x="502" d="M4 -375l260 1086h62l-203 -1086h-119zM272 981q0 55 25 89t68 34q67 0 67 -74q0 -56 -25 -88.5t-69 -32.5q-66 0 -66 72z" /> -<glyph unicode="¢" d="M250 600q0 184 63.5 341t178 253t256.5 111l36 178h90l-38 -176q116 -4 217 -43l-29 -90q-107 47 -217 47q-130 0 -233 -76t-162.5 -221t-59.5 -322q0 -164 74.5 -247t208.5 -83q127 0 264 60v-92q-118 -58 -281 -58l-40 -202h-93l45 215q-132 25 -206 132.5t-74 272.5z " /> -<glyph unicode="£" d="M-4 0l16 84q93 11 165.5 95.5t107.5 236.5l57 260h-199l17 82h198l76 350q41 187 155 279t290 92q170 0 313 -78l-39 -84l-54 26q-108 50 -231 50q-134 0 -220.5 -74.5t-117.5 -220.5l-73 -340h409l-18 -82h-408l-57 -268q-50 -225 -188 -314h759l-20 -94h-938z" /> -<glyph unicode="¤" d="M207 1077l63 64l127 -129q105 78 230 78q118 0 223 -78l131 129l61 -62l-129 -129q78 -106 78 -227q0 -135 -78 -227l129 -127l-61 -62l-131 127q-104 -76 -223 -76q-126 0 -228 80l-129 -129l-61 62l127 127q-74 98 -74 225q0 118 74 225zM350 723q0 -116 80 -196.5 t197 -80.5t198.5 81t81.5 196q0 75 -36.5 140t-102.5 104t-141 39q-114 0 -195.5 -82t-81.5 -201z" /> -<glyph unicode="¥" d="M166 289l18 84h299l41 190h-301l17 76h258l-215 823h100l201 -817l544 817h117l-559 -823h266l-16 -76h-315l-39 -190h317l-18 -84h-316l-59 -289h-105l64 289h-299z" /> -<glyph unicode="¦" d="M578 246h100v-756h-100v756zM578 805v756h100v-756h-100z" /> -<glyph unicode="§" horiz-adv-x="995" d="M102 51v99q47 -27 126 -46.5t153 -19.5q149 0 228 52.5t79 150.5q0 62 -42.5 106t-166.5 96q-155 65 -211.5 130t-56.5 159q0 101 69.5 182t198.5 130q-64 31 -103.5 85.5t-39.5 120.5q0 74 46 134.5t132.5 94.5t202.5 34q163 0 289 -58l-31 -80q-138 54 -264 54 q-124 0 -202.5 -46.5t-78.5 -123.5q0 -59 46 -104.5t183 -106.5q112 -52 158.5 -89.5t71 -85t24.5 -110.5q0 -197 -249 -317q122 -64 122 -197q0 -86 -48 -153.5t-139.5 -105.5t-221.5 -38q-157 0 -275 53zM303 786q0 -57 24.5 -96.5t81 -73t187.5 -81.5q103 49 162 113.5 t59 156.5q0 72 -57.5 126t-200.5 107q-119 -30 -187.5 -97.5t-68.5 -154.5z" /> -<glyph unicode="¨" horiz-adv-x="1135" d="M492 1366q0 49 20.5 78t56.5 29q54 0 54 -64q0 -48 -21 -77t-55 -29q-55 0 -55 63zM836 1366q0 49 20.5 78t56.5 29q54 0 54 -64q0 -48 -21 -77t-55 -29q-55 0 -55 63z" /> -<glyph unicode="©" horiz-adv-x="1704" d="M147 731q0 200 100 375t275 276t377 101q200 0 375 -100t276 -275t101 -377q0 -197 -97 -370t-272 -277t-383 -104q-207 0 -382 103.5t-272.5 276.5t-97.5 371zM240 731q0 -178 88.5 -329.5t240.5 -240.5t330 -89q174 0 325 85.5t243 239t92 334.5q0 178 -89 330 t-240.5 241t-330.5 89q-182 0 -335 -92t-238.5 -243t-85.5 -325zM537 725q0 207 110 332t297 125q119 0 227 -52l-36 -83q-99 45 -191 45q-142 0 -222.5 -94.5t-80.5 -264.5q0 -186 74.5 -275t220.5 -89q85 0 199 43v-88q-104 -45 -209 -45q-187 0 -288 116t-101 330z" /> -<glyph unicode="ª" horiz-adv-x="643" d="M170 1032q0 189 90.5 321t226.5 132q55 0 97.5 -29t66.5 -86h6l35 103h66l-137 -650h-72l22 125h-4q-96 -137 -223 -137q-80 0 -127 56.5t-47 164.5zM258 1028q0 -143 111 -143q66 0 133.5 75.5t97.5 184.5q16 51 16 123q0 58 -36 100.5t-93 42.5q-94 0 -161.5 -111.5 t-67.5 -271.5z" /> -<glyph unicode="«" horiz-adv-x="860" d="M61 541l2 26l363 365l57 -49l-317 -336l213 -385l-64 -39zM422 541l2 26l362 365l58 -49l-314 -336l209 -385l-63 -39z" /> -<glyph unicode="¬" d="M125 672v100h903v-500h-100v400h-803z" /> -<glyph unicode="­" horiz-adv-x="629" d="M77 502l18 90h457l-16 -90h-459z" /> -<glyph unicode="®" horiz-adv-x="1704" d="M150 731q0 207 103.5 382t276.5 272.5t371 97.5q200 0 375 -100t276 -275t101 -377q0 -197 -97 -370t-272 -277t-383 -104q-204 0 -376.5 100.5t-273.5 273t-101 377.5zM242 731q0 -178 88.5 -329.5t240.5 -240.5t330 -89q174 0 325 85.5t243 239t92 334.5q0 178 -89 330 t-240.5 241t-330.5 89q-182 0 -335 -92t-238.5 -243t-85.5 -325zM657 291v880h211q143 0 222 -62t79 -191q0 -80 -39.5 -141t-109.5 -93l237 -393h-120l-211 360h-168v-360h-101zM758 731h112q93 0 144 46.5t51 135.5q0 172 -197 172h-110v-354z" /> -<glyph unicode="¯" horiz-adv-x="655" d="M348 1556l53 97h654l-54 -97h-653z" /> -<glyph unicode="°" horiz-adv-x="877" d="M242 1190q0 120 85 206.5t208 86.5q122 0 207 -86.5t85 -206.5q0 -122 -85.5 -207.5t-206.5 -85.5q-122 0 -207.5 85.5t-85.5 207.5zM315 1190q0 -89 64.5 -153t155.5 -64q92 0 155.5 64t63.5 153q0 90 -64 155.5t-155 65.5q-90 0 -155 -65.5t-65 -155.5z" /> -<glyph unicode="±" d="M127 0v100h903v-100h-903zM127 629v98h401v406h101v-406h401v-98h-401v-400h-101v400h-401z" /> -<glyph unicode="²" horiz-adv-x="643" d="M82 586l16 80l297 258q137 118 182.5 190.5t45.5 153.5q0 59 -38.5 97t-105.5 38q-95 0 -194 -76l-41 62q108 90 239 90q73 0 125 -27t78.5 -72t26.5 -100q0 -106 -59 -198.5t-183 -194.5l-266 -223h416l-17 -78h-522z" /> -<glyph unicode="³" horiz-adv-x="643" d="M109 625v90q46 -28 108 -48t125 -20q99 0 159 52.5t60 142.5q0 162 -196 162h-84l16 79h86q102 0 168.5 49.5t66.5 129.5q0 68 -37.5 102.5t-105.5 34.5q-100 0 -199 -68l-40 64q109 86 251 86q100 0 159 -56.5t59 -148.5q0 -85 -48.5 -148t-154.5 -88v-4 q66 -16 105.5 -68t39.5 -124q0 -77 -39 -141t-109 -99t-161 -35q-59 0 -123.5 15.5t-105.5 40.5z" /> -<glyph unicode="´" horiz-adv-x="1135" d="M580 1241v21q66 51 150.5 142t129.5 165h137v-23q-51 -66 -157.5 -158.5t-192.5 -146.5h-67z" /> -<glyph unicode="µ" horiz-adv-x="1171" d="M-29 -492l338 1579h101l-152 -698q-20 -96 -20 -147q0 -82 48.5 -127t135.5 -45q110 0 207 64.5t162.5 182.5t101.5 285l104 485h99l-234 -1087h-78l29 205h-6q-164 -221 -404 -221q-85 0 -139 32.5t-76 89.5h-6q-18 -132 -51 -284l-63 -314h-97z" /> -<glyph unicode="¶" horiz-adv-x="1341" d="M215 1042q0 260 109 387t342 127h542v-1816h-100v1722h-227v-1722h-101v819q-64 -18 -145 -18q-216 0 -318 125t-102 376z" /> -<glyph unicode="·" horiz-adv-x="485" d="M207 698q0 56 25 88.5t69 32.5q66 0 66 -72q0 -53 -25 -87.5t-67 -34.5q-68 0 -68 73z" /> -<glyph unicode="¸" horiz-adv-x="420" d="M-174 -406q30 -6 72 -6q198 0 198 115q0 97 -151 107l110 190h80l-78 -137q140 -30 140 -152q0 -94 -75.5 -148.5t-217.5 -54.5q-46 0 -78 7v79z" /> -<glyph unicode="¹" horiz-adv-x="643" d="M254 1288l258 174h80l-186 -876h-84l118 569q5 21 11.5 50.5t14 60t15.5 59t15 49.5q-34 -31 -60 -51.5t-143 -93.5z" /> -<glyph unicode="º" horiz-adv-x="655" d="M190 1059q0 112 41.5 209.5t116 154t170.5 56.5q105 0 165 -64t60 -180q0 -115 -40 -214t-114 -156.5t-175 -57.5q-114 0 -169 67.5t-55 184.5zM270 1067q0 -186 156 -186q73 0 125.5 46.5t81.5 127.5t29 176q0 83 -39 128.5t-115 45.5q-70 0 -124 -46.5t-84 -124.5 t-30 -167z" /> -<glyph unicode="»" horiz-adv-x="860" d="M33 172l313 336l-209 385l64 39l254 -418l-2 -27l-363 -364zM393 172l314 336l-209 385l63 39l254 -418l-2 -27l-362 -364z" /> -<glyph unicode="¼" horiz-adv-x="1481" d="M715 230l21 76l506 577h86l-125 -581h133l-17 -72h-131l-49 -229h-82l49 229h-391zM830 302h291q61 294 79 365.5t29 105.5q-10 -16 -61 -79t-338 -392zM129 0l1086 1462h108l-1087 -1462h-107zM251 1288l258 174h80l-186 -876h-84l118 569q5 21 11.5 50.5t14 60t15.5 59 t15 49.5q-34 -31 -60 -51.5t-143 -93.5z" /> -<glyph unicode="½" horiz-adv-x="1458" d="M756 1l16 80l297 258q137 118 182.5 190.5t45.5 153.5q0 59 -38.5 97t-105.5 38q-95 0 -194 -76l-41 62q108 90 239 90q73 0 125 -27t78.5 -72t26.5 -100q0 -106 -59 -198.5t-183 -194.5l-266 -223h416l-17 -78h-522zM173 1288l258 174h80l-186 -876h-84l118 569 q5 21 11.5 50.5t14 60t15.5 59t15 49.5q-34 -31 -60 -51.5t-143 -93.5zM53 0l1086 1462h108l-1087 -1462h-107z" /> -<glyph unicode="¾" horiz-adv-x="1458" d="M776 230l21 76l506 577h86l-125 -581h133l-17 -72h-131l-49 -229h-82l49 229h-391zM891 302h291q61 294 79 365.5t29 105.5q-10 -16 -61 -79t-338 -392zM71 625v90q46 -28 108 -48t125 -20q99 0 159 52.5t60 142.5q0 162 -196 162h-84l16 79h86q102 0 168.5 49.5 t66.5 129.5q0 68 -37.5 102.5t-105.5 34.5q-100 0 -199 -68l-40 64q109 86 251 86q100 0 159 -56.5t59 -148.5q0 -85 -48.5 -148t-154.5 -88v-4q66 -16 105.5 -68t39.5 -124q0 -77 -39 -141t-109 -99t-161 -35q-59 0 -123.5 15.5t-105.5 40.5zM213 0l1086 1462h108 l-1087 -1462h-107z" /> -<glyph unicode="¿" horiz-adv-x="799" d="M0 -90q0 133 70 240.5t227 220.5q85 61 133.5 109t73 95t45.5 142h92l-6 -29q-28 -127 -79 -200t-161 -154q-118 -84 -175 -145.5t-86.5 -127.5t-29.5 -141q0 -106 65.5 -168.5t184.5 -62.5q141 0 308 100l38 -86q-85 -49 -170.5 -77.5t-187.5 -28.5q-159 0 -250.5 84.5 t-91.5 228.5zM553 971q0 56 25 89.5t67 33.5q68 0 68 -74q0 -56 -25.5 -88.5t-69.5 -32.5q-65 0 -65 72z" /> -<glyph unicode="À" horiz-adv-x="1059" d="M-111 0l822 1468h67l201 -1468h-105l-69 520h-512l-287 -520h-117zM344 612h449l-39 291q-31 242 -39 402q-30 -63 -64.5 -130t-306.5 -563zM536 1886v21h115q46 -129 164 -303v-25h-66q-50 52 -114 144.5t-99 162.5z" /> -<glyph unicode="Á" horiz-adv-x="1059" d="M-111 0l822 1468h67l201 -1468h-105l-69 520h-512l-287 -520h-117zM344 612h449l-39 291q-31 242 -39 402q-30 -63 -64.5 -130t-306.5 -563zM668 1579v21q66 51 150.5 142t129.5 165h137v-23q-51 -66 -157.5 -158.5t-192.5 -146.5h-67z" /> -<glyph unicode="Â" horiz-adv-x="1059" d="M-111 0l822 1468h67l201 -1468h-105l-69 520h-512l-287 -520h-117zM344 612h449l-39 291q-31 242 -39 402q-30 -63 -64.5 -130t-306.5 -563zM493 1579v29q68 56 157.5 148.5t127.5 150.5h64q23 -64 72.5 -152.5t92.5 -146.5v-29h-49q-70 60 -161 207q-55 -57 -125 -114.5 t-125 -92.5h-54z" /> -<glyph unicode="Ã" horiz-adv-x="1059" d="M-111 0l822 1468h67l201 -1468h-105l-69 520h-512l-287 -520h-117zM344 612h449l-39 291q-31 242 -39 402q-30 -63 -64.5 -130t-306.5 -563zM426 1581q19 108 71 166.5t134 58.5q41 0 73.5 -14t117.5 -72q52 -36 94 -36q43 0 71.5 30.5t46.5 100.5h76 q-26 -118 -74.5 -173t-124.5 -55q-40 0 -77.5 19t-75.5 45q-34 23 -64.5 41t-68.5 18q-45 0 -74 -28.5t-51 -100.5h-74z" /> -<glyph unicode="Ä" horiz-adv-x="1059" d="M-111 0l822 1468h67l201 -1468h-105l-69 520h-512l-287 -520h-117zM344 612h449l-39 291q-31 242 -39 402q-30 -63 -64.5 -130t-306.5 -563zM535 1704q0 49 20.5 78t56.5 29q54 0 54 -64q0 -48 -21 -77t-55 -29q-55 0 -55 63zM879 1704q0 49 20.5 78t56.5 29q54 0 54 -64 q0 -48 -21 -77t-55 -29q-55 0 -55 63z" /> -<glyph unicode="Å" horiz-adv-x="1059" d="M-111 0l822 1468h67l201 -1468h-105l-69 520h-512l-287 -520h-117zM344 612h449l-39 291q-31 242 -39 402q-30 -63 -64.5 -130t-306.5 -563zM539 1592q0 88 59.5 144t149.5 56q88 0 142.5 -50t54.5 -142t-57.5 -148.5t-145.5 -56.5q-93 0 -148 52t-55 145zM619 1592 q0 -57 33 -90t90 -33q56 0 90.5 36t34.5 93t-33.5 90t-87.5 33q-60 0 -93.5 -36t-33.5 -93z" /> -<glyph unicode="Æ" horiz-adv-x="1640" d="M-117 0l946 1462h883l-20 -94h-625l-117 -553h590l-20 -94h-588l-135 -627h626l-20 -94h-727l110 522h-444l-328 -522h-131zM408 627h401l156 741h-88z" /> -<glyph unicode="Ç" horiz-adv-x="1169" d="M170 535q0 266 104.5 488t284.5 341t402 119q177 0 307 -68l-45 -90q-55 30 -124.5 47t-137.5 17q-197 0 -351.5 -104.5t-245 -304.5t-90.5 -441q0 -225 110.5 -346t317.5 -121q140 0 304 51v-94q-156 -49 -316 -49q-252 0 -386 145t-134 410zM381 -406q30 -6 72 -6 q198 0 198 115q0 97 -151 107l110 190h80l-78 -137q140 -30 140 -152q0 -94 -75.5 -148.5t-217.5 -54.5q-46 0 -78 7v79z" /> -<glyph unicode="È" horiz-adv-x="1067" d="M102 0l310 1462h727l-21 -94h-624l-117 -553h590l-21 -94h-588l-135 -627h627l-21 -94h-727zM612 1886v21h115q46 -129 164 -303v-25h-66q-50 52 -114 144.5t-99 162.5z" /> -<glyph unicode="É" horiz-adv-x="1067" d="M102 0l310 1462h727l-21 -94h-624l-117 -553h590l-21 -94h-588l-135 -627h627l-21 -94h-727zM654 1579v21q66 51 150.5 142t129.5 165h137v-23q-51 -66 -157.5 -158.5t-192.5 -146.5h-67z" /> -<glyph unicode="Ê" horiz-adv-x="1067" d="M102 0l310 1462h727l-21 -94h-624l-117 -553h590l-21 -94h-588l-135 -627h627l-21 -94h-727zM522 1579v29q68 56 157.5 148.5t127.5 150.5h64q23 -64 72.5 -152.5t92.5 -146.5v-29h-49q-70 60 -161 207q-55 -57 -125 -114.5t-125 -92.5h-54z" /> -<glyph unicode="Ë" horiz-adv-x="1067" d="M102 0l310 1462h727l-21 -94h-624l-117 -553h590l-21 -94h-588l-135 -627h627l-21 -94h-727zM558 1704q0 49 20.5 78t56.5 29q54 0 54 -64q0 -48 -21 -77t-55 -29q-55 0 -55 63zM902 1704q0 49 20.5 78t56.5 29q54 0 54 -64q0 -48 -21 -77t-55 -29q-55 0 -55 63z" /> -<glyph unicode="Ì" horiz-adv-x="504" d="M102 0l310 1462h98l-309 -1462h-99zM246 1886v21h115q46 -129 164 -303v-25h-66q-50 52 -114 144.5t-99 162.5z" /> -<glyph unicode="Í" horiz-adv-x="504" d="M102 0l310 1462h98l-309 -1462h-99zM419 1579v21q66 51 150.5 142t129.5 165h137v-23q-51 -66 -157.5 -158.5t-192.5 -146.5h-67z" /> -<glyph unicode="Î" horiz-adv-x="504" d="M102 0l310 1462h98l-309 -1462h-99zM224 1579v29q68 56 157.5 148.5t127.5 150.5h64q23 -64 72.5 -152.5t92.5 -146.5v-29h-49q-70 60 -161 207q-55 -57 -125 -114.5t-125 -92.5h-54z" /> -<glyph unicode="Ï" horiz-adv-x="504" d="M102 0l310 1462h98l-309 -1462h-99zM260 1704q0 49 20.5 78t56.5 29q54 0 54 -64q0 -48 -21 -77t-55 -29q-55 0 -55 63zM604 1704q0 49 20.5 78t56.5 29q54 0 54 -64q0 -48 -21 -77t-55 -29q-55 0 -55 63z" /> -<glyph unicode="Ð" horiz-adv-x="1352" d="M90 676l21 96h155l146 690h305q282 0 426.5 -147.5t144.5 -435.5q0 -253 -109.5 -461.5t-300.5 -313t-446 -104.5h-330l144 676h-156zM221 90h209q226 0 394.5 94.5t261 275.5t92.5 412q0 498 -476 498h-206l-129 -598h378l-20 -96h-379z" /> -<glyph unicode="Ñ" horiz-adv-x="1372" d="M102 0l310 1462h80l522 -1294h8q23 176 74 416l188 878h94l-309 -1462h-86l-516 1284h-8q-23 -149 -48 -273t-214 -1011h-95zM577 1581q19 108 71 166.5t134 58.5q41 0 73.5 -14t117.5 -72q52 -36 94 -36q43 0 71.5 30.5t46.5 100.5h76q-26 -118 -74.5 -173t-124.5 -55 q-40 0 -77.5 19t-75.5 45q-34 23 -64.5 41t-68.5 18q-45 0 -74 -28.5t-51 -100.5h-74z" /> -<glyph unicode="Ò" horiz-adv-x="1464" d="M172 559q0 262 93 477.5t255 331t373 115.5q247 0 378.5 -148.5t131.5 -423.5q0 -255 -94 -481.5t-252 -338t-365 -111.5q-250 0 -385 149t-135 430zM276 573q0 -245 109.5 -373t319.5 -128q169 0 300 98.5t210 300t79 430.5q0 240 -104.5 364t-310.5 124 q-174 0 -308.5 -101t-214.5 -298t-80 -417zM710 1886v21h115q46 -129 164 -303v-25h-66q-50 52 -114 144.5t-99 162.5z" /> -<glyph unicode="Ó" horiz-adv-x="1464" d="M172 559q0 262 93 477.5t255 331t373 115.5q247 0 378.5 -148.5t131.5 -423.5q0 -255 -94 -481.5t-252 -338t-365 -111.5q-250 0 -385 149t-135 430zM276 573q0 -245 109.5 -373t319.5 -128q169 0 300 98.5t210 300t79 430.5q0 240 -104.5 364t-310.5 124 q-174 0 -308.5 -101t-214.5 -298t-80 -417zM844 1579v21q66 51 150.5 142t129.5 165h137v-23q-51 -66 -157.5 -158.5t-192.5 -146.5h-67z" /> -<glyph unicode="Ô" horiz-adv-x="1464" d="M172 559q0 262 93 477.5t255 331t373 115.5q247 0 378.5 -148.5t131.5 -423.5q0 -255 -94 -481.5t-252 -338t-365 -111.5q-250 0 -385 149t-135 430zM276 573q0 -245 109.5 -373t319.5 -128q169 0 300 98.5t210 300t79 430.5q0 240 -104.5 364t-310.5 124 q-174 0 -308.5 -101t-214.5 -298t-80 -417zM657 1579v29q68 56 157.5 148.5t127.5 150.5h64q23 -64 72.5 -152.5t92.5 -146.5v-29h-49q-70 60 -161 207q-55 -57 -125 -114.5t-125 -92.5h-54z" /> -<glyph unicode="Õ" horiz-adv-x="1464" d="M172 559q0 262 93 477.5t255 331t373 115.5q247 0 378.5 -148.5t131.5 -423.5q0 -255 -94 -481.5t-252 -338t-365 -111.5q-250 0 -385 149t-135 430zM276 573q0 -245 109.5 -373t319.5 -128q169 0 300 98.5t210 300t79 430.5q0 240 -104.5 364t-310.5 124 q-174 0 -308.5 -101t-214.5 -298t-80 -417zM592 1581q19 108 71 166.5t134 58.5q41 0 73.5 -14t117.5 -72q52 -36 94 -36q43 0 71.5 30.5t46.5 100.5h76q-26 -118 -74.5 -173t-124.5 -55q-40 0 -77.5 19t-75.5 45q-34 23 -64.5 41t-68.5 18q-45 0 -74 -28.5t-51 -100.5h-74z " /> -<glyph unicode="Ö" horiz-adv-x="1464" d="M172 559q0 262 93 477.5t255 331t373 115.5q247 0 378.5 -148.5t131.5 -423.5q0 -255 -94 -481.5t-252 -338t-365 -111.5q-250 0 -385 149t-135 430zM276 573q0 -245 109.5 -373t319.5 -128q169 0 300 98.5t210 300t79 430.5q0 240 -104.5 364t-310.5 124 q-174 0 -308.5 -101t-214.5 -298t-80 -417zM687 1704q0 49 20.5 78t56.5 29q54 0 54 -64q0 -48 -21 -77t-55 -29q-55 0 -55 63zM1031 1704q0 49 20.5 78t56.5 29q54 0 54 -64q0 -48 -21 -77t-55 -29q-55 0 -55 63z" /> -<glyph unicode="×" d="M221 1055l70 69l330 -329l333 329l68 -67l-332 -334l332 -332l-68 -67l-333 329l-330 -327l-68 67l328 330z" /> -<glyph unicode="Ø" horiz-adv-x="1464" d="M139 -14l146 172q-113 149 -113 401q0 263 94 479.5t256.5 330.5t370.5 114q219 0 352 -121l133 168l70 -53l-145 -183q45 -51 72.5 -161t27.5 -222q0 -187 -52 -365.5t-144.5 -304.5t-223 -193.5t-291.5 -67.5q-215 0 -348 112l-139 -170zM276 573q0 -105 21.5 -191 t56.5 -138l826 1032q-107 113 -301 113q-134 0 -244 -59.5t-188.5 -170t-124.5 -267.5t-46 -319zM412 172q107 -100 293 -100q170 0 301 100t209.5 296.5t78.5 432.5q0 85 -17.5 172t-43.5 129z" /> -<glyph unicode="Ù" horiz-adv-x="1370" d="M176 381q0 83 27 201l186 880h103l-193 -899q-20 -89 -20 -184q0 -309 342 -309q195 0 307.5 96.5t158.5 318.5l207 977h101l-207 -977q-58 -270 -197 -387.5t-375 -117.5q-440 0 -440 401zM667 1886v21h115q46 -129 164 -303v-25h-66q-50 52 -114 144.5t-99 162.5z" /> -<glyph unicode="Ú" horiz-adv-x="1370" d="M176 381q0 83 27 201l186 880h103l-193 -899q-20 -89 -20 -184q0 -309 342 -309q195 0 307.5 96.5t158.5 318.5l207 977h101l-207 -977q-58 -270 -197 -387.5t-375 -117.5q-440 0 -440 401zM838 1579v21q66 51 150.5 142t129.5 165h137v-23q-51 -66 -157.5 -158.5 t-192.5 -146.5h-67z" /> -<glyph unicode="Û" horiz-adv-x="1370" d="M176 381q0 83 27 201l186 880h103l-193 -899q-20 -89 -20 -184q0 -309 342 -309q195 0 307.5 96.5t158.5 318.5l207 977h101l-207 -977q-58 -270 -197 -387.5t-375 -117.5q-440 0 -440 401zM634 1579v29q68 56 157.5 148.5t127.5 150.5h64q23 -64 72.5 -152.5 t92.5 -146.5v-29h-49q-70 60 -161 207q-55 -57 -125 -114.5t-125 -92.5h-54z" /> -<glyph unicode="Ü" horiz-adv-x="1370" d="M176 381q0 83 27 201l186 880h103l-193 -899q-20 -89 -20 -184q0 -309 342 -309q195 0 307.5 96.5t158.5 318.5l207 977h101l-207 -977q-58 -270 -197 -387.5t-375 -117.5q-440 0 -440 401zM678 1704q0 49 20.5 78t56.5 29q54 0 54 -64q0 -48 -21 -77t-55 -29 q-55 0 -55 63zM1022 1704q0 49 20.5 78t56.5 29q54 0 54 -64q0 -48 -21 -77t-55 -29q-55 0 -55 63z" /> -<glyph unicode="Ý" horiz-adv-x="965" d="M193 1462h100l201 -817l544 817h117l-631 -932l-108 -530h-105l119 545zM563 1579v21q66 51 150.5 142t129.5 165h137v-23q-51 -66 -157.5 -158.5t-192.5 -146.5h-67z" /> -<glyph unicode="Þ" horiz-adv-x="1145" d="M102 0l310 1462h102l-57 -266h213q200 0 308.5 -92.5t108.5 -267.5q0 -247 -153 -373.5t-457 -126.5h-201l-71 -336h-103zM293 428h190q256 0 376 98.5t120 302.5q0 275 -330 275h-211z" /> -<glyph unicode="ß" horiz-adv-x="1094" d="M-281 -379q53 -24 115 -24q79 0 123 50.5t66 153.5l305 1409q80 357 405 357q137 0 215 -61.5t78 -174.5q0 -75 -44.5 -140.5t-166.5 -148.5q-107 -76 -141.5 -124.5t-34.5 -106.5q0 -51 34 -88.5t93 -75.5q96 -63 138 -133.5t42 -165.5q0 -170 -106.5 -269t-286.5 -99 q-143 0 -234 65v109q45 -36 112.5 -59t129.5 -23q132 0 208.5 71t76.5 195q0 75 -31.5 129t-109.5 108q-82 58 -119 110.5t-37 121.5q0 57 21 103t60.5 88.5t137.5 113.5q101 70 131.5 116t30.5 101q0 70 -55 110t-150 40q-129 0 -205 -76t-108 -229l-291 -1377 q-33 -152 -103.5 -220.5t-179.5 -68.5q-73 0 -119 23v90z" /> -<glyph unicode="à" horiz-adv-x="1133" d="M102 354q0 197 75 376t200.5 276.5t277.5 97.5q232 0 279 -219h6l59 202h80l-229 -1087h-82l45 274h-6q-84 -142 -187 -218t-237 -76q-281 0 -281 374zM205 365q0 -152 50 -223.5t151 -71.5q89 0 177.5 62t159 166t107.5 230t37 213q0 79 -26 141.5t-77 99t-127 36.5 q-124 0 -224 -82t-164 -245.5t-64 -325.5zM530 1548v21h115q46 -129 164 -303v-25h-66q-50 52 -114 144.5t-99 162.5z" /> -<glyph unicode="á" horiz-adv-x="1133" d="M102 354q0 197 75 376t200.5 276.5t277.5 97.5q232 0 279 -219h6l59 202h80l-229 -1087h-82l45 274h-6q-84 -142 -187 -218t-237 -76q-281 0 -281 374zM205 365q0 -152 50 -223.5t151 -71.5q89 0 177.5 62t159 166t107.5 230t37 213q0 79 -26 141.5t-77 99t-127 36.5 q-124 0 -224 -82t-164 -245.5t-64 -325.5zM586 1241v21q66 51 150.5 142t129.5 165h137v-23q-51 -66 -157.5 -158.5t-192.5 -146.5h-67z" /> -<glyph unicode="â" horiz-adv-x="1133" d="M102 354q0 197 75 376t200.5 276.5t277.5 97.5q232 0 279 -219h6l59 202h80l-229 -1087h-82l45 274h-6q-84 -142 -187 -218t-237 -76q-281 0 -281 374zM205 365q0 -152 50 -223.5t151 -71.5q89 0 177.5 62t159 166t107.5 230t37 213q0 79 -26 141.5t-77 99t-127 36.5 q-124 0 -224 -82t-164 -245.5t-64 -325.5zM441 1243v29q68 56 157.5 148.5t127.5 150.5h64q23 -64 72.5 -152.5t92.5 -146.5v-29h-49q-70 60 -161 207q-55 -57 -125 -114.5t-125 -92.5h-54z" /> -<glyph unicode="ã" horiz-adv-x="1133" d="M102 354q0 197 75 376t200.5 276.5t277.5 97.5q232 0 279 -219h6l59 202h80l-229 -1087h-82l45 274h-6q-84 -142 -187 -218t-237 -76q-281 0 -281 374zM205 365q0 -152 50 -223.5t151 -71.5q89 0 177.5 62t159 166t107.5 230t37 213q0 79 -26 141.5t-77 99t-127 36.5 q-124 0 -224 -82t-164 -245.5t-64 -325.5zM373 1243q19 108 71 166.5t134 58.5q41 0 73.5 -14t117.5 -72q52 -36 94 -36q43 0 71.5 30.5t46.5 100.5h76q-26 -118 -74.5 -173t-124.5 -55q-40 0 -77.5 19t-75.5 45q-34 23 -64.5 41t-68.5 18q-45 0 -74 -28.5t-51 -100.5h-74z " /> -<glyph unicode="ä" horiz-adv-x="1133" d="M102 354q0 197 75 376t200.5 276.5t277.5 97.5q232 0 279 -219h6l59 202h80l-229 -1087h-82l45 274h-6q-84 -142 -187 -218t-237 -76q-281 0 -281 374zM205 365q0 -152 50 -223.5t151 -71.5q89 0 177.5 62t159 166t107.5 230t37 213q0 79 -26 141.5t-77 99t-127 36.5 q-124 0 -224 -82t-164 -245.5t-64 -325.5zM491 1366q0 49 20.5 78t56.5 29q54 0 54 -64q0 -48 -21 -77t-55 -29q-55 0 -55 63zM835 1366q0 49 20.5 78t56.5 29q54 0 54 -64q0 -48 -21 -77t-55 -29q-55 0 -55 63z" /> -<glyph unicode="å" horiz-adv-x="1133" d="M102 354q0 197 75 376t200.5 276.5t277.5 97.5q232 0 279 -219h6l59 202h80l-229 -1087h-82l45 274h-6q-84 -142 -187 -218t-237 -76q-281 0 -281 374zM205 365q0 -152 50 -223.5t151 -71.5q89 0 177.5 62t159 166t107.5 230t37 213q0 79 -26 141.5t-77 99t-127 36.5 q-124 0 -224 -82t-164 -245.5t-64 -325.5zM521 1440q0 88 59.5 144t149.5 56q88 0 142.5 -50t54.5 -142t-57.5 -148.5t-145.5 -56.5q-93 0 -148 52t-55 145zM601 1440q0 -57 33 -90t90 -33q56 0 90.5 36t34.5 93t-33.5 90t-87.5 33q-60 0 -93.5 -36t-33.5 -93z" /> -<glyph unicode="æ" horiz-adv-x="1602" d="M102 344q0 206 70.5 384.5t192.5 277t274 98.5q106 0 166 -56.5t74 -156.5h10l59 192h66l-35 -186q139 207 350 207q112 0 175 -61.5t63 -172.5q0 -179 -158.5 -271.5t-470.5 -92.5h-39q-8 -51 -8 -96q0 -161 69.5 -250.5t217.5 -89.5q69 0 133.5 21t130.5 52v-94 q-80 -37 -147 -53t-140 -16q-123 0 -211 60t-117 165l-39 -205h-77l41 254h-9q-94 -142 -189 -208t-208 -66q-120 0 -182 94t-62 270zM205 352q0 -150 42.5 -216t121.5 -66q67 0 138.5 42t134 117.5t106 170.5t63.5 199t20 165q0 118 -49 186t-141 68q-123 0 -223 -86 t-156.5 -240t-56.5 -340zM913 594h48q263 0 383 67t120 203q0 71 -38.5 112.5t-108.5 41.5q-119 0 -232 -115.5t-172 -308.5z" /> -<glyph unicode="ç" horiz-adv-x="887" d="M102 397q0 193 73.5 361.5t198.5 257t290 88.5q134 0 241 -43l-28 -90q-107 47 -218 47q-129 0 -232.5 -77t-162.5 -222t-59 -320q0 -158 73.5 -243.5t208.5 -85.5q71 0 131.5 13t131.5 46v-92q-116 -57 -273 -57q-174 0 -274.5 110.5t-100.5 306.5zM203 -406 q30 -6 72 -6q198 0 198 115q0 97 -151 107l110 190h80l-78 -137q140 -30 140 -152q0 -94 -75.5 -148.5t-217.5 -54.5q-46 0 -78 7v79z" /> -<glyph unicode="è" horiz-adv-x="928" d="M102 395q0 181 71 347t195.5 264t274.5 98q114 0 182 -61t68 -166q0 -181 -163.5 -276t-485.5 -95h-33q-6 -44 -6 -98q0 -165 74 -251.5t213 -86.5q132 0 276 73v-94q-140 -69 -299 -69q-173 0 -270 109.5t-97 305.5zM225 594h49q517 0 517 270q0 67 -43.5 110.5 t-116.5 43.5q-131 0 -243.5 -115.5t-162.5 -308.5zM472 1548v21h115q46 -129 164 -303v-25h-66q-50 52 -114 144.5t-99 162.5z" /> -<glyph unicode="é" horiz-adv-x="928" d="M102 395q0 181 71 347t195.5 264t274.5 98q114 0 182 -61t68 -166q0 -181 -163.5 -276t-485.5 -95h-33q-6 -44 -6 -98q0 -165 74 -251.5t213 -86.5q132 0 276 73v-94q-140 -69 -299 -69q-173 0 -270 109.5t-97 305.5zM225 594h49q517 0 517 270q0 67 -43.5 110.5 t-116.5 43.5q-131 0 -243.5 -115.5t-162.5 -308.5zM532 1241v21q66 51 150.5 142t129.5 165h137v-23q-51 -66 -157.5 -158.5t-192.5 -146.5h-67z" /> -<glyph unicode="ê" horiz-adv-x="928" d="M102 395q0 181 71 347t195.5 264t274.5 98q114 0 182 -61t68 -166q0 -181 -163.5 -276t-485.5 -95h-33q-6 -44 -6 -98q0 -165 74 -251.5t213 -86.5q132 0 276 73v-94q-140 -69 -299 -69q-173 0 -270 109.5t-97 305.5zM225 594h49q517 0 517 270q0 67 -43.5 110.5 t-116.5 43.5q-131 0 -243.5 -115.5t-162.5 -308.5zM390 1241v29q68 56 157.5 148.5t127.5 150.5h64q23 -64 72.5 -152.5t92.5 -146.5v-29h-49q-70 60 -161 207q-55 -57 -125 -114.5t-125 -92.5h-54z" /> -<glyph unicode="ë" horiz-adv-x="928" d="M102 395q0 181 71 347t195.5 264t274.5 98q114 0 182 -61t68 -166q0 -181 -163.5 -276t-485.5 -95h-33q-6 -44 -6 -98q0 -165 74 -251.5t213 -86.5q132 0 276 73v-94q-140 -69 -299 -69q-173 0 -270 109.5t-97 305.5zM225 594h49q517 0 517 270q0 67 -43.5 110.5 t-116.5 43.5q-131 0 -243.5 -115.5t-162.5 -308.5zM436 1366q0 49 20.5 78t56.5 29q54 0 54 -64q0 -48 -21 -77t-55 -29q-55 0 -55 63zM780 1366q0 49 20.5 78t56.5 29q54 0 54 -64q0 -48 -21 -77t-55 -29q-55 0 -55 63z" /> -<glyph unicode="ì" horiz-adv-x="475" d="M76 0l231 1087h96l-229 -1087h-98zM175 1548v21h115q46 -129 164 -303v-25h-66q-50 52 -114 144.5t-99 162.5z" /> -<glyph unicode="í" horiz-adv-x="475" d="M76 0l231 1087h96l-229 -1087h-98zM284 1241v21q66 51 150.5 142t129.5 165h137v-23q-51 -66 -157.5 -158.5t-192.5 -146.5h-67z" /> -<glyph unicode="î" horiz-adv-x="475" d="M76 0l231 1087h96l-229 -1087h-98zM128 1241v29q68 56 157.5 148.5t127.5 150.5h64q23 -64 72.5 -152.5t92.5 -146.5v-29h-49q-70 60 -161 207q-55 -57 -125 -114.5t-125 -92.5h-54z" /> -<glyph unicode="ï" horiz-adv-x="475" d="M76 0l231 1087h96l-229 -1087h-98zM171 1366q0 49 20.5 78t56.5 29q54 0 54 -64q0 -48 -21 -77t-55 -29q-55 0 -55 63zM515 1366q0 49 20.5 78t56.5 29q54 0 54 -64q0 -48 -21 -77t-55 -29q-55 0 -55 63z" /> -<glyph unicode="ð" horiz-adv-x="1124" d="M102 381q0 170 63 301.5t178.5 203.5t262.5 72q107 0 188 -49.5t121 -142.5h5q0 139 -43 289t-115 243l-295 -163l-39 73l285 156q-54 60 -158 139l59 68q32 -26 81 -66t100 -94l266 150l39 -74l-256 -141q87 -116 131.5 -276t44.5 -335q0 -355 -141.5 -555t-399.5 -200 q-177 0 -277 106.5t-100 294.5zM205 389q0 -153 73.5 -236t210.5 -83q118 0 208.5 61t144 186.5t53.5 270.5q0 77 -35 142t-100 101.5t-156 36.5q-124 0 -213.5 -61.5t-137.5 -169.5t-48 -248z" /> -<glyph unicode="ñ" horiz-adv-x="1143" d="M76 0l231 1087h82l-37 -221h6q164 238 416 238q130 0 195 -64t65 -184q0 -70 -24 -182l-148 -674h-98l149 692q21 92 21 156q0 80 -43.5 125t-134.5 45q-112 0 -210.5 -67t-166 -187.5t-103.5 -286.5l-102 -477h-98zM389 1243q19 108 71 166.5t134 58.5q41 0 73.5 -14 t117.5 -72q52 -36 94 -36q43 0 71.5 30.5t46.5 100.5h76q-26 -118 -74.5 -173t-124.5 -55q-40 0 -77.5 19t-75.5 45q-34 23 -64.5 41t-68.5 18q-45 0 -74 -28.5t-51 -100.5h-74z" /> -<glyph unicode="ò" horiz-adv-x="1124" d="M98 403q0 191 73 358t197 257t281 90q180 0 278.5 -108.5t98.5 -299.5q0 -197 -71.5 -368.5t-195.5 -261.5t-286 -90q-184 0 -279.5 109.5t-95.5 313.5zM201 408q0 -342 282 -342q127 0 225.5 77.5t157 228t58.5 330.5q0 154 -73 237t-210 83q-124 0 -223 -78.5 t-158 -225t-59 -310.5zM465 1548v21h115q46 -129 164 -303v-25h-66q-50 52 -114 144.5t-99 162.5z" /> -<glyph unicode="ó" horiz-adv-x="1124" d="M98 403q0 191 73 358t197 257t281 90q180 0 278.5 -108.5t98.5 -299.5q0 -197 -71.5 -368.5t-195.5 -261.5t-286 -90q-184 0 -279.5 109.5t-95.5 313.5zM201 408q0 -342 282 -342q127 0 225.5 77.5t157 228t58.5 330.5q0 154 -73 237t-210 83q-124 0 -223 -78.5 t-158 -225t-59 -310.5zM573 1241v21q66 51 150.5 142t129.5 165h137v-23q-51 -66 -157.5 -158.5t-192.5 -146.5h-67z" /> -<glyph unicode="ô" horiz-adv-x="1124" d="M98 403q0 191 73 358t197 257t281 90q180 0 278.5 -108.5t98.5 -299.5q0 -197 -71.5 -368.5t-195.5 -261.5t-286 -90q-184 0 -279.5 109.5t-95.5 313.5zM201 408q0 -342 282 -342q127 0 225.5 77.5t157 228t58.5 330.5q0 154 -73 237t-210 83q-124 0 -223 -78.5 t-158 -225t-59 -310.5zM427 1241v29q68 56 157.5 148.5t127.5 150.5h64q23 -64 72.5 -152.5t92.5 -146.5v-29h-49q-70 60 -161 207q-55 -57 -125 -114.5t-125 -92.5h-54z" /> -<glyph unicode="õ" horiz-adv-x="1124" d="M98 403q0 191 73 358t197 257t281 90q180 0 278.5 -108.5t98.5 -299.5q0 -197 -71.5 -368.5t-195.5 -261.5t-286 -90q-184 0 -279.5 109.5t-95.5 313.5zM201 408q0 -342 282 -342q127 0 225.5 77.5t157 228t58.5 330.5q0 154 -73 237t-210 83q-124 0 -223 -78.5 t-158 -225t-59 -310.5zM354 1243q19 108 71 166.5t134 58.5q41 0 73.5 -14t117.5 -72q52 -36 94 -36q43 0 71.5 30.5t46.5 100.5h76q-26 -118 -74.5 -173t-124.5 -55q-40 0 -77.5 19t-75.5 45q-34 23 -64.5 41t-68.5 18q-45 0 -74 -28.5t-51 -100.5h-74z" /> -<glyph unicode="ö" horiz-adv-x="1124" d="M98 403q0 191 73 358t197 257t281 90q180 0 278.5 -108.5t98.5 -299.5q0 -197 -71.5 -368.5t-195.5 -261.5t-286 -90q-184 0 -279.5 109.5t-95.5 313.5zM201 408q0 -342 282 -342q127 0 225.5 77.5t157 228t58.5 330.5q0 154 -73 237t-210 83q-124 0 -223 -78.5 t-158 -225t-59 -310.5zM468 1366q0 49 20.5 78t56.5 29q54 0 54 -64q0 -48 -21 -77t-55 -29q-55 0 -55 63zM812 1366q0 49 20.5 78t56.5 29q54 0 54 -64q0 -48 -21 -77t-55 -29q-55 0 -55 63z" /> -<glyph unicode="÷" d="M168 672v100h903v-100h-903zM522 373q0 106 96 106q48 0 73.5 -27.5t25.5 -78.5q0 -57 -29 -82t-70 -25q-96 0 -96 107zM522 1071q0 107 96 107q46 0 72.5 -27.5t26.5 -79.5q0 -57 -29 -81.5t-70 -24.5q-96 0 -96 106z" /> -<glyph unicode="ø" horiz-adv-x="1124" d="M45 -18l119 145q-66 106 -66 276q0 191 73 358t197 257t281 90q150 0 250 -82l109 133l65 -53l-117 -143q70 -105 70 -263q0 -197 -71.5 -368.5t-195.5 -261.5t-286 -90q-163 0 -254 83l-110 -135zM201 408q0 -125 32 -197l605 739q-74 72 -197 72q-124 0 -223 -78.5 t-158 -225t-59 -310.5zM281 139q67 -73 202 -73q127 0 225.5 77.5t157 228t58.5 330.5q0 101 -35 179z" /> -<glyph unicode="ù" horiz-adv-x="1143" d="M109 227q0 60 22 170l150 690h100l-152 -698q-22 -106 -22 -158q0 -74 47.5 -117.5t138.5 -43.5q110 0 207.5 65.5t164 187t99.5 279.5l105 485h98l-231 -1087h-80l28 205h-6q-167 -221 -403 -221q-131 0 -198.5 62t-67.5 181zM495 1548v21h115q46 -129 164 -303v-25h-66 q-50 52 -114 144.5t-99 162.5z" /> -<glyph unicode="ú" horiz-adv-x="1143" d="M109 227q0 60 22 170l150 690h100l-152 -698q-22 -106 -22 -158q0 -74 47.5 -117.5t138.5 -43.5q110 0 207.5 65.5t164 187t99.5 279.5l105 485h98l-231 -1087h-80l28 205h-6q-167 -221 -403 -221q-131 0 -198.5 62t-67.5 181zM627 1241v21q66 51 150.5 142t129.5 165 h137v-23q-51 -66 -157.5 -158.5t-192.5 -146.5h-67z" /> -<glyph unicode="û" horiz-adv-x="1143" d="M109 227q0 60 22 170l150 690h100l-152 -698q-22 -106 -22 -158q0 -74 47.5 -117.5t138.5 -43.5q110 0 207.5 65.5t164 187t99.5 279.5l105 485h98l-231 -1087h-80l28 205h-6q-167 -221 -403 -221q-131 0 -198.5 62t-67.5 181zM443 1241v29q68 56 157.5 148.5 t127.5 150.5h64q23 -64 72.5 -152.5t92.5 -146.5v-29h-49q-70 60 -161 207q-55 -57 -125 -114.5t-125 -92.5h-54z" /> -<glyph unicode="ü" horiz-adv-x="1143" d="M109 227q0 60 22 170l150 690h100l-152 -698q-22 -106 -22 -158q0 -74 47.5 -117.5t138.5 -43.5q110 0 207.5 65.5t164 187t99.5 279.5l105 485h98l-231 -1087h-80l28 205h-6q-167 -221 -403 -221q-131 0 -198.5 62t-67.5 181zM483 1366q0 49 20.5 78t56.5 29 q54 0 54 -64q0 -48 -21 -77t-55 -29q-55 0 -55 63zM827 1366q0 49 20.5 78t56.5 29q54 0 54 -64q0 -48 -21 -77t-55 -29q-55 0 -55 63z" /> -<glyph unicode="ý" horiz-adv-x="920" d="M-217 -379q71 -27 137 -27q80 0 147 49.5t130 164.5t100 184l-174 1095h100l82 -548q51 -351 55 -449h11q43 105 186 367l348 630h103l-713 -1290q-72 -127 -122.5 -178t-114 -81t-146.5 -30q-68 0 -129 21v92zM505 1241v21q66 51 150.5 142t129.5 165h137v-23 q-51 -66 -157.5 -158.5t-192.5 -146.5h-67z" /> -<glyph unicode="þ" horiz-adv-x="1163" d="M-33 -492l434 2048h99q-114 -535 -164 -751h6q93 156 199 229.5t231 73.5q133 0 206 -92.5t73 -282.5q0 -195 -72 -371t-197.5 -277t-283.5 -101q-230 0 -279 219h-4q-13 -72 -149 -695h-99zM266 346q0 -125 61.5 -200.5t168.5 -75.5q124 0 225 84t164 243.5t63 325.5 q0 295 -200 295q-86 0 -172.5 -57.5t-162.5 -169.5t-111.5 -238t-35.5 -207z" /> -<glyph unicode="ÿ" horiz-adv-x="920" d="M-217 -379q71 -27 137 -27q80 0 147 49.5t130 164.5t100 184l-174 1095h100l82 -548q51 -351 55 -449h11q43 105 186 367l348 630h103l-713 -1290q-72 -127 -122.5 -178t-114 -81t-146.5 -30q-68 0 -129 21v92zM354 1366q0 49 20.5 78t56.5 29q54 0 54 -64q0 -48 -21 -77 t-55 -29q-55 0 -55 63zM698 1366q0 49 20.5 78t56.5 29q54 0 54 -64q0 -48 -21 -77t-55 -29q-55 0 -55 63z" /> -<glyph unicode="ı" horiz-adv-x="475" d="M76 0l231 1087h96l-229 -1087h-98z" /> -<glyph unicode="Œ" horiz-adv-x="1767" d="M172 559q0 263 96 482t262 330.5t381 111.5q130 0 240 -21h688l-20 -94h-625l-117 -553h590l-20 -94h-588l-135 -627h626l-20 -94h-666q-25 -6 -77.5 -13t-94.5 -7q-251 0 -385.5 149.5t-134.5 429.5zM276 573q0 -245 109 -373t320 -128q68 0 116 12l271 1290 q-110 15 -189 15q-182 0 -321.5 -98.5t-222.5 -293.5t-83 -424z" /> -<glyph unicode="œ" horiz-adv-x="1720" d="M98 403q0 191 73 358t197 257t281 90q141 0 237 -74.5t126 -212.5q70 132 182.5 207.5t241.5 75.5q114 0 182 -61t68 -166q0 -181 -163.5 -276t-486.5 -95h-32q-7 -38 -7 -98q0 -165 74 -251.5t213 -86.5q133 0 277 73v-94q-140 -69 -299 -69q-135 0 -228 69t-125 201 q-65 -127 -179 -198.5t-257 -71.5q-184 0 -279.5 109.5t-95.5 313.5zM201 408q0 -342 282 -342q127 0 225.5 77.5t157 228t58.5 330.5q0 154 -73 237t-210 83q-124 0 -223 -78.5t-158 -225t-59 -310.5zM1018 594h49q516 0 516 270q0 70 -44.5 112t-115.5 42 q-131 0 -243 -115t-162 -309z" /> -<glyph unicode="Ÿ" horiz-adv-x="965" d="M193 1462h100l201 -817l544 817h117l-631 -932l-108 -530h-105l119 545zM454 1704q0 49 20.5 78t56.5 29q54 0 54 -64q0 -48 -21 -77t-55 -29q-55 0 -55 63zM798 1704q0 49 20.5 78t56.5 29q54 0 54 -64q0 -48 -21 -77t-55 -29q-55 0 -55 63z" /> -<glyph unicode="ˆ" horiz-adv-x="1135" d="M444 1241v29q68 56 157.5 148.5t127.5 150.5h64q23 -64 72.5 -152.5t92.5 -146.5v-29h-49q-70 60 -161 207q-55 -57 -125 -114.5t-125 -92.5h-54z" /> -<glyph unicode="˚" horiz-adv-x="1182" d="M561 1440q0 88 59.5 144t149.5 56q88 0 142.5 -50t54.5 -142t-57.5 -148.5t-145.5 -56.5q-93 0 -148 52t-55 145zM641 1440q0 -57 33 -90t90 -33q56 0 90.5 36t34.5 93t-33.5 90t-87.5 33q-60 0 -93.5 -36t-33.5 -93z" /> -<glyph unicode="˜" horiz-adv-x="1135" d="M346 1243q19 108 71 166.5t134 58.5q41 0 73.5 -14t117.5 -72q52 -36 94 -36q43 0 71.5 30.5t46.5 100.5h76q-26 -118 -74.5 -173t-124.5 -55q-40 0 -77.5 19t-75.5 45q-34 23 -64.5 41t-68.5 18q-45 0 -74 -28.5t-51 -100.5h-74z" /> -<glyph unicode=" " horiz-adv-x="953" /> -<glyph unicode=" " horiz-adv-x="1907" /> -<glyph unicode=" " horiz-adv-x="953" /> -<glyph unicode=" " horiz-adv-x="1907" /> -<glyph unicode=" " horiz-adv-x="635" /> -<glyph unicode=" " horiz-adv-x="476" /> -<glyph unicode=" " horiz-adv-x="317" /> -<glyph unicode=" " horiz-adv-x="317" /> -<glyph unicode=" " horiz-adv-x="238" /> -<glyph unicode=" " horiz-adv-x="381" /> -<glyph unicode=" " horiz-adv-x="105" /> -<glyph unicode="‐" horiz-adv-x="629" d="M82 502l18 90h457l-16 -90h-459z" /> -<glyph unicode="‑" horiz-adv-x="629" d="M82 502l18 90h457l-16 -90h-459z" /> -<glyph unicode="‒" horiz-adv-x="629" d="M82 502l18 90h457l-16 -90h-459z" /> -<glyph unicode="–" horiz-adv-x="983" d="M66 502l18 90h807l-17 -90h-808z" /> -<glyph unicode="—" horiz-adv-x="1966" d="M68 502l18 90h1788l-16 -90h-1790z" /> -<glyph unicode="‘" horiz-adv-x="299" d="M129 983q41 100 116 231t161 248h73q-66 -106 -129.5 -242.5t-103.5 -258.5h-113z" /> -<glyph unicode="’" horiz-adv-x="299" d="M129 961q66 106 129.5 242.5t103.5 258.5h113l4 -22q-43 -105 -117.5 -235.5t-158.5 -243.5h-74z" /> -<glyph unicode="‚" horiz-adv-x="451" d="M-100 -264q68 110 131.5 248t101.5 254h113l4 -23q-40 -97 -115.5 -230t-161.5 -249h-73z" /> -<glyph unicode="“" horiz-adv-x="631" d="M129 983q41 100 116 231t161 248h73q-66 -106 -129.5 -242.5t-103.5 -258.5h-113zM463 983q43 104 120 238.5t156 240.5h74q-66 -106 -129.5 -242.5t-103.5 -258.5h-113z" /> -<glyph unicode="”" horiz-adv-x="631" d="M129 961q66 106 129.5 242.5t103.5 258.5h113l4 -22q-43 -105 -117.5 -235.5t-158.5 -243.5h-74zM463 961q66 106 129.5 242.5t103.5 258.5h113l4 -22q-43 -105 -117.5 -235.5t-158.5 -243.5h-74z" /> -<glyph unicode="„" horiz-adv-x="776" d="M-119 -264q73 119 135.5 254.5t98.5 247.5h112l4 -23q-43 -105 -117.5 -235.5t-158.5 -243.5h-74zM215 -264q66 108 129 242.5t105 259.5h112l4 -23q-43 -105 -117.5 -235.5t-158.5 -243.5h-74z" /> -<glyph unicode="•" horiz-adv-x="793" d="M248 682q0 137 63 213t172 76q76 0 116 -39.5t40 -118.5q0 -125 -66 -207t-176 -82q-149 0 -149 158z" /> -<glyph unicode="…" horiz-adv-x="1489" d="M69 55q0 56 25 88.5t69 32.5q66 0 66 -72q0 -53 -25 -87.5t-67 -34.5q-68 0 -68 73zM569 55q0 56 25 88.5t69 32.5q66 0 66 -72q0 -53 -25 -87.5t-67 -34.5q-68 0 -68 73zM1071 55q0 56 25 88.5t69 32.5q66 0 66 -72q0 -53 -25 -87.5t-67 -34.5q-68 0 -68 73z" /> -<glyph unicode=" " horiz-adv-x="381" /> -<glyph unicode="‹" horiz-adv-x="537" d="M86 541l2 26l363 365l57 -49l-318 -336l213 -385l-63 -39z" /> -<glyph unicode="›" horiz-adv-x="537" d="M37 172l317 336l-213 385l64 39l254 -418l-2 -27l-363 -364z" /> -<glyph unicode="⁄" horiz-adv-x="274" d="M-463 0l1086 1462h108l-1087 -1462h-107z" /> -<glyph unicode=" " horiz-adv-x="476" /> -<glyph unicode="⁴" horiz-adv-x="643" d="M53 815l21 76l506 577h86l-125 -581h133l-17 -72h-131l-49 -229h-82l49 229h-391zM168 887h291q61 294 79 365.5t29 105.5q-10 -16 -61 -79t-338 -392z" /> -<glyph unicode="€" d="M80 541l16 82h172q5 101 35 217h-170l19 82h174q95 273 270 417t399 144q166 0 287 -90l-53 -82q-102 78 -238 78q-186 0 -330.5 -120.5t-226.5 -346.5h457l-21 -82h-460q-30 -98 -39 -217h442l-20 -82h-424q0 -243 89 -356t265 -113q115 0 252 57v-94q-129 -55 -270 -55 q-209 0 -325 139.5t-116 394.5v27h-184z" /> -<glyph unicode="™" horiz-adv-x="1534" d="M174 1384v78h522v-78h-219v-643h-86v643h-217zM772 741v721h125l221 -606l223 606h125v-721h-86v398l4 207h-6l-227 -605h-74l-221 609h-6l4 -201v-408h-82z" /> -<glyph unicode="" horiz-adv-x="1085" d="M0 1085h1085v-1085h-1085v1085z" /> -<glyph unicode="ff" horiz-adv-x="1155" d="M-233 -383q53 -16 100 -16q88 0 134 53t75 186l246 1166h-205l14 67l205 14l35 160q35 168 116.5 244t227.5 76q73 0 166 -31l-25 -80q-87 27 -147 27q-96 0 -153.5 -53.5t-84.5 -178.5l-35 -164h477l35 160q35 168 116.5 244t227.5 76q73 0 166 -31l-24 -80 q-87 27 -148 27q-97 0 -154.5 -54.5t-82.5 -177.5l-35 -164h248l-17 -81h-248l-252 -1190q-34 -165 -105.5 -236.5t-193.5 -71.5q-48 0 -102 19v90q53 -16 100 -16q88 0 134 53t75 186l244 1166h-477l-252 -1190q-33 -161 -104 -234.5t-195 -73.5q-48 0 -102 19v90z" /> -<glyph unicode="fi" horiz-adv-x="1040" d="M641 0l231 1087h96l-229 -1087h-98zM915 1366q0 55 22 88t60 33q57 0 57 -72q0 -57 -22 -90t-57 -33q-29 0 -44.5 19.5t-15.5 54.5zM-250 -383q53 -16 100 -16q88 0 134 53t75 186l246 1166h-205l14 67l205 14l35 160q35 168 116.5 244t227.5 76q73 0 166 -31l-25 -80 q-87 27 -147 27q-96 0 -153.5 -53.5t-84.5 -178.5l-35 -164h248l-16 -81h-248l-252 -1190q-33 -161 -104 -234.5t-195 -73.5q-48 0 -102 19v90z" /> -<glyph unicode="fl" horiz-adv-x="1042" d="M643 0l334 1556h94l-334 -1556h-94zM-250 -383q53 -16 100 -16q88 0 134 53t75 186l246 1166h-205l14 67l205 14l35 160q35 168 116.5 244t227.5 76q73 0 166 -31l-25 -80q-87 27 -147 27q-96 0 -153.5 -53.5t-84.5 -178.5l-35 -164h248l-16 -81h-248l-252 -1190 q-33 -161 -104 -234.5t-195 -73.5q-48 0 -102 19v90z" /> -<glyph unicode="ffi" horiz-adv-x="1616" d="M-250 -383q53 -16 100 -16q88 0 134 53t75 186l246 1166h-205l14 67l205 14l35 160q35 168 116.5 244t227.5 76q73 0 166 -31l-25 -80q-87 27 -147 27q-96 0 -153.5 -53.5t-84.5 -178.5l-35 -164h477l35 160q35 168 116.5 244t227.5 76q73 0 166 -31l-24 -80 q-87 27 -148 27q-97 0 -154.5 -54.5t-82.5 -177.5l-35 -164h248l-17 -81h-248l-252 -1190q-34 -165 -105.5 -236.5t-193.5 -71.5q-48 0 -102 19v90q53 -16 100 -16q88 0 134 53t75 186l244 1166h-477l-252 -1190q-33 -161 -104 -234.5t-195 -73.5q-48 0 -102 19v90zM1217 0 l231 1087h96l-229 -1087h-98zM1491 1366q0 55 22 88t60 33q57 0 57 -72q0 -57 -22 -90t-57 -33q-29 0 -44.5 19.5t-15.5 54.5z" /> -<glyph unicode="ffl" horiz-adv-x="1626" d="M-250 -383q53 -16 100 -16q88 0 134 53t75 186l246 1166h-205l14 67l205 14l35 160q35 168 116.5 244t227.5 76q73 0 166 -31l-25 -80q-87 27 -147 27q-96 0 -153.5 -53.5t-84.5 -178.5l-35 -164h477l35 160q35 168 116.5 244t227.5 76q73 0 166 -31l-24 -80 q-87 27 -148 27q-97 0 -154.5 -54.5t-82.5 -177.5l-35 -164h248l-17 -81h-248l-252 -1190q-34 -165 -105.5 -236.5t-193.5 -71.5q-48 0 -102 19v90q53 -16 100 -16q88 0 134 53t75 186l244 1166h-477l-252 -1190q-33 -161 -104 -234.5t-195 -73.5q-48 0 -102 19v90zM1227 0 l334 1556h94l-334 -1556h-94z" /> -</font> -</defs></svg> -\ No newline at end of file diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-LightItalic-webfont.ttf b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-LightItalic-webfont.ttf Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-LightItalic-webfont.woff b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-LightItalic-webfont.woff Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-Regular-webfont.eot b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-Regular-webfont.eot Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-Regular-webfont.svg b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-Regular-webfont.svg @@ -1,252 +0,0 @@ -<?xml version="1.0" standalone="no"?> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" > -<svg xmlns="http://www.w3.org/2000/svg"> -<metadata> -This is a custom SVG webfont generated by Font Squirrel. -Copyright : Digitized data copyright 20102011 Google Corporation -Foundry : Ascender Corporation -Foundry URL : httpwwwascendercorpcom -</metadata> -<defs> -<font id="OpenSansRegular" horiz-adv-x="1171" > -<font-face units-per-em="2048" ascent="1638" descent="-410" /> -<missing-glyph horiz-adv-x="532" /> -<glyph unicode=" " horiz-adv-x="532" /> -<glyph unicode="	" horiz-adv-x="532" /> -<glyph unicode=" " horiz-adv-x="532" /> -<glyph unicode="!" horiz-adv-x="547" d="M152 106q0 136 120 136q58 0 89.5 -35t31.5 -101q0 -64 -32 -99.5t-89 -35.5q-52 0 -86 31.5t-34 103.5zM170 1462h207l-51 -1059h-105z" /> -<glyph unicode=""" horiz-adv-x="821" d="M133 1462h186l-40 -528h-105zM502 1462h186l-41 -528h-104z" /> -<glyph unicode="#" horiz-adv-x="1323" d="M51 430v129h287l68 340h-277v127h299l82 436h139l-82 -436h305l84 436h134l-84 -436h264v-127h-289l-66 -340h283v-129h-307l-84 -430h-137l84 430h-303l-82 -430h-136l80 430h-262zM475 559h303l66 340h-303z" /> -<glyph unicode="$" d="M131 170v156q83 -37 191.5 -60.5t197.5 -23.5v440q-205 65 -287.5 151t-82.5 222q0 131 101.5 215t268.5 102v182h129v-180q184 -5 355 -74l-52 -131q-149 59 -303 70v-434q157 -50 235 -97.5t115 -109t37 -149.5q0 -136 -102 -224.5t-285 -111.5v-232h-129v223 q-112 0 -217 17.5t-172 48.5zM319 1057q0 -76 45 -122t156 -87v387q-99 -16 -150 -62.5t-51 -115.5zM649 252q217 30 217 184q0 72 -44.5 116.5t-172.5 88.5v-389z" /> -<glyph unicode="%" horiz-adv-x="1686" d="M104 1026q0 227 74.5 342t220.5 115q145 0 223 -119t78 -338q0 -228 -76.5 -344.5t-224.5 -116.5q-140 0 -217.5 119t-77.5 342zM242 1026q0 -170 37 -255t120 -85q164 0 164 340q0 338 -164 338q-83 0 -120 -84t-37 -254zM365 0l811 1462h147l-811 -1462h-147zM985 440 q0 227 74.5 342t220.5 115q142 0 221.5 -117.5t79.5 -339.5q0 -227 -76.5 -343.5t-224.5 -116.5q-142 0 -218.5 119t-76.5 341zM1122 440q0 -171 37 -255.5t121 -84.5t124 83.5t40 256.5q0 171 -40 253.5t-124 82.5t-121 -82.5t-37 -253.5z" /> -<glyph unicode="&" horiz-adv-x="1495" d="M113 379q0 130 69.5 230t249.5 202q-85 95 -115.5 144t-48.5 102t-18 110q0 150 98 234t273 84q162 0 255 -83.5t93 -232.5q0 -107 -68 -197.5t-225 -183.5l407 -391q56 62 89.5 145.5t56.5 182.5h168q-68 -286 -205 -434l299 -291h-229l-185 178q-118 -106 -240 -152 t-272 -46q-215 0 -333.5 106t-118.5 293zM285 383q0 -117 77.5 -185.5t206.5 -68.5q241 0 400 154l-437 424q-111 -68 -157 -112.5t-68 -95.5t-22 -116zM414 1171q0 -69 36 -131.5t123 -150.5q129 75 179.5 138.5t50.5 146.5q0 77 -51.5 125.5t-137.5 48.5q-89 0 -144.5 -48 t-55.5 -129z" /> -<glyph unicode="'" horiz-adv-x="453" d="M133 1462h186l-40 -528h-105z" /> -<glyph unicode="(" horiz-adv-x="606" d="M82 561q0 265 77.5 496t223.5 405h162q-144 -193 -216.5 -424t-72.5 -475q0 -240 74 -469t213 -418h-160q-147 170 -224 397t-77 488z" /> -<glyph unicode=")" horiz-adv-x="606" d="M61 1462h162q147 -175 224 -406.5t77 -494.5t-77.5 -490t-223.5 -395h-160q139 188 213 417.5t74 469.5q0 244 -72.5 475t-216.5 424z" /> -<glyph unicode="*" horiz-adv-x="1130" d="M86 1090l29 182l391 -111l-43 395h194l-43 -395l398 111l26 -182l-381 -31l248 -326l-172 -94l-176 362l-160 -362l-176 94l242 326z" /> -<glyph unicode="+" d="M104 653v138h410v428h139v-428h412v-138h-412v-426h-139v426h-410z" /> -<glyph unicode="," horiz-adv-x="502" d="M63 -264q27 104 59.5 257t45.5 245h182l15 -23q-26 -100 -75 -232.5t-102 -246.5h-125z" /> -<glyph unicode="-" horiz-adv-x="659" d="M84 473v152h491v-152h-491z" /> -<glyph unicode="." horiz-adv-x="545" d="M152 106q0 67 30.5 101.5t87.5 34.5q58 0 90.5 -34.5t32.5 -101.5q0 -65 -33 -100t-90 -35q-51 0 -84.5 31.5t-33.5 103.5z" /> -<glyph unicode="/" horiz-adv-x="752" d="M20 0l545 1462h166l-545 -1462h-166z" /> -<glyph unicode="0" d="M102 733q0 382 119 567t363 185q238 0 361.5 -193t123.5 -559q0 -379 -119.5 -566t-365.5 -187q-236 0 -359 191.5t-123 561.5zM270 733q0 -319 75 -464.5t239 -145.5q166 0 240.5 147.5t74.5 462.5t-74.5 461.5t-240.5 146.5q-164 0 -239 -144.5t-75 -463.5z" /> -<glyph unicode="1" d="M188 1163l387 299h140v-1462h-162v1042q0 130 8 246q-21 -21 -47 -44t-238 -195z" /> -<glyph unicode="2" d="M100 0v143l385 387q176 178 232 254t84 148t28 155q0 117 -71 185.5t-197 68.5q-91 0 -172.5 -30t-181.5 -109l-88 113q202 168 440 168q206 0 323 -105.5t117 -283.5q0 -139 -78 -275t-292 -344l-320 -313v-8h752v-154h-961z" /> -<glyph unicode="3" d="M94 59v158q95 -47 202.5 -71.5t203.5 -24.5q379 0 379 297q0 266 -418 266h-144v143h146q171 0 271 75.5t100 209.5q0 107 -73.5 168t-199.5 61q-96 0 -181 -26t-194 -96l-84 112q90 71 207.5 111.5t247.5 40.5q213 0 331 -97.5t118 -267.5q0 -140 -78.5 -229 t-222.5 -119v-8q176 -22 261 -112t85 -236q0 -209 -145 -321.5t-412 -112.5q-116 0 -212.5 17.5t-187.5 61.5z" /> -<glyph unicode="4" d="M43 336v145l694 989h176v-983h217v-151h-217v-336h-159v336h-711zM209 487h545v486q0 143 10 323h-8q-48 -96 -90 -159z" /> -<glyph unicode="5" d="M133 59v160q70 -45 174 -70.5t205 -25.5q176 0 273.5 83t97.5 240q0 306 -375 306q-95 0 -254 -29l-86 55l55 684h727v-153h-585l-37 -439q115 23 229 23q231 0 363.5 -114.5t132.5 -313.5q0 -227 -144.5 -356t-398.5 -129q-247 0 -377 79z" /> -<glyph unicode="6" d="M117 625q0 431 167.5 644.5t495.5 213.5q113 0 178 -19v-143q-77 25 -176 25q-235 0 -359 -146.5t-136 -460.5h12q110 172 348 172q197 0 310.5 -119t113.5 -323q0 -228 -124.5 -358.5t-336.5 -130.5q-227 0 -360 170.5t-133 474.5zM287 506q0 -103 40 -192t113.5 -141 t167.5 -52q142 0 220.5 89.5t78.5 258.5q0 145 -73 228t-218 83q-90 0 -165 -37t-119.5 -102t-44.5 -135z" /> -<glyph unicode="7" d="M94 1309v153h973v-133l-598 -1329h-184l606 1309h-797z" /> -<glyph unicode="8" d="M104 373q0 251 306 391q-138 78 -198 168.5t-60 202.5q0 159 117.5 253.5t314.5 94.5q200 0 317 -93t117 -257q0 -108 -67 -197t-214 -162q178 -85 253 -178.5t75 -216.5q0 -182 -127 -290.5t-348 -108.5q-234 0 -360 102.5t-126 290.5zM268 369q0 -120 83.5 -187 t234.5 -67q149 0 232 70t83 192q0 97 -78 172.5t-272 146.5q-149 -64 -216 -141.5t-67 -185.5zM315 1128q0 -92 59 -158t218 -132q143 60 202.5 129t59.5 161q0 101 -72.5 160.5t-199.5 59.5q-125 0 -196 -60t-71 -160z" /> -<glyph unicode="9" d="M106 991q0 228 127.5 360t335.5 132q149 0 260.5 -76.5t171.5 -223t60 -345.5q0 -858 -664 -858q-116 0 -184 20v143q80 -26 182 -26q240 0 362.5 148.5t133.5 455.5h-12q-55 -83 -146 -126.5t-205 -43.5q-194 0 -308 116t-114 324zM270 993q0 -144 72 -226.5t219 -82.5 q91 0 167.5 37t120.5 101t44 134q0 105 -41 194t-114.5 140t-168.5 51q-143 0 -221 -92t-78 -256z" /> -<glyph unicode=":" horiz-adv-x="545" d="M152 106q0 67 30.5 101.5t87.5 34.5q58 0 90.5 -34.5t32.5 -101.5q0 -65 -33 -100t-90 -35q-51 0 -84.5 31.5t-33.5 103.5zM152 989q0 135 118 135q123 0 123 -135q0 -65 -33 -100t-90 -35q-51 0 -84.5 31.5t-33.5 103.5z" /> -<glyph unicode=";" horiz-adv-x="545" d="M63 -264q27 104 59.5 257t45.5 245h182l15 -23q-26 -100 -75 -232.5t-102 -246.5h-125zM147 989q0 135 119 135q123 0 123 -135q0 -65 -33 -100t-90 -35q-58 0 -88.5 35t-30.5 100z" /> -<glyph unicode="<" d="M104 664v98l961 479v-149l-782 -371l782 -328v-151z" /> -<glyph unicode="=" d="M119 449v137h930v-137h-930zM119 858v137h930v-137h-930z" /> -<glyph unicode=">" d="M104 242v151l783 326l-783 373v149l961 -479v-98z" /> -<glyph unicode="?" horiz-adv-x="879" d="M27 1384q189 99 395 99q191 0 297 -94t106 -265q0 -73 -19.5 -128.5t-57.5 -105t-164 -159.5q-101 -86 -133.5 -143t-32.5 -152v-33h-129v54q0 117 36 192.5t134 159.5q136 115 171.5 173t35.5 140q0 102 -65.5 157.5t-188.5 55.5q-79 0 -154 -18.5t-172 -67.5zM240 106 q0 136 120 136q58 0 89.5 -35t31.5 -101q0 -64 -32 -99.5t-89 -35.5q-52 0 -86 31.5t-34 103.5z" /> -<glyph unicode="@" horiz-adv-x="1841" d="M121 571q0 260 107 463t305 314.5t454 111.5q215 0 382.5 -90.5t259 -257t91.5 -383.5q0 -142 -44 -260t-124 -183t-184 -65q-86 0 -145 52t-70 133h-8q-40 -87 -114.5 -136t-176.5 -49q-150 0 -234.5 102.5t-84.5 278.5q0 204 118 331.5t310 127.5q68 0 154 -12.5 t155 -34.5l-25 -470v-22q0 -178 133 -178q91 0 148 107.5t57 279.5q0 181 -74 317t-210.5 209.5t-313.5 73.5q-223 0 -388 -92.5t-252 -264t-87 -396.5q0 -305 161 -469t464 -164q210 0 436 86v-133q-192 -84 -436 -84q-363 0 -563.5 199.5t-200.5 557.5zM686 598 q0 -254 195 -254q207 0 225 313l14 261q-72 20 -157 20q-130 0 -203.5 -90t-73.5 -250z" /> -<glyph unicode="A" horiz-adv-x="1296" d="M0 0l578 1468h143l575 -1468h-176l-182 465h-586l-180 -465h-172zM412 618h473l-170 453q-33 86 -68 211q-22 -96 -63 -211z" /> -<glyph unicode="B" horiz-adv-x="1327" d="M201 0v1462h413q291 0 421 -87t130 -275q0 -130 -72.5 -214.5t-211.5 -109.5v-10q333 -57 333 -350q0 -196 -132.5 -306t-370.5 -110h-510zM371 145h305q177 0 266.5 68.5t89.5 214.5q0 136 -91.5 200t-278.5 64h-291v-547zM371 836h280q180 0 259 56.5t79 190.5 q0 123 -88 177.5t-280 54.5h-250v-479z" /> -<glyph unicode="C" horiz-adv-x="1292" d="M125 733q0 226 84.5 396t244 262t375.5 92q230 0 402 -84l-72 -146q-166 78 -332 78q-241 0 -380.5 -160.5t-139.5 -439.5q0 -287 134.5 -443.5t383.5 -156.5q153 0 349 55v-149q-152 -57 -375 -57q-323 0 -498.5 196t-175.5 557z" /> -<glyph unicode="D" horiz-adv-x="1493" d="M201 0v1462h448q341 0 530 -189t189 -528q0 -362 -196.5 -553.5t-565.5 -191.5h-405zM371 147h207q304 0 457 149.5t153 442.5q0 286 -143.5 431t-426.5 145h-247v-1168z" /> -<glyph unicode="E" horiz-adv-x="1139" d="M201 0v1462h815v-151h-645v-471h606v-150h-606v-538h645v-152h-815z" /> -<glyph unicode="F" horiz-adv-x="1057" d="M201 0v1462h815v-151h-645v-535h606v-151h-606v-625h-170z" /> -<glyph unicode="G" horiz-adv-x="1491" d="M125 731q0 228 91.5 399.5t263.5 262t403 90.5q234 0 436 -86l-66 -150q-198 84 -381 84q-267 0 -417 -159t-150 -441q0 -296 144.5 -449t424.5 -153q152 0 297 35v450h-327v152h497v-711q-116 -37 -236 -56t-278 -19q-332 0 -517 197.5t-185 553.5z" /> -<glyph unicode="H" horiz-adv-x="1511" d="M201 0v1462h170v-622h770v622h170v-1462h-170v688h-770v-688h-170z" /> -<glyph unicode="I" horiz-adv-x="571" d="M201 0v1462h170v-1462h-170z" /> -<glyph unicode="J" horiz-adv-x="547" d="M-160 -213q71 -20 148 -20q99 0 150.5 60t51.5 173v1462h170v-1448q0 -190 -96 -294.5t-276 -104.5q-94 0 -148 27v145z" /> -<glyph unicode="K" horiz-adv-x="1257" d="M201 0v1462h170v-725l663 725h201l-588 -635l610 -827h-200l-533 709l-153 -136v-573h-170z" /> -<glyph unicode="L" horiz-adv-x="1063" d="M201 0v1462h170v-1308h645v-154h-815z" /> -<glyph unicode="M" horiz-adv-x="1849" d="M201 0v1462h256l463 -1206h8l467 1206h254v-1462h-170v942q0 162 14 352h-8l-500 -1294h-137l-496 1296h-8q14 -154 14 -366v-930h-157z" /> -<glyph unicode="N" horiz-adv-x="1544" d="M201 0v1462h192l797 -1222h8q-2 28 -9 174q-5 114 -5 177v32v839h159v-1462h-194l-799 1227h-8q16 -216 16 -396v-831h-157z" /> -<glyph unicode="O" horiz-adv-x="1595" d="M125 735q0 357 176 553.5t500 196.5q315 0 492 -200t177 -552q0 -351 -177.5 -552t-493.5 -201q-323 0 -498.5 197.5t-175.5 557.5zM305 733q0 -297 126.5 -450.5t367.5 -153.5q243 0 367 153t124 451q0 295 -123.5 447.5t-365.5 152.5q-243 0 -369.5 -153.5 t-126.5 -446.5z" /> -<glyph unicode="P" horiz-adv-x="1233" d="M201 0v1462h379q548 0 548 -426q0 -222 -151.5 -341.5t-433.5 -119.5h-172v-575h-170zM371 721h153q226 0 327 73t101 234q0 145 -95 216t-296 71h-190v-594z" /> -<glyph unicode="Q" horiz-adv-x="1595" d="M125 735q0 357 176 553.5t500 196.5q315 0 492 -200t177 -552q0 -281 -113 -467t-319 -252l348 -362h-247l-285 330l-55 -2q-323 0 -498.5 197.5t-175.5 557.5zM305 733q0 -297 126.5 -450.5t367.5 -153.5q243 0 367 153t124 451q0 295 -123.5 447.5t-365.5 152.5 q-243 0 -369.5 -153.5t-126.5 -446.5z" /> -<glyph unicode="R" horiz-adv-x="1266" d="M201 0v1462h401q269 0 397.5 -103t128.5 -310q0 -290 -294 -392l397 -657h-201l-354 608h-305v-608h-170zM371 754h233q180 0 264 71.5t84 214.5q0 145 -85.5 209t-274.5 64h-221v-559z" /> -<glyph unicode="S" horiz-adv-x="1124" d="M106 47v164q90 -38 196 -60t210 -22q170 0 256 64.5t86 179.5q0 76 -30.5 124.5t-102 89.5t-217.5 93q-204 73 -291.5 173t-87.5 261q0 169 127 269t336 100q218 0 401 -80l-53 -148q-181 76 -352 76q-135 0 -211 -58t-76 -161q0 -76 28 -124.5t94.5 -89t203.5 -89.5 q230 -82 316.5 -176t86.5 -244q0 -193 -140 -301t-380 -108q-260 0 -400 67z" /> -<glyph unicode="T" horiz-adv-x="1133" d="M18 1311v151h1096v-151h-463v-1311h-170v1311h-463z" /> -<glyph unicode="U" horiz-adv-x="1491" d="M186 520v942h170v-954q0 -183 100 -281t294 -98q185 0 285 98.5t100 282.5v952h170v-946q0 -250 -151 -393t-415 -143t-408.5 144t-144.5 396z" /> -<glyph unicode="V" horiz-adv-x="1219" d="M0 1462h180l336 -946q58 -163 92 -317q36 162 94 323l334 940h183l-527 -1462h-168z" /> -<glyph unicode="W" horiz-adv-x="1896" d="M27 1462h180l231 -903q48 -190 70 -344q27 183 80 358l262 889h180l275 -897q48 -155 81 -350q19 142 72 346l230 901h180l-391 -1462h-168l-295 979q-21 65 -47 164t-27 119q-22 -132 -70 -289l-286 -973h-168z" /> -<glyph unicode="X" horiz-adv-x="1182" d="M8 0l486 764l-453 698h188l363 -579l366 579h181l-453 -692l488 -770h-193l-393 643l-400 -643h-180z" /> -<glyph unicode="Y" horiz-adv-x="1147" d="M0 1462h186l387 -731l390 731h184l-488 -895v-567h-172v559z" /> -<glyph unicode="Z" horiz-adv-x="1169" d="M82 0v133l776 1176h-752v153h959v-133l-776 -1175h798v-154h-1005z" /> -<glyph unicode="[" horiz-adv-x="674" d="M166 -324v1786h457v-141h-289v-1503h289v-142h-457z" /> -<glyph unicode="\" horiz-adv-x="752" d="M23 1462h163l547 -1462h-166z" /> -<glyph unicode="]" horiz-adv-x="674" d="M51 -182h289v1503h-289v141h457v-1786h-457v142z" /> -<glyph unicode="^" horiz-adv-x="1110" d="M49 551l434 922h99l477 -922h-152l-372 745l-334 -745h-152z" /> -<glyph unicode="_" horiz-adv-x="918" d="M-4 -184h926v-131h-926v131z" /> -<glyph unicode="`" horiz-adv-x="1182" d="M393 1548v21h203q32 -69 89 -159.5t101 -143.5v-25h-110q-65 52 -154 148t-129 159z" /> -<glyph unicode="a" horiz-adv-x="1139" d="M94 303q0 332 531 348l186 6v68q0 129 -55.5 190.5t-177.5 61.5q-137 0 -310 -84l-51 127q81 44 177.5 69t193.5 25q196 0 290.5 -87t94.5 -279v-748h-123l-33 156h-8q-82 -103 -163.5 -139.5t-203.5 -36.5q-163 0 -255.5 84t-92.5 239zM268 301q0 -90 54.5 -137 t152.5 -47q155 0 243.5 85t88.5 238v99l-166 -7q-198 -7 -285.5 -61.5t-87.5 -169.5z" /> -<glyph unicode="b" horiz-adv-x="1255" d="M176 0v1556h166v-378q0 -127 -8 -228h8q116 164 344 164q216 0 335.5 -147.5t119.5 -417.5t-120.5 -419.5t-334.5 -149.5q-107 0 -195.5 39.5t-148.5 121.5h-12l-35 -141h-119zM342 549q0 -231 77 -330.5t247 -99.5q153 0 228 111.5t75 320.5q0 214 -75 319t-232 105 q-170 0 -245 -97.5t-75 -328.5z" /> -<glyph unicode="c" horiz-adv-x="975" d="M115 541q0 275 132.5 425t377.5 150q79 0 158 -17t124 -40l-51 -141q-55 22 -120 36.5t-115 14.5q-334 0 -334 -426q0 -202 81.5 -310t241.5 -108q137 0 281 59v-147q-110 -57 -277 -57q-238 0 -368.5 146.5t-130.5 414.5z" /> -<glyph unicode="d" horiz-adv-x="1255" d="M115 545q0 271 120 421t334 150q223 0 342 -162h13l-7 79l-4 77v446h166v-1556h-135l-22 147h-9q-115 -167 -344 -167q-215 0 -334.5 147t-119.5 418zM287 543q0 -210 77 -317t226 -107q170 0 246.5 92.5t76.5 298.5v35q0 233 -77.5 332.5t-247.5 99.5 q-146 0 -223.5 -113.5t-77.5 -320.5z" /> -<glyph unicode="e" horiz-adv-x="1149" d="M115 539q0 265 130.5 421t350.5 156q206 0 326 -135.5t120 -357.5v-105h-755q5 -193 97.5 -293t260.5 -100q177 0 350 74v-148q-88 -38 -166.5 -54.5t-189.5 -16.5q-243 0 -383.5 148t-140.5 411zM291 653h573q0 157 -70 240.5t-200 83.5q-132 0 -210.5 -86t-92.5 -238z " /> -<glyph unicode="f" horiz-adv-x="694" d="M29 967v75l196 60v61q0 404 353 404q87 0 204 -35l-43 -133q-96 31 -164 31q-94 0 -139 -62.5t-45 -200.5v-71h279v-129h-279v-967h-166v967h-196z" /> -<glyph unicode="g" horiz-adv-x="1122" d="M39 -186q0 100 64 173t180 99q-42 19 -70.5 59t-28.5 93q0 60 32 105t101 87q-85 35 -138.5 119t-53.5 192q0 180 108 277.5t306 97.5q86 0 155 -20h379v-105l-203 -24q28 -35 50 -91.5t22 -127.5q0 -161 -110 -257t-302 -96q-49 0 -92 8q-106 -56 -106 -141 q0 -45 37 -66.5t127 -21.5h194q178 0 273.5 -75t95.5 -218q0 -182 -146 -277.5t-426 -95.5q-215 0 -331.5 80t-116.5 226zM199 -184q0 -89 75 -135t215 -46q209 0 309.5 62.5t100.5 169.5q0 89 -55 123.5t-207 34.5h-199q-113 0 -176 -54t-63 -155zM289 745q0 -115 65 -174 t181 -59q243 0 243 236q0 247 -246 247q-117 0 -180 -63t-63 -187z" /> -<glyph unicode="h" horiz-adv-x="1257" d="M176 0v1556h166v-471q0 -85 -8 -141h10q49 79 139.5 124.5t206.5 45.5q201 0 301.5 -95.5t100.5 -303.5v-715h-166v709q0 134 -61 200t-191 66q-173 0 -252.5 -94t-79.5 -308v-573h-166z" /> -<glyph unicode="i" horiz-adv-x="518" d="M162 1393q0 57 28 83.5t70 26.5q40 0 69 -27t29 -83t-29 -83.5t-69 -27.5q-42 0 -70 27.5t-28 83.5zM176 0v1096h166v-1096h-166z" /> -<glyph unicode="j" horiz-adv-x="518" d="M-111 -332q69 -20 136 -20q78 0 114.5 42.5t36.5 129.5v1276h166v-1264q0 -324 -299 -324q-95 0 -154 25v135zM162 1393q0 57 28 83.5t70 26.5q40 0 69 -27t29 -83t-29 -83.5t-69 -27.5q-42 0 -70 27.5t-28 83.5z" /> -<glyph unicode="k" horiz-adv-x="1075" d="M176 0v1556h164v-825q0 -55 -8 -170h8q43 61 131 160l354 375h197l-444 -467l475 -629h-201l-387 518l-125 -108v-410h-164z" /> -<glyph unicode="l" horiz-adv-x="518" d="M176 0v1556h166v-1556h-166z" /> -<glyph unicode="m" horiz-adv-x="1905" d="M176 0v1096h135l27 -150h8q47 80 132.5 125t191.5 45q257 0 336 -186h8q49 86 142 136t212 50q186 0 278.5 -95.5t92.5 -305.5v-715h-166v713q0 131 -56 196.5t-174 65.5q-155 0 -229 -89t-74 -274v-612h-166v713q0 131 -56 196.5t-175 65.5q-156 0 -228.5 -93.5 t-72.5 -306.5v-575h-166z" /> -<glyph unicode="n" horiz-adv-x="1257" d="M176 0v1096h135l27 -150h8q51 81 143 125.5t205 44.5q198 0 298 -95.5t100 -305.5v-715h-166v709q0 134 -61 200t-191 66q-172 0 -252 -93t-80 -307v-575h-166z" /> -<glyph unicode="o" horiz-adv-x="1237" d="M115 549q0 268 134 417.5t372 149.5q230 0 365.5 -153t135.5 -414q0 -268 -135 -418.5t-373 -150.5q-147 0 -261 69t-176 198t-62 302zM287 549q0 -210 84 -320t247 -110t247.5 109.5t84.5 320.5q0 209 -84.5 317.5t-249.5 108.5q-163 0 -246 -107t-83 -319z" /> -<glyph unicode="p" horiz-adv-x="1255" d="M176 -492v1588h135l23 -150h8q64 90 149 130t195 40q218 0 336.5 -149t118.5 -418q0 -270 -120.5 -419.5t-334.5 -149.5q-107 0 -195.5 39.5t-148.5 121.5h-12q12 -96 12 -182v-451h-166zM342 549q0 -231 77 -330.5t247 -99.5q142 0 222.5 115t80.5 317 q0 205 -80.5 314.5t-226.5 109.5q-168 0 -243 -93t-77 -296v-37z" /> -<glyph unicode="q" horiz-adv-x="1255" d="M115 545q0 269 120 420t334 151q225 0 346 -170h9l24 150h131v-1588h-166v469q0 100 11 170h-13q-115 -167 -346 -167q-212 0 -331 149t-119 416zM287 543q0 -207 76.5 -315.5t226.5 -108.5q166 0 242 89t81 300v37q0 230 -78 331t-247 101q-146 0 -223.5 -113.5 t-77.5 -320.5z" /> -<glyph unicode="r" horiz-adv-x="836" d="M176 0v1096h137l19 -203h8q61 107 147 165t189 58q73 0 131 -12l-23 -154q-68 15 -120 15q-133 0 -227.5 -108t-94.5 -269v-588h-166z" /> -<glyph unicode="s" horiz-adv-x="977" d="M106 827q0 134 109 211.5t299 77.5q177 0 346 -72l-59 -135q-165 68 -299 68q-118 0 -178 -37t-60 -102q0 -44 22.5 -75t72.5 -59t192 -81q195 -71 263.5 -143t68.5 -181q0 -153 -114 -236t-320 -83q-218 0 -340 69v154q79 -40 169.5 -63t174.5 -23q130 0 200 41.5 t70 126.5q0 64 -55.5 109.5t-216.5 107.5q-153 57 -217.5 99.5t-96 96.5t-31.5 129z" /> -<glyph unicode="t" horiz-adv-x="723" d="M31 967v80l157 69l70 234h96v-254h318v-129h-318v-645q0 -99 47 -152t129 -53q44 0 85 6.5t65 13.5v-127q-27 -13 -79.5 -21.5t-94.5 -8.5q-318 0 -318 335v652h-157z" /> -<glyph unicode="u" horiz-adv-x="1257" d="M164 379v717h168v-711q0 -134 61 -200t191 -66q172 0 251.5 94t79.5 307v576h166v-1096h-137l-24 147h-9q-51 -81 -141.5 -124t-206.5 -43q-200 0 -299.5 95t-99.5 304z" /> -<glyph unicode="v" horiz-adv-x="1026" d="M0 1096h178l236 -650q80 -228 94 -296h8q11 53 69.5 219.5t262.5 726.5h178l-416 -1096h-194z" /> -<glyph unicode="w" horiz-adv-x="1593" d="M23 1096h174q106 -413 161.5 -629t63.5 -291h8q11 57 35.5 147.5t42.5 143.5l201 629h180l196 -629q56 -172 76 -289h8q4 36 21.5 111t208.5 807h172l-303 -1096h-197l-201 643q-19 59 -71 268h-8q-40 -175 -70 -270l-207 -641h-192z" /> -<glyph unicode="x" horiz-adv-x="1073" d="M39 0l401 561l-381 535h189l289 -420l288 420h187l-381 -535l401 -561h-188l-307 444l-310 -444h-188z" /> -<glyph unicode="y" horiz-adv-x="1032" d="M2 1096h178l240 -625q79 -214 98 -309h8q13 51 54.5 174.5t271.5 759.5h178l-471 -1248q-70 -185 -163.5 -262.5t-229.5 -77.5q-76 0 -150 17v133q55 -12 123 -12q171 0 244 192l61 156z" /> -<glyph unicode="z" horiz-adv-x="958" d="M82 0v113l598 854h-561v129h743v-129l-590 -838h605v-129h-795z" /> -<glyph unicode="{" horiz-adv-x="776" d="M61 498v141q130 2 188 48t58 142v306q0 155 108 241t290 86v-139q-230 -6 -230 -199v-295q0 -215 -223 -254v-12q223 -39 223 -254v-297q0 -102 58.5 -148t171.5 -48v-140q-190 2 -294 87t-104 239v303q0 104 -63 148.5t-183 44.5z" /> -<glyph unicode="|" horiz-adv-x="1128" d="M494 -496v2052h141v-2052h-141z" /> -<glyph unicode="}" horiz-adv-x="776" d="M72 -184q111 2 169 48t58 148v297q0 114 55 174t168 80v12q-223 39 -223 254v295q0 193 -227 199v139q184 0 289.5 -87t105.5 -240v-306q0 -97 59 -142.5t189 -47.5v-141q-122 0 -185 -44.5t-63 -148.5v-303q0 -153 -102.5 -238.5t-292.5 -87.5v140z" /> -<glyph unicode="~" d="M104 592v151q100 109 244 109q68 0 124.5 -14t145.5 -52q66 -28 115 -41.5t96 -13.5q54 0 118 32t118 89v-150q-102 -110 -244 -110q-72 0 -135 16.5t-135 48.5q-75 32 -120 44t-93 12q-53 0 -116.5 -33.5t-117.5 -87.5z" /> -<glyph unicode="¡" horiz-adv-x="547" d="M152 983q0 63 31.5 99t88.5 36q51 0 86 -32t35 -103q0 -135 -121 -135q-60 0 -90 35.5t-30 99.5zM168 -373l51 1057h105l51 -1057h-207z" /> -<glyph unicode="¢" d="M190 741q0 508 396 570v172h135v-164q75 -3 146 -19.5t120 -39.5l-49 -140q-133 51 -242 51q-172 0 -253 -105.5t-81 -322.5q0 -212 79.5 -313.5t246.5 -101.5q141 0 283 59v-147q-105 -54 -252 -60v-200h-133v206q-203 32 -299.5 168.5t-96.5 386.5z" /> -<glyph unicode="£" d="M63 0v141q205 47 205 291v223h-198v127h198v316q0 178 112 280.5t302 102.5t360 -84l-61 -133q-154 77 -297 77q-123 0 -185.5 -62t-62.5 -202v-295h422v-127h-422v-221q0 -100 -32.5 -168t-106.5 -112h795v-154h-1029z" /> -<glyph unicode="¤" d="M123 1092l94 92l135 -133q104 73 234 73q127 0 229 -73l137 133l95 -92l-134 -138q74 -113 74 -231q0 -131 -74 -234l131 -135l-92 -92l-137 133q-102 -71 -229 -71q-134 0 -234 73l-135 -133l-92 92l133 136q-74 107 -74 231q0 122 74 229zM313 723q0 -112 78.5 -192 t194.5 -80t195 79.5t79 192.5q0 114 -80 195t-194 81q-116 0 -194.5 -82t-78.5 -194z" /> -<glyph unicode="¥" d="M31 1462h178l375 -727l379 727h174l-416 -770h262v-127h-317v-170h317v-127h-317v-268h-164v268h-316v127h316v170h-316v127h256z" /> -<glyph unicode="¦" horiz-adv-x="1128" d="M494 281h141v-777h-141v777zM494 780v776h141v-776h-141z" /> -<glyph unicode="§" horiz-adv-x="1057" d="M123 57v148q78 -37 175 -59.5t179 -22.5q134 0 204.5 38t70.5 109q0 46 -24 75t-78 58t-169 72q-142 52 -209 97t-100 102t-33 135q0 86 43 154.5t121 105.5q-74 40 -116 95.5t-42 140.5q0 121 103.5 190.5t300.5 69.5q94 0 173.5 -14.5t176.5 -53.5l-53 -131 q-98 39 -165.5 52.5t-143.5 13.5q-116 0 -174 -29.5t-58 -93.5q0 -60 61.5 -102t215.5 -97q186 -68 261 -143.5t75 -182.5q0 -90 -41 -160.5t-115 -111.5q153 -81 153 -227q0 -140 -117 -216.5t-329 -76.5q-218 0 -346 65zM285 829q0 -77 66 -129.5t233 -113.5l49 -19 q137 80 137 191q0 83 -73.5 139t-258.5 113q-68 -19 -110.5 -69t-42.5 -112z" /> -<glyph unicode="¨" horiz-adv-x="1182" d="M309 1393q0 52 26.5 75t63.5 23q38 0 65.5 -23t27.5 -75q0 -50 -27.5 -74.5t-65.5 -24.5q-37 0 -63.5 24.5t-26.5 74.5zM690 1393q0 52 26.5 75t63.5 23t64.5 -23t27.5 -75q0 -50 -27.5 -74.5t-64.5 -24.5t-63.5 24.5t-26.5 74.5z" /> -<glyph unicode="©" horiz-adv-x="1704" d="M100 731q0 200 100 375t275 276t377 101q200 0 375 -100t276 -275t101 -377q0 -197 -97 -370t-272 -277t-383 -104q-207 0 -382 103.5t-272.5 276.5t-97.5 371zM205 731q0 -173 87 -323.5t237.5 -237t322.5 -86.5q174 0 323 87t236.5 235.5t87.5 324.5q0 174 -87 323 t-235.5 236.5t-324.5 87.5q-174 0 -323 -87t-236.5 -235.5t-87.5 -324.5zM481 731q0 209 110.5 332t301.5 123q128 0 246 -60l-58 -118q-108 51 -188 51q-125 0 -192.5 -87t-67.5 -241q0 -168 63.5 -249t194.5 -81q86 0 211 45v-124q-48 -20 -98.5 -34t-120.5 -14 q-194 0 -298 120.5t-104 336.5z" /> -<glyph unicode="ª" horiz-adv-x="725" d="M70 989q0 102 77 154.5t242 58.5l117 4v39q0 133 -148 133q-100 0 -204 -51l-43 96q114 56 247 56q130 0 198.5 -52.5t68.5 -173.5v-452h-93l-24 84q-92 -97 -232 -97q-95 0 -150.5 49.5t-55.5 151.5zM193 989q0 -100 112 -100q201 0 201 180v49l-98 -4 q-112 -4 -163.5 -32.5t-51.5 -92.5z" /> -<glyph unicode="«" horiz-adv-x="1018" d="M82 524v27l342 407l119 -69l-289 -350l289 -351l-119 -71zM477 524v27l344 407l117 -69l-287 -350l287 -351l-117 -71z" /> -<glyph unicode="¬" d="M104 653v138h961v-527h-137v389h-824z" /> -<glyph unicode="­" horiz-adv-x="659" d="M84 473v152h491v-152h-491z" /> -<glyph unicode="®" horiz-adv-x="1704" d="M100 731q0 200 100 375t275 276t377 101q200 0 375 -100t276 -275t101 -377q0 -197 -97 -370t-272 -277t-383 -104q-207 0 -382 103.5t-272.5 276.5t-97.5 371zM205 731q0 -173 87 -323.5t237.5 -237t322.5 -86.5q174 0 323 87t236.5 235.5t87.5 324.5q0 174 -87 323 t-235.5 236.5t-324.5 87.5q-174 0 -323 -87t-236.5 -235.5t-87.5 -324.5zM575 285v891h261q166 0 243.5 -65t77.5 -198q0 -80 -42.5 -141.5t-119.5 -91.5l238 -395h-168l-207 354h-135v-354h-148zM723 762h108q80 0 128.5 41.5t48.5 105.5q0 75 -43 107.5t-136 32.5h-106 v-287z" /> -<glyph unicode="¯" horiz-adv-x="1024" d="M-6 1556v127h1036v-127h-1036z" /> -<glyph unicode="°" horiz-adv-x="877" d="M127 1171q0 130 90.5 221t220.5 91t221 -90.5t91 -221.5q0 -84 -41 -155.5t-114 -113.5t-157 -42q-130 0 -220.5 90t-90.5 221zM242 1171q0 -82 58.5 -139t139.5 -57q80 0 137.5 56.5t57.5 139.5q0 84 -56.5 140.5t-138.5 56.5q-83 0 -140.5 -57t-57.5 -140z" /> -<glyph unicode="±" d="M104 653v138h410v428h139v-428h412v-138h-412v-426h-139v426h-410zM104 1v138h961v-138h-961z" /> -<glyph unicode="²" horiz-adv-x="711" d="M49 586v104l236 230q89 86 130 134.5t57.5 86.5t16.5 92q0 68 -40 102.5t-103 34.5q-52 0 -101 -19t-118 -69l-66 88q131 111 283 111q132 0 205.5 -65t73.5 -177q0 -80 -44.5 -155.5t-191.5 -213.5l-174 -165h440v-119h-604z" /> -<glyph unicode="³" horiz-adv-x="711" d="M33 625v123q147 -68 270 -68q211 0 211 162q0 145 -231 145h-117v107h119q103 0 152.5 39.5t49.5 107.5q0 61 -40 95t-107 34q-66 0 -122 -21.5t-112 -56.5l-69 90q63 45 133 72t164 27q136 0 214.5 -59.5t78.5 -166.5q0 -80 -41 -131.5t-109 -74.5q176 -47 176 -209 q0 -128 -92 -199.5t-260 -71.5q-152 0 -268 56z" /> -<glyph unicode="´" horiz-adv-x="1182" d="M393 1241v25q48 62 103.5 150t87.5 153h202v-21q-44 -65 -131 -160t-151 -147h-111z" /> -<glyph unicode="µ" horiz-adv-x="1268" d="M176 -492v1588h166v-715q0 -262 254 -262q171 0 250.5 94.5t79.5 306.5v576h166v-1096h-136l-26 147h-10q-111 -167 -340 -167q-150 0 -238 92h-10q10 -84 10 -244v-320h-166z" /> -<glyph unicode="¶" horiz-adv-x="1341" d="M113 1042q0 260 109 387t341 127h557v-1816h-114v1712h-213v-1712h-115v819q-62 -18 -146 -18q-216 0 -317.5 125t-101.5 376z" /> -<glyph unicode="·" horiz-adv-x="545" d="M152 723q0 66 31 100.5t87 34.5q58 0 90.5 -34.5t32.5 -100.5q0 -65 -33 -100t-90 -35q-51 0 -84.5 31.5t-33.5 103.5z" /> -<glyph unicode="¸" horiz-adv-x="465" d="M37 -377q45 -8 104 -8q79 0 119.5 20t40.5 74q0 43 -39.5 69.5t-148.5 43.5l88 178h110l-55 -115q180 -39 180 -174q0 -97 -76.5 -150t-226.5 -53q-51 0 -96 9v106z" /> -<glyph unicode="¹" horiz-adv-x="711" d="M76 1280l262 182h143v-876h-133v579q0 91 6 181q-22 -22 -49 -44.5t-162 -117.5z" /> -<glyph unicode="º" horiz-adv-x="768" d="M66 1135q0 163 84 253.5t235 90.5q152 0 234.5 -91t82.5 -253q0 -164 -85.5 -255.5t-235.5 -91.5q-146 0 -230.5 93t-84.5 254zM188 1135q0 -122 45.5 -183t149.5 -61q105 0 151 61t46 183q0 123 -46 182t-151 59q-103 0 -149 -59t-46 -182z" /> -<glyph unicode="»" horiz-adv-x="1018" d="M80 188l287 351l-287 350l117 69l344 -407v-27l-344 -407zM475 188l287 351l-287 350l117 69l344 -407v-27l-344 -407z" /> -<glyph unicode="¼" horiz-adv-x="1597" d="M252 0l903 1462h143l-903 -1462h-143zM75 1280l262 182h143v-876h-133v579q0 91 6 181q-22 -22 -49 -44.5t-162 -117.5zM817 203v101l408 579h139v-563h125v-117h-125v-202h-145v202h-402zM957 320h262v195q0 134 6 209q-5 -12 -17 -31.5t-27 -41.5l-30 -46 q-15 -22 -26 -39z" /> -<glyph unicode="½" horiz-adv-x="1597" d="M184 0l903 1462h143l-903 -1462h-143zM46 1280l262 182h143v-876h-133v579q0 91 6 181q-22 -22 -49 -44.5t-162 -117.5zM895 1v104l236 230q89 86 130 134.5t57.5 86.5t16.5 92q0 68 -40 102.5t-103 34.5q-52 0 -101 -19t-118 -69l-66 88q131 111 283 111 q132 0 205.5 -65t73.5 -177q0 -80 -44.5 -155.5t-191.5 -213.5l-174 -165h440v-119h-604z" /> -<glyph unicode="¾" horiz-adv-x="1597" d="M26 625v123q147 -68 270 -68q211 0 211 162q0 145 -231 145h-117v107h119q103 0 152.5 39.5t49.5 107.5q0 61 -40 95t-107 34q-66 0 -122 -21.5t-112 -56.5l-69 90q63 45 133 72t164 27q136 0 214.5 -59.5t78.5 -166.5q0 -80 -41 -131.5t-109 -74.5q176 -47 176 -209 q0 -128 -92 -199.5t-260 -71.5q-152 0 -268 56zM344 0l903 1462h143l-903 -1462h-143zM897 203v101l408 579h139v-563h125v-117h-125v-202h-145v202h-402zM1037 320h262v195q0 134 6 209q-5 -12 -17 -31.5t-27 -41.5l-30 -46q-15 -22 -26 -39z" /> -<glyph unicode="¿" horiz-adv-x="879" d="M51 -37q0 70 17.5 122.5t49.5 97t76.5 85.5t98.5 88q101 88 133.5 146t32.5 151v31h131v-51q0 -122 -37.5 -196t-134.5 -158q-121 -106 -151.5 -143.5t-43 -76t-12.5 -94.5q0 -100 66 -156.5t188 -56.5q80 0 155 19t173 67l59 -135q-197 -96 -395 -96q-190 0 -298 93 t-108 263zM397 983q0 64 33 99.5t88 35.5q51 0 86 -32t35 -103q0 -135 -121 -135q-59 0 -90 34.5t-31 100.5z" /> -<glyph unicode="À" horiz-adv-x="1296" d="M0 0l578 1468h143l575 -1468h-176l-182 465h-586l-180 -465h-172zM412 618h473l-170 453q-33 86 -68 211q-22 -96 -63 -211zM331 1886v21h203q32 -69 89 -159.5t101 -143.5v-25h-110q-65 52 -154 148t-129 159z" /> -<glyph unicode="Á" horiz-adv-x="1296" d="M0 0l578 1468h143l575 -1468h-176l-182 465h-586l-180 -465h-172zM412 618h473l-170 453q-33 86 -68 211q-22 -96 -63 -211zM526 1579v25q48 62 103.5 150t87.5 153h202v-21q-44 -65 -131 -160t-151 -147h-111z" /> -<glyph unicode="Â" horiz-adv-x="1296" d="M0 0l578 1468h143l575 -1468h-176l-182 465h-586l-180 -465h-172zM412 618h473l-170 453q-33 86 -68 211q-22 -96 -63 -211zM303 1579v23q127 136 178 200t74 105h166q22 -42 76.5 -108.5t179.5 -196.5v-23h-119q-88 55 -221 186q-136 -134 -219 -186h-115z" /> -<glyph unicode="Ã" horiz-adv-x="1296" d="M0 0l578 1468h143l575 -1468h-176l-182 465h-586l-180 -465h-172zM412 618h473l-170 453q-33 86 -68 211q-22 -96 -63 -211zM268 1579q13 121 70.5 189.5t148.5 68.5q46 0 89 -18.5t82 -41t75 -41t68 -18.5q49 0 73 29.5t39 91.5h99q-13 -121 -69.5 -189.5t-150.5 -68.5 q-43 0 -84 18.5t-80.5 41t-76 41t-70.5 18.5q-50 0 -75.5 -30t-39.5 -91h-98z" /> -<glyph unicode="Ä" horiz-adv-x="1296" d="M0 0l578 1468h143l575 -1468h-176l-182 465h-586l-180 -465h-172zM412 618h473l-170 453q-33 86 -68 211q-22 -96 -63 -211zM364 1731q0 52 26.5 75t63.5 23q38 0 65.5 -23t27.5 -75q0 -50 -27.5 -74.5t-65.5 -24.5q-37 0 -63.5 24.5t-26.5 74.5zM745 1731q0 52 26.5 75 t63.5 23t64.5 -23t27.5 -75q0 -50 -27.5 -74.5t-64.5 -24.5t-63.5 24.5t-26.5 74.5z" /> -<glyph unicode="Å" horiz-adv-x="1296" d="M0 0l578 1468h143l575 -1468h-176l-182 465h-586l-180 -465h-172zM412 618h473l-170 453q-33 86 -68 211q-22 -96 -63 -211zM424 1585q0 98 60.5 155.5t160.5 57.5q101 0 163 -59.5t62 -151.5q0 -98 -61.5 -157.5t-163.5 -59.5q-101 0 -161 58.5t-60 156.5zM528 1585 q0 -56 30 -86.5t87 -30.5q52 0 84.5 30.5t32.5 86.5t-33 86.5t-84 30.5t-84 -30.5t-33 -86.5z" /> -<glyph unicode="Æ" horiz-adv-x="1788" d="M-2 0l698 1462h969v-151h-580v-471h541v-150h-541v-538h580v-152h-750v465h-514l-227 -465h-176zM469 618h446v693h-118z" /> -<glyph unicode="Ç" horiz-adv-x="1292" d="M125 733q0 226 84.5 396t244 262t375.5 92q230 0 402 -84l-72 -146q-166 78 -332 78q-241 0 -380.5 -160.5t-139.5 -439.5q0 -287 134.5 -443.5t383.5 -156.5q153 0 349 55v-149q-152 -57 -375 -57q-323 0 -498.5 196t-175.5 557zM551 -377q45 -8 104 -8q79 0 119.5 20 t40.5 74q0 43 -39.5 69.5t-148.5 43.5l88 178h110l-55 -115q180 -39 180 -174q0 -97 -76.5 -150t-226.5 -53q-51 0 -96 9v106z" /> -<glyph unicode="È" horiz-adv-x="1139" d="M201 0v1462h815v-151h-645v-471h606v-150h-606v-538h645v-152h-815zM320 1886v21h203q32 -69 89 -159.5t101 -143.5v-25h-110q-65 52 -154 148t-129 159z" /> -<glyph unicode="É" horiz-adv-x="1139" d="M201 0v1462h815v-151h-645v-471h606v-150h-606v-538h645v-152h-815zM456 1579v25q48 62 103.5 150t87.5 153h202v-21q-44 -65 -131 -160t-151 -147h-111z" /> -<glyph unicode="Ê" horiz-adv-x="1139" d="M201 0v1462h815v-151h-645v-471h606v-150h-606v-538h645v-152h-815zM263 1579v23q127 136 178 200t74 105h166q22 -42 76.5 -108.5t179.5 -196.5v-23h-119q-88 55 -221 186q-136 -134 -219 -186h-115z" /> -<glyph unicode="Ë" horiz-adv-x="1139" d="M201 0v1462h815v-151h-645v-471h606v-150h-606v-538h645v-152h-815zM327 1731q0 52 26.5 75t63.5 23q38 0 65.5 -23t27.5 -75q0 -50 -27.5 -74.5t-65.5 -24.5q-37 0 -63.5 24.5t-26.5 74.5zM708 1731q0 52 26.5 75t63.5 23t64.5 -23t27.5 -75q0 -50 -27.5 -74.5 t-64.5 -24.5t-63.5 24.5t-26.5 74.5z" /> -<glyph unicode="Ì" horiz-adv-x="571" d="M201 0v1462h170v-1462h-170zM5 1886v21h203q32 -69 89 -159.5t101 -143.5v-25h-110q-65 52 -154 148t-129 159z" /> -<glyph unicode="Í" horiz-adv-x="571" d="M201 0v1462h170v-1462h-170zM179 1579v25q48 62 103.5 150t87.5 153h202v-21q-44 -65 -131 -160t-151 -147h-111z" /> -<glyph unicode="Î" horiz-adv-x="571" d="M201 0v1462h170v-1462h-170zM-57 1579v23q127 136 178 200t74 105h166q22 -42 76.5 -108.5t179.5 -196.5v-23h-119q-88 55 -221 186q-136 -134 -219 -186h-115z" /> -<glyph unicode="Ï" horiz-adv-x="571" d="M201 0v1462h170v-1462h-170zM5 1731q0 52 26.5 75t63.5 23q38 0 65.5 -23t27.5 -75q0 -50 -27.5 -74.5t-65.5 -24.5q-37 0 -63.5 24.5t-26.5 74.5zM386 1731q0 52 26.5 75t63.5 23t64.5 -23t27.5 -75q0 -50 -27.5 -74.5t-64.5 -24.5t-63.5 24.5t-26.5 74.5z" /> -<glyph unicode="Ð" horiz-adv-x="1479" d="M47 649v150h154v663h434q337 0 527 -187.5t190 -529.5q0 -362 -196.5 -553.5t-565.5 -191.5h-389v649h-154zM371 147h190q610 0 610 592q0 576 -569 576h-231v-516h379v-150h-379v-502z" /> -<glyph unicode="Ñ" horiz-adv-x="1544" d="M201 0v1462h192l797 -1222h8q-2 28 -9 174q-5 114 -5 177v32v839h159v-1462h-194l-799 1227h-8q16 -216 16 -396v-831h-157zM411 1579q13 121 70.5 189.5t148.5 68.5q46 0 89 -18.5t82 -41t75 -41t68 -18.5q49 0 73 29.5t39 91.5h99q-13 -121 -69.5 -189.5t-150.5 -68.5 q-43 0 -84 18.5t-80.5 41t-76 41t-70.5 18.5q-50 0 -75.5 -30t-39.5 -91h-98z" /> -<glyph unicode="Ò" horiz-adv-x="1595" d="M125 735q0 357 176 553.5t500 196.5q315 0 492 -200t177 -552q0 -351 -177.5 -552t-493.5 -201q-323 0 -498.5 197.5t-175.5 557.5zM305 733q0 -297 126.5 -450.5t367.5 -153.5q243 0 367 153t124 451q0 295 -123.5 447.5t-365.5 152.5q-243 0 -369.5 -153.5 t-126.5 -446.5zM514 1886v21h203q32 -69 89 -159.5t101 -143.5v-25h-110q-65 52 -154 148t-129 159z" /> -<glyph unicode="Ó" horiz-adv-x="1595" d="M125 735q0 357 176 553.5t500 196.5q315 0 492 -200t177 -552q0 -351 -177.5 -552t-493.5 -201q-323 0 -498.5 197.5t-175.5 557.5zM305 733q0 -297 126.5 -450.5t367.5 -153.5q243 0 367 153t124 451q0 295 -123.5 447.5t-365.5 152.5q-243 0 -369.5 -153.5 t-126.5 -446.5zM659 1579v25q48 62 103.5 150t87.5 153h202v-21q-44 -65 -131 -160t-151 -147h-111z" /> -<glyph unicode="Ô" horiz-adv-x="1595" d="M125 735q0 357 176 553.5t500 196.5q315 0 492 -200t177 -552q0 -351 -177.5 -552t-493.5 -201q-323 0 -498.5 197.5t-175.5 557.5zM305 733q0 -297 126.5 -450.5t367.5 -153.5q243 0 367 153t124 451q0 295 -123.5 447.5t-365.5 152.5q-243 0 -369.5 -153.5 t-126.5 -446.5zM448 1579v23q127 136 178 200t74 105h166q22 -42 76.5 -108.5t179.5 -196.5v-23h-119q-88 55 -221 186q-136 -134 -219 -186h-115z" /> -<glyph unicode="Õ" horiz-adv-x="1595" d="M125 735q0 357 176 553.5t500 196.5q315 0 492 -200t177 -552q0 -351 -177.5 -552t-493.5 -201q-323 0 -498.5 197.5t-175.5 557.5zM305 733q0 -297 126.5 -450.5t367.5 -153.5q243 0 367 153t124 451q0 295 -123.5 447.5t-365.5 152.5q-243 0 -369.5 -153.5 t-126.5 -446.5zM418 1579q13 121 70.5 189.5t148.5 68.5q46 0 89 -18.5t82 -41t75 -41t68 -18.5q49 0 73 29.5t39 91.5h99q-13 -121 -69.5 -189.5t-150.5 -68.5q-43 0 -84 18.5t-80.5 41t-76 41t-70.5 18.5q-50 0 -75.5 -30t-39.5 -91h-98z" /> -<glyph unicode="Ö" horiz-adv-x="1595" d="M125 735q0 357 176 553.5t500 196.5q315 0 492 -200t177 -552q0 -351 -177.5 -552t-493.5 -201q-323 0 -498.5 197.5t-175.5 557.5zM305 733q0 -297 126.5 -450.5t367.5 -153.5q243 0 367 153t124 451q0 295 -123.5 447.5t-365.5 152.5q-243 0 -369.5 -153.5 t-126.5 -446.5zM522 1731q0 52 26.5 75t63.5 23q38 0 65.5 -23t27.5 -75q0 -50 -27.5 -74.5t-65.5 -24.5q-37 0 -63.5 24.5t-26.5 74.5zM903 1731q0 52 26.5 75t63.5 23t64.5 -23t27.5 -75q0 -50 -27.5 -74.5t-64.5 -24.5t-63.5 24.5t-26.5 74.5z" /> -<glyph unicode="×" d="M133 1075l100 101l353 -355l354 355l96 -99l-352 -354l350 -352l-96 -99l-354 351l-348 -351l-101 99l350 352z" /> -<glyph unicode="Ø" horiz-adv-x="1595" d="M125 735q0 357 176 553.5t500 196.5q209 0 366 -94l97 135l120 -80l-106 -148q192 -202 192 -565q0 -351 -177.5 -552t-493.5 -201q-235 0 -383 100l-101 -141l-120 79l108 154q-178 198 -178 563zM305 733q0 -262 101 -416l669 943q-106 73 -274 73 q-243 0 -369.5 -153.5t-126.5 -446.5zM508 211q115 -82 291 -82q243 0 367 153t124 451q0 272 -110 426z" /> -<glyph unicode="Ù" horiz-adv-x="1491" d="M186 520v942h170v-954q0 -183 100 -281t294 -98q185 0 285 98.5t100 282.5v952h170v-946q0 -250 -151 -393t-415 -143t-408.5 144t-144.5 396zM463 1886v21h203q32 -69 89 -159.5t101 -143.5v-25h-110q-65 52 -154 148t-129 159z" /> -<glyph unicode="Ú" horiz-adv-x="1491" d="M186 520v942h170v-954q0 -183 100 -281t294 -98q185 0 285 98.5t100 282.5v952h170v-946q0 -250 -151 -393t-415 -143t-408.5 144t-144.5 396zM600 1579v25q48 62 103.5 150t87.5 153h202v-21q-44 -65 -131 -160t-151 -147h-111z" /> -<glyph unicode="Û" horiz-adv-x="1491" d="M186 520v942h170v-954q0 -183 100 -281t294 -98q185 0 285 98.5t100 282.5v952h170v-946q0 -250 -151 -393t-415 -143t-408.5 144t-144.5 396zM393 1579v23q127 136 178 200t74 105h166q22 -42 76.5 -108.5t179.5 -196.5v-23h-119q-88 55 -221 186q-136 -134 -219 -186 h-115z" /> -<glyph unicode="Ü" horiz-adv-x="1491" d="M186 520v942h170v-954q0 -183 100 -281t294 -98q185 0 285 98.5t100 282.5v952h170v-946q0 -250 -151 -393t-415 -143t-408.5 144t-144.5 396zM461 1731q0 52 26.5 75t63.5 23q38 0 65.5 -23t27.5 -75q0 -50 -27.5 -74.5t-65.5 -24.5q-37 0 -63.5 24.5t-26.5 74.5z M842 1731q0 52 26.5 75t63.5 23t64.5 -23t27.5 -75q0 -50 -27.5 -74.5t-64.5 -24.5t-63.5 24.5t-26.5 74.5z" /> -<glyph unicode="Ý" horiz-adv-x="1147" d="M0 1462h186l387 -731l390 731h184l-488 -895v-567h-172v559zM442 1579v25q48 62 103.5 150t87.5 153h202v-21q-44 -65 -131 -160t-151 -147h-111z" /> -<glyph unicode="Þ" horiz-adv-x="1251" d="M201 0v1462h170v-256h215q281 0 420 -103.5t139 -318.5q0 -227 -151.5 -346t-438.5 -119h-184v-319h-170zM371 465h168q226 0 327 71.5t101 235.5q0 149 -95 218t-297 69h-204v-594z" /> -<glyph unicode="ß" horiz-adv-x="1274" d="M176 0v1202q0 178 110 271.5t332 93.5q206 0 318.5 -78.5t112.5 -222.5q0 -135 -143 -250q-88 -70 -116 -103.5t-28 -66.5q0 -32 13.5 -53t49 -49.5t113.5 -79.5q140 -95 191 -173.5t51 -179.5q0 -160 -97 -245.5t-276 -85.5q-188 0 -295 69v154q63 -39 141 -62.5 t150 -23.5q215 0 215 182q0 75 -41.5 128.5t-151.5 123.5q-127 82 -175 143.5t-48 145.5q0 63 34.5 116t105.5 106q75 57 107 102t32 98q0 80 -68 122.5t-195 42.5q-276 0 -276 -223v-1204h-166z" /> -<glyph unicode="à" horiz-adv-x="1139" d="M94 303q0 332 531 348l186 6v68q0 129 -55.5 190.5t-177.5 61.5q-137 0 -310 -84l-51 127q81 44 177.5 69t193.5 25q196 0 290.5 -87t94.5 -279v-748h-123l-33 156h-8q-82 -103 -163.5 -139.5t-203.5 -36.5q-163 0 -255.5 84t-92.5 239zM268 301q0 -90 54.5 -137 t152.5 -47q155 0 243.5 85t88.5 238v99l-166 -7q-198 -7 -285.5 -61.5t-87.5 -169.5zM279 1548v21h203q32 -69 89 -159.5t101 -143.5v-25h-110q-65 52 -154 148t-129 159z" /> -<glyph unicode="á" horiz-adv-x="1139" d="M94 303q0 332 531 348l186 6v68q0 129 -55.5 190.5t-177.5 61.5q-137 0 -310 -84l-51 127q81 44 177.5 69t193.5 25q196 0 290.5 -87t94.5 -279v-748h-123l-33 156h-8q-82 -103 -163.5 -139.5t-203.5 -36.5q-163 0 -255.5 84t-92.5 239zM268 301q0 -90 54.5 -137 t152.5 -47q155 0 243.5 85t88.5 238v99l-166 -7q-198 -7 -285.5 -61.5t-87.5 -169.5zM436 1241v25q48 62 103.5 150t87.5 153h202v-21q-44 -65 -131 -160t-151 -147h-111z" /> -<glyph unicode="â" horiz-adv-x="1139" d="M94 303q0 332 531 348l186 6v68q0 129 -55.5 190.5t-177.5 61.5q-137 0 -310 -84l-51 127q81 44 177.5 69t193.5 25q196 0 290.5 -87t94.5 -279v-748h-123l-33 156h-8q-82 -103 -163.5 -139.5t-203.5 -36.5q-163 0 -255.5 84t-92.5 239zM268 301q0 -90 54.5 -137 t152.5 -47q155 0 243.5 85t88.5 238v99l-166 -7q-198 -7 -285.5 -61.5t-87.5 -169.5zM228 1241v23q127 136 178 200t74 105h166q22 -42 76.5 -108.5t179.5 -196.5v-23h-119q-88 55 -221 186q-136 -134 -219 -186h-115z" /> -<glyph unicode="ã" horiz-adv-x="1139" d="M94 303q0 332 531 348l186 6v68q0 129 -55.5 190.5t-177.5 61.5q-137 0 -310 -84l-51 127q81 44 177.5 69t193.5 25q196 0 290.5 -87t94.5 -279v-748h-123l-33 156h-8q-82 -103 -163.5 -139.5t-203.5 -36.5q-163 0 -255.5 84t-92.5 239zM268 301q0 -90 54.5 -137 t152.5 -47q155 0 243.5 85t88.5 238v99l-166 -7q-198 -7 -285.5 -61.5t-87.5 -169.5zM197 1241q13 121 70.5 189.5t148.5 68.5q46 0 89 -18.5t82 -41t75 -41t68 -18.5q49 0 73 29.5t39 91.5h99q-13 -121 -69.5 -189.5t-150.5 -68.5q-43 0 -84 18.5t-80.5 41t-76 41 t-70.5 18.5q-50 0 -75.5 -30t-39.5 -91h-98z" /> -<glyph unicode="ä" horiz-adv-x="1139" d="M94 303q0 332 531 348l186 6v68q0 129 -55.5 190.5t-177.5 61.5q-137 0 -310 -84l-51 127q81 44 177.5 69t193.5 25q196 0 290.5 -87t94.5 -279v-748h-123l-33 156h-8q-82 -103 -163.5 -139.5t-203.5 -36.5q-163 0 -255.5 84t-92.5 239zM268 301q0 -90 54.5 -137 t152.5 -47q155 0 243.5 85t88.5 238v99l-166 -7q-198 -7 -285.5 -61.5t-87.5 -169.5zM279 1393q0 52 26.5 75t63.5 23q38 0 65.5 -23t27.5 -75q0 -50 -27.5 -74.5t-65.5 -24.5q-37 0 -63.5 24.5t-26.5 74.5zM660 1393q0 52 26.5 75t63.5 23t64.5 -23t27.5 -75 q0 -50 -27.5 -74.5t-64.5 -24.5t-63.5 24.5t-26.5 74.5z" /> -<glyph unicode="å" horiz-adv-x="1139" d="M94 303q0 332 531 348l186 6v68q0 129 -55.5 190.5t-177.5 61.5q-137 0 -310 -84l-51 127q81 44 177.5 69t193.5 25q196 0 290.5 -87t94.5 -279v-748h-123l-33 156h-8q-82 -103 -163.5 -139.5t-203.5 -36.5q-163 0 -255.5 84t-92.5 239zM268 301q0 -90 54.5 -137 t152.5 -47q155 0 243.5 85t88.5 238v99l-166 -7q-198 -7 -285.5 -61.5t-87.5 -169.5zM358 1456q0 98 60.5 155.5t160.5 57.5q101 0 163 -59.5t62 -151.5q0 -98 -61.5 -157.5t-163.5 -59.5q-101 0 -161 58.5t-60 156.5zM462 1456q0 -56 30 -86.5t87 -30.5q52 0 84.5 30.5 t32.5 86.5t-33 86.5t-84 30.5t-84 -30.5t-33 -86.5z" /> -<glyph unicode="æ" horiz-adv-x="1757" d="M94 303q0 161 124 250.5t378 97.5l184 6v68q0 129 -58 190.5t-177 61.5q-144 0 -307 -84l-52 127q74 41 173.5 67.5t197.5 26.5q130 0 212.5 -43.5t123.5 -138.5q53 88 138.5 136t195.5 48q192 0 308 -133.5t116 -355.5v-107h-701q8 -395 322 -395q91 0 169.5 17.5 t162.5 56.5v-148q-86 -38 -160.5 -54.5t-175.5 -16.5q-289 0 -414 233q-81 -127 -179.5 -180t-232.5 -53q-163 0 -255.5 85t-92.5 238zM268 301q0 -95 53.5 -139.5t141.5 -44.5q145 0 229 84.5t84 238.5v99l-158 -7q-186 -8 -268 -62.5t-82 -168.5zM954 653h519 q0 156 -64 240t-184 84q-121 0 -190.5 -83t-80.5 -241z" /> -<glyph unicode="ç" horiz-adv-x="975" d="M115 541q0 275 132.5 425t377.5 150q79 0 158 -17t124 -40l-51 -141q-55 22 -120 36.5t-115 14.5q-334 0 -334 -426q0 -202 81.5 -310t241.5 -108q137 0 281 59v-147q-110 -57 -277 -57q-238 0 -368.5 146.5t-130.5 414.5zM363 -377q45 -8 104 -8q79 0 119.5 20t40.5 74 q0 43 -39.5 69.5t-148.5 43.5l88 178h110l-55 -115q180 -39 180 -174q0 -97 -76.5 -150t-226.5 -53q-51 0 -96 9v106z" /> -<glyph unicode="è" horiz-adv-x="1149" d="M115 539q0 265 130.5 421t350.5 156q206 0 326 -135.5t120 -357.5v-105h-755q5 -193 97.5 -293t260.5 -100q177 0 350 74v-148q-88 -38 -166.5 -54.5t-189.5 -16.5q-243 0 -383.5 148t-140.5 411zM291 653h573q0 157 -70 240.5t-200 83.5q-132 0 -210.5 -86t-92.5 -238z M318 1548v21h203q32 -69 89 -159.5t101 -143.5v-25h-110q-65 52 -154 148t-129 159z" /> -<glyph unicode="é" horiz-adv-x="1149" d="M115 539q0 265 130.5 421t350.5 156q206 0 326 -135.5t120 -357.5v-105h-755q5 -193 97.5 -293t260.5 -100q177 0 350 74v-148q-88 -38 -166.5 -54.5t-189.5 -16.5q-243 0 -383.5 148t-140.5 411zM291 653h573q0 157 -70 240.5t-200 83.5q-132 0 -210.5 -86t-92.5 -238z M471 1241v25q48 62 103.5 150t87.5 153h202v-21q-44 -65 -131 -160t-151 -147h-111z" /> -<glyph unicode="ê" horiz-adv-x="1149" d="M115 539q0 265 130.5 421t350.5 156q206 0 326 -135.5t120 -357.5v-105h-755q5 -193 97.5 -293t260.5 -100q177 0 350 74v-148q-88 -38 -166.5 -54.5t-189.5 -16.5q-243 0 -383.5 148t-140.5 411zM291 653h573q0 157 -70 240.5t-200 83.5q-132 0 -210.5 -86t-92.5 -238z M259 1241v23q127 136 178 200t74 105h166q22 -42 76.5 -108.5t179.5 -196.5v-23h-119q-88 55 -221 186q-136 -134 -219 -186h-115z" /> -<glyph unicode="ë" horiz-adv-x="1149" d="M115 539q0 265 130.5 421t350.5 156q206 0 326 -135.5t120 -357.5v-105h-755q5 -193 97.5 -293t260.5 -100q177 0 350 74v-148q-88 -38 -166.5 -54.5t-189.5 -16.5q-243 0 -383.5 148t-140.5 411zM291 653h573q0 157 -70 240.5t-200 83.5q-132 0 -210.5 -86t-92.5 -238z M319 1393q0 52 26.5 75t63.5 23q38 0 65.5 -23t27.5 -75q0 -50 -27.5 -74.5t-65.5 -24.5q-37 0 -63.5 24.5t-26.5 74.5zM700 1393q0 52 26.5 75t63.5 23t64.5 -23t27.5 -75q0 -50 -27.5 -74.5t-64.5 -24.5t-63.5 24.5t-26.5 74.5z" /> -<glyph unicode="ì" horiz-adv-x="518" d="M176 0v1096h166v-1096h-166zM-38 1548v21h203q32 -69 89 -159.5t101 -143.5v-25h-110q-65 52 -154 148t-129 159z" /> -<glyph unicode="í" horiz-adv-x="518" d="M176 0v1096h166v-1096h-166zM169 1241v25q48 62 103.5 150t87.5 153h202v-21q-44 -65 -131 -160t-151 -147h-111z" /> -<glyph unicode="î" horiz-adv-x="518" d="M176 0v1096h166v-1096h-166zM-77 1241v23q127 136 178 200t74 105h166q22 -42 76.5 -108.5t179.5 -196.5v-23h-119q-88 55 -221 186q-136 -134 -219 -186h-115z" /> -<glyph unicode="ï" horiz-adv-x="518" d="M176 0v1096h166v-1096h-166zM-20 1393q0 52 26.5 75t63.5 23q38 0 65.5 -23t27.5 -75q0 -50 -27.5 -74.5t-65.5 -24.5q-37 0 -63.5 24.5t-26.5 74.5zM361 1393q0 52 26.5 75t63.5 23t64.5 -23t27.5 -75q0 -50 -27.5 -74.5t-64.5 -24.5t-63.5 24.5t-26.5 74.5z" /> -<glyph unicode="ð" horiz-adv-x="1221" d="M113 475q0 230 131.5 361t351.5 131q226 0 326 -121l8 4q-57 214 -262 405l-271 -155l-73 108l233 133q-92 62 -186 111l69 117q156 -73 258 -148l238 138l76 -107l-207 -119q152 -143 234.5 -342t82.5 -428q0 -281 -130.5 -432t-377.5 -151q-222 0 -361.5 134.5 t-139.5 360.5zM281 469q0 -167 87.5 -258.5t249.5 -91.5q175 0 255.5 100.5t80.5 292.5q0 147 -90 232t-246 85q-337 0 -337 -360z" /> -<glyph unicode="ñ" horiz-adv-x="1257" d="M176 0v1096h135l27 -150h8q51 81 143 125.5t205 44.5q198 0 298 -95.5t100 -305.5v-715h-166v709q0 134 -61 200t-191 66q-172 0 -252 -93t-80 -307v-575h-166zM278 1241q13 121 70.5 189.5t148.5 68.5q46 0 89 -18.5t82 -41t75 -41t68 -18.5q49 0 73 29.5t39 91.5h99 q-13 -121 -69.5 -189.5t-150.5 -68.5q-43 0 -84 18.5t-80.5 41t-76 41t-70.5 18.5q-50 0 -75.5 -30t-39.5 -91h-98z" /> -<glyph unicode="ò" horiz-adv-x="1237" d="M115 549q0 268 134 417.5t372 149.5q230 0 365.5 -153t135.5 -414q0 -268 -135 -418.5t-373 -150.5q-147 0 -261 69t-176 198t-62 302zM287 549q0 -210 84 -320t247 -110t247.5 109.5t84.5 320.5q0 209 -84.5 317.5t-249.5 108.5q-163 0 -246 -107t-83 -319zM349 1548v21 h203q32 -69 89 -159.5t101 -143.5v-25h-110q-65 52 -154 148t-129 159z" /> -<glyph unicode="ó" horiz-adv-x="1237" d="M115 549q0 268 134 417.5t372 149.5q230 0 365.5 -153t135.5 -414q0 -268 -135 -418.5t-373 -150.5q-147 0 -261 69t-176 198t-62 302zM287 549q0 -210 84 -320t247 -110t247.5 109.5t84.5 320.5q0 209 -84.5 317.5t-249.5 108.5q-163 0 -246 -107t-83 -319zM479 1241v25 q48 62 103.5 150t87.5 153h202v-21q-44 -65 -131 -160t-151 -147h-111z" /> -<glyph unicode="ô" horiz-adv-x="1237" d="M115 549q0 268 134 417.5t372 149.5q230 0 365.5 -153t135.5 -414q0 -268 -135 -418.5t-373 -150.5q-147 0 -261 69t-176 198t-62 302zM287 549q0 -210 84 -320t247 -110t247.5 109.5t84.5 320.5q0 209 -84.5 317.5t-249.5 108.5q-163 0 -246 -107t-83 -319zM282 1241v23 q127 136 178 200t74 105h166q22 -42 76.5 -108.5t179.5 -196.5v-23h-119q-88 55 -221 186q-136 -134 -219 -186h-115z" /> -<glyph unicode="õ" horiz-adv-x="1237" d="M115 549q0 268 134 417.5t372 149.5q230 0 365.5 -153t135.5 -414q0 -268 -135 -418.5t-373 -150.5q-147 0 -261 69t-176 198t-62 302zM287 549q0 -210 84 -320t247 -110t247.5 109.5t84.5 320.5q0 209 -84.5 317.5t-249.5 108.5q-163 0 -246 -107t-83 -319zM249 1241 q13 121 70.5 189.5t148.5 68.5q46 0 89 -18.5t82 -41t75 -41t68 -18.5q49 0 73 29.5t39 91.5h99q-13 -121 -69.5 -189.5t-150.5 -68.5q-43 0 -84 18.5t-80.5 41t-76 41t-70.5 18.5q-50 0 -75.5 -30t-39.5 -91h-98z" /> -<glyph unicode="ö" horiz-adv-x="1237" d="M115 549q0 268 134 417.5t372 149.5q230 0 365.5 -153t135.5 -414q0 -268 -135 -418.5t-373 -150.5q-147 0 -261 69t-176 198t-62 302zM287 549q0 -210 84 -320t247 -110t247.5 109.5t84.5 320.5q0 209 -84.5 317.5t-249.5 108.5q-163 0 -246 -107t-83 -319zM336 1393 q0 52 26.5 75t63.5 23q38 0 65.5 -23t27.5 -75q0 -50 -27.5 -74.5t-65.5 -24.5q-37 0 -63.5 24.5t-26.5 74.5zM717 1393q0 52 26.5 75t63.5 23t64.5 -23t27.5 -75q0 -50 -27.5 -74.5t-64.5 -24.5t-63.5 24.5t-26.5 74.5z" /> -<glyph unicode="÷" d="M104 653v138h961v-138h-961zM471 373q0 60 29.5 90.5t83.5 30.5q52 0 81 -31.5t29 -89.5q0 -57 -29.5 -89t-80.5 -32q-52 0 -82.5 31.5t-30.5 89.5zM471 1071q0 60 29.5 90.5t83.5 30.5q52 0 81 -31.5t29 -89.5q0 -57 -29.5 -89t-80.5 -32q-52 0 -82.5 31.5t-30.5 89.5z " /> -<glyph unicode="ø" horiz-adv-x="1237" d="M115 549q0 268 134 417.5t372 149.5q154 0 270 -76l84 119l117 -76l-97 -133q127 -152 127 -401q0 -268 -135 -418.5t-373 -150.5q-154 0 -266 69l-84 -117l-114 78l94 131q-129 152 -129 408zM287 549q0 -171 53 -273l465 646q-75 53 -189 53q-163 0 -246 -107t-83 -319 zM434 170q71 -51 184 -51q163 0 247.5 109.5t84.5 320.5q0 164 -51 264z" /> -<glyph unicode="ù" horiz-adv-x="1257" d="M164 379v717h168v-711q0 -134 61 -200t191 -66q172 0 251.5 94t79.5 307v576h166v-1096h-137l-24 147h-9q-51 -81 -141.5 -124t-206.5 -43q-200 0 -299.5 95t-99.5 304zM333 1548v21h203q32 -69 89 -159.5t101 -143.5v-25h-110q-65 52 -154 148t-129 159z" /> -<glyph unicode="ú" horiz-adv-x="1257" d="M164 379v717h168v-711q0 -134 61 -200t191 -66q172 0 251.5 94t79.5 307v576h166v-1096h-137l-24 147h-9q-51 -81 -141.5 -124t-206.5 -43q-200 0 -299.5 95t-99.5 304zM506 1241v25q48 62 103.5 150t87.5 153h202v-21q-44 -65 -131 -160t-151 -147h-111z" /> -<glyph unicode="û" horiz-adv-x="1257" d="M164 379v717h168v-711q0 -134 61 -200t191 -66q172 0 251.5 94t79.5 307v576h166v-1096h-137l-24 147h-9q-51 -81 -141.5 -124t-206.5 -43q-200 0 -299.5 95t-99.5 304zM286 1241v23q127 136 178 200t74 105h166q22 -42 76.5 -108.5t179.5 -196.5v-23h-119 q-88 55 -221 186q-136 -134 -219 -186h-115z" /> -<glyph unicode="ü" horiz-adv-x="1257" d="M164 379v717h168v-711q0 -134 61 -200t191 -66q172 0 251.5 94t79.5 307v576h166v-1096h-137l-24 147h-9q-51 -81 -141.5 -124t-206.5 -43q-200 0 -299.5 95t-99.5 304zM342 1393q0 52 26.5 75t63.5 23q38 0 65.5 -23t27.5 -75q0 -50 -27.5 -74.5t-65.5 -24.5 q-37 0 -63.5 24.5t-26.5 74.5zM723 1393q0 52 26.5 75t63.5 23t64.5 -23t27.5 -75q0 -50 -27.5 -74.5t-64.5 -24.5t-63.5 24.5t-26.5 74.5z" /> -<glyph unicode="ý" horiz-adv-x="1032" d="M2 1096h178l240 -625q79 -214 98 -309h8q13 51 54.5 174.5t271.5 759.5h178l-471 -1248q-70 -185 -163.5 -262.5t-229.5 -77.5q-76 0 -150 17v133q55 -12 123 -12q171 0 244 192l61 156zM411 1241v25q48 62 103.5 150t87.5 153h202v-21q-44 -65 -131 -160t-151 -147h-111 z" /> -<glyph unicode="þ" horiz-adv-x="1255" d="M176 -492v2048h166v-466q0 -52 -6 -142h8q66 89 151 128.5t191 39.5q215 0 335 -150t120 -417q0 -268 -120.5 -418.5t-334.5 -150.5q-222 0 -344 161h-12l4 -34q8 -77 8 -140v-459h-166zM342 549q0 -231 77 -330.5t247 -99.5q303 0 303 432q0 215 -74 319.5t-231 104.5 q-168 0 -244 -92t-78 -293v-41z" /> -<glyph unicode="ÿ" horiz-adv-x="1032" d="M2 1096h178l240 -625q79 -214 98 -309h8q13 51 54.5 174.5t271.5 759.5h178l-471 -1248q-70 -185 -163.5 -262.5t-229.5 -77.5q-76 0 -150 17v133q55 -12 123 -12q171 0 244 192l61 156zM234 1393q0 52 26.5 75t63.5 23q38 0 65.5 -23t27.5 -75q0 -50 -27.5 -74.5 t-65.5 -24.5q-37 0 -63.5 24.5t-26.5 74.5zM615 1393q0 52 26.5 75t63.5 23t64.5 -23t27.5 -75q0 -50 -27.5 -74.5t-64.5 -24.5t-63.5 24.5t-26.5 74.5z" /> -<glyph unicode="ı" horiz-adv-x="518" d="M176 0v1096h166v-1096h-166z" /> -<glyph unicode="Œ" horiz-adv-x="1890" d="M125 735q0 360 174 555t494 195q102 0 192 -23h782v-151h-589v-471h551v-150h-551v-538h589v-152h-768q-102 -20 -194 -20q-327 0 -503.5 196.5t-176.5 558.5zM305 733q0 -297 128.5 -450.5t375.5 -153.5q112 0 199 33v1141q-87 30 -197 30q-249 0 -377.5 -152.5 t-128.5 -447.5z" /> -<glyph unicode="œ" horiz-adv-x="1929" d="M113 549q0 265 131 415t366 150q131 0 233.5 -59.5t164.5 -173.5q58 112 154 172.5t222 60.5q201 0 320 -132.5t119 -358.5v-105h-729q8 -393 338 -393q94 0 174.5 17.5t167.5 56.5v-148q-88 -39 -164 -55t-180 -16q-293 0 -418 235q-62 -116 -166.5 -175.5t-241.5 -59.5 q-223 0 -357 152.5t-134 416.5zM287 549q0 -211 76 -320.5t243 -109.5q163 0 239.5 106.5t76.5 315.5q0 221 -77.5 327.5t-242.5 106.5q-166 0 -240.5 -108t-74.5 -318zM1098 653h544q0 158 -66 240t-194 82q-127 0 -199.5 -82t-84.5 -240z" /> -<glyph unicode="Ÿ" horiz-adv-x="1147" d="M0 1462h186l387 -731l390 731h184l-488 -895v-567h-172v559zM294 1731q0 52 26.5 75t63.5 23q38 0 65.5 -23t27.5 -75q0 -50 -27.5 -74.5t-65.5 -24.5q-37 0 -63.5 24.5t-26.5 74.5zM675 1731q0 52 26.5 75t63.5 23t64.5 -23t27.5 -75q0 -50 -27.5 -74.5t-64.5 -24.5 t-63.5 24.5t-26.5 74.5z" /> -<glyph unicode="ˆ" horiz-adv-x="1212" d="M268 1241v23q127 136 178 200t74 105h166q22 -42 76.5 -108.5t179.5 -196.5v-23h-119q-88 55 -221 186q-136 -134 -219 -186h-115z" /> -<glyph unicode="˚" horiz-adv-x="1182" d="M367 1456q0 98 60.5 155.5t160.5 57.5q101 0 163 -59.5t62 -151.5q0 -98 -61.5 -157.5t-163.5 -59.5q-101 0 -161 58.5t-60 156.5zM471 1456q0 -56 30 -86.5t87 -30.5q52 0 84.5 30.5t32.5 86.5t-33 86.5t-84 30.5t-84 -30.5t-33 -86.5z" /> -<glyph unicode="˜" horiz-adv-x="1212" d="M264 1241q13 121 70.5 189.5t148.5 68.5q46 0 89 -18.5t82 -41t75 -41t68 -18.5q49 0 73 29.5t39 91.5h99q-13 -121 -69.5 -189.5t-150.5 -68.5q-43 0 -84 18.5t-80.5 41t-76 41t-70.5 18.5q-50 0 -75.5 -30t-39.5 -91h-98z" /> -<glyph unicode=" " horiz-adv-x="953" /> -<glyph unicode=" " horiz-adv-x="1907" /> -<glyph unicode=" " horiz-adv-x="953" /> -<glyph unicode=" " horiz-adv-x="1907" /> -<glyph unicode=" " horiz-adv-x="635" /> -<glyph unicode=" " horiz-adv-x="476" /> -<glyph unicode=" " horiz-adv-x="317" /> -<glyph unicode=" " horiz-adv-x="317" /> -<glyph unicode=" " horiz-adv-x="238" /> -<glyph unicode=" " horiz-adv-x="381" /> -<glyph unicode=" " horiz-adv-x="105" /> -<glyph unicode="‐" horiz-adv-x="659" d="M84 473v152h491v-152h-491z" /> -<glyph unicode="‑" horiz-adv-x="659" d="M84 473v152h491v-152h-491z" /> -<glyph unicode="‒" horiz-adv-x="659" d="M84 473v152h491v-152h-491z" /> -<glyph unicode="–" horiz-adv-x="1024" d="M82 473v152h860v-152h-860z" /> -<glyph unicode="—" horiz-adv-x="2048" d="M82 473v152h1884v-152h-1884z" /> -<glyph unicode="‘" horiz-adv-x="348" d="M25 983q22 90 71 224t105 255h123q-66 -254 -103 -501h-184z" /> -<glyph unicode="’" horiz-adv-x="348" d="M25 961q70 285 102 501h182l15 -22q-26 -100 -75 -232.5t-102 -246.5h-122z" /> -<glyph unicode="‚" horiz-adv-x="502" d="M63 -264q27 104 59.5 257t45.5 245h182l15 -23q-26 -100 -75 -232.5t-102 -246.5h-125z" /> -<glyph unicode="“" horiz-adv-x="717" d="M25 983q22 90 71 224t105 255h123q-66 -254 -103 -501h-184zM391 983q56 215 178 479h123q-30 -115 -59.5 -259.5t-42.5 -241.5h-184z" /> -<glyph unicode="”" horiz-adv-x="717" d="M25 961q70 285 102 501h182l15 -22q-26 -100 -75 -232.5t-102 -246.5h-122zM391 961q26 100 59 254t46 247h182l14 -22q-24 -91 -72 -224t-104 -255h-125z" /> -<glyph unicode="„" horiz-adv-x="829" d="M25 -263q70 285 102 501h182l15 -22q-26 -100 -75 -232.5t-102 -246.5h-122zM391 -263q26 100 59 254t46 247h182l14 -22q-24 -91 -72 -224t-104 -255h-125z" /> -<glyph unicode="•" horiz-adv-x="770" d="M164 748q0 121 56.5 184t164.5 63q105 0 163 -62t58 -185q0 -119 -57.5 -183.5t-163.5 -64.5q-107 0 -164 65.5t-57 182.5z" /> -<glyph unicode="…" horiz-adv-x="1606" d="M152 106q0 67 30.5 101.5t87.5 34.5q58 0 90.5 -34.5t32.5 -101.5q0 -65 -33 -100t-90 -35q-51 0 -84.5 31.5t-33.5 103.5zM682 106q0 67 30.5 101.5t87.5 34.5q58 0 90.5 -34.5t32.5 -101.5q0 -65 -33 -100t-90 -35q-51 0 -84.5 31.5t-33.5 103.5zM1213 106 q0 67 30.5 101.5t87.5 34.5q58 0 90.5 -34.5t32.5 -101.5q0 -65 -33 -100t-90 -35q-51 0 -84.5 31.5t-33.5 103.5z" /> -<glyph unicode=" " horiz-adv-x="381" /> -<glyph unicode="‹" horiz-adv-x="623" d="M82 524v27l342 407l119 -69l-289 -350l289 -351l-119 -71z" /> -<glyph unicode="›" horiz-adv-x="623" d="M80 188l287 351l-287 350l117 69l344 -407v-27l-344 -407z" /> -<glyph unicode="⁄" horiz-adv-x="266" d="M-391 0l903 1462h143l-903 -1462h-143z" /> -<glyph unicode=" " horiz-adv-x="476" /> -<glyph unicode="⁴" horiz-adv-x="711" d="M20 788v101l408 579h139v-563h125v-117h-125v-202h-145v202h-402zM160 905h262v195q0 134 6 209q-5 -12 -17 -31.5t-27 -41.5l-30 -46q-15 -22 -26 -39z" /> -<glyph unicode="€" horiz-adv-x="1208" d="M63 506v129h152l-2 42v44l2 80h-152v129h164q39 261 185 407t383 146q201 0 366 -97l-71 -139q-166 86 -295 86q-319 0 -398 -403h510v-129h-524l-2 -57v-64l2 -45h463v-129h-447q37 -180 138.5 -278.5t271.5 -98.5q156 0 309 66v-150q-146 -65 -317 -65 q-237 0 -381.5 134.5t-190.5 391.5h-166z" /> -<glyph unicode="™" horiz-adv-x="1589" d="M37 1356v106h543v-106h-211v-615h-123v615h-209zM647 741v721h187l196 -559l203 559h180v-721h-127v420l6 137h-8l-211 -557h-104l-201 559h-8l6 -129v-430h-119z" /> -<glyph unicode="−" d="M104 653v138h961v-138h-961z" /> -<glyph unicode="" horiz-adv-x="1095" d="M0 1095h1095v-1095h-1095v1095z" /> -<glyph unicode="fi" horiz-adv-x="1212" d="M29 967v75l196 60v61q0 404 353 404q87 0 204 -35l-43 -133q-96 31 -164 31q-94 0 -139 -62.5t-45 -200.5v-71h279v-129h-279v-967h-166v967h-196zM856 1393q0 57 28 83.5t70 26.5q40 0 69 -27t29 -83t-29 -83.5t-69 -27.5q-42 0 -70 27.5t-28 83.5zM870 0v1096h166 v-1096h-166z" /> -<glyph unicode="fl" horiz-adv-x="1212" d="M29 967v75l196 60v61q0 404 353 404q87 0 204 -35l-43 -133q-96 31 -164 31q-94 0 -139 -62.5t-45 -200.5v-71h279v-129h-279v-967h-166v967h-196zM870 0v1556h166v-1556h-166z" /> -<glyph unicode="ffi" horiz-adv-x="1909" d="M717 967v75l196 60v61q0 404 353 404q87 0 204 -35l-43 -133q-96 31 -164 31q-94 0 -139 -62.5t-45 -200.5v-71h279v-129h-279v-967h-166v967h-196zM29 967v75l196 60v61q0 404 353 404q87 0 204 -35l-43 -133q-96 31 -164 31q-94 0 -139 -62.5t-45 -200.5v-71h279v-129 h-279v-967h-166v967h-196zM1551 1393q0 57 28 83.5t70 26.5q40 0 69 -27t29 -83t-29 -83.5t-69 -27.5q-42 0 -70 27.5t-28 83.5zM1565 0v1096h166v-1096h-166z" /> -<glyph unicode="ffl" horiz-adv-x="1909" d="M717 967v75l196 60v61q0 404 353 404q87 0 204 -35l-43 -133q-96 31 -164 31q-94 0 -139 -62.5t-45 -200.5v-71h279v-129h-279v-967h-166v967h-196zM29 967v75l196 60v61q0 404 353 404q87 0 204 -35l-43 -133q-96 31 -164 31q-94 0 -139 -62.5t-45 -200.5v-71h279v-129 h-279v-967h-166v967h-196zM1565 0v1556h166v-1556h-166z" /> -</font> -</defs></svg> -\ No newline at end of file diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-Regular-webfont.ttf b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-Regular-webfont.ttf Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-Regular-webfont.woff b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-Regular-webfont.woff Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-Semibold-webfont.eot b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-Semibold-webfont.eot Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-Semibold-webfont.svg b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-Semibold-webfont.svg @@ -1,251 +0,0 @@ -<?xml version="1.0" standalone="no"?> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" > -<svg xmlns="http://www.w3.org/2000/svg"> -<metadata> -This is a custom SVG webfont generated by Font Squirrel. -Copyright : Digitized data copyright 2011 Google Corporation -Foundry : Ascender Corporation -Foundry URL : httpwwwascendercorpcom -</metadata> -<defs> -<font id="OpenSansSemibold" horiz-adv-x="1169" > -<font-face units-per-em="2048" ascent="1638" descent="-410" /> -<missing-glyph horiz-adv-x="532" /> -<glyph unicode=" " horiz-adv-x="532" /> -<glyph unicode="	" horiz-adv-x="532" /> -<glyph unicode=" " horiz-adv-x="532" /> -<glyph unicode="!" horiz-adv-x="565" d="M133 125q0 74 39 112.5t111 38.5q71 0 109 -40t38 -111t-38.5 -112.5t-108.5 -41.5q-71 0 -110.5 40t-39.5 114zM145 1462h277l-51 -1018h-174z" /> -<glyph unicode=""" horiz-adv-x="893" d="M133 1462h232l-41 -528h-150zM528 1462h232l-41 -528h-150z" /> -<glyph unicode="#" horiz-adv-x="1323" d="M47 418v168h283l57 284h-264v168h293l80 422h180l-80 -422h252l80 422h174l-80 -422h252v-168h-285l-55 -284h270v-168h-303l-80 -418h-178l80 418h-248l-80 -418h-174l76 418h-250zM506 586h250l57 284h-250z" /> -<glyph unicode="$" d="M111 168v211q86 -42 201 -70.5t206 -29.5v374l-84 31q-164 63 -239.5 150.5t-75.5 216.5q0 138 107.5 227t291.5 108v168h133v-165q203 -7 385 -82l-73 -183q-157 62 -312 74v-364l76 -29q190 -73 263 -154t73 -198q0 -145 -106 -239t-306 -116v-217h-133v211 q-248 4 -407 76zM354 1053q0 -57 35.5 -95t128.5 -75v311q-80 -12 -122 -49t-42 -92zM651 287q176 27 176 151q0 58 -40.5 95.5t-135.5 72.5v-319z" /> -<glyph unicode="%" horiz-adv-x="1765" d="M84 1026q0 457 319 457q157 0 241.5 -118.5t84.5 -338.5q0 -230 -82.5 -345.5t-243.5 -115.5q-152 0 -235.5 119.5t-83.5 341.5zM279 1024q0 -149 29 -222t95 -73q132 0 132 295t-132 295q-66 0 -95 -73t-29 -222zM379 0l811 1462h194l-811 -1462h-194zM1036 440 q0 457 320 457q154 0 239.5 -118t85.5 -339q0 -230 -83 -345t-242 -115q-152 0 -236 118.5t-84 341.5zM1231 440q0 -149 29.5 -223t95.5 -74q131 0 131 297q0 293 -131 293q-66 0 -95.5 -72t-29.5 -221z" /> -<glyph unicode="&" horiz-adv-x="1516" d="M96 387q0 131 64 228.5t231 193.5q-95 111 -129.5 187.5t-34.5 158.5q0 152 108.5 240t291.5 88q177 0 278 -85.5t101 -230.5q0 -114 -67.5 -207t-225.5 -186l346 -334q81 107 135 314h242q-70 -284 -224 -463l301 -291h-303l-149 145q-102 -82 -217.5 -123.5 t-255.5 -41.5q-230 0 -361 109t-131 298zM344 403q0 -98 69.5 -159.5t186.5 -61.5q183 0 313 107l-383 377q-106 -68 -146 -127.5t-40 -135.5zM451 1147q0 -63 33.5 -119t93.5 -119q113 64 158.5 119.5t45.5 124.5q0 65 -43.5 104t-115.5 39q-79 0 -125.5 -40.5 t-46.5 -108.5z" /> -<glyph unicode="'" horiz-adv-x="498" d="M133 1462h232l-41 -528h-150z" /> -<glyph unicode="(" horiz-adv-x="649" d="M82 561q0 265 77.5 496t223.5 405h205q-139 -188 -213 -421.5t-74 -477.5t74 -473t211 -414h-203q-147 170 -224 397t-77 488z" /> -<glyph unicode=")" horiz-adv-x="649" d="M61 1462h205q147 -175 224 -406.5t77 -494.5t-77.5 -490t-223.5 -395h-203q138 187 211.5 415t73.5 472q0 245 -74 477.5t-213 421.5z" /> -<glyph unicode="*" horiz-adv-x="1122" d="M74 1065l35 217l376 -108l-41 382h228l-41 -382l385 108l28 -217l-360 -29l236 -311l-199 -107l-166 338l-149 -338l-205 107l231 311z" /> -<glyph unicode="+" d="M96 633v178h398v408h180v-408h399v-178h-399v-406h-180v406h-398z" /> -<glyph unicode="," horiz-adv-x="547" d="M63 -264q69 270 103 502h231l15 -23q-48 -186 -176 -479h-173z" /> -<glyph unicode="-" horiz-adv-x="659" d="M72 449v200h514v-200h-514z" /> -<glyph unicode="." horiz-adv-x="563" d="M133 125q0 73 38 112t110 39q73 0 111 -40.5t38 -110.5q0 -71 -38.5 -112.5t-110.5 -41.5t-110 41t-38 113z" /> -<glyph unicode="/" horiz-adv-x="799" d="M16 0l545 1462h221l-544 -1462h-222z" /> -<glyph unicode="0" d="M88 731q0 387 122.5 570.5t373.5 183.5q245 0 371 -192t126 -562q0 -381 -122.5 -566t-374.5 -185q-244 0 -370 191t-126 560zM326 731q0 -299 61.5 -427t196.5 -128t197.5 130t62.5 425q0 294 -62.5 425.5t-197.5 131.5t-196.5 -129t-61.5 -428z" /> -<glyph unicode="1" d="M154 1124l430 338h196v-1462h-235v944q0 169 8 268q-23 -24 -56.5 -53t-224.5 -184z" /> -<glyph unicode="2" d="M90 0v178l377 379q167 171 221.5 242.5t79.5 134.5t25 135q0 99 -59.5 156t-164.5 57q-84 0 -162.5 -31t-181.5 -112l-127 155q122 103 237 146t245 43q204 0 327 -106.5t123 -286.5q0 -99 -35.5 -188t-109 -183.5t-244.5 -255.5l-254 -246v-10h694v-207h-991z" /> -<glyph unicode="3" d="M86 59v209q93 -46 197 -71t200 -25q170 0 254 63t84 195q0 117 -93 172t-292 55h-127v191h129q350 0 350 242q0 94 -61 145t-180 51q-83 0 -160 -23.5t-182 -91.5l-115 164q201 148 467 148q221 0 345 -95t124 -262q0 -139 -81 -231.5t-228 -124.5v-8q176 -22 264 -109.5 t88 -232.5q0 -211 -149 -325.5t-424 -114.5q-243 0 -410 79z" /> -<glyph unicode="4" d="M39 319v181l668 966h229v-952h197v-195h-197v-319h-229v319h-668zM258 514h449v367q0 196 10 321h-8q-28 -66 -88 -160z" /> -<glyph unicode="5" d="M117 59v213q81 -46 186 -71t195 -25q159 0 242 71t83 208q0 262 -334 262q-47 0 -116 -9.5t-121 -21.5l-105 62l56 714h760v-209h-553l-33 -362q35 6 85.5 14t123.5 8q221 0 350 -117t129 -319q0 -234 -146.5 -365.5t-416.5 -131.5q-245 0 -385 79z" /> -<glyph unicode="6" d="M94 623q0 858 699 858q110 0 186 -17v-196q-76 22 -176 22q-235 0 -353 -126t-128 -404h12q47 81 132 125.5t200 44.5q199 0 310 -122t111 -331q0 -230 -128.5 -363.5t-350.5 -133.5q-157 0 -273 75.5t-178.5 220t-62.5 347.5zM332 508q0 -141 76.5 -237.5t195.5 -96.5 q121 0 186.5 78t65.5 223q0 126 -61.5 198t-184.5 72q-76 0 -140 -32.5t-101 -89t-37 -115.5z" /> -<glyph unicode="7" d="M74 1253v207h1011v-164l-575 -1296h-254l578 1253h-760z" /> -<glyph unicode="8" d="M88 371q0 122 68.5 219.5t224.5 173.5q-134 80 -191 169t-57 200q0 159 125 253.5t326 94.5q208 0 329 -95.5t121 -255.5q0 -225 -270 -358q172 -86 244.5 -181t72.5 -212q0 -181 -133 -290t-360 -109q-238 0 -369 102t-131 289zM313 379q0 -104 73 -161.5t198 -57.5 q129 0 200.5 59.5t71.5 161.5q0 81 -66 148t-200 124l-29 13q-132 -58 -190 -127.5t-58 -159.5zM360 1116q0 -52 22 -93t64 -74.5t142 -80.5q120 53 169.5 111.5t49.5 136.5q0 85 -61.5 134.5t-163.5 49.5q-100 0 -161 -49.5t-61 -134.5z" /> -<glyph unicode="9" d="M86 981q0 229 128.5 364.5t350.5 135.5q156 0 272 -76t179 -220.5t63 -346.5q0 -432 -174 -645t-524 -213q-133 0 -191 16v197q89 -25 179 -25q238 0 355 128t128 402h-12q-59 -90 -142.5 -130t-195.5 -40q-194 0 -305 121t-111 332zM317 983q0 -125 60.5 -196.5 t183.5 -71.5q119 0 200 71t81 166q0 89 -34.5 166.5t-96.5 122.5t-142 45q-122 0 -187 -79.5t-65 -223.5z" /> -<glyph unicode=":" horiz-adv-x="563" d="M133 125q0 73 38 112t110 39q73 0 111 -40.5t38 -110.5q0 -71 -38.5 -112.5t-110.5 -41.5t-110 41t-38 113zM133 979q0 151 148 151q75 0 112 -40t37 -111t-38.5 -112.5t-110.5 -41.5t-110 41t-38 113z" /> -<glyph unicode=";" horiz-adv-x="569" d="M63 -264q69 270 103 502h231l15 -23q-48 -186 -176 -479h-173zM131 979q0 151 148 151q75 0 112 -40t37 -111t-38.5 -112.5t-110.5 -41.5t-110 41t-38 113z" /> -<glyph unicode="<" d="M96 651v121l977 488v-195l-733 -344l733 -303v-197z" /> -<glyph unicode="=" d="M102 432v178h963v-178h-963zM102 831v179h963v-179h-963z" /> -<glyph unicode=">" d="M96 221v197l733 303l-733 344v195l977 -488v-121z" /> -<glyph unicode="?" horiz-adv-x="928" d="M16 1370q203 113 435 113q196 0 311 -96t115 -265q0 -75 -22 -133.5t-66.5 -111.5t-153.5 -138q-93 -73 -124.5 -121t-31.5 -129v-45h-196v64q0 110 40 183t140 151q119 94 153.5 146t34.5 124q0 84 -56 129t-161 45q-95 0 -176 -27t-158 -65zM242 125q0 151 147 151 q72 0 110 -39.5t38 -111.5q0 -71 -38.5 -112.5t-109.5 -41.5t-109 40.5t-38 113.5z" /> -<glyph unicode="@" horiz-adv-x="1839" d="M111 586q0 261 112 464.5t310.5 311.5t449.5 108q217 0 386.5 -90t263 -256.5t93.5 -384.5q0 -143 -45 -261.5t-126.5 -184.5t-188.5 -66q-79 0 -137 42t-78 114h-12q-49 -78 -121 -117t-162 -39q-163 0 -256.5 105t-93.5 284q0 206 124 334.5t333 128.5 q76 0 168.5 -13.5t164.5 -37.5l-22 -465v-24q0 -160 104 -160q79 0 125.5 102t46.5 260q0 171 -70 300.5t-199 199.5t-296 70q-213 0 -370.5 -88t-240.5 -251.5t-83 -379.5q0 -290 155 -446t445 -156q221 0 461 90v-164q-210 -86 -457 -86q-370 0 -577 199.5t-207 556.5z M698 612q0 -233 183 -233q193 0 211 293l12 239q-63 17 -135 17q-128 0 -199.5 -85t-71.5 -231z" /> -<glyph unicode="A" horiz-adv-x="1354" d="M0 0l547 1468h260l547 -1468h-254l-146 406h-559l-143 -406h-252zM465 612h426l-137 398q-15 40 -41.5 126t-36.5 126q-27 -123 -79 -269z" /> -<glyph unicode="B" horiz-adv-x="1352" d="M193 0v1462h434q302 0 436.5 -88t134.5 -278q0 -128 -66 -213t-190 -107v-10q154 -29 226.5 -114.5t72.5 -231.5q0 -197 -137.5 -308.5t-382.5 -111.5h-528zM432 201h254q150 0 226.5 57.5t76.5 181.5q0 114 -78 169t-237 55h-242v-463zM432 858h230q150 0 219 47.5 t69 161.5q0 103 -74.5 149t-236.5 46h-207v-404z" /> -<glyph unicode="C" horiz-adv-x="1298" d="M121 731q0 228 83.5 399t241.5 262t371 91q224 0 414 -94l-86 -199q-74 35 -156.5 61.5t-173.5 26.5q-206 0 -324 -146t-118 -403q0 -269 113.5 -407t328.5 -138q93 0 180 18.5t181 47.5v-205q-172 -65 -390 -65q-321 0 -493 194.5t-172 556.5z" /> -<glyph unicode="D" horiz-adv-x="1503" d="M193 0v1462h452q349 0 543 -188t194 -529q0 -362 -201 -553.5t-579 -191.5h-409zM432 201h170q528 0 528 536q0 525 -491 525h-207v-1061z" /> -<glyph unicode="E" horiz-adv-x="1143" d="M193 0v1462h827v-202h-588v-398h551v-200h-551v-459h588v-203h-827z" /> -<glyph unicode="F" horiz-adv-x="1090" d="M193 0v1462h825v-202h-588v-457h551v-203h-551v-600h-237z" /> -<glyph unicode="G" horiz-adv-x="1487" d="M121 731q0 353 203 552.5t559 199.5q229 0 434 -88l-84 -199q-178 82 -356 82q-234 0 -370 -147t-136 -402q0 -268 122.5 -407.5t352.5 -139.5q116 0 248 29v377h-303v205h538v-734q-132 -43 -253.5 -61t-262.5 -18q-332 0 -512 196.5t-180 554.5z" /> -<glyph unicode="H" horiz-adv-x="1538" d="M193 0v1462h239v-598h674v598h240v-1462h-240v659h-674v-659h-239z" /> -<glyph unicode="I" horiz-adv-x="625" d="M193 0v1462h239v-1462h-239z" /> -<glyph unicode="J" horiz-adv-x="612" d="M-156 -182q84 -21 146 -21q196 0 196 248v1417h240v-1409q0 -224 -106.5 -342.5t-311.5 -118.5q-98 0 -164 25v201z" /> -<glyph unicode="K" horiz-adv-x="1309" d="M193 0v1462h239v-698q98 120 195 231l395 467h272q-383 -450 -549 -641l564 -821h-277l-459 662l-141 -115v-547h-239z" /> -<glyph unicode="L" horiz-adv-x="1110" d="M193 0v1462h239v-1257h619v-205h-858z" /> -<glyph unicode="M" horiz-adv-x="1890" d="M193 0v1462h337l406 -1163h6l418 1163h338v-1462h-230v723q0 109 5.5 284t9.5 212h-8l-439 -1219h-211l-424 1221h-8q17 -272 17 -510v-711h-217z" /> -<glyph unicode="N" horiz-adv-x="1604" d="M193 0v1462h290l717 -1159h6q-2 23 -8 167.5t-6 225.5v766h219v-1462h-293l-719 1165h-8l5 -65q14 -186 14 -340v-760h-217z" /> -<glyph unicode="O" horiz-adv-x="1612" d="M121 735q0 362 178.5 556t509.5 194q326 0 504 -197t178 -555q0 -357 -178.5 -555t-505.5 -198q-331 0 -508.5 196.5t-177.5 558.5zM375 733q0 -270 109 -409.5t323 -139.5q213 0 321.5 138t108.5 411q0 269 -107.5 408t-320.5 139q-215 0 -324.5 -139t-109.5 -408z" /> -<glyph unicode="P" horiz-adv-x="1260" d="M193 0v1462h421q274 0 410.5 -112t136.5 -330q0 -229 -150 -351t-427 -122h-152v-547h-239zM432 748h127q184 0 270 64t86 200q0 126 -77 188t-240 62h-166v-514z" /> -<glyph unicode="Q" horiz-adv-x="1612" d="M121 735q0 362 178.5 556t509.5 194q326 0 504 -197t178 -555q0 -266 -101.5 -448t-295.5 -256l350 -377h-322l-276 328h-39q-331 0 -508.5 196.5t-177.5 558.5zM375 733q0 -270 109 -409.5t323 -139.5q213 0 321.5 138t108.5 411q0 269 -107.5 408t-320.5 139 q-215 0 -324.5 -139t-109.5 -408z" /> -<glyph unicode="R" horiz-adv-x="1309" d="M193 0v1462h413q283 0 419 -106t136 -320q0 -273 -284 -389l413 -647h-272l-350 584h-236v-584h-239zM432 782h166q167 0 242 62t75 184q0 124 -81 178t-244 54h-158v-478z" /> -<glyph unicode="S" horiz-adv-x="1126" d="M100 57v226q100 -47 212.5 -74t209.5 -27q142 0 209.5 54t67.5 145q0 82 -62 139t-256 135q-200 81 -282 185t-82 250q0 183 130 288t349 105q210 0 418 -92l-76 -195q-195 82 -348 82q-116 0 -176 -50.5t-60 -133.5q0 -57 24 -97.5t79 -76.5t198 -95q161 -67 236 -125 t110 -131t35 -172q0 -195 -141 -306t-389 -111t-406 77z" /> -<glyph unicode="T" horiz-adv-x="1159" d="M29 1257v205h1099v-205h-430v-1257h-239v1257h-430z" /> -<glyph unicode="U" horiz-adv-x="1520" d="M180 520v942h240v-925q0 -181 84 -267t258 -86q338 0 338 355v923h239v-946q0 -162 -69.5 -283.5t-201 -187t-314.5 -65.5q-272 0 -423 144t-151 396z" /> -<glyph unicode="V" horiz-adv-x="1274" d="M0 1462h246l305 -909q24 -65 51 -167.5t35 -152.5q13 76 40 176t44 148l305 905h248l-512 -1462h-252z" /> -<glyph unicode="W" horiz-adv-x="1937" d="M12 1462h244l209 -852q49 -205 70 -362q11 85 33 190t40 170l238 854h237l244 -858q35 -119 74 -356q15 143 72 364l208 850h242l-381 -1462h-260l-248 872q-16 57 -40 164.5t-29 149.5q-10 -64 -32.5 -166t-37.5 -152l-242 -868h-260l-189 732z" /> -<glyph unicode="X" horiz-adv-x="1274" d="M4 0l485 758l-454 704h266l338 -553l338 553h258l-457 -708l492 -754h-275l-366 598l-369 -598h-256z" /> -<glyph unicode="Y" horiz-adv-x="1212" d="M0 1462h260l346 -667l346 667h260l-487 -895v-567h-240v559z" /> -<glyph unicode="Z" horiz-adv-x="1178" d="M66 0v166l737 1091h-717v205h1006v-168l-740 -1089h760v-205h-1046z" /> -<glyph unicode="[" horiz-adv-x="676" d="M154 -324v1786h471v-176h-256v-1433h256v-177h-471z" /> -<glyph unicode="\" horiz-adv-x="799" d="M16 1462h222l544 -1462h-221z" /> -<glyph unicode="]" horiz-adv-x="676" d="M51 -147h256v1433h-256v176h469v-1786h-469v177z" /> -<glyph unicode="^" horiz-adv-x="1100" d="M29 535l436 935h121l485 -935h-194l-349 694l-307 -694h-192z" /> -<glyph unicode="_" horiz-adv-x="879" d="M-4 -184h887v-135h-887v135z" /> -<glyph unicode="`" horiz-adv-x="1212" d="M362 1548v21h273q38 -70 103.5 -161t109.5 -142v-25h-158q-69 52 -174.5 150.5t-153.5 156.5z" /> -<glyph unicode="a" horiz-adv-x="1188" d="M90 317q0 171 127 258t387 95l191 6v59q0 106 -49.5 158.5t-153.5 52.5q-85 0 -163 -25t-150 -59l-76 168q90 47 197 71.5t202 24.5q211 0 318.5 -92t107.5 -289v-745h-168l-47 154h-8q-80 -101 -161 -137.5t-208 -36.5q-163 0 -254.5 88t-91.5 249zM334 315 q0 -74 44 -114.5t132 -40.5q128 0 205.5 71.5t77.5 200.5v96l-142 -6q-166 -6 -241.5 -55.5t-75.5 -151.5z" /> -<glyph unicode="b" horiz-adv-x="1276" d="M168 0v1556h235v-370q0 -41 -4 -122t-6 -103h10q112 165 330 165q207 0 322.5 -150t115.5 -421q0 -272 -117 -423.5t-325 -151.5q-210 0 -326 151h-16l-43 -131h-176zM403 555q0 -202 64 -292.5t209 -90.5q125 0 189.5 99t64.5 286q0 377 -258 377q-142 0 -204.5 -83.5 t-64.5 -279.5v-16z" /> -<glyph unicode="c" horiz-adv-x="1014" d="M102 547q0 279 136.5 429t394.5 150q175 0 315 -65l-71 -189q-149 58 -246 58q-287 0 -287 -381q0 -186 71.5 -279.5t209.5 -93.5q157 0 297 78v-205q-63 -37 -134.5 -53t-173.5 -16q-251 0 -381.5 146.5t-130.5 420.5z" /> -<glyph unicode="d" horiz-adv-x="1276" d="M102 551q0 272 117.5 423.5t325.5 151.5q218 0 332 -161h12q-17 119 -17 188v403h236v-1556h-184l-41 145h-11q-113 -165 -331 -165q-207 0 -323 150t-116 421zM344 547q0 -184 65 -280.5t195 -96.5q145 0 211 81.5t68 264.5v33q0 209 -68 297t-213 88 q-124 0 -191 -100.5t-67 -286.5z" /> -<glyph unicode="e" horiz-adv-x="1180" d="M102 545q0 271 135 426t371 155q219 0 346 -133t127 -366v-127h-737q5 -161 87 -247.5t231 -86.5q98 0 182.5 18.5t181.5 61.5v-191q-86 -41 -174 -58t-201 -17q-258 0 -403.5 150.5t-145.5 414.5zM348 670h502q-2 137 -66 207.5t-176 70.5t-179.5 -71t-80.5 -207z" /> -<glyph unicode="f" horiz-adv-x="743" d="M35 928v110l182 72v72q0 196 92 290.5t281 94.5q124 0 244 -41l-62 -178q-87 28 -166 28q-80 0 -116.5 -49.5t-36.5 -148.5v-72h270v-178h-270v-928h-236v928h-182z" /> -<glyph unicode="g" horiz-adv-x="1139" d="M23 -184q0 102 64.5 171.5t180.5 96.5q-47 20 -77.5 64.5t-30.5 93.5q0 62 35 105t104 85q-86 37 -139.5 120.5t-53.5 195.5q0 180 113.5 279t323.5 99q47 0 98.5 -6.5t77.5 -13.5h383v-129l-189 -35q26 -35 43 -86t17 -108q0 -171 -118 -269t-325 -98q-53 0 -96 8 q-76 -47 -76 -110q0 -38 35.5 -57t130.5 -19h193q183 0 278 -78t95 -225q0 -188 -155 -290t-448 -102q-226 0 -345 80t-119 228zM233 -172q0 -76 68.5 -117t192.5 -41q192 0 286 55t94 146q0 72 -51.5 102.5t-191.5 30.5h-178q-101 0 -160.5 -47.5t-59.5 -128.5zM334 748 q0 -104 53.5 -160t153.5 -56q204 0 204 218q0 108 -50.5 166.5t-153.5 58.5q-102 0 -154.5 -58t-52.5 -169z" /> -<glyph unicode="h" horiz-adv-x="1300" d="M168 0v1556h235v-395q0 -95 -12 -203h15q48 80 133.5 124t199.5 44q402 0 402 -405v-721h-236v680q0 128 -51.5 191t-163.5 63q-148 0 -217.5 -88.5t-69.5 -296.5v-549h-235z" /> -<glyph unicode="i" horiz-adv-x="571" d="M154 1399q0 63 34.5 97t98.5 34q62 0 96.5 -34t34.5 -97q0 -60 -34.5 -94.5t-96.5 -34.5q-64 0 -98.5 34.5t-34.5 94.5zM168 0v1106h235v-1106h-235z" /> -<glyph unicode="j" horiz-adv-x="571" d="M-121 -281q68 -18 139 -18q150 0 150 170v1235h235v-1251q0 -171 -89.5 -259t-258.5 -88q-106 0 -176 25v186zM154 1399q0 63 34.5 97t98.5 34q62 0 96.5 -34t34.5 -97q0 -60 -34.5 -94.5t-96.5 -34.5q-64 0 -98.5 34.5t-34.5 94.5z" /> -<glyph unicode="k" horiz-adv-x="1171" d="M168 0v1556h233v-759l-12 -213h6l133 166l334 356h271l-445 -475l473 -631h-276l-355 485l-129 -106v-379h-233z" /> -<glyph unicode="l" horiz-adv-x="571" d="M168 0v1556h235v-1556h-235z" /> -<glyph unicode="m" horiz-adv-x="1958" d="M168 0v1106h184l33 -145h12q46 79 133.5 122t192.5 43q255 0 338 -174h16q49 82 138 128t204 46q198 0 288.5 -100t90.5 -305v-721h-235v682q0 127 -48.5 189.5t-150.5 62.5q-137 0 -200.5 -85.5t-63.5 -262.5v-586h-236v682q0 127 -48 189.5t-150 62.5 q-136 0 -199.5 -88.5t-63.5 -294.5v-551h-235z" /> -<glyph unicode="n" horiz-adv-x="1300" d="M168 0v1106h184l33 -145h12q50 79 142 122t204 43q398 0 398 -405v-721h-236v680q0 128 -51.5 191t-163.5 63q-149 0 -218 -88t-69 -295v-551h-235z" /> -<glyph unicode="o" horiz-adv-x="1251" d="M102 555q0 269 138 420t389 151q240 0 380 -154.5t140 -416.5q0 -271 -139 -423t-387 -152q-155 0 -274 70t-183 201t-64 304zM344 555q0 -383 283 -383q280 0 280 383q0 379 -282 379q-148 0 -214.5 -98t-66.5 -281z" /> -<glyph unicode="p" horiz-adv-x="1276" d="M168 -492v1598h190q8 -31 33 -148h12q110 168 330 168q207 0 322.5 -150t115.5 -421t-117.5 -423t-324.5 -152q-210 0 -326 151h-14q14 -140 14 -170v-453h-235zM403 555q0 -202 64 -292.5t209 -90.5q122 0 188 100t66 285q0 186 -65.5 281.5t-192.5 95.5 q-140 0 -204.5 -82t-64.5 -262v-35z" /> -<glyph unicode="q" horiz-adv-x="1276" d="M102 551q0 270 118 422.5t325 152.5q104 0 186.5 -38.5t147.5 -126.5h8l26 145h195v-1598h-236v469q0 44 4 93t7 75h-13q-104 -165 -331 -165q-205 0 -321 150.5t-116 420.5zM344 547q0 -379 262 -379q148 0 212.5 85.5t64.5 258.5v37q0 205 -66.5 295t-214.5 90 q-126 0 -192 -100t-66 -287z" /> -<glyph unicode="r" horiz-adv-x="883" d="M168 0v1106h184l31 -195h12q55 99 143.5 157t190.5 58q71 0 117 -10l-23 -219q-50 12 -104 12q-141 0 -228.5 -92t-87.5 -239v-578h-235z" /> -<glyph unicode="s" horiz-adv-x="997" d="M98 827q0 142 114.5 220.5t311.5 78.5q195 0 369 -79l-76 -177q-179 74 -301 74q-186 0 -186 -106q0 -52 48.5 -88t211.5 -99q137 -53 199 -97t92 -101.5t30 -137.5q0 -162 -118 -248.5t-338 -86.5q-221 0 -355 67v203q195 -90 363 -90q217 0 217 131q0 42 -24 70t-79 58 t-153 68q-191 74 -258.5 148t-67.5 192z" /> -<glyph unicode="t" horiz-adv-x="805" d="M39 928v104l162 86l80 234h145v-246h315v-178h-315v-592q0 -85 42.5 -125.5t111.5 -40.5q86 0 172 27v-177q-39 -17 -100.5 -28.5t-127.5 -11.5q-334 0 -334 352v596h-151z" /> -<glyph unicode="u" horiz-adv-x="1300" d="M158 383v723h237v-682q0 -127 52 -190.5t163 -63.5q148 0 217.5 88.5t69.5 296.5v551h236v-1106h-185l-33 145h-12q-49 -77 -139.5 -121t-206.5 -44q-201 0 -300 100t-99 303z" /> -<glyph unicode="v" horiz-adv-x="1096" d="M0 1106h248l225 -643q58 -162 70 -262h8q9 72 70 262l225 643h250l-422 -1106h-254z" /> -<glyph unicode="w" horiz-adv-x="1673" d="M20 1106h240l141 -545q48 -202 68 -346h6q10 73 30.5 167.5t35.5 141.5l168 582h258l163 -582q15 -49 37.5 -150t26.5 -157h8q15 123 70 344l143 545h236l-312 -1106h-264l-143 516q-26 82 -94 381h-9q-58 -270 -92 -383l-147 -514h-260z" /> -<glyph unicode="x" horiz-adv-x="1128" d="M25 0l389 565l-371 541h268l252 -387l254 387h266l-372 -541l391 -565h-266l-273 414l-272 -414h-266z" /> -<glyph unicode="y" horiz-adv-x="1098" d="M0 1106h256l225 -627q51 -134 68 -252h8q9 55 33 133.5t254 745.5h254l-473 -1253q-129 -345 -430 -345q-78 0 -152 17v186q53 -12 121 -12q170 0 239 197l41 104z" /> -<glyph unicode="z" horiz-adv-x="979" d="M68 0v145l559 781h-525v180h789v-164l-547 -762h563v-180h-839z" /> -<glyph unicode="{" horiz-adv-x="791" d="M45 473v191q135 0 200.5 45.5t65.5 138.5v311q0 156 108.5 229.5t325.5 73.5v-182q-114 -5 -165.5 -46.5t-51.5 -123.5v-297q0 -199 -229 -238v-12q229 -36 229 -237v-299q0 -82 51 -124t166 -44v-183q-231 2 -332.5 78.5t-101.5 247.5v285q0 186 -266 186z" /> -<glyph unicode="|" horiz-adv-x="1128" d="M473 -481v2033h180v-2033h-180z" /> -<glyph unicode="}" horiz-adv-x="760" d="M45 -141q95 1 148 38.5t53 129.5v262q0 121 53 187t176 87v12q-229 39 -229 238v297q0 82 -45.5 123.5t-155.5 46.5v182q223 0 320.5 -76.5t97.5 -250.5v-287q0 -100 63.5 -142t188.5 -42v-191q-123 0 -187.5 -42.5t-64.5 -143.5v-307q0 -156 -99.5 -229t-318.5 -75v183z " /> -<glyph unicode="~" d="M96 571v191q99 108 250 108q66 0 125 -13t147 -50q131 -55 220 -55q52 0 114.5 31t120.5 89v-190q-105 -111 -250 -111q-65 0 -127.5 15.5t-146.5 50.5q-127 55 -219 55q-50 0 -111.5 -30t-122.5 -91z" /> -<glyph unicode="¡" horiz-adv-x="565" d="M133 965q0 69 38 111t110 42t110.5 -40.5t38.5 -112.5q0 -74 -37.5 -113t-111.5 -39q-72 0 -110 39.5t-38 112.5zM141 -371l52 1016h174l51 -1016h-277z" /> -<glyph unicode="¢" d="M166 741q0 254 100.5 397t306.5 175v170h158v-162q152 -5 283 -66l-70 -188q-146 59 -250 59q-146 0 -216 -95t-70 -288q0 -194 72 -283t210 -89q75 0 142.5 15t154.5 52v-200q-119 -59 -258 -64v-194h-156v200q-207 31 -307 171t-100 390z" /> -<glyph unicode="£" d="M72 0v195q98 30 145 96t47 178v184h-188v172h188v256q0 188 113.5 294t312.5 106q194 0 375 -82l-76 -182q-162 71 -284 71q-205 0 -205 -219v-244h397v-172h-397v-182q0 -91 -33 -155t-113 -109h756v-207h-1038z" /> -<glyph unicode="¤" d="M117 1069l121 119l131 -129q100 63 215 63t213 -65l133 131l121 -117l-131 -133q63 -100 63 -215q0 -119 -63 -217l129 -129l-119 -119l-133 129q-99 -61 -213 -61q-126 0 -215 61l-131 -127l-119 119l131 129q-64 99 -64 215q0 109 64 213zM354 723q0 -98 68 -164.5 t162 -66.5q97 0 165 66.5t68 164.5q0 97 -68 165t-165 68q-93 0 -161.5 -68t-68.5 -165z" /> -<glyph unicode="¥" d="M18 1462h246l320 -665l321 665h244l-399 -760h227v-151h-281v-154h281v-153h-281v-244h-225v244h-283v153h283v154h-283v151h224z" /> -<glyph unicode="¦" horiz-adv-x="1128" d="M473 315h180v-796h-180v796zM473 758v794h180v-794h-180z" /> -<glyph unicode="§" horiz-adv-x="1026" d="M115 57v179q77 -40 173 -65.5t177 -25.5q235 0 235 131q0 43 -21 70t-71 54t-147 65q-141 55 -206 101.5t-95.5 105t-30.5 135.5q0 80 38.5 145.5t111.5 108.5q-146 83 -146 235q0 129 109.5 202t294.5 73q91 0 174 -17t182 -59l-68 -162q-116 50 -176 63t-121 13 q-194 0 -194 -109q0 -54 55 -93.5t191 -90.5q175 -68 250 -146.5t75 -187.5q0 -177 -139 -266q139 -80 139 -223q0 -142 -118 -224.5t-326 -82.5q-212 0 -346 71zM313 827q0 -45 24 -80t78.5 -69t194.5 -90q109 65 109 168q0 75 -62 126.5t-221 104.5q-54 -16 -88.5 -61.5 t-34.5 -98.5z" /> -<glyph unicode="¨" horiz-adv-x="1212" d="M293 1399q0 62 33.5 89.5t81.5 27.5q53 0 84.5 -31t31.5 -86q0 -53 -32 -85t-84 -32q-48 0 -81.5 29t-33.5 88zM686 1399q0 62 33.5 89.5t81.5 27.5q53 0 85 -31t32 -86q0 -54 -33 -85.5t-84 -31.5q-48 0 -81.5 29t-33.5 88z" /> -<glyph unicode="©" horiz-adv-x="1704" d="M100 731q0 200 100 375t275 276t377 101q200 0 375 -100t276 -275t101 -377q0 -197 -97 -370t-272 -277t-383 -104q-207 0 -382 103.5t-272.5 276.5t-97.5 371zM223 731q0 -170 84.5 -315.5t230.5 -229.5t314 -84q170 0 316 85.5t229.5 230t83.5 313.5q0 168 -84.5 314.5 t-231 230.5t-313.5 84q-168 0 -312.5 -83t-230.5 -229t-86 -317zM471 731q0 214 110 337.5t306 123.5q138 0 274 -70l-65 -143q-106 55 -203 55q-111 0 -171 -80.5t-60 -222.5q0 -147 54 -226t177 -79q55 0 118 15t109 36v-158q-115 -51 -235 -51q-197 0 -305.5 120.5 t-108.5 342.5z" /> -<glyph unicode="ª" horiz-adv-x="754" d="M57 981q0 104 84 159.5t252 61.5l107 4q0 72 -34.5 108t-103.5 36q-90 0 -210 -56l-54 115q144 70 285 70q138 0 207 -62.5t69 -187.5v-447h-112l-29 97q-46 -55 -105 -82t-130 -27q-113 0 -169.5 52.5t-56.5 158.5zM221 983q0 -88 96 -88q91 0 137 41t46 123v43l-99 -4 q-71 -2 -125.5 -34t-54.5 -81z" /> -<glyph unicode="«" horiz-adv-x="1139" d="M82 535v26l356 432l168 -94l-282 -350l282 -348l-168 -97zM532 535v26l357 432l168 -94l-283 -350l283 -348l-168 -97z" /> -<glyph unicode="¬" d="M96 633v178h977v-555h-178v377h-799z" /> -<glyph unicode="­" horiz-adv-x="659" d="M72 449v200h514v-200h-514z" /> -<glyph unicode="®" horiz-adv-x="1704" d="M100 731q0 200 100 375t275 276t377 101q200 0 375 -100t276 -275t101 -377q0 -197 -97 -370t-272 -277t-383 -104q-207 0 -382 103.5t-272.5 276.5t-97.5 371zM223 731q0 -170 84.5 -315.5t230.5 -229.5t314 -84q170 0 316 85.5t229.5 230t83.5 313.5q0 168 -84.5 314.5 t-231 230.5t-313.5 84q-168 0 -312.5 -83t-230.5 -229t-86 -317zM559 279v903h262q174 0 255 -68t81 -205q0 -171 -153 -233l237 -397h-211l-192 346h-90v-346h-189zM748 770h69q74 0 112 35t38 100q0 72 -36.5 100.5t-115.5 28.5h-67v-264z" /> -<glyph unicode="¯" horiz-adv-x="1024" d="M-6 1556v164h1036v-164h-1036z" /> -<glyph unicode="°" horiz-adv-x="877" d="M109 1153q0 135 95 232.5t234 97.5q138 0 233 -96t95 -234q0 -139 -96 -233.5t-232 -94.5q-88 0 -164.5 43.5t-120.5 119.5t-44 165zM262 1153q0 -70 51 -122t125 -52t125 51.5t51 122.5q0 76 -52 127t-124 51t-124 -52t-52 -126z" /> -<glyph unicode="±" d="M96 0v178h977v-178h-977zM96 664v178h398v407h180v-407h399v-178h-399v-406h-180v406h-398z" /> -<glyph unicode="²" horiz-adv-x="743" d="M51 586v135l230 225q117 112 149.5 165t32.5 112q0 52 -32 79t-83 27q-93 0 -201 -88l-94 121q139 119 309 119q136 0 211.5 -66t75.5 -180q0 -83 -46 -158.5t-183 -202.5l-139 -129h397v-159h-627z" /> -<glyph unicode="³" horiz-adv-x="743" d="M45 631v157q145 -79 270 -79q179 0 179 135q0 125 -199 125h-115v133h105q184 0 184 129q0 52 -34.5 80t-90.5 28q-57 0 -105.5 -20t-105.5 -57l-84 114q61 46 134 75.5t171 29.5q134 0 212.5 -61.5t78.5 -168.5q0 -75 -40.5 -122.5t-119.5 -86.5q94 -21 141.5 -76 t47.5 -132q0 -127 -93 -196t-266 -69q-148 0 -270 62z" /> -<glyph unicode="´" horiz-adv-x="1212" d="M362 1241v25q57 70 117.5 156t95.5 147h273v-21q-52 -61 -155.5 -157.5t-174.5 -149.5h-156z" /> -<glyph unicode="µ" horiz-adv-x="1309" d="M168 -492v1598h235v-684q0 -252 218 -252q146 0 215 88.5t69 296.5v551h236v-1106h-183l-34 147h-13q-48 -83 -119.5 -125t-175.5 -42q-140 0 -219 90h-4q3 -28 6.5 -117t3.5 -125v-320h-235z" /> -<glyph unicode="¶" horiz-adv-x="1341" d="M113 1042q0 260 109 387t341 127h580v-1816h-137v1663h-191v-1663h-137v819q-62 -18 -146 -18q-216 0 -317.5 125t-101.5 376z" /> -<glyph unicode="·" horiz-adv-x="563" d="M133 723q0 73 38 112t110 39q73 0 111 -40.5t38 -110.5q0 -71 -38.5 -112.5t-110.5 -41.5t-110 41t-38 113z" /> -<glyph unicode="¸" horiz-adv-x="442" d="M0 -340q54 -14 123 -14q54 0 85.5 16.5t31.5 61.5q0 85 -179 110l84 166h152l-41 -88q80 -21 125 -68.5t45 -113.5q0 -222 -305 -222q-66 0 -121 15v137z" /> -<glyph unicode="¹" horiz-adv-x="743" d="M84 1253l281 209h167v-876h-186v512l3 103l5 91q-17 -18 -40.5 -40t-141.5 -111z" /> -<glyph unicode="º" horiz-adv-x="780" d="M61 1124q0 169 88.5 262t241.5 93q152 0 240 -94.5t88 -260.5q0 -164 -87.5 -259t-244.5 -95q-150 0 -238 95.5t-88 258.5zM223 1124q0 -111 39 -166t127 -55t127 55t39 166q0 113 -39 167.5t-127 54.5t-127 -54.5t-39 -167.5z" /> -<glyph unicode="»" horiz-adv-x="1139" d="M80 201l282 348l-282 350l168 94l358 -432v-26l-358 -431zM530 201l283 348l-283 350l168 94l359 -432v-26l-359 -431z" /> -<glyph unicode="¼" horiz-adv-x="1700" d="M285 0l858 1462h190l-856 -1462h-192zM60 1253l281 209h167v-876h-186v512l3 103l5 91q-17 -18 -40.5 -40t-141.5 -111zM876 177v127l396 579h188v-563h125v-143h-125v-176h-192v176h-392zM1038 320h230v178q0 97 6 197q-52 -104 -88 -158z" /> -<glyph unicode="½" horiz-adv-x="1700" d="M250 0l858 1462h190l-856 -1462h-192zM46 1253l281 209h167v-876h-186v512l3 103l5 91q-17 -18 -40.5 -40t-141.5 -111zM981 1v135l230 225q117 112 149.5 165t32.5 112q0 52 -32 79t-83 27q-93 0 -201 -88l-94 121q139 119 309 119q136 0 211.5 -66t75.5 -180 q0 -83 -46 -158.5t-183 -202.5l-139 -129h397v-159h-627z" /> -<glyph unicode="¾" horiz-adv-x="1700" d="M367 0l858 1462h190l-856 -1462h-192zM931 177v127l396 579h188v-563h125v-143h-125v-176h-192v176h-392zM1093 320h230v178q0 97 6 197q-52 -104 -88 -158zM55 631v157q145 -79 270 -79q179 0 179 135q0 125 -199 125h-115v133h105q184 0 184 129q0 52 -34.5 80 t-90.5 28q-57 0 -105.5 -20t-105.5 -57l-84 114q61 46 134 75.5t171 29.5q134 0 212.5 -61.5t78.5 -168.5q0 -75 -40.5 -122.5t-119.5 -86.5q94 -21 141.5 -76t47.5 -132q0 -127 -93 -196t-266 -69q-148 0 -270 62z" /> -<glyph unicode="¿" horiz-adv-x="928" d="M55 -33q0 73 21 130t64 109t157 142q94 76 125 124.5t31 127.5v45h198v-63q0 -106 -41 -181t-143 -155q-124 -98 -155 -147t-31 -124q0 -78 54 -125t161 -47q90 0 174 27.5t166 65.5l82 -179q-220 -110 -424 -110q-207 0 -323 95.5t-116 264.5zM395 965q0 69 38 111 t110 42t110.5 -40.5t38.5 -112.5q0 -74 -37.5 -113t-111.5 -39q-72 0 -110 39.5t-38 112.5z" /> -<glyph unicode="À" horiz-adv-x="1354" d="M0 0l547 1468h260l547 -1468h-254l-146 406h-559l-143 -406h-252zM465 612h426l-137 398q-15 40 -41.5 126t-36.5 126q-27 -123 -79 -269zM334 1886v21h273q38 -70 103.5 -161t109.5 -142v-25h-158q-69 52 -174.5 150.5t-153.5 156.5z" /> -<glyph unicode="Á" horiz-adv-x="1354" d="M0 0l547 1468h260l547 -1468h-254l-146 406h-559l-143 -406h-252zM465 612h426l-137 398q-15 40 -41.5 126t-36.5 126q-27 -123 -79 -269zM532 1579v25q57 70 117.5 156t95.5 147h273v-21q-52 -61 -155.5 -157.5t-174.5 -149.5h-156z" /> -<glyph unicode="Â" horiz-adv-x="1354" d="M0 0l547 1468h260l547 -1468h-254l-146 406h-559l-143 -406h-252zM465 612h426l-137 398q-15 40 -41.5 126t-36.5 126q-27 -123 -79 -269zM286 1579v25q191 198 254 303h260q63 -110 256 -303v-25h-159q-123 73 -228 180q-103 -103 -225 -180h-158z" /> -<glyph unicode="Ã" horiz-adv-x="1354" d="M0 0l547 1468h260l547 -1468h-254l-146 406h-559l-143 -406h-252zM465 612h426l-137 398q-15 40 -41.5 126t-36.5 126q-27 -123 -79 -269zM281 1577q12 139 77.5 212t167.5 73q43 0 84 -17.5t80 -39t75.5 -39t70.5 -17.5q79 0 106 115h125q-12 -134 -77 -209.5 t-169 -75.5q-42 0 -82.5 17.5t-79.5 39t-76 39t-71 17.5q-81 0 -109 -115h-122z" /> -<glyph unicode="Ä" horiz-adv-x="1354" d="M0 0l547 1468h260l547 -1468h-254l-146 406h-559l-143 -406h-252zM465 612h426l-137 398q-15 40 -41.5 126t-36.5 126q-27 -123 -79 -269zM363 1737q0 62 33.5 89.5t81.5 27.5q53 0 84.5 -31t31.5 -86q0 -53 -32 -85t-84 -32q-48 0 -81.5 29t-33.5 88zM756 1737 q0 62 33.5 89.5t81.5 27.5q53 0 85 -31t32 -86q0 -54 -33 -85.5t-84 -31.5q-48 0 -81.5 29t-33.5 88z" /> -<glyph unicode="Å" horiz-adv-x="1354" d="M0 0l547 1468h260l547 -1468h-254l-146 406h-559l-143 -406h-252zM465 612h426l-137 398q-15 40 -41.5 126t-36.5 126q-27 -123 -79 -269zM438 1575q0 101 63.5 163.5t172.5 62.5q104 0 171.5 -62t67.5 -162q0 -102 -65.5 -165.5t-173.5 -63.5t-172 62.5t-64 164.5z M567 1575q0 -106 107 -106q46 0 76 27.5t30 78.5q0 50 -30 78.5t-76 28.5q-47 0 -77 -28.5t-30 -78.5z" /> -<glyph unicode="Æ" horiz-adv-x="1868" d="M-2 0l678 1462h1071v-202h-571v-398h532v-200h-532v-459h571v-203h-811v406h-504l-188 -406h-246zM522 612h414v641h-123z" /> -<glyph unicode="Ç" horiz-adv-x="1298" d="M121 731q0 228 83.5 399t241.5 262t371 91q224 0 414 -94l-86 -199q-74 35 -156.5 61.5t-173.5 26.5q-206 0 -324 -146t-118 -403q0 -269 113.5 -407t328.5 -138q93 0 180 18.5t181 47.5v-205q-172 -65 -390 -65q-321 0 -493 194.5t-172 556.5zM526 -340q54 -14 123 -14 q54 0 85.5 16.5t31.5 61.5q0 85 -179 110l84 166h152l-41 -88q80 -21 125 -68.5t45 -113.5q0 -222 -305 -222q-66 0 -121 15v137z" /> -<glyph unicode="È" horiz-adv-x="1143" d="M193 0v1462h827v-202h-588v-398h551v-200h-551v-459h588v-203h-827zM289 1886v21h273q38 -70 103.5 -161t109.5 -142v-25h-158q-69 52 -174.5 150.5t-153.5 156.5z" /> -<glyph unicode="É" horiz-adv-x="1143" d="M193 0v1462h827v-202h-588v-398h551v-200h-551v-459h588v-203h-827zM440 1579v25q57 70 117.5 156t95.5 147h273v-21q-52 -61 -155.5 -157.5t-174.5 -149.5h-156z" /> -<glyph unicode="Ê" horiz-adv-x="1143" d="M193 0v1462h827v-202h-588v-398h551v-200h-551v-459h588v-203h-827zM220 1579v25q191 198 254 303h260q63 -110 256 -303v-25h-159q-123 73 -228 180q-103 -103 -225 -180h-158z" /> -<glyph unicode="Ë" horiz-adv-x="1143" d="M193 0v1462h827v-202h-588v-398h551v-200h-551v-459h588v-203h-827zM297 1737q0 62 33.5 89.5t81.5 27.5q53 0 84.5 -31t31.5 -86q0 -53 -32 -85t-84 -32q-48 0 -81.5 29t-33.5 88zM690 1737q0 62 33.5 89.5t81.5 27.5q53 0 85 -31t32 -86q0 -54 -33 -85.5t-84 -31.5 q-48 0 -81.5 29t-33.5 88z" /> -<glyph unicode="Ì" horiz-adv-x="625" d="M193 0v1462h239v-1462h-239zM-6 1886v21h273q38 -70 103.5 -161t109.5 -142v-25h-158q-69 52 -174.5 150.5t-153.5 156.5z" /> -<glyph unicode="Í" horiz-adv-x="625" d="M193 0v1462h239v-1462h-239zM179 1579v25q57 70 117.5 156t95.5 147h273v-21q-52 -61 -155.5 -157.5t-174.5 -149.5h-156z" /> -<glyph unicode="Î" horiz-adv-x="625" d="M193 0v1462h239v-1462h-239zM-75 1579v25q191 198 254 303h260q63 -110 256 -303v-25h-159q-123 73 -228 180q-103 -103 -225 -180h-158z" /> -<glyph unicode="Ï" horiz-adv-x="625" d="M193 0v1462h239v-1462h-239zM1 1737q0 62 33.5 89.5t81.5 27.5q53 0 84.5 -31t31.5 -86q0 -53 -32 -85t-84 -32q-48 0 -81.5 29t-33.5 88zM394 1737q0 62 33.5 89.5t81.5 27.5q53 0 85 -31t32 -86q0 -54 -33 -85.5t-84 -31.5q-48 0 -81.5 29t-33.5 88z" /> -<glyph unicode="Ð" horiz-adv-x="1497" d="M47 623v200h146v639h446q347 0 541 -188.5t194 -528.5q0 -360 -201 -552.5t-579 -192.5h-401v623h-146zM432 201h160q530 0 530 536q0 260 -124.5 392.5t-368.5 132.5h-197v-439h307v-200h-307v-422z" /> -<glyph unicode="Ñ" horiz-adv-x="1604" d="M193 0v1462h290l717 -1159h6q-2 23 -8 167.5t-6 225.5v766h219v-1462h-293l-719 1165h-8l5 -65q14 -186 14 -340v-760h-217zM414 1577q12 139 77.5 212t167.5 73q43 0 84 -17.5t80 -39t75.5 -39t70.5 -17.5q79 0 106 115h125q-12 -134 -77 -209.5t-169 -75.5 q-42 0 -82.5 17.5t-79.5 39t-76 39t-71 17.5q-81 0 -109 -115h-122z" /> -<glyph unicode="Ò" horiz-adv-x="1612" d="M121 735q0 362 178.5 556t509.5 194q326 0 504 -197t178 -555q0 -357 -178.5 -555t-505.5 -198q-331 0 -508.5 196.5t-177.5 558.5zM375 733q0 -270 109 -409.5t323 -139.5q213 0 321.5 138t108.5 411q0 269 -107.5 408t-320.5 139q-215 0 -324.5 -139t-109.5 -408z M481 1886v21h273q38 -70 103.5 -161t109.5 -142v-25h-158q-69 52 -174.5 150.5t-153.5 156.5z" /> -<glyph unicode="Ó" horiz-adv-x="1612" d="M121 735q0 362 178.5 556t509.5 194q326 0 504 -197t178 -555q0 -357 -178.5 -555t-505.5 -198q-331 0 -508.5 196.5t-177.5 558.5zM375 733q0 -270 109 -409.5t323 -139.5q213 0 321.5 138t108.5 411q0 269 -107.5 408t-320.5 139q-215 0 -324.5 -139t-109.5 -408z M657 1579v25q57 70 117.5 156t95.5 147h273v-21q-52 -61 -155.5 -157.5t-174.5 -149.5h-156z" /> -<glyph unicode="Ô" horiz-adv-x="1612" d="M121 735q0 362 178.5 556t509.5 194q326 0 504 -197t178 -555q0 -357 -178.5 -555t-505.5 -198q-331 0 -508.5 196.5t-177.5 558.5zM375 733q0 -270 109 -409.5t323 -139.5q213 0 321.5 138t108.5 411q0 269 -107.5 408t-320.5 139q-215 0 -324.5 -139t-109.5 -408z M413 1579v25q191 198 254 303h260q63 -110 256 -303v-25h-159q-123 73 -228 180q-103 -103 -225 -180h-158z" /> -<glyph unicode="Õ" horiz-adv-x="1612" d="M121 735q0 362 178.5 556t509.5 194q326 0 504 -197t178 -555q0 -357 -178.5 -555t-505.5 -198q-331 0 -508.5 196.5t-177.5 558.5zM375 733q0 -270 109 -409.5t323 -139.5q213 0 321.5 138t108.5 411q0 269 -107.5 408t-320.5 139q-215 0 -324.5 -139t-109.5 -408z M410 1577q12 139 77.5 212t167.5 73q43 0 84 -17.5t80 -39t75.5 -39t70.5 -17.5q79 0 106 115h125q-12 -134 -77 -209.5t-169 -75.5q-42 0 -82.5 17.5t-79.5 39t-76 39t-71 17.5q-81 0 -109 -115h-122z" /> -<glyph unicode="Ö" horiz-adv-x="1612" d="M121 735q0 362 178.5 556t509.5 194q326 0 504 -197t178 -555q0 -357 -178.5 -555t-505.5 -198q-331 0 -508.5 196.5t-177.5 558.5zM375 733q0 -270 109 -409.5t323 -139.5q213 0 321.5 138t108.5 411q0 269 -107.5 408t-320.5 139q-215 0 -324.5 -139t-109.5 -408z M496 1737q0 62 33.5 89.5t81.5 27.5q53 0 84.5 -31t31.5 -86q0 -53 -32 -85t-84 -32q-48 0 -81.5 29t-33.5 88zM889 1737q0 62 33.5 89.5t81.5 27.5q53 0 85 -31t32 -86q0 -54 -33 -85.5t-84 -31.5q-48 0 -81.5 29t-33.5 88z" /> -<glyph unicode="×" d="M131 1049l125 127l328 -326l329 326l125 -123l-329 -330l325 -328l-123 -125l-329 326l-324 -326l-125 125l324 328z" /> -<glyph unicode="Ø" horiz-adv-x="1612" d="M121 735q0 362 178.5 556t509.5 194q199 0 354 -82l90 129l142 -92l-99 -140q195 -199 195 -567q0 -357 -178.5 -555t-505.5 -198q-213 0 -361 81l-94 -137l-141 94l98 144q-188 196 -188 573zM375 733q0 -231 78 -362l587 850q-92 59 -231 59q-215 0 -324.5 -139 t-109.5 -408zM571 244q97 -60 236 -60q213 0 321.5 138t108.5 411q0 225 -80 361z" /> -<glyph unicode="Ù" horiz-adv-x="1520" d="M180 520v942h240v-925q0 -181 84 -267t258 -86q338 0 338 355v923h239v-946q0 -162 -69.5 -283.5t-201 -187t-314.5 -65.5q-272 0 -423 144t-151 396zM417 1886v21h273q38 -70 103.5 -161t109.5 -142v-25h-158q-69 52 -174.5 150.5t-153.5 156.5z" /> -<glyph unicode="Ú" horiz-adv-x="1520" d="M180 520v942h240v-925q0 -181 84 -267t258 -86q338 0 338 355v923h239v-946q0 -162 -69.5 -283.5t-201 -187t-314.5 -65.5q-272 0 -423 144t-151 396zM600 1579v25q57 70 117.5 156t95.5 147h273v-21q-52 -61 -155.5 -157.5t-174.5 -149.5h-156z" /> -<glyph unicode="Û" horiz-adv-x="1520" d="M180 520v942h240v-925q0 -181 84 -267t258 -86q338 0 338 355v923h239v-946q0 -162 -69.5 -283.5t-201 -187t-314.5 -65.5q-272 0 -423 144t-151 396zM366 1579v25q191 198 254 303h260q63 -110 256 -303v-25h-159q-123 73 -228 180q-103 -103 -225 -180h-158z" /> -<glyph unicode="Ü" horiz-adv-x="1520" d="M180 520v942h240v-925q0 -181 84 -267t258 -86q338 0 338 355v923h239v-946q0 -162 -69.5 -283.5t-201 -187t-314.5 -65.5q-272 0 -423 144t-151 396zM445 1737q0 62 33.5 89.5t81.5 27.5q53 0 84.5 -31t31.5 -86q0 -53 -32 -85t-84 -32q-48 0 -81.5 29t-33.5 88z M838 1737q0 62 33.5 89.5t81.5 27.5q53 0 85 -31t32 -86q0 -54 -33 -85.5t-84 -31.5q-48 0 -81.5 29t-33.5 88z" /> -<glyph unicode="Ý" horiz-adv-x="1212" d="M0 1462h260l346 -667l346 667h260l-487 -895v-567h-240v559zM450 1579v25q57 70 117.5 156t95.5 147h273v-21q-52 -61 -155.5 -157.5t-174.5 -149.5h-156z" /> -<glyph unicode="Þ" horiz-adv-x="1268" d="M193 0v1462h239v-243h197q268 0 404 -112t136 -331q0 -227 -146 -349t-423 -122h-168v-305h-239zM432 504h133q187 0 273 63t86 203q0 127 -78 188.5t-250 61.5h-164v-516z" /> -<glyph unicode="ß" horiz-adv-x="1364" d="M168 0v1169q0 193 128.5 295.5t367.5 102.5q225 0 355 -84t130 -230q0 -74 -38.5 -140.5t-104.5 -117.5q-90 -69 -117 -98t-27 -57q0 -30 22.5 -55.5t79.5 -63.5l95 -64q92 -62 135.5 -109.5t65.5 -103.5t22 -127q0 -165 -107 -251t-311 -86q-190 0 -299 65v199 q58 -37 139 -61.5t148 -24.5q192 0 192 151q0 61 -34.5 105t-155.5 118q-119 73 -171 135t-52 146q0 63 34 115.5t105 105.5q75 55 107 97.5t32 93.5q0 72 -67 112.5t-178 40.5q-127 0 -194 -54t-67 -159v-1165h-235z" /> -<glyph unicode="à" horiz-adv-x="1188" d="M90 317q0 171 127 258t387 95l191 6v59q0 106 -49.5 158.5t-153.5 52.5q-85 0 -163 -25t-150 -59l-76 168q90 47 197 71.5t202 24.5q211 0 318.5 -92t107.5 -289v-745h-168l-47 154h-8q-80 -101 -161 -137.5t-208 -36.5q-163 0 -254.5 88t-91.5 249zM334 315 q0 -74 44 -114.5t132 -40.5q128 0 205.5 71.5t77.5 200.5v96l-142 -6q-166 -6 -241.5 -55.5t-75.5 -151.5zM259 1548v21h273q38 -70 103.5 -161t109.5 -142v-25h-158q-69 52 -174.5 150.5t-153.5 156.5z" /> -<glyph unicode="á" horiz-adv-x="1188" d="M90 317q0 171 127 258t387 95l191 6v59q0 106 -49.5 158.5t-153.5 52.5q-85 0 -163 -25t-150 -59l-76 168q90 47 197 71.5t202 24.5q211 0 318.5 -92t107.5 -289v-745h-168l-47 154h-8q-80 -101 -161 -137.5t-208 -36.5q-163 0 -254.5 88t-91.5 249zM334 315 q0 -74 44 -114.5t132 -40.5q128 0 205.5 71.5t77.5 200.5v96l-142 -6q-166 -6 -241.5 -55.5t-75.5 -151.5zM438 1241v25q57 70 117.5 156t95.5 147h273v-21q-52 -61 -155.5 -157.5t-174.5 -149.5h-156z" /> -<glyph unicode="â" horiz-adv-x="1188" d="M90 317q0 171 127 258t387 95l191 6v59q0 106 -49.5 158.5t-153.5 52.5q-85 0 -163 -25t-150 -59l-76 168q90 47 197 71.5t202 24.5q211 0 318.5 -92t107.5 -289v-745h-168l-47 154h-8q-80 -101 -161 -137.5t-208 -36.5q-163 0 -254.5 88t-91.5 249zM334 315 q0 -74 44 -114.5t132 -40.5q128 0 205.5 71.5t77.5 200.5v96l-142 -6q-166 -6 -241.5 -55.5t-75.5 -151.5zM203 1241v25q191 198 254 303h260q63 -110 256 -303v-25h-159q-123 73 -228 180q-103 -103 -225 -180h-158z" /> -<glyph unicode="ã" horiz-adv-x="1188" d="M90 317q0 171 127 258t387 95l191 6v59q0 106 -49.5 158.5t-153.5 52.5q-85 0 -163 -25t-150 -59l-76 168q90 47 197 71.5t202 24.5q211 0 318.5 -92t107.5 -289v-745h-168l-47 154h-8q-80 -101 -161 -137.5t-208 -36.5q-163 0 -254.5 88t-91.5 249zM334 315 q0 -74 44 -114.5t132 -40.5q128 0 205.5 71.5t77.5 200.5v96l-142 -6q-166 -6 -241.5 -55.5t-75.5 -151.5zM208 1239q12 139 77.5 212t167.5 73q43 0 84 -17.5t80 -39t75.5 -39t70.5 -17.5q79 0 106 115h125q-12 -134 -77 -209.5t-169 -75.5q-42 0 -82.5 17.5t-79.5 39 t-76 39t-71 17.5q-81 0 -109 -115h-122z" /> -<glyph unicode="ä" horiz-adv-x="1188" d="M90 317q0 171 127 258t387 95l191 6v59q0 106 -49.5 158.5t-153.5 52.5q-85 0 -163 -25t-150 -59l-76 168q90 47 197 71.5t202 24.5q211 0 318.5 -92t107.5 -289v-745h-168l-47 154h-8q-80 -101 -161 -137.5t-208 -36.5q-163 0 -254.5 88t-91.5 249zM334 315 q0 -74 44 -114.5t132 -40.5q128 0 205.5 71.5t77.5 200.5v96l-142 -6q-166 -6 -241.5 -55.5t-75.5 -151.5zM282 1399q0 62 33.5 89.5t81.5 27.5q53 0 84.5 -31t31.5 -86q0 -53 -32 -85t-84 -32q-48 0 -81.5 29t-33.5 88zM675 1399q0 62 33.5 89.5t81.5 27.5q53 0 85 -31 t32 -86q0 -54 -33 -85.5t-84 -31.5q-48 0 -81.5 29t-33.5 88z" /> -<glyph unicode="å" horiz-adv-x="1188" d="M90 317q0 171 127 258t387 95l191 6v59q0 106 -49.5 158.5t-153.5 52.5q-85 0 -163 -25t-150 -59l-76 168q90 47 197 71.5t202 24.5q211 0 318.5 -92t107.5 -289v-745h-168l-47 154h-8q-80 -101 -161 -137.5t-208 -36.5q-163 0 -254.5 88t-91.5 249zM334 315 q0 -74 44 -114.5t132 -40.5q128 0 205.5 71.5t77.5 200.5v96l-142 -6q-166 -6 -241.5 -55.5t-75.5 -151.5zM366 1466q0 101 63.5 163.5t172.5 62.5q104 0 171.5 -62t67.5 -162q0 -102 -65.5 -165.5t-173.5 -63.5t-172 62.5t-64 164.5zM495 1466q0 -106 107 -106 q46 0 76 27.5t30 78.5q0 50 -30 78.5t-76 28.5q-47 0 -77 -28.5t-30 -78.5z" /> -<glyph unicode="æ" horiz-adv-x="1817" d="M90 317q0 172 121.5 258.5t370.5 94.5l188 6v76q0 194 -201 194q-141 0 -307 -82l-74 166q88 47 192.5 71.5t203.5 24.5q241 0 340 -155q120 155 346 155q206 0 328 -134.5t122 -362.5v-127h-712q10 -336 301 -336q184 0 356 80v-191q-86 -41 -171.5 -58t-195.5 -17 q-140 0 -248.5 54.5t-175.5 164.5q-94 -125 -190.5 -172t-241.5 -47q-165 0 -258.5 90t-93.5 247zM334 315q0 -155 166 -155q124 0 196 72.5t72 199.5v96l-135 -6q-155 -6 -227 -54.5t-72 -152.5zM1014 670h473q0 130 -58.5 204t-162.5 74q-112 0 -177.5 -69.5t-74.5 -208.5 z" /> -<glyph unicode="ç" horiz-adv-x="1014" d="M102 547q0 279 136.5 429t394.5 150q175 0 315 -65l-71 -189q-149 58 -246 58q-287 0 -287 -381q0 -186 71.5 -279.5t209.5 -93.5q157 0 297 78v-205q-63 -37 -134.5 -53t-173.5 -16q-251 0 -381.5 146.5t-130.5 420.5zM356 -340q54 -14 123 -14q54 0 85.5 16.5 t31.5 61.5q0 85 -179 110l84 166h152l-41 -88q80 -21 125 -68.5t45 -113.5q0 -222 -305 -222q-66 0 -121 15v137z" /> -<glyph unicode="è" horiz-adv-x="1180" d="M102 545q0 271 135 426t371 155q219 0 346 -133t127 -366v-127h-737q5 -161 87 -247.5t231 -86.5q98 0 182.5 18.5t181.5 61.5v-191q-86 -41 -174 -58t-201 -17q-258 0 -403.5 150.5t-145.5 414.5zM348 670h502q-2 137 -66 207.5t-176 70.5t-179.5 -71t-80.5 -207z M281 1548v21h273q38 -70 103.5 -161t109.5 -142v-25h-158q-69 52 -174.5 150.5t-153.5 156.5z" /> -<glyph unicode="é" horiz-adv-x="1180" d="M102 545q0 271 135 426t371 155q219 0 346 -133t127 -366v-127h-737q5 -161 87 -247.5t231 -86.5q98 0 182.5 18.5t181.5 61.5v-191q-86 -41 -174 -58t-201 -17q-258 0 -403.5 150.5t-145.5 414.5zM348 670h502q-2 137 -66 207.5t-176 70.5t-179.5 -71t-80.5 -207z M458 1241v25q57 70 117.5 156t95.5 147h273v-21q-52 -61 -155.5 -157.5t-174.5 -149.5h-156z" /> -<glyph unicode="ê" horiz-adv-x="1180" d="M102 545q0 271 135 426t371 155q219 0 346 -133t127 -366v-127h-737q5 -161 87 -247.5t231 -86.5q98 0 182.5 18.5t181.5 61.5v-191q-86 -41 -174 -58t-201 -17q-258 0 -403.5 150.5t-145.5 414.5zM348 670h502q-2 137 -66 207.5t-176 70.5t-179.5 -71t-80.5 -207z M227 1241v25q191 198 254 303h260q63 -110 256 -303v-25h-159q-123 73 -228 180q-103 -103 -225 -180h-158z" /> -<glyph unicode="ë" horiz-adv-x="1180" d="M102 545q0 271 135 426t371 155q219 0 346 -133t127 -366v-127h-737q5 -161 87 -247.5t231 -86.5q98 0 182.5 18.5t181.5 61.5v-191q-86 -41 -174 -58t-201 -17q-258 0 -403.5 150.5t-145.5 414.5zM348 670h502q-2 137 -66 207.5t-176 70.5t-179.5 -71t-80.5 -207z M307 1399q0 62 33.5 89.5t81.5 27.5q53 0 84.5 -31t31.5 -86q0 -53 -32 -85t-84 -32q-48 0 -81.5 29t-33.5 88zM700 1399q0 62 33.5 89.5t81.5 27.5q53 0 85 -31t32 -86q0 -54 -33 -85.5t-84 -31.5q-48 0 -81.5 29t-33.5 88z" /> -<glyph unicode="ì" horiz-adv-x="571" d="M168 0v1106h235v-1106h-235zM-69 1548v21h273q38 -70 103.5 -161t109.5 -142v-25h-158q-69 52 -174.5 150.5t-153.5 156.5z" /> -<glyph unicode="í" horiz-adv-x="571" d="M168 0v1106h235v-1106h-235zM156 1241v25q57 70 117.5 156t95.5 147h273v-21q-52 -61 -155.5 -157.5t-174.5 -149.5h-156z" /> -<glyph unicode="î" horiz-adv-x="571" d="M168 0v1106h235v-1106h-235zM-100 1241v25q191 198 254 303h260q63 -110 256 -303v-25h-159q-123 73 -228 180q-103 -103 -225 -180h-158z" /> -<glyph unicode="ï" horiz-adv-x="571" d="M168 0v1106h235v-1106h-235zM-25 1399q0 62 33.5 89.5t81.5 27.5q53 0 84.5 -31t31.5 -86q0 -53 -32 -85t-84 -32q-48 0 -81.5 29t-33.5 88zM368 1399q0 62 33.5 89.5t81.5 27.5q53 0 85 -31t32 -86q0 -54 -33 -85.5t-84 -31.5q-48 0 -81.5 29t-33.5 88z" /> -<glyph unicode="ð" horiz-adv-x="1243" d="M102 481q0 231 131 365.5t351 134.5q214 0 301 -111l8 4q-62 189 -227 345l-250 -150l-88 133l204 119q-86 59 -167 102l84 146q140 -63 258 -144l231 138l88 -129l-188 -113q152 -140 231.5 -330t79.5 -424q0 -279 -137.5 -433t-388.5 -154q-235 0 -378 136t-143 365z M342 477q0 -153 74 -234t211 -81q148 0 215 91t67 269q0 127 -75.5 202t-206.5 75q-151 0 -218 -82t-67 -240z" /> -<glyph unicode="ñ" horiz-adv-x="1300" d="M168 0v1106h184l33 -145h12q50 79 142 122t204 43q398 0 398 -405v-721h-236v680q0 128 -51.5 191t-163.5 63q-149 0 -218 -88t-69 -295v-551h-235zM269 1239q12 139 77.5 212t167.5 73q43 0 84 -17.5t80 -39t75.5 -39t70.5 -17.5q79 0 106 115h125q-12 -134 -77 -209.5 t-169 -75.5q-42 0 -82.5 17.5t-79.5 39t-76 39t-71 17.5q-81 0 -109 -115h-122z" /> -<glyph unicode="ò" horiz-adv-x="1251" d="M102 555q0 269 138 420t389 151q240 0 380 -154.5t140 -416.5q0 -271 -139 -423t-387 -152q-155 0 -274 70t-183 201t-64 304zM344 555q0 -383 283 -383q280 0 280 383q0 379 -282 379q-148 0 -214.5 -98t-66.5 -281zM293 1548v21h273q38 -70 103.5 -161t109.5 -142v-25 h-158q-69 52 -174.5 150.5t-153.5 156.5z" /> -<glyph unicode="ó" horiz-adv-x="1251" d="M102 555q0 269 138 420t389 151q240 0 380 -154.5t140 -416.5q0 -271 -139 -423t-387 -152q-155 0 -274 70t-183 201t-64 304zM344 555q0 -383 283 -383q280 0 280 383q0 379 -282 379q-148 0 -214.5 -98t-66.5 -281zM473 1241v25q57 70 117.5 156t95.5 147h273v-21 q-52 -61 -155.5 -157.5t-174.5 -149.5h-156z" /> -<glyph unicode="ô" horiz-adv-x="1251" d="M102 555q0 269 138 420t389 151q240 0 380 -154.5t140 -416.5q0 -271 -139 -423t-387 -152q-155 0 -274 70t-183 201t-64 304zM344 555q0 -383 283 -383q280 0 280 383q0 379 -282 379q-148 0 -214.5 -98t-66.5 -281zM239 1241v25q191 198 254 303h260q63 -110 256 -303 v-25h-159q-123 73 -228 180q-103 -103 -225 -180h-158z" /> -<glyph unicode="õ" horiz-adv-x="1251" d="M102 555q0 269 138 420t389 151q240 0 380 -154.5t140 -416.5q0 -271 -139 -423t-387 -152q-155 0 -274 70t-183 201t-64 304zM344 555q0 -383 283 -383q280 0 280 383q0 379 -282 379q-148 0 -214.5 -98t-66.5 -281zM235 1239q12 139 77.5 212t167.5 73q43 0 84 -17.5 t80 -39t75.5 -39t70.5 -17.5q79 0 106 115h125q-12 -134 -77 -209.5t-169 -75.5q-42 0 -82.5 17.5t-79.5 39t-76 39t-71 17.5q-81 0 -109 -115h-122z" /> -<glyph unicode="ö" horiz-adv-x="1251" d="M102 555q0 269 138 420t389 151q240 0 380 -154.5t140 -416.5q0 -271 -139 -423t-387 -152q-155 0 -274 70t-183 201t-64 304zM344 555q0 -383 283 -383q280 0 280 383q0 379 -282 379q-148 0 -214.5 -98t-66.5 -281zM311 1399q0 62 33.5 89.5t81.5 27.5q53 0 84.5 -31 t31.5 -86q0 -53 -32 -85t-84 -32q-48 0 -81.5 29t-33.5 88zM704 1399q0 62 33.5 89.5t81.5 27.5q53 0 85 -31t32 -86q0 -54 -33 -85.5t-84 -31.5q-48 0 -81.5 29t-33.5 88z" /> -<glyph unicode="÷" d="M96 633v178h977v-178h-977zM457 373q0 64 31.5 99.5t95.5 35.5q61 0 93 -36t32 -99t-34 -100t-91 -37q-60 0 -93.5 35.5t-33.5 101.5zM457 1071q0 64 31.5 99.5t95.5 35.5q61 0 93 -36t32 -99t-34 -100t-91 -37q-60 0 -93.5 35.5t-33.5 101.5z" /> -<glyph unicode="ø" horiz-adv-x="1251" d="M102 555q0 269 138 420t389 151q144 0 258 -63l69 100l136 -92l-78 -108q135 -152 135 -408q0 -271 -139 -423t-387 -152q-144 0 -250 57l-76 -109l-135 90l82 117q-142 155 -142 420zM344 555q0 -135 37 -219l391 559q-60 39 -147 39q-148 0 -214.5 -98t-66.5 -281z M487 205q54 -33 140 -33q280 0 280 383q0 121 -33 203z" /> -<glyph unicode="ù" horiz-adv-x="1300" d="M158 383v723h237v-682q0 -127 52 -190.5t163 -63.5q148 0 217.5 88.5t69.5 296.5v551h236v-1106h-185l-33 145h-12q-49 -77 -139.5 -121t-206.5 -44q-201 0 -300 100t-99 303zM289 1548v21h273q38 -70 103.5 -161t109.5 -142v-25h-158q-69 52 -174.5 150.5t-153.5 156.5z " /> -<glyph unicode="ú" horiz-adv-x="1300" d="M158 383v723h237v-682q0 -127 52 -190.5t163 -63.5q148 0 217.5 88.5t69.5 296.5v551h236v-1106h-185l-33 145h-12q-49 -77 -139.5 -121t-206.5 -44q-201 0 -300 100t-99 303zM501 1241v25q57 70 117.5 156t95.5 147h273v-21q-52 -61 -155.5 -157.5t-174.5 -149.5h-156z " /> -<glyph unicode="û" horiz-adv-x="1300" d="M158 383v723h237v-682q0 -127 52 -190.5t163 -63.5q148 0 217.5 88.5t69.5 296.5v551h236v-1106h-185l-33 145h-12q-49 -77 -139.5 -121t-206.5 -44q-201 0 -300 100t-99 303zM260 1241v25q191 198 254 303h260q63 -110 256 -303v-25h-159q-123 73 -228 180 q-103 -103 -225 -180h-158z" /> -<glyph unicode="ü" horiz-adv-x="1300" d="M158 383v723h237v-682q0 -127 52 -190.5t163 -63.5q148 0 217.5 88.5t69.5 296.5v551h236v-1106h-185l-33 145h-12q-49 -77 -139.5 -121t-206.5 -44q-201 0 -300 100t-99 303zM332 1399q0 62 33.5 89.5t81.5 27.5q53 0 84.5 -31t31.5 -86q0 -53 -32 -85t-84 -32 q-48 0 -81.5 29t-33.5 88zM725 1399q0 62 33.5 89.5t81.5 27.5q53 0 85 -31t32 -86q0 -54 -33 -85.5t-84 -31.5q-48 0 -81.5 29t-33.5 88z" /> -<glyph unicode="ý" horiz-adv-x="1098" d="M0 1106h256l225 -627q51 -134 68 -252h8q9 55 33 133.5t254 745.5h254l-473 -1253q-129 -345 -430 -345q-78 0 -152 17v186q53 -12 121 -12q170 0 239 197l41 104zM401 1241v25q57 70 117.5 156t95.5 147h273v-21q-52 -61 -155.5 -157.5t-174.5 -149.5h-156z" /> -<glyph unicode="þ" horiz-adv-x="1276" d="M168 -492v2048h235v-430l-7 -138l-3 -27h10q61 86 142.5 125.5t187.5 39.5q206 0 322 -151t116 -420q0 -272 -116.5 -423.5t-321.5 -151.5q-219 0 -330 149h-14l8 -72l6 -92v-457h-235zM403 555q0 -202 64 -292.5t209 -90.5q254 0 254 385q0 190 -61.5 283.5t-194.5 93.5 q-142 0 -206.5 -82t-64.5 -260v-37z" /> -<glyph unicode="ÿ" horiz-adv-x="1098" d="M0 1106h256l225 -627q51 -134 68 -252h8q9 55 33 133.5t254 745.5h254l-473 -1253q-129 -345 -430 -345q-78 0 -152 17v186q53 -12 121 -12q170 0 239 197l41 104zM239 1399q0 62 33.5 89.5t81.5 27.5q53 0 84.5 -31t31.5 -86q0 -53 -32 -85t-84 -32q-48 0 -81.5 29 t-33.5 88zM632 1399q0 62 33.5 89.5t81.5 27.5q53 0 85 -31t32 -86q0 -54 -33 -85.5t-84 -31.5q-48 0 -81.5 29t-33.5 88z" /> -<glyph unicode="ı" horiz-adv-x="571" d="M168 0v1106h235v-1106h-235z" /> -<glyph unicode="Œ" horiz-adv-x="1942" d="M121 735q0 360 172 555t491 195q115 0 209 -23h826v-202h-576v-398h539v-200h-539v-459h576v-203h-820q-102 -20 -211 -20q-320 0 -493.5 196.5t-173.5 558.5zM371 733q0 -269 106 -409t314 -140q129 0 213 35v1024q-80 37 -211 37q-208 0 -315 -139t-107 -408z" /> -<glyph unicode="œ" horiz-adv-x="1966" d="M102 555q0 272 137 421.5t382 149.5q121 0 223 -49t168 -145q131 194 379 194q221 0 349 -133.5t128 -365.5v-127h-738q11 -164 85.5 -249t228.5 -85q102 0 187 18.5t181 61.5v-191q-84 -40 -171.5 -57.5t-202.5 -17.5q-281 0 -420 194q-132 -194 -400 -194 q-236 0 -376 155t-140 420zM344 555q0 -189 65.5 -286t211.5 -97q141 0 206.5 95.5t65.5 283.5q0 192 -66 287.5t-211 95.5q-143 0 -207.5 -95t-64.5 -284zM1137 670h497q0 134 -63 206t-178 72q-110 0 -177.5 -69.5t-78.5 -208.5z" /> -<glyph unicode="Ÿ" horiz-adv-x="1212" d="M0 1462h260l346 -667l346 667h260l-487 -895v-567h-240v559zM293 1737q0 62 33.5 89.5t81.5 27.5q53 0 84.5 -31t31.5 -86q0 -53 -32 -85t-84 -32q-48 0 -81.5 29t-33.5 88zM686 1737q0 62 33.5 89.5t81.5 27.5q53 0 85 -31t32 -86q0 -54 -33 -85.5t-84 -31.5 q-48 0 -81.5 29t-33.5 88z" /> -<glyph unicode="ˆ" horiz-adv-x="1227" d="M227 1241v25q191 198 254 303h260q63 -110 256 -303v-25h-159q-123 73 -228 180q-103 -103 -225 -180h-158z" /> -<glyph unicode="˚" horiz-adv-x="1182" d="M352 1466q0 101 63.5 163.5t172.5 62.5q104 0 171.5 -62t67.5 -162q0 -102 -65.5 -165.5t-173.5 -63.5t-172 62.5t-64 164.5zM481 1466q0 -106 107 -106q46 0 76 27.5t30 78.5q0 50 -30 78.5t-76 28.5q-47 0 -77 -28.5t-30 -78.5z" /> -<glyph unicode="˜" horiz-adv-x="1227" d="M236 1239q12 139 77.5 212t167.5 73q43 0 84 -17.5t80 -39t75.5 -39t70.5 -17.5q79 0 106 115h125q-12 -134 -77 -209.5t-169 -75.5q-42 0 -82.5 17.5t-79.5 39t-76 39t-71 17.5q-81 0 -109 -115h-122z" /> -<glyph unicode=" " horiz-adv-x="953" /> -<glyph unicode=" " horiz-adv-x="1907" /> -<glyph unicode=" " horiz-adv-x="953" /> -<glyph unicode=" " horiz-adv-x="1907" /> -<glyph unicode=" " horiz-adv-x="635" /> -<glyph unicode=" " horiz-adv-x="476" /> -<glyph unicode=" " horiz-adv-x="317" /> -<glyph unicode=" " horiz-adv-x="317" /> -<glyph unicode=" " horiz-adv-x="238" /> -<glyph unicode=" " horiz-adv-x="381" /> -<glyph unicode=" " horiz-adv-x="105" /> -<glyph unicode="‐" horiz-adv-x="659" d="M72 449v200h514v-200h-514z" /> -<glyph unicode="‑" horiz-adv-x="659" d="M72 449v200h514v-200h-514z" /> -<glyph unicode="‒" horiz-adv-x="659" d="M72 449v200h514v-200h-514z" /> -<glyph unicode="–" horiz-adv-x="1024" d="M82 455v190h860v-190h-860z" /> -<glyph unicode="—" horiz-adv-x="2048" d="M82 455v190h1884v-190h-1884z" /> -<glyph unicode="‘" horiz-adv-x="395" d="M25 983q20 83 71 224t105 255h170q-64 -256 -101 -501h-233z" /> -<glyph unicode="’" horiz-adv-x="395" d="M25 961q69 289 100 501h231l15 -22q-53 -209 -176 -479h-170z" /> -<glyph unicode="‚" horiz-adv-x="549" d="M63 -264q69 270 103 502h231l15 -23q-48 -186 -176 -479h-173z" /> -<glyph unicode="“" horiz-adv-x="813" d="M25 983q20 83 71 224t105 255h170q-64 -256 -101 -501h-233zM440 983q53 203 178 479h170q-69 -296 -100 -501h-233z" /> -<glyph unicode="”" horiz-adv-x="813" d="M25 961q69 289 100 501h231l15 -22q-53 -209 -176 -479h-170zM440 961q69 271 103 501h231l14 -22q-53 -209 -176 -479h-172z" /> -<glyph unicode="„" horiz-adv-x="944" d="M43 -264q66 260 102 502h232l14 -23q-55 -214 -176 -479h-172zM461 -264q66 260 102 502h232l14 -23q-48 -186 -176 -479h-172z" /> -<glyph unicode="•" horiz-adv-x="770" d="M131 748q0 138 66 210t188 72q121 0 187.5 -72.5t66.5 -209.5q0 -135 -67 -209t-187 -74t-187 72.5t-67 210.5z" /> -<glyph unicode="…" horiz-adv-x="1677" d="M133 125q0 73 38 112t110 39q73 0 111 -40.5t38 -110.5q0 -71 -38.5 -112.5t-110.5 -41.5t-110 41t-38 113zM690 125q0 73 38 112t110 39q73 0 111 -40.5t38 -110.5q0 -71 -38.5 -112.5t-110.5 -41.5t-110 41t-38 113zM1247 125q0 73 38 112t110 39q73 0 111 -40.5 t38 -110.5q0 -71 -38.5 -112.5t-110.5 -41.5t-110 41t-38 113z" /> -<glyph unicode=" " horiz-adv-x="381" /> -<glyph unicode="‹" horiz-adv-x="688" d="M82 535v26l356 432l168 -94l-282 -350l282 -348l-168 -97z" /> -<glyph unicode="›" horiz-adv-x="688" d="M80 201l282 348l-282 350l168 94l358 -432v-26l-358 -431z" /> -<glyph unicode="⁄" horiz-adv-x="266" d="M-393 0l858 1462h190l-856 -1462h-192z" /> -<glyph unicode=" " horiz-adv-x="476" /> -<glyph unicode="⁴" horiz-adv-x="743" d="M16 762v127l396 579h188v-563h125v-143h-125v-176h-192v176h-392zM178 905h230v178q0 97 6 197q-52 -104 -88 -158z" /> -<glyph unicode="€" horiz-adv-x="1188" d="M63 494v153h136l-2 37v37l2 65h-136v154h150q38 251 191 394t395 143q200 0 358 -88l-84 -187q-154 76 -274 76q-141 0 -230.5 -84t-119.5 -254h456v-154h-471l-2 -45v-55l2 -39h408v-153h-391q64 -312 364 -312q143 0 293 62v-203q-131 -61 -305 -61q-241 0 -391.5 132 t-196.5 382h-152z" /> -<glyph unicode="™" horiz-adv-x="1561" d="M27 1333v129h553v-129h-205v-592h-146v592h-202zM635 741v721h217l178 -534l187 534h210v-721h-147v414l4 129h-6l-193 -543h-122l-185 543h-6l4 -119v-424h-141z" /> -<glyph unicode="" horiz-adv-x="1105" d="M0 1105h1105v-1105h-1105v1105z" /> -<glyph unicode="fi" horiz-adv-x="1315" d="M35 928v110l182 72v72q0 196 92 290.5t281 94.5q124 0 244 -41l-62 -178q-87 28 -166 28q-80 0 -116.5 -49.5t-36.5 -148.5v-72h270v-178h-270v-928h-236v928h-182zM897 1399q0 63 34.5 97t98.5 34q62 0 96.5 -34t34.5 -97q0 -60 -34.5 -94.5t-96.5 -34.5 q-64 0 -98.5 34.5t-34.5 94.5zM911 0v1106h235v-1106h-235z" /> -<glyph unicode="fl" horiz-adv-x="1315" d="M35 928v110l182 72v72q0 196 92 290.5t281 94.5q124 0 244 -41l-62 -178q-87 28 -166 28q-80 0 -116.5 -49.5t-36.5 -148.5v-72h270v-178h-270v-928h-236v928h-182zM911 0v1556h235v-1556h-235z" /> -<glyph unicode="ffi" horiz-adv-x="2058" d="M35 928v110l182 72v72q0 196 92 290.5t281 94.5q124 0 244 -41l-62 -178q-87 28 -166 28q-80 0 -116.5 -49.5t-36.5 -148.5v-72h270v-178h-270v-928h-236v928h-182zM778 928v110l182 72v72q0 196 92 290.5t281 94.5q124 0 244 -41l-62 -178q-87 28 -166 28 q-80 0 -116.5 -49.5t-36.5 -148.5v-72h270v-178h-270v-928h-236v928h-182zM1641 1399q0 63 34.5 97t98.5 34q62 0 96.5 -34t34.5 -97q0 -60 -34.5 -94.5t-96.5 -34.5q-64 0 -98.5 34.5t-34.5 94.5zM1655 0v1106h235v-1106h-235z" /> -<glyph unicode="ffl" horiz-adv-x="2058" d="M35 928v110l182 72v72q0 196 92 290.5t281 94.5q124 0 244 -41l-62 -178q-87 28 -166 28q-80 0 -116.5 -49.5t-36.5 -148.5v-72h270v-178h-270v-928h-236v928h-182zM778 928v110l182 72v72q0 196 92 290.5t281 94.5q124 0 244 -41l-62 -178q-87 28 -166 28 q-80 0 -116.5 -49.5t-36.5 -148.5v-72h270v-178h-270v-928h-236v928h-182zM1655 0v1556h235v-1556h-235z" /> -</font> -</defs></svg> -\ No newline at end of file diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-Semibold-webfont.ttf b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-Semibold-webfont.ttf Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-Semibold-webfont.woff b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-Semibold-webfont.woff Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-SemiboldItalic-webfont.eot b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-SemiboldItalic-webfont.eot Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-SemiboldItalic-webfont.svg b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-SemiboldItalic-webfont.svg @@ -1,251 +0,0 @@ -<?xml version="1.0" standalone="no"?> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" > -<svg xmlns="http://www.w3.org/2000/svg"> -<metadata> -This is a custom SVG webfont generated by Font Squirrel. -Copyright : Digitized data copyright 20102011 Google Corporation -Foundry : Ascender Corporation -Foundry URL : httpwwwascendercorpcom -</metadata> -<defs> -<font id="OpenSansSemiboldItalic" horiz-adv-x="1128" > -<font-face units-per-em="2048" ascent="1638" descent="-410" /> -<missing-glyph horiz-adv-x="532" /> -<glyph unicode=" " horiz-adv-x="532" /> -<glyph unicode="	" horiz-adv-x="532" /> -<glyph unicode=" " horiz-adv-x="532" /> -<glyph unicode="!" horiz-adv-x="557" d="M33 96q0 80 45.5 130t130.5 50q57 0 91 -32.5t34 -93.5q0 -79 -47 -128t-123 -49q-62 0 -96.5 33.5t-34.5 89.5zM160 444l168 1018h272l-264 -1018h-176z" /> -<glyph unicode=""" horiz-adv-x="858" d="M213 934l72 528h231l-151 -528h-152zM588 934l74 528h231l-152 -528h-153z" /> -<glyph unicode="#" horiz-adv-x="1323" d="M51 418l17 168h280l84 286h-264l16 168h295l121 422h178l-121 -422h252l121 422h174l-121 -422h252l-14 -168h-285l-84 -286h271l-15 -168h-303l-121 -418h-180l123 418h-248l-121 -418h-174l117 418h-250zM526 586h250l82 286h-250z" /> -<glyph unicode="$" d="M61 172v209q78 -42 179.5 -70t193.5 -30l84 387q-156 56 -223.5 138.5t-67.5 199.5q0 167 118.5 267.5t324.5 117.5l37 163h135l-35 -165q161 -16 289 -82l-86 -185q-134 66 -244 74l-80 -371q128 -51 186.5 -95t86.5 -101t28 -135q0 -172 -119.5 -277t-337.5 -125 l-45 -211h-135l45 211q-197 13 -334 80zM451 1016q0 -98 110 -139l68 319q-89 -11 -133.5 -57.5t-44.5 -122.5zM571 285q86 11 136.5 60t50.5 126q0 101 -115 145z" /> -<glyph unicode="%" horiz-adv-x="1688" d="M141 872q0 166 53 313.5t142.5 222.5t208.5 75q127 0 193.5 -76t66.5 -221q0 -160 -55.5 -313.5t-146.5 -230.5t-206 -77q-124 0 -190 79t-66 228zM231 0l1086 1462h194l-1085 -1462h-195zM334 866q0 -135 80 -135q52 0 95.5 58t73 175.5t29.5 219.5q0 131 -82 131 q-55 0 -99 -61t-70.5 -173t-26.5 -215zM940 279q0 171 53 320t142.5 223.5t207.5 74.5q127 0 195 -75t68 -218q0 -161 -55.5 -315.5t-146.5 -231.5t-204 -77q-127 0 -193.5 76.5t-66.5 222.5zM1133 281q0 -134 81 -134q52 0 96 58.5t73.5 174.5t29.5 220q0 131 -84 131 q-52 0 -95.5 -57.5t-72 -171t-28.5 -221.5z" /> -<glyph unicode="&" horiz-adv-x="1411" d="M66 350q0 147 85.5 254t286.5 205q-88 151 -88 283q0 180 112.5 286.5t297.5 106.5q160 0 252 -81t92 -218q0 -129 -89.5 -230t-293.5 -192l235 -326q109 112 181 295h233q-113 -270 -297 -454l205 -279h-277l-94 131q-106 -80 -211 -115.5t-229 -35.5 q-190 0 -295.5 97.5t-105.5 272.5zM305 371q0 -86 56 -140.5t147 -54.5q77 0 147 27t144 82l-264 381q-133 -74 -181.5 -141.5t-48.5 -153.5zM567 1102q0 -109 62 -201q147 75 199.5 133.5t52.5 126.5q0 66 -36 101.5t-97 35.5q-87 0 -134 -54t-47 -142z" /> -<glyph unicode="'" horiz-adv-x="483" d="M213 934l72 528h231l-151 -528h-152z" /> -<glyph unicode="(" horiz-adv-x="639" d="M78 276q0 343 124.5 632.5t379.5 553.5h209q-498 -548 -498 -1190q0 -329 115 -596h-183q-147 261 -147 600z" /> -<glyph unicode=")" horiz-adv-x="639" d="M-154 -324q498 548 498 1190q0 327 -115 596h183q147 -265 147 -602q0 -342 -123 -629.5t-381 -554.5h-209z" /> -<glyph unicode="*" horiz-adv-x="1122" d="M193 1167l71 195l354 -178l37 383l213 -43l-116 -367l403 23l-12 -205l-367 45l170 -361l-205 -61l-102 371l-227 -312l-162 144l293 266z" /> -<glyph unicode="+" d="M117 631v180h379v381h180v-381h377v-180h-377v-375h-180v375h-379z" /> -<glyph unicode="," horiz-adv-x="530" d="M-102 -264q105 238 200 502h236l8 -23q-125 -260 -266 -479h-178z" /> -<glyph unicode="-" horiz-adv-x="649" d="M47 446l45 203h502l-45 -203h-502z" /> -<glyph unicode="." horiz-adv-x="551" d="M33 94q0 83 47 132.5t131 49.5q56 0 89.5 -31.5t33.5 -92.5q0 -78 -47.5 -129.5t-124.5 -51.5q-66 0 -97.5 35.5t-31.5 87.5z" /> -<glyph unicode="/" horiz-adv-x="788" d="M-92 0l811 1462h233l-811 -1462h-233z" /> -<glyph unicode="0" d="M92 471q0 284 83 526t222.5 365t321.5 123q187 0 284 -118.5t97 -354.5q0 -306 -79 -546.5t-219 -363t-325 -122.5q-194 0 -289.5 127.5t-95.5 363.5zM330 469q0 -143 39 -218t129 -75q100 0 182.5 113.5t132 316.5t49.5 414q0 268 -162 268q-97 0 -180 -112 t-136.5 -312.5t-53.5 -394.5z" /> -<glyph unicode="1" d="M242 1145l508 317h198l-311 -1462h-238l189 870q28 150 82 324q-57 -55 -135 -102l-187 -117z" /> -<glyph unicode="2" d="M-18 0l36 180l471 422q176 159 238.5 231t90.5 133.5t28 131.5q0 85 -49.5 134.5t-139.5 49.5q-70 0 -139 -30t-170 -109l-115 160q120 97 231 138.5t228 41.5q181 0 288 -93t107 -251q0 -108 -39 -201t-123 -190.5t-284 -268.5l-311 -264v-8h622l-41 -207h-929z" /> -<glyph unicode="3" d="M31 59v215q84 -49 185.5 -75.5t195.5 -26.5q157 0 245 71.5t88 196.5q0 219 -278 219h-133l37 183h106q164 0 267.5 74.5t103.5 199.5q0 79 -49.5 124.5t-139.5 45.5q-72 0 -146.5 -25.5t-162.5 -84.5l-104 161q120 81 225.5 113.5t226.5 32.5q183 0 286 -88.5 t103 -241.5q0 -158 -99 -264t-269 -137v-7q127 -24 196.5 -106t69.5 -205q0 -133 -68 -236.5t-196.5 -160.5t-304.5 -57q-225 0 -385 79z" /> -<glyph unicode="4" d="M-4 317l37 197l803 952h254l-201 -952h201l-43 -197h-201l-68 -317h-229l69 317h-622zM262 514h397l68 309q31 136 100 377h-8q-51 -86 -135 -186z" /> -<glyph unicode="5" d="M53 59v217q167 -100 342 -100q173 0 270 83t97 230q0 105 -62 168.5t-188 63.5q-95 0 -225 -35l-88 68l200 708h713l-45 -209h-506l-106 -364q93 18 155 18q181 0 288.5 -103.5t107.5 -285.5q0 -161 -70 -283t-204 -188.5t-324 -66.5q-214 0 -355 79z" /> -<glyph unicode="6" d="M111 446q0 205 60.5 406t165 343t251 215t342.5 73q117 0 203 -25l-43 -194q-72 22 -181 22q-205 0 -337 -129.5t-197 -392.5h6q125 170 326 170q156 0 243.5 -99t87.5 -272q0 -162 -68.5 -301t-185.5 -210.5t-270 -71.5q-194 0 -298.5 120t-104.5 346zM340 418 q0 -110 49.5 -177t140.5 -67q81 0 143 48.5t96 134.5t34 188q0 200 -178 200q-51 0 -95.5 -19t-79 -48t-58.5 -64.5t-39 -82t-13 -113.5z" /> -<glyph unicode="7" d="M125 0l754 1257h-674l43 205h932l-33 -168l-758 -1294h-264z" /> -<glyph unicode="8" d="M76 348q0 297 368 432q-91 70 -130.5 145t-39.5 162q0 179 127 288.5t330 109.5q179 0 283 -89t104 -239q0 -132 -79 -229.5t-248 -163.5q120 -78 172.5 -165.5t52.5 -201.5q0 -121 -61.5 -216.5t-175.5 -148t-271 -52.5q-203 0 -317.5 100t-114.5 268zM311 369 q0 -93 59 -149t158 -56q115 0 184.5 64t69.5 167q0 91 -48.5 157.5t-139.5 119.5q-149 -54 -216 -126.5t-67 -176.5zM504 1096q0 -83 39 -137t104 -93q115 43 177.5 105t62.5 157q0 81 -48 126.5t-128 45.5q-93 0 -150 -56t-57 -148z" /> -<glyph unicode="9" d="M92 12v207q121 -43 236 -43q188 0 306 123t177 389h-6q-113 -160 -305 -160q-165 0 -255.5 102t-90.5 288q0 156 67 289t186.5 204.5t274.5 71.5q192 0 294.5 -119.5t102.5 -345.5q0 -205 -58 -414.5t-152.5 -349t-226 -207t-310.5 -67.5q-133 0 -240 32zM387 932 q0 -105 46 -160t134 -55q117 0 198 94t81 240q0 108 -48 172.5t-134 64.5q-82 0 -145.5 -47t-97.5 -130t-34 -179z" /> -<glyph unicode=":" horiz-adv-x="551" d="M33 94q0 83 47 132.5t131 49.5q56 0 89.5 -31.5t33.5 -92.5q0 -78 -47.5 -129.5t-124.5 -51.5q-66 0 -97.5 35.5t-31.5 87.5zM205 948q0 83 47 132.5t131 49.5q56 0 89.5 -31.5t33.5 -92.5q0 -79 -48.5 -130t-125.5 -51q-66 0 -96.5 35.5t-30.5 87.5z" /> -<glyph unicode=";" horiz-adv-x="551" d="M-100 -264q95 214 198 502h236l8 -23q-125 -260 -266 -479h-176zM205 948q0 83 47 132.5t131 49.5q56 0 89.5 -31.5t33.5 -92.5q0 -79 -48.5 -130t-125.5 -51q-66 0 -96.5 35.5t-30.5 87.5z" /> -<glyph unicode="<" d="M115 651v121l936 488v-195l-697 -344l697 -303v-197z" /> -<glyph unicode="=" d="M117 430v180h936v-180h-936zM117 831v179h936v-179h-936z" /> -<glyph unicode=">" d="M115 221v197l694 303l-694 344v195l936 -488v-121z" /> -<glyph unicode="?" horiz-adv-x="907" d="M162 94q0 83 47 132.5t131 49.5q56 0 89.5 -31.5t33.5 -92.5q0 -79 -49 -129t-125 -50q-66 0 -96.5 34.5t-30.5 86.5zM186 1370q207 113 410 113q171 0 269 -85.5t98 -242.5q0 -120 -63.5 -217.5t-231.5 -216.5q-104 -74 -150 -133t-61 -144h-197q18 133 71.5 220.5 t176.5 177.5q107 77 146.5 117t58 80.5t18.5 88.5q0 70 -42.5 114t-123.5 44q-77 0 -150 -27.5t-151 -64.5z" /> -<glyph unicode="@" horiz-adv-x="1743" d="M100 502q0 270 122.5 489t343 344t493.5 125q200 0 346 -74.5t223.5 -214.5t77.5 -325q0 -176 -59.5 -322.5t-166.5 -229.5t-239 -83q-98 0 -150.5 46t-64.5 120h-6q-101 -166 -277 -166q-123 0 -189.5 78.5t-66.5 218.5q0 151 67.5 279.5t188 203t263.5 74.5 q52 0 94.5 -5t79.5 -13t129 -39l-101 -392q-30 -114 -30 -159q0 -92 79 -92q72 0 134 66.5t97.5 174.5t35.5 230q0 228 -128.5 347.5t-363.5 119.5q-214 0 -385 -99.5t-266.5 -281.5t-95.5 -406q0 -259 140.5 -401t391.5 -142q200 0 430 86v-155q-219 -90 -454 -90 q-210 0 -367 83.5t-241.5 239.5t-84.5 365zM676 522q0 -157 112 -157q82 0 141.5 72t100.5 220l64 240q-53 16 -105 16q-86 0 -158.5 -53.5t-113.5 -144t-41 -193.5z" /> -<glyph unicode="A" horiz-adv-x="1210" d="M-121 0l783 1464h274l166 -1464h-234l-41 406h-485l-209 -406h-254zM446 614h365q-40 416 -45.5 503.5t-5.5 139.5q-55 -139 -142 -307z" /> -<glyph unicode="B" horiz-adv-x="1247" d="M70 0l309 1462h399q222 0 335.5 -84t113.5 -248q0 -146 -86.5 -243t-239.5 -127v-8q108 -28 167.5 -103.5t59.5 -183.5q0 -217 -150 -341t-417 -124h-491zM348 201h223q147 0 230.5 68t83.5 194q0 98 -60 149.5t-176 51.5h-200zM489 858h199q139 0 215 60.5t76 171.5 q0 172 -223 172h-181z" /> -<glyph unicode="C" horiz-adv-x="1225" d="M135 545q0 260 105.5 483t281.5 339t402 116q217 0 389 -92l-94 -195q-63 34 -134 58t-161 24q-154 0 -275 -89t-193.5 -259.5t-72.5 -374.5q0 -180 82.5 -275.5t243.5 -95.5q141 0 329 68v-205q-180 -67 -374 -67q-248 0 -388.5 148.5t-140.5 416.5z" /> -<glyph unicode="D" horiz-adv-x="1374" d="M70 0l309 1462h369q271 0 417 -145t146 -424q0 -271 -100 -473t-291 -311t-449 -109h-401zM348 201h135q177 0 309 86t202.5 242t70.5 356q0 184 -88 280.5t-256 96.5h-146z" /> -<glyph unicode="E" horiz-adv-x="1077" d="M70 0l309 1462h776l-43 -205h-539l-84 -395h502l-41 -203h-504l-96 -456h539l-43 -203h-776z" /> -<glyph unicode="F" horiz-adv-x="1026" d="M70 0l309 1462h774l-43 -205h-537l-96 -454h502l-45 -203h-500l-127 -600h-237z" /> -<glyph unicode="G" horiz-adv-x="1399" d="M135 539q0 264 102.5 483t290 340t426.5 121q111 0 213 -20.5t205 -69.5l-90 -203q-174 86 -334 86q-158 0 -287 -90.5t-203.5 -258t-74.5 -372.5q0 -183 89 -277t253 -94q109 0 215 33l80 371h-277l43 205h512l-157 -736q-112 -40 -218.5 -58.5t-238.5 -18.5 q-261 0 -405 146t-144 413z" /> -<glyph unicode="H" horiz-adv-x="1411" d="M70 0l309 1462h237l-127 -598h566l127 598h237l-309 -1462h-238l140 659h-566l-139 -659h-237z" /> -<glyph unicode="I" horiz-adv-x="608" d="M70 0l311 1462h235l-311 -1462h-235z" /> -<glyph unicode="J" horiz-adv-x="612" d="M-322 -383l5 201q84 -21 153 -21q201 0 254 250l299 1415h238l-305 -1446q-46 -217 -161.5 -320.5t-312.5 -103.5q-104 0 -170 25z" /> -<glyph unicode="K" horiz-adv-x="1198" d="M70 0l309 1462h237l-151 -706l141 166l492 540h284l-616 -669l321 -793h-262l-252 655l-149 -100l-117 -555h-237z" /> -<glyph unicode="L" horiz-adv-x="1016" d="M70 0l309 1462h237l-266 -1257h539l-43 -205h-776z" /> -<glyph unicode="M" horiz-adv-x="1757" d="M68 0l309 1462h323l109 -1149h6l606 1149h344l-305 -1462h-227l182 872q39 186 86 342h-6l-643 -1214h-205l-115 1214h-6q-9 -118 -55 -340l-184 -874h-219z" /> -<glyph unicode="N" horiz-adv-x="1491" d="M68 0l309 1462h268l399 -1149h7q6 54 31 192.5t40 203.5l160 753h219l-309 -1462h-260l-410 1163h-6l-10 -69q-24 -149 -35.5 -212.5t-183.5 -881.5h-219z" /> -<glyph unicode="O" horiz-adv-x="1485" d="M135 543q0 267 98.5 487.5t269.5 337.5t388 117q251 0 390.5 -149t139.5 -414q0 -279 -95 -497t-261.5 -331.5t-386.5 -113.5q-259 0 -401 149.5t-142 413.5zM383 545q0 -173 81.5 -267t227.5 -94q138 0 248.5 95.5t172 265t61.5 375.5q0 170 -79 265t-223 95 q-138 0 -250 -96t-175.5 -266.5t-63.5 -372.5z" /> -<glyph unicode="P" horiz-adv-x="1174" d="M70 0l309 1462h334q229 0 345 -100.5t116 -300.5q0 -248 -169.5 -381t-472.5 -133h-110l-115 -547h-237zM465 748h94q178 0 275.5 79.5t97.5 225.5q0 109 -58.5 159t-179.5 50h-119z" /> -<glyph unicode="Q" horiz-adv-x="1485" d="M135 543q0 267 98.5 487.5t269.5 337.5t388 117q251 0 390.5 -149t139.5 -414q0 -322 -130 -563t-355 -332l264 -375h-289l-202 328h-31q-259 0 -401 149.5t-142 413.5zM383 545q0 -173 81.5 -267t227.5 -94q138 0 248.5 94t172 263.5t61.5 378.5q0 170 -79 265t-223 95 q-138 0 -250 -96t-175.5 -266.5t-63.5 -372.5z" /> -<glyph unicode="R" horiz-adv-x="1206" d="M70 0l309 1462h338q223 0 342 -94.5t119 -290.5q0 -165 -86.5 -278.5t-257.5 -165.5l249 -633h-260l-207 584h-186l-123 -584h-237zM473 782h123q170 0 254 75t84 206q0 105 -59 151t-183 46h-119z" /> -<glyph unicode="S" horiz-adv-x="1057" d="M39 55v224q173 -97 350 -97q137 0 216 58.5t79 162.5q0 69 -41 122.5t-172 136.5q-105 67 -155 122t-76.5 120.5t-26.5 144.5q0 128 61.5 227t174 153t253.5 54q205 0 381 -92l-86 -191q-161 78 -295 78q-109 0 -175 -58.5t-66 -152.5q0 -47 15 -82.5t46.5 -66 t134.5 -95.5q155 -97 214 -187.5t59 -207.5q0 -210 -144.5 -329t-398.5 -119q-210 0 -348 75z" /> -<glyph unicode="T" horiz-adv-x="1053" d="M176 1257l45 205h998l-43 -205h-381l-267 -1257h-237l264 1257h-379z" /> -<glyph unicode="U" horiz-adv-x="1399" d="M152 391q0 83 20 170l193 901h237l-192 -905q-21 -88 -21 -158q0 -102 59.5 -158.5t180.5 -56.5q145 0 230 80.5t124 261.5l199 936h237l-202 -956q-56 -267 -208 -396.5t-403 -129.5q-217 0 -335.5 106t-118.5 305z" /> -<glyph unicode="V" horiz-adv-x="1165" d="M186 1462h232l74 -905q9 -103 11 -233l-1 -76h4q70 178 137 309l455 905h254l-764 -1462h-258z" /> -<glyph unicode="W" horiz-adv-x="1788" d="M203 1462h229l19 -850q0 -136 -13 -346h6q83 221 142 355l387 841h225l31 -839l3 -169l-3 -188h8q28 88 70 197.5t61 152.5l358 846h246l-655 -1462h-258l-37 842l-6 185l4 106h-6q-47 -144 -117 -291l-385 -842h-256z" /> -<glyph unicode="X" horiz-adv-x="1151" d="M-111 0l586 770l-250 692h246l178 -540l402 540h266l-551 -710l274 -752h-256l-192 592l-438 -592h-265z" /> -<glyph unicode="Y" horiz-adv-x="1092" d="M186 1462h242l154 -669l432 669h266l-623 -913l-114 -549h-238l119 553z" /> -<glyph unicode="Z" horiz-adv-x="1092" d="M-39 0l33 168l850 1087h-598l43 207h897l-35 -172l-852 -1085h645l-43 -205h-940z" /> -<glyph unicode="[" horiz-adv-x="631" d="M-27 -324l381 1786h430l-39 -176h-221l-303 -1433h221l-39 -177h-430z" /> -<glyph unicode="\" horiz-adv-x="788" d="M221 1462h207l219 -1462h-209z" /> -<glyph unicode="]" horiz-adv-x="631" d="M-143 -324l37 177h219l305 1433h-221l39 176h430l-381 -1786h-428z" /> -<glyph unicode="^" horiz-adv-x="1069" d="M37 537l608 933h127l272 -933h-184l-188 690l-434 -690h-201z" /> -<glyph unicode="_" horiz-adv-x="813" d="M-188 -324l30 140h817l-30 -140h-817z" /> -<glyph unicode="`" horiz-adv-x="1135" d="M541 1548v21h245q47 -154 132 -303v-25h-144q-65 63 -132 151.5t-101 155.5z" /> -<glyph unicode="a" horiz-adv-x="1186" d="M94 367q0 202 69.5 378t191.5 278.5t268 102.5q97 0 167 -45.5t109 -132.5h10l62 158h180l-236 -1106h-182l21 176h-6q-158 -196 -349 -196q-141 0 -223 101.5t-82 285.5zM332 373q0 -102 40.5 -152.5t112.5 -50.5q82 0 161 77.5t130 207.5t51 284q0 88 -47 141.5 t-123 53.5q-85 0 -160 -77t-120 -209.5t-45 -274.5z" /> -<glyph unicode="b" horiz-adv-x="1200" d="M47 0l330 1556h235l-71 -333q-13 -63 -38 -156.5t-40 -140.5h8q90 113 165 156.5t161 43.5q145 0 226 -103.5t81 -285.5q0 -202 -69.5 -379.5t-190.5 -277.5t-266 -100q-98 0 -168.5 45t-110.5 131h-10l-64 -156h-178zM369 373q0 -96 46.5 -149.5t131.5 -53.5t159 78.5 t117 210t43 274.5q0 201 -155 201q-81 0 -162 -80t-130.5 -210.5t-49.5 -270.5z" /> -<glyph unicode="c" horiz-adv-x="954" d="M94 389q0 207 73.5 376.5t206.5 265t302 95.5q164 0 297 -61l-70 -184q-122 53 -221 53q-150 0 -250 -153.5t-100 -379.5q0 -111 56 -171t155 -60q74 0 138.5 22t129.5 54v-195q-140 -71 -305 -71q-196 0 -304 106t-108 303z" /> -<glyph unicode="d" horiz-adv-x="1198" d="M94 369q0 205 71.5 383t191.5 276t266 98q179 0 268 -178h8q13 146 37 250l76 358h233l-330 -1556h-184l19 176h-7q-88 -106 -170 -151t-174 -45q-143 0 -224 101.5t-81 287.5zM332 373q0 -203 157 -203q82 0 162.5 82t129 214t48.5 267q0 91 -43.5 146t-132.5 55 q-85 0 -159 -77t-118 -211t-44 -273z" /> -<glyph unicode="e" horiz-adv-x="1075" d="M94 401q0 198 77.5 368.5t210 263.5t296.5 93q161 0 250.5 -72.5t89.5 -205.5q0 -182 -166.5 -284.5t-474.5 -102.5h-43l-2 -31v-29q0 -111 56.5 -174t168.5 -63q72 0 143 19t168 65v-187q-96 -44 -176.5 -62.5t-179.5 -18.5q-197 0 -307.5 111t-110.5 310zM362 633h29 q188 0 294 53.5t106 151.5q0 51 -32 79.5t-95 28.5q-96 0 -180.5 -86t-121.5 -227z" /> -<glyph unicode="f" horiz-adv-x="702" d="M-225 -279q64 -20 114 -20q134 0 177 205l217 1022h-179l21 106l194 76l21 92q44 198 134.5 281.5t256.5 83.5q115 0 211 -43l-61 -176q-74 28 -136 28q-69 0 -110.5 -43t-63.5 -141l-18 -86h229l-37 -178h-229l-223 -1053q-40 -189 -131 -278t-238 -89q-90 0 -149 23 v190z" /> -<glyph unicode="g" horiz-adv-x="1067" d="M-121 -211q0 103 69.5 178t223.5 127q-76 45 -76 127q0 69 46.5 119.5t146.5 97.5q-135 81 -135 252q0 196 122.5 316t323.5 120q80 0 160 -20h383l-31 -137l-192 -33q28 -58 28 -137q0 -193 -119 -306.5t-319 -113.5q-52 0 -92 8q-111 -40 -111 -104q0 -38 31.5 -52 t91.5 -22l127 -16q176 -22 252 -87.5t76 -187.5q0 -196 -151 -303t-429 -107q-203 0 -314.5 75t-111.5 206zM92 -184q0 -65 55.5 -103.5t169.5 -38.5q163 0 255 54t92 155q0 51 -45 80t-158 41l-137 14q-112 -18 -172 -71t-60 -131zM377 680q0 -71 35.5 -109.5t101.5 -38.5 q65 0 112.5 39t74 107t26.5 149q0 142 -133 142q-65 0 -114 -38.5t-76 -105t-27 -145.5z" /> -<glyph unicode="h" horiz-adv-x="1208" d="M47 0l330 1556h235l-57 -262q-27 -126 -73 -293l-19 -75h8q84 106 168.5 153t177.5 47q136 0 208.5 -77.5t72.5 -221.5q0 -76 -23 -174l-139 -653h-234l142 672q18 90 18 127q0 135 -129 135q-112 0 -209.5 -125t-142.5 -342l-98 -467h-236z" /> -<glyph unicode="i" horiz-adv-x="563" d="M47 0l236 1106h235l-235 -1106h-236zM330 1378q0 68 39 110t110 42q53 0 86 -26.5t33 -80.5q0 -71 -40 -112t-105 -41q-53 0 -88 26t-35 82z" /> -<glyph unicode="j" horiz-adv-x="563" d="M-262 -279q64 -20 117 -20q131 0 170 186l260 1219h233l-266 -1247q-38 -181 -127.5 -266t-237.5 -85q-90 0 -149 23v190zM332 1378q0 68 38 110t109 42q54 0 86.5 -26.5t32.5 -80.5q0 -71 -40 -112t-105 -41q-53 0 -87 25.5t-34 82.5z" /> -<glyph unicode="k" horiz-adv-x="1081" d="M47 0l330 1556h235q-135 -627 -159.5 -729.5t-59.5 -226.5h4l490 506h272l-483 -485l291 -621h-262l-209 471l-136 -96l-77 -375h-236z" /> -<glyph unicode="l" horiz-adv-x="563" d="M47 0l330 1556h235l-331 -1556h-234z" /> -<glyph unicode="m" horiz-adv-x="1819" d="M47 0l236 1106h184l-21 -205h9q148 225 352 225q220 0 254 -235h8q75 116 170.5 175.5t198.5 59.5q133 0 202.5 -76.5t69.5 -215.5q0 -64 -22 -181l-140 -653h-235l143 672q19 95 19 133q0 129 -121 129q-108 0 -201.5 -124t-136.5 -329l-101 -481h-235l143 672 q17 82 17 127q0 135 -117 135q-110 0 -203.5 -127t-138.5 -338l-98 -469h-236z" /> -<glyph unicode="n" horiz-adv-x="1208" d="M47 0l236 1106h184l-21 -205h9q83 118 171 171.5t191 53.5q134 0 207.5 -76t73.5 -216q0 -69 -23 -181l-137 -653h-236l142 672q18 90 18 131q0 131 -129 131q-72 0 -142 -57t-126 -164.5t-84 -243.5l-98 -469h-236z" /> -<glyph unicode="o" horiz-adv-x="1174" d="M94 408q0 199 71.5 365t200.5 258.5t298 92.5q195 0 305 -116t110 -316q0 -202 -73 -367.5t-200.5 -254t-293.5 -88.5q-192 0 -305 114.5t-113 311.5zM332 403q0 -111 49.5 -170t146.5 -59q90 0 162 68t112 190.5t40 269.5q0 107 -49 167.5t-140 60.5q-93 0 -166.5 -71.5 t-114 -194t-40.5 -261.5z" /> -<glyph unicode="p" horiz-adv-x="1200" d="M-55 -492l338 1598h184l-21 -188h9q157 208 344 208q143 0 224 -103t81 -286q0 -204 -70 -381.5t-190.5 -276.5t-265.5 -99q-181 0 -269 176h-10q-7 -97 -25 -185l-96 -463h-233zM369 373q0 -96 46.5 -149.5t131.5 -53.5t159 78.5t117 210t43 274.5q0 201 -155 201 q-81 0 -161 -79.5t-130.5 -210.5t-50.5 -271z" /> -<glyph unicode="q" horiz-adv-x="1198" d="M94 367q0 208 73 387t192.5 275.5t265.5 96.5q183 0 274 -178h10l64 158h178l-340 -1598h-233l75 349q12 56 43.5 180t38.5 141h-8q-84 -108 -164 -153t-170 -45q-139 0 -219 102.5t-80 284.5zM332 373q0 -203 160 -203q80 0 159 81t127.5 213t48.5 269q0 94 -45.5 147.5 t-126.5 53.5q-86 0 -160 -77.5t-118.5 -209.5t-44.5 -274z" /> -<glyph unicode="r" horiz-adv-x="836" d="M47 0l236 1106h184l-21 -205h9q83 120 166 172.5t176 52.5q62 0 108 -12l-51 -219q-54 14 -102 14q-126 0 -225 -113t-138 -296l-106 -500h-236z" /> -<glyph unicode="s" horiz-adv-x="922" d="M14 47v203q153 -90 312 -90q97 0 157 40t60 109q0 51 -34.5 87.5t-141.5 97.5q-125 67 -176.5 136.5t-51.5 164.5q0 155 107 243t289 88q196 0 346 -84l-76 -176q-140 76 -266 76q-73 0 -118.5 -33t-45.5 -92q0 -45 33 -80t135 -90q105 -59 149 -101t67 -91.5t23 -114.5 q0 -173 -118 -266.5t-328 -93.5q-190 0 -322 67z" /> -<glyph unicode="t" horiz-adv-x="752" d="M92 928l21 110l190 82l129 232h146l-52 -246h279l-39 -178h-277l-122 -572q-13 -55 -13 -92q0 -43 25 -68.5t76 -25.5q68 0 151 31v-178q-35 -17 -95 -30t-120 -13q-274 0 -274 247q0 57 16 131l121 570h-162z" /> -<glyph unicode="u" horiz-adv-x="1208" d="M111 274q0 63 12 124.5t24 123.5l123 584h236l-129 -610q-31 -141 -31 -193q0 -133 127 -133q72 0 143 57t126 162.5t85 247.5l99 469h233l-233 -1106h-185l21 205h-8q-82 -116 -171 -170.5t-192 -54.5q-134 0 -207 76t-73 218z" /> -<glyph unicode="v" horiz-adv-x="997" d="M100 1106h232l55 -598q14 -159 14 -297h7q28 74 70 165t65 132l311 598h250l-598 -1106h-275z" /> -<glyph unicode="w" horiz-adv-x="1540" d="M121 1106h221l13 -646q-2 -87 -11 -245h6q66 176 109 272l278 619h254l19 -604l1 -53l-3 -234h6q17 50 57 158.5t63.5 163.5t251.5 569h244l-518 -1106h-268l-19 627l-1 70l3 200q-25 -62 -51.5 -125t-345.5 -772h-262z" /> -<glyph unicode="x" horiz-adv-x="1032" d="M-86 0l475 569l-231 537h245l144 -373l287 373h274l-461 -549l248 -557h-246l-160 387l-305 -387h-270z" /> -<glyph unicode="y" horiz-adv-x="1004" d="M-170 -285q75 -16 125 -16q74 0 134 43.5t124 155.5l51 92l-164 1116h232l63 -531q9 -62 16 -174.5t7 -181.5h6q86 215 135 313l293 574h254l-688 -1280q-90 -165 -196 -241.5t-249 -76.5q-76 0 -143 19v188z" /> -<glyph unicode="z" horiz-adv-x="920" d="M-39 0l29 147l635 781h-439l39 178h705l-37 -170l-623 -758h486l-37 -178h-758z" /> -<glyph unicode="{" horiz-adv-x="721" d="M8 485l39 187q120 0 191.5 42.5t93.5 143.5l59 275q28 134 73 201.5t120 97.5t198 30h60l-41 -184q-96 0 -139.5 -34t-61.5 -116l-70 -309q-24 -108 -87 -170.5t-179 -79.5v-6q160 -45 160 -215q0 -38 -16 -121l-43 -194q-11 -48 -11 -74q0 -51 32.5 -74.5t109.5 -23.5 v-185h-39q-316 0 -316 236q0 61 17 133l45 201q14 65 14 98q0 141 -209 141z" /> -<glyph unicode="|" d="M498 -481v2033h178v-2033h-178z" /> -<glyph unicode="}" horiz-adv-x="721" d="M-88 -141q106 2 152.5 36.5t64.5 114.5l70 309q24 109 87 170t179 78v6q-158 48 -158 215q0 55 17 121l43 197q10 44 10 74q0 58 -43 78t-121 20l35 184h22q318 0 318 -235q0 -61 -17 -133l-45 -203q-14 -65 -14 -98q0 -142 209 -142l-39 -186q-121 0 -192 -42t-93 -142 l-63 -306q-34 -165 -123.5 -232t-269.5 -67h-29v183z" /> -<glyph unicode="~" d="M111 571v191q100 108 249 108q64 0 118.5 -12t146.5 -51q70 -30 115 -42.5t94 -12.5q50 0 112.5 31t120.5 89v-190q-103 -111 -250 -111q-63 0 -124 16.5t-138 49.5q-76 32 -119.5 43.5t-91.5 11.5q-51 0 -112 -31t-121 -90z" /> -<glyph unicode="¡" horiz-adv-x="557" d="M-45 -373l266 1018h174l-166 -1018h-274zM221 936q0 82 49 132t127 50q65 0 95 -35.5t30 -89.5q0 -80 -47 -130t-127 -50q-59 0 -93 31.5t-34 91.5z" /> -<glyph unicode="¢" d="M195 586q0 190 63.5 351t178 260.5t261.5 121.5l35 164h156l-37 -164q124 -12 221 -57l-69 -185q-125 53 -222 53q-99 0 -180 -71.5t-125.5 -194.5t-44.5 -266q0 -111 56 -171t155 -60q74 0 138.5 21.5t129.5 53.5v-194q-133 -69 -293 -74l-40 -194h-156l45 213 q-132 34 -202 134.5t-70 258.5z" /> -<glyph unicode="£" d="M-18 0l38 193q200 45 250 276l35 164h-196l36 172h197l61 299q38 185 153 282t300 97q188 0 352 -86l-88 -183q-143 74 -258 74q-185 0 -227 -205l-57 -278h333l-34 -172h-336l-33 -152q-21 -98 -68.5 -165t-130.5 -109h690l-45 -207h-972z" /> -<glyph unicode="¤" d="M141 1057l119 119l127 -127q102 61 207 61q108 0 207 -63l127 129l121 -117l-129 -129q61 -99 61 -207q0 -114 -61 -209l127 -125l-119 -119l-127 127q-95 -59 -207 -59q-120 0 -207 59l-127 -125l-117 119l127 125q-61 95 -61 207q0 110 61 205zM377 723 q0 -91 62.5 -154t154.5 -63q91 0 156 62t65 155t-65 156t-156 63q-92 0 -154.5 -64t-62.5 -155z" /> -<glyph unicode="¥" d="M106 244l33 155h273l30 148h-272l35 155h211l-199 760h232l145 -669l432 669h248l-518 -760h217l-35 -155h-274l-31 -148h274l-33 -155h-272l-53 -244h-221l51 244h-273z" /> -<glyph unicode="¦" d="M498 315h178v-796h-178v796zM498 758v794h178v-794h-178z" /> -<glyph unicode="§" horiz-adv-x="995" d="M39 53v187q152 -93 319 -93q116 0 174 40.5t58 111.5q0 43 -39 79.5t-141 84.5q-130 60 -189 131.5t-59 169.5q0 188 219 307q-47 32 -78 82t-31 115q0 138 111.5 220.5t296.5 82.5q178 0 332 -78l-68 -158q-62 29 -129.5 50.5t-144.5 21.5q-86 0 -134.5 -34.5 t-48.5 -94.5q0 -43 36.5 -76.5t148.5 -83.5q127 -56 186.5 -127.5t59.5 -167.5q0 -92 -52.5 -171t-160.5 -140q102 -76 102 -193q0 -157 -123 -245t-330 -88q-188 0 -315 67zM358 793q0 -61 46.5 -104.5t173.5 -100.5q62 36 99.5 90.5t37.5 114.5t-49.5 104.5t-155.5 89.5 q-69 -26 -110.5 -79t-41.5 -115z" /> -<glyph unicode="¨" horiz-adv-x="1135" d="M426 1380q0 60 35 98t98 38q48 0 76.5 -23.5t28.5 -71.5q0 -65 -35.5 -102t-93.5 -37q-47 0 -78 23.5t-31 74.5zM809 1380q0 60 35 98t98 38q48 0 76.5 -23.5t28.5 -71.5q0 -65 -35.5 -102t-93.5 -37q-47 0 -78 23.5t-31 74.5z" /> -<glyph unicode="©" horiz-adv-x="1704" d="M131 731q0 200 100 375t275 276t377 101q199 0 373.5 -99t276 -275.5t101.5 -377.5q0 -199 -98.5 -373t-272.5 -276t-380 -102q-207 0 -382 103.5t-272.5 276.5t-97.5 371zM254 731q0 -168 83 -312.5t229 -230.5t317 -86q173 0 319.5 87t227.5 231.5t81 310.5 q0 165 -82 310.5t-227.5 232t-318.5 86.5q-168 0 -314.5 -84.5t-230.5 -231t-84 -313.5zM502 727q0 216 113.5 340.5t312.5 124.5q138 0 266 -66l-68 -147q-106 55 -196 55q-113 0 -175.5 -76t-62.5 -231q0 -301 238 -301q47 0 112 16t109 35v-158q-117 -51 -240 -51 q-197 0 -303 123.5t-106 335.5z" /> -<glyph unicode="ª" horiz-adv-x="729" d="M160 1016q0 128 47 238.5t122.5 167.5t168.5 57q113 0 166 -103h6l39 90h118l-147 -684h-123l10 105h-4q-50 -62 -98 -89.5t-109 -27.5q-91 0 -143.5 66t-52.5 180zM319 1022q0 -125 93 -125q50 0 97.5 48t77 127.5t29.5 158.5q0 119 -102 119q-82 0 -138.5 -97.5 t-56.5 -230.5z" /> -<glyph unicode="«" horiz-adv-x="1055" d="M80 553v22l395 420l135 -118l-288 -332l153 -369l-178 -76zM520 530v25l385 434l137 -112l-280 -351l147 -350l-180 -76z" /> -<glyph unicode="¬" d="M117 631v180h936v-555h-179v375h-757z" /> -<glyph unicode="­" horiz-adv-x="649" d="M47 446l45 203h502l-45 -203h-502z" /> -<glyph unicode="®" horiz-adv-x="1704" d="M131 731q0 200 100 375t275 276t377 101q199 0 373.5 -99t276 -275.5t101.5 -377.5q0 -199 -98.5 -373t-272.5 -276t-380 -102q-207 0 -382 103.5t-272.5 276.5t-97.5 371zM254 731q0 -168 83 -312.5t229 -230.5t317 -86q173 0 319.5 87t227.5 231.5t81 310.5 q0 165 -82 310.5t-227.5 232t-318.5 86.5q-168 0 -314.5 -84.5t-230.5 -231t-84 -313.5zM608 291v878h269q337 0 337 -262q0 -83 -45.5 -145t-130.5 -98l211 -373h-200l-172 325h-91v-325h-178zM786 760h72q84 0 129 36t45 99q0 73 -45.5 101t-128.5 28h-72v-264z" /> -<glyph unicode="¯" horiz-adv-x="903" d="M111 1556l39 166h911l-41 -166h-909z" /> -<glyph unicode="°" horiz-adv-x="877" d="M188 1153q0 136 97 233t233 97t232 -97t96 -233q0 -137 -96 -231.5t-232 -94.5q-88 0 -165 44t-121 119t-44 163zM340 1153q0 -70 52 -122t126 -52q72 0 124 52t52 122q0 74 -51.5 126t-124.5 52q-74 0 -126 -51.5t-52 -126.5z" /> -<glyph unicode="±" d="M117 0v180h936v-180h-936zM117 657v181h379v381h180v-381h377v-181h-377v-374h-180v374h-379z" /> -<glyph unicode="²" horiz-adv-x="745" d="M78 586l28 135l269 223q111 95 148.5 136t55 77t17.5 74q0 46 -28 72t-76 26q-91 0 -191 -80l-80 123q68 54 142.5 81.5t168.5 27.5q115 0 183.5 -60t68.5 -155q0 -69 -23.5 -124.5t-74 -110.5t-168.5 -146l-174 -142h371l-33 -157h-604z" /> -<glyph unicode="³" horiz-adv-x="745" d="M104 625v159q126 -71 248 -71q90 0 139.5 37t49.5 106q0 113 -146 113h-108l28 133h93q89 0 142.5 34t53.5 99q0 100 -117 100q-92 0 -188 -65l-68 121q126 90 291 90q124 0 193 -55.5t69 -153.5q0 -90 -54.5 -149t-158.5 -85v-4q78 -18 115 -67t37 -115 q0 -129 -99.5 -206t-269.5 -77q-138 0 -250 56z" /> -<glyph unicode="´" horiz-adv-x="1135" d="M508 1241v25q97 108 225 303h264v-19q-54 -66 -158 -161.5t-175 -147.5h-156z" /> -<glyph unicode="µ" horiz-adv-x="1221" d="M-55 -492l338 1598h235l-141 -670q-19 -84 -19 -129q0 -65 33 -101t96 -36q113 0 209.5 125.5t141.5 337.5l102 473h231l-235 -1106h-184l22 190h-10q-75 -111 -153 -160.5t-165 -49.5q-108 0 -155 81h-8q-9 -73 -39 -235l-66 -318h-233z" /> -<glyph unicode="¶" horiz-adv-x="1341" d="M172 1042q0 260 109 387t342 127h581v-1816h-139v1638h-188v-1638h-140v819q-62 -18 -145 -18q-216 0 -318 125t-102 376z" /> -<glyph unicode="·" horiz-adv-x="551" d="M150 692q0 83 47 132.5t131 49.5q56 0 89.5 -31.5t33.5 -92.5q0 -78 -47.5 -129.5t-124.5 -51.5q-66 0 -97.5 35.5t-31.5 87.5z" /> -<glyph unicode="¸" horiz-adv-x="420" d="M-188 -342q47 -14 96 -14q137 0 137 96q0 40 -35 61.5t-104 30.5l98 168h146l-50 -96q72 -25 104 -67t32 -101q0 -106 -82 -167t-224 -61q-64 0 -118 15v135z" /> -<glyph unicode="¹" horiz-adv-x="745" d="M193 1247l339 215h162l-186 -876h-191l99 461q17 79 57 217q-21 -20 -49.5 -43t-153.5 -103z" /> -<glyph unicode="º" horiz-adv-x="721" d="M164 1047q0 122 44 221.5t125.5 155t188.5 55.5q124 0 189 -71.5t65 -201.5q0 -126 -42 -225t-121 -155t-189 -56q-122 0 -191 73t-69 204zM326 1042q0 -141 112 -141q77 0 127.5 87.5t50.5 219.5q0 138 -106 138q-81 0 -132.5 -87.5t-51.5 -216.5z" /> -<glyph unicode="»" horiz-adv-x="1055" d="M10 211l281 348l-146 352l179 76l211 -432v-25l-385 -432zM444 211l287 330l-153 370l180 76l217 -455v-22l-397 -418z" /> -<glyph unicode="¼" horiz-adv-x="1661" d="M149 0l1085 1462h195l-1083 -1462h-197zM151 1247l339 215h162l-186 -876h-191l99 461q17 79 57 217q-21 -20 -49.5 -43t-153.5 -103zM775 177l26 137l477 569h197l-121 -563h123l-29 -143h-122l-39 -176h-183l39 176h-368zM973 320h199l52 221l34 129q-32 -51 -98 -131z " /> -<glyph unicode="½" horiz-adv-x="1661" d="M121 0l1085 1462h195l-1083 -1462h-197zM122 1247l339 215h162l-186 -876h-191l99 461q17 79 57 217q-21 -20 -49.5 -43t-153.5 -103zM860 1l28 135l269 223q111 95 148.5 136t55 77t17.5 74q0 46 -28 72t-76 26q-91 0 -191 -80l-80 123q68 54 142.5 81.5t168.5 27.5 q115 0 183.5 -60t68.5 -155q0 -69 -23.5 -124.5t-74 -110.5t-168.5 -146l-174 -142h371l-33 -157h-604z" /> -<glyph unicode="¾" horiz-adv-x="1683" d="M291 0l1085 1462h195l-1083 -1462h-197zM881 177l26 137l477 569h197l-121 -563h123l-29 -143h-122l-39 -176h-183l39 176h-368zM1079 320h199l52 221l34 129q-32 -51 -98 -131zM108 625v159q126 -71 248 -71q90 0 139.5 37t49.5 106q0 113 -146 113h-108l28 133h93 q89 0 142.5 34t53.5 99q0 100 -117 100q-92 0 -188 -65l-68 121q126 90 291 90q124 0 193 -55.5t69 -153.5q0 -90 -54.5 -149t-158.5 -85v-4q78 -18 115 -67t37 -115q0 -129 -99.5 -206t-269.5 -77q-138 0 -250 56z" /> -<glyph unicode="¿" horiz-adv-x="907" d="M-35 -68q0 120 64 219t231 216q93 64 141 122.5t70 153.5h197q-25 -146 -79.5 -231t-170.5 -168q-107 -79 -145.5 -118t-57 -79t-18.5 -88q0 -71 42 -114.5t123 -43.5q76 0 149.5 27.5t152.5 65.5l75 -177q-205 -112 -409 -112q-174 0 -269.5 85.5t-95.5 241.5zM465 934 q0 78 46.5 129t125.5 51q66 0 97.5 -34t31.5 -87q0 -85 -48 -134.5t-130 -49.5q-56 0 -89.5 32.5t-33.5 92.5z" /> -<glyph unicode="À" horiz-adv-x="1210" d="M-121 0l783 1464h274l166 -1464h-234l-41 406h-485l-209 -406h-254zM446 614h365q-40 416 -45.5 503.5t-5.5 139.5q-55 -139 -142 -307zM538 1886v21h245q47 -154 132 -303v-25h-144q-65 63 -132 151.5t-101 155.5z" /> -<glyph unicode="Á" horiz-adv-x="1210" d="M-121 0l783 1464h274l166 -1464h-234l-41 406h-485l-209 -406h-254zM446 614h365q-40 416 -45.5 503.5t-5.5 139.5q-55 -139 -142 -307zM707 1579v25q97 108 225 303h264v-19q-54 -66 -158 -161.5t-175 -147.5h-156z" /> -<glyph unicode="Â" horiz-adv-x="1210" d="M-121 0l783 1464h274l166 -1464h-234l-41 406h-485l-209 -406h-254zM446 614h365q-40 416 -45.5 503.5t-5.5 139.5q-55 -139 -142 -307zM444 1579v25q138 128 201 195.5t90 107.5h248q38 -99 174 -303v-25h-152q-76 63 -161 178q-131 -110 -236 -178h-164z" /> -<glyph unicode="Ã" horiz-adv-x="1210" d="M-121 0l783 1464h274l166 -1464h-234l-41 406h-485l-209 -406h-254zM446 614h365q-40 416 -45.5 503.5t-5.5 139.5q-55 -139 -142 -307zM441 1577q57 285 256 285q46 0 85 -17.5t72.5 -38t63.5 -38t59 -17.5q40 0 65 26.5t48 86.5h137q-66 -285 -260 -285q-45 0 -82.5 17 t-71.5 37.5t-65.5 37.5t-63.5 17q-38 0 -63 -27.5t-43 -83.5h-137z" /> -<glyph unicode="Ä" horiz-adv-x="1210" d="M-121 0l783 1464h274l166 -1464h-234l-41 406h-485l-209 -406h-254zM446 614h365q-40 416 -45.5 503.5t-5.5 139.5q-55 -139 -142 -307zM518 1718q0 60 35 98t98 38q48 0 76.5 -23.5t28.5 -71.5q0 -65 -35.5 -102t-93.5 -37q-47 0 -78 23.5t-31 74.5zM901 1718 q0 60 35 98t98 38q48 0 76.5 -23.5t28.5 -71.5q0 -65 -35.5 -102t-93.5 -37q-47 0 -78 23.5t-31 74.5z" /> -<glyph unicode="Å" horiz-adv-x="1210" d="M-121 0l783 1464h274l166 -1464h-234l-41 406h-485l-209 -406h-254zM446 614h365q-40 416 -45.5 503.5t-5.5 139.5q-55 -139 -142 -307zM568 1573q0 103 65 164.5t168 61.5q104 0 171 -60.5t67 -163.5q0 -104 -66 -165.5t-172 -61.5t-169.5 61t-63.5 164zM697 1573 q0 -49 26.5 -76.5t77.5 -27.5q47 0 77 27.5t30 76.5q0 50 -30 78.5t-77 28.5q-45 0 -74.5 -28.5t-29.5 -78.5z" /> -<glyph unicode="Æ" horiz-adv-x="1753" d="M-121 0l930 1462h1020l-43 -205h-539l-84 -395h504l-43 -200h-502l-98 -459h539l-43 -203h-777l86 406h-432l-256 -406h-262zM528 614h344l138 643h-82z" /> -<glyph unicode="Ç" horiz-adv-x="1225" d="M135 545q0 260 105.5 483t281.5 339t402 116q217 0 389 -92l-94 -195q-63 34 -134 58t-161 24q-154 0 -275 -89t-193.5 -259.5t-72.5 -374.5q0 -180 82.5 -275.5t243.5 -95.5q141 0 329 68v-205q-180 -67 -374 -67q-248 0 -388.5 148.5t-140.5 416.5zM367 -342 q47 -14 96 -14q137 0 137 96q0 40 -35 61.5t-104 30.5l98 168h146l-50 -96q72 -25 104 -67t32 -101q0 -106 -82 -167t-224 -61q-64 0 -118 15v135z" /> -<glyph unicode="È" horiz-adv-x="1077" d="M70 0l309 1462h776l-43 -205h-539l-84 -395h502l-41 -203h-504l-96 -456h539l-43 -203h-776zM526 1886v21h245q47 -154 132 -303v-25h-144q-65 63 -132 151.5t-101 155.5z" /> -<glyph unicode="É" horiz-adv-x="1077" d="M70 0l309 1462h776l-43 -205h-539l-84 -395h502l-41 -203h-504l-96 -456h539l-43 -203h-776zM633 1579v25q97 108 225 303h264v-19q-54 -66 -158 -161.5t-175 -147.5h-156z" /> -<glyph unicode="Ê" horiz-adv-x="1077" d="M70 0l309 1462h776l-43 -205h-539l-84 -395h502l-41 -203h-504l-96 -456h539l-43 -203h-776zM417 1579v25q138 128 201 195.5t90 107.5h248q38 -99 174 -303v-25h-152q-76 63 -161 178q-131 -110 -236 -178h-164z" /> -<glyph unicode="Ë" horiz-adv-x="1077" d="M70 0l309 1462h776l-43 -205h-539l-84 -395h502l-41 -203h-504l-96 -456h539l-43 -203h-776zM479 1718q0 60 35 98t98 38q48 0 76.5 -23.5t28.5 -71.5q0 -65 -35.5 -102t-93.5 -37q-47 0 -78 23.5t-31 74.5zM862 1718q0 60 35 98t98 38q48 0 76.5 -23.5t28.5 -71.5 q0 -65 -35.5 -102t-93.5 -37q-47 0 -78 23.5t-31 74.5z" /> -<glyph unicode="Ì" horiz-adv-x="608" d="M70 0l311 1462h235l-311 -1462h-235zM253 1886v21h245q47 -154 132 -303v-25h-144q-65 63 -132 151.5t-101 155.5z" /> -<glyph unicode="Í" horiz-adv-x="608" d="M70 0l311 1462h235l-311 -1462h-235zM415 1579v25q97 108 225 303h264v-19q-54 -66 -158 -161.5t-175 -147.5h-156z" /> -<glyph unicode="Î" horiz-adv-x="608" d="M70 0l311 1462h235l-311 -1462h-235zM160 1579v25q138 128 201 195.5t90 107.5h248q38 -99 174 -303v-25h-152q-76 63 -161 178q-131 -110 -236 -178h-164z" /> -<glyph unicode="Ï" horiz-adv-x="608" d="M70 0l311 1462h235l-311 -1462h-235zM243 1718q0 60 35 98t98 38q48 0 76.5 -23.5t28.5 -71.5q0 -65 -35.5 -102t-93.5 -37q-47 0 -78 23.5t-31 74.5zM626 1718q0 60 35 98t98 38q48 0 76.5 -23.5t28.5 -71.5q0 -65 -35.5 -102t-93.5 -37q-47 0 -78 23.5t-31 74.5z" /> -<glyph unicode="Ð" horiz-adv-x="1374" d="M53 623l45 200h144l137 639h369q271 0 417 -145t146 -424q0 -271 -100 -473t-291 -311t-449 -109h-401l129 623h-146zM348 201h135q177 0 309 86t202.5 242t70.5 356q0 184 -88 280.5t-256 96.5h-146l-94 -439h285l-45 -200h-283z" /> -<glyph unicode="Ñ" horiz-adv-x="1491" d="M68 0l309 1462h268l399 -1149h7q6 54 31 192.5t40 203.5l160 753h219l-309 -1462h-260l-410 1163h-6l-10 -69q-24 -149 -35.5 -212.5t-183.5 -881.5h-219zM582 1577q57 285 256 285q46 0 85 -17.5t72.5 -38t63.5 -38t59 -17.5q40 0 65 26.5t48 86.5h137 q-66 -285 -260 -285q-45 0 -82.5 17t-71.5 37.5t-65.5 37.5t-63.5 17q-38 0 -63 -27.5t-43 -83.5h-137z" /> -<glyph unicode="Ò" horiz-adv-x="1485" d="M135 543q0 267 98.5 487.5t269.5 337.5t388 117q251 0 390.5 -149t139.5 -414q0 -279 -95 -497t-261.5 -331.5t-386.5 -113.5q-259 0 -401 149.5t-142 413.5zM383 545q0 -173 81.5 -267t227.5 -94q138 0 248.5 95.5t172 265t61.5 375.5q0 170 -79 265t-223 95 q-138 0 -250 -96t-175.5 -266.5t-63.5 -372.5zM652 1886v21h245q47 -154 132 -303v-25h-144q-65 63 -132 151.5t-101 155.5z" /> -<glyph unicode="Ó" horiz-adv-x="1485" d="M135 543q0 267 98.5 487.5t269.5 337.5t388 117q251 0 390.5 -149t139.5 -414q0 -279 -95 -497t-261.5 -331.5t-386.5 -113.5q-259 0 -401 149.5t-142 413.5zM383 545q0 -173 81.5 -267t227.5 -94q138 0 248.5 95.5t172 265t61.5 375.5q0 170 -79 265t-223 95 q-138 0 -250 -96t-175.5 -266.5t-63.5 -372.5zM787 1579v25q97 108 225 303h264v-19q-54 -66 -158 -161.5t-175 -147.5h-156z" /> -<glyph unicode="Ô" horiz-adv-x="1485" d="M135 543q0 267 98.5 487.5t269.5 337.5t388 117q251 0 390.5 -149t139.5 -414q0 -279 -95 -497t-261.5 -331.5t-386.5 -113.5q-259 0 -401 149.5t-142 413.5zM383 545q0 -173 81.5 -267t227.5 -94q138 0 248.5 95.5t172 265t61.5 375.5q0 170 -79 265t-223 95 q-138 0 -250 -96t-175.5 -266.5t-63.5 -372.5zM555 1579v25q138 128 201 195.5t90 107.5h248q38 -99 174 -303v-25h-152q-76 63 -161 178q-131 -110 -236 -178h-164z" /> -<glyph unicode="Õ" horiz-adv-x="1485" d="M135 543q0 267 98.5 487.5t269.5 337.5t388 117q251 0 390.5 -149t139.5 -414q0 -279 -95 -497t-261.5 -331.5t-386.5 -113.5q-259 0 -401 149.5t-142 413.5zM383 545q0 -173 81.5 -267t227.5 -94q138 0 248.5 95.5t172 265t61.5 375.5q0 170 -79 265t-223 95 q-138 0 -250 -96t-175.5 -266.5t-63.5 -372.5zM543 1577q57 285 256 285q46 0 85 -17.5t72.5 -38t63.5 -38t59 -17.5q40 0 65 26.5t48 86.5h137q-66 -285 -260 -285q-45 0 -82.5 17t-71.5 37.5t-65.5 37.5t-63.5 17q-38 0 -63 -27.5t-43 -83.5h-137z" /> -<glyph unicode="Ö" horiz-adv-x="1485" d="M135 543q0 267 98.5 487.5t269.5 337.5t388 117q251 0 390.5 -149t139.5 -414q0 -279 -95 -497t-261.5 -331.5t-386.5 -113.5q-259 0 -401 149.5t-142 413.5zM383 545q0 -173 81.5 -267t227.5 -94q138 0 248.5 95.5t172 265t61.5 375.5q0 170 -79 265t-223 95 q-138 0 -250 -96t-175.5 -266.5t-63.5 -372.5zM623 1718q0 60 35 98t98 38q48 0 76.5 -23.5t28.5 -71.5q0 -65 -35.5 -102t-93.5 -37q-47 0 -78 23.5t-31 74.5zM1006 1718q0 60 35 98t98 38q48 0 76.5 -23.5t28.5 -71.5q0 -65 -35.5 -102t-93.5 -37q-47 0 -78 23.5t-31 74.5 z" /> -<glyph unicode="×" d="M147 1034l125 125l312 -309l313 309l127 -123l-315 -313l311 -313l-123 -123l-313 309l-312 -307l-122 123l307 311z" /> -<glyph unicode="Ø" horiz-adv-x="1485" d="M109 18l129 160q-103 138 -103 365q0 267 98.5 487.5t269.5 337.5t388 117q189 0 317 -94l119 149l133 -104l-133 -166q94 -130 94 -348q0 -279 -95 -497t-261.5 -331.5t-386.5 -113.5q-193 0 -318 83l-118 -149zM377 545q0 -88 24 -164l668 836q-80 65 -197 65 q-141 0 -253 -93t-177 -265t-65 -379zM500 238q75 -56 194 -56q139 0 250.5 95.5t173.5 264.5t62 378q0 88 -19 143z" /> -<glyph unicode="Ù" horiz-adv-x="1399" d="M152 391q0 83 20 170l193 901h237l-192 -905q-21 -88 -21 -158q0 -102 59.5 -158.5t180.5 -56.5q145 0 230 80.5t124 261.5l199 936h237l-202 -956q-56 -267 -208 -396.5t-403 -129.5q-217 0 -335.5 106t-118.5 305zM619 1886v21h245q47 -154 132 -303v-25h-144 q-65 63 -132 151.5t-101 155.5z" /> -<glyph unicode="Ú" horiz-adv-x="1399" d="M152 391q0 83 20 170l193 901h237l-192 -905q-21 -88 -21 -158q0 -102 59.5 -158.5t180.5 -56.5q145 0 230 80.5t124 261.5l199 936h237l-202 -956q-56 -267 -208 -396.5t-403 -129.5q-217 0 -335.5 106t-118.5 305zM791 1579v25q97 108 225 303h264v-19 q-54 -66 -158 -161.5t-175 -147.5h-156z" /> -<glyph unicode="Û" horiz-adv-x="1399" d="M152 391q0 83 20 170l193 901h237l-192 -905q-21 -88 -21 -158q0 -102 59.5 -158.5t180.5 -56.5q145 0 230 80.5t124 261.5l199 936h237l-202 -956q-56 -267 -208 -396.5t-403 -129.5q-217 0 -335.5 106t-118.5 305zM536 1579v25q138 128 201 195.5t90 107.5h248 q38 -99 174 -303v-25h-152q-76 63 -161 178q-131 -110 -236 -178h-164z" /> -<glyph unicode="Ü" horiz-adv-x="1399" d="M152 391q0 83 20 170l193 901h237l-192 -905q-21 -88 -21 -158q0 -102 59.5 -158.5t180.5 -56.5q145 0 230 80.5t124 261.5l199 936h237l-202 -956q-56 -267 -208 -396.5t-403 -129.5q-217 0 -335.5 106t-118.5 305zM602 1718q0 60 35 98t98 38q48 0 76.5 -23.5 t28.5 -71.5q0 -65 -35.5 -102t-93.5 -37q-47 0 -78 23.5t-31 74.5zM985 1718q0 60 35 98t98 38q48 0 76.5 -23.5t28.5 -71.5q0 -65 -35.5 -102t-93.5 -37q-47 0 -78 23.5t-31 74.5z" /> -<glyph unicode="Ý" horiz-adv-x="1092" d="M186 1462h242l154 -669l432 669h266l-623 -913l-114 -549h-238l119 553zM610 1579v25q97 108 225 303h264v-19q-54 -66 -158 -161.5t-175 -147.5h-156z" /> -<glyph unicode="Þ" horiz-adv-x="1174" d="M70 0l309 1462h237l-51 -243h97q227 0 344.5 -101t117.5 -301q0 -243 -166.5 -377.5t-476.5 -134.5h-108l-66 -305h-237zM414 506h96q176 0 274.5 78.5t98.5 226.5q0 109 -59.5 158t-180.5 49h-121z" /> -<glyph unicode="ß" horiz-adv-x="1266" d="M-258 -276q61 -21 113 -21q65 0 106.5 43.5t63.5 147.5l262 1234q48 231 173 333t349 102q188 0 292.5 -80t104.5 -215q0 -169 -179 -299q-118 -87 -148.5 -119.5t-30.5 -67.5q0 -44 74 -101q107 -84 143 -127t55 -92.5t19 -109.5q0 -172 -116 -272t-314 -100 q-182 0 -283 65v201q126 -86 252 -86q105 0 164 44t59 124q0 48 -23.5 85t-111.5 107q-82 64 -121 121.5t-39 126.5q0 75 44.5 139t135.5 124q98 66 138.5 112t40.5 98q0 65 -47 101t-132 36q-210 0 -262 -239l-264 -1260q-42 -197 -134.5 -284t-242.5 -87q-69 0 -141 23 v193z" /> -<glyph unicode="à" horiz-adv-x="1186" d="M94 367q0 202 69.5 378t191.5 278.5t268 102.5q97 0 167 -45.5t109 -132.5h10l62 158h180l-236 -1106h-182l21 176h-6q-158 -196 -349 -196q-141 0 -223 101.5t-82 285.5zM332 373q0 -102 40.5 -152.5t112.5 -50.5q82 0 161 77.5t130 207.5t51 284q0 88 -47 141.5 t-123 53.5q-85 0 -160 -77t-120 -209.5t-45 -274.5zM470 1548v21h245q47 -154 132 -303v-25h-144q-65 63 -132 151.5t-101 155.5z" /> -<glyph unicode="á" horiz-adv-x="1186" d="M94 367q0 202 69.5 378t191.5 278.5t268 102.5q97 0 167 -45.5t109 -132.5h10l62 158h180l-236 -1106h-182l21 176h-6q-158 -196 -349 -196q-141 0 -223 101.5t-82 285.5zM332 373q0 -102 40.5 -152.5t112.5 -50.5q82 0 161 77.5t130 207.5t51 284q0 88 -47 141.5 t-123 53.5q-85 0 -160 -77t-120 -209.5t-45 -274.5zM598 1241v25q97 108 225 303h264v-19q-54 -66 -158 -161.5t-175 -147.5h-156z" /> -<glyph unicode="â" horiz-adv-x="1186" d="M94 367q0 202 69.5 378t191.5 278.5t268 102.5q97 0 167 -45.5t109 -132.5h10l62 158h180l-236 -1106h-182l21 176h-6q-158 -196 -349 -196q-141 0 -223 101.5t-82 285.5zM332 373q0 -102 40.5 -152.5t112.5 -50.5q82 0 161 77.5t130 207.5t51 284q0 88 -47 141.5 t-123 53.5q-85 0 -160 -77t-120 -209.5t-45 -274.5zM351 1241v25q138 128 201 195.5t90 107.5h248q38 -99 174 -303v-25h-152q-76 63 -161 178q-131 -110 -236 -178h-164z" /> -<glyph unicode="ã" horiz-adv-x="1186" d="M94 367q0 202 69.5 378t191.5 278.5t268 102.5q97 0 167 -45.5t109 -132.5h10l62 158h180l-236 -1106h-182l21 176h-6q-158 -196 -349 -196q-141 0 -223 101.5t-82 285.5zM332 373q0 -102 40.5 -152.5t112.5 -50.5q82 0 161 77.5t130 207.5t51 284q0 88 -47 141.5 t-123 53.5q-85 0 -160 -77t-120 -209.5t-45 -274.5zM344 1239q57 285 256 285q46 0 85 -17.5t72.5 -38t63.5 -38t59 -17.5q40 0 65 26.5t48 86.5h137q-66 -285 -260 -285q-45 0 -82.5 17t-71.5 37.5t-65.5 37.5t-63.5 17q-38 0 -63 -27.5t-43 -83.5h-137z" /> -<glyph unicode="ä" horiz-adv-x="1186" d="M94 367q0 202 69.5 378t191.5 278.5t268 102.5q97 0 167 -45.5t109 -132.5h10l62 158h180l-236 -1106h-182l21 176h-6q-158 -196 -349 -196q-141 0 -223 101.5t-82 285.5zM332 373q0 -102 40.5 -152.5t112.5 -50.5q82 0 161 77.5t130 207.5t51 284q0 88 -47 141.5 t-123 53.5q-85 0 -160 -77t-120 -209.5t-45 -274.5zM425 1380q0 60 35 98t98 38q48 0 76.5 -23.5t28.5 -71.5q0 -65 -35.5 -102t-93.5 -37q-47 0 -78 23.5t-31 74.5zM808 1380q0 60 35 98t98 38q48 0 76.5 -23.5t28.5 -71.5q0 -65 -35.5 -102t-93.5 -37q-47 0 -78 23.5 t-31 74.5z" /> -<glyph unicode="å" horiz-adv-x="1186" d="M94 367q0 202 69.5 378t191.5 278.5t268 102.5q97 0 167 -45.5t109 -132.5h10l62 158h180l-236 -1106h-182l21 176h-6q-158 -196 -349 -196q-141 0 -223 101.5t-82 285.5zM332 373q0 -102 40.5 -152.5t112.5 -50.5q82 0 161 77.5t130 207.5t51 284q0 88 -47 141.5 t-123 53.5q-85 0 -160 -77t-120 -209.5t-45 -274.5zM517 1464q0 103 65 164.5t168 61.5q104 0 171 -60.5t67 -163.5q0 -104 -66 -165.5t-172 -61.5t-169.5 61t-63.5 164zM646 1464q0 -49 26.5 -76.5t77.5 -27.5q47 0 77 27.5t30 76.5q0 50 -30 78.5t-77 28.5 q-45 0 -74.5 -28.5t-29.5 -78.5z" /> -<glyph unicode="æ" horiz-adv-x="1726" d="M94 367q0 201 69 378t188.5 279t260.5 102q88 0 152 -43.5t108 -134.5h9l63 158h148l-25 -117q51 63 131 100t180 37q140 0 220.5 -76.5t80.5 -201.5q0 -182 -166.5 -284.5t-474.5 -102.5h-45l-4 -60q0 -117 60.5 -177t175.5 -60q125 0 305 84v-189q-175 -79 -344 -79 q-222 0 -305 137l-23 -117h-151l20 176h-8q-85 -106 -165.5 -151t-174.5 -45q-134 0 -209.5 103t-75.5 284zM332 373q0 -105 37 -154t96 -49q85 0 162.5 80.5t125.5 215.5t48 267q0 91 -38.5 146t-113.5 55q-85 0 -159.5 -80t-116 -211t-41.5 -270zM1022 633h31 q187 0 293 53.5t106 149.5q0 58 -34 84t-85 26q-103 0 -188.5 -86t-122.5 -227z" /> -<glyph unicode="ç" horiz-adv-x="954" d="M94 389q0 207 73.5 376.5t206.5 265t302 95.5q164 0 297 -61l-70 -184q-122 53 -221 53q-150 0 -250 -153.5t-100 -379.5q0 -111 56 -171t155 -60q74 0 138.5 22t129.5 54v-195q-140 -71 -305 -71q-196 0 -304 106t-108 303zM197 -342q47 -14 96 -14q137 0 137 96 q0 40 -35 61.5t-104 30.5l98 168h146l-50 -96q72 -25 104 -67t32 -101q0 -106 -82 -167t-224 -61q-64 0 -118 15v135z" /> -<glyph unicode="è" horiz-adv-x="1075" d="M94 401q0 198 77.5 368.5t210 263.5t296.5 93q161 0 250.5 -72.5t89.5 -205.5q0 -182 -166.5 -284.5t-474.5 -102.5h-43l-2 -31v-29q0 -111 56.5 -174t168.5 -63q72 0 143 19t168 65v-187q-96 -44 -176.5 -62.5t-179.5 -18.5q-197 0 -307.5 111t-110.5 310zM362 633h29 q188 0 294 53.5t106 151.5q0 51 -32 79.5t-95 28.5q-96 0 -180.5 -86t-121.5 -227zM436 1548v21h245q47 -154 132 -303v-25h-144q-65 63 -132 151.5t-101 155.5z" /> -<glyph unicode="é" horiz-adv-x="1075" d="M94 401q0 198 77.5 368.5t210 263.5t296.5 93q161 0 250.5 -72.5t89.5 -205.5q0 -182 -166.5 -284.5t-474.5 -102.5h-43l-2 -31v-29q0 -111 56.5 -174t168.5 -63q72 0 143 19t168 65v-187q-96 -44 -176.5 -62.5t-179.5 -18.5q-197 0 -307.5 111t-110.5 310zM362 633h29 q188 0 294 53.5t106 151.5q0 51 -32 79.5t-95 28.5q-96 0 -180.5 -86t-121.5 -227zM557 1241v25q97 108 225 303h264v-19q-54 -66 -158 -161.5t-175 -147.5h-156z" /> -<glyph unicode="ê" horiz-adv-x="1075" d="M94 401q0 198 77.5 368.5t210 263.5t296.5 93q161 0 250.5 -72.5t89.5 -205.5q0 -182 -166.5 -284.5t-474.5 -102.5h-43l-2 -31v-29q0 -111 56.5 -174t168.5 -63q72 0 143 19t168 65v-187q-96 -44 -176.5 -62.5t-179.5 -18.5q-197 0 -307.5 111t-110.5 310zM362 633h29 q188 0 294 53.5t106 151.5q0 51 -32 79.5t-95 28.5q-96 0 -180.5 -86t-121.5 -227zM320 1241v25q138 128 201 195.5t90 107.5h248q38 -99 174 -303v-25h-152q-76 63 -161 178q-131 -110 -236 -178h-164z" /> -<glyph unicode="ë" horiz-adv-x="1075" d="M94 401q0 198 77.5 368.5t210 263.5t296.5 93q161 0 250.5 -72.5t89.5 -205.5q0 -182 -166.5 -284.5t-474.5 -102.5h-43l-2 -31v-29q0 -111 56.5 -174t168.5 -63q72 0 143 19t168 65v-187q-96 -44 -176.5 -62.5t-179.5 -18.5q-197 0 -307.5 111t-110.5 310zM362 633h29 q188 0 294 53.5t106 151.5q0 51 -32 79.5t-95 28.5q-96 0 -180.5 -86t-121.5 -227zM388 1380q0 60 35 98t98 38q48 0 76.5 -23.5t28.5 -71.5q0 -65 -35.5 -102t-93.5 -37q-47 0 -78 23.5t-31 74.5zM771 1380q0 60 35 98t98 38q48 0 76.5 -23.5t28.5 -71.5q0 -65 -35.5 -102 t-93.5 -37q-47 0 -78 23.5t-31 74.5z" /> -<glyph unicode="ì" horiz-adv-x="563" d="M47 0l236 1106h235l-235 -1106h-236zM159 1548v21h245q47 -154 132 -303v-25h-144q-65 63 -132 151.5t-101 155.5z" /> -<glyph unicode="í" horiz-adv-x="563" d="M47 0l236 1106h235l-235 -1106h-236zM308 1241v25q97 108 225 303h264v-19q-54 -66 -158 -161.5t-175 -147.5h-156z" /> -<glyph unicode="î" horiz-adv-x="563" d="M47 0l236 1106h235l-235 -1106h-236zM64 1241v25q138 128 201 195.5t90 107.5h248q38 -99 174 -303v-25h-152q-76 63 -161 178q-131 -110 -236 -178h-164z" /> -<glyph unicode="ï" horiz-adv-x="563" d="M47 0l236 1106h235l-235 -1106h-236zM142 1380q0 60 35 98t98 38q48 0 76.5 -23.5t28.5 -71.5q0 -65 -35.5 -102t-93.5 -37q-47 0 -78 23.5t-31 74.5zM525 1380q0 60 35 98t98 38q48 0 76.5 -23.5t28.5 -71.5q0 -65 -35.5 -102t-93.5 -37q-47 0 -78 23.5t-31 74.5z" /> -<glyph unicode="ð" horiz-adv-x="1174" d="M80 389q0 162 65.5 299t184.5 215t266 78q96 0 168 -38.5t113 -108.5h6q-10 243 -133 383l-250 -142l-72 129l219 121q-44 41 -135 96l106 152q129 -72 209 -146l250 138l70 -127l-217 -121q155 -205 155 -512q0 -255 -73 -444.5t-204 -285t-312 -95.5q-197 0 -306.5 107 t-109.5 302zM317 377q0 -104 49 -159.5t142 -55.5q92 0 161.5 59.5t108.5 159t39 205.5q0 97 -52 155t-144 58q-91 0 -160.5 -56t-106.5 -153.5t-37 -212.5z" /> -<glyph unicode="ñ" horiz-adv-x="1208" d="M47 0l236 1106h184l-21 -205h9q83 118 171 171.5t191 53.5q134 0 207.5 -76t73.5 -216q0 -69 -23 -181l-137 -653h-236l142 672q18 90 18 131q0 131 -129 131q-72 0 -142 -57t-126 -164.5t-84 -243.5l-98 -469h-236zM363 1239q57 285 256 285q46 0 85 -17.5t72.5 -38 t63.5 -38t59 -17.5q40 0 65 26.5t48 86.5h137q-66 -285 -260 -285q-45 0 -82.5 17t-71.5 37.5t-65.5 37.5t-63.5 17q-38 0 -63 -27.5t-43 -83.5h-137z" /> -<glyph unicode="ò" horiz-adv-x="1174" d="M94 408q0 199 71.5 365t200.5 258.5t298 92.5q195 0 305 -116t110 -316q0 -202 -73 -367.5t-200.5 -254t-293.5 -88.5q-192 0 -305 114.5t-113 311.5zM332 403q0 -111 49.5 -170t146.5 -59q90 0 162 68t112 190.5t40 269.5q0 107 -49 167.5t-140 60.5q-93 0 -166.5 -71.5 t-114 -194t-40.5 -261.5zM444 1548v21h245q47 -154 132 -303v-25h-144q-65 63 -132 151.5t-101 155.5z" /> -<glyph unicode="ó" horiz-adv-x="1174" d="M94 408q0 199 71.5 365t200.5 258.5t298 92.5q195 0 305 -116t110 -316q0 -202 -73 -367.5t-200.5 -254t-293.5 -88.5q-192 0 -305 114.5t-113 311.5zM332 403q0 -111 49.5 -170t146.5 -59q90 0 162 68t112 190.5t40 269.5q0 107 -49 167.5t-140 60.5q-93 0 -166.5 -71.5 t-114 -194t-40.5 -261.5zM580 1241v25q97 108 225 303h264v-19q-54 -66 -158 -161.5t-175 -147.5h-156z" /> -<glyph unicode="ô" horiz-adv-x="1174" d="M94 408q0 199 71.5 365t200.5 258.5t298 92.5q195 0 305 -116t110 -316q0 -202 -73 -367.5t-200.5 -254t-293.5 -88.5q-192 0 -305 114.5t-113 311.5zM332 403q0 -111 49.5 -170t146.5 -59q90 0 162 68t112 190.5t40 269.5q0 107 -49 167.5t-140 60.5q-93 0 -166.5 -71.5 t-114 -194t-40.5 -261.5zM341 1241v25q138 128 201 195.5t90 107.5h248q38 -99 174 -303v-25h-152q-76 63 -161 178q-131 -110 -236 -178h-164z" /> -<glyph unicode="õ" horiz-adv-x="1174" d="M94 408q0 199 71.5 365t200.5 258.5t298 92.5q195 0 305 -116t110 -316q0 -202 -73 -367.5t-200.5 -254t-293.5 -88.5q-192 0 -305 114.5t-113 311.5zM332 403q0 -111 49.5 -170t146.5 -59q90 0 162 68t112 190.5t40 269.5q0 107 -49 167.5t-140 60.5q-93 0 -166.5 -71.5 t-114 -194t-40.5 -261.5zM328 1239q57 285 256 285q46 0 85 -17.5t72.5 -38t63.5 -38t59 -17.5q40 0 65 26.5t48 86.5h137q-66 -285 -260 -285q-45 0 -82.5 17t-71.5 37.5t-65.5 37.5t-63.5 17q-38 0 -63 -27.5t-43 -83.5h-137z" /> -<glyph unicode="ö" horiz-adv-x="1174" d="M94 408q0 199 71.5 365t200.5 258.5t298 92.5q195 0 305 -116t110 -316q0 -202 -73 -367.5t-200.5 -254t-293.5 -88.5q-192 0 -305 114.5t-113 311.5zM332 403q0 -111 49.5 -170t146.5 -59q90 0 162 68t112 190.5t40 269.5q0 107 -49 167.5t-140 60.5q-93 0 -166.5 -71.5 t-114 -194t-40.5 -261.5zM409 1380q0 60 35 98t98 38q48 0 76.5 -23.5t28.5 -71.5q0 -65 -35.5 -102t-93.5 -37q-47 0 -78 23.5t-31 74.5zM792 1380q0 60 35 98t98 38q48 0 76.5 -23.5t28.5 -71.5q0 -65 -35.5 -102t-93.5 -37q-47 0 -78 23.5t-31 74.5z" /> -<glyph unicode="÷" d="M117 631v180h936v-180h-936zM459 373q0 64 31.5 99.5t93.5 35.5t94.5 -36t32.5 -99q0 -64 -34.5 -100.5t-92.5 -36.5t-91.5 35.5t-33.5 101.5zM459 1071q0 64 31.5 99.5t93.5 35.5t94.5 -36t32.5 -99q0 -64 -34.5 -100.5t-92.5 -36.5t-91.5 35.5t-33.5 101.5z" /> -<glyph unicode="ø" horiz-adv-x="1174" d="M51 6l115 141q-70 104 -70 261q0 200 70.5 365t199.5 258t298 93q136 0 239 -61l86 108l125 -96l-100 -117q63 -100 63 -258q0 -208 -74 -376t-200.5 -255t-288.5 -87q-137 0 -235 59l-105 -131zM324 426q0 -39 8 -74l442 549q-45 35 -121 35q-141 0 -235 -145.5 t-94 -364.5zM408 201q41 -33 120 -33q89 0 163 66.5t116.5 184t42.5 257.5q0 45 -6 67z" /> -<glyph unicode="ù" horiz-adv-x="1208" d="M111 274q0 63 12 124.5t24 123.5l123 584h236l-129 -610q-31 -141 -31 -193q0 -133 127 -133q72 0 143 57t126 162.5t85 247.5l99 469h233l-233 -1106h-185l21 205h-8q-82 -116 -171 -170.5t-192 -54.5q-134 0 -207 76t-73 218zM446 1548v21h245q47 -154 132 -303v-25 h-144q-65 63 -132 151.5t-101 155.5z" /> -<glyph unicode="ú" horiz-adv-x="1208" d="M111 274q0 63 12 124.5t24 123.5l123 584h236l-129 -610q-31 -141 -31 -193q0 -133 127 -133q72 0 143 57t126 162.5t85 247.5l99 469h233l-233 -1106h-185l21 205h-8q-82 -116 -171 -170.5t-192 -54.5q-134 0 -207 76t-73 218zM623 1241v25q97 108 225 303h264v-19 q-54 -66 -158 -161.5t-175 -147.5h-156z" /> -<glyph unicode="û" horiz-adv-x="1208" d="M111 274q0 63 12 124.5t24 123.5l123 584h236l-129 -610q-31 -141 -31 -193q0 -133 127 -133q72 0 143 57t126 162.5t85 247.5l99 469h233l-233 -1106h-185l21 205h-8q-82 -116 -171 -170.5t-192 -54.5q-134 0 -207 76t-73 218zM370 1241v25q138 128 201 195.5t90 107.5 h248q38 -99 174 -303v-25h-152q-76 63 -161 178q-131 -110 -236 -178h-164z" /> -<glyph unicode="ü" horiz-adv-x="1208" d="M111 274q0 63 12 124.5t24 123.5l123 584h236l-129 -610q-31 -141 -31 -193q0 -133 127 -133q72 0 143 57t126 162.5t85 247.5l99 469h233l-233 -1106h-185l21 205h-8q-82 -116 -171 -170.5t-192 -54.5q-134 0 -207 76t-73 218zM432 1380q0 60 35 98t98 38 q48 0 76.5 -23.5t28.5 -71.5q0 -65 -35.5 -102t-93.5 -37q-47 0 -78 23.5t-31 74.5zM815 1380q0 60 35 98t98 38q48 0 76.5 -23.5t28.5 -71.5q0 -65 -35.5 -102t-93.5 -37q-47 0 -78 23.5t-31 74.5z" /> -<glyph unicode="ý" horiz-adv-x="1004" d="M-170 -285q75 -16 125 -16q74 0 134 43.5t124 155.5l51 92l-164 1116h232l63 -531q9 -62 16 -174.5t7 -181.5h6q86 215 135 313l293 574h254l-688 -1280q-90 -165 -196 -241.5t-249 -76.5q-76 0 -143 19v188zM501 1241v25q97 108 225 303h264v-19q-54 -66 -158 -161.5 t-175 -147.5h-156z" /> -<glyph unicode="þ" horiz-adv-x="1200" d="M-55 -492l432 2048h235q-48 -223 -73 -339t-76 -291h8q155 200 328 200q144 0 224.5 -102t80.5 -287q0 -204 -68 -381.5t-184.5 -276.5t-265.5 -99q-94 0 -165 45.5t-114 130.5h-8q-7 -91 -25 -185l-96 -463h-233zM369 373q0 -98 46 -150.5t132 -52.5t159.5 77t116.5 209 t43 277q0 100 -41 150.5t-118 50.5q-84 0 -163 -81t-127 -213.5t-48 -266.5z" /> -<glyph unicode="ÿ" horiz-adv-x="1004" d="M-170 -285q75 -16 125 -16q74 0 134 43.5t124 155.5l51 92l-164 1116h232l63 -531q9 -62 16 -174.5t7 -181.5h6q86 215 135 313l293 574h254l-688 -1280q-90 -165 -196 -241.5t-249 -76.5q-76 0 -143 19v188zM323 1380q0 60 35 98t98 38q48 0 76.5 -23.5t28.5 -71.5 q0 -65 -35.5 -102t-93.5 -37q-47 0 -78 23.5t-31 74.5zM706 1380q0 60 35 98t98 38q48 0 76.5 -23.5t28.5 -71.5q0 -65 -35.5 -102t-93.5 -37q-47 0 -78 23.5t-31 74.5z" /> -<glyph unicode="ı" horiz-adv-x="563" d="M47 0l236 1106h235l-235 -1106h-236z" /> -<glyph unicode="Œ" horiz-adv-x="1798" d="M135 543q0 267 98.5 487.5t269.5 337.5t388 117q145 0 223 -23h760l-43 -205h-539l-84 -395h504l-43 -200h-504l-96 -459h539l-43 -203h-717q-84 -20 -170 -20q-259 0 -401 149.5t-142 413.5zM383 545q0 -173 81.5 -267t227.5 -94q74 0 139 27l222 1038q-68 31 -181 31 q-138 0 -250 -96t-175.5 -266.5t-63.5 -372.5z" /> -<glyph unicode="œ" horiz-adv-x="1788" d="M94 410q0 206 73.5 372.5t201 254t293.5 87.5q237 0 335 -192q73 91 174 142.5t226 51.5q159 0 246.5 -74.5t87.5 -203.5q0 -183 -165.5 -285t-471.5 -102h-47l-3 -60q0 -111 56.5 -174t169.5 -63q69 0 134.5 17.5t176.5 66.5v-189q-91 -43 -175 -61t-181 -18 q-120 0 -212.5 46t-140.5 138q-137 -182 -374 -182q-186 0 -295 115.5t-109 312.5zM332 412q0 -116 48.5 -177t139.5 -61q143 0 229.5 146.5t86.5 381.5q0 111 -49.5 169.5t-139.5 58.5q-87 0 -157.5 -64t-114 -186.5t-43.5 -267.5zM1073 633h31q189 0 294 54t105 155 q0 48 -30 76t-87 28q-105 0 -192 -85.5t-121 -227.5z" /> -<glyph unicode="Ÿ" horiz-adv-x="1092" d="M186 1462h242l154 -669l432 669h266l-623 -913l-114 -549h-238l119 553zM440 1718q0 60 35 98t98 38q48 0 76.5 -23.5t28.5 -71.5q0 -65 -35.5 -102t-93.5 -37q-47 0 -78 23.5t-31 74.5zM823 1718q0 60 35 98t98 38q48 0 76.5 -23.5t28.5 -71.5q0 -65 -35.5 -102 t-93.5 -37q-47 0 -78 23.5t-31 74.5z" /> -<glyph unicode="ˆ" horiz-adv-x="1135" d="M354 1241v25q138 128 201 195.5t90 107.5h248q38 -99 174 -303v-25h-152q-76 63 -161 178q-131 -110 -236 -178h-164z" /> -<glyph unicode="˚" horiz-adv-x="1182" d="M541 1464q0 103 65 164.5t168 61.5q104 0 171 -60.5t67 -163.5q0 -104 -66 -165.5t-172 -61.5t-169.5 61t-63.5 164zM670 1464q0 -49 26.5 -76.5t77.5 -27.5q47 0 77 27.5t30 76.5q0 50 -30 78.5t-77 28.5q-45 0 -74.5 -28.5t-29.5 -78.5z" /> -<glyph unicode="˜" horiz-adv-x="1135" d="M326 1239q57 285 256 285q46 0 85 -17.5t72.5 -38t63.5 -38t59 -17.5q40 0 65 26.5t48 86.5h137q-66 -285 -260 -285q-45 0 -82.5 17t-71.5 37.5t-65.5 37.5t-63.5 17q-38 0 -63 -27.5t-43 -83.5h-137z" /> -<glyph unicode=" " horiz-adv-x="953" /> -<glyph unicode=" " horiz-adv-x="1907" /> -<glyph unicode=" " horiz-adv-x="953" /> -<glyph unicode=" " horiz-adv-x="1907" /> -<glyph unicode=" " horiz-adv-x="635" /> -<glyph unicode=" " horiz-adv-x="476" /> -<glyph unicode=" " horiz-adv-x="317" /> -<glyph unicode=" " horiz-adv-x="317" /> -<glyph unicode=" " horiz-adv-x="238" /> -<glyph unicode=" " horiz-adv-x="381" /> -<glyph unicode=" " horiz-adv-x="105" /> -<glyph unicode="‐" horiz-adv-x="649" d="M47 446l45 203h502l-45 -203h-502z" /> -<glyph unicode="‑" horiz-adv-x="649" d="M47 446l45 203h502l-45 -203h-502z" /> -<glyph unicode="‒" horiz-adv-x="649" d="M47 446l45 203h502l-45 -203h-502z" /> -<glyph unicode="–" horiz-adv-x="983" d="M47 453l43 194h838l-43 -194h-838z" /> -<glyph unicode="—" horiz-adv-x="1966" d="M47 453l43 194h1821l-43 -194h-1821z" /> -<glyph unicode="‘" horiz-adv-x="393" d="M119 983q34 76 106.5 209t159.5 270h176q-122 -286 -199 -501h-237z" /> -<glyph unicode="’" horiz-adv-x="393" d="M115 961q43 95 106 255t92 246h238l8 -22q-37 -83 -110.5 -217.5t-155.5 -261.5h-178z" /> -<glyph unicode="‚" horiz-adv-x="530" d="M-102 -264q105 238 200 502h236l8 -23q-108 -233 -266 -479h-178z" /> -<glyph unicode="“" horiz-adv-x="803" d="M119 983q34 76 106.5 209t159.5 270h176q-122 -286 -199 -501h-237zM526 983q84 190 267 479h176q-122 -286 -199 -501h-235z" /> -<glyph unicode="”" horiz-adv-x="803" d="M115 961q43 95 106 255t92 246h238l8 -22q-37 -83 -110.5 -217.5t-155.5 -261.5h-178zM522 961q51 114 109 261t90 240h237l9 -22q-98 -220 -269 -479h-176z" /> -<glyph unicode="„" horiz-adv-x="938" d="M-102 -264q105 238 200 502h236l8 -23q-108 -233 -266 -479h-178zM307 -264q120 281 199 502h235l9 -23q-92 -206 -267 -479h-176z" /> -<glyph unicode="•" horiz-adv-x="756" d="M152 684q0 156 83.5 252t223.5 96q100 0 158.5 -54.5t58.5 -168.5q0 -156 -82 -252t-227 -96q-102 0 -158.5 57.5t-56.5 165.5z" /> -<glyph unicode="…" horiz-adv-x="1634" d="M834 94q0 83 47 132.5t131 49.5q56 0 89.5 -31.5t33.5 -92.5q0 -78 -47.5 -129.5t-124.5 -51.5q-66 0 -97.5 35.5t-31.5 87.5zM594 94q0 83 47 132.5t131 49.5q56 0 89.5 -31.5t33.5 -92.5q0 -78 -47.5 -129.5t-124.5 -51.5q-66 0 -97.5 35.5t-31.5 87.5zM293 94 q0 83 47 132.5t131 49.5q56 0 89.5 -31.5t33.5 -92.5q0 -78 -47.5 -129.5t-124.5 -51.5q-66 0 -97.5 35.5t-31.5 87.5z" /> -<glyph unicode=" " horiz-adv-x="381" /> -<glyph unicode="‹" horiz-adv-x="621" d="M80 549v24l395 422l135 -118l-288 -334l153 -367l-178 -76z" /> -<glyph unicode="›" horiz-adv-x="621" d="M10 211l289 334l-154 366l179 76l217 -448v-25l-396 -422z" /> -<glyph unicode="⁄" horiz-adv-x="262" d="M-510 0l1085 1462h195l-1083 -1462h-197z" /> -<glyph unicode=" " horiz-adv-x="476" /> -<glyph unicode="⁴" horiz-adv-x="745" d="M70 762l26 137l477 569h197l-121 -563h123l-29 -143h-122l-39 -176h-183l39 176h-368zM268 905h199l52 221l34 129q-32 -51 -98 -131z" /> -<glyph unicode="€" d="M51 492l33 155h139q15 95 27 139h-137l32 154h148q92 260 255.5 401.5t371.5 141.5q88 0 164.5 -22t156.5 -77l-102 -180q-54 34 -107 56t-119 22q-118 0 -214.5 -87t-161.5 -255h387l-33 -154h-402q-18 -67 -28 -139h340l-33 -155h-319q0 -161 60.5 -234.5t195.5 -73.5 q120 0 258 60v-203q-129 -61 -306 -61q-216 0 -330 130t-114 382h-162z" /> -<glyph unicode="™" horiz-adv-x="1534" d="M113 1335v127h540v-127h-198v-594h-146v594h-196zM709 741v721h215l170 -534l182 534h205v-721h-146v418l4 121h-6l-184 -539h-119l-178 539h-6l4 -115v-424h-141z" /> -<glyph unicode="" horiz-adv-x="1105" d="M0 1105h1105v-1105h-1105v1105z" /> -<glyph unicode="fi" horiz-adv-x="1257" d="M-225 -279q64 -20 114 -20q134 0 177 205l217 1022h-179l21 106l194 76l21 92q44 198 134.5 281.5t256.5 83.5q115 0 211 -43l-61 -176q-74 28 -136 28q-69 0 -110.5 -43t-63.5 -141l-18 -86h229l-37 -178h-229l-223 -1053q-40 -189 -131 -278t-238 -89q-90 0 -149 23 v190zM739 0l236 1106h235l-235 -1106h-236zM1022 1378q0 68 39 110t110 42q53 0 86 -26.5t33 -80.5q0 -71 -40 -112t-105 -41q-53 0 -88 26t-35 82z" /> -<glyph unicode="fl" horiz-adv-x="1257" d="M-225 -279q64 -20 114 -20q134 0 177 205l217 1022h-179l21 106l194 76l21 92q44 198 134.5 281.5t256.5 83.5q115 0 211 -43l-61 -176q-74 28 -136 28q-69 0 -110.5 -43t-63.5 -141l-18 -86h229l-37 -178h-229l-223 -1053q-40 -189 -131 -278t-238 -89q-90 0 -149 23 v190zM739 0l330 1556h235l-331 -1556h-234z" /> -<glyph unicode="ffi" horiz-adv-x="1931" d="M-225 -279q64 -20 114 -20q133 0 177 205l217 1022h-179l21 106l194 76l21 92q44 198 134.5 281.5t256.5 83.5q115 0 211 -43l-61 -176q-74 28 -136 28q-69 0 -110.5 -43t-63.5 -141l-18 -86h438l23 96q44 197 133 281t256 84q117 0 213 -43l-62 -176q-74 28 -135 28 q-71 0 -111.5 -43t-62.5 -141l-18 -86h229l-39 -178h-227l-223 -1053q-43 -192 -133.5 -279.5t-235.5 -87.5q-95 0 -149 23v190q60 -20 114 -20q136 0 176 205l215 1022h-438l-223 -1053q-40 -189 -131 -278t-238 -89q-90 0 -149 23v190zM1415 0l236 1106h233l-235 -1106 h-234zM1698 1378q0 68 39 110t108 42q54 0 86.5 -26.5t32.5 -80.5q0 -71 -39.5 -112t-105.5 -41q-51 0 -86 26t-35 82z" /> -<glyph unicode="ffl" horiz-adv-x="1931" d="M-225 -279q64 -20 114 -20q133 0 177 205l217 1022h-179l21 106l194 76l21 92q44 198 134.5 281.5t256.5 83.5q115 0 211 -43l-61 -176q-74 28 -136 28q-69 0 -110.5 -43t-63.5 -141l-18 -86h438l23 96q44 197 133 281t256 84q117 0 213 -43l-62 -176q-74 28 -135 28 q-71 0 -111.5 -43t-62.5 -141l-18 -86h229l-39 -178h-227l-223 -1053q-43 -192 -133.5 -279.5t-235.5 -87.5q-95 0 -149 23v190q60 -20 114 -20q136 0 176 205l215 1022h-438l-223 -1053q-40 -189 -131 -278t-238 -89q-90 0 -149 23v190zM1413 0l332 1556h233l-329 -1556 h-236z" /> -</font> -</defs></svg> -\ No newline at end of file diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-SemiboldItalic-webfont.ttf b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-SemiboldItalic-webfont.ttf Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-SemiboldItalic-webfont.woff b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/fonts/OpenSans-SemiboldItalic-webfont.woff Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/stylesheet.css b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/open-sans/stylesheet.css @@ -1,136 +0,0 @@ -/***** Font Definition for Open Sans. This stylesheet comes from qrohlf.com/posts/better-opensans *****/ - -/* Regular */ -@font-face { - font-family: 'Open Sans'; - - src: url('fonts/OpenSans-Regular-webfont.eot'); - src: url('fonts/OpenSans-Regular-webfont.eot?#iefix') format('embedded-opentype'), - url('fonts/OpenSans-Regular-webfont.woff') format('woff'), - url('fonts/OpenSans-Regular-webfont.ttf') format('truetype'), - url('fonts/OpenSans-Regular-webfont.svg#OpenSansRegular') format('svg'); - font-weight: normal; - font-weight: 400; - font-style: normal; - -} - -/* Italic */ -@font-face { - font-family: 'Open Sans'; - src: url('fonts/OpenSans-Italic-webfont.eot'); - src: url('fonts/OpenSans-Italic-webfont.eot?#iefix') format('embedded-opentype'), - url('fonts/OpenSans-Italic-webfont.woff') format('woff'), - url('fonts/OpenSans-Italic-webfont.ttf') format('truetype'), - url('fonts/OpenSans-Italic-webfont.svg#OpenSansItalic') format('svg'); - font-weight: normal; - font-weight: 400; - font-style: italic; - -} - -/* Light */ -@font-face { - font-family: 'Open Sans'; - src: url('fonts/OpenSans-Light-webfont.eot'); - src: url('fonts/OpenSans-Light-webfont.eot?#iefix') format('embedded-opentype'), - url('fonts/OpenSans-Light-webfont.woff') format('woff'), - url('fonts/OpenSans-Light-webfont.ttf') format('truetype'), - url('fonts/OpenSans-Light-webfont.svg#OpenSansLight') format('svg'); - font-weight: 200; - font-style: normal; - -} - -/* Light Italic */ -@font-face { - font-family: 'Open Sans'; - src: url('fonts/OpenSans-LightItalic-webfont.eot'); - src: url('fonts/OpenSans-LightItalic-webfont.eot?#iefix') format('embedded-opentype'), - url('fonts/OpenSans-LightItalic-webfont.woff') format('woff'), - url('fonts/OpenSans-LightItalic-webfont.ttf') format('truetype'), - url('fonts/OpenSans-LightItalic-webfont.svg#OpenSansLightItalic') format('svg'); - font-weight: 200; - font-style: italic; - -} - -/* Semibold */ -@font-face { - font-family: 'Open Sans'; - src: url('fonts/OpenSans-Semibold-webfont.eot'); - src: url('fonts/OpenSans-Semibold-webfont.eot?#iefix') format('embedded-opentype'), - url('fonts/OpenSans-Semibold-webfont.woff') format('woff'), - url('fonts/OpenSans-Semibold-webfont.ttf') format('truetype'), - url('fonts/OpenSans-Semibold-webfont.svg#OpenSansSemibold') format('svg'); - font-weight: 500; - font-style: normal; - -} - -/* Semibold Italic */ -@font-face { - font-family: 'Open Sans'; - src: url('fonts/OpenSans-SemiboldItalic-webfont.eot'); - src: url('fonts/OpenSans-SemiboldItalic-webfont.eot?#iefix') format('embedded-opentype'), - url('fonts/OpenSans-SemiboldItalic-webfont.woff') format('woff'), - url('fonts/OpenSans-SemiboldItalic-webfont.ttf') format('truetype'), - url('fonts/OpenSans-SemiboldItalic-webfont.svg#OpenSansSemiboldItalic') format('svg'); - font-weight: 500; - font-style: italic; - -} - -/* Bold */ -@font-face { - font-family: 'Open Sans'; - src: url('fonts/OpenSans-Bold-webfont.eot'); - src: url('fonts/OpenSans-Bold-webfont.eot?#iefix') format('embedded-opentype'), - url('fonts/OpenSans-Bold-webfont.woff') format('woff'), - url('fonts/OpenSans-Bold-webfont.ttf') format('truetype'), - url('fonts/OpenSans-Bold-webfont.svg#OpenSansBold') format('svg'); - font-weight: bold; - font-weight: 700; - font-style: normal; - -} - -/* Bold Italic */ -@font-face { - font-family: 'Open Sans'; - src: url('fonts/OpenSans-BoldItalic-webfont.eot'); - src: url('fonts/OpenSans-BoldItalic-webfont.eot?#iefix') format('embedded-opentype'), - url('fonts/OpenSans-BoldItalic-webfont.woff') format('woff'), - url('fonts/OpenSans-BoldItalic-webfont.ttf') format('truetype'), - url('fonts/OpenSans-BoldItalic-webfont.svg#OpenSansBoldItalic') format('svg'); - font-weight: bold; - font-weight: 700; - font-style: italic; - -} - -/* Extra Bold */ -@font-face { - font-family: 'Open Sans'; - src: url('fonts/OpenSans-ExtraBold-webfont.eot'); - src: url('fonts/OpenSans-ExtraBold-webfont.eot?#iefix') format('embedded-opentype'), - url('fonts/OpenSans-ExtraBold-webfont.woff') format('woff'), - url('fonts/OpenSans-ExtraBold-webfont.ttf') format('truetype'), - url('fonts/OpenSans-ExtraBold-webfont.svg#OpenSansExtrabold') format('svg'); - font-weight: 900; - font-style: normal; - -} - -/* Extra Bold Italic */ -@font-face { - font-family: 'Open Sans'; - src: url('fonts/OpenSans-ExtraBoldItalic-webfont.eot'); - src: url('fonts/OpenSans-ExtraBoldItalic-webfont.eot?#iefix') format('embedded-opentype'), - url('fonts/OpenSans-ExtraBoldItalic-webfont.woff') format('woff'), - url('fonts/OpenSans-ExtraBoldItalic-webfont.ttf') format('truetype'), - url('fonts/OpenSans-ExtraBoldItalic-webfont.svg#OpenSansExtraboldItalic') format('svg'); - font-weight: 900; - font-style: italic; - -} diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/EOT/SourceSerifPro-Black.eot b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/EOT/SourceSerifPro-Black.eot Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/EOT/SourceSerifPro-Bold.eot b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/EOT/SourceSerifPro-Bold.eot Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/EOT/SourceSerifPro-ExtraLight.eot b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/EOT/SourceSerifPro-ExtraLight.eot Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/EOT/SourceSerifPro-Light.eot b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/EOT/SourceSerifPro-Light.eot Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/EOT/SourceSerifPro-Regular.eot b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/EOT/SourceSerifPro-Regular.eot Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/EOT/SourceSerifPro-Semibold.eot b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/EOT/SourceSerifPro-Semibold.eot Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/LICENSE.txt b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/LICENSE.txt @@ -1,93 +0,0 @@ -Copyright 2014 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries. - -This Font Software is licensed under the SIL Open Font License, Version 1.1. - -This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL - - ------------------------------------------------------------ -SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ------------------------------------------------------------ - -PREAMBLE -The goals of the Open Font License (OFL) are to stimulate worldwide -development of collaborative font projects, to support the font creation -efforts of academic and linguistic communities, and to provide a free and -open framework in which fonts may be shared and improved in partnership -with others. - -The OFL allows the licensed fonts to be used, studied, modified and -redistributed freely as long as they are not sold by themselves. The -fonts, including any derivative works, can be bundled, embedded, -redistributed and/or sold with any software provided that any reserved -names are not used by derivative works. The fonts and derivatives, -however, cannot be released under any other type of license. The -requirement for fonts to remain under this license does not apply -to any document created using the fonts or their derivatives. - -DEFINITIONS -"Font Software" refers to the set of files released by the Copyright -Holder(s) under this license and clearly marked as such. This may -include source files, build scripts and documentation. - -"Reserved Font Name" refers to any names specified as such after the -copyright statement(s). - -"Original Version" refers to the collection of Font Software components as -distributed by the Copyright Holder(s). - -"Modified Version" refers to any derivative made by adding to, deleting, -or substituting -- in part or in whole -- any of the components of the -Original Version, by changing formats or by porting the Font Software to a -new environment. - -"Author" refers to any designer, engineer, programmer, technical -writer or other person who contributed to the Font Software. - -PERMISSION & CONDITIONS -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Font Software, to use, study, copy, merge, embed, modify, -redistribute, and sell modified and unmodified copies of the Font -Software, subject to the following conditions: - -1) Neither the Font Software nor any of its individual components, -in Original or Modified Versions, may be sold by itself. - -2) Original or Modified Versions of the Font Software may be bundled, -redistributed and/or sold with any software, provided that each copy -contains the above copyright notice and this license. These can be -included either as stand-alone text files, human-readable headers or -in the appropriate machine-readable metadata fields within text or -binary files as long as those fields can be easily viewed by the user. - -3) No Modified Version of the Font Software may use the Reserved Font -Name(s) unless explicit written permission is granted by the corresponding -Copyright Holder. This restriction only applies to the primary font name as -presented to the users. - -4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font -Software shall not be used to promote, endorse or advertise any -Modified Version, except to acknowledge the contribution(s) of the -Copyright Holder(s) and the Author(s) or with their explicit written -permission. - -5) The Font Software, modified or unmodified, in part or in whole, -must be distributed entirely under this license, and must not be -distributed under any other license. The requirement for fonts to -remain under this license does not apply to any document created -using the Font Software. - -TERMINATION -This license becomes null and void if any of the above conditions are -not met. - -DISCLAIMER -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE -COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM -OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/OTF/SourceSerifPro-Black.otf b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/OTF/SourceSerifPro-Black.otf Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/OTF/SourceSerifPro-Bold.otf b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/OTF/SourceSerifPro-Bold.otf Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/OTF/SourceSerifPro-ExtraLight.otf b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/OTF/SourceSerifPro-ExtraLight.otf Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/OTF/SourceSerifPro-Light.otf b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/OTF/SourceSerifPro-Light.otf Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/OTF/SourceSerifPro-Regular.otf b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/OTF/SourceSerifPro-Regular.otf Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/OTF/SourceSerifPro-Semibold.otf b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/OTF/SourceSerifPro-Semibold.otf Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/README.md b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/README.md @@ -1,18 +0,0 @@ -# Source Serif Pro - -Source Serif Pro is a set of OpenType fonts to complement the [Source Sans Pro](https://github.com/adobe-fonts/source-sans-pro) family. -In addition to a functional OpenType font, this open source project provides all of the source files that were used to build this OpenType font by using the AFDKO makeotf tool. - -## Installation instructions - -* [Mac OS X](http://support.apple.com/kb/HT2509) -* [Windows](http://windows.microsoft.com/en-us/windows-vista/install-or-uninstall-fonts) -* [Linux/Unix-based systems](https://github.com/adobe-fonts/source-code-pro/issues/17#issuecomment-8967116) - -## Getting Involved - -Send suggestions for changes to the Source Serif OpenType font project maintainer, [Frank Grießhammer](mailto:opensourcefonts@adobe.com?subject=[GitHub] Source Serif Pro), for consideration. - -## Further information - -For information about the design and background of Source Serif, please refer to the [official font readme file](http://htmlpreview.github.io/?https://github.com/adobe-fonts/source-serif-pro/blob/master/SourceSerifProReadMe.html). diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/ReadMe.html b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/ReadMe.html @@ -1,72 +0,0 @@ -<!DOCTYPE html> -<html> -<head> - <title>Read Me File for Adobe® OpenType® Fonts</title> - <meta charset="utf-8" /> -</head> -<body bgcolor="white" link="#ce0000" alink="#ce0000" vlink="#9c6363"> - <h2><font color="#333333" -face="verdana,geneva,arial">Adobe® OpenType® Fonts</font></h2> - <p><font size="2" face="verdana,geneva,arial">Thank -you for licensing Adobe OpenType fonts. In order to ensure that you -have the most up-to-date product information, Adobe has posted <a -href="http://www.adobe.com/type/browser/OTReadMe.html">an OpenType -Read Me file</a> on the Adobe web site that contains information such -as minimum system requirements, technical support contact information -and software installation notes. We have also posted <a -href="http://www.adobe.com/type/browser/pdfs/OTGuide.pdf">an OpenType -User's Guide</a> in PDF format on the Adobe web site that can be -viewed online and downloaded to your computer. <P>If you have -licensed an Adobe OpenType Pro font, there may be additional PDF -documents, such as a specimen book, a glyph complement showing, and a -typeface-specific Read Me file, available on the typeface’s -product pages on the Adobe web site. These additional files may be -viewed online or downloaded to your computer.<P>To get you started -quickly, below are links to localized installation instructions for -your fonts. - -<h4>Installation Instructions</h4><hr> -<p lang=en><b>English</b><br> -Instructions for installing this font can be found online at <a -href="http://www.adobe.com/type/browser/fontinstall/instructions_main.html">http://www.adobe.com/type/browser/fontinstall/instructions_main.html</a>.</p> -<p lang=fr><b>French / Français</b><br> -Le mode d'installation de cette police de caractère se trouve en -ligne à <a -href="http://www.adobe.com/type/browser/fontinstall/instructions_main.html">http://www.adobe.com/type/browser/fontinstall/instructions_main.html</a>.</p> -<p lang=de><b>German / Deutsch</b><br> -Die Anweisungen zur Installation dieser Schriftart finden Sie online -unter <a -href="http://www.adobe.com/type/browser/fontinstall/instructions_main.html">http://www.adobe.com/type/browser/fontinstall/instructions_main.html</a>.</p> -<p lang=it><b>Italian / Italiano</b><br> -Le istruzioni per l'installazione di questo font sono disponibili -online all'indirizzo <a -href="http://www.adobe.com/type/browser/fontinstall/instructions_main.html">http://www.adobe.com/type/browser/fontinstall/instructions_main.html</a>.</p> -<p lang=es><b>Spanish / Español</b><br> -Las instrucciones para instalar esta fuente se pueden encontrar -online en <a -href="http://www.adobe.com/type/browser/fontinstall/instructions_main.html">http://www.adobe.com/type/browser/fontinstall/instructions_main.html</a>.</p> -<p lang=nl><b>Dutch / Hollands</b><br> -De instructies voor de installatie van dit lettertype vindt u op <a -href="http://www.adobe.com/type/browser/fontinstall/instructions_main.html">http://www.adobe.com/type/browser/fontinstall/instructions_main.html</a>.</p> -<p><b>Swedish / Svenska</b><br> -Anvisningar för hur det här teckensnittet installeras finns -online på <a -href="http://www.adobe.com/type/browser/fontinstall/instructions_main.html">http://www.adobe.com/type/browser/fontinstall/instructions_main.html</a>.</p> -<p><b>Norwegian / Norsk</b><br> -Instruksjoner for installering av skrifttypen finnes online på -<a -href="http://www.adobe.com/type/browser/fontinstall/instructions_main.html">http://www.adobe.com/type/browser/fontinstall/instructions_main.html</a>.</p> -<p><b>Finnish / Suomi</b><br> -Ohjeet tämän fontin asentamiseen löytyvät -osoitteesta <a -href="http://www.adobe.com/type/browser/fontinstall/instructions_main.html">http://www.adobe.com/type/browser/fontinstall/instructions_main.html</a>.</p> -<p><b>Danish / Dansk</b><br> -Du finder en vejledning i installation af denne skrifttype online -på adressen <a -href="http://www.adobe.com/type/browser/fontinstall/instructions_main.html">http://www.adobe.com/type/browser/fontinstall/instructions_main.html</a>.</p> -<p lang=ja><b>Japanese / 日本語</b><br> -このフォントをインストールする手順は、オンラインで <a -href="http://www.adobe.com/type/browser/fontinstall/instructions_main.html">http://www.adobe.com/type/browser/fontinstall/instructions_main.html</a> -を参照してください。</p> -</body> -</html> diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/SourceSerifProReadMe.html b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/SourceSerifProReadMe.html @@ -1,189 +0,0 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> -<!-- Read-me Template Version 1.003 Jan 145 2013 --> -<html> - <head> - <meta http-equiv="content-type" content="text/html" /> - <meta name="title" content="Read Me File for Source Serif Pro" /> - <meta name="description" content="Read Me file for Source Serif Pro ..." /> - <title>Source Serif Pro Read Me</title> - <style type="text/css" media="screen"> - /*********************** fonts ************************/ - body {font-family: sans-serif; font-weight: normal; font-size: 10pt; color: #000000; margin: 0px; background-color: white;} - h1 {display:inline; font-family: sans-serif; font-weight: normal; color: #999999;} - h2 {display:inline; font-size: 10pt; font-family: sans-serif; font-weight: bold; color: #666666;} - hFooter {font-family: sans-serif; font-weight: normal; font-size: 7pt; color: #000000; margin: 0px; background-color: white;} - /*********************** links ************************/ - a:link {color:#004477; text-decoration:none; margin: 0px 0px 0px 0px;} - a:visited {color:#6d7f8e; text-decoration:none; margin: 0px 0px 0px 0px;} - a:hover {color:#ff0000; text-decoration:none; margin: 0px 0px 0px 0px;} - /*********************** div tags ************************/ - #page {float:left; width:700px; margin:20px 20px 20px 20px;} - #subTitle {background-color:#e3e3e3; float:left; width:700px; border-bottom:solid #999999 1.0pt; border-bottom-alt:solid #999999 .5pt; padding:2px 0px 4px 0px;} - #title {background-color:#e3e3e3; float:left; width:700px; border-bottom:solid #999999 1.0pt; border-bottom-alt:solid #999999 .5pt; padding:2px 0px 4px 0px;} - #description {float:left; width:700px; padding:15px 0px 15px 0px;} .style6 {color: #666666} .style7 {color: #FF0000}</style> - </head> - <body> - <div id="page"> - <h1> - <span style="font-size:16pt">Source™ Serif Pro Read Me</span> - </h1> - <br /> - <div id="description"> - <p>This document contains late-breaking product information, updates, and troubleshooting tips. - <br /> - <br /> - <a href="#A1">Minimum system requirements and font installation instructions</a> - <br /> - <a href="#A2A">Font versions</a> - <br /> - <a href="#A2">Family information</a> - <br /> - <a href="#A3">Release Notes</a> - <br /> - <a href="#A8">Known issues</a> - <br /> - <a href="#A9">Customer care</a> - <br /> - <a href="#A10">Other resources</a> - <br /> - <a href="#A12"></a> - <br /></p> - </div> - <div id="title"> - <a name="A1" id="A1"></a> - <h2>Minimum system requirements and font installation instructions</h2> - </div> - <div id="description"> - <p>For information on minimum system requirements and font installation, see <span class="style7"> - <a title="http://www.adobe.com/go/learn_fontinstall_en" href="http://www.adobe.com/go/learn_fontinstall_en">http://www.adobe.com/go/learn_fontinstall_en</a>.</span></p> - </div> - <div id="title"> - <a name="A2A" id=A2A></a> - <h2>Font versions</h2> - </div> - <div id="description"> - <p>To check that you have the correct font file, compare the font version of your font file to the font version provided in the Release Notes section below.</p> - </div> - <div id="title"> - <h2> - <a name="A2" id="A2">Family information</a> - </h2> - </div> - <div id="description"> - <p> - <strong>History</strong> - </p>Source Serif Pro is a serif typeface in the transitional style, designed to complement Source Sans. Their close companionship is achieved by a careful match of letter proportions and typographic color. While designed to harmonize with its serif-less counterpart, Source Serif often takes its own direction, in part because the two are inspired by different historical precedents. Source Serif is loosely based on the work of Pierre Simon Fournier, and many idiosyncrasies typical to Fournier’s designs (like the bottom serif on the b or the middle serif on the w) are also found in Source Serif. Without being a pure historical revival, Source Serif takes cues from the Fournier model and reworks it for a modern age.<br><br>Source Sans and Source Serif also have different personalities because they spring from the hands of different designers. Source Serif was designed by Frank Grießhammer, Source Sans was designed by Paul Hunt. Robert Slimbach consulted on both designs, which helped maintain the overall family harmony. Either design feels confident on its own but also works in combination with the other — just like their designers do.<br><br>Source Serif continues Adobe’s line of high-quality open source typefaces. Designed for a digital environment, the letter shapes are simplified and highly readable. Its historical roots, combined with the guidance through an experienced designer give the typeface a strong character of its own that will shine when used for extended text on paper or on screen.<br><br>There is still more to come for Source Serif. Additional weights, Italic cuts, and Cyrillic and Greek language support are all planned. If you are interested in contributing to this open source project, please visit this project page for information on how to become involved. Source Serif Pro can be adapted and redistributed according to the terms of the Open Font License (OFL) agreement. - <p> - <strong>Menu Names And Style Linking</strong> - </p> -<p>In many Windows<sup>®</sup> applications, instead of every font appearing on -the menu, fonts are grouped into style-linked sets, and only the name of -the base style font for a set is shown in the menu. The italic and the -bold weight fonts of the set (if any) are not shown in the font menu, but can still be -accessed by selecting the base style font, and then using the italic -and bold style buttons. In this family, such programs will show only the -following base style font names in the menu:</p> -<p>Source Serif Pro<br> -Source Serif Pro Black<br> -Source Serif Pro ExtraLight<br> -Source Serif Pro Light<br> -Source Serif Pro SemiBold<br></p> -<p>The other fonts in this family must be selected by choosing a menu name -and then a style option following the guide below.</p> -<table border="0"> -<tr> <td>Menu Name</td> <td> </td> <td>plus Style Option... </td> <td> </td> <td>selects this font</td> </tr> -<tr> <td>Source Serif Pro</td> <td> </td> <td>[none]</td> <td> </td> <td>Source Serif Pro Regular</td> </tr> -<tr> <td>Source Serif Pro</td> <td> </td> <td>Bold</td> <td> </td> <td>Source Serif Pro Bold</td> </tr> -<tr> <td> </td> <td> </td> <td> </td> <td> </td> <td> </td> </tr> -<tr> <td>Source Serif Pro Black</td> <td> </td> <td>[none]</td> <td> </td> <td>Source Serif Pro Black</td> </tr> -<tr> <td> </td> <td> </td> <td> </td> <td> </td> <td> </td> </tr> -<tr> <td>Source Serif Pro ExtraLight</td> <td> </td> <td>[none]</td> <td> </td> <td>Source Serif Pro ExtraLight</td> </tr> -<tr> <td> </td> <td> </td> <td> </td> <td> </td> <td> </td> </tr> -<tr> <td>Source Serif Pro Light</td> <td> </td> <td>[none]</td> <td> </td> <td>Source Serif Pro Light</td> </tr> -<tr> <td> </td> <td> </td> <td> </td> <td> </td> <td> </td> </tr> -<tr> <td>Source Serif Pro SemiBold</td> <td> </td> <td>[none]</td> <td> </td> <td>Source Serif Pro Semibold</td> </tr> -<tr> <td> </td> <td> </td> <td> </td> <td> </td> <td> </td> </tr> -</table> -<p>On the Mac OS operating system, although each font appears as a separate entry on the -font menu, users may also select fonts by means of style links. -Selecting a base style font and then using the style links (as described -above for Windows applications) enhances cross-platform document compatibility with -many applications, such as Microsoft Word and Adobe<sup>®</sup> PageMaker<sup>®</sup> software, -although it is unnecessary with more sophisticated Adobe applications -such as recent versions of Illustrator<sup>®</sup>, Photoshop<sup>®</sup> or -InDesign<sup>®</sup> software.</p> -<p>One should not, however, select a base font which has no style-linked -variant, and then use the bold or italic styling button. Doing so will -either have no effect, or result in programmatic bolding or slanting of -the base font, which will usually produce inferior screen and print -results.</p> -</div> - <div id="title"> - <h2> - <a name="A3" id="A3">Release Notes</a> - </h2> - </div> - <div id="description"><p>For all fonts of family Source Serif Pro: version 1.017 created on Tue Sep 16 17:12:36 2014.</p> -<p>version 1.017 created 2014/09/16</p> -<ul> -<li> Added three more weights: Black, Light, ExtraLight.</li> -<li> Added missing L/lcommaaccent (U+013B/C) to all fonts.</li> -</ul> -<p>version 1.014 created 2014/04/27</p> -<ul> -<li> First release.</li> -</ul> -</div> - <div id="title"> - <h2> - <a name="A8" id="A8">Known issues</a> - </h2> - </div> - <div id="description"><ul> <li>Some glyphs in the font cannot be accessed unless you are using an OpenType<sup>®</sup> compatible application. - </li> -</ul></div> - <div id="title"> - <h2> - <a name="A9" id="A9">Customer care</a> - </h2> - </div> - <div id="description"> - <p> - <strong>Customer Service</strong> - <br />Adobe Customer Service provides assistance with product information, sales, registration, and other non-technical issues. - To find out how to contact Adobe Customer Service, please visit <a href="http://www.adobe.com">Adobe.com</a> for your region or country and click on Contact Adobe.</p> - <p> - <strong>Support Plan Options and Technical Resources</strong> - <br />If you require technical assistance for your product, including information on free and paid support options and troubleshooting resources, more information is available at - <a title="http://www.adobe.com/go/support/" href="http://www.adobe.com/go/support/"> - <span title="http://www.adobe.com/go/support/">http://www.adobe.com/go/support/.</span> - </a> Outside of North America, go to - <a title="http://www.adobe.com/go/intlsupport/" href="http://www.adobe.com/go/intlsupport/"> - <span title="http://www.adobe.com/go/intlsupport/">http://www.adobe.com/go/intlsupport/.</span> - </a>Font specific resources include the <a href="http://helpx.adobe.com/font-folio-type.html">Font Folio and Type Product Help page</a> and the <a href="http://forums.adobe.com/community/typography_fonts">Adobe Type user-to-user forums</a>.</p> - </div> - <div id="title"> - <h2> - <a name="A10" id="A10">Other resources</a> - </h2> - </div> - <div id="description"> - <p> - <a href="http://www.adobe.com/type">Adobe Type Showroom</a> - <br /> - <a href="http://www.adobe.com/type/family_readmes.html">Index page for all family Read Me files</a> - <br /> - </p> - <p align="left"> - <br /> - Adobe, the Adobe Logo, Source, Illustrator, InDesign, PageMaker and Photoshop are either registered trademarks or trademarks of Adobe Systems Incorporated in the United States and/or other countries. Windows and OpenType are either registered trademarks or trademarks of Microsoft Corporation in the United States and/or other countries. Mac, Mac OS and TrueType are trademarks of Apple Inc., registered in the U.S. and other countries. All other trademarks are the property of their respective owners. <br /> - <br /> - <hFooter> - © 2014 Adobe Systems Incorporated. All rights reserved.<br /><br />created 2014 Sep 24 - <hFooter> - </p> - </div> - </div> - </body> -</html> diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/TTF/SourceSerifPro-Black.ttf b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/TTF/SourceSerifPro-Black.ttf Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/TTF/SourceSerifPro-Bold.ttf b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/TTF/SourceSerifPro-Bold.ttf Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/TTF/SourceSerifPro-ExtraLight.ttf b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/TTF/SourceSerifPro-ExtraLight.ttf Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/TTF/SourceSerifPro-Light.ttf b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/TTF/SourceSerifPro-Light.ttf Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/TTF/SourceSerifPro-Regular.ttf b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/TTF/SourceSerifPro-Regular.ttf Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/TTF/SourceSerifPro-Semibold.ttf b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/TTF/SourceSerifPro-Semibold.ttf Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/WOFF/OTF/SourceSerifPro-Black.otf.woff b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/WOFF/OTF/SourceSerifPro-Black.otf.woff Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/WOFF/OTF/SourceSerifPro-Bold.otf.woff b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/WOFF/OTF/SourceSerifPro-Bold.otf.woff Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/WOFF/OTF/SourceSerifPro-ExtraLight.otf.woff b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/WOFF/OTF/SourceSerifPro-ExtraLight.otf.woff Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/WOFF/OTF/SourceSerifPro-Light.otf.woff b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/WOFF/OTF/SourceSerifPro-Light.otf.woff Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/WOFF/OTF/SourceSerifPro-Regular.otf.woff b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/WOFF/OTF/SourceSerifPro-Regular.otf.woff Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/WOFF/OTF/SourceSerifPro-Semibold.otf.woff b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/WOFF/OTF/SourceSerifPro-Semibold.otf.woff Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/WOFF/TTF/SourceSerifPro-Black.ttf.woff b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/WOFF/TTF/SourceSerifPro-Black.ttf.woff Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/WOFF/TTF/SourceSerifPro-Bold.ttf.woff b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/WOFF/TTF/SourceSerifPro-Bold.ttf.woff Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/WOFF/TTF/SourceSerifPro-ExtraLight.ttf.woff b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/WOFF/TTF/SourceSerifPro-ExtraLight.ttf.woff Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/WOFF/TTF/SourceSerifPro-Light.ttf.woff b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/WOFF/TTF/SourceSerifPro-Light.ttf.woff Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/WOFF/TTF/SourceSerifPro-Regular.ttf.woff b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/WOFF/TTF/SourceSerifPro-Regular.ttf.woff Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/WOFF/TTF/SourceSerifPro-Semibold.ttf.woff b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/WOFF/TTF/SourceSerifPro-Semibold.ttf.woff Binary files differ. diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/bower.json b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/bower.json @@ -1,15 +0,0 @@ -{ - "name": "source-serif-pro", - "version": "1.014", - "main": "source-serif-pro.css", - "homepage": "https://github.com/adobe-fonts/source-serif-pro", - "repository": { - "type": "git", - "url": "https://github.com/adobe-fonts/source-serif-pro.git" - }, - "authors": [ - { "name": "Frank Grießhammer" } - ], - "description": "Source Serif Pro font family by Adobe", - "license": "SIL OFL 1.1" -} diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/source-serif-pro.css b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/fonts/source-serif-pro/source-serif-pro.css @@ -1,65 +0,0 @@ -@font-face{ - font-family: 'Source Serif Pro'; - font-weight: 200; - font-style: normal; - font-stretch: normal; - src: url('EOT/SourceSerifPro-ExtraLight.eot') format('embedded-opentype'), - url('WOFF/OTF/SourceSerifPro-ExtraLight.otf.woff') format('woff'), - url('OTF/SourceSerifPro-ExtraLight.otf') format('opentype'), - url('TTF/SourceSerifPro-ExtraLight.ttf') format('truetype'); -} - -@font-face{ - font-family: 'Source Serif Pro'; - font-weight: 300; - font-style: normal; - font-stretch: normal; - src: url('EOT/SourceSerifPro-Light.eot') format('embedded-opentype'), - url('WOFF/OTF/SourceSerifPro-Light.otf.woff') format('woff'), - url('OTF/SourceSerifPro-Light.otf') format('opentype'), - url('TTF/SourceSerifPro-Light.ttf') format('truetype'); -} - -@font-face{ - font-family: 'Source Serif Pro'; - font-weight: 400; - font-style: normal; - font-stretch: normal; - src: url('EOT/SourceSerifPro-Regular.eot') format('embedded-opentype'), - url('WOFF/OTF/SourceSerifPro-Regular.otf.woff') format('woff'), - url('OTF/SourceSerifPro-Regular.otf') format('opentype'), - url('TTF/SourceSerifPro-Regular.ttf') format('truetype'); -} - -@font-face{ - font-family: 'Source Serif Pro'; - font-weight: 600; - font-style: normal; - font-stretch: normal; - src: url('EOT/SourceSerifPro-Semibold.eot') format('embedded-opentype'), - url('WOFF/OTF/SourceSerifPro-Semibold.otf.woff') format('woff'), - url('OTF/SourceSerifPro-Semibold.otf') format('opentype'), - url('TTF/SourceSerifPro-Semibold.ttf') format('truetype'); -} - -@font-face{ - font-family: 'Source Serif Pro'; - font-weight: 700; - font-style: normal; - font-stretch: normal; - src: url('EOT/SourceSerifPro-Bold.eot') format('embedded-opentype'), - url('WOFF/OTF/SourceSerifPro-Bold.otf.woff') format('woff'), - url('OTF/SourceSerifPro-Bold.otf') format('opentype'), - url('TTF/SourceSerifPro-Bold.ttf') format('truetype'); -} - -@font-face{ - font-family: 'Source Serif Pro'; - font-weight: 900; - font-style: normal; - font-stretch: normal; - src: url('EOT/SourceSerifPro-Black.eot') format('embedded-opentype'), - url('WOFF/OTF/SourceSerifPro-Black.otf.woff') format('woff'), - url('OTF/SourceSerifPro-Black.otf') format('opentype'), - url('TTF/SourceSerifPro-Black.ttf') format('truetype'); -} diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/guzzle.css_t b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/guzzle.css_t @@ -1,1037 +0,0 @@ -/* Sphinx themes --------------------------------------------------- */ - -body { - background-color: #edf0f2; - margin: 0; - padding: 0; - font-family: "Open Sans", Helvetica, Arial, sans-serif; - font-size: 16px; - color: #333; - line-height: 1.5; -} - -#left-column { - float: left; - position: fixed; - height: 100%; - border-right: 1px solid #e0e0e0; - width: 300px; - overflow: auto; - background: #fafafa; -} - -#right-column { - padding: 20px 0; - margin-left: 300px; - background-color: #fff; -} - -a.headerlink { - visibility: hidden; - color: #ddd; - padding: 0 4px; - text-decoration: none; -} - -h1:hover > a.headerlink, -h2:hover > a.headerlink, -h3:hover > a.headerlink, -h4:hover > a.headerlink, -h5:hover > a.headerlink, -h6:hover > a.headerlink, -dt:hover > a.headerlink, -.code-block-caption:hover > a.headerlink { - visibility: visible; -} - -h1 > a, h2 > a, h3 > a, h4 > a, h5 > a, h6 > a { - color: #5C7C98; -} - -h1, h2, h3, h4, h5, h6 { - color: black; - font-weight: normal; - padding: 0; - font-family: "Source Serif Pro", "serif"; -} - -h1, h2, h3 { - margin-top: 30px; - margin-bottom: 20px; -} - -h1 { - font-size: 38px; - padding: 10px 10px 10px 45px; - margin: 20px 0 35px -45px; - background-color: aliceblue; - width: calc(100% + 90px); - border-bottom: 1px solid #D8E4EF; -} - -h2 { - font-size: 34px; - padding: .2em 0; - border-bottom: 1px solid #ddd; -} - -h3 { - margin-top: 35px; - font-size: 28px; -} - -h4 { - margin-top: 30px; - font-size: 24px; -} - -h5 { - margin-top: 25px; - font-size: 20px; -} - -div.clearer { - clear: both; -} - -.container-wrapper { - padding: 0; - position: relative; -} - -div.related { - display: none; -} - -p { - padding: 0; - font-family: inherit; - font-size: inherit; - color: #333; -} - -code, pre, tt { - font-size: 15px; - font-family: Consolas, monospace; -} - -code, tt { - color: #8D1A38; -} - -tt { - padding: 0 2px; -} - -code, pre { - line-height: 23px; - margin: 20px 0; - word-wrap: normal; - background-color: #fff; -} - -pre { - color: #333; - background-color: #fff; - overflow: auto; - border-width: 0 0 0 2px; - border-color: #eee; - border-style: solid; - padding: 14px 0 14px 20px; - padding-right: 0; - margin: 20px 0; -} - -div.highlight { - background-color: white; -} - -a.internal em { - font-style: normal; -} - -dl dd { - margin: 3px 0 10px 30px; -} - -dl.method { - border-bottom: 1px solid #ccc; -} - -.breadcrumb { - font-size: 15px; - margin-bottom: 12px; - background: #fff; -} - -blockquote { - border-width: .1em 0 .1em 0; - border-color: #e5eef2; - border-style: solid; - background-color: #f3f8f9; - color: #000; - margin: 20px 0; - padding: 15px 20px; - font-size: 16px; -} - -/* Sphinx sidebar --------------------------------------------------- */ - -div.sphinxsidebar { - word-wrap: break-word; -} - -div.sphinxsidebar .panel-default > .panel-heading { - background-image: none; -} - -.sidebar-wrapper { - padding: 0 22px; -} - -div.sphinxsidebar h3, -div.sphinxsidebar h4 { - color: #444; - font-size: 20px; - font-weight: normal; - margin: 0; - padding: 0; -} - -div.sphinxsidebar h4 { - font-size: 16px; -} - -div.sphinxsidebar p { - color: #555; - margin: 10px 0; -} - -.sidebar-toc { - font-size: 15px; -} - -div.sphinxsidebar .sidebar-toc ul { - margin: 0 0 4px 0; - list-style-type: none; - color: #000; -} - -div.sphinxsidebar .sidebar-toc a { - font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; - color: #444; - text-decoration: none; -} - -.sidebar-toc > ul { - padding: 0 !important; - list-style-type: none; - margin: 0; -} - -.sidebar-toc ul li a { - display: block; -} - -.sidebar-toc ul li a:hover { - background-color: #428bca; - color: #fff; -} - -.sidebar-toc ul li.current > a, -.sidebar-toc ul li.current > a:hover { - background-color: #e6e6e6; - color: #444; -} - -.sidebar-toc ul li.toctree-l1 a { - padding: 5px 25px; -} - -.sidebar-toc ul li.toctree-l2 a { - padding: 5px 50px; -} - -.sidebar-toc ul li.toctree-l3 a { - padding: 5px 75px; -} - -div.sphinxsidebar ul.want-points { - padding-left: 20px; - margin: 0; -} - -div.sphinxsidebar .sidebar-toc ul ul { - margin: 0; - padding: 0; -} - -.sidebar-localtoc ul { - padding-left: 24px; -} - -div.sphinxsidebar input { - border: 1px solid #ccc; - font-family: Helvetica, arial, freesans, clean, sans-serif; - font-size: 1em; -} - -.margin-top-1em { - margin-top: 1em; -} - -.sidebar-block { - padding: 0; - margin: 14px 0 30px 0; -} - -.sidebar-block h2 { - border-bottom: none; - margin: 0 0 17px 0; - font-size: 14px; - font-family: "Open Sans", Helvetica, Arial, sans-serif; - padding: 0 0 6px 0; - font-weight: bold; - text-transform: uppercase; - color: #606060; -} - -.sidebar-block .bd { - font-size: 16px; -} - -.sphinxsidebar > .sidebar-block:not(:last-child):after { - content: ''; - display:block; - border-top: 1px solid #ccc; - margin: 24px 22px 0 22px; -} - -.text-logo { - font-size: 18px; - text-align: center; - display: block; - padding: 8px; - color: #fff; - font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; - margin: 0 0 20px 0; - font-weight: bold; - background-color: #337ab7; - border-bottom: 1px solid #fff; -} - -.text-logo:hover { - color: #fff; -} - -/* Left-nav search box --------------------------------------------------- */ - -#main-search form .input-group { - width: 100%; - margin: 0 0 12px 0; - padding: 0; - border: none; -} - -#main-search form .input-group input { - padding: 4px; - width: 100%; - border-radius: 5px; - margin: 0; - font-size: 15px; -} - -.search-page-form { - width: 350px; -} - -/* Two-pane table list --------------------------------------------------- */ - -.table-bordered>thead>tr>th, -.table-bordered>tbody>tr>th, -.table-bordered>tfoot>tr>th, -.table-bordered>thead>tr>td, -.table-bordered>tbody>tr>td, -.table-bordered>tfoot>tr>td, -table.two-column.table-bordered caption+thead tr:first-child th:first-child, -table.two-column.table-bordered caption+tbody tr:first-child td:first-child, -table.two-column.table-bordered colgroup+thead tr:first-child th:first-child, -table.two-column.table-bordered colgroup+tbody tr:first-child td:first-child, -table.two-column tbody td - border: 0 0 1px 0 solid #eee; - border-left: none; - padding: 8px 4px; - font-size: 16px; -} - -table.two-column { - width: 100%; - border: 0px none !important; - box-shadow: none; -} - -/* Disqus comments styles --------------------------------------------------- */ - -.comment-container { - margin: 24px auto; -} - -/* Next and previous links --------------------------------------------------- */ - -.footer-relations { - display: relative; - border-top: 1px solid #ccc; - padding: 12px 45px; - margin-top: 30px; - font-size: 24px; -} - -.rel-spacer { - height: 40px; -} - -/* Footer styling --------------------------------------------------- */ - -div.footer { - padding: 25px; - font-size: 14px; - color: #888; - text-align: right; - max-width: 1200px; - width: 100%; -} - -div.footer a { - color: #888; -} - -/* -- relbar ---------------------------------------------------------------- */ - -div.related { - width: 100%; - font-size: 90%; -} - -div.related h3 { - display: none; -} - -div.related ul { - margin: 0; - padding: 0 0 0 10px; - list-style: none; -} - -div.related li { - display: inline; -} - -div.related li.right { - float: right; - margin-right: 5px; -} - -/* -- search page ----------------------------------------------------------- */ - -ul.search { - margin: 10px 0 0 20px; - padding: 0; -} - -ul.search li { - padding: 5px 0 5px 20px; - background: url(file.png) no-repeat 0 7px; -} - -ul.search li a { - font-weight: bold; -} - -ul.search li div.context { - color: #888; - margin: 2px 0 0 30px; - text-align: left; -} - -ul.keywordmatches li.goodmatch a { - font-weight: bold; -} - -/* -- general index --------------------------------------------------------- */ - -table { - margin-bottom: 20px; -} - -table.indextable { - width: 100%; -} - -table.indextable td { - text-align: left; - vertical-align: top; -} - -table.indextable dl, table.indextable dd { - margin-top: 0; - margin-bottom: 0; -} - -table.indextable tr.pcap { - height: 10px; -} - -table.indextable tr.cap { - margin-top: 10px; - background-color: #f2f2f2; -} - -img.toggler { - margin-right: 3px; - margin-top: 3px; - cursor: pointer; -} - -div.modindex-jumpbox { - border-top: 1px solid #ddd; - border-bottom: 1px solid #ddd; - margin: 1em 0 1em 0; - padding: 0.4em; -} - -div.genindex-jumpbox { - border-top: 1px solid #ddd; - border-bottom: 1px solid #ddd; - margin: 1em 0 1em 0; - padding: 0.4em; -} - -/* -- general body styles --------------------------------------------------- */ - -.body { - padding: 0 45px; -} - -div.body p.caption { - text-align: inherit; -} - -table.field-list { - border: 1px solid #ddd; - border-collapse: collapse; - border-spacing: 0; - width: 100%; -} - -table.field-list td, -table.field-list th { - border: 1px solid #ddd; - padding: 8px; - vertical-align: top; - line-height: 1.4; -} - -.field-list ul { - padding-left: 1em; -} - -.first { - margin-top: 0 !important; -} - -p.rubric { - margin-top: 30px; - font-weight: bold; -} - -img.align-left, .figure.align-left, object.align-left { - clear: left; - float: left; - margin-right: 1em; -} - -img.align-right, .figure.align-right, object.align-right { - clear: right; - float: right; - margin-left: 1em; -} - -img.align-center, .figure.align-center, object.align-center { - display: block; - margin-left: auto; - margin-right: auto; -} - -.align-left { - text-align: left; -} - -.align-center { - text-align: center; -} - -.align-right { - text-align: right; -} - -/* -- topics ---------------------------------------------------------------- */ - -div.topic { - border: 1px solid #e8e8e8; - padding: 7px 7px 0 7px; - margin: 10px 0 10px 0; - background-color: #f8f8f8; -} - -p.topic-title { - font-size: 1.1em; - font-weight: bold; - margin-top: 10px; -} - -/* -- contents-------------------------------------------------------------- */ - -div.topic.contents { - display: inline-block; - border-radius: 3px; - padding: 24px 36px 18px 36px; -} - -div.topic.contents > ul { - padding-left: 20px; -} - -/* -- admonitions ----------------------------------------------------------- */ - -.admonition { - margin: 20px 0; - padding: 20px; - background-color: #fff; - border: 1px solid #eee; - border-left-width: 6px; - border-radius: 3px; -} - -.admonition dt { - font-weight: bold; -} - -.admonition dl { - margin-bottom: 0; -} - -.admonition-title { - margin: 0px 0 5px; - padding: 0; - font-weight: bold; - font-size: 18px; - line-height: 1.1; - font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; -} - -.admonition.danger, -.admonition.error { - border-left-color: #d9534f; -} - -.admonition.danger .admonition-title, -.admonition.error .admonition-title { - color: #d9534f; -} - -.admonition.important, -.admonition.warning, -.admonition.attention, -.admonition.caution { - border-left-color: #f0ad4e; -} - -.admonition.important .admonition-title, -.admonition.warning .admonition-title, -.admonition.attention .admonition-title, -.admonition.caution .admonition-title { - color: #9B581F; -} - -.admonition.note, -.admonition.hint { - border-left-color: #31708f; -} - -.admonition.note .admonition-title, -.admonition.hint .admonition-title { - color: #31708f; -} - -.admonition.tip { - border-left-color: #3c763d; -} - -.admonition.tip .admonition-title { - color: #3c763d; -} - -div.body p.centered { - text-align: center; - margin-top: 25px; -} - -div.seealso { - background-color: #ffc; - border: 1px solid #ff6; -} - -div.admonition tt.xref, div.admonition a tt { - border-bottom: 1px solid #fafafa; -} - -div.admonition p.last { - margin-bottom: 0; -} - -/* -- other body styles ----------------------------------------------------- */ - -ol.arabic { - list-style: decimal; -} - -ol.loweralpha { - list-style: lower-alpha; -} - -ol.upperalpha { - list-style: upper-alpha; -} - -ol.lowerroman { - list-style: lower-roman; -} - -ol.upperroman { - list-style: upper-roman; -} - -.highlighted { - background-color: #fbe54e; -} - -dl.glossary dt { - font-weight: bold; - font-size: 1.1em; -} - -.field-list ul { - margin: 0; - padding-left: 1em; -} - -.refcount { - color: #060; -} - -.optional { - font-size: 1.3em; -} - -.versionmodified { - font-style: italic; -} - -.system-message { - background-color: #fda; - padding: 5px; - border: 3px solid red; -} - -.footnote:target { - background-color: #ffa; -} - -.line-block { - display: block; - margin-top: 1em; - margin-bottom: 1em; -} - -.line-block .line-block { - margin-top: 0; - margin-bottom: 0; - margin-left: 1.5em; -} - -.guilabel, .menuselection { - font-family: sans-serif; -} - -.accelerator { - text-decoration: underline; -} - -.classifier { - font-style: oblique; -} - -abbr, acronym { - border-bottom: dotted 1px; - cursor: help; -} - -dt:target, .highlight { - background: #FAF3E8; -} - -/* -- code displays --------------------------------------------------------- */ - -.code-block-caption { - margin-bottom: -20px; -} - -.code-block-caption .caption-text { - display: inline-block; - padding: 6px 20px; - font-weight: bold; - font-size: 18px; - line-height: 1.1; - font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; - color: #fff; - background-color: #337ab7; -} - -td.linenos pre { - padding: 5px 0px; - border: 0; - background-color: transparent; - color: #aaa; -} - -table.highlighttable { - margin-left: 0.5em; -} - -table.highlighttable td { - padding: 0 0.5em 0 0.5em; -} - -tt.descname { - background-color: transparent; - font-weight: bold; - padding-right: 0.08em; -} - -tt.descclassname { - background-color: transparent; -} - -tt.descname, tt.descclassname { - font-size: 0.95em; -} - -tt.xref, a tt { - background-color: transparent; - font-weight: bold; -} - -h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt { - background-color: transparent; -} - -.viewcode-link { - float: right; -} - -.viewcode-back { - float: right; - font-family: sans-serif; -} - -div.viewcode-block:target { - margin: -1px -10px; - padding: 0 10px; -} - -/* -- math display ---------------------------------------------------------- */ - -img.math { - vertical-align: middle; -} - -div.body div.math p { - text-align: center; -} - -span.eqno { - float: right; -} - -/* -- Theme specific classes - */ - -.overflow-height-500px { - overflow: auto; - height: 500px; -} - -.overflow-height-250px { - overflow: auto; - height: 250px; -} - -/* Toggle mobile view --------------------------------------------------- */ - -#mobile-toggle { - height: 40px; - width: 100%; - display: none; - padding: 12px; - border-bottom: 1px solid #ccc; - position: fixed; - top: 0; - left: 0; - background-color: #fff; - z-index: 1; -} - -/* Small screen styles --------------------------------------------------- */ - -@media screen and (max-width: 768px) { - - body { - padding: 0px; - margin: 0px; - background-color: #fff; - } - - h1 { - margin-left: 0; - width: 100%; - padding: 10px; - font-size: 40px; - } - - #left-column { - position: relative; - top: 0; - left: 0; - display: none; - width: 100%; - float: none; - margin: 40px 0 0 0; - } - - .footer-relations { - padding: 12px 0; - } - - #right-column { - margin-left: 0; - margin-top: 0; - padding: 50px 20px 8px 20px; - width: 100%; - float: none; - } - - .document { - position: relative; - padding: 0; - width: 100% - } - - .body { - padding: 0px; - } - - #mobile-toggle { - display: block; - } - - p { - padding: 0; - } -} - -/* Account for when the left column is closed then page is expanded. --------------------------------------------------- */ - -@media screen and (min-width: 769px) { - #left-column { - display: block !important; - } - div.footer { - margin-left: 300px; - } -} - -/* Syntax highlighting --------------------------------------------------- */ - -.hll { background-color: #ffffcc } -.c { color: #999988; font-style: italic } /* Comment */ -.err { color: #a61717; background-color: #e3d2d2 } /* Error */ -.k { color: #000000; font-weight: bold } /* Keyword */ -.o { color: #000000; font-weight: bold } /* Operator */ -.cm { color: #999988; font-style: italic } /* Comment.Multiline */ -.cp { color: #999999; font-weight: bold; font-style: italic } /* Comment.Preproc */ -.c1 { color: #999988; font-style: italic } /* Comment.Single */ -.cs { color: #999999; font-weight: bold; font-style: italic } /* Comment.Special */ -.gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ -.ge { color: #000000; font-style: italic } /* Generic.Emph */ -.gr { color: #aa0000 } /* Generic.Error */ -.gh { color: #999999 } /* Generic.Heading */ -.gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ -.go { color: #888888 } /* Generic.Output */ -.gp { color: #555555 } /* Generic.Prompt */ -.gs { font-weight: bold } /* Generic.Strong */ -.gu { color: #aaaaaa } /* Generic.Subheading */ -.gt { color: #aa0000 } /* Generic.Traceback */ -.kc { color: #000000; font-weight: bold } /* Keyword.Constant */ -.kd { color: #000000; font-weight: bold } /* Keyword.Declaration */ -.kn { color: #000000; font-weight: bold } /* Keyword.Namespace */ -.kp { color: #000000; font-weight: bold } /* Keyword.Pseudo */ -.kr { color: #000000; font-weight: bold } /* Keyword.Reserved */ -.kt { color: #445588; font-weight: bold } /* Keyword.Type */ -.m { color: #009999 } /* Literal.Number */ -.s { color: #d01040 } /* Literal.String */ -.na { color: #008080 } /* Name.Attribute */ -.nb { color: #0086B3 } /* Name.Builtin */ -.nc { color: #445588; font-weight: bold } /* Name.Class */ -.no { color: #008080 } /* Name.Constant */ -.nd { color: #3c5d5d; font-weight: bold } /* Name.Decorator */ -.ni { color: #800080 } /* Name.Entity */ -.ne { color: #990000; font-weight: bold } /* Name.Exception */ -.nf { color: #990000; font-weight: bold } /* Name.Function */ -.nl { color: #990000; font-weight: bold } /* Name.Label */ -.nn { color: #555555 } /* Name.Namespace */ -.nt { color: #000080 } /* Name.Tag */ -.nv { color: #008080 } /* Name.Variable */ -.ow { color: #000000; font-weight: bold } /* Operator.Word */ -.w { color: #bbbbbb } /* Text.Whitespace */ -.mf { color: #009999 } /* Literal.Number.Float */ -.mh { color: #009999 } /* Literal.Number.Hex */ -.mi { color: #009999 } /* Literal.Number.Integer */ -.mo { color: #009999 } /* Literal.Number.Oct */ -.mn { color: #009999 } /* Literal.Number.Number */ -.mrow { color: #009999 } /* Literal.Number.Row */ -.sb { color: #d01040 } /* Literal.String.Backtick */ -.sc { color: #d01040 } /* Literal.String.Char */ -.sd { color: #d01040 } /* Literal.String.Doc */ -.s2 { color: #d01040 } /* Literal.String.Double */ -.se { color: #d01040 } /* Literal.String.Escape */ -.sh { color: #d01040 } /* Literal.String.Heredoc */ -.si { color: #d01040 } /* Literal.String.Interpol */ -.sx { color: #d01040 } /* Literal.String.Other */ -.sr { color: #009926 } /* Literal.String.Regex */ -.s1 { color: #d01040 } /* Literal.String.Single */ -.ss { color: #990073 } /* Literal.String.Symbol */ -.bp { color: #999999 } /* Name.Builtin.Pseudo */ -.vc { color: #008080 } /* Name.Variable.Class */ -.vg { color: #008080 } /* Name.Variable.Global */ -.vi { color: #008080 } /* Name.Variable.Instance */ -.il { color: #009999 } /* Literal.Number.Integer.Long */ diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/jquery.js b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/jquery.js @@ -1,5 +0,0 @@ -/*! jQuery v1.9.1 | (c) 2005, 2012 jQuery Foundation, Inc. | jquery.org/license - //@ sourceMappingURL=jquery.min.map - */(function(e,t){var n,r,i=typeof t,o=e.document,a=e.location,s=e.jQuery,u=e.$,l={},c=[],p="1.9.1",f=c.concat,d=c.push,h=c.slice,g=c.indexOf,m=l.toString,y=l.hasOwnProperty,v=p.trim,b=function(e,t){return new b.fn.init(e,t,r)},x=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,w=/\S+/g,T=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,N=/^(?:(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,k=/^[\],:{}\s]*$/,E=/(?:^|:|,)(?:\s*\[)+/g,S=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,A=/"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,j=/^-ms-/,D=/-([\da-z])/gi,L=function(e,t){return t.toUpperCase()},H=function(e){(o.addEventListener||"load"===e.type||"complete"===o.readyState)&&(q(),b.ready())},q=function(){o.addEventListener?(o.removeEventListener("DOMContentLoaded",H,!1),e.removeEventListener("load",H,!1)):(o.detachEvent("onreadystatechange",H),e.detachEvent("onload",H))};b.fn=b.prototype={jquery:p,constructor:b,init:function(e,n,r){var i,a;if(!e)return this;if("string"==typeof e){if(i="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:N.exec(e),!i||!i[1]&&n)return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e);if(i[1]){if(n=n instanceof b?n[0]:n,b.merge(this,b.parseHTML(i[1],n&&n.nodeType?n.ownerDocument||n:o,!0)),C.test(i[1])&&b.isPlainObject(n))for(i in n)b.isFunction(this[i])?this[i](n[i]):this.attr(i,n[i]);return this}if(a=o.getElementById(i[2]),a&&a.parentNode){if(a.id!==i[2])return r.find(e);this.length=1,this[0]=a}return this.context=o,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):b.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),b.makeArray(e,this))},selector:"",length:0,size:function(){return this.length},toArray:function(){return h.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=b.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return b.each(this,e,t)},ready:function(e){return b.ready.promise().done(e),this},slice:function(){return this.pushStack(h.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(b.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:d,sort:[].sort,splice:[].splice},b.fn.init.prototype=b.fn,b.extend=b.fn.extend=function(){var e,n,r,i,o,a,s=arguments[0]||{},u=1,l=arguments.length,c=!1;for("boolean"==typeof s&&(c=s,s=arguments[1]||{},u=2),"object"==typeof s||b.isFunction(s)||(s={}),l===u&&(s=this,--u);l>u;u++)if(null!=(o=arguments[u]))for(i in o)e=s[i],r=o[i],s!==r&&(c&&r&&(b.isPlainObject(r)||(n=b.isArray(r)))?(n?(n=!1,a=e&&b.isArray(e)?e:[]):a=e&&b.isPlainObject(e)?e:{},s[i]=b.extend(c,a,r)):r!==t&&(s[i]=r));return s},b.extend({noConflict:function(t){return e.$===b&&(e.$=u),t&&e.jQuery===b&&(e.jQuery=s),b},isReady:!1,readyWait:1,holdReady:function(e){e?b.readyWait++:b.ready(!0)},ready:function(e){if(e===!0?!--b.readyWait:!b.isReady){if(!o.body)return setTimeout(b.ready);b.isReady=!0,e!==!0&&--b.readyWait>0||(n.resolveWith(o,[b]),b.fn.trigger&&b(o).trigger("ready").off("ready"))}},isFunction:function(e){return"function"===b.type(e)},isArray:Array.isArray||function(e){return"array"===b.type(e)},isWindow:function(e){return null!=e&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?l[m.call(e)]||"object":typeof e},isPlainObject:function(e){if(!e||"object"!==b.type(e)||e.nodeType||b.isWindow(e))return!1;try{if(e.constructor&&!y.call(e,"constructor")&&!y.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(n){return!1}var r;for(r in e);return r===t||y.call(e,r)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||o;var r=C.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=b.buildFragment([e],t,i),i&&b(i).remove(),b.merge([],r.childNodes))},parseJSON:function(n){return e.JSON&&e.JSON.parse?e.JSON.parse(n):null===n?n:"string"==typeof n&&(n=b.trim(n),n&&k.test(n.replace(S,"@").replace(A,"]").replace(E,"")))?Function("return "+n)():(b.error("Invalid JSON: "+n),t)},parseXML:function(n){var r,i;if(!n||"string"!=typeof n)return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,"text/xml")):(r=new ActiveXObject("Microsoft.XMLDOM"),r.async="false",r.loadXML(n))}catch(o){r=t}return r&&r.documentElement&&!r.getElementsByTagName("parsererror").length||b.error("Invalid XML: "+n),r},noop:function(){},globalEval:function(t){t&&b.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(j,"ms-").replace(D,L)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,o=e.length,a=M(e);if(n){if(a){for(;o>i;i++)if(r=t.apply(e[i],n),r===!1)break}else for(i in e)if(r=t.apply(e[i],n),r===!1)break}else if(a){for(;o>i;i++)if(r=t.call(e[i],i,e[i]),r===!1)break}else for(i in e)if(r=t.call(e[i],i,e[i]),r===!1)break;return e},trim:v&&!v.call("\ufeff\u00a0")?function(e){return null==e?"":v.call(e)}:function(e){return null==e?"":(e+"").replace(T,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(M(Object(e))?b.merge(n,"string"==typeof e?[e]:e):d.call(n,e)),n},inArray:function(e,t,n){var r;if(t){if(g)return g.call(t,e,n);for(r=t.length,n=n?0>n?Math.max(0,r+n):n:0;r>n;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,n){var r=n.length,i=e.length,o=0;if("number"==typeof r)for(;r>o;o++)e[i++]=n[o];else while(n[o]!==t)e[i++]=n[o++];return e.length=i,e},grep:function(e,t,n){var r,i=[],o=0,a=e.length;for(n=!!n;a>o;o++)r=!!t(e[o],o),n!==r&&i.push(e[o]);return i},map:function(e,t,n){var r,i=0,o=e.length,a=M(e),s=[];if(a)for(;o>i;i++)r=t(e[i],i,n),null!=r&&(s[s.length]=r);else for(i in e)r=t(e[i],i,n),null!=r&&(s[s.length]=r);return f.apply([],s)},guid:1,proxy:function(e,n){var r,i,o;return"string"==typeof n&&(o=e[n],n=e,e=o),b.isFunction(e)?(r=h.call(arguments,2),i=function(){return e.apply(n||this,r.concat(h.call(arguments)))},i.guid=e.guid=e.guid||b.guid++,i):t},access:function(e,n,r,i,o,a,s){var u=0,l=e.length,c=null==r;if("object"===b.type(r)){o=!0;for(u in r)b.access(e,n,u,r[u],!0,a,s)}else if(i!==t&&(o=!0,b.isFunction(i)||(s=!0),c&&(s?(n.call(e,i),n=null):(c=n,n=function(e,t,n){return c.call(b(e),n)})),n))for(;l>u;u++)n(e[u],r,s?i:i.call(e[u],u,n(e[u],r)));return o?e:c?n.call(e):l?n(e[0],r):a},now:function(){return(new Date).getTime()}}),b.ready.promise=function(t){if(!n)if(n=b.Deferred(),"complete"===o.readyState)setTimeout(b.ready);else if(o.addEventListener)o.addEventListener("DOMContentLoaded",H,!1),e.addEventListener("load",H,!1);else{o.attachEvent("onreadystatechange",H),e.attachEvent("onload",H);var r=!1;try{r=null==e.frameElement&&o.documentElement}catch(i){}r&&r.doScroll&&function a(){if(!b.isReady){try{r.doScroll("left")}catch(e){return setTimeout(a,50)}q(),b.ready()}}()}return n.promise(t)},b.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){l["[object "+t+"]"]=t.toLowerCase()});function M(e){var t=e.length,n=b.type(e);return b.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}r=b(o);var _={};function F(e){var t=_[e]={};return b.each(e.match(w)||[],function(e,n){t[n]=!0}),t}b.Callbacks=function(e){e="string"==typeof e?_[e]||F(e):b.extend({},e);var n,r,i,o,a,s,u=[],l=!e.once&&[],c=function(t){for(r=e.memory&&t,i=!0,a=s||0,s=0,o=u.length,n=!0;u&&o>a;a++)if(u[a].apply(t[0],t[1])===!1&&e.stopOnFalse){r=!1;break}n=!1,u&&(l?l.length&&c(l.shift()):r?u=[]:p.disable())},p={add:function(){if(u){var t=u.length;(function i(t){b.each(t,function(t,n){var r=b.type(n);"function"===r?e.unique&&p.has(n)||u.push(n):n&&n.length&&"string"!==r&&i(n)})})(arguments),n?o=u.length:r&&(s=t,c(r))}return this},remove:function(){return u&&b.each(arguments,function(e,t){var r;while((r=b.inArray(t,u,r))>-1)u.splice(r,1),n&&(o>=r&&o--,a>=r&&a--)}),this},has:function(e){return e?b.inArray(e,u)>-1:!(!u||!u.length)},empty:function(){return u=[],this},disable:function(){return u=l=r=t,this},disabled:function(){return!u},lock:function(){return l=t,r||p.disable(),this},locked:function(){return!l},fireWith:function(e,t){return t=t||[],t=[e,t.slice?t.slice():t],!u||i&&!l||(n?l.push(t):c(t)),this},fire:function(){return p.fireWith(this,arguments),this},fired:function(){return!!i}};return p},b.extend({Deferred:function(e){var t=[["resolve","done",b.Callbacks("once memory"),"resolved"],["reject","fail",b.Callbacks("once memory"),"rejected"],["notify","progress",b.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return b.Deferred(function(n){b.each(t,function(t,o){var a=o[0],s=b.isFunction(e[t])&&e[t];i[o[1]](function(){var e=s&&s.apply(this,arguments);e&&b.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[a+"With"](this===r?n.promise():this,s?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?b.extend(e,r):r}},i={};return r.pipe=r.then,b.each(t,function(e,o){var a=o[2],s=o[3];r[o[1]]=a.add,s&&a.add(function(){n=s},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=a.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=h.call(arguments),r=n.length,i=1!==r||e&&b.isFunction(e.promise)?r:0,o=1===i?e:b.Deferred(),a=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?h.call(arguments):r,n===s?o.notifyWith(t,n):--i||o.resolveWith(t,n)}},s,u,l;if(r>1)for(s=Array(r),u=Array(r),l=Array(r);r>t;t++)n[t]&&b.isFunction(n[t].promise)?n[t].promise().done(a(t,l,n)).fail(o.reject).progress(a(t,u,s)):--i;return i||o.resolveWith(l,n),o.promise()}}),b.support=function(){var t,n,r,a,s,u,l,c,p,f,d=o.createElement("div");if(d.setAttribute("className","t"),d.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",n=d.getElementsByTagName("*"),r=d.getElementsByTagName("a")[0],!n||!r||!n.length)return{};s=o.createElement("select"),l=s.appendChild(o.createElement("option")),a=d.getElementsByTagName("input")[0],r.style.cssText="top:1px;float:left;opacity:.5",t={getSetAttribute:"t"!==d.className,leadingWhitespace:3===d.firstChild.nodeType,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/top/.test(r.getAttribute("style")),hrefNormalized:"/a"===r.getAttribute("href"),opacity:/^0.5/.test(r.style.opacity),cssFloat:!!r.style.cssFloat,checkOn:!!a.value,optSelected:l.selected,enctype:!!o.createElement("form").enctype,html5Clone:"<:nav></:nav>"!==o.createElement("nav").cloneNode(!0).outerHTML,boxModel:"CSS1Compat"===o.compatMode,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},a.checked=!0,t.noCloneChecked=a.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!l.disabled;try{delete d.test}catch(h){t.deleteExpando=!1}a=o.createElement("input"),a.setAttribute("value",""),t.input=""===a.getAttribute("value"),a.value="t",a.setAttribute("type","radio"),t.radioValue="t"===a.value,a.setAttribute("checked","t"),a.setAttribute("name","t"),u=o.createDocumentFragment(),u.appendChild(a),t.appendChecked=a.checked,t.checkClone=u.cloneNode(!0).cloneNode(!0).lastChild.checked,d.attachEvent&&(d.attachEvent("onclick",function(){t.noCloneEvent=!1}),d.cloneNode(!0).click());for(f in{submit:!0,change:!0,focusin:!0})d.setAttribute(c="on"+f,"t"),t[f+"Bubbles"]=c in e||d.attributes[c].expando===!1;return d.style.backgroundClip="content-box",d.cloneNode(!0).style.backgroundClip="",t.clearCloneStyle="content-box"===d.style.backgroundClip,b(function(){var n,r,a,s="padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",u=o.getElementsByTagName("body")[0];u&&(n=o.createElement("div"),n.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",u.appendChild(n).appendChild(d),d.innerHTML="<table><tr><td></td><td>t</td></tr></table>",a=d.getElementsByTagName("td"),a[0].style.cssText="padding:0;margin:0;border:0;display:none",p=0===a[0].offsetHeight,a[0].style.display="",a[1].style.display="none",t.reliableHiddenOffsets=p&&0===a[0].offsetHeight,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",t.boxSizing=4===d.offsetWidth,t.doesNotIncludeMarginInBodyOffset=1!==u.offsetTop,e.getComputedStyle&&(t.pixelPosition="1%"!==(e.getComputedStyle(d,null)||{}).top,t.boxSizingReliable="4px"===(e.getComputedStyle(d,null)||{width:"4px"}).width,r=d.appendChild(o.createElement("div")),r.style.cssText=d.style.cssText=s,r.style.marginRight=r.style.width="0",d.style.width="1px",t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)),typeof d.style.zoom!==i&&(d.innerHTML="",d.style.cssText=s+"width:1px;padding:1px;display:inline;zoom:1",t.inlineBlockNeedsLayout=3===d.offsetWidth,d.style.display="block",d.innerHTML="<div></div>",d.firstChild.style.width="5px",t.shrinkWrapBlocks=3!==d.offsetWidth,t.inlineBlockNeedsLayout&&(u.style.zoom=1)),u.removeChild(n),n=d=a=r=null)}),n=s=u=l=r=a=null,t}();var O=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,B=/([A-Z])/g;function P(e,n,r,i){if(b.acceptData(e)){var o,a,s=b.expando,u="string"==typeof n,l=e.nodeType,p=l?b.cache:e,f=l?e[s]:e[s]&&s;if(f&&p[f]&&(i||p[f].data)||!u||r!==t)return f||(l?e[s]=f=c.pop()||b.guid++:f=s),p[f]||(p[f]={},l||(p[f].toJSON=b.noop)),("object"==typeof n||"function"==typeof n)&&(i?p[f]=b.extend(p[f],n):p[f].data=b.extend(p[f].data,n)),o=p[f],i||(o.data||(o.data={}),o=o.data),r!==t&&(o[b.camelCase(n)]=r),u?(a=o[n],null==a&&(a=o[b.camelCase(n)])):a=o,a}}function R(e,t,n){if(b.acceptData(e)){var r,i,o,a=e.nodeType,s=a?b.cache:e,u=a?e[b.expando]:b.expando;if(s[u]){if(t&&(o=n?s[u]:s[u].data)){b.isArray(t)?t=t.concat(b.map(t,b.camelCase)):t in o?t=[t]:(t=b.camelCase(t),t=t in o?[t]:t.split(" "));for(r=0,i=t.length;i>r;r++)delete o[t[r]];if(!(n?$:b.isEmptyObject)(o))return}(n||(delete s[u].data,$(s[u])))&&(a?b.cleanData([e],!0):b.support.deleteExpando||s!=s.window?delete s[u]:s[u]=null)}}}b.extend({cache:{},expando:"jQuery"+(p+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(e){return e=e.nodeType?b.cache[e[b.expando]]:e[b.expando],!!e&&!$(e)},data:function(e,t,n){return P(e,t,n)},removeData:function(e,t){return R(e,t)},_data:function(e,t,n){return P(e,t,n,!0)},_removeData:function(e,t){return R(e,t,!0)},acceptData:function(e){if(e.nodeType&&1!==e.nodeType&&9!==e.nodeType)return!1;var t=e.nodeName&&b.noData[e.nodeName.toLowerCase()];return!t||t!==!0&&e.getAttribute("classid")===t}}),b.fn.extend({data:function(e,n){var r,i,o=this[0],a=0,s=null;if(e===t){if(this.length&&(s=b.data(o),1===o.nodeType&&!b._data(o,"parsedAttrs"))){for(r=o.attributes;r.length>a;a++)i=r[a].name,i.indexOf("data-")||(i=b.camelCase(i.slice(5)),W(o,i,s[i]));b._data(o,"parsedAttrs",!0)}return s}return"object"==typeof e?this.each(function(){b.data(this,e)}):b.access(this,function(n){return n===t?o?W(o,e,b.data(o,e)):null:(this.each(function(){b.data(this,e,n)}),t)},null,n,arguments.length>1,null,!0)},removeData:function(e){return this.each(function(){b.removeData(this,e)})}});function W(e,n,r){if(r===t&&1===e.nodeType){var i="data-"+n.replace(B,"-$1").toLowerCase();if(r=e.getAttribute(i),"string"==typeof r){try{r="true"===r?!0:"false"===r?!1:"null"===r?null:+r+""===r?+r:O.test(r)?b.parseJSON(r):r}catch(o){}b.data(e,n,r)}else r=t}return r}function $(e){var t;for(t in e)if(("data"!==t||!b.isEmptyObject(e[t]))&&"toJSON"!==t)return!1;return!0}b.extend({queue:function(e,n,r){var i;return e?(n=(n||"fx")+"queue",i=b._data(e,n),r&&(!i||b.isArray(r)?i=b._data(e,n,b.makeArray(r)):i.push(r)),i||[]):t},dequeue:function(e,t){t=t||"fx";var n=b.queue(e,t),r=n.length,i=n.shift(),o=b._queueHooks(e,t),a=function(){b.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),o.cur=i,i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return b._data(e,n)||b._data(e,n,{empty:b.Callbacks("once memory").add(function(){b._removeData(e,t+"queue"),b._removeData(e,n)})})}}),b.fn.extend({queue:function(e,n){var r=2;return"string"!=typeof e&&(n=e,e="fx",r--),r>arguments.length?b.queue(this[0],e):n===t?this:this.each(function(){var t=b.queue(this,e,n);b._queueHooks(this,e),"fx"===e&&"inprogress"!==t[0]&&b.dequeue(this,e)})},dequeue:function(e){return this.each(function(){b.dequeue(this,e)})},delay:function(e,t){return e=b.fx?b.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,n){var r,i=1,o=b.Deferred(),a=this,s=this.length,u=function(){--i||o.resolveWith(a,[a])};"string"!=typeof e&&(n=e,e=t),e=e||"fx";while(s--)r=b._data(a[s],e+"queueHooks"),r&&r.empty&&(i++,r.empty.add(u));return u(),o.promise(n)}});var I,z,X=/[\t\r\n]/g,U=/\r/g,V=/^(?:input|select|textarea|button|object)$/i,Y=/^(?:a|area)$/i,J=/^(?:checked|selected|autofocus|autoplay|async|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped)$/i,G=/^(?:checked|selected)$/i,Q=b.support.getSetAttribute,K=b.support.input;b.fn.extend({attr:function(e,t){return b.access(this,b.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){b.removeAttr(this,e)})},prop:function(e,t){return b.access(this,b.prop,e,t,arguments.length>1)},removeProp:function(e){return e=b.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,o,a=0,s=this.length,u="string"==typeof e&&e;if(b.isFunction(e))return this.each(function(t){b(this).addClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(X," "):" ")){o=0;while(i=t[o++])0>r.indexOf(" "+i+" ")&&(r+=i+" ");n.className=b.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,a=0,s=this.length,u=0===arguments.length||"string"==typeof e&&e;if(b.isFunction(e))return this.each(function(t){b(this).removeClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(X," "):"")){o=0;while(i=t[o++])while(r.indexOf(" "+i+" ")>=0)r=r.replace(" "+i+" "," ");n.className=e?b.trim(r):""}return this},toggleClass:function(e,t){var n=typeof e,r="boolean"==typeof t;return b.isFunction(e)?this.each(function(n){b(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if("string"===n){var o,a=0,s=b(this),u=t,l=e.match(w)||[];while(o=l[a++])u=r?u:!s.hasClass(o),s[u?"addClass":"removeClass"](o)}else(n===i||"boolean"===n)&&(this.className&&b._data(this,"__className__",this.className),this.className=this.className||e===!1?"":b._data(this,"__className__")||"")})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;r>n;n++)if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(X," ").indexOf(t)>=0)return!0;return!1},val:function(e){var n,r,i,o=this[0];{if(arguments.length)return i=b.isFunction(e),this.each(function(n){var o,a=b(this);1===this.nodeType&&(o=i?e.call(this,n,a.val()):e,null==o?o="":"number"==typeof o?o+="":b.isArray(o)&&(o=b.map(o,function(e){return null==e?"":e+""})),r=b.valHooks[this.type]||b.valHooks[this.nodeName.toLowerCase()],r&&"set"in r&&r.set(this,o,"value")!==t||(this.value=o))});if(o)return r=b.valHooks[o.type]||b.valHooks[o.nodeName.toLowerCase()],r&&"get"in r&&(n=r.get(o,"value"))!==t?n:(n=o.value,"string"==typeof n?n.replace(U,""):null==n?"":n)}}}),b.extend({valHooks:{option:{get:function(e){var t=e.attributes.value;return!t||t.specified?e.value:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,a=o?null:[],s=o?i+1:r.length,u=0>i?s:o?i:0;for(;s>u;u++)if(n=r[u],!(!n.selected&&u!==i||(b.support.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&b.nodeName(n.parentNode,"optgroup"))){if(t=b(n).val(),o)return t;a.push(t)}return a},set:function(e,t){var n=b.makeArray(t);return b(e).find("option").each(function(){this.selected=b.inArray(b(this).val(),n)>=0}),n.length||(e.selectedIndex=-1),n}}},attr:function(e,n,r){var o,a,s,u=e.nodeType;if(e&&3!==u&&8!==u&&2!==u)return typeof e.getAttribute===i?b.prop(e,n,r):(a=1!==u||!b.isXMLDoc(e),a&&(n=n.toLowerCase(),o=b.attrHooks[n]||(J.test(n)?z:I)),r===t?o&&a&&"get"in o&&null!==(s=o.get(e,n))?s:(typeof e.getAttribute!==i&&(s=e.getAttribute(n)),null==s?t:s):null!==r?o&&a&&"set"in o&&(s=o.set(e,r,n))!==t?s:(e.setAttribute(n,r+""),r):(b.removeAttr(e,n),t))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(w);if(o&&1===e.nodeType)while(n=o[i++])r=b.propFix[n]||n,J.test(n)?!Q&&G.test(n)?e[b.camelCase("default-"+n)]=e[r]=!1:e[r]=!1:b.attr(e,n,""),e.removeAttribute(Q?n:r)},attrHooks:{type:{set:function(e,t){if(!b.support.radioValue&&"radio"===t&&b.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(e,n,r){var i,o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return a=1!==s||!b.isXMLDoc(e),a&&(n=b.propFix[n]||n,o=b.propHooks[n]),r!==t?o&&"set"in o&&(i=o.set(e,r,n))!==t?i:e[n]=r:o&&"get"in o&&null!==(i=o.get(e,n))?i:e[n]},propHooks:{tabIndex:{get:function(e){var n=e.getAttributeNode("tabindex");return n&&n.specified?parseInt(n.value,10):V.test(e.nodeName)||Y.test(e.nodeName)&&e.href?0:t}}}}),z={get:function(e,n){var r=b.prop(e,n),i="boolean"==typeof r&&e.getAttribute(n),o="boolean"==typeof r?K&&Q?null!=i:G.test(n)?e[b.camelCase("default-"+n)]:!!i:e.getAttributeNode(n);return o&&o.value!==!1?n.toLowerCase():t},set:function(e,t,n){return t===!1?b.removeAttr(e,n):K&&Q||!G.test(n)?e.setAttribute(!Q&&b.propFix[n]||n,n):e[b.camelCase("default-"+n)]=e[n]=!0,n}},K&&Q||(b.attrHooks.value={get:function(e,n){var r=e.getAttributeNode(n);return b.nodeName(e,"input")?e.defaultValue:r&&r.specified?r.value:t},set:function(e,n,r){return b.nodeName(e,"input")?(e.defaultValue=n,t):I&&I.set(e,n,r)}}),Q||(I=b.valHooks.button={get:function(e,n){var r=e.getAttributeNode(n);return r&&("id"===n||"name"===n||"coords"===n?""!==r.value:r.specified)?r.value:t},set:function(e,n,r){var i=e.getAttributeNode(r);return i||e.setAttributeNode(i=e.ownerDocument.createAttribute(r)),i.value=n+="","value"===r||n===e.getAttribute(r)?n:t}},b.attrHooks.contenteditable={get:I.get,set:function(e,t,n){I.set(e,""===t?!1:t,n)}},b.each(["width","height"],function(e,n){b.attrHooks[n]=b.extend(b.attrHooks[n],{set:function(e,r){return""===r?(e.setAttribute(n,"auto"),r):t}})})),b.support.hrefNormalized||(b.each(["href","src","width","height"],function(e,n){b.attrHooks[n]=b.extend(b.attrHooks[n],{get:function(e){var r=e.getAttribute(n,2);return null==r?t:r}})}),b.each(["href","src"],function(e,t){b.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}})),b.support.style||(b.attrHooks.style={get:function(e){return e.style.cssText||t},set:function(e,t){return e.style.cssText=t+""}}),b.support.optSelected||(b.propHooks.selected=b.extend(b.propHooks.selected,{get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null}})),b.support.enctype||(b.propFix.enctype="encoding"),b.support.checkOn||b.each(["radio","checkbox"],function(){b.valHooks[this]={get:function(e){return null===e.getAttribute("value")?"on":e.value}}}),b.each(["radio","checkbox"],function(){b.valHooks[this]=b.extend(b.valHooks[this],{set:function(e,n){return b.isArray(n)?e.checked=b.inArray(b(e).val(),n)>=0:t}})});var Z=/^(?:input|select|textarea)$/i,et=/^key/,tt=/^(?:mouse|contextmenu)|click/,nt=/^(?:focusinfocus|focusoutblur)$/,rt=/^([^.]*)(?:\.(.+)|)$/;function it(){return!0}function ot(){return!1}b.event={global:{},add:function(e,n,r,o,a){var s,u,l,c,p,f,d,h,g,m,y,v=b._data(e);if(v){r.handler&&(c=r,r=c.handler,a=c.selector),r.guid||(r.guid=b.guid++),(u=v.events)||(u=v.events={}),(f=v.handle)||(f=v.handle=function(e){return typeof b===i||e&&b.event.triggered===e.type?t:b.event.dispatch.apply(f.elem,arguments)},f.elem=e),n=(n||"").match(w)||[""],l=n.length;while(l--)s=rt.exec(n[l])||[],g=y=s[1],m=(s[2]||"").split(".").sort(),p=b.event.special[g]||{},g=(a?p.delegateType:p.bindType)||g,p=b.event.special[g]||{},d=b.extend({type:g,origType:y,data:o,handler:r,guid:r.guid,selector:a,needsContext:a&&b.expr.match.needsContext.test(a),namespace:m.join(".")},c),(h=u[g])||(h=u[g]=[],h.delegateCount=0,p.setup&&p.setup.call(e,o,m,f)!==!1||(e.addEventListener?e.addEventListener(g,f,!1):e.attachEvent&&e.attachEvent("on"+g,f))),p.add&&(p.add.call(e,d),d.handler.guid||(d.handler.guid=r.guid)),a?h.splice(h.delegateCount++,0,d):h.push(d),b.event.global[g]=!0;e=null}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,p,f,d,h,g,m=b.hasData(e)&&b._data(e);if(m&&(c=m.events)){t=(t||"").match(w)||[""],l=t.length;while(l--)if(s=rt.exec(t[l])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d){p=b.event.special[d]||{},d=(r?p.delegateType:p.bindType)||d,f=c[d]||[],s=s[2]&&RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),u=o=f.length;while(o--)a=f[o],!i&&g!==a.origType||n&&n.guid!==a.guid||s&&!s.test(a.namespace)||r&&r!==a.selector&&("**"!==r||!a.selector)||(f.splice(o,1),a.selector&&f.delegateCount--,p.remove&&p.remove.call(e,a));u&&!f.length&&(p.teardown&&p.teardown.call(e,h,m.handle)!==!1||b.removeEvent(e,d,m.handle),delete c[d])}else for(d in c)b.event.remove(e,d+t[l],n,r,!0);b.isEmptyObject(c)&&(delete m.handle,b._removeData(e,"events"))}},trigger:function(n,r,i,a){var s,u,l,c,p,f,d,h=[i||o],g=y.call(n,"type")?n.type:n,m=y.call(n,"namespace")?n.namespace.split("."):[];if(l=f=i=i||o,3!==i.nodeType&&8!==i.nodeType&&!nt.test(g+b.event.triggered)&&(g.indexOf(".")>=0&&(m=g.split("."),g=m.shift(),m.sort()),u=0>g.indexOf(":")&&"on"+g,n=n[b.expando]?n:new b.Event(g,"object"==typeof n&&n),n.isTrigger=!0,n.namespace=m.join("."),n.namespace_re=n.namespace?RegExp("(^|\\.)"+m.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,n.result=t,n.target||(n.target=i),r=null==r?[n]:b.makeArray(r,[n]),p=b.event.special[g]||{},a||!p.trigger||p.trigger.apply(i,r)!==!1)){if(!a&&!p.noBubble&&!b.isWindow(i)){for(c=p.delegateType||g,nt.test(c+g)||(l=l.parentNode);l;l=l.parentNode)h.push(l),f=l;f===(i.ownerDocument||o)&&h.push(f.defaultView||f.parentWindow||e)}d=0;while((l=h[d++])&&!n.isPropagationStopped())n.type=d>1?c:p.bindType||g,s=(b._data(l,"events")||{})[n.type]&&b._data(l,"handle"),s&&s.apply(l,r),s=u&&l[u],s&&b.acceptData(l)&&s.apply&&s.apply(l,r)===!1&&n.preventDefault();if(n.type=g,!(a||n.isDefaultPrevented()||p._default&&p._default.apply(i.ownerDocument,r)!==!1||"click"===g&&b.nodeName(i,"a")||!b.acceptData(i)||!u||!i[g]||b.isWindow(i))){f=i[u],f&&(i[u]=null),b.event.triggered=g;try{i[g]()}catch(v){}b.event.triggered=t,f&&(i[u]=f)}return n.result}},dispatch:function(e){e=b.event.fix(e);var n,r,i,o,a,s=[],u=h.call(arguments),l=(b._data(this,"events")||{})[e.type]||[],c=b.event.special[e.type]||{};if(u[0]=e,e.delegateTarget=this,!c.preDispatch||c.preDispatch.call(this,e)!==!1){s=b.event.handlers.call(this,e,l),n=0;while((o=s[n++])&&!e.isPropagationStopped()){e.currentTarget=o.elem,a=0;while((i=o.handlers[a++])&&!e.isImmediatePropagationStopped())(!e.namespace_re||e.namespace_re.test(i.namespace))&&(e.handleObj=i,e.data=i.data,r=((b.event.special[i.origType]||{}).handle||i.handler).apply(o.elem,u),r!==t&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,e),e.result}},handlers:function(e,n){var r,i,o,a,s=[],u=n.delegateCount,l=e.target;if(u&&l.nodeType&&(!e.button||"click"!==e.type))for(;l!=this;l=l.parentNode||this)if(1===l.nodeType&&(l.disabled!==!0||"click"!==e.type)){for(o=[],a=0;u>a;a++)i=n[a],r=i.selector+" ",o[r]===t&&(o[r]=i.needsContext?b(r,this).index(l)>=0:b.find(r,this,null,[l]).length),o[r]&&o.push(i);o.length&&s.push({elem:l,handlers:o})}return n.length>u&&s.push({elem:this,handlers:n.slice(u)}),s},fix:function(e){if(e[b.expando])return e;var t,n,r,i=e.type,a=e,s=this.fixHooks[i];s||(this.fixHooks[i]=s=tt.test(i)?this.mouseHooks:et.test(i)?this.keyHooks:{}),r=s.props?this.props.concat(s.props):this.props,e=new b.Event(a),t=r.length;while(t--)n=r[t],e[n]=a[n];return e.target||(e.target=a.srcElement||o),3===e.target.nodeType&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,s.filter?s.filter(e,a):e},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,n){var r,i,a,s=n.button,u=n.fromElement;return null==e.pageX&&null!=n.clientX&&(i=e.target.ownerDocument||o,a=i.documentElement,r=i.body,e.pageX=n.clientX+(a&&a.scrollLeft||r&&r.scrollLeft||0)-(a&&a.clientLeft||r&&r.clientLeft||0),e.pageY=n.clientY+(a&&a.scrollTop||r&&r.scrollTop||0)-(a&&a.clientTop||r&&r.clientTop||0)),!e.relatedTarget&&u&&(e.relatedTarget=u===e.target?n.toElement:u),e.which||s===t||(e.which=1&s?1:2&s?3:4&s?2:0),e}},special:{load:{noBubble:!0},click:{trigger:function(){return b.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):t}},focus:{trigger:function(){if(this!==o.activeElement&&this.focus)try{return this.focus(),!1}catch(e){}},delegateType:"focusin"},blur:{trigger:function(){return this===o.activeElement&&this.blur?(this.blur(),!1):t},delegateType:"focusout"},beforeunload:{postDispatch:function(e){e.result!==t&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=b.extend(new b.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?b.event.trigger(i,null,t):b.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},b.removeEvent=o.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)}:function(e,t,n){var r="on"+t;e.detachEvent&&(typeof e[r]===i&&(e[r]=null),e.detachEvent(r,n))},b.Event=function(e,n){return this instanceof b.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.returnValue===!1||e.getPreventDefault&&e.getPreventDefault()?it:ot):this.type=e,n&&b.extend(this,n),this.timeStamp=e&&e.timeStamp||b.now(),this[b.expando]=!0,t):new b.Event(e,n)},b.Event.prototype={isDefaultPrevented:ot,isPropagationStopped:ot,isImmediatePropagationStopped:ot,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=it,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=it,e&&(e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=it,this.stopPropagation()}},b.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){b.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj; - return(!i||i!==r&&!b.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),b.support.submitBubbles||(b.event.special.submit={setup:function(){return b.nodeName(this,"form")?!1:(b.event.add(this,"click._submit keypress._submit",function(e){var n=e.target,r=b.nodeName(n,"input")||b.nodeName(n,"button")?n.form:t;r&&!b._data(r,"submitBubbles")&&(b.event.add(r,"submit._submit",function(e){e._submit_bubble=!0}),b._data(r,"submitBubbles",!0))}),t)},postDispatch:function(e){e._submit_bubble&&(delete e._submit_bubble,this.parentNode&&!e.isTrigger&&b.event.simulate("submit",this.parentNode,e,!0))},teardown:function(){return b.nodeName(this,"form")?!1:(b.event.remove(this,"._submit"),t)}}),b.support.changeBubbles||(b.event.special.change={setup:function(){return Z.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(b.event.add(this,"propertychange._change",function(e){"checked"===e.originalEvent.propertyName&&(this._just_changed=!0)}),b.event.add(this,"click._change",function(e){this._just_changed&&!e.isTrigger&&(this._just_changed=!1),b.event.simulate("change",this,e,!0)})),!1):(b.event.add(this,"beforeactivate._change",function(e){var t=e.target;Z.test(t.nodeName)&&!b._data(t,"changeBubbles")&&(b.event.add(t,"change._change",function(e){!this.parentNode||e.isSimulated||e.isTrigger||b.event.simulate("change",this.parentNode,e,!0)}),b._data(t,"changeBubbles",!0))}),t)},handle:function(e){var n=e.target;return this!==n||e.isSimulated||e.isTrigger||"radio"!==n.type&&"checkbox"!==n.type?e.handleObj.handler.apply(this,arguments):t},teardown:function(){return b.event.remove(this,"._change"),!Z.test(this.nodeName)}}),b.support.focusinBubbles||b.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){b.event.simulate(t,e.target,b.event.fix(e),!0)};b.event.special[t]={setup:function(){0===n++&&o.addEventListener(e,r,!0)},teardown:function(){0===--n&&o.removeEventListener(e,r,!0)}}}),b.fn.extend({on:function(e,n,r,i,o){var a,s;if("object"==typeof e){"string"!=typeof n&&(r=r||n,n=t);for(a in e)this.on(a,n,r,e[a],o);return this}if(null==r&&null==i?(i=n,r=n=t):null==i&&("string"==typeof n?(i=r,r=t):(i=r,r=n,n=t)),i===!1)i=ot;else if(!i)return this;return 1===o&&(s=i,i=function(e){return b().off(e),s.apply(this,arguments)},i.guid=s.guid||(s.guid=b.guid++)),this.each(function(){b.event.add(this,e,i,r,n)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,n,r){var i,o;if(e&&e.preventDefault&&e.handleObj)return i=e.handleObj,b(e.delegateTarget).off(i.namespace?i.origType+"."+i.namespace:i.origType,i.selector,i.handler),this;if("object"==typeof e){for(o in e)this.off(o,n,e[o]);return this}return(n===!1||"function"==typeof n)&&(r=n,n=t),r===!1&&(r=ot),this.each(function(){b.event.remove(this,e,r,n)})},bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},trigger:function(e,t){return this.each(function(){b.event.trigger(e,t,this)})},triggerHandler:function(e,n){var r=this[0];return r?b.event.trigger(e,n,r,!0):t}}),function(e,t){var n,r,i,o,a,s,u,l,c,p,f,d,h,g,m,y,v,x="sizzle"+-new Date,w=e.document,T={},N=0,C=0,k=it(),E=it(),S=it(),A=typeof t,j=1<<31,D=[],L=D.pop,H=D.push,q=D.slice,M=D.indexOf||function(e){var t=0,n=this.length;for(;n>t;t++)if(this[t]===e)return t;return-1},_="[\\x20\\t\\r\\n\\f]",F="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",O=F.replace("w","w#"),B="([*^$|!~]?=)",P="\\["+_+"*("+F+")"+_+"*(?:"+B+_+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+O+")|)|)"+_+"*\\]",R=":("+F+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+P.replace(3,8)+")*)|.*)\\)|)",W=RegExp("^"+_+"+|((?:^|[^\\\\])(?:\\\\.)*)"+_+"+$","g"),$=RegExp("^"+_+"*,"+_+"*"),I=RegExp("^"+_+"*([\\x20\\t\\r\\n\\f>+~])"+_+"*"),z=RegExp(R),X=RegExp("^"+O+"$"),U={ID:RegExp("^#("+F+")"),CLASS:RegExp("^\\.("+F+")"),NAME:RegExp("^\\[name=['\"]?("+F+")['\"]?\\]"),TAG:RegExp("^("+F.replace("w","w*")+")"),ATTR:RegExp("^"+P),PSEUDO:RegExp("^"+R),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+_+"*(even|odd|(([+-]|)(\\d*)n|)"+_+"*(?:([+-]|)"+_+"*(\\d+)|))"+_+"*\\)|)","i"),needsContext:RegExp("^"+_+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+_+"*((?:-\\d)?\\d*)"+_+"*\\)|)(?=[^-]|$)","i")},V=/[\x20\t\r\n\f]*[+~]/,Y=/^[^{]+\{\s*\[native code/,J=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,G=/^(?:input|select|textarea|button)$/i,Q=/^h\d$/i,K=/'|\\/g,Z=/\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,et=/\\([\da-fA-F]{1,6}[\x20\t\r\n\f]?|.)/g,tt=function(e,t){var n="0x"+t-65536;return n!==n?t:0>n?String.fromCharCode(n+65536):String.fromCharCode(55296|n>>10,56320|1023&n)};try{q.call(w.documentElement.childNodes,0)[0].nodeType}catch(nt){q=function(e){var t,n=[];while(t=this[e++])n.push(t);return n}}function rt(e){return Y.test(e+"")}function it(){var e,t=[];return e=function(n,r){return t.push(n+=" ")>i.cacheLength&&delete e[t.shift()],e[n]=r}}function ot(e){return e[x]=!0,e}function at(e){var t=p.createElement("div");try{return e(t)}catch(n){return!1}finally{t=null}}function st(e,t,n,r){var i,o,a,s,u,l,f,g,m,v;if((t?t.ownerDocument||t:w)!==p&&c(t),t=t||p,n=n||[],!e||"string"!=typeof e)return n;if(1!==(s=t.nodeType)&&9!==s)return[];if(!d&&!r){if(i=J.exec(e))if(a=i[1]){if(9===s){if(o=t.getElementById(a),!o||!o.parentNode)return n;if(o.id===a)return n.push(o),n}else if(t.ownerDocument&&(o=t.ownerDocument.getElementById(a))&&y(t,o)&&o.id===a)return n.push(o),n}else{if(i[2])return H.apply(n,q.call(t.getElementsByTagName(e),0)),n;if((a=i[3])&&T.getByClassName&&t.getElementsByClassName)return H.apply(n,q.call(t.getElementsByClassName(a),0)),n}if(T.qsa&&!h.test(e)){if(f=!0,g=x,m=t,v=9===s&&e,1===s&&"object"!==t.nodeName.toLowerCase()){l=ft(e),(f=t.getAttribute("id"))?g=f.replace(K,"\\$&"):t.setAttribute("id",g),g="[id='"+g+"'] ",u=l.length;while(u--)l[u]=g+dt(l[u]);m=V.test(e)&&t.parentNode||t,v=l.join(",")}if(v)try{return H.apply(n,q.call(m.querySelectorAll(v),0)),n}catch(b){}finally{f||t.removeAttribute("id")}}}return wt(e.replace(W,"$1"),t,n,r)}a=st.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},c=st.setDocument=function(e){var n=e?e.ownerDocument||e:w;return n!==p&&9===n.nodeType&&n.documentElement?(p=n,f=n.documentElement,d=a(n),T.tagNameNoComments=at(function(e){return e.appendChild(n.createComment("")),!e.getElementsByTagName("*").length}),T.attributes=at(function(e){e.innerHTML="<select></select>";var t=typeof e.lastChild.getAttribute("multiple");return"boolean"!==t&&"string"!==t}),T.getByClassName=at(function(e){return e.innerHTML="<div class='hidden e'></div><div class='hidden'></div>",e.getElementsByClassName&&e.getElementsByClassName("e").length?(e.lastChild.className="e",2===e.getElementsByClassName("e").length):!1}),T.getByName=at(function(e){e.id=x+0,e.innerHTML="<a name='"+x+"'></a><div name='"+x+"'></div>",f.insertBefore(e,f.firstChild);var t=n.getElementsByName&&n.getElementsByName(x).length===2+n.getElementsByName(x+0).length;return T.getIdNotName=!n.getElementById(x),f.removeChild(e),t}),i.attrHandle=at(function(e){return e.innerHTML="<a href='#'></a>",e.firstChild&&typeof e.firstChild.getAttribute!==A&&"#"===e.firstChild.getAttribute("href")})?{}:{href:function(e){return e.getAttribute("href",2)},type:function(e){return e.getAttribute("type")}},T.getIdNotName?(i.find.ID=function(e,t){if(typeof t.getElementById!==A&&!d){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},i.filter.ID=function(e){var t=e.replace(et,tt);return function(e){return e.getAttribute("id")===t}}):(i.find.ID=function(e,n){if(typeof n.getElementById!==A&&!d){var r=n.getElementById(e);return r?r.id===e||typeof r.getAttributeNode!==A&&r.getAttributeNode("id").value===e?[r]:t:[]}},i.filter.ID=function(e){var t=e.replace(et,tt);return function(e){var n=typeof e.getAttributeNode!==A&&e.getAttributeNode("id");return n&&n.value===t}}),i.find.TAG=T.tagNameNoComments?function(e,n){return typeof n.getElementsByTagName!==A?n.getElementsByTagName(e):t}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},i.find.NAME=T.getByName&&function(e,n){return typeof n.getElementsByName!==A?n.getElementsByName(name):t},i.find.CLASS=T.getByClassName&&function(e,n){return typeof n.getElementsByClassName===A||d?t:n.getElementsByClassName(e)},g=[],h=[":focus"],(T.qsa=rt(n.querySelectorAll))&&(at(function(e){e.innerHTML="<select><option selected=''></option></select>",e.querySelectorAll("[selected]").length||h.push("\\["+_+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),e.querySelectorAll(":checked").length||h.push(":checked")}),at(function(e){e.innerHTML="<input type='hidden' i=''/>",e.querySelectorAll("[i^='']").length&&h.push("[*^$]="+_+"*(?:\"\"|'')"),e.querySelectorAll(":enabled").length||h.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),h.push(",.*:")})),(T.matchesSelector=rt(m=f.matchesSelector||f.mozMatchesSelector||f.webkitMatchesSelector||f.oMatchesSelector||f.msMatchesSelector))&&at(function(e){T.disconnectedMatch=m.call(e,"div"),m.call(e,"[s!='']:x"),g.push("!=",R)}),h=RegExp(h.join("|")),g=RegExp(g.join("|")),y=rt(f.contains)||f.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},v=f.compareDocumentPosition?function(e,t){var r;return e===t?(u=!0,0):(r=t.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(t))?1&r||e.parentNode&&11===e.parentNode.nodeType?e===n||y(w,e)?-1:t===n||y(w,t)?1:0:4&r?-1:1:e.compareDocumentPosition?-1:1}:function(e,t){var r,i=0,o=e.parentNode,a=t.parentNode,s=[e],l=[t];if(e===t)return u=!0,0;if(!o||!a)return e===n?-1:t===n?1:o?-1:a?1:0;if(o===a)return ut(e,t);r=e;while(r=r.parentNode)s.unshift(r);r=t;while(r=r.parentNode)l.unshift(r);while(s[i]===l[i])i++;return i?ut(s[i],l[i]):s[i]===w?-1:l[i]===w?1:0},u=!1,[0,0].sort(v),T.detectDuplicates=u,p):p},st.matches=function(e,t){return st(e,null,null,t)},st.matchesSelector=function(e,t){if((e.ownerDocument||e)!==p&&c(e),t=t.replace(Z,"='$1']"),!(!T.matchesSelector||d||g&&g.test(t)||h.test(t)))try{var n=m.call(e,t);if(n||T.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(r){}return st(t,p,null,[e]).length>0},st.contains=function(e,t){return(e.ownerDocument||e)!==p&&c(e),y(e,t)},st.attr=function(e,t){var n;return(e.ownerDocument||e)!==p&&c(e),d||(t=t.toLowerCase()),(n=i.attrHandle[t])?n(e):d||T.attributes?e.getAttribute(t):((n=e.getAttributeNode(t))||e.getAttribute(t))&&e[t]===!0?t:n&&n.specified?n.value:null},st.error=function(e){throw Error("Syntax error, unrecognized expression: "+e)},st.uniqueSort=function(e){var t,n=[],r=1,i=0;if(u=!T.detectDuplicates,e.sort(v),u){for(;t=e[r];r++)t===e[r-1]&&(i=n.push(r));while(i--)e.splice(n[i],1)}return e};function ut(e,t){var n=t&&e,r=n&&(~t.sourceIndex||j)-(~e.sourceIndex||j);if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function lt(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function ct(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function pt(e){return ot(function(t){return t=+t,ot(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}o=st.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=o(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r];r++)n+=o(t);return n},i=st.selectors={cacheLength:50,createPseudo:ot,match:U,find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(et,tt),e[3]=(e[4]||e[5]||"").replace(et,tt),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||st.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&st.error(e[0]),e},PSEUDO:function(e){var t,n=!e[5]&&e[2];return U.CHILD.test(e[0])?null:(e[4]?e[2]=e[4]:n&&z.test(n)&&(t=ft(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){return"*"===e?function(){return!0}:(e=e.replace(et,tt).toLowerCase(),function(t){return t.nodeName&&t.nodeName.toLowerCase()===e})},CLASS:function(e){var t=k[e+" "];return t||(t=RegExp("(^|"+_+")"+e+"("+_+"|$)"))&&k(e,function(e){return t.test(e.className||typeof e.getAttribute!==A&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=st.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.slice(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,p,f,d,h,g=o!==a?"nextSibling":"previousSibling",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!u&&!s;if(m){if(o){while(g){p=t;while(p=p[g])if(s?p.nodeName.toLowerCase()===y:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&v){c=m[x]||(m[x]={}),l=c[e]||[],d=l[0]===N&&l[1],f=l[0]===N&&l[2],p=d&&m.childNodes[d];while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if(1===p.nodeType&&++f&&p===t){c[e]=[N,d,f];break}}else if(v&&(l=(t[x]||(t[x]={}))[e])&&l[0]===N)f=l[1];else while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if((s?p.nodeName.toLowerCase()===y:1===p.nodeType)&&++f&&(v&&((p[x]||(p[x]={}))[e]=[N,f]),p===t))break;return f-=i,f===r||0===f%r&&f/r>=0}}},PSEUDO:function(e,t){var n,r=i.pseudos[e]||i.setFilters[e.toLowerCase()]||st.error("unsupported pseudo: "+e);return r[x]?r(t):r.length>1?(n=[e,e,"",t],i.setFilters.hasOwnProperty(e.toLowerCase())?ot(function(e,n){var i,o=r(e,t),a=o.length;while(a--)i=M.call(e,o[a]),e[i]=!(n[i]=o[a])}):function(e){return r(e,0,n)}):r}},pseudos:{not:ot(function(e){var t=[],n=[],r=s(e.replace(W,"$1"));return r[x]?ot(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:ot(function(e){return function(t){return st(e,t).length>0}}),contains:ot(function(e){return function(t){return(t.textContent||t.innerText||o(t)).indexOf(e)>-1}}),lang:ot(function(e){return X.test(e||"")||st.error("unsupported lang: "+e),e=e.replace(et,tt).toLowerCase(),function(t){var n;do if(n=d?t.getAttribute("xml:lang")||t.getAttribute("lang"):t.lang)return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===f},focus:function(e){return e===p.activeElement&&(!p.hasFocus||p.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!i.pseudos.empty(e)},header:function(e){return Q.test(e.nodeName)},input:function(e){return G.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:pt(function(){return[0]}),last:pt(function(e,t){return[t-1]}),eq:pt(function(e,t,n){return[0>n?n+t:n]}),even:pt(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:pt(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:pt(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:pt(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}};for(n in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})i.pseudos[n]=lt(n);for(n in{submit:!0,reset:!0})i.pseudos[n]=ct(n);function ft(e,t){var n,r,o,a,s,u,l,c=E[e+" "];if(c)return t?0:c.slice(0);s=e,u=[],l=i.preFilter;while(s){(!n||(r=$.exec(s)))&&(r&&(s=s.slice(r[0].length)||s),u.push(o=[])),n=!1,(r=I.exec(s))&&(n=r.shift(),o.push({value:n,type:r[0].replace(W," ")}),s=s.slice(n.length));for(a in i.filter)!(r=U[a].exec(s))||l[a]&&!(r=l[a](r))||(n=r.shift(),o.push({value:n,type:a,matches:r}),s=s.slice(n.length));if(!n)break}return t?s.length:s?st.error(e):E(e,u).slice(0)}function dt(e){var t=0,n=e.length,r="";for(;n>t;t++)r+=e[t].value;return r}function ht(e,t,n){var i=t.dir,o=n&&"parentNode"===i,a=C++;return t.first?function(t,n,r){while(t=t[i])if(1===t.nodeType||o)return e(t,n,r)}:function(t,n,s){var u,l,c,p=N+" "+a;if(s){while(t=t[i])if((1===t.nodeType||o)&&e(t,n,s))return!0}else while(t=t[i])if(1===t.nodeType||o)if(c=t[x]||(t[x]={}),(l=c[i])&&l[0]===p){if((u=l[1])===!0||u===r)return u===!0}else if(l=c[i]=[p],l[1]=e(t,n,s)||r,l[1]===!0)return!0}}function gt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function mt(e,t,n,r,i){var o,a=[],s=0,u=e.length,l=null!=t;for(;u>s;s++)(o=e[s])&&(!n||n(o,r,i))&&(a.push(o),l&&t.push(s));return a}function yt(e,t,n,r,i,o){return r&&!r[x]&&(r=yt(r)),i&&!i[x]&&(i=yt(i,o)),ot(function(o,a,s,u){var l,c,p,f=[],d=[],h=a.length,g=o||xt(t||"*",s.nodeType?[s]:s,[]),m=!e||!o&&t?g:mt(g,f,e,s,u),y=n?i||(o?e:h||r)?[]:a:m;if(n&&n(m,y,s,u),r){l=mt(y,d),r(l,[],s,u),c=l.length;while(c--)(p=l[c])&&(y[d[c]]=!(m[d[c]]=p))}if(o){if(i||e){if(i){l=[],c=y.length;while(c--)(p=y[c])&&l.push(m[c]=p);i(null,y=[],l,u)}c=y.length;while(c--)(p=y[c])&&(l=i?M.call(o,p):f[c])>-1&&(o[l]=!(a[l]=p))}}else y=mt(y===a?y.splice(h,y.length):y),i?i(null,a,y,u):H.apply(a,y)})}function vt(e){var t,n,r,o=e.length,a=i.relative[e[0].type],s=a||i.relative[" "],u=a?1:0,c=ht(function(e){return e===t},s,!0),p=ht(function(e){return M.call(t,e)>-1},s,!0),f=[function(e,n,r){return!a&&(r||n!==l)||((t=n).nodeType?c(e,n,r):p(e,n,r))}];for(;o>u;u++)if(n=i.relative[e[u].type])f=[ht(gt(f),n)];else{if(n=i.filter[e[u].type].apply(null,e[u].matches),n[x]){for(r=++u;o>r;r++)if(i.relative[e[r].type])break;return yt(u>1&>(f),u>1&&dt(e.slice(0,u-1)).replace(W,"$1"),n,r>u&&vt(e.slice(u,r)),o>r&&vt(e=e.slice(r)),o>r&&dt(e))}f.push(n)}return gt(f)}function bt(e,t){var n=0,o=t.length>0,a=e.length>0,s=function(s,u,c,f,d){var h,g,m,y=[],v=0,b="0",x=s&&[],w=null!=d,T=l,C=s||a&&i.find.TAG("*",d&&u.parentNode||u),k=N+=null==T?1:Math.random()||.1;for(w&&(l=u!==p&&u,r=n);null!=(h=C[b]);b++){if(a&&h){g=0;while(m=e[g++])if(m(h,u,c)){f.push(h);break}w&&(N=k,r=++n)}o&&((h=!m&&h)&&v--,s&&x.push(h))}if(v+=b,o&&b!==v){g=0;while(m=t[g++])m(x,y,u,c);if(s){if(v>0)while(b--)x[b]||y[b]||(y[b]=L.call(f));y=mt(y)}H.apply(f,y),w&&!s&&y.length>0&&v+t.length>1&&st.uniqueSort(f)}return w&&(N=k,l=T),x};return o?ot(s):s}s=st.compile=function(e,t){var n,r=[],i=[],o=S[e+" "];if(!o){t||(t=ft(e)),n=t.length;while(n--)o=vt(t[n]),o[x]?r.push(o):i.push(o);o=S(e,bt(i,r))}return o};function xt(e,t,n){var r=0,i=t.length;for(;i>r;r++)st(e,t[r],n);return n}function wt(e,t,n,r){var o,a,u,l,c,p=ft(e);if(!r&&1===p.length){if(a=p[0]=p[0].slice(0),a.length>2&&"ID"===(u=a[0]).type&&9===t.nodeType&&!d&&i.relative[a[1].type]){if(t=i.find.ID(u.matches[0].replace(et,tt),t)[0],!t)return n;e=e.slice(a.shift().value.length)}o=U.needsContext.test(e)?0:a.length;while(o--){if(u=a[o],i.relative[l=u.type])break;if((c=i.find[l])&&(r=c(u.matches[0].replace(et,tt),V.test(a[0].type)&&t.parentNode||t))){if(a.splice(o,1),e=r.length&&dt(a),!e)return H.apply(n,q.call(r,0)),n;break}}}return s(e,p)(r,t,d,n,V.test(e)),n}i.pseudos.nth=i.pseudos.eq;function Tt(){}i.filters=Tt.prototype=i.pseudos,i.setFilters=new Tt,c(),st.attr=b.attr,b.find=st,b.expr=st.selectors,b.expr[":"]=b.expr.pseudos,b.unique=st.uniqueSort,b.text=st.getText,b.isXMLDoc=st.isXML,b.contains=st.contains}(e);var at=/Until$/,st=/^(?:parents|prev(?:Until|All))/,ut=/^.[^:#\[\.,]*$/,lt=b.expr.match.needsContext,ct={children:!0,contents:!0,next:!0,prev:!0};b.fn.extend({find:function(e){var t,n,r,i=this.length;if("string"!=typeof e)return r=this,this.pushStack(b(e).filter(function(){for(t=0;i>t;t++)if(b.contains(r[t],this))return!0}));for(n=[],t=0;i>t;t++)b.find(e,this[t],n);return n=this.pushStack(i>1?b.unique(n):n),n.selector=(this.selector?this.selector+" ":"")+e,n},has:function(e){var t,n=b(e,this),r=n.length;return this.filter(function(){for(t=0;r>t;t++)if(b.contains(this,n[t]))return!0})},not:function(e){return this.pushStack(ft(this,e,!1))},filter:function(e){return this.pushStack(ft(this,e,!0))},is:function(e){return!!e&&("string"==typeof e?lt.test(e)?b(e,this.context).index(this[0])>=0:b.filter(e,this).length>0:this.filter(e).length>0)},closest:function(e,t){var n,r=0,i=this.length,o=[],a=lt.test(e)||"string"!=typeof e?b(e,t||this.context):0;for(;i>r;r++){n=this[r];while(n&&n.ownerDocument&&n!==t&&11!==n.nodeType){if(a?a.index(n)>-1:b.find.matchesSelector(n,e)){o.push(n);break}n=n.parentNode}}return this.pushStack(o.length>1?b.unique(o):o)},index:function(e){return e?"string"==typeof e?b.inArray(this[0],b(e)):b.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n="string"==typeof e?b(e,t):b.makeArray(e&&e.nodeType?[e]:e),r=b.merge(this.get(),n);return this.pushStack(b.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),b.fn.andSelf=b.fn.addBack;function pt(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}b.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return b.dir(e,"parentNode")},parentsUntil:function(e,t,n){return b.dir(e,"parentNode",n)},next:function(e){return pt(e,"nextSibling")},prev:function(e){return pt(e,"previousSibling")},nextAll:function(e){return b.dir(e,"nextSibling")},prevAll:function(e){return b.dir(e,"previousSibling")},nextUntil:function(e,t,n){return b.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return b.dir(e,"previousSibling",n)},siblings:function(e){return b.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return b.sibling(e.firstChild)},contents:function(e){return b.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:b.merge([],e.childNodes)}},function(e,t){b.fn[e]=function(n,r){var i=b.map(this,t,n);return at.test(e)||(r=n),r&&"string"==typeof r&&(i=b.filter(r,i)),i=this.length>1&&!ct[e]?b.unique(i):i,this.length>1&&st.test(e)&&(i=i.reverse()),this.pushStack(i)}}),b.extend({filter:function(e,t,n){return n&&(e=":not("+e+")"),1===t.length?b.find.matchesSelector(t[0],e)?[t[0]]:[]:b.find.matches(e,t)},dir:function(e,n,r){var i=[],o=e[n];while(o&&9!==o.nodeType&&(r===t||1!==o.nodeType||!b(o).is(r)))1===o.nodeType&&i.push(o),o=o[n];return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});function ft(e,t,n){if(t=t||0,b.isFunction(t))return b.grep(e,function(e,r){var i=!!t.call(e,r,e);return i===n});if(t.nodeType)return b.grep(e,function(e){return e===t===n});if("string"==typeof t){var r=b.grep(e,function(e){return 1===e.nodeType});if(ut.test(t))return b.filter(t,r,!n);t=b.filter(t,r)}return b.grep(e,function(e){return b.inArray(e,t)>=0===n})}function dt(e){var t=ht.split("|"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}var ht="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",gt=/ jQuery\d+="(?:null|\d+)"/g,mt=RegExp("<(?:"+ht+")[\\s/>]","i"),yt=/^\s+/,vt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bt=/<([\w:]+)/,xt=/<tbody/i,wt=/<|&#?\w+;/,Tt=/<(?:script|style|link)/i,Nt=/^(?:checkbox|radio)$/i,Ct=/checked\s*(?:[^=]|=\s*.checked.)/i,kt=/^$|\/(?:java|ecma)script/i,Et=/^true\/(.*)/,St=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,At={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],area:[1,"<map>","</map>"],param:[1,"<object>","</object>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:b.support.htmlSerialize?[0,"",""]:[1,"X<div>","</div>"]},jt=dt(o),Dt=jt.appendChild(o.createElement("div"));At.optgroup=At.option,At.tbody=At.tfoot=At.colgroup=At.caption=At.thead,At.th=At.td,b.fn.extend({text:function(e){return b.access(this,function(e){return e===t?b.text(this):this.empty().append((this[0]&&this[0].ownerDocument||o).createTextNode(e))},null,e,arguments.length)},wrapAll:function(e){if(b.isFunction(e))return this.each(function(t){b(this).wrapAll(e.call(this,t))});if(this[0]){var t=b(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&1===e.firstChild.nodeType)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return b.isFunction(e)?this.each(function(t){b(this).wrapInner(e.call(this,t))}):this.each(function(){var t=b(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=b.isFunction(e);return this.each(function(n){b(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){b.nodeName(this,"body")||b(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(e){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&this.appendChild(e)})},prepend:function(){return this.domManip(arguments,!0,function(e){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&this.insertBefore(e,this.firstChild)})},before:function(){return this.domManip(arguments,!1,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,!1,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=0;for(;null!=(n=this[r]);r++)(!e||b.filter(e,[n]).length>0)&&(t||1!==n.nodeType||b.cleanData(Ot(n)),n.parentNode&&(t&&b.contains(n.ownerDocument,n)&&Mt(Ot(n,"script")),n.parentNode.removeChild(n)));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++){1===e.nodeType&&b.cleanData(Ot(e,!1));while(e.firstChild)e.removeChild(e.firstChild);e.options&&b.nodeName(e,"select")&&(e.options.length=0)}return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return b.clone(this,e,t)})},html:function(e){return b.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return 1===n.nodeType?n.innerHTML.replace(gt,""):t;if(!("string"!=typeof e||Tt.test(e)||!b.support.htmlSerialize&&mt.test(e)||!b.support.leadingWhitespace&&yt.test(e)||At[(bt.exec(e)||["",""])[1].toLowerCase()])){e=e.replace(vt,"<$1></$2>");try{for(;i>r;r++)n=this[r]||{},1===n.nodeType&&(b.cleanData(Ot(n,!1)),n.innerHTML=e);n=0}catch(o){}}n&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(e){var t=b.isFunction(e);return t||"string"==typeof e||(e=b(e).not(this).detach()),this.domManip([e],!0,function(e){var t=this.nextSibling,n=this.parentNode;n&&(b(this).remove(),n.insertBefore(e,t))})},detach:function(e){return this.remove(e,!0)},domManip:function(e,n,r){e=f.apply([],e);var i,o,a,s,u,l,c=0,p=this.length,d=this,h=p-1,g=e[0],m=b.isFunction(g);if(m||!(1>=p||"string"!=typeof g||b.support.checkClone)&&Ct.test(g))return this.each(function(i){var o=d.eq(i);m&&(e[0]=g.call(this,i,n?o.html():t)),o.domManip(e,n,r)});if(p&&(l=b.buildFragment(e,this[0].ownerDocument,!1,this),i=l.firstChild,1===l.childNodes.length&&(l=i),i)){for(n=n&&b.nodeName(i,"tr"),s=b.map(Ot(l,"script"),Ht),a=s.length;p>c;c++)o=l,c!==h&&(o=b.clone(o,!0,!0),a&&b.merge(s,Ot(o,"script"))),r.call(n&&b.nodeName(this[c],"table")?Lt(this[c],"tbody"):this[c],o,c);if(a)for(u=s[s.length-1].ownerDocument,b.map(s,qt),c=0;a>c;c++)o=s[c],kt.test(o.type||"")&&!b._data(o,"globalEval")&&b.contains(u,o)&&(o.src?b.ajax({url:o.src,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0}):b.globalEval((o.text||o.textContent||o.innerHTML||"").replace(St,"")));l=i=null}return this}});function Lt(e,t){return e.getElementsByTagName(t)[0]||e.appendChild(e.ownerDocument.createElement(t))}function Ht(e){var t=e.getAttributeNode("type");return e.type=(t&&t.specified)+"/"+e.type,e}function qt(e){var t=Et.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function Mt(e,t){var n,r=0;for(;null!=(n=e[r]);r++)b._data(n,"globalEval",!t||b._data(t[r],"globalEval"))}function _t(e,t){if(1===t.nodeType&&b.hasData(e)){var n,r,i,o=b._data(e),a=b._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;i>r;r++)b.event.add(t,n,s[n][r])}a.data&&(a.data=b.extend({},a.data))}}function Ft(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!b.support.noCloneEvent&&t[b.expando]){i=b._data(t);for(r in i.events)b.removeEvent(t,r,i.handle);t.removeAttribute(b.expando)}"script"===n&&t.text!==e.text?(Ht(t).text=e.text,qt(t)):"object"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),b.support.html5Clone&&e.innerHTML&&!b.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):"input"===n&&Nt.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):"option"===n?t.defaultSelected=t.selected=e.defaultSelected:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}}b.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){b.fn[e]=function(e){var n,r=0,i=[],o=b(e),a=o.length-1;for(;a>=r;r++)n=r===a?this:this.clone(!0),b(o[r])[t](n),d.apply(i,n.get());return this.pushStack(i)}});function Ot(e,n){var r,o,a=0,s=typeof e.getElementsByTagName!==i?e.getElementsByTagName(n||"*"):typeof e.querySelectorAll!==i?e.querySelectorAll(n||"*"):t;if(!s)for(s=[],r=e.childNodes||e;null!=(o=r[a]);a++)!n||b.nodeName(o,n)?s.push(o):b.merge(s,Ot(o,n));return n===t||n&&b.nodeName(e,n)?b.merge([e],s):s}function Bt(e){Nt.test(e.type)&&(e.defaultChecked=e.checked)}b.extend({clone:function(e,t,n){var r,i,o,a,s,u=b.contains(e.ownerDocument,e);if(b.support.html5Clone||b.isXMLDoc(e)||!mt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(Dt.innerHTML=e.outerHTML,Dt.removeChild(o=Dt.firstChild)),!(b.support.noCloneEvent&&b.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||b.isXMLDoc(e)))for(r=Ot(o),s=Ot(e),a=0;null!=(i=s[a]);++a)r[a]&&Ft(i,r[a]);if(t)if(n)for(s=s||Ot(e),r=r||Ot(o),a=0;null!=(i=s[a]);a++)_t(i,r[a]);else _t(e,o);return r=Ot(o,"script"),r.length>0&&Mt(r,!u&&Ot(e,"script")),r=s=i=null,o},buildFragment:function(e,t,n,r){var i,o,a,s,u,l,c,p=e.length,f=dt(t),d=[],h=0;for(;p>h;h++)if(o=e[h],o||0===o)if("object"===b.type(o))b.merge(d,o.nodeType?[o]:o);else if(wt.test(o)){s=s||f.appendChild(t.createElement("div")),u=(bt.exec(o)||["",""])[1].toLowerCase(),c=At[u]||At._default,s.innerHTML=c[1]+o.replace(vt,"<$1></$2>")+c[2],i=c[0];while(i--)s=s.lastChild;if(!b.support.leadingWhitespace&&yt.test(o)&&d.push(t.createTextNode(yt.exec(o)[0])),!b.support.tbody){o="table"!==u||xt.test(o)?"<table>"!==c[1]||xt.test(o)?0:s:s.firstChild,i=o&&o.childNodes.length;while(i--)b.nodeName(l=o.childNodes[i],"tbody")&&!l.childNodes.length&&o.removeChild(l) -}b.merge(d,s.childNodes),s.textContent="";while(s.firstChild)s.removeChild(s.firstChild);s=f.lastChild}else d.push(t.createTextNode(o));s&&f.removeChild(s),b.support.appendChecked||b.grep(Ot(d,"input"),Bt),h=0;while(o=d[h++])if((!r||-1===b.inArray(o,r))&&(a=b.contains(o.ownerDocument,o),s=Ot(f.appendChild(o),"script"),a&&Mt(s),n)){i=0;while(o=s[i++])kt.test(o.type||"")&&n.push(o)}return s=null,f},cleanData:function(e,t){var n,r,o,a,s=0,u=b.expando,l=b.cache,p=b.support.deleteExpando,f=b.event.special;for(;null!=(n=e[s]);s++)if((t||b.acceptData(n))&&(o=n[u],a=o&&l[o])){if(a.events)for(r in a.events)f[r]?b.event.remove(n,r):b.removeEvent(n,r,a.handle);l[o]&&(delete l[o],p?delete n[u]:typeof n.removeAttribute!==i?n.removeAttribute(u):n[u]=null,c.push(o))}}});var Pt,Rt,Wt,$t=/alpha\([^)]*\)/i,It=/opacity\s*=\s*([^)]*)/,zt=/^(top|right|bottom|left)$/,Xt=/^(none|table(?!-c[ea]).+)/,Ut=/^margin/,Vt=RegExp("^("+x+")(.*)$","i"),Yt=RegExp("^("+x+")(?!px)[a-z%]+$","i"),Jt=RegExp("^([+-])=("+x+")","i"),Gt={BODY:"block"},Qt={position:"absolute",visibility:"hidden",display:"block"},Kt={letterSpacing:0,fontWeight:400},Zt=["Top","Right","Bottom","Left"],en=["Webkit","O","Moz","ms"];function tn(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=en.length;while(i--)if(t=en[i]+n,t in e)return t;return r}function nn(e,t){return e=t||e,"none"===b.css(e,"display")||!b.contains(e.ownerDocument,e)}function rn(e,t){var n,r,i,o=[],a=0,s=e.length;for(;s>a;a++)r=e[a],r.style&&(o[a]=b._data(r,"olddisplay"),n=r.style.display,t?(o[a]||"none"!==n||(r.style.display=""),""===r.style.display&&nn(r)&&(o[a]=b._data(r,"olddisplay",un(r.nodeName)))):o[a]||(i=nn(r),(n&&"none"!==n||!i)&&b._data(r,"olddisplay",i?n:b.css(r,"display"))));for(a=0;s>a;a++)r=e[a],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[a]||"":"none"));return e}b.fn.extend({css:function(e,n){return b.access(this,function(e,n,r){var i,o,a={},s=0;if(b.isArray(n)){for(o=Rt(e),i=n.length;i>s;s++)a[n[s]]=b.css(e,n[s],!1,o);return a}return r!==t?b.style(e,n,r):b.css(e,n)},e,n,arguments.length>1)},show:function(){return rn(this,!0)},hide:function(){return rn(this)},toggle:function(e){var t="boolean"==typeof e;return this.each(function(){(t?e:nn(this))?b(this).show():b(this).hide()})}}),b.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Wt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":b.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var o,a,s,u=b.camelCase(n),l=e.style;if(n=b.cssProps[u]||(b.cssProps[u]=tn(l,u)),s=b.cssHooks[n]||b.cssHooks[u],r===t)return s&&"get"in s&&(o=s.get(e,!1,i))!==t?o:l[n];if(a=typeof r,"string"===a&&(o=Jt.exec(r))&&(r=(o[1]+1)*o[2]+parseFloat(b.css(e,n)),a="number"),!(null==r||"number"===a&&isNaN(r)||("number"!==a||b.cssNumber[u]||(r+="px"),b.support.clearCloneStyle||""!==r||0!==n.indexOf("background")||(l[n]="inherit"),s&&"set"in s&&(r=s.set(e,r,i))===t)))try{l[n]=r}catch(c){}}},css:function(e,n,r,i){var o,a,s,u=b.camelCase(n);return n=b.cssProps[u]||(b.cssProps[u]=tn(e.style,u)),s=b.cssHooks[n]||b.cssHooks[u],s&&"get"in s&&(a=s.get(e,!0,r)),a===t&&(a=Wt(e,n,i)),"normal"===a&&n in Kt&&(a=Kt[n]),""===r||r?(o=parseFloat(a),r===!0||b.isNumeric(o)?o||0:a):a},swap:function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=a[o];return i}}),e.getComputedStyle?(Rt=function(t){return e.getComputedStyle(t,null)},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),u=s?s.getPropertyValue(n)||s[n]:t,l=e.style;return s&&(""!==u||b.contains(e.ownerDocument,e)||(u=b.style(e,n)),Yt.test(u)&&Ut.test(n)&&(i=l.width,o=l.minWidth,a=l.maxWidth,l.minWidth=l.maxWidth=l.width=u,u=s.width,l.width=i,l.minWidth=o,l.maxWidth=a)),u}):o.documentElement.currentStyle&&(Rt=function(e){return e.currentStyle},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),u=s?s[n]:t,l=e.style;return null==u&&l&&l[n]&&(u=l[n]),Yt.test(u)&&!zt.test(n)&&(i=l.left,o=e.runtimeStyle,a=o&&o.left,a&&(o.left=e.currentStyle.left),l.left="fontSize"===n?"1em":u,u=l.pixelLeft+"px",l.left=i,a&&(o.left=a)),""===u?"auto":u});function on(e,t,n){var r=Vt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function an(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,a=0;for(;4>o;o+=2)"margin"===n&&(a+=b.css(e,n+Zt[o],!0,i)),r?("content"===n&&(a-=b.css(e,"padding"+Zt[o],!0,i)),"margin"!==n&&(a-=b.css(e,"border"+Zt[o]+"Width",!0,i))):(a+=b.css(e,"padding"+Zt[o],!0,i),"padding"!==n&&(a+=b.css(e,"border"+Zt[o]+"Width",!0,i)));return a}function sn(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=Rt(e),a=b.support.boxSizing&&"border-box"===b.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=Wt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Yt.test(i))return i;r=a&&(b.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+an(e,t,n||(a?"border":"content"),r,o)+"px"}function un(e){var t=o,n=Gt[e];return n||(n=ln(e,t),"none"!==n&&n||(Pt=(Pt||b("<iframe frameborder='0' width='0' height='0'/>").css("cssText","display:block !important")).appendTo(t.documentElement),t=(Pt[0].contentWindow||Pt[0].contentDocument).document,t.write("<!doctype html><html><body>"),t.close(),n=ln(e,t),Pt.detach()),Gt[e]=n),n}function ln(e,t){var n=b(t.createElement(e)).appendTo(t.body),r=b.css(n[0],"display");return n.remove(),r}b.each(["height","width"],function(e,n){b.cssHooks[n]={get:function(e,r,i){return r?0===e.offsetWidth&&Xt.test(b.css(e,"display"))?b.swap(e,Qt,function(){return sn(e,n,i)}):sn(e,n,i):t},set:function(e,t,r){var i=r&&Rt(e);return on(e,t,r?an(e,n,r,b.support.boxSizing&&"border-box"===b.css(e,"boxSizing",!1,i),i):0)}}}),b.support.opacity||(b.cssHooks.opacity={get:function(e,t){return It.test((t&&e.currentStyle?e.currentStyle.filter:e.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":t?"1":""},set:function(e,t){var n=e.style,r=e.currentStyle,i=b.isNumeric(t)?"alpha(opacity="+100*t+")":"",o=r&&r.filter||n.filter||"";n.zoom=1,(t>=1||""===t)&&""===b.trim(o.replace($t,""))&&n.removeAttribute&&(n.removeAttribute("filter"),""===t||r&&!r.filter)||(n.filter=$t.test(o)?o.replace($t,i):o+" "+i)}}),b(function(){b.support.reliableMarginRight||(b.cssHooks.marginRight={get:function(e,n){return n?b.swap(e,{display:"inline-block"},Wt,[e,"marginRight"]):t}}),!b.support.pixelPosition&&b.fn.position&&b.each(["top","left"],function(e,n){b.cssHooks[n]={get:function(e,r){return r?(r=Wt(e,n),Yt.test(r)?b(e).position()[n]+"px":r):t}}})}),b.expr&&b.expr.filters&&(b.expr.filters.hidden=function(e){return 0>=e.offsetWidth&&0>=e.offsetHeight||!b.support.reliableHiddenOffsets&&"none"===(e.style&&e.style.display||b.css(e,"display"))},b.expr.filters.visible=function(e){return!b.expr.filters.hidden(e)}),b.each({margin:"",padding:"",border:"Width"},function(e,t){b.cssHooks[e+t]={expand:function(n){var r=0,i={},o="string"==typeof n?n.split(" "):[n];for(;4>r;r++)i[e+Zt[r]+t]=o[r]||o[r-2]||o[0];return i}},Ut.test(e)||(b.cssHooks[e+t].set=on)});var cn=/%20/g,pn=/\[\]$/,fn=/\r?\n/g,dn=/^(?:submit|button|image|reset|file)$/i,hn=/^(?:input|select|textarea|keygen)/i;b.fn.extend({serialize:function(){return b.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=b.prop(this,"elements");return e?b.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!b(this).is(":disabled")&&hn.test(this.nodeName)&&!dn.test(e)&&(this.checked||!Nt.test(e))}).map(function(e,t){var n=b(this).val();return null==n?null:b.isArray(n)?b.map(n,function(e){return{name:t.name,value:e.replace(fn,"\r\n")}}):{name:t.name,value:n.replace(fn,"\r\n")}}).get()}}),b.param=function(e,n){var r,i=[],o=function(e,t){t=b.isFunction(t)?t():null==t?"":t,i[i.length]=encodeURIComponent(e)+"="+encodeURIComponent(t)};if(n===t&&(n=b.ajaxSettings&&b.ajaxSettings.traditional),b.isArray(e)||e.jquery&&!b.isPlainObject(e))b.each(e,function(){o(this.name,this.value)});else for(r in e)gn(r,e[r],n,o);return i.join("&").replace(cn,"+")};function gn(e,t,n,r){var i;if(b.isArray(t))b.each(t,function(t,i){n||pn.test(e)?r(e,i):gn(e+"["+("object"==typeof i?t:"")+"]",i,n,r)});else if(n||"object"!==b.type(t))r(e,t);else for(i in t)gn(e+"["+i+"]",t[i],n,r)}b.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(e,t){b.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),b.fn.hover=function(e,t){return this.mouseenter(e).mouseleave(t||e)};var mn,yn,vn=b.now(),bn=/\?/,xn=/#.*$/,wn=/([?&])_=[^&]*/,Tn=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Nn=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Cn=/^(?:GET|HEAD)$/,kn=/^\/\//,En=/^([\w.+-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,Sn=b.fn.load,An={},jn={},Dn="*/".concat("*");try{yn=a.href}catch(Ln){yn=o.createElement("a"),yn.href="",yn=yn.href}mn=En.exec(yn.toLowerCase())||[];function Hn(e){return function(t,n){"string"!=typeof t&&(n=t,t="*");var r,i=0,o=t.toLowerCase().match(w)||[];if(b.isFunction(n))while(r=o[i++])"+"===r[0]?(r=r.slice(1)||"*",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function qn(e,n,r,i){var o={},a=e===jn;function s(u){var l;return o[u]=!0,b.each(e[u]||[],function(e,u){var c=u(n,r,i);return"string"!=typeof c||a||o[c]?a?!(l=c):t:(n.dataTypes.unshift(c),s(c),!1)}),l}return s(n.dataTypes[0])||!o["*"]&&s("*")}function Mn(e,n){var r,i,o=b.ajaxSettings.flatOptions||{};for(i in n)n[i]!==t&&((o[i]?e:r||(r={}))[i]=n[i]);return r&&b.extend(!0,e,r),e}b.fn.load=function(e,n,r){if("string"!=typeof e&&Sn)return Sn.apply(this,arguments);var i,o,a,s=this,u=e.indexOf(" ");return u>=0&&(i=e.slice(u,e.length),e=e.slice(0,u)),b.isFunction(n)?(r=n,n=t):n&&"object"==typeof n&&(a="POST"),s.length>0&&b.ajax({url:e,type:a,dataType:"html",data:n}).done(function(e){o=arguments,s.html(i?b("<div>").append(b.parseHTML(e)).find(i):e)}).complete(r&&function(e,t){s.each(r,o||[e.responseText,t,e])}),this},b.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){b.fn[t]=function(e){return this.on(t,e)}}),b.each(["get","post"],function(e,n){b[n]=function(e,r,i,o){return b.isFunction(r)&&(o=o||i,i=r,r=t),b.ajax({url:e,type:n,dataType:o,data:r,success:i})}}),b.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:yn,type:"GET",isLocal:Nn.test(mn[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Dn,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":e.String,"text html":!0,"text json":b.parseJSON,"text xml":b.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?Mn(Mn(e,b.ajaxSettings),t):Mn(b.ajaxSettings,e)},ajaxPrefilter:Hn(An),ajaxTransport:Hn(jn),ajax:function(e,n){"object"==typeof e&&(n=e,e=t),n=n||{};var r,i,o,a,s,u,l,c,p=b.ajaxSetup({},n),f=p.context||p,d=p.context&&(f.nodeType||f.jquery)?b(f):b.event,h=b.Deferred(),g=b.Callbacks("once memory"),m=p.statusCode||{},y={},v={},x=0,T="canceled",N={readyState:0,getResponseHeader:function(e){var t;if(2===x){if(!c){c={};while(t=Tn.exec(a))c[t[1].toLowerCase()]=t[2]}t=c[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return 2===x?a:null},setRequestHeader:function(e,t){var n=e.toLowerCase();return x||(e=v[n]=v[n]||e,y[e]=t),this},overrideMimeType:function(e){return x||(p.mimeType=e),this},statusCode:function(e){var t;if(e)if(2>x)for(t in e)m[t]=[m[t],e[t]];else N.always(e[N.status]);return this},abort:function(e){var t=e||T;return l&&l.abort(t),k(0,t),this}};if(h.promise(N).complete=g.add,N.success=N.done,N.error=N.fail,p.url=((e||p.url||yn)+"").replace(xn,"").replace(kn,mn[1]+"//"),p.type=n.method||n.type||p.method||p.type,p.dataTypes=b.trim(p.dataType||"*").toLowerCase().match(w)||[""],null==p.crossDomain&&(r=En.exec(p.url.toLowerCase()),p.crossDomain=!(!r||r[1]===mn[1]&&r[2]===mn[2]&&(r[3]||("http:"===r[1]?80:443))==(mn[3]||("http:"===mn[1]?80:443)))),p.data&&p.processData&&"string"!=typeof p.data&&(p.data=b.param(p.data,p.traditional)),qn(An,p,n,N),2===x)return N;u=p.global,u&&0===b.active++&&b.event.trigger("ajaxStart"),p.type=p.type.toUpperCase(),p.hasContent=!Cn.test(p.type),o=p.url,p.hasContent||(p.data&&(o=p.url+=(bn.test(o)?"&":"?")+p.data,delete p.data),p.cache===!1&&(p.url=wn.test(o)?o.replace(wn,"$1_="+vn++):o+(bn.test(o)?"&":"?")+"_="+vn++)),p.ifModified&&(b.lastModified[o]&&N.setRequestHeader("If-Modified-Since",b.lastModified[o]),b.etag[o]&&N.setRequestHeader("If-None-Match",b.etag[o])),(p.data&&p.hasContent&&p.contentType!==!1||n.contentType)&&N.setRequestHeader("Content-Type",p.contentType),N.setRequestHeader("Accept",p.dataTypes[0]&&p.accepts[p.dataTypes[0]]?p.accepts[p.dataTypes[0]]+("*"!==p.dataTypes[0]?", "+Dn+"; q=0.01":""):p.accepts["*"]);for(i in p.headers)N.setRequestHeader(i,p.headers[i]);if(p.beforeSend&&(p.beforeSend.call(f,N,p)===!1||2===x))return N.abort();T="abort";for(i in{success:1,error:1,complete:1})N[i](p[i]);if(l=qn(jn,p,n,N)){N.readyState=1,u&&d.trigger("ajaxSend",[N,p]),p.async&&p.timeout>0&&(s=setTimeout(function(){N.abort("timeout")},p.timeout));try{x=1,l.send(y,k)}catch(C){if(!(2>x))throw C;k(-1,C)}}else k(-1,"No Transport");function k(e,n,r,i){var c,y,v,w,T,C=n;2!==x&&(x=2,s&&clearTimeout(s),l=t,a=i||"",N.readyState=e>0?4:0,r&&(w=_n(p,N,r)),e>=200&&300>e||304===e?(p.ifModified&&(T=N.getResponseHeader("Last-Modified"),T&&(b.lastModified[o]=T),T=N.getResponseHeader("etag"),T&&(b.etag[o]=T)),204===e?(c=!0,C="nocontent"):304===e?(c=!0,C="notmodified"):(c=Fn(p,w),C=c.state,y=c.data,v=c.error,c=!v)):(v=C,(e||!C)&&(C="error",0>e&&(e=0))),N.status=e,N.statusText=(n||C)+"",c?h.resolveWith(f,[y,C,N]):h.rejectWith(f,[N,C,v]),N.statusCode(m),m=t,u&&d.trigger(c?"ajaxSuccess":"ajaxError",[N,p,c?y:v]),g.fireWith(f,[N,C]),u&&(d.trigger("ajaxComplete",[N,p]),--b.active||b.event.trigger("ajaxStop")))}return N},getScript:function(e,n){return b.get(e,t,n,"script")},getJSON:function(e,t,n){return b.get(e,t,n,"json")}});function _n(e,n,r){var i,o,a,s,u=e.contents,l=e.dataTypes,c=e.responseFields;for(s in c)s in r&&(n[c[s]]=r[s]);while("*"===l[0])l.shift(),o===t&&(o=e.mimeType||n.getResponseHeader("Content-Type"));if(o)for(s in u)if(u[s]&&u[s].test(o)){l.unshift(s);break}if(l[0]in r)a=l[0];else{for(s in r){if(!l[0]||e.converters[s+" "+l[0]]){a=s;break}i||(i=s)}a=a||i}return a?(a!==l[0]&&l.unshift(a),r[a]):t}function Fn(e,t){var n,r,i,o,a={},s=0,u=e.dataTypes.slice(),l=u[0];if(e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u[1])for(i in e.converters)a[i.toLowerCase()]=e.converters[i];for(;r=u[++s];)if("*"!==r){if("*"!==l&&l!==r){if(i=a[l+" "+r]||a["* "+r],!i)for(n in a)if(o=n.split(" "),o[1]===r&&(i=a[l+" "+o[0]]||a["* "+o[0]])){i===!0?i=a[n]:a[n]!==!0&&(r=o[0],u.splice(s--,0,r));break}if(i!==!0)if(i&&e["throws"])t=i(t);else try{t=i(t)}catch(c){return{state:"parsererror",error:i?c:"No conversion from "+l+" to "+r}}}l=r}return{state:"success",data:t}}b.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(e){return b.globalEval(e),e}}}),b.ajaxPrefilter("script",function(e){e.cache===t&&(e.cache=!1),e.crossDomain&&(e.type="GET",e.global=!1)}),b.ajaxTransport("script",function(e){if(e.crossDomain){var n,r=o.head||b("head")[0]||o.documentElement;return{send:function(t,i){n=o.createElement("script"),n.async=!0,e.scriptCharset&&(n.charset=e.scriptCharset),n.src=e.url,n.onload=n.onreadystatechange=function(e,t){(t||!n.readyState||/loaded|complete/.test(n.readyState))&&(n.onload=n.onreadystatechange=null,n.parentNode&&n.parentNode.removeChild(n),n=null,t||i(200,"success"))},r.insertBefore(n,r.firstChild)},abort:function(){n&&n.onload(t,!0)}}}});var On=[],Bn=/(=)\?(?=&|$)|\?\?/;b.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=On.pop()||b.expando+"_"+vn++;return this[e]=!0,e}}),b.ajaxPrefilter("json jsonp",function(n,r,i){var o,a,s,u=n.jsonp!==!1&&(Bn.test(n.url)?"url":"string"==typeof n.data&&!(n.contentType||"").indexOf("application/x-www-form-urlencoded")&&Bn.test(n.data)&&"data");return u||"jsonp"===n.dataTypes[0]?(o=n.jsonpCallback=b.isFunction(n.jsonpCallback)?n.jsonpCallback():n.jsonpCallback,u?n[u]=n[u].replace(Bn,"$1"+o):n.jsonp!==!1&&(n.url+=(bn.test(n.url)?"&":"?")+n.jsonp+"="+o),n.converters["script json"]=function(){return s||b.error(o+" was not called"),s[0]},n.dataTypes[0]="json",a=e[o],e[o]=function(){s=arguments},i.always(function(){e[o]=a,n[o]&&(n.jsonpCallback=r.jsonpCallback,On.push(o)),s&&b.isFunction(a)&&a(s[0]),s=a=t}),"script"):t});var Pn,Rn,Wn=0,$n=e.ActiveXObject&&function(){var e;for(e in Pn)Pn[e](t,!0)};function In(){try{return new e.XMLHttpRequest}catch(t){}}function zn(){try{return new e.ActiveXObject("Microsoft.XMLHTTP")}catch(t){}}b.ajaxSettings.xhr=e.ActiveXObject?function(){return!this.isLocal&&In()||zn()}:In,Rn=b.ajaxSettings.xhr(),b.support.cors=!!Rn&&"withCredentials"in Rn,Rn=b.support.ajax=!!Rn,Rn&&b.ajaxTransport(function(n){if(!n.crossDomain||b.support.cors){var r;return{send:function(i,o){var a,s,u=n.xhr();if(n.username?u.open(n.type,n.url,n.async,n.username,n.password):u.open(n.type,n.url,n.async),n.xhrFields)for(s in n.xhrFields)u[s]=n.xhrFields[s];n.mimeType&&u.overrideMimeType&&u.overrideMimeType(n.mimeType),n.crossDomain||i["X-Requested-With"]||(i["X-Requested-With"]="XMLHttpRequest");try{for(s in i)u.setRequestHeader(s,i[s])}catch(l){}u.send(n.hasContent&&n.data||null),r=function(e,i){var s,l,c,p;try{if(r&&(i||4===u.readyState))if(r=t,a&&(u.onreadystatechange=b.noop,$n&&delete Pn[a]),i)4!==u.readyState&&u.abort();else{p={},s=u.status,l=u.getAllResponseHeaders(),"string"==typeof u.responseText&&(p.text=u.responseText);try{c=u.statusText}catch(f){c=""}s||!n.isLocal||n.crossDomain?1223===s&&(s=204):s=p.text?200:404}}catch(d){i||o(-1,d)}p&&o(s,c,p,l)},n.async?4===u.readyState?setTimeout(r):(a=++Wn,$n&&(Pn||(Pn={},b(e).unload($n)),Pn[a]=r),u.onreadystatechange=r):r()},abort:function(){r&&r(t,!0)}}}});var Xn,Un,Vn=/^(?:toggle|show|hide)$/,Yn=RegExp("^(?:([+-])=|)("+x+")([a-z%]*)$","i"),Jn=/queueHooks$/,Gn=[nr],Qn={"*":[function(e,t){var n,r,i=this.createTween(e,t),o=Yn.exec(t),a=i.cur(),s=+a||0,u=1,l=20;if(o){if(n=+o[2],r=o[3]||(b.cssNumber[e]?"":"px"),"px"!==r&&s){s=b.css(i.elem,e,!0)||n||1;do u=u||".5",s/=u,b.style(i.elem,e,s+r);while(u!==(u=i.cur()/a)&&1!==u&&--l)}i.unit=r,i.start=s,i.end=o[1]?s+(o[1]+1)*n:n}return i}]};function Kn(){return setTimeout(function(){Xn=t}),Xn=b.now()}function Zn(e,t){b.each(t,function(t,n){var r=(Qn[t]||[]).concat(Qn["*"]),i=0,o=r.length;for(;o>i;i++)if(r[i].call(e,t,n))return})}function er(e,t,n){var r,i,o=0,a=Gn.length,s=b.Deferred().always(function(){delete u.elem}),u=function(){if(i)return!1;var t=Xn||Kn(),n=Math.max(0,l.startTime+l.duration-t),r=n/l.duration||0,o=1-r,a=0,u=l.tweens.length;for(;u>a;a++)l.tweens[a].run(o);return s.notifyWith(e,[l,o,n]),1>o&&u?n:(s.resolveWith(e,[l]),!1)},l=s.promise({elem:e,props:b.extend({},t),opts:b.extend(!0,{specialEasing:{}},n),originalProperties:t,originalOptions:n,startTime:Xn||Kn(),duration:n.duration,tweens:[],createTween:function(t,n){var r=b.Tween(e,l.opts,t,n,l.opts.specialEasing[t]||l.opts.easing);return l.tweens.push(r),r},stop:function(t){var n=0,r=t?l.tweens.length:0;if(i)return this;for(i=!0;r>n;n++)l.tweens[n].run(1);return t?s.resolveWith(e,[l,t]):s.rejectWith(e,[l,t]),this}}),c=l.props;for(tr(c,l.opts.specialEasing);a>o;o++)if(r=Gn[o].call(l,e,c,l.opts))return r;return Zn(l,c),b.isFunction(l.opts.start)&&l.opts.start.call(e,l),b.fx.timer(b.extend(u,{elem:e,anim:l,queue:l.opts.queue})),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always)}function tr(e,t){var n,r,i,o,a;for(i in e)if(r=b.camelCase(i),o=t[r],n=e[i],b.isArray(n)&&(o=n[1],n=e[i]=n[0]),i!==r&&(e[r]=n,delete e[i]),a=b.cssHooks[r],a&&"expand"in a){n=a.expand(n),delete e[r];for(i in n)i in e||(e[i]=n[i],t[i]=o)}else t[r]=o}b.Animation=b.extend(er,{tweener:function(e,t){b.isFunction(e)?(t=e,e=["*"]):e=e.split(" ");var n,r=0,i=e.length;for(;i>r;r++)n=e[r],Qn[n]=Qn[n]||[],Qn[n].unshift(t)},prefilter:function(e,t){t?Gn.unshift(e):Gn.push(e)}});function nr(e,t,n){var r,i,o,a,s,u,l,c,p,f=this,d=e.style,h={},g=[],m=e.nodeType&&nn(e);n.queue||(c=b._queueHooks(e,"fx"),null==c.unqueued&&(c.unqueued=0,p=c.empty.fire,c.empty.fire=function(){c.unqueued||p()}),c.unqueued++,f.always(function(){f.always(function(){c.unqueued--,b.queue(e,"fx").length||c.empty.fire()})})),1===e.nodeType&&("height"in t||"width"in t)&&(n.overflow=[d.overflow,d.overflowX,d.overflowY],"inline"===b.css(e,"display")&&"none"===b.css(e,"float")&&(b.support.inlineBlockNeedsLayout&&"inline"!==un(e.nodeName)?d.zoom=1:d.display="inline-block")),n.overflow&&(d.overflow="hidden",b.support.shrinkWrapBlocks||f.always(function(){d.overflow=n.overflow[0],d.overflowX=n.overflow[1],d.overflowY=n.overflow[2]}));for(i in t)if(a=t[i],Vn.exec(a)){if(delete t[i],u=u||"toggle"===a,a===(m?"hide":"show"))continue;g.push(i)}if(o=g.length){s=b._data(e,"fxshow")||b._data(e,"fxshow",{}),"hidden"in s&&(m=s.hidden),u&&(s.hidden=!m),m?b(e).show():f.done(function(){b(e).hide()}),f.done(function(){var t;b._removeData(e,"fxshow");for(t in h)b.style(e,t,h[t])});for(i=0;o>i;i++)r=g[i],l=f.createTween(r,m?s[r]:0),h[r]=s[r]||b.style(e,r),r in s||(s[r]=l.start,m&&(l.end=l.start,l.start="width"===r||"height"===r?1:0))}}function rr(e,t,n,r,i){return new rr.prototype.init(e,t,n,r,i)}b.Tween=rr,rr.prototype={constructor:rr,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||"swing",this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(b.cssNumber[n]?"":"px")},cur:function(){var e=rr.propHooks[this.prop];return e&&e.get?e.get(this):rr.propHooks._default.get(this)},run:function(e){var t,n=rr.propHooks[this.prop];return this.pos=t=this.options.duration?b.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):rr.propHooks._default.set(this),this}},rr.prototype.init.prototype=rr.prototype,rr.propHooks={_default:{get:function(e){var t;return null==e.elem[e.prop]||e.elem.style&&null!=e.elem.style[e.prop]?(t=b.css(e.elem,e.prop,""),t&&"auto"!==t?t:0):e.elem[e.prop]},set:function(e){b.fx.step[e.prop]?b.fx.step[e.prop](e):e.elem.style&&(null!=e.elem.style[b.cssProps[e.prop]]||b.cssHooks[e.prop])?b.style(e.elem,e.prop,e.now+e.unit):e.elem[e.prop]=e.now}}},rr.propHooks.scrollTop=rr.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},b.each(["toggle","show","hide"],function(e,t){var n=b.fn[t];b.fn[t]=function(e,r,i){return null==e||"boolean"==typeof e?n.apply(this,arguments):this.animate(ir(t,!0),e,r,i)}}),b.fn.extend({fadeTo:function(e,t,n,r){return this.filter(nn).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=b.isEmptyObject(e),o=b.speed(t,n,r),a=function(){var t=er(this,b.extend({},e),o);a.finish=function(){t.stop(!0)},(i||b._data(this,"finish"))&&t.stop(!0)};return a.finish=a,i||o.queue===!1?this.each(a):this.queue(o.queue,a)},stop:function(e,n,r){var i=function(e){var t=e.stop;delete e.stop,t(r)};return"string"!=typeof e&&(r=n,n=e,e=t),n&&e!==!1&&this.queue(e||"fx",[]),this.each(function(){var t=!0,n=null!=e&&e+"queueHooks",o=b.timers,a=b._data(this);if(n)a[n]&&a[n].stop&&i(a[n]);else for(n in a)a[n]&&a[n].stop&&Jn.test(n)&&i(a[n]);for(n=o.length;n--;)o[n].elem!==this||null!=e&&o[n].queue!==e||(o[n].anim.stop(r),t=!1,o.splice(n,1));(t||!r)&&b.dequeue(this,e)})},finish:function(e){return e!==!1&&(e=e||"fx"),this.each(function(){var t,n=b._data(this),r=n[e+"queue"],i=n[e+"queueHooks"],o=b.timers,a=r?r.length:0;for(n.finish=!0,b.queue(this,e,[]),i&&i.cur&&i.cur.finish&&i.cur.finish.call(this),t=o.length;t--;)o[t].elem===this&&o[t].queue===e&&(o[t].anim.stop(!0),o.splice(t,1));for(t=0;a>t;t++)r[t]&&r[t].finish&&r[t].finish.call(this);delete n.finish})}});function ir(e,t){var n,r={height:e},i=0;for(t=t?1:0;4>i;i+=2-t)n=Zt[i],r["margin"+n]=r["padding"+n]=e;return t&&(r.opacity=r.width=e),r}b.each({slideDown:ir("show"),slideUp:ir("hide"),slideToggle:ir("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,t){b.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),b.speed=function(e,t,n){var r=e&&"object"==typeof e?b.extend({},e):{complete:n||!n&&t||b.isFunction(e)&&e,duration:e,easing:n&&t||t&&!b.isFunction(t)&&t};return r.duration=b.fx.off?0:"number"==typeof r.duration?r.duration:r.duration in b.fx.speeds?b.fx.speeds[r.duration]:b.fx.speeds._default,(null==r.queue||r.queue===!0)&&(r.queue="fx"),r.old=r.complete,r.complete=function(){b.isFunction(r.old)&&r.old.call(this),r.queue&&b.dequeue(this,r.queue)},r},b.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2}},b.timers=[],b.fx=rr.prototype.init,b.fx.tick=function(){var e,n=b.timers,r=0;for(Xn=b.now();n.length>r;r++)e=n[r],e()||n[r]!==e||n.splice(r--,1);n.length||b.fx.stop(),Xn=t},b.fx.timer=function(e){e()&&b.timers.push(e)&&b.fx.start()},b.fx.interval=13,b.fx.start=function(){Un||(Un=setInterval(b.fx.tick,b.fx.interval))},b.fx.stop=function(){clearInterval(Un),Un=null},b.fx.speeds={slow:600,fast:200,_default:400},b.fx.step={},b.expr&&b.expr.filters&&(b.expr.filters.animated=function(e){return b.grep(b.timers,function(t){return e===t.elem}).length}),b.fn.offset=function(e){if(arguments.length)return e===t?this:this.each(function(t){b.offset.setOffset(this,e,t)});var n,r,o={top:0,left:0},a=this[0],s=a&&a.ownerDocument;if(s)return n=s.documentElement,b.contains(n,a)?(typeof a.getBoundingClientRect!==i&&(o=a.getBoundingClientRect()),r=or(s),{top:o.top+(r.pageYOffset||n.scrollTop)-(n.clientTop||0),left:o.left+(r.pageXOffset||n.scrollLeft)-(n.clientLeft||0)}):o},b.offset={setOffset:function(e,t,n){var r=b.css(e,"position");"static"===r&&(e.style.position="relative");var i=b(e),o=i.offset(),a=b.css(e,"top"),s=b.css(e,"left"),u=("absolute"===r||"fixed"===r)&&b.inArray("auto",[a,s])>-1,l={},c={},p,f;u?(c=i.position(),p=c.top,f=c.left):(p=parseFloat(a)||0,f=parseFloat(s)||0),b.isFunction(t)&&(t=t.call(e,n,o)),null!=t.top&&(l.top=t.top-o.top+p),null!=t.left&&(l.left=t.left-o.left+f),"using"in t?t.using.call(e,l):i.css(l)}},b.fn.extend({position:function(){if(this[0]){var e,t,n={top:0,left:0},r=this[0];return"fixed"===b.css(r,"position")?t=r.getBoundingClientRect():(e=this.offsetParent(),t=this.offset(),b.nodeName(e[0],"html")||(n=e.offset()),n.top+=b.css(e[0],"borderTopWidth",!0),n.left+=b.css(e[0],"borderLeftWidth",!0)),{top:t.top-n.top-b.css(r,"marginTop",!0),left:t.left-n.left-b.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||o.documentElement;while(e&&!b.nodeName(e,"html")&&"static"===b.css(e,"position"))e=e.offsetParent;return e||o.documentElement})}}),b.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(e,n){var r=/Y/.test(n);b.fn[e]=function(i){return b.access(this,function(e,i,o){var a=or(e);return o===t?a?n in a?a[n]:a.document.documentElement[i]:e[i]:(a?a.scrollTo(r?b(a).scrollLeft():o,r?o:b(a).scrollTop()):e[i]=o,t)},e,i,arguments.length,null)}});function or(e){return b.isWindow(e)?e:9===e.nodeType?e.defaultView||e.parentWindow:!1}b.each({Height:"height",Width:"width"},function(e,n){b.each({padding:"inner"+e,content:n,"":"outer"+e},function(r,i){b.fn[i]=function(i,o){var a=arguments.length&&(r||"boolean"!=typeof i),s=r||(i===!0||o===!0?"margin":"border");return b.access(this,function(n,r,i){var o;return b.isWindow(n)?n.document.documentElement["client"+e]:9===n.nodeType?(o=n.documentElement,Math.max(n.body["scroll"+e],o["scroll"+e],n.body["offset"+e],o["offset"+e],o["client"+e])):i===t?b.css(n,r,s):b.style(n,r,i,s)},n,a?i:t,a,null)}})}),e.jQuery=e.$=b,"function"==typeof define&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return b})})(window); diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/jquery.min.map b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/jquery.min.map @@ -1 +0,0 @@ -{"version":3,"file":"jquery.min.js","sources":["jquery.js"],"names":["window","undefined","readyList","rootjQuery","core_strundefined","document","location","_jQuery","jQuery","_$","$","class2type","core_deletedIds","core_version","core_concat","concat","core_push","push","core_slice","slice","core_indexOf","indexOf","core_toString","toString","core_hasOwn","hasOwnProperty","core_trim","trim","selector","context","fn","init","core_pnum","source","core_rnotwhite","rtrim","rquickExpr","rsingleTag","rvalidchars","rvalidbraces","rvalidescape","rvalidtokens","rmsPrefix","rdashAlpha","fcamelCase","all","letter","toUpperCase","completed","event","addEventListener","type","readyState","detach","ready","removeEventListener","detachEvent","prototype","jquery","constructor","match","elem","this","charAt","length","exec","find","merge","parseHTML","nodeType","ownerDocument","test","isPlainObject","isFunction","attr","getElementById","parentNode","id","makeArray","size","toArray","call","get","num","pushStack","elems","ret","prevObject","each","callback","args","promise","done","apply","arguments","first","eq","last","i","len","j","map","end","sort","splice","extend","src","copyIsArray","copy","name","options","clone","target","deep","isArray","noConflict","isReady","readyWait","holdReady","hold","wait","body","setTimeout","resolveWith","trigger","off","obj","Array","isWindow","isNumeric","isNaN","parseFloat","isFinite","String","e","key","isEmptyObject","error","msg","Error","data","keepScripts","parsed","scripts","createElement","buildFragment","remove","childNodes","parseJSON","JSON","parse","replace","Function","parseXML","xml","tmp","DOMParser","parseFromString","ActiveXObject","async","loadXML","documentElement","getElementsByTagName","noop","globalEval","execScript","camelCase","string","nodeName","toLowerCase","value","isArraylike","text","arr","results","Object","inArray","Math","max","second","l","grep","inv","retVal","arg","guid","proxy","access","chainable","emptyGet","raw","bulk","now","Date","getTime","Deferred","attachEvent","top","frameElement","doScroll","doScrollCheck","split","optionsCache","createOptions","object","_","flag","Callbacks","firing","memory","fired","firingLength","firingIndex","firingStart","list","stack","once","fire","stopOnFalse","shift","self","disable","add","start","unique","has","index","empty","disabled","lock","locked","fireWith","func","tuples","state","always","deferred","fail","then","fns","newDefer","tuple","action","returned","resolve","reject","progress","notify","pipe","stateString","when","subordinate","resolveValues","remaining","updateFunc","contexts","values","progressValues","notifyWith","progressContexts","resolveContexts","support","a","input","select","fragment","opt","eventName","isSupported","div","setAttribute","innerHTML","appendChild","style","cssText","getSetAttribute","className","leadingWhitespace","firstChild","tbody","htmlSerialize","getAttribute","hrefNormalized","opacity","cssFloat","checkOn","optSelected","selected","enctype","html5Clone","cloneNode","outerHTML","boxModel","compatMode","deleteExpando","noCloneEvent","inlineBlockNeedsLayout","shrinkWrapBlocks","reliableMarginRight","boxSizingReliable","pixelPosition","checked","noCloneChecked","optDisabled","radioValue","createDocumentFragment","appendChecked","checkClone","lastChild","click","submit","change","focusin","attributes","expando","backgroundClip","clearCloneStyle","container","marginDiv","tds","divReset","offsetHeight","display","reliableHiddenOffsets","boxSizing","offsetWidth","doesNotIncludeMarginInBodyOffset","offsetTop","getComputedStyle","width","marginRight","zoom","removeChild","rbrace","rmultiDash","internalData","pvt","acceptData","thisCache","internalKey","getByName","isNode","cache","pop","toJSON","internalRemoveData","isEmptyDataObject","cleanData","random","noData","embed","applet","hasData","removeData","_data","_removeData","attrs","dataAttr","queue","dequeue","startLength","hooks","_queueHooks","next","cur","unshift","stop","setter","delay","time","fx","speeds","timeout","clearTimeout","clearQueue","count","defer","elements","nodeHook","boolHook","rclass","rreturn","rfocusable","rclickable","rboolean","ruseDefault","getSetInput","removeAttr","prop","removeProp","propFix","addClass","classes","clazz","proceed","removeClass","toggleClass","stateVal","isBool","classNames","hasClass","val","valHooks","set","option","specified","selectedIndex","one","notxml","nType","isXMLDoc","attrHooks","propName","attrNames","removeAttribute","tabindex","readonly","for","class","maxlength","cellspacing","cellpadding","rowspan","colspan","usemap","frameborder","contenteditable","propHooks","tabIndex","attributeNode","getAttributeNode","parseInt","href","detail","defaultValue","button","setAttributeNode","createAttribute","parent","rformElems","rkeyEvent","rmouseEvent","rfocusMorph","rtypenamespace","returnTrue","returnFalse","global","types","handler","events","t","handleObjIn","special","eventHandle","handleObj","handlers","namespaces","origType","elemData","handle","triggered","dispatch","delegateType","bindType","needsContext","expr","namespace","join","delegateCount","setup","mappedTypes","origCount","RegExp","teardown","removeEvent","onlyHandlers","ontype","bubbleType","eventPath","Event","isTrigger","namespace_re","result","noBubble","defaultView","parentWindow","isPropagationStopped","preventDefault","isDefaultPrevented","_default","fix","matched","handlerQueue","delegateTarget","preDispatch","currentTarget","isImmediatePropagationStopped","stopPropagation","postDispatch","sel","matches","originalEvent","fixHook","fixHooks","mouseHooks","keyHooks","props","srcElement","metaKey","filter","original","which","charCode","keyCode","eventDoc","doc","fromElement","pageX","clientX","scrollLeft","clientLeft","pageY","clientY","scrollTop","clientTop","relatedTarget","toElement","load","focus","activeElement","blur","beforeunload","returnValue","simulate","bubble","isSimulated","defaultPrevented","getPreventDefault","timeStamp","cancelBubble","stopImmediatePropagation","mouseenter","mouseleave","orig","related","contains","submitBubbles","form","_submit_bubble","changeBubbles","propertyName","_just_changed","focusinBubbles","attaches","on","origFn","bind","unbind","delegate","undelegate","triggerHandler","cachedruns","Expr","getText","isXML","compile","hasDuplicate","outermostContext","setDocument","docElem","documentIsXML","rbuggyQSA","rbuggyMatches","sortOrder","preferredDoc","dirruns","classCache","createCache","tokenCache","compilerCache","strundefined","MAX_NEGATIVE","whitespace","characterEncoding","identifier","operators","pseudos","rcomma","rcombinators","rpseudo","ridentifier","matchExpr","ID","CLASS","NAME","TAG","ATTR","PSEUDO","CHILD","rsibling","rnative","rinputs","rheader","rescape","rattributeQuotes","runescape","funescape","escaped","high","fromCharCode","isNative","keys","cacheLength","markFunction","assert","Sizzle","seed","m","groups","old","nid","newContext","newSelector","getByClassName","getElementsByClassName","qsa","tokenize","toSelector","querySelectorAll","qsaError","node","tagNameNoComments","createComment","insertBefore","pass","getElementsByName","getIdNotName","attrHandle","attrId","tag","matchesSelector","mozMatchesSelector","webkitMatchesSelector","oMatchesSelector","msMatchesSelector","disconnectedMatch","compareDocumentPosition","b","adown","bup","compare","aup","ap","bp","siblingCheck","detectDuplicates","uniqueSort","duplicates","diff","sourceIndex","nextSibling","createInputPseudo","createButtonPseudo","createPositionalPseudo","argument","matchIndexes","textContent","nodeValue","selectors","createPseudo","relative",">","dir"," ","+","~","preFilter","excess","unquoted","pattern","operator","check","what","simple","forward","ofType","outerCache","nodeIndex","useCache","pseudo","setFilters","idx","not","matcher","unmatched","innerText","lang","elemLang","hash","root","hasFocus","enabled","header","even","odd","lt","gt","radio","checkbox","file","password","image","reset","parseOnly","tokens","soFar","preFilters","cached","addCombinator","combinator","base","checkNonElements","doneName","dirkey","elementMatcher","matchers","condense","newUnmatched","mapped","setMatcher","postFilter","postFinder","postSelector","temp","preMap","postMap","preexisting","multipleContexts","matcherIn","matcherOut","matcherFromTokens","checkContext","leadingRelative","implicitRelative","matchContext","matchAnyContext","matcherFromGroupMatchers","elementMatchers","setMatchers","matcherCachedRuns","bySet","byElement","superMatcher","expandContext","setMatched","matchedCount","outermost","contextBackup","dirrunsUnique","group","token","filters","runtil","rparentsprev","isSimple","rneedsContext","guaranteedUnique","children","contents","prev","targets","winnow","is","closest","pos","prevAll","addBack","andSelf","sibling","parents","parentsUntil","until","nextAll","nextUntil","prevUntil","siblings","contentDocument","contentWindow","reverse","n","r","qualifier","keep","filtered","createSafeFragment","nodeNames","safeFrag","rinlinejQuery","rnoshimcache","rleadingWhitespace","rxhtmlTag","rtagName","rtbody","rhtml","rnoInnerhtml","manipulation_rcheckableType","rchecked","rscriptType","rscriptTypeMasked","rcleanScript","wrapMap","legend","area","param","thead","tr","col","td","safeFragment","fragmentDiv","optgroup","tfoot","colgroup","caption","th","append","createTextNode","wrapAll","html","wrap","wrapInner","unwrap","replaceWith","domManip","prepend","before","after","keepData","getAll","setGlobalEval","dataAndEvents","deepDataAndEvents","isFunc","table","hasScripts","iNoClone","disableScript","findOrAppend","restoreScript","ajax","url","dataType","throws","refElements","cloneCopyEvent","dest","oldData","curData","fixCloneNodeIssues","defaultChecked","defaultSelected","appendTo","prependTo","insertAfter","replaceAll","insert","found","fixDefaultChecked","destElements","srcElements","inPage","selection","safe","nodes","iframe","getStyles","curCSS","ralpha","ropacity","rposition","rdisplayswap","rmargin","rnumsplit","rnumnonpx","rrelNum","elemdisplay","BODY","cssShow","position","visibility","cssNormalTransform","letterSpacing","fontWeight","cssExpand","cssPrefixes","vendorPropName","capName","origName","isHidden","el","css","showHide","show","hidden","css_defaultDisplay","styles","hide","toggle","bool","cssHooks","computed","cssNumber","columnCount","fillOpacity","lineHeight","orphans","widows","zIndex","cssProps","float","extra","swap","_computed","minWidth","maxWidth","getPropertyValue","currentStyle","left","rs","rsLeft","runtimeStyle","pixelLeft","setPositiveNumber","subtract","augmentWidthOrHeight","isBorderBox","getWidthOrHeight","valueIsBorderBox","actualDisplay","write","close","$1","visible","margin","padding","border","prefix","suffix","expand","expanded","parts","r20","rbracket","rCRLF","rsubmitterTypes","rsubmittable","serialize","serializeArray","traditional","s","encodeURIComponent","ajaxSettings","buildParams","v","hover","fnOver","fnOut","ajaxLocParts","ajaxLocation","ajax_nonce","ajax_rquery","rhash","rts","rheaders","rlocalProtocol","rnoContent","rprotocol","rurl","_load","prefilters","transports","allTypes","addToPrefiltersOrTransports","structure","dataTypeExpression","dataTypes","inspectPrefiltersOrTransports","originalOptions","jqXHR","inspected","seekingTransport","inspect","prefilterOrFactory","dataTypeOrTransport","ajaxExtend","flatOptions","params","response","responseText","complete","status","method","success","active","lastModified","etag","isLocal","processData","contentType","accepts","*","json","responseFields","converters","* text","text html","text json","text xml","ajaxSetup","settings","ajaxPrefilter","ajaxTransport","cacheURL","responseHeadersString","timeoutTimer","fireGlobals","transport","responseHeaders","callbackContext","globalEventContext","completeDeferred","statusCode","requestHeaders","requestHeadersNames","strAbort","getResponseHeader","getAllResponseHeaders","setRequestHeader","lname","overrideMimeType","mimeType","code","abort","statusText","finalText","crossDomain","hasContent","ifModified","headers","beforeSend","send","nativeStatusText","responses","isSuccess","modified","ajaxHandleResponses","ajaxConvert","rejectWith","getScript","getJSON","firstDataType","ct","finalDataType","conv2","current","conv","dataFilter","script","text script","head","scriptCharset","charset","onload","onreadystatechange","isAbort","oldCallbacks","rjsonp","jsonp","jsonpCallback","originalSettings","callbackName","overwritten","responseContainer","jsonProp","xhrCallbacks","xhrSupported","xhrId","xhrOnUnloadAbort","createStandardXHR","XMLHttpRequest","createActiveXHR","xhr","cors","username","open","xhrFields","err","firefoxAccessException","unload","fxNow","timerId","rfxtypes","rfxnum","rrun","animationPrefilters","defaultPrefilter","tweeners","unit","tween","createTween","scale","maxIterations","createFxNow","createTweens","animation","collection","Animation","properties","stopped","tick","currentTime","startTime","duration","percent","tweens","run","opts","specialEasing","originalProperties","Tween","easing","gotoEnd","propFilter","timer","anim","tweener","prefilter","dataShow","oldfire","handled","unqueued","overflow","overflowX","overflowY","eased","step","cssFn","speed","animate","genFx","fadeTo","to","optall","doAnimation","finish","stopQueue","timers","includeWidth","height","slideDown","slideUp","slideToggle","fadeIn","fadeOut","fadeToggle","linear","p","swing","cos","PI","interval","setInterval","clearInterval","slow","fast","animated","offset","setOffset","win","box","getBoundingClientRect","getWindow","pageYOffset","pageXOffset","curElem","curOffset","curCSSTop","curCSSLeft","calculatePosition","curPosition","curTop","curLeft","using","offsetParent","parentOffset","scrollTo","Height","Width","content","defaultExtra","funcName","define","amd"],"mappings":"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"} -\ No newline at end of file diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/js/bootstrap.js b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/js/bootstrap.js @@ -1,1951 +0,0 @@ -/*! - * Bootstrap v3.1.1 (http://getbootstrap.com) - * Copyright 2011-2014 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - */ - -if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript requires jQuery') } - -/* ======================================================================== - * Bootstrap: transition.js v3.1.1 - * http://getbootstrap.com/javascript/#transitions - * ======================================================================== - * Copyright 2011-2014 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/) - // ============================================================ - - function transitionEnd() { - var el = document.createElement('bootstrap') - - var transEndEventNames = { - 'WebkitTransition' : 'webkitTransitionEnd', - 'MozTransition' : 'transitionend', - 'OTransition' : 'oTransitionEnd otransitionend', - 'transition' : 'transitionend' - } - - for (var name in transEndEventNames) { - if (el.style[name] !== undefined) { - return { end: transEndEventNames[name] } - } - } - - return false // explicit for ie8 ( ._.) - } - - // http://blog.alexmaccaw.com/css-transitions - $.fn.emulateTransitionEnd = function (duration) { - var called = false, $el = this - $(this).one($.support.transition.end, function () { called = true }) - var callback = function () { if (!called) $($el).trigger($.support.transition.end) } - setTimeout(callback, duration) - return this - } - - $(function () { - $.support.transition = transitionEnd() - }) - -}(jQuery); - -/* ======================================================================== - * Bootstrap: alert.js v3.1.1 - * http://getbootstrap.com/javascript/#alerts - * ======================================================================== - * Copyright 2011-2014 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // ALERT CLASS DEFINITION - // ====================== - - var dismiss = '[data-dismiss="alert"]' - var Alert = function (el) { - $(el).on('click', dismiss, this.close) - } - - Alert.prototype.close = function (e) { - var $this = $(this) - var selector = $this.attr('data-target') - - if (!selector) { - selector = $this.attr('href') - selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 - } - - var $parent = $(selector) - - if (e) e.preventDefault() - - if (!$parent.length) { - $parent = $this.hasClass('alert') ? $this : $this.parent() - } - - $parent.trigger(e = $.Event('close.bs.alert')) - - if (e.isDefaultPrevented()) return - - $parent.removeClass('in') - - function removeElement() { - $parent.trigger('closed.bs.alert').remove() - } - - $.support.transition && $parent.hasClass('fade') ? - $parent - .one($.support.transition.end, removeElement) - .emulateTransitionEnd(150) : - removeElement() - } - - - // ALERT PLUGIN DEFINITION - // ======================= - - var old = $.fn.alert - - $.fn.alert = function (option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.alert') - - if (!data) $this.data('bs.alert', (data = new Alert(this))) - if (typeof option == 'string') data[option].call($this) - }) - } - - $.fn.alert.Constructor = Alert - - - // ALERT NO CONFLICT - // ================= - - $.fn.alert.noConflict = function () { - $.fn.alert = old - return this - } - - - // ALERT DATA-API - // ============== - - $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close) - -}(jQuery); - -/* ======================================================================== - * Bootstrap: button.js v3.1.1 - * http://getbootstrap.com/javascript/#buttons - * ======================================================================== - * Copyright 2011-2014 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // BUTTON PUBLIC CLASS DEFINITION - // ============================== - - var Button = function (element, options) { - this.$element = $(element) - this.options = $.extend({}, Button.DEFAULTS, options) - this.isLoading = false - } - - Button.DEFAULTS = { - loadingText: 'loading...' - } - - Button.prototype.setState = function (state) { - var d = 'disabled' - var $el = this.$element - var val = $el.is('input') ? 'val' : 'html' - var data = $el.data() - - state = state + 'Text' - - if (!data.resetText) $el.data('resetText', $el[val]()) - - $el[val](data[state] || this.options[state]) - - // push to event loop to allow forms to submit - setTimeout($.proxy(function () { - if (state == 'loadingText') { - this.isLoading = true - $el.addClass(d).attr(d, d) - } else if (this.isLoading) { - this.isLoading = false - $el.removeClass(d).removeAttr(d) - } - }, this), 0) - } - - Button.prototype.toggle = function () { - var changed = true - var $parent = this.$element.closest('[data-toggle="buttons"]') - - if ($parent.length) { - var $input = this.$element.find('input') - if ($input.prop('type') == 'radio') { - if ($input.prop('checked') && this.$element.hasClass('active')) changed = false - else $parent.find('.active').removeClass('active') - } - if (changed) $input.prop('checked', !this.$element.hasClass('active')).trigger('change') - } - - if (changed) this.$element.toggleClass('active') - } - - - // BUTTON PLUGIN DEFINITION - // ======================== - - var old = $.fn.button - - $.fn.button = function (option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.button') - var options = typeof option == 'object' && option - - if (!data) $this.data('bs.button', (data = new Button(this, options))) - - if (option == 'toggle') data.toggle() - else if (option) data.setState(option) - }) - } - - $.fn.button.Constructor = Button - - - // BUTTON NO CONFLICT - // ================== - - $.fn.button.noConflict = function () { - $.fn.button = old - return this - } - - - // BUTTON DATA-API - // =============== - - $(document).on('click.bs.button.data-api', '[data-toggle^=button]', function (e) { - var $btn = $(e.target) - if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn') - $btn.button('toggle') - e.preventDefault() - }) - -}(jQuery); - -/* ======================================================================== - * Bootstrap: carousel.js v3.1.1 - * http://getbootstrap.com/javascript/#carousel - * ======================================================================== - * Copyright 2011-2014 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // CAROUSEL CLASS DEFINITION - // ========================= - - var Carousel = function (element, options) { - this.$element = $(element) - this.$indicators = this.$element.find('.carousel-indicators') - this.options = options - this.paused = - this.sliding = - this.interval = - this.$active = - this.$items = null - - this.options.pause == 'hover' && this.$element - .on('mouseenter', $.proxy(this.pause, this)) - .on('mouseleave', $.proxy(this.cycle, this)) - } - - Carousel.DEFAULTS = { - interval: 5000, - pause: 'hover', - wrap: true - } - - Carousel.prototype.cycle = function (e) { - e || (this.paused = false) - - this.interval && clearInterval(this.interval) - - this.options.interval - && !this.paused - && (this.interval = setInterval($.proxy(this.next, this), this.options.interval)) - - return this - } - - Carousel.prototype.getActiveIndex = function () { - this.$active = this.$element.find('.item.active') - this.$items = this.$active.parent().children() - - return this.$items.index(this.$active) - } - - Carousel.prototype.to = function (pos) { - var that = this - var activeIndex = this.getActiveIndex() - - if (pos > (this.$items.length - 1) || pos < 0) return - - if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) - if (activeIndex == pos) return this.pause().cycle() - - return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos])) - } - - Carousel.prototype.pause = function (e) { - e || (this.paused = true) - - if (this.$element.find('.next, .prev').length && $.support.transition) { - this.$element.trigger($.support.transition.end) - this.cycle(true) - } - - this.interval = clearInterval(this.interval) - - return this - } - - Carousel.prototype.next = function () { - if (this.sliding) return - return this.slide('next') - } - - Carousel.prototype.prev = function () { - if (this.sliding) return - return this.slide('prev') - } - - Carousel.prototype.slide = function (type, next) { - var $active = this.$element.find('.item.active') - var $next = next || $active[type]() - var isCycling = this.interval - var direction = type == 'next' ? 'left' : 'right' - var fallback = type == 'next' ? 'first' : 'last' - var that = this - - if (!$next.length) { - if (!this.options.wrap) return - $next = this.$element.find('.item')[fallback]() - } - - if ($next.hasClass('active')) return this.sliding = false - - var e = $.Event('slide.bs.carousel', { relatedTarget: $next[0], direction: direction }) - this.$element.trigger(e) - if (e.isDefaultPrevented()) return - - this.sliding = true - - isCycling && this.pause() - - if (this.$indicators.length) { - this.$indicators.find('.active').removeClass('active') - this.$element.one('slid.bs.carousel', function () { - var $nextIndicator = $(that.$indicators.children()[that.getActiveIndex()]) - $nextIndicator && $nextIndicator.addClass('active') - }) - } - - if ($.support.transition && this.$element.hasClass('slide')) { - $next.addClass(type) - $next[0].offsetWidth // force reflow - $active.addClass(direction) - $next.addClass(direction) - $active - .one($.support.transition.end, function () { - $next.removeClass([type, direction].join(' ')).addClass('active') - $active.removeClass(['active', direction].join(' ')) - that.sliding = false - setTimeout(function () { that.$element.trigger('slid.bs.carousel') }, 0) - }) - .emulateTransitionEnd($active.css('transition-duration').slice(0, -1) * 1000) - } else { - $active.removeClass('active') - $next.addClass('active') - this.sliding = false - this.$element.trigger('slid.bs.carousel') - } - - isCycling && this.cycle() - - return this - } - - - // CAROUSEL PLUGIN DEFINITION - // ========================== - - var old = $.fn.carousel - - $.fn.carousel = function (option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.carousel') - var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option) - var action = typeof option == 'string' ? option : options.slide - - if (!data) $this.data('bs.carousel', (data = new Carousel(this, options))) - if (typeof option == 'number') data.to(option) - else if (action) data[action]() - else if (options.interval) data.pause().cycle() - }) - } - - $.fn.carousel.Constructor = Carousel - - - // CAROUSEL NO CONFLICT - // ==================== - - $.fn.carousel.noConflict = function () { - $.fn.carousel = old - return this - } - - - // CAROUSEL DATA-API - // ================= - - $(document).on('click.bs.carousel.data-api', '[data-slide], [data-slide-to]', function (e) { - var $this = $(this), href - var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7 - var options = $.extend({}, $target.data(), $this.data()) - var slideIndex = $this.attr('data-slide-to') - if (slideIndex) options.interval = false - - $target.carousel(options) - - if (slideIndex = $this.attr('data-slide-to')) { - $target.data('bs.carousel').to(slideIndex) - } - - e.preventDefault() - }) - - $(window).on('load', function () { - $('[data-ride="carousel"]').each(function () { - var $carousel = $(this) - $carousel.carousel($carousel.data()) - }) - }) - -}(jQuery); - -/* ======================================================================== - * Bootstrap: collapse.js v3.1.1 - * http://getbootstrap.com/javascript/#collapse - * ======================================================================== - * Copyright 2011-2014 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // COLLAPSE PUBLIC CLASS DEFINITION - // ================================ - - var Collapse = function (element, options) { - this.$element = $(element) - this.options = $.extend({}, Collapse.DEFAULTS, options) - this.transitioning = null - - if (this.options.parent) this.$parent = $(this.options.parent) - if (this.options.toggle) this.toggle() - } - - Collapse.DEFAULTS = { - toggle: true - } - - Collapse.prototype.dimension = function () { - var hasWidth = this.$element.hasClass('width') - return hasWidth ? 'width' : 'height' - } - - Collapse.prototype.show = function () { - if (this.transitioning || this.$element.hasClass('in')) return - - var startEvent = $.Event('show.bs.collapse') - this.$element.trigger(startEvent) - if (startEvent.isDefaultPrevented()) return - - var actives = this.$parent && this.$parent.find('> .panel > .in') - - if (actives && actives.length) { - var hasData = actives.data('bs.collapse') - if (hasData && hasData.transitioning) return - actives.collapse('hide') - hasData || actives.data('bs.collapse', null) - } - - var dimension = this.dimension() - - this.$element - .removeClass('collapse') - .addClass('collapsing') - [dimension](0) - - this.transitioning = 1 - - var complete = function () { - this.$element - .removeClass('collapsing') - .addClass('collapse in') - [dimension]('auto') - this.transitioning = 0 - this.$element.trigger('shown.bs.collapse') - } - - if (!$.support.transition) return complete.call(this) - - var scrollSize = $.camelCase(['scroll', dimension].join('-')) - - this.$element - .one($.support.transition.end, $.proxy(complete, this)) - .emulateTransitionEnd(350) - [dimension](this.$element[0][scrollSize]) - } - - Collapse.prototype.hide = function () { - if (this.transitioning || !this.$element.hasClass('in')) return - - var startEvent = $.Event('hide.bs.collapse') - this.$element.trigger(startEvent) - if (startEvent.isDefaultPrevented()) return - - var dimension = this.dimension() - - this.$element - [dimension](this.$element[dimension]()) - [0].offsetHeight - - this.$element - .addClass('collapsing') - .removeClass('collapse') - .removeClass('in') - - this.transitioning = 1 - - var complete = function () { - this.transitioning = 0 - this.$element - .trigger('hidden.bs.collapse') - .removeClass('collapsing') - .addClass('collapse') - } - - if (!$.support.transition) return complete.call(this) - - this.$element - [dimension](0) - .one($.support.transition.end, $.proxy(complete, this)) - .emulateTransitionEnd(350) - } - - Collapse.prototype.toggle = function () { - this[this.$element.hasClass('in') ? 'hide' : 'show']() - } - - - // COLLAPSE PLUGIN DEFINITION - // ========================== - - var old = $.fn.collapse - - $.fn.collapse = function (option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.collapse') - var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option) - - if (!data && options.toggle && option == 'show') option = !option - if (!data) $this.data('bs.collapse', (data = new Collapse(this, options))) - if (typeof option == 'string') data[option]() - }) - } - - $.fn.collapse.Constructor = Collapse - - - // COLLAPSE NO CONFLICT - // ==================== - - $.fn.collapse.noConflict = function () { - $.fn.collapse = old - return this - } - - - // COLLAPSE DATA-API - // ================= - - $(document).on('click.bs.collapse.data-api', '[data-toggle=collapse]', function (e) { - var $this = $(this), href - var target = $this.attr('data-target') - || e.preventDefault() - || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7 - var $target = $(target) - var data = $target.data('bs.collapse') - var option = data ? 'toggle' : $this.data() - var parent = $this.attr('data-parent') - var $parent = parent && $(parent) - - if (!data || !data.transitioning) { - if ($parent) $parent.find('[data-toggle=collapse][data-parent="' + parent + '"]').not($this).addClass('collapsed') - $this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed') - } - - $target.collapse(option) - }) - -}(jQuery); - -/* ======================================================================== - * Bootstrap: dropdown.js v3.1.1 - * http://getbootstrap.com/javascript/#dropdowns - * ======================================================================== - * Copyright 2011-2014 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // DROPDOWN CLASS DEFINITION - // ========================= - - var backdrop = '.dropdown-backdrop' - var toggle = '[data-toggle=dropdown]' - var Dropdown = function (element) { - $(element).on('click.bs.dropdown', this.toggle) - } - - Dropdown.prototype.toggle = function (e) { - var $this = $(this) - - if ($this.is('.disabled, :disabled')) return - - var $parent = getParent($this) - var isActive = $parent.hasClass('open') - - clearMenus() - - if (!isActive) { - if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) { - // if mobile we use a backdrop because click events don't delegate - $('<div class="dropdown-backdrop"/>').insertAfter($(this)).on('click', clearMenus) - } - - var relatedTarget = { relatedTarget: this } - $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget)) - - if (e.isDefaultPrevented()) return - - $parent - .toggleClass('open') - .trigger('shown.bs.dropdown', relatedTarget) - - $this.trigger('focus') - } - - return false - } - - Dropdown.prototype.keydown = function (e) { - if (!/(38|40|27)/.test(e.keyCode)) return - - var $this = $(this) - - e.preventDefault() - e.stopPropagation() - - if ($this.is('.disabled, :disabled')) return - - var $parent = getParent($this) - var isActive = $parent.hasClass('open') - - if (!isActive || (isActive && e.keyCode == 27)) { - if (e.which == 27) $parent.find(toggle).trigger('focus') - return $this.trigger('click') - } - - var desc = ' li:not(.divider):visible a' - var $items = $parent.find('[role=menu]' + desc + ', [role=listbox]' + desc) - - if (!$items.length) return - - var index = $items.index($items.filter(':focus')) - - if (e.keyCode == 38 && index > 0) index-- // up - if (e.keyCode == 40 && index < $items.length - 1) index++ // down - if (!~index) index = 0 - - $items.eq(index).trigger('focus') - } - - function clearMenus(e) { - $(backdrop).remove() - $(toggle).each(function () { - var $parent = getParent($(this)) - var relatedTarget = { relatedTarget: this } - if (!$parent.hasClass('open')) return - $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget)) - if (e.isDefaultPrevented()) return - $parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget) - }) - } - - function getParent($this) { - var selector = $this.attr('data-target') - - if (!selector) { - selector = $this.attr('href') - selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 - } - - var $parent = selector && $(selector) - - return $parent && $parent.length ? $parent : $this.parent() - } - - - // DROPDOWN PLUGIN DEFINITION - // ========================== - - var old = $.fn.dropdown - - $.fn.dropdown = function (option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.dropdown') - - if (!data) $this.data('bs.dropdown', (data = new Dropdown(this))) - if (typeof option == 'string') data[option].call($this) - }) - } - - $.fn.dropdown.Constructor = Dropdown - - - // DROPDOWN NO CONFLICT - // ==================== - - $.fn.dropdown.noConflict = function () { - $.fn.dropdown = old - return this - } - - - // APPLY TO STANDARD DROPDOWN ELEMENTS - // =================================== - - $(document) - .on('click.bs.dropdown.data-api', clearMenus) - .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() }) - .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle) - .on('keydown.bs.dropdown.data-api', toggle + ', [role=menu], [role=listbox]', Dropdown.prototype.keydown) - -}(jQuery); - -/* ======================================================================== - * Bootstrap: modal.js v3.1.1 - * http://getbootstrap.com/javascript/#modals - * ======================================================================== - * Copyright 2011-2014 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // MODAL CLASS DEFINITION - // ====================== - - var Modal = function (element, options) { - this.options = options - this.$element = $(element) - this.$backdrop = - this.isShown = null - - if (this.options.remote) { - this.$element - .find('.modal-content') - .load(this.options.remote, $.proxy(function () { - this.$element.trigger('loaded.bs.modal') - }, this)) - } - } - - Modal.DEFAULTS = { - backdrop: true, - keyboard: true, - show: true - } - - Modal.prototype.toggle = function (_relatedTarget) { - return this[!this.isShown ? 'show' : 'hide'](_relatedTarget) - } - - Modal.prototype.show = function (_relatedTarget) { - var that = this - var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget }) - - this.$element.trigger(e) - - if (this.isShown || e.isDefaultPrevented()) return - - this.isShown = true - - this.escape() - - this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this)) - - this.backdrop(function () { - var transition = $.support.transition && that.$element.hasClass('fade') - - if (!that.$element.parent().length) { - that.$element.appendTo(document.body) // don't move modals dom position - } - - that.$element - .show() - .scrollTop(0) - - if (transition) { - that.$element[0].offsetWidth // force reflow - } - - that.$element - .addClass('in') - .attr('aria-hidden', false) - - that.enforceFocus() - - var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget }) - - transition ? - that.$element.find('.modal-dialog') // wait for modal to slide in - .one($.support.transition.end, function () { - that.$element.trigger('focus').trigger(e) - }) - .emulateTransitionEnd(300) : - that.$element.trigger('focus').trigger(e) - }) - } - - Modal.prototype.hide = function (e) { - if (e) e.preventDefault() - - e = $.Event('hide.bs.modal') - - this.$element.trigger(e) - - if (!this.isShown || e.isDefaultPrevented()) return - - this.isShown = false - - this.escape() - - $(document).off('focusin.bs.modal') - - this.$element - .removeClass('in') - .attr('aria-hidden', true) - .off('click.dismiss.bs.modal') - - $.support.transition && this.$element.hasClass('fade') ? - this.$element - .one($.support.transition.end, $.proxy(this.hideModal, this)) - .emulateTransitionEnd(300) : - this.hideModal() - } - - Modal.prototype.enforceFocus = function () { - $(document) - .off('focusin.bs.modal') // guard against infinite focus loop - .on('focusin.bs.modal', $.proxy(function (e) { - if (this.$element[0] !== e.target && !this.$element.has(e.target).length) { - this.$element.trigger('focus') - } - }, this)) - } - - Modal.prototype.escape = function () { - if (this.isShown && this.options.keyboard) { - this.$element.on('keyup.dismiss.bs.modal', $.proxy(function (e) { - e.which == 27 && this.hide() - }, this)) - } else if (!this.isShown) { - this.$element.off('keyup.dismiss.bs.modal') - } - } - - Modal.prototype.hideModal = function () { - var that = this - this.$element.hide() - this.backdrop(function () { - that.removeBackdrop() - that.$element.trigger('hidden.bs.modal') - }) - } - - Modal.prototype.removeBackdrop = function () { - this.$backdrop && this.$backdrop.remove() - this.$backdrop = null - } - - Modal.prototype.backdrop = function (callback) { - var animate = this.$element.hasClass('fade') ? 'fade' : '' - - if (this.isShown && this.options.backdrop) { - var doAnimate = $.support.transition && animate - - this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />') - .appendTo(document.body) - - this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) { - if (e.target !== e.currentTarget) return - this.options.backdrop == 'static' - ? this.$element[0].focus.call(this.$element[0]) - : this.hide.call(this) - }, this)) - - if (doAnimate) this.$backdrop[0].offsetWidth // force reflow - - this.$backdrop.addClass('in') - - if (!callback) return - - doAnimate ? - this.$backdrop - .one($.support.transition.end, callback) - .emulateTransitionEnd(150) : - callback() - - } else if (!this.isShown && this.$backdrop) { - this.$backdrop.removeClass('in') - - $.support.transition && this.$element.hasClass('fade') ? - this.$backdrop - .one($.support.transition.end, callback) - .emulateTransitionEnd(150) : - callback() - - } else if (callback) { - callback() - } - } - - - // MODAL PLUGIN DEFINITION - // ======================= - - var old = $.fn.modal - - $.fn.modal = function (option, _relatedTarget) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.modal') - var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option) - - if (!data) $this.data('bs.modal', (data = new Modal(this, options))) - if (typeof option == 'string') data[option](_relatedTarget) - else if (options.show) data.show(_relatedTarget) - }) - } - - $.fn.modal.Constructor = Modal - - - // MODAL NO CONFLICT - // ================= - - $.fn.modal.noConflict = function () { - $.fn.modal = old - return this - } - - - // MODAL DATA-API - // ============== - - $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) { - var $this = $(this) - var href = $this.attr('href') - var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) //strip for ie7 - var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data()) - - if ($this.is('a')) e.preventDefault() - - $target - .modal(option, this) - .one('hide', function () { - $this.is(':visible') && $this.trigger('focus') - }) - }) - - $(document) - .on('show.bs.modal', '.modal', function () { $(document.body).addClass('modal-open') }) - .on('hidden.bs.modal', '.modal', function () { $(document.body).removeClass('modal-open') }) - -}(jQuery); - -/* ======================================================================== - * Bootstrap: tooltip.js v3.1.1 - * http://getbootstrap.com/javascript/#tooltip - * Inspired by the original jQuery.tipsy by Jason Frame - * ======================================================================== - * Copyright 2011-2014 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // TOOLTIP PUBLIC CLASS DEFINITION - // =============================== - - var Tooltip = function (element, options) { - this.type = - this.options = - this.enabled = - this.timeout = - this.hoverState = - this.$element = null - - this.init('tooltip', element, options) - } - - Tooltip.DEFAULTS = { - animation: true, - placement: 'top', - selector: false, - template: '<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>', - trigger: 'hover focus', - title: '', - delay: 0, - html: false, - container: false - } - - Tooltip.prototype.init = function (type, element, options) { - this.enabled = true - this.type = type - this.$element = $(element) - this.options = this.getOptions(options) - - var triggers = this.options.trigger.split(' ') - - for (var i = triggers.length; i--;) { - var trigger = triggers[i] - - if (trigger == 'click') { - this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this)) - } else if (trigger != 'manual') { - var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin' - var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout' - - this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this)) - this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this)) - } - } - - this.options.selector ? - (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) : - this.fixTitle() - } - - Tooltip.prototype.getDefaults = function () { - return Tooltip.DEFAULTS - } - - Tooltip.prototype.getOptions = function (options) { - options = $.extend({}, this.getDefaults(), this.$element.data(), options) - - if (options.delay && typeof options.delay == 'number') { - options.delay = { - show: options.delay, - hide: options.delay - } - } - - return options - } - - Tooltip.prototype.getDelegateOptions = function () { - var options = {} - var defaults = this.getDefaults() - - this._options && $.each(this._options, function (key, value) { - if (defaults[key] != value) options[key] = value - }) - - return options - } - - Tooltip.prototype.enter = function (obj) { - var self = obj instanceof this.constructor ? - obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) - - clearTimeout(self.timeout) - - self.hoverState = 'in' - - if (!self.options.delay || !self.options.delay.show) return self.show() - - self.timeout = setTimeout(function () { - if (self.hoverState == 'in') self.show() - }, self.options.delay.show) - } - - Tooltip.prototype.leave = function (obj) { - var self = obj instanceof this.constructor ? - obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) - - clearTimeout(self.timeout) - - self.hoverState = 'out' - - if (!self.options.delay || !self.options.delay.hide) return self.hide() - - self.timeout = setTimeout(function () { - if (self.hoverState == 'out') self.hide() - }, self.options.delay.hide) - } - - Tooltip.prototype.show = function () { - var e = $.Event('show.bs.' + this.type) - - if (this.hasContent() && this.enabled) { - this.$element.trigger(e) - - if (e.isDefaultPrevented()) return - var that = this; - - var $tip = this.tip() - - this.setContent() - - if (this.options.animation) $tip.addClass('fade') - - var placement = typeof this.options.placement == 'function' ? - this.options.placement.call(this, $tip[0], this.$element[0]) : - this.options.placement - - var autoToken = /\s?auto?\s?/i - var autoPlace = autoToken.test(placement) - if (autoPlace) placement = placement.replace(autoToken, '') || 'top' - - $tip - .detach() - .css({ top: 0, left: 0, display: 'block' }) - .addClass(placement) - - this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element) - - var pos = this.getPosition() - var actualWidth = $tip[0].offsetWidth - var actualHeight = $tip[0].offsetHeight - - if (autoPlace) { - var $parent = this.$element.parent() - - var orgPlacement = placement - var docScroll = document.documentElement.scrollTop || document.body.scrollTop - var parentWidth = this.options.container == 'body' ? window.innerWidth : $parent.outerWidth() - var parentHeight = this.options.container == 'body' ? window.innerHeight : $parent.outerHeight() - var parentLeft = this.options.container == 'body' ? 0 : $parent.offset().left - - placement = placement == 'bottom' && pos.top + pos.height + actualHeight - docScroll > parentHeight ? 'top' : - placement == 'top' && pos.top - docScroll - actualHeight < 0 ? 'bottom' : - placement == 'right' && pos.right + actualWidth > parentWidth ? 'left' : - placement == 'left' && pos.left - actualWidth < parentLeft ? 'right' : - placement - - $tip - .removeClass(orgPlacement) - .addClass(placement) - } - - var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight) - - this.applyPlacement(calculatedOffset, placement) - this.hoverState = null - - var complete = function() { - that.$element.trigger('shown.bs.' + that.type) - } - - $.support.transition && this.$tip.hasClass('fade') ? - $tip - .one($.support.transition.end, complete) - .emulateTransitionEnd(150) : - complete() - } - } - - Tooltip.prototype.applyPlacement = function (offset, placement) { - var replace - var $tip = this.tip() - var width = $tip[0].offsetWidth - var height = $tip[0].offsetHeight - - // manually read margins because getBoundingClientRect includes difference - var marginTop = parseInt($tip.css('margin-top'), 10) - var marginLeft = parseInt($tip.css('margin-left'), 10) - - // we must check for NaN for ie 8/9 - if (isNaN(marginTop)) marginTop = 0 - if (isNaN(marginLeft)) marginLeft = 0 - - offset.top = offset.top + marginTop - offset.left = offset.left + marginLeft - - // $.fn.offset doesn't round pixel values - // so we use setOffset directly with our own function B-0 - $.offset.setOffset($tip[0], $.extend({ - using: function (props) { - $tip.css({ - top: Math.round(props.top), - left: Math.round(props.left) - }) - } - }, offset), 0) - - $tip.addClass('in') - - // check to see if placing tip in new offset caused the tip to resize itself - var actualWidth = $tip[0].offsetWidth - var actualHeight = $tip[0].offsetHeight - - if (placement == 'top' && actualHeight != height) { - replace = true - offset.top = offset.top + height - actualHeight - } - - if (/bottom|top/.test(placement)) { - var delta = 0 - - if (offset.left < 0) { - delta = offset.left * -2 - offset.left = 0 - - $tip.offset(offset) - - actualWidth = $tip[0].offsetWidth - actualHeight = $tip[0].offsetHeight - } - - this.replaceArrow(delta - width + actualWidth, actualWidth, 'left') - } else { - this.replaceArrow(actualHeight - height, actualHeight, 'top') - } - - if (replace) $tip.offset(offset) - } - - Tooltip.prototype.replaceArrow = function (delta, dimension, position) { - this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + '%') : '') - } - - Tooltip.prototype.setContent = function () { - var $tip = this.tip() - var title = this.getTitle() - - $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title) - $tip.removeClass('fade in top bottom left right') - } - - Tooltip.prototype.hide = function () { - var that = this - var $tip = this.tip() - var e = $.Event('hide.bs.' + this.type) - - function complete() { - if (that.hoverState != 'in') $tip.detach() - that.$element.trigger('hidden.bs.' + that.type) - } - - this.$element.trigger(e) - - if (e.isDefaultPrevented()) return - - $tip.removeClass('in') - - $.support.transition && this.$tip.hasClass('fade') ? - $tip - .one($.support.transition.end, complete) - .emulateTransitionEnd(150) : - complete() - - this.hoverState = null - - return this - } - - Tooltip.prototype.fixTitle = function () { - var $e = this.$element - if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') { - $e.attr('data-original-title', $e.attr('title') || '').attr('title', '') - } - } - - Tooltip.prototype.hasContent = function () { - return this.getTitle() - } - - Tooltip.prototype.getPosition = function () { - var el = this.$element[0] - return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : { - width: el.offsetWidth, - height: el.offsetHeight - }, this.$element.offset()) - } - - Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) { - return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } : - placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } : - placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } : - /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width } - } - - Tooltip.prototype.getTitle = function () { - var title - var $e = this.$element - var o = this.options - - title = $e.attr('data-original-title') - || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title) - - return title - } - - Tooltip.prototype.tip = function () { - return this.$tip = this.$tip || $(this.options.template) - } - - Tooltip.prototype.arrow = function () { - return this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow') - } - - Tooltip.prototype.validate = function () { - if (!this.$element[0].parentNode) { - this.hide() - this.$element = null - this.options = null - } - } - - Tooltip.prototype.enable = function () { - this.enabled = true - } - - Tooltip.prototype.disable = function () { - this.enabled = false - } - - Tooltip.prototype.toggleEnabled = function () { - this.enabled = !this.enabled - } - - Tooltip.prototype.toggle = function (e) { - var self = e ? $(e.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) : this - self.tip().hasClass('in') ? self.leave(self) : self.enter(self) - } - - Tooltip.prototype.destroy = function () { - clearTimeout(this.timeout) - this.hide().$element.off('.' + this.type).removeData('bs.' + this.type) - } - - - // TOOLTIP PLUGIN DEFINITION - // ========================= - - var old = $.fn.tooltip - - $.fn.tooltip = function (option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.tooltip') - var options = typeof option == 'object' && option - - if (!data && option == 'destroy') return - if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options))) - if (typeof option == 'string') data[option]() - }) - } - - $.fn.tooltip.Constructor = Tooltip - - - // TOOLTIP NO CONFLICT - // =================== - - $.fn.tooltip.noConflict = function () { - $.fn.tooltip = old - return this - } - -}(jQuery); - -/* ======================================================================== - * Bootstrap: popover.js v3.1.1 - * http://getbootstrap.com/javascript/#popovers - * ======================================================================== - * Copyright 2011-2014 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // POPOVER PUBLIC CLASS DEFINITION - // =============================== - - var Popover = function (element, options) { - this.init('popover', element, options) - } - - if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js') - - Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, { - placement: 'right', - trigger: 'click', - content: '', - template: '<div class="popover"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>' - }) - - - // NOTE: POPOVER EXTENDS tooltip.js - // ================================ - - Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype) - - Popover.prototype.constructor = Popover - - Popover.prototype.getDefaults = function () { - return Popover.DEFAULTS - } - - Popover.prototype.setContent = function () { - var $tip = this.tip() - var title = this.getTitle() - var content = this.getContent() - - $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title) - $tip.find('.popover-content')[ // we use append for html objects to maintain js events - this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text' - ](content) - - $tip.removeClass('fade top bottom left right in') - - // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do - // this manually by checking the contents. - if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide() - } - - Popover.prototype.hasContent = function () { - return this.getTitle() || this.getContent() - } - - Popover.prototype.getContent = function () { - var $e = this.$element - var o = this.options - - return $e.attr('data-content') - || (typeof o.content == 'function' ? - o.content.call($e[0]) : - o.content) - } - - Popover.prototype.arrow = function () { - return this.$arrow = this.$arrow || this.tip().find('.arrow') - } - - Popover.prototype.tip = function () { - if (!this.$tip) this.$tip = $(this.options.template) - return this.$tip - } - - - // POPOVER PLUGIN DEFINITION - // ========================= - - var old = $.fn.popover - - $.fn.popover = function (option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.popover') - var options = typeof option == 'object' && option - - if (!data && option == 'destroy') return - if (!data) $this.data('bs.popover', (data = new Popover(this, options))) - if (typeof option == 'string') data[option]() - }) - } - - $.fn.popover.Constructor = Popover - - - // POPOVER NO CONFLICT - // =================== - - $.fn.popover.noConflict = function () { - $.fn.popover = old - return this - } - -}(jQuery); - -/* ======================================================================== - * Bootstrap: scrollspy.js v3.1.1 - * http://getbootstrap.com/javascript/#scrollspy - * ======================================================================== - * Copyright 2011-2014 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // SCROLLSPY CLASS DEFINITION - // ========================== - - function ScrollSpy(element, options) { - var href - var process = $.proxy(this.process, this) - - this.$element = $(element).is('body') ? $(window) : $(element) - this.$body = $('body') - this.$scrollElement = this.$element.on('scroll.bs.scroll-spy.data-api', process) - this.options = $.extend({}, ScrollSpy.DEFAULTS, options) - this.selector = (this.options.target - || ((href = $(element).attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7 - || '') + ' .nav li > a' - this.offsets = $([]) - this.targets = $([]) - this.activeTarget = null - - this.refresh() - this.process() - } - - ScrollSpy.DEFAULTS = { - offset: 10 - } - - ScrollSpy.prototype.refresh = function () { - var offsetMethod = this.$element[0] == window ? 'offset' : 'position' - - this.offsets = $([]) - this.targets = $([]) - - var self = this - var $targets = this.$body - .find(this.selector) - .map(function () { - var $el = $(this) - var href = $el.data('target') || $el.attr('href') - var $href = /^#./.test(href) && $(href) - - return ($href - && $href.length - && $href.is(':visible') - && [[ $href[offsetMethod]().top + (!$.isWindow(self.$scrollElement.get(0)) && self.$scrollElement.scrollTop()), href ]]) || null - }) - .sort(function (a, b) { return a[0] - b[0] }) - .each(function () { - self.offsets.push(this[0]) - self.targets.push(this[1]) - }) - } - - ScrollSpy.prototype.process = function () { - var scrollTop = this.$scrollElement.scrollTop() + this.options.offset - var scrollHeight = this.$scrollElement[0].scrollHeight || this.$body[0].scrollHeight - var maxScroll = scrollHeight - this.$scrollElement.height() - var offsets = this.offsets - var targets = this.targets - var activeTarget = this.activeTarget - var i - - if (scrollTop >= maxScroll) { - return activeTarget != (i = targets.last()[0]) && this.activate(i) - } - - if (activeTarget && scrollTop <= offsets[0]) { - return activeTarget != (i = targets[0]) && this.activate(i) - } - - for (i = offsets.length; i--;) { - activeTarget != targets[i] - && scrollTop >= offsets[i] - && (!offsets[i + 1] || scrollTop <= offsets[i + 1]) - && this.activate( targets[i] ) - } - } - - ScrollSpy.prototype.activate = function (target) { - this.activeTarget = target - - $(this.selector) - .parentsUntil(this.options.target, '.active') - .removeClass('active') - - var selector = this.selector + - '[data-target="' + target + '"],' + - this.selector + '[href="' + target + '"]' - - var active = $(selector) - .parents('li') - .addClass('active') - - if (active.parent('.dropdown-menu').length) { - active = active - .closest('li.dropdown') - .addClass('active') - } - - active.trigger('activate.bs.scrollspy') - } - - - // SCROLLSPY PLUGIN DEFINITION - // =========================== - - var old = $.fn.scrollspy - - $.fn.scrollspy = function (option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.scrollspy') - var options = typeof option == 'object' && option - - if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options))) - if (typeof option == 'string') data[option]() - }) - } - - $.fn.scrollspy.Constructor = ScrollSpy - - - // SCROLLSPY NO CONFLICT - // ===================== - - $.fn.scrollspy.noConflict = function () { - $.fn.scrollspy = old - return this - } - - - // SCROLLSPY DATA-API - // ================== - - $(window).on('load', function () { - $('[data-spy="scroll"]').each(function () { - var $spy = $(this) - $spy.scrollspy($spy.data()) - }) - }) - -}(jQuery); - -/* ======================================================================== - * Bootstrap: tab.js v3.1.1 - * http://getbootstrap.com/javascript/#tabs - * ======================================================================== - * Copyright 2011-2014 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // TAB CLASS DEFINITION - // ==================== - - var Tab = function (element) { - this.element = $(element) - } - - Tab.prototype.show = function () { - var $this = this.element - var $ul = $this.closest('ul:not(.dropdown-menu)') - var selector = $this.data('target') - - if (!selector) { - selector = $this.attr('href') - selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 - } - - if ($this.parent('li').hasClass('active')) return - - var previous = $ul.find('.active:last a')[0] - var e = $.Event('show.bs.tab', { - relatedTarget: previous - }) - - $this.trigger(e) - - if (e.isDefaultPrevented()) return - - var $target = $(selector) - - this.activate($this.parent('li'), $ul) - this.activate($target, $target.parent(), function () { - $this.trigger({ - type: 'shown.bs.tab', - relatedTarget: previous - }) - }) - } - - Tab.prototype.activate = function (element, container, callback) { - var $active = container.find('> .active') - var transition = callback - && $.support.transition - && $active.hasClass('fade') - - function next() { - $active - .removeClass('active') - .find('> .dropdown-menu > .active') - .removeClass('active') - - element.addClass('active') - - if (transition) { - element[0].offsetWidth // reflow for transition - element.addClass('in') - } else { - element.removeClass('fade') - } - - if (element.parent('.dropdown-menu')) { - element.closest('li.dropdown').addClass('active') - } - - callback && callback() - } - - transition ? - $active - .one($.support.transition.end, next) - .emulateTransitionEnd(150) : - next() - - $active.removeClass('in') - } - - - // TAB PLUGIN DEFINITION - // ===================== - - var old = $.fn.tab - - $.fn.tab = function ( option ) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.tab') - - if (!data) $this.data('bs.tab', (data = new Tab(this))) - if (typeof option == 'string') data[option]() - }) - } - - $.fn.tab.Constructor = Tab - - - // TAB NO CONFLICT - // =============== - - $.fn.tab.noConflict = function () { - $.fn.tab = old - return this - } - - - // TAB DATA-API - // ============ - - $(document).on('click.bs.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) { - e.preventDefault() - $(this).tab('show') - }) - -}(jQuery); - -/* ======================================================================== - * Bootstrap: affix.js v3.1.1 - * http://getbootstrap.com/javascript/#affix - * ======================================================================== - * Copyright 2011-2014 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // AFFIX CLASS DEFINITION - // ====================== - - var Affix = function (element, options) { - this.options = $.extend({}, Affix.DEFAULTS, options) - this.$window = $(window) - .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this)) - .on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this)) - - this.$element = $(element) - this.affixed = - this.unpin = - this.pinnedOffset = null - - this.checkPosition() - } - - Affix.RESET = 'affix affix-top affix-bottom' - - Affix.DEFAULTS = { - offset: 0 - } - - Affix.prototype.getPinnedOffset = function () { - if (this.pinnedOffset) return this.pinnedOffset - this.$element.removeClass(Affix.RESET).addClass('affix') - var scrollTop = this.$window.scrollTop() - var position = this.$element.offset() - return (this.pinnedOffset = position.top - scrollTop) - } - - Affix.prototype.checkPositionWithEventLoop = function () { - setTimeout($.proxy(this.checkPosition, this), 1) - } - - Affix.prototype.checkPosition = function () { - if (!this.$element.is(':visible')) return - - var scrollHeight = $(document).height() - var scrollTop = this.$window.scrollTop() - var position = this.$element.offset() - var offset = this.options.offset - var offsetTop = offset.top - var offsetBottom = offset.bottom - - if (this.affixed == 'top') position.top += scrollTop - - if (typeof offset != 'object') offsetBottom = offsetTop = offset - if (typeof offsetTop == 'function') offsetTop = offset.top(this.$element) - if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element) - - var affix = this.unpin != null && (scrollTop + this.unpin <= position.top) ? false : - offsetBottom != null && (position.top + this.$element.height() >= scrollHeight - offsetBottom) ? 'bottom' : - offsetTop != null && (scrollTop <= offsetTop) ? 'top' : false - - if (this.affixed === affix) return - if (this.unpin) this.$element.css('top', '') - - var affixType = 'affix' + (affix ? '-' + affix : '') - var e = $.Event(affixType + '.bs.affix') - - this.$element.trigger(e) - - if (e.isDefaultPrevented()) return - - this.affixed = affix - this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null - - this.$element - .removeClass(Affix.RESET) - .addClass(affixType) - .trigger($.Event(affixType.replace('affix', 'affixed'))) - - if (affix == 'bottom') { - this.$element.offset({ top: scrollHeight - offsetBottom - this.$element.height() }) - } - } - - - // AFFIX PLUGIN DEFINITION - // ======================= - - var old = $.fn.affix - - $.fn.affix = function (option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.affix') - var options = typeof option == 'object' && option - - if (!data) $this.data('bs.affix', (data = new Affix(this, options))) - if (typeof option == 'string') data[option]() - }) - } - - $.fn.affix.Constructor = Affix - - - // AFFIX NO CONFLICT - // ================= - - $.fn.affix.noConflict = function () { - $.fn.affix = old - return this - } - - - // AFFIX DATA-API - // ============== - - $(window).on('load', function () { - $('[data-spy="affix"]').each(function () { - var $spy = $(this) - var data = $spy.data() - - data.offset = data.offset || {} - - if (data.offsetBottom) data.offset.bottom = data.offsetBottom - if (data.offsetTop) data.offset.top = data.offsetTop - - $spy.affix(data) - }) - }) - -}(jQuery); -\ No newline at end of file diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/js/bootstrap.min.js b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/static/js/bootstrap.min.js @@ -1,6 +0,0 @@ -/*! - * Bootstrap v3.1.1 (http://getbootstrap.com) - * Copyright 2011-2014 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - */ -if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one(a.support.transition.end,function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b()})}(jQuery),+function(a){"use strict";var b='[data-dismiss="alert"]',c=function(c){a(c).on("click",b,this.close)};c.prototype.close=function(b){function c(){f.trigger("closed.bs.alert").remove()}var d=a(this),e=d.attr("data-target");e||(e=d.attr("href"),e=e&&e.replace(/.*(?=#[^\s]*$)/,""));var f=a(e);b&&b.preventDefault(),f.length||(f=d.hasClass("alert")?d:d.parent()),f.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(f.removeClass("in"),a.support.transition&&f.hasClass("fade")?f.one(a.support.transition.end,c).emulateTransitionEnd(150):c())};var d=a.fn.alert;a.fn.alert=function(b){return this.each(function(){var d=a(this),e=d.data("bs.alert");e||d.data("bs.alert",e=new c(this)),"string"==typeof b&&e[b].call(d)})},a.fn.alert.Constructor=c,a.fn.alert.noConflict=function(){return a.fn.alert=d,this},a(document).on("click.bs.alert.data-api",b,c.prototype.close)}(jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d),this.isLoading=!1};b.DEFAULTS={loadingText:"loading..."},b.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",f.resetText||d.data("resetText",d[e]()),d[e](f[b]||this.options[b]),setTimeout(a.proxy(function(){"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c))},this),0)},b.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")&&(c.prop("checked")&&this.$element.hasClass("active")?a=!1:b.find(".active").removeClass("active")),a&&c.prop("checked",!this.$element.hasClass("active")).trigger("change")}a&&this.$element.toggleClass("active")};var c=a.fn.button;a.fn.button=function(c){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof c&&c;e||d.data("bs.button",e=new b(this,f)),"toggle"==c?e.toggle():c&&e.setState(c)})},a.fn.button.Constructor=b,a.fn.button.noConflict=function(){return a.fn.button=c,this},a(document).on("click.bs.button.data-api","[data-toggle^=button]",function(b){var c=a(b.target);c.hasClass("btn")||(c=c.closest(".btn")),c.button("toggle"),b.preventDefault()})}(jQuery),+function(a){"use strict";var b=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=this.sliding=this.interval=this.$active=this.$items=null,"hover"==this.options.pause&&this.$element.on("mouseenter",a.proxy(this.pause,this)).on("mouseleave",a.proxy(this.cycle,this))};b.DEFAULTS={interval:5e3,pause:"hover",wrap:!0},b.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},b.prototype.getActiveIndex=function(){return this.$active=this.$element.find(".item.active"),this.$items=this.$active.parent().children(),this.$items.index(this.$active)},b.prototype.to=function(b){var c=this,d=this.getActiveIndex();return b>this.$items.length-1||0>b?void 0:this.sliding?this.$element.one("slid.bs.carousel",function(){c.to(b)}):d==b?this.pause().cycle():this.slide(b>d?"next":"prev",a(this.$items[b]))},b.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},b.prototype.next=function(){return this.sliding?void 0:this.slide("next")},b.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},b.prototype.slide=function(b,c){var d=this.$element.find(".item.active"),e=c||d[b](),f=this.interval,g="next"==b?"left":"right",h="next"==b?"first":"last",i=this;if(!e.length){if(!this.options.wrap)return;e=this.$element.find(".item")[h]()}if(e.hasClass("active"))return this.sliding=!1;var j=a.Event("slide.bs.carousel",{relatedTarget:e[0],direction:g});return this.$element.trigger(j),j.isDefaultPrevented()?void 0:(this.sliding=!0,f&&this.pause(),this.$indicators.length&&(this.$indicators.find(".active").removeClass("active"),this.$element.one("slid.bs.carousel",function(){var b=a(i.$indicators.children()[i.getActiveIndex()]);b&&b.addClass("active")})),a.support.transition&&this.$element.hasClass("slide")?(e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),d.one(a.support.transition.end,function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger("slid.bs.carousel")},0)}).emulateTransitionEnd(1e3*d.css("transition-duration").slice(0,-1))):(d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger("slid.bs.carousel")),f&&this.cycle(),this)};var c=a.fn.carousel;a.fn.carousel=function(c){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c),g="string"==typeof c?c:f.slide;e||d.data("bs.carousel",e=new b(this,f)),"number"==typeof c?e.to(c):g?e[g]():f.interval&&e.pause().cycle()})},a.fn.carousel.Constructor=b,a.fn.carousel.noConflict=function(){return a.fn.carousel=c,this},a(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",function(b){var c,d=a(this),e=a(d.attr("data-target")||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"")),f=a.extend({},e.data(),d.data()),g=d.attr("data-slide-to");g&&(f.interval=!1),e.carousel(f),(g=d.attr("data-slide-to"))&&e.data("bs.carousel").to(g),b.preventDefault()}),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var b=a(this);b.carousel(b.data())})})}(jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d),this.transitioning=null,this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};b.DEFAULTS={toggle:!0},b.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},b.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b=a.Event("show.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.$parent&&this.$parent.find("> .panel > .in");if(c&&c.length){var d=c.data("bs.collapse");if(d&&d.transitioning)return;c.collapse("hide"),d||c.data("bs.collapse",null)}var e=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[e](0),this.transitioning=1;var f=function(){this.$element.removeClass("collapsing").addClass("collapse in")[e]("auto"),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return f.call(this);var g=a.camelCase(["scroll",e].join("-"));this.$element.one(a.support.transition.end,a.proxy(f,this)).emulateTransitionEnd(350)[e](this.$element[0][g])}}},b.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse").removeClass("in"),this.transitioning=1;var d=function(){this.transitioning=0,this.$element.trigger("hidden.bs.collapse").removeClass("collapsing").addClass("collapse")};return a.support.transition?void this.$element[c](0).one(a.support.transition.end,a.proxy(d,this)).emulateTransitionEnd(350):d.call(this)}}},b.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()};var c=a.fn.collapse;a.fn.collapse=function(c){return this.each(function(){var d=a(this),e=d.data("bs.collapse"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c);!e&&f.toggle&&"show"==c&&(c=!c),e||d.data("bs.collapse",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.collapse.Constructor=b,a.fn.collapse.noConflict=function(){return a.fn.collapse=c,this},a(document).on("click.bs.collapse.data-api","[data-toggle=collapse]",function(b){var c,d=a(this),e=d.attr("data-target")||b.preventDefault()||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,""),f=a(e),g=f.data("bs.collapse"),h=g?"toggle":d.data(),i=d.attr("data-parent"),j=i&&a(i);g&&g.transitioning||(j&&j.find('[data-toggle=collapse][data-parent="'+i+'"]').not(d).addClass("collapsed"),d[f.hasClass("in")?"addClass":"removeClass"]("collapsed")),f.collapse(h)})}(jQuery),+function(a){"use strict";function b(b){a(d).remove(),a(e).each(function(){var d=c(a(this)),e={relatedTarget:this};d.hasClass("open")&&(d.trigger(b=a.Event("hide.bs.dropdown",e)),b.isDefaultPrevented()||d.removeClass("open").trigger("hidden.bs.dropdown",e))})}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}var d=".dropdown-backdrop",e="[data-toggle=dropdown]",f=function(b){a(b).on("click.bs.dropdown",this.toggle)};f.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a('<div class="dropdown-backdrop"/>').insertAfter(a(this)).on("click",b);var h={relatedTarget:this};if(f.trigger(d=a.Event("show.bs.dropdown",h)),d.isDefaultPrevented())return;f.toggleClass("open").trigger("shown.bs.dropdown",h),e.trigger("focus")}return!1}},f.prototype.keydown=function(b){if(/(38|40|27)/.test(b.keyCode)){var d=a(this);if(b.preventDefault(),b.stopPropagation(),!d.is(".disabled, :disabled")){var f=c(d),g=f.hasClass("open");if(!g||g&&27==b.keyCode)return 27==b.which&&f.find(e).trigger("focus"),d.trigger("click");var h=" li:not(.divider):visible a",i=f.find("[role=menu]"+h+", [role=listbox]"+h);if(i.length){var j=i.index(i.filter(":focus"));38==b.keyCode&&j>0&&j--,40==b.keyCode&&j<i.length-1&&j++,~j||(j=0),i.eq(j).trigger("focus")}}}};var g=a.fn.dropdown;a.fn.dropdown=function(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new f(this)),"string"==typeof b&&d[b].call(c)})},a.fn.dropdown.Constructor=f,a.fn.dropdown.noConflict=function(){return a.fn.dropdown=g,this},a(document).on("click.bs.dropdown.data-api",b).on("click.bs.dropdown.data-api",".dropdown form",function(a){a.stopPropagation()}).on("click.bs.dropdown.data-api",e,f.prototype.toggle).on("keydown.bs.dropdown.data-api",e+", [role=menu], [role=listbox]",f.prototype.keydown)}(jQuery),+function(a){"use strict";var b=function(b,c){this.options=c,this.$element=a(b),this.$backdrop=this.isShown=null,this.options.remote&&this.$element.find(".modal-content").load(this.options.remote,a.proxy(function(){this.$element.trigger("loaded.bs.modal")},this))};b.DEFAULTS={backdrop:!0,keyboard:!0,show:!0},b.prototype.toggle=function(a){return this[this.isShown?"hide":"show"](a)},b.prototype.show=function(b){var c=this,d=a.Event("show.bs.modal",{relatedTarget:b});this.$element.trigger(d),this.isShown||d.isDefaultPrevented()||(this.isShown=!0,this.escape(),this.$element.on("click.dismiss.bs.modal",'[data-dismiss="modal"]',a.proxy(this.hide,this)),this.backdrop(function(){var d=a.support.transition&&c.$element.hasClass("fade");c.$element.parent().length||c.$element.appendTo(document.body),c.$element.show().scrollTop(0),d&&c.$element[0].offsetWidth,c.$element.addClass("in").attr("aria-hidden",!1),c.enforceFocus();var e=a.Event("shown.bs.modal",{relatedTarget:b});d?c.$element.find(".modal-dialog").one(a.support.transition.end,function(){c.$element.trigger("focus").trigger(e)}).emulateTransitionEnd(300):c.$element.trigger("focus").trigger(e)}))},b.prototype.hide=function(b){b&&b.preventDefault(),b=a.Event("hide.bs.modal"),this.$element.trigger(b),this.isShown&&!b.isDefaultPrevented()&&(this.isShown=!1,this.escape(),a(document).off("focusin.bs.modal"),this.$element.removeClass("in").attr("aria-hidden",!0).off("click.dismiss.bs.modal"),a.support.transition&&this.$element.hasClass("fade")?this.$element.one(a.support.transition.end,a.proxy(this.hideModal,this)).emulateTransitionEnd(300):this.hideModal())},b.prototype.enforceFocus=function(){a(document).off("focusin.bs.modal").on("focusin.bs.modal",a.proxy(function(a){this.$element[0]===a.target||this.$element.has(a.target).length||this.$element.trigger("focus")},this))},b.prototype.escape=function(){this.isShown&&this.options.keyboard?this.$element.on("keyup.dismiss.bs.modal",a.proxy(function(a){27==a.which&&this.hide()},this)):this.isShown||this.$element.off("keyup.dismiss.bs.modal")},b.prototype.hideModal=function(){var a=this;this.$element.hide(),this.backdrop(function(){a.removeBackdrop(),a.$element.trigger("hidden.bs.modal")})},b.prototype.removeBackdrop=function(){this.$backdrop&&this.$backdrop.remove(),this.$backdrop=null},b.prototype.backdrop=function(b){var c=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var d=a.support.transition&&c;if(this.$backdrop=a('<div class="modal-backdrop '+c+'" />').appendTo(document.body),this.$element.on("click.dismiss.bs.modal",a.proxy(function(a){a.target===a.currentTarget&&("static"==this.options.backdrop?this.$element[0].focus.call(this.$element[0]):this.hide.call(this))},this)),d&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in"),!b)return;d?this.$backdrop.one(a.support.transition.end,b).emulateTransitionEnd(150):b()}else!this.isShown&&this.$backdrop?(this.$backdrop.removeClass("in"),a.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one(a.support.transition.end,b).emulateTransitionEnd(150):b()):b&&b()};var c=a.fn.modal;a.fn.modal=function(c,d){return this.each(function(){var e=a(this),f=e.data("bs.modal"),g=a.extend({},b.DEFAULTS,e.data(),"object"==typeof c&&c);f||e.data("bs.modal",f=new b(this,g)),"string"==typeof c?f[c](d):g.show&&f.show(d)})},a.fn.modal.Constructor=b,a.fn.modal.noConflict=function(){return a.fn.modal=c,this},a(document).on("click.bs.modal.data-api",'[data-toggle="modal"]',function(b){var c=a(this),d=c.attr("href"),e=a(c.attr("data-target")||d&&d.replace(/.*(?=#[^\s]+$)/,"")),f=e.data("bs.modal")?"toggle":a.extend({remote:!/#/.test(d)&&d},e.data(),c.data());c.is("a")&&b.preventDefault(),e.modal(f,this).one("hide",function(){c.is(":visible")&&c.trigger("focus")})}),a(document).on("show.bs.modal",".modal",function(){a(document.body).addClass("modal-open")}).on("hidden.bs.modal",".modal",function(){a(document.body).removeClass("modal-open")})}(jQuery),+function(a){"use strict";var b=function(a,b){this.type=this.options=this.enabled=this.timeout=this.hoverState=this.$element=null,this.init("tooltip",a,b)};b.DEFAULTS={animation:!0,placement:"top",selector:!1,template:'<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,container:!1},b.prototype.init=function(b,c,d){this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d);for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},b.prototype.getDefaults=function(){return b.DEFAULTS},b.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},b.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},b.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type);return clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show()},b.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type);return clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide()},b.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){if(this.$element.trigger(b),b.isDefaultPrevented())return;var c=this,d=this.tip();this.setContent(),this.options.animation&&d.addClass("fade");var e="function"==typeof this.options.placement?this.options.placement.call(this,d[0],this.$element[0]):this.options.placement,f=/\s?auto?\s?/i,g=f.test(e);g&&(e=e.replace(f,"")||"top"),d.detach().css({top:0,left:0,display:"block"}).addClass(e),this.options.container?d.appendTo(this.options.container):d.insertAfter(this.$element);var h=this.getPosition(),i=d[0].offsetWidth,j=d[0].offsetHeight;if(g){var k=this.$element.parent(),l=e,m=document.documentElement.scrollTop||document.body.scrollTop,n="body"==this.options.container?window.innerWidth:k.outerWidth(),o="body"==this.options.container?window.innerHeight:k.outerHeight(),p="body"==this.options.container?0:k.offset().left;e="bottom"==e&&h.top+h.height+j-m>o?"top":"top"==e&&h.top-m-j<0?"bottom":"right"==e&&h.right+i>n?"left":"left"==e&&h.left-i<p?"right":e,d.removeClass(l).addClass(e)}var q=this.getCalculatedOffset(e,h,i,j);this.applyPlacement(q,e),this.hoverState=null;var r=function(){c.$element.trigger("shown.bs."+c.type)};a.support.transition&&this.$tip.hasClass("fade")?d.one(a.support.transition.end,r).emulateTransitionEnd(150):r()}},b.prototype.applyPlacement=function(b,c){var d,e=this.tip(),f=e[0].offsetWidth,g=e[0].offsetHeight,h=parseInt(e.css("margin-top"),10),i=parseInt(e.css("margin-left"),10);isNaN(h)&&(h=0),isNaN(i)&&(i=0),b.top=b.top+h,b.left=b.left+i,a.offset.setOffset(e[0],a.extend({using:function(a){e.css({top:Math.round(a.top),left:Math.round(a.left)})}},b),0),e.addClass("in");var j=e[0].offsetWidth,k=e[0].offsetHeight;if("top"==c&&k!=g&&(d=!0,b.top=b.top+g-k),/bottom|top/.test(c)){var l=0;b.left<0&&(l=-2*b.left,b.left=0,e.offset(b),j=e[0].offsetWidth,k=e[0].offsetHeight),this.replaceArrow(l-f+j,j,"left")}else this.replaceArrow(k-g,k,"top");d&&e.offset(b)},b.prototype.replaceArrow=function(a,b,c){this.arrow().css(c,a?50*(1-a/b)+"%":"")},b.prototype.setContent=function(){var a=this.tip(),b=this.getTitle();a.find(".tooltip-inner")[this.options.html?"html":"text"](b),a.removeClass("fade in top bottom left right")},b.prototype.hide=function(){function b(){"in"!=c.hoverState&&d.detach(),c.$element.trigger("hidden.bs."+c.type)}var c=this,d=this.tip(),e=a.Event("hide.bs."+this.type);return this.$element.trigger(e),e.isDefaultPrevented()?void 0:(d.removeClass("in"),a.support.transition&&this.$tip.hasClass("fade")?d.one(a.support.transition.end,b).emulateTransitionEnd(150):b(),this.hoverState=null,this)},b.prototype.fixTitle=function(){var a=this.$element;(a.attr("title")||"string"!=typeof a.attr("data-original-title"))&&a.attr("data-original-title",a.attr("title")||"").attr("title","")},b.prototype.hasContent=function(){return this.getTitle()},b.prototype.getPosition=function(){var b=this.$element[0];return a.extend({},"function"==typeof b.getBoundingClientRect?b.getBoundingClientRect():{width:b.offsetWidth,height:b.offsetHeight},this.$element.offset())},b.prototype.getCalculatedOffset=function(a,b,c,d){return"bottom"==a?{top:b.top+b.height,left:b.left+b.width/2-c/2}:"top"==a?{top:b.top-d,left:b.left+b.width/2-c/2}:"left"==a?{top:b.top+b.height/2-d/2,left:b.left-c}:{top:b.top+b.height/2-d/2,left:b.left+b.width}},b.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},b.prototype.tip=function(){return this.$tip=this.$tip||a(this.options.template)},b.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},b.prototype.validate=function(){this.$element[0].parentNode||(this.hide(),this.$element=null,this.options=null)},b.prototype.enable=function(){this.enabled=!0},b.prototype.disable=function(){this.enabled=!1},b.prototype.toggleEnabled=function(){this.enabled=!this.enabled},b.prototype.toggle=function(b){var c=b?a(b.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type):this;c.tip().hasClass("in")?c.leave(c):c.enter(c)},b.prototype.destroy=function(){clearTimeout(this.timeout),this.hide().$element.off("."+this.type).removeData("bs."+this.type)};var c=a.fn.tooltip;a.fn.tooltip=function(c){return this.each(function(){var d=a(this),e=d.data("bs.tooltip"),f="object"==typeof c&&c;(e||"destroy"!=c)&&(e||d.data("bs.tooltip",e=new b(this,f)),"string"==typeof c&&e[c]())})},a.fn.tooltip.Constructor=b,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=c,this}}(jQuery),+function(a){"use strict";var b=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");b.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:'<div class="popover"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'}),b.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),b.prototype.constructor=b,b.prototype.getDefaults=function(){return b.DEFAULTS},b.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content")[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},b.prototype.hasContent=function(){return this.getTitle()||this.getContent()},b.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},b.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")},b.prototype.tip=function(){return this.$tip||(this.$tip=a(this.options.template)),this.$tip};var c=a.fn.popover;a.fn.popover=function(c){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof c&&c;(e||"destroy"!=c)&&(e||d.data("bs.popover",e=new b(this,f)),"string"==typeof c&&e[c]())})},a.fn.popover.Constructor=b,a.fn.popover.noConflict=function(){return a.fn.popover=c,this}}(jQuery),+function(a){"use strict";function b(c,d){var e,f=a.proxy(this.process,this);this.$element=a(a(c).is("body")?window:c),this.$body=a("body"),this.$scrollElement=this.$element.on("scroll.bs.scroll-spy.data-api",f),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||(e=a(c).attr("href"))&&e.replace(/.*(?=#[^\s]+$)/,"")||"")+" .nav li > a",this.offsets=a([]),this.targets=a([]),this.activeTarget=null,this.refresh(),this.process()}b.DEFAULTS={offset:10},b.prototype.refresh=function(){var b=this.$element[0]==window?"offset":"position";this.offsets=a([]),this.targets=a([]);{var c=this;this.$body.find(this.selector).map(function(){var d=a(this),e=d.data("target")||d.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[b]().top+(!a.isWindow(c.$scrollElement.get(0))&&c.$scrollElement.scrollTop()),e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){c.offsets.push(this[0]),c.targets.push(this[1])})}},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.$scrollElement[0].scrollHeight||this.$body[0].scrollHeight,d=c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(b>=d)return g!=(a=f.last()[0])&&this.activate(a);if(g&&b<=e[0])return g!=(a=f[0])&&this.activate(a);for(a=e.length;a--;)g!=f[a]&&b>=e[a]&&(!e[a+1]||b<=e[a+1])&&this.activate(f[a])},b.prototype.activate=function(b){this.activeTarget=b,a(this.selector).parentsUntil(this.options.target,".active").removeClass("active");var c=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',d=a(c).parents("li").addClass("active");d.parent(".dropdown-menu").length&&(d=d.closest("li.dropdown").addClass("active")),d.trigger("activate.bs.scrollspy")};var c=a.fn.scrollspy;a.fn.scrollspy=function(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.scrollspy.Constructor=b,a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=c,this},a(window).on("load",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);b.scrollspy(b.data())})})}(jQuery),+function(a){"use strict";var b=function(b){this.element=a(b)};b.prototype.show=function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.data("target");if(d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),!b.parent("li").hasClass("active")){var e=c.find(".active:last a")[0],f=a.Event("show.bs.tab",{relatedTarget:e});if(b.trigger(f),!f.isDefaultPrevented()){var g=a(d);this.activate(b.parent("li"),c),this.activate(g,g.parent(),function(){b.trigger({type:"shown.bs.tab",relatedTarget:e})})}}},b.prototype.activate=function(b,c,d){function e(){f.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),b.addClass("active"),g?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu")&&b.closest("li.dropdown").addClass("active"),d&&d()}var f=c.find("> .active"),g=d&&a.support.transition&&f.hasClass("fade");g?f.one(a.support.transition.end,e).emulateTransitionEnd(150):e(),f.removeClass("in")};var c=a.fn.tab;a.fn.tab=function(c){return this.each(function(){var d=a(this),e=d.data("bs.tab");e||d.data("bs.tab",e=new b(this)),"string"==typeof c&&e[c]()})},a.fn.tab.Constructor=b,a.fn.tab.noConflict=function(){return a.fn.tab=c,this},a(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(b){b.preventDefault(),a(this).tab("show")})}(jQuery),+function(a){"use strict";var b=function(c,d){this.options=a.extend({},b.DEFAULTS,d),this.$window=a(window).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(c),this.affixed=this.unpin=this.pinnedOffset=null,this.checkPosition()};b.RESET="affix affix-top affix-bottom",b.DEFAULTS={offset:0},b.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(b.RESET).addClass("affix");var a=this.$window.scrollTop(),c=this.$element.offset();return this.pinnedOffset=c.top-a},b.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},b.prototype.checkPosition=function(){if(this.$element.is(":visible")){var c=a(document).height(),d=this.$window.scrollTop(),e=this.$element.offset(),f=this.options.offset,g=f.top,h=f.bottom;"top"==this.affixed&&(e.top+=d),"object"!=typeof f&&(h=g=f),"function"==typeof g&&(g=f.top(this.$element)),"function"==typeof h&&(h=f.bottom(this.$element));var i=null!=this.unpin&&d+this.unpin<=e.top?!1:null!=h&&e.top+this.$element.height()>=c-h?"bottom":null!=g&&g>=d?"top":!1;if(this.affixed!==i){this.unpin&&this.$element.css("top","");var j="affix"+(i?"-"+i:""),k=a.Event(j+".bs.affix");this.$element.trigger(k),k.isDefaultPrevented()||(this.affixed=i,this.unpin="bottom"==i?this.getPinnedOffset():null,this.$element.removeClass(b.RESET).addClass(j).trigger(a.Event(j.replace("affix","affixed"))),"bottom"==i&&this.$element.offset({top:c-h-this.$element.height()}))}}};var c=a.fn.affix;a.fn.affix=function(c){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof c&&c;e||d.data("bs.affix",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.affix.Constructor=b,a.fn.affix.noConflict=function(){return a.fn.affix=c,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var b=a(this),c=b.data();c.offset=c.offset||{},c.offsetBottom&&(c.offset.bottom=c.offsetBottom),c.offsetTop&&(c.offset.top=c.offsetTop),b.affix(c)})})}(jQuery); -\ No newline at end of file diff --git a/_exts/taler_sphinx_theme/guzzle_sphinx_theme/theme.conf b/_exts/taler_sphinx_theme/guzzle_sphinx_theme/theme.conf @@ -1,40 +0,0 @@ -[theme] - -inherit = basic -stylesheet = guzzle.css - -[options] - -# Set to an html template to load custom HTML for the homepage -index_template = - -# Set the name of the project to appear in the left sidebar. -project_nav_name = - -# Path to a touch icon -touch_icon = - -# Set this value to enable Disqus comments -disqus_comments_shortname = - -# Set to enable google analytics -google_analytics_account = - -# Specify a base_url used to generate sitemap.xml links. If not specified, then -# no sitemap will be built. -base_url = - -# Allow a separate homepage from the "master_doc" -homepage = - -# Allow the project link to be overwritten to a custom URL. -projectlink = - -# The maximum depth of the global TOC; set it to -1 to allow unlimited depth -globaltoc_depth = 2 - -# If true, TOC entries that are not ancestors of the current page are collapsed -globaltoc_collapse = true - -# If true, the global TOC tree will also contain hidden entries -globaltoc_includehidden = true diff --git a/_static/custom.css b/_static/custom.css @@ -0,0 +1,15 @@ +@media (min-width: 960px) { + .container { + max-width: 100rem; + } + + .bd-sidebar { + flex-basis: 25%; + } +} + +@media (min-width: 768px) { + .bd-sidebar { + max-width: 25%; + } +} diff --git a/arch-api.png b/arch-api.png Binary files differ. diff --git a/arch.png b/arch.png Binary files differ. diff --git a/checklist-demo-upgrade.rst b/checklist-demo-upgrade.rst @@ -78,16 +78,16 @@ Merchant SPA: - |check| pay for order with wallet - |check| trigger refund - |check| accept refund with wallet -- |check| TBD: tipping +- |check| TBD: rewards - |check| TBD: products with previews - |check| TBD: inventory management - |check| TBD: adding transactions - |check| TBD: test various settings - |check| TBD: ... -Survey/Tipping: +Survey/Rewards: -- |check| Visit https://survey.demo.taler.net/ and receive a tip. +- |check| Visit https://survey.demo.taler.net/ and receive a reward. - |check| Verify that the survey stats page (https://survey.demo.taler.net/survey-stats) is working, and that the survey reserve has sufficient funds. diff --git a/checklist-release.rst b/checklist-release.rst @@ -20,8 +20,8 @@ For exchange: - |check| upgrade 'demo.taler.net' - |check| run :doc:`demo upgrade checklist <checklist-demo-upgrade>` - |check| tag repo. -- |check| use deployment.git/packaging/*-docker/ to build Debian and Ubuntu packages -- |check| upload packages to deb.taler.net/ (note: only Florian/Christian can sign) +- |check| use 'deployment.git/packaging/\*-docker/' to build Debian and Ubuntu packages +- |check| upload packages to 'deb.taler.net' (note: only Florian/Christian can sign) - |check| change 'demo.taler.net' deployment to use new tag. - |check| Upload triplet to ftp-upload.gnu.org/incoming/ftp or /incoming/alpha @@ -39,8 +39,8 @@ For merchant (C backend): - |check| upgrade 'demo.taler.net' - |check| run :doc:`demo upgrade checklist <checklist-demo-upgrade>` - |check| tag repo. -- |check| use deployment.git/packaging/*-docker/ to build Debian and Ubuntu packages -- |check| upload packages to deb.taler.net/ (note: only Florian/Christian can sign) +- |check| use 'deployment.git/packaging/\*-docker/' to build Debian and Ubuntu packages +- |check| upload packages to 'deb.taler.net' (note: only Florian/Christian can sign) - |check| change 'demo.taler.net' deployment to use new tag. - |check| Upload triplet to ftp-upload.gnu.org/incoming/ftp or /incoming/alpha @@ -57,8 +57,8 @@ For sync: - |check| upgrade 'demo.taler.net' - |check| run :doc:`demo upgrade checklist <checklist-demo-upgrade>` - |check| tag repo. -- |check| use deployment.git/packaging/*-docker/ to build Debian and Ubuntu packages -- |check| upload packages to deb.taler.net/ (note: only Florian/Christian can sign) +- |check| use 'deployment.git/packaging/\*-docker/' to build Debian and Ubuntu packages +- |check| upload packages to 'deb.taler.net' (note: only Florian/Christian can sign) - |check| change 'demo.taler.net' deployment to use new tag. - |check| Upload triplet to ftp-upload.gnu.org/incoming/ftp or /incoming/alpha @@ -69,8 +69,8 @@ For taler-mdb: - |check| Change version number in configure.ac. - |check| make dist for release. - |check| tag repo. -- |check| use deployment.git/packaging/*-docker/ to build Debian and Ubuntu packages -- |check| upload packages to deb.taler.net/ (note: only Florian/Christian can sign) +- |check| use 'deployment.git/packaging/\*-docker/' to build Debian and Ubuntu packages +- |check| upload packages to 'deb.taler.net' (note: only Florian/Christian can sign) - |check| Upload triplet to ftp-upload.gnu.org/incoming/ftp or /incoming/alpha For taler-twister: @@ -97,8 +97,8 @@ For libeufin: - |check| make dist for release. - |check| verify dist builds from source - |check| tag repo. -- |check| use deployment.git/packaging/*-docker/ to build Debian and Ubuntu packages -- |check| upload packages to deb.taler.net/ (note: only Florian/Christian can sign) +- |check| use 'deployment.git/packaging/\*-docker/' to build Debian and Ubuntu packages +- |check| upload packages to 'deb.taler.net' (note: only Florian/Christian can sign) - |check| change 'demo.taler.net' deployment to use new tag. - |check| Upload triplet to ftp-upload.gnu.org/incoming/ftp or /incoming/alpha @@ -115,8 +115,8 @@ Wallet-core: - |check| make dist for release. - |check| verify dist builds from source - |check| tag repo. -- |check| use deployment.git/packaging/*-docker/ to build Debian and Ubuntu packages -- |check| upload packages to deb.taler.net/ (note: only Florian/Christian can sign) +- |check| use 'deployment.git/packaging/\*-docker/' to build Debian and Ubuntu packages +- |check| upload packages to 'deb.taler.net' (note: only Florian/Christian can sign) - |check| change 'demo.taler.net' deployment to use new tag. - |check| Upload triplet to ftp-upload.gnu.org/incoming/ftp or /incoming/alpha diff --git a/ci/Containerfile b/ci/Containerfile @@ -0,0 +1,23 @@ +FROM docker.io/library/debian:bookworm-slim + +ENV DEBIAN_FRONTEND=noninteractive + +# Install docs generation utils +RUN apt-get update -yqq && \ + apt-get install -yqq --no-install-recommends \ + make \ + graphviz \ + python3-sphinx \ + python3-recommonmark \ + python3-texext \ + python3-sphinx-book-theme \ + texlive-latex-extra \ + texlive-fonts-recommended \ + tex-gyre \ + dvipng \ + latexmk \ + && rm -rf /var/lib/apt/lists/* + +WORKDIR /workdir + +CMD ["bash", "/workdir/ci/jobs/0-build/job.sh"] diff --git a/ci/jobs/0-build/build-docs.sh b/ci/jobs/0-build/build-docs.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +set -eu + +make html +make latexpdf + +rm -rf /artifacts/docs_build + +mkdir -p /artifacts/docs_build/docs/html/ +mkdir -p /artifacts/docs_build/docs/pdf/ + +cp -r _build/html/* /artifacts/docs_build/docs/html/ +cp -r _build/latex/*.pdf /artifacts/docs_build/docs/pdf/ diff --git a/ci/jobs/0-build/job.sh b/ci/jobs/0-build/job.sh @@ -0,0 +1,6 @@ +#!/bin/bash +set -exuo pipefail + +job_dir=$(dirname "${BASH_SOURCE[0]}") + +"${job_dir}"/build-docs.sh diff --git a/coin.png b/coin.png Binary files differ. diff --git a/conf.py b/conf.py @@ -1,6 +1,6 @@ """ This file is part of GNU TALER. - Copyright (C) 2014, 2015, 2016, 2020, 2021 Taler Systems SA + Copyright (C) 2014-2023 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software @@ -17,6 +17,7 @@ @author Benedikt Muller @author Sree Harsha Totakura @author Marcello Stanisci + @author Christian Grothoff """ # -*- coding: utf-8 -*- # @@ -37,8 +38,6 @@ import os sys.path.append(os.path.abspath("_exts")) -import taler_sphinx_theme - # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. @@ -55,7 +54,6 @@ needs_sphinx = "2.2.0" extensions = [ "ebicsdomain", "typescriptdomain", - "taler_sphinx_theme", "sphinx.ext.todo", "sphinx.ext.imgmath", "httpdomain.httpdomain", @@ -110,6 +108,8 @@ exclude_patterns = [ "prebuilt", "**/README.md", "extract-tsdefs", + "frags", + "orphaned", ] # The reST default role (used for this markup: `text`) to use for all @@ -140,16 +140,15 @@ pygments_style = "sphinx" # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -html_theme = "taler_sphinx_theme" -html_theme_path = taler_sphinx_theme.html_theme_path() +html_theme = "sphinx_book_theme" -html_sidebars = {"**": ["logo-text.html", "globaltoc.html", "searchbox.html"]} +#html_sidebars = {"**": ["logo-text.html", "globaltoc.html", "searchbox.html"]} +#html_sidebars = {"**": ["globaltoc.html", "searchbox.html"]} html_theme_options = { # Set the name of the project to appear in the sidebar - "project_nav_name": "GNU Taler", - "globaltoc_depth": 4, - "globaltoc_includehidden": False, + "home_page_in_toc": True, + "show_navbar_depth": 1, } # Add any paths that contain custom themes here, relative to this directory. @@ -157,14 +156,14 @@ html_theme_options = { # The name for this set of Sphinx documents. If None, it defaults to # "<project> v<release> documentation". -# html_title = None +html_title = "GNU Taler" # A shorter title for the navigation bar. Default is the same as html_title. -# html_short_title = None +html_short_title = "GNU Taler" # The name of an image file (relative to this directory) to place at the top # of the sidebar. -# html_logo = None +html_logo = "images/taler-logo.svg" # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 @@ -176,6 +175,9 @@ html_theme_options = { # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ["_static"] +# This is a sphinx-book-themes specific parameter to allow for customized css +html_css_files = ["custom.css"] + # Add any extra paths that contain custom files (such as robots.txt or # .htaccess) here, relative to this directory. These files are copied # directly to the root of the documentation. @@ -252,6 +254,13 @@ latex_documents = [ "manual", ), ( + "taler-challenger-manual", + "taler-challenger-manual.tex", + "GNU Taler Challenger Manual", + "GNU Taler team", + "manual", + ), + ( "taler-merchant-manual", "taler-merchant-manual.tex", "GNU Taler Merchant Manual", @@ -307,6 +316,41 @@ latex_appendices = ["fdl-1.3"] # (source start file, name, description, authors, manual section). man_pages = [ ( + "manpages/challenger-config.1", + "challenger-config", + "manipulate Challenger configuration files", + "GNU Taler contributors", + 1, + ), + ( + "manpages/challenger-dbinit.1", + "challenger-dbinit", + "initialize the Challenger database", + "GNU Taler contributors", + 1, + ), + ( + "manpages/challenger-admin.1", + "challenger-admin", + "manipulate list of authorized Challenger clients", + "GNU Taler contributors", + 1, + ), + ( + "manpages/challenger-httpd.1", + "challenger-httpd", + "provide the Challenger HTTP interface", + "GNU Taler contributors", + 1, + ), + ( + "manpages/challenger.conf.5", + "challenger.conf", + "Challenger configuration file", + "GNU Taler contributors", + 5, + ), + ( "manpages/sync-config.1", "sync-config", "manipulate Sync configuration files", @@ -377,6 +421,13 @@ man_pages = [ 1, ), ( + "manpages/taler-terms-generator.1", + "taler-terms-generator", + "create legal policy documents for services", + "GNU Taler contributors", + 1, + ), + ( "manpages/taler-exchange-closer.1", "taler-exchange-closer", "close idle reserves", @@ -419,6 +470,13 @@ man_pages = [ 1, ), ( + "manpages/taler-unified-setup.1", + "taler-unified-setup", + "conveniently start and stop various GNU Taler services", + "GNU Taler contributors", + 1, + ), + ( "manpages/taler-exchange-benchmark.1", "taler-exchange-benchmark", "measure exchange performance", @@ -426,6 +484,55 @@ man_pages = [ 1, ), ( + "manpages/taler-bank-benchmark.1", + "taler-bank-benchmark", + "measure bank performance", + "GNU Taler contributors", + 1, + ), + ( + "manpages/taler-aggregator-benchmark.1", + "taler-aggregator-benchmark", + "generate database to measure aggregator performance", + "GNU Taler contributors", + 1, + ), + ( + "manpages/taler-auditor-dbconfig.1", + "taler-auditor-dbconfig", + "configure Taler auditor database", + "GNU Taler contributors", + 1, + ), + ( + "manpages/taler-exchange-dbconfig.1", + "taler-exchange-dbconfig", + "configure Taler exchange database", + "GNU Taler contributors", + 1, + ), + ( + "manpages/taler-merchant-dbconfig.1", + "taler-merchant-dbconfig", + "configure Taler merchant database", + "GNU Taler contributors", + 1, + ), + ( + "manpages/sync-dbconfig.1", + "sync-dbconfig", + "configure sync database", + "GNU Taler contributors", + 1, + ), + ( + "manpages/challenger-dbconfig.1", + "challenger-dbconfig", + "configure challenger database", + "GNU Taler contributors", + 1, + ), + ( "manpages/taler-exchange-dbinit.1", "taler-exchange-dbinit", "initialize Taler exchange database", @@ -482,9 +589,23 @@ man_pages = [ 1, ), ( + "manpages/taler-merchant-webhook.1", + "taler-merchant-webhook", + "execute webhooks of the Taler merchant backend (optional service)", + "GNU Taler contributors", + 1, + ), + ( + "manpages/taler-merchant-wirewatch.1", + "taler-merchant-wirewatch", + "import credit transactions from a merchant bank account into merchant backend (optional)", + "GNU Taler contributors", + 1, + ), + ( "manpages/taler-merchant-setup-reserve.1", "taler-merchant-setup-reserve", - "setup reserve for tipping at a Taler merchant backend", + "setup reserve for rewards at a Taler merchant backend", "GNU Taler contributors", 1, ), @@ -503,6 +624,13 @@ man_pages = [ 1, ), ( + "manpages/taler-exchange-kyc-aml-pep-trigger.1", + "taler-exchange-kyc-aml-pep-trigger", + "Taler KYC_AML_TRIGGER example", + "GNU Taler contributors", + 1, + ), + ( "manpages/taler.conf.5", "taler.conf", "Taler configuration file", @@ -616,6 +744,15 @@ texinfo_documents = [ "CATEGORY", ), ( + "taler-challenger-manual", + "challenger", + "Taler Challenger Manual", + "GNU Taler team", + "MENU ENTRY", + "DESCRIPTION", + "CATEGORY", + ), + ( "taler-merchant-manual", "taler-merchant", "Taler Merchant Manual", diff --git a/core/api-auditor.rst b/core/api-auditor.rst @@ -24,6 +24,8 @@ for all details not specified in the individual requests. The `glossary <https://docs.taler.net/glossary.html#glossary>`_ defines all specific terms used in this section. +.. contents:: Table of Contents + .. _auditor-version: ------------------------- @@ -34,7 +36,7 @@ This API is used by merchants to obtain a list of all exchanges audited by this auditor. This may be required for the merchant to perform the required know-your-customer (KYC) registration before issuing contracts. -.. http:get:: /version +.. http:get:: /config Get the protocol version and some meta data about the auditor. diff --git a/core/api-bank-access.rst b/core/api-bank-access.rst @@ -1,279 +0,0 @@ -.. - This file is part of GNU TALER. - - Copyright (C) 2014-2020 Taler Systems SA - - TALER 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 2.1, or (at your option) any later version. - - TALER 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 - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - - @author Florian Dold - -===================== -Taler Bank Access API -===================== - -This chapter describes the API that the GNU Taler demonstrator bank offers to access accounts. - -This API differs from the "Bank Integration API" in that it provides advanced API access to accounts, as opposed -to enabling wallets to withdraw with a better user experience ("tight integration"). - - ------------------------- -Accounts and Withdrawals ------------------------- - -.. http:get:: ${BANK_API_BASE_URL}/public-accounts - - Show those accounts whose histories are publicly visible. For example, - accounts from donation receivers. As such, this request is unauthenticated. - - **Response** - - **Details** - - .. ts:def:: PublicAccountsResponse - - interface PublicAccountsResponse { - publicAccounts: PublicAccount[] - } - - .. ts:def:: PublicAccount - - interface PublicAccount { - iban: string; - balance: string; - // The account name _and_ the username of the - // Sandbox customer that owns such a bank account. - accountLabel: string; - } - -The following endpoints require HTTP "Basic" authentication with the account -name and account password, at least in the GNU Taler demo bank implementation. - - -.. http:get:: ${BANK_API_BASE_URL}/accounts/${account_name} - - Request the current balance of an account. (New: ) In case of a public bank - account, no authentication is required. - - **Response** - - **Details** - - .. ts:def:: BankAccountBalanceResponse - - interface BankAccountBalanceResponse { - // Available balance on the account. - balance: { - amount: Amount; - credit_debit_indicator: "credit" | "debit"; - }; - // payto://-URI of the account. (New) - paytoUri: string; - } - - -.. http:post:: ${BANK_API_BASE_URL}/accounts/${account_name}/withdrawals - - Create a withdrawal operation, resulting in a ``taler://withdraw`` URI. - - **Request** - - .. ts:def:: BankAccountCreateWithdrawalRequest - - interface BankAccountCreateWithdrawalRequest { - // Amount to withdraw. - amount: Amount; - } - - **Response** - - .. ts:def:: BankAccountCreateWithdrawalResponse - - interface BankAccountCreateWithdrawalResponse { - // ID of the withdrawal, can be used to view/modify the withdrawal operation. - withdrawal_id: string; - - // URI that can be passed to the wallet to initiate the withdrawal. - taler_withdraw_uri: string; - } - - :http:statuscode:`403 Forbidden`: - The operation was rejected due to insufficient funds. - -.. http:get:: ${BANK_API_BASE_URL}/accounts/${account_name}/withdrawals/${withdrawal_id} - - Query the status of a withdrawal operation. - - **Response** - - **Details** - - .. ts:def:: BankAccountGetWithdrawalResponse - - interface BankAccountGetWithdrawalResponse { - // Amount that will be withdrawn with this withdrawal operation. - amount: Amount; - - // Was the withdrawal aborted? - aborted: boolean; - - // Has the withdrawal been confirmed by the bank? - // The wire transfer for a withdrawal is only executed once - // both ``confirmation_done`` is ``true`` and ``selection_done`` is ``true``. - confirmation_done: boolean; - - // Did the wallet select reserve details? - selection_done: boolean; - - // Reserve public key selected by the exchange, - // only non-null if ``selection_done`` is ``true``. - selected_reserve_pub: string | null; - - // Exchange account selected by the wallet, or by the bank - // (with the default exchange) in case the wallet did not provide one - // through the Integration API. - selected_exchange_account: string | null; - } - - -.. http:post:: ${BANK_API_BASE_URL}/accounts/${account_name}/withdrawals/${withdrawal_id}/abort - - Abort a withdrawal operation. Has no effect on an already aborted withdrawal operation. - - :http:statuscode:`200 OK`: The withdrawal operation has been aborted. The response is an empty JSON object. - :http:statuscode:`409 Conflict`: The reserve operation has been confirmed previously and can't be aborted. - - -.. http:post:: ${BANK_API_BASE_URL}/accounts/${account_name}/withdrawals/${withdrawal_id}/confirm - - Confirm a withdrawal operation. Has no effect on an already confirmed withdrawal operation. - This call is responsible of wiring the funds to the exchange. - - **Response** - - :http:statuscode:`200 OK`: - The withdrawal operation has been confirmed. The response is an empty JSON object. - :http:statuscode:`409 Conflict`: - The withdrawal has been aborted previously and can't be confirmed. - :http:statuscode:`422 Unprocessable Entity` (New): - The withdraw operation cannot be confirmed because no exchange and reserve public key selection happened before. - ------------- -Transactions ------------- - -.. http:get:: ${BANK_API_BASE_URL}/accounts/${account_name}/transactions - - Retrieve a subset of transactions related to $account_name. Without - query parameters, it returns the last 5 transactions. - - **Request** - - :query page: page number (defaults to 1, meaning the page with the latest transactions.) - :query size: how many transactions per page, defaults to 5. - - **Response** - - .. ts:def:: BankAccountTransactionsResponse - - interface BankAccountTransactionsResponse { - transactions: BankAccountTransactionInfo[]; - } - -.. http:get:: ${BANK_API_BASE_URL}/accounts/${account_name}/transactions/${transaction_id} - - **Response** - - Retrieve the transaction whose identifier is ``transaction_id``, - in the following format: - - .. ts:def:: BankAccountTransactionInfo - - interface BankAccountTransactionInfo { - - creditorIban: string; - creditorBic: string; // Optional - creditorName: string; - - debtorIban: string; - debtorBic: string; - debtorName: string; - - amount: number; - currency: string; - subject: string; - - // Transaction unique ID. Matches - // $transaction_id from the URI. - uid: string; - direction: "DBIT" | "CRDT"; - date: string; // milliseconds since the Unix epoch - } - - -.. http:post:: ${BANK_API_BASE_URL}/accounts/${account_name}/transactions - - Create a new transaction where the bank account with the label ``account_name`` is **debited**. - - **Request** - - .. ts:def:: BankAccountTransactionCreate - - interface CreateBankAccountTransactionCreate { - - // Address in the Payto format of the wire transfer receiver. - // It needs at least the 'message' query string parameter. - paytoUri: string; - - // Transaction amount (in the $currency:x.y format), optional. - // However, when not given, its value must occupy the 'amount' - // query string parameter of the 'payto' field. In case it - // is given in both places, the paytoUri's takes the precedence. - amount: string; - } - - **Response** - - :http:statuscode:`200 OK`: - the transaction has been created. - - :http:statuscode:`400 Bad Request`: - the request was invalid or the payto://-URI used unacceptable features. - -.. http:delete:: ${BANK_API_BASE_URL}/accounts/${account_name} - - Delete the bank account (and the customer entry) from the database. - Note, customer usernames and bank accounts have the same value. - ----------------------- -Registration (Testing) ----------------------- - -.. http:post:: ${BANK_API_BASE_URL}/testing/register - - Create a new bank account. This endpoint should be disabled for most deployments, but is useful - for automated testing / integration tests. - - **Request** - - .. ts:def:: BankRegistrationRequest - - interface BankRegistrationRequest { - username: string; - - password: string; - } - - - **Response** - - :http:statuscode:`200 OK`: Registration was successful. diff --git a/core/api-bank-integration.rst b/core/api-bank-integration.rst @@ -112,6 +112,7 @@ for the withdrawal operation (the ``wopid``) to interact with the withdrawal ope // URL that the user needs to navigate to in order to // complete some final confirmation (e.g. 2FA). + // It may contain withdrawal operation id confirm_transfer_url?: string; // Wire transfer types supported by the bank. @@ -160,5 +161,6 @@ for the withdrawal operation (the ``wopid``) to interact with the withdrawal ope // complete some final confirmation (e.g. 2FA). // // Only applicable when ``transfer_done`` is ``false``. + // It may contain withdrawal operation id confirm_transfer_url?: string; } diff --git a/core/api-bank-merchant.rst b/core/api-bank-merchant.rst @@ -1,126 +0,0 @@ -.. - This file is part of GNU TALER. - Copyright (C) 2021 Taler Systems SA - - TALER 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 2.1, or (at your option) any later version. - - TALER 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 - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - -============================ -Taler Bank Merchant HTTP API -============================ - -This section describes an API offered by the Taler wire gateway. The API is -used by the merchant to query for incoming transactions. - -This API is TO BE implemented by the Taler Demo Bank, as well as by -LibEuFin (work in progress). - - --------------- -Authentication --------------- - -The bank library authenticates requests to the bank merchant API using -`HTTP basic auth <https://tools.ietf.org/html/rfc7617>`_. - --------------------------------- -Querying the transaction history --------------------------------- - - -.. http:get:: ${BASE_URL}/history - - Return a list of transactions made from an exchange to the merchant. - - Incoming transactions must contain a valid wire transfer identifier and - exchange base URL. If a bank transaction does not conform to the right - syntax, the wire gateway must not report it to the merchant via this - endpoint. - - The bank account of the merchant is determined via the base URL and/or the - user name in the ``Authorization`` header. In fact, the transaction history - might come from a "virtual" account, where multiple real bank accounts are - merged into one history. - - Transactions are identified by an opaque numeric identifier, referred to here - as *row ID*. The semantics of the row ID (including its sorting order) are - determined by the bank server and completely opaque to the client. - - The list of returned transactions is determined by a row ID *starting point* - and a signed non-zero integer *delta*: - - * If *delta* is positive, return a list of up to *delta* transactions (all matching - the filter criteria) strictly **after** the starting point. The transactions are sorted - in **ascending** order of the row ID. - * If *delta* is negative, return a list of up to *-delta* transactions (all matching - the filter criteria) strictly **before** the starting point. The transactions are sorted - in **descending** order of the row ID. - - If *starting point* is not explicitly given, it defaults to: - - * A value that is **smaller** than all other row IDs if *delta* is **positive**. - * A value that is **larger** than all other row IDs if *delta* is **negative**. - - **Request:** - - :query start: *Optional.* - Row identifier to explicitly set the *starting point* of the query. - :query delta: - The *delta* value that determines the range of the query. - :query long_poll_ms: *Optional.* If this parameter is specified and the - result of the query would be empty, the bank will wait up to ``long_poll_ms`` - milliseconds for new transactions that match the query to arrive and only - then send the HTTP response. A client must never rely on this behavior, as - the bank may return a response immediately or after waiting only a fraction - of ``long_poll_ms``. - - **Response:** - - :http:statuscode:`200 OK`: - JSON object of type `MerchantIncomingHistory`. - :http:statuscode:`400 Bad request`: - Request malformed. The bank replies with an `ErrorDetail` object. - :http:statuscode:`401 Unauthorized`: - Authentication failed, likely the credentials are wrong. - :http:statuscode:`404 Not found`: - The endpoint is wrong or the user name is unknown. The bank replies with an `ErrorDetail` object. - - .. ts:def:: MerchantIncomingHistory - - interface MerchantIncomingHistory { - - // Array of incoming transactions. - incoming_transactions : MerchantIncomingBankTransaction[]; - - } - - .. ts:def:: MerchantIncomingBankTransaction - - interface MerchantIncomingBankTransaction { - - // Opaque identifier of the returned record. - row_id: SafeUint64; - - // Date of the transaction. - date: Timestamp; - - // Amount transferred. - amount: Amount; - - // Payto URI to identify the sender of funds. - debit_account: string; - - // Base URL of the exchange where the transfer originated form. - exchange_url: string; - - // The wire transfer identifier. - wtid: WireTransferIdentifierRawP; - } diff --git a/core/api-bank-nexus.rst b/core/api-bank-nexus.rst @@ -0,0 +1,1129 @@ +.. + This file is part of GNU TALER. + + Copyright (C) 2014-2020 Taler Systems SA + + TALER 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 2.1, or (at your option) any later version. + + TALER 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 + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + + +.. target audience: core developer + +Nexus HTTP API +############## + +.. contents:: Table of Contents + +In the current version, the API calls are only available to +the superuser, when no authorization condition is explictly stated. + +Configuration +------------- + + +Returns configuration values currently used by Nexus. +This call is unauthenticated. + +.. http:get:: {nexusBase}/config + + **Response:** + + .. ts:def:: ConfigResponse + + interface ConfigResponse { + + // nexus version, X.Y.Z format. + version: string; + } + + +Authentication +-------------- + +Currently every request made to nexus must be authenticated using the *HTTP +basic auth* mechanism. + +Other authentication mechanisms (e.g. OpenID Connect) might +be supported in the future. + +User Management +--------------- + +.. http:get:: {nexusBase}/user + + Get information about the current user. The username carried + along the HTTP basic auth points at the user to be shown. + + **Response:** + + .. ts:def:: UserResponse + + interface UserResponse { + + // User name + username: string; + + // Is this a super user? + superuser: boolean; + } + +.. http:post:: {nexusBase}/users/{userName}/password + + Change password of the ``{userName}`` user. The call is + available to any superuser on any username. + + **Request:** + + .. code-block:: ts + + interface UserChangePassword { + newPassword: string; + } + + **Response:** + + :http:statuscode:`200 OK`: The password was successfully changeD. + + +.. http:post:: {nexusBase}/users + + Create a new user. Only a superuser can call this API. + + **Request:** + + The body is a `User` object. + + **Response:** + + :http:statuscode:`409 Conflict`: Username is not available. + + **Details:** + + .. ts:def:: User + + interface User { + + // User name + username: string; + + // Initial password + password: string; + } + + +.. http:get:: {nexusBase}/users + + Return the list of all users. + + **Response:** + + .. ts:def:: UsersResponse + + interface UsersResponse { + users: UserResponse[]; + } + +.. _nexus-permissions-api: + +Permissions API +--------------- + +The permissions API manages authorization of access of subjects +(usually users) to resources. + +Permissions are modeled a set of ``(subject, resource, permission)`` +triples. Subjects and resources consist of a type and an identifier. + +Superusers are not subject to further permission checks, they are +allowed to do any operation. + +The following subject types are currently supported: + +* ``user``: An authenticated user. The subject ID + is interpreted as the user ID. + +The following permissions are currently defined: + +* ``facade.talerWireGateway.history``: Allows querying the + transaction history through a Taler wire gateway facade. +* ``facade.talerWireGateway.transfer``: Allows creating payment + initiations to transfer money via a Taler wire gateway facade. + +The following resource IDs are currently supported: + +* ``facade``: A LibEuFin facade. The resource ID is interpreted + as the facade name. + +* ``bank-account``: A Nexus bank account, currently used in + `scheduled tasks <nexus-task_>`_ of type ``fetch`` and ``submit``. + +.. http:get:: {nexusbase}/permissions + + Lists all permissions. + + **Response** + + .. ts:def:: QueryPermissionsResponse + + interface QueryPermissionsResponse { + permissions: LibeufinPermission[]; + } + +.. http:post:: {nexusbase}/permissions + + Modifies permissions. + + **Request** + + .. ts:def:: QueryPermissionsResponse + + interface QueryPermissionsResponse { + action: "grant" | "revoke"; + permission: LibeufinPermission; + } + + **Response** + + The response is an empty JSON object. + + +Test API +-------- + +.. http:post:: {nexusbase}/bank-accounts/{acctid}/test-camt-ingestion/{type} + + This call allows tests to **directly** give Nexus a Camt document. After + the processing, all the payment(s) details should be ingested as if the + Camt came normally from a bank / the Sandbox. ``acctid`` must match the + label of a locally imported bank account, and ``type`` for now can only be + ``C53``. + + **Response** + + The successful case should respond with a ``200 OK`` and an empty JSON body. + +Bank Accounts +------------- + +Neuxs maintains a copy of the bank account transaction history and +balance information, manages payment initiations of the account and +tracks the initiations of payments. + +.. http:get:: {nexusBase}/bank-accounts + + **Response:** + + A list of `BankAccount` objects that belong to the requester. + The list is held in the ``accounts`` field. + + .. ts:def:: BankAccount + + interface BankAccount { + // mnemonic name identifying this bank account. + nexusBankAccountId: string; + // IBAN + iban: string; + // BIC + bic: string; + // Legal subject owning the account. + ownerName: string; + } + + +.. http:get:: {nexusBase}/bank-accounts/{my-acct} + + Get basic information about the bank account named ``my-acct``. + + .. ts:def:: BankAccountInfoWithBalance + + interface BankAccountInfoWithBalance { + // ID number of the database row being the default bank connection + // of ``my-acct``. + defaultBankConnection: number; + // Payto://-URI of ``my-acct``. + accountPaytoUri: string; + // Balance of ``my-acct`` as it was downloaded from the bank + // along the last Camt document. A human-readable message + // will inform the requester, should this value not be found. + lastSeenBalance: string; + } + +.. http:post:: {nexusBase}/bank-accounts/{acctid}/submit-all-payment-initiations + + Asks nexus to submit all the prepared initiations that weren't + already submitted. + + +.. http:post:: {nexusBase}/bank-accounts/{acctid}/payment-initiations/{pmtid}/submit + + Asks nexus to submit one prepare payment at the bank. + + :http:statuscode:`404 Not found`: the unique identifier **or** + the bank connection could not be found in the system + + +.. http:get:: {nexus}/bank-accounts/{my-acct}/payment-initiations/{uuid} + + Asks the status of payment ``$uuid``. + + **Response:** + + .. ts:def:: PaymentStatus + + interface PaymentStatus { + // Can be "BOOK" or "PDNG" ('pending'). + status: string; + + // Payment unique identifier + paymentInitiationId: string; + + // True for submitted payments + submitted: boolean; + + // Creditor IBAN + creditorIban: string; + + // Creditor BIC + creditorBic: string; + + // Creditor legal name + creditorName: string; + + // Amount + amount: string; + + // Subject + subject: string; + + // Date of submission (in dashed form YYYY-MM-DD) + submissionDate: string; + + // Date of preparation (in dashed form YYYY-MM-DD) + preparationDate: string; + } + +.. http:get:: {nexusBase}/bank-accounts/{my-acct}/payment-initiations + + Asks nexus the list of initiated payments. At this stage of the API, + **all** is returned: submitted and non-submitted payments. + + **Response** + + .. ts:def:: InitiatedPayments + + interface InitiatedPayments { + + // list of all the initiated payments' UID. + initiatedPayments: PaymentStatus[]; + } + + +.. http:post:: {nexusBase}/bank-accounts/{my-acct}/payment-initiations + + Ask nexus to prepare instructions for a new payment. + Note that ``my-acct`` is the bank account that will be + **debited** after this operation. + + **Request:** + + .. ts:def:: PreparedPaymentRequest + + interface PreparedPaymentRequest { + // IBAN that will receive the payment. + iban: string; + // BIC hosting the IBAN. + bic: string; + // Legal subject that will receive the payment. + name: string; + // payment subject. + subject: string; + // amount, in the format CURRENCY:XX.YY + amount: string, + + // This option lets the client associate a unique + // identifier to the payment being created. This + // identifier will NOT be the identifier of the resource + // created by this request, therefore it won't be possible + // to _retrieve_ the resource by using this UID. + // This UID helps, for example, if the client wrongly submits + // the same request twice, because Nexus can make it idempotent + // and avoid financial loss. + uid?: string + } + + **Response:** + + .. ts:def:: PreparedPaymentResponse + + interface PreparedPaymentResponse { + + // Opaque identifier to be communicated when + // the user wants to submit the payment to the + // bank. + uuid: string; + } + +.. http:post:: {nexusBase}/bank-accounts/{acctid}/fetch-transactions + + Nexus will download bank transactions using the given connection. + + **Request:** + + Refer to :ref:`FetchParams <fetch-params>` for + ``level`` and ``rangeType`` specifications. + + .. ts:def:: CollectedTransaction + + interface CollectedTransaction { + level: string; + rangeType: string; + // Bank connection to use. Uses the default bank connection, + // when not given. + bankConnection?: string; + } + + **Response:** + + .. code-block:: ts + + interface NewTransactions { + // How many transactions are new to Nexus. + newTransactions: number; + // How many transactions got downloaded by the request. + // Note that a transaction can be downloaded multiple + // times but only counts as new once. + downloadedTransactions: number; + } + + :http:statuscode:`500 Internal Server Error`: Nexus itself had a problem + along the operation, and not the bank. + + +.. http:get:: {nexusBase}/bank-accounts/{acctid}/transactions + + Shows the transactions fetched for ``{acctid}``, according to + the URI parameters. + + **Request:** + + :query long_poll_ms: Optional number to express how many milliseconds + the server should wait for at least one result to be shown. If not + given, the server responds immediately, regardless of the result. + :query start: Optional number to express the **earliest** transaction + index, starting from **1**. For example, if *start* is 6 and three + transactions are returned, they will have the following indexes: + 6, x, y, where x and y are both greater than 6 but not necessarily + sequential. This parameter defaults to 1. + :query size: Optional number indicating how many transactions are to + be included in the response. It defaults to 5. + + **Response:** + + :http:statuscode:`200 OK`: + a JSON object with a unique field named ``transactions`` that + is a list of `Transaction` objects. This status code applies + even for an **empty** list. The list is such that index **x-1** + is always a **earlier** transaction than **x**. For example, the + transaction having the 'start' index lies always at index zero. + Note that the order does NOT reflect the transaction's timestamp + as given by the bank, but rather the order that Nexus stored them + into its database. + + .. ts:def:: Transaction + + interface Transaction { + + // Number as a string, which is the index identifying this + // transaction at Nexus. + // Note: users can ONLY expect that this index grows + // as new transactions get fetched from the bank, but + // should NOT expect it to grow continuously. + index: string; + + // Nexus representation of a transaction. The format is shaped + // around the CaMt terminology and its XML structure. + camtData: { + // money moved by the transaction + amount: string; + + // CRDT or DBIT + creditDebitIndicator: string + + // Two of the most used values are BOOK, or PENDING + status: string; + + // FIXME + bankTransactionCode: string; + + // FIXME + valueDate: string; + + // When this payment got booked. In the form YYYY-MM-DD + bookingDate: string; + + // FIXME + accountServicerRef: string; + + // FIXME + batches: { + // list of batched transactions + batchTransactions: BatchedTransaction[]; + }; + } + } + + .. ts:def:: BatchedTransaction + + interface BatchedTransaction { + // FIXME + amount: string; + // FIXME + creditDebitIndicator: string; + // FIXME + details { + debtor: { + name: string; + }; + debtorAccount: { + iban: string; + }; + // Missing, when the payment is DBIT. + debtorAgent: { + bic: string; + }; + creditor: { + name: string; + }; + creditorAccount: { + iban: string; + }; + // Missing, when the payment is CRDT. + creditorAgent: { + iban: string; + }; + // FIXME + endToEndId: string; + // FIXME + unstructuredRemittanceInformation: string; + } + } + +Scheduling API +-------------- + +.. http:post:: {nexusBase}/bank-accounts/{acctid}/schedule + + This endpoint allows the caller to define a recurrent + execution of a task. + + **Request** + + .. ts:def:: ScheduleTask + + interface ScheduleTask { + // Name to assign to the task being created. + name: string; + + // a Unix-compatible cron pattern representing + // the frequency of execution of this task. + cronspec: string; + + // Can take values "fetch" (to download the history + // of the requester's bank account) or "submit" (to submit + // any initiated payment associated to the requester's + // bank account). + type: string; + + // Currently only used for "fetch" operations but required + // for any type of task. Whatever value "submit" tasks pass + // here, it is not going to be consumed by Nexus. Typically, + // submit tasks pass FetchParams with all of its fields set + // as null. + params: FetchParams; + } + + +.. http:get:: {nexusBase}/bank-accounts/{acctid}/schedule/{taskId} + + Shows ``taskId`` state. + + .. _nexus-task: + + **Response** + + .. ts:def:: NexusTask + + // This object is a mere reflection of + // what the Nexus database keeps to implement + // the scheduling feature. + + interface NexusTask { + // The resource being impacted by this operation. + // Typically a (Nexus) bank account being ``fetch``ed + // or whose payments are ``submit``ted. In this cases, + // this value is the "bank-account" constant. + resourceType: string; + // Name of the resource. In case of "bank-account", that + // is the name under which the bank account was imported + // from the bank. + resourceId: string; + // Task name, equals 'taskId' + taskName: string; + // Values allowed are "fetch" or "submit". + taskType: string; + // FIXME: describe. + taskCronSpec: string; + // Only meaningful for "fetch" types. + taskParams: FetchParams; + // Timestamp in secons when the next iteration will run. + nextScheduledExecutionSec: number; + // Timestamp in seconds when the previous iteration ran. + prevScheduledExecutionSec: number; + } + + +.. http:delete:: {nexusBase}/bank-accounts/{acctid}/schedule/{taskId} + + This call deletes the task associated to ``taskId``. + +.. http:get:: {nexusBase}/bank-accounts/{acctid}/schedule + + Shows all the scheduled tasks from ``acctid``. + + **Response** + + .. ts:def:: TaskCollection + + interface TaskCollection { + + // This field can contain *multiple* objects of the type sampled below. + schedule: { + + 'task-name': { + cronspec: string; + type: "fetch" | "submit"; + params: FetchParams; + } + } + } + + +Bank Connections +---------------- + +Bank connections connect the local Nexus bank account to the bank. + +.. http:post:: <nexus>/bank-connections + + Activate a new bank connection for the requesting user. + + **Request:** + + This request can accept two formats, depending on whether a + new bank connection is being made, or a connection backup is + being restored. + + + This type allows the creation of new bank accounts. + + .. _new-conn: + + .. ts:def:: NewBankConnection + + interface NewBankConnection { + + source: string; // only "new" allowed + + // connection name. + name: string; + + // type of the connection to make: "ebics" for example. + type: string; + + // Strictly dependent from the connection type. Notably, + // a "dialect" field is accepted here to adapt the EBICS client + // to one particular bank. + data: any; + } + + This type allows to restore a previously made bank connection. + + .. _restore-conn: + + .. ts:def:: BankConnectionRestore + + interface BankConnectionRestore { + + source: "backup"; + + // connection name. + name: string; + + // Backup data, as typically returned by the + // "../export-backup" API. + backup: any; + + passphrase?: string; + } + + The following examples show the EBICS types for creating and + restoring a connection. + + This type is found in the ``data`` field of `NewBankConnection <new-conn_>`_. + + .. _ebics-new-conn: + + .. ts:def:: EbicsNewConnection + + interface EbicsNewConnection { + userID: string, + partnerID: string, + hostID: string, + ebicsURL: string, + systemID?: string + } + + This type is found in the ``backup`` field of `BankConnectionRestore <restore-conn_>`_. + + .. ts:def:: EbicsBackup + + interface EbicsBackup { + type: string, // constant to "ebics" + userID: string, + partnerID: string, + hostID: string, + ebicsURL: string, + + // The following three values are the EBICS private keys. + authBlob: string, + encBlob: string, + sigBlob: string + } + + **Response:** + + :http:statuscode:`406 Not acceptable`: a connection with the + requested name already exists for this user. + +.. http:post:: {nexusBase}/bank-connections/delete-connection + + **Request:** + + .. ts:def:: BankConnectionDeletion + + interface BankConnectionDeletion { + // label of the bank connection to delete + bankConnectionId: string; + } + +.. http:get:: {nexusBase}/bank-connections + + List available bank connections. + + **Response** + + A JSON object whose ``bankConnections`` element is a list of the following type: + + .. ts:def:: BankConnection + + interface BankConnection { + + // connection type. For example "ebics". + type: string; + + // connection name as given by the user at + // the moment of creation. + name: string; + } + + +.. http:get:: {nexusBase}/bank-connections/{connId} + + Get information about one bank connection. + + .. ts:def:: BankConnectionInfo + + interface BankConnectionInfo { + type: string; + owner: string; + // if true, this connection can be used to communicate + // with the bank. + ready: boolean; + // Depends on the type. + details: any; + } + + For example, the following type occupies the ``details`` + field for EBICS connections. + + .. ts:def:: EbicsConnectionInfo + + interface EbicsConnectionInfo { + ebicsUrl: string; + ebicsHostId: string; + partnerId: string; + userId: string; + } + +.. http:post:: {nexusBase}/bank-connections/{connId}/connect + + Initialize the connection by talking to the bank. For EBICS + connections, this endpoint causes Nexus to submit its own keys + and download the bank's. That however **still** requires the + user to send the public keys to the bank via post, in order + to start operating. + +.. http:post:: {nexusBase}/bank-connections/{connId}/export-backup + + Make a passphrase-encrypted backup of this connection. + +.. http:post:: {nexusBase}/bank-connections/{connId}/fetch-accounts + + Update accounts that are accessible via this bank connection. + After this operation, Nexus has stored the names of each bank + account, under ``connId``, that the bank communicated. + + Note: after this operation, Nexus **still** needs to + `assign each bank account a local name <import-account_>`_ , + in order to start operating. + +.. _import-account: + +.. http:post:: {nexusBase}/bank-connections/{connId}/import-account + + Import a bank account provided by the connection into the Nexus. + This operation assigns a local name to one bank account that was + downloaded from the bank. + + If no Nexus bank account with the ID ``nexusBankAccountId`` exists, + a new one will be created, and it will have ``connId`` as the + default bank connection. + + If an existing local bank account whose ID equals ``nexusBankAccountId`` + already exists, this call fails if ``offeredAccountId`` and ``nexusBankAccountId`` + have different IBANs. If instead the IBAN is the same, this call merely + associates ``offeredAccountId`` to ``nexusBankAccountId`` internally + in the database without changing ``nexusBankAccountId`` default connection. + + .. ts:def:: ImportBankAccount + + interface ImportBankAccount { + + // Identifier for the bank account, as returned by /accounts + // of the bank connection. + offeredAccountId: string; + + // Nexus-local identifier for the bank account. + nexusBankAccountId: string; + } + + **Response:** + + :http:statuscode:`409 Conflict`: ``nexusBankAccountId`` exists already but + its IBAN is different from the one carried by ``offeredAccountId``. + +.. http:get:: {nexusBase}/bank-connections/{connId}/accounts + + List the bank accounts that this bank connection provides access to. + + **Response:** + + The response is a JSON object whose ``accounts`` field is a list of the + following type. + + .. ts:def:: OfferedBankAccount + + interface OfferedBankAccount { + + // Unique identifier for the offered account + offeredAccountId: string; + + // IBAN of the offered account + iban: string; + + // BIC of the account's financial institution + bic: string; + + // Account owner name + ownerName: string; + + // If the account has been imported, + // this field contains the ID of the + // Nexus bank account associated with it, + // null otherwise. + nexusBankAccountId: string | null; + } + + +.. http:get:: <nexus>/bank-connections/{connId}/messages + + List *some* details of all the ISO2022 messages gotten from + the bank. + + **Response:** + + The response is a JSON object whose ``bankMessages`` field + is a list of the following type. + + .. code-block:: ts + + interface BankMessageInfo { + + // the message type, typically how the containing layer + // (Ebics, for example) would label this information. For + // Camt.053 types, this value is "C53". + code: string; + + // the unique identifier of the message. + messageId: string; + + // bytes length of the message. + length: number; + } + +.. http:get:: <nexus>/bank-connections/{connId}/messages/{msgId} + + Return the ISO20022 XML corresponding to ``msgId``. + + +Facades +------- + +.. http:get:: <nexus>/facades/{fcid} + + **Response:** A `FacadeShowInfo` whose name is ``fcid``. + +.. http:get:: <nexus>/facades + + List available facades that belong to the requesting user. + + **Response:** A list of the following elements: + + .. ts:def:: FacadeShowInfo + + interface FacadeShowInfo { + + // Name of the facade, same as the "fcid" parameter. + name: string; + + // Type of the facade. + // For example, "taler-wire-gateway". + type: string; + + // Bas URL of the facade. + baseUrl: string; + + // details depending on the facade type. + config: any; + } + + For "taler-wire-gateway" and "anastasis" facades, + ``config`` contains the following type: + + .. ts:def:: TalerAnastasisFacadeState + + interface TalerAnastasisFacadeState { + // Bank connection this facade relies on. + bankConnection: string; + // (Nexus local) bank account associated to this facade. + bankAccount: string; + // Whether the facade seeks reports or statements from the bank. + reserveTransferLevel: string; + currency: string; + } + +.. http:delete:: {nexus}/facades/{fcid} + + Deletes a facade. + +.. http:post:: {nexus}/facades + + Creates a new facade. + + **Request:** + + .. ts:def:: FacadeInfo + + interface FacadeInfo { + // Name of the facade, same as the "fcid" parameter. + name: string; + + // Type of the facade. + // For example, "taler-wire-gateway" or "anastasis". + type: string; + + // Bank accounts that the facade has read/write access to. + bankAccountsRead?: string[]; + bankAccountsWrite?: string[]; + + // Bank connections that the facade has read/write access to. + bankConnectionsRead?: string[]; + bankConnectionsWrite?: string[]; + + // Facade-specific configuration details. Only the + // following type is available. + config: TalerAnastasisFacadeState; + } + + **Response:** + + :http:statuscode:`200 OK`: Either the facade was created, or the request was idempotent. + :http:statuscode:`409 Conflict`: The facade name was unavailable. + +Bank Connection Protocols +------------------------- + +.. http:get:: {nexus}/bank-connection-protocols + + Lists supported bank connection protocols. + +.. http:post:: {nexus}/bank-connection-protocols/ebics/test-host + + Check if Nexus can talk to an EBICS host. + This doesn't create a new connection in the database, + and is useful during setup when the user hasn't entered + the full details for the connection yet. + + .. ts:def:: EbicsHostTestRequest + + interface EbicsHostTestRequest { + ebicsBaseUrl: string; + ebicsHostId: string; + } + + +EBICS-specific APIs +------------------- + +The following endpoints are only available for EBICS bank connections. +They are namespaced under the ``/ebics/`` sub-resource. + +.. http:post:: {nexusBase}/bank-connections/{connection-name}/ebics/download/{msg} + + .. warning:: + + Use with care. Typically only necessary for testing and debugging. + + Perform an EBICS download transaction of type ``msg``. + This request will not affect any bank account or other state + in Nexus database. It will just make a request to the bank + and return the answer. + +Anastasis API. +-------------- + +This is a read-only API offering a view over *only* the incoming +transactions of a bank account. The name comes from the use in +`Anastasis <https://www.anastasis.lu>`_. + +.. http:get:: ${BASE_URL}/history/incoming + + Returns a list of transactions made to the customer. + + Transactions are identified by a numeric identifier, + that reflects the order in which Nexus downloaded each + transaction from the bank. + + The list of returned transactions is determined by a row + ID *starting point* and a signed non-zero integer *delta*: + + * If *delta* is positive, returns a list of up to *delta* + transactions (all matching the filter criteria) strictly + **after** the starting point. The transactions are sorted + in **ascending** order of the row ID. + * If *delta* is negative, return a list of up to *-delta* + transactions (all matching the filter criteria) strictly + **before** the starting point. The transactions are sorted + in **descending** order of the row ID. + + If *starting point* is not explicitly given, it defaults to: + + * A value that is **smaller** than all other row IDs if *delta* + is **positive**. + * A value that is **larger** than all other row IDs if *delta* + is **negative**. + + **Request** + + :query start: *Optional.* + Row identifier to explicitly set the *starting point* of the query. + :query delta: + The *delta* value that determines the range of the query. + :query long_poll_ms: *Optional.* If this parameter is specified and the + result of the query would be empty, Nexus will wait up to ``long_poll_ms`` + milliseconds for new transactions that match the query to arrive and only + then send the HTTP response. A client must never rely on this behavior, as + Nexus may return a response immediately or after waiting only a fraction + of ``long_poll_ms``. + + **Response** + + :http:statuscode:`200 OK`: JSON object of type `IncomingHistory`. + + :http:statuscode:`400 Bad request`: Request malformed. Nexus replies + with an `ErrorDetail` object. + + :http:statuscode:`401 Unauthorized`: Authentication failed, likely + the credentials are wrong. + + :http:statuscode:`404 Not found`: The endpoint is wrong or the user + name is unknown. Nexus replies with an `ErrorDetail` object. + + .. ts:def:: IncomingHistory + + interface IncomingHistory { + + // Array of incoming transactions. + incoming_transactions : IncomingBankTransaction[]; + + } + + .. ts:def:: IncomingBankTransaction + + interface IncomingBankTransaction { + + // Opaque identifier of the returned record. + row_id: SafeUint64; + + // Date of the transaction. + date: Timestamp; + + // Amount transferred. + amount: Amount; + + // Payto URI to identify the receiver of funds. + // Typically an exchange's bank accounts. + credit_account: string; + + // Payto URI to identify the sender of funds. + debit_account: string; + + // subject of the incoming payment. + subject: string; + } + +Reaching the facade +------------------- + +Once a facade with name ``fcid`` and type ``ftype`` has been +created, all its endpoints become offered by the following base +URL: + +.. code-block:: console + + $NEXUS_URL/facades/$fcid/$ftype + +For example, a ``taler-wire-gateway`` facade named ``foo`` will +offer its endpoints under + +.. code-block:: console + + https://nexus.example.com/facades/foo/taler-wire-gateway/ diff --git a/core/api-bank-revenue.rst b/core/api-bank-revenue.rst @@ -0,0 +1,130 @@ +.. + This file is part of GNU TALER. + Copyright (C) 2021-2023 Taler Systems SA + + TALER 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 2.1, or (at your option) any later version. + + TALER 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 + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + +.. _taler-bank-merchant-http-api: + +=========================== +Taler Bank Revenue HTTP API +=========================== + +This section describes an API offered by libeufin-nexus and libeufin-bank. The API is +used by the merchant (or other parties) to query for incoming transactions to their account. + + +-------------- +Authentication +-------------- + +The bank library authenticates requests to the bank merchant API using +`HTTP basic auth <https://tools.ietf.org/html/rfc7617>`_. + +-------------------------------- +Querying the transaction history +-------------------------------- + +.. http:get:: ${BASE_URL}/history + + Return a list of transactions made from an exchange to the merchant. + + Incoming transactions must contain a valid wire transfer identifier and + exchange base URL. If a bank transaction does not conform to the right + syntax, the wire gateway must not report it to the merchant via this + endpoint. + + The bank account of the merchant is determined via the base URL and/or the + user name in the ``Authorization`` header. In fact, the transaction history + might come from a "virtual" account, where multiple real bank accounts are + merged into one history. + + Transactions are identified by an opaque numeric identifier, referred to here + as *row ID*. The semantics of the row ID (including its sorting order) are + determined by the bank server and completely opaque to the client. + + The list of returned transactions is determined by a row ID *starting point* + and a signed non-zero integer *delta*: + + * If *delta* is positive, return a list of up to *delta* transactions (all matching + the filter criteria) strictly **after** the starting point. The transactions are sorted + in **ascending** order of the row ID. + * If *delta* is negative, return a list of up to *-delta* transactions (all matching + the filter criteria) strictly **before** the starting point. The transactions are sorted + in **descending** order of the row ID. + + If *starting point* is not explicitly given, it defaults to: + + * A value that is **smaller** than all other row IDs if *delta* is **positive**. + * A value that is **larger** than all other row IDs if *delta* is **negative**. + + **Request:** + + :query start: *Optional.* + Row identifier to explicitly set the *starting point* of the query. + :query delta: + The *delta* value that determines the range of the query. + :query long_poll_ms: *Optional.* If this parameter is specified and the + result of the query would be empty, the bank will wait up to ``long_poll_ms`` + milliseconds for new transactions that match the query to arrive and only + then send the HTTP response. A client must never rely on this behavior, as + the bank may return a response immediately or after waiting only a fraction + of ``long_poll_ms``. + + **Response:** + + :http:statuscode:`200 OK`: + JSON object of type `MerchantIncomingHistory`. + :http:statuscode:`400 Bad request`: + Request malformed. The bank replies with an `ErrorDetail` object. + :http:statuscode:`401 Unauthorized`: + Authentication failed, likely the credentials are wrong. + :http:statuscode:`404 Not found`: + The endpoint is wrong or the user name is unknown. The bank replies with an `ErrorDetail` object. + + .. ts:def:: MerchantIncomingHistory + + interface MerchantIncomingHistory { + + // Array of incoming transactions. + incoming_transactions : MerchantIncomingBankTransaction[]; + + // Payto URI to identify the receiver of funds. + // This must be one of the merchant's bank accounts. + // Credit account is shared by all incoming transactions + // as per the nature of the request. + credit_account: string; + + } + + .. ts:def:: MerchantIncomingBankTransaction + + interface MerchantIncomingBankTransaction { + + // Opaque identifier of the returned record. + row_id: SafeUint64; + + // Date of the transaction. + date: Timestamp; + + // Amount transferred. + amount: Amount; + + // Payto URI to identify the sender of funds. + debit_account: string; + + // Base URL of the exchange where the transfer originated form. + exchange_url: string; + + // The wire transfer identifier. + wtid: WireTransferIdentifierRawP; + } diff --git a/core/api-bank-wire.rst b/core/api-bank-wire.rst @@ -0,0 +1,402 @@ +.. + This file is part of GNU TALER. + Copyright (C) 2019-2023 Taler Systems SA + + TALER 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 2.1, or (at your option) any later version. + + TALER 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 + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + +=========================== +Taler Wire Gateway HTTP API +=========================== + +This section describes the API offered by the Taler wire gateway. The API is +used by the exchange to trigger transactions and query incoming transactions, as +well as by the auditor to query incoming and outgoing transactions. + +This API is currently implemented by the Taler Demo Bank, as well as by +LibEuFin (work in progress). + + +-------------- +Authentication +-------------- + +The bank library authenticates requests to the wire gateway via +`HTTP basic auth <https://tools.ietf.org/html/rfc7617>`_. + +------------------- +Making Transactions +------------------- + +.. http:post:: ${BASE_URL}/transfer + + This API allows the exchange to make a transaction, typically to a merchant. The bank account + of the exchange is not included in the request, but instead derived from the user name in the + authentication header and/or the request base URL. + + To make the API idempotent, the client must include a nonce. Requests with the same nonce + are rejected unless the request is the same. + + **Request:** The body of this request must have the format of a `TransferRequest`. + + **Response:** + + :http:statuscode:`200 OK`: + The request has been correctly handled, so the funds have been transferred to + the recipient's account. The body is a `TransferResponse`. + :http:statuscode:`400 Bad request`: + Request malformed. The bank replies with an `ErrorDetail` object. + :http:statuscode:`401 Unauthorized`: + Authentication failed, likely the credentials are wrong. + :http:statuscode:`404 Not found`: + The endpoint is wrong or the user name is unknown. The bank replies with an `ErrorDetail` object. + :http:statuscode:`409 Conflict`: + A transaction with the same ``transaction_uid`` but different transaction details + has been submitted before. + + **Details:** + + .. ts:def:: TransferResponse + + interface TransferResponse { + + // Timestamp that indicates when the wire transfer will be executed. + // In cases where the wire transfer gateway is unable to know when + // the wire transfer will be executed, the time at which the request + // has been received and stored will be returned. + // The purpose of this field is for debugging (humans trying to find + // the transaction) as well as for taxation (determining which + // time period a transaction belongs to). + timestamp: Timestamp; + + // Opaque ID of the transaction that the bank has made. + row_id: SafeUint64; + } + + + .. ts:def:: TransferRequest + + interface TransferRequest { + // Nonce to make the request idempotent. Requests with the same + // ``transaction_uid`` that differ in any of the other fields + // are rejected. + request_uid: HashCode; + + // Amount to transfer. + amount: Amount; + + // Base URL of the exchange. Shall be included by the bank gateway + // in the appropriate section of the wire transfer details. + exchange_base_url: string; + + // Wire transfer identifier chosen by the exchange, + // used by the merchant to identify the Taler order(s) + // associated with this wire transfer. + wtid: ShortHashCode; + + // The recipient's account identifier as a payto URI. + credit_account: string; + } + + +-------------------------------- +Querying the transaction history +-------------------------------- + + +.. http:get:: ${BASE_URL}/history/incoming + + Return a list of transactions made from or to the exchange. + + Incoming transactions must contain a valid reserve public key. If a bank + transaction does not conform to the right syntax, the wire gateway must not + report it to the exchange, and send funds back to the sender if possible. + + The bank account of the exchange is determined via the base URL and/or the + user name in the ``Authorization`` header. In fact the transaction history + might come from a "virtual" account, where multiple real bank accounts are + merged into one history. + + Transactions are identified by an opaque numeric identifier, referred to here + as *row ID*. The semantics of the row ID (including its sorting order) are + determined by the bank server and completely opaque to the client. + + The list of returned transactions is determined by a row ID *starting point* + and a signed non-zero integer *delta*: + + * If *delta* is positive, return a list of up to *delta* transactions (all matching + the filter criteria) strictly **after** the starting point. The transactions are sorted + in **ascending** order of the row ID. + * If *delta* is negative, return a list of up to *-delta* transactions (all matching + the filter criteria) strictly **before** the starting point. The transactions are sorted + in **descending** order of the row ID. + + If *starting point* is not explicitly given, it defaults to: + + * A value that is **smaller** than all other row IDs if *delta* is **positive**. + * A value that is **larger** than all other row IDs if *delta* is **negative**. + + **Request:** + + :query start: *Optional.* + Row identifier to explicitly set the *starting point* of the query. + :query delta: + The *delta* value that determines the range of the query. + :query long_poll_ms: *Optional.* If this parameter is specified and the + result of the query would be empty, the bank will wait up to ``long_poll_ms`` + milliseconds for new transactions that match the query to arrive and only + then send the HTTP response. A client must never rely on this behavior, as + the bank may return a response immediately or after waiting only a fraction + of ``long_poll_ms``. + + **Response:** + + :http:statuscode:`200 OK`: + JSON object of type `IncomingHistory`. + :http:statuscode:`204 No content`: + There are not transactions to report (under the given filter). + :http:statuscode:`400 Bad request`: + Request malformed. The bank replies with an `ErrorDetail` object. + :http:statuscode:`401 Unauthorized`: + Authentication failed, likely the credentials are wrong. + :http:statuscode:`404 Not found`: + The endpoint is wrong or the user name is unknown. The bank replies with an `ErrorDetail` object. + + .. ts:def:: IncomingHistory + + interface IncomingHistory { + + // Array of incoming transactions. + incoming_transactions : IncomingBankTransaction[]; + + // Payto URI to identify the receiver of funds. + // This must be one of the exchange's bank accounts. + // Credit account is shared by all incoming transactions + // as per the nature of the request. + credit_account: string; + + } + + .. ts:def:: IncomingBankTransaction + + // Union discriminated by the "type" field. + type IncomingBankTransaction = + | IncomingReserveTransaction + | IncomingWadTransaction; + + .. ts:def:: IncomingReserveTransaction + + interface IncomingReserveTransaction { + type: "RESERVE"; + + // Opaque identifier of the returned record. + row_id: SafeUint64; + + // Date of the transaction. + date: Timestamp; + + // Amount transferred. + amount: Amount; + + // Payto URI to identify the sender of funds. + debit_account: string; + + // The reserve public key extracted from the transaction details. + reserve_pub: EddsaPublicKey; + + } + + .. ts:def:: IncomingWadTransaction + + interface IncomingWadTransaction { + type: "WAD"; + + // Opaque identifier of the returned record. + row_id: SafeUint64; + + // Date of the transaction. + date: Timestamp; + + // Amount transferred. + amount: Amount; + + // Payto URI to identify the receiver of funds. + // This must be one of the exchange's bank accounts. + credit_account: string; + + // Payto URI to identify the sender of funds. + debit_account: string; + + // Base URL of the exchange that originated the wad. + origin_exchange_url: string; + + // The reserve public key extracted from the transaction details. + wad_id: WadId; + } + + +.. http:get:: ${BASE_URL}/history/outgoing + + Return a list of transactions made by the exchange, typically to a merchant. + + The bank account of the exchange is determined via the base URL and/or the + user name in the ``Authorization`` header. In fact the transaction history + might come from a "virtual" account, where multiple real bank accounts are + merged into one history. + + Transactions are identified by an opaque integer, referred to here as *row + ID*. The semantics of the row ID (including its sorting order) are + determined by the bank server and completely opaque to the client. + + The list of returned transactions is determined by a row ID *starting point* + and a signed non-zero integer *delta*: + + * If *delta* is positive, return a list of up to *delta* transactions (all matching + the filter criteria) strictly **after** the starting point. The transactions are sorted + in **ascending** order of the row ID. + * If *delta* is negative, return a list of up to *-delta* transactions (all matching + the filter criteria) strictly **before** the starting point. The transactions are sorted + in **descending** order of the row ID. + + If *starting point* is not explicitly given, it defaults to: + + * A value that is **smaller** than all other row IDs if *delta* is **positive**. + * A value that is **larger** than all other row IDs if *delta* is **negative**. + + **Request:** + + :query start: *Optional.* + Row identifier to explicitly set the *starting point* of the query. + :query delta: + The *delta* value that determines the range of the query. + :query long_poll_ms: *Optional.* If this parameter is specified and the + result of the query would be empty, the bank will wait up to ``long_poll_ms`` + milliseconds for new transactions that match the query to arrive and only + then send the HTTP response. A client must never rely on this behavior, as + the bank may return a response immediately or after waiting only a fraction + of ``long_poll_ms``. + + **Response:** + + :http:statuscode:`200 OK`: + JSON object of type `OutgoingHistory`. + :http:statuscode:`204 No content`: + There are not transactions to report (under the given filter). + :http:statuscode:`400 Bad request`: + Request malformed. The bank replies with an `ErrorDetail` object. + :http:statuscode:`401 Unauthorized`: + Authentication failed, likely the credentials are wrong. + :http:statuscode:`404 Not found`: + The endpoint is wrong or the user name is unknown. The bank replies with an `ErrorDetail` object. + + .. ts:def:: OutgoingHistory + + interface OutgoingHistory { + + // Array of outgoing transactions. + outgoing_transactions : OutgoingBankTransaction[]; + + // Payto URI to identify the sender of funds. + // This must be one of the exchange's bank accounts. + // Credit account is shared by all incoming transactions + // as per the nature of the request. + debit_account: string; + + } + + .. ts:def:: OutgoingBankTransaction + + interface OutgoingBankTransaction { + + // Opaque identifier of the returned record. + row_id: SafeUint64; + + // Date of the transaction. + date: Timestamp; + + // Amount transferred. + amount: Amount; + + // Payto URI to identify the receiver of funds. + credit_account: string; + + // The wire transfer ID in the outgoing transaction. + wtid: ShortHashCode; + + // Base URL of the exchange. + exchange_base_url: string; + } + + +----------------------- +Wire Transfer Test APIs +----------------------- + +Endpoints in this section are only used for integration tests and never +exposed by bank gateways in production. + +.. _twg-admin-add-incoming: + +.. http:post:: ${BASE_URL}/admin/add-incoming + + Simulate a transfer from a customer to the exchange. This API is *not* + idempotent since it's only used in testing. + + **Request:** The body of this request must have the format of a `AddIncomingRequest`. + + **Response:** + + :http:statuscode:`200 OK`: + The request has been correctly handled, so the funds have been transferred to + the recipient's account. The body is a `AddIncomingResponse`. + :http:statuscode:`400 Bad request`: + The request is malformed. The bank replies with an `ErrorDetail` object. + :http:statuscode:`401 Unauthorized`: + Authentication failed, likely the credentials are wrong. + :http:statuscode:`404 Not found`: + The endpoint is wrong or the user name is unknown. The bank replies with an `ErrorDetail` object. + :http:statuscode:`409 Conflict`: + The 'reserve_pub' argument was used previously in another transfer, and the specification mandates that reserve public keys must not be reused. + + .. ts:def:: AddIncomingRequest + + interface AddIncomingRequest { + // Amount to transfer. + amount: Amount; + + // Reserve public key that is included in the wire transfer details + // to identify the reserve that is being topped up. + reserve_pub: EddsaPublicKey; + + // Account (as payto URI) that makes the wire transfer to the exchange. + // Usually this account must be created by the test harness before this API is + // used. An exception is the "exchange-fakebank", where any debit account can be + // specified, as it is automatically created. + debit_account: string; + } + + + .. ts:def:: AddIncomingResponse + + interface AddIncomingResponse { + + // Timestamp that indicates when the wire transfer will be executed. + // In cases where the wire transfer gateway is unable to know when + // the wire transfer will be executed, the time at which the request + // has been received and stored will be returned. + // The purpose of this field is for debugging (humans trying to find + // the transaction) as well as for taxation (determining which + // time period a transaction belongs to). + timestamp: Timestamp; + + // Opaque ID of the transaction that the bank has made. + row_id: SafeUint64; + } diff --git a/core/api-bank.rst b/core/api-bank.rst @@ -0,0 +1,38 @@ +.. + This file is part of GNU TALER. + Copyright (C) 2014-2023 Taler Systems SA + + TALER 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 2.1, or (at your option) any later version. + + TALER 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 + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + + @author Florian Dold + @author Benedikt Muller + @author Sree Harsha Totakura + @author Marcello Stanisci + @author Christian Grothoff + +================= +Bank RESTful APIs +================= + + +.. toctree:: + :maxdepth: 1 + + api-bank-wire + api-bank-revenue + api-bank-integration + api-libeufin-bank + api-bank-nexus + + +.. toctree:: + :hidden: diff --git a/core/api-challenger.rst b/core/api-challenger.rst @@ -0,0 +1,340 @@ +.. + This file is part of GNU TALER. + Copyright (C) 2023 Taler Systems SA + + TALER 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 2.1, or (at your option) any later version. + + TALER 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 + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + + @author Christian Grothoff + +.. _challenger-api: + +====================== +Challenger Service API +====================== + +The challenger service validates that a user is able to receive challenges at +an address (such as e-mail or SMS) and allows an OAuth 2.0 client to obtain +access to these validated addresses. + +The high-level flow is that an OAuth 2.0 client is first registered with the +challenger service (via command-line). Using the command-line tool will print +the resulting client ID to the console. + + .. note:: + + The current service mandates that redirection URIs + start with "http://" or "https://". See issue #7838 + for what should be done to lift this restriction. + + .. note:: + + Right now, registration of a unique redirection URI is *mandatory* for + each client. If multiple redirection URIs are needed, it is suggested to + just register additional clients. (While OAuth 2.0 would support not + registering fixed redirection URIs with a client, this is not recommended + as it would create an open redirector.) + +Once a client is registered, that client can use the challenger service when +it needs a user to prove that the user is able to receive messages at a +particular address. However, asking a user to prove access to a particular +address can be expensive as it may involve sending an SMS or even postal mail +depending on the type of address. Thus, challenger does not allow a user +agent to begin an address validation process without prior approval by a +registered client. Thus, the process begins with a ``/setup`` request where a +client requests challenger to begin an address validation request. The +``/setup`` response contains a ``nonce`` which is then used to construct the +URL of the endpoint to which the client must redirect the user-agent to begin +the address validation and authorization process. + +The client then redirects the user-agent to the ``/authorize/$NONCE`` endpoint +of the challenger service, adding its ``state``, ``client_id`` and +``redirect_uri`` as query parameters. The ``redirect_uri`` must match the +redirect URI registered with the client. From this endpoint, the challenger +service will return a Web page asking the user to provide its address. + + .. note:: + + Challenger is a bit unusual in that the ``$NONCE`` in the endpoint URL + makes the authorization endpoint URL (deliberately) unpredictable, while + for many other OAuth 2.0 APIs this endpoint is static. However, this is + compliant with OAuth 2.0 as determining the authorization URL is left out + of the scope of the standard. + +When the user has filled in the form with their address, it will be submitted +to the ``/challenge/$NONCE`` endpoint and the challenger service will send a +challenge to the user's address and generate an HTML form asking the user to +enter the received challenge value. + +The user can then enter the answer to the challenge which is then submitted to +the ``/solve/$NONCE`` endpoint. If the answer is correct, the user agent will +be redirected to the client redirect URI that was specified by the OAuth 2.0 +client upon ``/authorize``, together with an authorization grant encoded in +the redirection URI. + +Given this authorization grant, the OAuth 2.0 client can then use the +``/token`` endpoint to obtain an access token which will grant it access to +the resource. + +Using the ``/info`` endpoint the client can then finally obtain the (now) +verified address of the user. + +.. contents:: Table of Contents + +.. include:: tos.rst + +----------------------- +Receiving Configuration +----------------------- + +.. http:get:: /config + + Obtain the key configuration settings of the storage service. + + **Response:** + + Returns a `ChallengerTermsOfServiceResponse`. + + .. ts:def:: ChallengerTermsOfServiceResponse + + interface ChallengerTermsOfServiceResponse { + // Name of the service + name: "challenger"; + + // libtool-style representation of the Challenger protocol version, see + // https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning + // The format is "current:revision:age". + version: string; + + } + +.. _challenger-setup: + +----- +Setup +----- + +.. http:post:: /setup/$CLIENT_ID + + This endpoint is used by the client to authorize the execution of an address + validation on its behalf. An ``Authorization`` header (for now always using + a ``Bearer`` token) should be included to provide the client's credentials + to authorize access to the challenger service. This token must match the + ``client_secret`` from the registration of the client with the challenger + service (which will also be used in the later ``/token`` request). + + **Response:** + + :http:statuscode:`200 OK`: + Response is a `ChallengeSetupResponse`. + :http:statuscode:`404 Not found`: + The backup service is unaware of a matching client. + or the credentials of the client are invalid. + + **Details::** + + .. ts:def:: ChallengeSetupResponse + + interface ChallengeSetupResponse { + // Nonce to use when constructing ``/authorize`` endpoint. + nonce: string; + } + + +.. _challenger-login: + +----- +Login +----- + +.. http:get:: /authorize/$NONCE +.. http:post:: /authorize/$NONCE + + This is the "authorization" endpoint of the OAuth 2.0 protocol. This + endpoint is used by the user-agent. It will return a form to enter the + address. + + **Request:** + + :query response_type: Must be ``code`` + :query client_id: Identifier of the client. + :query redirect_uri: URI-encoded redirection URI to use upon authorization. + :query state: Arbitrary client state to associate with the request. + :query scope: Not supported, any value is accepted. + + **Response:** + + :http:statuscode:`200 OK`: + The body contains a form to be submitted by the user-agent. + The form will ask the user to specify their address. + :http:statuscode:`404 Not found`: + The backup service is unaware of a matching $NONCE. + + +.. _challenger-challenge: + +--------- +Challenge +--------- + +.. http:post:: /challenge/$NONCE + + This endpoint is used by the user-agent to submit the address to which a + challenge should be sent by the challenger service. + + **Request:** + + Body should use the mime-type "application/x-www-form-urlencoded". + The posted form data must contain an "address". + + **Response:** + + :http:statuscode:`200 OK`: + The body contains a form asking for the answer to + the challenge to be entered by the user. + :http:statuscode:`404 Not found`: + The challenger service is unaware of a matching nonce. + :http:statuscode:`429 Too Many Requests`: + There have been too many attempts to request challenge + transmissions for this $NONCE. The user-agent should + wait and (eventually) request a fresh nonce to be set + up by the client. + + +.. _challenger-solve: + +----- +Solve +----- + +.. http:post:: /solve/$NONCE + + Used by the user-agent to submit an answer to the challenge. If the answer + is correct, the user will be redirected to the client's redirect URI, + otherwise the user may be given another chance to complete the process. + + **Request:** + + Depends on the form from ``/challenge``. TBD. + + **Response:** + + :http:statuscode:`302 Found`: + The user is redirected to the redirect URI of the client to pass the + grant to the client. The target will be the redirect URI specified + by the client (during registration and again upon ``/authorize``), + plus a ``code`` argument with the authorization code, and the + ``state`` argument from the ``/authorize`` endpoint. + :http:statuscode:`403 Forbidden`: + The solution of the user to the challenge is invalid. + :http:statuscode:`404 Not found`: + The service is unaware of a matching challenge. + :http:statuscode:`429 Too Many Requests`: + There have been too many attempts to solve the challenge + for this address (and $NONCE). The user-agent should + either try a different address (or wait and (eventually) + request a fresh nonce to be set up by the client). + + +.. _challenger-auth: + +---- +Auth +---- + +.. http:post:: /token + + This is the token endpoint of the OAuth 2.0 specification. + This endpoint is used by the client to provide its authorization code, + demonstrating that it has the right to learn a particular user's validated + address. In return, the challenger service returns the access token. + Renewal is not supported. + + **Request:** + + The request must include an ``application/www-form-urlencoded`` body + specifying the ``client_id``, ``redirect_uri``, ``client_secret``, ``code`` + and ``grant_type``. The ``grant_type`` must be set to + ``authorization_code``. The ``redirect_uri`` must match the URI from + ``/authorize``. The ``code`` must be the authorization code that ``/solve`` + returned to the user. The ``client_id`` and ``client_secret`` must match + the usual client credentials. + + **Response:** + + Error responses follow RFC 6749, section 5.2 with an "error" field in JSON, + as well as also returning GNU Taler style error messages. + + :http:statuscode:`200 OK`: + The body will be a `ChallengerAuthResponse` + :http:statuscode:`403 Forbidden`: + The credentials of the client are invalid. + :http:statuscode:`404 Not found`: + The service is unaware of a matching login process. + + **Details::** + + .. ts:def:: ChallengerAuthResponse + + interface ChallengerAuthResponse { + // Token used to authenticate access in ``/info``. + access_token: string; + + // Type of the access token. + token_type: "Bearer"; + + // Amount of time that an access token is valid (in seconds). + expires_in: Integer; + + } + + +.. _challenger-info: + +---- +Info +---- + +.. http:get:: /info + + This userinfo endpoint of the OAuth 2.0 specification. + This endpoint is used by the client to obtain the user's validated address. + + **Request:** + + Must include the token returned to the client from the ``/token`` endpoint + as a ``Bearer`` token in an ``Authorization`` header. + + **Response:** + + :http:statuscode:`200 OK`: + The body contains the address as a `ChallengerInfoResponse`. + :http:statuscode:`403 Forbidden`: + The bearer token is missing or invalid (malformed). + :http:statuscode:`404 Not found`: + The bearer token is invalid (includes unknown or expired). + + **Details::** + + .. ts:def:: ChallengerInfoResponse + + interface ChallengerInfoResponse { + // Address that was validated. + address: string; + + // Type of the address. + address_type: string; + + // How long do we consider the address to be + // valid for this user. + expires: Timestamp; + + } diff --git a/core/api-common.rst b/core/api-common.rst @@ -18,9 +18,11 @@ .. _http-common: -================================= -Common Taler HTTP API Conventions -================================= +.. _foo_bar: + +================================== +Conventions for Taler RESTful APIs +================================== ------------------------- @@ -186,6 +188,29 @@ Examples: to decide whether it will talk to the service. +.. _error-codes: + +----------- +Error Codes +----------- + +All error codes used in GNU Taler are defined in +`GANA <https://git.gnunet.org/gana.git/tree/gnu-taler-error-codes/>`__. + +This centralized registry also contains generators that create enumerations +and mappings from error codes to HTTP status codes and human-readable error +messages for various programming languages. + +All error codes have numeric values below 100 or above 1000, so as to never be +confused with HTTP status codes. A value of 0 is reserved for "no error" or +"success". + +In C, the respective enumeration is the ``enum TALER_ErrorCode``. + +Developers may have to re-run ``bootstrap`` and/or update their Git +submodules to ensure that they have the lastest GANA registry. + + .. _encodings-ref: ---------------- @@ -212,6 +237,7 @@ resulting encoding. Hash codes ^^^^^^^^^^ + Hash codes are strings representing base32 encoding of the respective hashed data. See `base32`_. @@ -352,6 +378,99 @@ Objects // JavaScript objects, no further restrictions. type Object = object; + +Contact details +^^^^^^^^^^^^^^^ + +.. ts:def:: EmailAddress + + type EmailAddress = string; + +.. ts:def:: PhoneNumber + + type PhoneNumber = string; + +Phone numbers should start with the ``+`` symbol and the country code. + +Ratios and Fees +^^^^^^^^^^^^^^^ + +.. ts:def:: LibeufinNumber + + type LibeufinNumber = number; + +**Note:** this quantity is normally enforced to have at most +two decimal digits. The reason is to preserve the 2-decimal +digits policy of the `Amount` type, as `LibeufinNumber` is used +to multiply `Amount`. + +Amounts +^^^^^^^ + +.. ts:def:: Amount + + type Amount = string; + +Amounts have the ``$currency:X.Y`` format, where the +fractional part is optional and may contain at most two +digits. + +Permissions +^^^^^^^^^^^ + +This type epresses which permissions for a subject +apply on a resource. + +.. ts:def:: LibeufinPermission + + interface LibeufinPermission { + subjectType: string; + subjectId: string; + resourceType: string; + resourceId: string; + permissionName: string + } + + +Fetch params +^^^^^^^^^^^^ + +.. _fetch-params: + +.. ts:def:: FetchParams + + interface FetchParams { + + // Because transactions are delivered by banks in "batches", + // then every batch can have different qualities. This value + // lets the request specify which type of batch ought to be + // returned. Currently, the following two type are supported: + // + // 'report': typically includes only non booked transactions. + // 'statement': typically includes only booked transactions. + level: "report" | "statement" | "all"; + + // This type indicates the time range of the query. + // It allows the following values: + // + // 'latest': retrieves the last transactions from the bank. + // If there are older unread transactions, those will *not* + // be downloaded. + // + // 'all': retrieves all the transactions from the bank, + // until the oldest. + // + // 'previous-days': currently *not* implemented, it will allow + // the request to download transactions from + // today until N days before. + // + // 'since-last': retrieves all the transactions since the last + // time one was downloaded. + // + rangeType: "latest" | "all" | "previous-days" | "since-last"; + }; + + Keys ^^^^ @@ -424,8 +543,31 @@ Blinded coin .. ts:def:: CoinEnvelope - // Blinded coin's `public EdDSA key <eddsa-coin-pub>`, `base32` encoded. - type CoinEnvelope = string; + // The type of a coin's blinded envelope depends on the cipher that is used + // for signing with a denomination key. + type CoinEnvelope = RSACoinEnvelope | CSCoinEnvelope ; + +.. ts:def:: RSACoinEnvelope + + // For denomination signatures based on RSA, the planchet is just a blinded + // coin's `public EdDSA key <eddsa-coin-pub>`. + interface RSACoinEnvelope { + cipher: "RSA" | "RSA+age_restricted"; + rsa_blinded_planchet: string; // Crockford `Base32` encoded + } + +.. ts:def:: CSCoinEnvelope + + // For denomination signatures based on Blind Clause-Schnorr, the planchet + // consists of the public nonce and two Curve25519 scalars which are two + // blinded challenges in the Blinded Clause-Schnorr signature scheme. + // See https://taler.net/papers/cs-thesis.pdf for details. + interface CSCoinEnvelope { + cipher: "CS" | "CS+age_restricted"; + cs_nonce: string; // Crockford `Base32` encoded + cs_blinded_c0: string; // Crockford `Base32` encoded + cs_blinded_c1: string; // Crockford `Base32` encoded + } .. ts:def:: DenominationBlindingKeyP @@ -804,6 +946,7 @@ uses 512-bit hash codes (64 bytes). Signatures ^^^^^^^^^^ + Any piece of signed data, complies to the abstract data structure given below. .. sourcecode:: c @@ -865,14 +1008,33 @@ within the */ struct GNUNET_CRYPTO_EccSignaturePurpose purpose; struct TALER_ReservePublicKeyP reserve_pub; - struct GNUNET_HashCode age_restricted_coins_commitment; - struct GNUNET_HashCode h_denoms_h; - uint8 max_age_group; + /** + * This is the running SHA512-hash over n*kappa + * `struct TALER_BlindedCoinHash` values + */ + struct GNUNET_HashCode h_commitment; + struct TALER_AgeMask mask; + uint8_t max_age_group; + }; + +.. _TALER_AgeWithdrawConfirmationPS: + +.. sourcecode:: c + + struct TALER_AgeWithdrawConfirmationPS { + /** + * purpose.purpose = TALER_SIGNATURE_EXCHANGE_CONFIRM_AGE_WITHDRAW + */ + struct GNUNET_CRYPTO_EccSignaturePurpose purpose; + struct GNUNET_HashCode h_commitment; + uint32_t noreveal_index; }; .. _TALER_DepositRequestPS: + .. sourcecode:: c + :caption: struct declaration struct TALER_DepositRequestPS { /** @@ -889,10 +1051,14 @@ within the struct TALER_AmountNBO amount_with_fee; struct TALER_AmountNBO deposit_fee; struct TALER_MerchantPublicKeyP merchant; + struct TALER_OutputCommitmentHash h_outputs; + struct GNUNET_HashCode wallet_data_hash; }; .. _TALER_DepositConfirmationPS: + .. sourcecode:: c + :caption: struct declaration struct TALER_DepositConfirmationPS { /** @@ -992,6 +1158,9 @@ within the */ struct GNUNET_CRYPTO_EccSignaturePurpose purpose; struct TALER_PaytoHash h_wire_details; + struct GNUNET_HashCode h_conversion_url; + struct GNUNET_HashCode h_credit_restrictions; + struct GNUNET_HashCode h_debit_restrictions; }; .. _TALER_MasterWireFeePS: @@ -1660,6 +1829,9 @@ within the struct GNUNET_CRYPTO_EccSignaturePurpose purpose; struct GNUNET_TIME_AbsoluteNBO start_date; struct TALER_PaytoHash h_wire; + struct GNUNET_HashCode h_conversion_url; + struct GNUNET_HashCode h_credit_restrictions; + struct GNUNET_HashCode h_debit_restrictions; }; .. _TALER_MasterDelWirePS: @@ -1755,4 +1927,4 @@ within the struct GNUNET_TIME_TimestampNBO expiration_time; struct TALER_ReservePublicKeyP reserve_pub; struct GNUNET_HashCode h_attributes; - }; + }; diff --git a/core/api-error.rst b/core/api-error.rst @@ -1,41 +0,0 @@ -.. - This file is part of GNU TALER. - - Copyright (C) 2014-2023 Taler Systems SA - - TALER 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 2.1, or (at your option) any later version. - - TALER 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 - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - - @author Marcello Stanisci - @author Christian Grothoff - -.. _error-codes: -.. _TALER_ErrorCode: - ------------ -Error Codes ------------ - -All error codes used in GNU Taler are defined in -`GANA <https://git.gnunet.org/gana.git/tree/gnu-taler-error-codes/>`__. - -This centralized registry also contains generators that create enumerations -and mappings from error codes to HTTP status codes and human-readable error -messages for various programming languages. - -All error codes have numeric values below 100 or above 1000, so as to never be -confused with HTTP status codes. A value of 0 is reserved for "no error" or -"success". - -In C, the respective enumeration is the ``enum TALER_ErrorCode``. - -Developers may have to re-run ``bootstrap`` and/or update their Git -submodules to ensure that they have the lastest GANA registry. diff --git a/core/api-exchange.rst b/core/api-exchange.rst @@ -24,6 +24,8 @@ for all details not specified in the individual requests. The `glossary <https://docs.taler.net/glossary.html#glossary>`_ defines all specific terms used in this section. +.. contents:: Table of Contents + .. include:: tos.rst .. _keys: @@ -114,11 +116,52 @@ possibly by using HTTPS. // The exchange's currency or asset unit. currency: string; + // How many digits should the amounts be rendered + // with by default. Small capitals should + // be used to render fractions beyond the number + // given here (like on gas stations). + currency_fraction_digits: Integer; + + // Absolute cost offset for the STEFAN curve used + // to (over) approximate fees payable by amount. + stefan_abs: Amount; + + // Factor to multiply the logarithm of the amount + // with to (over) approximate fees payable by amount. + // Note that the total to be paid is first to be + // divided by the smallest denomination to obtain + // the value that the logarithm is to be taken of. + stefan_log: Amount; + + // Linear cost factor for the STEFAN curve used + // to (over) approximate fees payable by amount. + // + // Note that the total to be paid is first to be + // divided by the smallest denomination to obtain + // the value to be multiplied with. + stefan_lin: Amount; + // Type of the asset. "fiat", "crypto", "regional" // or "stock". Wallets should adjust their UI/UX // based on this value. asset_type: string; + // Array of wire accounts operated by the exchange for + // incoming wire transfers. + accounts: WireAccount[]; + + // Object mapping names of wire methods (i.e. "iban" or "x-taler-bank") + // to wire fees. + wire_fees: { method : AggregateTransferFee[] }; + + // List of exchanges that this exchange is partnering + // with to enable wallet-to-wallet transfers. + wads: ExchangePartner[]; + + // Set to true if this exchange allows the use + // of reserves for rewards. + rewards_allowed: boolean; + // EdDSA master public key of the exchange, used to sign entries // in ``denoms`` and ``signkeys``. master_public_key: EddsaPublicKey; @@ -188,6 +231,7 @@ possibly by using HTTPS. // explicitly as the client might otherwise be confused by clock skew as to // which signing key was used. eddsa_pub: EddsaPublicKey; + } .. ts:def:: GlobalFees @@ -346,6 +390,15 @@ possibly by using HTTPS. // be settled, as the exchange will afterwards destroy its evidence relating to // transactions involving this coin. stamp_expire_legal: Timestamp; + + // Set to 'true' if the exchange somehow "lost" + // the private key. The denomination was not + // necessarily revoked, but still cannot be used + // to withdraw coins at this time (theoretically, + // the private key could be recovered in the + // future; coins signed with the private key + // remain valid). + lost?: boolean; } .. ts:def:: Denom @@ -532,7 +585,7 @@ possibly by using HTTPS. // Object mapping names of wire methods (i.e. "iban" or "x-taler-bank") // to wire fees. - fees: { method : AggregateTransferFee }; + fees: { method : AggregateTransferFee[] }; // List of exchanges that this exchange is partnering // with to enable wallet-to-wallet transfers. @@ -547,12 +600,71 @@ possibly by using HTTPS. // ``payto://`` URI identifying the account and wire method payto_uri: string; + // URI to convert amounts from or to the currency used by + // this wire account of the exchange. Missing if no + // conversion is applicable. + conversion_url?: string; + + // Restrictions that apply to bank accounts that would send + // funds to the exchange (crediting this exchange bank account). + // Optional, empty array for unrestricted. + credit_restrictions: AccountRestriction[]; + + // Restrictions that apply to bank accounts that would receive + // funds from the exchange (debiting this exchange bank account). + // Optional, empty array for unrestricted. + debit_restrictions: AccountRestriction[]; + // Signature using the exchange's offline key over // a `TALER_MasterWireDetailsPS` // with purpose ``TALER_SIGNATURE_MASTER_WIRE_DETAILS``. master_sig: EddsaSignature; } + .. ts:def:: AccountRestriction + + type AccountRestriction = + | RegexAccountRestriction + | DenyAllAccountRestriction + + .. ts:def:: DenyAllAccountRestriction + + // Account restriction that disables this type of + // account for the indicated operation categorically. + interface DenyAllAccountRestriction { + + type: "deny"; + } + + .. ts:def:: RegexAccountRestriction + + // Accounts interacting with this type of account + // restriction must have a payto://-URI matching + // the given regex. + interface RegexAccountRestriction { + + type: "regex"; + + // Regular expression that the payto://-URI of the + // partner account must follow. The regular expression + // should follow posix-egrep, but without support for character + // classes, GNU extensions, back-references or intervals. See + // https://www.gnu.org/software/findutils/manual/html_node/find_html/posix_002degrep-regular-expression-syntax.html + // for a description of the posix-egrep syntax. Applications + // may support regexes with additional features, but exchanges + // must not use such regexes. + payto_regex: string; + + // Hint for a human to understand the restriction + // (that is hopefully easier to comprehend than the regex itself). + human_hint: string; + + // Map from IETF BCP 47 language tags to localized + // human hints. + human_hint_i18n?: { [lang_tag: string]: string }; + + } + Aggregate wire transfer fees representing the fees the exchange charges per wire transfer to a merchant must be specified as an array in all wire transfer response objects under ``fees``. The @@ -2011,7 +2123,7 @@ Withdraw .. ts:def:: WithdrawPrepareResponse - type WithdrawPrepareResponse + type WithdrawPrepareResponse = | ExchangeWithdrawValue; .. ts:def:: ExchangeWithdrawValue @@ -2070,8 +2182,13 @@ Withdraw In this case, the wallet should repeat the exact same request later again using exactly the same blinded coin. :http:statuscode:`409 Conflict`: - The balance of the reserve is not sufficient to withdraw a coin of the indicated denomination. - The response is `WithdrawError` object. + One of the following reasons occured: + + 1. The balance of the reserve is not sufficient to withdraw the coins of the + indicated denominations. The response is `WithdrawError` object. + + 2. The reserve has a birthday set and requires a request to ``/age-withdraw`` instead. + The response comes with a standard `ErrorDetail` response with error-code ``TALER_EC_EXCHANGE_RESERVES_AGE_RESTRICTION_REQUIRED`` and an additional field ``maximum_allowed_age`` for the maximum age (in years) that the client can commit to in the call to ``/age-withdraw`` :http:statuscode:`410 Gone`: The requested denomination key is not yet or no longer valid. It either before the validity start, past the expiration or was revoked. The response is a @@ -2266,8 +2383,13 @@ Batch Withdraw In this case, the wallet should repeat the exact same request later again using exactly the same blinded coin. :http:statuscode:`409 Conflict`: - The balance of the reserve is not sufficient to withdraw the coins of the + One of the following reasons occured: + + 1. The balance of the reserve is not sufficient to withdraw the coins of the indicated denominations. The response is `WithdrawError` object. + + 2. The reserve has a birthday set and requires a request to ``/age-withdraw`` instead. + The response comes with a standard `ErrorDetail` response with error-code ``TALER_EC_EXCHANGE_RESERVES_AGE_RESTRICTION_REQUIRED`` and an additional field ``maximum_allowed_age`` for the maximum age (in years) that the client can commit to in the call to ``/age-withdraw`` :http:statuscode:`410 Gone`: A requested denomination key is not yet or no longer valid. It either before the validity start, past the expiration or was revoked. @@ -2347,8 +2469,13 @@ If so, the exchange will blindly sign ``n`` undisclosed coins from the request. A signature is invalid. This response comes with a standard `ErrorDetail` response. :http:statuscode:`409 Conflict`: - The balance of the reserve is not sufficient to withdraw the coins of the + One of two reasons occured: + + 1. The balance of the reserve is not sufficient to withdraw the coins of the given amount. The response is a `WithdrawError` object. + + 2. The provided value for ``max_age`` is higher than the allowed value according to the reserve's birthday. + The response comes with a standard `ErrorDetail` response with error-code ``TALER_EC_EXCHANGE_AGE_WITHDRAW_MAXIMUM_AGE_TOO_LARGE`` and an additional field ``maximum_allowed_age`` for the maximum age (in years) that the client can commit to in a call to ``/age-withdraw`` :http:statuscode:`410 Gone`: A requested denomination key is not yet or no longer valid. It either before the validity start, past the expiration or was revoked. @@ -2369,24 +2496,25 @@ If so, the exchange will blindly sign ``n`` undisclosed coins from the request. .. ts:def:: AgeWithdrawRequest interface AgeWithdrawRequest { - // Commitment to the coins with age restriction. This is the SHA512 - // hash value $ACH over all n*kappa `BlindedCoinHash` values of all - // coins and their age commitments. It is alter used as part of the URL - // in the subsequent call to /age-withdraw/$ACH/reveal. - h_commitment : HashCode; - - // The total amount that the client wants to withdraw from the reserve - // and must be at most the balance of the reserve. The balance of the - // reserve will be immediatley reduced by that amount. - // In the subsequent call to /age-withdraw/$ACH/reveal, the client has to - // provide the list of denominations (with support for age restriction) - // that the coins shall be signed with. The sum of the values of those - // denominations MUST equal this amount. - amount: Amount; + // Array of ``n`` hash codes of denomination public keys to order. + // These denominations MUST support age restriction as defined in the + // output to /keys. + // The sum of all denomination's values and fees MUST be at most the + // balance of the reserve. The balance of the reserve will be + // immediatley reduced by that amount. + denoms_h: HashCode[]; + + // ``n`` arrays of ``kappa`` entries with blinded coin envelopes. Each + // (toplevel) entry represents ``kappa`` canditates for a particular + // coin. The exchange will respond with an index ``gamma``, which is + // the index that shall remain undisclosed during the reveal phase. + // The SHA512 hash $ACH over the blinded coin envelopes is the commitment + // that is later used as the key to the reveal-URL. + blinded_coins_evs: CoinEnvelope[][]; - // The maximum age group to commit to. MUST be the same as the maximum - // age group in the reserve. - max_age_group: number; + // The maximum age to commit to. MUST be the same as the maximum + // age in the reserve. + max_age: number; // Signature of `TALER_AgeWithdrawRequestPS` created with // the `reserves's private key <reserve-priv>` @@ -2401,7 +2529,7 @@ If so, the exchange will blindly sign ``n`` undisclosed coins from the request. // have to disclose noreveal_index: Integer; - // Signature of `TALER_AgeWithdrawRequestPS` whereby + // Signature of `TALER_AgeWithdrawConfirmationPS` whereby // the exchange confirms the ``noreveal_index``. exchange_sig: EddsaSignature; @@ -2430,7 +2558,7 @@ If so, the exchange will blindly sign ``n`` undisclosed coins from the request. **Response:** :http:statuscode:`200 OK`: - The request was successful, and the response is a `BlindedSignaturesResponse`. + The request was successful, and the response is a `AgeWithdrawRevealResponse`. Note that repeating exactly the same request will again yield the same response, so if the network goes down during the transaction or before the client can commit the coin signature to disk, the coin is not lost. @@ -2440,75 +2568,54 @@ If so, the exchange will blindly sign ``n`` undisclosed coins from the request. The reveal operation failed and the response is an `WithdrawError` object. The error codes indicate one of two cases: - 1. An age commitment for one of the coins did not fulfill the required - maximum age requirement of the corresponding reserve. Error code: + 1. An age commitment for at least one of the coins did not fulfill the + required maximum age requirement of the corresponding reserve. + Error code: ``TALER_EC_EXCHANGE_GENERIC_COIN_AGE_REQUIREMENT_FAILURE``. - 2. The sum of all denominations in the request is not equal to the amount - that was given in the previous commitment via the call to - /reserves/$RESERVE_PUB/age-withdraw. Error code: - ``TALER_EC_EXCHANGE_GENERIC_MISMATCH_OF_AMOUNT_AND_DENOMINATIONS``. + 2. The computation of the hash of the commitment with provided input does + result in the value $ACH. + Error code: + ``TALER_EC_EXCHANGE_AGE_WITHDRAW_REVEAL_INVALID_HASH`` .. ts:def:: AgeWithdrawRevealRequest interface AgeWithdrawRevealRequest { - // The public key of the reserve that was used for the initial commitment - // request. Needed for optimized database lookup. - reserve_pub: EddsaPublicKey; - - // Array of ``n`` hash codes of denomination public keys to order. - // These denominations MUST support age restriction as defined in the - // output to /keys. - // The sum of all denomination's values MUST equal the original amount - // of the previous commitment. - denoms_h: HashCode[]; - - // Array of ``n`` entries with blinded coins, which are the non-desclosed - // coins in the previous commitment. They match the respective entries - // in ``denoms_h``. - coin_evs: CoinEnvelope[]; - - // Array of ``n`` arrays of ``kappa - 1`` disclosed coin private keys, - // from which the associated age commitments are also derived. - disclosed_coins: DisclosedAgeRestrictedCoin[][]; - - } - - .. ts:def:: DisclosedAgeRestrictedCoin - - interface DisclosedAgeRestrictedCoin { - // A coin's private key. The associated blinding and age commitment for - // this coin MUST be derived from this private key as follows: - // - // Calculate the blinding beta as - // beta := HKDF(coin_priv, "blinding") - // - // If the denominations are for Clause-Schnorr-Signatures, calculate the - // nonce as - // nonce := HKDF(coin_priv, "cs-nonce") - // - // Let m ∈ {1,...,M} be the maximum age group as defined in the reserve - // that the wallet can commit to. - // - // For age group $AG ∈ {1,...m}, set - // seed = HDKF(coin_priv, "age-commitment", $AG) - // p[$AG] = Edx25519_generate_private(seed) - // and calculate the corresponding Edx25519PublicKey as - // q[$AG] = Edx25519_public_from_private(p[$AG]) + // Array of ``n`` of ``(kappa - 1)`` disclosed coin master secrets, from + // which the coins' private key, blinding, nonce (for Clause-Schnorr) and + // age-restriction is calculated. // - // For age groups $AG ∈ {m,...,M}, set - // f[$AG] = HDKF(coin_priv, "age-factor", $AG) - // and calculate the corresponding Edx25519PublicKey as - // q[$AG] = Edx25519_derive_public(`PublishedAgeRestrictionBaseKey`, f[$AG]) - // - // Finally, with coin_priv and age commitment (q[]), the exchange - // will calculate the coin's public key coin_pub and use the - // TALER_CoinPubHashP(coin_pub, age_commitment_hash(q)) + // Given each coin's private key and age commitment, the exchange will + // calculate each coin's blinded hash value und use all those (disclosed) + // blinded hashes together with the non-disclosed envelopes ``coin_evs`` // during the verification of the original age-withdraw-commitment. - coin_priv: EddsaPrivateKey; - + disclosed_coin_secrets: AgeRestrictedCoinSecret[][]; } + .. ts:def:: AgeRestrictedCoinSecret + + // The Master key material from which the coins' private key ``coin_priv``, + // blinding ``beta`` and nonce ``nonce`` (for Clause-Schnorr) itself are + // derived as usually in wallet-core. Given a coin's master key material, + // the age commitment for the coin MUST be derived from this private key as + // follows: + // + // Let m ∈ {1,...,M} be the maximum age group as defined in the reserve + // that the wallet can commit to. + // + // For age group $AG ∈ {1,...m}, set + // seed = HDKF(coin_secret, "age-commitment", $AG) + // p[$AG] = Edx25519_generate_private(seed) + // and calculate the corresponding Edx25519PublicKey as + // q[$AG] = Edx25519_public_from_private(p[$AG]) + // + // For age groups $AG ∈ {m,...,M}, set + // f[$AG] = HDKF(coin_secret, "age-factor", $AG) + // and calculate the corresponding Edx25519PublicKey as + // q[$AG] = Edx25519_derive_public(`PublishedAgeRestrictionBaseKey`, f[$AG]) + // + type AgeRestrictedCoinSecret = string; + .. ts:def:: PublishedAgeRestrictionBaseKey // The value for ``PublishedAgeRestrictionBaseKey`` is a randomly chosen @@ -2517,8 +2624,14 @@ If so, the exchange will blindly sign ``n`` undisclosed coins from the request. // derived all public keys to age groups higher than their allowed maximum // from this particular value. const PublishedAgeRestrictionBaseKey = - new Edx25519PublicKey("DZJRF6HXN520505XDAWM8NMH36QV9J3VH77265WQ09EBQ76QSKCG"); + new Edx25519PublicKey("CH0VKFDZ2GWRWHQBBGEK9MWV5YDQVJ0RXEE0KYT3NMB69F0R96TG"); + + .. ts:def:: AgeWithdrawRevealResponse + interface AgeWithdrawRevealResponse { + // List of the exchange's blinded RSA signatures on the new coins. + ev_sigs : BlindedDenominationSignature[]; + } .. _deposit-par: @@ -2574,13 +2687,17 @@ proof to the seller for the escrow of sufficient fund. :http:statuscode:`409 Conflict`: The deposit operation has either failed because the coin has insufficient residual value, or because the same public key of the coin has been - previously used with a different denomination. Which case it is + previously used with a different denomination. It is also a conflict + to use the same coin multiple times (with different amounts) for the + same contract. Which case it is can be decided by looking at the error code - (``TALER_EC_EXCHANGE_GENERIC_INSUFFICIENT_FUNDS`` or - ``TALER_EC_EXCHANGE_GENERIC_COIN_CONFLICTING_DENOMINATION_KEY``). - The fields of the response are the same in both cases. + (``TALER_EC_EXCHANGE_DEPOSIT_CONFLICTING_CONTRACT`` (same coin used in different ways), + ``TALER_EC_EXCHANGE_GENERIC_INSUFFICIENT_FUNDS`` (balance insufficient) or + ``TALER_EC_EXCHANGE_GENERIC_COIN_CONFLICTING_DENOMINATION_KEY`` + (same coin public key, but different denomination)). + The fields of the response are still evolving (see bug 7267), + for now the format of the response is a `DepositDoubleSpendError`. The request should not be repeated again with this coin. - In this case, the response is a `DepositDoubleSpendError`. :http:statuscode:`410 Gone`: The requested denomination key is not yet or no longer valid. It either before the validity start, past the expiration or was revoked. The response is a @@ -3203,15 +3320,16 @@ proof to the seller for the escrow of sufficient fund. :http:statuscode:`409 Conflict`: The deposit operation has either failed because a coin has insufficient residual value, or because the same public key of a coin has been - previously used with a different denomination. Which case it is + previously used with a different denomination. + Which case it is can be decided by looking at the error code - (``TALER_EC_EXCHANGE_GENERIC_INSUFFICIENT_FUNDS`` or - ``TALER_EC_EXCHANGE_GENERIC_COIN_CONFLICTING_DENOMINATION_KEY``). - The fields of the response are the same in both cases. + (``TALER_EC_EXCHANGE_DEPOSIT_CONFLICTING_CONTRACT`` (same coin used in different ways), + ``TALER_EC_EXCHANGE_GENERIC_INSUFFICIENT_FUNDS`` (balance insufficient) or + ``TALER_EC_EXCHANGE_GENERIC_COIN_CONFLICTING_DENOMINATION_KEY`` + (same coin public key, but different denomination)). + The fields of the response are still evolving (see bug 7267), + for now the format of the response is a `DepositDoubleSpendError`. The request should not be repeated again with this coin. - In this case, the response is a `DepositDoubleSpendError` with - an additional ``coin_pub`` field specifying the public key of the - coin that was double-spent. :http:statuscode:`410 Gone`: The requested denomination key is not yet or no longer valid. It either before the validity start, past the expiration or was revoked. The response is a @@ -3984,7 +4102,13 @@ typically also view the balance.) **Request:** - :query merchant_sig: EdDSA signature of the merchant made with purpose ``TALER_SIGNATURE_MERCHANT_TRACK_TRANSACTION`` over a ``TALER_DepositTrackPS``, affirming that it is really the merchant who requires obtaining the wire transfer identifier. + :query merchant_sig: EdDSA signature of the merchant made with purpose + ``TALER_SIGNATURE_MERCHANT_TRACK_TRANSACTION`` over a + ``TALER_DepositTrackPS``, affirming that it is really the merchant who + requires obtaining the wire transfer identifier. + :query timeout_ms=NUMBER: *Optional.* If specified, the exchange will wait + up to ``NUMBER`` milliseconds for completion of a deposit operation before + sending the HTTP response. **Response:** @@ -5036,6 +5160,9 @@ KYC status updates The provided hash does not match the payment target. :http:statuscode:`404 Not found`: The payment target is unknown. + :http:statuscode:`451 Unavailable for Legal Reasons`: + The transaction cannot be completed due to AML rules. + The response will be a `AccountAmlBlocked` object. **Details:** @@ -5059,6 +5186,12 @@ KYC status updates // public key used to create the signature. exchange_pub: EddsaPublicKey; + + // Current AML state for the target account. Non-zero + // values indicate that the transfer is blocked due to + // AML enforcement. + aml_status: Integer; + } .. ts:def:: AccountKycRedirect @@ -5069,6 +5202,22 @@ KYC status updates // proceed with the KYC process. kyc_url: string; + // Current AML state for the target account. Non-zero + // values indicate that the transfer is blocked due to + // AML enforcement. + aml_status: Integer; + + } + + .. ts:def:: AccountAmlBlocked + + interface AccountAmlBlocked { + + // Current AML state for the target account. Non-zero + // values indicate that the transfer is blocked due to + // AML enforcement. + aml_status: Integer; + } .. ts:def:: KycDetails @@ -5095,13 +5244,13 @@ KYC status updates If the KYC plugin logic is OAuth 2.0, the query parameters are: - :query code=CODE : OAuth 2.0 code argument. + :query code=CODE: OAuth 2.0 code argument. :query state=STATE: OAuth 2.0 state argument with the H_PAYTO. - .. note:: + .. note:: - Depending on the OAuth variant used, additional - query parameters may need to be passed here. + Depending on the OAuth variant used, additional + query parameters may need to be passed here. **Response:** @@ -5152,7 +5301,7 @@ Reserve control This section describes the reserve control API which can be used to (1) prevent a reserve from expiring (which is useful if the reserve is used for -tipping), to (2) pay an annual fee to allow a number of purses to be created +rewards), to (2) pay an annual fee to allow a number of purses to be created for the respective reserve without paying a purse fee each time, to (3) obtain KYC information associated with a reserve to prove the identity of the person sending an invoice to the payer, and to (4) close a reserve before it would @@ -5164,7 +5313,7 @@ naturally expire and possibly (5) wire the funds to a designated account. .. http:post:: /reserves/$RESERVE_PUB/open - Request keeping a reserve open for tipping or invoicing. + Request keeping a reserve open for rewards or invoicing. **Request:** diff --git a/core/api-libeufin-bank.rst b/core/api-libeufin-bank.rst @@ -0,0 +1,1028 @@ +.. + This file is part of GNU TALER. + + Copyright (C) 2014-2020 Taler Systems SA + + TALER 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 2.1, or (at your option) any later version. + + TALER 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 + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + +.. target audience: developer, core developer + +.. _libeufin-bank-api: + +================= +Libeufin Bank API +================= + +.. contents:: Table of Contents + +Introduction +------------ + +The Libeufin bank provides a minimal core banking system. In addition to that, +it provides features for local/regional currencies. + +Authentication +-------------- + +Some requests require the client to authenticate via HTTP Basic auth (RFC 7617) +or using a bearer token which can be obtained or refreshed from the +``/accounts/$USERNAME/auth-token`` endpoint. +When using Basic authentication, the user-id must be the libeufin-bank +username, and the password the password for the corresponding user. + +Another way to obtain a login token is by manually configuring it for certain +endpoints. For example, the exchange could give an auditor read-only access to +the taler-wire-gateway facade via such a manually configured access token. + +The ``admin`` user is a special, hard-coded username. Some requests require the +client to authenticate as the admin. + +.. http:post:: /accounts/$USERNAME/auth-token + + See :ref:`DD 48 token endpoint <dd48-token>`. + + +Libeufin Bank Web UI +-------------------- + +The web UI for the libeufin-bank is typically served under ``/``. + +Config +------ + +.. http:get:: /config + + **Response:** + + .. ts:def:: Config + + interface Config { + // Name of this API, always "libeufin-bank". + name: string; + + // API version in the form $n:$n:$n + version: string; + + // If 'true', the server provides local currency + // conversion support. + // If missing or false, some parts of the API + // are not supported and return 404. + have_cashout?: boolean; + + // Fiat currency. That is the currency in which + // cash-out operations ultimately wire money. + // Only applicable if have_cashout=true. + fiat_currency?: string; + } + + +Account Management +------------------ + +.. _libeufin-bank-account-register: + +.. http:post:: /accounts + + Create a new bank account. Depending on the configuration, + the account creation is self-serve, or only restricted to + the administrators. + + **Request:** + + .. ts:def:: RegisterAccountRequest + + interface RegisterAccountRequest { + // Username + username: string; + + // Password. + password: string; + + // Legal name of the account owner + name: string; + + // Defaults to false. + is_public?: boolean; + + // Is this a taler exchange account? + // If true: + // - incoming transactions to the account that do not + // have a valid reserve public key are automatically + // - the account provides the taler-wire-gateway-api endpoints + // Defaults to false. + is_taler_exchange?: boolean; + + // Addresses where to send the TAN for transactions. + // Currently only used for cashouts. + // If missing, cashouts will fail. + // In the future, might be used for other transactions + // as well. + challenge_contact_data?: ChallengeContactData; + + // 'payto' address pointing a bank account + // external to the libeufin-bank. + // Payments will be sent to this bank account + // when the user wants to convert the local currency + // back to fiat currency outside libeufin-bank. + cashout_payto_uri?: string; + + // Internal payto URI of this bank account. + // Used mostly for testing. + internal_payto_uri?: string; + } + + .. ts:def:: ChallengeContactData + + interface ChallengeContactData { + + // E-Mail address + email?: EmailAddress; + + // Phone number. + phone?: PhoneNumber; + } + + + **Response:** + + :http:statuscode:`204 No content`: + The account was successfully created. + :http:statuscode:`400 Bad request`: + Input data was invalid. For example, the client specified a invalid + phone number or e-mail address. + :http:statuscode:`403 Forbidden`: + The response should indicate one of the following reasons. + + * A reserved username was attempted, like ``admin`` or ``bank``. + * An unauthorized user tried to create the account + + :http:statuscode:`409 Conflict`: + The internal account payto URI or username already exists. + +.. _delete-account: + +.. http:delete:: /accounts/$USERNAME + + Delete the account whose username is ``$USERNAME``. The deletion + succeeds only if the balance is *zero*. + + **Response:** + + :http:statuscode:`204 No content`: + The account was successfully deleted. + :http:statuscode:`403 Forbidden`: + The request specified a reserved internal username, like + ``admin`` or ``bank``. + :http:statuscode:`404 Not found`: + The username was not found. + :http:statuscode:`412 Precondition failed`: + The balance was not zero. + + +.. _account-reconfig: + +.. http:patch:: /accounts/$USERNAME + + Allows reconfiguring the account data of ``$USERNAME``. + + **Request:** + + .. ts:def:: AccountReconfiguration + + interface AccountReconfiguration { + + // Addresses where to send the TAN for transactions. + // Currently only used for cashouts. + // If missing, cashouts will fail. + // In the future, might be used for other transactions + // as well. + challenge_contact_data?: ChallengeContactData; + + // 'payto' address pointing a bank account + // external to the libeufin-bank. + // Payments will be sent to this bank account + // when the user wants to convert the local currency + // back to fiat currency outside libeufin-bank. + cashout_address?: string; + + // Legal name associated with $username. + // When missing, the old name is kept. + name?: string; + + // If present, change the is_exchange configuration. + // See `RegisterAccountRequest` + is_exchange?: boolean; + } + + **Response:** + + :http:statuscode:`204 No content`: + Operation successful. + + :http:statuscode:`403 Forbidden`: + The rights to change ``$USERNAME`` are not sufficient. + That includes the case where a correctly authenticated + user tries to change their legal name. It also + includes the case where 'admin' tries to change its + own account. + + :http:statuscode:`404 Not found`: + The account pointed by ``$USERNAME`` + was not found. + + +.. _account-password-reconfig: + +.. http:patch:: /accounts/$USERNAME/auth + + Allows changing the account's password. + + **Request:** + + .. ts:def:: AccountPasswordChange + + interface AccountPasswordChange { + + // New password. + new_password: string; + } + + **Response:** + + :http:statuscode:`204 No content`: + Operation successful. + + +.. _account-list: + +.. http:get:: ${BANK_API_BASE_URL}/public-accounts + + Show those accounts whose histories are publicly visible. For example, + accounts from donation receivers. As such, this request is unauthenticated. + + **Response** + + **Details** + + .. ts:def:: PublicAccountsResponse + + interface PublicAccountsResponse { + public_accounts: PublicAccount[]; + } + + .. ts:def:: PublicAccount + + interface PublicAccount { + payto_uri: string; + + balance: Balance; + + // The account name (=username) of the + // libeufin-bank account. + account_name: string; + } + + +.. http:get:: /accounts + + Obtains a list of the accounts registered at the bank. + It returns only the information that this API handles, without + any balance or transactions list. + This request is only available to the administrator. + + **Request:** + + :query filter_name: *Optional.* + Pattern to filter on the account legal name. Given + the filter 'foo', all the results will **contain** + 'foo' in their legal name. Without this option, + all the existing accounts are returned. + + **Response:** + + :http:statuscode:`200 OK`: + At least one account was found. + The server responds with a `ListBankAccountsResponse` object. + :http:statuscode:`204 No Content`: + No accounts were found for the given request. + :http:statuscode:`403 Forbidden`: + A ordinary user invoked this call. + + **Details:** + + .. ts:def:: ListBankAccountsResponse + + interfaces ListBankAccountsResponse { + accounts: AccountMinimalData[]; + } + + .. ts:def:: Balance + + interface Balance { + amount: Amount; + credit_debit_indicator: "credit" | "debit"; + } + + .. ts:def:: AccountMinimalData + + interface AccountMinimalData { + // Username + username: string; + + // Legal name of the account owner. + name: string; + + // current balance of the account + balance: Balance; + + // Number indicating the max debit allowed for the requesting user. + debit_threshold: Amount; + } + +.. _libeufin-bank-account-info: + +.. http:get:: /accounts/$USERNAME + + Obtains information relative to the account owned by + ``$USERNAME``. The request is available to the administrator + and ``$USERNAME`` itself. + + **Response:** + + :http:statuscode:`200 OK`: + The libeufin-bank responds with an `AccountData` object. + + **Details:** + + .. ts:def:: AccountData + + interface AccountData { + // Legal name of the account owner. + name: string; + + // Available balance on the account. + balance: Balance; + + // payto://-URI of the account. + payto_uri: string; + + // Number indicating the max debit allowed for the requesting user. + debit_threshold: Amount; + + contact_data?: ChallengeContactData; + + // 'payto' address pointing the bank account + // where to send cashouts. This field is optional + // because not all the accounts are required to participate + // in the merchants' circuit. One example is the exchange: + // that never cashouts. Registering these accounts can + // be done via the access API. + cashout_payto_uri?: string; + } + +Transactions +------------ + +.. http:get:: ${BANK_API_BASE_URL}/accounts/${account_name}/transactions + + Retrieve a subset of transactions related to $account_name. Without + query parameters, it returns the last 5 transactions. + + The list of returned transactions is determined by a row ID *starting point* + and a signed non-zero integer *delta*: + + * If *delta* is positive, return a list of up to *delta* transactions (all matching + the filter criteria) strictly **after** the starting point. The transactions are sorted + in **ascending** order of the row ID. + * If *delta* is negative, return a list of up to *-delta* transactions (all matching + the filter criteria) strictly **before** the starting point. The transactions are sorted + in **descending** order of the row ID. + + If *starting point* is not explicitly given, it defaults to: + + * A value that is **smaller** than all other row IDs if *delta* is **positive**. + * A value that is **larger** than all other row IDs if *delta* is **negative**. + + **Request** + + :query long_poll_ms: Optional number to express how many milliseconds the server + should wait for at least one result to be shown. If not given, the server + responds immediately, regardless of the result. + :query start: *Optional.* + Row identifier to explicitly set the *starting point* of the query. + :query delta: + The *delta* value that determines the range of the query. + + **Response** + + .. ts:def:: BankAccountTransactionsResponse + + interface BankAccountTransactionsResponse { + transactions: BankAccountTransactionInfo[]; + } + +.. http:get:: ${BANK_API_BASE_URL}/accounts/${account_name}/transactions/${transaction_id} + + **Response** + + Retrieve the transaction whose identifier is ``transaction_id``, + in the following format: + + .. ts:def:: BankAccountTransactionInfo + + interface BankAccountTransactionInfo { + creditor_payto_uri: string; + debtor_payto_uri: string; + + amount: Amount; + direction: "debit" | "credit"; + + subject: string; + + // Transaction unique ID. Matches + // $transaction_id from the URI. + row_id: number; + date: Timestamp; + } + + +.. http:post:: ${BANK_API_BASE_URL}/accounts/${account_name}/transactions + + Create a new transaction where the bank account with the label ``account_name`` is **debited**. + + **Request** + + .. ts:def:: BankAccountTransactionCreate + + interface CreateBankAccountTransactionCreate { + + // Address in the Payto format of the wire transfer receiver. + // It needs at least the 'message' query string parameter. + payto_uri: string; + + // Transaction amount (in the $currency:x.y format), optional. + // However, when not given, its value must occupy the 'amount' + // query string parameter of the 'payto' field. In case it + // is given in both places, the payto_uri's takes the precedence. + amount: string; + } + + **Response** + + :http:statuscode:`200 OK`: + the transaction has been created. + + :http:statuscode:`400 Bad Request`: + the request was invalid or the payto://-URI used unacceptable features. + + +Taler Withdrawals +----------------- + +.. http:post:: ${BANK_API_BASE_URL}/accounts/${account_name}/withdrawals + + Create a withdrawal operation, resulting in a ``taler://withdraw`` URI. + + **Request** + + .. ts:def:: BankAccountCreateWithdrawalRequest + + interface BankAccountCreateWithdrawalRequest { + // Amount to withdraw. + amount: Amount; + } + + **Response** + + .. ts:def:: BankAccountCreateWithdrawalResponse + + interface BankAccountCreateWithdrawalResponse { + // ID of the withdrawal, can be used to view/modify the withdrawal operation. + withdrawal_id: string; + + // URI that can be passed to the wallet to initiate the withdrawal. + taler_withdraw_uri: string; + } + + :http:statuscode:`403 Forbidden`: + The operation was rejected due to insufficient funds. + +.. http:get:: ${BANK_API_BASE_URL}/accounts/${account_name}/withdrawals/${withdrawal_id} + + Query the status of a withdrawal operation. + + **Response** + + **Details** + + .. ts:def:: BankAccountGetWithdrawalResponse + + interface BankAccountGetWithdrawalResponse { + // Amount that will be withdrawn with this withdrawal operation. + amount: Amount; + + // Was the withdrawal aborted? + aborted: boolean; + + // Has the withdrawal been confirmed by the bank? + // The wire transfer for a withdrawal is only executed once + // both ``confirmation_done`` is ``true`` and ``selection_done`` is ``true``. + confirmation_done: boolean; + + // Did the wallet select reserve details? + selection_done: boolean; + + // Reserve public key selected by the exchange, + // only non-null if ``selection_done`` is ``true``. + selected_reserve_pub: string | null; + + // Exchange account selected by the wallet, or by the bank + // (with the default exchange) in case the wallet did not provide one + // through the Integration API. + selected_exchange_account: string | null; + } + + +.. http:post:: ${BANK_API_BASE_URL}/accounts/${account_name}/withdrawals/${withdrawal_id}/abort + + Abort a withdrawal operation. Has no effect on an already aborted withdrawal operation. + + :http:statuscode:`200 OK`: The withdrawal operation has been aborted. The response is an empty JSON object. + :http:statuscode:`409 Conflict`: The reserve operation has been confirmed previously and can't be aborted. + + +.. http:post:: ${BANK_API_BASE_URL}/accounts/${account_name}/withdrawals/${withdrawal_id}/confirm + + Confirm a withdrawal operation. Has no effect on an already confirmed withdrawal operation. + This call is responsible of wiring the funds to the exchange. + + **Response** + + :http:statuscode:`200 OK`: + The withdrawal operation has been confirmed. The response is an empty JSON object. + :http:statuscode:`409 Conflict`: + The withdrawal has been aborted previously and can't be confirmed. + :http:statuscode:`422 Unprocessable Entity` (New): + The withdraw operation cannot be confirmed because no exchange and reserve public key selection happened before. + +Cashouts +-------- + +.. _account-cashout: + +.. http:post:: /accounts/$USERNAME/cashouts + + Initiates a conversion to fiat currency. The external + bank account to be + credited is the one specified at registration time via the + *cashout_address* parameter. The libeufin-bank internal account + is specified via ``$USERNAME``. + The bank sends a TAN to the customer to let them confirm the + operation. The request is only available to ordinary users, not + to the administrator. + + .. note:: + + Consult the `cashout rates call <cashout-rates_>`_ to learn + about any applicable fee or exchange rate. + + .. note:: + + FIXME: Eventually, the env variables will be replaced with + configuration settings. + + To test this operation without relying on any SMS/E-mail provider, + Libeufin offers two methods: defining an environment variable called + ``LIBEUFIN_CASHOUT_TEST_TAN`` or specifying the value ``file`` to + the ``tan_channel`` field of the `request object <cashout-request_>`_. + Assuming ``LIBEUFIN_CASHOUT_TEST_TAN`` is set to *T*, every */confirm* + operation can use *T* as the TAN. Setting instead the ``tan_channel`` + field to ``file`` will cause the server to (over)write every TAN to + ``/tmp/libeufin-cashout-tan.txt``. If both are used, the environment + variable takes the precedence. + + + **Request:** + + `CashoutRequest <cashout-request_>`_ + + .. ts:def:: TanChannel + + enum TanChannel { + SMS = "sms", + EMAIL = "email", + FILE = "file" + } + + .. _cashout-request: + + .. ts:def:: CashoutRequest + + interface CashoutRequest { + + // Optional subject to associate to the + // cashout operation. This data will appear + // as the incoming wire transfer subject in + // the user's external bank account. + subject?: string; + + // That is the plain amount that the user specified + // to cashout. Its $currency is the (regional) currency of the + // libeufin-bank instance. + amount_debit: Amount; + + // That is the amount that will effectively be + // transferred by the bank to the user's bank + // account, that is external to the regional currency. + // It is expressed in the fiat currency and + // is calculated after the cashout fee and the + // exchange rate. See the /cashout-rates call. + // The client needs to calculate this amount + // correctly based on the amount_debit and the cashout rate, + // otherwise the request will fail. + amount_credit: Amount; + + // Which channel the TAN should be sent to. If + // this field is missing, it defaults to SMS. + // The default choice prefers to change the communication + // channel respect to the one used to issue this request. + tan_channel?: TanChannel; + } + + **Response:** + + :http:statuscode:`202 Accepted`: + The cashout request was correctly created and + the TAN authentication now is pending. + This returns the `CashoutPending` response. + :http:statuscode:`409 Conflict`: + The user did not share any contact data where to send the TAN, + the account does not have sufficient funds, or the + exchange rate was calculated incorrectly by the client. + :http:statuscode:`503 Service unavailable`: + The bank does not support the TAN channel for this operation. + + **Details:** + + .. ts:def:: CashoutPending + + interface CashoutPending { + // ID identifying the operation being created + // and now waiting for the TAN confirmation. + cashout_id: string; + } + + +.. _cashout-abort: + +.. http:post:: /accounts/$USERNAME/cashouts/$CASHOUT_ID/abort + + Aborts the ``$CASHOUT_ID`` operation. + + **Response:** + + :http:statuscode:`204 No content`: + ``$CASHOUT_ID`` was found in the *pending* state + and got successfully aborted. + :http:statuscode:`404 Not found`: + ``$CASHOUT_ID`` is not found. Note: that happens + also when ``$CASHOUT_ID`` got aborted before this request. + :http:statuscode:`409 Conflict`: + ``$CASHOUT_ID`` was already confirmed. + + +.. _cashout-confirm: + +.. http:post:: /accounts/$USERNAME/cashouts/$CASHOUT_ID/confirm + + Confirms the ``$CASHOUT_ID`` operation by providing its + TAN. The request should still be authenticated with + the users credentials. + + **Request:** + + .. ts:def:: CashoutConfirm + + interface CashoutConfirm { + // the TAN that confirms $CASHOUT_ID. + tan: string; + } + + **Response:** + + :http:statuscode:`204 No content`: + The request succeeded, either for the first time, or it already was + confirmed previously (idempotency!). + :http:statuscode:`403 Forbidden`: + Wrong TAN or bad credentials. + :http:statuscode:`404 Not found`: + ``$CASHOUT_ID`` is not found. Note: that happens + also when ``$CASHOUT_ID`` got aborted before this request. + :http:statuscode:`409 Conflict`: + The user changed their cash-out address between the creation and the confirmation of ``$CASHOUT_ID``. + + +.. _cashout-rates: + +.. http:get:: /cashout-rate + + This public endpoint allows clients to calculate + the exchange rate between the regional currency + and the external banking system. + + This endpoint shows how the bank would apply the cash-out + ratio and fee to one input amount. Typically, frontends + ask this endpoint before creating cash-out operations. + At least one of the two query parameters must be provided. If both are + given, then the server checks their correctness. Amounts must include the + currency. + + **Request:** + + :query amount_debit: this is the amount that the user will get + deducted from their regional bank account. + + :query amount_credit: this is the amount that the user will receive + in their fiat bank account. + + **Response:** + + .. ts:def:: CashoutConversionResponse + + interface CashoutConversionResponse { + // Amount that the user will get deducted from their regional + // bank account, according to the 'amount_credit' value. + amount_debit: Amount; + // Amount that the user will receive in their fiat + // bank account, according to 'amount_debit'. + amount_credit: Amount; + } + + + :http:statuscode:`200 Ok`: + Response is a `CashoutConversionResponse`. + :http:statuscode:`400 Bad request`: + Both parameters have been provided and the calculation is not correct, + or none of them has been provided. + :http:statuscode:`404 Not found`: + The server does not support local currency conversion. + + +.. _circuit-cashouts: + +.. http:get:: /accounts/$USERNAME/cashouts + + Returns the list of all the (pending and confirmed) cash-out operations + for an account. + + **Response:** + + .. ts:def:: Cashouts + + interface Cashouts { + // Every string represents a cash-out operation ID. + cashouts: CashoutInfo[]; + } + + .. ts:def:: CashoutInfo + + interface CashoutInfo { + cashout_id: string; + status: "pending" | "confirmed"; + } + + :http:statuscode:`200 OK`: + At least one cash-out operation was found. + + :http:statuscode:`204 No Content`: + No cash-out operations were found at the bank + +.. http:get:: /cashouts + + Returns the list of all the (pending and confirmed) cash-out operations + for **all** accounts. + + Typically can only be used by the administrators. + + .. note:: + + We might want to add a filter in the future to only + query pending cashout operations. + + **Response:** + + .. ts:def:: GlobalCashouts + + interface GlobalCashouts { + // Every string represents a cash-out operation ID. + cashouts: { cashout_id: string, username: string}[]; + } + + .. ts:def:: GlobalCashoutInfo + + interface GlobalCashoutInfo { + cashout_id: string; + username: string; + status: "pending" | "confirmed"; + } + + :http:statuscode:`200 OK`: + At least one cash-out operation was found. + + :http:statuscode:`204 No Content`: + No cash-out operations were found at the bank + +.. _circuit-cashout-details: + +.. http:get:: /accounts/$USERNAME/cashouts/$CASHOUT_ID + + Returns information about the status of the ``$CASHOUT_ID`` operation. + The request is available to the administrator and the account owner. + + **Response:** + + `CashoutStatusResponse <cashout-status_>`_ + + .. _cashout-status: + + .. ts:def:: CashoutStatus + + interface CashoutStatusResponse { + status: "pending" | "confirmed"; + + // Amount debited to the internal + // regional currency bank account. + amount_debit: Amount; + + // Amount credited to the external bank account. + amount_credit: Amount; + + // Transaction subject. + subject: string; + + // Fiat bank account that will receive the cashed out amount. + // Specified as a payto URI. + credit_payto_uri: string; + + // Time when the cashout was created. + creation_time: Timestamp; + + // Time when the cashout was confirmed via its TAN. + // Missing when the operation wasn't confirmed yet. + confirmation_time?: Timestamp; + } + + **Response:** + + :http:statuscode:`404 Not found`: + The cashout operation was not found. + Aborted cashout operations will also not be found. + +Taler Bank Integration API +-------------------------- + +.. http:any:: /taler-integration/* + + All endpoints under this prefix are specified by the. + :doc:`GNU Taler bank integration API </core/api-bank-integration>`. + This API handles the communication with Taler wallets. + +Taler Wire Gateway API +---------------------- + +.. http:any:: /accounts/$USERNAME/taler-wire-gateway/* + + All endpoints under this prefix are specified + by the :doc:`GNU Taler wire gateway API </core/api-bank-wire>`. + + The endpoints are only available for accounts configured with ``is_exchange=true``. + +Taler Revenue API +---------------------- + +.. http:any:: /accounts/$USERNAME/taler-revenue/* + + All endpoints under this prefix are specified + by the :doc:`GNU Taler Revenue API </core/api-bank-revenue>`. + +EBICS Host Management +--------------------- + +The libeufin-bank can be configured to serve the +bank account transactions via the EBICS protocol. + +The API for this is served under ``/ebics``. + +.. http:post:: /ebics/request + + EBICS base URL. This URL allows clients to make EBICS requests to one of + the configured EBICS hosts. + +.. http:post:: /ebics/hosts + + Create a new EBICS host. + + **Request:** + + .. ts:def:: EbicsHostRequest + + interface EbicsHostRequest { + + // Ebics version. + host_id: string; + + // Name of the host. + ebics_version: string; + } + + +.. http:get:: /ebics/hosts + + Shows the list of all the hosts in the system. + + **Response:** + + .. ts:def:: EbicsHostResponse + + interface EbicsHostResponse { + + // shows the host IDs that are active in the system. + // The Ebics version *is* missing, but it's still available + // via the HEV message. + ebics_hosts: string[]; + } + +.. http:post:: /ebics/hosts/$HOST_ID/rotate-keys + + Overwrite the bank's Ebics keys with random ones. This is entirely + meant for tests (as the Sandbox itself is) and no backup will be + produced along this operation. + +.. http:post:: /ebics/subscribers + + Allows (only) the ``admin`` user create an EBICS + subscriber associated to a bank account. + + **Request:** + + .. ts:def:: SubscriberRequest + + interface SubscriberRequest { + + // EBICS HostID + host_id: string; + + // EBICS UserID + user_id: string; + + // EBICS PartnerID + partner_id: string; + + // Optional EBICS SystemID + system_id?: string; + + // Username of the bank account to associate with + // this subscriber. + account_username: string; + } + + +.. http:get:: /ebics/subscribers + + Shows the list of all the subscribers in the system. + + **Response:** + + .. ts:def:: SubscribersResponse + + interface SubscribersResponse { + + subscribers: Subscriber[] + } + + .. ts:def:: Subscriber + + interface Subscriber { + + // userID + user_id: string; + + // partnerID + partner_id: string; + + // hostID + host_id: string; + + // Label of the bank account + // associated with this Ebics subscriber. + account_username: string; + } diff --git a/core/api-merchant.rst b/core/api-merchant.rst @@ -20,9 +20,9 @@ .. _merchant-api: -==================== -Merchant Backend API -==================== +============================ +Merchant Backend RESTful API +============================ .. contents:: Table of Contents @@ -99,12 +99,17 @@ Authentication Each merchant instance has separate authentication settings for the private API resources of that instance. -Currently, the API supports two auth methods: +Currently, the API supports two main authentication methods: * ``external``: With this method, no checks are done by the merchant backend. Instead, a reverse proxy / API gateway must do all authentication/authorization checks. * ``token``: With this method, the client must provide a ``Authorization: Bearer $TOKEN`` - header, where ``$TOKEN`` is a secret authentication token configured for the instance. + header, where ``$TOKEN`` is a secret authentication token configured for the instance which must begin with the RFC 8959 prefix. + +Additionally, clients can send a **login token** which they may obtain from +the ``/private/login`` endpoint. Such a login token is valid only for a +limited period of time and can be used by clients to avoid storing the +long-term login secrets from an authentication method. ----------------- Configuration API @@ -148,7 +153,7 @@ to interact with directly (without HTTP-based authentication). These endpoints are used to process payments (claiming an order, paying for the order, checking payment/refund status and aborting payments), process refunds (checking refund status, obtaining the refund), -and to pick up tips. +and to pick up rewards. Claiming an order @@ -252,9 +257,11 @@ Making the payment The backend took too long to process the request. Likely the merchant's connection to the exchange timed out. Try again. :http:statuscode:`409 Conflict`: - The exchange rejected the payment because a coin was already spent, or + The exchange rejected the payment because a coin was already spent (or + used in a different way for the same purchase previously), or the merchant rejected the payment because the order was already fully paid - (and then return signatures with refunds). If a coin was already spent, + (and then return signatures with refunds). If a coin was already spent + (this includes re-using the same coin after a refund), the response will include the ``exchange_url`` for which the payment failed, in addition to the response from the exchange to the ``/batch-deposit`` request. :http:statuscode:`410 Gone`: @@ -458,10 +465,10 @@ again. **Response:** - :http:statuscode:`204 No content`: + :http:statuscode:`200 Ok`: The merchant accepted the signature. The ``frontend`` should now fulfill the contract. - Note that it is possible that refunds have been granted. + Note that it is possible that refunds have been granted. Response is of type `PaidRefundStatusResponse`. :http:statuscode:`400 Bad request`: Either the client request is malformed or some specific processing error happened that may be the fault of the client as detailed in the JSON body @@ -472,6 +479,21 @@ again. The merchant backend could not find the order or the instance and thus cannot process the request. + **Details**: + + .. ts:def:: PaidRefundStatusResponse + + interface PaidRefundStatusResponse { + + // Text to be shown to the point-of-sale staff as a proof of + // payment (present only if re-usable OTP algorithm is used). + pos_confirmation?: string; + + // True if the order has been subjected to + // refunds. False if it was simply paid. + refunded: boolean; + } + .. ts:def:: PaidRequest interface PaidRequest { @@ -723,6 +745,10 @@ the contract. Refunds must be approved by the merchant's business logic. // Amount that was refunded, including refund fee charged by the exchange // to the customer. refund_amount: Amount; + + // Timestamp when the merchant approved the refund. + // Useful for grouping refunds. + execution_time: Timestamp; } .. ts:def:: MerchantCoinRefundSuccessStatus @@ -757,18 +783,22 @@ the contract. Refunds must be approved by the merchant's business logic. // Amount that was refunded, including refund fee charged by the exchange // to the customer. refund_amount: Amount; + + // Timestamp when the merchant approved the refund. + // Useful for grouping refunds. + execution_time: Timestamp; } -Picking up tips ---------------- +Picking up rewards +------------------ -Tips are a way for wallets to obtain e-cash from +Rewards are a way for wallets to obtain e-cash from a website. -.. http:get:: [/instances/$INSTANCE]/tips/$TIP_ID +.. http:get:: [/instances/$INSTANCE]/rewards/$REWARD_ID - Handle request from wallet to provide details about a tip. + Handle request from wallet to provide details about a reward. This endpoint typically also supports requests with the "Accept" header requesting "text/html". In this case, an HTML response suitable for @@ -779,60 +809,60 @@ a website. **Response:** :http:statuscode:`200 OK`: - A tip is being returned. The backend responds with a `TipInformation`. + A reward is being returned. The backend responds with a `RewardInformation`. :http:statuscode:`404 Not found`: - The tip identifier is unknown. + The reward identifier is unknown. :http:statuscode:`406 Not acceptable`: The merchant backend could not load the template required to generate a reply in the desired format. (Likely HTML templates were not properly installed.) :http:statuscode:`410 Gone`: - A tip has been fully claimed. The JSON reply still contains the `TipInformation`. + A reward has been fully claimed. The JSON reply still contains the `RewardInformation`. - .. ts:def:: TipInformation + .. ts:def:: RewardInformation - interface TipInformation { + interface RewardInformation { - // Exchange from which the tip will be withdrawn. Needed by the + // Exchange from which the reward will be withdrawn. Needed by the // wallet to determine denominations, fees, etc. exchange_url: string; - // URL where to go after obtaining the tip. + // URL where to go after obtaining the reward. next_url: string; - // (Remaining) amount of the tip (including fees). - tip_amount: Amount; + // (Remaining) amount of the reward (including fees). + reward_amount: Amount; - // Timestamp indicating when the tip is set to expire (may be in the past). - // Note that tips that have expired MAY also result in a 404 response. + // Timestamp indicating when the reward is set to expire (may be in the past). + // Note that rewards that have expired MAY also result in a 404 response. expiration: Timestamp; } -.. http:post:: [/instances/$INSTANCE]/tips/$TIP_ID/pickup +.. http:post:: [/instances/$INSTANCE]/rewards/$REWARD_ID/pickup - Handle request from wallet to pick up a tip. + Handle request from wallet to pick up a reward. **Request:** - The request body is a `TipPickupRequest` object. + The request body is a `RewardPickupRequest` object. **Response:** :http:statuscode:`200 OK`: - A tip is being returned. The backend responds with a `TipResponse`. + A reward is being returned. The backend responds with a `RewardResponse`. :http:statuscode:`401 Unauthorized`: - The tip amount requested exceeds the tip. + The reward amount requested exceeds the reward. :http:statuscode:`404 Not found`: - The tip identifier is unknown. + The reward identifier is unknown. :http:statuscode:`409 Conflict`: Some of the denomination key hashes of the request do not match those currently available from the exchange (hence there is a conflict between what the wallet requests and what the merchant believes the exchange can provide). :http:statuscode:`410 Gone`: - The tip has expired. + The reward has expired. - .. ts:def:: TipPickupRequest + .. ts:def:: RewardPickupRequest - interface TipPickupRequest { + interface RewardPickupRequest { - // List of planchets the wallet wants to use for the tip. + // List of planchets the wallet wants to use for the reward. planchets: PlanchetDetail[]; } @@ -847,9 +877,9 @@ a website. coin_ev: CoinEnvelope; } - .. ts:def:: TipResponse + .. ts:def:: RewardResponse - interface TipResponse { + interface RewardResponse { // Blind RSA signatures over the planchets. // The order of the signatures matches the planchets list. @@ -901,13 +931,6 @@ Setting up instances .. ts:def:: InstanceConfigurationMessage interface InstanceConfigurationMessage { - // The URI where the wallet will send coins. A merchant may have - // multiple accounts, thus this is an array. Note that by - // removing URIs from this list the respective account is set to - // inactive and thus unavailable for new contracts, but preserved - // in the database as existing offers and contracts may still refer - // to it. - payto_uris: string[]; // Name of the merchant instance to create (will become $INSTANCE). // Must match the regex ``^[A-Za-z0-9][A-Za-z0-9_.@-]+$``. @@ -916,6 +939,11 @@ Setting up instances // Merchant name corresponding to this instance. name: string; + // Type of the user (business or individual). + // Defaults to 'business'. Should become mandatory field + // in the future, left as optional for API compatibility for now. + user_type?: string; + // Merchant email for customer contact. email?: string; @@ -935,17 +963,10 @@ Setting up instances // (to be put into contracts). jurisdiction: Location; - // Maximum wire fee this instance is willing to pay. - // Can be overridden by the frontend on a per-order basis. - default_max_wire_fee: Amount; - - // Default factor for wire fee amortization calculations. - // Can be overridden by the frontend on a per-order basis. - default_wire_fee_amortization: Integer; - - // Maximum deposit fee (sum over all coins) this instance is willing to pay. - // Can be overridden by the frontend on a per-order basis. - default_max_deposit_fee: Amount; + // Use STEFAN curves to determine default fees? + // If false, no fees are allowed by default. + // Can always be overridden by the frontend on a per-order basis. + use_stefan: boolean; // If the frontend does NOT specify an execution date, how long should // we tell the exchange to wait to aggregate transactions before @@ -959,7 +980,6 @@ Setting up instances } - .. http:post:: /management/instances/$INSTANCE/auth .. http:post:: [/instances/$INSTANCE]/private/auth @@ -995,6 +1015,62 @@ Setting up instances } +.. http:post:: [/instances/$INSTANCE]/private/token + + **Request:** + + The request must be a `LoginTokenRequest`. + + **Response:** + + :http:statuscode:`200 Ok`: + The backend is returning the access token in a + `LoginTokenSuccessResponse`. + + **Details:** + + .. ts:def:: LoginTokenRequest + + interface LoginTokenRequest { + // Scope of the token (which kinds of operations it will allow) + scope: "readonly" | "write"; + + // Server may impose its own upper bound + // on the token validity duration + duration?: RelativeTime; + + // Can this token be refreshed? + // Defaults to false. + refreshable?: boolean; + } + + .. ts:def:: LoginTokenSuccessResponse + + interface LoginTokenSuccessResponse { + // The login token that can be used to access resources + // that are in scope for some time. Must be prefixed + // with "Bearer " when used in the "Authorization" HTTP header. + // Will already begin with the RFC 8959 prefix. + token: string; + + // Scope of the token (which kinds of operations it will allow) + scope: "readonly" | "write"; + + // Server may impose its own upper bound + // on the token validity duration + expiration: Timestamp; + + // Can this token be refreshed? + refreshable: boolean; + } + +.. http:delete:: [/instances/$INSTANCE]/private/token + + **Response:** + + :http:statuscode:`204 No content`: + The access token used to authorize this request was revoked. + .. http:patch:: /management/instances/$INSTANCE .. http:patch:: [/instances/$INSTANCE]/private @@ -1020,15 +1096,15 @@ Setting up instances .. ts:def:: InstanceReconfigurationMessage interface InstanceReconfigurationMessage { - // The URI where the wallet will send coins. A merchant may have - // multiple accounts, thus this is an array. Note that removing - // URIs from this list deactivates the specified accounts - // (they will no longer be used for future contracts). - payto_uris: string[]; // Merchant name corresponding to this instance. name: string; + // Type of the user (business or individual). + // Defaults to 'business'. Should become mandatory field + // in the future, left as optional for API compatibility for now. + user_type?: string; + // Merchant email for customer contact. email?: string; @@ -1045,17 +1121,10 @@ Setting up instances // (to be put into contracts). jurisdiction: Location; - // Maximum wire fee this instance is willing to pay. - // Can be overridden by the frontend on a per-order basis. - default_max_wire_fee: Amount; - - // Default factor for wire fee amortization calculations. - // Can be overridden by the frontend on a per-order basis. - default_wire_fee_amortization: Integer; - - // Maximum deposit fee (sum over all coins) this instance is willing to pay. - // Can be overridden by the frontend on a per-order basis. - default_max_deposit_fee: Amount; + // Use STEFAN curves to determine default fees? + // If false, no fees are allowed by default. + // Can always be overridden by the frontend on a per-order basis. + use_stefan: boolean; // If the frontend does NOT specify an execution date, how long should // we tell the exchange to wait to aggregate transactions before @@ -1103,6 +1172,9 @@ Inspecting instances // Merchant name corresponding to this instance. name: string; + // Type of the user ("business" or "individual"). + user_type: string; + // Merchant public website. website?: string; @@ -1142,13 +1214,13 @@ Inspecting instances .. ts:def:: QueryInstancesResponse interface QueryInstancesResponse { - // The URI where the wallet will send coins. A merchant may have - // multiple accounts, thus this is an array. - accounts: MerchantAccount[]; // Merchant name corresponding to this instance. name: string; + // Type of the user ("business" or "individual"). + user_type: string; + // Merchant email for customer contact. email?: string; @@ -1168,17 +1240,10 @@ Inspecting instances // (to be put into contracts). jurisdiction: Location; - // Maximum wire fee this instance is willing to pay. - // Can be overridden by the frontend on a per-order basis. - default_max_wire_fee: Amount; - - // Default factor for wire fee amortization calculations. - // Can be overridden by the frontend on a per-order basis. - default_wire_fee_amortization: Integer; - - // Maximum deposit fee (sum over all coins) this instance is willing to pay. - // Can be overridden by the frontend on a per-order basis. - default_max_deposit_fee: Amount; + // Use STEFAN curves to determine default fees? + // If false, no fees are allowed by default. + // Can always be overridden by the frontend on a per-order basis. + use_stefan: boolean; // If the frontend does NOT specify an execution date, how long should // we tell the exchange to wait to aggregate transactions before @@ -1198,24 +1263,6 @@ Inspecting instances } - .. ts:def:: MerchantAccount - - interface MerchantAccount { - - // payto:// URI of the account. - payto_uri: string; - - // Hash over the wire details (including over the salt). - h_wire: HashCode; - - // Salt used to compute h_wire. - salt: HashCode; - - // true if this account is active, - // false if it is historic. - active: boolean; - } - Deleting instances ------------------ @@ -1327,7 +1374,12 @@ KYC status checks // URL that the user should open in a browser to // proceed with the KYC process (as returned // by the exchange's ``/kyc-check/`` endpoint). - kyc_url: string; + // Optional, missing if the account is blocked + // due to AML and not due to KYC. + kyc_url?: string; + + // AML status of the account. + aml_status: Integer; // Base URL of the exchange this is about. exchange_url: string; @@ -1355,6 +1407,193 @@ KYC status checks } + +------------- +Bank Accounts +------------- + +One or more bank accounts must be associated with an instance +so that the instance can receive payments. Payments may be made +into any of the active bank accounts of an instance. + + +.. http:post:: [/instances/$INSTANCE]/private/accounts + + This is used to add an account to an instance. + + **Request:** + + The request must have an `AccountAddDetails` body. + + **Response:** + + :http:statuscode:`200 Ok`: + Adding the account was successful, we return the salt selected by the backend and the resulting wire hash in an `AccountAddResponse`. + :http:statuscode:`404 Not found`: + The merchant instance is unknown or it is not in our data. + :http:statuscode:`409 Conflict`: + The provided information is inconsistent with the current state of the instance. + Usually this means we already have this account, but with conflicting credit facade information. + Inactive accounts can be reactivated using this method even if the + credit facade information differs from the previous state. + + .. ts:def:: AccountAddDetails + + interface AccountAddDetails { + + // payto:// URI of the account. + payto_uri: string; + + // URL from where the merchant can download information + // about incoming wire transfers to this account. + credit_facade_url?: string; + + // Credentials to use when accessing the credit facade. + // Never returned on a GET (as this may be somewhat + // sensitive data). Can be set in POST + // or PATCH requests to update (or delete) credentials. + // To really delete credentials, set them to the type: "none". + credit_facade_credentials?: FacadeCredentials; + + } + + .. ts:def:: FacadeCredentials + + type FacadeCredentials = + | NoFacadeCredentials + | BasicAuthFacadeCredentials; + + .. ts:def:: NoFacadeCredentials + + interface NoFacadeCredentials { + type: "none"; + }; + + .. ts:def:: BasicAuthFacadeCredentials + + interface BasicAuthFacadeCredentials { + type: "basic"; + + // Username to use to authenticate + username: string; + + // Password to use to authenticate + password: string; + }; + + .. ts:def:: AccountAddResponse + + interface AccountAddResponse { + + // Hash over the wire details (including over the salt). + h_wire: HashCode; + + // Salt used to compute h_wire. + salt: HashCode; + + } + + +.. http:patch:: [/instances/$INSTANCE]/private/accounts/$H_WIRE + + This is used to update a bank account. + + **Request:** + + The request must be a `AccountPatchDetails`. + + **Response:** + + :http:statuscode:`204 No content`: + The template has successfully modified. + :http:statuscode:`404 Not found`: + The template(ID) is unknown to the backend. + + .. ts:def:: AccountPatchDetails + + interface AccountPatchDetails { + + // URL from where the merchant can download information + // about incoming wire transfers to this account. + credit_facade_url?: string; + + // Credentials to use when accessing the credit facade. + // Never returned on a GET (as this may be somewhat + // sensitive data). Can be set in POST + // or PATCH requests to update (or delete) credentials. + // To really delete credentials, set them to the type: "none". + // If the argument is omitted, the old credentials + // are simply preserved. + credit_facade_credentials?: FacadeCredentials; + } + + +.. http:get:: [/instances/$INSTANCE]/private/accounts + + This is used to return the list of all the bank accounts + of an instance. + + **Response:** + + :http:statuscode:`200 OK`: + The backend has successfully returned all the accounts. Returns a `AccountsSummaryResponse`. + :http:statuscode:`404 Not found`: + The backend has does not know about the instance. + + .. ts:def:: AccountsSummaryResponse + + interface AccountsSummaryResponse { + + // List of accounts that are known for the instance. + accounts: BankAccountEntry[]; + } + + .. ts:def:: BankAccountEntry + + interface BankAccountEntry { + + // payto:// URI of the account. + payto_uri: string; + + // Hash over the wire details (including over the salt). + h_wire: HashCode; + + // Salt used to compute h_wire. + salt: HashCode; + + // URL from where the merchant can download information + // about incoming wire transfers to this account. + credit_facade_url?: string; + + // true if this account is active, + // false if it is historic. + active: boolean; + } + +.. http:get:: [/instances/$INSTANCE]/private/accounts/$H_WIRE + + This is used to obtain detailed information about a specific bank account. + + + **Response:** + + :http:statuscode:`200 OK`: + The backend has successfully returned the detailed information about a specific bank account. + Returns a `BankAccountEntry`. + :http:statuscode:`404 Not found`: + The bank account or instance is unknown to the backend. + + +.. http:delete:: [/instances/$INSTANCE]/private/accounts/$H_WIRE + + **Response:** + + :http:statuscode:`204 No content`: + The backend has successfully deactivated the account. + :http:statuscode:`404 Not found`: + The backend does not know the instance or the account. + + -------------------- Inventory management -------------------- @@ -1724,6 +1963,7 @@ Creating orders (2) The merchant instance is unknown (including possibly the instance being not configured for new orders). (3) The wire method specified is not supported by the backend. + (4) An OTP device ID was specified and is unknown. Details in the error code. NOTE: currently the client has no good way to find out which product @@ -1775,6 +2015,9 @@ Creating orders // if the backend auto-generates one). Default is 'true'. create_token?: boolean; + // OTP device ID to associate with the order. + // This parameter is optional. + otp_id?: string; } .. ts:def:: Order @@ -2271,35 +2514,12 @@ Informing the backend about incoming wire transfers **Response:** - :http:statuscode:`200 OK`: - The wire transfer is known to the exchange, details about it follow in the body. - The body of the response is a `MerchantTrackTransferResponse`. - :http:statuscode:`202 Accepted`: - The exchange provided conflicting information about the transfer. Namely, - there is at least one deposit among the deposits aggregated by ``wtid`` - that accounts for a coin whose - details don't match the details stored in merchant's database about the same keyed coin. - The response body contains the `ExchangeConflictDetails`. - This is indicative of a malicious exchange that claims one thing, but did - something else. (With respect to the HTTP specficiation, it is not - precisely that we did not act upon the request, more that the usual - action of filing the transaction as 'finished' does not apply. In - the future, this is a case where the backend actually should report - the bad behavior to the auditor -- and then hope for the auditor to - resolve it. So in that respect, 202 is the right status code as more - work remains to be done for a final resolution.) + :http:statuscode:`204 No content`: + The wire transfer is now confirmed at the merchant. :http:statuscode:`404 Not found`: The instance or account are unknown to the exchange. :http:statuscode:`409 Conflict`: - The wire transfer identifier is already known to us, but for a different amount, - wire method or exchange, or the amount reported by the exchange differs from - the amount reported by the merchant. - :http:statuscode:`502 Bad gateway`: - The exchange returned an error when we asked it about the ``GET /transfer`` status - for this wire transfer. Details of the exchange error are returned. - :http:statuscode:`504 Gateway timeout`: - The merchant's interaction with the exchange took too long. - The client might want to try again later. + The wire transfer identifier is already known to us, but for a different amount. **Details:** @@ -2319,168 +2539,6 @@ Informing the backend about incoming wire transfers exchange_url: string; } - .. ts:def:: MerchantTrackTransferResponse - - interface MerchantTrackTransferResponse { - // Total amount transferred. - total: Amount; - - // Applicable wire fee that was charged. - wire_fee: Amount; - - // Time of the execution of the wire transfer by the exchange, according to the exchange. - execution_time: Timestamp; - - // Details about the deposits. - deposits_sums: MerchantTrackTransferDetail[]; - } - - .. ts:def:: MerchantTrackTransferDetail - - interface MerchantTrackTransferDetail { - // Business activity associated with the wire transferred amount - // ``deposit_value``. - order_id: string; - - // The total amount the exchange paid back for ``order_id``. - deposit_value: Amount; - - // Applicable fees for the deposit. - deposit_fee: Amount; - } - - - .. ts:def:: ExchangeConflictDetails - - type ExchangeConflictDetails = WireFeeConflictDetails | - TrackTransferConflictDetails; - - - .. ts:def:: WireFeeConflictDetails - - // Note: this is not the full 'proof' of misbehavior, as - // the bogus message from the exchange with a signature - // over the 'different' wire fee is missing. - // - // This information is NOT provided by the current implementation, - // because this would be quite expensive to generate and is - // hardly needed _here_. Once we add automated reports for - // the Taler auditor, we need to generate this data anyway - // and should probably return it here as well. - interface WireFeeConflictDetails { - // Numerical `error code <error-codes>`: - code: "TALER_EC_MERCHANT_PRIVATE_POST_TRANSFERS_BAD_WIRE_FEE"; - - // Text describing the issue for humans. - hint: string; - - // Wire fee (wrongly) charged by the exchange, breaking the - // contract affirmed by the ``exchange_sig``. - wire_fee: Amount; - - // Timestamp of the wire transfer. - execution_time: Timestamp; - - // The expected wire fee (as signed by the exchange). - expected_wire_fee: Amount; - - // Expected closing fee (needed to verify signature). - expected_closing_fee: Amount; - - // Start date of the expected fee structure. - start_date: Timestamp; - - // End date of the expected fee structure. - end_date: Timestamp; - - // Signature of the exchange affirming the expected fee structure. - master_sig: EddsaSignature; - - // Master public key of the exchange. - master_pub: EddsaPublicKey; - } - - - .. ts:def:: TrackTransferConflictDetails - - interface TrackTransferConflictDetails { - // Numerical `error code <error-codes>`. - code: "TALER_EC_MERCHANT_PRIVATE_POST_TRANSFERS_CONFLICTING_REPORTS"; - - // Text describing the issue for humans. - hint: string; - - // Offset in the ``exchange_transfer`` where the - // exchange's response fails to match the ``exchange_deposit_proof``. - conflict_offset: number; - - // The response from the exchange which tells us when the - // coin was returned to us, except that it does not match - // the expected value of the coin. - // - // This field is NOT provided by the current implementation, - // because this would be quite expensive to generate and is - // hardly needed _here_. Once we add automated reports for - // the Taler auditor, we need to generate this data anyway - // and should probably return it here as well. - exchange_transfer?: TrackTransferResponse; - - // Public key of the exchange used to sign the response to - // our deposit request. - deposit_exchange_pub: EddsaPublicKey; - - // Signature of the exchange signing the (conflicting) response. - // Signs over a ``struct TALER_DepositConfirmationPS``. - deposit_exchange_sig: EddsaSignature; - - // Hash of the merchant's bank account the wire transfer went to. - h_wire: HashCode; - - // Hash of the contract terms with the conflicting deposit. - h_contract_terms: HashCode; - - // At what time the exchange received the deposit. Needed - // to verify the ``exchange_sig``. - deposit_timestamp: Timestamp; - - // At what time the refund possibility expired (needed to verify ``exchange_sig``). - refund_deadline: Timestamp; - - // Public key of the coin for which we have conflicting information. - coin_pub: EddsaPublicKey; - - // Amount the exchange counted the coin for in the transfer. - amount_with_fee: Amount; - - // Expected value of the coin. - coin_value: Amount; - - // Expected deposit fee of the coin. - coin_fee: Amount; - - // Expected deposit fee of the coin. - deposit_fee: Amount; - - } - - .. ts:def:: TrackTransferProof - - interface TrackTransferProof { - // Signature from the exchange made with purpose - // ``TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE_DEPOSIT``. - exchange_sig: EddsaSignature; - - // Public EdDSA key of the exchange that was used to generate the signature. - // Should match one of the exchange's signing keys from ``/keys``. Again given - // explicitly as the client might otherwise be confused by clock skew as to - // which signing key was used. - exchange_pub: EddsaSignature; - - // Hash of the wire details (identical for all deposits). - // Needed to check the ``exchange_sig`` - h_wire: HashCode; - } - Querying known wire transfers ----------------------------- @@ -2582,36 +2640,34 @@ once we got a reply from the exchange. The transfer cannot be deleted anymore. --------------------- -Backend: Giving tips --------------------- +----------------------- +Backend: Giving rewards +----------------------- -Tips are a way for websites to give small amounts of e-cash to visitors (for +Rewards are a way for websites to give small amounts of e-cash to visitors (for example as a financial reward for providing information or watching -advertizements). Tips are non-contractual: neither merchant nor consumer +advertizements). Rewards are non-contractual: neither merchant nor consumer have any contractual information about the other party as a result of the -tip. +reward. Create reserve -------------- -Reserves are basically funds a merchant has provided -to an exchange for a tipping campaign. Each reserve -has a limited lifetime (say 2--4 weeks). Any funds -not used to tip customers will automatically be wired -back from the exchange to the originating account. +Reserves are basically funds a merchant has provided to an exchange for a +rewards campaign. Each reserve has a limited lifetime (say 2--4 weeks). Any +funds not used to reward customers will automatically be wired back from the +exchange to the originating account. -To begin tipping, a merchant must tell the backend -to set up a reserve. The backend will return a -reserve public key which must be used as the wire -transfer subject when wiring the tipping campaign -funds to the exchange. +Before handing out rewards, a merchant must tell the backend to set up a +reserve. The backend will return a reserve public key which must be used as +the wire transfer subject when wiring the reward campaign funds to the +exchange. -.. _tips: +.. _rewards: .. http:post:: [/instances/$INSTANCE]/private/reserves - Create a reserve for tipping. + Create a reserve for rewards. This request is **not** idempotent. However, while repeating it will create another reserve, that is generally pretty harmless @@ -2631,7 +2687,7 @@ funds to the exchange. :http:statuscode:`408 Request timeout`: The exchange did not respond on time. :http:statuscode:`409 Conflict`: - The exchange does not support the requested wire method. + The exchange does not support the requested wire method or does not allow rewards. :http:statuscode:`502 Bad gateway`: We could not obtain ``/wire`` details from the specified exchange base URL. :http:statuscode:`504 Gateway timeout`: @@ -2644,7 +2700,7 @@ funds to the exchange. // Amount that the merchant promises to put into the reserve. initial_balance: Amount; - // Exchange the merchant intends to use for tipping. + // Exchange the merchant intends to use for rewards. exchange_url: string; // Desired wire method, for example "iban" or "x-taler-bank". @@ -2657,13 +2713,13 @@ funds to the exchange. // Public key identifying the reserve. reserve_pub: EddsaPublicKey; - // Wire account of the exchange where to transfer the funds. - payto_uri: string; + // Wire accounts of the exchange where to transfer the funds. + accounts: WireAccount[]; } .. http:get:: [/instances/$INSTANCE]/private/reserves - Obtain list of reserves that have been created for tipping. + Obtain list of reserves that have been created for rewards. **Request:** @@ -2674,12 +2730,12 @@ funds to the exchange. **Response:** :http:statuscode:`200 OK`: - Returns a list of known tipping reserves. - The body is a `TippingReserveStatus`. + Returns a list of known reward reserves. + The body is a `RewardReserveStatus`. - .. ts:def:: TippingReserveStatus + .. ts:def:: RewardReserveStatus - interface TippingReserveStatus { + interface RewardReserveStatus { // Array of all known reserves (possibly empty!). reserves: ReserveStatusEntry[]; } @@ -2706,7 +2762,7 @@ funds to the exchange. // Amount picked up so far. pickup_amount: Amount; - // Amount approved for tips that exceeds the pickup_amount. + // Amount approved for rewards that exceeds the pickup_amount. committed_amount: Amount; // Is this reserve active (false if it was deleted but not purged)? @@ -2719,18 +2775,18 @@ Query funds remaining .. http:get:: [/instances/$INSTANCE]/private/reserves/$RESERVE_PUB - Obtain information about a specific reserve that have been created for tipping. + Obtain information about a specific reserve that have been created for rewards. **Request:** - :query tips: *Optional*. If set to "yes", returns also information about all of the tips created. + :query rewards: *Optional*. If set to "yes", returns also information about all of the rewards created. **Response:** :http:statuscode:`200 OK`: Returns the `ReserveDetail`. :http:statuscode:`404 Not found`: - The tipping reserve is not known. + The reward reserve is not known. :http:statuscode:`502 Bad gateway`: We are having trouble with the request because of a problem with the exchange. Likely returned with an "exchange_code" in addition to a "code" and @@ -2762,111 +2818,112 @@ Query funds remaining // Amount picked up so far. pickup_amount: Amount; - // Amount approved for tips that exceeds the pickup_amount. + // Amount approved for rewards that exceeds the pickup_amount. committed_amount: Amount; - // Array of all tips created by this reserves (possibly empty!). + // Array of all rewards created by this reserves (possibly empty!). // Only present if asked for explicitly. - tips?: TipStatusEntry[]; + rewards?: RewardStatusEntry[]; // Is this reserve active (false if it was deleted but not purged)? active: boolean; - // URI to use to fill the reserve, can be NULL + // Array of wire accounts of the exchange that could + // be used to fill the reserve, can be NULL // if the reserve is inactive or was already filled - payto_uri: string; + accounts?: WireAccount[]; // URL of the exchange hosting the reserve, // NULL if the reserve is inactive exchange_url: string; } - .. ts:def:: TipStatusEntry + .. ts:def:: RewardStatusEntry - interface TipStatusEntry { + interface RewardStatusEntry { - // Unique identifier for the tip. - tip_id: HashCode; + // Unique identifier for the reward. + reward_id: HashCode; - // Total amount of the tip that can be withdrawn. + // Total amount of the reward that can be withdrawn. total_amount: Amount; - // Human-readable reason for why the tip was granted. + // Human-readable reason for why the reward was granted. reason: string; } -Authorizing tips ----------------- +Authorizing rewards +------------------- -.. http:post:: [/instances/$INSTANCE]/private/reserves/$RESERVE_PUB/authorize-tip +.. http:post:: [/instances/$INSTANCE]/private/reserves/$RESERVE_PUB/authorize-reward - Authorize creation of a tip from the given reserve. + Authorize creation of a reward from the given reserve. **Request:** - The request body is a `TipCreateRequest` object. + The request body is a `RewardCreateRequest` object. **Response:** :http:statuscode:`200 OK`: - A tip has been created. The backend responds with a `TipCreateConfirmation`. + A reward has been created. The backend responds with a `RewardCreateConfirmation`. :http:statuscode:`404 Not found`: The instance or the reserve is unknown to the backend. :http:statuscode:`412 Precondition failed`: - The tip amount requested exceeds the available reserve balance for tipping. + The reward amount requested exceeds the available reserve balance for rewards. - .. ts:def:: TipCreateRequest + .. ts:def:: RewardCreateRequest - interface TipCreateRequest { - // Amount that the customer should be tipped. + interface RewardCreateRequest { + // Amount that the customer should be rewarded. amount: Amount; - // Justification for giving the tip. + // Justification for giving the reward. justification: string; - // URL that the user should be directed to after tipping, - // will be included in the tip_token. + // URL that the user should be directed to after receiving the reward, + // will be included in the reward_token. next_url: string; } - .. ts:def:: TipCreateConfirmation + .. ts:def:: RewardCreateConfirmation - interface TipCreateConfirmation { - // Unique tip identifier for the tip that was created. - tip_id: HashCode; + interface RewardCreateConfirmation { + // Unique reward identifier for the reward that was created. + reward_id: HashCode; - // taler://tip URI for the tip. - taler_tip_uri: string; + // taler://reward URI for the reward. + taler_reward_uri: string; // URL that will directly trigger processing - // the tip when the browser is redirected to it. - tip_status_url: string; + // the reward when the browser is redirected to it. + reward_status_url: string; - // When does the tip expire? - tip_expiration: Timestamp; + // When does the reward expire? + reward_expiration: Timestamp; } -.. http:post:: [/instances/$INSTANCE]/private/tips +.. http:post:: [/instances/$INSTANCE]/private/rewards - Authorize creation of a tip from the given reserve, except with + Authorize creation of a reward, with automatic selection of a working reserve of the instance by the - backend. Intentionally otherwise identical to the ``/authorize-tip`` + backend. Intentionally otherwise identical to the ``/authorize-reward`` endpoint given above. **Request:** - The request body is a `TipCreateRequest` object. + The request body is a `RewardCreateRequest` object. **Response:** :http:statuscode:`200 OK`: - A tip has been created. The backend responds with a `TipCreateConfirmation`. + A reward has been created. The backend responds with a `RewardCreateConfirmation`. :http:statuscode:`404 Not found`: The instance is unknown to the backend. :http:statuscode:`412 Precondition failed`: - The tip amount requested exceeds the available reserve balance for tipping + The reward amount requested exceeds the available reserve balance for rewards in all of the reserves of the instance. @@ -2876,13 +2933,13 @@ Deleting reserves .. http:delete:: [/instances/$INSTANCE]/private/reserves/$RESERVE_PUB Delete information about a reserve. Fails if the reserve still has - committed to tips that were not yet picked up and that have not yet + committed to rewards that were not yet picked up and that have not yet expired. **Request:** :query purge: *Optional*. If set to YES, the reserve and all information - about tips it issued will be fully deleted. + about rewards it issued will be fully deleted. Otherwise only the private key would be deleted. **Response:** @@ -2892,43 +2949,48 @@ Deleting reserves :http:statuscode:`404 Not found`: The backend does not know the instance or the reserve. :http:statuscode:`409 Conflict`: - The backend refuses to delete the reserve (committed tips awaiting pickup). + The backend refuses to delete the reserve (committed rewards awaiting pickup). -Checking tip status -------------------- +Checking reward status +---------------------- -.. http:get:: [/instances/$INSTANCE]/private/tips/$TIP_ID +.. http:get:: [/instances/$INSTANCE]/private/rewards/$REWARD_ID - Obtain information about a particular tip. + Obtain information about a particular reward. **Request:** - :query pickups: If set to "yes", returns also information about all of the pickups. + :query pickups: *Optional*. If set to "yes", returns also information about all of the pickups. + :query min_amount: *Optional*. Minimum pick-up amount the client is interested in. + :query timeout_ms=NUMBER: *Optional.* If specified, the merchant backend will + wait up to ``timeout_ms`` milliseconds for rewards of at least min_pick_up to be + picked up. A client must never rely on this behavior, as the + merchant backend may return a response immediately. **Response:** :http:statuscode:`200 OK`: - The tip is known. The backend responds with a `TipDetails` message. + The reward is known. The backend responds with a `RewardDetails` message. :http:statuscode:`404 Not found`: - The tip is unknown to the backend. + The reward is unknown to the backend. - .. ts:def:: TipDetails + .. ts:def:: RewardDetails - interface TipDetails { - // Amount that we authorized for this tip. + interface RewardDetails { + // Amount that we authorized for this reward. total_authorized: Amount; // Amount that was picked up by the user already. total_picked_up: Amount; - // Human-readable reason given when authorizing the tip. + // Human-readable reason given when authorizing the reward. reason: string; - // Timestamp indicating when the tip is set to expire (may be in the past). + // Timestamp indicating when the reward is set to expire (may be in the past). expiration: Timestamp; - // Reserve public key from which the tip is funded. + // Reserve public key from which the reward is funded. reserve_pub: EddsaPublicKey; // Array showing the pickup operations of the wallet (possibly empty!). @@ -2950,13 +3012,13 @@ Checking tip status } -.. http:get:: [/instances/$INSTANCE]/private/tips +.. http:get:: [/instances/$INSTANCE]/private/rewards - Return the list of all tips. + Return the list of all rewards. **Request:** - :query include_expired: *Optional*. If set to "yes", the result includes expired tips also. Otherwise, only active tips are returned. + :query include_expired: *Optional*. If set to "yes", the result includes expired rewards also. Otherwise, only active rewards are returned. :query limit: *Optional*. At most return the given number of results. Negative for descending in database row id, positive for ascending in database row id. @@ -2965,36 +3027,182 @@ Checking tip status **Response:** :http:statuscode:`200 OK`: - The backend has successfully found the list of tips. The backend responds - with a `TipsResponse`. + The backend has successfully found the list of rewards. The backend responds + with a `RewardsResponse`. - .. ts:def:: TipsResponse + .. ts:def:: RewardsResponse - interface TipsResponse { + interface RewardsResponse { - // List of tips that are present in the backend. - tips: Tip[]; + // List of rewards that are present in the backend. + rewards: Reward[]; } - .. ts:def:: Tip + .. ts:def:: Reward - interface Tip { + interface Reward { - // ID of the tip in the backend database. + // ID of the reward in the backend database. row_id: number; - // Unique identifier for the tip. - tip_id: HashCode; + // Unique identifier for the reward. + reward_id: HashCode; - // (Remaining) amount of the tip (including fees). - tip_amount: Amount; + // (Remaining) amount of the reward (including fees). + reward_amount: Amount; } +----------- +OTP Devices +----------- +OTP devices can be used to allow offline merchants +to validate that a customer made a payment. --------- -Template --------- + +.. http:post:: [/instances/$INSTANCE]/private/otp-devices + + This is used to associate an OTP device with an instance. + + **Request:** + + The request must be a `OtpDeviceAddDetails`. + + **Response:** + + :http:statuscode:`204 No content`: + The creation of the template is successful. + :http:statuscode:`404 Not found`: + The merchant instance is unknown or it is not in our data. + + .. ts:def:: OtpDeviceAddDetails + + interface OtpDeviceAddDetails { + + // Device ID to use. + otp_device_id: string; + + // Human-readable description for the device. + otp_device_description: string; + + // A base64-encoded key + otp_key: string; + + // Algorithm for computing the POS confirmation. + otp_algorithm: Integer; + + // Counter for counter-based OTP devices. + otp_ctr?: Integer; + } + + +.. http:patch:: [/instances/$INSTANCE]/private/otp-devices/$DEVICE_ID + + This is used to update an OTP device. It is useful when we need to change information in the OTP device or when we have mistake some information. + + **Request:** + + The request must be a `OtpDevicePatchDetails`. + + **Response:** + + :http:statuscode:`204 No content`: + The template has successfully modified. + :http:statuscode:`404 Not found`: + The template(ID) is unknown to the backend. + :http:statuscode:`409 Conflict`: + The provided information is inconsistent with the current state of the template. Changes made is the same with + another store. + + .. ts:def:: OtpDevicePatchDetails + + interface OtpDevicePatchDetails { + + // Human-readable description for the device. + otp_device_description: string; + + // A base64-encoded key + otp_key: string; + + // Algorithm for computing the POS confirmation. + otp_algorithm: Integer; + + // Counter for counter-based OTP devices. + otp_ctr?: Integer; + } + + +.. http:get:: [/instances/$INSTANCE]/private/otp-devices + + This is used to return the list of all the OTP devices. + + **Response:** + + :http:statuscode:`200 OK`: + The backend has successfully returned all the templates. Returns a `OtpDeviceSummaryResponse`. + :http:statuscode:`404 Not found`: + The backend has does not know about the instance. + + .. ts:def:: OtpDeviceSummaryResponse + + interface OtpDeviceSummaryResponse { + + // Array of devices that are present in our backend. + otp_devices: OtpDeviceEntry[]; + } + + .. ts:def:: OtpDeviceEntry + + interface OtpDeviceEntry { + + // Device identifier. + otp_device_id: string; + + // Human-readable description for the device. + device_description: string; + } + +.. http:get:: [/instances/$INSTANCE]/private/otp-devices/$DEVICE_ID + + This is used to obtain detailed information about a specific OTP device. + + + **Response:** + + :http:statuscode:`200 OK`: + The backend has successfully returned the detailed information about a specific OTP device. + Returns a `OtpDeviceDetails`. + :http:statuscode:`404 Not found`: + The OTP device or instance is unknown to the backend. + + .. ts:def:: OtpDeviceDetails + + interface OtpDeviceDetails { + + // Human-readable description for the device. + device_description: string; + + // Algorithm for computing the POS confirmation. + otp_algorithm: Integer; + + // Counter for counter-based OTP devices. + otp_ctr?: Integer; + + } + +.. http:delete:: [/instances/$INSTANCE]/private/otp-devices/$DEVICE_ID + + **Response:** + + :http:statuscode:`204 No content`: + The backend has successfully deleted the OTP device. + :http:statuscode:`404 Not found`: + The backend does not know the instance or the OTP device. + + +--------- +Templates +--------- The template is a backend feature that is used to allow wallets to create an order. This is useful in cases where a store does not have Internet @@ -3071,12 +3279,9 @@ Adding templates // Human-readable description for the template. template_description: string; - // A base64-encoded key of the point-of-sale. + // OTP device ID. // This parameter is optional. - pos_key?: string; - - // Algorithm for computing the POS confirmation, 0 for none. - pos_algorithm?: Integer; + otp_id?: string; // Additional information in a separate template. template_contract: TemplateContractDetails; @@ -3135,12 +3340,9 @@ Editing templates // Human-readable description for the template. template_description: string; - // A base64-encoded key of the point-of-sale. + // OTP device ID. // This parameter is optional. - pos_key?: string; - - // Algorithm for computing the POS confirmation, 0 for none. - pos_algorithm?: Integer; + otp_id?: string; // Additional information in a separate template. template_contract: TemplateContractDetails; @@ -3197,7 +3399,7 @@ Inspecting template The backend has successfully returned the detailed information about a specific template. Returns a `TemplateDetails`. :http:statuscode:`404 Not found`: - The template(ID) is unknown to the backend. + The instance or template(ID) is unknown to the backend. .. ts:def:: TemplateDetails @@ -3207,12 +3409,9 @@ Inspecting template // Human-readable description for the template. template_description: string; - // A base64-encoded key of the point-of-sale. + // OTP device ID. // This parameter is optional. - pos_key?: string; - - // Algorithm for computing the POS confirmation, 0 for none. - pos_algorithm?: Integer; + otp_id?: string; // Additional information in a separate template. template_contract: TemplateContractDetails; @@ -3514,23 +3713,9 @@ The contract terms must have the following structure: fulfillment_message_i18n?: { [lang_tag: string]: string }; // Maximum total deposit fee accepted by the merchant for this contract. + // Overrides defaults of the merchant instance. max_fee: Amount; - // Maximum wire fee accepted by the merchant (customer share to be - // divided by the ``wire_fee_amortization`` factor, and further reduced - // if deposit fees are below ``max_fee``). Default if missing is zero. - max_wire_fee: Amount; - - // Over how many customer transactions does the merchant expect to - // amortize wire fees on average? If the exchange's wire fee is - // above ``max_wire_fee``, the difference is divided by this number - // to compute the expected customer's contribution to the wire fee. - // The customer's contribution may further be reduced by the difference - // between the ``max_fee`` and the sum of the actual deposit fees. - // Optional, default value if missing is 1. 0 and negative values are - // invalid and also interpreted as 1. - wire_fee_amortization: number; - // List of products that are part of the purchase (see `Product`). products: Product[]; @@ -3567,9 +3752,6 @@ The contract terms must have the following structure: // The wire transfer fees must be added based on this wire transfer method. wire_method: string; - // Any exchanges audited by these auditors are accepted by the merchant. - auditors: Auditor[]; - // Exchanges that the merchant accepts even if it does not accept any auditors that audit them. exchanges: Exchange[]; @@ -3737,6 +3919,18 @@ It has the following structure: // The exchange's base URL. url: string; + // How much would the merchant like to use this exchange. + // The wallet should use a suitable exchange with high + // priority. The following priority values are used, but + // it should be noted that they are NOT in any way normative. + // + // 0: likely it will not work (recently seen with account + // restriction that would be bad for this merchant) + // 512: merchant does not know, might be down (merchant + // did not yet get /wire response). + // 1024: good choice (recently confirmed working) + priority: Integer; + // Master public key of the exchange. master_pub: EddsaPublicKey; } diff --git a/core/api-overview.rst b/core/api-overview.rst @@ -0,0 +1,146 @@ +.. + This file is part of GNU TALER. + Copyright (C) 2014-2023 Taler Systems SA + + TALER 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 2.1, or (at your option) any later version. + + TALER 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 + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + + @author Florian Dold + @author Benedikt Muller + @author Sree Harsha Totakura + @author Marcello Stanisci + @author Christian Grothoff + +======== +Overview +======== + +.. rubric:: Taler Exchange Public API + +* **Summary**: Public API for the payment service provider component of GNU Taler. +* **Providers**: GNU Taler Exchange +* **Consumers**: Wallet, Merchant +* :doc:`Docs <api-exchange>` + +.. rubric:: Taler Exchange Management API + +* **Summary**: Management API for the payment service provider component of GNU Taler. +* **Providers**: GNU Taler Exchange +* **Consumers**: Exchange tooling (``taler-exchange-offline``), Auditor +* :doc:`Docs <api-exchange>` + +.. rubric:: Taler Merchant Backend Public API + +* **Summary**: Allows communication between merchants and users' wallets. +* **Providers**: GNU Taler Merchant backend +* **Consumers**: Wallet +* :doc:`Docs <api-merchant>` + +.. rubric:: Taler Merchant Backend Private API + +* **Summary**: Allows the merchant to manage Taler-based payments and related functionality. +* **Providers**: GNU Taler Merchant backend +* **Consumers**: Merchant's shop Website backend, Merchant PoS app, Merchant Backoffice UI +* :doc:`Docs <api-merchant>` + +.. rubric:: Taler Wallet Core API + +* **Summary**: API to access functionality of the Taler Wallet service running locally on user's devices. +* **Providers**: wallet-core +* **Consumers**: UIs for the GNU Taler wallet + +.. rubric:: Taler Bank Integration API + +* **Summary**: Offered by banks to provide the wallet/user with more information about ongoing withdrawals of Taler digital cash. +* **Providers**: Taler fakebank, LibEuFin demobank, Banks (that provide extra Taler support) +* **Consumers**: Taler Wallet +* :doc:`Docs <api-bank-integration>` + +.. rubric:: Libefin Bank API + +* **Summary**: Protocol to manage a simple core bank with optional regional + currency support. Allows access to a bank account by the owner of the + account. The owner can access the account balance, transaction list, and initate + payments. +* **Providers**: LibEuFin demobank, Taler Fakebank (partial) +* **Consumers**: Cashier App, demobank-ui +* :doc:`Docs <api-libeufin-bank>` + + +.. rubric:: Taler Wire Gateway API + +* **Summary**: Allows the Taler Exchange to query incoming transactions and initiate payments with a protocol that abstracts away details of the underlying banking system. + +* **Providers**: Taler fakebank, LibEuFin Nexus, Depoloymerization wire gateway + +* **Consumers**: GNU Taler Exchange, Wire Auditor + +* :doc:`Docs <api-bank-wire>` + +.. rubric:: Taler Sync API + +* **Summary**: Encrypted Data blob storage and retrieval API with payments for storage handled by GNU Taler payments. + +* **Providers**: GNU Taler Sync service + +* **Consumers**: Taler Wallet + +* :doc:`Docs <api-sync>` + +.. rubric:: Taler Auditor API + +* **Summary**: Reporting of certain transactions or potential problems directly to the auditor. +* **Providers**: GNU Taler Auditor service +* **Consumers**: GNU Taler Merchant, eventually Taler Wallet +* :doc:`Docs <api-auditor>` + +.. rubric:: Taldir API + +* **Summary**: Looking up of Taler mailboxes associated with particular Internet service addresses. +* **Providers**: GNU TalDir service +* **Consumers**: GNU Taler Wallet +* :doc:`Docs <api-taldir>` + +.. rubric:: Taler Mailbox API + +* **Summary**: Tansmission of encrypted payment messages between Taler wallets. +* **Providers**: GNU Taler Mailbox service +* **Consumers**: GNU Taler Wallet +* :doc:`Docs <api-mailbox>` + +.. rubric:: Anastasis Provider Public API + +* **Summary**: Backup for secret splitting backup and recovery with GNU Anastasis providers. +* **Providers**: GNU Anastasis providers +* **Consumers**: Anastasis core client implementations (C implementation, TypeScript implementation) + +.. rubric:: Anastasis Reducer API + +* **Summary**: API used to step through the backup and recovery process of GNU Anastasis. +* **Providers**: Anastasis core client implementations (C implementation, TypeScript implementation) +* **Consumers**: Anastasis UIs (CLI, GTK, anastasis-webui) + +.. rubric:: LibEuFin Nexus API + +* **Summary**: API used to configure and access LibEuFin nexus, a generic server that supports multiple protocols to access a bank account. + +* **Providers**: LibEuFin Nexus service + +* **Consumers**: ``libeufin-cli``, (future) LibEuFin Web UI + +.. rubric:: EBICS + +* **Summary**: Allows businesses/banks/consumers to exchange data with a bank's core banking system. +* **Consumers**: LibEuFin Nexus +* **Providers**: libeufin-bank, Banks + + + diff --git a/core/api-sync.rst b/core/api-sync.rst @@ -18,7 +18,7 @@ .. _sync-api: ====================================== -Backup and Synchronization Service API +Backup and Synchronization RESTful API ====================================== The backup and synchronization service uses an EdDSA key @@ -102,6 +102,8 @@ over TLS, and that the synchronization service is trusted to not build user's location profiles by linking client IP addresses and client keys. +.. contents:: Table of Contents + .. include:: tos.rst diff --git a/core/api-wire.rst b/core/api-wire.rst @@ -1,398 +0,0 @@ -.. - This file is part of GNU TALER. - Copyright (C) 2019-2021 Taler Systems SA - - TALER 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 2.1, or (at your option) any later version. - - TALER 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 - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - -=========================== -Taler Wire Gateway HTTP API -=========================== - -This section describes the API offered by the Taler wire gateway. The API is -used by the exchange to trigger transactions and query incoming transactions, as -well as by the auditor to query incoming and outgoing transactions. - -This API is currently implemented by the Taler Demo Bank, as well as by -LibEuFin (work in progress). - - --------------- -Authentication --------------- - -The bank library authenticates requests to the wire gateway via -`HTTP basic auth <https://tools.ietf.org/html/rfc7617>`_. - -------------------- -Making Transactions -------------------- - -.. http:post:: ${BASE_URL}/transfer - - This API allows the exchange to make a transaction, typically to a merchant. The bank account - of the exchange is not included in the request, but instead derived from the user name in the - authentication header and/or the request base URL. - - To make the API idempotent, the client must include a nonce. Requests with the same nonce - are rejected unless the request is the same. - - **Request:** The body of this request must have the format of a `TransferRequest`. - - **Response:** - - :http:statuscode:`200 OK`: - The request has been correctly handled, so the funds have been transferred to - the recipient's account. The body is a `TransferResponse`. - :http:statuscode:`400 Bad request`: - Request malformed. The bank replies with an `ErrorDetail` object. - :http:statuscode:`401 Unauthorized`: - Authentication failed, likely the credentials are wrong. - :http:statuscode:`404 Not found`: - The endpoint is wrong or the user name is unknown. The bank replies with an `ErrorDetail` object. - :http:statuscode:`409 Conflict`: - A transaction with the same ``transaction_uid`` but different transaction details - has been submitted before. - - **Details:** - - .. ts:def:: TransferResponse - - interface TransferResponse { - - // Timestamp that indicates when the wire transfer will be executed. - // In cases where the wire transfer gateway is unable to know when - // the wire transfer will be executed, the time at which the request - // has been received and stored will be returned. - // The purpose of this field is for debugging (humans trying to find - // the transaction) as well as for taxation (determining which - // time period a transaction belongs to). - timestamp: Timestamp; - - // Opaque ID of the transaction that the bank has made. - row_id: SafeUint64; - } - - - .. ts:def:: TransferRequest - - interface TransferRequest { - // Nonce to make the request idempotent. Requests with the same - // ``transaction_uid`` that differ in any of the other fields - // are rejected. - request_uid: HashCode; - - // Amount to transfer. - amount: Amount; - - // Base URL of the exchange. Shall be included by the bank gateway - // in the appropriate section of the wire transfer details. - exchange_base_url: string; - - // Wire transfer identifier chosen by the exchange, - // used by the merchant to identify the Taler order(s) - // associated with this wire transfer. - wtid: ShortHashCode; - - // The recipient's account identifier as a payto URI. - credit_account: string; - } - - --------------------------------- -Querying the transaction history --------------------------------- - - -.. http:get:: ${BASE_URL}/history/incoming - - Return a list of transactions made from or to the exchange. - - Incoming transactions must contain a valid reserve public key. If a bank - transaction does not conform to the right syntax, the wire gateway must not - report it to the exchange, and send funds back to the sender if possible. - - The bank account of the exchange is determined via the base URL and/or the - user name in the ``Authorization`` header. In fact the transaction history - might come from a "virtual" account, where multiple real bank accounts are - merged into one history. - - Transactions are identified by an opaque numeric identifier, referred to here - as *row ID*. The semantics of the row ID (including its sorting order) are - determined by the bank server and completely opaque to the client. - - The list of returned transactions is determined by a row ID *starting point* - and a signed non-zero integer *delta*: - - * If *delta* is positive, return a list of up to *delta* transactions (all matching - the filter criteria) strictly **after** the starting point. The transactions are sorted - in **ascending** order of the row ID. - * If *delta* is negative, return a list of up to *-delta* transactions (all matching - the filter criteria) strictly **before** the starting point. The transactions are sorted - in **descending** order of the row ID. - - If *starting point* is not explicitly given, it defaults to: - - * A value that is **smaller** than all other row IDs if *delta* is **positive**. - * A value that is **larger** than all other row IDs if *delta* is **negative**. - - **Request:** - - :query start: *Optional.* - Row identifier to explicitly set the *starting point* of the query. - :query delta: - The *delta* value that determines the range of the query. - :query long_poll_ms: *Optional.* If this parameter is specified and the - result of the query would be empty, the bank will wait up to ``long_poll_ms`` - milliseconds for new transactions that match the query to arrive and only - then send the HTTP response. A client must never rely on this behavior, as - the bank may return a response immediately or after waiting only a fraction - of ``long_poll_ms``. - - **Response:** - - :http:statuscode:`200 OK`: - JSON object of type `IncomingHistory`. - :http:statuscode:`204 No content`: - There are not transactions to report (under the given filter). - :http:statuscode:`400 Bad request`: - Request malformed. The bank replies with an `ErrorDetail` object. - :http:statuscode:`401 Unauthorized`: - Authentication failed, likely the credentials are wrong. - :http:statuscode:`404 Not found`: - The endpoint is wrong or the user name is unknown. The bank replies with an `ErrorDetail` object. - - .. ts:def:: IncomingHistory - - interface IncomingHistory { - - // Array of incoming transactions. - incoming_transactions : IncomingBankTransaction[]; - - } - - .. ts:def:: IncomingBankTransaction - - // Union discriminated by the "type" field. - type IncomingBankTransaction = - | IncomingReserveTransaction - | IncomingWadTransaction; - - .. ts:def:: IncomingReserveTransaction - - interface IncomingReserveTransaction { - type: "RESERVE"; - - // Opaque identifier of the returned record. - row_id: SafeUint64; - - // Date of the transaction. - date: Timestamp; - - // Amount transferred. - amount: Amount; - - // Payto URI to identify the receiver of funds. - // This must be one of the exchange's bank accounts. - credit_account: string; - - // Payto URI to identify the sender of funds. - debit_account: string; - - // The reserve public key extracted from the transaction details. - reserve_pub: EddsaPublicKey; - - } - - .. ts:def:: IncomingWadTransaction - - interface IncomingWadTransaction { - type: "WAD"; - - // Opaque identifier of the returned record. - row_id: SafeUint64; - - // Date of the transaction. - date: Timestamp; - - // Amount transferred. - amount: Amount; - - // Payto URI to identify the receiver of funds. - // This must be one of the exchange's bank accounts. - credit_account: string; - - // Payto URI to identify the sender of funds. - debit_account: string; - - // Base URL of the exchange that originated the wad. - origin_exchange_url: string; - - // The reserve public key extracted from the transaction details. - wad_id: WadId; - } - - -.. http:get:: ${BASE_URL}/history/outgoing - - Return a list of transactions made by the exchange, typically to a merchant. - - The bank account of the exchange is determined via the base URL and/or the - user name in the ``Authorization`` header. In fact the transaction history - might come from a "virtual" account, where multiple real bank accounts are - merged into one history. - - Transactions are identified by an opaque integer, referred to here as *row - ID*. The semantics of the row ID (including its sorting order) are - determined by the bank server and completely opaque to the client. - - The list of returned transactions is determined by a row ID *starting point* - and a signed non-zero integer *delta*: - - * If *delta* is positive, return a list of up to *delta* transactions (all matching - the filter criteria) strictly **after** the starting point. The transactions are sorted - in **ascending** order of the row ID. - * If *delta* is negative, return a list of up to *-delta* transactions (all matching - the filter criteria) strictly **before** the starting point. The transactions are sorted - in **descending** order of the row ID. - - If *starting point* is not explicitly given, it defaults to: - - * A value that is **smaller** than all other row IDs if *delta* is **positive**. - * A value that is **larger** than all other row IDs if *delta* is **negative**. - - **Request:** - - :query start: *Optional.* - Row identifier to explicitly set the *starting point* of the query. - :query delta: - The *delta* value that determines the range of the query. - :query long_poll_ms: *Optional.* If this parameter is specified and the - result of the query would be empty, the bank will wait up to ``long_poll_ms`` - milliseconds for new transactions that match the query to arrive and only - then send the HTTP response. A client must never rely on this behavior, as - the bank may return a response immediately or after waiting only a fraction - of ``long_poll_ms``. - - **Response:** - - :http:statuscode:`200 OK`: - JSON object of type `OutgoingHistory`. - :http:statuscode:`204 No content`: - There are not transactions to report (under the given filter). - :http:statuscode:`400 Bad request`: - Request malformed. The bank replies with an `ErrorDetail` object. - :http:statuscode:`401 Unauthorized`: - Authentication failed, likely the credentials are wrong. - :http:statuscode:`404 Not found`: - The endpoint is wrong or the user name is unknown. The bank replies with an `ErrorDetail` object. - - .. ts:def:: OutgoingHistory - - interface OutgoingHistory { - - // Array of outgoing transactions. - outgoing_transactions : OutgoingBankTransaction[]; - - } - - .. ts:def:: OutgoingBankTransaction - - interface OutgoingBankTransaction { - - // Opaque identifier of the returned record. - row_id: SafeUint64; - - // Date of the transaction. - date: Timestamp; - - // Amount transferred. - amount: Amount; - - // Payto URI to identify the receiver of funds. - credit_account: string; - - // Payto URI to identify the sender of funds. - // This must be one of the exchange's bank accounts. - debit_account: string; - - // The wire transfer ID in the outgoing transaction. - wtid: ShortHashCode; - - // Base URL of the exchange. - exchange_base_url: string; - } - - ------------------------ -Wire Transfer Test APIs ------------------------ - -Endpoints in this section are only used for integration tests and never -exposed by bank gateways in production. - -.. _twg-admin-add-incoming: - -.. http:post:: ${BASE_URL}/admin/add-incoming - - Simulate a transfer from a customer to the exchange. This API is *not* - idempotent since it's only used in testing. - - **Request:** The body of this request must have the format of a `AddIncomingRequest`. - - **Response:** - - :http:statuscode:`200 OK`: - The request has been correctly handled, so the funds have been transferred to - the recipient's account. The body is a `AddIncomingResponse`. - :http:statuscode:`400 Bad request`: - The request is malformed. The bank replies with an `ErrorDetail` object. - :http:statuscode:`401 Unauthorized`: - Authentication failed, likely the credentials are wrong. - :http:statuscode:`404 Not found`: - The endpoint is wrong or the user name is unknown. The bank replies with an `ErrorDetail` object. - :http:statuscode:`409 Conflict`: - The 'reserve_pub' argument was used previously in another transfer, and the specification mandates that reserve public keys must not be reused. - - .. ts:def:: AddIncomingRequest - - interface AddIncomingRequest { - // Amount to transfer. - amount: Amount; - - // Reserve public key that is included in the wire transfer details - // to identify the reserve that is being topped up. - reserve_pub: EddsaPublicKey; - - // Account (as payto URI) that makes the wire transfer to the exchange. - // Usually this account must be created by the test harness before this API is - // used. An exception is the "exchange-fakebank", where any debit account can be - // specified, as it is automatically created. - debit_account: string; - } - - - .. ts:def:: AddIncomingResponse - - interface AddIncomingResponse { - - // Timestamp that indicates when the wire transfer will be executed. - // In cases where the wire transfer gateway is unable to know when - // the wire transfer will be executed, the time at which the request - // has been received and stored will be returned. - // The purpose of this field is for debugging (humans trying to find - // the transaction) as well as for taxation (determining which - // time period a transaction belongs to). - timestamp: Timestamp; - - // Opaque ID of the transaction that the bank has made. - row_id: SafeUint64; - } diff --git a/core/index.rst b/core/index.rst @@ -26,200 +26,25 @@ Core Protocol Specification This chapter describes the APIs used in the GNU Taler project. It includes both APIs that are pre-existing as well as APIs specific to the project. -These *protocol specification* defines the HTTP-based, predominantly RESTful -interfaces between the core components of Taler. +These *protocol specifications* define the interfaces between the core +components of GNU Taler. Most of these interfaces use HTTP-based RESTful +protocols using JSON. .. toctree:: :maxdepth: 2 + api-overview api-common - api-error api-exchange api-merchant + ../wallet/wallet-core api-auditor api-sync + api-challenger api-taldir api-mailbox - api-wire - api-bank-merchant - api-bank-integration - api-bank-access + api-bank .. toctree:: :hidden: - -======== -Overview -======== - - * Taler Exchange Public API - - - **Summary**: Public API for the payment service provider component of GNU Taler. - - **Providers**: GNU Taler Exchange - - **Consumers**: Wallet, Merchant - - :doc:`Docs <api-exchange>` - - - * Taler Exchange Management API - - **Summary**: Management API for the payment service provider component of GNU Taler. - - **Providers**: GNU Taler Exchange - - **Consumers**: Exchange tooling (``taler-exchange-offline``), Auditor - - :doc:`Docs <api-exchange>` - - - * Taler Merchant Backend Public API - - **Summary**: Allows communication between merchants and users' wallets. - - **Providers**: GNU Taler Merchant backend - - **Consumers**: Wallet - - :doc:`Docs <api-merchant>` - - * Taler Merchant Backend Private API - - **Summary**: Allows the merchant to manage Taler-based payments and related functionality. - - **Providers**: GNU Taler Merchant backend - - **Consumers**: Merchant's shop Website backend, Merchant PoS app, Merchant Backoffice UI - - :doc:`Docs <api-merchant>` - - * Taler Wallet Core API - - **Summary**: API to access functionality of the Taler Wallet service running locally on user's devices. - - **Providers**: wallet-core - - **Consumers**: UIs for the GNU Taler wallet - - * Taler Bank Integration API - - **Summary**: Offered by banks to provide the wallet/user with more information about ongoing withdrawals of Taler digital cash. - - **Providers**: Taler fakebank, LibEuFin demobank, Banks (that provide extra Taler support) - - **Consumers**: Taler Wallet - - :doc:`Docs <api-bank-integration>` - - * Taler Bank Access API - - **Summary**: Protocol to manage access to a bank account by the owner of the account. Allows access to account balance, transaction list, payment initiation. - - **Providers**: LibEuFin demobank, Taler Fakebank (partial) - - **Consumers**: Cashier App, demobank-ui - - :doc:`Docs <api-bank-access>` - - - * Taler Bank Circuits API - - **Summary**: Allows management of bank user accounts in a regional currency bank deployment. - - **Providers**: LibEuFin Sandbox demobank - - **Consumers**: demobank-ui - - * Taler Wire Gateway API - - **Summary**: Allows the Taler Exchange to query incoming transactions and initiate payments with a protocol that abstracts away details of the underlying banking system. - - **Providers**: Taler fakebank, LibEuFin Nexus, Depoloymerization wire gateway - - **Consumers**: GNU Taler Exchange, Wire Auditor - - :doc:`Docs <api-wire>` - - * Taler Sync API - - **Summary**: Encrypted Data blob storage and retrieval API with payments for storage handled by GNU Taler payments. - - **Providers**: GNU Taler Sync service - - **Consumers**: Taler Wallet - - :doc:`Docs <api-sync>` - - * Taler Auditor API - - **Summary**: Reporting of certain transactions or potential problems directly to the auditor. - - **Providers**: GNU Taler Auditor service - - **Consumers**: GNU Taler Merchant, eventually Taler Wallet - - :doc:`Docs <api-auditor>` - - * Taldir API - - **Summary**: Looking up of Taler mailboxes associated with particular Internet service addresses. - - **Providers**: GNU TalDir service - - **Consumers**: GNU Taler Wallet - - :doc:`Docs <api-taldir>` - - * Taler Mailbox API - - **Summary**: Tansmission of encrypted payment messages between Taler wallets. - - **Providers**: GNU Taler Mailbox service - - **Consumers**: GNU Taler Wallet - - :doc:`Docs <api-mailbox>` - - * Anastasis Provider Public API - - **Summary**: Backup for secret splitting backup and recovery with GNU Anastasis providers. - - **Providers**: GNU Anastasis providers - - **Consumers**: Anastasis core client implementations (C implementation, TypeScript implementation) - - * Anastasis Reducer API - - **Summary**: API used to step through the backup and recovery process of GNU Anastasis. - - **Providers**: Anastasis core client implementations (C implementation, TypeScript implementation) - - **Consumers**: Anastasis UIs (CLI, GTK, anastasis-webui) - - * LibEuFin Nexus API - - **Summary**: API used to configure and access LibEuFin nexus, a generic server that supports multiple protocols to access a bank account. - - **Providers**: LibEuFin Nexus service - - **Consumers**: ``libeufin-cli``, (future) LibEuFin Web UI - - * LibEuFin Sandbox API - - **Summary** API used to configure the LibEuFin sandbox, a simulator for various protocols related to core banking that would typically offered by banks. - - **Providers**: LibEuFin Sandbox service - - **Consumers**: ``libeufin-cli``, (future) LibEuFin Web UI - - * EBICS - - **Summary**: Allows businesses/banks/consumers to exchange data with a bank's core banking system. - - **Consumers**: LibEuFin Nexus - - **Providers**: LibEuFin Sandbox, Banks - diff --git a/core/tos.rst b/core/tos.rst @@ -29,9 +29,10 @@ and the privacy policy of a service. the case if the terms of service were not configured correctly. When returning a full response (not a "304 Not Modified"), the server - should also include a "Acceptable-Languages" header which includes - a space-separated list of the languages in which the terms of service - are available in. Clients can use this to generate a language switcher + should also include a "Avail-Languages" header which includes + a comma-separated list of the languages in which the terms of service + are available in (see `availability hints specification + <https://datatracker.ietf.org/doc/draft-nottingham-http-availability-hints/>`_). Clients can use this to generate a language switcher for users that may not have expressed a proper language preference. diff --git a/demo-deployment.rst b/demo-deployment.rst @@ -1,10 +0,0 @@ -This document explains how to install Taler+LibEuFin -on gv.taler.net, for demo.taler.net. - -1. Login as the ``demo`` user on ``gv.taler.net``. -2. Pull the latest ``deployment.git`` code. -3. Navigate to the ``deployment.git/docker/demo`` directory. -4. The README file is the reference about building and running the services. - -Nginx is already configured to reach the services as exported by -Docker Compose. diff --git a/design-documents/001-new-browser-integration.rst b/design-documents/001-new-browser-integration.rst @@ -1,5 +1,5 @@ -DD1: New Browser Integration -############################ +DD 01: New Browser Integration +############################## .. warning:: diff --git a/design-documents/002-wallet-exchange-management.rst b/design-documents/002-wallet-exchange-management.rst @@ -1,5 +1,5 @@ -DD2: Wallet Exchange Management -############################### +DD 02: Wallet Exchange Management +################################# .. note:: diff --git a/design-documents/003-tos-rendering.rst b/design-documents/003-tos-rendering.rst @@ -1,5 +1,5 @@ -DD3: ToS rendering -################## +DD 03: ToS rendering +#################### Summary ======= @@ -22,6 +22,24 @@ way. Proposed Solution ================= +Internationalization +-------------------- + +The server will parse the ``Accept-Languages`` request header to determine +which language the user will most likely want to read the terms of service +in. If multiple languages are given, the server will check against the +available languages and return the one with the highest preference. + +Additionally, the server will return an ``Avail-Languages`` header which +details what other langauges the terms of service are available in. The +user interface in the wallet should then allow the user to switch to one +of these alternatives using some language switcher. + + +Encoding +-------- + + The service providers can output legal agreements in various formats, determined via the ``"Accept: "`` request header. The format provider **must** support the ``text/plain`` mime type. The format provider **must** support diff --git a/design-documents/004-wallet-withdrawal-flow.rst b/design-documents/004-wallet-withdrawal-flow.rst @@ -1,5 +1,5 @@ -DD4: Wallet Withdrawal Flow -########################### +DD 04: Wallet Withdrawal Flow +############################# Summary ======= @@ -104,7 +104,7 @@ For those, the wallet should not offer the option to change an exchange. After confirming the withdrawal, the user is brought to the list of transactions of the current currency. -It will include a pending `TransactionWithdrawal` which might require additional user confirmation +It will include a pending ``TransactionWithdrawal`` which might require additional user confirmation such as a two-factor-authentication step with the bank. 1. The bank transfer happens immediately @@ -114,7 +114,7 @@ such as a two-factor-authentication step with the bank. 3. The bank provides a ``bankConfirmationUrl`` that the user needs to visit. If the withdrawal proceeds very quickly, -the `TransactionWithdrawal` might not show as pending +the ``TransactionWithdrawal`` might not show as pending and its effective amount is added to the displayed balance right away. Alternatives diff --git a/design-documents/005-wallet-backup-sync.rst b/design-documents/005-wallet-backup-sync.rst @@ -1,5 +1,5 @@ -DD5: Wallet Backup and Sync -########################### +DD 05: Wallet Backup and Sync +############################# .. warning:: @@ -44,7 +44,7 @@ The managed entities are: * set of reserves together with reserve history * set of accepted bank withdrawal operations * set of coins together with coin history and blinding secret (both for normal withdrawal and refresh) - and coin source info (refresh operation, tip, reserve) + and coin source info (refresh operation, reward, reserve) * set of purchases (contract terms, applied refunds, ...) * assignment of coins to their "primary wallet" @@ -59,7 +59,7 @@ Entities that **could** be synchronized (to be decided): * private keys of other sync accounts * coin planchets -* tips before the corresponding coins have been withdrawn +* rewards before the corresponding coins have been withdrawn * refresh sessions (not only the "meta data" about the operation, but everything) diff --git a/design-documents/006-extensions.rst b/design-documents/006-extensions.rst @@ -1,5 +1,5 @@ -DD6: Extensions for GNU Taler -############################# +DD 06: Extensions for GNU Taler +############################### Summary ======= diff --git a/design-documents/007-payment.rst b/design-documents/007-payment.rst @@ -1,5 +1,5 @@ -DD7: Specification of the Payment Flow -###################################### +DD 07: Specification of the Payment Flow +######################################## Summary ======= diff --git a/design-documents/008-fees.rst b/design-documents/008-fees.rst @@ -1,5 +1,5 @@ -DD8: Fee Structure Metrics -########################## +DD 08: Fee Structure Metrics +############################ .. note:: diff --git a/design-documents/009-backup.rst b/design-documents/009-backup.rst @@ -1,5 +1,5 @@ -DD9: Wallet Backup -################## +DD 09: Wallet Backup +#################### Summary ======= diff --git a/design-documents/010-exchange-helpers.rst b/design-documents/010-exchange-helpers.rst @@ -1,5 +1,5 @@ -DD10: Exchange crypto helper design -################################### +DD 10: Exchange crypto helper design +#################################### Summary ======= diff --git a/design-documents/011-auditor-db-sync.rst b/design-documents/011-auditor-db-sync.rst @@ -1,5 +1,5 @@ -DD11: Auditor-Exchange Database Synchronization -############################################### +DD 11: Auditor-Exchange Database Synchronization +################################################ Summary ======= diff --git a/design-documents/012-fee-schedule-metrics.rst b/design-documents/012-fee-schedule-metrics.rst @@ -1,5 +1,5 @@ -DD12: Exchange Fee Configuration -################################ +DD 12: Exchange Fee Configuration +################################# .. note:: diff --git a/design-documents/013-peer-to-peer-payments.rst b/design-documents/013-peer-to-peer-payments.rst @@ -1,5 +1,5 @@ -DD13: Wallet-to-Wallet Payments -############################### +DD 13: Wallet-to-Wallet Payments +################################ Summary ======= diff --git a/design-documents/014-merchant-backoffice-ui.rst b/design-documents/014-merchant-backoffice-ui.rst @@ -1,5 +1,5 @@ -DD14: Merchant backoffice UI -############################ +DD 14: Merchant backoffice UI +############################# Motivation @@ -141,9 +141,9 @@ Story #4: Manage inventory - delete products from inventory -Story #5: Manage tipping +Story #5: Manage rewards ------------------------ -- set up tipping reserve +- set up reward reserve -- check tipping reserve status +- check reward reserve status diff --git a/design-documents/015-merchant-backoffice-routing.rst b/design-documents/015-merchant-backoffice-routing.rst @@ -1,5 +1,5 @@ -DD15: Merchant backoffice Routing -################################# +DD 15: Merchant backoffice Routing +################################## Motivation diff --git a/design-documents/016-backoffice-order-management.rst b/design-documents/016-backoffice-order-management.rst @@ -1,5 +1,5 @@ -DD16: Backoffice Order Management -################################# +DD 16: Backoffice Order Management +################################## Summary ======= @@ -32,7 +32,7 @@ Proposed Solution Listing orders -------------- -.. image:: ../backoffice-order-list.svg +.. image:: ../images/backoffice-order-list.svg :width: 800 4 tabs will be show for an easy access to common filter, click on any of this and @@ -101,7 +101,7 @@ In both cases, the total unit and price of the products will be calculated and shown in the bottom of the section. If the merchant collapse one of the product list a line with a resume of the total price and units will be shown. -.. image:: ../backoffice-order-create.product-section.svg +.. image:: ../images/backoffice-order-create.product-section.svg :width: 800 Create order: Price section @@ -117,7 +117,7 @@ of all products prices will be shown. The ``order price`` will default to ``total products price``. The ``products taxes`` and ``profit`` will be shown since ``order price`` cannot be less that ``product taxes``. -.. image:: ../backoffice-order-create.price-section.svg +.. image:: ../images/backoffice-order-create.price-section.svg :width: 800 Create order: Payment section @@ -142,7 +142,7 @@ This section show optional values that can be overwritten by the merchant * ``wire_fee_amortization``: default value from the instance -.. image:: ../backoffice-order-create.payment-section.svg +.. image:: ../images/backoffice-order-create.payment-section.svg :width: 800 Create order: all section expanded @@ -150,7 +150,7 @@ Create order: all section expanded An example of how all section in a page will be shown. -.. image:: ../backoffice-order-create.all-expanded.svg +.. image:: ../images/backoffice-order-create.all-expanded.svg :width: 800 @@ -291,10 +291,10 @@ Ask for: * drop down options: duplicated, requested by customer, other * after selecting, free text for additional information -.. image:: ../backoffice-order-refund.svg +.. image:: ../images/backoffice-order-refund.svg :width: 800 -.. image:: ../backoffice-order-refund.already.svg +.. image:: ../images/backoffice-order-refund.already.svg :width: 800 Example of details by status @@ -302,16 +302,16 @@ Example of details by status -.. image:: ../backoffice-order-details.paid.svg +.. image:: ../images/backoffice-order-details.paid.svg :width: 800 -.. image:: ../backoffice-order-details.unpaid.svg +.. image:: ../images/backoffice-order-details.unpaid.svg :width: 800 -.. image:: ../backoffice-order-details.claimed.svg +.. image:: ../images/backoffice-order-details.claimed.svg :width: 800 -.. image:: ../backoffice-order-details.refunded.svg +.. image:: ../images/backoffice-order-details.refunded.svg :width: 800 @@ -323,7 +323,7 @@ pagination ---------- order list was originally thought with pagination footer -.. image:: ../backoffice-order-list.pagination.svg +.. image:: ../images/backoffice-order-list.pagination.svg :width: 800 ascending boolean flag cloud be eliminated using the load before and load after diff --git a/design-documents/017-backoffice-inventory-management.rst b/design-documents/017-backoffice-inventory-management.rst @@ -1,5 +1,5 @@ -DD17: Backoffice Inventory Management -##################################### +DD 17: Backoffice Inventory Management +###################################### Summary ======= @@ -31,7 +31,7 @@ Proposed Solution Inspecting inventory -------------------- -.. image:: ../backoffice-product-list.svg +.. image:: ../images/backoffice-product-list.svg :width: 800 Listing the product will shown this columns: @@ -53,7 +53,7 @@ Actions will be Create and Update Product form ------------------------------ -.. image:: ../backoffice-product-create.svg +.. image:: ../images/backoffice-product-create.svg :width: 800 Update product will use the same form except for the ``product_id`` @@ -111,7 +111,7 @@ Stock management * a label at the end of the section will inform about the final result -.. image:: ../backoffice-product-create.stock.svg +.. image:: ../images/backoffice-product-create.stock.svg :width: 800 @@ -124,7 +124,7 @@ Alternatives * rows in the table can be expandable when clicked to get access to some common actions like increase stock or change price -.. image:: ../backoffice-product-list.actions.svg +.. image:: ../images/backoffice-product-list.actions.svg :width: 800 * detail page was intentionally left out since all information can be access diff --git a/design-documents/018-contract-json.rst b/design-documents/018-contract-json.rst @@ -1,5 +1,5 @@ -DD18: Forgettable Data in JSON Contract Terms -############################################# +DD 18: Forgettable Data in JSON Contract Terms +############################################## Summary ======= diff --git a/design-documents/019-wallet-backup-merge.rst b/design-documents/019-wallet-backup-merge.rst @@ -1,5 +1,5 @@ -DD19: Wallet Backup Merging -########################### +DD 19: Wallet Backup Merging +############################ Summary ======= diff --git a/design-documents/020-backoffice-rewards-management.rst b/design-documents/020-backoffice-rewards-management.rst @@ -0,0 +1,95 @@ +DD 20: Backoffice Rewards Management +#################################### + +Summary +======= + +This document describe the complete list features for rewards and reserve +management and how will be shown. + +Motivation +========== + +User will use the backoffice to manage reserve and authorize + +Requirements +============ + +User should use the backoffice to: + +* creating new reserves +* listing active reserves +* authorize rewards for a reserve +* list all rewards for an active reserve +* check rewards status + +Proposed Solution +================= + +Listing reserves +---------------- + +.. image:: ../images/backoffice-reserve-list.svg + :width: 400 + + +Can be filtered with optional arguments: + +* after: if present will brings reserve created after specified date + +* active: if present will bring reserve active (or inactive), otherwise all + +* failures: if present will bring all reserves that have different initial + balance reported by the exchange (or equal), otherwise all + +columns: + +* initial: if the exchange and merchant-backend disagree in the initial balance + (failure) the cell will be red and have a tooltip with more information + +* actions: delete button will be disabled on failure or committed > 0, new_reward + button will be disabled on picked_up == initial or failure + + +Create new reserve +------------------ + +.. image:: ../images/backoffice-reserve-create.svg + :width: 400 + +fields: + +* initial balance must be >0 and the current currency + +* exchange should be a known exchange of the merchant backend + +* wire method should be one of the current supported of the instance + +If there is an error in the creation a Notification message will be shown + +Authorize Reward +---------------- + +The merchant can authorize rewards clicking in the plus (+) button that will bring +the next popup + +.. image:: ../images/backoffice-reward-create.svg + :width: 400 + +after confirm it will continue with a success page: + +.. image:: ../images/backoffice-reward-create.confirmation.svg + :width: 400 + +Details of reserve +------------------ + +.. image:: ../images/backoffice-reserve-details.svg + :width: 400 + +Rewards sorted from newer to older + +When the reserve has not yet funded + +.. image:: ../images/backoffice-reserve-details.unfunded.svg + :width: 400 diff --git a/design-documents/020-backoffice-tips-management.rst b/design-documents/020-backoffice-tips-management.rst @@ -1,95 +0,0 @@ -DD20: Backoffice Tips Management -################################ - -Summary -======= - -This document describe the complete list features for tips and reserve -management and how will be shown. - -Motivation -========== - -User will use the backoffice to manage reserve and authorize - -Requirements -============ - -User should use the backoffice to: - -* creating new reserves -* listing active reserves -* authorize tips for a reserve -* list all tips for an active reserve -* check tips status - -Proposed Solution -================= - -Listing reserves ----------------- - -.. image:: ../backoffice-reserve-list.svg - :width: 400 - - -Can be filtered with optional arguments: - -* after: if present will brings reserve created after specified date - -* active: if present will bring reserve active (or inactive), otherwise all - -* failures: if present will bring all reserves that have different initial - balance reported by the exchange (or equal), otherwise all - -columns: - -* initial: if the exchange and merchant-backend disagree in the initial balance - (failure) the cell will be red and have a tooltip with more information - -* actions: delete button will be disabled on failure or committed > 0, new_tip - button will be disabled on picked_up == initial or failure - - -Create new reserve ------------------- - -.. image:: ../backoffice-reserve-create.svg - :width: 400 - -fields: - -* initial balance must be >0 and the current currency - -* exchange should be a known exchange of the merchant backend - -* wire method should be one of the current supported of the instance - -If there is an error in the creation a Notification message will be shown - -Authorize Tip -------------- - -The merchant can authorize tips clicking in the plus (+) button that will bring -the next popup - -.. image:: ../backoffice-tip-create.svg - :width: 400 - -after confirm it will continue with a success page: - -.. image:: ../backoffice-tip-create.confirmation.svg - :width: 400 - -Details of reserve ----------------------------- - -.. image:: ../backoffice-reserve-details.svg - :width: 400 - -Tips sorted from newer to older - -When the reserve has not yet funded - -.. image:: ../backoffice-reserve-details.unfunded.svg - :width: 400 diff --git a/design-documents/021-exchange-key-continuity.rst b/design-documents/021-exchange-key-continuity.rst @@ -1,5 +1,5 @@ -DD21: Exchange Key Continuity -############################# +DD 21: Exchange Key Continuity +############################## Summary ======= diff --git a/design-documents/022-wallet-auditor-reports.rst b/design-documents/022-wallet-auditor-reports.rst @@ -1,5 +1,5 @@ -DD22: Wallet Proofs to Auditor -############################## +DD 22: Wallet Proofs to Auditor +############################### .. note:: diff --git a/design-documents/023-taler-kyc.rst b/design-documents/023-taler-kyc.rst @@ -1,5 +1,5 @@ -DD23: Taler KYC -############### +DD 23: Taler KYC +################ Summary ======= @@ -40,7 +40,7 @@ Taler needs to run KYC checks in the following circumstances: * key: IBAN (encoded as payto:// URI) -* Reserve is "opened" for invoicing or tipping. +* Reserve is "opened" for invoicing or rewards. * key: reserve (=KYC account) long term public key per wallet (encoded as payto:// URI) diff --git a/design-documents/024-age-restriction.rst b/design-documents/024-age-restriction.rst @@ -1,5 +1,5 @@ -DD24: Anonymous Age Restriction Extension for GNU Taler -####################################################### +DD 24: Anonymous Age Restriction Extension +########################################## Summary ======= @@ -303,6 +303,8 @@ The withdraw protocol is affected in the following situations: - A wire transfer to the exchange (to fill a reserve) was marked by the originating bank as coming from a bank account of a minor, belonging to a of a specific age group, or by other means. +- A KYC-process has been performed with the owner of a reserve and the user has + been identified as being a minor. - A Peer-to-Peer transaction was performed between customers. The receiving customer's KYC result tells the exchange that the customer belongs to a specific age group. @@ -332,33 +334,35 @@ for the withdrawal of one coin: #. calculates :math:`f_i := \text{FDH}(C_i, H(\vec{Q}^i))` for :math:`i \in \{ 1,\ldots,\kappa \}`. #. chooses random blindings :math:`\beta_i(.)` for :math:`i \in \{1,\ldots,\kappa\}`. The blinding functions depend on the cipher (RSA, CS). - #. calculates :math:`F := \text{H}(\beta_1(f_1)||\ldots||\beta_\kappa(f_\kappa))` - #. sends :math:`F` to the Exchange + #. sends :math:`(\beta_1(f_1),\ldots,\beta_\kappa(f_\kappa))` to the Exchange - *Exchange* - 7. receives and stores :math:`F` + 7. receives :math:`(b_1,\ldots,b_\kappa)` + #. calculates :math:`F := \text{H}(b_1||\ldots||b_\kappa)` #. chooses randomly :math:`\gamma \in \{1,\ldots,\kappa\}` and + #. signs :math:`r := b_\gamma` resulting in signature :math:`\sigma_r` + #. stores :math:`F \mapsto (r, \sigma_r)` #. sends :math:`\gamma` to the Wallet. - *Wallet* 10. receives :math:`\gamma` - #. sends to the Exchange the tuple :math:`\left(r_\gamma, \vec{\beta}, \vec{\vec{Q}}, \vec{\vec{S}}\right)` with + #. sends to the Exchange the tuple :math:`\left(F, \vec{\beta}, \vec{\vec{Q}}, \vec{\vec{S}}\right)` with - - :math:`r_\gamma := \beta_\gamma(f_\gamma)` - - :math:`\vec{\beta} := (\beta^1,\ldots,\beta^{\gamma-1},\bot,\beta^{\gamma+1},\ldots,\beta^\kappa)` + - :math:`F := \text{H}(\beta_1(f_1)||\ldots||\beta_\kappa(f_\kappa))` + - :math:`\vec{\beta} := (\beta_1,\ldots,\beta_{\gamma-1},\bot,\beta_{\gamma+1},\ldots,\beta_\kappa)` - :math:`\vec{\vec{Q}} := (\vec{Q}^1,\ldots,\vec{Q}^{\gamma-1},\bot,\vec{Q}^{\gamma+1},\ldots,\vec{Q}^\kappa)` - :math:`\vec{\vec{S}} := (\vec{S}^1,\ldots,\vec{S}^{\gamma-1},\bot,\vec{S}^{\gamma+1},\ldots,\vec{S}^\kappa)` with :math:`\vec{S}^i := (s^i_j)` - *Exchange* - 12. receives :math:`\left(r, (\beta^i), (\vec{Q}^i), (\vec{B}^i) \right)` - #. calculates :math:`g_i := \beta_i\left(\text{FDH}(\vec{Q}^i)\right)` for :math:`i \neq \gamma` - #. compares :math:`F \overset{?}{=} \text{H}(g_1||\ldots||g_{\gamma - 1}||r||g_{\gamma+1}||\ldots||g_\kappa)` and bails out on inequality + 12. receives :math:`\left(F, (\beta_i), (\vec{Q}^i), (\vec{B}^i) \right)` + #. retrieves :math:`(r, \sigma_r)` from :math:`F` or bails out if not present + #. calculates :math:`b_i := \beta_i\left(\text{FDH}(\vec{Q}^i)\right)` for :math:`i \neq \gamma` + #. compares :math:`F \overset{?}{=} \text{H}(b_1||\ldots||b_{\gamma - 1}||r||b_{\gamma+1}||\ldots||b_\kappa)` and bails out on inequality #. for each :math:`\vec{B}^i, i \neq \gamma` i. calculates :math:`\tilde{\omega}^i_j := b^i_j * \Omega` for :math:`j \in \{a+1,\ldots,M\}` #. compares each :math:`\tilde{\omega}^i_j` to :math:`q^i_j` from :math:`\vec{Q}^i = (q^i_1, \ldots, q^i_M)` and bails out on inequality - #. signs :math:`r` #. sends (blinded) signature :math:`\sigma_r` to Wallet - *Wallet* @@ -372,47 +376,35 @@ accomodate for handling multiple coins at once -- thus multiplying the amount of data by the amount of coins in question--, but all with the same value of :math:`\gamma`. -The *actual* implementation of the protocol above will have a major optimization -to keep the bandwidth usage to a minimum. Instead of generating and sending -the age commitment (array of public keys) and blindings for each coin, the -wallet *MUST* derive the corresponding blindings and the age commitments from -the coin's private key itself as follows: +The *actual* implementation of the protocol above will have major optimizations +to keep the bandwidth usage to a minimum and also ensure that a denomination in +the commitment doesn't expire before the reveal. + +Instead of generating and sending the age commitment (array of public keys) and +blindings for each coin, the wallet *MUST* derive the corresponding blindings +and the age commitments from the coin's private key itself as follows: Let -- :math:`c_s` be the private key of the coin, +- :math:`s` be the master secret of the coin, from which the private key :math:`c_s`, blinding :math:`\beta` and nonce :math:`n` are derived as usual in the wallet core - :math:`m \in \{1,\ldots,M\}` be the maximum age (according to the reserve) that a wallet can commit to during the withdrawal. - :math:`P` be a published constant Edx25519-public-key to which the private key is not known to any client. - -Then calculate the blinding :math:`\beta` for the coin as - -.. math:: - \beta &:= \text{HKDF}(c_s, \text{"blinding"}) - -If the denomination is using Clause-Schnorr signatures, calculate the nonce -:math:`n` for the coin as - -.. math:: - n &:= \text{HKDF}(c_s, \text{"cs-nonce"}) - - - For the age commitment, calculate: 1. For age group :math:`a \in \{1,\ldots,m\}`, set .. math:: - s_a &:= \text{HDKF}(c_s, \text{"age-commitment"}, a) \\ + s_a &:= \text{HDKF}(s, \text{"age-commitment"}, a) \\ p_a &:= \text{Edx25519\_generate\_private}(s_a) \\ q_a &:= \text{Edx25519\_public\_from\_private}(p_a) 2. For age group :math:`a \in \{m,\ldots,M\}`, set .. math:: - f_a &:= \text{HDKF}(c_s, \text{"age-factor"}, a) \\ + f_a &:= \text{HDKF}(s, \text{"age-factor"}, a) \\ q_a &:= \text{Edx25519\_derive\_public}(P, f_a). Then the vector :math:`\vec{q} = \{q_1,\ldots,q_M\}` is then the age commitment @@ -420,10 +412,10 @@ associated to the coin's private key :math:`c_s`. For the non-disclosed coins, the wallet can use the vector :math:`(p_1,\ldots,p_m,\bot,\ldots,\bot)` of private keys for the attestation. -Provided with the private key :math:`c_s`, the exchange can therefore calculate -the blinding :math:`\beta`, the nonce :math:`n` (if needed) and the age -commitment :math:`\vec{q}` itself, along with the coin's public key :math:`C_p` -and use the value of +Provided with the secret :math:`s`, the exchange can therefore calculate the +private key :math:`c_s`, the blinding :math:`\beta`, the nonce :math:`n` (if +needed) and the age commitment :math:`\vec{q}`, along with the coin's public +key :math:`C_p` and use the value of .. math:: @@ -431,7 +423,6 @@ and use the value of during the verification of the original age-withdraw-commitment. - For the withdrawal with age restriction, a sketch of the corresponding database schema in the exchange is given here: @@ -447,25 +438,15 @@ schema in the exchange is given here: ] subgraph cluster_commitments { - label=<<B>withdraw_age_commitments</B>> + label=<<B>age_withdraw</B>> margin=20 commitments [ - label="withdraw_age_commitments_id\l|<hc>h_commitment\l|amount_with_fee_val\l|amount_with_fee_frac\l|noreveal_index\l|max_age_group\l|<res>reserve_pub\l|reserve_sig\l|timestamp\l" - ] - } - - subgraph cluster_reveals { - label=<<B>withdraw_age_reveals</B>> - margin=20 - reveals [ - label="freshcoin_index\l|<comm>h_commitment\l|<denom>denominations_serial\l|h_coin_ev\l" + label="age_withdraw_id\l|<hc>h_commitment\l|amount_with_fee_val\l|amount_with_fee_frac\l|noreveal_index\l|max_age\l|<res>reserve_pub\l|reserve_sig\l|<denom>[n] denominations_serials\l|[n] h_blind_evs\l|[n] denom_sigs\l" ] } commitments:res->reserves:id [ label="n:1"; fontname="monospace"]; - reveals:comm -> commitments:hc [ label="n:1"; fontname="monospace" ]; - reveals:denom -> denominations:id [ label="n:1"; fontname="monospace"] ; - + commitments:denom -> denominations:id [ label="n:1"; fontname="monospace"] ; } diff --git a/design-documents/025-withdraw-from-wallet.rst b/design-documents/025-withdraw-from-wallet.rst @@ -1,5 +1,5 @@ -DD25: Withdraw coins manually starting from the wallet -###################################################### +DD 25: Withdraw coins manually starting from the wallet +####################################################### Summary ======= @@ -29,7 +29,7 @@ This screen the user will be able to select the currency from a list of known currencies, switch the exchange, go to a page to add an exchange and define an amount to be withdraw. -.. image:: ../wallet-start-manual-withdraw.svg +.. image:: ../images/wallet-start-manual-withdraw.svg :width: 800 @@ -39,7 +39,7 @@ Success Here the user will see the account details where it needs to send money to complete the withdrawal. -.. image:: ../wallet-confirm-withdraw.svg +.. image:: ../images/wallet-confirm-withdraw.svg :width: 800 Transaction history diff --git a/design-documents/026-refund-fees.rst b/design-documents/026-refund-fees.rst @@ -1,5 +1,5 @@ -DD26: Refunds and Fees -###################### +DD 26: Refunds and Fees +####################### Summary ======= diff --git a/design-documents/027-sandboxing-taler.rst b/design-documents/027-sandboxing-taler.rst @@ -1,5 +1,5 @@ -DD27: Sandboxing all the Taler services -####################################### +DD 27: Sandboxing all the Taler services +######################################## .. note:: diff --git a/design-documents/028-deposit-policies.rst b/design-documents/028-deposit-policies.rst @@ -1,5 +1,5 @@ -DD28: Deposit Policy Extensions -############################### +DD 28: Deposit Policy Extensions +################################ .. note:: diff --git a/design-documents/029-mobile-ui.rst b/design-documents/029-mobile-ui.rst @@ -1,5 +1,5 @@ -DD29: Mobile P2P UI -################### +DD 29: Mobile P2P UI +#################### Summary ======= @@ -23,7 +23,7 @@ Requirements Proposed Solution ================= -.. image:: ../wallet-mobile-overview.svg +.. image:: ../images/wallet-mobile-overview.svg :width: 800 diff --git a/design-documents/030-offline-payments.rst b/design-documents/030-offline-payments.rst @@ -1,5 +1,5 @@ -DD30: Offline payments -###################### +DD 30: Offline payments +####################### Summary ======= diff --git a/design-documents/031-invoicing.rst b/design-documents/031-invoicing.rst @@ -1,11 +1,11 @@ -DD31: Invoicing -############### +DD 31: Invoicing +################ Summary ======= This document proposes new endpoints to support invoicing, -that incidentally also address the long-standing tipping +that incidentally also address the long-standing rewards reserve expiration problem. @@ -37,7 +37,7 @@ Requirements * Wallets may want to pay for the reserve with coins (reserve fresh, not created via bank transfer), while - tipping merchants likely want to pay from the reserve + rewarding merchants likely want to pay from the reserve balance itself. So both styles of payment should be supported. @@ -62,12 +62,12 @@ charge the ``account_fee``, bump the number of open purses threshold in the ``reserves`` table and stop auto-closing of the reserve. This will ensure that the users can withdraw the reserve balance into their wallet even after a longer time period. This helps if the invoice is paid after a significant -delay, and also addresses the unwanted tipping reserve closure +delay, and also addresses the unwanted reward reserve closure problem. Introduce a way to force an immediate closure of a reserve, allowing P2P reserve from invoices to be send to a bank account (this allows a wallet to be used for convenient invoicing and not strictly require the wallet to -receive the funds) and also allowing the user to recover funds from a tipping -reserve after tips are no longer issued. +receive the funds) and also allowing the user to recover funds from a reward +reserve after rewards are no longer issued. The solution needs three new tables for: diff --git a/design-documents/032-brandt-vickrey-auctions.rst b/design-documents/032-brandt-vickrey-auctions.rst @@ -1,5 +1,5 @@ -DD32: Brandt-Vickrey Auctions -############################# +DD 32: Brandt-Vickrey Auctions +############################## Summary ======= diff --git a/design-documents/033-database.rst b/design-documents/033-database.rst @@ -1,5 +1,5 @@ -Database Schema and Versioning -############################## +DD 33: Database Schema and Versioning +##################################### Summary ======= diff --git a/design-documents/034-wallet-db-migration.rst b/design-documents/034-wallet-db-migration.rst @@ -1,5 +1,5 @@ -DD 034: Considerations for Wallet Database Migrations -##################################################### +DD 34: Considerations for Wallet Database Migrations +#################################################### Summary ======= diff --git a/design-documents/036-currency-conversion-service.rst b/design-documents/036-currency-conversion-service.rst @@ -1,5 +1,5 @@ -DD 36: Currency conversion service. -################################### +DD 36: Currency conversion service +################################## Summary ======= diff --git a/design-documents/037-wallet-transactions-lifecycle.rst b/design-documents/037-wallet-transactions-lifecycle.rst @@ -1,6 +1,9 @@ DD 37: Wallet Transaction Lifecycle ################################### +.. contents:: Table of Contents + :depth: 2 + Summary ======= @@ -12,65 +15,68 @@ Motivation The transactions in wallet-core all should have an associated state machine. All transactions should have some common actions that work uniformly across all transactions. +Requirements +============ + +The underlying state machine should make it obvious what interactions +are possible for the user. The number of possible user interactions +in any state should be small. + Proposed Solution ================= + Common States ------------- -The following states apply to multiple different transactions. They can -have transaction-specific sub-states, denoted by ``state(substate)``. +The following states apply to multiple different transactions. Only pending +and aborting have transaction-specific sub-states, denoted by ``state(substate)``. ``pending``: A pending transaction waits for some external event/service. -The transaction stays pending until its change on the wallet's material balance is finished. +The transaction stays pending until its change on the wallet's material balance +is finished. Any pending state can be suspended and resumed. There are some other distinctions for pending transactions: -* long-polling vs exponential backoff: A pending transaction is either waiting +* long-polling vs. exponential backoff: A pending transaction is either waiting on an external service by making a long-polling request or by repeating requests with exponential back-off. * ``lastError``: A pending transaction is either clean (i.e. the network interaction is literally active in transmission or the external service successfully - communicated that it is not ready yet) or has a ``lastError``, which is a ``TalerErrorDetails`` + communicated that it is not ready yet and this is perfectly normal) + or has a ``lastError``, which is a ``TalerErrorDetails`` object with details about what happened during the last attempt to proceed with the transaction. ``done``: A transaction that is done does not require any more processing. It also never has a ``lastError`` but is considered successful. +``dialog``: A transaction requires input from the user. + ``aborting``: Similar to a pending transaction, but instead of taking active steps to complete the transaction, the wallet is taking active steps to abort it. The ``lastError`` indicates errors the wallet experienced while taking active steps to abort the transaction. -.. attention:: - Should there be an abortReason for aborted transactions? - -``aborted``: Similar to a ``done`` transaction, but the transaction was successfully aborted -instead of successfully finished. +``aborted``: Similar to ``done``, but the transaction was successfully aborted +instead of successfully finished. It will have the information of when (timestamp) it was +aborted and in which pending sub-state the abort action was initiated. Also, we can +include more information information relevant to the transaction in ``abortReason`` ``suspended``: Similar to a ``aborted`` transaction, but the transaction was could be resumed and may then still succeed. -``failed``: Similar to ``done``, but the transaction could not even be aborted successfully. - -``kyc-required``: The transaction can't proceed because the user needs to actively -finish a KYC process. +``suspended-aborting``: Network requests or other expensive work +to abort a transaction is paused. -``aml-required``: The transaction can't proceed because the user needs to wait for -the exchange operator to conclude an AML investigation. +``failed``: Similar to ``done``, but the transaction could not be completed or +possibly not even be aborted properly. The user may have lost money. In some +cases, a report to the auditor would make sense in this state. -There are two key distinctions for AML-required transactions: - -* pending: the staff at the exchange is running its investigation. The user is not - expected to take any action and should just wait for the investigation to conclude. - -* frozen: the staff at the exchange decided that the account needed to be frozen. - The user should contact the exchange provider's customer service department and - seek resolution (possibly through the courts) to avoid loosing the funds for good. +``expired``: Similar to ``failed``, but the failure was caused by a timeout. ``deleted``: A ``deleted`` state is always a final state. We only use this state for illustrative purposes. In the implementation, the data associated -with the transaction would be deleted. +with the transaction would be literally deleted. Common Transitions @@ -78,112 +84,237 @@ Common Transitions Transitions are actions or other events. -``[action:delete]``: Deleting a transaction (also called "forgetting" in the UI) -completely deletes the transaction in the database. Depending on the type of -transaction, some of the other data *resulting* from the transaction might -still survive deletion. For example, deleting a withdrawal transaction does not -delete already successfully withdrawn coins. - -``[action:retry]``: Retrying a transaction *(1.)* stops ongoing longpolling +``[action:retry]``: Retrying a transaction *(1.)* stops ongoing long-polling requests for the transaction *(2.)* resets the retry timeout *(3.)* re-runs the handler to process the transaction. Retries are always possible the following -states: ``pending(*)``, ``kyc-required(*)``, ``updating(*)``, ``aborting(*)``. +states: ``pending(*)`` and ``aborting(*)``. .. attention:: Should we show the retry timeout in the UI somewhere? Should we show it in dev mode? -``[action:abort]``: Aborting a transaction either directly stops processing for the transaction and puts it in an ``aborted`` state -or starts the necessary steps to actively abort the transaction (e.g. to avoid losing money) and puts it in an ``aborting`` state. + SEBASJM: Since the wallet will retry anyway, maybe is better if we replace the "retry" + button with a "try now" button and a side text "retrying in xxx seconds". + + CG: Instead of a side text, this *might* make a good mouse-over hint for + a "retry" (or "try now") button. I would not make this overly visible with + side-text as the information is not that important. The text should also be + "retrying next at XXX" using an absolute time XXX --- otherwise the UI would + be way too busy recomputing/updating all of these strings: Using an absolute time, + we only have to redraw anything once a retry actually happened. Given that + retries should basically never be > 24h (we can impose a hard cap), the absolute + time can just be in the format HH:MM:SS (without day). + +``[action:suspend]``: Suspends a pending transaction, stopping any associated +network activities, but with a chance of trying again at a later time. This +could be useful if a user needs to save battery power or bandwidth and an +operation is expected to take longer (such as a backup, recovery or very large +withdrawal operation). + +``[action:resume]``: Suspended transactions may be resumed, placing them back +into a pending state. + +``[action:abort]``: Aborting a transaction either directly stops processing for the +transaction and puts it in an ``aborted`` state, or starts the necessary steps to +actively abort the transaction (e.g. to avoid losing money) and puts it in an +``aborting`` state. + +``[action:fail]``: Directly puts an ``aborting`` or ``pending`` transaction into a +``failed`` state. May result in an ultimate loss of funds (beyond fees) to the +user and thus requires additional consent. -``[action:suspend]``: Suspends a pending transaction, stopping any associated network activities, but with a chance of trying -again at a later time. This could be useful if a user needs to save battery power or bandwidth and an operation is expected -to take longer (such as a backup, recovery or very large withdrawal operation). +``[action:delete]``: Deleting a transaction completely deletes the transaction +from the database. Depending on the type of transaction, some of the other +data *resulting* from the transaction might still survive deletion. For +example, deleting a withdrawal transaction does not delete already +successfully withdrawn coins. Deleting is only safe (no money lost) on initial +and final states (failed, aborted, done). -``[action:resume]``: Suspended transactions may be resumed, placing them back into a pending state. +Whether aborting, deleting or suspending are possible depends on +the transaction type, and usually only one of the four choices should be +offered. -``[action:abort-force]``: Directly puts an ``aborting`` transaction into the ``failed`` state. -``[action:retry]``: Reset the retry timeout / reset long-polling -for a pending transaction and immediately try processing the transaction again. -We usually don't explicitly document this self-transition. +.. image:: ../images/transaction-common-states.png -Whether aborting or resuming is possible depends on the transaction type, and usually only one -of the two choices should be offered. +Boxed labels indicate an end state in which there is no network activity and +hence no need to give the user a way to abort or suspend the activity. The +circle indicates the initial state. Ovals are states with network activity. + +Blue arrows are used for user-triggered actions (via UI buttons). Purple +arrows are used to indicate externally triggered actions. Black arrows +without labels are used for the normal successful path. Red arrows indicate +failure paths. + + +Common pending sub-states +------------------------- + +During the pending state the transaction can go through several sub-states before +reaching a final state. Some of this sub-states are shared between different +transaction types: + +``kyc``: The transaction cannot proceed because the user needs to actively +finish a KYC process. The wallet should show the user a hint on how to +start the KYC process. + +``aml``: The transaction can't proceed because the user needs to wait for the +exchange operator to conclude an AML investigation by the staff at the +exchange. There are two AML substates. In the substate ``pending`` the user +is not expected to take any action and should just wait for the investigation +to conclude. In the substate ``frozen`` the staff at the exchange decided that +the account needed to be frozen. The user should contact the exchange +provider's customer service department and seek resolution (possibly through +the courts) to avoid loosing the funds for good. Transaction Type: Withdrawal ---------------------------- -XXX: What if available denominations change? Does this require a user re-approval if fees -change due to this? -CG: I think the answer can be "no", for two reasons: the wallet MUST pick denominations -to withdraw with the "most long-term" withdraw window (i.e. active denominations that have -the longest available withdraw durations). So in 99.9% of all cases, this will just succeed -as a sane exchange will have a reasonable duration overlap, and in the 0.1% of cases it's -really the user's fault for going offline in the middle of the operation. Plus, even in those -0.1% of cases, it is highly unlikely that the fee would actually change: again 99% of key -roatations can be expected to be there to rotate the key, and not to adjust the withdraw fee. -And in the 1:1M case that the fee does *increase*, it's again unlikely to matter much to the -user. So special-casing this and testing this is IMO just not worth it. - * ``pending(bank-register-reserve)`` Initial state for bank-integrated withdrawals. The wallet submits the reserve public key - and selected exchange to the bank (via the bank integration API). + and selected exchange to the bank (via the bank integration API). Note that if the + user aborts at this stage, we do not know if the bank is in the confirmation stage, + so we must still *try* to abort the transaction at the bank. + + * ``[processed-success] => pending(bank-confirm-transfer)`` + * ``[processed-error] => failed``: On permanent errors (like 404 for the withdrawal operation), + the wallet gives up. + * ``[action:abort] => aborting(bank)`` + +* ``pending(bank-confirm-transfer)`` + + The wallet waits until the bank has confirmed the withdrawal operation; + usually the user has to complete a 2FA step to *approve* that the money is + wired to the chosen exchange. Note that the user's *approve* action is done + in the bank's user interface and not the wallet's user interface. The wallet + internally merely *polls* for the success or failure of the approve action. + The wallet **may** occasionally (after some initial delay, especially on + failures from the bank-poll to return any result) long-poll for the reserve + status and, if successful, may then directly jump to + ``pending(withdraw-coins)`` if the reserve is filled even if the poll at + the bank did not return success or failure. + + * ``[bank-poll-success] => pending(exchange-wait-reserve)`` + * ``[bank-aborted] => aborted``: Bank denied the operation. + * ``[exchange-poll-success] => pending(withdraw-coins)``: Optional + short-cut transition. Exchange was faster than the bank. + * ``[action:abort] => aborting(bank)`` + +* ``aborting(bank)`` + + The user aborted the withdraw operation in the wallet. The wallet must now + try to signal the bank that the wire transfer should no longer be performed. + Note that it is possible that the bank registration never succeeded (if the + user aborted us during ``pending(bank-register-reserve)``) and in this case + we get an ``unknown transaction`` failure here. It is also theoretically + possible that the user approved the transaction in the bank while + simultaneously aborting in the wallet. In this case, we transition to + ``suspended(exchange-wait-reserve)`` (treating the ``abort`` action as a ``suspend`` + action). - * ``[processed-success] => pending(bank-confirming)`` - * ``[processed-error(bank-aborted)] => aborted(bank)`` + * ``[processed-success] => aborted`` + * ``[processed-error(already-confirmed)] => suspended(exchange-wait-reserve)``: We + keep a transaction history entry reminding the user about when the already + wired funds will be returned. + * ``[processed-error(unknown-transaction)] => failed`` -* ``pending(bank-confirming)`` +* ``suspended(exchange-wait-reserve)`` - The wallet waits until the bank has confirmed the withdrawal operation; usually - the user has to complete a 2FA step to confirm that the money is wired to the chosen - exchange. + State where funds were (presumably) wired to the exchange but the wallet + was asked to not proceed with the withdraw, but we still resume. - * ``[poll-success] => pending(exchange-wait-reserve)`` - * ``[action:abort] => aborting(wallet-to-bank)`` + In this state, the wallet should show to the user that the money from the + withdrawal reserve will be sent back to the originating bank account after + ``$closing_delay``. Note that the ``resume`` action should be disabled + after ``$closing_delay``. + + * ``[action:delete] => deleted`` + * ``[action:resume] => pending(exchange-wait-reserve)`` * ``pending(exchange-wait-reserve)`` - Initial state for manual withdrawals. + Initial state for manual withdrawals. Here, the wallet long-polls the + exchange for the reserve status, waiting for the wire transfer to arrive + at the exchange. - * ``[poll-success] => pending(withdrawing-coins)`` + * ``[exchange-poll-success] => pending(withdraw-coins)`` + * ``[action:suspend] => suspended(exchange-wait-reserve)`` -* ``pending(withdrawing-coins)`` +* ``pending(withdraw-coins)`` + + State where we are finally withdrawing the actual coins. Depending on + the AML and KYC thresholds, we may at any time transition into a + holding pattern on the AML or KYC checks of the exchange. + + It is possible that the selected denominations expired. + In that case, the wallet will re-select denominations. - * ``[action:suspend] => suspended`` * ``[processed-success] => done`` - * ``[processed-kyc-required] => kyc-required`` + * ``[processed-kyc-required] => pending(kyc)`` + * ``[processed-aml-required] => pending(aml)`` + * ``[reserve-expired] => expired(reserve)`` + * ``[action:suspend] => suspended(withdraw-coins)`` -* ``suspended`` +* ``pending(kyc)`` - * ``[action:resume] => pending`` - * ``[action:abort] => aborted(after-wired)`` - -* ``kyc-required`` + State where the user needs to provide some identity data to pass a KYC + check. The wallet only shows the user the link for starting the KYC + process and long-polls the exchange in anticipation of the user + completing the KYC requirement. + + * ``[poll-success] => pending(withdraw-coins)`` + * ``[action:suspend] => suspended(kyc)`` - * ``[poll-success] => pending(withdrawing-coins)`` +* ``suspended(kyc)`` -* ``aborting(wallet-to-bank)`` + State where the user needs to provide some identity data to pass a KYC + check, but the long-polling was explicitly stopped. The user can + choose to resume or delete. - * ``[processed-success] => aborted(wallet-to-bank)`` - * ``[processed-error(already-confirmed)] => aborted(after-wired)`` + * ``[action:delete] => deleted`` + * ``[action:resume] => pending(kyc)`` + +* ``pending(aml)`` + + State where the wallet needs to wait for completion of an AML process by an + AML officer of the exchange. The wallet shows that the AML process is + blocking progress. The message shown should distinguish between a mere + pending AML process and an AML freezing decision in terms of the message + shown to the user. If the AML decision is pending at the exchange, he user + should be urged to simply wait. If the funds were frozen, the wallet + informs the user that their funds were frozen due to an AML decision. The + user is urged to contact the exchange operator's AML department out-of-band. + In any case, the wallet long-polls for the AML decision to be made or change + (possibly at a lower frequeny in case of a freeze). -* ``aborted(bank-to-wallet)``: The bank notified the wallet that the withdrawal - was aborted on the side of the bank and won't proceed. + * ``[poll-success] => pending(withdraw-coins)`` + * ``[action:suspend] => suspended(aml)`` -* ``aborted(wallet-to-bank)``: The wallet notified the bank that the withdrawal - should be aborted, before any money was wired. +* ``suspended(aml)`` -* ``aborted(after-wired)``: + State where the user needs to await some AML decision by the exchange. + The long-polling was explicitly stopped. The user can choose to resume or delete. + + * ``[action:delete] => deleted`` + * ``[action:resume] => pending(aml)`` - In this state, the wallet should show to the user that the money from the withdrawal - reserve will be sent back to the originating bank account after ``$closing_delay``. +* ``suspended(withdraw-coins)`` + + In this state, the wallet should show how much money arrived into the wallet + and the rest of the money will be sent back to the originating bank account + after ``$closing_delay``. Note that the ``resume`` action should be + disabled after ``$closing_delay``. + + * ``[action:delete] => deleted`` + * ``[action:resume] => pending(exchange-wait-reserve)`` * ``done`` + The withdrawal operation is complete. + * ``[action:delete] => deleted`` * ``deleted`` @@ -193,192 +324,363 @@ user. So special-casing this and testing this is IMO just not worth it. Only once all coins were spent, the withdraw is fully removed. -Transaction Type: Payment to Merchant -------------------------------------- +.. image:: ../images/transaction-withdrawal-states.png -XXX: Also consider re-selection when the wallet accidentally double-spends coins -or the selected coins have expired. Do we ask the user in this case? -CG: I think no. We correct our balance (after all, we got a proof of -double-spending) and try other coins. If we do not have enough money left, we -abort and simply inform the user that their balance was insufficient to make -the payment after all (very sorry...). - -Note that the case of selected coins having expired shouldn't really happen, -as the wallet should have noticed that when is started up, tried to refresh, -and if that already failed should have update the balance with a transaction -history entry saying something like "coins expired, offline too long" or -something like that. +Transaction Type: Payment to Merchant +------------------------------------- -* ``pending(download-proposal)`` +* ``pending(claim-proposal)`` - Initial state. Download (claim) the proposal from the merchant. + We received a ``pay`` URI. Download (claim) the proposal from the merchant. Can fail if + the proposal was already claimed by someone else. If repurchase detection + tells us that we already paid for this product, we go immediately to + ``failed(repurchase)`` state for this transaction, but with a side-effect of + transitioning the UI into a ``pending(repurchase-session-reset)`` on a + *different* transaction (which before was in ``done``). - XXX: Also consider repurchase detection here? + A ``failed(repurchase)`` transaction will eventually be GCed (=deleted) + automatically. - CG: Well, we could mention that this is a possible transition from - ``pending(download-proposal)`` to ``deleted`` with a side-effect - of transitioning the UI into a ``pending(repurchase-session-reset)`` - on a different transaction (which before was in ``done``). + * ``[error:already-claimed] => failed(already-claimed)`` -- the proposal was + already claimed by someone else. + * ``[error:invalid-proposal] => failed(invalid-proposal)`` -- the merchant provided a + proposal that is invalid (e.g. malformed contract + terms or bad signature). -* ``pending(proposed)`` +* ``dialog(merchant-order-proposed)`` Let the user accept (or refuse) the payment. * ``[action:pay-accept] => pending(submit-payment)`` - * ``[action:abort] => deleted`` -- user explicitly decides not - to proceed - * ``[action:expired] => deleted`` -- when the offer expires - before the user decides to make the payment! (We can keep - pending contracts even in a 'pending transaction' list to - allow the user to choose to not proceed, but then this - transition would clean up that list). + * ``[action:pay-refuse] => ``aborted(refused)`` -- The user explicitly + decided not to proceed (at least not with this wallet). + * ``[expired] => failed(expired)`` -- The offer has expired before the user made any + decision. Note that we should use this transition at + least a few seconds before the offer *actually* expires to avoid + encountering an expiration during ``pending(submit-payment)`` in most + real-world scenarios. Basically, we should prevent last-second payments to + be event attempted client-side. + + The ``failed(expired)`` might be automatically deleted upon GC. * ``pending(submit-payment)`` - * ``[action:abort] => aborting(refund)`` - * ``[processed-success(auto-refund-enabled)] => pending(paid-auto-refund-check)`` - * ``[processed-error(expired)] => aborting(refresh)`` XXX: If the order is expired but the payment - succeeded partially before, do we still try an abort-refund? CG: YES, but of course - we probably should use the ``expired`` transition above a few seconds before the - offer *actually* expires to avoid this problem in 99.9% of real-world scenarios - ("prevent last-second payments client-side") + Submit coin-by-coin (or in bulk groups) until payment is complete. -* ``pending(submit-payment-replay)`` + * ``[action:abort] => aborting(pay-incomplete)`` -- The user explicitly decided to + abort the process while the payment was happening. Note that if the + payment was already completed (and hence the merchant refuses any + refunds), it is theoretically possible that pressing the abort button will + nevertheless end up in a ``pending(auto-refund)`` state (and subsequently + a ``done`` state) instead! + * ``[success] => pending(auto-refund)`` -- Upon receiving confirmation from + the merchant that the purchase was completed. + * ``[error(insufficient balance)] => aborting(pay-incomplete)`` This transition + happens if we detect double-spending and our balance is not sufficient + after the double-spending. It is also conceivable (but should be rare) + that this transition happens because the offer expired. -* ``pending(paid-auto-refund-check)`` +* ``pending(auto-refund)`` - * ``[auto-refund-timeout] => done`` + The payment succeed. We remain in this state as long as an auto-refund-check + is active. If auto refunds are not enabled, we immediately continue to + ``done``. -* ``pending(paid-check-refund)`` + * ``[no-auto-refund] => done`` + * ``[timeout] => done`` -- This happens when the auto refund set by the + contract expired. + * ``[long-poll:refund] => aborting(pay-incomplete)`` -- An auto-refund was detected. + * ``[action:abort] => done`` -- The user may explicitly request to abort the + auto-refund processing (for example to enable subsequent deletion before + the auto-refund delay expires). -* ``done`` +* ``aborting(pay-incomplete)`` - * ``[action:check-refund] => pending(paid-check-refund)`` - * ``[action:pay-replay] => pending(submit-payment-replay)`` - * ``[action:delete] => deleted`` + The wallet should interact with the merchant to request + a refund on the incomplete payment. -* ``aborting(refund)`` + * ``[success] => aborted(pay-incomplete)`` + * ``[already-paid] => done`` - * ``[processed-success] => aborted(refunded)`` - * ``[processed-failure] => aborting(refresh)`` +* ``aborted(refunded)`` -* ``aborting(refresh)`` + The purchase ended with a (partial) refund. The state (and UI) should show + the specific provenance of the state, which may include an insufficient + balance (due to double-spending being detected during payment), and one or + more partial or full refunds. -* ``failed(invalid-proposal)`` + * ``[action:delete] => deleted`` - The merchant provided a proposal that is invalid (e.g. malformed contract terms or bad signature). +* ``done`` -* ``aborted(refunded)`` + The purchase is completed. * ``[action:delete] => deleted`` + * ``[repurchase] => pending(rebind-session)``: Another offer + became pending for this product and we need to update the session so + that the user does not have to buy it again. + * ``[check-refunds]` => pending(check-refunds)``: New refunds + might be available for this purchase. + +* ``pending(check-refund)`` + + New refunds might be available for this purchase. + This state must only be entered *after* the payment has successfully + completed. It is not relevant for auto-refunds or refunds for incomplete + payments. + + * ``[refunds-checked] => pending(user-new-refund)`` --- New + refund(s) are available, user needs to confirm. + * ``[refunds-checked] => done`` --- Refunds were checked, but no + new refunds are available. + * ``[action:stop-refund-query] => done`` --- + This action would usually only be offered when the state is pending + with errors. It stops the refund query, but the payment of course + is left intact. + +* ``pending(rebind-session)`` + + The wallet should reset the associated session for the already purchased + (digital) item. + + * ``[success] => done`` + * ``[action:abort] => done`` -- User aborted the session reset. * ``deleted`` - When a payment is deleted, associated refunds are always deleted with it - + When a payment is deleted, associated refund transactions are always deleted + with it. + +.. image:: ../images/transaction-payment-states.png + Transaction Type: Refund ------------------------ -A refund is a pseudo-transaction that is always associated with a merchant payment transaction. +A refund is a pseudo-transaction that is always associated with a merchant +payment transaction. -* ``pending`` +* ``pending(accept)`` - A refund is pending when the merchant is getting a non-permanent error from - the exchange (and relaying that error response to the wallet). + Initial state for a refund. - * ``[processed-success] => done`` - * ``[processed-error] => failed`` - -* ``done`` + * ``[processed-error] => failed``: we received a permanent failure (such as money already wired to the merchant) * ``failed`` - A failed refund can technically still transition to ``done``, because the wallet - doesn't query some refund resource, but the purchase for refunds. Thus, a previously - failed refund can suddenly transition to ``done``. + The refund failed permanently. - * ``[payment-refund-processed-success] => done`` +.. image:: ../images/transaction-refund-states.png -* ``*`` - - Transitions from any state: - - * ``[action:delete] => deleted`` Deleting a refund has no effect on the wallet's balance. Transaction Type: Refresh ------------------------- -XXX: If we have to adjust the refund amount (because a coin has fewer funds on -it than we expect), what is the resulting state of the whole refresh? +This is about refreshes that are triggered via coin expiration or as part of +getting change after making a payment. In the first case, the refresh +transaction is forever shown as a separate transaction in the history unless +it did not affect the wallet balance (in which case we hide it). In the second +case, the refresh transaction is folded into the payment transaction upon +completion, so that the balance changes are included in the fees of the +transaction that caused us to obtain change. -CG: first the pending balance is decreased by the reduced amount, and then of -course the final balance. The coin transaction responsible for the reduction -in funds is historic (and we don't have details), so that just changes the total -available balance in the wallet, but without an associated history entry (as we -cannot give details). +If we have to adjust the refund amount (because a coin has fewer funds on it +than we expect) the transaction only shows the changes due to the refresh, and +we merely adjust the current balance of the wallet but without giving any +justification (as we cannot give details we do not have). So this will look +the same as if the double-spending transaction had been deleted by the user. * ``pending`` + A refresh operation is pending. + * ``[processed-success] => done`` - * ``[action:abort] => aborted``: Money that has not been refreshed yet is lost. + * ``[action:suspend] => suspended`` + * ``[failed] => failed`` + +* ``suspended`` + + A refresh operation was suspended by the user. + + * ``[action:resume] => pending`` * ``done`` -Transaction Type: Tip ---------------------- + The refresh operation completed. + + * ``[action:delete] => deleted`` + +* ``failed`` + + The refresh operation failed. The user lost funds. -* ``pending(initial)`` + * ``[action:delete] => deleted`` + +* ``deleted`` - The wallet has downloaded metadata for the tip from the merchant and - stored it in the databse. The user needs to accept/refuse it. + All memory of the refresh operation is lost, but of course the resulting + fresh coins are preserved. - * ``[tip-expired] => failed(expired)`` - * ``[action:accept-tip] => pending(pickup)`` - * ``[action:abort] => aborted`` +.. image:: ../images/transaction-refresh-states.png + + + +Transaction Type: Reward +------------------------ + +* ``pending(user)`` + + We have downloaded the metadata for the reward. This is the initial state for a + reward transaction. The user needs to accept/refuse the reward. + + * ``[reward-expired] => expired`` + * ``[action:accept] => pending(pickup)`` * ``pending(pickup)`` - * ``[tip-expired] => failed(expired)`` - * ``[processed-success] => done`` - * ``[action:abort] => aborted`` + We are picking up the reward. + + * ``[failure] => failed``: any type of failure, including expiration. + * ``[processed-kyc-required] => pending(kyc-required)`` + * ``[success] => done`` + * ``[action:suspend] => suspended(pickup)`` + +* ``suspended(pickup)`` + + The user suspended the operation while the reward was being picked up. + + * ``[reward-expired] => failed`` + * ``[action:resume] => pending(pickup)`` + +* ``pending(kyc)`` + + The user needs to perform a KYC check to continue. This usually should only + happen if the wallet balance exceeds some threshold. + + * ``[poll-success] => pending(pickup)`` + * ``[action:suspend] => suspended(kyc)`` + +* ``suspended(kyc)`` + + The user suspended the KYC operation. Note that we do not time out here if + the reward expires, as the wallet balance threshold KYC likely applies even + without the reward. + + * ``[action:resume] => pending(kyc)`` + +* ``done`` + + The reward operation completed. + + * ``[action:delete] => deleted`` + +* ``deleted`` + + All memory of the reward operation is lost, but of course the resulting fresh + coins are preserved. + +.. image:: ../images/transaction-reward-states.png Transaction Type: Deposit ------------------------- -XXX: Handle expired/invalid coins in the coin selection. Does this require user approval if fees changed? +* ``pending(deposit)`` -CG: Again, expired coins should never happen. If deposit fees *increase* due -to a double-spend detection during payment, we might want to have an -_optional_ dialog ("Balance reduced by X as wallet state was not up-to-date -(did you restore from backup?). Consequently, the fees for this transactions -increased from Y to Z. [Abort] [Continue] + checkbox: [X] Do not ask again." + Initial state for deposit transactions. + We deposit the amount coin-by-coin (or in bulk groups) until deposit is completed. -* ``pending(initial)`` + * ``[action:suspend] => suspended(submit-deposit)`` + * ``[processed-success] => pending(track)`` + * ``[processed-failure] => aborting(refund)`` - The wallet deposits coins with the exchange. +* ``suspended(deposit)`` - * ``[processed-success] => pending(track)`` + The user suspended our ongoing deposit operation. + + * ``[action:resume] => pending(deposit)`` * ``[action:abort] => aborting(refund)`` * ``pending(track)`` + All the coins were submitted, waiting to be wired. + * ``[poll-success] => done`` + * ``[poll-accepted-kyc] => pending(kyc)`` + * ``[poll-accepted-aml] => pending(aml)`` + * ``[action:abort] => aborting(refund)`` + +* ``pending(kyc)`` + + Exchange requires KYC before making the wire transfer. + + * ``[long-poll:kyc] => done`` + * ``[action:suspend] => suspended(kyc)`` + +* ``suspended(kyc)`` + + The user suspended us while we were waiting for KYC to be finished. + + * ``[action:resume] => pending(kyc)`` + +* ``pending(aml)`` + + Exchange requires AML before making the wire transfer. + + * ``[long-poll:aml] => done`` + * ``[action:suspend] => suspended(aml)`` + +* ``suspended(aml)`` + + The user suspended us while we were waiting for AML to be finished. + + * ``[action:resume] => pending(aml)`` * ``aborting(refund)`` - ``[processed-success] => aborting(refresh)`` - ``[processed-error] => aborting(refresh)`` XXX Shouldn't this be some error state? + Wallet should try to get the deposited amount back from the exchange (by submitting a refund). + + * ``[action:suspend] => suspended(refund)`` + * ``[processed-success] => aborting(refresh)`` + * ``[processed-error] => aborting(refresh)``: Even if the refund attempt failed, maybe the deposit failed as well and we can still succeed with a refresh. + +* ``suspended(refund)`` + + The user suspended us while we were trying to get a refund. + + * ``[action:resume] => aborting(refund)`` * ``aborting(refresh)`` - ``[processed-success] => aborted`` - ``[processed-error] => failed`` + * ``[action:suspend] => suspended(refresh)`` + * ``[processed-success] => aborted`` + * ``[processed-error] => failed`` + +* ``suspended(refresh)`` + + The user suspended us while we were trying to do the refresh. + + * ``[action:resume] => aborting(refresh)`` + +* ``aborted`` + + The operation was aborted, some funds may have been lost (to fees or deposited anyway). + + * ``[action:delete] => deleted`` * ``done`` + The deposit operation completed. + + * ``[action:delete] => deleted`` + +* ``deleted`` + + All memory of the deposit operation is lost. + +.. image:: ../images/transaction-deposit-states.png + Transaction Type: Peer Push Debit --------------------------------- @@ -388,49 +690,74 @@ to another wallet. States and transitions: -* ``pending(initial)`` +* ``pending(purse-create)`` + + The wallet is creating a purse. Initial state. - In this state, the user is not yet able to send the payment to somebody else. + * ``[process-success] => pending(ready)``: The wallet has created the purse. + * ``[process-failure] => aborting(refund)``: The purse creation failed. + * ``[action:suspend] => suspended(purse-create)``: The user suspended the operation. - * ``[action:abort] => aborted``: The payment is aborted early, before the wallet even had the chance to create a purse. - No fees are incurred. - * ``[action:delete] => deleted``: No funds are lost. - * ``[processsing-success] => pending(purse-created)``: The wallet was able to successfully create a purse. +* ``suspended(purse-create)`` -* ``pending(purse-created)`` + * ``[action:resume] => pending(purse-create)``: The user resumed the operation. + * ``[action:abort] => aborting(refund)``: The user aborted the operation. + +* ``pending(ready)`` In this state, the user can send / show the ``taler://`` URI or QR code to somebody else. * ``[action:abort] => aborting(delete-purse)``: The user aborts the P2P payment. The wallet tries to reclaim money in the purse. - * ``[purse-timeout] => aborting(refresh)``: The other party was too slow. + * ``[purse-timeout] => aborting(refresh)``: The other party was too slow and the purse has now expired. * ``[poll-success] => done``: The other party has accepted the payment. - * ``[poll-error] => aborting(refresh)``: The exchange claims that there is a permanent error regarding the purse. + * ``[poll-error] => aborting(refresh)``: The exchange claims that there is a permanent error regarding the purse. (FIXME(CG): not clear that this is the best transition! Could also go to ``aborting(refund)`` or ``aborting(delete-purse)``; best choice may depend on the specific error returned.) * ``aborting(delete-purse)`` + The wallet is deleting the purse to prevent the receiver from merging it and to reclaim the funds in it. + * ``[processed-success] => aborting(refresh)``: The purse was deleted successfully, and refunded coins must be refreshed. * ``[processed-failed(already-merged)] => done``: The other party claimed the funds faster that we were able to abort. * ``[processed-failed(other)] => aborting(refresh)``: The exchange reports a permanent error. We still try to refresh. + * ``[action:fail] => failed``: The user explicitly asked us to give up and accepted the possible loss of funds. + +* ``aborting(refund)`` - * ``[action:abort-force] => failed`` + We abandon the purse that was never fully funded and ask for the deposited coins to be refunded. + + * ``[processed-success] => aborting(refresh)``: After the refund, we still need to refresh the coins. + * ``[processed-failure] => aborting(refresh)``: The refund failed, we still try to refresh the coins. + * ``[action:fail] => failed``: The user explicitly asked us to give up and accepted the possible loss of funds. * ``aborting(refresh)`` - * ``[processed-success] => aborted)``: Refresh group finished. Aborting was successful, money was reclaimed - * ``[processed-failed] => failed)``: Refresh group failed to complete with a permanent error. - * ``[action:abort-force] => failed``: XXX will this abort the refresh session or just orphan it? + * ``[processed-success] => aborted``: Refresh group finished. Aborting was successful, money was reclaimed. + * ``[processed-failed] => failed``: Refresh group failed to complete with a permanent error. + * ``[action:fail] => failed``: The user explicitly asked us to give up and accepted the possible loss of funds. * ``done`` - * ``[action:delete]`` No money should be lost in this case. + The transfer was successful. + + * ``[action:delete] => deleted`` * ``aborted`` - * ``[action:delete]`` No additional money is lost other than fees from aborting/refreshing. + The transfer was aborted. Except for fees, the money was recovered. + + * ``[action:delete] => deleted`` * ``failed`` - * ``[action:delete]``: Money will be lost. + The transfer failed. Money was lost. Unless on a forced abort, we should probably complain to the auditor. + + * ``[action:delete] => deleted`` + +* ``deleted`` + + All memory of the push debit operation is lost. + +.. image:: ../images/transaction-push-debit-states.png Transaction Type: Peer Push Credit @@ -441,109 +768,340 @@ a ``taler://pay-push`` URI. States and transitions: -* ``pending(initial)`` +* ``pending(download)`` - * ``[processed-success] => pending(withdrawing)``: Merging the reserve was successful + Wallet read the taler:// URI and is downloading the contract details for the user. -* ``pending(withdrawing)`` + * ``[processed-success] => pending(user)``: Contract can be shown to the user. + * ``[action:suspend] => suspended(download)``: User suspended the operation. - * ``[processed-kyc-required] => kyc-required`` +* ``suspended(download)`` -* ``kyc-required`` + The download of the purse meta data was suspended by the user. - * ``[poll-success] => pending(withdrawing)`` - * ``[action:abort] => aborted``: The user will lose the coins they were not able to withdraw yet, unless they - resume the transaction again. + * ``[action:resume] => pending(download)`` -* ``aborted`` +* ``pending(user)`` + + User needs to decide about accepting the money. + + * ``[action:accept] => pending(merge)`` + * ``[timeout] => failed``: User took too long to decide. + +* ``pending(merge)`` + + * ``[processed-success] => pending(withdraw)``: Merging the reserve was successful. + * ``[kyc-required] => pending(merge-kyc)``: User must pass KYC checks before the purse can be merged. + * ``[timeout] => failed``: The purse expired before we could complete the merge. + * ``[failure] => failed``: The merge failed permanently. + * FIXME(CG): do we want to allow suspending here? + +* ``pending(merge-kyc)`` + + We cannot merge the purse until passing a KYC check. + The user is shown a hint where to begin the KYC + process and the wallet long-polls on the KYC status. + + * ``[poll-success] => pending(withdraw)`` + * ``[action:suspend] => suspended(kyc)`` + * ``[timeout] => failed``: The purse expired before we could complete the merge. + +* ``suspended(merge-kyc)`` + + We cannot merge the purse until passing a KYC check, + and that check was suspended by the user. + + * ``[action:resume] => pending(kyc)`` + * ``[timeout] => failed``: The purse expired before we could complete the merge. + +* ``pending(withdraw)`` + + The wallet is withdrawing coins from the reserve that was filled by merging + the purse. + + * ``[kyc-required] => pending(withdraw-kyc)`` + * ``[aml-required] => pending(withdraw-aml)`` + * ``[withdraw-failure] => failed`` + * ``[withdraw-success] => done`` + * ``[action:suspend] => suspended(withdraw)`` + +* ``suspended(withdraw)`` + + The user requested the withdraw operation to be suspended. + + * ``[action:resume] => pending(withdraw)`` + +* ``pending(withdraw-kyc)`` + + We cannot withdraw more coins until passing a KYC check. + The user is shown a hint where to begin the KYC + process and the wallet long-polls on the KYC status. + + * ``[poll-success] => pending(withdraw-coins)`` + * ``[action:suspend] => suspended(withdraw-kyc)`` + +* ``suspended(withdraw-kyc)`` + + We cannot withdraw from the reserve until passing a KYC check, + and that check was suspended by the user. + + * ``[action:resume] => pending(withdraw-kyc)`` + +* ``pending(withdraw-aml)`` + + We cannot withdraw more coins until AML rules are satisfied. + The user is shown a hint as to the AML status (pending or frozen). + + * ``[poll-success] => pending(withdraw-coins)`` + * ``[action:suspend] => suspended(withdraw-aml)`` + +* ``suspended(withdraw-aml)`` + + We cannot withdraw from the reserve until AML rules are satisfied, + and the status check was suspended by the user. + + * ``[action:resume] => pending(withdraw-aml)`` + * ``[action:delete] => deleted`` - * ``[action:resume] => pending(withdrawing)`` - * ``[action:delete] => deleted``: The user will irrevocable lose coins that were not withdrawn from the reserve yet. +* ``failed`` + + The operation failed. Details are shown to the user. The money from the purse eventually goes to the sender (or some other wallet that merged it). + + * ``[action:delete] => deleted`` * ``done`` + The operation succeeded. + * ``[action:delete] => deleted``: No money will be lost, the withdrawn coins will be kept +* ``deleted`` + + All memory of the push credit operation is lost. + +.. image:: ../images/transaction-push-credit-states.png Transaction Type: Peer Pull Credit ---------------------------------- -TODO: Also specify variant where account reserve needs to be created / funded first. +TODO: Also specify variant where account reserve needs to be created / funded first (Note: post 1.0-feature). + +* ``pending(purse-create)`` -* ``pending(initial)`` + The wallet is creating a purse. Initial state. - In this state, the purse is created (already in a merged state, with the initiator - providing the reserve). + * ``[process-success] => pending(ready)``: The wallet has created the purse. + * ``[process-failure] => deleted``: The purse creation failed. We only show a transient error. + * ``[action:abort] => deleted``: The user aborted the operation. - * ``[action:abort] => aborted``: At this stage, it's safe to just abort. +* ``pending(ready)`` - CG: is this not 'suspend' (safe to resume!). Also, deletion transitions are missing. + In this state, the user can send / show the ``taler://`` URI or QR code to + somebody else. -* ``pending(wait-deposit)`` + * ``[action:abort] => aborting(delete-purse)``: The user aborts the P2P payment. + * ``[purse-timeout] => aborted``: The other party was too slow and the purse + has now expired. + * ``[poll-success] => pending(withdraw)``: The other party has made the payment. + * ``[poll-error] => aborting(delete-purse)``: The exchange claims that there + is a permanent error regarding the purse. We should try to delete it. - We're waiting for the other party to pay into the pre-merged purse. +* ``aborting(delete-purse)`` + + We are cleaning up the purse after the operation failed or was aborted by + the user. + + * ``[failure:already-merged] => pending(withdraw)``: Too late to abort, the + other side already paid the invoice. + * ``[process-success] => aborted``: The wallet has deleted the purse. + * ``[failure:other] => failed``: The purse deletion failed; we are + nevertheless done. + * ``[action:fail] => failed``: Money may be lost if it was deposited + into the purse in the meantime. + +* ``aborted`` + + The invoicing process ended without success. + + * ``[action:delete] => deleted`` - * ``[action:abort] => aborting(delete-purse)``: At this stage, it's safe to just abort. - * ``[process-failed(expired)] => failed(expired)`` +* ``pending(withdraw)`` -* ``pending(withdrawing)`` + The wallet is withdrawing the money paid for the invoice. * ``[processed-success] => done`` + * ``[failure] => failed`` + * ``[processed-kyc] => pending(kyc)`` + * ``[processed-aml] => pending(aml)`` + * ``[action:suspend] => suspended(withdraw)`` -* ``aborting(delete-purse)`` +* ``suspended(withdraw)`` - * ``[processed-success] => aborted`` - * ``[processed-failed(merge)] => done`` - * ``[processed-failed(expired)] => failed(expired)`` + The user suspended a withdraw operation. -* ``aborted`` + * ``[action:resume] => pending(withdraw)`` + +* ``pending(kyc)`` + + The user must supply KYC information before withdrawing can continue. + + * ``[poll-success] => pending(withdraw)`` + * ``[action:suspend] => suspended(kyc)`` + +* ``suspended(kyc)`` + + The user suspended waiting for the KYC operation to complete. + + * ``[action:resume] => pending(kyc)`` + +* ``pending(aml)`` + + The user must await a positive exchange AML decision. + + * ``[poll-success] => pending(withdraw)`` + * ``[action:suspend] => suspended(aml)`` + +* ``suspended(aml)`` + + The user suspended waiting for the AML decision to be successful. + + * ``[action:resume] => pending(aml)`` + +* ``failed`` + + Obtaining the money for the invoce failed. This is likely a case for the + auditor. + + * ``[action:delete] => deleted`` * ``done`` -* ``failed(expired)`` + The payment for the invoice was successfully received. + + * ``[action:delete] => deleted`` + +* ``deleted`` + +.. image:: ../images/transaction-pull-credit-states.png - Transaction Type: Peer Pull Debit --------------------------------- -* ``pending(initial)`` +* ``pending(download)`` + + We are downloading the information about the invoice. Initial state. - We've downloaded information about the pull payment and are waiting - for the user to confirm. + * ``[action:suspend] => suspended(download)`` + * ``[success] => pending(user)`` - * ``[action:abort] => aborted``: Safe to abort! - * ``[action:confirm-pay] => pending(deposit)``: Safe to abort! +* ``suspended(download)`` + + User suspended downloading the information about the invoice. + + * ``[action:resume] => pending(download)`` + * ``[action:delete] => deleted`` + +* ``pending(user)`` + + We have downloaded information about the pull payment and are waiting for + the user to confirm. + + * ``[action:confirm-pay] => pending(submit-payment)`` + * ``[action:delete] => deleted`` + * ``[timeout] => aborted`` * ``pending(deposit)`` The user has confirmed the payment and the wallet tries to deposit into the provided purse. + * ``[action:suspend] => suspended(deposit)`` + * ``[processed-success] => done`` + * ``[failure:timeout] => aborting(refresh)`` * ``[processed-success] => done`` - * ``[action:abort] => aborting(refresh)``: Wallet tries to refresh coins - that were not already deposited. XXX Do we really always refresh even if no deposit - attempt has been made yet? CG: only every refresh those coins that are dirty. + * ``[failure:other] => aborting(refund)`` + +* ``suspended(deposit)`` + + User suspended depositing into the purse. + + * ``[action:resume] => pending(deposit)`` + * ``[action:abort] => aborting_refund`` + +* ``aborting(refund)`` + + Aborts the payment, asking for the already deposited coins to be refunded. + + * ``[processed-success] => aborted(refunded)`` + * ``[processed-failure] => aborting(refresh)`` + * ``[action:fail] => failed`` * ``aborting(refresh)`` - XXX Before refreshing, should we not wait until the purse has expired? + Refreshes the coins that were previously deposited into the purse to recover their value. * ``[processed-success] => aborted`` * ``[processed-failed] => failed`` * ``done`` + The invoice was successfully paid. + + * ``[action:delete] => deleted`` + +* ``deleted`` + + All information about the invoice has been deleted. + +.. image:: ../images/transaction-pull-debit-states.png + Alternatives ============ -* each transaction could be treated completely separately +* Each transaction could be treated completely separately; however, uniform + terminology for actions (and thus button labels) is likely more helpful for + the user experience. + +* We could require user re-approval if fees changed when the available + denominations change during a *withdraw*. This would require a different + state machine on withdraw. We believe the answer can be "no", for two + reasons: the wallet MUST pick denominations to withdraw with the "most + long-term" withdraw window (i.e. active denominations that have the longest + available withdraw durations). So in virtually all normal cases, this will + just succeed as a sane exchange will have a reasonable duration overlap, and + in the very few cases it's really the user's fault for going offline in the + middle of the operation. Plus, even in those few cases, it is highly + unlikely that the fee would actually change: again most key rotations can be + expected to be there to rotate the key, and not to adjust the withdraw fee. + And in the extremely rare case that the user went offline and in the + meantime the fees did *increase*, it's again unlikely to matter much to the + user. So special-casing this and testing this is probably not worth it. + +* We could require user re-approval if due to expired/invalid coins the coin + selection (and thus fees) changes during a *deposit*. Again, expired coins + should virtually never happen unless a user goes offline for a long time in + the middle of a purchase (which would be very strange). If deposit fees + *increase* due to a double-spend detection during payment, we might want to + have an *optional* dialog ("Balance reduced by X as wallet state was not + up-to-date (did you restore from backup?). Consequently, the fees for this + transactions increased from Y to Z. [Abort] [Continue] + checkbox: [X] Do + not ask again."). Probably at best a post-1.0 feature. -Drawbacks -========= Discussion / Q&A ================ -(This should be filled in with results from discussions on mailing lists / personal communication.) +* The diagrams only show what is happening **after** the wallet + has created the transaction. It is possible that network requests + are happening before that, but they are not considered to be part + of the transaction. +* We have decided against a ``cancel`` state, because it resulted + in too much complexity. Instead of doing a direct ``cancel``, + the user has to go to the transaction and abort and/or delete + it. +* We might add a ``revive`` action in the future that allows + to go from ``aborting`` back to ``pending`` for transactions + where this makes sense. We're not doing it right now + to simplify things. diff --git a/design-documents/038-demobanks-protocol-suppliers.rst b/design-documents/038-demobanks-protocol-suppliers.rst @@ -0,0 +1,158 @@ +DD 38: Demobanks protocol suppliers +#################################### + +Summary +======= + +This document models the association between financial data +held in a LibEuFin *demobank* and the interface to let users +access such financial data. + +Motivation +========== + +LibEuFin Sandbox offers multitenency banking by the means of +'demobanks'. Each demobank offers access to financial data via +*several* APIs. The objective is to model such APIs so that each +operation impacts one and only one demobank. + +Definitions +=========== + +Each API to access financial data at one demobank is offered by +a **resource** called *protocol supplier*. Therefore protocol +suppliers MAY be subject to all the CRUD operations + +For each request that a protocol supplier serves, the demobank +being impacted can be found in the following ways: + +.. _demobank-mutually-exclusive: + +1. In a value that belongs to the request. +2. In a value that belongs to the protocol supplier's state. +3. Relying on the default demobank. + +Note: the three elements are mutually exclusive, so as to reduce +ambiguity and simplify the implementation. + +Suppliers creation +================== + +Suppliers can be static or dynamic. + +Static +^^^^^^ + +This supplier never changes its state. Whether this type +of supplier is associated or not with a particular demobank +MUST be stated in the documentation. + +Examples +-------- + +1. A JSON-based protocol that lets users access their bank accounts +always under the 'default' demobank belongs to this category. It +is therefore a 'static protocol supplier' with static demobank. + +2. A XML-based protocol that lets users access their bank accounts +in a demobank whose name appear in the URI is as well a 'static protocol +supplier' with dynamic demobank. + +Note: the upcoming (in version 0.9.3) JSON-based supplier that will +let Nexus reach Sandbox accounts is planned as a 'dynamic protocol +supplier' with dynamic demobank. That allows Taler demos to only +speak JSON. + +Dynamic +^^^^^^^ + +This supplier has a name and its state CAN refer to one +particular demobank. These suppliers need to be created +first, in order to be used. + +Examples +-------- + +1. A JSON-based protocol that lets users access their bank +accounts under the demobank whose name is held in the supplier +state belongs to this category. It is therefore a dynamic +supplier with semi-dynamic demobank. + +2. A XML-based protocol that lets user access their bank +accounts under the demobank whose name is held both in the +supplier state *and* in the URI is **wrong**. This supplier +doesn't respect this `mutual exclusivity <demobank-mutually-exclusive_>`_. + +3. A XML-based protocol that lets user access their bank accounts +always under the 'default' demobank belongs to this category. It +is a dynamic supplier with static demobank. + +Supplier reachability +===================== + +Each supplier must be available under its own URI. + + +Current protocol suppliers design +================================= + +Static X-LIBEUFIN-BANK with dynamic demobank +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The ``x-libeufin-bank`` protocol supplier is reachable under +``/demobanks/{demobankName}/access-api/``. As the path suggests, +it offers banking operations via the :doc:`Libeufin Bank API </core/api-libeufin-bank>`. +It is static in the sense that it's not possible to assign a name +to one particular x-libeufin-bank protocol supplier. On the other +hand, the demobank is dynamic because can be specified along the path +in the ``demobankName`` placeholder. + +Dynamic EBICS supplier with dynamic demobank +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Every protocol supplier of this type is reachable under ``POST /ebicsweb`` +and by specifying its EBICS host name inside the EBICS message. + +As of the internal representation, Sandbox keeps a database table called +``EbicsHostsTable`` that does **not** point at any demobank. Such table +is the one that provides the bank's EBICS private keys and has **no** business +implications. + +CCT (Payment initiations) +------------------------- + +This handler gets the bank account directly from the IBAN that was +carried along the pain.001, therefore -- as long as every IBAN is +unique -- this works with **any** demobank that hosts such IBAN. The +EBICS subscriber public keys are extracted differently: they come from +the tuple [userID, partnerID, systemID?] held in the request. Hence as +long as such tuple is unique for each subscriber (Sandbox checks that), +even the subscriber public keys are found regardless of the demobank name. + +.. note:: + + The 'context' object found via the [userID, partnerID, systemID?] tuple + has **also** a reference to the bank account. The consistency with the + other bank account reference returned by the IBAN is currently NOT checked. + +C52 (transactions report) +------------------------- + +This handler gets the reference to the subscriber public keys and bank +account via the [userID, partnerID, systemID?] tuple. It then uses +this bank account label to find the transactions that belong to the +subscriber that made the request. + +.. note:: + + The current implementation does NOT uses any demobank name along + the transactions research: only the bank account label. This can + lead to **ambiguity**, in case two different demobanks host respectively + one bank account under the same label. This is not possible however + in the current version, as Sandbox only admits one ``default`` demobank. + + +Alternatives +============ + +Drop support for multitenancy banking. What is the benefit of this anyway? diff --git a/design-documents/039-taler-browser-integration.rst b/design-documents/039-taler-browser-integration.rst @@ -0,0 +1,142 @@ +DD 39: Taler Wallet Browser Integration Considerations +###################################################### + +Summary +======= + +This design document discusses considerations for integrating the GNU Taler +wallet with browsers and highlights difficulties with the implementation of a +GNU Taler wallet as a cross-browser WebExtension. + +Motivation +========== + +GNU Taler is a payment system based on open standards with a free and open +source reference implementation. The GNU Taler wallet is the main component +used by end users to manage their electronic cash balance and payments. + +Payments with GNU Taler are typically initiated via a QR code or link that +contains a ``taler://pay/{merchant}/{order_id}`` URI. Navigating to such a +link should result in a context switch to the wallet, where the payment can can +be approved/declined, and the user is subsequently redirected to the merchant's +website again. + +Other ``taler://`` URIs (for withdrawals, refunds, etc.) are also commonly +used, but not explicitly discussed in this document, as very similar +considerations apply. + +There are multiple reference implementations available for multiple +platforms (command line, Android, iOS, WebExtension). + +While native applications can register themselves as a handler for the +``taler`` URI scheme, the story is different for WebExtensions: There is +currently no reasonable, cross-platform mechanism that allows a WebExtension to +register itself as the handler for the ``taler`` URI scheme. + +This is unfortunate, as a WebExtension could otherwise easily provide a Taler +wallet implementation without requiring the user to install a native App, +providing a better and safer user experience. + +The problems with individual browsers are: + +* Firefox allows specifying ``protocol_handlers`` in the extension manifest. + However, this list only allows schemes with the prefix ``ext+`` and + schemes that are included in an allowlist. The ``taler`` URI scheme + is not part of this list yet. +* Chromium / Google Chrome allows extensions to use the + ``registerProtocolHandler`` API. However, the same allowlist restrictions + apply. Furthermore, the registered protocol scheme is not listed as the + extension's required/optional permissions. Instead, a different permission + prompt is dynamically shown to the user. +* Safari currently neither supports ``registerProtocolHandler`` nor the + ``protocol_handlers`` mechanism. +* Opera does not seem to have any support for WebExtension protocol handlers + either. + +Another issue is that Websites can't easily find out whether a browser +extension handling the ``taler://`` protocol is installed. To avoid using this +information for fingerprinting, anchors could provide an alternative ``href`` +in case the main one is not handled, such as: + +.. code:: html + + <a href="taler://pay/..." handler-unavailable-href="https://wallet.taler.net/">...</a> + +Requirements +============ + +* No vendor lock-in: The integration should not require merchant + Websites to rely on a particular list of extension IDs but instead + any WebExtension to potentially handle ``taler://`` URIs + or other mechanisms that Websites can use to interact with Taler + wallets. +* Security: The integration mechanism should require as few + permissions as possible. +* Ergonomic user experience: As few clicks and permission + prompts as possible should be shown to the user. +* Ergonomic developer experience: The code size and + effort to trigger a Taler payment on a merchant's Website + should be minimized. +* Forward compatibility: The integration mechanism + should work smoothly with future browsers that + have native, built-in support for Taler payments. + + +Alternatives +============ + +* JavaScript API: The WebExtension could inject a JavaScript API into Websites + that allow interacting with the Taler wallet. This is the approach taken by + the MetaMask crypto wallet. It requires excessive permissions, may break + some Websites (https://github.com/brave/browser-laptop/issues/13711) and + requires merchants to include extra JavaScript. + + * This type of interaction is useful for Single Page Apps and + might be provided by the GNU Taler wallet reference implementation, + at least when the user grants additional permissions. + * Unfortunately, browsers currently do not provide a safe way + for the communication between a WebExtension and the page + without excessive permissions. This especially applies + if the Website does not know the extension's ID. Hard-coding + the extension IDs would violate the "no vendor lock-in requirement". + +* Handling ``taler://`` URIs by overriding the onclick handler of ``a`` HTML elements. + This requires excessive permissions but would be a viable work-around, + at least on pages that opt in with a special ``<meta name="taler-support" content="uri">`` tag. + It does not work in all use-cases, for example when a navigation + to a ``taler://`` URI is initiated programmatically or by pasting + the URI in the browser's address bar. + +* Triggering interactions with the ``taler://`` URI in a ``Taler:`` HTTP + header. This approach would allow browsers with native Taler support + (or a WebExtension) to handle payment/withdrawal initiations directly, + without rendering a page that shows the QR code or link. + However, the WebExtension APIs do not allow extensions to + read particular headers without excessive permissions. Furthermore, + more recent versions of Chrome/Chromium do not allow blocking + processing of headers, leading to flickering when the extension + redirects based on the presence of the ``Taler:`` header. + +* Browser and wallet presence detection. Merchants' Websites could include custom + code to detect the browser and/or presence of a Taler WebExtension and show + different instructions to guide the user towards processing the payment or to + show ``ext+taler`` URIs instead of ``taler`` URIs. This is not a viable + solution, as it requires a lot of extra and brittle logic on merchants' + Websites. + +* Always use ``ext+taler`` URIs. This would help with Firefox. + Bad for forward compatibility, as we have already provisionally registered the + ``taler`` URI scheme. + +* Web Payments API: Using the Web Payments API is not possible, because current + browsers do not allow specifying a WebExtension as a handler. Furthermore, + the Web Payments API would not support the withdrawal flow + (``taler://withdraw`` URIs). + + +Related Work and References +=========================== + +* **[1]** https://github.com/whatwg/html/issues/8596 +* **[2]** https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/protocol_handlers +* **[3]** https://github.com/ipfs/devgrants/blob/master/targeted-grants/protocol-handler-api-for-browser-extensions.md diff --git a/design-documents/040-distro-packaging.rst b/design-documents/040-distro-packaging.rst @@ -0,0 +1,139 @@ +DD 40: Distro Packaging +####################### + +.. admonition:: Metadata + + Status + proposed + +Summary +======= + +This DD discusses considerations for disto packages of GNU Taler components, +especially with regards to configuration and setup. We focus on Debian +packages for now. + +Motivation +========== + +The current way that configuration files are handled does not work well with +automated setup tools and furthermore does not easily allow restoring +configuration files in ``/etc/`` that the admin deleted or manually modified. + +The database configuration is currently handled inconsistently. While some +packages use Debian's dbconfig-common facilities, others don't, even though +they require a database for operation. + +The guidelines in this document are based on pratical experience +with third parties setting up Taler based on the Debian packages +and scripting supplied by us (i.e. ``deployment.git/netzbon``). + +Requirements +============ + +* The distro package should work nicely both for a manual setup + process by a sysadmin, as well as for automated installation + via helper scripts or other tools. +* Major differences between different distributions should be minimized, the + more code and config templates that can be shared the better. + +Proposed Solution +================= + +This section contains the new guidelines that we want to apply to all our +distro packages, specifically the Debian packages. + +General Considerations +---------------------- + +* Packages may not enable a systemd service by default. + +Config Files: Taler-specific +---------------------------- + +The "pristine" version of config files must be installed into +``/usr/share/taler/etc-original``. These files should not be modified by +tooling or the user. These files may contain direct placeholders or +placeholder comments that are replaced (but not in-place, only in ``etc/``!) +when the package is configured. + +During the postinstall step, the files from ``/usr/share/taler/etc-original`` +are copied to ``/etc/`` (using the ``ucf`` tool on Debian) and, if required, +placeholders are filled in. + +When using tooling to set up Taler, the tooling **should not** +use files from ``/etc/`` as template, but instead from ``/usr/share/taler/etc-original`` or alternatively generate custom configuration files. + +Rationale: Debian manages conffiles in ``/etc/`` with special logic. +In particular, when files are deleted from ``/etc/taler`` and the package +is reinstalled (even with ``--reinstall``), there is no easy way for +tooling (or the admin) to restore the unmodified config files. +The only way to restore it is ``apt install --reinstall libtalerexchange -o Dpkg::Options::="--force-confmiss"``, which might be unsafe as it forces +overriding of *all* config files of the package. + +Config Files: HTTP Server +------------------------- + +The same considerations apply to configuration files of HTTP +servers (nginx, apache, caddy, ...). Additionally: + +* Configuration files *must* either have a well-known name + or particular suffix to easily identify them + + * In particular, file names like ``sites-available/exchange.$domain`` + are unacceptable, as they are very difficult to uninstall + or remove when ``$domain`` is changed. + +* Configuration files for the HTTP server must not be + active by default, i.e. they must be placed in ``sites-available`` + but not ``sites-enabled``. + +Database +-------- + +Packages should *not* use ``dbconfig-common``. Reasons are: + +* ``dbconfig-common`` is lacking in documentation and very difficult + to use for packagers. +* ``dbconfig-common`` offers too much flexibility and + asks too many questions to the administrator, especially when + reconfiguring a package. The ``taler-merchant`` package + currently breaks when the user chooses anything else than ``ident`` auth. +* Using ``debconfig-common`` makes the database setup logic difficult to test. + That is not a problem with simple packages, but most Taler packages + require a non-trivial database setup. +* Very few packages in Debian (<30) actually use ``dbconfig-common``; + even fewer are notable or widely used packages. + +Instead, each package should document how to set up +the database and *optionally* ship an executable named +``taler-$component-dbconfig`` that: + +1. Creates the database and adjusts permissions +2. Checks if the database is accessible +3. Runs ``taler-$component-dbinit`` if applicable + and unless supressed by the user. + +For now, our tooling shall only support PostgreSQL and only set up ``ident`` +authentication or set up ``password`` authentication with a random password for +components that do not support DB connections via unix domain sockets. + +Definition of Done +================== + +* All Taler and Anastasis packages follow the guidelines from this DD +* Packages installation has been manually tested +* Automated setup scripts (``deployment.git``) have been adjusted to use the + configuration file templates shipped in the package, + instead of using their own config templates. + +Alternatives +============ + +* Do not ship with distro-specific configuration files, instead only ship + tooling to generate config files and set up the database. + +Discussion / Q&A +================ + +(This should be filled in with results from discussions on mailing lists / personal communication.) diff --git a/design-documents/041-wallet-balance-amount-definitions.rst b/design-documents/041-wallet-balance-amount-definitions.rst @@ -0,0 +1,424 @@ +DD 41: Wallet Balance and Amount Definitions +############################################ + +Summary +======= + +This design document discusses terminology and concepts used in the wallet +for balances and amounts. + +Motivation +========== + +There are many different types of balances and amounts, and they need +to have a clear definition. + +Furthermore, the user in some situations needs to know/decide whether +an amount that the user chooses includes fees or not. + + +Proposed Solution +================= + +Amounts +------- + +* "effective amount": An effective amount always represents the direct effect on the + wallet's balance of the same currency. +* "raw amount": The raw amount always refers to the amount with fees applied. + The exact interpretation of that depends on the transaction type. +* "instructed amount": An instructed amount always refers to the amount that + a user has explicitly specified as an input. It is not directly a property + of transactions, but might be added as metadata to transactions for + informational purposes. How the instructed amount is interpreted + differs based on the "instructed amount mode" that is specified + together with the amount. By default, the instructed amount + is assumed to translate to the raw amount of the corresponding transaction. +* "counter-party effective amount": An amount that **estimates** the effect + of the transaction of the balance (either wallet or bank account) of the other + party. This is usually a conservative estimate, i.e. when sending money, + this is the lower bound for the funds that the other party will obtain + *after* fees. + + +Transaction types initialized by the wallet +------------------------------------------- + +MANUAL_WITHDRAW + raw amount is the amount that need to be added into the exchange account, + this is not the same as the amount leaving the user account since their own + account may charge some fee that can be taken into account + + ``coins`` = select-coin-for-operation(credit, mode, instructed_amount) + + if instructed_amount mode = raw + ``raw_amount`` = instructed_amount + + ``effective_amount`` = instructed_amount - coins.withdrawal_fee + + if instructed_amount mode = effective + ``raw_amount`` = instructed_amount + coins.withdrawal_fee + + ``effective_amount`` = instructed_amount + +DEPOSIT + raw amount is the amount leaving the exchange account without the wire fee, + this should be what the user see as an increase in the user bank account unless + there are some extra fee not seen from the exchange + + ``coins`` = select-coin-for-operation(debit, mode, instructed_amount) + + if instructed_amount mode = raw + ``raw_amount`` = instructed_amount + + ``effective_amount`` = instructed_amount + coins.deposit_fee + coins.refresh_fee + wire.transfer_fee + + if instructed_amount mode = effective + ``raw_amount`` = instructed_amount - coins.deposit_fee - coins.refresh_fee - wire.transfer_fee + + ``effective_amount`` = instructed_amount + +PULL CREDIT (creating an invoice) + raw amount is the amount in the exchange that counter-party need will pay (purse_value), + this is exactly the same raw amount of the PULL DEBIT operation (paying the invoice) + counter-party amount is an aprox amount of the other wallet assuming the same coin selection + algorithm + + ``coins`` = select-coin-for-operation(credit, mode, instructed_amount) + + if instructed_amount mode = raw + ``raw_amount`` = instructed_amount + + ``effective_amount`` = instructed_amount - coins.withdrawal_fee - purse_fee + + if instructed_amount mode = effective + ``raw_amount`` = instructed_amount + coins.withdrawal_fee + purse_fee + + ``effective_amount`` = instructed_amount + + if instructed_amount mode = counter-party + ``raw_amount`` = instructed_amount - coins.counter-party_deposit_fee + + ``effective_amount`` = instructed_amount - coins.counter-party_deposit_fee - coins.withdrawal_fee - purse_fee + + ``counter-party_raw_amount`` = raw_amount + + ``counter-party_effective_amount`` = raw_amount + coins.counter-party_deposit_fee + + .. note:: + + counter-party_effective_amount is an estimation since refresh fee is not included. + Refresh fee can't be calculated because depends on the coins available in the wallet + of the counter-party + + .. note:: + coins.counter-party_deposit_fee is the minimum deposit_fee that can be calculated for the + given exchange. Counter-party may pay more if it have different preferences doing the coin + selection. + + +PUSH DEBIT (creating a transfer) + raw amount is the amount in the exchange that counter-party need be able to withdraw (purse_value), + this is exactly the same raw amount of the PUSH CREDIT operation (getting the transfer) + counter-party amount is an aprox amount of the other wallet assuming the same coin selection + algorithm + + ``coins`` = select-coin-for-operation(debit, mode, instructed_amount) + + if instructed_amount mode = raw + ``raw_amount`` = instructed_amount + + ``effective_amount`` = instructed_amount + coins.deposit_fee + purse_fee + + if instructed_amount mode = effective + ``raw_amount`` = instructed_amount - coins.deposit_fee - purse_fee + + ``effective_amount`` = instructed_amount + + if instructed_amount mode = counter-party + ``raw_amount`` = instructed_amount + coins.counter-party_withdraw_fee + + ``effective_amount`` = instructed_amount - coins.counter-party_withdraw_fee - coins.withdrawal_fee - purse_fee + + ``counter-party_raw_amount`` = raw_amount + + ``counter-party_effective_amount`` = raw_amount - coins.counter-party_withdraw_fee + + .. note:: + coins.counter-party_withdraw_fee is the minimum withdraw_fee that can be calculated for the + given exchange. Counter-party may pay more if it have different preferences doing the coin + selection. + + +Transaction types completed by the wallet +------------------------------------------- + +Next transaction types are not initiated in the wallet so instructed amount is not defined by the wallet user. + +We need to calculate effective_amount to check if the wallet is able to perform the operation or the user accept +the fees. + +BANK_WITHDRAW + raw amount is that reached the bank account of the exchange, + this is not the same as the amount leaving the user account since their own + account may charge some fee that can be taken into account + + ``coins`` = select-coin-for-operation(credit, mode, instructed_amount) + + if instructed_amount mode = raw + ``raw_amount`` = instructed_amount + + ``effective_amount`` = instructed_amount - coins.withdrawal_fee + + if instructed_amount mode = effective + ``raw_amount`` = instructed_amount + coins.withdrawal_fee + + ``effective_amount`` = instructed_amount + + +.. note :: + how much wire_fee the merchant is willing to pay + + ``merchant_wire_fee`` = min(wire.transfer_fee / contractTerms.amortization_factor, contractTerms.max_wire_fee) + + ``merchant_deposit_fee`` = min(contractTerms.max_fee, contract_wire_fee) + + +PAYMENT + raw amount is the amount the merchant should get if is not doing aggregated transaction. + + + ``instructed_amount`` = contractTerms.amount + + ``coins`` = select-coin-for-operation(debit, mode, raw_amount) + + ``raw_amount`` = instructed_amount - merchant_deposit_fee + + ``effective_amount`` = instructed_amount + coins.deposit_fee + coins.refresh_fee + (wire.transfer_fee - merchant_wire_fee) + + .. note:: + The current coin-selection algorithm the order_price is neither raw_amount nor effective_amount. + We can calculate the raw_amount of the payment as (contractTerms.amount - max_merchant_fee) and then this + operation becomes equivalent than a deposit (in terms of fee calculation). + + +PUSH CREDIT (getting the transfer) + raw amount is the purse_value in the exchange to be withdrawn + + ``instructed_amount`` = p2pContract.amount + + ``coins`` = select-coin-for-operation(credit, mode, raw_amount) + + ``raw_amount`` = instructed_amount + + ``effective_amount`` = instructed_amount - coins.withdrawal_fee + + .. note:: + In the case that the withdrawal_fee of the coin selection for the push-credit amount + is higher than the wire_fee of the exchange, can the wallet ask the exchange to make + a wire transfer of the purse instead of proceeding? + +PULL DEBIT (paying an invoice) + raw amount is the net value of the invoice without fees + + ``instructed_amount`` = p2pContract.amount + + ``coins`` = select-coin-for-operation(debit, mode, raw_amount) + + ``raw_amount`` = instructed_amount + + ``effective_amount`` = instructed_amount + coins.deposit_fee + coins.refresh_fee + wire.transfer_fee + +REFUND + raw amount is the amount that the merchant refunded + + ``instructed_amount`` = refund.amount + + ``raw_amount`` = instructed_amount + + ``effective_amount`` = instructed_amount - refund_fee - refresh_fee + + .. note:: + There may be the case that the merchant should refund all the value of the purchase + and that may include paying for the refund_fee. + + Is there a way that the merchant can initiate a refund of purchase + refund_fee so + the wallet will get the same effective_amount? + +REWARD + raw amount is the amount that the merchant send as reward + + ``instructed_amount`` = reward.amount + + ``raw_amount`` = instructed_amount + withdrawal_fee + + ``effective_amount`` = instructed_amount + + .. note:: + We should not show fee for rewards in the wallet since the merchant is the one choosing + the exchange and we can assume that those rewards are paid by the merchant. + So the wallet only care about the effective. + +Coin selection algorithm +------------------------ + +Is an internal optimization algorithm that will choose coins given a denomination list or current coin list +until amount is reached. The coins selected to minimize the fee spent. + +``select-coin-for-operation`` will receive 3 parameters: + + * operation: define if the coins are selected from wallet database or from denomination list. Possible values are: + + - credit: reduce withdrawal fee, use exchange denomination list + - debit: reduce deposit fee, use database denomination and current coin count + + * amount: how much value the coins need to sum up + * mode: the interpretation of the amount parameter + + - net: the amount does not include the operation fee + - gross: the amount include the operation fee + +If the operation is debit and with the current coins there is no way to reach the amount then + + 1. an optimized withdrawal operation can be suggested (list of denominations) + 2. an optimized refresh operation can be suggested (amount gap, coin to be refreshed and list of denominations to withdraw) + +.. note:: + + ``select-coin-for-operation`` must be predictable (select the same coins for the same parameters) and if + the difference between two amounts are the fee for a given operation: + + operation: credit + + withdrawal_fee = amount1 - amount2 + + then the wallet should select the same coins using the correct mode + + select-coin(withdraw, raw, amount1) == select-coin(withdraw, effective, amount2) + + +Instructed Amount Modes +----------------------- + +The interpretation and possible choices of the instructed amount mode +depends on which transaction is initiated. + +For withdrawal: + +* ``raw-mode`` (default): instructed amount is what is subtracted from the reserve balance (i.e. it's the raw amount) +* ``effective-mode``: instructed amount is what the user wants to have as material balance in the wallet + +FIXME(dold): However, that does not really cover the user case where the merchant charges fees and the user has to pay for that. +So in theory we could have a mode that withdraws enough to pay for some particular claimed order, but IMHO that's overkill. + +For deposits (where there is no contract that already specifies an amount): + +* ``max-mode``: The instructed amount is ignored (can be zero in the request), and all coins are spent (note that the calculation should be made available when the user is asked to specify an amount when using a template) +* ``raw-mode`` (default): The instructed amount is what will be paid to the "merchant" (or the customer's bank account), ignoring wire fees +* ``effective-mode``: The instructed amount is how the wallet's balance will be affected. Difficult to compute accurately because refresh is involved. Note that the calculation should ideally again be made available when the user is asked to specify an amount when using a template. + + +For peer-push-debit: + +* ``raw-mode`` (default): The instructed amount is what will be paid, deposit fees are covered by the sender, withdrawal fees from the reserve by the receiver +* ``effective-mode``: Instructed amount is the effect on the material balance. Difficult to compute accurately because refresh is involved. +* ``counter-party-effective-mode``: Instructed amount is the effect on the counterparty's wallet balance. Difficult to compute accurately because coin selection by receiver may not match our expectations. + +FIXME(dold): Should we also have a mode where withdrawal fees are covered by the side that does peer-push-debit? However, that assumes the other party has the same withdrawal coin selection algorithm. FIXME(grothoff): isn't this the counterparty-effective-mode you described above, and that would seem to exactly have this issue? + +For peer-pull-credit: + +* ``raw-mode`` (default): Amount that the other party has to put in the reserve. The payer has to pay any deposit fees on top. The receiver balance is increased by the specified amount minus any withdraw fees. +* ``effective-mode``: Amount by which the initiator's balance is increased. Difficult to compute as the receiver has to simulate different coin selections and their effect on withdraw fees to arrive at the minimum total amount that must be deposited into the reserve. + + + +Illustrative Example +-------------------- + +To explain the differences between raw, effective and instructed amounts, consider the following scenario: Alice wants to send money +to Bob via a P2P push payment. + +Example 1: + +* Alice starts a withdrawal of ``KUDOS:10`` from her bank's web interface into her Taler + wallet. The instructed amount is ``KUDOS:10`` and (by default for bank-integrated withdrawals), + the mode is ``raw-mode``. After fees, ``KUDOS:9.8`` arrive in her Taler wallet. + +Example 3: + +* Alice wants to pay for a ``KUDOS:10`` monthly magazine subscription. Her Taler wallet is empty though. +* She starts withdrawal through her Android wallet app, where she selects ``KUDOS:10`` as the instructed + amount with ``mode=effective-mode``. This translates to ``amountEffective=KUDOS:10`` and ``amountRaw=KUDOS:10.10``. +* Alice is redirected to her banking app where she transfers ``KUDOS:10.10`` to the exchange. +* Her Taler wallet balance will be ``KUDOS:10.10`` after the withdrawal completes. + +Note that on the amount she chooses and the fees / denom structure of the exchange, the ``amountEffective`` might be *higher* +than the instructed amount. + +FIXME(dold): That flow does not work if withdrawal starts in the bank. Maybe there needs to be a mechanism +where the wallet tells the bank the adjusted amount that needs to be transferred? That would be a new +feature in the bank integration API. + +Example 4: + +* Alice has ``KUDOS:10`` in her wallet. +* Alice wants to initiate a peer-push payment with ``amountInstructed=KUDOS:8`` + and ``mode=effective-mode``. That means that after the payment, she expects + exactly ``KUDOS:2`` to remain in her wallet. +* Due to the fee configuration, her wallet computes ``amountRaw=KUDOS:7.5`` and ``amountEffective=KUDOS:7.8``. + The effective amount in this case does **not** equal the instructed amount, despite the ``mode=effective-mode``. + That's because there no amount that can be spend so that the spend amount with resulting refresh + fees equal ``KUDOS:8``. +* Alice confirms the peer-push payment initiation, and exactly ``KUDOS:7.5`` are credited + to the purse that her wallet creates. +* Bob merges the purse into his reserve. Bob's wallet automatically withdraws + from the reserve, and his wallet balance increases by ``KUDOS:7.1``, since + withdrawal fees are deducted. + +Balances +-------- + +The following types of balances are defined: + +- ``available``: Balance that the wallet believes will certainly be available + for spending, modulo any failures of the exchange or double spending issues. + This includes available coins *not* allocated to any + spending/refresh/... operation. Pending withdrawals are *not* counted + towards this balance, because they are not certain to succeed. + Pending refreshes *are* counted towards this balance. + This balance type is nice to show to the user, because it does not + temporarily decrease after payment when we are waiting for refreshes + +- ``material``: Balance that the wallet believes it could spend *right now*, + without waiting for any operations to complete. + This balance type is important when showing "insufficient balance" error messages. + +- ``age-acceptable``: Subset of the material balance that can be spent + with age restrictions applied. + +- ``merchant-acceptable``: Subset of the material balance that can be spent with a particular + merchant (restricted via min age, exchange, auditor, wire_method). + +- ``merchant-depositable``: Subset of the merchant-acceptable balance that the merchant + can accept via their supported wire methods. + +Balance Mismatch +---------------- + +The wallet uses the following terminology when an operation can't succeed +because the balance is too low, even though the instructed amount + +- "fee-gap-estimate": Additional (material) balance that the wallet estimates it + still needs for the operation to succeed. + + - This value is an estimated, because newly withdrawn coins might have different fees. + - This value is specified *per exchange*, because each exchange has different fees. + +FIXME(dold): Should we specify an upper-bound fee-gap-estimate to simplify it for the UIs? + + +Discussion / Q&A +================ + +(This should be filled in with results from discussions on mailing lists / personal communication.) diff --git a/design-documents/042-synthetic-wallet-errors.rst b/design-documents/042-synthetic-wallet-errors.rst @@ -0,0 +1,57 @@ +DD 42: Wallet Dev Experiments +############################# + +Summary +======= + +This design document defines new ``taler://`` URIs to cause synthetic errors +or special states in the wallet that can then be rendered by the UI. + +Motivation +========== + +UIs need to handle various (error-) states and responses of wallet-core. It's +not easy to cover all of these states and responses manually. Some of them are +hard to reach or simulate without an elaborate test setup. + +Requirements +============ + +The implementation of synthetic errors should be as separate from production +code as possible, to avoid making the normal code paths unreadable. + + +Proposed Solution +================= + +Special taler:// URIs +--------------------- + +* ``taler://dev-experiment/$STATE_ID`` +* ``taler://pay/...?dev-experiment=`` + +Special http(s):// URIs +----------------------- + +* ``http(s)://*.dev-experiment.taler.net/`` + + * URLs for this subdomain are handled specially by the + wallet's HTTP layer and return fixed / mocked responses + instead of making real requests. + + +List of experiments +------------------- + + + +Alternatives +============ + +Drawbacks +========= + +Discussion / Q&A +================ + +(This should be filled in with results from discussions on mailing lists / personal communication.) diff --git a/design-documents/043-managing-prebuilt-artifacts.rst b/design-documents/043-managing-prebuilt-artifacts.rst @@ -0,0 +1,107 @@ +DD 43: Managing Prebuilt Artifacts and Source-Level Dependencies +################################################################ + +Summary +======= + +This design document defines how the GNU Taler project manages prebuilt +artifacts and other source-level dependencies in repositories +that are part of project. + +Motivation +========== + +Some repositories have source-level dependencies on the build results of other +repositories. While it is possible to build these dependencies from scratch, +we often want to avoid that extra step in order to make building the software +easier and faster. + +Examples are: + +* man-pages built via Sphinx, produced in ``docs.git`` and consumed in ``exchange.git``. +* SPAs used by the exchange, merchant libeufin. +* (formerly): The ``taler-wallet-core-embedded.js`` file used + by the Android repo. + +Another type of source-level dependency is on other **source** files. +Examples for this are: + +* The ``build-common.git`` repository that contains common build-time helpers +* The ``gana.git`` repository + +Requirements +============ + +* We are a free software project, users must always be able to + easily re-build the prebuilt artifacts for themselves. +* We want to reduce reliance on third party infrastructure as much + as possible. +* We want to keep our own infrastructure as slim as possible. +* Builds must be reproducible and remain reproducible in the future. +* Offline builds should be supported as well as possible. +* Ideally, prebuilt artifacts can easily be cached / archived by third parties. + +Proposed Solution +================= + +Instead of using a full-blown artifact management solution from the start, we +make use of Git. Since Git is not very good at managing binary artifacts, +prebuilt files are not managed alongside the source code. Instead, we use +(orphan-)branches) in a (possibly separate) repository to manage them. This +allows us to re-use Git authentication and Git commit signing. + +Due to a historical accident, prebuilt files are currently stored in the +``prebuilt`` branch of the ``wallet-core.git`` repository. This might change +in the future. + +To enable forwards-compatibility, we are implementing the following approach: +The ``taler.net`` HTTP server redirects requests in the form of +``https://artifacts.taler.net/$component/$version/$file`` to +``https://git.taler.net/$repo.git/tree/$version/$file?h=$branch``, where +``$component`` determines ``$repo`` and ``$branch``. + +We are also introducing the new rule that a prebuilt artifact must be a single +archive file (preferable ``.tar.gz.``). + +Repositories that produce artifacts *MUST* have phony Makefile helper targets +to (a) create the prebuilt artifact (b) check out the prebuilt branch as a Git worktree, (c) +move the artifact to the right place in the prebuilt branch and commit/push. + +Repositories that depend on prebuilt components must download them +in their ``./bootstrap`` script. After downloading, the bootstrap +script *SHOULD* verify a checksum of the downloaded artifact. + +FIXME: Link to an example bootstrap file, once the approach from this document +is fully implemented. + +Alternatives +============ + +* The prebuilt branch could be integrated into source repositories that + depend on it via a git submodule. This has the following disadvantages: + + 1. Git submodules are difficult to handle for some developers. We've had issues + in the past where the prebuilt submodule wasn't integrated properly and would + lead to non-reproducible builds + 2. Relying purely on the Git commit hash of the prebuilt branch + makes it very difficult to know which version of the prebuilt + artifact is being used. It also makes it very difficult + to reliable find older versions of the artifact. + 3. Relying on the commit hash instead of a version and artifact hash + couples the artifact to the Git commit. That means that + we can never compact the commit history of the prebuilt + branch of move artifacts around. + +* Set up a full-blown artifact management solution like JFrog Artifactory. + That's costly and requires a lot of admin work. + +* Never rely on prebuilt files. That slows down the build process + and in some cases requires exotic dependencies. + +Drawbacks +========= + +Discussion / Q&A +================ + +(This should be filled in with results from discussions on mailing lists / personal communication.) diff --git a/design-documents/044-ci-system.rst b/design-documents/044-ci-system.rst @@ -0,0 +1,121 @@ +DD 44: CI System +################ + +Summary +======= + +This documents describes Taler's CI system based on Buildbot. + +This document uses `RFC 2119 <https://tools.ietf.org/html/rfc2119>`_ +keywords throughout. + +Motivation +========== + +With the current CI system there are an array of issues: + +- Central place for all the jobs. +- The central config is poorly organized. +- We should prefer to keep as much CI logic in respective project source repos + as possible. +- Jobs should be split up further to allow for more granular control and + insight. +- Job triggers are unclear. +- The build environments are mutable. +- Non-trivial and error-prone to keep track of environment state. +- Hard to get an overview of what repo is causing a failure, at a quick glance. +- Bad for development workflow on a single project when you are getting + false-negatives all the time. + +Proposed Solution +================= + +General +------- + +Jobs shall be executed inside of containers. + +One build pipeline (aka. "builder") per repo. + +Build steps are generated from directory structure within a given repo. + +Example directory structure: + +:: + + ci + ├── ci.sh + ├── Containerfile + └── jobs + ├── 0-codespell + │ ├── config.ini + │ ├── dictionary.txt + │ └── job.sh + ├── 1-build + │ ├── build.sh + │ └── job.sh + └── 2-docs + ├── docs.sh + └── job.sh + +Job directories **MUST** follow this pattern: +``<repo_root>/ci/jobs/<n-job_name>/`` + +``n`` is an integer used for ordering the build steps. + +Job directories **MUST** contain a script named ``job.sh`` which **MAY** +execute other scripts. + +Config files may optionally be created, and MUST be named ``config.ini`` and +placed in the job directory. + +Available config options: + +:: + + [build] + HALT_ON_FAILURE = True|False + WARN_ON_FAILURE = True|False + CONTAINER_BUILD = True|False + CONTAINER_NAME = <string> + + +Unless *all* jobs specify a "CONTAINER_NAME" in their custom config a +container file **MUST** be present at ``<repo_root>/ci/Containerfile``. +The container file will be built and used to run all of a repo's jobs +by default. + +All projects SHOULD have a ``build`` step and a ``test`` step, at a minimum. + +Running CI Locally +------------------ + +Running the CI scripts locally can be useful for development and testing. + +*Be aware that custom configs for a given job may specify a alternate +container.* + + +Example of building the environment and running a job locally: + +:: + + # From root of repo directory, build the container: + docker build -t <local_name_for_container> -f ci/Containerfile . # <- don't forget the "." + + # Then to run one of the job scripts. For example: + docker run --rm --volume $PWD:/workdir --workdir /workdir <local_name_for_container> ci/jobs/1-build/job.sh + + # or to get an interactive shell in the container, with the repo mounted at /workdir: + docker run -ti --rm --volume $PWD:/workdir --workdir /workdir <local_name_for_container> /bin/bash + + + + +Additional Builders +------------------- + +To run some tests there is a need for many or most project's sourcecode to be +available in the same environment. This will be a separate builder/pipeline +from the per-repo builders. Triggers for this builder are yet to be +determined. diff --git a/design-documents/045-kyc-inheritance.rst b/design-documents/045-kyc-inheritance.rst @@ -0,0 +1,186 @@ +DD 45: Single-Depth Inheritance of KYC for Reserves +################################################### + +Summary +======= + +This document presents and discusses a mechanism by which a reserve A can +provide KYC attestation for another reserve B, whenever A's KYC attestation is +the result of a proper KYC-process and not inherited itself. During the +transitive attestation process, A can change the birthday for reserve B become +younger, i.e. choose a date closer to the current date than the original +birthday. + + +Motivation +========== + +There are two reasons that motivate our proposal: + +#. KYC attestation of a reserve is a must for Peer-2-Peer payments. However, + a KYC process is usually costly for the exchange and -ultimately- the + customer. When a customer has multiple long-term reserves, it should be + possible to inherit the KYC attestation from one to another. + +#. A parent should be able to provide KYC attestation for the long-term reserve + of his or her child and at the same time provide appropriate birthday + information. That way, the child can withdraw money from its reserve + + - with appropriate and evolving age-restriction always in place, + + - no further age-commitment interaction with the parent. + +With the ability to attest KYC transitively, we can reduce the cost of +ownership of long-term reserves and enable the principle of subsidiarity, +according to which parents are responsible for age-restriction settings. + + +Requirements +============ + +* none + +Proposed Solution +================= + +There are changes in the exchange and in the wallet necessary. + +Changes in the Exchange +^^^^^^^^^^^^^^^^^^^^^^^ + +A new configuration option in the TALER-configuration defines the maximum +number of attestations that a (KYC'ed) reserve can provide for other reserves. + +.. code:: none + + [kyc-legitimization-inheritance] + MAXIMUM_ATTESTATIONS = [number] + + +The database schema needs to be adjusted to incorporate + +* a boolean field ``inherited`` in the table ``kyc_attributes`` to indicate the + inheritance status + +* an integer field ``attestations`` in the table ``reserves`` to count the + number of transitive attestations performed by a reserve. + + +On the exchange we propose the following new endpoint: + + +.. http:post:: /kyc-attest/$TARGET_RESERVE_PUB + +**Request:** + +The request body must be a `KYCAttestationRequest` object. + +**Response:** + + :http:statuscode:`200 OK`: + Both, the attesting and the target reserves were known to the exchange, and the + KYC data of the attesting reserve has been successfully inherited by the + target reserve (with optionally adjusted birthday). + :http:statuscode:`403 Forbidden`: + The attesting reserve is not allowed to transitively attest another reserve. + This is because the attesting reserve either + + #. lacks KYC attestation or + + #. its KYC attestation was itself inherited or + + #. has reached the allowed maximum number of transitive attestations. + + The response comes with a standard `ErrorDetail`. + :http:statuscode:`404 Not found`: + One of the reserve keys belongs to a reserve which is unknown to the exchange. + The response comes with a standard `ErrorDetail`, containing the unknown key. + :http:statuscode:`409 Conflict`: + The birthday in the request is not acceptable, as it points to an earlier + point in time (more distant from current time) than the birthday of the + attesting reserve. + +**Details:** + +.. ts:def:: KYCAttestationRequest + + interface KYCAttestationRequest { + // An optional birthday for the target reserve. MUST be equal or younger + // (more recent to current time) than the birthday of the attesting + // reserve. + birthday?: FuzzyDateString; + + // The public key of the attesting reserve + attester_pub: EddsaPublicKey; + + // Signature of purpose + // ``TALER_SIGNATURE_WALLET_RESERVE_TRANSITIVE_KYC`` over + // a `TALER_ReserveKYCAttestationPS`. + attester_sig: EddsaSignature; + } + + +.. ts:def:: FuzzyDateString + + // A date of the form "YYYY-MM-DD","YYYY-MM-00" or "YYYY-00-00". + // "YYYY-MM-00" will be evaluated as "YYYY-MM-01" and + // "YYYY-00-00" will be evaluated as "YYYY-01-01". + type FuzzyDateString = string; + + +.. _TALER_ReserveKYCAttestationPS: +.. sourcecode:: c + + struct TALER_ReserveKYCAttestationPS { + /** + * purpose.purpose = TALER_SIGNATURE_WALLET_RESERVE_TRANSITIVE_KYC + */ + struct GNUNET_CRYPTO_EccSignaturePurpose purpose; + struct TALER_ReservePublicKeyP attester_reserve_pub; + struct TALER_ReservePublicKeyP target_reserve_pub; + /* If no birthday is set, must be all 0 */ + char birthday[sizeof("YYYY-MM-DD")]; + } + + +Changes in the Wallet +^^^^^^^^^^^^^^^^^^^^^ + +We need a workflow for the attestation of one wallet through another. + +TODO. + + +Definition of Done +================== + +For the exchange, the implementation of the configuration option and the +endpoint, and corresponding unit tests in ``src/testing`` are necessary. + + +For the wallet: TODO. + +Alternatives +============ + +* KYC for a reserve can only be provided by a full KYC legitimization process. + +Drawbacks +========= + +Other than adding code to the exchange: unknown. + +Discussion / Q&A +================ + +The proposed solution makes the principle of subsidiarity for age-restrictions +(i.e parents are responsible for setting the age-restriction) explicit in the +code. + +It also simplifies the KYC process for many situations for customers: Families +members and partners benefit from it. + +However, the proposed solution still allows for other ways to set +age-restriction in the wallet. For example, parents who do **not** have a +Taler wallet, are still able to assist their children with the settings of +age-restriction during the withdraw process. diff --git a/design-documents/046-mumimo-contracts.rst b/design-documents/046-mumimo-contracts.rst @@ -0,0 +1,721 @@ +Contract Format v1 +################## + +Summary +======= + +The contract v1 format enables a multitude of advanced interactions between +merchants and wallets, including donations, subscriptions, coupons, currency +exchange and more. + +Motivation +========== + +The existing v0 contract format is too simplistic to +support many frequenly requested types of contracts. + +Requirements +============ + +We want Taler to support various interesting use-cases: + + - Unlinkable, uncopyable subscriptions without accounts (reader can pay with + Taler to subscribe to online publication, read unlimited number of + articles during a certain period, transfer subscription to other devices, + maintain unlinkability / full anonymity amongst all anonymous + subscribers). + + - Coupons, discounts and stamps -- like receiving a discount on a product, + product basket or subscription -- based on previous purchase(s). Again, + with unlinkability and anonymity (modulo there being other users eligible + for the discount). + + - Subscription tokens lost (due to loss of device without backup) should + be recoverable from any previous backup of the subscription. + + - Currency conversion, that is exchanging one currency for another. + + - Donations, including privacy-preserving tax receipts that prove that the + user donated to an entity that is eligible for tax-deductions but without + revealing which entity the user donated to. At the same time, the entity + issuing the tax receipt must be transparent (to the state) with respect to + the amount of tax-deductable donations it has received. + + - Throttled political donations where each individual is only allowed to + donate anonymously up to a certain amount per year or election cycle. + + - Unlinkable gifts -- enabling the purchase of digital goods (such as + articles, albums, etc.) to be consumed by a third party. For example, a + newspaper subscription may include a fixed number of articles that can be + gifted to others each week, all while maintaining unlinkability and + anonymity between the giver and the recipient. + + - Temporally-constrained, unlinkable event ticketing. Allowing visitors to + use Taler to purchase a ticket for an event. This ticket grants entry and + exit privileges to the event location during a specified time window, while + preserving the anonymity of the ticket holder (within the group of all the + ticket holders). + + - Event deposit systems. A deposit mechanism for events where customers + receive a token alongside their cup or plate, which they are expected to + return. This system validates that the cup or plate was legitimately + acquired (i.e., not brought from home or stolen from a stack of dirty items) + and incentivizes return after use. + +TODO: add more use-cases here! + + +Proposed Solution +================= + +Merchants will also blindly sign tokens (not coins) to indicate the +eligibility of a user for certain special offers. Contracts will be modified +to allow requiring multiple inputs (to be *provisioned*" to the merchant) and +multiple outputs (to be *yielded* by the merchant). Contracts will also +include multiple options for how a user may pay or what they might want to +purchase. The wallet will then allow the user to select between the choices +that the user could pay for, or possibly make an automatic choice if the +correct choice is obvious. One output option is blindly signed coins from +another exchange, possibly in a different currency. Another output option is +blindly signed donation receipts from a DONation AUthority (DONAU). +Subscriptions can be modeled by requiring the wallet to provision a token of +the same type that is also yielded by the contract. For security, payments +using subscription tokens (and possibly certain other special tokens?) will be +limited to a list of domains explicitly defined as trusted by the token +issuer. When paying for a contract, the wallet must additionally sign over +the selected sub-contract index and a hash committing it to the blinded +envelopes (if any). The merchant backend will (probably?) need to be changed +to truly support multiple currencies (ugh). + +.. _contract-terms-v1: + +New Contract Terms Format +------------------------- + +The contract terms v1 will have the following structure: + +.. ts:def:: ContractTermsV1 + + interface ContractTermsV1 { + + // This is version 1, the previous contract terms SHOULD + // be indicated using "0", but in v0 specifying the version + // is optional. + version: "1"; + + // Unique, free-form identifier for the proposal. + // Must be unique within a merchant instance. + // For merchants that do not store proposals in their DB + // before the customer paid for them, the ``order_id`` can be used + // by the frontend to restore a proposal from the information + // encoded in it (such as a short product identifier and timestamp). + order_id: string; + + // URL where the same contract could be ordered again (if + // available). Returned also at the public order endpoint + // for people other than the actual buyer (hence public, + // in case order IDs are guessable). + public_reorder_url?: string; + + // Time when this contract was generated. + timestamp: Timestamp; + + // After this deadline, the merchant won't accept payments for the contract. + pay_deadline: Timestamp; + + // Transfer deadline for the exchange. Must be in the + // deposit permissions of coins used to pay for this order. + wire_transfer_deadline: Timestamp; + + // Merchant's public key used to sign this proposal; this information + // is typically added by the backend. Note that this can be an ephemeral key. + merchant_pub: EddsaPublicKey; + + // Base URL of the (public!) merchant backend API. + // Must be an absolute URL that ends with a slash. + merchant_base_url: string; + + // More info about the merchant (same as in v0). + merchant: Merchant; + + // After this deadline has passed, no refunds will be accepted. + refund_deadline: Timestamp; + + // Specifies for how long the wallet should try to get an + // automatic refund for the purchase. If this field is + // present, the wallet should wait for a few seconds after + // the purchase and then automatically attempt to obtain + // a refund. The wallet should probe until "delay" + // after the payment was successful (i.e. via long polling + // or via explicit requests with exponential back-off). + // + // In particular, if the wallet is offline + // at that time, it MUST repeat the request until it gets + // one response from the merchant after the delay has expired. + // If the refund is granted, the wallet MUST automatically + // recover the payment. This is used in case a merchant + // knows that it might be unable to satisfy the contract and + // desires for the wallet to attempt to get the refund without any + // customer interaction. Note that it is NOT an error if the + // merchant does not grant a refund. + auto_refund?: RelativeTime; + + // Delivery location for (all!) products (same as in v0). + delivery_location?: Location; + + // Time indicating when the order should be delivered. + // May be overwritten by individual products. + delivery_date?: Timestamp; + + // Nonce generated by the wallet and echoed by the merchant + // in this field when the proposal is generated. + // Note: required in contract, absent in order! + nonce: string; + + // Array of possible specific contracts the wallet/customer + // may choose from by selecting the respective index when + // signing the deposit confirmation. + choices: ContractChoice[]; + + // Extra data that is only interpreted by the merchant frontend. + // Useful when the merchant needs to store extra information on a + // contract without storing it separately in their database. + extra?: any; + + // Fee limits and wire account details by currency. + limits: { [currency:string] : CurrencyLimit }; + } + +.. ts:def:: CurrencyLimit + + interface CurrencyLimit { + + // The hash of the merchant instance's wire details. + h_wire: HashCode; + + // Wire transfer method identifier for the wire method associated with ``h_wire``. + // The wallet may only select exchanges via a matching auditor if the + // exchange also supports this wire method. + // The wire transfer fees must be added based on this wire transfer method. + wire_method: string; + + // Maximum total deposit fee accepted by the merchant for this contract. + max_fee: Amount; + + // Maximum wire fee accepted by the merchant (customer share to be + // divided by the ``wire_fee_amortization`` factor, and further reduced + // if deposit fees are below ``max_fee``). Default if missing is zero. + max_wire_fee: Amount; + + // Over how many customer transactions does the merchant expect to + // amortize wire fees on average? If the exchange's wire fee is + // above ``max_wire_fee``, the difference is divided by this number + // to compute the expected customer's contribution to the wire fee. + // The customer's contribution may further be reduced by the difference + // between the ``max_fee`` and the sum of the actual deposit fees. + // Optional, default value if missing is 1. 0 and negative values are + // invalid and also interpreted as 1. + wire_fee_amortization: number; + + // Exchanges that the merchant accepts for this currency. + exchanges: Exchange[]; + + } + + +.. ts:def:: ContractChoice + + interface ContractChoice { + + // Human-readable description of the choice. + summary: string; + + // Map from IETF BCP 47 language tags to localized summaries. + summary_i18n?: { [lang_tag: string]: string }; + + // URL that will show that the order was successful after + // it has been paid for. Optional. When POSTing to the + // merchant, the placeholder "${ORDER_ID}" will be + // replaced with the actual order ID (useful if the + // order ID is generated server-side and needs to be + // in the URL). + // Note that this placeholder can only be used once. + // Either fulfillment_url or fulfillment_message must be specified. + fulfillment_url?: string; + + // Message shown to the customer after paying for the order. + // Either fulfillment_url or fulfillment_message must be specified. + fulfillment_message?: string; + + // Map from IETF BCP 47 language tags to localized fulfillment + // messages. + fulfillment_message_i18n?: { [lang_tag: string]: string }; + + // List of products that are part of the purchase (see `Product`). + products: Product[]; + + // List of inputs the wallet must provision (all of them) to + // satisfy the conditions for the contract. + inputs: ContractInput[]; + + // List of outputs the merchant promises to yield (all of them) + // once the contract is paid. + outputs: ContractOutput[]; + + // Map from authority labels to meta data abou the + // respective token authority. + token_types: { [authority_label: TokenAuthority }; + + } + +.. ts:def:: ContractInput + + type ContractInput = + | ContractInputCurrency + | ContractInputRation + | ContractInputToken; + +.. ts:def:: ContractInputCurrency + + interface ContractInputCurrency { + + type: "coin"; + + // Price to be paid for the transaction. + // The exchange will subtract deposit fees from that amount + // before transferring it to the merchant. + price: Amount; + + // FIXME-DOLD: do we want to move this into a 'details' + // sub-structure as done with tokens below? + class: "currency"; + + }; + +.. ts:def:: ContractInputRation + + interface ContractInputRation { + + type: "coin"; + + // Price to be paid for the transaction. + price: Amount; + + // FIXME-DOLD: do we want to move this into a 'details' + // sub-structure as done with tokens below? + class: "ration"; + + // Base URL of the ration authority. + ration_authority_url: string; + + }; + +.. ts:def:: ContractInputToken + + interface ContractInputToken { + + type: "token"; + + // Hash over the public key used to sign the + // type of subscription token required. + h_issuer: HashCode; + + // Number of tokens of this type required. + // Defaults to one if the field is not provided. + number?: Integer; + + }; + +.. ts:def:: ContractOutput + + type ContractOutput = + | ContractOutputCurrency + | ContractOutputTaxReceipt + | ContractOutputToken; + +.. ts:def:: ContractOutputCurrency + + interface ContractOutputCurrency { + + type: "currency"; + + // Amount of currency that will be yielded. + // This excludes any applicable withdraw fees. + brutto_yield: Amount; + + // Base URL of the exchange that will issue the + // coins. + exchange_url: string; + + }; + +.. ts:def:: ContractOutputTaxReceipt + + interface ContractOutputTaxReceipt { + + type: "tax-receipt"; + + // Base URL of the donation authority that will + // issue the tax receipt. + donau_url: string; + + }; + +.. ts:def:: ContractOutputToken + + interface ContractOutputToken { + + type: "token"; + + // Label of the token authority in the + // 'token_types' map on the top-level. + authority_label: string; + + // Must a wallet understand this token type to + // process contracts that consume or yield it? + critical: boolean; + + // Information about the class of token that will + // be yielded. + details: OutputTokenClass; + } + +.. ts:def:: OutputTokenClass + + type OutputTokenClass = + | OutputTokenClassSubscription + | OutputTokenClassDiscount + +.. ts:def:: OutputTokenClassSubscription + + interface OutputTokenClassSubscription { + + class: "subscription"; + + // When does the subscription period start? + start_date: Timestamp; + + // When does the subscription period end? + end_date: Timestamp; + + // Array of domain names where this subscription + // can be safely used (e.g. the issuer warrants that + // these sites will re-issue tokens of this type + // if the respective contract says so). May contain + // "*" for any domain or subdomain. + trusted_domains: string[]; + + }; + +.. ts:def:: OutputTokenClassDiscount + + interface OutputTokenClassDiscount { + + class: "discount"; + + // Array of domain names where this discount token + // is intended to be used. May contain "*" for any + // domain or subdomain. Users should be warned about + // sites proposing to consume discount tokens of this + // type that are not in this list that the merchant + // is accepting a coupon from a competitor and thus + // may be attaching different semantics (like get 20% + // discount for my competitors 30% discount token). + expected_domains: string[]; + + }; + + +.. ts:def:: TokenAuthority + + interface TokenAuthority { + + // Human-readable description of the semantics of + // the tokens issued by this authority (for display). + summary: string; + + // Map from IETF BCP 47 language tags to localized summaries. + summary_i18n?: { [lang_tag: string]: string }; + + // Public key used to validate tokens issued + // by this token authority (merchant backend). + key: TokenSignerPublicKey; + + // When will tokens signed by this key expire? + token_expiration: Timestamp; + + // Number of tokens issued according to ASS authority + // FIXME: this is still rather speculative in the design... + ass?: Integer; + + // Signature affirming sum of token issuance deposit (?) fees + // collected by an exchange according to the ASS authority. + // FIXME: this is still rather speculative in the design... + ass_cost?: Amount; + + // Signature affirming the ass by the ASS authority. + // FIXME: this is still rather speculative in the design... + ass_sig?: EddsaSignature; + + }; + + +.. ts:def:: TokenSignerPublicKey + + type TokenSignerPublicKey = + | DenomGroupRsa + | DenomGroupCs; + +TODO: may want to do a deep copy and rename +DenomGroup* to TokenSignerPublicKey* here. + + +Alternative Contracts +--------------------- + +The contract terms object may contain any number of alternative contracts that +the user must choose between. The alternatives can differ by inputs, outputs +or other details. The wallet must filter the contracts by those that the user +can actually pay for, and move those that the user could currently not pay for +to the end of the rendered list. Similarly, the wallet must move up the +cheaper contracts, so if a contract has a definitively lower price and +consumes an available discount token, that contract should be moved up in the +list. + +Which specific alternative contract was chosen by the user is indicated in the +subcontract index field of the :ref:`TALER_DepositRequestPS`. + +FIXME-DOLD: Should we also sign over this in the +:ref:`TALER_DepositConfirmationPS`? + + +Output Commitments +------------------ + +When a contract has outputs, the wallet must send an array of blinded tokens, +coins or tax receipts together with the payment request. The order in the +array must match the order in the outputs field of the contract. For currency outputs, one array element must include all of the required planchets for a batch withdrawal, +but of course not the reserve signature. + + .. note:: + + We can probably spec this rather nicely if we first change the + batch-withdraw API to only use a single reserve signature. + +This array of blinded values is hashed to create the output commitment hash +(``h_outputs``) in the :ref:`TALER_DepositRequestPS`. + +FIXME-DOLD: Should we also sign over this in the +:ref:`TALER_DepositConfirmationPS`? + + + +Subscriptions +------------- + +The user buys a subscription (and possibly at the same time an article) using +currency and the contract yields an additional subscription token as an +output. Active subscriptions are listed below the currencies in the wallet +under a new heading. Subscriptions are never auto-renewing, if the user wants +to extend the subscription they can trivially pay for it with one click. + +When a contract consumes and yields exactly one subscription +token of the same type in a trusted domain, the wallet may automatically +approve the transaction without asking the user for confirmation (as it is free). + +The token expiration for a subscription can be past the "end date" to enable a +previous subscription to be used to get a discount on renewing the +subscription. The wallet should show applicable contracts with a lower price +that only additionally consume subscription tokens after their end date before +higher-priced alternative offers. + +Subscription tokens are "critical" in that a wallet implementation must +understand them before allowing a user to interact with this class of token. +Subscription token secrets should be derived from a master secret associated +with the subscription, so that the private keys are recoverable from backup. +To obtain the blind signatures, a merchant must offer an endpoint where +one can submit the public key of the N-1 subscription token and obtain the +blinded signature over the N-th subscription token. The wallet can then +effectively recover the subscription from backup using a binary search. + +The merchant SPA should allow the administrator to create (maybe update) and +delete subscriptions. Each subscription is identified by a subscription +label and includes a validity period. + +The merchant backend must then automatically manage (create, use, delete) the +respective signing keys. When creating an order, the frontend can just refer +to the subscription label (and possibly a start date) in the inputs or +outputs. The backend should then automatically substitute this with the +respective cryptographic fields for the respective time period and +subscription label. + + + + +Discounts +--------- + +To offer a discount based on one or more previous purchases, a merchant must +yield some discount-specific token as an output with the previous purchase, +and then offer an alternative contract with a lower price that consumes currency +and the discount token. The wallet should show contracts with a lower price that +only additionally consume discount tokens + +The merchant SPA should allow the administrator to create (maybe update) and +delete discount tokens. Each discount token is identified by a discount +label and includes an expiration time or validity duration. + +The merchant backend must then automatically manage (create, use, delete) the +respective signing keys. When creating an order, the frontend can just refer +to the discount token label in the inputs or outputs. The backend should then +automatically substitute this with the respective cryptographic fields for the +respective discount token. + + +Donation Authority +------------------ + +A donation authority (DONAU) implements a service that is expected to be run +by a government authority that determines eligibility for tax deduction. A +DONAU blindly signs tax receipts using a protocol very close to that of the +Taler exchange's withdraw protocol, except that the reserves are not filled +via wire transfers but instead represent accounts of the organizations +eligible to issue tax deduction receipts. These accounts are bascially +expected to have only negative balances, but the DONAU may have a +per-organization negative balance limit to cap tax deduction receipt +generation to a plausible account. DONAU administators are expected to be +able to add, update or remove these accounts using a SPA. Tax receipts +are blindly signed by keys that always have a usage period of one calendar +year. + +A stand-alone app for tax authorities can scan QR codes representing DONAU +signatures to validate that a given tax payer has donated a certain amount. +As RSA signatures are typically very large and a single donation may require +multiple blind signatures, CS blind signatures must also be supported. To +avoid encoding the public keys, QR codes with tax receipts should reference +the DONAU, the year and the amount, but not the specific public key. A +single donation may nevertheless be rendered using multiple QR codes. + +Revocations, refresh, deposits, age-restrictions and other exchange features +are not applicable for a DONAU. + +The merchant SPA should allow the administrator to manage DONAU accounts in +the merchant backend. Each DONAU account includes a base URL and a private +signing key for signing the requests to the DONAU on behalf of the eligible +organization. + +When creating an order, the frontend must specify a configured DONAU base URL +in the outputs. The backend should then automatically interact with the DONAU +when the wallet supplies the payment request with the blinded tax receipts. +The DONAU interaction must only happen after the exchange confirmed that the +contract was successfully paid. A partial error must be returned if the +exchange interaction was successful but the DONAU interaction failed. In this +case, the fulfillment action should still be triggered, but the wallet should +display a warning that the donation receipt could not be obtained. The wallet +should then re-try the payment (in the background with an exponential +back-off) to possibly obtain the tax receipt at a later time. + + +Tax Receipts +------------ + +Tax receipts differ from coins and tokens in that what is blindly signed over +should be the taxpayer identification number of the tax payer. The format of +the taxpayer identification number should simply be a string, with the rest +being defined by the national authority. The DONAU should indicate in its +``/config`` response what format this string should have, using possibly both +an Anastasis-style regex and an Anastasis-style function name (to check things +like checksums that cannot be validated using a regex). Wallets must then +validate the regex (if given) and if possible should implement the +Anastasis-style logic. + +Wallets should collect tax receipts by year and offer an +export functionality. The export should generate either + + (a) a JSON file, + (b) a PDF (with QR codes), or + (c) a series of screens with QR codes. + +Wallets may only implement some of the above options due to resource +constraints. + +The documents should encode the taxpayer ID, the amount and the DONAU +signature (including the year, excluding the exact public key as there should +only be one possible). + + +Rationing (future work) +----------------------- + +If per-capita rationing must be imposed on certain transactions, a rationing +authority (RA) must exist that identifies each eligible human and issues that +human a number of ration coins for the respective rationing period. An RA +largely functions like a regular exchange, except that eligible humans will +need to authenticate directly to withdraw rations (instead of transferring +fiat to an exchange). Merchants selling rationed goods will be (legally) +required to collect deposit confirmations in proportion to the amount of +rationed goods sold. A difference to regular exchanges is that RAs do not +charge any fees. RAs may or may not allow refreshing rations that are about +to expire for ration coins in the next period. + +Once an RA is added to a wallet, it should automatically try to withdraw the +maximum amount of ration coins it is eligible for. Available rations should be +shown below the subscriptions by RA (if any). + + ..note:: + + RAs are considered an idea for future work and not part of our current timeline. + + +Limited Donations per Capita (future work) +------------------------------------------ + +If per-capita limitations must be imposed on anonymous donations (for example +for donations to political parties), an RA can be used to issue donation +rations that limit the amount of donations that can be made for the respective +period. + + ..note:: + + RAs are considered an idea for future work and not part of our current timeline. + + + +Definition of Done +================== + + - Merchant backend support for multiple currencies + - Merchant backend support for consuming and issuing tokens + - Merchant SPA support for configuring new tokens of different types + - Wallet-core support for various new contract types + - Wallet-core filters for feasible contracts and possibly auto-executes subscriptions + - Wallet-GUIs (WebEx, Android, iOS) render new contract types + - Wallet-GUIs (WebEx, Android, iOS) allow user to select between multiple contracts + - Documentation for developers is up-to-date + - Token anonymity set size (ASS) authority implemented, documented + - Merchants report anonymity set size increases to ASS authority + - Wallets process anonymity set size reports from ASS authority + - Bachelor thesis written on applications and design + - Academic paper written on DONAU (requirements, design, implementation) + - DONAU implemented, documented + - DONAU receipt validation application implemented + - Integration tests exist in wallet-core + - Deliverables accepted by EC + + +Alternatives +============ + +None. + + +Drawbacks +========= + +Significant change, but actually good ratio compared to use-cases covered. + + +Discussion / Q&A +================ + +(This should be filled in with results from discussions on mailing lists / personal communication.) diff --git a/design-documents/047-stefan.rst b/design-documents/047-stefan.rst @@ -0,0 +1,172 @@ +DD 47: STEFAN +############# + +Summary +======= + +The Standardized Template for Effective-Fee Approximation Numbers (STEFAN) +is a feature to ensure customers see consistent fees for equivalent +purchases (largely) independent of the specific coins selected. It will also +make it easier for merchants to configure their systems to pay all reasonable +fees. + + +Motivation +========== + +Taler has a logarithmic fee structure for good reasons (to compete in +different market segments with reasonable profit margins). However, the +logarithmic fee structure inherently implies that the specific coin selection +made by the wallet can result in very different fees being applicable for the +same amount at the same merchant merely due to different coins being available +in the wallet. To minimize support costs, it is important that customers do +not need to be aware of the concept of coins and are instead shown consistent +fees for equivalent transactions. + + +Requirements +============ + + - keep the logarithmic nature of the fees (proportionally high fees + for tiny amounts, medium fees for medium amounts, low fees for large amounts) + - same purchase, same perceived price; prices are predictable for users + - enable merchants to easily cover all fees in most cases + + +Proposed Solution +================= + +The proposal is for the exchange to advertise three STEFAN-parameters that +encode a fee curve of the form ``stefan_abs + stefan_log * log P + +stefan_lin * P`` where P represents the gross price to be paid. +Here, the numerical value for P is to be computed by +dividing the actual gross price by the smallest denomination +offered by the exchange. + +.. note:: + + This calculation is already done using floating point (!) as we want the + STEFAN-curve to be smooth and not a step-function. This is also needed so + that we can invert the computation and calculate gross amounts from net + amounts and actually get a nice invertible computation where both + directions always match. Note that the computation itself is nevertheless + non-trivial involving Newton's method to solve ``f(x)=0`` using a + well-estimated starting point for the iteration to avoid divergence issues. + Finally, while we do the STEFAN-curve computations using doubles, we should + then convert the final amounts back into "human-friendly" numbers rounding + towards the nearest value that can be represented using the canonical + number of decimal places at the exchange. libtalerexchange (C) has a + reference implementation of the gross-net conversion functions (in both + directions) and of the final rounding logic. This exception to the general + rule of no floating-points for amounts is acceptable as it is not actually + done at the protocol level but only in internal computations of the wallet + and merchant backend as part of the STEFAN cost estimation logic, which by + definition is an estimate and does not need to be exact. (And even if + wallet and merchant backend were to (slightly) disagree about the + computations due to different floating point implementations, everything + would still be fine, and even a significant disagreement would not cause + anything but resurface the UI issue the STEFAN-curves addresses.) + +The fee curve will be the displayed fee, except in cases where the coin +selection is exceptionally bad (which should happen in substantially less than +1% of all cases). The fee curve will also be used as the maximum fee a +merchant will cover unless the merchant overrides the mechanism. + +In the most common case, where the STEFAN-curve fee is at or below what the +merchant covers, no fees are displayed, except in the exceptionally rare +case where the actual fees (due to unfortunate coin selection) are above +both the exchange's STEFAN-curve and the what the merchant covers. In this +last case the fees shown will be the actual fees minus what the merchant +covers and here the fees may vary even for equivalent transactions. + +In the uncommon case where a merchant does not cover any fees or only covers +parts of the fee according to the STEFAN-curve, the displayed fee will be the +value on the STEFAN-curve minus the amount covered by the merchant. If the +actual fees paid end up being below the approximation by the STEFAN-curve, the +delta is (by default) *hidden* from the balance of the user to simulate a +consistent fee. + +However, only the total available balance is marked down based on the +STEFAN-curve value. Thus, the wallet will contains coins with a potentially +higher balance value than what is shown to the user. This difference is +reconciled annually by adding a special transaction that increases the wallet +balance to eliminate the difference without any actual network interaction. +The entry in the transaction history that boosts the balance links to an +explanation. We may consider suggesting the user to donate the windfall. + +In developer mode, the user should probably be given the choice to see the +delta, to disable the feature, and/or to force the windfall transaction to +happen immediately. + + +Computing the curve +------------------- + +Typically, the ``stefan_abs`` value should represent a single wire transfer +fee. The ``stefan_log`` value should be computed to approximate the deposit +(and if applicable) refresh and withdraw fees for a coin, to be multiplied by +the number of coins. In a canonical setup, ``stefan_lin`` would be zero. +However, if an exchange is configured to use a linear fee structure, then +``stefan_lin`` would become applicable. + +The taler-wallet-cli should have an option to compute the STEFAN-values +given a denomination fee structure. This computation could probably be done +either analytically (if the fee structure is systematic) or by simulation. + +Modifications to the merchant +----------------------------- + +Instead of having (just) a "default fee", merchants should have an option to +use the STEFAN-curve when computing the fees they would be willing to cover. + +Modifications to the exchange +----------------------------- + +The STEFAN-curve can be configured using three simple configuration values +in the ``[exchange]`` section. The resulting values should be shared as +part of the ``/keys`` response, without digital signature. + +Modifications to the wallets +---------------------------- + +The STEFAN-curves will be useful as an easy approximate way to compare +exchange fee structures. However, wallets may not want to just trust an +exchange to honestly report STEFAN-curve values but could possibly use +a simulation to check that the given STEFAN-curve matches the actual fees. + +Wallets will need to keep the hidden STEFAN-balance and add the annual +internal reconcilliation transaction. + +Wallets will need to compute both the STEFAN-fee for display and still +do their own internal actual coin selection to minimize fees. + + + +Definition of Done +================== + + - exchange modified (DONE) + - merchant understands STEFAN curve in backend (DONE) + - merchant SPA has configuration option to enable use of STEFAN-curves + - wallet-core uses STEFAN-curves to compute display fees + - wallet-core supports annual reconcilliation transaction + - wallet GUIs use STEFAN-curves when comparing exchange fee structures + + +Alternatives +============ + +Refresh fees could additionally be waived if the refresh operation yields coins +of a lower denomination than the original coin. We should check if this allows +us to define tighter STEFAN-curves. + + +Drawbacks +========= + + + +Discussion / Q&A +================ + +(This should be filled in with results from discussions on mailing lists / personal communication.) diff --git a/design-documents/048-wallet-exchange-lifecycle.rst b/design-documents/048-wallet-exchange-lifecycle.rst @@ -0,0 +1,125 @@ +DD 48: Wallet Exchange Lifecycle and Management +############################################### + +Summary +======= + +This design document covers the lifecycle and management +of exchanges in the wallet. + +Motivation +========== + +The current wallet implementation lacks requests to manage exchanges. +It also always fetches the /keys info of all exchanges, because it doens't +distinguish between used and preset/added exchanges. + +Requirements +============ + +The following properties of of exchanges managed by the wallet +are important: + +* is the exchange used for something (coins, (account-)reserves, purses, ...) +* did the user (ever) accept the ToS? +* does the exchange have newer ToS available? +* is a current version of /keys (including former /wire) downloaded? +* were there errors downloading or checking the keys info? +* is the exchange permanently added or ephemeral? + + * ephemeral exchange records are created when the user + checks fees of an exchange but doesn't use it, + they would typically be hidden in the UI + + +Proposed Solution +================= + +Exchange Entry Status +--------------------- + +The wallet exposes three separate status fields for each exchange entry: + +* the entry status +* the update status +* the ToS status + + +Entry Status +~~~~~~~~~~~~ + +* ``preset``: Exchange record has been added to the exchange (typically as + a hardcoded preset in wallet-core). While the exchange can be selected for operations, + the wallet doesn't update the status yet, i.e. no /keys queries are done. +* ``ephemeral``: Exchange has been updated (or update has been attempted) at + least once (for example as part of checking the fees for a transaction using + the exchange). However, the exchange is not yet used for any resource in the wallet. + In this state, the exchange record will be garbage-collected eventually. +* ``used``: The exchange is known and used, the wallet regularly queries /keys. + +Transitions: + +* A transition from ``used`` to ``emphemeral`` is not possible, + since this would eventually remove preset exchanges and likely confuse + the user. + +Update Status +~~~~~~~~~~~~~ + +* ``initial``: Not updated, no need to update +* ``initial(update)``: Update pending, possibly with error +* ``suspended``: Exchange was manually disabled, should not be contacted + anymore, but record is kept in the wallet. Mostly useful for testing. +* ``failed``: Updating the exchange info failed permanently, the exchange is + not usable for any operations. +* ``outdated(update)`` +* ``ready``: Exchange is useable. +* ``ready(update)``: Exchange is useable, but currently being updated. + +ToS Status +~~~~~~~~~~ + +* ``pending``: The wallet is still trying to download the ToS. + Possibly the last download attempt failed, will be reflected in an + error details object. +* ``proposed``: The user needs to accept the current ToS. +* ``accepted``: The user has accepted the latest version of the ToS. + +Management Requests +------------------- + +* ``listExchanges``: List exchanges with their status info. +* ``addExchange``: Adds an exchange, entry status will be ``ephemeral`` + until the user actually uses the exchange. +* ``getExchangeResources``: List resources (number of coins, reserves, ...) associated + with the exchange. +* ``deleteExchange({exchangeUrl: string, purge: boolean})``: Removes an exchange. + Unless ``purge: true`` is specified, only an exchange without any associated + resources can be deleted. +* ``getExchangeTos({exchangeUrl: string, acceptLanguage?: string[], acceptFormat?: string[]}) => { language: string, mime: string, content: string, altLanguages: string[] }`` + +FIXME: Purging should probably delete *all* resources associated with the exchange. +But does it also remove the associated transactions? + +ToS Management +-------------- + +The wallet only stores the last accepted ToS ETag and the ETag last offered by +the exchange. The ToS contents are not stored by the wallet database (and thus +not included in backups). However, the wallet implementation may cache the +``/terms`` response on the level of the HTTP client. + +In future iterations, the UI might specify the prefered language and content type +for ``/terms``, so that the wallet can already download the full response (not just ``HEAD``). + + +Definition of Done +================== + +* states implemented in wallet-core +* exchange management specified on a UI level and implemented in UIs + +Discussion / Q&A +================ + +(This should be filled in with results from discussions on mailing lists / personal communication.) diff --git a/design-documents/049-auth.rst b/design-documents/049-auth.rst @@ -0,0 +1,177 @@ +DD 49: Authentication +##################### + +Summary +======= + +This design document specifies a simple authentication framework to be used by multiple Taler +components that require authentication. + +Motivation +========== + +SPAs currently store the username and password in locals storage (or at least +session storage). + +There's also no way to manage auth tokens third parties (e.g. +auditors). + +Requirements +============ + +* simple specification +* simple implementation +* simple to use +* must cover two main use cases: + + * SPA login + * delegating (possibly restricted) access to a third party using a token + +Proposed Solution +================= + +We define a ``token`` endpoint that can be used to obtain access tokens from +other forms of authentication, typically HTTP Basic auth. + + +.. _dd48-token: + +Token Endpoint +-------------- + +.. http:post:: /${RESOURCE...}/auth-token + + **Request Body** + + .. ts:def:: TokenRequest + + interface TokenRequest { + // Service-defined scope for the token. + // Typical scopes would be "readonly" or "readwrite". + scope: string; + + // Server may impose its own upper bound + // on the token validity duration + duration?: RelativeTime; + + // - "session": Token with short expiration. + // When one session token is revoked, + // other session tokens might be revoked + // as well. + // - "durable": Token with longer allowed expiration. + // Durable tokens are explicitly and individually revoked. + // Defaults to "session" when the server supports session tokens. + kind?: "session" | "durable"; + } + + **Response:** + + :http:statuscode:`200 Ok`: + The response is a `TokenSuccessResponse` + + **Details:** + + .. ts:def:: TokenSuccessResponse + + interface TokenSuccessResponse { + // Expiration determined by the server. + // Can be based on the token_duration + // from the request, but ultimately the + // server decides the expiration. + expiration: Timestamp; + + // Opque access token. + access_token: string; + + // Token kind. + kind: string; + } + +Token Revocation +------------------------------- + +Clients using session tokens log by forgetting the session token. + +.. http:post:: /${SERVICE}/auth-revoke-sessions + + Revoke all session tokens. + + **Authentication:** The client must authenticate + with a valid access token. + +.. http:post:: /${SERVICE}/auth-revoke-tokens + + Revoke all access tokens (durable and session tokens). + + **Authentication:** The client must authenticate + with a valid access token. + + +Implementation Considerations +----------------------------- + +Session Tokens +^^^^^^^^^^^^^^ + +Session access tokens should be implemented as "self-encoded tokens", i.e. +as tokens signed by the server without requiring server-side token storage. +Session access tokens should have a rather short maximum expiration. + +The signature should be over ``(username, kind, scope, creation_timestamp, expiry)``. + +To revoke session tokens, the server must store the timestamp of the last +revocation and only accept tokens with a ``creation_timestamp`` larger than the +last revocation timestamp. Individual session tokens cannot be revoked, only +all issued session tokens can be revoked at once. + +Session tokens *may* also be implemented as server-stored tokens instead. + +Durable Tokens +^^^^^^^^^^^^^^ + +Durable tokens should be stored in a server-side database. + + +Performance Considerations +-------------------------- + +For performance reasons, OAuth 2.0 uses two types of tokens: Short-lived access +tokens and long-lived refresh tokens. The access tokens can be implemented via +signatures and the long-lived refresh tokens via server-stored tokens. This +allows to cheaply validate access tokens, while still allowing longer expiration times +for refresh tokens. + +We could do something similar by introducing ``kind=login`` tokens. A login +token is a server-stored token. In addition to being used directly as an +access token, a login token can also be converted to a short-lived session +token. + + +Definition of Done +================== + +* spec reviewed +* implemented in merchant backend +* implemented in libeufin-bank +* implemented in the bank webui SPA +* implemented in the merchant backoffice SPA + + +Alternatives +============ + +* use something much closer to OAuth2 + + * would be unnecessarly generic and complex + +* only use durable tokens + +Drawbacks +========= + +* still more complex than simple auth tokens or HTTP basic auth + +Discussion / Q&A +================ + +(This should be filled in with results from discussions on mailing lists / personal communication.) diff --git a/design-documents/999-template.rst b/design-documents/999-template.rst @@ -1,5 +1,5 @@ -Template -######## +DD XY: Template +############### Summary ======= diff --git a/design-documents/index.rst b/design-documents/index.rst @@ -7,6 +7,7 @@ new features while keeping track of the evolution of the whole system and protocol. .. toctree:: + :maxdepth: 1 :glob: 001-new-browser-integration @@ -28,7 +29,7 @@ and protocol. 017-backoffice-inventory-management 018-contract-json 019-wallet-backup-merge - 020-backoffice-tips-management + 020-backoffice-rewards-management 021-exchange-key-continuity 022-wallet-auditor-reports 023-taler-kyc @@ -46,4 +47,16 @@ and protocol. 035-regional-currencies 036-currency-conversion-service 037-wallet-transactions-lifecycle.rst + 038-demobanks-protocol-suppliers.rst + 039-taler-browser-integration.rst + 040-distro-packaging.rst + 041-wallet-balance-amount-definitions.rst + 042-synthetic-wallet-errors.rst + 043-managing-prebuilt-artifacts.rst + 044-ci-system.rst + 045-kyc-inheritance.rst + 046-mumimo-contracts.rst + 047-stefan.rst + 048-wallet-exchange-lifecycle.rst + 049-auth.rst 999-template diff --git a/exchange-db.png b/exchange-db.png Binary files differ. diff --git a/extract-tsdefs/foo b/extract-tsdefs/foo @@ -0,0 +1,3562 @@ +# Wallet-Core API Documentation +This file is auto-generated from [wallet-core](https://git.taler.net/wallet-core.git/tree/packages/taler-wallet-core/src/wallet-api-types.ts). +## Overview +### Unknown Group +* [InitWalletOp](#initwalletop) +* [GetVersionOp](#getversionop) +### Basic Wallet Information +* [GetBalancesOp](#getbalancesop) +* [GetBalancesDetailOp](#getbalancesdetailop) +### Managing Transactions +* [GetTransactionsOp](#gettransactionsop) +* [GetTransactionByIdOp](#gettransactionbyidop) +* [RetryPendingNowOp](#retrypendingnowop) +* [DeleteTransactionOp](#deletetransactionop) +* [RetryTransactionOp](#retrytransactionop) +* [AbortTransactionOp](#aborttransactionop) +* [SuspendTransactionOp](#suspendtransactionop) +* [ResumeTransactionOp](#resumetransactionop) +### Withdrawals +* [GetWithdrawalDetailsForAmountOp](#getwithdrawaldetailsforamountop) +* [GetWithdrawalDetailsForUriOp](#getwithdrawaldetailsforuriop) +* [AcceptBankIntegratedWithdrawalOp](#acceptbankintegratedwithdrawalop) +* [AcceptManualWithdrawalOp](#acceptmanualwithdrawalop) +### Merchant Payments +* [PreparePayForUriOp](#preparepayforuriop) +* [PreparePayForTemplateOp](#preparepayfortemplateop) +* [GetContractTermsDetailsOp](#getcontracttermsdetailsop) +* [ConfirmPayOp](#confirmpayop) +* [ApplyRefundOp](#applyrefundop) +* [ApplyRefundFromPurchaseIdOp](#applyrefundfrompurchaseidop) +* [PrepareRefundOp](#preparerefundop) +### Tipping +* [PrepareTipOp](#preparetipop) +* [AcceptTipOp](#accepttipop) +### Exchange Management +* [ListExchangesOp](#listexchangesop) +* [AddExchangeOp](#addexchangeop) +* [ListKnownBankAccountsOp](#listknownbankaccountsop) +* [AddKnownBankAccountsOp](#addknownbankaccountsop) +* [ForgetKnownBankAccountsOp](#forgetknownbankaccountsop) +* [SetExchangeTosAcceptedOp](#setexchangetosacceptedop) +* [GetExchangeTosOp](#getexchangetosop) +* [GetExchangeDetailedInfoOp](#getexchangedetailedinfoop) +* [ListCurrenciesOp](#listcurrenciesop) +### Deposits +* [GenerateDepositGroupTxIdOp](#generatedepositgrouptxidop) +* [CreateDepositGroupOp](#createdepositgroupop) +* [PrepareDepositOp](#preparedepositop) +### Backups +* [ExportBackupRecoveryOp](#exportbackuprecoveryop) +* [ImportBackupRecoveryOp](#importbackuprecoveryop) +* [RunBackupCycleOp](#runbackupcycleop) +* [ExportBackupOp](#exportbackupop) +* [AddBackupProviderOp](#addbackupproviderop) +* [RemoveBackupProviderOp](#removebackupproviderop) +* [GetBackupInfoOp](#getbackupinfoop) +* [SetWalletDeviceIdOp](#setwalletdeviceidop) +* [ExportBackupPlainOp](#exportbackupplainop) +### Peer Payments +* [CheckPeerPushDebitOp](#checkpeerpushdebitop) +* [InitiatePeerPushDebitOp](#initiatepeerpushdebitop) +* [PreparePeerPushCreditOp](#preparepeerpushcreditop) +* [ConfirmPeerPushCreditOp](#confirmpeerpushcreditop) +* [CheckPeerPullCreditOp](#checkpeerpullcreditop) +* [InitiatePeerPullCreditOp](#initiatepeerpullcreditop) +* [PreparePeerPullDebitOp](#preparepeerpulldebitop) +* [ConfirmPeerPullDebitOp](#confirmpeerpulldebitop) +### Data Validation +* [ValidateIbanOp](#validateibanop) +### Database Management +* [ExportDbOp](#exportdbop) +* [ImportDbOp](#importdbop) +* [ClearDbOp](#cleardbop) +* [RecycleOp](#recycleop) +### Testing and Debugging +* [ApplyDevExperimentOp](#applydevexperimentop) +* [RunIntegrationTestOp](#runintegrationtestop) +* [RunIntegrationTestV2Op](#runintegrationtestv2op) +* [TestCryptoOp](#testcryptoop) +* [WithdrawTestBalanceOp](#withdrawtestbalanceop) +* [WithdrawTestkudosOp](#withdrawtestkudosop) +* [TestPayOp](#testpayop) +* [WithdrawFakebankOp](#withdrawfakebankop) +* [GetPendingTasksOp](#getpendingtasksop) +* [DumpCoinsOp](#dumpcoinsop) +* [SetCoinSuspendedOp](#setcoinsuspendedop) +* [ForceRefreshOp](#forcerefreshop) +## Operation Reference +### InitWalletOp +```typescript +/** + * Initialize wallet-core. + * + * Must be the request before any other operations. + */ +export type InitWalletOp = { + op: WalletApiOperation.InitWallet; + request: InitRequest; + response: InitResponse; +}; +// InitWallet = "initWallet" + +``` +```typescript +export interface InitRequest { + skipDefaults?: boolean; +} + +``` +```typescript +export interface InitResponse { + versionInfo: WalletCoreVersion; +} + +``` + +### GetVersionOp +```typescript +export type GetVersionOp = { + op: WalletApiOperation.GetVersion; + request: EmptyObject; + response: WalletCoreVersion; +}; +// GetVersion = "getVersion" + +``` + +### GetBalancesOp +```typescript +/** + * Get current wallet balance. + */ +export type GetBalancesOp = { + op: WalletApiOperation.GetBalances; + request: EmptyObject; + response: BalancesResponse; +}; +// GetBalances = "getBalances" + +``` +```typescript +export interface BalancesResponse { + balances: Balance[]; +} + +``` +```typescript +export interface Balance { + scopeInfo: ScopeInfo; + available: AmountString; + pendingIncoming: AmountString; + pendingOutgoing: AmountString; + hasPendingTransactions: boolean; + requiresUserInput: boolean; +} + +``` +```typescript +export type ScopeInfo = + | { + type: ScopeType.Global; + currency: string; + } + | { + type: ScopeType.Exchange; + currency: string; + url: string; + } + | { + type: ScopeType.Auditor; + currency: string; + url: string; + }; + +``` + +### GetBalancesDetailOp +```typescript +export type GetBalancesDetailOp = { + op: WalletApiOperation.GetBalanceDetail; + request: GetBalanceDetailRequest; + response: MerchantPaymentBalanceDetails; +}; +// GetBalanceDetail = "getBalanceDetail" + +``` +```typescript +export interface GetBalanceDetailRequest { + currency: string; +} + +``` +```typescript +export interface MerchantPaymentBalanceDetails { + /** + * Balance of type "available" (see balance.ts for definition). + */ + balanceAvailable: AmountJson; + /** + * Balance of type "material" (see balance.ts for definition). + */ + balanceMaterial: AmountJson; + /** + * Balance of type "age-acceptable" (see balance.ts for definition). + */ + balanceAgeAcceptable: AmountJson; + /** + * Balance of type "merchant-acceptable" (see balance.ts for definition). + */ + balanceMerchantAcceptable: AmountJson; + /** + * Balance of type "merchant-depositable" (see balance.ts for definition). + */ + balanceMerchantDepositable: AmountJson; +} + +``` +```typescript +/** + * Non-negative financial amount. Fractional values are expressed as multiples + * of 1e-8. + */ +export interface AmountJson { + /** + * Value, must be an integer. + */ + readonly value: number; + /** + * Fraction, must be an integer. Represent 1/1e8 of a unit. + */ + readonly fraction: number; + /** + * Currency of the amount. + */ + readonly currency: string; +} + +``` + +### GetTransactionsOp +```typescript +/** + * Get transactions. + */ +export type GetTransactionsOp = { + op: WalletApiOperation.GetTransactions; + request: TransactionsRequest; + response: TransactionsResponse; +}; +// GetTransactions = "getTransactions" + +``` +```typescript +export interface TransactionsRequest { + /** + * return only transactions in the given currency + */ + currency?: string; + /** + * if present, results will be limited to transactions related to the given search string + */ + search?: string; + /** + * If true, include all refreshes in the transactions list. + */ + includeRefreshes?: boolean; +} + +``` +```typescript +export interface TransactionsResponse { + transactions: Transaction[]; +} + +``` + +### GetTransactionByIdOp +```typescript +export type GetTransactionByIdOp = { + op: WalletApiOperation.GetTransactionById; + request: TransactionByIdRequest; + response: Transaction; +}; +// GetTransactionById = "getTransactionById" + +``` +```typescript +export interface TransactionByIdRequest { + transactionId: string; +} + +``` + +### RetryPendingNowOp +```typescript +export type RetryPendingNowOp = { + op: WalletApiOperation.RetryPendingNow; + request: EmptyObject; + response: EmptyObject; +}; +// RetryPendingNow = "retryPendingNow" + +``` + +### DeleteTransactionOp +```typescript +/** + * Delete a transaction locally in the wallet. + */ +export type DeleteTransactionOp = { + op: WalletApiOperation.DeleteTransaction; + request: DeleteTransactionRequest; + response: EmptyObject; +}; +// DeleteTransaction = "deleteTransaction" + +``` +```typescript +export interface DeleteTransactionRequest { + transactionId: string; +} + +``` + +### RetryTransactionOp +```typescript +/** + * Immediately retry a transaction. + */ +export type RetryTransactionOp = { + op: WalletApiOperation.RetryTransaction; + request: RetryTransactionRequest; + response: EmptyObject; +}; +// RetryTransaction = "retryTransaction" + +``` +```typescript +export interface RetryTransactionRequest { + transactionId: string; +} + +``` + +### AbortTransactionOp +```typescript +/** + * Abort a transaction + * + * For payment transactions, it puts the payment into an "aborting" state. + */ +export type AbortTransactionOp = { + op: WalletApiOperation.AbortTransaction; + request: AbortTransactionRequest; + response: EmptyObject; +}; +// AbortTransaction = "abortTransaction" + +``` + +### SuspendTransactionOp +```typescript +/** + * Suspend a transaction + */ +export type SuspendTransactionOp = { + op: WalletApiOperation.SuspendTransaction; + request: AbortTransactionRequest; + response: EmptyObject; +}; +// SuspendTransaction = "suspendTransaction" + +``` + +### ResumeTransactionOp +```typescript +/** + * Resume a transaction + */ +export type ResumeTransactionOp = { + op: WalletApiOperation.ResumeTransaction; + request: AbortTransactionRequest; + response: EmptyObject; +}; +// ResumeTransaction = "resumeTransaction" + +``` + +### GetWithdrawalDetailsForAmountOp +```typescript +/** + * Get details for withdrawing a particular amount (manual withdrawal). + */ +export type GetWithdrawalDetailsForAmountOp = { + op: WalletApiOperation.GetWithdrawalDetailsForAmount; + request: GetWithdrawalDetailsForAmountRequest; + response: ManualWithdrawalDetails; +}; +// GetWithdrawalDetailsForAmount = "getWithdrawalDetailsForAmount" + +``` +```typescript +export interface GetWithdrawalDetailsForAmountRequest { + exchangeBaseUrl: string; + amount: string; + restrictAge?: number; +} + +``` +```typescript +export interface ManualWithdrawalDetails { + /** + * Did the user accept the current version of the exchange's + * terms of service? + */ + tosAccepted: boolean; + /** + * Amount that the user will transfer to the exchange. + */ + amountRaw: AmountString; + /** + * Amount that will be added to the user's wallet balance. + */ + amountEffective: AmountString; + /** + * Ways to pay the exchange. + */ + paytoUris: string[]; + /** + * If the exchange supports age-restricted coins it will return + * the array of ages. + */ + ageRestrictionOptions?: number[]; +} + +``` + +### GetWithdrawalDetailsForUriOp +```typescript +/** + * Get details for withdrawing via a particular taler:// URI. + */ +export type GetWithdrawalDetailsForUriOp = { + op: WalletApiOperation.GetWithdrawalDetailsForUri; + request: GetWithdrawalDetailsForUriRequest; + response: WithdrawUriInfoResponse; +}; +// GetWithdrawalDetailsForUri = "getWithdrawalDetailsForUri" + +``` +```typescript +export interface GetWithdrawalDetailsForUriRequest { + talerWithdrawUri: string; + restrictAge?: number; +} + +``` +```typescript +export interface WithdrawUriInfoResponse { + amount: AmountString; + defaultExchangeBaseUrl?: string; + possibleExchanges: ExchangeListItem[]; +} + +``` + +### AcceptBankIntegratedWithdrawalOp +```typescript +/** + * Accept a bank-integrated withdrawal. + */ +export type AcceptBankIntegratedWithdrawalOp = { + op: WalletApiOperation.AcceptBankIntegratedWithdrawal; + request: AcceptBankIntegratedWithdrawalRequest; + response: AcceptWithdrawalResponse; +}; +// AcceptBankIntegratedWithdrawal = "acceptBankIntegratedWithdrawal" + +``` +```typescript +export interface AcceptBankIntegratedWithdrawalRequest { + talerWithdrawUri: string; + exchangeBaseUrl: string; + forcedDenomSel?: ForcedDenomSel; + restrictAge?: number; +} + +``` +```typescript +export interface AcceptWithdrawalResponse { + reservePub: string; + confirmTransferUrl?: string; + transactionId: string; +} + +``` + +### AcceptManualWithdrawalOp +```typescript +/** + * Create a manual withdrawal. + */ +export type AcceptManualWithdrawalOp = { + op: WalletApiOperation.AcceptManualWithdrawal; + request: AcceptManualWithdrawalRequest; + response: AcceptManualWithdrawalResult; +}; +// AcceptManualWithdrawal = "acceptManualWithdrawal" + +``` +```typescript +export interface AcceptManualWithdrawalRequest { + exchangeBaseUrl: string; + amount: string; + restrictAge?: number; +} + +``` +```typescript +export interface AcceptManualWithdrawalResult { + /** + * Payto URIs that can be used to fund the withdrawal. + */ + exchangePaytoUris: string[]; + /** + * Public key of the newly created reserve. + */ + reservePub: string; + transactionId: string; +} + +``` + +### PreparePayForUriOp +```typescript +/** + * Prepare to make a payment based on a taler://pay/ URI. + */ +export type PreparePayForUriOp = { + op: WalletApiOperation.PreparePayForUri; + request: PreparePayRequest; + response: PreparePayResult; +}; +// PreparePayForUri = "preparePayForUri" + +``` +```typescript +export interface PreparePayRequest { + talerPayUri: string; +} + +``` + +### PreparePayForTemplateOp +```typescript +/** + * Prepare to make a payment based on a taler://pay-template/ URI. + */ +export type PreparePayForTemplateOp = { + op: WalletApiOperation.PreparePayForTemplate; + request: PreparePayTemplateRequest; + response: PreparePayResult; +}; +// PreparePayForTemplate = "preparePayForTemplate" + +``` +```typescript +export interface PreparePayTemplateRequest { + talerPayTemplateUri: string; + templateParams: Record<string, string>; +} + +``` + +### GetContractTermsDetailsOp +```typescript +export type GetContractTermsDetailsOp = { + op: WalletApiOperation.GetContractTermsDetails; + request: GetContractTermsDetailsRequest; + response: WalletContractData; +}; +// GetContractTermsDetails = "getContractTermsDetails" + +``` +```typescript +export interface GetContractTermsDetailsRequest { + proposalId: string; +} + +``` +```typescript +/** + * Data extracted from the contract terms that is relevant for payment + * processing in the wallet. + */ +export interface WalletContractData { + products?: Product[]; + summaryI18n: + | { + [lang_tag: string]: string; + } + | undefined; + /** + * Fulfillment URL, or the empty string if the order has no fulfillment URL. + * + * Stored as a non-nullable string as we use this field for IndexedDB indexing. + */ + fulfillmentUrl: string; + contractTermsHash: string; + fulfillmentMessage?: string; + fulfillmentMessageI18n?: InternationalizedString; + merchantSig: string; + merchantPub: string; + merchant: MerchantInfo; + amount: AmountString; + orderId: string; + merchantBaseUrl: string; + summary: string; + autoRefund: TalerProtocolDuration | undefined; + maxWireFee: AmountString; + wireFeeAmortization: number; + payDeadline: TalerProtocolTimestamp; + refundDeadline: TalerProtocolTimestamp; + allowedAuditors: AllowedAuditorInfo[]; + allowedExchanges: AllowedExchangeInfo[]; + timestamp: TalerProtocolTimestamp; + wireMethod: string; + wireInfoHash: string; + maxDepositFee: AmountString; + minimumAge?: number; + deliveryDate: TalerProtocolTimestamp | undefined; + deliveryLocation: Location | undefined; +} + +``` +```typescript +export interface AllowedAuditorInfo { + auditorBaseUrl: string; + auditorPub: string; +} + +``` +```typescript +export interface AllowedExchangeInfo { + exchangeBaseUrl: string; + exchangePub: string; +} + +``` + +### ConfirmPayOp +```typescript +/** + * Confirm a payment that was previously prepared with + * {@link PreparePayForUriOp} + */ +export type ConfirmPayOp = { + op: WalletApiOperation.ConfirmPay; + request: ConfirmPayRequest; + response: ConfirmPayResult; +}; +// ConfirmPay = "confirmPay" + +``` +```typescript +export interface ConfirmPayRequest { + proposalId: string; + sessionId?: string; + forcedCoinSel?: ForcedCoinSel; +} + +``` +```typescript +export type ConfirmPayResult = ConfirmPayResultDone | ConfirmPayResultPending; + +``` +```typescript +/** + * Result for confirmPay + */ +export interface ConfirmPayResultDone { + type: ConfirmPayResultType.Done; + contractTerms: MerchantContractTerms; + transactionId: string; +} + +``` +```typescript +export interface ConfirmPayResultPending { + type: ConfirmPayResultType.Pending; + transactionId: string; + lastError: TalerErrorDetail | undefined; +} + +``` + +### ApplyRefundOp +```typescript +/** + * Check for a refund based on a taler://refund URI. + */ +export type ApplyRefundOp = { + op: WalletApiOperation.ApplyRefund; + request: ApplyRefundRequest; + response: ApplyRefundResponse; +}; +// ApplyRefund = "applyRefund" + +``` +```typescript +export interface ApplyRefundRequest { + talerRefundUri: string; +} + +``` + +### ApplyRefundFromPurchaseIdOp +```typescript +export type ApplyRefundFromPurchaseIdOp = { + op: WalletApiOperation.ApplyRefundFromPurchaseId; + request: ApplyRefundFromPurchaseIdRequest; + response: ApplyRefundResponse; +}; +// ApplyRefundFromPurchaseId = "applyRefundFromPurchaseId" + +``` +```typescript +export interface ApplyRefundFromPurchaseIdRequest { + purchaseId: string; +} + +``` + +### PrepareRefundOp +```typescript +export type PrepareRefundOp = { + op: WalletApiOperation.PrepareRefund; + request: PrepareRefundRequest; + response: PrepareRefundResult; +}; +// PrepareRefund = "prepareRefund" + +``` +```typescript +export interface PrepareRefundRequest { + talerRefundUri: string; +} + +``` +```typescript +export interface PrepareRefundResult { + proposalId: string; + effectivePaid: AmountString; + gone: AmountString; + granted: AmountString; + pending: boolean; + awaiting: AmountString; + info: OrderShortInfo; +} + +``` + +### PrepareTipOp +```typescript +/** + * Query and store information about a tip. + */ +export type PrepareTipOp = { + op: WalletApiOperation.PrepareTip; + request: PrepareTipRequest; + response: PrepareTipResult; +}; +// PrepareTip = "prepareTip" + +``` +```typescript +export interface PrepareTipRequest { + talerTipUri: string; +} + +``` +```typescript +export interface PrepareTipResult { + /** + * Unique ID for the tip assigned by the wallet. + * Typically different from the merchant-generated tip ID. + */ + walletTipId: string; + /** + * Has the tip already been accepted? + */ + accepted: boolean; + /** + * Amount that the merchant gave. + */ + tipAmountRaw: AmountString; + /** + * Amount that arrived at the wallet. + * Might be lower than the raw amount due to fees. + */ + tipAmountEffective: AmountString; + /** + * Base URL of the merchant backend giving then tip. + */ + merchantBaseUrl: string; + /** + * Base URL of the exchange that is used to withdraw the tip. + * Determined by the merchant, the wallet/user has no choice here. + */ + exchangeBaseUrl: string; + /** + * Time when the tip will expire. After it expired, it can't be picked + * up anymore. + */ + expirationTimestamp: TalerProtocolTimestamp; +} + +``` + +### AcceptTipOp +```typescript +/** + * Accept a tip. + */ +export type AcceptTipOp = { + op: WalletApiOperation.AcceptTip; + request: AcceptTipRequest; + response: AcceptTipResponse; +}; +// AcceptTip = "acceptTip" + +``` +```typescript +export interface AcceptTipRequest { + walletTipId: string; +} + +``` +```typescript +export interface AcceptTipResponse { + transactionId: string; + next_url?: string; +} + +``` + +### ListExchangesOp +```typescript +/** + * List exchanges known to the wallet. + */ +export type ListExchangesOp = { + op: WalletApiOperation.ListExchanges; + request: EmptyObject; + response: ExchangesListResponse; +}; +// ListExchanges = "listExchanges" + +``` +```typescript +export interface ExchangesListResponse { + exchanges: ExchangeListItem[]; +} + +``` + +### AddExchangeOp +```typescript +/** + * Add / force-update an exchange. + */ +export type AddExchangeOp = { + op: WalletApiOperation.AddExchange; + request: AddExchangeRequest; + response: EmptyObject; +}; +// AddExchange = "addExchange" + +``` + +### ListKnownBankAccountsOp +```typescript +export type ListKnownBankAccountsOp = { + op: WalletApiOperation.ListKnownBankAccounts; + request: ListKnownBankAccountsRequest; + response: KnownBankAccounts; +}; +// ListKnownBankAccounts = "listKnownBankAccounts" + +``` +```typescript +export interface ListKnownBankAccountsRequest { + currency?: string; +} + +``` +```typescript +export interface KnownBankAccounts { + accounts: KnownBankAccountsInfo[]; +} + +``` +```typescript +export interface KnownBankAccountsInfo { + uri: PaytoUri; + kyc_completed: boolean; + currency: string; + alias: string; +} + +``` +```typescript +export type PaytoUri = + | PaytoUriUnknown + | PaytoUriIBAN + | PaytoUriTalerBank + | PaytoUriBitcoin; + +``` +```typescript +export interface PaytoUriUnknown extends PaytoUriGeneric { + isKnown: false; +} + +``` +```typescript +export interface PaytoUriGeneric { + targetType: string; + targetPath: string; + params: { + [name: string]: string; + }; +} + +``` +```typescript +export interface PaytoUriIBAN extends PaytoUriGeneric { + isKnown: true; + targetType: "iban"; + iban: string; + bic?: string; +} + +``` +```typescript +export interface PaytoUriTalerBank extends PaytoUriGeneric { + isKnown: true; + targetType: "x-taler-bank"; + host: string; + account: string; +} + +``` +```typescript +export interface PaytoUriBitcoin extends PaytoUriGeneric { + isKnown: true; + targetType: "bitcoin"; + segwitAddrs: Array<string>; +} + +``` + +### AddKnownBankAccountsOp +```typescript +export type AddKnownBankAccountsOp = { + op: WalletApiOperation.AddKnownBankAccounts; + request: AddKnownBankAccountsRequest; + response: EmptyObject; +}; +// AddKnownBankAccounts = "addKnownBankAccounts" + +``` +```typescript +export interface AddKnownBankAccountsRequest { + payto: string; + alias: string; + currency: string; +} + +``` + +### ForgetKnownBankAccountsOp +```typescript +export type ForgetKnownBankAccountsOp = { + op: WalletApiOperation.ForgetKnownBankAccounts; + request: ForgetKnownBankAccountsRequest; + response: EmptyObject; +}; +// ForgetKnownBankAccounts = "forgetKnownBankAccounts" + +``` +```typescript +export interface ForgetKnownBankAccountsRequest { + payto: string; +} + +``` + +### SetExchangeTosAcceptedOp +```typescript +/** + * Accept a particular version of the exchange terms of service. + */ +export type SetExchangeTosAcceptedOp = { + op: WalletApiOperation.SetExchangeTosAccepted; + request: AcceptExchangeTosRequest; + response: EmptyObject; +}; +// SetExchangeTosAccepted = "setExchangeTosAccepted" + +``` +```typescript +export interface AcceptExchangeTosRequest { + exchangeBaseUrl: string; + etag: string | undefined; +} + +``` + +### GetExchangeTosOp +```typescript +/** + * Get the current terms of a service of an exchange. + */ +export type GetExchangeTosOp = { + op: WalletApiOperation.GetExchangeTos; + request: GetExchangeTosRequest; + response: GetExchangeTosResult; +}; +// GetExchangeTos = "getExchangeTos" + +``` +```typescript +export interface GetExchangeTosRequest { + exchangeBaseUrl: string; + acceptedFormat?: string[]; +} + +``` +```typescript +export interface GetExchangeTosResult { + /** + * Markdown version of the current ToS. + */ + content: string; + /** + * Version tag of the current ToS. + */ + currentEtag: string; + /** + * Version tag of the last ToS that the user has accepted, + * if any. + */ + acceptedEtag: string | undefined; + /** + * Accepted content type + */ + contentType: string; + tosStatus: ExchangeTosStatus; +} + +``` + +### GetExchangeDetailedInfoOp +```typescript +/** + * Get the current terms of a service of an exchange. + */ +export type GetExchangeDetailedInfoOp = { + op: WalletApiOperation.GetExchangeDetailedInfo; + request: AddExchangeRequest; + response: ExchangeDetailedResponse; +}; +// GetExchangeDetailedInfo = "getExchangeDetailedInfo" + +``` +```typescript +export interface ExchangeDetailedResponse { + exchange: ExchangeFullDetails; +} + +``` +```typescript +export interface ExchangeFullDetails { + exchangeBaseUrl: string; + currency: string; + paytoUris: string[]; + tos: ExchangeTosStatusDetails; + auditors: ExchangeAuditor[]; + wireInfo: WireInfo; + denomFees: DenomOperationMap<FeeDescription[]>; + transferFees: Record<string, FeeDescription[]>; + globalFees: FeeDescription[]; +} + +``` +```typescript +export interface ExchangeTosStatusDetails { + acceptedVersion?: string; + currentVersion?: string; + contentType?: string; + content?: string; +} + +``` +```typescript +export interface WireInfo { + feesForType: WireFeeMap; + accounts: ExchangeAccount[]; +} + +``` +```typescript +/** + * Information about one of the exchange's bank accounts. + */ +export interface ExchangeAccount { + payto_uri: string; + master_sig: string; +} + +``` +```typescript +export interface FeeDescription { + group: string; + from: AbsoluteTime; + until: AbsoluteTime; + fee?: AmountString; +} + +``` + +### ListCurrenciesOp +```typescript +/** + * List currencies known to the wallet. + */ +export type ListCurrenciesOp = { + op: WalletApiOperation.ListCurrencies; + request: EmptyObject; + response: WalletCurrencyInfo; +}; +// ListCurrencies = "listCurrencies" + +``` +```typescript +export interface WalletCurrencyInfo { + trustedAuditors: { + currency: string; + auditorPub: string; + auditorBaseUrl: string; + }[]; + trustedExchanges: { + currency: string; + exchangeMasterPub: string; + exchangeBaseUrl: string; + }[]; +} + +``` + +### GenerateDepositGroupTxIdOp +```typescript +/** + * Generate a fresh transaction ID for a deposit group. + * + * The resulting transaction ID can be specified when creating + * a deposit group, so that the client can already start waiting for notifications + * on that specific deposit group before the GreateDepositGroup request returns. + */ +export type GenerateDepositGroupTxIdOp = { + op: WalletApiOperation.GenerateDepositGroupTxId; + request: EmptyObject; + response: TxIdResponse; +}; +// GenerateDepositGroupTxId = "generateDepositGroupTxId" + +``` +```typescript +export interface TxIdResponse { + transactionId: string; +} + +``` + +### CreateDepositGroupOp +```typescript +/** + * Create a new deposit group. + * + * Deposit groups are used to deposit multiple coins to a bank + * account, usually the wallet user's own bank account. + */ +export type CreateDepositGroupOp = { + op: WalletApiOperation.CreateDepositGroup; + request: CreateDepositGroupRequest; + response: CreateDepositGroupResponse; +}; +// CreateDepositGroup = "createDepositGroup" + +``` +```typescript +export interface CreateDepositGroupRequest { + /** + * Pre-allocated transaction ID. + * Allows clients to easily handle notifications + * that occur while the operation has been created but + * before the creation request has returned. + */ + transactionId?: string; + depositPaytoUri: string; + amount: AmountString; +} + +``` +```typescript +export interface CreateDepositGroupResponse { + depositGroupId: string; + transactionId: string; +} + +``` + +### PrepareDepositOp +```typescript +export type PrepareDepositOp = { + op: WalletApiOperation.PrepareDeposit; + request: PrepareDepositRequest; + response: PrepareDepositResponse; +}; +// PrepareDeposit = "prepareDeposit" + +``` +```typescript +export interface PrepareDepositRequest { + depositPaytoUri: string; + amount: AmountString; +} + +``` +```typescript +export interface PrepareDepositResponse { + totalDepositCost: AmountString; + effectiveDepositAmount: AmountString; + fees: DepositGroupFees; +} + +``` +```typescript +export interface DepositGroupFees { + coin: AmountString; + wire: AmountString; + refresh: AmountString; +} + +``` + +### ExportBackupRecoveryOp +```typescript +/** + * Export the recovery information for the wallet. + */ +export type ExportBackupRecoveryOp = { + op: WalletApiOperation.ExportBackupRecovery; + request: EmptyObject; + response: BackupRecovery; +}; +// ExportBackupRecovery = "exportBackupRecovery" + +``` + +### ImportBackupRecoveryOp +```typescript +/** + * Import recovery information into the wallet. + */ +export type ImportBackupRecoveryOp = { + op: WalletApiOperation.ImportBackupRecovery; + request: RecoveryLoadRequest; + response: EmptyObject; +}; +// ImportBackupRecovery = "importBackupRecovery" + +``` +```typescript +/** + * Load recovery information into the wallet. + */ +export interface RecoveryLoadRequest { + recovery: BackupRecovery; + strategy?: RecoveryMergeStrategy; +} + +``` +```typescript +/** + * Strategy for loading recovery information. + */ +export declare enum RecoveryMergeStrategy { + /** + * Keep the local wallet root key, import and take over providers. + */ + Ours = "ours", + /** + * Migrate to the wallet root key from the recovery information. + */ + Theirs = "theirs", +} + +``` + +### RunBackupCycleOp +```typescript +/** + * Manually make and upload a backup. + */ +export type RunBackupCycleOp = { + op: WalletApiOperation.RunBackupCycle; + request: RunBackupCycleRequest; + response: EmptyObject; +}; +// RunBackupCycle = "runBackupCycle" + +``` +```typescript +export interface RunBackupCycleRequest { + /** + * List of providers to backup or empty for all known providers. + */ + providers?: Array<string>; +} + +``` + +### ExportBackupOp +```typescript +export type ExportBackupOp = { + op: WalletApiOperation.ExportBackup; + request: EmptyObject; + response: EmptyObject; +}; +// ExportBackup = "exportBackup" + +``` + +### AddBackupProviderOp +```typescript +/** + * Add a new backup provider. + */ +export type AddBackupProviderOp = { + op: WalletApiOperation.AddBackupProvider; + request: AddBackupProviderRequest; + response: AddBackupProviderResponse; +}; +// AddBackupProvider = "addBackupProvider" + +``` +```typescript +export interface AddBackupProviderRequest { + backupProviderBaseUrl: string; + name: string; + /** + * Activate the provider. Should only be done after + * the user has reviewed the provider. + */ + activate?: boolean; +} + +``` +```typescript +export type AddBackupProviderResponse = + | AddBackupProviderOk + | AddBackupProviderPaymentRequired; + +``` +```typescript +interface AddBackupProviderOk { + status: "ok"; +} + +``` +```typescript +interface AddBackupProviderPaymentRequired { + status: "payment-required"; + talerUri?: string; +} + +``` + +### RemoveBackupProviderOp +```typescript +export type RemoveBackupProviderOp = { + op: WalletApiOperation.RemoveBackupProvider; + request: RemoveBackupProviderRequest; + response: EmptyObject; +}; +// RemoveBackupProvider = "removeBackupProvider" + +``` +```typescript +export interface RemoveBackupProviderRequest { + provider: string; +} + +``` + +### GetBackupInfoOp +```typescript +/** + * Get some useful stats about the backup state. + */ +export type GetBackupInfoOp = { + op: WalletApiOperation.GetBackupInfo; + request: EmptyObject; + response: BackupInfo; +}; +// GetBackupInfo = "getBackupInfo" + +``` +```typescript +export interface BackupInfo { + walletRootPub: string; + deviceId: string; + providers: ProviderInfo[]; +} + +``` +```typescript +/** + * Information about one provider. + * + * We don't store the account key here, + * as that's derived from the wallet root key. + */ +export interface ProviderInfo { + active: boolean; + syncProviderBaseUrl: string; + name: string; + terms?: BackupProviderTerms; + /** + * Last communication issue with the provider. + */ + lastError?: TalerErrorDetail; + lastSuccessfulBackupTimestamp?: TalerProtocolTimestamp; + lastAttemptedBackupTimestamp?: TalerProtocolTimestamp; + paymentProposalIds: string[]; + backupProblem?: BackupProblem; + paymentStatus: ProviderPaymentStatus; +} + +``` +```typescript +export interface BackupProviderTerms { + supportedProtocolVersion: string; + annualFee: AmountString; + storageLimitInMegabytes: number; +} + +``` +```typescript +export type BackupProblem = + | BackupUnreadableProblem + | BackupConflictingDeviceProblem; + +``` +```typescript +export interface BackupUnreadableProblem { + type: "backup-unreadable"; +} + +``` +```typescript +export interface BackupConflictingDeviceProblem { + type: "backup-conflicting-device"; + otherDeviceId: string; + myDeviceId: string; + backupTimestamp: AbsoluteTime; +} + +``` +```typescript +export type ProviderPaymentStatus = + | ProviderPaymentTermsChanged + | ProviderPaymentPaid + | ProviderPaymentInsufficientBalance + | ProviderPaymentUnpaid + | ProviderPaymentPending; + +``` +```typescript +export interface ProviderPaymentTermsChanged { + type: ProviderPaymentType.TermsChanged; + paidUntil: AbsoluteTime; + oldTerms: BackupProviderTerms; + newTerms: BackupProviderTerms; +} + +``` +```typescript +export interface ProviderPaymentPaid { + type: ProviderPaymentType.Paid; + paidUntil: AbsoluteTime; +} + +``` +```typescript +export interface ProviderPaymentInsufficientBalance { + type: ProviderPaymentType.InsufficientBalance; + amount: AmountString; +} + +``` +```typescript +export interface ProviderPaymentUnpaid { + type: ProviderPaymentType.Unpaid; +} + +``` +```typescript +export interface ProviderPaymentPending { + type: ProviderPaymentType.Pending; + talerUri?: string; +} + +``` + +### SetWalletDeviceIdOp +```typescript +/** + * Set the internal device ID of the wallet, used to + * identify whether a different/new wallet is accessing + * the backup of another wallet. + */ +export type SetWalletDeviceIdOp = { + op: WalletApiOperation.SetWalletDeviceId; + request: SetWalletDeviceIdRequest; + response: EmptyObject; +}; +// SetWalletDeviceId = "setWalletDeviceId" + +``` +```typescript +export interface SetWalletDeviceIdRequest { + /** + * New wallet device ID to set. + */ + walletDeviceId: string; +} + +``` + +### ExportBackupPlainOp +```typescript +/** + * Export a backup JSON, mostly useful for testing. + */ +export type ExportBackupPlainOp = { + op: WalletApiOperation.ExportBackupPlain; + request: EmptyObject; + response: WalletBackupContentV1; +}; +// ExportBackupPlain = "exportBackupPlain" + +``` + +### CheckPeerPushDebitOp +```typescript +/** + * Check if initiating a peer push payment is possible + * based on the funds in the wallet. + */ +export type CheckPeerPushDebitOp = { + op: WalletApiOperation.CheckPeerPushDebit; + request: CheckPeerPushDebitRequest; + response: CheckPeerPushDebitResponse; +}; +// CheckPeerPushDebit = "checkPeerPushDebit" + +``` +```typescript +export interface CheckPeerPushDebitRequest { + /** + * Preferred exchange to use for the p2p payment. + */ + exchangeBaseUrl?: string; + /** + * Instructed amount. + * + * FIXME: Allow specifying the instructed amount type. + */ + amount: AmountString; +} + +``` +```typescript +export interface CheckPeerPushDebitResponse { + amountRaw: AmountString; + amountEffective: AmountString; +} + +``` + +### InitiatePeerPushDebitOp +```typescript +/** + * Initiate an outgoing peer push payment. + */ +export type InitiatePeerPushDebitOp = { + op: WalletApiOperation.InitiatePeerPushDebit; + request: InitiatePeerPushPaymentRequest; + response: InitiatePeerPushPaymentResponse; +}; +// InitiatePeerPushDebit = "initiatePeerPushDebit" + +``` +```typescript +export interface InitiatePeerPushPaymentRequest { + exchangeBaseUrl?: string; + partialContractTerms: PeerContractTerms; +} + +``` +```typescript +export interface InitiatePeerPushPaymentResponse { + exchangeBaseUrl: string; + pursePub: string; + mergePriv: string; + contractPriv: string; + talerUri: string; + transactionId: string; +} + +``` + +### PreparePeerPushCreditOp +```typescript +/** + * Check an incoming peer push payment. + */ +export type PreparePeerPushCreditOp = { + op: WalletApiOperation.PreparePeerPushCredit; + request: PreparePeerPushCredit; + response: PreparePeerPushCreditResponse; +}; +// PreparePeerPushCredit = "preparePeerPushCredit" + +``` +```typescript +export interface PreparePeerPushCreditResponse { + contractTerms: PeerContractTerms; + /** + * @deprecated + */ + amount: AmountString; + amountRaw: AmountString; + amountEffective: AmountString; + peerPushPaymentIncomingId: string; +} + +``` + +### ConfirmPeerPushCreditOp +```typescript +/** + * Accept an incoming peer push payment. + */ +export type ConfirmPeerPushCreditOp = { + op: WalletApiOperation.ConfirmPeerPushCredit; + request: ConfirmPeerPushCreditRequest; + response: EmptyObject; +}; +// ConfirmPeerPushCredit = "confirmPeerPushCredit" + +``` +```typescript +export interface ConfirmPeerPushCreditRequest { + /** + * Transparent identifier of the incoming peer push payment. + */ + peerPushPaymentIncomingId: string; +} + +``` + +### CheckPeerPullCreditOp +```typescript +/** + * Check fees for an outgoing peer pull payment. + */ +export type CheckPeerPullCreditOp = { + op: WalletApiOperation.CheckPeerPullCredit; + request: CheckPeerPullCreditRequest; + response: CheckPeerPullCreditResponse; +}; +// CheckPeerPullCredit = "checkPeerPullCredit" + +``` +```typescript +export interface CheckPeerPullCreditRequest { + exchangeBaseUrl?: string; + amount: AmountString; +} + +``` +```typescript +export interface CheckPeerPullCreditResponse { + exchangeBaseUrl: string; + amountRaw: AmountString; + amountEffective: AmountString; +} + +``` + +### InitiatePeerPullCreditOp +```typescript +/** + * Initiate an outgoing peer pull payment. + */ +export type InitiatePeerPullCreditOp = { + op: WalletApiOperation.InitiatePeerPullCredit; + request: InitiatePeerPullCreditRequest; + response: InitiatePeerPullCreditResponse; +}; +// InitiatePeerPullCredit = "initiatePeerPullCredit" + +``` +```typescript +export interface InitiatePeerPullCreditRequest { + exchangeBaseUrl?: string; + partialContractTerms: PeerContractTerms; +} + +``` +```typescript +export interface InitiatePeerPullCreditResponse { + /** + * Taler URI for the other party to make the payment + * that was requested. + */ + talerUri: string; + transactionId: string; +} + +``` + +### PreparePeerPullDebitOp +```typescript +/** + * Prepare for an incoming peer pull payment. + */ +export type PreparePeerPullDebitOp = { + op: WalletApiOperation.PreparePeerPullDebit; + request: PreparePeerPullDebitRequest; + response: PreparePeerPullDebitResponse; +}; +// PreparePeerPullDebit = "preparePeerPullDebit" + +``` +```typescript +export interface PreparePeerPullDebitRequest { + talerUri: string; +} + +``` +```typescript +export interface PreparePeerPullDebitResponse { + contractTerms: PeerContractTerms; + /** + * @deprecated Redundant field with bad name, will be removed soon. + */ + amount: AmountString; + amountRaw: AmountString; + amountEffective: AmountString; + peerPullPaymentIncomingId: string; +} + +``` + +### ConfirmPeerPullDebitOp +```typescript +/** + * Accept an incoming peer pull payment (i.e. pay the other party). + */ +export type ConfirmPeerPullDebitOp = { + op: WalletApiOperation.ConfirmPeerPullDebit; + request: ConfirmPeerPullDebitRequest; + response: EmptyObject; +}; +// ConfirmPeerPullDebit = "confirmPeerPullDebit" + +``` +```typescript +export interface ConfirmPeerPullDebitRequest { + /** + * Transparent identifier of the incoming peer pull payment. + */ + peerPullPaymentIncomingId: string; +} + +``` + +### ValidateIbanOp +```typescript +export type ValidateIbanOp = { + op: WalletApiOperation.ValidateIban; + request: ValidateIbanRequest; + response: ValidateIbanResponse; +}; +// ValidateIban = "validateIban" + +``` +```typescript +export interface ValidateIbanRequest { + iban: string; +} + +``` +```typescript +export interface ValidateIbanResponse { + valid: boolean; +} + +``` + +### ExportDbOp +```typescript +/** + * Export the wallet database's contents to JSON. + */ +export type ExportDbOp = { + op: WalletApiOperation.ExportDb; + request: EmptyObject; + response: any; +}; +// ExportDb = "exportDb" + +``` + +### ImportDbOp +```typescript +export type ImportDbOp = { + op: WalletApiOperation.ImportDb; + request: any; + response: any; +}; +// ImportDb = "importDb" + +``` + +### ClearDbOp +```typescript +/** + * Dangerously clear the whole wallet database. + */ +export type ClearDbOp = { + op: WalletApiOperation.ClearDb; + request: EmptyObject; + response: EmptyObject; +}; +// ClearDb = "clearDb" + +``` + +### RecycleOp +```typescript +/** + * Export a backup, clear the database and re-import it. + */ +export type RecycleOp = { + op: WalletApiOperation.Recycle; + request: EmptyObject; + response: EmptyObject; +}; +// Recycle = "recycle" + +``` + +### ApplyDevExperimentOp +```typescript +/** + * Apply a developer experiment to the current wallet state. + * + * This allows UI developers / testers to play around without + * an elaborate test environment. + */ +export type ApplyDevExperimentOp = { + op: WalletApiOperation.ApplyDevExperiment; + request: ApplyDevExperimentRequest; + response: EmptyObject; +}; +// ApplyDevExperiment = "applyDevExperiment" + +``` +```typescript +export interface ApplyDevExperimentRequest { + devExperimentUri: string; +} + +``` + +### RunIntegrationTestOp +```typescript +/** + * Run a simple integration test on a test deployment + * of the exchange and merchant. + */ +export type RunIntegrationTestOp = { + op: WalletApiOperation.RunIntegrationTest; + request: IntegrationTestArgs; + response: EmptyObject; +}; +// RunIntegrationTest = "runIntegrationTest" + +``` + +### RunIntegrationTestV2Op +```typescript +/** + * Run a simple integration test on a test deployment + * of the exchange and merchant. + */ +export type RunIntegrationTestV2Op = { + op: WalletApiOperation.RunIntegrationTestV2; + request: IntegrationTestArgs; + response: EmptyObject; +}; +// RunIntegrationTestV2 = "runIntegrationTestV2" + +``` + +### TestCryptoOp +```typescript +/** + * Test crypto worker. + */ +export type TestCryptoOp = { + op: WalletApiOperation.TestCrypto; + request: EmptyObject; + response: any; +}; +// TestCrypto = "testCrypto" + +``` + +### WithdrawTestBalanceOp +```typescript +/** + * Make withdrawal on a test deployment of the exchange + * and merchant. + */ +export type WithdrawTestBalanceOp = { + op: WalletApiOperation.WithdrawTestBalance; + request: WithdrawTestBalanceRequest; + response: EmptyObject; +}; +// WithdrawTestBalance = "withdrawTestBalance" + +``` +```typescript +export interface WithdrawTestBalanceRequest { + amount: string; + /** + * Bank access API base URL. + */ + bankAccessApiBaseUrl: string; + exchangeBaseUrl: string; + forcedDenomSel?: ForcedDenomSel; +} + +``` + +### WithdrawTestkudosOp +```typescript +/** + * Make a withdrawal of testkudos on test.taler.net. + */ +export type WithdrawTestkudosOp = { + op: WalletApiOperation.WithdrawTestkudos; + request: EmptyObject; + response: EmptyObject; +}; +// WithdrawTestkudos = "withdrawTestkudos" + +``` + +### TestPayOp +```typescript +/** + * Make a test payment using a test deployment of + * the exchange and merchant. + */ +export type TestPayOp = { + op: WalletApiOperation.TestPay; + request: TestPayArgs; + response: TestPayResult; +}; +// TestPay = "testPay" + +``` +```typescript +export interface TestPayArgs { + merchantBaseUrl: string; + merchantAuthToken?: string; + amount: string; + summary: string; + forcedCoinSel?: ForcedCoinSel; +} + +``` +```typescript +export interface TestPayResult { + payCoinSelection: PayCoinSelection; +} + +``` +```typescript +/** + * Result of selecting coins, contains the exchange, and selected + * coins with their denomination. + */ +export interface PayCoinSelection { + /** + * Amount requested by the merchant. + */ + paymentAmount: AmountString; + /** + * Public keys of the coins that were selected. + */ + coinPubs: string[]; + /** + * Amount that each coin contributes. + */ + coinContributions: AmountString[]; + /** + * How much of the wire fees is the customer paying? + */ + customerWireFees: AmountString; + /** + * How much of the deposit fees is the customer paying? + */ + customerDepositFees: AmountString; +} + +``` + +### WithdrawFakebankOp +```typescript +/** + * Make a withdrawal from a fakebank, i.e. + * a bank where test users can be registered freely + * and testing APIs are available. + */ +export type WithdrawFakebankOp = { + op: WalletApiOperation.WithdrawFakebank; + request: WithdrawFakebankRequest; + response: EmptyObject; +}; +// WithdrawFakebank = "withdrawFakebank" + +``` +```typescript +export interface WithdrawFakebankRequest { + amount: AmountString; + exchange: string; + bank: string; +} + +``` + +### GetPendingTasksOp +```typescript +/** + * Get wallet-internal pending tasks. + */ +export type GetPendingTasksOp = { + op: WalletApiOperation.GetPendingOperations; + request: EmptyObject; + response: PendingTasksResponse; +}; +// GetPendingOperations = "getPendingOperations" + +``` +```typescript +/** + * Response returned from the pending operations API. + */ +export interface PendingOperationsResponse { + /** + * List of pending operations. + */ + pendingOperations: PendingTaskInfo[]; +} + +``` +```typescript +/** + * Information about a pending operation. + */ +export type PendingTaskInfo = PendingTaskInfoCommon & + ( + | PendingExchangeUpdateTask + | PendingExchangeCheckRefreshTask + | PendingPurchaseTask + | PendingRefreshTask + | PendingTipPickupTask + | PendingWithdrawTask + | PendingRecoupTask + | PendingDepositTask + | PendingBackupTask + | PendingPeerPushInitiationTask + | PendingPeerPullInitiationTask + | PendingPeerPullDebitTask + | PendingPeerPushCreditTask + ); + +``` +```typescript +/** + * Fields that are present in every pending operation. + */ +export interface PendingTaskInfoCommon { + /** + * Type of the pending operation. + */ + type: PendingTaskType; + /** + * Unique identifier for the pending task. + */ + id: string; + /** + * Set to true if the operation indicates that something is really in progress, + * as opposed to some regular scheduled operation that can be tried later. + */ + givesLifeness: boolean; + /** + * Operation is active and waiting for a longpoll result. + */ + isLongpolling: boolean; + /** + * Operation is waiting to be executed. + */ + isDue: boolean; + /** + * Timestamp when the pending operation should be executed next. + */ + timestampDue: AbsoluteTime; + /** + * Retry info. Currently used to stop the wallet after any operation + * exceeds a number of retries. + */ + retryInfo?: RetryInfo; +} + +``` +```typescript +export enum PendingTaskType { + ExchangeUpdate = "exchange-update", + ExchangeCheckRefresh = "exchange-check-refresh", + Purchase = "purchase", + Refresh = "refresh", + Recoup = "recoup", + TipPickup = "tip-pickup", + Withdraw = "withdraw", + Deposit = "deposit", + Backup = "backup", + // FIXME: Rename to peer-push-debit and peer-pull-debit + PeerPushInitiation = "peer-push-initiation", + PeerPullInitiation = "peer-pull-initiation", + PeerPushCredit = "peer-push-credit", + PeerPullDebit = "peer-pull-debit", +} + +``` +```typescript +export interface RetryInfo { + firstTry: AbsoluteTime; + nextRetry: AbsoluteTime; + retryCounter: number; +} + +``` +```typescript +export interface RetryPolicy { + readonly backoffDelta: Duration; + readonly backoffBase: number; + readonly maxTimeout: Duration; +} + +``` +```typescript +// Declare "static" methods in Error +interface ErrorConstructor { + /** Create .stack property on a target object */ + captureStackTrace(targetObject: object, constructorOpt?: Function): void; + /** + * Optional override for formatting stack traces + * + * @see https://v8.dev/docs/stack-trace-api#customizing-stack-traces + */ + prepareStackTrace?: + | ((err: Error, stackTraces: NodeJS.CallSite[]) => any) + | undefined; + stackTraceLimit: number; +} + +``` +```typescript +interface CallSite { + /** + * Value of "this" + */ + getThis(): unknown; + /** + * Type of "this" as a string. + * This is the name of the function stored in the constructor field of + * "this", if available. Otherwise the object's [[Class]] internal + * property. + */ + getTypeName(): string | null; + /** + * Current function + */ + getFunction(): Function | undefined; + /** + * Name of the current function, typically its name property. + * If a name property is not available an attempt will be made to try + * to infer a name from the function's context. + */ + getFunctionName(): string | null; + /** + * Name of the property [of "this" or one of its prototypes] that holds + * the current function + */ + getMethodName(): string | null; + /** + * Name of the script [if this function was defined in a script] + */ + getFileName(): string | null; + /** + * Current line number [if this function was defined in a script] + */ + getLineNumber(): number | null; + /** + * Current column number [if this function was defined in a script] + */ + getColumnNumber(): number | null; + /** + * A call site object representing the location where eval was called + * [if this function was created using a call to eval] + */ + getEvalOrigin(): string | undefined; + /** + * Is this a toplevel invocation, that is, is "this" the global object? + */ + isToplevel(): boolean; + /** + * Does this call take place in code defined by a call to eval? + */ + isEval(): boolean; + /** + * Is this call in native V8 code? + */ + isNative(): boolean; + /** + * Is this a constructor call? + */ + isConstructor(): boolean; +} + +``` +```typescript +/** + * The wallet is currently updating information about an exchange. + */ +export interface PendingExchangeUpdateTask { + type: PendingTaskType.ExchangeUpdate; + exchangeBaseUrl: string; + lastError: TalerErrorDetail | undefined; +} + +``` +```typescript +/** + * The wallet should check whether coins from this exchange + * need to be auto-refreshed. + */ +export interface PendingExchangeCheckRefreshTask { + type: PendingTaskType.ExchangeCheckRefresh; + exchangeBaseUrl: string; +} + +``` +```typescript +/** + * A purchase needs to be processed (i.e. for download / payment / refund). + */ +export interface PendingPurchaseTask { + type: PendingTaskType.Purchase; + proposalId: string; + retryInfo?: RetryInfo; + /** + * Status of the payment as string, used only for debugging. + */ + statusStr: string; + lastError: TalerErrorDetail | undefined; +} + +``` +```typescript +/** + * Status of an ongoing withdrawal operation. + */ +export interface PendingRefreshTask { + type: PendingTaskType.Refresh; + lastError?: TalerErrorDetail; + refreshGroupId: string; + finishedPerCoin: boolean[]; + retryInfo?: RetryInfo; +} + +``` +```typescript +/** + * The wallet is picking up a tip that the user has accepted. + */ +export interface PendingTipPickupTask { + type: PendingTaskType.TipPickup; + tipId: string; + merchantBaseUrl: string; + merchantTipId: string; +} + +``` +```typescript +/** + * Status of an ongoing withdrawal operation. + */ +export interface PendingWithdrawTask { + type: PendingTaskType.Withdraw; + lastError: TalerErrorDetail | undefined; + retryInfo?: RetryInfo; + withdrawalGroupId: string; +} + +``` +```typescript +export interface PendingRecoupTask { + type: PendingTaskType.Recoup; + recoupGroupId: string; + retryInfo?: RetryInfo; + lastError: TalerErrorDetail | undefined; +} + +``` +```typescript +/** + * Status of an ongoing deposit operation. + */ +export interface PendingDepositTask { + type: PendingTaskType.Deposit; + lastError: TalerErrorDetail | undefined; + retryInfo: RetryInfo | undefined; + depositGroupId: string; +} + +``` +```typescript +export interface PendingBackupTask { + type: PendingTaskType.Backup; + backupProviderBaseUrl: string; + lastError: TalerErrorDetail | undefined; +} + +``` +```typescript +/** + * The wallet wants to send a peer push payment. + */ +export interface PendingPeerPushInitiationTask { + type: PendingTaskType.PeerPushInitiation; + pursePub: string; +} + +``` +```typescript +/** + * The wallet wants to send a peer pull payment. + */ +export interface PendingPeerPullInitiationTask { + type: PendingTaskType.PeerPullInitiation; + pursePub: string; +} + +``` +```typescript +/** + * The wallet wants to send a peer pull payment. + */ +export interface PendingPeerPullDebitTask { + type: PendingTaskType.PeerPullDebit; + peerPullPaymentIncomingId: string; +} + +``` +```typescript +/** + */ +export interface PendingPeerPushCreditTask { + type: PendingTaskType.PeerPushCredit; + peerPushPaymentIncomingId: string; +} + +``` + +### DumpCoinsOp +```typescript +/** + * Dump all coins of the wallet in a simple JSON format. + */ +export type DumpCoinsOp = { + op: WalletApiOperation.DumpCoins; + request: EmptyObject; + response: CoinDumpJson; +}; +// DumpCoins = "dumpCoins" + +``` +```typescript +/** + * Easy to process format for the public data of coins + * managed by the wallet. + */ +export interface CoinDumpJson { + coins: Array<{ + /** + * The coin's denomination's public key. + */ + denom_pub: DenominationPubKey; + /** + * Hash of denom_pub. + */ + denom_pub_hash: string; + /** + * Value of the denomination (without any fees). + */ + denom_value: string; + /** + * Public key of the coin. + */ + coin_pub: string; + /** + * Base URL of the exchange for the coin. + */ + exchange_base_url: string; + /** + * Public key of the parent coin. + * Only present if this coin was obtained via refreshing. + */ + refresh_parent_coin_pub: string | undefined; + /** + * Public key of the reserve for this coin. + * Only present if this coin was obtained via refreshing. + */ + withdrawal_reserve_pub: string | undefined; + coin_status: CoinStatus; + spend_allocation: + | { + id: string; + amount: string; + } + | undefined; + /** + * Information about the age restriction + */ + ageCommitmentProof: AgeCommitmentProof | undefined; + }>; +} + +``` +```typescript +export type DenominationPubKey = RsaDenominationPubKey | CsDenominationPubKey; + +``` +```typescript +export interface RsaDenominationPubKey { + readonly cipher: DenomKeyType.Rsa; + readonly rsa_public_key: string; + readonly age_mask: number; +} + +``` +```typescript +export interface CsDenominationPubKey { + readonly cipher: DenomKeyType.ClauseSchnorr; + readonly age_mask: number; + readonly cs_public_key: string; +} + +``` +```typescript +/** + * Status of a coin. + */ +export declare enum CoinStatus { + /** + * Withdrawn and never shown to anybody. + */ + Fresh = "fresh", + /** + * Fresh, but currently marked as "suspended", thus won't be used + * for spending. Used for testing. + */ + FreshSuspended = "fresh-suspended", + /** + * A coin that has been spent and refreshed. + */ + Dormant = "dormant", +} + +``` +```typescript +export interface AgeCommitmentProof { + commitment: AgeCommitment; + proof: AgeProof; +} + +``` +```typescript +export interface AgeCommitment { + mask: number; + /** + * Public keys, one for each age group specified in the age mask. + */ + publicKeys: Edx25519PublicKeyEnc[]; +} + +``` +```typescript +export type Edx25519PublicKeyEnc = FlavorP<string, "Edx25519PublicKeyEnc", 32>; + +``` +```typescript +export type FlavorP<T, FlavorT extends string, S extends number> = T & { + _flavor?: `taler.${FlavorT}`; + _size?: S; +}; + +``` +```typescript +export interface AgeProof { + /** + * Private keys. Typically smaller than the number of public keys, + * because we drop private keys from age groups that are restricted. + */ + privateKeys: Edx25519PrivateKeyEnc[]; +} + +``` +```typescript +export type Edx25519PrivateKeyEnc = FlavorP< + string, + "Edx25519PrivateKeyEnc", + 64 +>; + +``` + +### SetCoinSuspendedOp +```typescript +/** + * Set a coin as (un-)suspended. + * Suspended coins won't be used for payments. + */ +export type SetCoinSuspendedOp = { + op: WalletApiOperation.SetCoinSuspended; + request: SetCoinSuspendedRequest; + response: EmptyObject; +}; +// SetCoinSuspended = "setCoinSuspended" + +``` +```typescript +export interface SetCoinSuspendedRequest { + coinPub: string; + suspended: boolean; +} + +``` + +### ForceRefreshOp +```typescript +/** + * Force a refresh on coins where it would not + * be necessary. + */ +export type ForceRefreshOp = { + op: WalletApiOperation.ForceRefresh; + request: ForceRefreshRequest; + response: EmptyObject; +}; +// ForceRefresh = "forceRefresh" + +``` +```typescript +export interface ForceRefreshRequest { + coinPubList: string[]; +} + +``` + +## Common Declarations +```typescript +export interface WalletCoreVersion { + hash: string | undefined; + version: string; + exchange: string; + merchant: string; + bank: string; + /** + * @deprecated will be removed + */ + devMode: boolean; +} +``` +```typescript +export type Transaction = + | TransactionWithdrawal + | TransactionPayment + | TransactionRefund + | TransactionTip + | TransactionRefresh + | TransactionDeposit + | TransactionPeerPullCredit + | TransactionPeerPullDebit + | TransactionPeerPushCredit + | TransactionPeerPushDebit; +``` +```typescript +export interface TransactionWithdrawal extends TransactionCommon { + type: TransactionType.Withdrawal; + /** + * Exchange of the withdrawal. + */ + exchangeBaseUrl: string; + /** + * Amount that got subtracted from the reserve balance. + */ + amountRaw: AmountString; + /** + * Amount that actually was (or will be) added to the wallet's balance. + */ + amountEffective: AmountString; + withdrawalDetails: WithdrawalDetails; +} +``` +```typescript +export interface TransactionCommon { + transactionId: TransactionIdStr; + type: TransactionType; + timestamp: TalerProtocolTimestamp; + /** + * Transaction state, as per DD37. + */ + txState: TransactionState; + /** + * @deprecated in favor of statusMajor and statusMinor + */ + extendedStatus: ExtendedStatus; + /** + * true if the transaction is still pending, false otherwise + * If a transaction is not longer pending, its timestamp will be updated, + * but its transactionId will remain unchanged + * + * @deprecated show extendedStatus + */ + pending: boolean; + /** + * True if the transaction encountered a problem that might be + * permanent. A frozen transaction won't be automatically retried. + * + * @deprecated show extendedStatus + */ + frozen: boolean; + /** + * Raw amount of the transaction (exclusive of fees or other extra costs). + */ + amountRaw: AmountString; + /** + * Amount added or removed from the wallet's balance (including all fees and other costs). + */ + amountEffective: AmountString; + error?: TalerErrorDetail; +} +``` +```typescript +export declare enum TransactionType { + Withdrawal = "withdrawal", + Payment = "payment", + Refund = "refund", + Refresh = "refresh", + Tip = "tip", + Deposit = "deposit", + PeerPushDebit = "peer-push-debit", + PeerPushCredit = "peer-push-credit", + PeerPullDebit = "peer-pull-debit", + PeerPullCredit = "peer-pull-credit", +} +``` +```typescript +export interface TalerProtocolTimestamp { + readonly t_s: number | "never"; +} +``` +```typescript +export interface TransactionState { + major: TransactionMajorState; + minor?: TransactionMinorState; +} +``` +```typescript +export declare enum TransactionMajorState { + None = "none", + Pending = "pending", + Done = "done", + Aborting = "aborting", + Aborted = "aborted", + Suspended = "suspended", + Failed = "failed", + Deleted = "deleted", + Unknown = "unknown", +} +``` +```typescript +export declare enum TransactionMinorState { + Unknown = "unknown", + Deposit = "deposit", + KycRequired = "kyc-required", + Track = "track", + Refresh = "refresh", +} +``` +```typescript +export declare enum ExtendedStatus { + Pending = "pending", + Done = "done", + Aborting = "aborting", + Aborted = "aborted", + Failed = "failed", + KycRequired = "kyc-required", +} +``` +```typescript +export interface TalerErrorDetail { + code: TalerErrorCode; + when?: AbsoluteTime; + hint?: string; + [x: string]: unknown; +} +``` +```typescript +export interface AbsoluteTime { + /** + * Timestamp in milliseconds. + */ + readonly t_ms: number | "never"; +} +``` +```typescript +export interface Duration { + /** + * Duration in milliseconds. + */ + readonly d_ms: number | "forever"; +} +``` +```typescript +export interface TalerProtocolDuration { + readonly d_us: number | "forever"; +} +``` +```typescript +export type WithdrawalDetails = + | WithdrawalDetailsForManualTransfer + | WithdrawalDetailsForTalerBankIntegrationApi; +``` +```typescript +interface WithdrawalDetailsForManualTransfer { + type: WithdrawalType.ManualTransfer; + /** + * Payto URIs that the exchange supports. + * + * Already contains the amount and message. + */ + exchangePaytoUris: string[]; + reservePub: string; + /** + * Is the reserve ready for withdrawal? + */ + reserveIsReady: boolean; +} +``` +```typescript +interface WithdrawalDetailsForTalerBankIntegrationApi { + type: WithdrawalType.TalerBankIntegrationApi; + /** + * Set to true if the bank has confirmed the withdrawal, false if not. + * An unconfirmed withdrawal usually requires user-input and should be highlighted in the UI. + * See also bankConfirmationUrl below. + */ + confirmed: boolean; + /** + * If the withdrawal is unconfirmed, this can include a URL for user + * initiated confirmation. + */ + bankConfirmationUrl?: string; + reservePub: string; + /** + * Is the reserve ready for withdrawal? + */ + reserveIsReady: boolean; +} +``` +```typescript +export interface TransactionPayment extends TransactionCommon { + type: TransactionType.Payment; + /** + * Additional information about the payment. + */ + info: OrderShortInfo; + /** + * Wallet-internal end-to-end identifier for the payment. + */ + proposalId: string; + /** + * How far did the wallet get with processing the payment? + * + * @deprecated use extendedStatus + */ + status: PaymentStatus; + /** + * Amount that must be paid for the contract + */ + amountRaw: AmountString; + /** + * Amount that was paid, including deposit, wire and refresh fees. + */ + amountEffective: AmountString; + /** + * Amount that has been refunded by the merchant + */ + totalRefundRaw: AmountString; + /** + * Amount will be added to the wallet's balance after fees and refreshing + */ + totalRefundEffective: AmountString; + /** + * Amount pending to be picked up + */ + refundPending: AmountString | undefined; + /** + * Reference to applied refunds + */ + refunds: RefundInfoShort[]; + /** + * Is the wallet currently checking for a refund? + */ + refundQueryActive: boolean; + /** + * Does this purchase has an pos validation + */ + posConfirmation: string | undefined; +} +``` +```typescript +export interface OrderShortInfo { + /** + * Order ID, uniquely identifies the order within a merchant instance + */ + orderId: string; + /** + * Hash of the contract terms. + */ + contractTermsHash: string; + /** + * More information about the merchant + */ + merchant: MerchantInfo; + /** + * Summary of the order, given by the merchant + */ + summary: string; + /** + * Map from IETF BCP 47 language tags to localized summaries + */ + summary_i18n?: InternationalizedString; + /** + * List of products that are part of the order + */ + products: Product[] | undefined; + /** + * Time indicating when the order should be delivered. + * May be overwritten by individual products. + */ + delivery_date?: TalerProtocolTimestamp; + /** + * Delivery location for (all!) products. + */ + delivery_location?: Location; + /** + * URL of the fulfillment, given by the merchant + */ + fulfillmentUrl?: string; + /** + * Plain text message that should be shown to the user + * when the payment is complete. + */ + fulfillmentMessage?: string; + /** + * Translations of fulfillmentMessage. + */ + fulfillmentMessage_i18n?: InternationalizedString; +} +``` +```typescript +export interface MerchantInfo { + name: string; + jurisdiction?: Location; + address?: Location; + logo?: string; + website?: string; + email?: string; +} +``` +```typescript +export interface Location { + country?: string; + country_subdivision?: string; + district?: string; + town?: string; + town_location?: string; + post_code?: string; + street?: string; + building_name?: string; + building_number?: string; + address_lines?: string[]; +} +``` +```typescript +export interface InternationalizedString { + [lang_tag: string]: string; +} +``` +```typescript +export interface Product { + product_id?: string; + description: string; + description_i18n?: { + [lang_tag: string]: string; + }; + quantity?: number; + unit?: string; + price?: AmountString; + image?: string; + taxes?: Tax[]; + delivery_date?: TalerProtocolTimestamp; +} +``` +```typescript +export interface Tax { + name: string; + tax: AmountString; +} +``` +```typescript +export declare enum PaymentStatus { + /** + * Explicitly aborted after timeout / failure + */ + Aborted = "aborted", + /** + * Payment failed, wallet will auto-retry. + * User should be given the option to retry now / abort. + */ + Failed = "failed", + /** + * Paid successfully + */ + Paid = "paid", + /** + * User accepted, payment is processing. + */ + Accepted = "accepted", +} +``` +```typescript +export interface RefundInfoShort { + transactionId: string; + timestamp: TalerProtocolTimestamp; + amountEffective: AmountString; + amountRaw: AmountString; +} +``` +```typescript +export interface TransactionRefund extends TransactionCommon { + type: TransactionType.Refund; + refundedTransactionId: string; + info: OrderShortInfo; + /** + * Amount pending to be picked up + */ + refundPending: AmountString | undefined; + amountRaw: AmountString; + amountEffective: AmountString; +} +``` +```typescript +export interface TransactionTip extends TransactionCommon { + type: TransactionType.Tip; + amountRaw: AmountString; + /** + * More information about the merchant + */ + amountEffective: AmountString; + merchantBaseUrl: string; +} +``` +```typescript +/** + * A transaction shown for refreshes. + * Only shown for (1) refreshes not associated with other transactions + * and (2) refreshes in an error state. + */ +export interface TransactionRefresh extends TransactionCommon { + type: TransactionType.Refresh; + refreshReason: RefreshReason; + /** + * Transaction ID that caused this refresh. + */ + originatingTransactionId?: string; + /** + * Always zero for refreshes + */ + amountRaw: AmountString; + /** + * Fees, i.e. the effective, negative effect of the refresh + * on the balance. + * + * Only applicable for stand-alone refreshes, and zero for + * other refreshes where the transaction itself accounts for the + * refresh fee. + */ + amountEffective: AmountString; + refreshInputAmount: AmountString; + refreshOutputAmount: AmountString; +} +``` +```typescript +/** + * Reasons for why a coin is being refreshed. + */ +export declare enum RefreshReason { + Manual = "manual", + PayMerchant = "pay-merchant", + PayDeposit = "pay-deposit", + PayPeerPush = "pay-peer-push", + PayPeerPull = "pay-peer-pull", + Refund = "refund", + AbortPay = "abort-pay", + AbortDeposit = "abort-deposit", + Recoup = "recoup", + BackupRestored = "backup-restored", + Scheduled = "scheduled", +} +``` +```typescript +/** + * Deposit transaction, which effectively sends + * money from this wallet somewhere else. + */ +export interface TransactionDeposit extends TransactionCommon { + type: TransactionType.Deposit; + depositGroupId: string; + /** + * Target for the deposit. + */ + targetPaytoUri: string; + /** + * Raw amount that is being deposited + */ + amountRaw: AmountString; + /** + * Effective amount that is being deposited + */ + amountEffective: AmountString; + wireTransferDeadline: TalerProtocolTimestamp; + wireTransferProgress: number; + /** + * Did all the deposit requests succeed? + */ + deposited: boolean; + trackingState: Array<{ + wireTransferId: string; + timestampExecuted: TalerProtocolTimestamp; + amountRaw: AmountString; + wireFee: AmountString; + }>; +} +``` +```typescript +/** + * Credit because we were paid for a P2P invoice we created. + */ +export interface TransactionPeerPullCredit extends TransactionCommon { + type: TransactionType.PeerPullCredit; + info: PeerInfoShort; + /** + * Exchange used. + */ + exchangeBaseUrl: string; + /** + * Amount that got subtracted from the reserve balance. + */ + amountRaw: AmountString; + /** + * Amount that actually was (or will be) added to the wallet's balance. + */ + amountEffective: AmountString; + /** + * URI to send to the other party. + */ + talerUri: string; +} +``` +```typescript +export interface PeerInfoShort { + expiration: TalerProtocolTimestamp | undefined; + summary: string | undefined; +} +``` +```typescript +/** + * Debit because we paid someone's invoice. + */ +export interface TransactionPeerPullDebit extends TransactionCommon { + type: TransactionType.PeerPullDebit; + info: PeerInfoShort; + /** + * Exchange used. + */ + exchangeBaseUrl: string; + amountRaw: AmountString; + amountEffective: AmountString; +} +``` +```typescript +/** + * We received money via a P2P payment. + */ +export interface TransactionPeerPushCredit extends TransactionCommon { + type: TransactionType.PeerPushCredit; + info: PeerInfoShort; + /** + * Exchange used. + */ + exchangeBaseUrl: string; + /** + * Amount that got subtracted from the reserve balance. + */ + amountRaw: AmountString; + /** + * Amount that actually was (or will be) added to the wallet's balance. + */ + amountEffective: AmountString; +} +``` +```typescript +/** + * We sent money via a P2P payment. + */ +export interface TransactionPeerPushDebit extends TransactionCommon { + type: TransactionType.PeerPushDebit; + info: PeerInfoShort; + /** + * Exchange used. + */ + exchangeBaseUrl: string; + /** + * Amount that got subtracted from the reserve balance. + */ + amountRaw: AmountString; + /** + * Amount that actually was (or will be) added to the wallet's balance. + */ + amountEffective: AmountString; + /** + * URI to accept the payment. + */ + talerUri: string; +} +``` +```typescript +export interface AbortTransactionRequest { + transactionId: string; + /** + * Move the payment immediately into an aborted state. + * The UI should warn the user that this might lead + * to money being lost. + * + * Defaults to false. + */ + forceImmediateAbort?: boolean; +} +``` +```typescript +export interface ExchangeListItem { + exchangeBaseUrl: string; + currency: string | undefined; + paytoUris: string[]; + tosStatus: ExchangeTosStatus; + exchangeStatus: ExchangeEntryStatus; + ageRestrictionOptions: number[]; + /** + * Permanently added to the wallet, as opposed to just + * temporarily queried. + */ + permanent: boolean; + /** + * Information about the last error that occurred when trying + * to update the exchange info. + */ + lastUpdateErrorInfo?: OperationErrorInfo; +} +``` +```typescript +export declare enum ExchangeTosStatus { + New = "new", + Accepted = "accepted", + Changed = "changed", + NotFound = "not-found", + Unknown = "unknown", +} +``` +```typescript +export declare enum ExchangeEntryStatus { + Unknown = "unknown", + Outdated = "outdated", + Ok = "ok", +} +``` +```typescript +export interface OperationErrorInfo { + error: TalerErrorDetail; +} +``` +```typescript +export interface ForcedDenomSel { + denoms: { + value: AmountString; + count: number; + }[]; +} +``` +```typescript +/** + * Result of a prepare pay operation. + */ +export type PreparePayResult = + | PreparePayResultInsufficientBalance + | PreparePayResultAlreadyConfirmed + | PreparePayResultPaymentPossible; +``` +```typescript +export interface PreparePayResultInsufficientBalance { + status: PreparePayResultType.InsufficientBalance; + proposalId: string; + contractTerms: MerchantContractTerms; + amountRaw: string; + noncePriv: string; + talerUri: string; + balanceDetails: PayMerchantInsufficientBalanceDetails; +} +``` +```typescript +/** + * Contract terms from a merchant. + * FIXME: Add type field! + */ +export interface MerchantContractTerms { + /** + * Hash of the merchant's wire details. + */ + h_wire: string; + /** + * Hash of the merchant's wire details. + */ + auto_refund?: TalerProtocolDuration; + /** + * Wire method the merchant wants to use. + */ + wire_method: string; + /** + * Human-readable short summary of the contract. + */ + summary: string; + summary_i18n?: InternationalizedString; + /** + * Nonce used to ensure freshness. + */ + nonce: string; + /** + * Total amount payable. + */ + amount: string; + /** + * Auditors accepted by the merchant. + */ + auditors: AuditorHandle[]; + /** + * Deadline to pay for the contract. + */ + pay_deadline: TalerProtocolTimestamp; + /** + * Maximum deposit fee covered by the merchant. + */ + max_fee: string; + /** + * Information about the merchant. + */ + merchant: MerchantInfo; + /** + * Public key of the merchant. + */ + merchant_pub: string; + /** + * Time indicating when the order should be delivered. + * May be overwritten by individual products. + */ + delivery_date?: TalerProtocolTimestamp; + /** + * Delivery location for (all!) products. + */ + delivery_location?: Location; + /** + * List of accepted exchanges. + */ + exchanges: ExchangeHandle[]; + /** + * Products that are sold in this contract. + */ + products?: Product[]; + /** + * Deadline for refunds. + */ + refund_deadline: TalerProtocolTimestamp; + /** + * Deadline for the wire transfer. + */ + wire_transfer_deadline: TalerProtocolTimestamp; + /** + * Time when the contract was generated by the merchant. + */ + timestamp: TalerProtocolTimestamp; + /** + * Order id to uniquely identify the purchase within + * one merchant instance. + */ + order_id: string; + /** + * Base URL of the merchant's backend. + */ + merchant_base_url: string; + /** + * Fulfillment URL to view the product or + * delivery status. + */ + fulfillment_url?: string; + /** + * URL meant to share the shopping cart. + */ + public_reorder_url?: string; + /** + * Plain text fulfillment message in the merchant's default language. + */ + fulfillment_message?: string; + /** + * Internationalized fulfillment messages. + */ + fulfillment_message_i18n?: InternationalizedString; + /** + * Share of the wire fee that must be settled with one payment. + */ + wire_fee_amortization?: number; + /** + * Maximum wire fee that the merchant agrees to pay for. + */ + max_wire_fee?: string; + minimum_age?: number; + /** + * Extra data, interpreted by the mechant only. + */ + extra?: any; +} +``` +```typescript +export interface AuditorHandle { + /** + * Official name of the auditor. + */ + name: string; + /** + * Master public signing key of the auditor. + */ + auditor_pub: string; + /** + * Base URL of the auditor. + */ + url: string; +} +``` +```typescript +/** + * Information about an exchange as stored inside a + * merchant's contract terms. + */ +export interface ExchangeHandle { + /** + * Master public signing key of the exchange. + */ + master_pub: string; + /** + * Base URL of the exchange. + */ + url: string; +} +``` +```typescript +/** + * Detailed reason for why the wallet's balance is insufficient. + */ +export interface PayMerchantInsufficientBalanceDetails { + /** + * Amount requested by the merchant. + */ + amountRequested: AmountString; + /** + * Balance of type "available" (see balance.ts for definition). + */ + balanceAvailable: AmountString; + /** + * Balance of type "material" (see balance.ts for definition). + */ + balanceMaterial: AmountString; + /** + * Balance of type "age-acceptable" (see balance.ts for definition). + */ + balanceAgeAcceptable: AmountString; + /** + * Balance of type "merchant-acceptable" (see balance.ts for definition). + */ + balanceMerchantAcceptable: AmountString; + /** + * Balance of type "merchant-depositable" (see balance.ts for definition). + */ + balanceMerchantDepositable: AmountString; + /** + * If the payment would succeed without fees + * (i.e. balanceMerchantDepositable >= amountRequested), + * this field contains an estimate of the amount that would additionally + * be required to cover the fees. + * + * It is not possible to give an exact value here, since it depends + * on the coin selection for the amount that would be additionally withdrawn. + */ + feeGapEstimate: AmountString; +} +``` +```typescript +export interface PreparePayResultAlreadyConfirmed { + status: PreparePayResultType.AlreadyConfirmed; + contractTerms: MerchantContractTerms; + paid: boolean; + amountRaw: string; + amountEffective: string; + contractTermsHash: string; + proposalId: string; + talerUri?: string; +} +``` +```typescript +/** + * Payment is possible. + */ +export interface PreparePayResultPaymentPossible { + status: PreparePayResultType.PaymentPossible; + proposalId: string; + contractTerms: MerchantContractTerms; + contractTermsHash: string; + amountRaw: string; + amountEffective: string; + noncePriv: string; + talerUri: string; +} +``` +```typescript +/** + * Forced coin selection for deposits/payments. + */ +export interface ForcedCoinSel { + coins: { + value: AmountString; + contribution: AmountString; + }[]; +} +``` +```typescript +export interface ApplyRefundResponse { + contractTermsHash: string; + transactionId: string; + proposalId: string; + amountEffectivePaid: AmountString; + amountRefundGranted: AmountString; + amountRefundGone: AmountString; + pendingAtExchange: boolean; + info: OrderShortInfo; +} +``` +```typescript +export interface AddExchangeRequest { + exchangeBaseUrl: string; + forceUpdate?: boolean; +} +``` +```typescript +export interface BackupRecovery { + walletRootPriv: string; + providers: { + name: string; + url: string; + }[]; +} +``` +```typescript +/** + * Contract terms between two wallets (as opposed to a merchant and wallet). + */ +export interface PeerContractTerms { + amount: AmountString; + summary: string; + purse_expiration: TalerProtocolTimestamp; +} +``` +```typescript +export interface IntegrationTestArgs { + exchangeBaseUrl: string; + bankAccessApiBaseUrl: string; + merchantBaseUrl: string; + merchantAuthToken?: string; + amountToWithdraw: string; + amountToSpend: string; +} +``` diff --git a/extract-tsdefs/pnpm-lock.yaml b/extract-tsdefs/pnpm-lock.yaml @@ -1,34 +1,40 @@ -lockfileVersion: 5.4 +lockfileVersion: '6.0' -specifiers: - '@types/node': ^18.8.1 - '@types/prettier': ^2.7.1 - prettier: ^2.7.1 - typescript: ^4.8.4 +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false devDependencies: - '@types/node': 18.8.1 - '@types/prettier': 2.7.1 - prettier: 2.7.1 - typescript: 4.8.4 + '@types/node': + specifier: ^18.8.1 + version: 18.8.1 + '@types/prettier': + specifier: ^2.7.1 + version: 2.7.1 + prettier: + specifier: ^2.7.1 + version: 2.7.1 + typescript: + specifier: ^4.8.4 + version: 4.8.4 packages: - /@types/node/18.8.1: + /@types/node@18.8.1: resolution: {integrity: sha512-vuYaNuEIbOYLTLUAJh50ezEbvxrD43iby+lpUA2aa148Nh5kX/AVO/9m1Ahmbux2iU5uxJTNF9g2Y+31uml7RQ==} dev: true - /@types/prettier/2.7.1: + /@types/prettier@2.7.1: resolution: {integrity: sha512-ri0UmynRRvZiiUJdiz38MmIblKK+oH30MztdBVR95dv/Ubw6neWSb8u1XpRb72L4qsZOhz+L+z9JD40SJmfWow==} dev: true - /prettier/2.7.1: + /prettier@2.7.1: resolution: {integrity: sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==} engines: {node: '>=10.13.0'} hasBin: true dev: true - /typescript/4.8.4: + /typescript@4.8.4: resolution: {integrity: sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==} engines: {node: '>=4.2.0'} hasBin: true diff --git a/frags/about-taler.rst b/frags/about-taler.rst @@ -0,0 +1,26 @@ +.. + This file is part of GNU TALER. + + Copyright (C) 2014-2023 Taler Systems SA + + TALER 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 2.1, or (at your option) any later version. + + TALER 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 + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + + +GNU Taler is an open protocol for an electronic payment system with a +free software reference implementation. GNU Taler offers secure, fast +and easy payment processing using well understood cryptographic +techniques. GNU Taler allows customers to remain anonymous, while +ensuring that merchants can be held accountable by governments. Hence, +GNU Taler is compatible with anti-money-laundering (AML) and +know-your-customer (KYC) regulation, as well as data protection +regulation (such as GDPR). + diff --git a/frags/apt-install-taler-merchant.rst b/frags/apt-install-taler-merchant.rst @@ -3,11 +3,12 @@ To install the Taler merchant backend, you can now simply run: .. code-block:: console - # apt install dbconfig-pgsql taler-merchant + # apt install taler-merchant Note that the package does not complete the integration of the backend with the HTTP reverse proxy (typically with TLS certificates). A configuration fragment for Nginx or Apache will be placed in ``/etc/{apache,nginx}/conf-available/taler-merchant.conf``. You must -furthermore still configure the instances, and may need to extend the fragment -with access control restrictions for non-default instances. +furthermore still configure the database and the instances, and may need to +extend the fragment with access control restrictions for non-default +instances. diff --git a/frags/common-conf-syntax.rst b/frags/common-conf-syntax.rst @@ -1,27 +1,18 @@ -The configuration file is line-oriented. -Blank lines and whitespace at the beginning and end of a line are ignored. -Comments start with ``#`` or ``%`` in the first column -(after any beginning-of-line whitespace) and go to the end of the line. - -The file is split into sections. -Every section begins with “[SECTIONNAME]” and -contains a number of options of the form “OPTION=VALUE”. -There may be whitespace around the ``=`` (equal sign). -Section names and options are *case-insensitive*. - -The values, however, are *case-sensitive*. -In particular, boolean values are one of ``YES`` or ``NO``. -Values can include whitespace by surrounding -the entire value with ``"`` (double quote). -Note, however, that there are no escape characters in such strings; -all characters between the double quotes (including other double quotes) -are taken verbatim. - -Values that represent filenames can begin with a ``/bin/sh``-like -variable reference. -This can be simple, such as ``$TMPDIR/foo``, or complex, -such as ``${TMPDIR:-${TMP:-/tmp}}/foo``. -See ``[PATHS]`` (below). +The configuration file is line-oriented. Blank lines and whitespace at the +beginning and end of a line are ignored. Comments start with ``#`` or ``%`` +in the first column (after any beginning-of-line whitespace) and go to the end +of the line. + +The file is split into sections. Every section begins with ``[SECTIONNAME]`` +and contains a number of options of the form ``OPTION=VALUE``. There may be +whitespace around the ``=`` (equal sign). Section names and options are +*case-insensitive*. + +The values, however, are *case-sensitive*. In particular, boolean values are +one of ``YES`` or ``NO``. Values can include whitespace by surrounding the +entire value with ``"`` (double quote). Note, however, that there are no +escape characters in such strings; all characters between the double quotes +(including other double quotes) are taken verbatim. Values that represent a time duration are represented as a series of one or more ``NUMBER UNIT`` pairs, e.g. ``60 s``, ``4 weeks 1 day``, @@ -30,3 +21,41 @@ of one or more ``NUMBER UNIT`` pairs, e.g. ``60 s``, ``4 weeks 1 day``, Values that represent an amount are in the usual amount syntax: ``CURRENCY:VALUE.FRACTION``, e.g. ``EUR:1.50``. The ``FRACTION`` portion may extend up to 8 places. + +Values that represent filenames can begin with a ``/bin/sh``-like variable +reference. This can be simple, such as ``$TMPDIR/foo``, or complex, such as +``${TMPDIR:-${TMP:-/tmp}}/foo``. The variables are expanded either using +key-values from the ``[PATHS]`` section (see below) or from the environment +(``getenv()``). The values from ``[PATHS]`` take precedence over those from +the environment. If the variable name is found in neither ``[PATHS]`` nor the +environment, a warning is printed and the value is left unchanged. Variables (including those from the environment) are expanded recursively, so if ``FOO=$BAR`` and ``BAR=buzz`` then the result is ``FOO=buzz``. Recursion is bounded to at most 128 levels to avoid undefined behavior for mutually recursive expansions like if ``BAR=$FOO`` in the example above. + +The ``[PATHS]`` section is special in that it contains paths that can be +referenced using ``$`` in other configuration values that specify +*filenames*. Note that configuration options that are not specifically +retrieved by the application as *filenames* will not see “$”-expressions +expanded. To expand ``$``-expressions when using ``taler-config``, you must pass +the ``-f`` command-line option. + +The system automatically pre-populates the ``[PATHS]`` section with a few values +at run-time (in addition to the values that are in the actual configuration +file and automatically overwriting those values if they are present). +These automatically generated values refer to installation properties +from `GNU autoconf +<https://www.gnu.org/prep/standards/html_node/Directory-Variables.html>`_. The +values are usually dependent on an ``INSTALL_PREFIX`` which is determined by +the ``--prefix`` option given to configure. The canonical values are: + + * LIBEXECDIR = $INSTALL_PREFIX/taler/libexec/ + * DOCDIR = $INSTALL_PREFIX/share/doc/taler/ + * ICONDIR = $INSTALL_PREFIX/share/icons/ + * LOCALEDIR = $INSTALL_PREFIX/share/locale/ + * PREFIX = $INSTALL_PREFIX/ + * BINDIR = $INSTALL_PREFIX/bin/ + * LIBDIR = $INSTALL_PREFIX/lib/taler/ + * DATADIR = $INSTALL_PREFIX/share/taler/ + +Note that on some platforms, the given paths may differ depending +on how the system was compiled or installed, the above are just the +canonical locations of the various resources. These +automatically generated values are never written to disk. diff --git a/frags/configuration-format.rst b/frags/configuration-format.rst @@ -1,16 +1,22 @@ Configuration format -------------------- -In Taler realm, any component obeys to the same pattern to get -configuration values. According to this pattern, once the component has -been installed, the installation deploys default values in -${prefix}/share/taler/config.d/, in .conf files. In order to override -these defaults, the user can write a custom .conf file and either pass -it to the component at execution time, or name it taler.conf and place -it under $HOME/.config/. +All GNU Taler components are designed to possibly share the same +configuration files. When installing a GNU Taler component, the +installation deploys default values in configuration files located +at ${prefix}/share/taler/config.d/ where ${prefix} is the installation +prefix. Different components must be installed to the same prefix. + +In order to override these defaults, the user can write a custom configuration +file and either pass it to the component at execution time using the *-c* +option, or name it taler.conf and place it under $HOME/.config/ which is where +components will look by default. Note that the systemd service files pass ``-c +/etc/taler.conf``, thus making ``/etc/taler.conf`` the primary location for +the configuration. A config file is a text file containing sections, and each section -contains its values. The right format follows: +contains maps options to their values. Configuration files follow +basically the INI syntax: .. code-block:: ini @@ -22,43 +28,38 @@ contains its values. The right format follows: value21 = string value22 = /path22 -Throughout any configuration file, it is possible to use ``$``-prefixed -variables, like ``$VAR``, especially when they represent filesystem -paths. It is also possible to provide defaults values for those +Comments start with a hash (``#``). Throughout the configuration, it is +possible to use ``$``-substitution for options relating to names of files or +directories. It is also possible to provide defaults values for those variables that are unset, by using the following syntax: -``${VAR:-default}``. However, there are two ways a user can set -``$``-prefixable variables: +``${VAR:-default}``. There are two ways a user can set the value +of ``$``-prefixable variables: -by defining them under a ``[paths]`` section, see example below, + (1) by defining them under a ``[paths]`` section: -.. code-block:: ini + .. code-block:: ini - [paths] - TALER_DEPLOYMENT_SHARED = ${HOME}/shared-data - .. - [section-x] - path-x = ${TALER_DEPLOYMENT_SHARED}/x + [paths] + TALER_DEPLOYMENT_SHARED = ${HOME}/shared-data + .. + [section-x] + path-x = ${TALER_DEPLOYMENT_SHARED}/x -or by setting them in the environment: + (2) or by setting them in the environment: -.. code-block:: console + .. code-block:: console - $ export VAR=/x + $ export VAR=/x The configuration loader will give precedence to variables set under -``[path]``, though. +``[path]`` over environment variables. -The utility ``taler-config``, which gets installed along with the -exchange, serves to get and set configuration values without directly -editing the .conf. The option ``-f`` is particularly useful to resolve +The utility ``taler-config``, which gets installed along with the exchange, +can be used get and set configuration values without directly editing the +configuration file. The option ``-f`` is particularly useful to resolve pathnames, when they use several levels of ``$``-expanded variables. See ``taler-config --help``. -Note that, in this stage of development, the file -``$HOME/.config/taler.conf`` can contain sections for *all* the -component. For example, both an exchange and a bank can read values from -it. - -The repository ``git://git.taler.net/deployment`` contains examples of -configuration file used in our demos. See under ``deployment/config``. +The repository ``git://git.taler.net/deployment`` contains example code +for generating configuration files under ``deployment/netzbon/``. diff --git a/frags/db-stores-sensitive-data.rst b/frags/db-stores-sensitive-data.rst @@ -1,6 +1,5 @@ .. note:: - The Taler merchant backend stores private keys and other sensitive - business and customer data in the database. The backend operator - SHOULD ensure that backup operations are encrypted and secured from - unauthorized access. + Taler may store sensitive business and customer data in the database. Any + operator SHOULD thus ensure that backup operations are encrypted and + secured from unauthorized access. diff --git a/frags/install-before-check.rst b/frags/install-before-check.rst @@ -2,9 +2,5 @@ Please note that unlike most packages, if you want to run the ``make check`` command, you should run it only *after* having done ``make install``. The latter ensures that necessary binaries are copied to the right place. -Gratuitous editorial note by TTN: I think this is a quirk that we should -fix in the long-term as such weirdness might hide other build issues. -However, this is probably a minority viewpoint. - In any case, if ``make check`` fails, please consider filing a bug report with the Taler `bug tracker <https://bugs.taler.net>`__. diff --git a/frags/installing-challenger.rst b/frags/installing-challenger.rst @@ -0,0 +1 @@ +TBD. diff --git a/frags/installing-debian.rst b/frags/installing-debian.rst @@ -15,7 +15,7 @@ into your keyring and update the package lists: .. code-block:: console - # wget -P /etc/apt/keyrings/ \ + # wget -O /etc/apt/keyrings/taler-systems.gpg \ https://taler.net/taler-systems.gpg # apt update diff --git a/frags/installing-trisquel.rst b/frags/installing-trisquel.rst @@ -1,4 +1,4 @@ To install the GNU Taler Trisquel packages, first ensure that you have the right Trisquel distribution. Packages are currently available for Trisquel GNU/Linux 10.0. Simply follow the same instructions provided -for Ubuntu 20.04 LTS (Focal Fossa). +for Ubuntu. diff --git a/frags/installing-ubuntu.rst b/frags/installing-ubuntu.rst @@ -16,7 +16,7 @@ into your keyring and update the package lists: .. code-block:: console - # wget -P /etc/apt/keyrings/ \ + # wget -O /etc/apt/keyrings/taler-systems.gpg \ https://taler.net/taler-systems.gpg # apt update diff --git a/frags/legal.rst b/frags/legal.rst @@ -0,0 +1,183 @@ +.. + This file is part of GNU TALER. + + Copyright (C) 2014-2023 Taler Systems SA + + TALER 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 2.1, or (at your option) any later version. + + TALER 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 + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + + @author Christian Grothoff + + +The service has well-known API endpoints to return its legal conditions to the +user in various languages and various formats. This section describes how to +setup and configure the legal conditions. + + +Terms of Service +---------------- + +The service has an endpoint "/terms" to return the terms of service (in legal +language) of the service operator. Client software show these terms of +service to the user when the user is first interacting with the service. +Terms of service are optional for experimental deployments, if none are +configured, the service will return a simple statement saying that there are +no terms of service available. + +To configure the terms of service response, there are two options +in the configuration file for the service: + +- ``TERMS_ETAG``: The current "Etag" to return for the terms of service. + This value must be changed whenever the terms of service are + updated. A common value to use would be a version number. + Note that if you change the ``TERMS_ETAG``, you MUST also provide + the respective files in ``TERMS_DIR`` (see below). +- ``TERMS_DIR``: The directory that contains the terms of service. + The files in the directory must be readable to the service + process. + + +Privacy Policy +-------------- + +The service has an endpoint "/pp" to return the terms privacy policy (in legal +language) of the service operator. Clients should show the privacy policy to +the user when the user explicitly asks for it, but it should not be shown by +default. Privacy policies are optional for experimental deployments, if none +are configured, the service will return a simple statement saying that there +is no privacy policy available. + +To configure the privacy policy response, there are two options +in the configuration file for the service: + +- ``PRIVACY_ETAG``: The current "Etag" to return for the privacy policy. + This value must be changed whenever the privacy policy is + updated. A common value to use would be a version number. + Note that if you change the ``PRIVACY_ETAG``, you MUST also provide + the respective files in ``PRIVACY_DIR`` (see below). +- ``PRIVACY_DIR``: The directory that contains the privacy policy. + The files in the directory must be readable to the service + process. + + +Legal policies directory layout +------------------------------- + +The ``TERMS_DIR`` and ``PRIVACY_DIR`` directory structures must follow a +particular layout. You may use the same directory for both the terms of +service and the privacy policy, as long as you use different ETAGs. Inside of +the directory, there should be sub-directories using two-letter language codes +like "en", "de", or "jp". Each of these directories would then hold +translations of the current terms of service into the respective language. +Empty directories are permitted in case translations are not available. + +Then, inside each language directory, files with the name of the value set as +the ``TERMS_ETAG`` or ``PRIVACY_ETAG`` must be provided. The extension of each +of the files should be typical for the respective mime type. The set of +supported mime types is currently hard-coded in the service, and includes +".epub", ".html", ".md", ".pdf" and ".txt" files. If other files are present, +the service may show a warning on startup. + +Example +^^^^^^^ + +A sample file structure for a ``TERMS_ETAG`` of "tos-v0" would be: + +- TERMS_DIR/en/tos-v0.txt +- TERMS_DIR/en/tos-v0.html +- TERMS_DIR/en/tos-v0.pdf +- TERMS_DIR/en/tos-v0.epub +- TERMS_DIR/en/tos-v0.md +- TERMS_DIR/de/tos-v0.txt +- TERMS_DIR/de/tos-v0.html +- TERMS_DIR/de/tos-v0.pdf +- TERMS_DIR/de/tos-v0.epub +- TERMS_DIR/de/tos-v0.md + +If the user requests an HTML format with language preferences "fr" followed by +"en", the service would return ``TERMS_DIR/en/tos-v0.html`` lacking a version in +French. + + +Generating the Legal Terms +-------------------------- + +The ``taler-terms-generator`` script can be used to generate directories with +terms of service and privacy policies in multiple languages and all required +data formats from a single source file in ``.rst`` format and GNU gettext +translations in ``.po`` format. + +To use the tool, you need to first write your legal conditions in English in +reStructuredText (rst). You should find a templates in +``$PREFIX/share/terms/*.rst`` where ``$PREFIX`` is the location where you +installed the service to. Whenever you make substantive changes to the legal +terms, you must use a fresh filename and change the respective ``ETAG``. The +resulting file must be called ``$ETAG.rst`` and the first line of the file should be the title of the document. + +Once you have written the ``$ETAG.rst`` file in English, you can +generate the first set of outputs: + +.. code-block:: shell-session + + $ taler-terms-generator -i $ETAG + +Afterwards, you should find the terms in various formats for all configured +languages (initially only English) in ``$PREFIX/share/terms/``. The generator +has a few options which are documented in its man page. + + +Adding translations +------------------- + +Translations must be available in subdirectories +``locale/$LANGUAGE/LC_MESSAGES/$ETAG.po``. +To start translating, you first need to add a new +language: + +.. code-block:: shell-session + + $ taler-terms-generator -i $ETAG -l $LANGUAGE + +Here, ``$LANGUAGE`` should be a two-letter language +code like ``de`` or ``fr``. The command will generate +a file ``locale/$LANGUAGE/LC_MESSAGES/$ETAG.po`` +which contains each English sentence or paragraph +in the original document and an initially empty +translation. Translators should update the ``.po`` +file. Afterwards, simply re-run + +.. code-block:: shell-session + + $ taler-terms-generator -i $ETAG + +to make the current translation(s) available to the +service. + +.. note:: + + You must restart the service whenever adding or updating legal documents or their translations. + + +Updating legal documents +------------------------ + +When making minor changes without legal implications, edit the ``.rst`` file, +then re-run the step to add a new language for each existing translation to +produce an updated ``.po`` file. Translate the sentences that have changed and +finally run the generator (without ``-l``) on the ETAG (``-i $ETAG``) to +create the final files. + +When making major changes with legal implications, you should first rename (or +copy) the existing ``.rst`` file and the associated translation files to a new +unique name. Afterwards, make the major changes, update the ``.po`` files, +complete the translations and re-create the final files. Finally, do not +forget to update the ``ETAG`` configuration option to the new name and to +restart the service. diff --git a/frags/semver.rst b/frags/semver.rst @@ -0,0 +1,25 @@ +.. + This file is part of GNU TALER. + + Copyright (C) 2014-2023 Taler Systems SA + + TALER 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 2.1, or (at your option) any later version. + + TALER 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 + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + + @author Christian Grothoff + +GNU Taler components version numbers follow the ``MAJOR.MINOR.MICRO`` format. +The general rule for compatibility is that ``MAJOR`` and ``MINOR`` must match. +Exceptions to this general rule are documented in the release notes. +For example, Taler merchant 1.3.0 should be compatible with Taler exchange 1.4.x +as the MAJOR version matches. A MAJOR version of 0 indicates experimental +development, and you are expected to always run all of the *latest* releases +together (no compatibility guarantees). diff --git a/frags/using-taler-config.rst b/frags/using-taler-config.rst @@ -1,9 +1,9 @@ Using taler-config ------------------ -The tool ``taler-config`` can be used to extract or manipulate -configuration values; however, the configuration use the well-known INI -file format and can also be edited by hand. +The tool ``taler-config`` can be used to extract or manipulate configuration +values; however, the configuration use the well-known INI file format and is +generally better edited by hand to preserve comments and structure. Run @@ -17,19 +17,19 @@ Run .. code-block:: console - $ taler-config -s $section -o $option + $ taler-config -s $SECTION -o $OPTION -to extract the respective configuration value for option ``$option`` in -section ``$section``. +to extract the respective configuration value for option ``$OPTION`` in +section ``$SECTION``. Finally, to change a setting, run .. code-block:: console - $ taler-config -s $section -o $option -V $value + $ taler-config -s $SECTION -o $OPTION -V $VALUE -to set the respective configuration value to ``$value``. Note that you -have to manually restart the Taler backend after you change the +to set the respective configuration value to ``$VALUE``. Note that you +have to manually restart affected Taler components after you change the configuration to make the new configuration go into effect. Some default options will use $-variables, such as ``$DATADIR`` within @@ -43,6 +43,5 @@ compare: $ taler-config -f --section exchange-offline --option MASTER_PRIV_FILE While the configuration file is typically located at -``$HOME/.config/taler.conf``, an alternative location can be specified -to ``taler-merchant-httpd`` and ``taler-config`` using the ``-c`` -option. +``$HOME/.config/taler.conf``, an alternative location can be specified to any +GNU Taler component using the ``-c`` option. diff --git a/global-licensing.rst b/global-licensing.rst @@ -2,28 +2,130 @@ Taler licensing information =========================== -This file gives an overview of all Taler component's licensing and of -runtime dependencies thereof. For "component" here is meant a set of -source files which can be retrieved from a single repository. If -components consist of sources under different licensing regimes, i.e. -because we want to enable third party developments to easily integrate -with Taler, those are described as well. - -All components are generally released under Lesser GPL, GPL or Affero -GPL. The main strategy is for libraries that third parties may need -to integrate with Taler to be under LGPL, standalone binaries and -testcases to be under GPL, and Web servers implementing Web services -to be under AGPL. - -+++++++++++++++++++++++++ -API (git://taler.net/api) -+++++++++++++++++++++++++ - -The specification has been jointly developed by INRIA and by individuals +This file gives an overview of all Taler component's licensing and of runtime +dependencies thereof. A "component" in this context is to be read as a set of +source files which can be retrieved from a single Git repository. If +components consist of sources under different licensing regimes, i.e. because +we want to enable third party developments to easily integrate with Taler, +those are described as well. + +All components are generally released under Lesser GPL, GPL or Affero GPL. +The main strategy is for libraries that third parties may need to integrate +with Taler to be under LGPL, standalone binaries and testcases to be under +GPL, and Web servers implementing Web services and REST APIs to be under AGPL. +Trivial code (such as build logic) is occasionally also simply put into the +public domain. Legislations that do not have a public domain should consider +that code to be under LGPL. + +The project was initially started based on code and documentation from GNUnet +e.V. and INRIA, and is continued to be developed by the GNUnet community and +Taler Systems SA. INRIA and GNUnet e.V. have both assigned or shared their +copyrights with Taler Systems SA. Thus, it should generally be said that the +code is copyright Taler Systems SA. + +We are also working closely with the GNU Anastasis package. Here, the same +copyright sharing is in place between the original developers from BFH and +GNUnet e.V., except that the copyright was assigned or shared with Anastasis +SARL. Agreements are in place that allows developers to freely move code +between GNU Anastasis, GNUnet and GNU Taler if this is technically warranted +(note that all developers must sign the GNUnet e.V. copyright contributor +agreement). + +Note that this file *may* be outdated. If in doubt, please contact the +involved GNU maintainers (currently Florian Dold, Christian Grothoff and +Martin Schanzenbach) as they generally have the responsibility and right to +determine the appropriate license for individual components. (That right is +technically granted and constrained by the copyright agreemnts signed by +individual contributors and possibly subject to decision processes within +Anastasis SARL, GNUnet e.V. and Taler Systems SA. However, in practice this +has so far never been an issue as so far everyone agrees on the licensing +strategy and the maintainers will just make minor adjustments to consistently +implement that strategy when issues arise, such as code moving between +LGPL, GPL and AGPL licensed components or developers accidentally using the +wrong license in a header.) + + +++++++++++++++++++ +Following the AGPL +++++++++++++++++++ + +The main goal of the AGPL is to require a service provider to make the source +code of the service easily accessible to all users of that service. + +For GNUnet, GNU Taler and GNU Anastasis, we are realizing this requirement by +implementing an ``/agpl/`` endpoint that directs users of the API to the +source code (either a TGZ or a redirect to the Git repository) of the +component and its dependencies (we believe it is acceptable to not include +unmodified dependencies that are easily available and findable elsewhere +already). The source code (as defined in the GPL) must then be downloadable +gratis and without access control from that address in a form suitable for +development (that is, including build system and instructions). All of the +usual constraints of distributing code under GPL apply as well. + +When deploying sources that have been modified from the upstream versions +released by GNU, you *must* thus update the ``/agpl/`` endpoint to point to +the modified source code. Note that you *must* always make the code of the +actually deployed version available, which includes customizations, +extensions, integrations or security enhancements or bug fixes. + +.. note: + + We provide this text as a clarification, the ultimate + license text that applies is that of the AGPLv3+. + ++++++++++++++++++ +Following the GPL ++++++++++++++++++ + +The GPL requires you to make the source code of the respective program +available to all users that may be running the program. This includes again +any customizations (branding, theming, extensions, integrations or security +enhancements or bug fixes) you may have made. The source code for the +modified program must be again released under the GPL and must be reasonably +easy to find gratis for all users of your program. + +When shipping binaries of *unmodified* versions of the GNU releases, this is +satisfied as GNU makes the sources available via both the Git repositories of +the project and the FTP mirrors of the GNU project. You are still required to +make any packaging logic you may have written to create the binaries available +to others. + +.. note: + + We provide this text as a clarification, the ultimate + license text that applies is that of the GPLv3+. + + +++++++++++++++++++ +Following the LGPL +++++++++++++++++++ + +To follow the LGPL, you basically do everything you need to do +under the GPL when it comes to the sources you were provided. + +However, you are allowed to integrate the code provided under +the LGPL with other code that is not under the LGPLv3+. +Nevertheless, modifications to our existing code must +remain under the LGPLv3+, and we strongly encourage you +to release all of your code under an appropriate FLOSS +license. + +.. note: + + We provide this text as a clarification, the ultimate + license text that applies is that of the LGPLv3+. + + + +++++++++++++++++++++++++++++++ +API (git://git.taler.net/docs) +++++++++++++++++++++++++++++++ + +The specification has been originally developed by INRIA and by individuals being under the juridical subject called 'GNUnet e.V.'. For each source file, the header indicated whose is holding the copyright, since some parts have been taken "verbatim" from the GNUnet e.V. foundation, and -some other have been developed at INRIA "ex novo". +some other have been developed at INRIA or Taler Systems SA "ex novo". Generally, GNU GPLv3 license is used for them; see COPYING.GPL. @@ -35,9 +137,9 @@ This component has no runtime dependencies as it is supposed to generate HTML. -++++++++++++++++++++++++++++++++++++++++++++++++++++++ -Firefox/Android/Python Wallet (git://taler.net/wallet) -++++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +Firefox/Android/Python Wallet (git://git.taler.net/wallet-core) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ This project includes contributions from INRIA and GNUnet e.V. developers. Please refer to each source file to obtain @@ -59,11 +161,11 @@ project, and gives the copyright holder for each of them: * Mozilla Firefox: Mozilla Public License, LGPL-Compatible, Mozilla Foundation -+++++++++++++++++++++++++++++++++++++++++++++++++++ -WebExtensions Wallet (git://taler.net/wallet-webex) -+++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +WebExtensions Wallet (git://git.taler.net/wallet-webex) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -The TypeScript code was developed 100% at INRIA, but the project +The TypeScript code was originally developed at INRIA, but the project involves compiling libgnunetutil and libtalerutil to JavaScript, and thus depends on software from GNUnet e.V. @@ -86,13 +188,13 @@ Note that these dependencies are compiled into the extension and do not appear as separate binary files. -+++++++++++++++++++++++++++++++++++ -Merchant (git://taler.net/merchant) -+++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++ +Merchant (git://git.taler.net/merchant) ++++++++++++++++++++++++++++++++++++++++ This project contains code under two different licenses, and whose copyright is held by INRIA and/or GNUnet e.V.. Please refer to each -source file to know which party holds the copyright. +source file to know which party holds the original copyright. Source files are located in the following directories: @@ -105,25 +207,21 @@ Source files are located in the following directories: * examples/shop/ * copylib/ -In examples/blog/articles/ we included a book by Richard Stallman. -It comes with its own permissive license (see COPYING in the -directory). +The merchant's backend (i.e. all the code in src/backend/) is under the GNU +Affero GPL. Note that the use of the Affero GPL has little impact as the +backend is not supposed to be directly accessible to the Internet). The +license for this code is in COPYING.GPL and COPYING.AGPL. +The merchant's frontend logic (i.e. JavaScript interacting with +the wallet, sample code for a shop) is under the GNU GPL. -The merchant's backend (i.e. all the code in src/backend/) is under -the GNU Affero GPL as it depends on libgnunetutil. Note that the use -of the Affero GPL has little impact as the backend is not supposed to -be directly accessible to the Internet). The license for this code is -in COPYING.GPL and COPYING.AGPL. +The merchant library (src/lib/) is under the Lesser GNU GPL as it can be +linked with more diverse licensed software. The license text for this code is +in COPYING.LGPL. -The merchant's frontend logic (i.e. JavaScript interacting with -the wallet, sample code for a shop) is under the GNU LGPL (but -we may choose to change this to be in the public domain or -BSD-licensed if necessary; the code is so short that there is -anyway the question whether it is copyrightable). Under this same -license, it comes the merchant library (src/lib/) as it can be linked -with more diverse licensed software. The license text for this code -is in COPYING.LGPL. +In taler-merchant-demos.git/talermerchantdemos/blog/articles/ we included a book +by Richard Stallman. It comes with its own permissive license (see COPYING in +the directory). @@ -140,26 +238,18 @@ project, and gives the copyright holder for each of them: * libgnunetutil (in all of its variants): GPLv3+, owned by GNUnet e.V. * PHP: PHP License, AGPL- and LGPL-Compatible, owned by The PHP Group -+++++++++++++++++++++++++++ -Bank (git://taler.net/bank) -+++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++ +Libeufin (git://git.taler.net/libeufin) ++++++++++++++++++++++++++++++++++++++++ --------- Licensing --------- -This project has been developed by INRIA. For each source file, the -header indicated whose is holding the copyright. The licensing plan -for the bank is to use the Affero GPLv3+. - -Source files of interest are located in the following directories: -(The repository holds also scaffolded files autogenerated by Django, -which do not have legal significance in this context.) - -* TalerBank/Bank/ -* TalerBank/Bank/templates/ -* TalerBank/my-static/ -* website/ +This project has been developed by Stanisci and Dold who are +sharing their copyright with Taler Systems SA. For each source file, the +header indicated whose is holding the copyright. The license is +the Affero GPLv3+. -------------------- Runtime dependencies @@ -178,13 +268,14 @@ project, and gives the copyright holder for each of them: .. _exchange-repo: -+++++++++++++++++++++++++++++++++++ -Exchange (git://taler.net/exchange) -+++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++ +Exchange (git://git.taler.net/exchange) ++++++++++++++++++++++++++++++++++++++++ -This component is based on code initially developed in Munich for -GNUnet e.V. Most recent improvements and maintenance has been done at -Inria. The copyright is thus shared between both institutions. +This component is based on code initially developed in Munich for GNUnet +e.V. but was significantly rewritten by INRIA. Most recent improvements and +maintenance has been done at Taler Systems SA and BFH (under a copyright +sharing agreement with GNUnet e.V.). The copyright is with Taler Systems SA. The licensing for exported libraries to access the exchange is LGPL, the exchange itself is under AGPL, and testcases and standalone @@ -200,14 +291,17 @@ project, and gives the copyright holder for each of them: * libjansson: MIT License, AGPL- and LGPL-Compatible, owned by Petri Lehtinen and other individuals * libgcrypt: LGPL, owned by Free Software Foundation +* libsodium: LGPL * postgresql: PostgreSQL License, AGPL- and LGPL-Compatible, owned by The PostgreSQL Global Development Group * libgnunetutil (in all of its variants): GPLv3+, owned by GNUnet e.V. -* libgnunetjson: GPLv3+, GNUnet e.V. +* libgnunetjson: LGPLv3+, GNUnet e.V. +* libgnunetpq: AGPLv3+, GNUnet e.V. +* libgnunetcurl: LGPLv3+, GNUnet e.V. -+++++++++++++++++++++++++++++++++++++++++ -Web includes (git://taler.net/web-common) -+++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++ +Web includes (git://git.taler.net/web-common) ++++++++++++++++++++++++++++++++++++++++++++++ All copyright owned by INRIA (but questionable whether creativity threshold for copyright is even met). diff --git a/images/Makefile b/images/Makefile @@ -0,0 +1,33 @@ +diagrams: arch-api.png coin.png deposit.png reserve.png transaction-common-states.png transaction-withdrawal-states.png transaction-payment-states.png transaction-refund-states.png transaction-refresh-states.png transaction-reward-states.png transaction-deposit-states.png transaction-push-debit-states.png transaction-push-credit-states.png transaction-pull-credit-states.png transaction-pull-debit-states.png + +arch-api.png: arch-api.dot + dot -Tpng arch-api.dot > arch-api.png +transaction-common-states.png: transaction-common-states.dot + dot -Tpng transaction-common-states.dot > transaction-common-states.png +transaction-withdrawal-states.png: transaction-withdrawal-states.dot + dot -Tpng transaction-withdrawal-states.dot > transaction-withdrawal-states.png +transaction-payment-states.png: transaction-payment-states.dot + dot -Tpng transaction-payment-states.dot > transaction-payment-states.png +transaction-refund-states.png: transaction-refund-states.dot + dot -Tpng transaction-refund-states.dot > transaction-refund-states.png +transaction-refresh-states.png: transaction-refresh-states.dot + dot -Tpng transaction-refresh-states.dot > transaction-refresh-states.png +transaction-reward-states.png: transaction-reward-states.dot + dot -Tpng transaction-reward-states.dot > transaction-reward-states.png +transaction-deposit-states.png: transaction-deposit-states.dot + dot -Tpng transaction-deposit-states.dot > transaction-deposit-states.png +transaction-push-debit-states.png: transaction-push-debit-states.dot + dot -Tpng transaction-push-debit-states.dot > transaction-push-debit-states.png +transaction-push-credit-states.png: transaction-push-credit-states.dot + dot -Tpng transaction-push-credit-states.dot > transaction-push-credit-states.png +transaction-pull-credit-states.png: transaction-pull-credit-states.dot + dot -Tpng transaction-pull-credit-states.dot > transaction-pull-credit-states.png +transaction-pull-debit-states.png: transaction-pull-debit-states.dot + dot -Tpng transaction-pull-debit-states.dot > transaction-pull-debit-states.png +coin.png: coin.dot + dot -Tpng coin.dot > coin.png +deposit.png: deposit.dot + dot -Tpng deposit.dot > deposit.png +reserve.png: reserve.dot + dot -Tpng reserve.dot > reserve.png + diff --git a/arch-api.dot b/images/arch-api.dot diff --git a/arch.dot b/images/arch.dot diff --git a/auditor-db.png b/images/auditor-db.png Binary files differ. diff --git a/backoffice-order-create.all-expanded.svg b/images/backoffice-order-create.all-expanded.svg diff --git a/backoffice-order-create.payment-section.svg b/images/backoffice-order-create.payment-section.svg diff --git a/backoffice-order-create.price-section.svg b/images/backoffice-order-create.price-section.svg diff --git a/backoffice-order-create.product-section.svg b/images/backoffice-order-create.product-section.svg diff --git a/backoffice-order-details.claimed.svg b/images/backoffice-order-details.claimed.svg diff --git a/backoffice-order-details.paid.svg b/images/backoffice-order-details.paid.svg diff --git a/backoffice-order-details.refunded.svg b/images/backoffice-order-details.refunded.svg diff --git a/backoffice-order-details.unpaid.svg b/images/backoffice-order-details.unpaid.svg diff --git a/backoffice-order-list.pagination.svg b/images/backoffice-order-list.pagination.svg diff --git a/backoffice-order-list.svg b/images/backoffice-order-list.svg diff --git a/backoffice-order-refund.already.svg b/images/backoffice-order-refund.already.svg diff --git a/backoffice-order-refund.svg b/images/backoffice-order-refund.svg diff --git a/backoffice-product-create.stock.svg b/images/backoffice-product-create.stock.svg diff --git a/backoffice-product-create.svg b/images/backoffice-product-create.svg diff --git a/backoffice-product-create.with-stock.svg b/images/backoffice-product-create.with-stock.svg diff --git a/backoffice-product-create.without-stock.svg b/images/backoffice-product-create.without-stock.svg diff --git a/backoffice-product-list.actions.svg b/images/backoffice-product-list.actions.svg diff --git a/backoffice-product-list.svg b/images/backoffice-product-list.svg diff --git a/backoffice-product-update.svg b/images/backoffice-product-update.svg diff --git a/backoffice-reserve-create.svg b/images/backoffice-reserve-create.svg diff --git a/backoffice-reserve-details.svg b/images/backoffice-reserve-details.svg diff --git a/backoffice-reserve-details.unfunded.svg b/images/backoffice-reserve-details.unfunded.svg diff --git a/backoffice-reserve-list.svg b/images/backoffice-reserve-list.svg diff --git a/backoffice-tip-create.confirmation.svg b/images/backoffice-reward-create.confirmation.svg diff --git a/backoffice-tip-create.svg b/images/backoffice-reward-create.svg diff --git a/coin.dot b/images/coin.dot diff --git a/deposit.dot b/images/deposit.dot diff --git a/diagram.dot b/images/diagram.dot diff --git a/images/exchange-db.png b/images/exchange-db.png Binary files differ. diff --git a/merchant-db.png b/images/merchant-db.png Binary files differ. diff --git a/replication.png b/images/replication.png Binary files differ. diff --git a/replication.svg b/images/replication.svg diff --git a/reserve.dot b/images/reserve.dot diff --git a/images/taler-logo.svg b/images/taler-logo.svg @@ -0,0 +1 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" width="300" height="100" viewBox="0 0 200 100"><g fill="#0042b3" fill-rule="evenodd" stroke-width=".3"><path d="M86.7 1.1c15.6 0 29 9.4 36 23.2h-5.9A35.1 35.1 0 0086.7 6.5C67 6.5 51 23.6 51 44.7c0 10.4 3.8 19.7 10 26.6a31.4 31.4 0 01-4.2 3A45.2 45.2 0 0146 44.7c0-24 18.2-43.6 40.7-43.6zm35.8 64.3a40.4 40.4 0 01-39 22.8c3-1.5 6-3.5 8.6-5.7a35.6 35.6 0 0024.6-17.1z"/><path d="M64.2 1.1l3.1.1c-3 1.6-5.9 3.5-8.5 5.8a37.5 37.5 0 00-30.2 37.7c0 14.3 7.3 26.7 18 33.3a29.6 29.6 0 01-8.5.2c-9-8-14.6-20-14.6-33.5 0-24 18.2-43.6 40.7-43.6zm5.4 81.4a35.6 35.6 0 0024.6-17.1h5.9a40.4 40.4 0 01-39 22.8c3-1.5 5.9-3.5 8.5-5.7zm24.8-58.2a37 37 0 00-12.6-12.8 29.6 29.6 0 018.5-.2c4 3.6 7.4 8 9.9 13z"/><path d="M41.8 1.1c1 0 2 0 3.1.2-3 1.5-5.9 3.4-8.5 5.6A37.5 37.5 0 006.1 44.7c0 21.1 16 38.3 35.7 38.3 12.6 0 23.6-7 30-17.6h5.8a40.4 40.4 0 01-35.8 23C19.3 88.4 1 68.8 1 44.7c0-24 18.2-43.6 40.7-43.6zm30.1 23.2a38.1 38.1 0 00-4.5-6.1c1.3-1.2 2.7-2.2 4.3-3 2.3 2.7 4.4 5.8 6 9.1z"/></g><path d="M76.1 34.4h9.2v-5H61.9v5H71v26h5.1zM92.6 52.9h13.7l3 7.4h5.3l-12.7-31.2h-4.7L84.5 60.3h5.2zm11.8-4.9h-9.9l5-12.4zM123.8 29.4h-4.6v31h20.6v-5h-16zM166.5 29.4H145v31h21.6v-5H150v-8.3h14.5v-4.9h-14.5v-8h16.4zM191.2 39.5c0 1.6-.5 2.8-1.6 3.8s-2.6 1.4-4.4 1.4h-7.4V34.3h7.4c1.9 0 3.4.4 4.4 1.3 1 .9 1.6 2.2 1.6 3.9zm6 20.8l-7.7-11.7c1-.3 1.9-.7 2.7-1.3a8.8 8.8 0 003.6-4.6c.4-1 .5-2.2.5-3.5 0-1.5-.2-2.9-.7-4.1a8.4 8.4 0 00-2.1-3.1c-1-.8-2-1.5-3.4-2-1.3-.4-2.8-.6-4.5-.6h-12.9v31h5V49.4h6.5l7 10.8z"/></svg> diff --git a/images/transaction-common-states.dot b/images/transaction-common-states.dot @@ -0,0 +1,52 @@ +digraph G { + + initial[label="", shape="circle"]; + pending[label="pending"]; + dialog[label="dialog", shape="box"]; + done[label="done", shape="box"]; + aborted[label="aborted", shape="box", style="dashed"]; + aborting[label="aborting", style="dashed"]; + expired[label="expired", shape="box"]; + failed[label="failed", shape="box"]; + suspended[label="suspended", shape="box"]; + suspended_aborting[label="suspended-aborting", shape="box", style="dashed"]; + deleted[label="deleted", shape="box"]; + + subgraph { + rank = same; done; failed; expired; aborted; + } + subgraph { + rank = same; pending; aborting; + } + subgraph { + rank = same; dialog; suspended; suspended_aborting; + } + + initial->pending; + pending->suspended [color="blue",label="suspend"]; + pending->expired [label="expire"]; + pending->dialog [color="green",label="success"]; + pending->pending [color="green",label="progress"]; + pending->done [color="green",label="success"]; + pending->failed [color="red",label="failure"]; + pending->failed [color="blue",label="fail"]; + pending->aborting [color="blue",label="abort", style="dashed"]; + dialog->pending [color="blue",label="OK"]; + dialog->deleted [color="blue", label="delete"]; + dialog->expired [label="expire"]; + dialog->aborting [color="blue", label="refuse", style="dashed"]; + suspended->pending [color="blue",label="resume"]; + suspended->aborting [color="blue",label="abort", style="dashed"]; + suspended->expired [label="expire"]; + aborting->aborting [color="green",label="progress"]; + aborting->aborted [color="green",label="success"]; + aborting->suspended_aborting [color="blue",label="suspend"]; + aborting->failed [color="red",label="failure"]; + aborting->failed [color="blue",label="fail"]; + suspended_aborting->aborting [color="blue",label="resume"]; + suspended_aborting->failed [color="blue",label="fail"]; + failed->deleted [color="blue",label="delete"]; + expired->deleted [color="blue",label="delete"]; + aborted->deleted [color="blue",label="delete"]; + done->deleted [color="blue",label="delete"]; +} diff --git a/images/transaction-common-states.svg b/images/transaction-common-states.svg @@ -0,0 +1,16 @@ +<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 551.0166702270508 470" width="551.0166702270508" height="470"> + <!-- svg-source:excalidraw --> + <!-- payload-type:application/vnd.excalidraw+json --><!-- payload-version:2 --><!-- payload-start -->eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO1dXVPbSlx1MDAxMn3Pr6C4r7HuTM/3fSNcdTAwMDHzXHUwMDE1IFx1MDAxMMdcdTAwMTC2tm45tlxmwsJ2bDlAbuW/b49cdTAwMDFLlixh2bJcdTAwMTG7K1dcdTAwMDWQZE1L6nPmdPfM5J93XHUwMDFiXHUwMDFim8FD3938a2PTvW82fK81aNxtvrf7f7qDodfr4iFcdTAwMTj/PeyNXHUwMDA2zfGZ10HQXHUwMDFm/vXnn+E3nGbv9vFbru/eut1giOf9XHUwMDBi/97Y+Gf8b7RcdTAwMWTf9/pDd3z6+ECkIcLie4973XGjklx1MDAxMcaVXHUwMDEwZHKCN9zGxlx1MDAwMreFR9tccn/ohkfsrs3Dmlx1MDAxZlx1MDAxOHn18/iXW/Ol73Xae6pcdTAwMTe22vZ8/0vw4D/eUaN5PVx1MDAxYURsXHUwMDFhXHUwMDA2g17HPfdawTVcdTAwMWWnsf2T71xye3j/4bdcdTAwMDa90dV111x1MDAxZNq7XHUwMDBmXHLt9Vx1MDAxYk0veLDXIeHeRvdqfI1wzz3+VdHCXHUwMDAxMdllv1RRjoi1/7Hn91x1MDAwNrb9P8h4XHUwMDBiLfjeaHau0Ixua3JOMGh0h/3GXHUwMDAw30p43t3TnUHY/LXrXV1cdTAwMDfT+4bu+PEqXHUwMDAzVFx1MDAwMFx1MDAwM5hcdTAwMWOwbfT3W+PX/O/o/XdbT/ffXHUwMDFk+X5olj2wXHUwMDEzd42oe0Re3GB4eulcdTAwMDJcdTAwMWN+uzlcdTAwMGVutlx1MDAwZW4u2dHoeGL6lC81XHUwMDA2g97d5uTI76ffQotG/Vbj0UWo1PZRaWaI4pPjvtftxI31e81O6FXjvb/fz/blwL1cdTAwMGZmOXKkhZhcdTAwMWZTXHUwMDEwmlBOuZzbkZX6dNA/q/bL7ruMJ1xcl8qVea6iXHUwMDBlZbhRMFqDpjDDkVnckSlnwlx1MDAwMFxiWXpPfp913ZODz9Uz9/JHcH65W6tcdTAwMWV/van2g89cdTAwMDVcXPdcXPZcdTAwMGY++e27mrd3rPbO2lx1MDAwN3dcdTAwMWbd81x1MDAwMq47+kXcTmX7S/2m/9BcdTAwMWHd3Fx1MDAxZtZujltcdTAwMDVcXPdbN6h//vt2UK/UmsPLykdV+/u7LOC6ny+q9+zIPTy4MJ9cdTAwMGV2L7fPPpPOnPa+yECUMiGMysFAIex73eCL98ud5mi7t9q49fyH56760UBLTWhg3+22vO7V5tSBLd+7sjy16bvtaVx1MDAwMlx1MDAwYjzs0yeHg16EdZrYUMPruoP9Vtzg3sC78rpccr+W1ijepbv3jEtErliIVqkh8b3PvCpAXHUwMDEz0GDm11x1MDAwN1Whj/Z3brdKT6vAXHUwMDFktUZeXHUwMDA1R2rkVWRKXCK0MGFPlsGrUoJcdTAwMDKjWGj5KmlcdTAwMTXa/nl198pcZjv9+n7/28np913+UFx1MDAwNJ1cXHbYz52DXHUwMDFi70LfNlv1tqLt+odcdTAwMDKu2z06v6n6X1x1MDAxZuTJ1cn97Wjrm9c8uStM0KDPXHUwMDBiiFx1MDAwMm2ldNL43kOOWDefJFstiFBYqlCTklx1MDAxMmDamLlcdOVnh/Ba8+ao7ITCrU4zxFx1MDAxMCm4wi18XHUwMDA0Y25cdTAwMDGqXHUwMDFkboBPPquLPtBcdTAwMTIucVNUXHQwXHUwMDEw6Vx1MDAxNbM0nGTKWmXWQzZLaKKXtVx1MDAwMNNS6PVpgVav66ZcdTAwMDC3ic/CXHUwMDFkrFx1MDAwMLrTbVx1MDAxNlx1MDAwNNtIJFx1MDAxYddcdTAwMDGcXHUwMDExzpVcYlx1MDAxZupLsL0//XZyxqBadtgyalx1MDAxYzJGpFx1MDAxMpRcYlx1MDAxMkqAJ9hcdTAwMWFH08iHxywrXHUwMDBltlI7xMJWSG4wko1Yklx1MDAxOXpJSqmKxL2rRO2quvJdUv377qwx7JGL6k1/+4L6nY9zRlx1MDAxY3OwgVx1MDAwMVxuNIqV1XflbutcdTAwMTV68mijXHUwMDA1MYJIZVx1MDAwNHQ8boxcdTAwMTJ5KOFB77Yvd05LT1x0jDh4llx1MDAxMppjP1wimFxmUTd+5UQ4wmg++aiYZVx1MDAwNfbkypFcdTAwMTQpgWstOYI8fFx1MDAwNlx1MDAxOZRgpDRoXHUwMDFmXU9HvoRcbs+khCWSXHUwMDFi81CCijL9qimh3fD8dTNCvM2CXGJB6TRCYMCYYkLNnypcdTAwMTBHXHUwMDBmvzqdw72y80FF6Xhcblx1MDAxNlxiW2H5wCjUXHUwMDFjuZWA4EZcdTAwMTOMPdaD+1UlXHSXSMK+jHtcZutBrFx1MDAwZvfD0dCm7NZccv1cdTAwMTnN5kP/44OdXHUwMDAxf1x1MDAxNumBXHUwMDEyeoApZFWWI1WYnccvK1x1MDAxOVxi5Vx1MDAwMIbWxEhhKGXAp5mBOopayUC5oYajSNIx04qjXHSNOoRGLFx0XHK5XHUwMDBlX7U2VFxirqlhoCRE4oTnXHUwMDFjI1K2zUvmKd2EsH12XHUwMDE5eNrzO7yZOJm8VD1cXFxilsOgMVxiPniPafEpw54q5vtzXHUwMDE0rcdAbo6slVx1MDAxNeJcdTAwMTCmUG0xTlxykVx1MDAwNt9cdTAwMWbhkfOuXHUwMDFhffvgXHUwMDEzd4twe9mKRMVxumF8P0RzKiRcdTAwMThcdTAwMDKCMZFoVyba9Vx1MDAxYsPgY+/21lx1MDAwYvCBfu553SD+4MZPaMtcdTAwMDL62m0kqFx1MDAwM+2OXHUwMDFliyO/b6843Vx1MDAxNYS/bYTIXHUwMDE4/zH5/d/vZ56d6q52qyQ9Nbzeu+jP3KTFIyFKjLQ0QpVLkmP4Q3b3VFLOYtJcdTAwMDHG8SORo40yMcYyjiCRjcXsXG5cdItJ3m6qJYogyuFcYniMnShobtSMxCRVzCEp1jzpXHUwMDFjRfDrTNEwXHUwMDEzs3bGelx1MDAxNFx1MDAxMiGzXHUwMDE3z1hZXFxBXHUwMDFjIa0uXHUwMDE0glFccpRAkqEoTL9TWJCyXHUwMDEyXHUwMDEyfZqyOGVIl8RcdTAwMTImxqeKqqQhxDHRTSWf+1visEqqXHUwMDBi2y3pvEVxXHUwMDE4Yya+d1wivITFtWYk7MFfXCKx7OR7SUlMXHUwMDFhh2OIKVx1MDAxMP1KcKBhy4+JWplcdTAwMTGQwXfdYO7ixEVcdTAwMWQpXHUwMDE4XHUwMDE4QzEgo0JcdTAwMTk2S2pJXHUwMDFhteCRrIQ2QKSORM2vwFWor8RC1ZBcdTAwMDK4ylxuKkW01Fx1MDAxY7RNS1x1MDAxMa6SusYsRk6JyuBcdTAwMTRHcoIvXG7lXHUwMDA25dxcdTAwMDBcdTAwMDYmbI5m31x1MDAxMlx1MDAxNaX7pN0qY3csin5cdTAwMDSk0lx1MDAwZmjL6pFq50vkkz3MoKTkXHUwMDAzwFx1MDAxY1tcdTAwMWVixqZkpFx1MDAwZXu6R/bR0pFcdTAwMDS7QDtqQKDKTa9cdTAwMTItq6GMQC2HJlx1MDAxMDuQXHUwMDA0+/9QXHUwMDFmTZhIXHUwMDEzh0lDOeJcdTAwMWb7XHUwMDA2Jlx1MDAxMqyE94skytlrslx1MDAxMpXIS6tUUPVu9ZDI81x1MDAxZtv76sc17Xzyd47q1dlUgeJcdTAwMTgwYLdcdTAwMTl/w8Ihj6GIcfAotyNxUHVyXGZcdTAwMGJcdTAwMTckrMTYqGmi1ETawIfbcUJcdTAwMDbjpP+y+C/Vc+2W8NnClFPGoGEmOD5xkYO8slx1MDAwYqAlJS98mo6RiDhU6YpFXHUwMDFj/Ek58Vx1MDAxNSonjFWUklx1MDAxMiR2VkxcdFAzXHUwMDA2vlGpksrJclx1MDAxNGo9xV41zKOg5CqlU1x1MDAxNiOgclx1MDAxMlx1MDAxOFlZalx1MDAxMohccpDh8MRIeLVcdTAwMThcdTAwMTMlRmdMM1x1MDAxMTBCXHUwMDA016izXHUwMDE115olmUgkmn1LTJTulHarjP2xKP7hPJV/gKAgRlx1MDAwN+fzR27Z1dbS8o9yiFx1MDAxNoRqQOKXepp/qMign6aBXHUwMDA2NJZcbtxcdTAwMTSG4ZJTovBfmDXuXHUwMDE2e6JcdTAwMTdSTopcdTAwMTnDXHUwMDE4vGbGiVx1MDAxOHyAsNCA1Fx1MDAwMqjIRnFcdTAwMTjCoThcdTAwMTLPP1x1MDAxM5SgXHUwMDE2ZKL4oJBYs0A40VQyQKxcdTAwMTI5Q5wl231LVFRJ91C7JX0zJy+lXHUwMDE18llqXHUwMDFkXHUwMDFmMWpcdTAwMTRcdTAwMTBlwjNeYqX9o2NNq3VZdlwiqsjkVCquV6h+XHUwMDE0YNSIolx1MDAwYpGriCCRNFBWIZ9xY+zAozx0k13Iz+JcdTAwMTWBnre+0XHDUbNpLZ46sPqCeKzRgsrhXHUwMDE51XBGbbCo1Pwgylx1MDAxZfBUUkRhUFx1MDAxMZ9FQ7NcdTAwMTKxy/bnyEuzOnBcdTAwMWHHXHUwMDEwYJCJ/i1JnnGxhZe1XHUwMDE1ZZG5O2tPvHKMbMFWZ4jk3PYuM8JcdTAwMDcnqeSL6LaxWa1cdTAwMThRlluAq2SvnaxHvaVeO+KGdkNcdTAwMDfM2S2nUkq0qlx1MDAxOOeUceJEyVx1MDAxY4We7EFaJeVcdTAwMTTiaIVhN+XScMa45tND8qmhXHUwMDE5XHUwMDA0s3SJXHUwMDFhL66ZUiiBJD5sXHUwMDFh5r0jJepEsoJhLGlcZuSaqLeSkvQqc1x1MDAxNVm1YJu901x1MDAwNqid26g5YURHTnouSS/GNC+NmpFcdTAwMDI4YkLbMVlCJds1MyjuLXFNqkfarYLOWFx1MDAxOPXI1Fwij1x1MDAxMFx1MDAwMEbLXHUwMDFjY/uyZ3SUlHlslUdcdTAwMWImKfJcdTAwMGY3XHUwMDE4csdqzFx1MDAwNlx1MDAxY2LHOTKmhVx1MDAxMkrFLSuwylx1MDAwM46RXHUwMDFjga1tdipqSEhDhDlcdTAwMDbDcZSaWqPaNIlAgqOVyphXzaBS7LDUQuFF8WVcdTAwMWWq8c1qfIFcdTAwMWGQrMNcdTAwMDFcdTAwMDRcdTAwMWKROlx1MDAwZkNzQVEuJCCtLJrTyMiuXHUwMDEyR4JcdTAwMDE7P1x1MDAxMewgXHUwMDFljPRcdTAwMTJmvG2+SnVdu1WSXpuTvtJcdTAwMTJcdTAwMWE8dZBcdTAwMWZcdTAwMTWIV06pnl83XdWPto9/9Mtf2ZEmmdFg6bT0OvlcZsSTwEiswIlcdJklXHUwMDFiqWlow//zXHUwMDE580NcYtLTXHUwMDE5XHUwMDA0qFx1MDAwMaVzVEpV8GVvu9ZVZYdcdTAwMTB2XG6JXGZcdTAwMDZkTe5ZNoXBUUTYkZCaY3SMinm+pUBcdTAwMDCVtbRZ4jxjNlx1MDAxNlx1MDAwN5GQdLG650IgcrE7XHUwMDFhrFx1MDAxN0KxJotcdTAwMDFQZGpRXHUwMDFjQFx1MDAxOJ5cdEaRO+dcdTAwMDZQcHt4cVU/KH1cbpDJRFadRlJcdTAwMTTlgI/VfShGo/W/VcJcdTAwMDfjUbNQ4u9/XHUwMDFhPip9srlGKUm5yVEpr41u+6SmS1x1MDAxZnNWdELCqaylKZdOcFx0m05gXGZcdTAwMDNcdTAwMTBpZ6fNt1x1MDAxMFx1MDAxNbq1XHUwMDE0dE2dj7ZyfY1cbm48W3LdXG4u1mhRXHUwMDBiL6VDiDG7Mlx1MDAxMaXz53A+NVx1MDAxYkc3Nz/cskOI0ziCTPqSXGbL4lx1MDAwN3s7bos7VFx1MDAwMEJIz8hcdTAwMGbP6H2sT+O3cmViXHUwMDE2x48h0Vx1MDAxOHDV+Fx1MDAxObjD0W3a+kcrgk+8zWLQk5VC4EJKO8tpbvA0XHUwMDBmt7buTlx1MDAwZptlXHUwMDA3XHUwMDBmRueJdVx1MDAxMFfaXHUwMDAxcenQ3GuaIII4Z1x1MDAxMtYyJmKsXHUwMDEz+UJj01x1MDAxN18xaL1cdTAwMDCKNZlcdTAwMGY/XHUwMDE5S41Tlo4hyqStR8P8XHUwMDFhLju3W1JA2YX+XHUwMDA0UWLy0dPgMtSJLlx1MDAxZZSxPsCySJsxSS05QY1cbju6cU2LhiyxXHUwMDAy8Pus6y6xfljmdZdYXHUwMDEy9em3l0ojeaLETFCmlvUoSc1KcIlqXHUwMDAxIEdWL/tcdTAwMDWWXHUwMDE0kXaQkl1FXHUwMDA3mMRcdTAwMGbocGbNU8bcOFx1MDAwMrgxlFx0gzEmWVx1MDAxZFwiKUGpaiRwO217rMaTXHUwMDEwRYGppWKCXHUwMDFhQeya1nHEXHUwMDFhrVx1MDAwNO7P1Vx1MDAxM1x1MDAxNj95XHUwMDBiXGLNs9x/5IlcdTAwMTYw/Z0zfIhcdTAwMDJfhsB/lE7OOjeONpH3rVx1MDAxN6zjzV1btONcdTAwMTDQXHUwMDE4XHUwMDE0+FQrXHUwMDA26EKQXHUwMDFjIFxyXHUwMDBl2GVcdTAwMGI0szP2QUjCXHUwMDEzVr2lOl+6L9utXHUwMDEyd+Pwcu+iP9PobOA2g0c0z6A0kfr/maD+YHZcdTAwMTmVSCnjJUrbue9cdTAwMWXsfVx1MDAxNec7XHUwMDFm6rXTk3PYv+Q7O2WnNKZcdTAwMWNcdTAwMDahxFx1MDAxMDKx2rBx7FrEk08qpS27XGKR0Fx1MDAwZYtudFZCSTg6elx1MDAwZU+WNzBqxVxiXHUwMDE5oLh1TLPXXHUwMDA3ppFcdTAwMTWol+x5M11cdTAwMTVS9bDSRFGQeSb//GrtfjK3RPDL092ds/bXi7r0Su+plDo64qrx9XWBrGt9XVxyzlxmRVxmXHRJjLGpIdi/rSXZSbUxkGfpq8VdkaVXp7Cn1DarlSO97lx1MDAxZvUuf2xVR2bv9Pvp/nH9uNl7XHUwMDAzvpi6XHUwMDA2+/PCroSK8LPC/1x1MDAwZYJMM+KsJdq5Y9Mkk21GTYvZlFS+xUVcdTAwMTZ3VMNcdTAwMTTkj1bePemHzUa//yXAS07k1uZPz737kHxuf7THm1xypcZubn3JXHUwMDFki9jf737/XHUwMDA3Yp+BqSJ9<!-- payload-end --> + <defs> + <style class="style-fonts"> + @font-face { + font-family: "Virgil"; + src: url("https://excalidraw.com/Virgil.woff2"); + } + @font-face { + font-family: "Cascadia"; + src: url("https://excalidraw.com/Cascadia.woff2"); + } + </style> + </defs> + <rect x="0" y="0" width="551.0166702270508" height="470" fill="#ffffff"></rect><g stroke-linecap="round" transform="translate(14 223.31818181818184) rotate(0 10 10)"><path d="M20 10 C20 10.58, 19.95 11.17, 19.85 11.74 C19.75 12.31, 19.59 12.88, 19.4 13.42 C19.2 13.96, 18.95 14.5, 18.66 15 C18.37 15.5, 18.03 15.98, 17.66 16.43 C17.29 16.87, 16.87 17.29, 16.43 17.66 C15.98 18.03, 15.5 18.37, 15 18.66 C14.5 18.95, 13.96 19.2, 13.42 19.4 C12.88 19.59, 12.31 19.75, 11.74 19.85 C11.17 19.95, 10.58 20, 10 20 C9.42 20, 8.83 19.95, 8.26 19.85 C7.69 19.75, 7.12 19.59, 6.58 19.4 C6.04 19.2, 5.5 18.95, 5 18.66 C4.5 18.37, 4.02 18.03, 3.57 17.66 C3.13 17.29, 2.71 16.87, 2.34 16.43 C1.97 15.98, 1.63 15.5, 1.34 15 C1.05 14.5, 0.8 13.96, 0.6 13.42 C0.41 12.88, 0.25 12.31, 0.15 11.74 C0.05 11.17, 0 10.58, 0 10 C0 9.42, 0.05 8.83, 0.15 8.26 C0.25 7.69, 0.41 7.12, 0.6 6.58 C0.8 6.04, 1.05 5.5, 1.34 5 C1.63 4.5, 1.97 4.02, 2.34 3.57 C2.71 3.13, 3.13 2.71, 3.57 2.34 C4.02 1.97, 4.5 1.63, 5 1.34 C5.5 1.05, 6.04 0.8, 6.58 0.6 C7.12 0.41, 7.69 0.25, 8.26 0.15 C8.83 0.05, 9.42 0, 10 0 C10.58 0, 11.17 0.05, 11.74 0.15 C12.31 0.25, 12.88 0.41, 13.42 0.6 C13.96 0.8, 14.5 1.05, 15 1.34 C15.5 1.63, 15.98 1.97, 16.43 2.34 C16.87 2.71, 17.29 3.13, 17.66 3.57 C18.03 4.02, 18.37 4.5, 18.66 5 C18.95 5.5, 19.2 6.04, 19.4 6.58 C19.59 7.12, 19.75 7.69, 19.85 8.26 C19.95 8.83, 19.97 9.71, 20 10 C20.03 10.29, 20.03 9.71, 20 10" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(133.5 214.81818181818184) rotate(0 35.56666564941406 11.5)"><text x="0" y="0" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="text-before-edge">pending</text></g><g transform="translate(424 214.81818181818184) rotate(0 36.34166717529297 11.5)"><text x="0" y="0" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="text-before-edge">aborting</text></g><g transform="translate(143.50909065477774 12.325757575757592) rotate(0 22.233333587646484 11.5)"><text x="22.233333587646484" y="0" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="text-before-edge">done</text></g><g transform="translate(418.2924247510506 11) rotate(0 34.03333282470703 11.5)"><text x="0" y="0" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="text-before-edge">aborted</text></g><g transform="translate(429.35075846585363 436.41666666666674) rotate(0 23.808332443237305 11.5)"><text x="0" y="0" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="text-before-edge">failed</text></g><g transform="translate(21 434.31818181818187) rotate(0 48.90833282470703 11.5)"><text x="0" y="0" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="text-before-edge">suspended</text></g><g stroke-linecap="round"><g transform="translate(41.982890340886755 232.53354496737632) rotate(0 42.75855482955662 -0.9457774096638123)"><path d="M0 0 C14.25 -0.32, 71.26 -1.58, 85.52 -1.89 M0 0 C14.25 -0.32, 71.26 -1.58, 85.52 -1.89" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(41.982890340886755 232.53354496737632) rotate(0 42.75855482955662 -0.9457774096638123)"><path d="M57.56 8.99 C68.59 4.7, 79.63 0.4, 85.52 -1.89 M57.56 8.99 C67.72 5.04, 77.87 1.08, 85.52 -1.89" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(41.982890340886755 232.53354496737632) rotate(0 42.75855482955662 -0.9457774096638123)"><path d="M57.11 -11.53 C68.32 -7.72, 79.53 -3.92, 85.52 -1.89 M57.11 -11.53 C67.43 -8.03, 77.75 -4.53, 85.52 -1.89" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(135.48434363799794 250.31818181818187) rotate(0 -38.740049206424885 86.50000000000001)"><path d="M0 0 C-12.91 28.83, -64.57 144.17, -77.48 173 M0 0 C-12.91 28.83, -64.57 144.17, -77.48 173" stroke="#364fc7" stroke-width="1" fill="none"></path></g><g transform="translate(135.48434363799794 250.31818181818187) rotate(0 -38.740049206424885 86.50000000000001)"><path d="M-75.32 143.08 C-75.83 150.16, -76.34 157.25, -77.48 173 M-75.32 143.08 C-75.84 150.23, -76.35 157.38, -77.48 173" stroke="#364fc7" stroke-width="1" fill="none"></path></g><g transform="translate(135.48434363799794 250.31818181818187) rotate(0 -38.740049206424885 86.50000000000001)"><path d="M-56.59 151.47 C-61.54 156.56, -66.48 161.66, -77.48 173 M-56.59 151.47 C-61.58 156.61, -66.58 161.76, -77.48 173" stroke="#364fc7" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(168.6733504175421 204.31818181818184) rotate(0 0.8266495824578968 -80.75)"><path d="M0 0 C0.28 -26.92, 1.38 -134.58, 1.65 -161.5 M0 0 C0.28 -26.92, 1.38 -134.58, 1.65 -161.5" stroke="#2b8a3e" stroke-width="1" fill="none"></path></g><g transform="translate(168.6733504175421 204.31818181818184) rotate(0 0.8266495824578968 -80.75)"><path d="M11.62 -133.21 C9.32 -139.74, 7.02 -146.27, 1.65 -161.5 M11.62 -133.21 C8.28 -142.71, 4.93 -152.21, 1.65 -161.5" stroke="#2b8a3e" stroke-width="1" fill="none"></path></g><g transform="translate(168.6733504175421 204.31818181818184) rotate(0 0.8266495824578968 -80.75)"><path d="M-8.9 -133.42 C-6.46 -139.9, -4.02 -146.38, 1.65 -161.5 M-8.9 -133.42 C-5.35 -142.85, -1.81 -152.28, 1.65 -161.5" stroke="#2b8a3e" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(322.76053964946817 144.21170891263012) rotate(0 47.619730175265914 40.184570842716774)"><path d="M0 0 C15.87 13.39, 79.37 66.97, 95.24 80.37 M0 0 C15.87 13.39, 79.37 66.97, 95.24 80.37" stroke="#364fc7" stroke-width="1" fill="none"></path></g><g transform="translate(322.76053964946817 144.21170891263012) rotate(0 47.619730175265914 40.184570842716774)"><path d="M67.08 70.03 C73.71 72.46, 80.33 74.9, 95.24 80.37 M67.08 70.03 C74.85 72.88, 82.62 75.74, 95.24 80.37" stroke="#364fc7" stroke-width="1" fill="none"></path></g><g transform="translate(322.76053964946817 144.21170891263012) rotate(0 47.619730175265914 40.184570842716774)"><path d="M80.31 54.35 C83.83 60.47, 87.34 66.6, 95.24 80.37 M80.31 54.35 C84.43 61.53, 88.55 68.71, 95.24 80.37" stroke="#364fc7" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(455.2111686673312 206.31818181818184) rotate(0 0.2888313326687637 -83.75)"><path d="M0 0 C0.1 -27.92, 0.48 -139.58, 0.58 -167.5 M0 0 C0.1 -27.92, 0.48 -139.58, 0.58 -167.5" stroke="#2b8a3e" stroke-width="1" fill="none"></path></g><g transform="translate(455.2111686673312 206.31818181818184) rotate(0 0.2888313326687637 -83.75)"><path d="M10.74 -139.27 C8.32 -146.01, 5.89 -152.74, 0.58 -167.5 M10.74 -139.27 C8.28 -146.12, 5.81 -152.96, 0.58 -167.5" stroke="#2b8a3e" stroke-width="1" fill="none"></path></g><g transform="translate(455.2111686673312 206.31818181818184) rotate(0 0.2888313326687637 -83.75)"><path d="M-9.78 -139.34 C-7.31 -146.06, -4.84 -152.78, 0.58 -167.5 M-9.78 -139.34 C-7.27 -146.17, -4.76 -152.99, 0.58 -167.5" stroke="#2b8a3e" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(456.3350182053682 246.31818181818184) rotate(0 -0.8350182053682147 91.50000000000001)"><path d="M0 0 C-0.28 30.5, -1.39 152.5, -1.67 183 M0 0 C-0.28 30.5, -1.39 152.5, -1.67 183" stroke="#c92a2a" stroke-width="1" fill="none"></path></g><g transform="translate(456.3350182053682 246.31818181818184) rotate(0 -0.8350182053682147 91.50000000000001)"><path d="M-11.67 154.72 C-9.33 161.34, -6.99 167.97, -1.67 183 M-11.67 154.72 C-8.06 164.93, -4.45 175.13, -1.67 183" stroke="#c92a2a" stroke-width="1" fill="none"></path></g><g transform="translate(456.3350182053682 246.31818181818184) rotate(0 -0.8350182053682147 91.50000000000001)"><path d="M8.85 154.9 C6.38 161.49, 3.92 168.07, -1.67 183 M8.85 154.9 C5.05 165.05, 1.25 175.19, -1.67 183" stroke="#c92a2a" stroke-width="1" fill="none"></path></g></g><mask></mask><g transform="translate(93 82.31818181818184) rotate(0 36.25833511352539 11.5)"><text x="0" y="0" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#2b8a3e" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="text-before-edge">success</text></g><g stroke-linecap="round"><g transform="translate(216 247.31818181818184) rotate(0 103.5 90.5)"><path d="M0 0 C34.5 30.17, 172.5 150.83, 207 181 M0 0 C34.5 30.17, 172.5 150.83, 207 181" stroke="#c92a2a" stroke-width="1" fill="none"></path></g><g transform="translate(216 247.31818181818184) rotate(0 103.5 90.5)"><path d="M179.02 170.17 C189.65 174.28, 200.27 178.39, 207 181 M179.02 170.17 C188.5 173.84, 197.98 177.51, 207 181" stroke="#c92a2a" stroke-width="1" fill="none"></path></g><g transform="translate(216 247.31818181818184) rotate(0 103.5 90.5)"><path d="M192.53 154.72 C198.03 164.7, 203.52 174.68, 207 181 M192.53 154.72 C197.43 163.62, 202.34 172.53, 207 181" stroke="#c92a2a" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(100.12276146943348 422.31818181818187) rotate(0 35.791889863028594 -87.5)"><path d="M0 0 C11.93 -29.17, 59.65 -145.83, 71.58 -175 M0 0 C11.93 -29.17, 59.65 -145.83, 71.58 -175" stroke="#364fc7" stroke-width="1" fill="none"></path></g><g transform="translate(100.12276146943348 422.31818181818187) rotate(0 35.791889863028594 -87.5)"><path d="M70.41 -145.02 C70.81 -155.4, 71.22 -165.77, 71.58 -175 M70.41 -145.02 C70.8 -155, 71.19 -164.97, 71.58 -175" stroke="#364fc7" stroke-width="1" fill="none"></path></g><g transform="translate(100.12276146943348 422.31818181818187) rotate(0 35.791889863028594 -87.5)"><path d="M51.41 -152.79 C58.39 -160.48, 65.37 -168.16, 71.58 -175 M51.41 -152.79 C58.13 -160.18, 64.84 -167.57, 71.58 -175" stroke="#364fc7" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(323.14361727490984 138.80380843242415) rotate(0 46.482340426374904 -51.975306594086966)"><path d="M0 0 C15.49 -17.33, 77.47 -86.63, 92.96 -103.95 M0 0 C15.49 -17.33, 77.47 -86.63, 92.96 -103.95" stroke="#364fc7" stroke-width="1" fill="none"></path></g><g transform="translate(323.14361727490984 138.80380843242415) rotate(0 46.482340426374904 -51.975306594086966)"><path d="M81.82 -76.1 C84.79 -83.51, 87.75 -90.92, 92.96 -103.95 M81.82 -76.1 C84.2 -82.04, 86.57 -87.98, 92.96 -103.95" stroke="#364fc7" stroke-width="1" fill="none"></path></g><g transform="translate(323.14361727490984 138.80380843242415) rotate(0 46.482340426374904 -51.975306594086966)"><path d="M66.52 -89.78 C73.56 -93.55, 80.59 -97.32, 92.96 -103.95 M66.52 -89.78 C72.16 -92.8, 77.8 -95.82, 92.96 -103.95" stroke="#364fc7" stroke-width="1" fill="none"></path></g></g><mask></mask><g transform="translate(468.5 99.81818181818184) rotate(0 36.25833511352539 11.5)"><text x="0" y="0" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#2b8a3e" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="text-before-edge">success</text></g><g transform="translate(286 354.31818181818187) rotate(0 21.049999237060547 11.5)"><text x="0" y="0" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#c92a2a" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="text-before-edge">error</text></g><g transform="translate(465.5 332.81818181818187) rotate(0 21.049999237060547 11.5)"><text x="0" y="0" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#c92a2a" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="text-before-edge">error</text></g><g transform="translate(10 308.31818181818187) rotate(0 37.79166793823242 11.5)"><text x="0" y="0" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#364fc7" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="text-before-edge">suspend</text></g><g transform="translate(140.5 327.81818181818187) rotate(0 33.20000076293945 11.5)"><text x="0" y="0" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#364fc7" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="text-before-edge">resume</text></g><g transform="translate(227 153.31818181818184) rotate(0 23.058332443237305 11.5)"><text x="0" y="0" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#364fc7" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="text-before-edge">abort</text></g><g stroke-linecap="round" transform="translate(317.75757575757575 138.83333333333337) rotate(0 2.5 2.5)"><path d="M5 2.5 C5 2.64, 4.99 2.79, 4.96 2.93 C4.94 3.08, 4.9 3.22, 4.85 3.36 C4.8 3.49, 4.74 3.62, 4.67 3.75 C4.59 3.88, 4.51 4, 4.42 4.11 C4.32 4.22, 4.22 4.32, 4.11 4.42 C4 4.51, 3.88 4.59, 3.75 4.67 C3.62 4.74, 3.49 4.8, 3.36 4.85 C3.22 4.9, 3.08 4.94, 2.93 4.96 C2.79 4.99, 2.64 5, 2.5 5 C2.36 5, 2.21 4.99, 2.07 4.96 C1.92 4.94, 1.78 4.9, 1.64 4.85 C1.51 4.8, 1.38 4.74, 1.25 4.67 C1.12 4.59, 1 4.51, 0.89 4.42 C0.78 4.32, 0.68 4.22, 0.58 4.11 C0.49 4, 0.41 3.88, 0.33 3.75 C0.26 3.62, 0.2 3.49, 0.15 3.36 C0.1 3.22, 0.06 3.08, 0.04 2.93 C0.01 2.79, 0 2.64, 0 2.5 C0 2.36, 0.01 2.21, 0.04 2.07 C0.06 1.92, 0.1 1.78, 0.15 1.64 C0.2 1.51, 0.26 1.38, 0.33 1.25 C0.41 1.12, 0.49 1, 0.58 0.89 C0.68 0.78, 0.78 0.68, 0.89 0.58 C1 0.49, 1.12 0.41, 1.25 0.33 C1.38 0.26, 1.51 0.2, 1.64 0.15 C1.78 0.1, 1.92 0.06, 2.07 0.04 C2.21 0.01, 2.36 0, 2.5 0 C2.64 0, 2.79 0.01, 2.93 0.04 C3.08 0.06, 3.22 0.1, 3.36 0.15 C3.49 0.2, 3.62 0.26, 3.75 0.33 C3.88 0.41, 4 0.49, 4.11 0.58 C4.22 0.68, 4.32 0.78, 4.42 0.89 C4.51 1, 4.59 1.12, 4.67 1.25 C4.74 1.38, 4.8 1.51, 4.85 1.64 C4.9 1.78, 4.94 1.92, 4.96 2.07 C4.99 2.21, 4.99 2.43, 5 2.5 C5.01 2.57, 5.01 2.43, 5 2.5" stroke="#364fc7" stroke-width="1" fill="none"></path></g><g stroke-linecap="round"><g transform="translate(215.3906236363281 211.29319045868777) rotate(0 50.64812410532706 -33.43367597517795)"><path d="M0 0 C16.88 -11.14, 84.41 -55.72, 101.3 -66.87 M0 0 C16.88 -11.14, 84.41 -55.72, 101.3 -66.87" stroke="#364fc7" stroke-width="1" fill="none"></path></g><g transform="translate(215.3906236363281 211.29319045868777) rotate(0 50.64812410532706 -33.43367597517795)"><path d="M83.42 -42.77 C89.72 -51.26, 96.01 -59.75, 101.3 -66.87 M83.42 -42.77 C89.61 -51.12, 95.8 -59.46, 101.3 -66.87" stroke="#364fc7" stroke-width="1" fill="none"></path></g><g transform="translate(215.3906236363281 211.29319045868777) rotate(0 50.64812410532706 -33.43367597517795)"><path d="M72.12 -59.9 C82.39 -62.35, 92.67 -64.81, 101.3 -66.87 M72.12 -59.9 C82.22 -62.31, 92.32 -64.72, 101.3 -66.87" stroke="#364fc7" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round" transform="translate(136.57575757575756 10.909090909090935) rotate(0 29.166666666666657 12.916666666666671)"><path d="M0 0 C18.84 0, 37.67 0, 58.33 0 M0 0 C22.09 0, 44.18 0, 58.33 0 M58.33 0 C58.33 8.9, 58.33 17.8, 58.33 25.83 M58.33 0 C58.33 6.77, 58.33 13.54, 58.33 25.83 M58.33 25.83 C39.95 25.83, 21.56 25.83, 0 25.83 M58.33 25.83 C40.09 25.83, 21.84 25.83, 0 25.83 M0 25.83 C0 16.47, 0 7.11, 0 0 M0 25.83 C0 17.29, 0 8.75, 0 0" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(411.0757575757576 10) rotate(0 41.25 12.5)"><path d="M0 0 C26.08 0, 52.17 0, 82.5 0 M0 0 C29.89 0, 59.79 0, 82.5 0 M82.5 0 C82.5 9.92, 82.5 19.84, 82.5 25 M82.5 0 C82.5 7.27, 82.5 14.54, 82.5 25 M82.5 25 C65.79 25, 49.07 25, 0 25 M82.5 25 C51.76 25, 21.03 25, 0 25 M0 25 C0 16.54, 0 8.08, 0 0 M0 25 C0 19.95, 0 14.9, 0 0" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(417.74242424242425 435.83333333333337) rotate(0 35.416666666666686 12.083333333333314)"><path d="M0 0 C23.12 0, 46.24 0, 70.83 0 M0 0 C26.44 0, 52.89 0, 70.83 0 M70.83 0 C70.83 8.75, 70.83 17.5, 70.83 24.17 M70.83 0 C70.83 4.89, 70.83 9.78, 70.83 24.17 M70.83 24.17 C44.44 24.17, 18.05 24.17, 0 24.17 M70.83 24.17 C54.46 24.17, 38.08 24.17, 0 24.17 M0 24.17 C0 15.54, 0 6.91, 0 0 M0 24.17 C0 16.22, 0 8.27, 0 0" stroke="#000000" stroke-width="1" fill="none"></path></g></svg> +\ No newline at end of file diff --git a/images/transaction-deposit-states.dot b/images/transaction-deposit-states.dot @@ -0,0 +1,44 @@ +digraph G { + + initial[label="", shape="circle", xlabel="deposit"]; + pending_deposit[label="deposit"]; + pending_track[label="track"]; + pending_kyc[label="kyc"]; + pending_aml[label="aml"]; + aborting_refresh[label="refresh", style=dashed]; + aborting_refund[label="refund", style=dashed]; + done[label="done", shape="box"]; + aborted[label="aborted", shape="box", style=dashed]; + + subgraph { + rank=same; + done; aborted; + } + + subgraph { + rank=same; + pending_track; aborting_refund; + } + + subgraph { + rank=same; + pending_deposit; pending_kyc; pending_aml; + } + + initial->pending_deposit; + + aborting_refund->aborting_refresh [color=green]; + aborting_refresh->aborted [color=green]; + + pending_deposit->pending_track [color=green]; + pending_deposit->aborting_refund [color="red"]; + pending_deposit->aborting_refund [color="blue", style=dashed]; + + pending_track->aborting_refund [color="blue", style=dashed]; + pending_track->done [color=green]; + pending_track->pending_kyc [color=red]; + pending_track->pending_aml [color=red]; + + pending_kyc->pending_track [color="green"]; + pending_aml->pending_track [color="green"]; +} diff --git a/images/transaction-payment-states.dot b/images/transaction-payment-states.dot @@ -0,0 +1,48 @@ +digraph G { + initial[label="", shape="circle", xlabel="pay merchant"]; + pending_dp[label="claim-proposal"]; + pending_sp[label="submit-payment"]; + pending_ar[label="auto-refund"]; + pending_re[label="rebind-session"]; + pending_cr[label="check-refund"]; + pending_accept_refunds[label="accept-refund"]; + aborting_pi[label="payment-incomplete", style=dashed]; + aborted[label="aborted", shape="box", style=dashed]; + dialog_proposal[label="dialog(merchant-order-proposed)", shape="box"]; + done[label="done", shape="box"]; + + subgraph { + rank=same; + done; aborted; pending_re; + } + + subgraph { + pending_ar; pending_sp; + } + + initial -> pending_dp; + + pending_dp -> dialog_proposal [color=green]; + + dialog_proposal -> pending_sp [color=blue]; + + pending_sp -> pending_ar [color=green]; + pending_sp -> aborting_pi [color=blue,style=dashed]; + + aborting_pi->done [color=red]; + aborting_pi->aborted [color=green]; + + pending_ar -> done [color=green, label="time over"]; + + pending_ar -> pending_accept_refunds; + + done -> pending_cr [color=blue]; + done -> pending_re [color=blue]; + + pending_cr -> done [color=green]; + pending_cr -> pending_accept_refunds [color=green]; + + pending_accept_refunds -> done [color=green]; + + pending_re -> done [color=green]; +} diff --git a/images/transaction-pull-credit-states.dot b/images/transaction-pull-credit-states.dot @@ -0,0 +1,43 @@ +digraph G { + initial[label="", shape="circle"]; + pending_create[label="purse-create"]; + pending_qr[label="ready"]; + aborting_delete[label="delete-purse", style=dashed]; + pending_withdraw[label="withdraw"]; + pending_kyc[label="kyc"]; + pending_aml[label="aml"]; + + aborted[label="aborted", shape="box", style=dashed]; + done[label="done", shape="box"]; + +// subgraph { +// rank = same; pending_withdraw; failed; +// } + + subgraph { + rank=max; + aborted; done; + } + + subgraph { + rank=same; + pending_create; pending_qr; + } + + initial->pending_create; + + pending_create->pending_qr; + + pending_qr->aborting_delete [color="blue", style=dashed]; + pending_qr->pending_withdraw [color=green]; + + aborting_delete->pending_withdraw [color="red"]; + aborting_delete->aborted [color=green]; + + pending_withdraw->done [color=green]; + pending_withdraw->pending_kyc [color=red]; + pending_withdraw->pending_aml [color=red]; + + pending_kyc->pending_withdraw [color="green"]; + pending_aml->pending_withdraw [color="green"]; +} diff --git a/images/transaction-pull-debit-states.dot b/images/transaction-pull-debit-states.dot @@ -0,0 +1,34 @@ +digraph G { + + initial[label="", shape="circle"]; + pending_download[label="download"]; + pending_user[label="monolog", shape="box"]; + + pending_deposit[label="deposit"]; + aborting_refresh[label="refresh", style=dashed]; + + aborted[label="aborted", shape="box", style=dashed]; + done[label="done", shape="box"]; + + subgraph { + rank=same; + done; aborted; + } + + subgraph { + rank=same; + pending_download; + pending_user; + } + + initial->pending_download; + + pending_download->pending_user [color=green]; + + pending_user->pending_deposit [color="blue"]; + + pending_deposit->done [color=green]; + pending_deposit->aborting_refresh [color=red]; + + aborting_refresh->aborted; +} diff --git a/images/transaction-push-credit-states.dot b/images/transaction-push-credit-states.dot @@ -0,0 +1,37 @@ +digraph G { + + initial[label="", shape="circle", xlabel="peer-push-credit"]; + pending_download[label="pending(download)"]; + pending_user[label="dialog", shape="box"]; + pending_merge[label="merge"]; + pending_merge_kyc[label="merge-kyc"]; + pending_withdraw[label="withdraw"]; + pending_withdraw_kyc[label="withdraw-kyc"]; + pending_withdraw_aml[label="withdraw-aml"]; + + subgraph { + rank=same; + pending_merge; pending_withdraw_kyc; pending_withdraw_aml; + } + + done[label="done", shape="box"]; + + initial->pending_download; + + pending_download->pending_user [color=green]; + + pending_user->pending_merge [color="blue", label="OK"]; + + pending_merge->pending_withdraw [color=green]; + pending_merge->pending_merge_kyc [color=red]; + + pending_merge_kyc->pending_merge [color="green"]; + + pending_withdraw->pending_withdraw_kyc [color=red]; + pending_withdraw->pending_withdraw_aml [color=red]; + pending_withdraw->done [color=green]; + + pending_withdraw_kyc->pending_withdraw [color="green"]; + + pending_withdraw_aml->pending_withdraw [color="green"]; +} diff --git a/images/transaction-push-debit-states.dot b/images/transaction-push-debit-states.dot @@ -0,0 +1,32 @@ +digraph G { + + initial[label="", shape="circle", xlabel="peer-push-debit"]; + pending_create[label="purse-create"]; + pending_qr[label="ready"]; + aborting_delete[label="delete-purse", style=dashed]; + aborting_refresh[label="refresh", style=dashed]; + done[label="done", shape="box"]; + aborted[label="aborted", shape="box"]; + + subgraph { + rank = same; done; aborted; + } + + subgraph { + rank=same; pending_qr;aborting_delete; aborting_refresh; + } + + initial->pending_create; + + pending_create->pending_qr [color=green]; + + pending_qr->aborting_delete [color="blue", style=dashed]; + pending_qr->aborting_refresh [xlabel="timeout"]; + pending_qr->done [color=green]; + + aborting_delete->aborting_refresh; + aborting_delete->done [color="red", label="already\nmerged"]; + aborting_delete->aborting_refresh [color="red"]; + + aborting_refresh->aborted; +} diff --git a/images/transaction-refresh-states.dot b/images/transaction-refresh-states.dot @@ -0,0 +1,27 @@ +digraph G { + + initial[label="", shape="circle", xlabel="refresh"]; + pending[label="refresh"]; + //aborting[label="refresh", style=dashed]; + //aborted[style=dashed]; + done[label="done", shape="box"]; + + subgraph { + rank=same; + pending; + // aborting; + } + + subgraph { + rank=same; + done; + //aborted; + } + + initial->pending; + + //pending -> aborting [color=blue, style=dashed, label="abort"]; + //aborting->aborted; + + pending->done [color=green]; +} diff --git a/images/transaction-refund-states.dot b/images/transaction-refund-states.dot @@ -0,0 +1,8 @@ +digraph G { + + initial[label="", shape="circle", xlabel="refund"]; + pending_accept[label="accept"]; + done[label="done", shape="box"]; + initial -> pending_accept; + pending_accept -> done; +} diff --git a/images/transaction-reward-states.dot b/images/transaction-reward-states.dot @@ -0,0 +1,11 @@ +digraph G { + initial[label="", shape="circle"]; + dialog_user[label="dialog(user)"]; + pending_pickup[label="pickup"]; + done[label="done", shape="box"]; + + initial -> dialog_user; + + dialog_user -> pending_pickup [color=blue, label="OK"]; + pending_pickup -> done [color=green]; +} diff --git a/images/transaction-withdrawal-states.dot b/images/transaction-withdrawal-states.dot @@ -0,0 +1,45 @@ +digraph G { + initial_manual[label="", xlabel="manual" shape="circle"]; + initial_bank[label="", xlabel="bank-integrated" shape="circle"]; + pending_brr[label="bank-register-reserve"]; + pending_bc[label="bank-confirm"]; + pending_ewr[label="exchange-wait-reserve"]; + pending_wc[label="withdraw-coins"]; + pending_kyc[label="kyc"]; + pending_aml[label="aml"]; + done[label="done", shape="box"]; + aborting_bank[label="bank", style="dashed"]; + aborted_bank[label="aborted", shape="box", style="dashed"]; + suspended_ewr[label="suspended(exchange-wait-reserve)", shape="box"]; + + subgraph { + rank = same; initial_bank; initial_manual; + } + + subgraph { + rank = same; pending_aml; pending_kyc; pending_ewr; + } + + subgraph { + rank = same; done; aborted_bank; + } + + initial_bank->pending_brr; + initial_manual->pending_ewr; + pending_brr->pending_bc [color="green"]; + pending_brr->aborting_bank [style="dashed", color="blue", label="abort"]; + pending_bc->pending_ewr[color="green"]; + pending_bc->aborting_bank [color="blue", label="abort", style="dashed"]; + pending_ewr->pending_wc[color="green"]; + pending_wc->pending_kyc[color="red"]; + pending_wc->pending_aml[color="red"]; + pending_kyc->pending_wc[color="green"]; + pending_aml->pending_wc[color="green"]; + + aborting_bank->suspended_ewr [color="red"]; + aborting_bank->aborted_bank; + pending_ewr->suspended_ewr [color="blue", label="suspend"]; + suspended_ewr->pending_ewr [color="blue", label="resume"]; + + pending_wc->done; +} diff --git a/images/transaction-withdrawal-states.svg b/images/transaction-withdrawal-states.svg @@ -0,0 +1,16 @@ +<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1126.6875 605.2129204635194" width="1126.6875" height="605.2129204635194"> + <!-- svg-source:excalidraw --> + <!-- payload-type:application/vnd.excalidraw+json --><!-- payload-version:2 --><!-- payload-start -->eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO1dWXPaWrZ+P79cIuV+uV11UO956DdcdTAwMDeP8Yhnp7uLkkFcZjZcdTAwMDZcZlwiXHUwMDE4us5/v2tcdTAwMTPbmoVEXHUwMDA0tjuQVGJrYkta69vfXHUwMDFh93//+PJlw530nY1/ftlwnmt2p11cdTAwMWbY440/zfZcdTAwMWbOYNjudWFcdTAwMTeZ/T7sjVx1MDAwNrXZkS3X7Vx1MDAwZv/5j394Z1i13uPPs5yO8+h03SFcdTAwMWP3L/j9y5f/zv71f0+n0+5cdTAwMGad2eGzXHUwMDFkvi9cdTAwMTI8vPW41519KWNcdTAwMWNjLlx1MDAxOHo7oD3cgi9znTrsbdidoePtMZs2ut9cdTAwMWYvXHUwMDBm8SZSna/lRn3y4+vm961971tcdTAwMWLtTufcnXR+3pFda41cdTAwMDa+MVxy3UHvwblu191cdTAwMTbsx6Htb+dccntw/95Zg96o2eo6Q3P33kB7fbvWdifmOsjbanebs2t4W57ht1x1MDAxMsXM8lx1MDAxZYI5qYSJsihW3p/QaMq9Tm9gRvM3NPt447mza1x1MDAwZk1cdTAwMThUt/52jDuwu8O+PYB35Fx1MDAxZDd+uU9C3ja1nHaz5Vx1MDAwNrdccp3ZwyaIS4SEVuxtj/mS/n599tb/439cdTAwMWPd+svjeFx1MDAxNVx1MDAwM09cdTAwMTDIy5a/vOGa47fDXHUwMDAy5Fx1MDAxN1wi3+udnpy590fV/d3t4W65W3rYx7s7o7dbXG5InD1cdTAwMTj0xlx1MDAxYm97/nr5yVx1MDAxYuioX7d/XG5cdTAwMTJcdTAwMTZcbp4gXHUwMDExRFx1MDAxMem9mU67+1x1MDAwMDu7o07H29arPXiy94fvTlwiXHUwMDEy7zrPbpy4Y0ySxF0gilx1MDAwNVwiKLu437BRs1692Ny8arn9XHUwMDBlc7ed5v3Dx1x1MDAxN3dtXHUwMDExRSnRXGJcdTAwMGVGWlxuXHUwMDExlH1CqMWET/bJ8oRfXHUwMDEyXHUwMDBiXHUwMDFlOMKEIFx0j5/wXHUwMDE4ZaBhZcBCS65cdTAwMThcdTAwMTc5dCEgR7mEvlrHlZPmLVx1MDAxZlx1MDAxZN90689V1GvsbrayXHT9n2nXvd6zb852XHUwMDBlbmt3O6x92DrZvmq0xLspkye0va573p7O0Fx1MDAwMlx1MDAwNbbu2I/tzuR1bvo5QKNlMMC+0623u83/u7O7XHUwMDBmpYHTbFx1MDAwZl1nXHUwMDAwP1xmncFcdTAwMGbn71x1MDAxYoHjNzvtptHEjVx1MDAxYTx9Z1x1MDAxMFBSt1xys9vbXHUwMDAxbq/v7a3BXGLsdtdcdTAwMTns18N30lx1MDAxYrSb7a7ducg5XHUwMDFheCrO3quYYVx1MDAwYvOFXHUwMDEwRbPwRm/+ZIIjybxcdTAwMDPmXHUwMDAxyrTEtlx1MDAxZPdwwsfV7bPt5lx1MDAxZdrZKqNPXHUwMDBmKJjolU2mwlwiXHUwMDAyPoTDMLjIiCeMSSm5f2r4jICiq1+P1PHB3f35qDYhT4eH51x1MDAxN7WtXHUwMDAyrlvtoVx1MDAxYqEn3XvcOd67KO9tXHUwMDFkTqe4KKCiijKk/Cq5OqBcdTAwMDJIabRcdTAwMDeP8Pv7QlTsOFxuXHUwMDAyJ51cdTAwMDROmFxiTaTwP/x56DQ43X0+rO+ebH7rVJpXnD1ccp+ao0+PTlx1MDAxY1nKXHUwMDBmTuGhXHUwMDE1iE6KW2ZcZkhgRDn28ZdUcMJSXHUwMDEwtiq281x1MDAwYlx1MDAxNP9dwKl2dHQoKrRzclx1MDAwMbjfqT2cVS7bO1x1MDAwNVxcVz6gve/1w52n3lx1MDAwZd+/vNpcdTAwMTblXHUwMDFk5lx1MDAxNlx1MDAwN3paS+1X9ZWAnvNcXGuBkjilsd12352dzVx1MDAxYk1BXHUwMDAwqMJcdTAwMWLfXHUwMDAwXHUwMDEwXHUwMDAx9mlMVXZ6dqBF9aiFXHUwMDAw+cb1SvVH9bi2Jc4+O1x1MDAwMMJuv7GHdWhkXHUwMDA14lx1MDAxZqNcdTAwMTbicFx0ijiWXFx6ryZccv9cdTAwMTTMVJxivVx1MDAxYXK2LDw57Hy7Kk3LpW9cdTAwMTdqs4KeXGI/qI6/XHUwMDE2cF37qDRq7D/2x+W287jb2Fx1MDAxZZRGN91cdTAwMDKuy1x1MDAwNuPj6lX3YtRvnNU3b79ccvTJ5XlcdTAwMDHXXHUwMDFkbd/dTntccnlwVG0+j+2DwbCunlxuuO7p3bXTt9s7d/2ansjpd/uodXpTwHVblYM6XHUwMDFlXHUwMDFkXZM9Nd1/mpQxLu3vXHUwMDE2Md7y0Xf7QY9cdTAwMWVcdTAwMWa6R6Rywrf2z68zvrf581x1MDAwYlg+XHUwMDAwUiufX8Ztt2U80/AzcNp2d/huc0vaSIqZV2TyvKJcdTAwMThcdTAwMTJcYqZ4XHUwMDBmZufNKy1ero/Y6Vb3hlxyXHUwMDBlx996XHUwMDFk0lNHXHUwMDFmfl7BSllcdTAwMDKDsa0kwljCr4F5XHUwMDA19lir8VwiYs0sQuEjXHUwMDE5cCtGZSarn0vgYFxcMW/Uy5xXPlx1MDAxYv6Xjm7s891v7jnWXHUwMDA3zafrybGub06LwidGNPU5W1aFT1x1MDAwZpNcdTAwMWHwzKdRe+DU31xymlx1MDAxMlx1MDAwNlFcdTAwMTDblcnmvlx1MDAxNPDkUY5g3tbj9aTBkcNrpfubelXdu5uT+4+OSlRahFx1MDAwM9vFRCtFlD+iMFx1MDAxM1x1MDAwZYFWXHUwMDA2SsJiKi8oKYowXHUwMDFjr1dj7H82knfLdy7F2eHhj7vrZ4Tr181Nd3hRXHUwMDA0XHUwMDE5u3BPqpVK9/Fq1FM2XHUwMDE5XFxM8cWgMLDDmHHuV/SVgJ392Hl/sEtcdTAwMThENrB78T6r2lC3L8ZyKnn1ujK9ZY1T6rufWEQ0SEBMVF8yrYVmXG6mXHUwMDFjXHUwMDEyXHUwMDAwXHUwMDAyXGa2aDxcdTAwMTC8KbCUluI+b11cXKDeU+AoXHUwMDFjXHUwMDE1hSjvXHK0OVx1MDAxMehcdTAwMDXJzHSjNCGR6Fx1MDAxOOxcdTAwMTOJMXjOqFx1MDAwMG3x9idPUrmQbmnIsSSzc9NtNStcdTAwMDPqdivDxj3vU9W7vEGFIVx1MDAxMqJIXG6/NmZFpDiQaVxmelOn69Pu3LC1WjyKjDdcdTAwMGZcdTAwMWFdno1vt++/yU6XnreOyPbZ1eDie1x1MDAxNI1+vpOguUQ0sVx1MDAxMOGaU05cdTAwMDWYKziSclx1MDAwNNRcdTAwMDVhaaCGXG5FPD+c5z/DXHUwMDE2j7/CXHUwMDFiXCIpamEsXHUwMDE4hW9iTCuf1+x3XHUwMDA2qCyZUK/+RuNcIuVcdTAwMDT54i1cdTAwMWVwUYLDW1+RS1x1MDAwYpjmcaZYf0bkip3afLLY/3H+eD65Kk1cdTAwMWX7u93L45NvdPqjk89PXHUwMDA0gkRcdTAwMTdcdTAwMDKCfq9cdTAwMWRcdTAwMWX7v3wjRP7horef//Nn7NGKJYi1+ZRgXHUwMDFhXHUwMDBlSDSed7lkNZldL6Ih3vVcIk+sY1x1MDAwZt1y7/Gx7cJzOzX3XHUwMDFjme1cXHvgfm3P4CW8XHUwMDBmQCdhz+ysTVx1MDAwM1x1MDAxMi3HjqBcdTAwMTec59/nR/h4VIqXhFxmXHUwMDFjqURcdTAwMDT5aS9xjCk8NE98X1LBiCVxOk1C2uJYXGKJXGKRiKM4rz5cdTAwMTWWt/V3xqE4ooRNbqdSftLjS1dMdDNS+GZFRCYvY1x1MDAxOHBcdTAwMDLDKFx1MDAxMFx1MDAxNV7pgclq+Fx1MDAwMsriNFx1MDAwN+bS/+6++mPtTixNwFwisPWXacJju17vOElMYd4kXHUwMDFlJlx1MDAwZpnuJlx1MDAwZolIj7Gnk1xipSxcdTAwMDKYppFA8Lp0mEMgYVwibFx1MDAwMl6iwlx1MDAwNGPfg/WTXGLpv0KMWSORJSmYTEhcdIBJTflaefORXGJFsFJCRnONjeKy5JxcdTAwMWMtSSDHe+lcdTAwMWOCsNJcdTAwMTPTu/vPN1ff3DOpyr3p7l0+XHUwMDBlgTVeLNO0UFx1MDAwZSFVglTPdoblOVx1MDAwYoVIvpxQiZf7dVx1MDAwNuGTspe6jv1cZqVcdTAwMTUz5KyNzNMsIVx1MDAwYqZjMPI4pkxxqoX0XHUwMDFk1bT7RsEtrVxiY0RqjKSZ9iOCXHUwMDFj4C5JY0pPXGJcdTAwMGKOyeR4c1x1MDAwZcKPXHUwMDA0N+RLxFxmisx4XHUwMDA0cDKtjc80ql3F0qZ44c9Gm7RFmVx1MDAxOS3Ya2DY+fzuM1x1MDAxY2bAaFx1MDAwMzllUVx1MDAxY8bY5F1QSlx1MDAxOeWIK+5LI37DYawsb+vvXGa9sbyJI4VcdTAwMTFcdTAwMTUyljeh8Ma3Klx1MDAwZlx1MDAwZXRXaZEl7TFcdTAwMWZvgrdM5EKprK+86dHujuzOl1d+8Vx1MDAxMbjSXHUwMDFjrlx1MDAxMuZKiXeQy+WbmiCdxo+4ilx1MDAxNHJpnJB7Po5I9Jve8TyEh9wpmzr/i1qXx2tiXGZuQUWs14Ql50oweCMs4CUuzIqBOZAulGNZKC/B/qP5SphCelWab1ZGJi9QUa5cYqJIc1x1MDAxZs9/m5P1YsQgvY4lRFZcYlx1MDAxNVQrXHUwMDEzJ8UwXHUwMDFlRiODkMsmXHUwMDAy6cnJqYCjw4CjQ4WjnuqmXHUwMDAwXHUwMDBlyzPNr1x1MDAwMcdYWFxiI8WFikCLsbBcdTAwMTIrmrFcdTAwMDamxVx1MDAxOCZZsiA+P94w5lx1MDAxZL48vMms7KDrXHUwMDE0MS6ZIFxiU8wkYr6jfuq6WlxmcPJYXCJcdTAwMDTIXHUwMDFmhb9MXGKGXHUwMDE4VZEx8KjQXHUwMDE1izfpScZpeCNolOCE8MZcdTAwMGJJv1x1MDAwMo63xWM43jy9XHUwMDA2XHUwMDFj/0NPXHUwMDA2XHUwMDFjalJzOIlcdTAwMThcdTAwMTZcdTAwMDa+k2vKYWJcdTAwMTXLMDY+XGLcUP/RXFysXHUwMDAybjKruqE3XGZmXGIuKZZcdTAwMTgzLaL8JkotMsFNeiFImN9cdTAwMTCkiFx1MDAwNNNQMcZcYot6Y5bu6EhPPk13OMtcdTAwMTDgSJlULuJFhGJcXMoqLXHv93Fk5DGpJMcgvP7Cl4yJnsCMXGJdJIUmXHUwMDFkcsCUpp4v8d0gp+STL/NRvjOWhzqZNVx1MDAxZVlcXEgktYRnJVx1MDAxOIb/I/qOXHUwMDE3dLeml1x0XHUwMDA0UVx1MDAwN0BPKsk15lr781x1MDAwZlMsu4JBJz0zPVx1MDAxNXQkXHUwMDBlgVx1MDAwZeZyTraeisOcPFZcdTAwMTVcdTAwMTWsUZO/OeZcdTAwMTCFhGKcxnlxUiBcdTAwMDcp48lWmTrn5MNcdTAwMWOmNWPvXHUwMDFmXVJcdTAwMDHEKamV2FV51N300EFaKcSYMn2iXHUwMDE48+qLU1S+WLKDLGomXHUwMDFljICbaoJ8zkBcdTAwMGb6UFT0ioWd9Jz2VNtcboWpXHUwMDBlnUd1YmM265S73ExcdTAwMDdpJlx1MDAwMvjhwVx1MDAwZU/MuONUM4r98Z/imFx1MDAwZXzePy+O+Y9cdTAwMDa5+mA8XHUwMDA3RsSAXlx1MDAwMEHlXHUwMDAyM1x1MDAxZkIm63omvEmvO1xu4p7E5lx1MDAwZmFcdTAwMDRLXHUwMDEzpY/aVkv35aTXuqThjVx1MDAwZZtWMNvNYzkxeCPzuHLWeGOAXHUwMDFlXGI6kjGdXHUwMDAwN1x1MDAwMqG/MMuh2qTqcVxcPN5cdTAwMTBEpHp/llNS/sNLIFmrQJw86k4lo8ByMEOaXHUwMDAy4aQxXHUwMDA0XHUwMDAzR9564Vx1MDAxZVx1MDAxZMQxTFeawNtcdTAwMTNgjEad2MtnOen1LGmoXHUwMDAzc1tu2GExISu5Ln3KXHQ7QImxXHR7xFVERTe+wlx1MDAwZeGESuFv/1RcdTAwMWPqXHUwMDAwmHlP7d1YTiBkVZL0Q4FcdTAwMGWymDa9d1x1MDAwMfZcdTAwMTUjiKpcdTAwMTiesyDkpFc2XHUwMDA2xsBcdTAwMDHsNOYwTVxiqUGG3lx1MDAwMXHSK93SXHUwMDEwh9Bw0Fxu03nuXHUwMDFjXHUwMDE2U9ok1oZVXsNKU1x1MDAwMVY4jlxyWtHkNGTjuORcZqPis3JcYlKcLtSZplimw4I1QWIltlVmhTf+W1x1MDAwNbDDuCZUc0SjoCNcIu+8cJpcdTAwMDPsRjEuqZaKXHUwMDEzhGJAJ0bwilx1MDAwNZ3HXG5h/PT2aEBa9ye60aj27tzLLFx1MDAxObpUcFx1MDAwYpBSgCBcdTAwMTPKKceRXHUwMDFl1yxcdTAwMTA2lzGFXHUwMDEyiFnxKb7r8u9cZtm5XHUwMDE0XHUwMDBi89hj678xSfYlXHUwMDBiXHUwMDEwd4X8LuiCSsCX2m+bS6nRQlxc6jX3177rXHLgkj87wrq90tjuwE1/7LLquWPOk/WrmpXecHwxvO91z76fXFztXf64XHUwMDFmVTPpOtdcdTAwMTZJ0fXk9tOeqsNcdTAwMTFcIraT1VrX5+s6zFx1MDAxMJrKXHUwMDA0wyZcdTAwMTJKetN0rChnpjVH0Zr+8K30fPe1fDqYXGZcdTAwMWKX4+rz4W75pohcdTAwMWW2m8/l8+bR4XZv52Javju4eqo9tVhcdTAwMDHX/aBccrZcdTAwMDPINOuqN1Nvo+hG4T9cdTAwMDE0pVx1MDAwZTpcdTAwMGY28SmvXHUwMDFlXlSOTvhXuzK5OCw/tkQpKzaxWfNVKYlmvlxcjp91QirQe1rymDohyS1kyoRcdTAwMTAzlHxe1+g1Nr1+8atcdGRKXHUwMDE04cHHxpaSnb1MXHUwMDFiXHUwMDAyI1x1MDAxNnK7pILTskBkqVxyq7nQiP06iFx1MDAwMFWwXHUwMDFiZi2Ocagh1EdcdTAwMDWQxFx1MDAwMedcdTAwMDFcdTAwMGZRumKD7UN971xc9tzK87j6vbo7yFx1MDAwMlx1MDAxZVxcXHUwMDE5IyXUwa7ERNByicFcZmO6zOk3t8aJ1y9+yXyhYK5cdTAwMDSEPNOaUVx1MDAxOM4wOe2Fw8QvcJgs6lxmlGChlnRhdf50lCBtzHmUunzxtPM8Pnualvdr6OG2uv3sjlkmRmCySswn3lphxFxu9FvxkWqvg4OYXWHtmFjMMaGYXGZEcf1+icRKRaWQ1tpfyF2Qoi+rwfgvdJBLve4v9MpMve5SXHUwMDFiXHUwMDBlc66Qon5FX1x1MDAxNPBAXHTcNlx1MDAwMMik9Frj/MFb32VcdTAwMWJ4XHUwMDFl6EufmtLLs0mkfFx083n1kjQmy054h63rl/yPPSXJjpmIXHUwMDBlim2XkNyQXHUwMDEzS8KI4EosoUJbKsJcdTAwMTcyKootYVxuxp/ntpejgbQ8sZLqg3Tf6JdAuJpwxKSCXHUwMDE3RuWsRY3vqJewXHK1lD+wIVx1MDAxNsxcdTAwMGJOt2u+XHUwMDA08/SQRkJSRYlWTEfT9JZejZBudqeBXHUwMDE2o1HQQniRXCLvPPHrmiY2sX9zzGJmtaCEclx1MDAwNK9PQCRjXHUwMDA2mXRcdIZcdTAwMTfqozVcdTAwMDeyXHUwMDE0oNb7l0BcdTAwMDWLvFdcdTAwMTK7zoFAXHUwMDE0UUEkxZQhMFVQlvrqTHiT7oRccuJccmZcdTAwMDKb+cW0/qYwmJhCc2vpqcHpfv30JD1cdTAwMWUlSvNcdTAwMWJL8Lj84Fx1MDAxY6CzroHaMI3LgfKA7MY5jFN4kpCCXHUwMDEyojItp/kpa6B80jX7dVx1MDAxNaiTq49cZqKaXHUwMDBizqTQXGZcdTAwMTNCovkqatao1ud5WVxmhzJDoUlcdTAwMTXWilx1MDAwM+PhXGJcdTAwMGKAQsGiRVmhPFx1MDAxNVx1MDAxZVx1MDAxZFTBqJSeXHUwMDA3kZrIx8JcdTAwMTVSJYLRvPZaOMZ8y1NcZr5cdTAwMDYlw49cdTAwMTVcdTAwMDU0kFwitvtEYjJccjfAXHUwMDAxnPt/XHUwMDE3kzBLOH55mJSjvVx1MDAxNoZ5XHUwMDA0SFxicCBhoElG0/ikNVusXGJcdTAwMWUqMWl2i0JSep5cXJhcdTAwMWFcdTAwMDVcdTAwMDZcdTAwMTXTXHUwMDFklK1cdTAwMWGS0mOXqZDEI1xycehcXJ6kY1x1MDAxYeLkcZivXHUwMDExyVxcmJilWqSMNc54onGGlSnaVIs1OU7HJG56rLy/caZcdTAwMDM9cVZSzZCr+1x1MDAxNVVcdTAwMWEsZK25lkxRXHUwMDFlh0mmmp9cdTAwMTBt+Fxuw2zB8obK0b3dOb9wXHUwMDE0yDSq3Fx1MDAxY4vRtmBJg9JIc6lcdEVIIc6i1G3pLVx1MDAwMNPDMKlcdTAwMTCEwlx1MDAwNVVcdTAwMWPPbZGzttSKaMklKfyN7zmaXFw2jqlZXHUwMDEyXHUwMDA00YWWavlcdTAwMWOsiIdcbjlXgUF5XG7HkaBaXHUwMDBiQlx1MDAxMFBcdTAwMTGmo71pwCaCl2SWcFGEY81pRFx1MDAwMjIhUHqMPjwkoYhEiME/IFRxpChcdTAwMTC1Xz4pSlx1MDAwZuCmeqxRtH9O0lq8aUG2df+cvIhcdTAwMDTIolx1MDAxMEyrcWZcdTAwMWFOXjtcblx1MDAwM2owU19YPCRJLlx1MDAwNH3/XCLPYNAsQ5DtPVx1MDAxYe7kKMikXHUwMDE4McExvGopaJxccqUt5Ft7XHUwMDEyq1x1MDAwNfua5oAwjrhcdTAwMTRCI1x1MDAwNcROqJhcdTAwMTjbXG5qRFNzQ/K5logkcyBcdTAwMGJcYn9cdTAwMTSzXGLKXHUwMDEzZVuDllx1MDAwMS2kkVnKJDYjKjnMhlx1MDAwMa9MXHUwMDBihiV4vD9cYmhcdTAwMTFcdTAwMTZCobkncFx1MDAxOThcdTAwMDGEcVx1MDAxNbiVo5idXGI9W1x1MDAxYUoyKjWiMb0rhCWD62cvXHUwMDE5uIyTnChCXHUwMDAxLVxyJ4evXHUwMDA2RI2MKlxun1x1MDAwNUNXevpZeotUajHt/3gqM1x1MDAwMzKE51x1MDAwMJmIW8iTiDyLUKyBzJhcclxcaUZEXFxcdTAwMTlcdTAwMWFJzuw0/epgOpd6kb4+vkF/VFx1MDAxNMPCfzimYt5cdFxcXHUwMDA2XHUwMDAzfYTMO0OElthcdTAwMDTwWFx1MDAwNe7laZBoVsTSWDCpTXdcdTAwMDNcdTAwMWVNSogpZi9cdTAwMWPopKZYzlp5MMYkj1x1MDAwNlx1MDAwM5dP0SZ7XHUwMDE3ZVRcdTAwMWJ+bU2eL5zt+8vb4e12zFx1MDAwMsZxa15xaVx1MDAxMWo+XHUwMDFjSC9cdTAwMTMhn1x1MDAxN1x1MDAwYoJcXEzeOmNcdTAwMTZb560vXFyggtisYDY2LyGlnFx1MDAxZVx1MDAxYo87XmhF9TnudsL93fBcdTAwMTfIqa73ur5cdTAwMDf/XHUwMDAxc6eDXHUwMDAzzJMjzVSf3d7uXVx1MDAxZXSeXHUwMDFhjc5cdTAwMTlqnJRojCU0cGruT0FcdTAwMGbpmlxiL2RcdTAwMTXyKcfpl4hTKL1WqFx1MDAwNIVcdTAwMDJcdTAwMTRSUlx1MDAxMlx1MDAxYVx1MDAxYlNPXkJcdTAwMDZcdTAwMTBcXFIm2FwiVk9qIchp+ei7/aBHj1x1MDAwZt0jUjnhW/vn113fRFx1MDAxMmGhb3uyrNLJXHUwMDA14nn67qTI9vTZXHUwMDFll2Xv5vpp4tT2Me2cbLZOMss25eG2l0Cg0dxmLCQmoXa9Lm2ycDNlukqS2HrGqMT71mOjZi2w4pvNcbPKZZ5cbpxcdTAwMTRcdTAwMDFMjyzOXHUwMDE3wEjKXHUwMDAwJ3NLarGKQVe6XtRcIlFcdTAwMDDhKUpcdTAwMTZYh8JcdTAwMTecS+x2iFx0ZVx1MDAxMv5ZqMlqKrwutz5eXHUwMDEyhvOkXHUwMDFlpEh39Xxvc/v4tMbY6c5Ne7pzONk9j2lgniDdXFxcdTAwMDEzUTIs4Gx+zTiOQ9g1fUimXHUwMDBmTFx1MDAwYizi3aZcIrk4gVwiZLrzL4GPXHUwMDBiKnGeou5cdTAwMTRcdTAwMTk8xjfHN+eVPfvrNjqc0uOdrVY5x1x1MDAxNFx1MDAxZmGvVMxlr7HefJonXHUwMDAy+XvJn6BI0EBuZ1x1MDAxNvHDSFx1MDAxYfN7XHUwMDE5S3VwxvzK8Evyl86FU72xLFxcOZHBcsIsLlx1MDAxZCfP5L4uMTViXHUwMDA3z1x1MDAxNmPB4lxmquRWO4JgTTRbRoGpcfq9fzpOySde5oM/2oJVXGZcdTAwMTNuVlx1MDAxYmNUU1x1MDAxNrtsi7CIKVx1MDAxOEVaaa1cdTAwMTFwtIhcYmTylaZ7Rb6EyjlAlJRSXHUwMDE0xiUxjum7XFxkTOiPl3ewYff75y6I0dtdbPxoO+OvUXX+W2P2MefPXHUwMDA2YFTZmSnMX3/89f9yoaBcdTAwMWQifQ==<!-- payload-end --> + <defs> + <style class="style-fonts"> + @font-face { + font-family: "Virgil"; + src: url("https://excalidraw.com/Virgil.woff2"); + } + @font-face { + font-family: "Cascadia"; + src: url("https://excalidraw.com/Cascadia.woff2"); + } + </style> + </defs> + <rect x="0" y="0" width="1126.6875" height="605.2129204635194" fill="#ffffff"></rect><g stroke-linecap="round" transform="translate(10 111.99999999999994) rotate(0 11 11)"><path d="M22 11 C22 11.64, 21.94 12.28, 21.83 12.91 C21.72 13.54, 21.55 14.16, 21.34 14.76 C21.12 15.36, 20.84 15.95, 20.53 16.5 C20.21 17.05, 19.84 17.58, 19.43 18.07 C19.02 18.56, 18.56 19.02, 18.07 19.43 C17.58 19.84, 17.05 20.21, 16.5 20.53 C15.95 20.84, 15.36 21.12, 14.76 21.34 C14.16 21.55, 13.54 21.72, 12.91 21.83 C12.28 21.94, 11.64 22, 11 22 C10.36 22, 9.72 21.94, 9.09 21.83 C8.46 21.72, 7.84 21.55, 7.24 21.34 C6.64 21.12, 6.05 20.84, 5.5 20.53 C4.95 20.21, 4.42 19.84, 3.93 19.43 C3.44 19.02, 2.98 18.56, 2.57 18.07 C2.16 17.58, 1.79 17.05, 1.47 16.5 C1.16 15.95, 0.88 15.36, 0.66 14.76 C0.45 14.16, 0.28 13.54, 0.17 12.91 C0.06 12.28, 0 11.64, 0 11 C0 10.36, 0.06 9.72, 0.17 9.09 C0.28 8.46, 0.45 7.84, 0.66 7.24 C0.88 6.64, 1.16 6.05, 1.47 5.5 C1.79 4.95, 2.16 4.42, 2.57 3.93 C2.98 3.44, 3.44 2.98, 3.93 2.57 C4.42 2.16, 4.95 1.79, 5.5 1.47 C6.05 1.16, 6.64 0.88, 7.24 0.66 C7.84 0.45, 8.46 0.28, 9.09 0.17 C9.72 0.06, 10.36 0, 11 0 C11.64 0, 12.28 0.06, 12.91 0.17 C13.54 0.28, 14.16 0.45, 14.76 0.66 C15.36 0.88, 15.95 1.16, 16.5 1.47 C17.05 1.79, 17.58 2.16, 18.07 2.57 C18.56 2.98, 19.02 3.44, 19.43 3.93 C19.84 4.42, 20.21 4.95, 20.53 5.5 C20.84 6.05, 21.12 6.64, 21.34 7.24 C21.55 7.84, 21.72 8.46, 21.83 9.09 C21.94 9.72, 21.97 10.68, 22 11 C22.03 11.32, 22.03 10.68, 22 11" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(285.21667098999023 16.849999999999937) rotate(0 136.10000610351562 11.5)"><text x="136.10000610351562" y="0" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="text-before-edge">pending(bank-register-reserve)</text></g><g transform="translate(285.21667098999023 110.99999999999994) rotate(0 113.13333129882812 11.5)"><text x="113.13333129882812" y="0" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="text-before-edge">pending(bank-confirming)</text></g><g transform="translate(285.21667098999023 189.49999999999994) rotate(0 142.5500030517578 11.5)"><text x="142.5500030517578" y="0" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="text-before-edge">pending(exchange-wait-reserve)</text></g><g transform="translate(285.21667098999023 279.99999999999994) rotate(0 121.5250015258789 11.5)"><text x="121.5250015258789" y="0" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="text-before-edge">pending(withdrawing-coins)</text></g><g transform="translate(135.88333129882812 406.99999999999994) rotate(0 97.11666870117188 11.5)"><text x="97.11666870117188" y="0" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="text-before-edge">pending(kyc-required)</text></g><g transform="translate(361.7583312988281 500.99999999999994) rotate(0 98.24166870117188 11.5)"><text x="98.24166870117188" y="0" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="text-before-edge">pending(aml-required)</text></g><g transform="translate(539.0749969482422 383.99999999999994) rotate(0 88.92500305175781 11.5)"><text x="88.92500305175781" y="0" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="text-before-edge">pending(aml-frozen)</text></g><g mask="url(#mask-URwYEjJ7ln3ShM2ERVrTZ)" stroke-linecap="round"><g transform="translate(32.474046463766854 113.11643025449885) rotate(0 120.76297676811657 -42.49546412822369)"><path d="M0 0 C14.09 -12.85, 44.27 -63.26, 84.53 -77.12 C124.78 -90.97, 215.36 -82.12, 241.53 -83.12 M0 0 C14.09 -12.85, 44.27 -63.26, 84.53 -77.12 C124.78 -90.97, 215.36 -82.12, 241.53 -83.12" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(32.474046463766854 113.11643025449885) rotate(0 120.76297676811657 -42.49546412822369)"><path d="M213.1 -73.51 C219.6 -75.71, 226.09 -77.9, 241.53 -83.12 M213.1 -73.51 C221.47 -76.34, 229.83 -79.16, 241.53 -83.12" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(32.474046463766854 113.11643025449885) rotate(0 120.76297676811657 -42.49546412822369)"><path d="M213.58 -94.03 C219.96 -91.54, 226.35 -89.04, 241.53 -83.12 M213.58 -94.03 C221.8 -90.82, 230.02 -87.61, 241.53 -83.12" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask id="mask-URwYEjJ7ln3ShM2ERVrTZ"><rect x="0" y="0" fill="#fff" width="374" height="296.23286050899776"></rect><rect x="62.24166488647461" y="17.599999999999937" fill="#000" width="109.51667022705078" height="36.8" opacity="1"></rect></mask><g transform="translate(62.24166488647461 17.599999999999937) rotate(0 90.99535834540882 53.020966126275226)"><text x="54.75833511352539" y="0" font-family="Helvetica, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="text-before-edge">bank integrated</text><text x="54.75833511352539" y="18.4" font-family="Helvetica, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="text-before-edge">withdrawal</text></g><g mask="url(#mask-zORtjM_IGEsGCn-kI1GFu)" stroke-linecap="round"><g transform="translate(36.276609398310484 134.2675791369706) rotate(0 120.86169530084476 37.70777219806918)"><path d="M0 0 C13.12 11.79, 38.44 59.28, 78.72 70.73 C119.01 82.19, 214.56 69.07, 241.72 68.73 M0 0 C13.12 11.79, 38.44 59.28, 78.72 70.73 C119.01 82.19, 214.56 69.07, 241.72 68.73" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(36.276609398310484 134.2675791369706) rotate(0 120.86169530084476 37.70777219806918)"><path d="M214.31 80.92 C221.53 77.71, 228.75 74.5, 241.72 68.73 M214.31 80.92 C224.92 76.2, 235.52 71.49, 241.72 68.73" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(36.276609398310484 134.2675791369706) rotate(0 120.86169530084476 37.70777219806918)"><path d="M212.89 60.45 C220.48 62.63, 228.08 64.81, 241.72 68.73 M212.89 60.45 C224.05 63.65, 235.2 66.86, 241.72 68.73" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask id="mask-zORtjM_IGEsGCn-kI1GFu"><rect x="0" y="0" fill="#fff" width="378" height="304.99999999999994"></rect><rect x="55.15833282470703" y="195.79999999999995" fill="#000" width="119.68333435058594" height="18.4" opacity="1"></rect></mask><g transform="translate(55.15833282470703 195.79999999999995) rotate(0 101.97997187444821 -23.824648664960165)"><text x="59.84166717529297" y="0" font-family="Helvetica, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="text-before-edge">manual withdraw</text></g><g stroke-linecap="round"><g transform="translate(383 48.99999999999994) rotate(0 0.5 27.5)"><path d="M0 0 C0.17 9.17, 0.83 45.83, 1 55 M0 0 C0.17 9.17, 0.83 45.83, 1 55" stroke="#2b8a3e" stroke-width="1" fill="none"></path></g><g transform="translate(383 48.99999999999994) rotate(0 0.5 27.5)"><path d="M-8.88 29.33 C-5.89 37.1, -2.9 44.87, 1 55 M-8.88 29.33 C-5.43 38.28, -1.99 47.23, 1 55" stroke="#2b8a3e" stroke-width="1" fill="none"></path></g><g transform="translate(383 48.99999999999994) rotate(0 0.5 27.5)"><path d="M9.94 28.99 C7.23 36.86, 4.53 44.73, 1 55 M9.94 28.99 C6.82 38.06, 3.7 47.13, 1 55" stroke="#2b8a3e" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(384 141.99999999999994) rotate(0 0.5 22)"><path d="M0 0 C0.17 7.33, 0.83 36.67, 1 44 M0 0 C0.17 7.33, 0.83 36.67, 1 44" stroke="#2b8a3e" stroke-width="1" fill="none"></path></g><g transform="translate(384 141.99999999999994) rotate(0 0.5 22)"><path d="M-6.99 23.5 C-4.19 30.69, -1.39 37.87, 1 44 M-6.99 23.5 C-4.02 31.13, -1.04 38.76, 1 44" stroke="#2b8a3e" stroke-width="1" fill="none"></path></g><g transform="translate(384 141.99999999999994) rotate(0 0.5 22)"><path d="M8.05 23.16 C5.58 30.46, 3.11 37.77, 1 44 M8.05 23.16 C5.43 30.91, 2.8 38.67, 1 44" stroke="#2b8a3e" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(388 220.99999999999994) rotate(0 1.5 28)"><path d="M0 0 C0.5 9.33, 2.5 46.67, 3 56 M0 0 C0.5 9.33, 2.5 46.67, 3 56" stroke="#2b8a3e" stroke-width="1" fill="none"></path></g><g transform="translate(388 220.99999999999994) rotate(0 1.5 28)"><path d="M-7.99 30.2 C-4.81 37.67, -1.63 45.13, 3 56 M-7.99 30.2 C-4.25 38.97, -0.52 47.74, 3 56" stroke="#2b8a3e" stroke-width="1" fill="none"></path></g><g transform="translate(388 220.99999999999994) rotate(0 1.5 28)"><path d="M11.17 29.18 C8.8 36.94, 6.44 44.7, 3 56 M11.17 29.18 C8.39 38.29, 5.62 47.41, 3 56" stroke="#2b8a3e" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(297 317.99999999999994) rotate(0 -51 40)"><path d="M0 0 C-17 13.33, -85 66.67, -102 80 M0 0 C-17 13.33, -85 66.67, -102 80" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(297 317.99999999999994) rotate(0 -51 40)"><path d="M-86.15 54.53 C-91.74 63.51, -97.33 72.49, -102 80 M-86.15 54.53 C-91.73 63.49, -97.3 72.45, -102 80" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(297 317.99999999999994) rotate(0 -51 40)"><path d="M-73.49 70.68 C-83.54 73.96, -93.6 77.25, -102 80 M-73.49 70.68 C-83.52 73.96, -93.55 77.24, -102 80" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(253 397.99999999999994) rotate(0 41 -42)"><path d="M0 0 C13.67 -14, 68.33 -70, 82 -84 M0 0 C13.67 -14, 68.33 -70, 82 -84" stroke="#364fc7" stroke-width="1" fill="none"></path></g><g transform="translate(253 397.99999999999994) rotate(0 41 -42)"><path d="M69.65 -56.66 C72.64 -63.27, 75.62 -69.88, 82 -84 M69.65 -56.66 C72.82 -63.67, 75.98 -70.68, 82 -84" stroke="#364fc7" stroke-width="1" fill="none"></path></g><g transform="translate(253 397.99999999999994) rotate(0 41 -42)"><path d="M54.97 -70.99 C61.5 -74.14, 68.04 -77.28, 82 -84 M54.97 -70.99 C61.9 -74.33, 68.83 -77.66, 82 -84" stroke="#364fc7" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(385 313.99999999999994) rotate(0 2 91)"><path d="M0 0 C0.67 30.33, 3.33 151.67, 4 182 M0 0 C0.67 30.33, 3.33 151.67, 4 182" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(385 313.99999999999994) rotate(0 2 91)"><path d="M-6.88 154.04 C-4.23 160.85, -1.58 167.66, 4 182 M-6.88 154.04 C-2.77 164.6, 1.34 175.16, 4 182" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(385 313.99999999999994) rotate(0 2 91)"><path d="M13.64 153.59 C11.29 160.51, 8.94 167.43, 4 182 M13.64 153.59 C10 164.32, 6.36 175.05, 4 182" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(422 489.99999999999994) rotate(0 -4 -88)"><path d="M0 0 C-1.33 -29.33, -6.67 -146.67, -8 -176 M0 0 C-1.33 -29.33, -6.67 -146.67, -8 -176" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(422 489.99999999999994) rotate(0 -4 -88)"><path d="M3.53 -148.3 C-0.95 -159.07, -5.43 -169.83, -8 -176 M3.53 -148.3 C-0.14 -157.11, -3.8 -165.92, -8 -176" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(422 489.99999999999994) rotate(0 -4 -88)"><path d="M-16.97 -147.37 C-13.48 -158.5, -10 -169.62, -8 -176 M-16.97 -147.37 C-14.12 -156.48, -11.26 -165.58, -8 -176" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(524 489.99999999999994) rotate(0 20.5 -36.5)"><path d="M0 0 C6.83 -12.17, 34.17 -60.83, 41 -73 M0 0 C6.83 -12.17, 34.17 -60.83, 41 -73" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(524 489.99999999999994) rotate(0 20.5 -36.5)"><path d="M36.14 -43.4 C37.35 -50.76, 38.56 -58.13, 41 -73 M36.14 -43.4 C37.79 -53.45, 39.44 -63.51, 41 -73" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(524 489.99999999999994) rotate(0 20.5 -36.5)"><path d="M18.25 -53.45 C23.91 -58.31, 29.57 -63.18, 41 -73 M18.25 -53.45 C25.98 -60.09, 33.71 -66.73, 41 -73" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(558 377.99999999999994) rotate(0 -22.5 -31)"><path d="M0 0 C-7.5 -10.33, -37.5 -51.67, -45 -62 M0 0 C-7.5 -10.33, -37.5 -51.67, -45 -62" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(558 377.99999999999994) rotate(0 -22.5 -31)"><path d="M-20.14 -45.21 C-25.27 -48.68, -30.4 -52.14, -45 -62 M-20.14 -45.21 C-25.69 -48.96, -31.24 -52.71, -45 -62" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(558 377.99999999999994) rotate(0 -22.5 -31)"><path d="M-36.74 -33.16 C-38.45 -39.11, -40.15 -45.07, -45 -62 M-36.74 -33.16 C-38.59 -39.6, -40.43 -46.04, -45 -62" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g transform="translate(690.2916641235352 16) rotate(0 102.20833587646484 11.5)"><text x="102.20833587646484" y="0" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="text-before-edge">aborted(bank-to-wallet)</text></g><g transform="translate(683.7916641235352 110.99999999999994) rotate(0 104.68333435058594 11.5)"><text x="104.68333435058594" y="0" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="text-before-edge">aborting(wallet-to-bank)</text></g><g transform="translate(683.9833297729492 191.5) rotate(0 87.51667022705078 11.5)"><text x="87.51667022705078" y="0" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="text-before-edge">aborted(after-wired)</text></g><g transform="translate(908.8125 194) rotate(0 102.375 11.5)"><text x="102.375" y="0" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="text-before-edge">aborted(wallet-to-bank)</text></g><g transform="translate(698.1666641235352 282.5) rotate(0 123.33333587646484 11.5)"><text x="123.33333587646484" y="0" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="text-before-edge">aborted(partially-withdrawn)</text></g><g stroke-linecap="round"><g transform="translate(907 124.99999999999994) rotate(0 17.218998830438863 27.38350120688684)"><path d="M0 0 C5.17 -0.17, 25.33 -11, 31 -1 C36.67 9, 33.5 49.83, 34 60 M0 0 C5.17 -0.17, 25.33 -11, 31 -1 C36.67 9, 33.5 49.83, 34 60" stroke="#2b8a3e" stroke-width="1" fill="none"></path></g><g transform="translate(907 124.99999999999994) rotate(0 17.218998830438863 27.38350120688684)"><path d="M24.1 31.68 C27.78 42.21, 31.47 52.75, 34 60 M24.1 31.68 C27.26 40.72, 30.42 49.75, 34 60" stroke="#2b8a3e" stroke-width="1" fill="none"></path></g><g transform="translate(907 124.99999999999994) rotate(0 17.218998830438863 27.38350120688684)"><path d="M44.62 31.94 C40.67 42.38, 36.72 52.81, 34 60 M44.62 31.94 C41.23 40.9, 37.84 49.85, 34 60" stroke="#2b8a3e" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(757 138.99999999999994) rotate(0 0.5 21)"><path d="M0 0 C0.17 7, 0.83 35, 1 42 M0 0 C0.17 7, 0.83 35, 1 42" stroke="#c92a2a" stroke-width="1" fill="none"></path></g><g transform="translate(757 138.99999999999994) rotate(0 0.5 21)"><path d="M-6.65 22.44 C-4.1 28.96, -1.55 35.47, 1 42 M-6.65 22.44 C-4.73 27.35, -2.81 32.26, 1 42" stroke="#c92a2a" stroke-width="1" fill="none"></path></g><g transform="translate(757 138.99999999999994) rotate(0 0.5 21)"><path d="M7.71 22.1 C5.48 28.73, 3.24 35.36, 1 42 M7.71 22.1 C6.03 27.09, 4.34 32.09, 1 42" stroke="#c92a2a" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(520 121.99999999999994) rotate(0 79 0.5)"><path d="M0 0 C26.33 0.17, 131.67 0.83, 158 1 M0 0 C26.33 0.17, 131.67 0.83, 158 1" stroke="#364fc7" stroke-width="1" fill="none"></path></g><g transform="translate(520 121.99999999999994) rotate(0 79 0.5)"><path d="M129.74 11.08 C135.67 8.97, 141.59 6.86, 158 1 M129.74 11.08 C138.19 8.07, 146.63 5.06, 158 1" stroke="#364fc7" stroke-width="1" fill="none"></path></g><g transform="translate(520 121.99999999999994) rotate(0 79 0.5)"><path d="M129.87 -9.44 C135.77 -7.25, 141.67 -5.06, 158 1 M129.87 -9.44 C138.28 -6.32, 146.68 -3.2, 158 1" stroke="#364fc7" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(565 29.999999999999943) rotate(0 57 0)"><path d="M0 0 C19 0, 95 0, 114 0 M0 0 C19 0, 95 0, 114 0" stroke="#364fc7" stroke-width="1" fill="none"></path></g><g transform="translate(565 29.999999999999943) rotate(0 57 0)"><path d="M85.81 10.26 C94.86 6.97, 103.9 3.68, 114 0 M85.81 10.26 C92.38 7.87, 98.95 5.48, 114 0" stroke="#364fc7" stroke-width="1" fill="none"></path></g><g transform="translate(565 29.999999999999943) rotate(0 57 0)"><path d="M85.81 -10.26 C94.86 -6.97, 103.9 -3.68, 114 0 M85.81 -10.26 C92.38 -7.87, 98.95 -5.48, 114 0" stroke="#364fc7" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(578 201.99999999999994) rotate(0 46.5 1.5)"><path d="M0 0 C15.5 0.5, 77.5 2.5, 93 3 M0 0 C15.5 0.5, 77.5 2.5, 93 3" stroke="#364fc7" stroke-width="1" fill="none"></path></g><g transform="translate(578 201.99999999999994) rotate(0 46.5 1.5)"><path d="M64.49 12.35 C73.81 9.29, 83.13 6.24, 93 3 M64.49 12.35 C74.69 9, 84.88 5.66, 93 3" stroke="#364fc7" stroke-width="1" fill="none"></path></g><g transform="translate(578 201.99999999999994) rotate(0 46.5 1.5)"><path d="M65.15 -8.16 C74.26 -4.52, 83.36 -0.87, 93 3 M65.15 -8.16 C75.11 -4.17, 85.07 -0.18, 93 3" stroke="#364fc7" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(534 291.99999999999994) rotate(0 79 -0.5)"><path d="M0 0 C26.33 -0.17, 131.67 -0.83, 158 -1 M0 0 C26.33 -0.17, 131.67 -0.83, 158 -1" stroke="#364fc7" stroke-width="1" fill="none"></path></g><g transform="translate(534 291.99999999999994) rotate(0 79 -0.5)"><path d="M129.87 9.44 C140.43 5.52, 150.98 1.61, 158 -1 M129.87 9.44 C140.92 5.34, 151.97 1.24, 158 -1" stroke="#364fc7" stroke-width="1" fill="none"></path></g><g transform="translate(534 291.99999999999994) rotate(0 79 -0.5)"><path d="M129.74 -11.08 C140.35 -7.3, 150.95 -3.52, 158 -1 M129.74 -11.08 C140.84 -7.12, 151.94 -3.16, 158 -1" stroke="#364fc7" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(726 396.99999999999994) rotate(0 17.998516892908526 -39.2735678019196)"><path d="M0 0 C5.67 -0.17, 28.67 13, 34 -1 C39.33 -15, 32.33 -70.17, 32 -84 M0 0 C5.67 -0.17, 28.67 13, 34 -1 C39.33 -15, 32.33 -70.17, 32 -84" stroke="#364fc7" stroke-width="1" fill="none"></path></g><g transform="translate(726 396.99999999999994) rotate(0 17.998516892908526 -39.2735678019196)"><path d="M44.32 -56.65 C41 -64.02, 37.68 -71.39, 32 -84 M44.32 -56.65 C41.51 -62.87, 38.71 -69.1, 32 -84" stroke="#364fc7" stroke-width="1" fill="none"></path></g><g transform="translate(726 396.99999999999994) rotate(0 17.998516892908526 -39.2735678019196)"><path d="M23.85 -55.13 C26.05 -62.91, 28.24 -70.69, 32 -84 M23.85 -55.13 C25.71 -61.7, 27.56 -68.28, 32 -84" stroke="#364fc7" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(565 513) rotate(0 132.5518314639386 -96.50620914312776)"><path d="M0 0 C40.33 -1.33, 199.17 25.67, 242 -8 C284.83 -41.67, 254.5 -169.67, 257 -202 M0 0 C40.33 -1.33, 199.17 25.67, 242 -8 C284.83 -41.67, 254.5 -169.67, 257 -202" stroke="#364fc7" stroke-width="1" fill="none"></path></g><g transform="translate(565 513) rotate(0 132.5518314639386 -96.50620914312776)"><path d="M269.35 -174.66 C264.72 -184.92, 260.08 -195.18, 257 -202 M269.35 -174.66 C265.76 -182.61, 262.16 -190.57, 257 -202" stroke="#364fc7" stroke-width="1" fill="none"></path></g><g transform="translate(565 513) rotate(0 132.5518314639386 -96.50620914312776)"><path d="M248.89 -173.12 C251.93 -183.96, 254.98 -194.79, 257 -202 M248.89 -173.12 C251.25 -181.52, 253.61 -189.92, 257 -202" stroke="#364fc7" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(301 441.99999999999994) rotate(0 300.91632424032133 12.106460231759684)"><path d="M0 0 C2.67 22.67, -80.33 115.67, 16 136 C112.33 156.33, 478.17 166.17, 578 122 C677.83 77.83, 608.83 -87.17, 615 -129 M0 0 C2.67 22.67, -80.33 115.67, 16 136 C112.33 156.33, 478.17 166.17, 578 122 C677.83 77.83, 608.83 -87.17, 615 -129" stroke="#364fc7" stroke-width="1" fill="none"></path></g><g transform="translate(301 441.99999999999994) rotate(0 300.91632424032133 12.106460231759684)"><path d="M628.73 -102.32 C624.92 -109.73, 621.11 -117.13, 615 -129 M628.73 -102.32 C624.88 -109.79, 621.04 -117.26, 615 -129" stroke="#364fc7" stroke-width="1" fill="none"></path></g><g transform="translate(301 441.99999999999994) rotate(0 300.91632424032133 12.106460231759684)"><path d="M608.37 -99.74 C610.21 -107.86, 612.05 -115.98, 615 -129 M608.37 -99.74 C610.22 -107.93, 612.08 -116.12, 615 -129" stroke="#364fc7" stroke-width="1" fill="none"></path></g></g><mask></mask><g transform="translate(67.26666641235352 295) rotate(0 22.233333587646484 11.5)"><text x="22.233333587646484" y="0" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="text-before-edge">done</text></g><g stroke-linecap="round" transform="translate(56 292) rotate(0 33.5 14.5)"><path d="M0 0 C21.07 0, 42.14 0, 67 0 M0 0 C14.61 0, 29.22 0, 67 0 M67 0 C67 10.78, 67 21.57, 67 29 M67 0 C67 7.62, 67 15.23, 67 29 M67 29 C48.58 29, 30.17 29, 0 29 M67 29 C46.95 29, 26.89 29, 0 29 M0 29 C0 19.83, 0 10.65, 0 0 M0 29 C0 22.07, 0 15.13, 0 0" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(682 10) rotate(0 110.5 17.5)"><path d="M0 0 C81.65 0, 163.3 0, 221 0 M0 0 C65.84 0, 131.68 0, 221 0 M221 0 C221 12.45, 221 24.91, 221 35 M221 0 C221 10.52, 221 21.04, 221 35 M221 35 C155.82 35, 90.65 35, 0 35 M221 35 C149 35, 76.99 35, 0 35 M0 35 C0 27.84, 0 20.69, 0 0 M0 35 C0 22.41, 0 9.83, 0 0" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(678 188) rotate(0 93.5 15)"><path d="M0 0 C52.12 0, 104.23 0, 187 0 M0 0 C54.52 0, 109.04 0, 187 0 M187 0 C187 8.95, 187 17.9, 187 30 M187 0 C187 11.05, 187 22.1, 187 30 M187 30 C124.94 30, 62.88 30, 0 30 M187 30 C147.63 30, 108.27 30, 0 30 M0 30 C0 18.69, 0 7.39, 0 0 M0 30 C0 22.53, 0 15.05, 0 0" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(905.6875 186) rotate(0 105.5 19.5)"><path d="M0 0 C74.72 0, 149.45 0, 211 0 M0 0 C64.15 0, 128.29 0, 211 0 M211 0 C211 8.42, 211 16.84, 211 39 M211 0 C211 13.08, 211 26.16, 211 39 M211 39 C138.63 39, 66.26 39, 0 39 M211 39 C139.7 39, 68.41 39, 0 39 M0 39 C0 30.58, 0 22.16, 0 0 M0 39 C0 29.88, 0 20.76, 0 0" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(693 277) rotate(0 128.5 17)"><path d="M0 0 C74.43 0, 148.85 0, 257 0 M0 0 C96.48 0, 192.96 0, 257 0 M257 0 C257 13.14, 257 26.29, 257 34 M257 0 C257 8.22, 257 16.45, 257 34 M257 34 C161.04 34, 65.07 34, 0 34 M257 34 C155.04 34, 53.07 34, 0 34 M0 34 C0 22, 0 9.99, 0 0 M0 34 C0 26.27, 0 18.55, 0 0" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round"><g transform="translate(279 292) rotate(0 -74 5)"><path d="M0 0 C-24.67 1.67, -123.33 8.33, -148 10 M0 0 C-24.67 1.67, -123.33 8.33, -148 10" stroke="#2b8a3e" stroke-width="1" fill="none"></path></g><g transform="translate(279 292) rotate(0 -74 5)"><path d="M-120.57 -2.14 C-128.71 1.47, -136.86 5.07, -148 10 M-120.57 -2.14 C-126.23 0.37, -131.9 2.88, -148 10" stroke="#2b8a3e" stroke-width="1" fill="none"></path></g><g transform="translate(279 292) rotate(0 -74 5)"><path d="M-119.18 18.34 C-127.74 15.86, -136.3 13.39, -148 10 M-119.18 18.34 C-125.14 16.61, -131.09 14.89, -148 10" stroke="#2b8a3e" stroke-width="1" fill="none"></path></g></g><mask></mask></svg> +\ No newline at end of file diff --git a/wallet-confirm-withdraw.svg b/images/wallet-confirm-withdraw.svg diff --git a/wallet-mobile-overview.svg b/images/wallet-mobile-overview.svg diff --git a/wallet-start-manual-withdraw.svg b/images/wallet-start-manual-withdraw.svg diff --git a/index.rst b/index.rst @@ -1,6 +1,6 @@ .. This file is part of GNU TALER. - Copyright (C) 2014-2021 Taler Systems SA + Copyright (C) 2014-2023 Taler Systems SA TALER 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 @@ -56,18 +56,17 @@ Documentation Overview :maxdepth: 2 core/index - taler-exchange-manual - taler-exchange-setup-guide + taler-user-guide taler-merchant-manual - taler-wallet-cli-manual taler-merchant-api-tutorial taler-merchant-pos-terminal + taler-wallet + taler-exchange-manual + taler-challenger-manual taler-auditor-manual taler-developer-manual - taler-wallet - wallet/wallet-core - design-documents/index libeufin/index + design-documents/index global-licensing manindex genindex diff --git a/libeufin/api-common.rst b/libeufin/api-common.rst @@ -1,40 +0,0 @@ -==================================== -Common LibEuFin HTTP API Conventions -==================================== - - -Contact details -^^^^^^^^^^^^^^^ - -.. ts:def:: EmailAddress - - type EmailAddress = string; - -.. ts:def:: PhoneNumber - - type PhoneNumber = string; - -Phone numbers should start with the ``+`` symbol and the country code. - -Ratios and Fees -^^^^^^^^^^^^^^^ - -.. ts:def:: LibeufinNumber - - type LibeufinNumber = number; - -**Note:** this quantity is normally enforced to have at most -two decimal digits. The reason is to preserve the 2-decimal -digits policy of the `Amount` type, as `LibeufinNumber` is used -to multiply `Amount`. - -Amounts -^^^^^^^ - -.. ts:def:: Amount - - type Amount = string; - -Amounts have the ``$currency:X.Y`` format, where the -fractional part is optional and may contain at most two -digits. diff --git a/libeufin/api-nexus.rst b/libeufin/api-nexus.rst @@ -1,1046 +0,0 @@ -.. target audience: core developer - -Nexus API -########### - -.. contents:: Table of Contents - -HTTP API -======== - -Configuration -------------- - -Returns configuration values currently used by the Nexus process. -This API is mostly used by testing jobs. - -.. http:get:: {nexusBase}/service-config - - **Response:** - - .. ts:def:: ServiceConfigResponse - - interface ConfigResponse { - - // Connection string to the database. - dbConn: string; - } - - -Returns configuration values currently used by Nexus. - -.. http:get:: {nexusBase}/config - - **Response:** - - .. ts:def:: ConfigResponse - - interface ConfigResponse { - - currency: string; - - // nexus version, X.Y.Z format. - version: string; - } - - -Authentication --------------- - -Currently every request made to nexus must be authenticated using the *HTTP -basic auth* mechanism. - -Other authentication mechanisms (e.g. OpenID Connect) might -be supported in the future. - -User Management ---------------- - -.. http:get:: {nexusBase}/user - - Get information about the current user (based on the authentication information - in this request). - - **Response:** - - .. ts:def:: GetUserResponse - - interface UserResponse { - - // User name - username: string; - - // Password - password: string; - } - -.. http:post:: {nexusBase}/users/password - - Change password of a user. The username is extracted from - the HTTP authentication parameters. - - **Request:** - - .. code-block:: ts - - interface UserChangePassword { - newPassword: string; - } - -.. http:post:: {nexusBase}/users - - Create a new user. Only a superuser can call this API. - - **Request:** - - The body is a `User` object. - - **Response:** - - :http:statuscode:`409 Conflict`: Username is not available. - - **Details:** - - .. ts:def:: User - - interface User { - - // User name - username: string; - - // Initial password - password: string; - } - - -.. http:get:: {nexusBase}/users - - Return list of users. - -.. _nexus-permissions-api: - -Permissions API ---------------- - -The permissions API manages authorization of access of subjects (usually users) -to resources. - -Permissions are modeled a set of ``(subject, resource, permission)`` triples. -Subjects and resources consist of a type and an identifier. - -Superusers are not subject to further permission checks, they are allowed -to do any operation. - -The following subject types are currently supported: - -* ``user``: An authenticated user. The subject ID - is interpreted as the user ID. - -The following permissions are currently defined: - -* ``facade.talerWireGateway.history``: Allows querying the - transaction history through a Taler wire gateway facade. -* ``facade.talerWireGateway.transfer``: Allows creating payment initiations - to transfer money via a Taler wire gateway facade. - -The following resource IDs are currently supported: - -* ``facade``: A LibEuFin facade. The resource ID is interpreted as the - facade name. - -.. http:get:: {nexusbase}/permissions - - List all permissions. - - **Response** - - .. ts:def:: QueryPermissionsResponse - - interface QueryPermissionsResponse { - permissions: { - subjectType: string; - subjectId: string; - resourceType: string; - resourceId: string; - permissionName: string - }[]; - } - -.. http:post:: {nexusbase}/permissions - - Modify permissions. - - **Request** - - .. ts:def:: QueryPermissionsResponse - - interface QueryPermissionsResponse { - action: "grant" | "revoke"; - permission: { - subjectType: string; - subjectId: string; - resourceType: string; - resourceId: string; - permissionName: string - }; - } - - **Response** - - The response is an empty JSON object. - - -Test API --------- - - -.. http:post:: {nexusbase}/bank-accounts/{acctid}/test-camt-ingestion/{type} - - This call allows tests to **directly** give Nexus a Camt document. After - the processing, all the payment(s) details should be ingested as if the - Camt came normally from a bank / the Sandbox. ``acctid`` must match the - label of a locally imported bank account, and ``type`` for now can only be - ``C53``. - - **Response** - - The successful case should respond with a ``200 OK`` and an empty JSON body. - - -Bank Accounts -------------- - -The LibEuFin maintains a copy of the bank account transaction history and balance information, -manages payment initiations of the account and tracks the initiations of payments. - -.. http:get:: {nexusBase}/bank-accounts - - **Response:** - - A list of `BankAccount` objects - that belong to the requester. - - .. ts:def:: BankAccount - - interface BankAccount { - // mnemonic name identifying this bank account. - nexusBankAccountId: string; - // IBAN - iban: string; - // BIC - bic: string; - // Legal subject owning the account. - ownerName: string; - } - - -.. http:get:: {nexusBase}/bank-accounts/{my-acct} - - Get basic information about the bank account named ``my-acct``. - - .. ts:def:: BankAccountInfoWithBalance - - interface BankAccountInfoWithBalance { - // ID number of the database row being the default bank connection - // of ``my-acct``. - defaultBankConnection: number; - // Payto://-URI of ``my-acct``. - accountPaytoUri: string; - // Balance of ``my-acct`` as it was downloaded from the bank - // along the last Camt document. A human-readable message - // will inform the requester, should this value not be found. - lastSeenBalance: string; - } - -.. http:post:: {nexusBase}/bank-accounts/{acctid}/payment-initiations/{pmtid}/submit - - Ask nexus to submit one prepare payment at the bank. - - :http:statuscode:`404 Not found`: the unique identifier **or** - the bank connection could not be found in the system - - -.. http:get:: {nexus}/bank-accounts/{my-acct}/payment-initiations/{uuid} - - Ask the status of payment ``$uuid``. - - **Response:** - - .. ts:def:: PaymentStatus - - interface PaymentStatus { - // Can be "BOOK" or "PDNG" ('pending'). - status: string; - - // Payment unique identifier - paymentInitiationId: string; - - // True for submitted payments - submitted: boolean; - - // Creditor IBAN - creditorIban: string; - - // Creditor BIC - creditorBic: string; - - // Creditor legal name - creditorName: string; - - // Amount - amount: string; - - // Subject - subject: string; - - // Date of submission (in dashed form YYYY-MM-DD) - submissionDate: string; - - // Date of preparation (in dashed form YYYY-MM-DD) - preparationDate: string; - } - -.. http:get:: {nexusBase}/bank-accounts/{my-acct}/payment-initiations - - Ask nexus the list of initiated payments. At this stage of the API, - **all** is returned: submitted and non-submitted payments. - - **Response** - - .. ts:def:: InitiatedPayments - - interface InitiatedPayments { - - // list of all the initiated payments' UID. - initiatedPayments: PaymentStatus[]; - } - - -.. http:post:: {nexusBase}/bank-accounts/{my-acct}/payment-initiations - - Ask nexus to prepare instructions for a new payment. - Note that ``my-acct`` is the bank account that will be - **debited** after this operation. - - **Request:** - - .. ts:def:: PreparedPaymentRequest - - interface PreparedPaymentRequest { - // IBAN that will receive the payment. - iban: string; - // BIC hosting the IBAN. - bic: string; - // Legal subject that will receive the payment. - name: string; - // payment subject. - subject: string; - // amount, in the format CURRENCY:XX.YY - amount: string - } - - **Response:** - - .. ts:def:: PreparedPaymentResponse - - interface PreparedPaymentResponse { - - // Opaque identifier to be communicated when - // the user wants to submit the payment to the - // bank. - uuid: string; - } - -.. http:post:: {nexusBase}/bank-accounts/{acctid}/fetch-transactions - - Nexus will download bank transactions using the given connection. - - **Request:** - - .. ts:def:: CollectedTransaction - - interface CollectedTransaction { - - // This type indicates the time range of the query. - // It can assume the following values: - // - // 'latest': retrieves the last transactions from the bank. - // If there are older unread transactions, those will *not* - // be downloaded. - // - // 'all': retrieves all the transactions from the bank, - // until the oldest. - // - // 'previous-days': currently *not* implemented, it will allow - // the request to download transactions from - // today until N days before. - // - // 'since-last': retrieves all the transactions since the last - // time one was downloaded. - // - rangeType: string; - - // Because transactions are delivered by banks in "batches", - // then every batch can have different qualities. This value - // lets the request specify which type of batch ought to be - // returned. Currently, the following two type are supported: - // - // 'report': intra-day information - // 'statement': prior day bank statement - level: string; - - // Bank connection to use. It is a *optional* value that - // defaults to the default bank connection, if not given. - bankConnection: string; - } - - **Response:** - - .. code-block:: ts - - interface NewTransactions { - // How many transactions are new to Nexus. - newTransactions: number; - // How many transactions got downloaded by the request. - // Note that a transaction can be downloaded multiple - // times but only counts as new once. - downloadedTransactions: number; - } - -.. http:get:: {nexusBase}/bank-accounts/{acctid}/transactions - - Shows which transactions are stored locally at nexus. - - **Query parameters:** - - * **start** start (dashed YYYY-MM-DD) date of desired payments. - Optional, defaults to "earliest possible" date. - * **end** end (dashed YYYY-MM-DD) date of desired payments. - Optional, defaults to "earliest possible" date. - - - **Response:** A object with a unique field named ``transactions`` - that contains a list of `Transaction` objects. - - .. ts:def:: Transaction - - interface Transaction { - - // money moved by the transaction - amount: string; - - // CRDT or DBIT - creditDebitIndicator: string - - // Two of the most used values are BOOK, or PENDING - status: string; - - // FIXME - bankTransactionCode: string; - - // FIXME - valueDate: string; - - // When this payment got booked. In the form YYYY-MM-DD - bookingDate: string; - - // FIXME - accountServicerRef: string; - - // FIXME - batches: { - // list of batched transactions - batchTransactions: BatchedTransaction[]; - }; - } - - .. ts:def:: BatchedTransaction - - interface BatchedTransaction { - // FIXME - amount: string; - // FIXME - creditDebitIndicator: string; - // FIXME - details { - debtor: { - name: string; - }; - debtorAccount: { - iban: string; - }; - // Missing, when the payment is DBIT. - debtorAgent: { - bic: string; - }; - creditor: { - name: string; - }; - creditorAccount: { - iban: string; - }; - // Missing, when the payment is CRDT. - creditorAgent: { - iban: string; - }; - // FIXME - endToEndId: string; - // FIXME - unstructuredRemittanceInformation: string; - } - } - -Scheduling API --------------- - -.. http:post:: {nexusBase}/bank-accounts/{acctid}/schedule - - This endpoint allows the caller to define a recurrent - execution of a task. - - **Request** - - .. ts:def:: ScheduleTask - - interface ScheduleTask { - name: string; - - // a Unix-compatible cron pattern representing - // the frequency of execution of this task. - cronspec: string; - - // Can take values "fetch" (to download the history - // of the requester's bank account) or "submit" (to submit - // any initiated payment associated to the requester's - // bank account). - type: string; - - // Currently only used for "fetch" operations - params: { - level: "report" | "statement" | "all"; - rangeType: "latest" | "all" | "previous-days" | "since-last"; - }; - } - - - -.. http:get:: {nexusBase}/bank-accounts/{acctid}/schedule/{taskId} - - **Response** - - .. ts:def:: NexusTask - - // This object is a mere reflection of - // what the Nexus database keeps to implement - // the scheduling feature. - - interface NexusTask { - // FIXME: document all. - resourceType: string; - resourceId: string; - taskName: string; - taskType: string; - taskCronSpec: string; - taskParams: string; - nextScheduledExecutionSec: number; - prevScheduledExecutionSec: number; - } - - -.. http:delete:: {nexusBase}/bank-accounts/{acctid}/schedule/{taskId} - - This call deletes the task associated to ``taskId``. - -.. http:get:: {nexusBase}/bank-accounts/{acctid}/schedule - - **Response** - - .. code-block:: ts - - interface TaskCollection { - - // This field can contain *multiple* objects of the type sampled below. - schedule: { - - 'task-name': { - cronspec: string; - type: string; // fetch | submit - - // Depends on the type. Submit has it empty, whereas - // the fetch type includes the time range and the report - // level. - params: any; - } - } - } - - -Bank Connections ----------------- - -Bank connections connect the local LibEuFin bank account -to the real bank. - -.. http:post:: <nexus>/bank-connections - - Activate a new bank connection for the requesting user. - - **Request:** - - This request can accept two formats, depending on whether a - new bank connection is being made, or a connection backup is - being restored. - - - This type allows the creation of new bank accounts. - - .. ts:def:: NewBankConnection - - interface NewBankConnection { - - source: string; // only "new" allowed - - // connection name. - name: string; - - // type of the connection to make: "ebics" for example. - type: string; - - data: BankConnectionNew; - } - - This type allows to restore a previously made bank connection. - - .. ts:def:: BankConnectionRestoreRequest - - interface BankConnectionRestoreRequest { - - source: "backup"; - - // connection name. - name: string; - - // Backup data, as typically returned by the "../export-backup" API. - backup: BankConnectionBackup; - - passphrase?: string; - } - - - .. ts:def:: BankConnectionNew - - interface BankConnectionNew { - - // This type is strictly dependent on - // the connection being created. For Ebics, - // it will contain the required fields (as strings): - // 'ebicsURL', 'userID', 'partnerID', 'hostID', and - // the optional 'systemID'. - - // Other connection types, like 'local' (used for testing - // purposes skipping any interaction with the bank service) - // and 'fints' are all work in progress! - - } - - - .. ts:def:: BankConnectionBackup - - interface BankConnectionBackup { - - // The information needed in this type depend entirely - // on which connection is being restored. - } - - **Response:** - - :http:statuscode:`406 Not acceptable`: a connection with the - requested name already exists for this user. - -.. http:post:: {nexusBase}/bank-connections/delete-connection - - **Request:** - - .. ts:def:: BankConnectionDeletion - - interface BankConnectionDeletion { - // label of the bank connection to delete - bankConnectionId: string; - } - -.. http:get:: {nexusBase}/bank-connections - - List available bank connections. - - **Response** - - A JSON object whose ``bankConnections`` element is a list of the following type: - - .. ts:def:: BankConnection - - interface BankConnection { - - // connection type. For example "ebics". - type: string; - - // connection name as given by the user at - // the moment of creation. - name: string; - } - - -.. http:get:: {nexusBase}/bank-connections/{connId} - - Get information about one bank connection. - - .. ts:def:: BankConnectionInfo - - interface BankConnectionInfo { - type: string; - owner: string; - // if true, this connection can be used to communicate - // with the bank. - ready: boolean; - // Depends on the type. - details: any; - } - - -.. http:post:: {nexusBase}/bank-connections/{connId}/connect - - Initialize the connection by talking to the bank. - -.. http:post:: {nexusBase}/bank-connections/{connId}/export-backup - - Make a passphrase-encrypted backup of this connection. - -.. http:post:: {nexusBase}/bank-connections/{connId}/fetch-accounts - - Update accounts that are accessible via this bank connection. - -.. http:get:: {nexusBase}/bank-connections/{connId}/accounts - - List the bank accounts that this bank connection provides access to. - - .. ts:def:: OfferedBankAccount - - interface OfferedBankAccount { - - // Unique identifier for the offered account - offeredAccountId: string; - - // IBAN of the offered account - iban: string; - - // BIC of the account's financial institution - bic: string; - - // Account owner name - ownerName: string; - - // If the account has been imported, - // this field contains the ID of the - // Nexus bank account associated with it. - nexusBankAccountId: string | null; - } - -.. http:post:: {nexusBase}/bank-connections/{connId}/import-account - - Import a bank account provided by the connection into the Nexus. - - If no Nexus bank account with the ID ``nexusBankAccountId`` exists, - a new one will be created, and it will have ``connId`` as the - default bank connection. - - If an existing Nexus bank account with the same ID already exists, - this connection will be added as an available connection for it. - This only succeeds if the bank account has the same IBAN. - - .. ts:def:: ImportBankAccount - - interface ImportBankAccount { - - // Identifier for the bank account, as returned by /accounts - // of the bank connection. - offeredAccountId: string; - - // Nexus-local identifier for the bank account. - nexusBankAccountId: string; - } - - -.. http:get:: <nexus>/bank-connections/{connId}/messages - - List *some* details of all the ISO2022 messages gotten from the bank. It - responds with a list of the following elements: - - .. code-block:: ts - - interface BankMessageInfo { - - // the message type, typically how the containing layer - // (Ebics, for example) would label this information. For - // Camt.053 types, this value is "C53". - code: string; - - // the unique identifier of the message. - messageId: string; - - // bytes length of the message. - length: number; - } - - - -.. http:get:: <nexus>/bank-connections/{connId}/messages/{msgId} - - Return the ISO20022 XML corresponding to ``msgId``. - - -Facades -------- - -.. http:get:: <nexus>/facades/{fcid} - - **Response:** A `FacadeShowInfo` pointed to by ``fcid``. - - -.. http:get:: <nexus>/facades - - List available facades that belong to the requesting user. - - **Response:** A list of the following elements: - -.. ts:def:: FacadeShowInfo - - interface FacadeShowInfo { - - // Name of the facade, same as the "fcid" parameter. - name: string; - - // Type of the facade. - // For example, "taler-wire-gateway". - type: string; - - // Bas URL of the facade. - baseUrl: string; - - // details depending on the facade type. - config: any; - } - -.. http:delete:: {nexus}/facades/{fcid} - - Delete a facade. - -.. http:post:: {nexus}/facades - - Create a new facade. - - **Request:** - - .. code-block:: ts - - interface FacadeInfo { - // Name of the facade, same as the "fcid" parameter. - name: string; - - // Type of the facade. - // For example, "taler-wire-gateway" or "anastasis". - type: string; - - // Bank accounts that the facade has read/write - // access to. - bankAccountsRead: string[]; - bankAccountsWrite: string[]; - - // Bank connections that the facade has read/write - // access to. - bankConnectionsRead: string[]; - bankConnectionsWrite: string[]; - - // Facade-specific configuration details. - config: any; - } - - -Bank Connection Protocols -------------------------- - -.. http:get:: {nexus}/bank-connection-protocols - - List supported bank connection protocols. - -.. http:post:: {nexus}/bank-connection-protocols/ebics/test-host - - Check if the nexus can talk to an EBICS host. - This doesn't create a new connection in the database, - and is useful during setup when the user hasn't entered - the full details for the connection yet. - - .. ts:def:: EbicsHostTestRequest - - interface EbicsHostTestRequest { - ebicsBaseUrl: string; - ebicsHostId: string; - } - - -EBICS-specific APIs -------------------- - -The following endpoints are only available for EBICS bank connections. -They are namespaced under the ``/ebics/`` sub-resource. - -.. http:post:: {nexusBase}/bank-connections/{connection-name}/ebics/download/{msg} - - .. warning:: - - Use with care. Typically only necessary for testing and debugging. - - Perform an EBICS download transaction of type ``msg``. - This request will not affect any bank account or other state - in the nexus database. It will just make a request to the bank - and return the answer. - -.. http:post:: {nexusBase}/bank-connections/{connection-name}/ebics/upload/{msg} - - .. warning:: - - Use with care. Typically only necessary for testing and debugging. - - Perform an EBICS upload transaction of type ``msg``. - This request will not affect any bank account or other state - in the nexus database. It will just make a request to the bank - and return the answer. - -Anastasis API. --------------- - -This is a read-only API offering a view over *only* the incoming -transactions of a bank account. It is named after the typical user - -a Anastasis service - but can be used in any case where only the -incoming transactions are of interest. - -.. http:get:: ${BASE_URL}/history/incoming - - Return a list of transactions made to the customer. - - The bank account of the customer is determined via the base URL and/or the - user name in the ``Authorization`` header. In fact the transaction history - might come from a "virtual" account, where multiple real bank accounts are - merged into one history. - - Transactions are identified by an opaque numeric identifier, referred to here - as *row ID*. The semantics of the row ID (including its sorting order) are - determined by the bank server and completely opaque to the client. - - The list of returned transactions is determined by a row ID *starting point* - and a signed non-zero integer *delta*: - - * If *delta* is positive, return a list of up to *delta* transactions (all matching - the filter criteria) strictly **after** the starting point. The transactions are sorted - in **ascending** order of the row ID. - * If *delta* is negative, return a list of up to *-delta* transactions (all matching - the filter criteria) strictly **before** the starting point. The transactions are sorted - in **descending** order of the row ID. - - If *starting point* is not explicitly given, it defaults to: - - * A value that is **smaller** than all other row IDs if *delta* is **positive**. - * A value that is **larger** than all other row IDs if *delta* is **negative**. - - **Request** - - :query start: *Optional.* - Row identifier to explicitly set the *starting point* of the query. - :query delta: - The *delta* value that determines the range of the query. - :query long_poll_ms: *Optional.* If this parameter is specified and the - result of the query would be empty, the bank will wait up to ``long_poll_ms`` - milliseconds for new transactions that match the query to arrive and only - then send the HTTP response. A client must never rely on this behavior, as - the bank may return a response immediately or after waiting only a fraction - of ``long_poll_ms``. - - **Response** - - :http:statuscode:`200 OK`: JSON object of type `IncomingHistory`. - :http:statuscode:`400 Bad request`: Request malformed. The bank replies with an `ErrorDetail` object. - :http:statuscode:`401 Unauthorized`: Authentication failed, likely the credentials are wrong. - :http:statuscode:`404 Not found`: The endpoint is wrong or the user name is unknown. The bank replies with an `ErrorDetail` object. - - .. ts:def:: IncomingHistory - - interface IncomingHistory { - - // Array of incoming transactions. - incoming_transactions : IncomingBankTransaction[]; - - } - - .. ts:def:: IncomingBankTransaction - - interface IncomingBankTransaction { - - // Opaque identifier of the returned record. - row_id: SafeUint64; - - // Date of the transaction. - date: Timestamp; - - // Amount transferred. - amount: Amount; - - // Payto URI to identify the receiver of funds. - // This must be one of the exchange's bank accounts. - credit_account: string; - - // Payto URI to identify the sender of funds. - debit_account: string; - - // subject of the incoming payment. - subject: string; - - } - -The anastasis facade --------------------- - -The ``anastasis`` facade has the following configuration: - - -.. ts:def:: AnastasisFacadeConfig - - interface AnastasisFacadeConfig { - // Bank account and connection that is abstracted over. - bankAccount: string; - bankConnection: string; - - currency: string; - - // Corresponds to whether we trust C52, C53 or C54 (SEPA ICT) - // for incoming transfers. - reserveTransferLevel: "statement" | "report" | "notification"; - } - -The taler-wire-gateway facade ------------------------------ - -The ``taler-wire-gateway`` facade has the following configuration: - - -.. ts:def:: TalerWireGatewayFacadeConfig - - interface TalerWireGatewayFacadeConfig { - // Bank account and connection that is - // abstracted over. - bankAccount: string; - bankConnection: string; - - currency: string; - - // Corresponds to whether we trust C52, C53 or C54 (SEPA ICT) - // for incoming transfers. - reserveTransferLevel: "statement" | "report" | "notification"; - } diff --git a/libeufin/api-sandbox-future.rst b/libeufin/api-sandbox-future.rst @@ -1,135 +0,0 @@ -Future Sandbox API -################## - -Resources. -^^^^^^^^^^ - -Sandbox serves the following resources: - - - Demobanks. - - Bank accounts. - - Subscribers. - - Transactions. - - Customers. - - Reports. - -The resources are subject to all CRUD operations, via by two -types of users: the 'admin' and the customers. The admin has -rights on all of them. - -One of the main differences with the previous versions is the -removal of the "/admin" initial component. If the administrator -authenticates for one operation, then this one is of type ``admin``: -no need for a dedicated and extra URI path component. - -For example, mocking transactions in the system was a typical -/admin-operation, but since transactions themselves are resources -and any resource is subject to CRUD operations, then mocking one -becomes just a ``C`` operation on the 'transactions' resources. If -a test case wants to simplify the authentication - by hard-coding -the credentials, for example - before mocking one transaction, then -it can impersonate the administrator. - -.. note:: - - ``POST``\ ing to an endpoint with a trailing ``$id`` means - modification of an existing resource. - -Demobanks -^^^^^^^^^ - -Demobanks are the main containers of all the other resources. -They take configuration values, like the currency for example. - -.. http:get:: /admin/demobanks -.. http:get:: /admin/demobanks/$id -.. http:post:: /admin/demobanks -.. http:post:: /admin/demobanks/$id -.. http:delete:: /admin/demobanks/$id - -Bank accounts. -^^^^^^^^^^^^^^ - -Bank accounts collect money of customers and participate -in transactions. - -The ``$base`` is one demobank, in the form ``/demobanks/$id``. -That is due because a bank account must inherit some defaults -from the demobank, like the currency. - -.. http:get:: $base/bankaccounts -.. http:get:: $base/bankaccounts/$id -.. http:post:: $base/bankaccounts -.. http:post:: $base/bankaccounts/$id -.. http:delete:: $base/bankaccounts/$id - -Subscribers. -^^^^^^^^^^^^ - -Subscribers are (optional) customers identities for protocols -other than the native one. - -A subscriber is not required to have a bank account "soon". Therefore, -it can be created, and later be linked to one bank account. For this -reason, the ``$base`` should not mention one bank account. - -.. note:: - - Creating a subscriber is a time-consuming operation that goes often - through slow channels, therefore it should basically never be done - more than once. - -.. http:get:: $base/subscribers -.. http:get:: $base/subscribers/$id -.. http:post:: $base/subscribers -.. http:post:: $base/subscribers/$id -.. http:delete:: $base/subscribers/$id - -Transactions. -^^^^^^^^^^^^^ - -Transactions are money movements between bank accounts. - -For convenience, ``$base`` **could** mention one bank account -to let customers see their transactions without defining "history" -query parameters: like ``$demobank/bankaccounts/$bankaccountId/transactions``. - -At the same time, transactions should be easy to query regardless -of whose bank account they involve -- for administrative reasons, for -example. Hence, a "global" URI scheme like ``$demobank/transactions?param=XXX`` -should be offered as well. - -.. http:get:: $base/transactions -.. http:get:: $base/transactions/$id -.. http:post:: $base/transactions -.. http:post:: $base/transactions/$id -.. http:delete:: $base/transactions/$id - -Customers. -^^^^^^^^^^ - -Customers are persons that **can** have one bank account. As -with subscribers, ``$base`` should not mention any bank account -so as to leave more flexibility to assign new bank accounts to -the same customer. - -.. http:get:: $base/customers -.. http:get:: $base/customers/$id -.. http:post:: $base/customers -.. http:post:: $base/customers/$id -.. http:delete:: $base/customers/$id - -Reports. -^^^^^^^^ - -Reports are persistent documents witnessing transactions. -A typical example is a Camt.053 statement. A report lives -even after a bank account gets deleted or a customer leaves -the bank, therefore ``$base`` should only mention a demobank -instance. - -.. http:get:: $base/reports -.. http:get:: $base/reports/$id -.. http:post:: $base/reports -.. http:post:: $base/reports/$id -.. http:delete:: $base/reports/$id diff --git a/libeufin/api-sandbox.rst b/libeufin/api-sandbox.rst @@ -1,1028 +0,0 @@ -.. target audience: developer, core developer - -.. _sandbox-api: - -Sandbox API -########### - -Sandbox emulates a minimal bank, to provide EBICS access to test -`Taler <https://taler.net>`_. The top-level API defines two main -groups: `demobanks <Demobanks_>`_ and `legacy <Legacy API_>`_. -Currently, `error types <error-types_>`_ are common to both groups. - -Demobanks -========= - -Sandbox is designed to allow multiple *demobanks* being hosted, -where every demobank can have its own configuration (including -a different currency). A demobank has a name, although currently -only one demobank, named ``default``, is supported. Such demobank -activates the API segment ``/demobanks/default``, under which several -APIs are then served. The following sections describe all such APIs. - - -.. _circuit-api: - -Circuit API -^^^^^^^^^^^ - -This API offers to manage a selected group of users who act as businesses -for a local currency. Policies to disincentivize cashout operations may -also apply, making therefore this setup a *circuit* within a wider traditional -currency. - -For brevity, the list of response statuses for each endpoint may not be exhaustive. - -.. note:: - This API requires to **disable** ordinary registrations in the - configuration, to avoid other APIs from circumventing this registration - policy. See ``libeufin-sandbox config --help``. - -The following endpoints are served under ``/demobanks/default/circuit-api``. - -The cliend side of this API is offered both along the -:doc:`CLI <circuit-cli-commands>` and the SPA. The SPA is generally served -along Sandbox ``/`` path. - -Accounts --------- - -.. _circuit-register: - -.. http:post:: /accounts - - Create a new bank account. Only the administrator is allowed. - - **Request:** - - .. ts:def:: CircuitAccountRequest - - interface CircuitAccountRequest { - // Username - username: string; - - // Password. - password: string; - - // Addresses where to send the TAN. If - // this field is missing, then the cashout - // won't succeed. - contact_data: CircuitContactData; - - // Legal subject owning the account. - name: string; - - // 'payto' address pointing the bank account - // where to send payments, in case the user - // wants to convert the local currency back - // to fiat. - cashout_address: string; - - // IBAN of this bank account, which is therefore - // internal to the circuit. Randomly generated, - // when it is not given. - internal_iban?: string; - } - - .. ts:def:: CircuitContactData - - interface CircuitContactData { - - // E-Mail address - email?: EmailAddress; - - // Phone number. - phone?: PhoneNumber; - } - - - **Response:** - - :http:statuscode:`204 No content`: - The account was successfully created. - :http:statuscode:`400 Bad request`: - Input data was invalid. For example, the client specified a invalid - phone number or e-mail address. - :http:statuscode:`403 Forbidden`: - The response should indicate one of the following reasons. - - * A institutional username was attempted, like ``admin`` or ``bank``. - * A non admin user tried the operation. - - :http:statuscode:`409 Conflict`: - At least one registration detail was not available, - the error message should inform about it. - - -.. _circuit-delete-account: - -.. http:delete:: /accounts/$username - - Delete the account whose username is ``$username``. The deletion - succeeds only if the balance is *zero*. Only the administrator is - allowed. - - **Response:** - - :http:statuscode:`204 No content`: - The account was successfully deleted. - :http:statuscode:`403 Forbidden`: - The administrator specified a institutional username, like - ``admin`` or ``bank``. - :http:statuscode:`404 Not found`: - The username was not found. - :http:statuscode:`412 Precondition failed`: - The balance was not zero. - - -.. _circuit-reconfig: - -.. http:patch:: /accounts/$username - - Allows the administrator and the user to reconfigure - the account data of ``$username``. - - .. note:: - - Only the administrator has the rights to change the - user legal name. - - **Request:** - - .. ts:def:: CircuitAccountReconfiguration - - interface CircuitAccountReconfiguration { - - // Addresses where to send the TAN. - contact_data: CircuitContactData; - - // 'payto' address pointing the bank account - // where to send payments, in case the user - // wants to convert the local currency back - // to fiat. - cashout_address: string; - - // Legal name associated with $username. NOTE: - // only the administrator can change this value. - name?: string; - } - - **Response:** - - :http:statuscode:`204 No content`: - Operation successful. - - :http:statuscode:`403 Forbidden`: - The rights to change ``$username`` are not sufficient. - That includes the case where a correctly authenticated - user tries to change their legal name. It also - includes the case where 'admin' tries to change its - own account. - - :http:statuscode:`404 Not found`: - The account pointed by ``$username`` - was not found. - - -.. _circuit-password-reconfig: - -.. http:patch:: /accounts/$username/auth - - Allows administrators *and* ordinary users to - change the account's password. - - **Request:** - - .. ts:def:: AccountPasswordChange - - interface AccountPasswordChange { - - // New password. - new_password: string; - } - - **Response:** - - :http:statuscode:`204 No content`: - Operation successful. - - -.. _circuit-account-list: - -.. http:get:: /accounts - - Obtains a list of the accounts registered at the bank. - It returns only the information that this API handles, without - any balance or transactions list. The :doc:`Access API </core/api-bank-access>` - offers that. This request is only available to the administrator. - - **Request:** - - :query filter: *Optional.* - Pattern to filter on the account legal name. Given - the filter 'foo', all the results will **contain** - 'foo' in their legal name. Without this option, - all the existing accounts are returned. - - **Response:** - - `CircuitAccounts <circuit-accounts_>`_ - - .. _circuit-accounts: - - .. ts:def:: CircuitAccounts - - interfaces CircuitAccounts { - customers: CircuitAccountMinimalData[]; - } - - .. ts:def:: CircuitAccountMinimalData - - interface CircuitAccountMinimalData { - // Username - username: string; - - // Legal subject owning the account. - name: string; - - } - - :http:statuscode:`200 OK`: - At least one account was found. - - :http:statuscode:`204 No Content`: - No accounts were found for the given request. - - :http:statuscode:`403 Forbidden`: - A ordinary user invoked this call. - - -.. _circuit-account-info: - -.. http:get:: /accounts/$username - - Obtains information relative to the account owned by - ``$username``. The request is available to the administrator - and ``$username`` itself. - - **Response:** - - .. ts:def:: CircuitAccountData - - interface CircuitAccountData { - // Username - username: string; - - // IBAN hosted at Libeufin Sandbox - iban: string; - - contact_data: CircuitContactData; - - // Legal subject owning the account. - name: string; - - // 'payto' address pointing the bank account - // where to send cashouts. - cashout_address: string; - } - - :http:statuscode:`403 Forbidden`: - The user is not allowed. - -Cashouts --------- - -.. _circuit-cashout: - -.. http:post:: /cashouts - - Initiates a conversion to fiat currency. The account to be - credited is the one specified at registration time via the - *cashout_address* parameter. The account to be - debited is extracted from the authentication credentials. - The bank sends a TAN to the customer to let them confirm the - operation. The request is only available to ordinary users, not - to the administrator. - - .. note:: - - Consult the `cashout rates call <cashout-rates_>`_ to learn - about any applicable fee or exchange rate. - - To test this operation without relying on any SMS/E-mail provider, - Libeufin offers two methods: defining an environment variable called - ``LIBEUFIN_CASHOUT_TEST_TAN`` or specifying the value ``file`` to - the ``tan_channel`` field of the `request object <cashout-request_>`_. - Assuming ``LIBEUFIN_CASHOUT_TEST_TAN`` is set to *T*, every */confirm* - operation can use *T* as the TAN. Setting instead the ``tan_channel`` - field to ``file`` will cause the server to (over)write every TAN to - ``/tmp/libeufin-cashout-tan.txt``. If both are used, the environment - variable takes the precedence. - - - **Request:** - - `CashoutRequest <cashout-request_>`_ - - .. ts:def:: TanChannel - - enum TanChannel { - SMS = "sms", - EMAIL = "email", - FILE = "file" - } - - .. _cashout-request: - - .. ts:def:: CashoutRequest - - interface CashoutRequest { - - // Optional subject to associate to the - // cashout operation. This data will appear - // as the incoming wire transfer subject in - // the user's external bank account. - subject?: string; - - // That is the plain amount that the user specified - // to cashout. Its $currency is the circuit currency. - amount_debit: Amount; - - // That is the amount that will effectively be - // transferred by the bank to the user's bank - // account, that is external to the circuit. - // It is expressed in the fiat currency and - // is calculated after the cashout fee and the - // exchange rate. See the /cashout-rates call. - amount_credit: Amount; - - // Which channel the TAN should be sent to. If - // this field is missing, it defaults to SMS. - // The default choice prefers to change the communication - // channel respect to the one used to issue this request. - tan_channel?: TanChannel; - } - - **Response:** - - .. ts:def:: CashoutPending - - interface CashoutPending { - // UUID identifying the operation being created - // and now waiting for the TAN confirmation. - uuid: string; - } - - :http:statuscode:`202 Accepted`: - The cashout request was correctly created and - the TAN authentication now is pending. - :http:statuscode:`400 Bad request`: - The exchange rate was incorrectly applied. - :http:statuscode:`403 Forbidden`: - A institutional user (``admin`` or ``bank``) tried the operation. - :http:statuscode:`409 Conflict`: - The user did not share any contact data where to send the TAN. - :http:statuscode:`412 Precondition failed`: - The account does not have sufficient funds. - :http:statuscode:`503 Service unavailable`: - The bank does not support the TAN channel for this operation. - - -.. _circuit-cashout-abort: - -.. http:post:: /cashouts/$cashoutId/abort - - Aborts the ``$cashoutId`` operation. Original author - *and* admin are both allowed. - - **Response:** - - :http:statuscode:`204 No content`: - ``$cashoutId`` was found in the *pending* state - and got successfully aborted. - :http:statuscode:`404 Not found`: - ``$cashoutId`` is not found. Note: that happens - also when ``$cashoutId`` got aborted before this request. - :http:statuscode:`412 Precondition failed`: - ``$cashoutId`` was already confirmed. - - -.. _circuit-cashout-confirm: - -.. http:post:: /cashouts/$cashoutId/confirm - - Confirms the ``$cashoutId`` operation by accepting its - TAN. The request should still be authenticated with - the users credentials. Only the original author is allowed. - - **Request:** - - .. ts:def:: CashoutConfirm - - interface CashoutConfirm { - - // the TAN that confirms $cashoutId. - tan: string; - } - - **Response:** - - :http:statuscode:`204 No content`: - ``$cashoutId`` was found in the *pending* state and - got successfully confirmed. - :http:statuscode:`403 Forbidden`: - wrong TAN. - :http:statuscode:`404 Not found`: - ``$cashoutId`` is not found. Note: that happens - also when ``$cashoutId`` got aborted before this request. - :http:statuscode:`409 Conflict`: - At least the following two cases are possible - * an institutional user (``admin`` or ``bank``) tried the operation - * the user changed their cash-out address between the creation and the confirmation of ``$cashoutId``. - :http:statuscode:`412 Precondition failed`: - ``$cashoutId`` was already confirmed. - -.. _cashout-rates: - -.. http:get:: /config - - **Response:** - - .. ts:def:: Config - - interface Config { - // Name of this API, always "circuit". - name: string; - // API version in the form $n:$n:$n - version: string; - // Contains ratios and fees related to buying - // and selling the circuit currency. - ratios_and_fees: RatiosAndFees; - // Fiat currency. That is the currency in which - // cash-out operations ultimately wire money. - fiat_currency: string; - } - - .. ts:def:: RatiosAndFees - - interface RatiosAndFees { - // Exchange rate to buy the circuit currency from fiat. - buy_at_ratio: LibeufinNumber; - // Exchange rate to sell the circuit currency for fiat. - sell_at_ratio: LibeufinNumber; - // Fee to subtract after applying the buy ratio. - buy_in_fee: LibeufinNumber; - // Fee to subtract after applying the sell ratio. - sell_out_fee: LibeufinNumber; - } - - - Example. Given a circuit currency CC, a fiat currency FC, - a *sell_at_ratio* = 0.9 and *sell_out_fee* = 0.03, selling - 10 CC would result in the following FC: (10 * 0.9) - 0.03 - = 8.97 FC. On the other hand, given *buy_at_ratio* = 1.1 - and *buy_in_fee* = 0.01, a user wanting to spend 10 FC to - buy the CC would result in the following CC: (10 * 1.1) - - 0.01 = 10.99 CC. - - .. note:: - - the terms 'sell out' and 'cashout' may be used interchangeably. - - -.. _circuit-cashouts: - -.. http:get:: /cashouts - - Returns the list of all the (pending and confirmed) cash-out operations. - Ordinary users can only use this endpoint to learn their *own* cash-out - operations. - - **Request:** - - :query account: *Optional.* - Filters the request to only get the cash-out operations related to - the account specified in this parameter. Ordinary users must use - this option and pass their own username as the value. - - **Response:** - - .. ts:def:: Cashouts - - interface Cashouts { - // Every string represents a cash-out operation UUID. - cashouts: string[]; - } - - :http:statuscode:`200 OK`: - At least one cash-out operation was found. - - :http:statuscode:`204 No Content`: - No cash-out operations were found at the bank - - :http:statuscode:`403 Forbidden`: - A ordinary user invoked this call either without - the ``account`` parameter or by passing to it someone - else's username. - - -.. _circuit-cashout-details: - -.. http:get:: /cashouts/$cashoutId - - Informs about the status of the ``$cashoutId`` operation. - The request is available to the administrator and the original author. - - **Response:** - - `CashoutStatusResponse <cashout-status_>`_ - - .. _cashout-status: - - .. ts:def:: CashoutStatus - - interface CashoutStatusResponse { - - status: CashoutStatus; - // Amount debited to the circuit bank account. - amount_debit: Amount; - // Amount credited to the external bank account. - amount_credit: Amount; - // Transaction subject. - subject: string; - // Circuit bank account that created the cash-out. - account: string; - // Fiat bank account that will receive the cashed out amount. - cashout_address: string; - // Ratios and fees related to this cash-out at the time - // when the operation was created. - ratios_and_fees: RatiosAndFees; - // Time when the cash-out was created. - creation_time: number; // milliseconds since the Unix epoch - // Time when the cash-out was confirmed via its TAN. - // Missing or null, when the operation wasn't confirmed yet. - confirmation_time?: number | null; // milliseconds since the Unix epoch - } - - .. ts:def:: CashoutStatus - - enum CashoutStatus { - - // The payment was initiated after a valid - // TAN was received by the bank. - CONFIRMED = "confirmed", - - // The cashout was created and now waits - // for the TAN by the author. - PENDING = "pending", - } - - **Response:** - - :http:statuscode:`404 Not found`: - The cashout operation was not found. That is - *also* the case of ``$cashoutId`` being an aborted - operation. - -Access API -^^^^^^^^^^ - -Every endpoint is served under ``/demobanks/default/access-api``. -See :doc:`/core/api-bank-access`. This API allows users to access -their bank accounts and trigger Taler withdrawals. - -Integration API -^^^^^^^^^^^^^^^ - -Every endpoint is served under ``/demobanks/default/integration-api``. -See :doc:`/core/api-bank-integration`. This API handles the communication -with Taler wallets. - -Taler Wire Gateway API -^^^^^^^^^^^^^^^^^^^^^^ - -Served under ``/demobanks/default/taler-wire-gateway``. Currently, -only the :ref:`admin/add-incoming <twg-admin-add-incoming>` endpoint -is implemented. This endpoint allows testing, but the rest of -this API does never involve the Sandbox. - -EBICS API -^^^^^^^^^ - -.. _demobank-create-ebics-subscriber: - -.. http:post:: /demobanks/default/ebics/subscribers - - Allows (only) the *admin* user to associate a bank account - to a EBICS subscriber. If the latter does not exist, it is - created. - - **Request:** - - .. ts:def:: SubscriberRequest - - interface SubscriberRequest { - - // hostID - hostID: string; - - // userID - userID: string; - - // partnerID - partnerID: string; - - // systemID, optional. - systemID: string; - - // Label of the bank account to associate with - // this subscriber. - demobankAccountLabel: string; - } - -.. note:: - - The following endpoints are **not** served under the ``/demobank/default`` segment. - -Legacy API -========== - -This was the first API offered by Sandbox. It is used in -some test cases. One is hosted at the Wallet repository; other -MAY as well exist. - -Except of the main EBICS handler located at "/ebicsweb", all -the EBICS calls have to authenticate the 'admin' user via -the HTTP basic auth scheme. - -EBICS Hosts -^^^^^^^^^^^ - -.. http:post:: /admin/ebics/hosts - - Create a new EBICS host. - - **Request:** - - .. ts:def:: EbicsHostRequest - - interface EbicsHostRequest { - - // Ebics version. - hostID: string; - - // Name of the host. - ebicsVersion: string; - } - - -.. http:get:: /admin/ebics/hosts - - Shows the list of all the hosts in the system. - - **Response:** - - .. ts:def:: EbicsHostResponse - - interface EbicsHostResponse { - - // shows the host IDs that are active in the system. - // The Ebics version *is* missing, but it's still available - // via the HEV message. - ebicsHosts: string[]; - } - -.. http:post:: /admin/ebics/hosts/$hostID/rotate-keys - - Overwrite the bank's Ebics keys with random ones. This is entirely - meant for tests (as the Sandbox itself is) and no backup will be - produced along this operation. - -EBICS Subscribers -^^^^^^^^^^^^^^^^^ - -.. http:post:: /admin/ebics/bank-accounts - - Associates a new bank account to an existing subscriber. - - .. note:: - - This call allows to create a bank account without - any associated user profile! That makes the basic auth - access to the financial data **only** possible for the - admin. - - **Request:** - - .. ts:def:: BankAccountRequest - - interface BankAccountRequest { - - // Ebics subscriber - subscriber: { - userID: string; - partnerID: string; - systemID: string; - }; - - // IBAN - iban: string; - - // BIC - bic: string; - - // human name - name: string; - - // bank account label - label: string; - } - -.. http:get:: /admin/ebics/subscribers - - Shows the list of all the subscribers in the system. - - **Response:** - - .. ts:def:: SubscribersResponse - - interface SubscribersResponse { - - subscribers: Subscriber[] - } - - .. ts:def:: Subscriber - - interface Subscriber { - - // userID - userID: string; - - // partnerID - partnerID: string; - - // hostID - hostID: string; - - // Label of the bank account - // associated with this Ebics subscriber. - demobankAccountLabel: string; - } - -.. http:post:: /admin/ebics/subscribers - - Create a new EBICS subscriber without associating - a bank account to it. This call is **deprecated**. - Follow `this page <https://bugs.gnunet.org/view.php?id=7507>`_ - for updates over the EBICS management REST design. - - **Request:** - - .. ts:def:: SubscriberRequestDeprecated - - interface SubscriberRequestDeprecated { - - // hostID - hostID: string; - - // userID - userID: string; - - // partnerID - partnerID: string; - - // systemID, optional. - systemID: string; - - } - -Bank accounts -^^^^^^^^^^^^^ - -The access to a particular bank account is granted either to the -owner or to admin, via the HTTP basic auth scheme. A 'owner' is -a registered customer, who is identified by a username. The -registration of customers is offered via the :doc:`/core/api-bank-access`. - -.. note:: - - The current version allows only one bank account per - customer, where the bank account name (also called 'label') - equals the owner's username. - -.. http:get:: /admin/bank-accounts - - Give summary of all the bank accounts. Only admin allowed. - - **Response:** - - .. ts:def:: AdminBankAccount - - interface AdminBankAccount { - - // IBAN - iban: string; - - // BIC - bic: string; - - // human name - name: string; - - // bank account label - label: string; - } - - -.. http:get:: /admin/bank-accounts/$accountLabel - - Give information about a bank account. - - **Response:** - - .. ts:def:: AdminBankAccountBalance - - interface AdminBankAccountBalance { - // Balance in the $currency:$amount format. - balance: string; - // IBAN of the bank account identified by $accountLabel - iban: string; - // BIC of the bank account identified by $accountLabel - bic: string; - // Mentions $accountLabel - label: string; - } - -.. http:post:: /admin/bank-accounts/$accountLabel - - Create bank account. Existing users without a bank account - can request too. - - **Request:** :ts:type:`AdminBankAccount` - -Transactions -^^^^^^^^^^^^ - -.. http:get:: /admin/bank-accounts/$accountLabel/transactions - - Inform about all the transactions of one bank account. - - **Response:** - - .. ts:def:: AdminTransactions - - interface AdminTransactions { - payments: AdminTransaction[]; - } - - .. ts:def:: AdminTransaction - - interface AdminTransaction { - - // Label of the bank account involved in this payment. - accountLabel: string; - - // Creditor IBAN - creditorIban: string; - - // Debtor IBAN - debtorIban: string; - - // UID given by one financial institute to this payment. - // FIXME: clarify whether that can be also assigned by - // the other party's institution. - accountServicerReference: string; - - // ID of the Pain.001 that initiated this payment. - paymentInformationId: string; - - // Unstructured remittance information. - subject: string; - - // Date of the payment in the HTTP header format. - date: string; - - // The number amount as a string. - amount: string; - - // BIC of the creditor IBAN. - creditorBic: string; - - // Legal name of the creditor. - creditorName: string; - - // BIC of the debtor IBAN. - debtorBic: string; - - // Legal name of the debtor. - debtorName: string; - - // Payment's currency - currency: string; - - // Have values 'credit' or 'debit' relative - // to the requesting user. - creditDebitIndicator: string; - } - -.. http:post:: /admin/bank-accounts/$accountLabel/generate-transactions - - Generate one incoming and one outgoing transaction for the bank account - identified by ``$accountLabel``. Only admin allowed. - -.. http:post:: /admin/bank-accounts/$accountLabel/simulate-incoming-transaction - - Book one incoming transaction for $accountLabel. - The debtor (not required to be in the same bank) - information is taken from the request. Only admin allowed. - - **Request:** - - .. ts:def:: AdminSimulateTransaction - - interface AdminSimulateTransaction { - - // Debtor IBAN. - debtorIban: string; - - // Debtor BIC. - debtorBic: string; - - // Debtor name. - debtorName: string; - - // Amount number (without currency) as a string. - amount: string; - - // Payment subject. - subject: string; - } - - -.. http:post:: /admin/payments/camt - - Return the last camt.053 document from the requesting account. - - **Request** - - .. code-block:: tsref - - interface CamtParams { - - // label of the bank account being queried. - bankaccount: string; - - // The Camt type to return. Only '53' is allowed - // at this moment. - type: number; - } - - **Response** - - The last Camt.053 document related to the bank account - mentioned in the request body. - - -.. _error-types: - -====== -Errors -====== - -The JSON type coming along a non 2xx response is the following: - -.. ts:def:: SandboxError - - interface SandboxError { - error: SandboxErrorDetail; - } - -.. ts:def:: SandboxErrorDetail - - interface SandboxErrorDetail { - - // String enum classifying the error. - type: ErrorType; - - // Human-readable error description. - description: string; - } - -.. ts:def:: ErrorType - - enum ErrorType { - /** - * This error can be related to a business operation, - * a non-existent object requested by the client, or - * even when the bank itself fails. - */ - SandboxError = "sandbox-error", - - /** - * It is the error type thrown by helper functions - * from the Util library. Those are used by both - * Sandbox and Nexus, therefore the actual meaning - * must be carried by the error 'message' field. - */ - UtilError = "util-error" - } diff --git a/libeufin/camt.054-style-0.png b/libeufin/camt.054-style-0.png Binary files differ. diff --git a/libeufin/camt.054-style-1.png b/libeufin/camt.054-style-1.png Binary files differ. diff --git a/libeufin/check-payment-subject-0.png b/libeufin/check-payment-subject-0.png Binary files differ. diff --git a/libeufin/check-payment-subject-1.png b/libeufin/check-payment-subject-1.png Binary files differ. diff --git a/libeufin/circuit-cli-commands.rst b/libeufin/circuit-cli-commands.rst @@ -1,3 +1,6 @@ +CLI commands for the circuit API +################################ + The following list shows all the CLI subcommands acting as the Circuit API's client side. Each section name is one subcommand available in this pattern: @@ -6,19 +9,19 @@ name is one subcommand available in this pattern: Finally, each section name links to the related API documentation of the endpoint being addressed. -:ref:`circuit-account-info <circuit-account-info>` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +circuit-account-info +^^^^^^^^^^^^^^^^^^^^ - Retrieve Circuit information about one account. Useful to get cash-out - address and contact details. +Retrieve Circuit information about one account. Useful to get cash-out +address and contact details. Options: --username TEXT Username of the account to retrieve. It defaults to LIBEUFIN_SANDBOX_USERNAME and doesn't accept 'admin'. --help Show this message and exit. -:ref:`circuit-accounts <circuit-account-list>` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +circuit-accounts +^^^^^^^^^^^^^^^^ Gets the list of all the accounts managed by the Circuit. Only 'admin' allowed @@ -26,10 +29,10 @@ Options: Options: --help Show this message and exit. -:ref:`circuit-cashout <circuit-cashout>` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +circuit-cashout +^^^^^^^^^^^^^^^ - Create a cash-out operation. If successful, the user gets a TAN. +Create a cash-out operation. If successful, the user gets a TAN. Options: --subject TEXT Payment subject to associate to the outgoing and @@ -47,20 +50,20 @@ Options: --help Show this message and exit. -:ref:`circuit-cashout-abort <circuit-cashout-abort>` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +circuit-cashout-abort +^^^^^^^^^^^^^^^^^^^^^ - Abort a cash-out operation. Admin and author are allowed to request. +Abort a cash-out operation. Admin and author are allowed to request. Options: --uuid TEXT UUID of the cash-out operation to abort. [required] --help Show this message and exit. -:ref:`circuit-cashout-confirm <circuit-cashout-confirm>` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +circuit-cashout-confirm +^^^^^^^^^^^^^^^^^^^^^^^ - Confirm a cash-out operation. Only the author is allowed (no admin). +Confirm a cash-out operation. Only the author is allowed (no admin). Options: --tan TEXT TAN that authorizes the cash-out operaion. [required] @@ -68,42 +71,42 @@ Options: --help Show this message and exit. -:ref:`circuit-cashout-details <circuit-cashout-details>` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +circuit-cashout-details +^^^^^^^^^^^^^^^^^^^^^^^ - Retrieve status information about one cash-out operation. Admin and author - are allowed to request. +Retrieve status information about one cash-out operation. Admin and author +are allowed to request. Options: --uuid TEXT UUID of the cash-out operation to retrieve. [required] --help Show this message and exit. -:ref:`circuit-cashouts <circuit-cashouts>` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +circuit-cashouts +^^^^^^^^^^^^^^^^ - Gets the list of all the pending and confirmed cash-out operations. +Gets the list of all the pending and confirmed cash-out operations. Options: --help Show this message and exit. -:ref:`circuit-delete-account <circuit-delete-account>` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +circuit-delete-account +^^^^^^^^^^^^^^^^^^^^^^ - Delete one account. Only available to the administrator and for accounts - with zero balance. +Delete one account. Only available to the administrator and for accounts +with zero balance. Options: --username TEXT account to delete [required] --help Show this message and exit. -:ref:`circuit-password-reconfig <circuit-password-reconfig>` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +circuit-password-reconfig +^^^^^^^^^^^^^^^^^^^^^^^^^ - Ask interactively to change the password. It needs administrator or owner - credentials +Ask interactively to change the password. It needs administrator or owner +credentials Options: --username TEXT Username whose password will change. Defaults to @@ -112,11 +115,11 @@ Options: --help Show this message and exit. -:ref:`circuit-reconfig <circuit-reconfig>` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +circuit-reconfig +^^^^^^^^^^^^^^^^ - Reconfigure an account with cash-out capabilities. It needs administrator - or owner credentials +Reconfigure an account with cash-out capabilities. It needs administrator +or owner credentials Options: --phone TEXT Phone number for the SMS TAN @@ -129,12 +132,12 @@ Options: --help Show this message and exit. -:ref:`circuit-register <circuit-register>` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +circuit-register +^^^^^^^^^^^^^^^^ - Register a new account with cash-out capabilities. It needs administrator - credentials, and the new account password exported in - LIBEUFIN_NEW_CIRCUIT_ACCOUNT_PASSWORD. +Register a new account with cash-out capabilities. It needs administrator +credentials, and the new account password exported in +LIBEUFIN_NEW_CIRCUIT_ACCOUNT_PASSWORD. Options: --username TEXT new account username [required] diff --git a/libeufin/ebics3-test-tutorial.rst b/libeufin/ebics3-test-tutorial.rst @@ -0,0 +1,217 @@ +EBICS 3.0 with PostFinance +########################## + +This tutorial shows how LibEuFin and the PostFinance test platform +communicate via EBICS 3. LibEuFin acts as the client via the Nexus +component. To hide the configuration details to the user, all the +client activity is handled by a Docker image. + +The main EBICS 3 operations that the client is expected to complete +are the following: + +* Key exchange: the customer sends their keys to the bank, and then downloads the bank keys. +* Uploading a payment instruction: the customer sends a payment to another fictional IBAN. +* Downloading banking records: the customer downloads the banking records that confirm the previous outgoing payment. + +Setting up the test platform at PostFinance +------------------------------------------- + +Because the test is based on the PostFinance test platform, the first +requirement is to create one account `there <https://isotest.postfinance.ch>`_. +It is advised to set the language as English, as this tutorial is meant +for the international audience. + +Set the language in the drop-down menu and navigate to the registration +section as it is shown below: + +.. image:: set-english-and-register.png + +Even if the above page doesn't welcome you in English, the two boxes in the +screenshot will still hold their position, so please look for box #1 to +set the language and for box #2 to get the page that offers to register. + +After a successful registration, an IBAN needs to be associated with +the user just created. Likely after the first login, the following +page should appear. Click then on box #2. + +.. note:: + + The navigation bar in the screenshot below is ubiquitous, + so click on box #1 if the depicted page did not show up automatically. + +.. image:: no-accounts.png + +If the following page appears, please obtain a checksum-valid but fictitious +Swiss IBAN and enter it as indicated by box #1 and then save it (box #2). + +.. _my-iban: + +.. image:: set-IBAN.png + +If the bank responds with a successful message, the next step is to enable +EBICS 3 and set the format of the ISO20022 documents. + +.. note:: + + There is no "use EBICS 3" setting since EBICS 3 is a "side effect" + of choosing one particular ISO format for banking records. + +To use EBICS 3, click the navigation bar item highlighted in the +following screenshot. + +.. image:: set-ISO-2019-0.png + +The following page should appear, where the ISO format can be specified +as it is depicted in the following screenshot. + +.. image:: set-ISO-2019-1.png + +After having saved the setting, proceed now to set the flavor +of payment confirmations. This setting instructs the bank to define +particular XML nodes when it releases the payment confirmations. Even +if each document is ISO20022, this step is essential because ISO20022 +has many optional fields and client and bank must agree on which fields +appear in the documents. + +Hover on box #1 and then click on box #2. + +.. image:: camt.054-style-0.png + +If the following page appears, please set everything as it is shown below: + +.. FIXME: now trying by NOT selecting the incoming confirmation. + Change it here if that works (screenshot taken already)! + +.. image:: camt.054-style-1.png + +.. _get-ebics-ids: + +The last step is to retrieve the user's EBICS identifiers, namely the +EBICS user and partner IDs. Hover on box #1 and then click on box #2. + +.. image:: get-EBICS-IDs-0.png + +At the first access, the following page should appear. Simply create +EBICS access and continue to the next step. + +.. image:: enable-EBICS.png + +After having obtained the following page, finally the EBICS identifiers +are shown in box #1. The test runner needs them. **Note**: the terms +'customer' and 'partner' are used as **synonyms** in this tutorial (and +in the EBICS specifications too). + +.. image:: get-EBICS-IDs-1.png + +Interestingly, box #2 contains the bank keys fingerprints. These are +important to check that the client, along the keying process, has obtained +the right bank keys. The test runner will pause the execution to let +the user check them. + +Setting up the local Docker and run the test +-------------------------------------------- + +This section shows how to run the test and explains how to interact +with the test runner. + +Clone the following repository: + +.. code-block:: shell-session + + git://git.taler.net/deployment + +navigate in the following directory + +.. code-block:: shell-session + + deployment/nlnet/task3 + +and build the Docker image with the following command: + +.. code-block:: shell-session + + docker build -t pofi . + +If the previous steps succeeded, the *pofi* image is ready to be run. + +The test runner needs the following three values: EBICS user ID, EBICS +partner ID and IBAN. The `previous section <get-ebics-ids_>`_ explains how +to get the EBICS IDs. The IBAN is the one entered `here <my-iban_>`_. + +.. code-block:: shell-session + + docker run -it pofi $EBICS_USER_ID $EBICS_PARTNER_ID $MY_IBAN + +Right after the start, the test runner needs the user intervention to +confirm the user keys at the bank side. For this reason, it will pause +the execution until the user is done. The following screenshot shows +how to navigate to the page where the user has to intervene: + +.. image:: get-EBICS-IDs-0.png + +Once obtaining the page below, box #1 resets potential previous uploaded +keys (only required when running the test more than once), and box #2 confirms +the newly uploaded keys. Note: in production cases, such confirmation happens +via the traditional paper mail. + +.. image:: set-EBICS-keys.png + +After having confirmed the new keys, the execution can be resumed to +for the uploading and downloading operations. + +Upload +====== + +After the key exchange, the test runner continues by uploading one +payment instruction. The payment instruction is a ``pain.001`` document +that complies with the ISO20022 specification, and EBICS is responsible +to transport the pain.001 from the client to the bank. + +The payment instruction causes one outgoing payment from the user +test platform account to another fictional IBAN and has a random subject. +A chance to specify a custom subject is also offered by the test runner. + +After the upload to the bank, the execution pauses to let the user +check whether the test platform has received the payment instruction. + +To this purpose, click on the following navigation item: + +.. image:: check-payment-subject-0.png + +the opened page should contain the following view: + +.. image:: check-payment-subject-1.png + +in this case, open the (archive) file whose timestamp corresponds to the +test execution and look for one XML file whose name contains "pain.001" +(likely, this XML file is named after the archive's name). If found, +the pain.001 file is expected to contain one node called ``Ustrd``: that +is the payment subject and must match the one that was specified right +before the upload. If they match, the upload succeeded and the execution +can be resumed for the `Download`_ operation. + +Download +======== + +The download tries to get one ``camt.054`` (as well +ISO20022) document from the bank; this document is expected to account +for the previous outgoing payment that was created via the pain.001. As +in the pain.001 case, EBICS is responsible to transport the camt.054 from +the bank to the client. + +The download operation logs its activity to the screen, and if the execution +is correct, the payment subject that was initially specified in the pain.001 +document must appear. + +Please, look for the following line: + +.. code-block:: shell-session + + $TIME [main] DEBUG tech.libeufin.nexus - Camt NOTIFICATION '$MSG_ID' has new payments: + - $PAYMENT_SUBJECT + +.. note:: + Replace $TIME, $PAYMENT_SUBJECT and $MSG_ID with the particular case. + +If $PAYMENT_SUBJECT equals the initial payment subject from the pain.001, +then the download operation succeeded. diff --git a/libeufin/enable-EBICS.png b/libeufin/enable-EBICS.png Binary files differ. diff --git a/libeufin/get-EBICS-IDs-0.png b/libeufin/get-EBICS-IDs-0.png Binary files differ. diff --git a/libeufin/get-EBICS-IDs-1.png b/libeufin/get-EBICS-IDs-1.png Binary files differ. diff --git a/libeufin/index.rst b/libeufin/index.rst @@ -4,13 +4,11 @@ LibEuFin LibEuFin is a project providing free software tooling for European FinTech. .. toctree:: + :maxdepth: 1 :glob: concepts bank-transport-ebics - api-common - api-nexus - api-sandbox ebics sepa iso20022 @@ -19,4 +17,7 @@ LibEuFin is a project providing free software tooling for European FinTech. frontend nexus-tutorial local-currencies-tutorial + circuit-cli-commands int-deployment-gv + ebics3-test-tutorial + performance diff --git a/libeufin/local-currencies-tutorial.rst b/libeufin/local-currencies-tutorial.rst @@ -3,22 +3,32 @@ Create a local currency (experimental) This tutorial shows how to setup LibEuFin to act as the bank of a local currency. The main features include the -registration and removal of user accounts, and the possibility -to convert the local currency into fiat. +registration and removal of user accounts *(only) by the +admin*, and the possibility to convert the local currency +into fiat (a.k.a. cashing out). -The banking capabilities used along the tutorial live in a -LibEuFin service called *Sandbox*. In particular, we'll rely -on the :ref:`Circuit API <circuit-api>`. More information -about libEufin can be found in the :doc:`How-To page </libeufin/nexus-tutorial>`. +The banking capabilities are offered by a LibEuFin service +called *Sandbox*. In particular, the tutorial relies on the +:ref:`Libeufin Bank API <libeufin-bank-api>`. More information about libEufin +can be found in the :doc:`How-To page </libeufin/nexus-tutorial>`. -The first step is :ref:`building LibEuFin <building-from-source>`. +The following sections show how to install and launch Sandbox +either `from sources <install-from-sources_>`_, or `with Docker <docker-setup_>`_. + + +.. _install-from-sources: + +Install and config from sources +=============================== + +First :ref:`build LibEuFin <building-from-source>`. If the installation succeeded, configure *Sandbox* with the following command. .. code-block:: console - $ export LIBEUFIN_SANDBOX_DB_CONNECTION=jdbc:sqlite:/tmp/libeufin.sqlite3 + $ export LIBEUFIN_SANDBOX_DB_CONNECTION=postgres:///libeufin $ libeufin-sandbox config --currency NB --without-registrations default .. note:: @@ -27,9 +37,6 @@ following command. to add new accounts. Without this option, other APIs may offer unrestricted registrations. -All the commands mentioned in the following steps support a ``--help`` -option that lists all the available options under the related command. - If the configuration step succeeded, Sandbox should be ready to serve the bank for a currency named *NB*. @@ -44,23 +51,123 @@ password as ``secret``. .. code-block:: console $ export LIBEUFIN_SANDBOX_ADMIN_PASSWORD=secret - $ libeufin-sandbox serve + $ libeufin-sandbox serve --port 5016 + +If Sandbox is running, jump to `this part <after-installation_>`_. + +.. _docker-setup: + + +Install and config with Docker +============================== + +First, clone the deployment repository: + +.. code-block:: console + + $ git clone git://git.taler.net/deployment + +Then navigate to the Docker image location: + +.. code-block:: console + + $ cd deployment/nlnet/task1 + +Now build the image with the following command. + +.. code-block:: console + + $ docker build -t nlnet . -Sandbox should now be listening on the port 5000. Check it with: +If the build step went well, the following command +should suffice to start Sandbox and NGINX, by mapping +the host's 8080 port to the container's 80. .. code-block:: console - $ curl http://localhost:5000 + $ export LIBEUFIN_EXPOSED_PORT=8080 + $ docker run \ + -e LIBEUFIN_EXPOSED_PORT=$LIBEUFIN_EXPOSED_PORT \ + -p $LIBEUFIN_EXPOSED_PORT:80 \ + -it nlnet + +The previous command uses a default admin password of 'admin'. +Do **CHANGE** the admin password in a production scenario. The +following command shows how to start the services with custom +values. + +.. note:: + + Start the services this way to provide the environment + suitable for this tutorial. + +.. code-block:: console + + $ export MY_ADMIN_PASSWORD=secret + $ export LIBEUFIN_EXPOSED_PORT=8080 + $ docker run \ + -e LIBEUFIN_SANDBOX_ADMIN_PASSWORD=$MY_ADMIN_PASSWORD \ + -e CURRENCY=NB \ + -e LIBEUFIN_EXPOSED_PORT=$LIBEUFIN_EXPOSED_PORT \ + -v libeufin_data:/libeufin-data \ + -v /tmp:/tmp \ + -p $LIBEUFIN_EXPOSED_PORT:80 \ + -p 5016:5016 \ + -it nlnet + +In the example above, Docker: + +0. Sets the admin password to *secret* +1. Sets the currency to *NB* +2. Stores the database in a *volume*. This helps to + share the database between containers. +3. Mounts container's ``/tmp`` to the host's, to let + the reader obtain the file TAN in the same way the + source-based installation does. +4. Maps the host's 8080 to the container's 80 port. +5. Maps the host's 5016 to the container's 5016 port. + That lets the CLI reach Sandbox inside the container, + and therefore run the tutorial. + +By success, Web browsers get the UI by visiting **http://localhost:8080** + +The following command shows how to delete the database, +by deleting its volume. + +.. code-block:: console + + $ docker volume rm libeufin_data + +Note: the removal might fail because the exited containers +are seen as still using the container. Please refer to the Docker +documentation for further information. + +.. _after-installation: + +If Sandbox is running +===================== + +Sandbox should now be reachable on the port 5016. Check it with: + +.. code-block:: console + + $ curl http://localhost:5016 If Sandbox is correctly running, it should respond with a greeting message. At this point, the administrator can add a new merchant to the bank with the following command. +.. note:: + + Consult :doc:`this document </libeufin/circuit-cli-commands>`, + to learn all the CLI commands that address the (Circuit) API + used in this tutorial. + .. code-block:: console export LIBEUFIN_SANDBOX_USERNAME=admin export LIBEUFIN_SANDBOX_PASSWORD=secret - export LIBEUFIN_SANDBOX_URL=http://localhost:5000/ + export LIBEUFIN_SANDBOX_URL=http://localhost:5016/ export LIBEUFIN_NEW_CIRCUIT_ACCOUNT_PASSWORD=shop-secret libeufin-cli \ @@ -125,7 +232,7 @@ this request, to make sure that both parties agree. demobank \ circuit-cashout \ --amount-debit=NB:1 \ - --amount-credit=FIAT:0.95 \ + --amount-credit=CHF:0.95 \ --tan-channel=file If the previous command succeeded, it returned a JSON looking @@ -177,7 +284,7 @@ account. .. code-block:: console - "subject" : "Cash-out of NB:1 to FIAT:0.95" + "subject" : "Cash-out of NB:1 to CHF:0.95" The next commands show how to delete one account from the local currency circuit. For the deletion to succeed, diff --git a/libeufin/nexus-tutorial.rst b/libeufin/nexus-tutorial.rst @@ -30,7 +30,7 @@ To install LibEuFin, you can now simply run: .. code-block:: console - # apt install libeufin + # apt install libeufin-nexus libeufin-sandbox Administration via SystemD -------------------------- @@ -147,7 +147,7 @@ core banking system with EBICS access to bank accounts. The sandbox uses HTTP Basic auth, with username ``admin``. Choose a password and set env var ``LIBEUFIN_SANDBOX_ADMIN_PASSWORD`` to it. -The sandbox relies on a database, which you must specify using a JDBC +The sandbox relies on a database, which you must specify using a Postgres connection URI with the ``LIBEUFIN_SANDBOX_DB_CONNECTION`` environment variable, before invoking any commands. If this variable is not set, ``libeufin-sandbox`` complains and exits: @@ -156,12 +156,10 @@ If this variable is not set, ``libeufin-sandbox`` complains and exits: $ export LIBEUFIN_SANDBOX_ADMIN_PASSWORD=secret $ libeufin-sandbox serve - DB connection string not found/valid in the env variable LIBEUFIN_SANDBOX_DB_CONNECTION. + DB connection string not found in the env variable LIBEUFIN_SANDBOX_DB_CONNECTION. The following two examples are valid connection strings: - jdbc:sqlite:/tmp/libeufindb.sqlite3 - jdbc:postgresql://localhost:5432/libeufindb?user=Foo&password=secret - -Only *SQLite* and *PostgreSQL (via TCP)* are supported right now. + postgresql://localhost:5432/libeufindb?user=Foo&password=secret + postgres:///libeufindb Before being usable, a Sandbox needs to be configured. This is done by creating the ``default`` demobank. A demobank is a set of configuration @@ -177,14 +175,14 @@ A default demobank having the EUR currency is created with the following command .. code-block:: console - $ export LIBEUFIN_SANDBOX_DB_CONNECTION=jdbc:sqlite:/tmp/libeufintestdb + $ export LIBEUFIN_SANDBOX_DB_CONNECTION=postgres:///libeufintestdb $ libeufin-sandbox config --currency EUR default In order to use Taler, a default exchange needs to be configured. .. code-block:: console - $ export LIBEUFIN_SANDBOX_DB_CONNECTION=jdbc:sqlite:/tmp/libeufintestdb + $ export LIBEUFIN_SANDBOX_DB_CONNECTION=postgres:///libeufintestdb $ libeufin-sandbox default-exchange --demobank default $exchange_base_url $exchange_payto_address The sandbox service can now be started with the following command: @@ -192,7 +190,7 @@ The sandbox service can now be started with the following command: .. code-block:: console $ export LIBEUFIN_SANDBOX_ADMIN_PASSWORD=secret - $ export LIBEUFIN_SANDBOX_DB_CONNECTION=jdbc:sqlite:/tmp/libeufintestdb + $ export LIBEUFIN_SANDBOX_DB_CONNECTION=postgres:///libeufintestdb $ libeufin-sandbox serve --port 5016 The instructions below hook Nginx to the Sandbox: @@ -285,11 +283,11 @@ are reset back to ``admin`` and ``secret``, respectively. $ libeufin-cli sandbox ebicssubscriber list { "subscribers" : [ { - "hostID" : "testhost", - "partnerID" : "partner01", - "userID" : "user02", - "systemID" : null, - "demobankAccountLabel" : "jrluser" + "host_id" : "testhost", + "partner_id" : "partner01", + "user_id" : "user02", + "system_id" : null, + "demobank_account_label" : "jrluser" } ] } @@ -324,20 +322,20 @@ subcommand, because there is no need to rely on EBICS: $ libeufin-cli sandbox bankaccount transactions jrluser { "payments" : [ { - "accountLabel" : "jrluser", - "creditorIban" : "DE724881", - "creditorBic" : "SANDBOXX", - "creditorName" : "Unknown", - "debtorIban" : "DE895351", - "debtorBic" : "SANDBOXX", - "debtorName" : "The Bank", + "account_label" : "jrluser", + "creditor_iban" : "DE724881", + "creditor_bic" : "SANDBOXX", + "creditor_name" : "Unknown", + "debtor_iban" : "DE895351", + "debtor_bic" : "SANDBOXX", + "debtor_name" : "The Bank", "amount" : "100", "currency" : "EUR", "subject" : "Sign-up bonus", "date" : "Tue, 22 Feb 2022 00:04:15 GMT", - "creditDebitIndicator" : "credit", - "accountServicerReference" : "2NG75I0O", - "paymentInformationId" : null + "credit_debit_indicator" : "credit", + "account_servicer_reference" : "2NG75I0O", + "payment_information_id" : null } ] } @@ -363,90 +361,68 @@ Now the list of transactions has grown by several entries: $ libeufin-cli sandbox bankaccount transactions jrluser { "payments" : [ { - "accountLabel" : "jrluser", - "creditorIban" : "DE724881", - "creditorBic" : "SANDBOXX", - "creditorName" : "Unknown", - "debtorIban" : "DE895351", - "debtorBic" : "SANDBOXX", - "debtorName" : "The Bank", + "account_label" : "jrluser", + "creditor_iban" : "DE724881", + "creditor_bic" : "SANDBOXX", + "creditor_name" : "Unknown", + "debtor_iban" : "DE895351", + "debtor_bic" : "SANDBOXX", + "debtor_name" : "The Bank", "amount" : "100", "currency" : "EUR", "subject" : "Sign-up bonus", "date" : "Tue, 22 Feb 2022 00:04:15 GMT", - "creditDebitIndicator" : "credit", - "accountServicerReference" : "2NG75I0O", - "paymentInformationId" : null + "credit_debit_indicator" : "credit", + "account_servicer_reference" : "2NG75I0O", + "payment_information_id" : null }, { - "accountLabel" : "jrluser", - "creditorIban" : "DE724881", - "creditorBic" : "SANDBOXX", - "creditorName" : "Creditor Name", - "debtorIban" : "DE64500105178797276788", - "debtorBic" : "DEUTDEBB101", - "debtorName" : "Max Mustermann", + "account_label" : "jrluser", + "creditor_iban" : "DE724881", + "creditor_bic" : "SANDBOXX", + "creditor_name" : "Creditor Name", + "debtor_iban" : "DE64500105178797276788", + "debtor_bic" : "DEUTDEBB101", + "debtor_name" : "Max Mustermann", "amount" : "22", "currency" : "EUR", "subject" : "sample transaction GSF7S5LC", "date" : "Tue, 22 Feb 2022 01:26:18 GMT", - "creditDebitIndicator" : "credit", - "accountServicerReference" : "GSF7S5LC", - "paymentInformationId" : null + "credit_debit_indicator" : "credit", + "account_servicer_reference" : "GSF7S5LC", + "payment_information_id" : null }, { - "accountLabel" : "jrluser", - "creditorIban" : "DE64500105178797276788", - "creditorBic" : "DEUTDEBB101", - "creditorName" : "Max Mustermann", - "debtorIban" : "DE724881", - "debtorBic" : "SANDBOXX", - "debtorName" : "Debitor Name", + "account_label" : "jrluser", + "creditor_iban" : "DE64500105178797276788", + "creditor_bic" : "DEUTDEBB101", + "creditor_name" : "Max Mustermann", + "debtor_iban" : "DE724881", + "debtor_bic" : "SANDBOXX", + "debtor_name" : "Debitor Name", "amount" : "10", "currency" : "EUR", "subject" : "sample transaction 1WUP303Q", "date" : "Tue, 22 Feb 2022 01:26:18 GMT", - "creditDebitIndicator" : "debit", - "accountServicerReference" : "1WUP303Q", - "paymentInformationId" : null + "credit_debit_indicator" : "debit", + "account_servicer_reference" : "1WUP303Q", + "payment_information_id" : null }, { - "accountLabel" : "jrluser", - "creditorIban" : "DE724881", - "creditorBic" : "SANDBOXX", - "creditorName" : "Creditor Name", - "debtorIban" : "DE06500105174526623718", - "debtorBic" : "INGDDEFFXXX", - "debtorName" : "Joe Foo", + "account_label" : "jrluser", + "creditor_iban" : "DE724881", + "creditor_bic" : "SANDBOXX", + "creditor_name" : "Creditor Name", + "debtor_iban" : "DE06500105174526623718", + "debtor_bic" : "INGDDEFFXXX", + "debtor_name" : "Joe Foo", "amount" : "10.50", "currency" : "EUR", "subject" : "Hello World", "date" : "Tue, 22 Feb 2022 01:26:41 GMT", - "creditDebitIndicator" : "credit", - "accountServicerReference" : "sandbox-ALQP8TXKJWRVKMAH", - "paymentInformationId" : null + "credit_debit_indicator" : "credit", + "account_servicer_reference" : "sandbox-ALQP8TXKJWRVKMAH", + "payment_information_id" : null } ] } -Lastly, you will want to schedule some tasks to run -periodically in the background. -This enables the Nexus to interact in (almost) real-time with the bank. - -.. code-block:: console - - $ libeufin-cli accounts task-schedule jrluser \ - --task-type submit \ - --task-name submit-payments-each-second \ - --task-cronspec "* * *" - $ libeufin-cli accounts task-schedule jrluser \ - --task-type fetch \ - --task-name fetch-reports-each-second \ - --task-cronspec "* * *" \ - --task-param-level report \ - --task-param-range-type latest - -The first task submits payments and the second fetches reports. -Both are specified to run every second (cronspec ``"* * *"``). -To reduce the frequency to every five seconds, use the cronspec ``"*/5 * *"`` -(remember to quote, to protect from shell filename expansion). - .. note:: The sandbox is intended as a testing tool and thus not stable. @@ -462,20 +438,16 @@ The responsible options are For more information on the available commands, use the built-in ``--help`` flag. The full functionality of the sandbox is available via -the :ref:`Sandbox API <sandbox-api>`. +the :ref:`Libeufin Bank API <libeufin-bank-api>`. -Connect Nexus with an EBICS account -=================================== +Connect Nexus with the bank. +============================ -Nexus relies on a database, which you must specify using a JDBC +Nexus relies on a database, which you must specify using a Postgres connection URI with the ``LIBEUFIN_NEXUS_DB_CONNECTION`` environment variable, before invoking any commands. (If this variable is not set, ``libeufin-nexus`` complains and exits.) -Only *SQLite* (e.g. ``jdbc:sqlite:/tmp/libeufintestdb``) and *PostgreSQL (via TCP)* -(e.g. ``jdbc:postgresql://localhost:$port/libeufintestdb?user=$username&password=$password``) -are supported right now. - Use the following command to run the Nexus service: Neuxs defaults to *not* storing the messages that it downloads @@ -485,7 +457,7 @@ Use the following command to run the Nexus service: .. code-block:: console - $ export LIBEUFIN_NEXUS_DB_CONNECTION=jdbc:postgresql://localhost:5433/libeufindb?user=foo&password=secret + $ export LIBEUFIN_NEXUS_DB_CONNECTION=postgresql://localhost:5433/libeufindb?user=foo&password=secret $ libeufin-nexus serve --port 5017 This assumes that the PostgreSQL service with a database @@ -518,7 +490,13 @@ set to ``foo``, and ``LIBEUFIN_NEXUS_PASSWORD`` to the value given for its passw in the previous step (with the ``libeufin-nexus superuser`` command). The ``LIBEUFIN_NEXUS_URL`` could be given as ``http://localhost:5017``. -Next, we create a EBICS *bank connection* that Nexus can use to communicate with the bank. +Nexus speaks two protocols to reach the bank: EBICS and x-libeufin-bank. +In Nexus speech, each protocol is also known as a *bank connection*. +The following two sections show how to setup such bank connections. Note: +only one is needed to operate! + +EBICS +----- .. note:: @@ -562,8 +540,8 @@ a backup copy* of such keys. $CONNECTION_NAME At this point, Nexus needs to both communicate its keys to the bank, and -download the bank's keys. This synchronization happens through the INI, HIA, and -finally, HPB message types. +download the bank's keys. This synchronization happens through the INI, +HIA, and finally, HPB message types. After the electronic synchronization, the subscriber must confirm their keys by sending a physical mail to the bank. The following command helps generating @@ -598,6 +576,8 @@ The command below downloads the list of the bank accounts offered by ``$CONNECTI It is now possible to list the accounts offered by the connection. +.. _list-connections: + .. code-block:: console $ libeufin-cli \ @@ -628,6 +608,114 @@ under a certain connection (``$CONNECTION_NAME``), it is possible to accomplish the usual operations for any bank account: asking for the list of transactions, and making a payment. +The last step is to create background tasks that fetch and submit +the information from and to the bank. The following command submits +the prepared payments to the bank each second. + +.. _submit-task: + +.. code-block:: console + + $ libeufin-cli accounts task-schedule $LOCAL_ACCOUNT_NAME \ + --task-type submit \ + --task-name submit-payments-each-second \ + --task-cronspec "* * *" + +The following step downloads from the bank all the new transactions, +each second. The ``report`` value indicates that Nexus is interested +in the transactions which did reach already the booked state, in order +to provide faster times to its users. + +.. code-block:: console + + $ libeufin-cli accounts task-schedule $LOCAL_ACCOUNT_NAME \ + --task-type fetch \ + --task-name fetch-reports-each-second \ + --task-cronspec "* * *" \ + --task-param-level report \ + --task-param-range-type latest + +For example, the cronspec can be changed to every five seconds by the +following value: ``"*/5 * *"`` (remember to quote, to protect from shell +filename expansion). + +x-libeufin-bank +--------------- + +This is a faster bank connection, because it relies on JSON and HTTP basic +auth, as oppsed to EBICS XML and RSA cryptography. It is also planned to equip +the server side with long-polling, in order to loop more slowly when asking +for new data. + +The first step is to create one x-libeufin-bank connection. Make sure that +the usual env variables LIBEUFIN_NEXUS_USERNAME, LIBEUFIN_NEXUS_PASSWORD, and +LIBEUFIN_NEXUS_URL are set. The following command instructs Nexus about +the bank URL and the credentials it needs + +.. code-block:: console + + libeufin-cli connections new-xlibeufinbank-connection \ + --bank-url "http://localhost:5016/demobanks/default/access-api" \ + --username jrluser \ + --password easy \ + $CONNECTION_NAME + +The ``--password`` option can be omitted, and in this case the CLI will +prompt to collect it. + + The credentials are exactly the same as the ones used to register a + new bank account at Sandbox. + +Once the connection is created, we need -- just as in the EBICS case -- +the "connect" step. In this case, the connect step will check if the +credentials and URL are correct and (as a side effect) download basic +information about the bank account. + +.. code-block:: console + + libeufin-cli connections connect $CONNECTION_NAME + +As a proof, you can `list <list-connections_>`_ which bank account +arrived at Nexus after the connect command succeeds. Now the bank +account can be imported under a local name at Nexus, just as it was +in the EBICS case. + +.. note:: + + One main difference with EBICS is that now we don't need the + ``download-bank-accounts`` step, because ``connect`` carried + it out as a side effect of checking the credentials. + + +.. code-block:: console + + libeufin-cli connections import-bank-account \ + --offered-account-id jrluser \ + --nexus-bank-account-id $LOCAL_ACCOUNT_NAME \ + $CONNECTION_NAME + + +Now that the account is imported, the background tasks need to +be setup, to provide always the most updated information from the +bank. + +The submit task can be `the same <submit-task_>`_ as EBICS. The fetch +task however needs one different setting, and namely it has to require +``statement`` instead of 'report' because x-libeufin-bank has only the +booked state for transactions. The time range is also different, because +x-libeufin-bank does NOT offer ``latest``. Any unsupported setting should +however generate one error and therefore not create wrong background tasks. + +.. code-block:: console + + libeufin-cli accounts task-schedule \ + --task-type fetch \ + --task-name fetch-every-second \ + --task-cronspec "* * *" \ + --task-param-level statement \ + --task-param-range-type since-last \ + $LOCAL_ACCOUNT_NAME + Request history of transactions =============================== diff --git a/libeufin/no-accounts.png b/libeufin/no-accounts.png Binary files differ. diff --git a/libeufin/performance.rst b/libeufin/performance.rst @@ -0,0 +1,114 @@ +Performance demonstrators +######################### + +This document explains how to prove the following performance +requirements implemented in LibEuFin. + +1. Long-polling offered by Nexus to the Exchange Wirewatch. +2. Reduced usage of disk space by the database. +3. PostgreSQL short-lived database sessions. +4. Participation in the Taler benchmark. + +It is worth noting that point 2 and 3 will be proved *via* +point 4. In particular, because the benchmark is a resource +demanding activity, its impact on the database should be +enough to reflect a worst case scenario with regard to points +2 and 3. + +The following two sections will describe how to run +`point 1 <Long-polling>`_, and `points 2, 3, 4 <Benchmark>`_ +altogether. + +Long-polling +^^^^^^^^^^^^ + +This demonstrator is a Docker image that installs LibEuFin +and registers one user at both Sandbox and Nexus. The Nexus +user is set up to use the Taler Wire Gateway, to let ``curl`` +emulate the Taler exchange (wire-watch). + +To run the demonstrator, clone the following repository: + +.. code-block:: shell-session + + git://git.taler.net/deployment + +and build the Docker image: + +.. code-block:: shell-session + + $ cd deployment/nlnet/task5/long-poll + $ docker build -t long-poller . + +Start the ``long-poller`` image and wait after the installation +and configuration complete. The completion should end with a message +starting by ``Services are online!``. At this point, it is possible +to request Taler incoming payments and observe how such request returns +**only after** we manually send Taler money to the long-polling client. + +Give the following command to request Taler incoming payment +with the long-polling feature: + +.. code-block:: shell-session + + $ curl -v -u test-user:x 'http://localhost:5001/facades/test-facade/taler-wire-gateway/history/incoming?delta=5&long_poll_ms=100000' + +After having observed that the previous command *actually* +long-polls, send it to the background by pressing CTRL-Z. Send +now a Taler payment to ``test-user`` with the following command. + +.. code-block:: shell-session + + $ wire_transfer + +Bring now the ``curl`` process again in the foreground, and if +it got the payment, now it shows the payment data. + +Benchmark +^^^^^^^^^ + +This demonstrator runs the Taler benchmark that relies on LibEuFin. + +Clone the following repository: + +.. code-block:: shell-session + + git://git.taler.net/deployment + +and build the Docker image: + +.. code-block:: shell-session + + $ cd deployment/nlnet/task5/benchmark + $ docker build -t benchmark . + +Run the ``benchmark`` image and wait for its completion. At this +point, the demonstrator prints the benchmark result regarding all +the components, and lastly the database disk usage and the LibEuFin +database session(s) duration(s). + +The database disk usage is complessive, therefore it shows how all +the services occupy database disk space. Hence if this quantity is +acceptable, then also LibEuFin's share is. + +On the other hand, the database session duration concerns only LibEuFin, +and compares the *longest* database session with the whole benchmark +duration. In particular, it shows what percentage of the whole benchmark +duration is represented by the longest LibEuFin session. Therefore +'low' percentages mean 'short' database sessions, as it is requested +in point 3. + +.. + Clone the following repository: + + .. code-block:: shell-session + + git://git.taler.net/deployment + + and build the Docker image: + + .. code-block:: shell-session + + $ cd deployment/nlnet/task5/date-range + $ docker build -t date-range . + diff --git a/libeufin/set-EBICS-keys.png b/libeufin/set-EBICS-keys.png Binary files differ. diff --git a/libeufin/set-IBAN.png b/libeufin/set-IBAN.png Binary files differ. diff --git a/libeufin/set-ISO-2019-0.png b/libeufin/set-ISO-2019-0.png Binary files differ. diff --git a/libeufin/set-ISO-2019-1.png b/libeufin/set-ISO-2019-1.png Binary files differ. diff --git a/libeufin/set-english-and-register.png b/libeufin/set-english-and-register.png Binary files differ. diff --git a/manpages/challenger-admin.1.rst b/manpages/challenger-admin.1.rst @@ -0,0 +1,65 @@ +challenger-admin(1) +################### + +.. only:: html + + Name + ==== + + **challenger-admin** - manipulate clients registered in Challenger database + + +Synopsis +======== + +**challenger-admin** +[**-a** *CLIENT_SECRET* | **--add=**\ \ *CLIENT_SECRET*] +[**-c** *FILENAME* | **--config=**\ \ *FILENAME*] +[**-d** | **--delete**] +[**-h** | **--help**] +[**-L** *LOGLEVEL* | **--log=**\ \ *LOGLEVEL*] +[**-l** *FILENAME* | **--logfile=**\ \ *FILENAME*] +[**-v** | **--version**] CLIENT_URL + + +Description +=========== + +**challenger-admin** is a command-line tool to add or delete clients from the Challenger database. + +Its options are as follows: + +**-a** *SECRET* \| **--add=**\ \ *SECRET* + Add the client with the given *CLIENT_URL setting the client secret to *SECRET*. Prints the CLIENT_ID of the added client. + +**-c** *FILENAME* \| **--config=**\ \ *FILENAME* + Use the configuration and other resources for the Challenger commands + to operate from *FILENAME*. + +**-d** \| **--delete** + Delete the client with the given *CLIENT_URL*. + +**-h** \| **--help** + Print short help on options. + +**-L** *LOGLEVEL* \| **--log=**\ \ *LOGLEVEL* + Configure logging to use *LOGLEVEL*. + +**-l** *FILENAME* \| **--logfile=**\ \ *FILENAME* + Configure logging to write logs to *FILENAME*. + +**-v** \| **–version** + Print version information. + + +See Also +======== + +challenger-config(1), challenger-httpd(1), challenger.conf(5). + + +Bugs +==== + +Report bugs by using https://bugs.taler.net or by sending electronic +mail to <taler@gnu.org>. diff --git a/manpages/challenger-config.1.rst b/manpages/challenger-config.1.rst @@ -0,0 +1,101 @@ +challenger-config(1) +#################### + +.. only:: html + + Name + ==== + + **challenger-config** - manipulate Challenger configuration file + +Synopsis +======== + +**challenger-config** +[**-b** *backend* | **--supported-backend=**\ \ *backend*] +[**-c** *filename* | **--config=**\ \ *filename*] +[**-f** | **--filename**] +[**-F** | **--full**] +[**-h** | **--help**] +[**-L** *loglevel* | **--loglevel=**\ \ *loglevel*] +[**-l** *filename* | **--logfile=**\ \ *filename*] +[**-o** *option* | **--option=**\ \ *option*] +[**-r** | **--rewrite**] +[**-S** | **--list-sections**] +[**-s** *section* | **--section=**\ \ *section*] +[**-V** *value* | **--value=**\ \ *value*] +[**-v** | **--version**] + + +Description +=========== + +**challenger-config** can be used to read or modify Challenger configuration files. + +**-b** *BACKEND* \| **--supported-backend=**\ \ *BACKEND* + Tests whether the specified *BACKEND* is supported by the current installation. + The backend must match the name of a plugin, i.e. "namestore_postgres" for + the PostgreSQL database backend of the "NAMESTORE" service. If *BACKEND* is + supported, challenger-config will return a status code of 0 (success), otherwise + 77 (unsupported). When this option is specified, no other options may be + specified. Specifying this option together with other options will cause + challenger-config to return a status code of 1 (error). + +**-c** *FILENAME* \| **--config=**\ \ *FILENAME* + Use the configuration file *FILENAME*. + +**-f** \| **--filename** + Try to perform expansions as if the option values represent filenames (will + also be applied even if the option is not really a filename). + +**-F** \| **--full** + Write the full configuration file, not just the differences to the defaults. + +**-h** \| **--help** + Print short help on options. + +**-L** *LOGLEVEL* \| **--loglevel=**\ \ *LOGLEVEL* + Use *LOGLEVEL* for logging. + Valid values are ``DEBUG``, ``INFO``, ``WARNING``, and ``ERROR``. + +**-l** *FILENAME* \| **--logfile=**\ \ *FILENAME* + Send logging output to *FILENAME*. + +**-o** *OPTION* \| **--option=**\ \ *OPTION* + Which configuration option should be accessed or edited. Required to set a + value. If not given, all values of a given section will be printed in the + format "OPTION = VALUE". + +**-r** \| **--rewrite** + Write the configuration file even if nothing changed. Will remove all comments! + +**-S** \| **--list-sections** + List available configuration sections for use with ``--section``. + +**-s** *SECTION* \| **--section=**\ \ *SECTION* + Which configuration section should be accessed or edited. + Required option. + +**-V** *VALUE* \| **--value=**\ \ *VALUE* + Configuration value to store in the given section under the given option. + Must only be given together with ``-s`` and ``-o`` options. + + Note: + Changing the configuration file with ``-V`` will remove comments + and may reorder sections and remove ``@INLINE@`` directives. + +**-v** \| **--version** + Print GNU Taler version number. + + +See Also +======== + +challenger-dbinit(1), challenger-httpd(1), challenger.conf(5). + + +Bugs +==== + +Report bugs by using https://bugs.taler.net or by sending electronic +mail to <taler@gnu.org>. diff --git a/manpages/challenger-dbconfig.1.rst b/manpages/challenger-dbconfig.1.rst @@ -0,0 +1,61 @@ +challenger-dbconfig(1) +###################### + +.. only:: html + + Name + ==== + + **challenger-dbconfig** - configure challenger database + + +Synopsis +======== + +**challenger-dbconfig** +[**-c** *FILENAME*] +[**-h**] +[**-n** *NAME*] +[**-r**] +[**-s**] +[**-u** *USER*] + +Description +=========== + +**challenger-dbconfig** is a simple shell script that configures +a Postgresql database for use by ``challenger-httpd``. + +Its options are as follows: + +**-c** *FILENAME* + Write the database configuration to FILENAME. The tool + will append the required ``CONFIG`` option for the + Postgresql access to the respective file. + +**-h** + Print short help on options. + +**-n** *DBNAME* + Use DBNAME for the name of the created database. + +**-r** + Reset any existing database. Looses all existing data. DANGEROUS. + +**-s** + Skip database initialization. Useful if you want to run + ``challenger-dbinit`` manually. + +**-u** *USER* + Specifies the (main) challenger user that will access the database. + +See Also +======== + +challenger-dbinit(1), challenger.conf(5). + +Bugs +==== + +Report bugs by using https://bugs.taler.net or by sending electronic +mail to <taler@gnu.org>. diff --git a/manpages/challenger-dbinit.1.rst b/manpages/challenger-dbinit.1.rst @@ -0,0 +1,65 @@ +challenger-dbinit(1) +#################### + +.. only:: html + + Name + ==== + + **challenger-dbinit** - initialize the Challenger database + + +Synopsis +======== + +**challenger-dbinit** +[**-c** *FILENAME* | **--config=**\ \ *FILENAME*] +[**-g** | **--garbagecollect**] +[**-h** | **--help**] +[**-L** *LOGLEVEL* | **--log=**\ \ *LOGLEVEL*] +[**-l** *FILENAME* | **--logfile=**\ \ *FILENAME*] +[**-r** | **--reset**] +[**-v** | **--version**] + + +Description +=========== + +**challenger-dbinit** is a command-line tool to initialize the Challenger database. + +Its options are as follows: + +**-c** *FILENAME* \| **--config=**\ \ *FILENAME* + Use the configuration and other resources for the Challenger commands + to operate from *FILENAME*. + +**-g** \| **--garbagecollect** + Remove state data from database. + +**-h** \| **--help** + Print short help on options. + +**-L** *LOGLEVEL* \| **--log=**\ \ *LOGLEVEL* + Configure logging to use *LOGLEVEL*. + +**-l** *FILENAME* \| **--logfile=**\ \ *FILENAME* + Configure logging to write logs to *FILENAME*. + +**-r** \| **--reset** + Reset database. (**DANGEROUS**: All existing data is lost!) + +**-v** \| **–version** + Print version information. + + +See Also +======== + +challenger-config(1), challenger-httpd(1), challenger.conf(5). + + +Bugs +==== + +Report bugs by using https://bugs.taler.net or by sending electronic +mail to <taler@gnu.org>. diff --git a/manpages/challenger-httpd.1.rst b/manpages/challenger-httpd.1.rst @@ -0,0 +1,61 @@ +challenger-httpd(1) +################### + +.. only:: html + + Name + ==== + + **challenger-httpd** - provide the Challenger HTTP interface + + +Synopsis +======== + +**challenger-httpd** +[**-C** | **--connection-close**] +[**-c** *FILENAME* | **--config=**\ \ *FILENAME*] +[**-h** | **--help**] +[**-L** *LOGLEVEL* | **--log=**\ \ *LOGLEVEL*] +[**-l** *FILENAME* | **--logfile=**\ \ *FILENAME*] +[**-v** | **--version**] + + +Description +=========== + +**challenger-httpd** is a command-line tool to provide the Challenger HTTP interface. + +Its options are as follows: + +**-C** \| **--connection-close** + Force HTTP connections to be closed after each request. + +**-c** *FILENAME* \| **--config=**\ \ *FILENAME* + Use the configuration and other resources for the Challenger commands + to operate from *FILENAME*. + +**-h** \| **--help** + Print short help on options. + +**-L** *LOGLEVEL* \| **--log=**\ \ *LOGLEVEL* + Configure logging to use *LOGLEVEL*. + +**-l** *FILENAME* \| **--logfile=**\ \ *FILENAME* + Configure logging to write logs to *FILENAME*. + +**-v** \| **–version** + Print version information. + + +See Also +======== + +challenger-config(1), challenger-dbinit(1), challenger.conf(5). + + +Bugs +==== + +Report bugs by using https://bugs.taler.net or by sending electronic +mail to <taler@gnu.org>. diff --git a/manpages/challenger.conf.5.rst b/manpages/challenger.conf.5.rst @@ -0,0 +1,86 @@ +challenger.conf(5) +################## + +.. only:: html + + Name + ==== + + **challenger.conf** - Challenger configuration file + + +Description +=========== + +.. include:: ../frags/common-conf-syntax.rst + +Files containing default values for many of the options described below +are installed under ``$PREFIX/share/challenger/config.d/``. +The configuration file given with **-c** to Challenger binaries +overrides these defaults. + +A configuration file may include another, by using the ``@INLINE@`` directive, +for example, in ``main.conf``, you could write ``@INLINE@ sub.conf`` to +include the entirety of ``sub.conf`` at that point in ``main.conf``. + +Be extra careful when using ``challenger-config -V VALUE`` to change configuration +values: it will destroy all uses of ``@INLINE@`` and furthermore remove all +comments from the configuration file! + + +GLOBAL OPTIONS +-------------- + +The following options are from the “[challenger]” section. +This is normally the only section in a challenger.conf file. + +SERVE + This can either be ``tcp`` or ``unix``. + +PORT + Port on which the HTTP server listens, e.g. 9967. + Only used if ``SERVE`` is ``tcp``. + +BIND_TO + Which IP address should we bind to? E.g. ``127.0.0.1`` or ``::1`` + for loopback. Can also be given as a hostname. We will bind to + the wildcard (dual-stack) if left empty. + Only used if ``SERVE`` is ``tcp``. + +UNIXPATH + Which unix domain path should we bind to? + Only used if ``SERVE`` is ``unix``. + +UNIXPATH_MODE = 660 + What should be the file access permissions for ``UNIXPATH``? + Only used if ``SERVE`` is ``unix``. + +DB + Plugin to use for the database, e.g. “postgres”. + +VALIDATION_DURATION + How long is a validation challenge valid. After this time period, a fresh random challenge code will be generated and the retry limit counter (against guessing attacks) will be reset (to 3). + +VALIDATION_EXPIRATION + How long is a validation allowed to take (time from + ``/setup`` to ``/token``). After this time, the garbage collection process can delete all associated data. (Note that tokens will always allow access to 1h after they have been issued, regardless of when the validation expires). + +AUTH_COMMAND + Which command should we execute to transmit the challenge code to the address. The address is given as the first argument, while the message to send is provided on stdin. Templates (possibly without the necessary credentials) for such commands are provided as challenger-send-email.sh, challenger-send-post.sh and challenger-send-sms.sh. + +ADDRESS_TYPE + Type of the address that is being collected, returned as part of the ``address_type`` in the ``/info`` endpoint. Examples include ``email`` or ``phone``. + + + +SEE ALSO +======== + +challenger-dbinit(1), challenger-httpd(1), challenger-config(1). + + +BUGS +==== + +Report bugs by using https://bugs.taler.net/ or by sending electronic +mail to <taler@gnu.org>. diff --git a/manpages/libeufin-cli.1.rst b/manpages/libeufin-cli.1.rst @@ -347,49 +347,49 @@ For example: $ libeufin-cli sandbox bankaccount transactions testacct01 { "payments" : [ { - "accountLabel" : "testacct01", - "creditorIban" : "DE18500105172929531888", - "creditorBic" : "INGDDEFFXXX", - "creditorName" : "Creditor Name", - "debtorIban" : "DE64500105178797276788", - "debtorBic" : "DEUTDEBB101", - "debtorName" : "Max Mustermann", + "account_label" : "testacct01", + "creditor_iban" : "DE18500105172929531888", + "creditor_bic" : "INGDDEFFXXX", + "creditor_name" : "Creditor Name", + "debtor_iban" : "DE64500105178797276788", + "debtor_bic" : "DEUTDEBB101", + "debtor_name" : "Max Mustermann", "amount" : "5", "currency" : "EUR", "subject" : "sample transaction DILWBJHL", "date" : "Wed, 26 Jan 2022 09:03:44 GMT", - "creditDebitIndicator" : "credit", - "accountServicerReference" : "DILWBJHL", + "credit_debit_indicator" : "credit", + "account_servicer_reference" : "DILWBJHL", "paymentInformationId" : null }, { - "accountLabel" : "testacct01", - "creditorIban" : "DE64500105178797276788", - "creditorBic" : "DEUTDEBB101", - "creditorName" : "Max Mustermann", - "debtorIban" : "DE18500105172929531888", - "debtorBic" : "INGDDEFFXXX", - "debtorName" : "Debitor Name", + "account_label" : "testacct01", + "creditor_iban" : "DE64500105178797276788", + "creditor_bic" : "DEUTDEBB101", + "creditor_name" : "Max Mustermann", + "debtor_iban" : "DE18500105172929531888", + "debtor_bic" : "INGDDEFFXXX", + "debtor_name" : "Debitor Name", "amount" : "12", "currency" : "EUR", "subject" : "sample transaction N7JSY17B", "date" : "Wed, 26 Jan 2022 09:03:44 GMT", - "creditDebitIndicator" : "debit", - "accountServicerReference" : "N7JSY17B", + "credit_debit_indicator" : "debit", + "account_servicer_reference" : "N7JSY17B", "paymentInformationId" : null }, { - "accountLabel" : "testacct01", - "creditorIban" : "DE18500105172929531888", - "creditorBic" : "INGDDEFFXXX", - "creditorName" : "Creditor Name", - "debtorIban" : "DE06500105174526623718", - "debtorBic" : "INGDDEFFXXX", - "debtorName" : "Joe Foo", + "account_label" : "testacct01", + "creditor_iban" : "DE18500105172929531888", + "creditor_bic" : "INGDDEFFXXX", + "creditor_name" : "Creditor Name", + "debtor_iban" : "DE06500105174526623718", + "debtor_bic" : "INGDDEFFXXX", + "debtor_name" : "Joe Foo", "amount" : "10.50", "currency" : "EUR", "subject" : "Hello World", "date" : "Wed, 26 Jan 2022 09:04:31 GMT", - "creditDebitIndicator" : "credit", - "accountServicerReference" : "sandbox-6UI2J3636J9EESXO", + "credit_debit_indicator" : "credit", + "account_servicer_reference" : "sandbox-6UI2J3636J9EESXO", "paymentInformationId" : null } ] } @@ -872,11 +872,11 @@ For example: $ libeufin-cli permissions list { "permissions" : [ { - "subjectType" : "some-subject-type", - "subjectId" : "some-subject-id", - "resourceType" : "some-resource-type", - "resourceId" : "some-resource-id", - "permissionName" : "facade.anastasis.history" + "subject_type" : "some-subject-type", + "subject_id" : "some-subject-id", + "resource_type" : "some-resource-type", + "resource_id" : "some-resource-id", + "permission_name" : "facade.anastasis.history" } ] } diff --git a/manpages/libeufin-sandbox.1.rst b/manpages/libeufin-sandbox.1.rst @@ -71,6 +71,15 @@ config This command takes argument ``NAME`` and creates a demobank with that name. Option ``--currency CUR`` (default: ``EUR``) specifes another currency. +Option ``--captcha-url $URL`` specifies where the wallet user is going +to be redirected to confirm the withdrawal operation. This $URL should +point to the bank frontend. More precisely to the UI that let the user +finish a withdrawal operation that needs to be confirmed. Example of +this value may be "https://bank.domain/#/operation/{wopid}" where +"https://bank.domain" returns the demobank SPA and the demobank view under +the route "/operation/{wopid}" will show the status of the operation id {wopid}. +Note that "{wopid}" is literally in the --captcha-url config and replaced at +runtime by the sandbox server. Option ``--bank-debt-limit N`` (default: 1000000) specifies that the bank debt limit should be N (units of currency). Similarly, option ``--users-debt-limit N`` (default: 1000) specifies diff --git a/manpages/sync-dbconfig.1.rst b/manpages/sync-dbconfig.1.rst @@ -0,0 +1,61 @@ +sync-dbconfig(1) +################ + +.. only:: html + + Name + ==== + + **sync-dbconfig** - configure sync database + + +Synopsis +======== + +**sync-dbconfig** +[**-c** *FILENAME*] +[**-h**] +[**-n** *NAME*] +[**-r**] +[**-s**] +[**-u** *USER*] + +Description +=========== + +**sync-dbconfig** is a simple shell script that configures +a Postgresql database for use by ``sync-httpd``. + +Its options are as follows: + +**-c** *FILENAME* + Write the database configuration to FILENAME. The tool + will append the required ``CONFIG`` option for the + Postgresql access to the respective file. + +**-h** + Print short help on options. + +**-n** *DBNAME* + Use DBNAME for the name of the created database. + +**-r** + Reset any existing database. Looses all existing data. DANGEROUS. + +**-s** + Skip database initialization. Useful if you want to run + ``sync-dbinit`` manually. + +**-u** *USER* + Specifies the (main) sync user that will access the database. + +See Also +======== + +sync-dbinit(1), sync.conf(5). + +Bugs +==== + +Report bugs by using https://bugs.taler.net or by sending electronic +mail to <taler@gnu.org>. diff --git a/manpages/taler-aggregator-benchmark.1.rst b/manpages/taler-aggregator-benchmark.1.rst @@ -0,0 +1,72 @@ +taler-aggregator-benchmark(1) +############################# + + +.. only:: html + + Name + ==== + + **taler-aggregator-benchmark** - setup database to measure aggregator performance + + +Synopsis +======== + +**taler-aggregator-benchmark** +[**-c** *CONFIG_FILENAME* | **--config=**\ \ *CONFIG_FILENAME*] +[**-d** *DN* | **--deposits=**\ \ *DN*] +[**-h** | **--help**] +[**-L** *LOGLEVEL* | **--log-level=**\ \ *LOGLEVEL*] +[**-l** *FILENAME* | **--logfile=**\ \ *FILENAME*] +[**-m** *DM* | **--merchants=**\ \ *DM*] +[**-r** *RATE* | **--refunds=**\ \ *RATE*] +[**-v** | **--version**] + +Description +=========== + +**taler-aggregator-benchmark** is a command-line tool to fill an exchange +database with records suitable for benchmarking the +**taler-exchange-aggregator**. The **taler-aggregator-benchmark** tool does +not run the actual workload for the benchmark (which usually consists of +starting multiple **taler-exchange-aggregator** processes) and instead only +prepares the database with synthetic work. + +**-c** *CONFIG_FILENAME* \| **--config=**\ \ *CONFIG_FILENAME* + (Mandatory) Use CONFIG_FILENAME as the name for the configuration file. + +**-d** *DN* \| **--deposits=**\ \ *DN* + How many deposits should be instantiated *per merchant*. + Defaults to 1. + +**-h** \| **--help** + Prints a compiled-in help text. + +**-L** *LOGLEVEL* \| **--log-level=**\ \ *LOGLEVEL* + Specifies the log level to use. Accepted values are: ``DEBUG``, ``INFO``, + ``WARNING``, ``ERROR``. + +**-l** *FILENAME* \| **--logfile=**\ \ *FILENAME* + Send logging output to *FILENAME*. + +**-m** *DM* \| **--merchants=**\ \ *DM* + How many different merchants should we create. Defaults to 1. + +**-r** *RATE* \| **--refunds=**\ \ *RATE* + Probability of a deposit having a refund (as an integer between 0-100). + +**-v** \| **--version** + Print version information. + +See Also +======== + +taler-exchange-dbinit(1), taler-merchant-benchmark(1), +taler-exchange-aggregator(1), taler-unified-setup(1), taler.conf(5) + +Bugs +==== + +Report bugs by using https://bugs.taler.net/ or by sending electronic +mail to <taler@gnu.org>. diff --git a/manpages/taler-auditor-dbconfig.1.rst b/manpages/taler-auditor-dbconfig.1.rst @@ -0,0 +1,61 @@ +taler-auditor-dbconfig(1) +######################### + +.. only:: html + + Name + ==== + + **taler-auditor-dbconfig** - configure Taler auditor database + + +Synopsis +======== + +**taler-auditor-dbconfig** +[**-c** *FILENAME*] +[**-h**] +[**-n** *NAME*] +[**-r**] +[**-s**] +[**-u** *USER*] + +Description +=========== + +**taler-auditor-dbconfig** is a simple shell script that configures +a Postgresql database for use by the GNU Taler auditor. + +Its options are as follows: + +**-c** *FILENAME* + Write the database configuration to FILENAME. The tool + will append the required ``CONFIG`` option for the + Postgresql access to the respective file. + +**-h** + Print short help on options. + +**-n** *DBNAME* + Use DBNAME for the name of the created database. + +**-r** + Reset any existing database. Looses all existing data. DANGEROUS. + +**-s** + Skip database initialization. Useful if you want to run + ``taler-auditor-dbinit`` manually. + +**-u** *USER* + Specifies the (main) auditor user that will access the database. + +See Also +======== + +taler-auditor-dbinit(1), taler.conf(5). + +Bugs +==== + +Report bugs by using https://bugs.taler.net or by sending electronic +mail to <taler@gnu.org>. diff --git a/manpages/taler-bank-benchmark.1.rst b/manpages/taler-bank-benchmark.1.rst @@ -13,18 +13,16 @@ Synopsis **taler-bank-benchmark** [**-c** *FILENAME* | **--config=**\ \ *FILENAME*] +[**-f** | **--fakebank**] [**-h** | **--help**] -[**-K** | **--linger**] [**-L** *LOGLEVEL* | **--loglevel=**\ \ *LOGLEVEL*] [**-l** *FILENAME* | **--logfile=**\ \ *FILENAME*] -[**-m** *MODE* | **--mode=**\ \ *MODE*] [**-p** *NPROCS* | **--worker-parallelism=**\ \ *NPROCS*] -[**-P** *NTHREADS* | **--service-parallelism=**\ \ *NTHREADS*] [**-r** *NRESERVES* | **--reserves=**\ \ *NRESERVES*] -[**-s** *HISTSIZE* | **--size=**\ \ *HISTSIZE*] +[**-u** *SECTION* | **--exchange-account-section=**\ \ *SECTION*] [**-V** | **--verbose**] [**-v** | **--version**] -[**-w** | **--wirewatch**] +[**-w**_*NPROC* | **--wirewatch=**\ \ *NPROC*] Description @@ -39,12 +37,12 @@ The options for **taler-bank-benchmark** are: Use the configuration and other resources for the merchant to operate from *FILENAME*. +**-f** \| **--fakebank** + Expect to be run against a fakebank (instead of against libeufin) + **-h** \| **--help** Print short help on options. -**-K** \| **--linger** - Linger around until key press. - **-L** *LOGLEVEL* \| **--loglevel=**\ \ *LOGLEVEL* Specifies the log level to use. Accepted values are: ``DEBUG``, ``INFO``, ``WARNING``, ``ERROR``. @@ -56,17 +54,14 @@ The options for **taler-bank-benchmark** are: Run as ``bank``, ``client`` or ``both``. If unspecified, *MODE* defaults to ``both``. -**-P** *NTHREADS** \| **--service-parallelism=**\ \ *NTHREADS* - Run with *NTHREADS* service threads. - **-p** *NPROCS* \| **--worker-parallelism=**\ \ *NPROCS* Run with *NPROCS* client processes. **-r** *NRESERVES* \| **--reserves=**\ \ *NRESERVES* Create *NRESERVES* reserves per client. -**-s** *HISTSIZE* \| **--size=**\ \ *HISTSIZE* - Configure the fakebank to keep in memory at most *HISTSIZE* history elements. +**-u** *SECTION* \| **--exchange-account-section=**\ \ *SECTION* + Use *SECTION* as the name of the configuration section which specifies the exchange bank account. **-V** \| **--verbose** Display more output than usual. @@ -74,8 +69,9 @@ The options for **taler-bank-benchmark** are: **-v** \| **--version** Print version information. -**-w** \| **--wirewatch** - Run the ``taler-exchange-wirewatch`` tool. +**-w** *NPROC* \| **--wirewatch=**\ \ *NPROC* + Run *NPROC* processes of the ``taler-exchange-wirewatch`` tool. + See Also ======== diff --git a/manpages/taler-exchange-benchmark.1.rst b/manpages/taler-exchange-benchmark.1.rst @@ -18,25 +18,21 @@ Synopsis [**-F** | **--reserves-first**] [**-f** | **--fakebank**] [**-h** | **--help**] -[**-K** | **--linger**] [**-L** *LOGLEVEL* | **--log-level=**\ \ *LOGLEVEL*] [**-l** *FILENAME* | **--logfile=**\ \ *FILENAME*] -[**-m** *MODE* | **--mode=**\ \ *MODE*] [**-n** *HOWMANY_COINS* | **--coins-number=**\ \ *HOWMANY_COINS*] [**-p** *NPROCS* | **--parallelism=**\ \ *NPROCS*] [**-R** *RATE* | **--refresh-rate=**\ \ *RATE*] [**-r** *N* | **--reserves=**\ \ *N*] +[**-u** *SECTION* | **--exchange-account-section=**\ \ *SECTION*] [**-v** | **--version**] Description =========== **taler-exchange-benchmark** is a command-line tool to measure the time -spent to serve withdrawals/deposits/refreshes. It usually needs a -dedicate configuration file where all the services - the exchange and -the (fake)bank - listen to URLs not subject to any reverse proxy, as say -Nginx. Moreover, the benchmark runs on a “volatile” database, that means -that table are always erased during a single benchmark run. +spent to serve withdrawals/deposits/refreshes. Before running the benchmark, +the GNU Taler services must already be running at the configured addresses. **-c** *CONFIG_FILENAME* \| **--config=**\ \ *CONFIG_FILENAME* (Mandatory) Use CONFIG_FILENAME. @@ -45,18 +41,11 @@ that table are always erased during a single benchmark run. Create all reserves first, before starting normal operations. **-f** \| **--fakebank** - Launch a fakebank instead of the Python bank. Only meaningful if the - mode is to launch more than just a client. Note that using the - fakebank will cause the benchmark application to reset all databases - as the fakebank is stateless and thus previous database state would - inherently cause trouble. + Expect to interact with a fakebank instead of libeufin. **-h** \| **--help** Prints a compiled-in help text. -**-K** \| **--linger** - Linger around until keypress after the benchmark is done. - **-L** *LOGLEVEL* \| **--log-level=**\ \ *LOGLEVEL* Specifies the log level to use. Accepted values are: ``DEBUG``, ``INFO``, ``WARNING``, ``ERROR``. @@ -64,9 +53,6 @@ that table are always erased during a single benchmark run. **-l** *FILENAME* \| **--logfile=**\ \ *FILENAME* Send logging output to *FILENAME*. -**-m** *MODE* \| **--mode=**\ \ *MODE* - Mode of operation. Accepted values are: ``exchange``, ``clients``, ``both``. - **-n** *HOWMANY_COINS* \| **--coins-number=**\ \ *HOWMANY_COINS* Defaults to 1. Specifies how many coins this benchmark should withdraw and spend. After being spent, each coin will be refreshed @@ -81,6 +67,10 @@ that table are always erased during a single benchmark run. **-r** *N* \| **--reserves=**\ \ *N* Create *N* reserves per client. +**-u** *SECTION* \| **--exchange-account-section=**\ \ *SECTION* + Which configuration section should be used for the bank account + of the exchange. + **-v** \| **--version** Print version information. @@ -88,7 +78,7 @@ See Also ======== taler-exchange-dbinit(1), taler-exchange-offline(1), taler-merchant-benchmark(1), -taler-exchange-httpd(1), taler.conf(5) +taler-exchange-httpd(1), taler-unified-setup(1), taler.conf(5) Bugs ==== diff --git a/manpages/taler-exchange-dbconfig.1.rst b/manpages/taler-exchange-dbconfig.1.rst @@ -0,0 +1,61 @@ +taler-exchange-dbconfig(1) +########################## + +.. only:: html + + Name + ==== + + **taler-exchange-dbconfig** - configure Taler exchange database + + +Synopsis +======== + +**taler-exchange-dbconfig** +[**-c** *FILENAME*] +[**-h**] +[**-n** *NAME*] +[**-r**] +[**-s**] +[**-u** *USER*] + +Description +=========== + +**taler-exchange-dbconfig** is a simple shell script that configures +a Postgresql database for use by the GNU Taler exchange. + +Its options are as follows: + +**-c** *FILENAME* + Write the database configuration to FILENAME. The tool + will append the required ``CONFIG`` option for the + Postgresql access to the respective file. + +**-h** + Print short help on options. + +**-n** *DBNAME* + Use DBNAME for the name of the created database. + +**-r** + Reset any existing database. Looses all existing data. DANGEROUS. + +**-s** + Skip database initialization. Useful if you want to run + ``taler-exchange-dbinit`` manually. + +**-u** *USER* + Specifies the (main) exchange user that will access the database. + +See Also +======== + +taler-exchange-dbinit(1), taler.conf(5). + +Bugs +==== + +Report bugs by using https://bugs.taler.net or by sending electronic +mail to <taler@gnu.org>. diff --git a/manpages/taler-exchange-kyc-aml-pep-trigger.1.rst b/manpages/taler-exchange-kyc-aml-pep-trigger.1.rst @@ -0,0 +1,35 @@ +taler-exchange-kyc-aml-pep-trigger(1) +##################################### + +.. only:: html + + Name + ==== + + **taler-exchange-kyc-aml-pep-trigger** - helper script to trigger AML if KYC attributes indicate a politically exposed person + +Synopsis +======== + +**taler-exchange-kyc-aml-pep-trigger** + + +Description +=========== + +**taler-exchange-kyc-aml-pep-trigger** is a trivial shell script to illustrate how to trigger an AML process when the KYC process sets the "PEP" flag in the attribute data. + +The script is mostly an example (or starting point) for +writing programs for the KYC_AML_TRIGGER option of the +exchange. + +See Also +======== + +taler.conf(5) + +Bugs +==== + +Report bugs by using https://bugs.taler.net or by sending electronic +mail to <taler@gnu.org>. diff --git a/manpages/taler-exchange-offline.1.rst b/manpages/taler-exchange-offline.1.rst @@ -258,11 +258,10 @@ in a format suitable for the ``upload`` subcommand. enable-account -------------- -This subcommand -informs an exchange that it should advertise a bank account as belonging to -the exchange on its ``/wire`` endpoint. Note that this does *not* ensure that -the exchange will use this bank account for incoming or outgoing wire -transfers! For this, the **taler-exchange-transfer** and +This subcommand informs an exchange that it should advertise a bank account as +belonging to the exchange on its ``/wire`` endpoint. Note that this does +*not* ensure that the exchange will use this bank account for incoming or +outgoing wire transfers! For this, the **taler-exchange-transfer** and **taler-exchange-wirewatch** tools must be configured. Furthermore, the bank account information advertised could theoretically differ from that which these tool actually use, for example if the public bank account is only a @@ -271,12 +270,47 @@ front for the actual internal business accounts. The ``payto://`` URI (RFC 8905) of the exchange's bank account must be given as the first argument to the subcommand. +Afterwards, optional arguments can be given: + + * ``conversion-url`` $URL: specifies that using this bank account is subject + to currency conversion. $URL must be the address of a currency conversion + REST API that allows merchants and wallets to determine the current + conversion rate. + + * ``credit-restriction`` $TYPE [$ARGS]: Specifies that there are + restrictions in place when crediting this bank account. Details depend on + the restriction $TYPE. This argument may be given multiple times, in which + case debitor accounts must satisfy all restrictions. Restriction types are + discussed below. + + * ``debit-restriction`` $TYPE [$ARGS]: Specifies that there are restrictions + in place when receiving money from the exchange. Wallets and merchants + must check that their target bank account satisfies these restrictions + before sending deposit requests to the exchange. Details depend on the + restriction $TYPE. This argument may be given multiple times, in which + case debitor accounts must satisfy all restrictions. Restriction types are + discussed below. + +The following types of credit- and debit-restrictions are supported: + + * ``deny``: A $TYPE of ``deny`` means that this bank account cannot be used + for the given operation. ``deny`` takes no further arguments. + + * ``regex`` $EXPR $HINT $JSON: A $TYPE of ``regex`` means that the partner's + bank account ``payto``-URI representation must follow a certain regular + expression given in $EXPR where the syntax follows posix-egrep, but + without support for character classes, GNU extensions, back-references or + intervals. See + `Findutils Manual <https://www.gnu.org/software/findutils/manual/html_node/find_html/posix_002degrep-regular-expression-syntax.html>`_ + for a description of the posix-egrep syntax. The $HINT must be a + human-readable description of the $EXPR. $JSON should be a JSON array + mapping IETF BCP 47 language tags to localized versions of $HINT. + The subcommand takes no inputs from ``stdin`` or other subcommands. It outputs the signature affirming the addition of the wire account, in a format suitable for the ``upload`` subcommand. - disable-account --------------- @@ -456,25 +490,58 @@ Upload signatures about future public keys (online) Download, sign and upload, all in one (online) ---------------------------------------------- -Note that doing this is only recommended in non-production deployments. +Note that doing this is only recommended in non-production deployments, +as this requires putting the "offline" key onto a system that is actually +online! .. code-block:: console - $ taler-exchange-offline download sign upload + $ taler-exchange-offline \ + download \ + sign \ + upload Here is a variant that shows the output of ``download``, but does not consume it, so that ``sign`` can see it as input, as in the variant without ``show``. .. code-block:: console - $ taler-exchange-offline download show - sign upload + $ taler-exchange-offline \ + download \ + show - \ + sign \ + upload + Create signature to enable bank account (offline) ------------------------------------------------- +The following command sets up an unrestricted simple exchange bank account +without conversion: + .. code-block:: console - $ taler-exchange-offline enable-account payto://iban/DE24242 > account.json + $ taler-exchange-offline \ + enable-account payto://iban/DE24242?receiver-name=operator > account.json + +The following command would set up an exchange bank account with conversion +and restrict it to only receive money from Switzerland and deny its use for +debit operations: + +.. code-block:: shell-session + + $ taler-exchange-offline \ + enable-account payto://x-taler-bank/example.com/?receiver-name=name \ + conversion-url http://conversion.exchange.com/ \ + debit-restriction \ + deny \ + credit-restriction \ + regex \ + 'payto://iban/.*/CH.*?receiver-name=.*' \ + 'Swiss only' \ + '{ "de" : "nur Schweiz", \ + "fr" : "Suisse uniquement" }' + Upload bank account signature (online) -------------------------------------- @@ -487,9 +554,19 @@ Upload bank account signature (online) Combine signing keys and enabling bank account (offline) -------------------------------------------------------- +You can chain multiple commands into one invocation: + .. code-block:: console - $ taler-exchange-offline sign enable-account payto://iban/DE24242 < keys.json > combo.json + $ taler-exchange-offline \ + sign \ + enable-account \ + payto://iban/DE24242 < keys.json > combo.json + +Note that ``sign`` must be first as it consumes the ``keys.json`` +input. The resulting output combines the outputs of the ``sign`` +and ``enable-account`` subcommands. + Upload various signatures (online) ---------------------------------- @@ -501,11 +578,20 @@ Upload various signatures (online) Create multiple revocation messages in one pass (offline) --------------------------------------------------------- +You can freely combine almost all commands, including those for +key revocation: + .. code-block:: console - $ taler-exchange-offline revoke-denomination $DKH1 revoke-denomination $DKH2 > revoke.json - $ taler-exchange-offline revoke-signkey $SK1 revoke-signkey $SK2 > revoke.json - $ taler-exchange-offline revoke-signkey $SK revoke-denomkey $DKH > mix.json + $ taler-exchange-offline \ + revoke-denomination $DKH1 \ + revoke-denomination $DKH2 > revoke.json + $ taler-exchange-offline \ + revoke-signkey $SK1 \ + revoke-signkey $SK2 > revoke.json + $ taler-exchange-offline \ + revoke-signkey $SK \ + revoke-denomkey $DKH > mix.json The outputs ("revoke.json", "mix.json") must be uploaded using the ``upload`` subcommand to the exchange to actually revoke the keys. diff --git a/manpages/taler-exchange-wirewatch.1.rst b/manpages/taler-exchange-wirewatch.1.rst @@ -35,7 +35,7 @@ Its options are as follows: from *FILENAME*. **-f** *DELAY*\| **--longpoll-timeout=**\ \ *DELAY* - How long do we wait for a response for bank transactions from the bank. This is both the timeout for the long polling as well as the maximum frequency at which we would query the bank. Default is 60s. + How long do we wait for a response for bank transactions from the bank. This is both the timeout for the long polling as well as the maximum frequency at which we would query the bank. Specified with unit (e.g. 30s, 1d, 2w), if no unit is given the number is interpreted in microseconds. Default is 60s. **-h** \| **--help** Print short help on options. diff --git a/manpages/taler-merchant-benchmark.1.rst b/manpages/taler-merchant-benchmark.1.rst @@ -29,20 +29,16 @@ Subcommands ordinary Generate normal payments: all the payments are performed (by the default instance) and aggregated by the exchange. Takes the following - options. + option: **-p** *PN* \| **--payments-number=**\ \ *PN* Perform PN many payments, defaults to 1. - **-t** *TN* \| **--tracks-number=**\ \ *TN* - Perform TN many tracking operations, defaults to 1. - - corner Drive the generator to create unusual situations, like for example leaving payments unaggregated, or using a non-default merchant - instance. Takes the following options. + instance. Takes the following options: **-t** *TC* \| **--two-coins=**\ \ *TC* @@ -67,8 +63,7 @@ Common Options Use the configuration and other resources for the merchant to operate from FILENAME. -**-e** *SECTION* \| **--exchange-account=**\ \ *SECTION* - Mandatory. +**-u** *SECTION* \| **--exchange-account-section=**\ \ *SECTION* Configuration *SECTION* specifying the exchange account to use. **-h** \| **--help** @@ -88,7 +83,7 @@ Common Options See Also ======== -taler-merchant-dbinit(1), taler-merchant-tip-enable(1), taler.conf(5) +taler-merchant-dbinit(1), taler.conf(5) Bugs diff --git a/manpages/taler-merchant-dbconfig.1.rst b/manpages/taler-merchant-dbconfig.1.rst @@ -0,0 +1,61 @@ +taler-merchant-dbconfig(1) +########################## + +.. only:: html + + Name + ==== + + **taler-merchant-dbconfig** - configure Taler merchant database + + +Synopsis +======== + +**taler-merchant-dbconfig** +[**-c** *FILENAME*] +[**-h**] +[**-n** *NAME*] +[**-r**] +[**-s**] +[**-u** *USER*] + +Description +=========== + +**taler-merchant-dbconfig** is a simple shell script that configures +a Postgresql database for use by the GNU Taler merchant. + +Its options are as follows: + +**-c** *FILENAME* + Write the database configuration to FILENAME. The tool + will append the required ``CONFIG`` option for the + Postgresql access to the respective file. + +**-h** + Print short help on options. + +**-n** *DBNAME* + Use DBNAME for the name of the created database. + +**-r** + Reset any existing database. Looses all existing data. DANGEROUS. + +**-s** + Skip database initialization. Useful if you want to run + ``taler-merchant-dbinit`` manually. + +**-u** *USER* + Specifies the (main) merchant user that will access the database. + +See Also +======== + +taler-merchant-dbinit(1), taler.conf(5). + +Bugs +==== + +Report bugs by using https://bugs.taler.net or by sending electronic +mail to <taler@gnu.org>. diff --git a/manpages/taler-merchant-httpd.1.rst b/manpages/taler-merchant-httpd.1.rst @@ -93,7 +93,7 @@ TALER_MERCHANT_TOKEN See Also ======== -taler-merchant-dbinit(1), taler-merchant-tip-enable(1), taler.conf(5) +taler-merchant-dbinit(1), taler-merchant-setup-reserve(1), taler.conf(5) Bugs diff --git a/manpages/taler-merchant-setup-reserve.1.rst b/manpages/taler-merchant-setup-reserve.1.rst @@ -7,7 +7,7 @@ taler-merchant-setup-reserve(1) Name ==== - **taler-merchant-setup-reserve** - setup reserve for tipping + **taler-merchant-setup-reserve** - setup reserve for rewards Synopsis diff --git a/manpages/taler-merchant-webhook.1.rst b/manpages/taler-merchant-webhook.1.rst @@ -0,0 +1,62 @@ +taler-merchant-webhook(1) +######################### + +.. only:: html + + Name + ==== + + **taler-merchant-webhook** - run webhooks of Taler merchant backend + + +Synopsis +======== + +**taler-merchant-webhook** +[**-c** *FILENAME* | **--config=**\ \ *FILENAME*] +[**-h** | **--help**] +[**-L** *LOGLEVEL* | **--loglevel=**\ \ *LOGLEVEL*] +[**-l** *FILENAME* | **--logfile=**\ \ *FILENAME*] +[**-t** | **--test**] +[**-v** | **--version**] + +Description +=========== + +**taler-merchant-webhook** is a command-line tool to trigger webhooks +scheduled by a Taler merchant backend. It makes the necessary HTTP +requests and updates the Taler merchant database accordingly. + +Its options are as follows: + +**-c** *FILENAME* \| **--config=**\ \ *FILENAME* + Use the configuration and other resources for the merchant to operate + from *FILENAME*. + +**-h** \| **--help** + Print short help on options. + +**-L** *LOGLEVEL* \| **--loglevel=**\ \ *LOGLEVEL* + Specifies the log level to use. Accepted values are: ``DEBUG``, ``INFO``, + ``WARNING``, ``ERROR``. + +**-l** *FILENAME* \| **--logfile=**\ \ *FILENAME* + Send logging output to *FILENAME*. + +**-t** \| **--test** + Run in test mode. Only runs until there are no more webhooks + to be executed. + +**-v** \| **–version** + Print version information. + +See Also +======== + +taler-merchant-httpd(1), taler.conf(5). + +Bugs +==== + +Report bugs by using https://bugs.taler.net or by sending electronic +mail to <taler@gnu.org>. diff --git a/manpages/taler-merchant-wirewatch.1.rst b/manpages/taler-merchant-wirewatch.1.rst @@ -0,0 +1,68 @@ +taler-merchant-wirewatch(1) +########################### + +.. only:: html + + Name + ==== + + **taler-merchant-wirewatch** - import bank transfers into Taler merchant backend + + +Synopsis +======== + +**taler-merchant-wirewatch** +[**-c** *FILENAME* | **--config=**\ \ *FILENAME*] +[**-h** | **--help**] +[**-L** *LOGLEVEL* | **--loglevel=**\ \ *LOGLEVEL*] +[**-l** *FILENAME* | **--logfile=**\ \ *FILENAME*] +[**-t** | **--test**] +[**-v** | **--version**] + +Description +=========== + +**taler-merchant-wirewatch** is a command-line tool to import +information about incoming bank transfers into a Taler merchant +backend. This will allow the merchant backend to validate that +the exchange paid the merchant correctly. + +Its options are as follows: + +**-c** *FILENAME* \| **--config=**\ \ *FILENAME* + Use the configuration and other resources for the merchant to operate + from *FILENAME*. + +**-h** \| **--help** + Print short help on options. + +**-L** *LOGLEVEL* \| **--loglevel=**\ \ *LOGLEVEL* + Specifies the log level to use. Accepted values are: ``DEBUG``, ``INFO``, + ``WARNING``, ``ERROR``. + +**-l** *FILENAME* \| **--logfile=**\ \ *FILENAME* + Send logging output to *FILENAME*. + +**-s** *SECTION* \| **--section=**\ \ *SECTION* + Configuration section to use. Default is taler-merchant-wirewatch. Needed + if different processes are used to watch multiple bank accounts (for the + same instance or different instances). + +**-t** \| **--test** + Run in test mode. Only runs until the current list of bank + transactions are all imported. + +**-v** \| **–version** + Print version information. + +See Also +======== + +taler-merchant-httpd(1), taler.conf(5). + +Bugs +==== + +Report bugs by using https://bugs.taler.net or by sending electronic +mail to <taler@gnu.org>. diff --git a/manpages/taler-terms-generator.1.rst b/manpages/taler-terms-generator.1.rst @@ -0,0 +1,66 @@ +taler-terms-generator(1) +######################## + + +.. only:: html + + Name + ==== + + **taler-terms-generator** - generate legal terms for GNU Taler services + + +Synopsis +======== + +**taler-terms-generator** +[**-a** *AUTHOR*] +[**-C** *COPYRIGHT*] +[**-h**] +[**-i** *INPUT*] +[**-l** *LANGUAGE*] +[**-o** *OUTPUT*] +[**-p** *PAPER*] +[**-t** *TITLE*] + + +Description +=========== + +**taler-terms-generator** is a command-line tool to create terms of service + and privacy policy files in various file formats and languages from a + reStructuredText (".rst") input. It can be used to generate the responses + various GNU Taler services serve under the ``/terms`` and ``/pp`` endpoints. + +**-a** *AUTHOR* + set the author information to the given AUTHOR in the meta-data of various generated outputs. + +**-C** *COPYRIGHT* + set the copyright information to the given COPYRIGHT in the meta-data of various generated outputs. + +**-h** \| **--help** + Prints a compiled-in help text. + +**-l** *LANGUAGE* + Add the given *LANGUAGE* to the list of translations for the current *INPUT*. *LANGUAGE* must be a two-letter language code (like "de" or "it"). This will generate or update the respective ".po" files to translate the *INPUT* terms to this *LANGUAGE*. + +**-o** *OUTPUT* + Specifies where to write the output. This should be the directory where the service expects to find the generated resources. Unless you changed the default configuration, you probably do not have to specify this value. + +**-p** *PAPER* + Specifies the paper format for generated PDF documents. Can be "a4" or "letter". + +**-t** *TITLE* + Overrides the document title. By default, the title will be set to the contents of the first line of the *INPUT* ".rst" file. + + +See Also +======== + +taler-config(1), taler.conf(5) + +Bugs +==== + +Report bugs by using https://bugs.taler.net/ or by sending electronic +mail to <taler@gnu.org>. diff --git a/manpages/taler-unified-setup.1.rst b/manpages/taler-unified-setup.1.rst @@ -0,0 +1,106 @@ +taler-unified-setup.sh(1) +######################### + + +.. only:: html + + Name + ==== + + **taler-unified-setup.sh** - conveniently launch GNU Taler services + + +Synopsis +======== + +**taler-unified-setup** +[**-a**] +[**-b**] +[**-c** *CONFIG_FILENAME*] +[**-d** *METHOD*] +[**-e**] +[**-f**] +[**-h**] +[**-l** *FILENAME*] +[**-m**] +[**-n**] +[**-r** *MEX*] +[**-s**] +[**-t**] +[**-u** *SECTION*] +[**-v**] +[**-w**] + + +Description +=========== + +**taler-unified-setup** is a command-line tool to launch and stop +GNU Taler services in bulk. It is usually used in test cases or +for development. For production, services should be launched via +systemd and not via this tool. + +**-a** + Start auditor + +**-b** + Start backup/sync service + +**-c** *CONFIG_FILENAME* + (Mandatory) Use CONFIG_FILENAME. + +**-d** *METHOD* + use the given wire method. Default is 'x-taler-bank'. + +**-e** + Start exchange + +**-f** + Start fakebank + +**-g** + Start aggregator + +**-h** \| **--help** + Prints a compiled-in help text. + +**-L** *LOGLEVEL* + Specifies the log level to use. Accepted values are: ``DEBUG``, ``INFO``, + ``WARNING``, ``ERROR``. + +**-m** + Start merchant + +**-n** + Start libeufin nexus + +**-r** *MEX* + Which exchange to use at the merchant + +**-s** + Start libeufin sandbox + +**-t** + Start taler-exchange-transfer + +**-u** *SECTION* + Specifies configuration section with the exchange account to use + +**-v** + Use valgrind + +**-w** + Start taler-exchange-wirewatch + + +See Also +======== + +taler-exchange-dbinit(1), taler-exchange-offline(1), taler-merchant-benchmark(1), +taler-exchange-httpd(1), taler-unified-setup(1), taler.conf(5) + +Bugs +==== + +Report bugs by using https://bugs.taler.net/ or by sending electronic +mail to <taler@gnu.org>. diff --git a/manpages/taler-wallet-cli.1.rst b/manpages/taler-wallet-cli.1.rst @@ -46,7 +46,7 @@ for testing. **withdraw-uri** URI -**tip-uri** URI +**reward-uri** URI **refund-uri** URI diff --git a/manpages/taler.conf.5.rst b/manpages/taler.conf.5.rst @@ -41,9 +41,6 @@ CURRENCY_ROUND_UNIT Smallest amount in this currency that can be transferred using the underlying RTGS. For example: "EUR:0.01" or "JPY:1". -AML_THRESHOLD - Largest amount in this currency that can be transferred per month without - an AML staff member doing a (manual) AML check. For example: "USD:1000000". The “[PATHS]” section is special in that it contains paths that can be @@ -79,16 +76,58 @@ exchange tools. DB Plugin to use for the database, e.g. “postgres”. +SERVE + Should the HTTP server listen on a UNIX domain socket (set option to "unix") or on a TCP socket (set option to "tcp")? + +UNIXPATH + Path to listen on if we "SERVE" is set to "unix". + +UNIXPATH_MODE + Access permission mask to use for the "UNIXPATH". + PORT Port on which the HTTP server listens, e.g. 8080. +BIND_TO + Hostname to which the exchange HTTP server should be bound to, e.g. "localhost". + MASTER_PUBLIC_KEY Crockford Base32-encoded master public key, public version of the exchange's long-time offline signing key. -MASTER_PRIV_FILE - Location of the master private key on disk. Only used by tools that - can be run offline (as the master key is for offline signing). +AML_THRESHOLD + Largest amount in this currency that can be transferred per month without + an AML staff member doing a (manual) AML check. For example: "USD:1000000". + +KYC_AML_TRIGGER + Program to run on KYC attribute data to decide whether we should immediately flag an account for AML review. Program must return 0 if a manual AML review is not needed, and non-zero to trigger an AML review. The KYC attribute data of the new user will be passed on standard-input. + +ENABLE_REWARDS + This option can be used to announce that an exchange does not allow + the use of the reserves for rewards. The default is YES which means + that rewards are allowed. The option merely announces that + rewards is enabled or disabled, and protocol-compliant merchant + backends will then enable or disable the feature accordingly. + +CURRENCY_FRACTION_DIGITS + How many digits should amounts be rendered + with by default. Small capitals should + be used to render fractions beyond the number + given here (like on gas stations). Defaults to 0. + For EUR and USD, the value would be 2, while for + JPY it would be 0. + +STEFAN_ABS + Absolte amount to use in the STEFAN fee approximation + curve (see DD47). Defaults to 0 if not specified. + +STEFAN_LOG + Logarithmic factor to use in the STEFAN fee approximation + curve (see DD47). Defaults to 0 if not specified. + +STEFAN_LIN + Linear factor to use in the STEFAN fee approximation + curve (see DD47). Defaults to 0 if not specified. BASE_URL The base URL under which the exchange can be reached. @@ -165,10 +204,13 @@ The following options must be in the section "[kyc-provider-XXX]" sections. COST Relative cost of the KYC provider, non-negative number. + LOGIC API type of the KYC provider. + USER_TYPE Type of user this provider is for, either INDIVIDUAL or BUSINESS. + PROVIDED_CHECKS List of checks performed by this provider. Space-separated names of checks, must match check names in legitimization rules. @@ -182,14 +224,14 @@ The following options must be in the section "[kyc-provider-XXX]" sections with KYC_OAUTH2_VALIDITY Duration (e.g. "12 months") of the validity of the performed KYC check. Can be "forever". -KYC_OAUTH2_AUTH_URL - URL of the OAuth2 endpoint to be used for KYC checks. This is where the server will ultimately send the authorization token from the client and obtain its access token (which currently must be a "bearer" token). Example: "http://localhost:8888/oauth/v2/auth" (or "/token") +KYC_OAUTH2_AUTHORIZE_URL + URL of the OAuth2 endpoint to be used for KYC checks. The authorize URL is where the exchange will redirect the client to begin the authorization process. Example: "http://localhost:8888/oauth/v2/authorize". To use the plugin in combination with the Challenger service's ``/setup`` step, append "#setup", thus "https://challenger.example.com/authorize#setup". Here, "#setup" is not a fragment but merely a hint to the logic to determine the full authorization URL via the ``/setup`` handler. -KYC_OAUTH2_LOGIN_URL - URL of the OAuth2 endpoint to be used for KYC checks. The login URL will be encoded as part of the 'redirect_uri' argument of the request to the KYC_AUTH2_AUTH_URL. Typically, the user will then be redirected to this URL to log in. Example: "http://localhost:8888/oauth/v2/login" +KYC_OAUTH2_TOKEN_URL + URL of the OAuth2 endpoint to be used for KYC checks. This is where the server will ultimately send the authorization token from the client and obtain its access token (which currently must be a "bearer" token). Example: "http://localhost:8888/oauth/v2/token" (or just "/token") KYC_OAUTH2_INFO_URL - URL of the endpoint where the OAuth 2.0 token can be used to download the user's details. The server will use the access token obtained from the KYC_AUTH2_AUTH_URL to show that it is authorized to obtain the details. Example: "http://localhost:8888/api/user/me" or "http://localhost:8888/oauth/v2/info" + URL of the OAuth2-protected resource endpoint, where the OAuth 2.0 token can be used to download information about the user that has undergone the KYC process. The exchange will use the access token obtained from the KYC_AUTH2_AUTH_URL to show that it is authorized to obtain the details. Example: "http://localhost:8888/api/user/me" or "http://localhost:8888/oauth/v2/info" KYC_OAUTH2_CLIENT_ID Client ID of the exchange when it talks to the KYC OAuth2 endpoint. @@ -238,6 +280,9 @@ KYC_PERSONA_SALT KYC_PERSONA_SUBDOMAIN Subdomain to use under Persona. +KYC_PERSONA_CONVERTER_HELPER + Helper to convert JSON with KYC data returned by Persona into GNU Taler internal format. Should probably always be set to "taler-exchange-kyc-persona-converter.sh". + KYC_PERSONA_POST_URL URL to which the exchange will redirect the client's browser after successful authorization/login for the KYC process. @@ -254,6 +299,47 @@ WEBHOOK_AUTH_TOKEN Authentication token Persona must supply to our webhook. This is an optional setting. +EXCHANGE EXTENSIONS OPTIONS +--------------------------- + +The functionality of the exchange can be extended by extensions. Those are +shared libraries which implement the extension-API of the exchange and are +located under ``$LIBDIR``, starting with prefix ``libtaler_extension_``. Each +extension can be enabled by adding a dedicated section +"[exchange-extension-<extensionname>]" and the following option: + +ENABLED + If set to ``YES`` the extension ``<extensionsname>`` is enabled. Extension-specific + options might be set in the same section. + + +EXCHANGE EXTENSION FOR AGE RESTRICTION +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The extension for age restriction support can be enabled by adding a section +"[exchange-extension-age_restriction]" with the following options: + +ENABLE + Must be set to ``YES`` in order to activate the extension. + +AGE_GROUPS + A colon-seperated string of increasing non-negative integers, defining the + buckets of age groups supported by the exchange. Each integer marks the + beginning of the next age group. The zero'th age group implicitly starts + with 0. For example, the string "10:18" would define three age groups: + + 1. Group 0: ages 0 through 9 (including) + 2. Group 1: ages 10 through 17 (including) + 3. Group 2: ages 18 and above + + If not provided, the default value is "8:10:12:14:16:18:21". + +**Note**: Age restriction is bound to specific denominations and must be +enabled for each selected denomination in the corresponding section by adding +the option ``AGE_RESTRICTED = YES``, see `EXCHANGE COIN OPTIONS`_. However, the +age groups are defined globally for all denominations. + + EXCHANGE OFFLINE SIGNING OPTIONS -------------------------------- @@ -261,7 +347,8 @@ EXCHANGE OFFLINE SIGNING OPTIONS The following options must be in the section "[exchange-offline]". MASTER_PRIV_FILE - Where to store the offline private key of the exchange. + Location of the master private key on disk. Only used by tools that + can be run offline (as the master key is for offline signing). Mandatory. SECM_TOFU_FILE @@ -497,6 +584,11 @@ CIPHER RSA_KEYSIZE What is the RSA keysize modulos (in bits)? Only used if "CIPHER=RSA". +AGE_RESTRICTED + Setting this option to ``YES`` marks the denomination as age restricted + (default is ``NO``). For this option to be accepted the extension for age + restriction MUST be enabled (see `EXCHANGE EXTENSION FOR AGE RESTRICTION`_). + MERCHANT OPTIONS ---------------- @@ -507,9 +599,21 @@ merchant backend. DB Plugin to use for the database, e.g._“postgres”. +SERVE + Should the HTTP server listen on a UNIX domain socket (set option to "unix") or on a TCP socket (set option to "tcp")? + +UNIXPATH + Path to listen on if we "SERVE" is set to "unix". + +UNIXPATH_MODE + Access permission mask to use for the "UNIXPATH". + PORT Port on which the HTTP server listens, e.g. 8080. +BIND_TO + Hostname to which the merchant HTTP server should be bound to, e.g. "localhost". + LEGAL_PRESERVATION How long do we keep data in the database for tax audits after the transaction has completed? Default is 10 years. @@ -558,26 +662,6 @@ CURRENCY The entire section is ignored if the currency does not match the currency we use, which must be given in the ``[taler]`` section. -KNOWN AUDITORS (for merchants) ------------------------------- - -The merchant configuration can include a list of known exchanges if the -merchant wants to specify that certain auditors are explicitly trusted. -For each trusted exchange, a section “[merchant-auditor-$NAME]” must exist, where -``$NAME`` is a merchant-given name for the auditor. The following options -must be given in each “[merchant-auditor-$NAME]” section. - -AUDITOR_BASE_URL - Base URL of the auditor, e.g. “https://auditor.demo.taler.net/” - -AUDITOR_KEY - Crockford Base32 encoded auditor public key. - -CURRENCY - Name of the currency for which this auditor is trusted, e.g. “KUDOS” - The entire section is ignored if the currency does not match the currency - we use, which must be given in the ``[taler]`` section. - AUDITOR OPTIONS --------------- @@ -598,6 +682,23 @@ PUBLIC_KEY BASE_URL Base URL of the auditor, e.g. “https://auditor.demo.taler.net/” +SERVE + Should the HTTP server listen on a UNIX domain socket (set option to "unix") or on a TCP socket (set option to "tcp")? + +UNIXPATH + Path to listen on if we "SERVE" is set to "unix". + +UNIXPATH_MODE + Access permission mask to use for the "UNIXPATH". + +PORT + Port on which the HTTP server listens, e.g. 8080. + +BIND_TO + Hostname to which the merchant HTTP server should be bound to, e.g. "localhost". + + + AUDITOR POSTGRES BACKEND DATABASE OPTIONS ----------------------------------------- diff --git a/orphaned/README b/orphaned/README @@ -0,0 +1,2 @@ +This document contains documentation that we currently don't link anywhere, +but that we might still want to salvage sometime. diff --git a/orphaned/taler-mcig.rst b/orphaned/taler-mcig.rst @@ -0,0 +1,563 @@ +.. + This file is part of GNU TALER. + Copyright (C) 2021 Taler Systems SA + + TALER 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 2.1, or (at your option) any later version. + + TALER 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 + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + + @author Thien-Thi Nguyen + + +Merchant/Customer Interaction Guide +################################### + +The audience for the Mechant/Customer Interaction Guide is the merchant +who wishes to set up a "web shop" that works with the Taler payment system. + + +Introduction +============ + +.. include:: frags/taler-payment-cycle.rst + +This guide focuses on step 4, the interaction between the customer and the +merchant. In particular, we first review two basic interaction flows +(with and without shopping cart), then describe Taler features involved in the +interaction, the decisions you (the merchant) must make, and +how to configure the Taler merchant backend to best support those decisions. +Lastly, we present protocol *traces* for various fictitious interaction flows. + + +Two Basic Flows +=============== + +.. index:: shopping cart experience +.. index:: individual product selection / purchase experience +.. index:: inventory management +.. index:: repurchase detection / prevention + +There are two basic payment flows, the first involving a shopping cart, +and the second, without (individual product selection / purchase). +We distinguish these because for some purchases, a shopping cart is overkill. +In either case, Taler can integrate +with your *inventory management* system. +Additionally, Taler offers *repurchase detection / prevention*, +most suitable for digital goods. + +In the shopping cart experience, you first offer a product on the website. +The customer adds the product to their shopping cart, at which point you may +optionally *lock* the product in the inventory system for a certain period of +time. +The accumulated set of products in the shopping cart is the *order*. +This process repeats until the customer is ready to move to the +*checkout* phase. + +At checkout, you may optionally support different payment methods (and make +this choice available to the customer) for the order. +This guide assumes you and the customer agree to use the Taler payment system. + +At this point, you generate a *contract* and present it to the customer for +authorization. +The contract includes: + +- the total amount due; +- a short summary; +- a *fulfillment URI*; +- the *duration* of the offer (how long the customer has to authorize before timeout); +- (optional) an itemized product list, with: + + - (optional) some kind of identification for the selected product(s); + +- (optional) applicable taxes and fee limits; +- (optional) an order ID (if omitted, the backend will auto-generate one); +- (optional) information which details are *forgettable*; +- (optional) a *claim token* that the customer can use later; +- (optional) information on the *refund deadline*; +- (optional) information on the *auto-refund period* (how long does the wallet check for refunds without user prompting for it). + +If the customer does nothing (timeout / the contract expires), +the merchant backend automatically *unlocks* the product(s), +allowing other consumers to add more items of the limited stock +to their orders. + +On the other hand, if the customer authorizes payment, +the customer's wallet transfers payment coins to you, +previously locked products are removed from inventory, +and (if possible) the wallet redirects the customer +to the *fulfillment URI*. + +The individual product selection / purchase experience is like the shopping +cart experience with the following exceptions: +- there is no shopping cart -- the order is solely the selected product; +- Taler payment method is assumed; +- customer selection moves directly to checkout; +- *repurchase detection / prevention* can be useful (for digital products). + + +Taler Details +============= + +This section describes aspects of Taler involved +in the basic payment flows in more detail. +Each aspect also includes one or more backend API calls that +are demonstrated in the next section. + +**product locking** + Taler can integrate with your inventory system to set aside + a certain quantity of a product for some duration of time. + This is called *product locking*. + This is useful for physical goods, or for goods that have a limited supply, + such as airline tickets. + Even for digital goods, product locking may be useful to effect exclusivity. + + To lock a product, use: + :http:post:`[/instances/$INSTANCE]/private/products/$PRODUCT_ID/lock`, + specifying a ``duration`` and a ``quantity``. + + If the customer removes a product from the shopping cart, you can *unlock* + the product by using the same API call, specifying a ``quantity`` of 0 (zero). + (Products are also unlocked automatically on timeout / contract expiration.) + + Before you can lock products, you need to manage the inventory, creating + an entry for the product (assigning a $PRODUCT_ID) and configure the + available stock. This can be done using the + Taler merchant backoffice Web interface. + + .. note:: + + Once we have documentation for that web interface, we should link to it here. + +**taxes** + The default taxes for each product is part of the product ``price`` + maintained by the backend. + Taxes can be set when the product is added to the inventory, + prior to any customer purchase experience + (see :http:post:`[/instances/$INSTANCE]/private/products`, + :http:get:`[/instances/$INSTANCE]/private/products`, + and :http:get:`[/instances/$INSTANCE]/private/products/$PRODUCT_ID`) + or specified explicitly by the frontend when adding + products to an order that are not managed by the backend inventory + (see :http:post:`[/instances/$INSTANCE]/private/orders`). + +**fees** + The Taler protocol charges a *deposit fee* (see step 5, above), + which you may choose to pay or to pass on to the customer. + This can be configured to a maximum amount, per order. + + You can set ``default_max_deposit_fee`` in :http:post:`/management/instances`, + or override the default by setting ``max_fee`` when creating an order. + + There is also the *wire fee* (see step 6, above), + which you may choose to pay or to pass on to the customer. + + You can set ``default_max_wire_fee`` in :http:post:`/management/instances`, + and ``max_wire_fee`` in the contract. + If unspecified, the default value is zero (meaning you bear the entire fee). + + You can *amortize* the wire fee across a number of customers + by setting ``default_wire_fee_amortization`` in :http:post:`/management/instances`, + and ``wire_fee_amortization`` in the contract. + This is the number of customer transactions over which you expect to + amortize wire fees on average. + If unspecified, the default value is one. + + .. Note:: :http:post:`/management/instances` must be done at + instance-setup time (prior to any purchase). + +**forgettable customer details** + Although Taler allows the customer to remain anonymous, you may need to + collect customer details (e.g. for shipping). + Taler has support for forgetting such details, to comply with GDPR + (for example). + This can occur even in the face of refunds (see below). + + To forget a set of details, first the details that are to be forgotten + must be marked by including the names of the respective fields + in one or more special ``_forgettable`` field(s) in the contract. + + Then, you can use: + :http:patch:`[/instances/$INSTANCE]/private/orders/$ORDER_ID/forget` + to forget those details. + +**claim token** + The claim token is a sort of handle on the order and its payment. + It is useful when the order ID is easily guessable + (e.g. incrementing serial number), + to prevent one customer hijacking the order of another. + On the other hand, even if the order ID is not easily guessable, + if you don't care about order theft (e.g. infinite supply, digital goods) + and you wish to reduce the required processing (e.g. smaller QR code), + you can safely disable the claim token. + + By default, Taler creates a claim token for each order. + To disable this, you can specify ``create_token`` to be ``false`` + in :http:post:`[/instances/$INSTANCE]/private/orders`. + +**refund deadline** + The refund deadline specifies the time after which you will prohibit + refunds. + Refunds may be full or partial. + Refunds do not require customer details. + You can configure the deadline to expire immediately to effect + an "all sales are final" policy. + + To set the deadline, specify ``refund_delay`` + in :http:post:`[/instances/$INSTANCE]/private/orders`. + To disable refunds altogether, omit this field. + +**auto-refund period** + The Taler protocol can automatically offer refunds to the customer's + wallet without their explicit prompting during the auto-refund period. + + This is useful in the case where the purchase cannot be fulfilled + (e.g. jammed vending machine), but there is no way to notify the + customer about a refund. + + If specified, after contract authorization, the customer's wallet will + repeatedly check for either fulfillment or refund, up to the end of + the auto-refund period. + (If neither occur within that period, the customer should complain + to you for breach of contract.) + + To set the auto-refund period, specify ``auto_refund`` + in :http:post:`[/instances/$INSTANCE]/private/orders`. + +**repurchase detection / prevention** + Taler can detect a repurchase attempt and prevent it from going through. + This feature allows customers to purchase a digital good only once, + but to later access the same digital good repeatedly (e.g. reload + in browser, after network trouble, etc.) without having to pay again. + + This feature is automatic in the protocol; + you do not need to do anything to enable it. + + .. note:: + For repurchase detection / prevention to work reliably, + you must use the same fulfillment URI for the same product + and likewise different fulfillment URIs for different products. + +**fulfillment URI** + This may be the actual product (digital goods), + or a tracking URL (physical goods). + If you issue a claim token with the contract, the customer can + access the fulfillment URI from a different device than the + one where the wallet is installed. + + The fulfillment URI is normally included in the contract. + You specify it in :http:post:`[/instances/$INSTANCE]/private/orders`. + + If the fulfillment URI contains the literal string ``${ORDER_ID}`` + (including curly braces), that will be replaced by the order ID when + POSTing to the merchant. (FIXME: What does "POSTing to the merchant" mean?) + This is useful when the backend auto-generates the order ID. + + +Sample Interaction Traces +========================= + +In the following descriptions, ``C`` stands for *customer*, ``W`` stands for +*customer's wallet*, ``M`` stands for *merchant* (you), and ``E`` stands for +*exchange*. +Unless otherwise noted, all API calls are directed toward the Taler backend. + +Also, all the traces share the initial pre-sales configuration step. + + +Pre-Sales Configuration +----------------------- + +In the pre-sales configuration step, you set up the *default instance*, +and add products to the inventory. + +NOTE: not sure we want to ultimately document this HERE. Most merchants +should do _this_ part via the Merchant Web interface that Sebastian is +building right now, and for that we want a separate guide that explains +the API (as you do here), and the Web interface. In this document, +we should focus on how the merchant integrates the (Web)front-end with the +backend, not how the backend itself is configured. +(This also applies to the other instance setup parts you described +above => refer to other guide, but of course specify how we can +override defaults from instance setup per-order.) + + +M: :http:post:`/management/instances` + +.. code-block:: javascript + + // InstanceConfigurationMessage + { + "accounts": [{"payto_uri":"payto://iban/CH9300762011623852957"}], + "id": "default", + "name": "Pretty Pianos", + "auth": + // InstanceAuthConfigurationMessage + { + "method": "external", + "token": "secret-token:eighty-eight-keys" + }, + "default_max_wire_fee": "KUDOS:5.0", + "default_wire_fee_amortization": 1, + "default_max_deposit_fee": "KUDOS:10.0", + "default_wire_transfer_delay": "2 days", + "default_pay_delay": "5 hours" + } + // (backend returns 204 No content) + +The fictitious store, Pretty Pianos, has only two products: +- pianos (physical good); +- *Beethoven Sonatas* (sheet music PDF files, digital good). + +M: POST ``/instances/default/private/products`` + +.. code-block:: javascript + + // ProductAddDetail + { + "product_id": "p001", + "description": "piano", + "unit": "unit", + "image": "data:image/png;base64,AAA=", + "price": "KUDOS:20000.0", + "taxes": [], + "total_stock": 3, + "next_restock": "2021-04-22", + "_forgettable": ["image"] + } + // (backend returns 204 No content) + +Note that the ``image`` field is mentioned by name in the ``_forgettable`` +field's list value. +This means the ``image`` value is *marked as forgettable*. +This will come into play later (see below). + +M: POST ``/instances/default/private/products`` + +.. code-block:: javascript + + // ProductAddDetail + { + "product_id": "f001", + "description": "Beethoven Sonatas", + "unit": "file", + "price": "KUDOS:9.87", + "taxes": [], + "total_stock": -1 + } + // (backend returns 204 No content) + +Note that there is no ``next_restock`` field in this ``ProductAddDetail`` +object. +This is because the ``total_stock`` field has value ``-1`` (meaning "infinite") +since the product is a PDF file. + + +Scenario 1: Simple File Purchase +-------------------------------- + +The first scenario is a simple file purchase, without shopping cart, +similar to the `GNU Essay demo <https://shop.demo.taler.net/en/>`_ experience. + +.. We hardcode "en/" for now because support for other + languages is not yet available (at time of writing). + (FIXME: Drop "en/" when other languages are supported.) + +Because there are infinite supplies of product ``f001``, +there is really no need for inventory management. +However, you choose to anyway generate a separate order ID +in the backend for accounting purposes. +Also, since the product is an easily reproduced digital good, +you decline to offer the customer the ability to select a "quantity" +other than 1 (one), and decide that "all sales are final" +(no refund possible). +On the other hand, you wish to enable repurchase detection / +prevention feature, so that once customers pay for the PDF file, +they need never pay again for it. + +When the customer clicks on the product's "buy" button, +you first POST to ``/private/orders`` to create an order: + +M: POST ``/instances/default/private/orders`` + +.. code-block:: javascript + + // PostOrderRequest + { + "order": + // Order (MinimalOrderDetail) + { + "amount": "KUDOS:9.87", + "summary": "Beethoven Sonatas", + "fulfillment_URI": "https://example.com/f001?${ORDER_ID}" + }, + "create_token": true + } + +Notes: + +- There is no ``refund_delay`` field (no refunds possible). +- We show the ``create_token`` field with value ``true`` even though that is the default (for illustrative purposes). +- The ``order`` value is actually a ``MinimalOrderDetail`` object. +- The ``fulfillment_URI`` value includes the product ID and the literal string ``${ORDER_ID}``, to be replaced by the backend-generated order ID. + +The backend returns ``200 OK`` with the body: + +.. code-block:: javascript + + // PostOrderResponse + { + "order_id": "G93420934823", + "token": "TEUFHEFBQALK" + } + +Notes: +- The backend-generated order ID is ``G93420934823``. +- The claim token is ``TEUFHEFBQALK``. + +(FIXME: Replace w/ more realistic examples?) + +Now that there is an order in the system, the wallet *claims* the order. + +W: POST ``/orders/G93420934823/claim`` + +.. code-block:: javascript + + // ClaimRequest + { + "nonce": "lksjdflaksjfdlaksjf", + "token": "TEUFHEFBQALK" + } + +Notes: + +- The ``nonce`` value is a randomly-generated string. +- The POST endpoint includes the order ID ``G93420934823``. +- The ``token`` value is the claim token ``TEUFHEFBQALK`` received in the ``PostOrderResponse``. + +The backend returns ``200 OK`` with body: + +.. code-block:: javascript + + // ContractTerms + { + "summary": "one copy of Beethoven Sonatas", + "order_id": "G93420934823", + "amount": "KUDOS:9.87000000", + "fulfillment_url": "https://example.com/f001?G93420934823", + "max_fee": "KUDOS:0.01500000", + "max_wire_fee": "KUDOS:0.01500000", + "wire_fee_amortization": 1, + "products": [ + // Product + { + "product_id": "f001", + "description": "Beethoven Sonatas" + } + ], + "timestamp": { "t_ms": 1616537665000 }, + "refund_deadline": { "t_ms": 1616537665000 }, + "pay_deadline": { "t_ms": 1616537725000 }, + "wire_transfer_deadline": { "t_ms": 1616537785000 }, + "merchant_pub": FIXME, + "merchant_base_url": "https://example.com/", + "merchant": + // Merchant + { + }, + "h_wire": FIXME, + "wire_method": FIXME, + "auditors": [ + // Auditor + ], + "exchanges": [ + // Exchange + ], + "nonce": "lksjdflaksjfdlaksjf" + } + +Notes: + +- The backend determined both fees to be 0.015 KUDOS. + Because the amortization is 1 (one), both fees (processing and wire + transfer) are included in full. + Thus, the total due by the customer is 9.87 + 0.015 + 0.015 = 9.900 KUDOS. +- The ``order_id`` value is the one given in the ``PostOrderResponse``. +- The ``timestamp`` value represents 2021-03-23 22:14:25 UTC + in milliseconds after the `epoch <https://en.wikipedia.org/wiki/Unix_epoch>`__. +- The ``refund_deadline`` value is the same as the ``timestamp`` value + (no refunds possible). +- The ``pay_deadline`` value is one minute after the ``timestamp`` value. +- The ``wire_transfer_deadline`` value is two minutes after + the ``timestamp`` value. +- The ``products`` value is a list of one element (one ``Product`` object), + which omits the ``price`` field since that is included in the + ``ContractTerms.amount`` value. Also, its ``quantity`` defaults to 1 (one). +- The ``nonce`` value is the same one specified by the wallet. + +At this point, the wallet displays the contract terms (or a subset of them) +to the customer, who now has the option to accept the contract or reject it +(either explicitly by pressing a "cancel" button, or implicitly by waiting +for the offer to time out). + +The customer accepts the contract: + +W: POST ``/orders/G93420934823/pay`` + +.. code-block:: javascript + + // PayRequest + { + "coins": [ + // CoinPaySig + { + "coin_sig": ..., + "coin_pub": ..., + "ub_sig": ..., + "h_denom": ..., + "contribution": "KUDOS:8.0", + "exchange_url": ... + }, + { + "coin_sig": ..., + "coin_pub": ..., + "ub_sig": ..., + "h_denom": ..., + "contribution": "KUDOS:2.0", + "exchange_url": ... + } + ] + } + +Notes: + +- There is no session ID in the ``PayRequest`` object. +- The total of the contribution is 8.0 + 2.0 = 10.0 KUDOS, + which is enough to cover the purchase price (9.900 KUDOS + from 9.87 + 0.015 + 0.015). + +The backend returns ``200 OK`` with body: + +.. code-block:: javascript + + // PaymentResponse + { + "sig": "..." // EddsaSignature + } + +FIXME: At this point, does the wallet need to query (status)? +Also, does the frontend need to do anything else? + +The wallet then redirects to the fulfillment URI, which displays +(or makes available for download) the PDF file "Beethoven Sonatas". + + + + +TODO/FIXME: Add more scenarios (including JSON). diff --git a/orphaned/taler-nfc-guide.rst b/orphaned/taler-nfc-guide.rst @@ -0,0 +1,285 @@ +GNU Taler NFC Guide +################### + +This guide explains how NFC (near-field communication) is +used in the GNU Taler payment system. + +Introduction +============ + +NFC is currently used for two different purposes: + +1. Operations in the wallet (payment, withdrawal, ...) can be triggered by a + merchant PoS (Point-of-Sale) terminal or Taler-capable ATM. +2. When either the wallet or the merchant do not have Internet connectivity, + the protocol messages to the exchange or merchant backend service can be + tunneled via NFC through the party that has Internet connectivity. + + +Background: Payment Processing with GNU Taler +============================================= + +The following steps show a simple payment process with GNU Taler. Examples are +written in `Bash <https://www.gnu.org/software/bash/>`_ syntax, +using `curl <https://curl.haxx.se/docs/manpage.html>`_ to make HTTP(S) requests. +They make use of the :http:post:`[/instances/$INSTANCE]/private/orders` +and :http:get:`[/instances/$INSTANCE]/private/orders` endpoints. + +1. The merchant creates an *order*, which contains the details of the payment + and the product/service that the customer will receive. + An order is identified by an alphanumeric *order ID*. + + The *fulfillment URL* is an URL that the wallet will redirect the customer + to once the payment is complete. For digital products, this is typically an + ``https(s)://`` URL that renders the purchased content. For physical + products and in-store purchases, a ``taler://fulfillment-success/<message>`` + URL should be specified instead. The wallet will display the URL-encoded + UTF-8 text ``<message>`` when the payment has succeeded. + + .. hint:: + + When an ``http(s)://`` URL is used as the fulfillment URL in an in-store / NFC payment, + the user might not be able to view the page, as request tunneling only works for requests + made by the wallet to the merchant backend / exchange. + + In these situations, wallets should display to the user that a page to view the purchase + can be opened, and give a warning if it is detected that the devices does not have Internet + connectivity. + + The following POST ``/private/orders`` request to the merchant backend creates a + simple order: + + .. code-block:: console + + $ backend_base_url=https://backend.demo.taler.net/ + $ auth_header='Authorization: ApiKey sandbox' + $ order_req=$(cat <<EOF + { + "order": { + "summary": "one ice cream", + "amount": "KUDOS:1.5", + "fulfillment_url": + "taler://fulfillment-success/Enjoy+your+ice+cream!" + } + } + EOF + ) + $ curl -XPOST -H"$auth_header" -d "$order_req" "$backend_base_url"/private/orders + { + "order_id": "2019.255-02YDHMXCBQP6J" + } + +2. The merchant checks the payment status of the order using + GET ``/private/orders/$ORDER_ID``: + + .. code-block:: console + + $ backend_base_url=https://backend.demo.taler.net/ + $ auth_header='Authorization: ApiKey sandbox' + $ curl -XGET -H"$auth_header" \ + "$backend_base_url/private/orders/2019.255-02YDHMXCBQP6J" + # Response: + { + "taler_pay_uri": "taler://pay/backend.demo.taler.net/-/-/2019.255-02YDHMXCBQP6J", + "paid": false, + # ... (some fields omitted) + } + + As expected, the order is not paid. To actually proceed with the payment, the value of ``taler_pay_uri`` + must be processed by the customer's wallet. There are multiple ways for the wallet to obtain the ``taler://pay/`` URI + + * in a QR code + * in the ``Taler:`` HTTP header of a Web site + * by manually entering it in the command-line wallet + * **via NFC** (explained in this guide) + + The details of ``taler://`` URIs are specified in `LSD 0006 <https://lsd.gnunet.org/lsd0006/>`_. + +3. The wallet processes the ``taler://pay/`` URI. In this example, we use the + command-line wallet: + + .. code-block:: console + + # Withdraw some toy money (KUDOS) from the demo bank + $ taler-wallet-cli test-withdraw \ + -e https://exchange.demo.taler.net/ \ + -b https://bank.demo.taler.net/ \ + -a KUDOS:10 + # Pay for the order from the merchant. + $ taler-wallet-cli pay-uri 'taler://pay/backend.demo.taler.net/-/-/2019.255-02YDHMXCBQP6J' + # [... User is asked to confirm the payment ...] + + .. hint:: + + The command-line wallet is typically used by developers and not by end-users. + See the :ref:`wallet manual <command-line-wallet>` for installation instructions. + + +4. The merchant checks the payment status again: + + .. code-block:: console + + $ backend_base_url=https://backend.demo.taler.net/ + $ auth_header='Authorization: ApiKey sandbox' + $ curl -XGET -H"$auth_header" \ + "$backend_base_url/private/orders/2019.255-02YDHMXCBQP6J" + # Response: + { + "paid": true, + # ... (some fields omitted) + } + + .. note:: + + When paying for digital products displayed on a Web site identified by the + fulfillment URL, the merchant only needs to check the payment status + before responding with the fulfillment page. + + For in-store payments, the merchant must periodically check the payment status. + Instead of polling in a busy loop, the ``timeout_ms`` parameter + of GET ``/private/orders/$ORDER_ID`` + should be used. + + +Taler NFC Basics +================ + +The NFC communication in GNU Taler follows the ISO-DEP (`ISO 14443-4 +<https://www.iso.org/standard/73599.html>`_) standard. The wallet always acts +as a tag (or more precisely, emulated card), while the merchant PoS terminal +and bank terminal act as a reader. + +The basic communication unit is the application protocol data unit (`APDU +<https://en.wikipedia.org/wiki/Smart_card_application_protocol_data_unit>`_), with the structure +and commands defined in `ISO 7816 <https://cardwerk.com/iso-7816-smart-card-standard>`_. + +The GNU Taler wallet uses the AID (application identifier) ``F00054414c4552``. +The ``F`` prefix indicates the proprietary/unregistered namespace of AIDs, and +the rest of the identifier is the hex-encoded ASCII-string ``TALER`` (with one +0-byte left padding). + +During the time that the wallet is paired with a reader, there is state +associated with the communication channel. Most importantly, the first message +sent by the reader to the wallet must be a ``SELECT FILE (=0xA4)`` that selects +the GNU Taler AID. Messages that are sent before the correct ``SELECT FILE`` +message results in implementation-defined behavior, such as the tag disconnecting, +ignoring the message or an app other than the wallet receiving the message. + +The reader sends commands to the wallet with the ``PUT DATA (=0xDA)`` +instruction, using the instruction parameters ``0x0100``, denoting a +proprietary instruction. + +The command data of the ``PUT DATA`` APDU is prefixed by a one-byte Taler +instruction ID (TID). Currently, the following TIDs are used: + +.. list-table:: + :widths: 5 50 + :header-rows: 1 + + * - TID (reader to wallet) + - Description + * - ``0x01`` + - Dereference the UTF-8 encoded ``taler://`` URI in the remainder of the command data. + * - ``0x02`` + - Accept the UTF-8 encoded JSON object in the remainder of the command data as a request tunneling response. + + +The ``GET DATA (=0xCA)`` instruction (again with the instruction parameters +``0x0100`` is used to request a command from the wallet. The APDU with this +instruction must be sent with a ``0x0000`` trailer to indicate that up to 65536 +bytes of data are expected in the response from the wallet. Note that the +wallet itself cannot initiate communication, and thus the reader must "poll" +the wallet for commands. + +The response to the ``GET DATA`` instruction has a Taler instruction ID in the +first byte. The rest of the +body is interpreted depending on the TID. + +.. list-table:: + :widths: 15 50 + :header-rows: 1 + + * - TID + (wallet to reader) + - Description + * - ``0x03`` + - Accept the UTF-8 encoded JSON object in the remainder of the command data as a request tunneling request. + + +Sending taler:// URIs to the Wallet via NFC +=========================================== + +To make the wallet process a ``taler://`` URI via NFC, the merchant PoS +terminal sends a ``SELECT FILE`` command with the GNU Taler AID, and a ``PUT +DATA`` command with TID ``0x01`` and the URI in the rest +of the command data. + +Here is an example protocol trace from an interaction which caused the wallet +to dereference the ``taler://pay`` URI from the example above: + +.. code-block:: none + + # SELECT FILE + m->w 00A4040007F00054414c4552 + # success response with no data + m<-w 9000 + + # PUT DATA (TID=0x01) + m->w 00DA01007c0174616c65723a2f2f7061792f6261636b656e642e64656d6f2e74 + 616c65722e6e65742f2d2f2d2f323031392e3235352d30325944484d58434251 + 50364a + # success response with no data + m<-w 9000 + +(Note that this process works analogously for communication between a bank/ATM +terminal or "reward provider".) + + +Request tunneling +================= + +Request tunneling allows tunneling a (very) restricted subset of HTTP through +NFC. In particular, only JSON request and response bodies are allowed. + +It is currently assumed that the requests and responses fit into one APDU frame. +For devices with more limited maximum APDU sizes, additional TIDs for segmented +tunnel requests/responses may be defined in the future. + +A request for tunneling is initiated with TID ``0x03`` and responded to with +TID ``0x02`` (see tables above). A tunneling request is identified by a +numeric ID, which must be unique during one pairing between reader and tag. + +The request tunneling request/response JSON messages have the following schema: + +.. code-block:: tsref + + interface TalerRequestTunnelRequest { + // Identifier for the request + id: number; + + // Request URL + url: string; + + // HTTP method to use + method: "post" | "get"; + + // Request headers + headers?: { [name: string]: string }; + + // JSON body for the request, only applicable to POST requests + body?: object; + } + + interface TalerRequestTunnelResponse { + // Identifier for the request + id: number; + + // Response HTTP status code, + // "0" if there was no response. + status: number; + + // JSON body of the response, or undefined + // if the response wasn't JSON. + // May contain error details if 'status==0' + body?: object; + } diff --git a/taler-auditor-manual.rst b/taler-auditor-manual.rst @@ -29,14 +29,7 @@ to become readable. About GNU Taler --------------- -GNU Taler is an open protocol for an electronic payment system with a -free software reference implementation. GNU Taler offers secure, fast -and easy payment processing using well understood cryptographic -techniques. GNU Taler allows customers to remain anonymous, while -ensuring that merchants can be held accountable by governments. Hence, -GNU Taler is compatible with anti-money-laundering (AML) and -know-your-customer (KYC) regulation, as well as data protection -regulation (such as GDPR). +.. include:: frags/about-taler.rst About this manual @@ -464,6 +457,12 @@ used when configuring the exchange' database: CONFIG = postgres:///exchangedemo +Legal conditions for using the service +-------------------------------------- + +.. include:: frags/legal.rst + + .. _AuditorDeployment: Deployment @@ -583,7 +582,7 @@ The next key step for the auditor is to configure replication of the *exchange*'s database in-house. This should be performed in two steps as illustrated in the following figure: -.. image:: replication.png +.. image:: images/replication.png First, the exchange should use standard PostgreSQL replication features to enable the auditor to obtain a full copy of the exchange's database. @@ -969,7 +968,7 @@ The auditor's database The database scheme used by the exchange looks as follows: -.. image:: auditor-db.png +.. image:: images/auditor-db.png Invariants checked by the auditor diff --git a/taler-challenger-manual.rst b/taler-challenger-manual.rst @@ -0,0 +1,491 @@ +.. + This file is part of GNU TALER. + + Copyright (C) 2023 Taler Systems SA + + TALER 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 2.1, or (at your option) any later version. + + TALER 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 + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + + @author Christian Grothoff + @author Florian Dold + +GNU Taler Challenger Operator Manual +#################################### + +Introduction +============ + +About Challenger +---------------- + +Challenger is an OAuth 2.0-compatible address validation service. +By redirecting a user-agent to a Challenger service a client can +have Challenger validate that the user is able to receive messages +at a particular address and obtain that address via the ``/info`` +endpoint. + + +About this manual +----------------- + +This manual targets system administrators who want to install, +operate or integrate a challenger service. To report issues +or learn about known limitations, please check our +`bug tracker <https://bugs.taler.net>`__. + + +Architecture overview +--------------------- + +TBC. + +.. _ChallengerInstallation: + +Installation +============ + +In this guide's shell-session fragments, the command prompt shows two pieces +of information: + +* Who is performing the command + (``$user`` vs ``root``, and ending character ``$`` vs ``#``). + + +Installing from source +---------------------- + +The following instructions will show how to install libgnunetutil and +the core GNU Taler libraries from source. + +The package sources can be find in our +`download directory <http://ftpmirror.gnu.org/taler/>`__. + +GNU Taler components version numbers follow the ``MAJOR.MINOR.MICRO`` format. +The general rule for compatibility is that ``MAJOR`` and ``MINOR`` must match. +Exceptions to this general rule are documented in the release notes. +For example, Challenger 1.3.0 should be compatible with Taler exchange 1.4.x +as the MAJOR version matches. A MAJOR version of 0 indicates experimental +development, and you are expected to always run all of the *latest* releases +together (no compatibility guarantees). + +First, the following packages need to be installed before we can compile the +backend: + +.. include:: frags/list-of-dependencies.rst + +.. include:: frags/installing-gnunet.rst + +.. include:: frags/install-before-check.rst + +There is no need to actually run a GNUnet peer or a Taler exchange to use +Challenger -- all Challenger needs from GNUnet and Taler are a number of +headers and libraries! + +.. include:: frags/installing-taler-exchange.rst + + +.. include:: frags/installing-challenger.rst + +.. include:: frags/install-before-check.rst + + + +Installing the Challenger binary packages on Debian +--------------------------------------------------- + +.. include:: frags/installing-debian.rst + +To install the Challenger, you can now simply run: + +.. code-block:: shell-session + + # apt install challenger + +Note that the package does not perform any configuration work except for +setting up the various users and the systemd service scripts. You still must +configure at least the database, HTTP reverse proxy (typically with TLS +certificates) and the terms of service. + +Installing the GNU Taler binary packages on Trisquel +---------------------------------------------------- + +.. include:: frags/installing-trisquel.rst + +Installing the GNU Taler binary packages on Ubuntu +-------------------------------------------------- + +.. include:: frags/installing-ubuntu.rst + +To install the Taler exchange, you can now simply run: + +.. code-block:: shell-session + + # apt install challenger + +Note that the package does not perform any configuration work except for +setting up the various users and the systemd service scripts. You still must +configure at least the database, HTTP reverse proxy (typically with TLS +certificates), and the terms of service. + + +Services, users, groups and file system hierarchy +------------------------------------------------- + +The *challenger* package will use several system users +to compartmentalize different parts of the system: + +* ``challenger-httpd``: runs the HTTP daemon with the core business logic. +* ``postgres``: runs the PostgreSQL database (from *postgresql* package). +* ``www-data``: runs the frontend HTTPS service with the TLS keys (from *nginx* package). + +The package will deploy a systemd service files in +``/usr/lib/systemd/system/`` for Challenger: + +* ``challenger-httpd.service``: the Challenger logic with the public REST API. + + +Configuration Fundamentals +========================== + +This chapter provides fundamental details about the exchange configuration. + +The configuration for all Taler components uses a single configuration file +as entry point: ``/etc/challenger/challenger.conf``. + +System defaults are automatically loaded from files in +``/usr/share/challenger/config.d``. These default files should never be modified. + +The default configuration ``challenger.conf`` configuration file also includes all +configuration files in ``/etc/challenger/conf.d``. + +To view the entire configuration annotated with the source of each configuration option, you +can use the ``challenger-config`` helper: + + +.. code-block:: shell-session + + [root@exchange-online]# challenger-config --diagnostics + < ... annotated, full configuration ... > + +.. warning:: + + While ``challenger-config`` also supports rewriting configuration files, we strongly + recommend to edit configuration files manually, as ``challenger-config`` does not + preserve comments and, by default, rewrites ``/etc/challenger/challenger.conf``. + +.. include:: frags/configuration-format.rst + + +Fundamental Setup: Address validation +------------------------------------- + +Each challenger service is designed to validate one type of address. Possible +address types include: + + * phone numbers (via SMS) + * e-mail addresses (via SMTP) + * mail addresses (via postal service) + +In principle, additional types of addresses can easily be added by extending +the respective HTML and programs to send challenges to the new address type. + +To make different types of address validations possible, the Challenger +configuration contains two configuration options. + + (1) The ``ADDRESS_TYPE`` configuration option informs Challenger about the + type of address it is expected to validate. It is returned as part of + the OAuth 2.0 ``/info`` endpoint to the client, and is typically also + used when deciding how to render the HTML form for address entry that is + shown to the user. + + (2) The ``AUTH_COMMAND`` configuration option specifies which command + Challenger should run to send a challenge to an address. The actual + address is given to this subcommand as the first argument (``$1``), + while the text with the challenge is passed to standard input. + The subcommand should terminate with a status code of 0 on success. + +.. code-block:: ini + :caption: /etc/challenger/challenger.conf + + [challenger] + ADDRESS_TYPE = email + AUTH_COMMAND = challenger-send-email.sh + # ... rest of file ... + +Challenger comes with ``AUTH_COMMAND`` shell scripts for sending e-mail, SMS +and postal mail. Note that for SMS and postal mail the Challenger scripts uses +third party services to actually send the SMS or print and mail the postal +mail. These third parties naturally charge money for their services, and thus +the Challenger administrator will need to add the respective credentials to +the SMS and postal mail scripts before they can function. In any case, these +scripts should be primarily seen as *examples* on how to write authentication +commands. + + ..note:: + + We strongly welcome contributions for additional scripts with alternative + providers or for new types of addresses. + + +Legal conditions for using the service +-------------------------------------- + +.. include:: frags/legal.rst + +Database Configuration +---------------------- + +The access credentials for the Challenger database are configured in +``/etc/challenger/challenger.conf``. Currently, only PostgreSQL is +supported as a database backend. + +.. note:: + + The **challenger-dbconfig** tool can be used to automate the database + setup. When using the Debian/Ubuntu packages, the user should already have + been created, so you can just run the tool without any arguments and should + have a working database configuration. Subsequently, you should still run + **taler-challenger-dbinit** as the ``challenger-httpd`` user to + initialize the database schema. + + +To create a database for Challenger on the local system, run: + +.. code-block:: shell-session + + [root@exchange-online]# su - postgres + [postgres@exchange-online]# createuser challenger-httpd + [postgres@exchange-online]# createdb -O challenger-httpd challenger + [postgres@exchange-online]# exit + +This will create a ``challenger`` database owned by the ``taler-httpd`` user. +We will use that user later to perform database maintenance operations. + +Assuming the above database setup, the database credentials to configure +in the configuration file would simply be: + +.. code-block:: ini + :caption: /etc/challenger/challenger.conf + + [challenger] + DB = postgres + + [challenger-postgres] + CONFIG = postgres:///challenger + +If the database is run on a different host, please follow the instructions +from the PostgreSQL manual for configuring remote access. + +After configuring the database credentials, the Challenger database needs +to be initialized with the following command: + +.. code-block:: shell-session + + [root@exchange-online]# sudo -u challenger-httpd challenger-dbinit + + ..note:: + + To run this command, the user must have ``CREATE TABLE``, ``CREATE + INDEX``, ``ALTER TABLE`` and (in the future possibly even) ``DROP TABLE`` + permissions. Those permissions are only required for this step (which may + have to be repeated when upgrading a deployment). Afterwards, during + normal operation, permissions to ``CREATE`` or ``ALTER`` tables are not + required by Challenger and thus should not be granted. For more + information, see :doc:`manpages/challenger-dbinit.1`. + + +Deployment +========== + +This chapter describes how to deploy Challenger once the basic installation +and configuration are completed. + +.. _ChallengerServing: + +Serving +------- + +The Challenger can serve HTTP over both TCP and UNIX domain socket. + +The following options are to be configured in the section ``[challenger]``: + +- ``SERVE``: Must be set to ``tcp`` to serve HTTP over TCP, or ``unix`` to serve + HTTP over a UNIX domain socket. + +- ``PORT``: Set to the TCP port to listen on if ``SERVE`` is ``tcp``. + +- ``UNIXPATH``: Set to the UNIX domain socket path to listen on if ``SERVE`` is + ``unix``. + +- ``UNIXPATH_MODE``: Number giving the mode with the access permission mask + for the ``UNIXPATH`` (i.e. 660 = ``rw-rw---``). Make sure to set it in such + a way that your reverse proxy has permissions to access the UNIX domain + socket. The default (660) assumes that the reverse proxy is a member of + the group under which the exchange HTTP server is running. + +.. _ChallengerReverseProxy: + +Reverse Proxy Setup +------------------- + +By default, the ``challenger-httpd`` service listens for HTTP connections +on a UNIX domain socket. To make the service publicly available, a reverse +proxy such as nginx should be used. You must configure the reverse proxy +to use TLS as this is required by OAuth 2.0. + +The ``challenger`` package ships with a sample configuration that can be +enabled in nginx: + +.. code-block:: shell-session + + [root@exchange-online]# vim /etc/nginx/sites-available/challenger + < ... customize configuration ... > + [root@exchange-online]# ln -s /etc/nginx/sites-available/challenger \ + /etc/nginx/sites-enabled/challenger + [root@exchange-online]# systemctl reload nginx + + +Launching Challenger +-------------------- + +A running exchange requires starting the following processes: + +- ``challenger-httpd`` (needs database access) + +The processes should be started via a hypervisor like +``systemd`` or ``gnunet-arm`` that automatically re-starts them should they +have terminated unexpectedly. Furthermore, the hypervisor +*should* periodically re-start the service (say once per hour) +to limit Postgres database memory utilization. + +.. note:: + The ``challenger-httpd`` does not ship with HTTPS enabled by default. + It must thus be run behind an HTTPS reverse proxy that performs + TLS termination on the same system. Thus, it would typically be configured + to listen on a UNIX domain socket. + +Given proper packaging, all of the above are realized via a simple systemd +target. This enables Challenger to be properly started using a simple command: + +.. code-block:: shell-session + + # systemctl start challenger-httpd.service + + +Authorizing clients +------------------- + +Before clients can use Challenger, they must be explicitly configured. Each +client is identified via its OAuth 2.0 REDIRECT URI. Thus, a client must have +exactly one REDIRECT URI + + ..note:: + + The OAuth 2.0 specification allows for a client to register + zero or multiple REDIRECT URIs. However, zero is insecure + as it creates an open redirector, and multiple REDIRECT URIs + can trivially be implemented with Challenger by adding more + clients. + +You can add or remove clients at any time; the Challenger service does not +need to be running, but if it is you can still add or remove clients without +restarting the service. To add (or remove) a client, you must use the +``challenger-admin`` command: + +.. code-block:: shell-session + + # sudo -u challenger-httpd challenger-admin --add=$SECRET $REDIRECT_URI + +Here, ``$SECRET`` is the client secret of OAuth 2.0 which will be used in +various parts of the protocol to authenticate the client. The +``$REDIRECT_URI`` is the URI where the user-agent will be redirected to upon +completion of the process. The ``challenger-admin`` command will +then output the *client ID*, which will be a unique positive number. +The first time you run the command, you will thus likely see: +``Client added. Client ID is: 1``. This client ID, the ``$SECRET`` +and the ``$REDIRECT_URI`` will form the foundation for the OAuth 2.0 +configuration. + + +OAuth 2.0 integration +--------------------- + +When integrating Challenger into an OAuth 2.0 process, you need to provide the +three options from the previous section, but also the authorization, token and +info endpoints. For Challenger, these are ``/authorize``, ``/token`` and +``/info``. However, the ``/authorize`` endpoint is special, as it is actually +``/authorize/$NONCE`` where ``$NONCE`` is a nonce that must be first requested +by the client using the ``/setup`` endpoint! + + ..note:: + + This extra step prevents user-agents from (ab)using the Challenger service + to send challenges to addresses even when there is no authorized client + that desires address validation. This is an important feature as address + validation could be expensive. + +Thus, to generate the authorization URL, a client must first POST to +``/setup`` using their client secret in an ``Authorization: Bearer $SECRET`` +HTTP header to obtain a fresh ``$NONCE``. + +In the GNU Taler exchange configuration, this is indicated by appending +``#setup`` to the ``KYC_OAUTH2_AUTHORIZE_URL`` endpoint. Be careful to quote +the URL, as ``#`` is otherwise interpreted as the beginning of a comment by +the configuration file syntax: + +.. code-block:: ini + :caption: /etc/taler/conf.d/exchange-oauth2.conf + + [kyc-provider-example-oauth2] + LOGIC = oauth2 + # (generic options omitted) + KYC_OAUTH2_AUTHORIZE_URL = "https://challenger.example.com/authorize#setup" + KYC_OAUTH2_TOKEN_URL = "https://challenger.example.com/token" + KYC_OAUTH2_INFO_URL = "https://challenger.example.com/info" + KYC_OAUTH2_CLIENT_ID = 1 + KYC_OAUTH2_CLIENT_SECRET = "$SECRET" + + + +Database management +------------------- + + .. note:: + + We advise to make good backups before experimenting with + the database. + +To update the Challenger database after upgrading to a newer +version of Challenger, you should simply re-run ``challenger-dbinit``. +Without further options, this command is expected to preserve +all data and only migrate the existing database to the latest +schema: + +.. code-block:: console + + $ challenger-dbinit + +To delete stale data from the Challenger database, you can use +garbage collection: + +.. code-block:: console + + $ challenger-dbinit --garbagecollect + + +The Challenger database can be re-initialized using: + +.. code-block:: console + + $ challenger-dbinit --reset + +However, running this command will result in all data in the database +being lost. diff --git a/taler-developer-manual.rst b/taler-developer-manual.rst @@ -24,6 +24,7 @@ Developer's Manual checklist-release checklist-demo-upgrade + python-guidelines .. note:: @@ -32,8 +33,88 @@ Developer's Manual and related components. It is not intended for a general audience. .. contents:: Table of Contents + :depth: 2 +Project Overview +================ + +GNU Taler consists of a large (and growing) number of components +in various Git repositories. The following list gives a first +overview: + + * exchange: core payment processing logic with a REST API, plus various + helper processes for interaction with banks and cryptographic + computations. Also includes the logic for the auditor and an + in-memory "bank" API implementation for testing. + + * libeufin: implementation of the "bank" API using the EBICS protocol + used by banks in the EU. Allows an exchange to interact with + European banks. + + * deploymerization: implementation of the "bank" API on top of + blockchains, specifically Bitcoin and Ethereum. Allows an exchange + to interact with crypto-currencies. + + * merchant: payment processing backend to be run by merchants, + offering a REST API. + + * wallet-core: platform-independent implementation of a wallet to be run by + normal users. Includes also the WebExtension for various browsers. + Furthermore, includes various single-page apps used by other + components (especially as libeufin and merchant). Also includes + command-line wallet and tools for testing. + + * taler-android: Android Apps including the Android wallet, the + Android point-of-sale App and the Android casher app. + + * taler-ios: iOS wallet App. + + * sync: backup service, provides a simple REST API to allow users to + make encrypted backups of their wallet state. + + * anastasis: key escrow service, provides a simple REST API to allow + users to distribute encryption keys across multiple providers and + define authorization policies for key recovery. + + * taler-mdb: integration of Taler with the multi-drop-bus (MDB) API + used by vending machines. Allows Taler payments to be integrated + with vending machines. + + * gnu-taler-payment-for-woocommerce: payment plugin for the + woocommerce (wordpress) E-commerce solution. + + * twister: man-in-the-middle proxy for tests that require fuzzing a + REST/JSON protocol. Used for some of our testing. + + * challenger: implementation of an OAuth 2.0 provider that can be used + to verify that a user can receive SMS or E-mail at particular addresses. + Used as part of KYC processes of the exchange. + + * taler-mailbox: messaging service used to store and forward payment + messages to Taler wallets. + + * taldir: directory service used to lookup Taler wallet addresses for + sending invoices or payments to other wallets. + + * taler-merchant-demos: various demonstration services operated at + 'demo.taler.net', including a simple shop, donation page and a + survey with reward functionality. + +There are other important repositories without code, including: + + * gana: Hosted on git.gnunet.org, this repository defines various + constants used in the GNU Taler project. + + * docs: documentation, including this very document. + + * marketing: various presentations, papers and other resources for + outreach. + + * large-media: very large data objects, such as videos. + + * www: the taler.net website. + Fundamentals ============ @@ -174,11 +255,12 @@ development. Communication ------------- -We use the #taler channel on the Freenode IRC network and the taler@gnu.org -public mailinglist for discussions. Not all developers are active on IRC, but -all developers should probably subscribe to the low-volume Taler mailinglist. -There are separate low-volume mailinglists for gnunet-developers (@gnu.org) -and for libmicrohttpd (@gnu.org). +For public discussions we use the taler@gnu.org mailinglist. All developers +should subscribe to the low-volume Taler mailinglist. There are separate +low-volume mailinglists for gnunet-developers (@gnu.org) and for libmicrohttpd +(@gnu.org). For internal discussions we use https://mattermost.taler.net/ +(invitation only, but also achieved). + What to put in bootstrap ------------------------ @@ -195,10 +277,9 @@ One common submodule is ``contrib/gana``, which pulls from the `GNUnet GANA repository <https://git.gnunet.org/gana.git/>`__. For example, in the `Taler exchange repository <https://git.taler.net/exchange.git>`__, -the bootstrap script eventually runs the ``git submodule update`` command -early on, and later runs script ``./contrib/gana.sh``, which in turn -runs script ``./contrib/gana-update.sh``, which performs various tasks, -such as generating the file ``src/include/taler_signatures.h``. +the bootstrap script eventually runs the ``git submodule update --init`` command +early on, and later runs script ``./contrib/gana-generate.sh``, which +generates files such as ``src/include/taler_signatures.h``. Thus, to update that file, you need to: @@ -210,8 +291,7 @@ Thus, to update that file, you need to: - Commit the change, and push it to the GANA Git repo. -- (in Taler Repo) Change directory to ``contrib/gana`` and run - command ``git pull`` there. +- (in Taler Repo) Run the ``contrib/gana-latest.sh`` script. - Bootstrap, configure, do ``make install``, ``make check``, etc. (Basically, make sure the change does not break anything.) @@ -254,22 +334,19 @@ Language-Specific Guidelines Taler Deployment on gv.taler.net ================================ -This section describes the GNU Taler deployment on ``gv.taler.net``. -``gv`` is our server at BFH. It hosts the Git repositories, Web sites, -CI and other services. Developers can receive an SSH account and -e-mail alias for the system. As with Git, ask your primary team -contact for shell access if you think you need it. +This section describes the GNU Taler deployment on ``gv.taler.net``. ``gv`` +is our server at BFH. It hosts the Git repositories, Web sites, CI and other +services. Developers can receive an SSH account and e-mail alias for the +system, you should contact Javier, Christian or Florian. As with Git, ask +your primary team contact for shell access if you think you need it. -Our old server, ``tripwire``, is currently offline and will likely -go back online to host ``production`` systems for operating real -Taler payments at BFH in the future. DNS --- -DNS records for taler.net are controlled by the GNU Taler -maintainers, specifically Christian and Florian. If you -need a sub-domain to be added, please contact one of them. +DNS records for taler.net are controlled by the GNU Taler maintainers, +specifically Christian and Florian, and our system administrator, Javier. If +you need a sub-domain to be added, please contact one of them. User Acccounts @@ -329,10 +406,10 @@ All commands run from deployment.git/docker/demo. # Start services. $ docker-compose start --remove-orphans -d - + # Stop services. $ docker-compose stop - + # Build base image (without tags-file builds master) $ ./build_base.sh images/base/Dockerfile [tags-file] @@ -510,7 +587,7 @@ Database schema versioning -------------------------- The PostgreSQL databases of the exchange and the auditor are versioned. -See the 0000.sql file in the respective directory for documentation. +See the ``versioning.sql`` file in the respective directory for documentation. Every set of changes to the database schema must be stored in a new versioned SQL script. The scripts must have contiguous numbers. After @@ -518,7 +595,7 @@ any release (or version being deployed to a production or staging environment), existing scripts MUST be immutable. Developers and operators MUST NOT make changes to database schema -outside of this versioning. +outside of this versioning. All tables of a GNU Taler component should live in their own schema. @@ -663,6 +740,8 @@ debian/changelog, and then run: in the respective source directory (GNUnet, exchange, merchant) to create the ``.deb`` files. Note that they will be created in the parent directory. This can be done on gv.taler.net, or on another (secure) machine. +Actual release builds should be done via the Docker images +that can be found in ``deployment.git`` under packaging. On ``gv``, we use the ``aptbuilder`` user to manage the reprepro repository. @@ -797,6 +876,48 @@ weblate.taler.net signs GPG commits with the GPG key CD33CE35801462FA5EB0B695F26 This means that contributions made through weblate will not be signed with the individual contributor's key when they are checked into the Git repository, but with the weblate key. + +iOS Apps +======== + +.. _Build-iOS-from-source: + +Building Taler Wallet for iOS from source +----------------------------------------- + +Currently the iOS Wallet app is in +`the official Git repository <https://git.taler.net/taler-ios.git>`__: + +Compatibility +^^^^^^^^^^^^^ + +The minimum version of iOS supported is 15.0. +This app runs on all iPhone models at least as new as the iPhone 6S. + + +Building +^^^^^^^^ + +Before building the iOS wallet, you must first checkout the +`quickjs-tart repo <https://git.taler.net/quickjs-tart.git>`__ +and the +`wallet-core repo <https://git.taler.net/wallet-core.git>`__. + +Build wallet-core first, then copy/move its product "taler-wallet-core-qjs.mjs" +into your quickjs-tart folder right at the top level. + +Open Taler.xcworkspace, and set scheme / target to Taler_Wallet. Build&run... + +Don't open QuickJS-rt.xcodeproj or TalerWallet.xcodeproj and build anything +there - all needed libraries and frameworks will be built automatically from +Taler.xcworkspace. + +Have all 3 local repos (wallet-core, quickjs-tart, and this one) adjacent at +the same level (e.g. in a "GNU Taler" folder). +Taler.xcworkspace expects the QuickJS framework sub-project to be at +``../quickjs-tart/QuickJS-rt.xcodeproj``. + + Android Apps ============ @@ -994,7 +1115,7 @@ then published at https://lcov.taler.net/ . Coding Conventions ================== -GNU Taler is developed primarily in C, Kotlin, Python and TypeScript. +GNU Taler is developed primarily in C, Kotlin, Python, Swift and TypeScript. Components written in C ----------------------- @@ -1127,6 +1248,19 @@ are useful: * ``subprocess`` for "shelling out" to other programs. Prefer ``subprocess.run`` over the older APIs. + +Swift +----- + +Please follow best practices for the language. + + +TypeScript +---------- + +Please follow best practices for the language. + + Testing library =============== @@ -1218,11 +1352,11 @@ Charge Charge has two opposite meanings (charge to a credit card vs. charge a battery). This can confuse users. - **Use instead**: "Obtain", "Credit", "Debit", "Withdraw" + **Use instead**: "Obtain", "Credit", "Debit", "Withdraw", "Top up" Coin Coins are an internal construct, the user should never be aware that their balance - is represented by coins if different denominations. + is represented by coins of different denominations. **Use instead**: "(Digital) Cash" or "(Wallet) Balance" @@ -1472,7 +1606,9 @@ use when talking to end users or even system administrators. key used by the exchange to sign online messages, other than coins order - FIXME: to be written! + offer made by the merchant to a wallet; pre-cursor to + a contract where the wallet is not yet fixed. Turns + into a :term:`contract` when a wallet claims the order. owner a coin is owned by the entity that knows the private key of the coin diff --git a/taler-exchange-manual.rst b/taler-exchange-manual.rst @@ -1,7 +1,7 @@ .. This file is part of GNU TALER. - Copyright (C) 2014-2020 Taler Systems SA + Copyright (C) 2014-2023 Taler Systems SA TALER 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 @@ -15,6 +15,7 @@ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> @author Christian Grothoff + @author Florian Dold GNU Taler Exchange Operator Manual ################################## @@ -22,52 +23,37 @@ GNU Taler Exchange Operator Manual Introduction ============ -This manual is an early draft that still needs significant editing work -to become readable. - About GNU Taler --------------- -GNU Taler is an open protocol for an electronic payment system with a -free software reference implementation. GNU Taler offers secure, fast -and easy payment processing using well understood cryptographic -techniques. GNU Taler allows customers to remain anonymous, while -ensuring that merchants can be held accountable by governments. Hence, -GNU Taler is compatible with anti-money-laundering (AML) and -know-your-customer (KYC) regulation, as well as data protection -regulation (such as GDPR). - -GNU Taler is not yet production-ready, after following this manual you -will have a backend that can process payments in “KUDOS”, but not -regular currencies. This is not so much because of limitations in the -backend, but because we are not aware of a Taler exchange operator -offering regular currencies today. +.. include:: frags/about-taler.rst + About this manual ----------------- -This tutorial targets system administrators who want to install and +This manual targets system administrators who want to install and operate a GNU Taler exchange. Organizational prerequisites ---------------------------- -Operating a GNU Taler exchange means that you are operating a payment -service provider, which means that you will most likely need a bank -license and/or follow applicable financial regulation. +Operating a GNU Taler exchange means that you are operating a payment service +provider, which means that you will most likely need a bank license and/or +follow applicable financial regulation. Exceptions may apply, especially if +you are operating a regional currency or a payment system for an event with a +closed user group. -GNU Taler payment service providers generally need to ensure high -availability and have *really* good backups (synchronous replication, -asynchronous remote replication, off-site backup, 24/7 monitoring, -etc.). This manual will not cover these aspects of operating a -payment service provider. +GNU Taler payment service providers generally need to ensure high availability +and should have *really* good backups (synchronous replication, asynchronous +remote replication, off-site backup, 24/7 monitoring, etc.). This manual will +not cover these aspects of operating a payment service provider. -We will assume that you can operate a (high-availability, +We will assume that you can operate a (sufficiently high-availability, high-assurance) PostgreSQL database. Furthermore, we expect some moderate familiarity with the compilation and installation of free software -packages. You need to understand the cryptographic concepts of private -and public keys and must be able to protect private keys stored in files -on disk. +packages. You need to understand the cryptographic concepts of private and +public keys and must be able to protect private keys stored in files on disk. .. include:: frags/db-stores-sensitive-data.rst @@ -75,58 +61,65 @@ on disk. Architecture overview --------------------- -Taler is a pure payment system, not a new crypto-currency. As such, it -operates in a traditional banking context. In particular, this means -that in order to receive funds via Taler, the merchant must have a -regular bank account, and payments can be executed in ordinary -currencies such as USD or EUR. Similarly, the Taler exchange must -interact with a bank. The bank of the exchange holds the exchange’s -funds in an escrow account. - -Note that, given the technical burden (XML-based communications, -additional cryptography, and a vast variety of standards) due to -interact with banks, the exchange uses an intermediary system to talk -to its bank. Such intermediary system abstracts the native banking -protocol by exposing the *Taler Wire Gateway API*; this way, the exchange -can conduct its banking operations in a simplified and JSON-based style. - -When customers wire money to the escrow account, the bank notifies the -exchange about the incoming wire transfers. The exchange then creates a -*reserve* based on the subject of the wire transfer. The wallet which -knows the secret key matching the wire transfer subject can then -withdraw coins from the reserve, thereby draining it. The liability of -the exchange against the reserve is thereby converted into a liability -against digital coins issued by the exchange. When the customer later -spends the coins at a merchant, and the merchant *deposits* the coins at +GNU Taler is a pure payment system, not a crypto-currency. As such, it +operates in a traditional banking context. In particular, this means that +payments can be executed in ordinary currencies such as USD or EUR. +Furthermore, a typical merchant in Taler has a regular bank account, and would +use it to receive funds via Taler. + +Consequently, a typical Taler exchange must interact with a bank. The bank of +the exchange holds funds in an account where the balance is basically +equivalent to the value of all coins in circulation. (Small mismatches arise +whenever customers are about to withdraw coins and have already send the funds +into the bank account, or if merchants just deposited coins and are about to +receive wire transfers for deposited coins, or due to fees charged by the +exchange and the operator not yet having drained the fees from the account.) + +The exchange uses an intermediary system to talk to its bank. This shifts the +technical burden (XML-based communications, additional cryptography, and a +vast variety of standards) for this interaction into another bank-specific +subsystem. Such intermediary system abstracts the native banking protocol by +exposing the *Taler Wire Gateway API*; this way, the exchange can conduct its +banking operations in a simplified and JSON-based style. + +When customers wire money to the exchange's bank account, the Taler Wire +Gateway API must notify the exchange about the incoming wire transfers. The +exchange then creates a *reserve* based on the subject of the wire +transfer. The wallet which knows the secret key matching the wire transfer +subject can then withdraw coins from the reserve, thereby draining it. The +liability of the exchange against the reserve is thereby converted into a +liability against digital coins issued by the exchange. When the customer +later spends the coins at a merchant, and the merchant *deposits* the coins at the exchange, the exchange first *aggregates* the amount from multiple -deposits from the same merchant and then instructs its bank to make a -wire transfer to the merchant, thereby fulfilling its obligation and -eliminating the liability. The exchange charges *fees* for some or all -of its operations to cover costs and possibly make a profit. +deposits from the same merchant and then instructs its bank to make a wire +transfer to the merchant, thereby fulfilling its obligation and eliminating +the liability. The exchange charges *fees* for some or all of its operations +to cover costs and possibly make a profit. -*Auditors* are third parties, for example financial regulators, that -verify that the exchange operates correctly. The same software is also -used to calculate the exchange’s profits, risk and liabilities by the -accountants of the exchange. +*Auditors* are third parties, for example financial regulators, that verify +that the exchange operates correctly. The same software is also used to +calculate the exchange’s profits, risk and liabilities by the accountants of +the exchange. The Taler software stack for an exchange consists of the following components: -- HTTP frontend +- **HTTP frontend**: The HTTP frontend interacts with Taler wallets and merchant backends. It is used to withdraw coins, deposit coins, refresh coins, issue refunds, map wire transfers to Taler transactions, inquire about the exchange’s bank account details, signing keys and fee structure. The binary is the ``taler-exchange-httpd``. -- Crypto-Helpers - The ``taler-exchange-secmod-rsa`` and ``taler-exchange-secmod-eddsa`` - are two programs that are responsible for managing the exchange's +- **Crypto-Helpers**: + The ``taler-exchange-secmod-rsa``, ``taler-exchange-secmod-cs`` and + ``taler-exchange-secmod-eddsa`` + are three programs that are responsible for managing the exchange's online signing keys. They must run on the same machine as the ``taler-exchange-httpd`` as the HTTP frontend communicates with the crypto helpers using UNIX Domain Sockets. -- Aggregator +- **Aggregator**: The aggregator combines multiple deposits made by the same merchant and (eventually) triggers wire transfers for the aggregate amount. The merchant can control how quickly wire transfers are made. The @@ -134,14 +127,14 @@ components: excessively frequent transfers. The binary is the ``taler-exchange-aggregator``. -- Closer +- **Closer**: The ``taler-exchange-closer`` tool check that reserves are properly closed. If a customer wires funds to an exchange and then fails to withdraw them, the closer will (eventually) trigger a wire transfer that sends the customer's funds back to the originating wire account. -- Transfer +- **Transfer**: The ``taler-exchange-transfer`` tool is responsible for actually executing the aggregated wire transfers. It is the only process that needs to have the credentials to execute outgoing wire @@ -151,7 +144,7 @@ components: by LibEuFin. LibEuFin is an adapter which maps the Taler Wire REST API to traditional banking protocols like EBICS and FinTS. -- Wirewatch +- **Wirewatch**: The ``taler-exchange-wirewatch`` tool is responsible for observing incoming wire transfers to the exchange. It needs to have the credentials to obtain a list of incoming wire transfers. @@ -160,24 +153,28 @@ components: making outgoing wire transfers is done via different bank accounts and/or credentials. -- Wire adapter +- **Wire adapter**: A wire adapter is a component that enables exchange to talk to a bank. - - (1) The libtalerfakebank implements a bank with a wire adapter API - inside of a testcase. - (2) For the demonstration Web site (or local currencies), - the Python bank provides a bank that directly provides - the wire adapter API. - (3) For production, libeufin's Nexus component implements a wire - adapter towards the traditional SEPA banking system with IBAN - accounts. - - The client-side wire adapter API is implemented in libtalerbank and - is used by the transfer to execute wire transfers and for the - auditor to query bank transaction histories. - - -- DBMS + Each wire adapter must implement the Taler Wire Gateway API. Three + wire adapters are currently provided: + + (1) The **libtalerfakebank** implements a bank with a wire adapter API + inside of a testcase. ``taler-fakebank-run`` is a stand-alone + process using libtalerfakebank. Note that this adapter is only + useful for tests, as all transaction data is kept in memory. + (2) For production, **libeufin**'s ``libeufin-nexus`` component + implements a wire adapter towards the traditional SEPA banking + system with IBAN accounts using the EBICS protocol. + (3) To use GNU Taler with blockchains, the **Depolymerization** + component provides a wire gateway API that runs on top of + blockchains like Bitcoin and Ethereum. + + The client-side wire adapter API is implemented in **libtalerbank** and + is used by ``taler-exchange-transfer`` to execute wire transfers and by + ``taler-exchange-wirewatch`` and the Taler auditor auditor to query bank + transaction histories. + +- **DBMS**: The exchange requires a DBMS to stores the transaction history for the Taler exchange and aggregator, and a (typically separate) DBMS for the Taler auditor. For now, the GNU Taler reference implementation @@ -185,7 +182,7 @@ components: support another DBMS. .. index:: PostgreSQL -- Auditor +- **Auditor**: The auditor verifies that the transactions performed by the exchange were done properly. It checks the various signatures, totals up the amounts and alerts the operator to any inconsistencies. It also @@ -193,13 +190,38 @@ components: exchange operator. The main binary is the ``taler-auditor``. Aside from the key setup procedures, the most critical setup for deploying an auditor is providing the auditor with an up-to-date - copy of the database. + copy of the exchange's database. + + +.. _KeyTypes: + +Key Types +--------- + +The exchange works with four types of keys: + +- master key (kept offline, configured manually at merchants and wallets) + +- online message signing keys (signs normal messages from the exchange) + +- denomination keys (signs digital coins) + +- security module keys (signs online message signing keys and denomination keys) + +Additionally, the exchange is sometimes concerned with the auditor's public +key (to verify messages signed by auditors approved by the exchange operator) +and the merchant's public key (to verify refunds are authorized by the +merchant). + +Most of the keys are managed fully automatically or configured as part of the +denomination configuration. Some configuration settings must be manually +set with regards to the exchange's master key. Offline keys ------------ -The exchange (and ideally also auditors) uses a long-term offline master +The exchange (and ideally also its auditor(s)) uses a long-term offline master siging key that identifies the operator and is used to authenticate critical information, such as the exchange's bank account and the actual keys the exchange uses online. @@ -212,11 +234,10 @@ computing power, a Raspberry-Pi is perfectly sufficient and the form-factor might be good for safe-keeping! (You should keep a copy of the (encrypted) private offline key on more than one physical medium though.) -Exchange operators are strongly advised to secure your private master key and -any copies on encrypted, always-offline computers. Again, we assume that you -are familiar with good best practices in operational security, including -securing key material. - +Exchange operators are strongly advised to secure their private master key and +any copies on encrypted, always-offline computers. Again, this manual assumes +that you are familiar with good best practices in operational security, +including securing key material. Online signing key security @@ -236,8 +257,10 @@ integration support. Functionality ^^^^^^^^^^^^^ -The UNIX domain sockets have mode 0620 (u+rw, g+w). The exchange process -MUST be in the same group as the crypto helper processes. +The UNIX domain sockets of the *secmod* helpers have mode 0620 (u+rw, g+w). +The exchange process MUST thus be in the same group as the crypto helper +processes to enable access to the keys. No other users should be in that +group! The two helper processes will create the required private keys, and allow anyone with access to the UNIX domain socket to sign arbitrary messages with @@ -245,6 +268,7 @@ the keys or to inform them about a key being revoked. The helper processes are also responsible for deleting the private keys if their validity period expires or if they are informed about a key having been revoked. + Security goals ^^^^^^^^^^^^^^ @@ -261,23 +285,21 @@ Setup ^^^^^ The helper processes should be run under a user ID that is separate from that -of the user running the main ``taler-exchange-httpd`` service. For security, -it is important that helpers run under a different user ID than the main HTTP -frontend, in fact ideally each helper should run under its own user ID. The -``taler-exchange-httpd`` service's will securely communicate with the helpers -using UNIX domain sockets. To enable access to the keys, the service's user -must be in the group of the helper processes (and no other users should be in -that group). +of the user running the main ``taler-exchange-httpd`` service. To get any +security benefit from this, it is important that helpers run under a different +user ID than the main HTTP frontend. In fact, ideally, each helper should run +under its own user ID. The ``taler-exchange-httpd`` service's will securely +communicate with the helpers using UNIX domain sockets. Configuration ^^^^^^^^^^^^^ -The helpers and the HTTP service need both access to the same configuration -information. Having divergent configurations may result in run-time failures. -It is recommended that the configuration file (``-c`` option) is simply shared -between all of the different processes, even though they run as different -system users. The configuration does not contain any sensitive information. - +The helpers and the exchange HTTP service need both access to the same +configuration information. Having divergent configurations may result in +run-time failures. It is recommended that the configuration file (``-c`` +option) is simply shared between all of the different processes, even though +they run as different system users. The configuration does not contain any +sensitive information. .. _ExchangeInstallation: @@ -285,9 +307,38 @@ system users. The configuration does not contain any sensitive information. Installation ============ -Before installing a Taler exchange, please make sure that your -system does not have swap space enabled. Swap space is a security -risk that Taler does not try to mitigate against. +Before installing a Taler exchange, please make sure that your system does not +have swap space enabled. Swap space is a security risk that Taler does not +try to mitigate against. + +We recommend the setup of offline signing keys to be done on a second machine that +does not have Internet access. + +In this guide's shell-session fragments, the command prompt shows two pieces +of information: + +* Who is performing the command + (``$user`` vs ``root``, and ending character ``$`` vs ``#``). +* Host where the command is supposed to be executed + (``exchange-offline`` vs ``exchange-online``). + It is possible to do the entire setup on one machine, + but we do not recommend this for security reasons. + +Before you start +---------------- + +To deploy this with a real bank, you need: + + * IBAN of the bank account to use + * BIC of the bank + * EBICS host, user and partner IDs + +Information to write down during the installation: + + * LibEuFin Nexus superuser password + * Taler facade base URL + * exchange Nexus username and password + Installing from source @@ -296,16 +347,10 @@ Installing from source The following instructions will show how to install libgnunetutil and the GNU Taler exchange from source. -The package sources can be find in our +The package sources can be find in our `download directory <http://ftpmirror.gnu.org/taler/>`__. -GNU Taler components version numbers follow the ``MAJOR.MINOR.MICRO`` format. -The general rule for compatibility is that ``MAJOR`` and ``MINOR`` must match. -Exceptions to this general rule are documented in the release notes. -For example, Taler merchant 1.3.0 should be compatible with Taler exchange 1.4.x -as the MAJOR version matches. A MAJOR version of 0 indicates experimental -development, and you are expected to always run all of the *latest* releases -together (no compatibility guarantees). +.. include:: frags/semver.rst First, the following packages need to be installed before we can compile the backend: @@ -333,9 +378,9 @@ Installing the GNU Taler binary packages on Debian To install the Taler exchange, you can now simply run: -.. code-block:: console +.. code-block:: shell-session - # apt install taler-exchange + [root@exchange-online]# apt install taler-exchange Note that the package does not perform any configuration work except for setting up the various users and the systemd service scripts. You still must @@ -343,8 +388,12 @@ configure at least the database, HTTP reverse proxy (typically with TLS certificates), denomination and fee structure, bank account, auditor(s), offline signing and the terms of service. -Sample configuration files for the HTTP reverse proxy can be found in -``/etc/taler-exchange/``. +On the offline system, you should run at least: + +.. code-block:: shell-session + + [root@exchange-offline]# apt install taler-exchange-offline + Installing the GNU Taler binary packages on Trisquel ---------------------------------------------------- @@ -358,9 +407,9 @@ Installing the GNU Taler binary packages on Ubuntu To install the Taler exchange, you can now simply run: -.. code-block:: console +.. code-block:: shell-session - # apt install taler-exchange + [root@exchange-online]# apt install taler-exchange Note that the package does not perform any configuration work except for setting up the various users and the systemd service scripts. You still must @@ -368,136 +417,249 @@ configure at least the database, HTTP reverse proxy (typically with TLS certificates), denomination and fee structure, bank account, auditor(s), offline signing and the terms of service. -Sample configuration files for the HTTP reverse proxy can be found in -``/etc/taler-exchange/``. +On the offline system, you should run at least: +.. code-block:: shell-session -Configuration -============= + [root@exchange-offline]# apt install taler-exchange-offline -This chapter provides an overview of the exchange configuration. Or at -least eventually will do so, for now it is a somewhat wild description -of some of the options. +Services, users, groups and file system hierarchy +------------------------------------------------- -.. include:: frags/configuration-format.rst +The *taler-exchange* package will create several system users +to compartmentalize different parts of the system: +* ``taler-exchange-httpd``: runs the HTTP daemon with the core business logic. +* ``taler-exchange-secmod-rsa``: manages the RSA private online signing keys. +* ``taler-exchange-secmod-cs``: manages the CS private online signing keys. +* ``taler-exchange-secmod-eddsa``: manages the EdDSA private online signing keys. +* ``taler-exchange-closer``: closes idle reserves by triggering wire transfers that refund the originator. +* ``taler-exchange-aggregator``: aggregates deposits into larger wire transfer requests. +* ``taler-exchange-transfer``: performs wire transfers with the bank (via LibEuFin/Nexus). +* ``taler-exchange-wirewatch``: checks for incoming wire transfers with the bank (via LibEuFin/Nexus). +* ``postgres``: runs the PostgreSQL database (from *postgresql* package). +* ``www-data``: runs the frontend HTTPS service with the TLS keys (from *nginx* package). -.. _Using-taler_002dconfig-exchange: +.. note:: -.. include:: frags/using-taler-config.rst + The *taler-merchant* package additionally creates a ``taler-merchant-httpd`` user + to run the HTTP daemon with the merchant business logic. -.. _Keying: +The exchange setup uses the following system groups: -Keying ------- +* ``taler-exchange-db``: group for all Taler users with direct database access, specifically taler-exchange-httpd, taler-exchange-wire, taler-exchange-closer and taler-exchange-aggregator. +* ``taler-exchange-secmod``: group for processes with access to online signing keys; this group must have four users: taler-exchange-secmod-rsa, taler-exchange-secmod-cs, taler-exchange-secmod-eddsa and taler-exchange-httpd. +* ``taler-exchange-offline``: group for the access to the offline private key (only used on the offline host and not used on the online system). -The exchange works with four types of keys: -- master key (kept offline) +The package will deploy systemd service files in +``/usr/lib/systemd/system/`` for the various components: - To create a master key, use: +* ``taler-exchange-aggregator.service``: service that schedules wire transfers + which combine multiple deposits to the same merchant. +* ``taler-exchange-closer.service``: service that watches for reserves that have been abandoned and schedules wire transfers to send the money back to the originator. +* ``taler-exchange-httpd.service``: main Taler exchange logic with the public REST API. +* ``taler-exchange-httpd.socket``: systemd socket activation for the Taler exchange HTTP daemon. +* ``taler-exchange-secmod-eddsa.service``: software security module for making EdDSA signatures. +* ``taler-exchange-secmod-rsa.service``: software security module for making RSA signatures. +* ``taler-exchange-secmod-cs.service``: software security module for making CS signatures. +* ``taler-exchange-transfer.service``: service that triggers outgoing wire transfers (pays merchants). +* ``taler-exchange-wirewatch.service``: service that watches for incoming wire transfers (first step of withdraw). +* ``taler-exchange.target``: Main target for the Taler exchange to be operational. - .. code-block:: console - $ taler-exchange-offline setup +The deployment creates the following key locations in the system: -- sign keys (signs normal messages from the exchange) +* ``/etc/taler/``: configuration files. +* ``/run/taler/``: contains the UNIX domain sockets for inter-process communication (IPC). +* ``/var/lib/taler/``: serves as the $HOME for all Taler users and contains sub-directories + with the private keys; which keys are stored here depends on the host: -- denomination keys (signs electronic coins, see section Coins) + * online system: exchange-secmod-eddsa, exchange-secmod-cs and exchange-secmod-rsa keys. + * offline system: exchange-offline keys. -- security module keys (signs sign keys and denomination keys) -Additionally, the exchange is sometimes concerned with the auditor's public -key (to verify messages signed by auditors approved by the exchange operator) -and the merchant's public key (to verify refunds are authorized by the -merchant). +Configuration Fundamentals +========================== +This chapter provides fundamental details about the exchange configuration. -Key options include: +The configuration for all Taler components uses a single configuration file +as entry point: ``/etc/taler/taler.conf``. -- ``[exchange-offline/MASTER_PRIV_FILE]``: Path to the exchange’s master private file. Only needs to be provided on the offline system where the ``taler-exchange-offline`` command is used. +System defaults are automatically loaded from files in +``/usr/share/taler/config.d``. These default files should never be modified. -- ``[exchange/MASTER_PUBLIC_KEY]``: Must specify the exchange’s master public key. Needed for the exchange to verify information signed by the offline system. +The default configuration ``taler.conf`` configuration file also includes all +configuration files in ``/etc/taler/conf.d``. The settings from files in +``conf.d`` are only relevant to particular components of Taler, while +``taler.conf`` contains settings that affect all components. -.. _Serving: +The directory ``/etc/taler/secrets`` contains configuration file snippets with +values that should only be readable to certain users. They are included with the ``@inline-secret@`` +directive and should end with ``.secret.conf``. -Serving -------- +To view the entire configuration annotated with the source of each configuration option, you +can use the ``taler-config`` helper: -The exchange can serve HTTP over both TCP and UNIX domain socket. -The following options are to be configured in the section ``[exchange]``: +.. code-block:: shell-session -- ``SERVE``: Must be set to ``tcp`` to serve HTTP over TCP, or ``unix`` to serve - HTTP over a UNIX domain socket. + [root@exchange-online]# taler-config --diagnostics + < ... annotated, full configuration ... > -- ``PORT``: Set to the TCP port to listen on if ``SERVE`` is ``tcp``. +.. warning:: -- ``UNIXPATH``: Set to the UNIX domain socket path to listen on if ``SERVE`` is - ``unix``. + While ``taler-config`` also supports rewriting configuration files, we strongly + recommend to edit configuration files manually, as ``taler-config`` does not + preserve comments and, by default, rewrites ``/etc/taler/taler.conf``. + + +.. include:: frags/configuration-format.rst -- ``UNIXPATH_MODE``: Number giving the mode with the access permission mask - for the ``UNIXPATH`` (i.e. 660 = ``rw-rw---``). -.. _Currency: +.. _Using-taler_002dconfig-exchange: + +.. include:: frags/using-taler-config.rst + + +Exchange Database Setup +======================= + +The access credentials for the exchange's database are configured in +``/etc/taler/secrets/exchange-db.secret.conf``. Currently, only PostgreSQL is +supported as a database backend. + +The following users must have access to the exchange database: + +* taler-exchange-httpd +* taler-exchange-wire +* taler-exchange-aggregator +* taler-exchange-closer -Currency --------- +These users are all in the taler-exchange-db group, and the +``exchange-db.secret.conf`` should already be only readable by users in +this group. -The exchange supports only one currency. This data is set under the -respective option ``CURRENCY`` in section ``[taler]``. +.. note:: + + The **taler-exchange-dbconfig** tool can be used to automate the database + setup. When using the Debian/Ubuntu packages, the users should already have + been created, so you can just run the tool without any arguments and should + have a working database configuration. Subsequently, must still grant + access to the other users (see below). (NOTE: we should automate this.) -.. _Database: +To create a database for the Taler exchange on the local system, run: -Database --------- +.. code-block:: shell-session -The option ``DB`` in section ``[exchange]`` gets the database backend’s name the -exchange is going to use. So far, only ``db = postgres`` is supported. After -choosing the backend, it is mandatory to supply the connection string -(namely, the database name). This is possible in two ways: + [root@exchange-online]# su - postgres + [postgres@exchange-online]# createuser taler-exchange-httpd + [postgres@exchange-online]# createuser taler-exchange-wire + [postgres@exchange-online]# createuser taler-exchange-aggregator + [postgres@exchange-online]# createuser taler-exchange-closer + [postgres@exchange-online]# createdb -O taler-exchange-httpd taler-exchange + [postgres@exchange-online]# exit -- via an environment variable: ``TALER_EXCHANGEDB_POSTGRES_CONFIG``. +This will create a ``taler-exchange`` database owned by the +``taler-exchange-httpd`` user. We will use that user later to perform +database maintenance operations. -- via configuration option ``CONFIG``, under section ``[exchangedb-$BACKEND]``. - For example, the demo exchange is configured as follows: + +Assuming the above database setup, the database credentials to configure +in the configuration file would simply be: .. code-block:: ini + :caption: /etc/taler/secrets/exchange-db.secret.conf - [exchange] - ... - DB = postgres - ... + [exchange] + DB = postgres - [exchangedb-postgres] - CONFIG = postgres:///talerdemo + [exchangedb-postgres] + CONFIG=postgres:///taler-exchange -Given this database configuration, the database can be initialized using: +If the database is run on a different host, please follow the instructions +from the PostgreSQL manual for configuring remote access. -.. code-block:: console +After configuring the database credentials, the exchange database needs +to be initialized with the following command: + +.. code-block:: shell-session + + [root@exchange-online]# sudo -u taler-exchange-httpd taler-exchange-dbinit + + ..note:: - $ taler-exchange-dbinit + To run this command, the user must have ``CREATE TABLE``, ``CREATE + INDEX``, ``ALTER TABLE`` and (in the future possibly even) ``DROP TABLE`` + permissions. Those permissions are only required for this step (which may + have to be repeated when upgrading a deployment). Afterwards, during + normal operation, permissions to ``CREATE`` or ``ALTER`` tables are not + required by any of the Taler exchange processes and thus should not be + granted. For more information, see + :doc:`manpages/taler-exchange-dbinit.1`. -Note that to run this command, the user must have ``CREATE TABLE``, ``CREATE -INDEX``, ``ALTER TABLE`` and (in the future possibly even) ``DROP TABLE`` -permissions. Those permissions are only required for this step (which may -have to be repeated when upgrading a deployment). Afterwards, during normal -operation, permissions to ``CREATE`` or ``ALTER`` tables are not required by -any of the Taler exchange processes and thus should not be granted. -For more information, see :doc:`manpages/taler-exchange-dbinit.1`. +Finally we need to grant the other accounts limited access: -Commands, like ``taler-exchange-dbinit``, that support the ``-l LOGFILE`` -command-line option, send logging output to standard error by default. +.. code-block:: shell-session -.. _Coins-denomination-keys: + [root@exchange-online]# sudo -u taler-exchange-httpd bash + [taler-exchange-httpd@exchange-online]# echo 'GRANT SELECT,INSERT,UPDATE ON ALL TABLES IN SCHEMA public TO "taler-exchange-aggregator";' \ + | psql taler-exchange + [taler-exchange-httpd@exchange-online]# echo 'GRANT SELECT,INSERT,UPDATE ON ALL TABLES IN SCHEMA public TO "taler-exchange-closer";' \ + | psql taler-exchange + [taler-exchange-httpd@exchange-online]# echo 'GRANT SELECT,INSERT,UPDATE ON ALL TABLES IN SCHEMA public TO "taler-exchange-wire";' \ + | psql taler-exchange + [taler-exchange-httpd@exchange-online]# echo 'GRANT USAGE ON ALL SEQUENCES IN SCHEMA public TO "taler-exchange-aggregator";' \ + | psql taler-exchange + [taler-exchange-httpd@exchange-online]# echo 'GRANT USAGE ON ALL SEQUENCES IN SCHEMA public TO "taler-exchange-closer";' \ + | psql taler-exchange + [taler-exchange-httpd@exchange-online]# echo 'GRANT USAGE ON ALL SEQUENCES IN SCHEMA public TO "taler-exchange-wire";' \ + | psql taler-exchange + [taler-exchange-httpd@exchange-online]# exit + +.. note:: + + The above instructions for changing database permissions only work *after* + having initialized the database with ``taler-exchange-dbinit``, as + the tables to exist before permissions can be granted on them. The + ``taler-exchange-dbinit`` tool cannot setup these permissions, as it + does not know which users will be used for which processes. + + +Basic Setup: Currency, Denominations and Keys +============================================= + +A Taler exchange only supports a single currency. The currency +and the smallest currency unit supported by the bank system +must be specified in ``/etc/taler/taler.conf``. + +.. code-block:: ini + :caption: /etc/taler/taler.conf + + [taler] + CURRENCY = EUR + CURRENCY_ROUND_UNIT = EUR:0.01 + + # ... rest of file ... + +.. warning:: + + When editing ``/etc/taler/taler.conf``, take care to not accidentally remove + the ``@inline-matching@`` directive to include the configuration files in ``conf.d``. + + .. _Coins-denomination-keys: Coins (denomination keys) ------------------------- +Next, the electronic cash denominations that the exchange offers must be +specified. + Sections specifying denomination (coin) information start with ``coin_``. By convention, the name continues with ``$CURRENCY_[$SUBUNIT]_$VALUE_$REVISION``, i.e. ``[coin_eur_ct_10_0]`` for a 10 cent piece. However, only the ``coin_`` @@ -536,6 +698,10 @@ must then have the following options: - ``RSA_KEYSIZE``: How many bits should the RSA modulus (product of the two primes) have for this type of coin. +- ``AGE_RESTRICTED``: Set to ``YES`` to make this a denomination with support + for age restrictions. See age restriction extension below for details. + This option is optional and defaults to ``NO``. + See :doc:`manpages/taler.conf.5` for information on *duration* values (i.e. ``DURATION_WITHDRAW`` and ``DURATION_SPEND`` above, and ``OVERLAP_DURATION`` and ``DURATION`` below). @@ -564,6 +730,23 @@ Additionally, there are two global configuration options of note: for the exchange and the crypto helpers. We recommend pointing both users to the same configuration file! +The ``taler-wallet-cli`` has a helper command that generates a +reasonable denomination structure. + +.. code-block:: shell-session + + [root@exchange-online]# taler-wallet-cli deployment gen-coin-config \ + --min-amount EUR:0.01 \ + --max-amount EUR:100 \ + > /etc/taler/conf.d/exchange-coins.conf + +You can manually review and edit the generated configuration file. The main +change that is possibly required is updating the various fees. Note that you +MUST NOT edit a coin configuration section after the initial setup. If you +must ``change`` the values, you must instead create a new section with a +different unique name (still with the ``coin-`` prefix) and comment out or +remove the existing section. Do take care to not introduce the name of the +disabled section again in the future. .. _Sign-keys: @@ -595,337 +778,1108 @@ There are three global configuration options of note for sign keys: delayed. -Terms of Service ----------------- +.. _OfflineConfiguration: -The exchange has an endpoint "/terms" to return the terms of service -(in legal language) of the exchange operator. The wallet will show -those terms of service to the user when the user is first withdrawing -coins. Terms of service are optional for experimental deployments, -if none are configured, the exchange will return a simple statement -saying that there are no terms of service available. - -To configure the terms of service response, there are two options -in the ``[exchange]`` section: - -- ``TERMS_ETAG``: The current "Etag" to return for the terms of service. - This value must be changed whenever the terms of service are - updated. A common value to use would be a version number. - Note that if you change the ``TERMS_ETAG``, you MUST also provide - the respective files in ``TERMS_DIR`` (see below). -- ``TERMS_DIR``: The directory that contains the terms of service. - The files in the directory must be readable to the exchange - process. - -The ``TERMS_DIR`` directory structure must follow a particular layout. -First, inside of ``TERMS_DIR``, there should be sub-directories using -two-letter language codes like "en", "de", or "jp". Each of these -directories would then hold translations of the current terms of -service into the respective language. Empty directories are -permitted in case translations are not available. - -Then, inside each language directory, files with the name of the -value set as the ``TERMS_ETAG`` must be provided. The extension of -each of the files should be typical for the respective mime type. -The set of supported mime types is currently hard-coded in the -exchange, and includes HTML, PDF and TXT files. If other files are -present, the exchange may show a warning on startup. - -Example -^^^^^^^ - -A sample file structure for a ``TERMS_ETAG`` of "v1" would be: - -- TERMS_DIR/en/v1.txt -- TERMS_DIR/en/v1.html -- TERMS_DIR/en/v1.pdf -- TERMS_DIR/de/v1.txt -- TERMS_DIR/de/v1.html -- TERMS_DIR/de/v1.pdf -- TERMS_DIR/fr/v1.pdf - -If the user requests an HTML format with language preferences "fr" followed by "en", -the exchange would return ``TERMS_DIR/en/v1.html`` lacking an HTML version in -French. +Setting up the offline signing key +---------------------------------- +Before launching an exchange, the offline signing (master) key must be +generated and set in the configuration. The offline signing keys of the +exchange should be stored on a different machine. The responsibilities of +this offline signing machine are: -.. _Bank-account: +* Generation of the exchange's offline master signing key. +* Secure storage of the exchange's offline master signing key. +* Generation of certificates (signed with the offline master signing key) that will be imported by the exchange. +* Revocation of keys when the online system was compromised or is being terminated -Bank account ------------- -To configure a bank account in Taler, we need to furnish two pieces of -information: +Configuration file options related to the master key are: -- The ``payto://`` URI of the bank account, which uniquely idenfies the - account. Examples for such URIs include - ``payto://iban/CH9300762011623852957`` for a bank account with - an IBAN or - ``payto://x-taler-bank/localhost:8080/2`` for the 2nd bank account a - the Taler bank demonstrator running at ``localhost`` on port 8080. - The first part of the URI following ``payto://`` (“iban” or - “x-taler-bank”) is called the wire method. +- ``[exchange-offline/MASTER_PRIV_FILE]``: Path to the exchange’s master + private file. Only needs to be provided on the offline system where the + ``taler-exchange-offline`` command is used. The default value is usually + fine and does not require adjustment. -- The ``taler-exchange-wirewatch`` and ``taler-exchange-transfer`` - tools needs to be provided resources for authentication - to the respective banking service. The format in which the - authentication information is currently a username and password - for HTTP basic authentication. +- ``[exchange/MASTER_PUBLIC_KEY]``: Must specify the exchange’s master public + key. Needed for the exchange to verify information signed by the offline + system. This value must almost always be set explicitly by hand. -You can configure multiple accounts for an exchange by creating sections -starting with “exchange-account-” for the section name. You can ENABLE for -each account whether it should be used, and for what (incoming or outgoing -wire transfers): + + +.. code-block:: shell-session + + [root@exchange-offline]# taler-exchange-offline setup + < ... prints the exchange master public key > + +The public key printed as the output of this command must be put into the +configuration of the online machine: .. code-block:: ini + :caption: /etc/taler/conf.d/exchange-business.conf - [exchange-account-1] - # With x-taler-bank (say for PyBank) - PAYTO_URI = "payto://x-taler-bank/bank.demo.taler.net/Exchange" + [exchange] + MASTER_PUBLIC_KEY = YE6Q6TR1ED... - # Example using IBAN (for use with LibEuFin) - # PAYTO_URI = "payto://iban/CH9300762011623852957" + # ... rest of file ... - # URL for talking to the bank wire the wire API. - WIRE_GATEWAY_URL = https://bank.demo.taler.net/taler-wire-gateway/Exchange - # Use for exchange-aggregator (outgoing transfers) - ENABLE_DEBIT = YES - # Use for exchange-wirewatch (and listed in /wire) - ENABLE_CREDIT = YES +Wire Gateway Setup +================== - # Authentication options for exchange bank account go here. - # (Next sections have examples of authentication mechanisms) - WIRE_GATEWAY_AUTH_METHOD = basic - USERNAME = exchange - PASSWORD = super-secure +The Taler Wire Gateway is an API that connects the Taler exchange to +the underlying core banking system. +LibEuFin is an implementation of the Wire Gateway API for the EBICS protocol. +This section will walk through (1) installing and configuring LibEuFin and +(2) connecting the Taler Exchange to LibEuFin. -The command line tool ``taler-exchange-offline`` must be used to -sign the ``payto://`` URI in a way suitable to convince wallets that -this is the correct address to wire funds to. -For example, the utility may be invoked as -follows to enable a wire account: +.. note:: -.. code-block:: console + If you do not have a bank account with EBICS but want to test these instructions, + you can use the EBICS sandbox as described in the + :doc:`LibEuFin Tutorial <libeufin/nexus-tutorial>`. - $ taler-exchange-offline enable-account payto://iban/CH9300762011623852957 -The resulting JSON output must be uploaded to the exchange using -``taler-exchange-offline upload``. -For details, see :doc:`manpages/taler-exchange-offline.1`. +Installation and Basic Configuration +------------------------------------ +First, install the ``libeufin`` package. This can be done on the ``exchange-online`` +machine or a different one. -.. _Wire-fee-structure: +.. code-block:: shell-session -Wire fee structure -^^^^^^^^^^^^^^^^^^ + [root@exchange-online]# apt-get install -y libeufin -.. index:: wire fee -.. index:: fee +The main component of LibEuFin is called the Nexus. It implements a Web +service that provides a JSON abstraction layer to access bank accounts. -For each wire method (“iban” or “x-taler-bank”) the -exchange must know about applicable wire fees. This is also done -using the ``taler-exchange-offline`` tool: +The HTTP port and database connection string can be edited in the configuration: -.. code-block:: console +.. code-block:: ini + :caption: /etc/libeufin/nexus.env - $ taler-exchange-offline wire-fee 2040 iban EUR:0.05 EUR:0.10 EUR:0.15 + LIBEUFIN_NEXUS_PORT=5017 + LIBEUFIN_NEXUS_DB_CONNECTION=jdbc:sqlite:/var/lib/libeufin/nexus/nexus-db.sqlite3 -The above sets the wire fees for wire transfers involving ``iban`` accounts -(in Euros) in the year 2040 to 5 cents (wire fee) and 10 cents (closing fee). -The tool only supports setting fees that applies for the entire calendar year. +After configuring the database, you can start the service. +The database is initialized automatically. -We recommend provisioning an exchange with wire fees at least for the next two -years. Note that once the fees have been set for a year, they cannot be -changed (basically, by signing the fees the exchange makes a legally binding -offer to the customers). -.. index:: maintenance +.. code-block:: shell-session + + [root@exchange-online]# systemctl enable libeufin-nexus + [root@exchange-online]# systemctl start libeufin-nexus + +You can now create a superuser account. The command to +create the superuser needs direct database access, thus +the configuration file is sourced first, and the relevant +environment variable is exported. + +.. code-block:: console + + [root@exchange-online]# source /etc/libeufin/nexus.env + [root@exchange-online]# export LIBEUFIN_NEXUS_DB_CONNECTION + [root@exchange-online]# NEXUS_ADMIN_PW=$(tr -dc A-Za-z0-9 </dev/urandom | head -c 13) + [root@exchange-online]# libeufin-nexus superuser admin --password $NEXUS_ADMIN_PW + +If you omit ``--password $NEXUS_ADMIN_PW``, you will interactively be asked for a password. +For simplicity, a superuser can as well act as a normal user, but an API +to create less privileged users is offered. + .. note:: - Provisioning future wire fees, like provisioning future denomination - and signing keys, are key regular maintenance procedures for every - exchange operator. We recommend setting automated reminders for - this maintenance activity! + User and permissions management in LibEuFin is still under development. + In particular, permissions for non-superusers are very limited at the moment. -.. _Auditor-configuration: -Auditor configuration ---------------------- +Connecting Nexus with an EBICS account +-------------------------------------- -The exchange must be informed about any auditor that is expected to provision -it with auditor signatures. This is also done using the -``taler-exchange-offline`` tool on the offline system. First, the auditor -must be configured and provide the exchange operator with its public key and -the URL of it's REST API. The exchange operator also needs a human-readable -name that may be shown to users to identify the auditor. Given this -information, the exchange operator can enable the auditor: +The command line interface of the LibEuFin Nexus needs the following three +values to be defined in the environment: ``LIBEUFIN_NEXUS_URL``, +``LIBEUFIN_NEXUS_USERNAME``, and ``LIBEUFIN_NEXUS_PASSWORD``. In this example, +``LIBEUFIN_NEXUS_USERNAME`` should be set to ``admin``, and +``LIBEUFIN_NEXUS_PASSWORD`` to the value hold in ``NEXUS_ADMIN_PW`` from the +previous step (the ``libeufin-nexus superuser`` command). The +``LIBEUFIN_NEXUS_URL`` could be given as ``http://localhost:5017/``. + +Next, we create a EBICS *bank connection* that Nexus can use to communicate with the bank. .. code-block:: console - $ taler-exchange-offline enable-auditor $PUB_KEY $REST_URL "$AUDITOR_NAME" > auditor.json + [root@exchange-online]# libeufin-cli \ + connections \ + new-ebics-connection \ + --ebics-url $EBICS_BASE_URL \ + --host-id $EBICS_HOST_ID \ + --partner-id $EBICS_PARTNER_ID \ + --ebics-user-id $EBICS_USER_ID \ + $CONNECTION_NAME -As before, the *auditor.json* file must then be copied from the offline system -to a system connected to the exchange and there ``uploaded`` to the exchange. +If this step executes correctly, Nexus will have created all the cryptographic +material that is needed on the client side; in this EBICS example, it created +the signature and identification keys. It is therefore advisable to *make +a backup copy* of such keys. +.. code-block:: console + [root@exchange-online]# libeufin-cli \ + connections \ + export-backup \ + --passphrase $SECRET \ + --output-file $BACKUP_FILE \ + $CONNECTION_NAME -.. _Deployment: +At this point, Nexus needs to both communicate its keys to the bank, and +download the bank's keys. This synchronization happens through the INI, HIA, and +finally, HPB message types. -Deployment -========== +After the electronic synchronization, the subscriber must confirm their keys +by sending a physical mail to the bank. The following command helps generating +such letter: -This chapter describes how to deploy the exchange once it has been -configured. +.. code-block:: console + [root@exchange-online]# libeufin-cli connections get-key-letter $CONNECTION_NAME out.pdf -.. _Launch: +.. code-block:: console -Launching an exchange ---------------------- + [root@exchange-online]# libeufin-cli \ + connections \ + connect \ + $CONNECTION_NAME -A running exchange requires starting the following processes: +.. + FIXME: Maybe is not 100% clear that 'connecting' means exchanging keys + with the bank? -- ``taler-exchange-secmod-rsa`` (as special user, sharing group with the HTTPD) -- ``taler-exchange-secmod-eddsa`` (as special user, sharing group with the HTTPD) -- ``taler-exchange-httpd`` (needs database access) -- ``taler-exchange-aggregator`` (only needs database access) -- ``taler-exchange-closer`` (only needs database access) -- ``taler-exchange-wirewatch`` (needs bank account read credentials and database access) -- ``taler-exchange-transfer`` (needs credentials to initiate outgoing wire transfers and database access) +Once the connection is synchronized, Nexus needs to import locally the data +corresponding to the bank accounts offered by the bank connection just made. +The command below downloads the list of the bank accounts offered by ``$CONNECTION_NAME``. -The crypto helpers must be started before the ``taler-exchange-httpd`` and -they should use the same configuration file. +.. code-block:: console -For the most secure deployment, we recommend using separate users for each of -these processes to minimize information disclosures should any of them be -compromised. The helpers do not need access to the PostgreSQL database (and -thus also should not have it). + [root@exchange-online]# libeufin-cli \ + connections \ + download-bank-accounts \ + $CONNECTION_NAME -The processes that require access to the bank account need to have a -configuration file with the respective credentials in it. We recommend using a -separate configuration at least for ``taler-exchange-transfer`` which is the -*only* process that needs to know the credentials to execute outgoing wire -transfers. +It is now possible to list the accounts offered by the connection. -All of these processes should also be started via a hypervisor like -``systemd`` or ``gnunet-arm`` that automatically re-starts them should they -have terminated unexpectedly. If the bank is down (say for maintenance), it is -*possible* to halt the ``taler-exchange-wirewatch`` and/or -``taler-exchange-transfer`` processes (to avoid them making requests to the -bank API that can only fail) without impacting other operations of the -exchange. Naturally, incoming wire transfers will only be observed once -``taler-exchange-wirewatch`` is resumed, and merchants may complain if the -disabled ``taler-exchange-transfer`` process causes payment deadlines to be -missed. +.. code-block:: console + + [root@exchange-online]# libeufin-cli \ + connections \ + list-offered-bank-accounts \ + $CONNECTION_NAME .. note:: - The ``taler-exchange-httpd`` does not ship with HTTPS enabled by default. - In production, it should be run behind an HTTPS reverse proxy that performs - TLS termination on the same system. Thus, it would typically be configured - to listen on a UNIX domain socket. The ``/management`` and ``/auditors`` - APIs do technically not have to be exposed on the Internet (only to the - administrators running ``taler-exchange-offline``) and should be blocked - by the reverse proxy for requests originating from outside of the bank. - (However, this is not a strong security assumption: in principle having - these endpoints available should do no harm. However, it increases the - attack surface.) + The ``nexusBankAccountId`` field should at this step be ``null``, + as we have not yet imported the bank account and thus the account + does not yet have a local name. -.. _Keys-generation: +Nexus now needs an explicit import of the accounts it should manage. This +step is needed to let the user pick a custom name for such accounts. -Keys generation ---------------- +.. code-block:: console -Once the configuration is properly set up, all the keys can be signed using -the offline key on the offline system by the tool ``taler-exchange-offline``. -To do this, one must first start the crypto helpers and the ``taler-exchange-httpd`` -process (the tools for wire transfers may also be started, but do not have to -run yet). + [root@exchange-online]# libeufin-cli \ + connections \ + import-bank-account \ + --offered-account-id testacct01 \ + --nexus-bank-account-id $LOCAL_ACCOUNT_NAME \ + $CONNECTION_NAME -Next, the *future* key material should be downloaded using: +Once a Nexus user imported a bank account (``$LOCAL_ACCOUNT_NAME``) +under a certain connection (``$CONNECTION_NAME``), it is possible +to accomplish the usual operations for any bank account: asking for the +list of transactions, and making a payment. -.. code-block:: console +Testing: Requesting the transaction history +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - $ taler-exchange-offline download > future-keys.json +The LibEuFin Nexus keeps a local copy of the bank account's transaction +history. Before querying transactions locally, it is necessary +to request transactions for the bank account via the bank connection. -Afterwards, *future-keys.json* contains data about denomination and -online signing keys that the exchange operator needs to sign with -the offline tool. The file should be copied to the offline system. -There, the operator should run: +This command asks Nexus to download the latest transaction reports/statements +through the bank connection: .. code-block:: console - $ taler-exchange-offline show < future-keys.json + [root@exchange-online]# libeufin-cli accounts fetch-transactions $LOCAL_ACCOUNT_NAME -and verify that the output contains the fee structure and key lifetimes -they expect to see. They should also note the public keys being shown -and communicate those to the *auditors* over a secure channel. Once -they are convinced the file is acceptable, they should run: +.. note:: -.. code-block:: console + By default, the latest available transactions are fetched. It is also + possible to specify a custom date range (or even all available transactions) + and the type of transactions to fetch (inter-day statements or intra-day + reports). - $ taler-exchange-offline sign < future-keys.json > offline-sigs.json +.. + FIXME: Possibly the date range filter is still missing, see #6243. -The *offline-sigs.json* file must then be copied to an online system -that is able to again communicate with the exchange. On that system, run: +Once Nexus has stored all the information in the database, the +client can ask to actually see the transactions: .. code-block:: console - $ taler-exchange-offline upload < offline-sigs.json + [root@exchange-online]# libeufin-cli accounts transactions $LOCAL_ACCOUNT_NAME + +Testing: Making payments +^^^^^^^^^^^^^^^^^^^^^^^^ -to provision the signatures to the exchange. At this point, the -exchange will be able to use those keys, but wallets and merchants -may not yet trust them! Thus, the next step is for the auditor -to affirm that they are auditing this exchange. Details about -this are described in :doc:`taler-auditor-manual`. +Payments pass through two phases: preparation and submission. The preparation +phase assigns the payment initiation a unique ID, which prevents accidental +double submissions of payments in case of network failures or other +disruptions. -The simplistic (without using offline keys for the auditor) way -to do this would be: + +The following command prepares a payment: .. code-block:: console - $ taler-auditor-offline download sign upload + [root@exchange-online]# libeufin-cli accounts prepare-payment \ + --creditor-iban=$IBAN_TO_SEND_MONEY_TO \ + --creditor-bic=$BIC_TO_SEND_MONEY_TO \ + --creditor-name=$CREDITOR_NAME \ + --payment-amount=$AMOUNT \ + --payment-subject=$SUBJECT \ + $LOCAL_ACCOUNT_NAME -For more information, see :doc:`manpages/taler-auditor-offline.1`. +Note: the ``$AMOUNT`` value needs the format ``X.Y:CURRENCY``; for example +``EUR:10``, or ``EUR:1.01``. +The previous command should return a value (``$UUID``) that uniquely +identifies the prepared payment in the Nexus system. That is needed +in the next step, to **send the payment instructions to the bank**: -Private key storage -------------------- +.. code-block:: console -Keeping the private keys the helpers create secret is paramount. If the -private keys are lost, it is easy to provision fresh keys (with the help of -the auditor). Thus, we recommend that the private keys of the crypto helpers -are *not* backed up: in the rare event of a disk failure, they can be -regenerated. However, we do recommend using RAID (1+1 or 1+1+1) for all -disks of the system. + [root@exchange-online]# libeufin-cli accounts submit-payments \ + --payment-uuid $UUID \ + $LOCAL_ACCOUNT_NAME +Automatic scheduling +^^^^^^^^^^^^^^^^^^^^ -.. _Database-upgrades: +With an EBICS bank connection, the LibEuFin Nexus needs to regularly query for +new transactions and (re-)submit prepared payments. -Database upgrades ------------------ +It is possible to schedule these tasks via an external task scheduler such as +cron(8). However, the nexus also has an internal task scheduling mechanism for +accounts. -Currently, there is no way to upgrade the database between Taler -versions. -The exchange database can be re-initialized using: +The following three commands create a schedule for submitting payments hourly, +fetching transactions (intra-day reports) every 5 minutes, and (inter-day statements) +once at 11pm every day: .. code-block:: console - $ taler-exchange-dbinit -r + [root@exchange-online]# libeufin-cli accounts task-schedule $LOCAL_ACCOUNT_NAME \ + --task-type="submit" \ + --task-name='submit-payments-hourly' \ + --task-cronspec='0 0 *' -However, running this command will result in all data in the database -being lost, which may result in significant financial liabilities as the -exchange can then not detect double-spending. Hence this operation must -not be performed in a production system. + [root@exchange-online]# libeufin-cli accounts task-schedule $LOCAL_ACCOUNT_NAME \ + --task-type="fetch" \ + --task-name='fetch-5min' \ + --task-cronspec='0 */5 *' \ + --task-param-level=report \ + --task-param-range-type=latest + [root@exchange-online]# libeufin-cli accounts task-schedule $LOCAL_ACCOUNT_NAME \ + --task-type="fetch" \ + --task-name='fetch-daily' \ + --task-cronspec='0 0 23' \ + --task-param-level=statement \ + --task-param-range-type=latest -.. _Revocations: +The cronspec has the following format, which is slightly non-standard due to +the ``SECONDS`` field -Revocations -^^^^^^^^^^^ +.. code-block:: none + + SECONDS MINUTES HOURS DAY-OF-MONTH[optional] MONTH[optional] DAY-OF-WEEK[optional] + + +Creating a Taler facade +^^^^^^^^^^^^^^^^^^^^^^^ + +Facades are additional abstraction layers that can serve +specific purposes. For example, one application might need +a filtered version of the transaction history, or it might +want to refuse payments that do not conform to certain rules. + +At this moment, only the *Taler facade type* is implemented +in the Nexus, and the command below instantiates one under a +existing bank account / connection pair. You can freely +assign an identifier for the ``$FACADE_NAME`` below: + +.. code-block:: console + + [root@exchange-online]# libeufin-cli facades new-taler-wire-gateway-facade \ + --currency EUR \ + --facade-name $FACADE_NAME \ + $CONNECTION_NAME \ + $LOCAL_ACCOUNT_NAME + +At this point, the additional :doc:`taler-wire-gateway API <core/api-bank-wire>` +becomes offered by the Nexus. The purpose is to let a Taler exchange rely on +Nexus to manage its bank account. + +The base URL of the facade that can be used by the Taler exchange +as the Taler Wire Gateway base URL can be seen by listing the facades: + +.. code-block:: console + + [root@exchange-online]# libeufin-cli facades list + +Managing Permissions and Users +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This guide has so far assumed that a superuser is accessing the LibEuFin Nexus. +However, it is advisable that the Nexus is accessed with users that only have a +minimal set of permissions. + +The Nexus currently only has support for giving non-superusers access to Taler +wire gateway facades. + +To create a new user, use the ``users`` subcommand of the CLI: + +.. code-block:: console + + [root@exchange-online]# libeufin-cli users list + # [ ... shows available users ... ] + + [root@exchange-online]# libeufin-cli users create $USERNAME + # [ ... will prompt for password ... ] + +Permissions are managed with the ``permissions`` subcommand. +The following commands grant permissions to view the transaction history +and create payment initiations with a Taler wire gateway facade: + + +.. code-block:: console + + [root@exchange-online]# libeufin-cli permissions grant \ + user $USERNAME \ + facade $FACADENAME \ + facade.talerwiregateway.history + + [root@exchange-online]# libeufin-cli permissions grant \ + user $USERNAME \ + facade $FACADENAME \ + facade.talerwiregateway.transfer + +.. + FIXME: The two commands above output an empty JSON object + when successful. Possibly, we should suppress that (just like + the other commands do). + +The list of all granted permissions can be reviewed: + +.. code-block:: console + + [root@exchange-online]# libeufin-cli permissions list + + +.. _Bank-account: + +Exchange Bank Account Configuration +----------------------------------- + +An exchange must be configured with the right settings to access its bank +account via a Taler Wire Gateway. An exchange can be configured to use +multiple bank accounts by using multiple Wire Gateways. Typically only one +Wire Gateway is used. + +To configure a bank account in Taler, we need to furnish two pieces of +information: + +- The ``payto://`` URI of the bank account, which uniquely idenfies the + account. Examples for such URIs include + ``payto://iban/CH9300762011623852957`` for a bank account with + an IBAN or + ``payto://x-taler-bank/localhost:8080/2`` for the 2nd bank account a + the Taler bank demonstrator running at ``localhost`` on port 8080. + The first part of the URI following ``payto://`` (“iban” or + “x-taler-bank”) is called the wire method. + +- The ``taler-exchange-wirewatch`` and ``taler-exchange-transfer`` + tools needs to be provided resources for authentication + to the respective banking service. The format in which the + authentication information is currently a username and password + for HTTP basic authentication. + + +A Taler Wire Gateway is configured in a configuration section that follows the +pattern ``exchange-account-$id``, where ``$id`` is an internal identifier for +the bank account accessed by the exchange. The basic information for an +account should be put in ``/etc/taler/conf.d/exchange-business.conf``. The +secret credentials to access the Taler Wire Gateway API should be put into a +corresponding ``exchange-accountcredentials-$id`` section in +``/etc/taler/secrets/exchange-accountcredentials.conf``. The latter file +should already be only readable for the ``taler-exchange-wire`` user. Other +exchange processes should not have access to this information. + +You can configure multiple accounts for an exchange by creating sections +starting with “exchange-account-” for the section name. You can ENABLE for +each account whether it should be used, and for what (incoming or outgoing +wire transfers): + +.. code-block:: ini + :caption: /etc/taler/conf.d/exchange-business.conf + + [exchange-account-1] + # Account identifier in the form of an RFC-8905 payto:// URI. + # For SEPA, looks like payto://iban/$IBAN?receiver-name=$NAME + # Make sure to URL-encode spaces in $NAME! + # + # With x-taler-bank (for Fakebank) + # PAYTO_URI = "payto://x-taler-bank/bank.demo.taler.net/Exchange?receiver-name=exop" + # + # Example using IBAN (for use with LibEuFin) + PAYTO_URI = "payto://iban/CH9300762011623852957?receiver=name=exop" + + # URL for talking to the bank wire the wire API. + WIRE_GATEWAY_URL = https://bank.demo.taler.net/taler-wire-gateway/Exchange + + # Use for exchange-aggregator (outgoing transfers) + ENABLE_DEBIT = YES + # Use for exchange-wirewatch (and listed in /wire) + ENABLE_CREDIT = YES + + @inline-secret@ exchange-accountcredentials-1 ../secrets/exchange-accountcredentials.secret.conf + + +.. code-block:: ini + :caption: /etc/taler/secrets/exchange-accountcredentials.secret.conf + + [exchange-accountcredentials-1] + + # LibEuFin expects basic auth. + WIRE_GATEWAY_AUTH_METHOD = basic + + # Username and password set in LibEuFin. + USERNAME = ... + PASSWORD = ... + + # Base URL of the wire gateway set up with LibEuFin. + WIRE_GATEWAY_URL = ... + + +Such a Wire Gateway configuration can be tested with the following commands: + +.. code-block:: shell-session + + [root@exchange-online]# taler-exchange-wire-gateway-client \ + --section exchange-accountcredentials-1 --debit-history + [root@exchange-online]# taler-exchange-wire-gateway-client \ + --section exchange-accountcredentials-1 --credit-history + + + +.. _LegalSetup: + +Legal Setup +=========== + +This chapter describes how to setup certain legal aspects of a GNU Taler +exchange. Users that just want to set up an exchange as an experiment without +legal requirements can safely skip these steps. + + +Legal conditions for using the service +-------------------------------------- + +.. include:: frags/legal.rst + + +KYC Configuration +----------------- + +To legally operate, Taler exchange operators may have to comply with KYC +regulation that requires financial institutions to identify parties involved +in transactions at certain points. + +Taler permits an exchange to require KYC data under the following circumstances: + + * Customer withdraws money over a threshold + * Wallet receives (via refunds) money resulting in a balance over a threshold + * Wallet receives money via P2P payments over a threshold + * Merchant receives money over a threshold + * Reserve is "opened" for invoicing or rewards (**planned feature**) + + +Taler KYC Terminology +^^^^^^^^^^^^^^^^^^^^^ + +* **Check**: A check establishes a particular attribute of a user, such as + their name based on an ID document and lifeness, mailing address, phone + number, taxpayer identity, etc. + +* **Type of operation**: The operation type determines which Taler-specific + operation has triggered the KYC requirement. We support four types of + operation: withdraw (by customer), deposit (by merchant), P2P receive (by + wallet) and (high) wallet balance. + +* **Condition**: A condition specifies when KYC is required. Conditions + include the *type of operation*, a threshold amount (e.g. above EUR:1000) + and possibly a time period (e.g. over the last month). + +* **Cost**: Metric for the business expense for a KYC check at a certain + *provider*. Not in any currency, costs are simply relative and non-negative + values. Costs are considered when multiple choices are allowed by the + *configuration*. + +* **Expiration**: KYC legitimizations may be outdated. Expiration rules + determine when *checks* have to be performed again. + +* **Legitimization rules**: The legitimization rules determine under which + *conditions* which *checks* must be performend and the *expiration* time + period for the *checks*. + +* **Logic**: Logic refers to a specific bit of code (realized as an exchange + plugin) that enables the interaction with a specific *provider*. Logic + typically requires configuration for access control (such as an + authorization token) and possibly the endpoint of the specific *provider* + implementing the respective API. + +* **Provider**: A provider performs a specific set of *checks* at a certain + *cost*. Interaction with a provider is performed by provider-specific + *logic*. + + +KYC Configuration Options +^^^^^^^^^^^^^^^^^^^^^^^^^ + +The KYC configuration determines the *legitimization rules*, and specifies +which providers offer which *checks* at what *cost*. + +The configuration specifies a set of providers, one per configuration section. The names of the configuration +sections must being with ``kyc-proider-`` followed by +an arbitrary ``$PROVIDER_ID``: + +.. code-block:: ini + :caption: /etc/taler/conf.d/exchange-kyc-providers.conf + + [kyc-provider-$PROVIDER_ID] + # How expensive is it to use this provider? + # Used to pick the cheapest provider possible. + COST = 42 + # Which plugin is responsible for this provider? + # Choices include "oauth2", "kycaid" and "persona". + LOGIC = oauth2 + # Which type of user does this provider handle? + # Either INDIVIDUAL or BUSINESS. + USER_TYPE = INDIVIDUAL + # Which checks does this provider provide? + # List of strings, no specific semantics. + PROVIDED_CHECKS = SMS GOVID PHOTO + # Plus additional logic-specific options, e.g.: + AUTHORIZATION_TOKEN = superdupersecret + FORM_ID = business_legi_form + # How long is the check considered valid? + EXPIRATION = 3650d + +The configuration also must specify a set of legitimization requirements, again one +per configuration section: + +.. code-block:: ini + :caption: /etc/taler/conf.d/exchange-kyc-rules.conf + + [kyc-legitimization-$RULE_NAME] + # Operation that triggers this legitimization. + # Must be one of WITHDRAW, DEPOSIT, P2P-RECEIVE + # or WALLET-BALANCE. + OPERATION_TYPE = WITHDRAW + # Required checks to be performed. + # List of strings, must individually match the + # strings in one or more provider's PROVIDED_CHECKS. + REQUIRED_CHECKS = SMS GOVID + # Threshold amount above which the legitimization is + # triggered. The total must be exceeded in the given + # timeframe. + THRESHOLD = KUDOS:100 + # Timeframe over which the amount to be compared to + # the THRESHOLD is calculated. Can be 'forever'. + # Ignored for WALLET-BALANCE. + TIMEFRAME = 30d + + +OAuth 2.0 specifics +^^^^^^^^^^^^^^^^^^^ + +In terms of configuration, the OAuth 2.0 logic requires the respective client +credentials to be configured apriori to enable access to the legitimization +service. The OAuth 2.0 configuration options are: + +.. code-block:: ini + :caption: /etc/taler/conf.d/exchange-oauth2.conf + + [kyc-provider-example-oauth2] + LOGIC = oauth2 + # (generic options omitted) + # How long is the KYC check valid? + KYC_OAUTH2_VALIDITY = forever + + # URL to which we redirect the user for the login process + KYC_OAUTH2_AUTHORIZE_URL = "http://kyc.example.com/authorize" + # URL where we POST the user's authentication information + KYC_OAUTH2_TOKEN_URL = "http://kyc.example.com/token" + # URL of the user info access point. + KYC_OAUTH2_INFO_URL = "http://kyc.example.com/info" + + # Where does the client get redirected upon completion? + KYC_OAUTH2_POST_URL = "http://example.com/thank-you" + + # For authentication to the OAuth2.0 service + KYC_OAUTH2_CLIENT_ID = testcase + KYC_OAUTH2_CLIENT_SECRET = password + + # Mustach template that converts OAuth2.0 data about the user + # into GNU Taler standardized attribute data. + # + KYC_OAUTH2_ATTRIBUTE_TEMPLATE = "{"fullname":"{{last_name}}, {{first_name}}","phone":"{{phone}}"}" + +The ``KYC_OAUTH2_ATTRIBUTE_TEMPLATE`` provides a generic way to convert data +returned by an OAuth-provider into the internal format used by the exchange. + +The Challenger service for address validation supports OAuth2.0, but does not +have a static AUTHORIZE_URL. Instead, the AUTHORIZE_URL must be enabled by the client +using a special authenticated request to the Challenger's ``/setup`` endpoint. +The exchange supports this by appending ``#setup`` to the AUTHORIZE_URL (note +that fragments are illegal in OAuth2.0 URLs). Be careful to quote the URL, +as ``#`` is otherwise interpreted as the beginning of a comment by the +configuration file syntax. + +.. code-block:: ini + :caption: /etc/taler/conf.d/exchange-challenger-oauth2.conf + + [kyc-provider-challenger-oauth2] + LOGIC = oauth2 + KYC_OAUTH2_AUTHORIZE_URL = "http://challenger.example.com/authorize/#setup" + KYC_OAUTH2_TOKEN_URL = "http://challenger.example.com/token" + KYC_OAUTH2_INFO_URL = "http://challenger.example.com/info" + +When using OAuth 2.0, the *CLIENT REDIRECT URI* must be set to the +``/kyc-proof/$PROVIDER_SECTION`` endpoint. For example, given the +configuration above and an exchange running on the host +``exchange.example.com``, the redirect URI would be +``https://exchange.example.com/kyc-proof/kyc-provider-challenger-oauth2/``. + + + +Persona specifics +^^^^^^^^^^^^^^^^^ + +We use the hosted flow. The Persona endpoints return a ``request-id``, which +we log for diagnosis. + +Persona should be configured to use the ``/kyc-webhook/`` endpoint of the +exchange to notify the exchange about the completion of KYC processes. +The webhook is authenticated using a shared secret, which should +be in the configuration. + +.. code-block:: ini + :caption: /etc/taler/conf.d/exchange-persona.conf + + [kyclogic-persona] + # Webhook authorization token. Global for all uses + # of the persona provider! + WEBHOOK_AUTH_TOKEN = wbhsec_698b5a19-c790-47f6-b396-deb572ec82f9 + + [kyc-provider-example-persona] + LOGIC = persona + # (generic options omitted) + + # How long is the KYC check valid? + KYC_PERSONA_VALIDITY = 365d + + # Which subdomain is used for our API? + KYC_PERSONA_SUBDOMAIN = taler + + # Helper to convert JSON with KYC data returned by Persona into GNU Taler + # internal format. Should probably always be set to + # "taler-exchange-kyc-persona-converter.sh". + KYC_PERSONA_CONVERTER_HELPER = "taler-exchange-kyc-persona-converter.sh" + + # Authentication token to use. + KYC_PERSONA_AUTH_TOKEN = persona_sandbox_42 + + # Form to use. + KYC_PERSONA_TEMPLATE_ID = itempl_Uj6Xxxxx + + # Where do we redirect to after KYC finished successfully. + KYC_PERSONA_POST_URL = "https://taler.net/" + + # Salt to give to requests for idempotency. + # Optional. + # KYC_PERSONA_SALT = salt + +To use the Persona webhook, you must set the webhook URL in the +Persona service to ``$EXCHANGE_BASE_URL/kyc-webhook/$SECTION_NAME/`` +where ``$SECTION_NAME`` is the name of the configuration section. +You should also extract the authentication token for the webhook +and put it into the configuration as shown above. + + +KYC AID specifics +----------------- + +We use the hosted flow. + +KYCAID should be configured to use the ``/kyc-webhook/`` endpoint of the +exchange to notify the exchange about the completion of KYC processes. + +.. code-block:: ini + :caption: /etc/taler/conf.d/exchange-kycaid.conf + + [kyc-provider-example-kycaid] + LOGIC = kycaid + # (generic options omitted) + + # How long is the KYC check valid? + KYC_KYCAID_VALIDITY = 365d + + # Authentication token to use. + KYC_KYCAID_AUTH_TOKEN = XXX + + # Form to use. + KYC_KYCAID_FORM_ID = XXX + + # URL to go to after the process is complete. + KYC_KYCAID_POST_URL = "https://taler.net/" + + +.. _Deployment: + +Deployment +========== + +This chapter describes how to deploy the exchange once the basic installation +and configuration are completed. + +.. _Serving: + +Serving +------- + +The exchange can serve HTTP over both TCP and UNIX domain socket. + +The following options are to be configured in the section ``[exchange]``: + +- ``SERVE``: Must be set to ``tcp`` to serve HTTP over TCP, or ``unix`` to serve + HTTP over a UNIX domain socket. + +- ``PORT``: Set to the TCP port to listen on if ``SERVE`` is ``tcp``. + +- ``UNIXPATH``: Set to the UNIX domain socket path to listen on if ``SERVE`` is + ``unix``. + +- ``UNIXPATH_MODE``: Number giving the mode with the access permission mask + for the ``UNIXPATH`` (i.e. 660 = ``rw-rw---``). Make sure to set it in such + a way that your reverse proxy has permissions to access the UNIX domain + socket. The default (660) assumes that the reverse proxy is a member of + the group under which the exchange HTTP server is running. + +.. _ReverseProxy: + +Reverse Proxy Setup +------------------- + +By default, the ``taler-exchange-httpd`` service listens for HTTP connections +on a UNIX domain socket. To make the service publicly available, a reverse +proxy such as nginx should be used. We strongly recommend to configure nginx +to use TLS. + +The public URL that the exchange will be served under should +be put in ``/etc/taler/conf.d/exchange-business.conf`` configuration file. + +.. code-block:: ini + :caption: /etc/taler/conf.d/exchange-business.conf + + [exchange] + BASE_URL = https://example.com/ + + # ... rest of file ... + +The ``taler-exchange`` package ships with a sample configuration that can be +enabled in nginx: + +.. code-block:: shell-session + + [root@exchange-online]# vim /etc/nginx/sites-available/taler-exchange + < ... customize configuration ... > + [root@exchange-online]# ln -s /etc/nginx/sites-available/taler-exchange \ + /etc/nginx/sites-enabled/taler-exchange + [root@exchange-online]# systemctl reload nginx + +Note that the reverse proxy must set a HTTP ``X-Forwarded-Host`` header to +refer to the hostname used by nginx and a HTTP ``X-Forwarded-Proto`` header to +inform the exchange whether the external protocol was ``http`` or ``https``. +Thus, depending on your setup, you will likely have to edit those parts of the +provided ``taler-exchange`` configuration file. + +With this last step, we are finally ready to launch the +main exchange process. + +.. _Launch: + +Launching an exchange +--------------------- + +A running exchange requires starting the following processes: + +- ``taler-exchange-secmod-rsa`` (as special user, sharing group with the HTTPD) +- ``taler-exchange-secmod-cs`` (as special user, sharing group with the HTTPD) +- ``taler-exchange-secmod-eddsa`` (as special user, sharing group with the HTTPD) +- ``taler-exchange-httpd`` (needs database access) +- ``taler-exchange-aggregator`` (only needs database access) +- ``taler-exchange-closer`` (only needs database access) +- ``taler-exchange-wirewatch`` (needs bank account read credentials and database access) +- ``taler-exchange-transfer`` (needs credentials to initiate outgoing wire transfers and database access) + +The crypto helpers (``secmod``) must be started before the ``taler-exchange-httpd`` and +they should use the same configuration file. + +For the most secure deployment, we recommend using separate users for each of +these processes to minimize information disclosures should any of them be +compromised. The helpers do not need access to the PostgreSQL database (and +thus also should not have it). + +The processes that require access to the bank account need to have a +configuration file with the respective credentials in it. We recommend using a +separate configuration at least for ``taler-exchange-transfer`` which is the +*only* process that needs to know the credentials to execute outgoing wire +transfers. + +All of these processes should also be started via a hypervisor like +``systemd`` or ``gnunet-arm`` that automatically re-starts them should they +have terminated unexpectedly. If the bank is down (say for maintenance), it is +*possible* to halt the ``taler-exchange-wirewatch`` and/or +``taler-exchange-transfer`` processes (to avoid them making requests to the +bank API that can only fail) without impacting other operations of the +exchange. Naturally, incoming wire transfers will only be observed once +``taler-exchange-wirewatch`` is resumed, and merchants may complain if the +disabled ``taler-exchange-transfer`` process causes payment deadlines to be +missed. + +.. note:: + The ``taler-exchange-httpd`` does not ship with HTTPS enabled by default. + In production, it should be run behind an HTTPS reverse proxy that performs + TLS termination on the same system. Thus, it would typically be configured + to listen on a UNIX domain socket. The ``/management`` and ``/auditors`` + APIs do technically not have to be exposed on the Internet (only to the + administrators running ``taler-exchange-offline``) and should be blocked + by the reverse proxy for requests originating from outside of the bank. + (However, this is not a strong security assumption: in principle having + these endpoints available should do no harm. However, it increases the + attack surface.) + + +Given proper packaging, all of the above are realized via a simple systemd +target. This enables the various processes of an exchange service to be +started using a simple command: + +.. code-block:: shell-session + + [root@exchange-online]# systemctl start taler-exchange.target + +.. note:: + + At this point, the exchange service is not yet fully operational. + + +To check whether the exchange is running correctly under the advertized +base URL, run: + +.. code-block:: shell-session + + [root@exchange-online]# export BASE_URL=$(taler-config -s exchange -o base_url) + [root@exchange-online]# wget ${BASE_URL}management/keys + +The request might take some time to complete on slow machines, because +a lot of key material will be generated. + + +Offline Signing Setup, Key Maintenance and Tear-Down +==================================================== + +The exchange HTTP service must be running before you can complete the +following offline signing procedure. Note that when an exchange is running +without offline keys its not fully operational. To make the exchange HTTP +service fully operational, the following steps involving the offline signing +machine must be completed: + + 1. The public keys of various online keys used by the exchange service are exported + via a management HTTP API. + 2. The offline signing system validates this request and signs it. + Additionally, the offline signing system signs policy messages + to configure the exchange's bank accounts and associated fees. + 3. The messages generated by the offline signing system are uploaded + via the management API of the exchange HTTP service. + +A typical minimal setup would look something like this: + +.. code-block:: shell-session + + [anybody@exchange-online]# taler-exchange-offline \ + download > sig-request.json + + [root@exchange-offline]# taler-exchange-offline \ + sign < sig-request.json > sig-response.json + [root@exchange-offline]# taler-exchange-offline \ + enable-account payto://iban/$IBAN?receiver-name=$NAME > acct-response.json + [root@exchange-offline]# taler-exchange-offline \ + wire-fee now iban EUR:0 EUR:0 > fee-response.json + [root@exchange-offline]# taler-exchange-offline \ + global-fee now EUR:0 EUR:0 EUR:0 4w 6y 4 > global-response.json + + [anybody@exchange-online]# taler-exchange-offline upload < sig-response.json + [anybody@exchange-online]# taler-exchange-offline upload < acct-response.json + [anybody@exchange-online]# taler-exchange-offline upload < fee-response.json + [anybody@exchange-online]# taler-exchange-offline upload < global-response.json + +The following sections will discuss these steps in more depth. + +.. _Keys-generation: + +Signing the online signing keys +------------------------------- + +To sign the online signing keys, first the *future* key material should be downloaded using: + +.. code-block:: console + + $ taler-exchange-offline download > future-keys.json + +Afterwards, *future-keys.json* contains data about denomination and +online signing keys that the exchange operator needs to sign with +the offline tool. The file should be copied to the offline system. +There, the operator should run: + +.. code-block:: console + + $ taler-exchange-offline show < future-keys.json + +and verify that the output contains the fee structure and key lifetimes +they expect to see. They should also note the public keys being shown +and communicate those to the *auditors* over a secure channel. Once +they are convinced the file is acceptable, they should run: + +.. code-block:: console + + $ taler-exchange-offline sign < future-keys.json > offline-sigs.json + +The *offline-sigs.json* file must then be copied to an online system +that is able to again communicate with the exchange. On that system, run: + +.. code-block:: console + + $ taler-exchange-offline upload < offline-sigs.json + +to provision the signatures to the exchange. + +The ``download sign upload`` sequence in the commands above has to be done +periodically, as it signs the various online signing keys of the exchange +which periodically expire. + + +Account signing +--------------- + +The ``enable-account`` step is important to must be used to sign the +``payto://`` URI in a way suitable to convince wallets that this is the +correct address to wire funds to. Note that for each bank account, additional +options **must** be set in the configuration file to tell the exchange how to +access the bank account. The offline tool *only* configures the externally +visible portions of the setup. The chapter on `Bank account <_Bank-account>`_ configuration has further details. + +taler-exchange-offline accepts additional options to configure the use of the +account. For example, additional options can be used to add currency +conversion or to restrict interactions to bank accounts from certain +countries: + +.. code-block:: console + + $ taler-exchange-offline \ + enable-account payto://iban/CH9300762011623852957 + conversion-url https://conversion.example.com/ + +For details on optional ``enable-account`` arguments, +see :doc:`manpages/taler-exchange-offline.1`. + +.. _Wire-fee-structure: + +Wire fee structure +------------------ + +.. index:: wire fee +.. index:: fee + +For each wire method (“iban” or “x-taler-bank”) the +exchange must know about applicable wire fees. This is also done +using the ``taler-exchange-offline`` tool: + +.. code-block:: console + + $ taler-exchange-offline wire-fee 2040 iban EUR:0.05 EUR:0.10 + +The above sets the wire fees for wire transfers involving ``iban`` accounts +(in Euros) in the year 2040 to 5 cents (wire fee) and 10 cents (closing fee). +The tool only supports setting fees that applies for the entire calendar year. + +We recommend provisioning an exchange with wire fees at least for the next two +years. Note that once the fees have been set for a year, they cannot be +changed (basically, by signing the fees the exchange makes a legally binding +offer to the customers). + +.. index:: maintenance +.. note:: + Provisioning future wire fees, like provisioning future denomination + and signing keys, are key regular maintenance procedures for every + exchange operator. We recommend setting automated reminders for + this maintenance activity! + + +.. _Auditor-configuration: + +Auditor configuration +--------------------- + +At this point, the exchange will be able to use those keys, but wallets and +merchants may not yet trust them! Thus, the next step is for an auditor to +affirm that they are auditing this exchange. Before an auditor can do this, +the exchange service must be informed about any auditor that is expected to +provision it with auditor signatures. + +This is also done using the ``taler-exchange-offline`` tool on the offline +system. First, the auditor must be configured and provide the exchange +operator with its public key (using ``taler-auditor-offline setup``) and the +URL of it's REST API. The exchange operator also needs a human-readable name +that may be shown to users to identify the auditor. For more information on +how to setup and operate an auditor, see +:doc:`manpages/taler-auditor-offline.1` and :doc:`taler-auditor-manual`. + +Given this information, the exchange operator can enable the auditor: + +.. code-block:: console + + $ taler-exchange-offline enable-auditor $PUB_KEY $REST_URL "$AUDITOR_NAME" > auditor.json + +As before, the *auditor.json* file must then be copied from the offline system +to a system connected to the exchange and there ``uploaded`` to the exchange using ``taler-exchange-offline upload``. + + +.. _Revocations: + +Revocations +----------- When an exchange goes out of business or detects that the private key of a denomination key pair has been compromised, it may revoke some or all @@ -952,24 +1906,215 @@ of ``taler-exchange-offline``. under highly unusual (“emergency”) conditions and not in normal operation. -Testing a deployment -==================== +AML Configuration +----------------- + +The AML configuration steps are used to add or remove keys of exchange +operator staff that are responsible for anti-money laundering (AML) +compliance. These AML officers are shown suspicious transactions and are +granted access to the KYC data of an exchange. They can then investigate the +transaction and decide on freezing or permitting the transfer. They may also +request additional KYC data from the consumer and can change the threshold +amount above which a further AML review is triggered. + +AML Officer Setup +^^^^^^^^^^^^^^^^^ + +To begin the AML setup, AML staff should launch the GNU Taler +exchange AML SPA Web interface. (FIXME-Sebastian: how?). The +SPA will generate a public-private key pair and store it in the +local storage of the browser. The public key will be displayed +and must be securely transmitted to the offline system for +approval. Using the offline system, one can then configure +which staff has access to the AML operations: + +.. code-block:: shell-session + + [root@exchange-offline]# taler-exchange-offline \ + aml-enable $PUBLIC_KEY "Legal Name" rw > aml.json + [root@exchange-online]# taler-exchange-offline \ + upload < aml.json + +The above commands would add an AML officer with the given "Legal Name" with +read-write (rw) access to the AML officer database. Using "ro" instead of +"rw" would grant read-only access to the data, leaving out the ability to +actually make AML decisions. Once AML access has been granted, the AML +officer can use the SPA to review cases and (with "rw" access) take AML +decisions. + +Access rights can be revoked at any time using: + +.. code-block:: shell-session + + [root@exchange-offline]# taler-exchange-offline \ + aml-disable $PUBLIC_KEY "Legal Name" > aml-off.json + [root@exchange-online]# taler-exchange-offline \ + upload < aml-off.json + + +AML Triggers +^^^^^^^^^^^^ + +AML decision processes are automatically triggered under certain configurable +conditions. The primary condition that *must* be configured is the +``AML_THRESHOLD``: + +.. code-block:: ini + :caption: /etc/taler/conf.d/exchange-business.conf + + [exchange] + # Accounts or wallets with monthly transaction volumes above this threshold + # are considered suspicious and are automatically flagged for AML review + # and put on hold until an AML officer has reached a decision. + AML_THRESHOLD = "EUR:1000000" + +Additionally, certain KYC attributes (such as the user being a +politically exposed person) may lead to an account being +flagged for AML review. The specific logic is configured by +providing the exchange with an external helper program that +makes the decision given the KYC attributes: + +.. code-block:: ini + :caption: /etc/taler/conf.d/exchange-business.conf + + [exchange] + # Specifies a program to run on KYC attribute data to decide + # whether we should immediately flag an account for AML review. + KYC_AML_TRIGGER = taler-exchange-kyc-aml-pep-trigger.sh + +The given program will be given the KYC attributes in JSON format on standard +input, and must return 0 to continue without AML and non-zero to flag the +account for manual review. To disable this triger, simply leave the option to +its default value of '[/usr/bin/]true'. To flag all new users for manual +review, simply set the program to '[/usr/bin/]false'. + + + +Setup Linting +============= + +The ``taler-wallet-cli`` package comes with an experimental tool that runs various +checks on the current GNU Taler exchange deployment: + +.. code-block:: shell-session + + [root@exchange-online]# apt install taler-wallet-cli + [root@exchange-online]# taler-wallet-cli deployment lint-exchange + +You can optionally pass the ``--debug`` option to get more verbose output, and +``--continue`` to continue with further checks even though a previous one has +failed. + + +Testing and Troubleshooting +=========================== We recommend testing whether an exchange deployment is functional by using the Taler wallet command line interface. The tool can be used to withdraw and deposit electronic cash via the exchange without having to deploy and operate a -separate merchant backend and storefront. For more information, see -:doc:`taler-wallet-cli-manual`. +separate merchant backend and storefront. +The following shell session illustrates how the wallet can be used to withdraw +electronic cash from the exchange and subsequently spend it. For these steps, +a merchant backend is not required, as the wallet acts as a merchant. -.. _Diagnostics: +.. code-block:: shell-session -Diagnostics -=========== + # This will now output a payto URI that money needs to be sent to in order to allow withdrawal + # of taler coins. + $ taler-wallet-cli advanced withdraw-manually --exchange $EXCHANGE_URL --amount EUR:10.50 + + +Show the status of the manual withdrawal operation. + +.. code-block:: shell-session + + $ taler-wallet-cli transactions + +At this point, a bank transfer to the exchange's bank account +needs to be made with the correct subject / remittance information +as instructed by the wallet after the first step. With the +above configuration, it should take about 5 minutes after the +wire transfer for the incoming transfer to be observed by the +Nexus. + +Run the following command to check whether the exchange received +an incoming bank transfer: + +.. code-block:: shell-session + + [root@exchange-online]# taler-exchange-wire-gateway-client \ + --section exchange-accountcredentials-1 --credit-history + +Once the transfer has been made, try completing the withdrawal +using: + +.. code-block:: shell-session + + $ taler-wallet-cli run-pending + +Afterwards, check the status of transactions and show the +current wallet balance: + +.. code-block:: shell-session + + $ taler-wallet-cli transactions + $ taler-wallet-cli balance + + +Now, we can directly deposit coins via the exchange into a target +account. (Usually, a payment is made via a merchant. The wallet +provides this functionality for testing.) + +.. code-block:: shell-session + + $ taler-wallet-cli deposit create EUR:5 \ + payto://iban/$IBAN?receiver-name=Name + $ taler-wallet-cli run-pending + + +Check if this transaction was successful (from the perspective +of the wallet): + +.. code-block:: shell-session + + $ taler-wallet-cli transactions + +If the transaction failed, fix any open issue(s) with the exchange and +run the "run-pending" command. + +The wallet can also track if the exchange wired the money to the merchant +account. The "deposit group id" can be found in the output of the +transactions list. + +.. code-block:: shell-session + + $ taler-wallet-cli deposit track $DEPOSIT_GROUP_ID + +You can also check using the exchange-tools whether the exchange sent +the an outgoing transfer: + +.. code-block:: shell-session + + [root@exchange-online]# taler-exchange-wire-gateway-client \ + --section exchange-accountcredentials-1 --debit-history + +After enough time has passed, the money should arrive at the specified IBAN. + +For more information on the taler-wallet-cli tool, see +:doc:`taler-wallet`. + + +Private key storage +------------------- + +Keeping the private keys the helpers create secret is paramount. If the +private keys are lost, it is easy to provision fresh keys (with the help of +the auditor). Thus, we recommend that the private keys of the crypto helpers +are *not* backed up: in the rare event of a disk failure, they can be +regenerated. However, we do recommend using RAID (1+1 or 1+1+1) for all +disks of the system. -This chapter includes various sections on specific topics that might be -helpful to understand how the exchange operates. The information may also be -helpful for diagnostics. .. _Internal-audit: @@ -1014,7 +2159,28 @@ allowing administrators to purge records that are no longer required. The database scheme used by the exchange looks as follows: -.. image:: exchange-db.png +.. image:: images/exchange-db.png + + +.. _Database-upgrades: + +Database upgrades +----------------- + +Currently, there is no way to upgrade the database between Taler +versions. + +The exchange database can be re-initialized using: + +.. code-block:: console + + $ taler-exchange-dbinit --reset + +However, running this command will result in all data in the database +being lost, which may result in significant financial liabilities as the +exchange can then not detect double-spending. Hence this operation must +not be performed in a production system. + .. _ExchangeBenchmarking: @@ -1022,62 +2188,164 @@ The database scheme used by the exchange looks as follows: Benchmarking ============ -This chapter describes how to run the Taler exchange benchmark. The benchmark -can be used to measure the performance of the exchange by running a (possibly -large) number of simulated clients against one Taler deployment with a bank, -exchange and auditor. For the bank, both a "fakebank" (``-f``) and a -"Pythonbank" deployment are currently supported. The -``taler-exchange-benchmark`` program can launch all required services and -clients, or only launch the parallel clients (``-m``), for example for -distributed testing over a network. - -For each *parallel* (``-p``) client, a number of *reserves* (``-r``) is first established by -**transferring** money from a "user" account (42) to the Exchange's account -with the respective reserve public key as wire subject. Next, the -client will **withdraw** a *number of coins* (``-n``) from the reserve and -**deposit** them. Additionally, a *fraction* (``-R``) of the dirty coins will then be -subject to **refreshing**. For some deposits, the auditor will receive -**deposit confirmations**. - -Operations that are not covered today include closing reserves, refunds and -recoups. - -The existing ``benchmark.conf`` file in ``src/benchmark/`` can be used as a -starting point for a configuration to run the benchmark. The existing -configuration file only requires that the ``talercheck`` database already -exists and will launch all required services locally as needed. - -You can run a first simple benchmark using: +This chapter describes how to run various benchmarks against a Taler exchange. +These benchmark can be used to measure the performance of the exchange by +running a (possibly large) number of simulated clients against one Taler +deployment with a bank, exchange and (optionally) auditor. + +Real benchmarks that are intended to demonstrate the scalability of GNU Taler +should not use the tools presented in this section: they may be suitable for +microbenchmarking and tuning, but the setup is inherently not optimzied for +performance or realism, both for the load generation and the server side. +Thus, we do not recommend using these performance numbers to assess the +scalability of GNU Taler. That said, the tools can be useful to help identify +performance issues. + +The ``taler-unified-setup.sh`` script can be used to launch all required +services and clients. However, the resulting deployment is simplistic +(everything on the local machine, one single-threaded process per service +type) and not optimized for performance at all. However, this can still be +useful to assess the performance impact of changes +to the code or configuration. + +The various configuration files used in the code snippets in this section can +be found in the ``src/benchmark/`` directory of the exchange. These are +generally intended as starting points. Note that the configuration files +ending in ``.edited`` are created by ``taler-unified-setup.sh`` and contain +some options that are determined at runtime by the setup logic provided by +``taler-unified-setup.sh``. + + +.. _Benchmark-choose-bank: + +Choosing a bank +--------------- -.. note:: - FIXME-TTN/CG: these instructions are incomplete and untested for the - current iteration of the code... +For the bank, both a fakebank (``-f``) and libeufin-based (``-ns``) +bank deployment are currently supported by all benchmark tools and +configuration templates. + +Fakebank is an ultra-fast in-memory implementation of the Taler bank API. It +is suitable when the goal is to benchmark the core GNU Taler payment system +and to ignore the real-time gross settlement (RTGS) system typically provided +by an existing bank. When using the fakebank, ``taler-unified-setup.sh`` must +be started with the ``-f`` option and be told to use the right exchange bank +account from the configuration files via ``-u exchange-account-1``. + +.. code-block:: console + + $ dropdb talercheck; createdb talercheck + $ taler-unified-setup.sh -emwt -c $CONF -f -u exchange-account-1 + + +libeufin is GNU Taler's adapter to the core banking system using the EBICS +banking protocol standard. It uses a Postgres database to persist data and is +thus much slower than fakebank. If your GNU Taler deployment uses libeufin in +production, it likely makes sense to benchmark with libeufin. When using the +fakebank, ``taler-unified-setup.sh`` must be started with the ``-ns`` options +(starting libeufin-nexus and libeufin-sandbox) and be told to use the right +exchange bank account from the configuration files via ``-u +exchange-account-2``. Note that ``taler-unified-setup.sh`` currently cannot +reset a libeufin database, and also will not run if the database is already +initialized. Thus, you must re-create the database every time before +running the command: .. code-block:: console - $ createdb talercheck # if it does not yet exist - $ taler-exchange-dbinit -c benchmark.conf - $ taler-exchange-httpd -c benchmark.conf & - $ HTTPD_PID=$! - $ taler-exchange-offline -c benchmark.conf \ - download sign \ - enable-account payto://iban/CH9300762011623852957 \ - wire-fee iban EUR:0 EUR:0 EUR:0 \ - global-fee EUR:0 EUR:0 EUR:0 EUR:0 4w 4w 6y 4 \ - upload - $ kill -TERM $HTTPD_PID - $ taler-exchange-benchmark -c benchmark.conf -p 4 -r 1 -n 10 - -This will run 4 parallel clients withdrawing 10 coins from 1 reserve and then -depositing those coins. The default refresh probability is 10 percent. Note -that the tiny run should only take a few seconds, most of it will be spent in -the setup of the original key material. For meaningful runs, all three values -should likely be increased. + $ dropdb talercheck; createdb talercheck + $ taler-unified-setup.sh -emwt -c $CONF -ns -u exchange-account-2 + + +taler-bank-benchmark +-------------------- + +This is the simplest benchmarking tool, simulating only the bank +interaction. + +.. code-block:: console + + $ CONF="benchmark-cs.conf" + $ # or with libeufin + $ dropdb talercheck; createdb talercheck + $ taler-unified-setup.sh -emwt -c "$CONF" -f -u exchange-account-1 + $ # Once <<READY>>, in another shell (remember to set $CONF): + $ time taler-bank-benchmark -c "$CONF" -r 40 -p 4 -P4 -u exchange-account-1 -f + $ # or with libeufin + $ dropdb talercheck; createdb talercheck + $ taler-unified-setup.sh -emwt -c "$CONF" -ns -u exchange-account-2 + $ # Once <<READY>>, in another shell (remember to set $CONF): + $ time taler-bank-benchmark -c "$CONF" -r 40 -p 1 -P1 -u exchange-account-2 + +For each *parallel* (``-p``) client, a number of *reserves* (``-r``) is first +established by **transferring** money from a "user" account (42) to the +Exchange's account with the respective reserve public key as wire subject. +Processing is then handled by *parallel* (``-P``) service workers. + + +taler-exchange-benchmark +------------------------ + +This is the benchmarking tool simulates a number of clients withdrawing, +depositing and refreshing coins. Operations that are not covered by the +``taler-exchange-benchmark`` tool today include closing reserves, refunds, +recoups and P2P payments. + +.. code-block:: console + + $ CONF="benchmark-cs.conf" # -rsa also makes sense + $ # With fakebank + $ dropdb talercheck; createdb talercheck + $ taler-unified-setup.sh -aemwt -c "$CONF" -f -u exchange-account-1 + $ # Once <<READY>>, in another shell (remember to set $CONF): + $ taler-exchange-benchmark -c "$CONF".edited -u exchange-account-1 -n 1 -p1 -r 5 -f + $ # + $ # With libeufin + $ dropdb talercheck; createdb talercheck + $ taler-unified-setup.sh -aemwt -c "$CONF" -ns -u exchange-account-2 + $ # Once <<READY>>, in another shell (remember to set $CONF): + $ taler-exchange-benchmark -c "$CONF".edited -u exchange-account-2 -L WARNING -n 1 -p1 -r 5 + +For each *parallel* (``-p``) client, a number of *reserves* (``-r``) is first +established by **transferring** money from a "user" account (42) to the +Exchange's account with the respective reserve public key as wire subject. +Next, the client will **withdraw** a *number of coins* (``-n``) from the +reserve and **deposit** them. Additionally, a *fraction* (``-R``) of the dirty +coins will then be subject to **refreshing**. For some deposits, the auditor +will receive **deposit confirmations**. The output of ``taler-exchange-benchmark`` will include for each parallel client the total time spent in each of the major operations, possible repetitions (i.e. if the operation failed the first time), total execution time (operating system and user space) and other details. -Naturally, additional instrumentation (including using features of the -PostgreSQL database itself) may help discover performance issues. + +taler-aggregator-benchmark +-------------------------- + +This is another simple benchmark tool that merely prepares an exchange +database to run a stand-alone benchmark of the ``taler-exchange-aggregator`` +tool. After preparing a database and running the tool, you can then +run one or more ``taler-exchange-aggregator`` processes and measure how +quickly they perform the aggregation work. + +.. code-block:: console + + $ CONF=benchmark-rsa.conf + $ taler-exchange-dbinit -c "$CONF" --reset + $ ./taler-aggregator-benchmark -c "$CONF" -m 500 -r 10 -d 100 + $ time taler-exchange-aggregator -c "$CONF" --test + +This above commands will first create 100 deposits with 10 refunds into each +of 500 merchant accounts using randomized time stamps. Afterwards, it will +time a single aggregator process in ``--test`` mode (asking it to terminate +as soon as there is no more pending work). + + +FIXMEs +====== + +* We should have some summary with the inventory of services that should be + running. Systemd by default doesn't show this nicely. Maybe suggest running + "systemd list-dependencies taler-exchange.target"? +* What happens when the TWG doesn't like one particular outgoing transaction? + How to recover from that as a sysadmin when it happens in practice? diff --git a/taler-exchange-setup-guide.rst b/taler-exchange-setup-guide.rst @@ -1,950 +0,0 @@ -.. - This file is part of GNU Taler. - - Copyright (C) 2021-2023 Taler Systems SA - - GNU Taler 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 2.1, or (at your option) any later version. - - GNU Taler 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 - GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - - @author Florian Dold - -GNU Taler Exchange Setup Guide -############################## - -This setup guide walks a system administrator through all steps required to -install an exchange and check that it is functional. For more background, -please read the :doc:`Operator Manual <taler-exchange-manual>`. - - -System Requirements -=================== - -This guide assumes that you are running Ubuntu 20.04 (Focal Fossa). - -We recommend the setup of offline signing keys to be done on a second machine that -does not have Internet access. - -In this guide's shell-session fragments, the command prompt shows two pieces -of information: - -* Who is performing the command - (``$user`` vs ``root``, and ending character ``$`` vs ``#``). -* Host where the command is supposed to be executed - (``exchange-offline`` vs ``exchange-online``). - It is possible to do the entire setup on one machine, - but we do not recommend this for security reasons. - - -Before you start -================ - -To deploy this with a real bank, you need: - -* IBAN of the bank account to use -* BIC of the bank -* EBICS host, user and partner IDs - -Information to write down during the installation: - -* LibEuFin Nexus superuser password -* Taler facade base URL -* exchange Nexus username and password - - - -Installation -============ - -Please see the chapter on `exchange installation <ExchangeInstallation>`_ for -various ways to install a GNU Taler exchange. - -Note that it is possible to run the HTTPS reverse proxy or -the PostgreSQL database on yet another host, but in these instructions we will -assume that only two hosts are used. Note that in addition to the exchange -you will thus need to install an HTTPS reverse proxy and the database: - -.. code-block:: shell-session - - [root@exchange-online]# apt-get update - [root@exchange-online]# apt-get install -y nginx postgresql - - -Configuration Basics -==================== - -The configuration for all Taler components uses a single configuration file -as entry point: ``/etc/taler/taler.conf``. - -System defaults are automatically loaded from files in -``/usr/share/taler/config.d``. These default files should never be modified. - -The default configuration ``taler.conf`` configuration file also includes all -configuration files in ``/etc/taler/conf.d``. The settings from files in -``conf.d`` are only relevant to particular components of Taler, while -``taler.conf`` contains settings that affect all components. - - -The directory ``/etc/taler/secrets`` contains configuration file snippets with -values that should only be readable to certain users. They are included with the ``@inline-secret@`` -directive and should end with ``.secret.conf``. - -To view the entire configuration annotated with the source of each configuration option, you -can use the ``taler-config`` helper: - - -.. code-block:: shell-session - - [root@exchange-online]# taler-config --diagnostics - < ... annotated, full configuration ... > - -.. warning:: - - While ``taler-config`` also supports rewriting configuration files, we strongly - recommend to edit configuration files manually, as ``taler-config`` does not - preserve comments and, by default, rewrites ``/etc/taler/taler.conf``. - - -Services, users, groups and file system hierarchy -================================================= - -The *taler-exchange* package will create several system users -to compartmentalize different parts of the system: - -* ``taler-exchange-httpd``: runs the HTTP daemon with the core business logic. -* ``taler-exchange-secmod-rsa``: manages the RSA private online signing keys. -* ``taler-exchange-secmod-eddsa``: manages the EdDSA private online signing keys. -* ``taler-exchange-closer``: closes idle reserves by triggering wire transfers that refund the originator. -* ``taler-exchange-aggregator``: aggregates deposits into larger wire transfer requests. -* ``taler-exchange-wire``: performs wire transfers with the bank (via LibEuFin/Nexus). -* ``postgres``: runs the PostgreSQL database (from *postgresql* package). -* ``www-data``: runs the frontend HTTPS service with the TLS keys (from *nginx* package). - -.. note:: - - The *taler-merchant* package additionally creates a ``taler-merchant-httpd`` user - to run the HTTP daemon with the merchant business logic. - - -The exchange setup uses the following system groups: - -* ``taler-exchange-db``: group for all Taler users with direct database access, specifically taler-exchange-httpd, taler-exchange-wire, taler-exchange-closer and taler-exchange-aggregator. -* ``taler-exchange-secmod``: group for processes with access to online signing keys; this group must have three users: taler-exchange-secmod-rsa, taler-exchange-secmod-eddsa and taler-exchange-httpd. -* ``taler-exchange-offline``: group for the access to the offline private key (only used on the offline host and not used on the online system). - - - -The package will deploy systemd service files in -``/usr/lib/systemd/system/`` for the various components: - -* ``taler-exchange-aggregator.service``: service that schedules wire transfers - which combine multiple deposits to the same merchant. -* ``taler-exchange-closer.service``: service that watches for reserves that have been abandoned and schedules wire transfers to send the money back to the originator. -* ``taler-exchange-httpd.service``: main Taler exchange logic with the public REST API. -* ``taler-exchange-httpd.socket``: systemd socket activation for the Taler exchange HTTP daemon. -* ``taler-exchange-secmod-eddsa.service``: software security module for making EdDSA signatures. -* ``taler-exchange-secmod-rsa.service``: software security module for making RSA signatures. -* ``taler-exchange-transfer.service``: service that triggers outgoing wire transfers (pays merchants). -* ``taler-exchange-wirewatch.service``: service that watches for incoming wire transfers (first step of withdraw). -* ``taler-exchange.target``: Main target for the Taler exchange to be operational. - - -The deployment creates the following key locations in the system: - -* ``/etc/taler/``: configuration files. -* ``/run/taler/``: contains the UNIX domain sockets for inter-process communication (IPC). -* ``/var/lib/taler/``: serves as the $HOME for all Taler users and contains sub-directories - with the private keys; which keys are stored here depends on the host: - - * online system: exchange-secmod-eddsa and exchange-secmod-rsa keys. - * offline system: exchange-offline keys. - - -Setup Linting -============= - -The ``taler-wallet-cli`` package comes with an experimental tool that runs various -checks on the current GNU Taler exchange deployment: - -.. code-block:: shell-session - - [root@exchange-online]# apt install taler-wallet-cli - [root@exchange-online]# taler-wallet-cli deployment lint-exchange - -You can optionally pass the ``--debug`` option to get more verbose output, and -``--continue`` to continue with further checks even though a previous one has -failed. - -Basic Setup: Currency and Denominations -======================================= - -A Taler exchange only supports a single currency. The currency -and the smallest currency unit supported by the bank system -must be specified in ``/etc/taler/taler.conf``. - -.. code-block:: ini - :caption: /etc/taler/taler.conf - - [taler] - CURRENCY = EUR - CURRENCY_ROUND_UNIT = EUR:0.01 - - # ... rest of file ... - -.. warning:: - - When editing ``/etc/taler/taler.conf``, take care to not accidentally remove - the ``@inline-matching@`` directive to include the configuration files in ``conf.d``. - -Next, the electronic cash denominations that the exchange offers must be -specified. The ``taler-wallet-cli`` has a helper command that generates a -reasonable denomination structure. - -.. code-block:: shell-session - - [root@exchange-online]# taler-wallet-cli deployment gen-coin-config \ - --min-amount EUR:0.01 \ - --max-amount EUR:100 \ - > /etc/taler/conf.d/exchange-coins.conf - -You can manually review and edit the generated configuration file. The main -change that is possibly required is updating the various fees. - - -Wire Gateway Setup -================== - -The Taler Wire Gateway is an API that connects the Taler exchange to -the underlying core banking system. - -LibEuFin is an implementation of the Wire Gateway API for the EBICS protocol. -This section will walk through (1) installing and configuring LibEuFin and -(2) connecting the Taler Exchange to LibEuFin. - -.. note:: - - If you do not have a bank account with EBICS but want to test these instructions, - you can use the EBICS sandbox as described in the - :doc:`LibEuFin Tutorial <libeufin/nexus-tutorial>`. - - -Installation and Basic Configuration ------------------------------------- - -First, install the ``libeufin`` package. This can be done on the ``exchange-online`` -machine or a different one. - -.. code-block:: shell-session - - [root@exchange-online]# apt-get install -y libeufin - -The main component of LibEuFin is called the Nexus. It implements a Web -service that provides a JSON abstraction layer to access bank accounts. - -The HTTP port and database connection string can be edited in the configuration: - -.. code-block:: ini - :caption: /etc/libeufin/nexus.env - - LIBEUFIN_NEXUS_PORT=5017 - LIBEUFIN_NEXUS_DB_CONNECTION=jdbc:sqlite:/var/lib/libeufin/nexus/nexus-db.sqlite3 - -After configuring the database, you can start the service. -The database is initialized automatically. - - -.. code-block:: shell-session - - [root@exchange-online]# systemctl enable libeufin-nexus - [root@exchange-online]# systemctl start libeufin-nexus - -You can now create a superuser account. The command to -create the superuser needs direct database access, thus -the configuration file is sourced first, and the relevant -environment variable is exported. - -.. code-block:: console - - [root@exchange-online]# source /etc/libeufin/nexus.env - [root@exchange-online]# export LIBEUFIN_NEXUS_DB_CONNECTION - [root@exchange-online]# NEXUS_ADMIN_PW=$(tr -dc A-Za-z0-9 </dev/urandom | head -c 13) - [root@exchange-online]# libeufin-nexus superuser admin --password $NEXUS_ADMIN_PW - -If you omit ``--password $NEXUS_ADMIN_PW``, you will interactively be asked for a password. -For simplicity, a superuser can as well act as a normal user, but an API -to create less privileged users is offered. - -.. note:: - - User and permissions management in LibEuFin is still under development. - In particular, permissions for non-superusers are very limited at the moment. - - -Connecting Nexus with an EBICS account --------------------------------------- - -The command line interface of the LibEuFin Nexus needs the following three -values to be defined in the environment: ``LIBEUFIN_NEXUS_URL``, -``LIBEUFIN_NEXUS_USERNAME``, and ``LIBEUFIN_NEXUS_PASSWORD``. In this example, -``LIBEUFIN_NEXUS_USERNAME`` should be set to ``admin``, and -``LIBEUFIN_NEXUS_PASSWORD`` to the value hold in ``NEXUS_ADMIN_PW`` from the -previous step (the ``libeufin-nexus superuser`` command). The -``LIBEUFIN_NEXUS_URL`` could be given as ``http://localhost:5017/``. - -Next, we create a EBICS *bank connection* that Nexus can use to communicate with the bank. - -.. code-block:: console - - [root@exchange-online]# libeufin-cli \ - connections \ - new-ebics-connection \ - --ebics-url $EBICS_BASE_URL \ - --host-id $EBICS_HOST_ID \ - --partner-id $EBICS_PARTNER_ID \ - --ebics-user-id $EBICS_USER_ID \ - $CONNECTION_NAME - -If this step executes correctly, Nexus will have created all the cryptographic -material that is needed on the client side; in this EBICS example, it created -the signature and identification keys. It is therefore advisable to *make -a backup copy* of such keys. - -.. code-block:: console - - [root@exchange-online]# libeufin-cli \ - connections \ - export-backup \ - --passphrase $SECRET \ - --output-file $BACKUP_FILE \ - $CONNECTION_NAME - -At this point, Nexus needs to both communicate its keys to the bank, and -download the bank's keys. This synchronization happens through the INI, HIA, and -finally, HPB message types. - -After the electronic synchronization, the subscriber must confirm their keys -by sending a physical mail to the bank. The following command helps generating -such letter: - -.. code-block:: console - - [root@exchange-online]# libeufin-cli connections get-key-letter $CONNECTION_NAME out.pdf - -.. code-block:: console - - [root@exchange-online]# libeufin-cli \ - connections \ - connect \ - $CONNECTION_NAME - -.. - FIXME: Maybe is not 100% clear that 'connecting' means exchanging keys - with the bank? - -Once the connection is synchronized, Nexus needs to import locally the data -corresponding to the bank accounts offered by the bank connection just made. -The command below downloads the list of the bank accounts offered by ``$CONNECTION_NAME``. - -.. code-block:: console - - [root@exchange-online]# libeufin-cli \ - connections \ - download-bank-accounts \ - $CONNECTION_NAME - -It is now possible to list the accounts offered by the connection. - -.. code-block:: console - - [root@exchange-online]# libeufin-cli \ - connections \ - list-offered-bank-accounts \ - $CONNECTION_NAME - -.. note:: - - The ``nexusBankAccountId`` field should at this step be ``null``, - as we have not yet imported the bank account and thus the account - does not yet have a local name. - -Nexus now needs an explicit import of the accounts it should manage. This -step is needed to let the user pick a custom name for such accounts. - -.. code-block:: console - - [root@exchange-online]# libeufin-cli \ - connections \ - import-bank-account \ - --offered-account-id testacct01 \ - --nexus-bank-account-id $LOCAL_ACCOUNT_NAME \ - $CONNECTION_NAME - -Once a Nexus user imported a bank account (``$LOCAL_ACCOUNT_NAME``) -under a certain connection (``$CONNECTION_NAME``), it is possible -to accomplish the usual operations for any bank account: asking for the -list of transactions, and making a payment. - -Testing: Requesting the transaction history -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The LibEuFin Nexus keeps a local copy of the bank account's transaction -history. Before querying transactions locally, it is necessary -to request transactions for the bank account via the bank connection. - -This command asks Nexus to download the latest transaction reports/statements -through the bank connection: - -.. code-block:: console - - [root@exchange-online]# libeufin-cli accounts fetch-transactions $LOCAL_ACCOUNT_NAME - -.. note:: - - By default, the latest available transactions are fetched. It is also - possible to specify a custom date range (or even all available transactions) - and the type of transactions to fetch (inter-day statements or intra-day - reports). - -.. - FIXME: Possibly the date range filter is still missing, see #6243. - -Once Nexus has stored all the information in the database, the -client can ask to actually see the transactions: - -.. code-block:: console - - [root@exchange-online]# libeufin-cli accounts transactions $LOCAL_ACCOUNT_NAME - -Testing: Making payments -~~~~~~~~~~~~~~~~~~~~~~~~ - -Payments pass through two phases: preparation and submission. The preparation -phase assigns the payment initiation a unique ID, which prevents accidental -double submissions of payments in case of network failures or other -disruptions. - - -The following command prepares a payment: - -.. code-block:: console - - [root@exchange-online]# libeufin-cli accounts prepare-payment \ - --creditor-iban=$IBAN_TO_SEND_MONEY_TO \ - --creditor-bic=$BIC_TO_SEND_MONEY_TO \ - --creditor-name=$CREDITOR_NAME \ - --payment-amount=$AMOUNT \ - --payment-subject=$SUBJECT \ - $LOCAL_ACCOUNT_NAME - -Note: the ``$AMOUNT`` value needs the format ``X.Y:CURRENCY``; for example -``EUR:10``, or ``EUR:1.01``. - -The previous command should return a value (``$UUID``) that uniquely -identifies the prepared payment in the Nexus system. That is needed -in the next step, to **send the payment instructions to the bank**: - -.. code-block:: console - - [root@exchange-online]# libeufin-cli accounts submit-payments \ - --payment-uuid $UUID \ - $LOCAL_ACCOUNT_NAME - -Automatic scheduling -~~~~~~~~~~~~~~~~~~~~ - -With an EBICS bank connection, the LibEuFin Nexus needs to regularly query for -new transactions and (re-)submit prepared payments. - -It is possible to schedule these tasks via an external task scheduler such as -cron(8). However, the nexus also has an internal task scheduling mechanism for -accounts. - - -The following three commands create a schedule for submitting payments hourly, -fetching transactions (intra-day reports) every 5 minutes, and (inter-day statements) -once at 11pm every day: - -.. code-block:: console - - [root@exchange-online]# libeufin-cli accounts task-schedule $LOCAL_ACCOUNT_NAME \ - --task-type="submit" \ - --task-name='submit-payments-hourly' \ - --task-cronspec='0 0 *' - - [root@exchange-online]# libeufin-cli accounts task-schedule $LOCAL_ACCOUNT_NAME \ - --task-type="fetch" \ - --task-name='fetch-5min' \ - --task-cronspec='0 */5 *' \ - --task-param-level=report \ - --task-param-range-type=latest - - [root@exchange-online]# libeufin-cli accounts task-schedule $LOCAL_ACCOUNT_NAME \ - --task-type="fetch" \ - --task-name='fetch-daily' \ - --task-cronspec='0 0 23' \ - --task-param-level=statement \ - --task-param-range-type=latest - -The cronspec has the following format, which is slightly non-standard due to -the ``SECONDS`` field - -.. code-block:: none - - SECONDS MINUTES HOURS DAY-OF-MONTH[optional] MONTH[optional] DAY-OF-WEEK[optional] - - -Creating a Taler facade -~~~~~~~~~~~~~~~~~~~~~~~ - -Facades are additional abstraction layers that can serve -specific purposes. For example, one application might need -a filtered version of the transaction history, or it might -want to refuse payments that do not conform to certain rules. - -At this moment, only the *Taler facade type* is implemented -in the Nexus, and the command below instantiates one under a -existing bank account / connection pair. You can freely -assign an identifier for the ``$FACADE_NAME`` below: - -.. code-block:: console - - [root@exchange-online]# libeufin-cli facades new-taler-wire-gateway-facade \ - --currency EUR \ - --facade-name $FACADE_NAME \ - $CONNECTION_NAME \ - $LOCAL_ACCOUNT_NAME - -At this point, the additional :doc:`taler-wire-gateway API <core/api-wire>` -becomes offered by the Nexus. The purpose is to let a Taler exchange rely on -Nexus to manage its bank account. - -The base URL of the facade that can be used by the Taler exchange -as the Taler Wire Gateway base URL can be seen by listing the facades: - -.. code-block:: console - - [root@exchange-online]# libeufin-cli facades list - -Managing Permissions and Users -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -This guide has so far assumed that a superuser is accessing the LibEuFin Nexus. -However, it is advisable that the Nexus is accessed with users that only have a -minimal set of permissions. - -The Nexus currently only has support for giving non-superusers access to Taler -wire gateway facades. - -To create a new user, use the ``users`` subcommand of the CLI: - -.. code-block:: console - - [root@exchange-online]# libeufin-cli users list - # [ ... shows available users ... ] - - [root@exchange-online]# libeufin-cli users create $USERNAME - # [ ... will prompt for password ... ] - -Permissions are managed with the ``permissions`` subcommand. -The following commands grant permissions to view the transaction history -and create payment initiations with a Taler wire gateway facade: - - -.. code-block:: console - - [root@exchange-online]# libeufin-cli permissions grant \ - user $USERNAME \ - facade $FACADENAME \ - facade.talerwiregateway.history - - [root@exchange-online]# libeufin-cli permissions grant \ - user $USERNAME \ - facade $FACADENAME \ - facade.talerwiregateway.transfer - -.. - FIXME: The two commands above output an empty JSON object - when successful. Possibly, we should suppress that (just like - the other commands do). - -The list of all granted permissions can be reviewed: - -.. code-block:: console - - [root@exchange-online]# libeufin-cli permissions list - - -Exchange Wire Configuration ---------------------------- - -The exchange must be configured with the right settings to -access the Taler Wire Gateway. An exchange can be configured -to use multiple bank accounts by using multiple Wire Gateways. -Typically only one Wire Gateway is used. - -A Taler Wire Gateway is configured in a configuration section that follows the -pattern ``exchange-account-$id``, where ``$id`` is an internal identifier for -the bank account accessed by the exchange. The basic information for an account should -be put in ``/etc/taler/conf.d/exchange-business.conf``. -The secret credentials to access the Taler Wire Gateway API should -be put into a corresponding ``exchange-accountcredentials-$id`` section -in ``/etc/taler/secrets/exchange-accountcredentials.conf``. -The latter file -should already be only readable for the ``taler-exchange-wire`` user. Other -exchange processes should not have access to this information. - -.. code-block:: ini - :caption: /etc/taler/conf.d/exchange-business.conf - - [exchange-account-1] - enable_credit = yes - enable_debit = yes - - # Account identifier in the form of an RFC-8905 payto:// URI. - # For SEPA, looks like payto://iban/$IBAN?receiver-name=$NAME - # Make sure to URL-encode spaces in $NAME! - payto_uri = - - @inline-secret@ exchange-accountcredentials-1 ../secrets/exchange-accountcredentials.secret.conf - - -.. code-block:: ini - :caption: /etc/taler/secrets/exchange-accountcredentials.secret.conf - - [exchange-accountcredentials-1] - - # LibEuFin expects basic auth. - wire_gateway_auth_method = basic - - # Username and password set in LibEuFin. - username = ... - password = ... - - # Base URL of the wire gateway set up with LibEuFin. - wire_gateway_url = ... - - -The Wire Gateway configuration can be tested with the following command: - -.. code-block:: shell-session - - [root@exchange-online]# taler-exchange-wire-gateway-client \ - --section exchange-accountcredentials-1 --debit-history - [root@exchange-online]# taler-exchange-wire-gateway-client \ - --section exchange-accountcredentials-1 --credit-history - - - -Exchange Database Setup -======================= - -The access credentials for the exchange's database are configured in -``/etc/taler/secrets/exchange-db.secret.conf``. Currently, only PostgreSQL is -supported as a database backend. - -The following users must have access to the exchange database: - -* taler-exchange-httpd -* taler-exchange-wire -* taler-exchange-aggregator -* taler-exchange-closer - -These users are all in the taler-exchange-db group, and the -``exchange-db.secret.conf`` should already be only readable by users in -this group. - -To create a database for the Taler exchange on the local system, run: - -.. code-block:: shell-session - - [root@exchange-online]# su - postgres - [postgres@exchange-online]# createuser taler-exchange-httpd - [postgres@exchange-online]# createuser taler-exchange-wire - [postgres@exchange-online]# createuser taler-exchange-aggregator - [postgres@exchange-online]# createuser taler-exchange-closer - [postgres@exchange-online]# createdb -O taler-exchange-httpd taler-exchange - [postgres@exchange-online]# exit - -This will create a ``taler-exchange`` database owned by the -``taler-exchange-httpd`` user. We will use that user later to perform -database maintenance operations. - - -Assuming the above database setup, the database credentials to configure -in the configuration file would simply be: - -.. code-block:: ini - :caption: /etc/taler/secrets/exchange-db.secret.conf - - [exchangedb-postgres] - CONFIG=postgres:///taler-exchange - - -If the database is run on a different host, please follow the instructions -from the PostgreSQL manual for configuring remote access. - -After configuring the database credentials, the exchange database needs -to be initialized with the following command: - -.. code-block:: shell-session - - [root@exchange-online]# sudo -u taler-exchange-httpd taler-exchange-dbinit - -Finally we need to grant the other accounts limited access: - -.. code-block:: shell-session - - [root@exchange-online]# sudo -u taler-exchange-httpd bash - [taler-exchange-httpd@exchange-online]# echo 'GRANT SELECT,INSERT,UPDATE ON ALL TABLES IN SCHEMA public TO "taler-exchange-aggregator";' \ - | psql taler-exchange - [taler-exchange-httpd@exchange-online]# echo 'GRANT SELECT,INSERT,UPDATE ON ALL TABLES IN SCHEMA public TO "taler-exchange-closer";' \ - | psql taler-exchange - [taler-exchange-httpd@exchange-online]# echo 'GRANT SELECT,INSERT,UPDATE ON ALL TABLES IN SCHEMA public TO "taler-exchange-wire";' \ - | psql taler-exchange - [taler-exchange-httpd@exchange-online]# echo 'GRANT USAGE ON ALL SEQUENCES IN SCHEMA public TO "taler-exchange-aggregator";' \ - | psql taler-exchange - [taler-exchange-httpd@exchange-online]# echo 'GRANT USAGE ON ALL SEQUENCES IN SCHEMA public TO "taler-exchange-closer";' \ - | psql taler-exchange - [taler-exchange-httpd@exchange-online]# echo 'GRANT USAGE ON ALL SEQUENCES IN SCHEMA public TO "taler-exchange-wire";' \ - | psql taler-exchange - [taler-exchange-httpd@exchange-online]# exit - -.. note:: - - The above instructions for changing database permissions only work *after* - having initialized the database with ``taler-exchange-dbinit``, as - the tables to exist before permissions can be granted on them. The - ``taler-exchange-dbinit`` tool cannot setup these permissions, as it - does not know which users will be used for which processes. - - -Offline Signing Setup -===================== - -The offline signing keys of the exchange should be stored on a different machine. -The responsibilities of this offline signing machine are: - -* Generation of the exchange's offline master signing key. -* Secure storage of the exchange's offline master signing key. -* Generation of certificates (signed with the offline master signing key) that will be imported by the exchange. - - -.. code-block:: shell-session - - [root@exchange-offline]# sudo -u taler-exchange-offline taler-exchange-offline setup - < ... prints the exchange master public key > - -The public key printed as the output of this command must be put into the configuration -of the online machine: - -.. code-block:: ini - :caption: /etc/taler/conf.d/exchange-business.conf - - [exchange] - MASTER_PUBLIC_KEY = YE6Q6TR1ED... - - # ... rest of file ... - - -Exchange Web service / API Setup -================================ - -By default, the ``taler-exchange-httpd`` service listens for HTTP connections -on a UNIX domain socket. To make the service publicly available, a reverse -proxy such as nginx should be used. We strongly recommend to configure nginx -to use TLS. - -The public URL that the exchange will be served under should -be put in ``/etc/taler/conf.d/exchange-business.conf`` configuration file. - -.. code-block:: ini - :caption: /etc/taler/conf.d/exchange-business.conf - - [exchange] - BASE_URL = https://example.com/ - - # ... rest of file ... - -The ``taler-exchange`` package ships with a sample configuration that can be -enabled in nginx: - -.. code-block:: shell-session - - [root@exchange-online]# vim /etc/nginx/sites-available/taler-exchange - < ... customize configuration ... > - [root@exchange-online]# ln -s /etc/nginx/sites-available/taler-exchange \ - /etc/nginx/sites-enabled/taler-exchange - [root@exchange-online]# systemctl reload nginx - - -The exchange HTTP service can now be started: - -.. code-block:: shell-session - - [root@exchange-online]# systemctl start taler-exchange.target - - -.. note:: - - At this point, the exchange service is not yet fully operational. - - -To check whether the exchange is running correctly under the advertized -base URL, run: - -.. code-block:: shell-session - - [root@exchange-online]# export BASE_URL=$(taler-config -s exchange -o base_url) - [root@exchange-online]# wget ${BASE_URL}management/keys - -The request might take some time to complete on slow machines, because -a lot of key material will be generated. - -Offline Signing Procedure -========================= - -The exchange HTTP service should be running now, but is not yet completely -operational. To make the exchange HTTP service operational, the following -steps involving the offline signing machine must be completed: - -1. The public keys of various online keys used by the exchange service are exported - via a management HTTP API. -2. The offline signing system validates this request and signs it. - Additionally, the offline signing system signs policy messages - to configure the exchange's bank accounts and associated fees. -3. The messages generated by the offline signing system are uploaded - via the management API of the exchange HTTP service. - - -.. code-block:: shell-session - - [root@exchange-online]# taler-exchange-offline \ - download > sig-request.json - - [root@exchange-offline]# taler-exchange-offline \ - sign < sig-request.json > sig-response.json - [root@exchange-offline]# taler-exchange-offline \ - enable-account payto://iban/$IBAN?receiver-name=$NAME > acct-response.json - [root@exchange-offline]# taler-exchange-offline \ - wire-fee now iban EUR:0 EUR:0 EUR:0 > fee-response.json - [root@exchange-offline]# taler-exchange-offline \ - global-fee now EUR:0 EUR:0 EUR:0 EUR:0 4w 4w 6y 4 > global-response.json - [root@exchange-online]# taler-exchange-offline upload < sig-response.json - [root@exchange-online]# taler-exchange-offline upload < acct-response.json - [root@exchange-online]# taler-exchange-offline upload < fee-response.json - [root@exchange-online]# taler-exchange-offline upload < global-response.json - - - - -Testing and Troubleshooting -=========================== - -The following shell session illustrates how the wallet can be used to withdraw -electronic cash from the exchange and subsequently spend it. For these steps, -a merchant backend is not required, as the wallet acts as a merchant. - - -.. code-block:: shell-session - - # This will now output a payto URI that money needs to be sent to in order to allow withdrawal - # of taler coins. - $ taler-wallet-cli advanced withdraw-manually --exchange $EXCHANGE_URL --amount EUR:10.50 - - -Show the status of the manual withdrawal operation. - -.. code-block:: shell-session - - $ taler-wallet-cli transactions - -At this point, a bank transfer to the exchange's bank account -needs to be made with the correct subject / remittance information -as instructed by the wallet after the first step. With the -above configuration, it should take about 5 minutes after the -wire transfer for the incoming transfer to be observed by the -Nexus. - -Run the following command to check whether the exchange received -an incoming bank transfer: - -.. code-block:: shell-session - - [root@exchange-online]# taler-exchange-wire-gateway-client \ - --section exchange-accountcredentials-1 --credit-history - -Once the transfer has been made, try completing the withdrawal -using: - -.. code-block:: shell-session - - $ taler-wallet-cli run-pending - -Afterwards, check the status of transactions and show the -current wallet balance: - -.. code-block:: shell-session - - $ taler-wallet-cli transactions - $ taler-wallet-cli balance - - -Now, we can directly deposit coins via the exchange into a target -account. (Usually, a payment is made via a merchant. The wallet -provides this functionality for testing.) - -.. code-block:: shell-session - - $ taler-wallet-cli deposit create EUR:5 \ - payto://iban/$IBAN?receiver-name=Name - $ taler-wallet-cli run-pending - - -Check if this transaction was successful (from the perspective -of the wallet): - -.. code-block:: shell-session - - $ taler-wallet-cli transactions - -If the transaction failed, fix any open issue(s) with the exchange and -run the "run-pending" command. - -The wallet can also track if the exchange wired the money to the merchant -account. The "deposit group id" can be found in the output of the -transactions list. - -.. code-block:: shell-session - - $ taler-wallet-cli deposit track $DEPOSIT_GROUP_ID - -You can also check using the exchange-tools whether the exchange sent -the an outgoing transfer: - -.. code-block:: shell-session - - [root@exchange-online]# taler-exchange-wire-gateway-client \ - --section exchange-accountcredentials-1 --debit-history - -After enough time has passed, the money should arrive at the specified IBAN. - - -FIXMEs -====== - -* We should have some summary with the inventory of services that should be - running. Systemd by default doesn't show this nicely. Maybe suggest running - "systemd list-dependencies taler-exchange.target"? -* When multiple TWGs are configured, which one will be used by the taler-exchange-transfer? CG: ALL! - - * FD: Sure, for incoming transactions. But how does taler-exchange-transfer decide which TWG to use for an outgoing transaction? - -* What happens when the TWG doesn't like one particular outgoing transaction? - How to recover from that as a sysadmin when it happens in practice? diff --git a/taler-mcig.rst b/taler-mcig.rst @@ -1,563 +0,0 @@ -.. - This file is part of GNU TALER. - Copyright (C) 2021 Taler Systems SA - - TALER 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 2.1, or (at your option) any later version. - - TALER 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 - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - - @author Thien-Thi Nguyen - - -Merchant/Customer Interaction Guide -################################### - -The audience for the Mechant/Customer Interaction Guide is the merchant -who wishes to set up a "web shop" that works with the Taler payment system. - - -Introduction -============ - -.. include:: frags/taler-payment-cycle.rst - -This guide focuses on step 4, the interaction between the customer and the -merchant. In particular, we first review two basic interaction flows -(with and without shopping cart), then describe Taler features involved in the -interaction, the decisions you (the merchant) must make, and -how to configure the Taler merchant backend to best support those decisions. -Lastly, we present protocol *traces* for various fictitious interaction flows. - - -Two Basic Flows -=============== - -.. index:: shopping cart experience -.. index:: individual product selection / purchase experience -.. index:: inventory management -.. index:: repurchase detection / prevention - -There are two basic payment flows, the first involving a shopping cart, -and the second, without (individual product selection / purchase). -We distinguish these because for some purchases, a shopping cart is overkill. -In either case, Taler can integrate -with your *inventory management* system. -Additionally, Taler offers *repurchase detection / prevention*, -most suitable for digital goods. - -In the shopping cart experience, you first offer a product on the website. -The customer adds the product to their shopping cart, at which point you may -optionally *lock* the product in the inventory system for a certain period of -time. -The accumulated set of products in the shopping cart is the *order*. -This process repeats until the customer is ready to move to the -*checkout* phase. - -At checkout, you may optionally support different payment methods (and make -this choice available to the customer) for the order. -This guide assumes you and the customer agree to use the Taler payment system. - -At this point, you generate a *contract* and present it to the customer for -authorization. -The contract includes: - -- the total amount due; -- a short summary; -- a *fulfillment URI*; -- the *duration* of the offer (how long the customer has to authorize before timeout); -- (optional) an itemized product list, with: - - - (optional) some kind of identification for the selected product(s); - -- (optional) applicable taxes and fee limits; -- (optional) an order ID (if omitted, the backend will auto-generate one); -- (optional) information which details are *forgettable*; -- (optional) a *claim token* that the customer can use later; -- (optional) information on the *refund deadline*; -- (optional) information on the *auto-refund period* (how long does the wallet check for refunds without user prompting for it). - -If the customer does nothing (timeout / the contract expires), -the merchant backend automatically *unlocks* the product(s), -allowing other consumers to add more items of the limited stock -to their orders. - -On the other hand, if the customer authorizes payment, -the customer's wallet transfers payment coins to you, -previously locked products are removed from inventory, -and (if possible) the wallet redirects the customer -to the *fulfillment URI*. - -The individual product selection / purchase experience is like the shopping -cart experience with the following exceptions: -- there is no shopping cart -- the order is solely the selected product; -- Taler payment method is assumed; -- customer selection moves directly to checkout; -- *repurchase detection / prevention* can be useful (for digital products). - - -Taler Details -============= - -This section describes aspects of Taler involved -in the basic payment flows in more detail. -Each aspect also includes one or more backend API calls that -are demonstrated in the next section. - -**product locking** - Taler can integrate with your inventory system to set aside - a certain quantity of a product for some duration of time. - This is called *product locking*. - This is useful for physical goods, or for goods that have a limited supply, - such as airline tickets. - Even for digital goods, product locking may be useful to effect exclusivity. - - To lock a product, use: - :http:post:`[/instances/$INSTANCE]/private/products/$PRODUCT_ID/lock`, - specifying a ``duration`` and a ``quantity``. - - If the customer removes a product from the shopping cart, you can *unlock* - the product by using the same API call, specifying a ``quantity`` of 0 (zero). - (Products are also unlocked automatically on timeout / contract expiration.) - - Before you can lock products, you need to manage the inventory, creating - an entry for the product (assigning a $PRODUCT_ID) and configure the - available stock. This can be done using the - Taler merchant backoffice Web interface. - - .. note:: - - Once we have documentation for that web interface, we should link to it here. - -**taxes** - The default taxes for each product is part of the product ``price`` - maintained by the backend. - Taxes can be set when the product is added to the inventory, - prior to any customer purchase experience - (see :http:post:`[/instances/$INSTANCE]/private/products`, - :http:get:`[/instances/$INSTANCE]/private/products`, - and :http:get:`[/instances/$INSTANCE]/private/products/$PRODUCT_ID`) - or specified explicitly by the frontend when adding - products to an order that are not managed by the backend inventory - (see :http:post:`[/instances/$INSTANCE]/private/orders`). - -**fees** - The Taler protocol charges a *deposit fee* (see step 5, above), - which you may choose to pay or to pass on to the customer. - This can be configured to a maximum amount, per order. - - You can set ``default_max_deposit_fee`` in :http:post:`/management/instances`, - or override the default by setting ``max_fee`` when creating an order. - - There is also the *wire fee* (see step 6, above), - which you may choose to pay or to pass on to the customer. - - You can set ``default_max_wire_fee`` in :http:post:`/management/instances`, - and ``max_wire_fee`` in the contract. - If unspecified, the default value is zero (meaning you bear the entire fee). - - You can *amortize* the wire fee across a number of customers - by setting ``default_wire_fee_amortization`` in :http:post:`/management/instances`, - and ``wire_fee_amortization`` in the contract. - This is the number of customer transactions over which you expect to - amortize wire fees on average. - If unspecified, the default value is one. - - .. Note:: :http:post:`/management/instances` must be done at - instance-setup time (prior to any purchase). - -**forgettable customer details** - Although Taler allows the customer to remain anonymous, you may need to - collect customer details (e.g. for shipping). - Taler has support for forgetting such details, to comply with GDPR - (for example). - This can occur even in the face of refunds (see below). - - To forget a set of details, first the details that are to be forgotten - must be marked by including the names of the respective fields - in one or more special ``_forgettable`` field(s) in the contract. - - Then, you can use: - :http:patch:`[/instances/$INSTANCE]/private/orders/$ORDER_ID/forget` - to forget those details. - -**claim token** - The claim token is a sort of handle on the order and its payment. - It is useful when the order ID is easily guessable - (e.g. incrementing serial number), - to prevent one customer hijacking the order of another. - On the other hand, even if the order ID is not easily guessable, - if you don't care about order theft (e.g. infinite supply, digital goods) - and you wish to reduce the required processing (e.g. smaller QR code), - you can safely disable the claim token. - - By default, Taler creates a claim token for each order. - To disable this, you can specify ``create_token`` to be ``false`` - in :http:post:`[/instances/$INSTANCE]/private/orders`. - -**refund deadline** - The refund deadline specifies the time after which you will prohibit - refunds. - Refunds may be full or partial. - Refunds do not require customer details. - You can configure the deadline to expire immediately to effect - an "all sales are final" policy. - - To set the deadline, specify ``refund_delay`` - in :http:post:`[/instances/$INSTANCE]/private/orders`. - To disable refunds altogether, omit this field. - -**auto-refund period** - The Taler protocol can automatically offer refunds to the customer's - wallet without their explicit prompting during the auto-refund period. - - This is useful in the case where the purchase cannot be fulfilled - (e.g. jammed vending machine), but there is no way to notify the - customer about a refund. - - If specified, after contract authorization, the customer's wallet will - repeatedly check for either fulfillment or refund, up to the end of - the auto-refund period. - (If neither occur within that period, the customer should complain - to you for breach of contract.) - - To set the auto-refund period, specify ``auto_refund`` - in :http:post:`[/instances/$INSTANCE]/private/orders`. - -**repurchase detection / prevention** - Taler can detect a repurchase attempt and prevent it from going through. - This feature allows customers to purchase a digital good only once, - but to later access the same digital good repeatedly (e.g. reload - in browser, after network trouble, etc.) without having to pay again. - - This feature is automatic in the protocol; - you do not need to do anything to enable it. - - .. note:: - For repurchase detection / prevention to work reliably, - you must use the same fulfillment URI for the same product - and likewise different fulfillment URIs for different products. - -**fulfillment URI** - This may be the actual product (digital goods), - or a tracking URL (physical goods). - If you issue a claim token with the contract, the customer can - access the fulfillment URI from a different device than the - one where the wallet is installed. - - The fulfillment URI is normally included in the contract. - You specify it in :http:post:`[/instances/$INSTANCE]/private/orders`. - - If the fulfillment URI contains the literal string ``${ORDER_ID}`` - (including curly braces), that will be replaced by the order ID when - POSTing to the merchant. (FIXME: What does "POSTing to the merchant" mean?) - This is useful when the backend auto-generates the order ID. - - -Sample Interaction Traces -========================= - -In the following descriptions, ``C`` stands for *customer*, ``W`` stands for -*customer's wallet*, ``M`` stands for *merchant* (you), and ``E`` stands for -*exchange*. -Unless otherwise noted, all API calls are directed toward the Taler backend. - -Also, all the traces share the initial pre-sales configuration step. - - -Pre-Sales Configuration ------------------------ - -In the pre-sales configuration step, you set up the *default instance*, -and add products to the inventory. - -NOTE: not sure we want to ultimately document this HERE. Most merchants -should do _this_ part via the Merchant Web interface that Sebastian is -building right now, and for that we want a separate guide that explains -the API (as you do here), and the Web interface. In this document, -we should focus on how the merchant integrates the (Web)front-end with the -backend, not how the backend itself is configured. -(This also applies to the other instance setup parts you described -above => refer to other guide, but of course specify how we can -override defaults from instance setup per-order.) - - -M: :http:post:`/management/instances` - -.. code-block:: javascript - - // InstanceConfigurationMessage - { - "payto_uris": ["payto://iban/CH9300762011623852957"], - "id": "default", - "name": "Pretty Pianos", - "auth": - // InstanceAuthConfigurationMessage - { - "method": "external", - "token": "secret-token:eighty-eight-keys" - }, - "default_max_wire_fee": "KUDOS:5.0", - "default_wire_fee_amortization": 1, - "default_max_deposit_fee": "KUDOS:10.0", - "default_wire_transfer_delay": "2 days", - "default_pay_delay": "5 hours" - } - // (backend returns 204 No content) - -The fictitious store, Pretty Pianos, has only two products: -- pianos (physical good); -- *Beethoven Sonatas* (sheet music PDF files, digital good). - -M: POST ``/instances/default/private/products`` - -.. code-block:: javascript - - // ProductAddDetail - { - "product_id": "p001", - "description": "piano", - "unit": "unit", - "image": "data:image/png;base64,AAA=", - "price": "KUDOS:20000.0", - "taxes": [], - "total_stock": 3, - "next_restock": "2021-04-22", - "_forgettable": ["image"] - } - // (backend returns 204 No content) - -Note that the ``image`` field is mentioned by name in the ``_forgettable`` -field's list value. -This means the ``image`` value is *marked as forgettable*. -This will come into play later (see below). - -M: POST ``/instances/default/private/products`` - -.. code-block:: javascript - - // ProductAddDetail - { - "product_id": "f001", - "description": "Beethoven Sonatas", - "unit": "file", - "price": "KUDOS:9.87", - "taxes": [], - "total_stock": -1 - } - // (backend returns 204 No content) - -Note that there is no ``next_restock`` field in this ``ProductAddDetail`` -object. -This is because the ``total_stock`` field has value ``-1`` (meaning "infinite") -since the product is a PDF file. - - -Scenario 1: Simple File Purchase --------------------------------- - -The first scenario is a simple file purchase, without shopping cart, -similar to the `GNU Essay demo <https://shop.demo.taler.net/en/>`_ experience. - -.. We hardcode "en/" for now because support for other - languages is not yet available (at time of writing). - (FIXME: Drop "en/" when other languages are supported.) - -Because there are infinite supplies of product ``f001``, -there is really no need for inventory management. -However, you choose to anyway generate a separate order ID -in the backend for accounting purposes. -Also, since the product is an easily reproduced digital good, -you decline to offer the customer the ability to select a "quantity" -other than 1 (one), and decide that "all sales are final" -(no refund possible). -On the other hand, you wish to enable repurchase detection / -prevention feature, so that once customers pay for the PDF file, -they need never pay again for it. - -When the customer clicks on the product's "buy" button, -you first POST to ``/private/orders`` to create an order: - -M: POST ``/instances/default/private/orders`` - -.. code-block:: javascript - - // PostOrderRequest - { - "order": - // Order (MinimalOrderDetail) - { - "amount": "KUDOS:9.87", - "summary": "Beethoven Sonatas", - "fulfillment_URI": "https://example.com/f001?${ORDER_ID}" - }, - "create_token": true - } - -Notes: - -- There is no ``refund_delay`` field (no refunds possible). -- We show the ``create_token`` field with value ``true`` even though that is the default (for illustrative purposes). -- The ``order`` value is actually a ``MinimalOrderDetail`` object. -- The ``fulfillment_URI`` value includes the product ID and the literal string ``${ORDER_ID}``, to be replaced by the backend-generated order ID. - -The backend returns ``200 OK`` with the body: - -.. code-block:: javascript - - // PostOrderResponse - { - "order_id": "G93420934823", - "token": "TEUFHEFBQALK" - } - -Notes: -- The backend-generated order ID is ``G93420934823``. -- The claim token is ``TEUFHEFBQALK``. - -(FIXME: Replace w/ more realistic examples?) - -Now that there is an order in the system, the wallet *claims* the order. - -W: POST ``/orders/G93420934823/claim`` - -.. code-block:: javascript - - // ClaimRequest - { - "nonce": "lksjdflaksjfdlaksjf", - "token": "TEUFHEFBQALK" - } - -Notes: - -- The ``nonce`` value is a randomly-generated string. -- The POST endpoint includes the order ID ``G93420934823``. -- The ``token`` value is the claim token ``TEUFHEFBQALK`` received in the ``PostOrderResponse``. - -The backend returns ``200 OK`` with body: - -.. code-block:: javascript - - // ContractTerms - { - "summary": "one copy of Beethoven Sonatas", - "order_id": "G93420934823", - "amount": "KUDOS:9.87000000", - "fulfillment_url": "https://example.com/f001?G93420934823", - "max_fee": "KUDOS:0.01500000", - "max_wire_fee": "KUDOS:0.01500000", - "wire_fee_amortization": 1, - "products": [ - // Product - { - "product_id": "f001", - "description": "Beethoven Sonatas" - } - ], - "timestamp": { "t_ms": 1616537665000 }, - "refund_deadline": { "t_ms": 1616537665000 }, - "pay_deadline": { "t_ms": 1616537725000 }, - "wire_transfer_deadline": { "t_ms": 1616537785000 }, - "merchant_pub": FIXME, - "merchant_base_url": "https://example.com/", - "merchant": - // Merchant - { - }, - "h_wire": FIXME, - "wire_method": FIXME, - "auditors": [ - // Auditor - ], - "exchanges": [ - // Exchange - ], - "nonce": "lksjdflaksjfdlaksjf" - } - -Notes: - -- The backend determined both fees to be 0.015 KUDOS. - Because the amortization is 1 (one), both fees (processing and wire - transfer) are included in full. - Thus, the total due by the customer is 9.87 + 0.015 + 0.015 = 9.900 KUDOS. -- The ``order_id`` value is the one given in the ``PostOrderResponse``. -- The ``timestamp`` value represents 2021-03-23 22:14:25 UTC - in milliseconds after the `epoch <https://en.wikipedia.org/wiki/Unix_epoch>`__. -- The ``refund_deadline`` value is the same as the ``timestamp`` value - (no refunds possible). -- The ``pay_deadline`` value is one minute after the ``timestamp`` value. -- The ``wire_transfer_deadline`` value is two minutes after - the ``timestamp`` value. -- The ``products`` value is a list of one element (one ``Product`` object), - which omits the ``price`` field since that is included in the - ``ContractTerms.amount`` value. Also, its ``quantity`` defaults to 1 (one). -- The ``nonce`` value is the same one specified by the wallet. - -At this point, the wallet displays the contract terms (or a subset of them) -to the customer, who now has the option to accept the contract or reject it -(either explicitly by pressing a "cancel" button, or implicitly by waiting -for the offer to time out). - -The customer accepts the contract: - -W: POST ``/orders/G93420934823/pay`` - -.. code-block:: javascript - - // PayRequest - { - "coins": [ - // CoinPaySig - { - "coin_sig": ..., - "coin_pub": ..., - "ub_sig": ..., - "h_denom": ..., - "contribution": "KUDOS:8.0", - "exchange_url": ... - }, - { - "coin_sig": ..., - "coin_pub": ..., - "ub_sig": ..., - "h_denom": ..., - "contribution": "KUDOS:2.0", - "exchange_url": ... - } - ] - } - -Notes: - -- There is no session ID in the ``PayRequest`` object. -- The total of the contribution is 8.0 + 2.0 = 10.0 KUDOS, - which is enough to cover the purchase price (9.900 KUDOS - from 9.87 + 0.015 + 0.015). - -The backend returns ``200 OK`` with body: - -.. code-block:: javascript - - // PaymentResponse - { - "sig": "..." // EddsaSignature - } - -FIXME: At this point, does the wallet need to query (status)? -Also, does the frontend need to do anything else? - -The wallet then redirects to the fulfillment URI, which displays -(or makes available for download) the PDF file "Beethoven Sonatas". - - - - -TODO/FIXME: Add more scenarios (including JSON). diff --git a/taler-merchant-api-tutorial.rst b/taler-merchant-api-tutorial.rst @@ -1,6 +1,6 @@ .. This file is part of GNU TALER. - Copyright (C) 2014-2020 Taler Systems SA + Copyright (C) 2014-2023 Taler Systems SA TALER 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 @@ -98,7 +98,7 @@ components: The following image illustrates the various interactions of these key components: -.. image:: arch-api.png +.. image:: images/arch-api.png The backend provides the cryptographic protocol support, stores Taler-specific financial information and communicates with the GNU Taler @@ -125,13 +125,13 @@ configuration. See :doc:`taler-merchant-manual`. The public sandbox backend https://backend.demo.taler.net/ uses an API key in the ``Authorization`` header. The value of this header must be -``ApiKey sandbox`` for the public sandbox backend. +``Bearer secret-token:sandbox`` for the public sandbox backend. .. code-block:: python >>> import requests - >>> requests.get("https://backend.demo.taler.net", - ... headers={"Authorization": "secret-token:secret"}) + >>> requests.get("https://backend.demo.taler.net/private/orders", + ... headers={"Authorization": "Bearer secret-token:sandbox"}) <Response [200]> If an HTTP status code other than 200 is returned, something went wrong. @@ -147,9 +147,9 @@ https://bank.demo.taler.net/. Merchant Instances ------------------ -The same Taler merchant backend server can be used by multiple separate +A single Taler merchant backend server can be used by multiple merchants that are separate business entities. Each of these separate -business entities is called a *merchant instance*, and is identified by +business entities is assigned a *merchant instance* which is identified by an alphanumeric *instance id*. If the instance is omitted, the instance id ``default`` is assumed. @@ -223,10 +223,10 @@ A minimal Python snippet for creating an order would look like this: >>> body = dict(order=dict(amount="KUDOS:10", ... summary="Donation", ... fulfillment_url="https://example.com/thanks.html"), - ... create_token=false) + ... create_token=False) >>> response = requests.post("https://backend.demo.taler.net/private/orders", ... json=body, - ... headers={"Authorization": "secret-token:secret"}) + ... headers={"Authorization": "Bearer secret-token:sandbox"}) <Response [200]> @@ -244,19 +244,23 @@ address of the merchant instance. The full details are called the you must adjust the code to construct the ``taler://pay/`` URI given below to include the claim token. -After successfully ``POST``\ ing to ``/private/orders``, an ``order_id`` will be -returned. Together with the merchant ``instance``, the order id uniquely -identifies the order within a merchant backend. Using the order ID, you -can trivially construct the respective ``taler://pay/`` URI that must -be provided to the wallet. Let ``example.com`` be the domain name where -the public endpoints of the instance are reachable. The Taler pay URI is -then simply ``taler://pay/example.com/$ORDER_ID/`` where ``$ORDER_ID`` -must be replaced with the ID of the order that was returned. +After successfully ``POST``\ ing to ``/private/orders``, a JSON with just an +``order_id`` field with a string representing the order ID will be returned. +If you also get a claim token, please double-check that you used the request +as described above. + +Together with the merchant ``instance``, the order id uniquely identifies the +order within a merchant backend. Using the order ID, you can trivially +construct the respective ``taler://pay/`` URI that must be provided to the +wallet. Let ``example.com`` be the domain name where the public endpoints of +the instance are reachable. The Taler pay URI is then simply +``taler://pay/example.com/$ORDER_ID/`` where ``$ORDER_ID`` must be replaced +with the ID of the order that was returned. You can put the ``taler://`` URI as the target of a link to open the Taler wallet via the ``taler://`` schema, or put it into a QR code. However, for a Web shop, the easiest way is to simply redirect the browser to -``https://example.com/orders/$ORDER_ID/``. That page will then trigger the +``https://example.com/orders/$ORDER_ID``. That page will then trigger the Taler wallet. Here the backend generates the right logic to trigger the wallet, supporting the various types of Taler wallets in existence. Instead of constructing the above URL by hand, it is best to obtain it by checking for @@ -267,11 +271,11 @@ Checking Payment Status and Prompting for Payment ------------------------------------------------- Given the order ID, the status of a payment can be checked with the -``/private/orders/$ORDER_ID/`` endpoint. If the payment is yet to be completed +``/private/orders/$ORDER_ID`` endpoint. If the payment is yet to be completed by the customer, ``/private/orders/$ORDER_ID`` will give the frontend a URL (under the name ``payment_redirect_url``) that will trigger the customer’s wallet to execute the payment. This is basically the -``https://example.com/orders/$ORDER_ID/`` URL we discussed above. +``https://example.com/orders/$ORDER_ID`` URL we discussed above. Note that the best way to obtain the ``payment_redirect_url`` is to check the status of the payment, even if you know that the user did not pay yet. There @@ -282,7 +286,7 @@ backend to do it is the safest method. >>> import requests >>> r = requests.get("https://backend.demo.taler.net/private/orders/" + order_id, - ... headers={"Authorization": "secret-token:secret"}) + ... headers={"Authorization": "Bearer secret-token:sandbox"}) >>> print(r.json()) If the ``order_status`` field in the response is ``paid``, you will not @@ -350,12 +354,12 @@ This code snipped illustrates giving a refund: ... reason="Customer did not like the product") >>> requests.post("https://backend.demo.taler.net/private/orders/" ... + order_id + "/refund", json=refund_req, - ... headers={"Authorization": "secret-token:secret"}) + ... headers={"Authorization": "Bearer secret-token:sandbox"}) <Response [200]> .. Note:: After granting a refund, the public - ``https://example.com/orders/$ORDER_ID/`` endpoint will + ``https://example.com/orders/$ORDER_ID`` endpoint will change its wallet interaction from requesting payment to offering a refund. Thus, frontends may again redirect browsers to this endpoint. However, to do so, a @@ -372,8 +376,6 @@ This code snipped illustrates giving a refund: Repurchase detection and fulfillment URLs ========================================= -.. TODO:: This section needs to be reviewed for 0.8. - A possible problem for merchants selling access to digital articles is that a customer may have paid for an article on one device, but may then want to read it on a different device, possibly one that @@ -411,79 +413,74 @@ considered to identify a resource you can pay for and thus do not have to be unique. -.. _Giving-Customers-Tips: -.. index:: tips - -Giving Customers Tips -===================== - -.. TODO:: This section needs to be updated for 0.8. +.. _Giving-Customers-Rewards: +.. index:: rewards +Giving Customers Rewards +======================== -GNU Taler allows Web sites to grant small amounts directly to the -visitor. The idea is that some sites may want incentivize actions such -as filling out a survey or trying a new feature. It is important to note -that tips are not enforceable for the visitor, as there is no contract. -It is simply a voluntary gesture of appreciation of the site to its -visitor. However, once a tip has been granted, the visitor obtains full -control over the funds provided by the site. +GNU Taler allows Web sites to grant digital cash directly to a visitor. The +idea is that some sites may want incentivize actions such as filling out a +survey or trying a new feature. It is important to note that receiving rewards is +not enforceable for the visitor, as there is no contract. It is simply a +voluntary gesture of appreciation of the site to its visitor. However, once a +reward has been granted, the visitor obtains full control over the funds provided +by the site. -The “merchant” backend of the site must be properly configured for -tipping, and sufficient funds must be made available for tipping See -Taler Merchant Operating Manual. +The merchant backend of the site must be properly configured for rewards, and +sufficient funds must be made available for rewards. See the :ref:`Taler User +Guide <Rewarding-visitors>` for details. -To check if tipping is configured properly and if there are sufficient -funds available for tipping, query the ``/tip-query`` endpoint: +To check if rewards are configured properly and if there are sufficient +funds available for granting rewards, query the ``/private/reserves`` endpoint: .. code-block:: python >>> import requests - >>> requests.get("https://backend.demo.taler.net/tip-query?instance=default", - ... headers={"Authorization": "secret-token:secret"}) + >>> requests.get("https://backend.demo.taler.net/private/reserves", + ... headers={"Authorization": "Bearer secret-token:sandbox"}) <Response [200]> -.. _authorize-tip: +Check that a reserve exists where the ``merchant_initial_amount`` is below the +``committed_amount`` and that the reserve is ``active``. -To authorize a tip, ``POST`` to ``/tip-authorize``. The following fields -are recognized in the JSON request object: +.. _authorize-reward: -- ``amount``: Amount that should be given to the visitor as a tip. +To authorize a reward, ``POST`` to ``/private/rewards``. The following fields +are recognized in the JSON request object: -- ``instance``: Merchant instance that grants the tip (each instance may - have its own independent tipping funds configured). +- ``amount``: Amount that should be given to the visitor as a reward. -- ``justification``: Description of why the tip was granted. Human-readable +- ``justification``: Description of why the reward was granted. Human-readable text not exposed to the customer, but used by the Back Office. - ``next_url``: The URL that the user’s browser should be redirected to by - the wallet, once the tip has been processed. + the wallet, once the reward has been processed. -The response from the backend contains a ``tip_redirect_url``. The +The response from the backend contains a ``taler_reward_url``. The customer’s browser must be redirected to this URL for the wallet to pick -up the tip. +up the reward. -.. _pick-up-tip: +.. _pick-up-reward: -This code snipped illustrates giving a tip: +This code snipped illustrates giving a reward: .. code-block:: python >>> import requests - >>> tip_req = dict(amount="KUDOS:0.5", - ... instance="default", + >>> reward_req = dict(amount="KUDOS:0.5", ... justification="User filled out survey", ... next_url="https://merchant.com/thanks.html") - >>> requests.post("https://backend.demo.taler.net/tip-authorize", json=tip_req, - ... headers={"Authorization": "secret-token:secret"}) + >>> requests.post("https://backend.demo.taler.net/private/rewards", json=reward_req, + ... headers={"Authorization": "Bearer secret-token:sandbox"}) <Response [200]> + .. _Advanced-topics: Advanced topics =============== -.. TODO:: This section needs to be updated for 0.8. - .. _Session_002dBound-Payments: Session-Bound Payments diff --git a/taler-merchant-manual.rst b/taler-merchant-manual.rst @@ -1,4 +1,22 @@ -.. _ffoobar: +.. + This file is part of GNU TALER. + + Copyright (C) 2014-2023 Taler Systems SA + + TALER 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 2.1, or (at your option) any later version. + + TALER 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 + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + + @author Christian Grothoff + +.. _taler-merchant-backend-operator-manual: GNU Taler Merchant Backend Operator Manual ########################################## @@ -9,20 +27,8 @@ Introduction About GNU Taler --------------- -GNU Taler is an open protocol for an electronic payment system with a -free software reference implementation. GNU Taler offers secure, fast -and easy payment processing using well understood cryptographic -techniques. GNU Taler allows customers to remain anonymous, while -ensuring that merchants can be held accountable by governments. Hence, -GNU Taler is compatible with anti-money-laundering (AML) and -know-your-customer (KYC) regulation, as well as data protection -regulation (such as GDPR). - -GNU Taler is not yet production-ready: after following this manual you -will have a backend that can process payments in “KUDOS”, but not -regular currencies. This is not so much because of limitations in the -backend, but because we are not aware of a Taler exchange operator -offering regular currencies today. +.. include:: frags/about-taler.rst + .. _About-this-manual: @@ -56,11 +62,11 @@ Architecture overview .. index:: KUDOS Taler is a pure payment system, not a new crypto-currency. As such, it -operates in a traditional banking context. In particular, this means -that in order to receive funds via Taler, the merchant must have a -regular bank account, and payments can be executed in ordinary -currencies such as USD or EUR. For testing purposes, Taler uses a -special currency “KUDOS” and includes its own special bank. +operates in a traditional banking context. In particular, this means that in +order to receive funds via Taler, the merchant must have a regular bank +account, and payments can be executed in ordinary currencies such as USD or +EUR. Taler can also be used as a regional currency; for such scenarios, the +Taler system also includes its own stand-alone bank. .. index:: frontend .. index:: back-office @@ -68,8 +74,7 @@ special currency “KUDOS” and includes its own special bank. .. index:: DBMS .. index:: PostgreSQL -The Taler software stack for a merchant consists of four main -components: +The Taler software stack for a merchant consists of four main components: - A *frontend* which interacts with the customer’s browser. The frontend enables the customer to build a shopping cart and place an order. @@ -97,7 +102,7 @@ components: The following image illustrates the various interactions of these key components: -.. image:: arch-api.png +.. image:: images/arch-api.png .. index:: RESTful @@ -107,13 +112,13 @@ Taler exchange over the Internet. The frontend accesses the backend via a RESTful API. As a result, the frontend never has to directly communicate with the exchange, and also does not deal with sensitive data. In particular, the merchant’s signing keys and bank account information are encapsulated within -the Taler backend. +the Taler merchant backend. A typical deployment will additionally include a full-blown Web server (like Apache or Nginx). Such a Web server would be responsible for TLS termination and access control to the ``/private/`` and ``/management/`` API endpoints of the -merchant backend. Please carefully review the section on :ref:`Secure setup -<Secure-setup>` before deploying a Taler merchant backend to production. +merchant backend. Please carefully review the section on :ref:`secure setup +<Secure-setup>` before deploying a Taler merchant backend into production. Terminology @@ -126,21 +131,44 @@ Instances .. index:: instance -The backend allows the user to run multiple *instances* of shops with distinct -business entities sharing a single backend. Each instance uses its own bank -accounts and key for signing contracts. All major accounting functionality is -separate per instance. What is shared is the database, HTTP(S) address and -the main Taler configuration (accepted currency, exchanges and auditors). - -Accounts --------- +The backend allows a single HTTP server to support multiple independent shops +with distinct business entities sharing a single backend. An *instance* is +the name or identifier that allows the single HTTP server to determine which +shop a request is intended for. Each instance has its own base URL in the +REST API of the merchant backend (``/instances/$INSTANCE/``). Each instance +can use its own bank accounts and keys for signing contracts. All major +accounting functionality is separate per instance. Access to each instance is +controlled via a bearer token (to be set in the HTTP "Authorization" header). +All instances share the same *database*, top-level HTTP(S) address and the +main Taler configuration (especially the accepted *currency* and *exchanges*). + + .. note:: + + This documentation does not use the term "user" or "username" in + conjunction with instances as that might create confusion between + instances with paying customers using the system. We also do not use the + term "account" in conjunction with instances, as that might cause + confusion with bank accounts. That said, conceptually it is of course + acceptable to consider instances to be the "users" or "accounts" of a + merchant backend and the bearer token is equivalent to a passphrase. + + +Instance Bank Accounts +---------------------- -.. index:: account +.. index:: instance-bank-account To receive payments, an instance must have configured one or more bank -*accounts*. The backend does not have accounts for users, and instances are -also not really 'accounts'. So whenever we use the term *account*, it is about -a bank account of a merchant. +*accounts*. When configuring the bank account of an instance, one should +ideally also provide the address and credentials of an HTTP service +implementing the `Taler Bank Merchant HTTP API +<taler-bank-merchant-http-api>`_. Given such a service, the GNU Taler +merchant backend can automatically reconcile wire transfers from the +exchange to the merchant's bank account with the orders that are being +settled. + +This documentation exclusively uses the term *account* for the bank +accounts of a merchant or shop that may be associated with an instance. Inventory --------- @@ -153,21 +181,26 @@ Inventory The Taler backend offers inventory management as an optional function. Inventory is tracked per instance and consists of *products* sold in -*units*. Inventory can be finite or infinite (for digital products). -Products may include previews (images) to be shown to the user and other -meta-data. Inventory management allows the frontend to *lock* products, -reserving them for a particular (unpaid) *order*. The backend can keep -track of how many units of a product remain in stock and ensure that -the number of units sold does not exceed the number of units in stock. +*units*. Inventory can be finite (physical stock) or infinite (for digital +products). Products may include previews (images) to be shown to the user as +well as other meta-data. Inventory management allows the frontend to *lock* +products, reserving a number of units from stock for a particular (unpaid) +*order*. The backend can keep track of how many units of a product remain in +stock and ensure that the number of units sold does not exceed the number of +units in stock. Inventory management is optional, and it is possible for the frontend to -include products in orders that are not in the inventory, or to override -prices of products in the inventory. +include products in orders that are not in the inventory. The frontend +can also override prices of products in the inventory or set a total price +for an order that is different from the price of the sum of the products +in the order. + Orders and Contracts -------------------- .. index:: order +.. index:: terms .. index:: contract .. index:: claim .. index:: pay @@ -176,8 +209,13 @@ Orders and Contracts .. index:: lock .. index:: legal expiration -In Taler, users pay merchants for orders. An order is first created by the -merchant, where the merchant specifies the specific terms of the order. +In Taler, users pay merchants for *orders*. An order is first created by the +merchant. To create an order, the merchant must specify the specific *terms* +of the order. Order *terms* include details such as the total amount to be +paid, payment fees the merchant is willing to cover, the set of products to +deliver, a delivery location and many other details. The `merchant API +specification <contract-terms>`_ specifies the full set of possible order +terms. After an order is created, it is *claimed* by a wallet. Once an order is claimed by a specific wallet, only that wallet will be able to pay for this @@ -189,35 +227,39 @@ purchase the same product. To prevent unauthorized wallets from claiming an order, merchants can specify that claims require authorization in the form of a *claim token*. This is useful in case the order ID is predictable (say because an existing order ID -scheme from the merchant frontend is used) and at the same time malicious -actors claiming orders is problematic (say because of limited stocks). The use -of claim tokens is optional, but if a claim token is used, it must be provided -to the wallet as part of the order URI. - -Additionally, when stocks are limited, you can configure Taler to -set a *product lock* on items (say, while composing the shopping cart). -These locks, as well as the *order lock* (when the order is complete), -can be configured to auto-unlock at certain times. - -.. FIXME: Is "can be configured" correct? (Are there controls surfaced?) - -A wallet may *pay* for a claimed order, at which point the order turns into -a (paid) contract. Orders have an expiration date after which the commercial -offer expires and any stock of products *locked* by the order is released, -allowing the stock to be sold in other orders. +scheme with predictable order IDs from the merchant frontend is used) and at +the same time malicious actors claiming orders is problematic (say because of +limited stocks). The use of claim tokens is optional, but if a claim token is +used, it must be provided to the wallet as part of the order URI. + +Additionally, when stocks are limited, you can configure Taler to set a +*product lock* on items (say, while composing the shopping cart). These +locks will ensure that the limited stock is respected when making offers +to consumers. + +A wallet may *pay* for a claimed order, at which point the order turns into a +(paid) *contract*. Orders have a configurable expiration date (the +``pay_deadline``) after which the commercial offer expires and any stock of +products *locked* by the order will be automatically released, allowing the +stock to be sold in other orders. When an unpaid order expires, the customer +must request a fresh order if they still want to make a purchase. Once a contract has been paid, the merchant should fulfill the contract. It is possible for the merchant to *refund* a contract order, for example if the contract cannot be fulfilled after all. Refunds are only possible after the customer paid and before the exchange has *wired* the payment to the merchant. Once the funds have been wired, refunds are no longer allowed by the -Taler exchange. The *wire deadline* specifies the latest time by which an -exchange must wire the funds, while the (earlier) *refund deadline* specifies -the earliest time when an exchange may wire the funds. +Taler exchange. The *wire deadline* specifies the latest point in time by +which an exchange must wire the funds, while the (earlier) *refund deadline* +specifies the earliest point in time when an exchange may wire the funds. +Thus, refunds are always possible between the time of purchase and the +refund deadline, but may remain possible until the wire deadline. + +Contract information is kept for legal reasons in the merchant database. The +main legal reason is typically to provide tax records in case of a tax audit. +After the *legal expiration* (by default: a decade), contract information is +deleted when running the garbage collector using ``taler-merchant-dbinit``. -Contract information is kept for legal reasons, typically to provide tax -records in case of a tax audit. After the *legal expiration* (by default a -decade), contract information is deleted. Transfers --------- @@ -226,27 +268,35 @@ Transfers .. index:: wire transfer The Taler backend can be used to verify that the exchange correctly wired all -of the funds to the merchant. However, the backend does not have access to the -incoming wire transfers of the merchant's bank account. Thus, merchants must -manually provide the backend with wire *transfer* data that specifies the wire -transfer subject and the amount that was received. Given this information, the -backend can detect and report any irregularities that might arise. - -Tipping +of the funds to the merchant. However, if no `Taler Bank Merchant HTTP API +<taler-bank-merchant-http-api>`_ was provided for the respective bank account, +the backend does not have access to the incoming wire transfers of the +merchant's bank account. In this case, merchants must manually provide the +backend with wire *transfer* data that specifies the *wire transfer subject* +and the amount that was received. Given this information, the backend can +detect and report any irregularities that might arise. + +Rewards ------- -.. index:: tip -.. index:: grant +.. index:: reward .. index:: pick up Taler does not only allow a Website to be paid, but also to make voluntary, -non-contractual payments to visitors, called *tips*. Such tips could be +non-contractual payments to visitors, called *rewards*. Such rewards could be granted as a reward for filling in surveys or watching advertizements. For -tips, there is no contract, tips are always voluntary actions by the Web +rewards, there is no contract, rewards are always voluntary actions by the Web site that do not arise from a contractual obligation. Before a Web site -can create tips, it must establish a reserve. Once a reserve has been -established, the merchant can *grant* tips, allowing wallets to *pick up* -the tip. +can create rewards, it must establish a reserve. Once a reserve has been +established, the merchant can *grant* rewards, allowing wallets to *pick up* +the reward. + + ..note:: + + Rewards are an optional feature, and exchanges may disable rewards (usually + if they see compliance issues). In this case, the reward feature will + not be available. + Reserves -------- @@ -256,12 +306,15 @@ Reserves A *reserve* is a pool of electronic cash at an exchange under the control of a private key. Merchants withdraw coins from a reserve when granting -tips. A reserve is established by first generating the required key material +rewards. A reserve is established by first generating the required key material in the merchant backend, and then wiring the desired amount of funds to the exchange. An exchange will automatically *close* a reserve after a fixed period of time (typically about a month), wiring any remaining funds back to the merchant. +While exchange APIs exists to (1) explicitly *open* a reserve to prevent it +from being automatically closed and to (2) explicitly *close* a reserve at any +time, the current merchant backend does not make use of these APIs. Installation @@ -277,16 +330,10 @@ Installing from source The following instructions will show how to install a GNU Taler merchant backend from source. -The package sources can be find in our +The package sources can be find in our `download directory <http://ftpmirror.gnu.org/taler/>`__. -GNU Taler components version numbers follow the ``MAJOR.MINOR.MICRO`` format. -The general rule for compatibility is that ``MAJOR`` and ``MINOR`` must match. -Exceptions to this general rule are documented in the release notes. -For example, Taler merchant 1.3.0 should be compatible with Taler exchange 1.4.x -as the MAJOR version matches. A MAJOR version of 0 indicates experimental -development, and you are expected to always run all of the *latest* releases -together (no compatibility guarantees). +.. include:: frags/semver.rst First, the following packages need to be installed before we can compile the backend: @@ -344,17 +391,15 @@ How to configure the merchant’s backend The installation already provides reasonable defaults for most of the configuration options. However, some must be provided, in particular the -database account and bank account that the backend should use. By -default, the file ``$HOME/.config/taler.conf`` is where the Web shop -administrator specifies configuration values that augment or override -the defaults. The format of the configuration file is the well-known INI -file format. You can edit the file by hand, or use the ``taler-config`` -commands given as examples. +database that the backend should use. By default, the file +``$HOME/.config/taler.conf`` is where the Web shop administrator specifies +configuration values that augment or override the defaults. +Note that when using our binary packages, the systemd service files +force the use of ``/etc/taler.conf`` as the main configuration file. .. include:: frags/configuration-format.rst - .. include:: frags/using-taler-config.rst @@ -375,8 +420,8 @@ Backend options .. index:: wire format The following table describes the options that commonly need to be -modified. Here, the notation ``[$section]/$option`` denotes the option -``$option`` under the section ``[$section]`` in the configuration file. +modified. Here, the notation ``[$SECTION]/$OPTION`` denotes the option +``$OPTION`` under the section ``[$SECTION]`` in the configuration file. Service address @@ -387,13 +432,13 @@ merchant backend: .. code-block:: ini - [MERCHANT]/SERVE = TCP | UNIX + [MERCHANT]/SERVE = tcp | unix -If given, +If this option is set to -- ``TCP``, then we need to set the TCP port in ``[MERCHANT]/PORT`` +- ``tcp`` then we need to set the TCP port in ``[MERCHANT]/PORT``; -- ``UNIX``, then we need to set the unix domain socket path and mode +- ``unix`` then we need to set the unix domain socket path and mode in ``[MERCHANT]/UNIXPATH`` and ``[MERCHANT]/UNIXPATH_MODE``. The latter takes the usual permission mask given as a number, e.g. 660 for user/group read-write access. @@ -407,7 +452,7 @@ To run the Taler backend on TCP port 8888, use: .. code-block:: console - $ taler-config -s MERCHANT -o SERVE -V TCP + $ taler-config -s MERCHANT -o SERVE -V tcp $ taler-config -s MERCHANT -o PORT -V 8888 .. note:: @@ -415,13 +460,12 @@ To run the Taler backend on TCP port 8888, use: When using the Debian/Ubuntu packages, these options are already configured in the ``/etc/taler/conf.d/merchant.conf`` configuration file. - If you need to change them, you should edit ``/etc/taler/merchant-overrides.conf``, - for example by passing ``-c /etc/taler/merchant-overrides.conf`` to the - ``taler-config`` commands above. By default, the Taler merchant - package when installed on Debian/Ubuntu will use a UNIX domain socket - at ``/run/taler/merchant-httpd/merchant-http.sock``. For the best possible - security, it is recommended to leave this in place and configure a reverse - proxy (nginx or Apache) as described below. + If you need to change them, you should edit + ``/etc/taler/merchant-overrides.conf``. By default, the Taler merchant + package will use a UNIX domain socket at + ``/run/taler/merchant-httpd/merchant-http.sock``. For the best possible + security it is recommended to leave this in place and configure a reverse + proxy (Nginx or Apache) as described below. @@ -435,9 +479,9 @@ specified using the option [TALER]/CURRENCY -For testing purposes, the currency MUST match “KUDOS” so that tests -will work with the Taler demonstration exchange at -https://exchange.demo.taler.net/: +When testing with the Taler demonstration exchange at +https://exchange.demo.taler.net/ you must set this +value to ``KUDOS``: .. code-block:: console @@ -471,23 +515,24 @@ DBMS-specific options to access the database. .. note:: - When using the Debian/Ubuntu packages, the database should already - be configured in the ``/etc/taler/secrets/merchant-db.secret.conf`` - configuration file. The ``talermerchant`` database is also already - configured (unless you answered ``no`` when asked the question during - installation), so you can skip everything in this section. + The **taler-merchant-dbconfig** tool can be used to automate the database + setup. When using the Debian/Ubuntu packages, the user should already have + been created, so you can just run the tool without any arguments and should + have a working database configuration. -For the ``postgres`` backend, you need to provide: + +For the ``postgres`` backend, you need to specify: .. code-block:: ini - [MERCHANTDB-postgres]/CONFIG + [MERCHANTDB-postgres] + CONFIG = "postgres://..." -This option specifies a postgres access path using the format -``postgres:///$DBNAME``, where ``$DBNAME`` is the name of the -PostgreSQL database you want to use. Suppose ``$USER`` is the name of -the user who will run the backend process. Then, you need to first -run: +This option specifies a PostgreSQL access path, typicallly using the format +``postgres:///$DBNAME``, where ``$DBNAME`` is the name of the PostgreSQL +database you want to use. Suppose ``$USER`` is the name of the user who will +run the backend process (usually ``taler-merchant-httpd``). Then, you need to +first run: .. code-block:: console @@ -504,30 +549,19 @@ as ``$USER`` run: to create the backend’s database. Here, ``$DBNAME`` must match the database name given in the configuration file. -To configure the Taler backend to use this database, run: - -.. code-block:: console - - $ taler-config -s MERCHANTDB-postgres -o CONFIG \ - -V postgres:///$DBNAME - -Now you should create the tables and indices. To do this, run as ``$USER``: +Now you should be able to create the tables and indices. To do this, run as +``$USER`` (usually ``taler-merchant-httpd``): .. code-block:: console $ taler-merchant-dbinit - -You can improve your security posture if you now REVOKE the rights to CREATE, +You may improve your security posture if you now REVOKE the rights to CREATE, DROP or ALTER tables from ``$USER``. However, if you do so, please be aware that you may have to temporarily GRANT those rights again when you update the merchant backend. For details on how to REVOKE or GRANT these rights, consult the PostgreSQL documentation. -Commands, like ``taler-merchant-dbinit``, that support the ``-l LOGFILE`` -command-line option, send logging output to standard error by default. -See :doc:`manpages/taler-merchant-dbinit.1` for more information. - .. include:: frags/db-stores-sensitive-data.rst @@ -543,95 +577,42 @@ section, the following options need to be configured: - The ``EXCHANGE_BASE_URL`` option specifies the exchange’s base URL. For example, to use the Taler demonstrator, specify: - .. code-block:: console + .. code-block:: ini - $ taler-config -s MERCHANT-EXCHANGE-demo \ - -o EXCHANGE_BASE_URL \ - -V https://exchange.demo.taler.net/ + [MERCHANT-EXCHANGE-demo] + EXCHANGE_BASE_URL = "https://exchange.demo.taler.net/" - The ``MASTER_KEY`` option specifies the exchange’s master public key in base32 encoding. For the Taler demonstrator, use: - .. code-block:: console + .. code-block:: ini - $ taler-config -s MERCHANT-EXCHANGE-demo \ - -o MASTER_KEY \ - -V FH1Y8ZMHCTPQ0YFSZECDH8C9407JR3YN0MF1706PTG24Q4NEWGV0 + [MERCHANT-EXCHANGE-demo] + MASTER_KEY = "FH1Y8ZMHCTPQ0YFSZECDH8C9407JR3YN0MF1706PTG24Q4NEWGV0" - The ``CURRENCY`` option specifies the exchange’s currency. For the Taler demonstrator, use: - .. code-block:: console + .. code-block:: ini + + [MERCHANT-EXCHANGE-demo] + CURRENCY = "KUDOS" - $ taler-config -s MERCHANT-EXCHANGE-demo \ - -o CURRENCY \ - -V KUDOS Note that multiple exchanges can be added to the system by using different -tokens in place of ``demo`` in the examples above. Note that all of the -exchanges must use the same currency: If the currency does not match the main -currency from the ``TALER`` section, the exchange is ignored. If you need to -support multiple currencies, you need to configure a backend per currency. +identifiers in place of ``demo`` in the example above. Note that all of the +exchanges actually used will use the same currency: If the currency does not +match the main ``CURRENCY`` option from the ``TALER`` section, the respective +``MERCHANT-EXCHANGE-`` section is automatically ignored. If you need support +for multiple currencies, you need to deploy one backend per currency. .. note:: Manually setting up exchanges is only recommended under special - circumstances. In general, GNU Taler will include trustworthy - auditors (for each currency) in the default configuration, and - there is rarely a good reason for trusting an exchange without - an accredited auditor. - - - -Auditor -^^^^^^^ - -To add an auditor to the list of trusted auditors (which implies -that all exchanges audited by this auditor will be trusted!) -you create a section with a name that starts with “MERCHANT-AUDITOR-”. In -4that section, the following options need to be configured: - -- The ``AUDITOR_BASE_URL`` option specifies the auditor’s base URL. - For example, to use the Taler demonstrator's auditor, specify: - - .. code-block:: console - - $ taler-config -s MERCHANT-AUDITOR-demo \ - -o AUDITOR_BASE_URL \ - -V https://exchange.demo.taler.net/ - -- The ``AUDITOR_KEY`` option specifies the auditor's public key - in base32 encoding. For the Taler demonstrator, use: - - .. code-block:: console - - $ taler-config -s MERCHANT-AUDITOR-demo \ - -o AUDITOR_KEY \ - -V DSDASDXAMDAARMNAD53ZA4AFAHA2QADAMAHHASWDAWXN84SDAA11 - -- The ``CURRENCY`` option specifies the auditor’s currency. - For the Taler demonstrator, use: - - .. code-block:: console - - $ taler-config -s MERCHANT-AUDITOR-demo \ - -o CURRENCY \ - -V KUDOS - - -Note that multiple auditors can be added to the system by using different -tokens in place of ``demo`` in the examples above. Note that all of the -auditors must use the same currency: If the currency does not match the main -currency from the ``TALER`` section, the auditor is ignored. If you need to -support multiple currencies, you need to configure a backend per currency. - -.. note:: - - Manually adding auditors is only recommended under special - circumstances. In general, GNU Taler will include trustworthy - auditors (for each currency) in the default configuration, and - there is rarely a good reason for adding an auditor that is - not coordinating its activities with the Taler developers. + circumstances. In general, GNU Taler distributions will include trustworthy + exchanges (for each currency) in the default configuration, and there is + rarely a good reason for trusting an exchange that has no relationship + with the GNU Taler development team. .. _Sample-backend-configuration: @@ -663,23 +644,13 @@ The following is an example for a complete backend configuration: # will be ignored! CURRENCY = KUDOS - [merchant-auditor-NAME] - AUDITOR_BASE_URL = https://auditor.demo.taler.net/ - AUDITOR_KEY = DSDASDXAMDAARMNAD53ZA4AFAHA2QADAMAHHASWDAWXN84SDAA11 - # If currency does not match [TALER] section, the auditor - # will be ignored! - CURRENCY = KUDOS - -Given the above configuration, the backend will use a database named -``donations`` within PostgreSQL. +Given the above configuration, the backend will use a PostgreSQL database +named ``donations`` running on the same host. The backend will deposit the coins it receives to the exchange at https://exchange.demo.taler.net/, which has the master key ``FH1Y8ZMHCTPQ0YFSZECDH8C9407JR3YN0MF1706PTG24Q4NEWGV0``. -Please note that ``doc/config.sh`` will walk you through all -configuration steps, showing how to invoke ``taler-config`` for each of -them. .. _Launching-the-backend: @@ -694,12 +665,21 @@ merchant backend as ``$USER`` using .. code-block:: console - $ taler-merchant-httpd + $ taler-merchant-httpd & + $ taler-merchant-webhook & + $ taler-merchant-wirewatch & + +You only need to run ``taler-merchant-webhook`` if one of the instances is +configured to trigger web hooks. Similarly, ``taler-merchant-wirewatch`` is +only required if instances have accounts configured with automatic import of +wire transfers via a bank wire gateway. -To ensure the process runs always in the background and also after rebooting, -you should use systemd, cron or some other init system of your operating -system to launch the process. Consult the documentation of your operating -system for how to start and stop daemons. +To ensure these processes runs always in the background and also after +rebooting, you should use systemd, cron or some other init system of your +operating system to launch the process. You should also periodically re-start +these services to prevent them from exhausing the memory utilization of the +PostgreSQL database. Consult the documentation of your operating system for +how to start and stop daemons. .. note:: @@ -723,7 +703,8 @@ If everything worked as expected, the command should return some basic configuration status data about the service. -Please note that your backend is right now likely globally reachable. You can either: +Please note that your backend might then be globally reachable without +any access control. You can either: * Use the ``--auth=$TOKEN`` command-line option to set an access token to be provided in an ``Authorize: Bearer $TOKEN`` HTTP header. Note that this can be used at anytime to override access control, but remains only in effect until a first instance is created or an existing instance authentication setting is modified. * Set the ``TALER_MERCHANT_TOKEN`` environment variable to ``$TOKEN`` for the same effect. This method has the advantage of ``$TOKEN`` not being visible as a command-line interface to other local users on the same machine. @@ -736,98 +717,72 @@ and use TLS for improved network privacy, see :ref:`Secure setup <Secure-setup>` .. index:: instance .. _Instance-setup: + Instance setup ============== First of all, we recommend the use of the single-page administration -application that is served by default at the base URL of the merchant backend. -You can use it to perform all steps described in this section (and more!), -using a simple Web interface instead of the ``wget`` commands given below. - -The first step for using the backend involves the creation of a ``default`` -instance. The ``default`` instance can also create / delete / configure other -instances, similar to the ``root`` account on UNIX. When no instance exists -and ``taler-merchant-httpd`` was started without the ``--auth`` option, then -the backend is reachable without any access control (unless you configured -some in the reverse proxy). +application (SPA) that is served by default at the base URL of the merchant +backend. You can use it to perform all steps described in this section (and +more!), using a simple Web interface instead of the ``wget`` commands given +below. + +Regardless of which tool you use, the first step for using the backend +involves the creation of a ``default`` instance. The ``default`` instance can +also create / delete / configure other instances, similar to the ``root`` +account on UNIX. When no instance exists and ``taler-merchant-httpd`` was +started without the ``--auth`` option, then the backend is reachable without +any access control (unless you configured some in the reverse proxy). The following documentation shows how to handle any instance. Thus, if you want to have multiple instances, you may need to perform the steps multiple times, once for each instance. .. note:: - A security concern is that normal API usage leaks instance existence. + + A potential security concern is that normal API usage leaks instance existence. This means unauthorized users can distinguish between the case where the instance does not exist (HTTP 404) and the case where access is denied (HTTP 403). - This is all moot behind a properly configured + This is concern can be addressed using a properly configured :ref:`reverse proxy <reverse-proxy-configuration>`. -KUDOS Accounts --------------- - -The main configuration data that must be provided for each instance -is the bank account information. - -In order to receive payments, the merchant backend needs to -communicate bank account details to the exchange. - -The bank account information is provided in the form of a ``payto://``-URI. -See `RFC 8905 <https://tools.ietf.org/html/rfc8905>`_ -for the format of ``payto://``-URIs. - -For first tests, you should sign up for a KUDOS bank -account at `https://bank.demo.taler.net/ <https://bank.demo.taler.net/>`_. -In this case, the ``payto://``-URI will be of the form -``payto://x-taler-bank/bank.demo.taler.net/$USERNAME`` where ``$USERNAME`` -must be replaced with the name of the account that was established -at `https://bank.demo.taler.net/ <https://bank.demo.taler.net/>`_. +Setup without the Web interface +------------------------------- - -IBAN Accounts -------------- - -When deploying Taler with the real banking system, you primarily need to -change the currency of the configuration from KUDOS to the actual currency -(such as EUR, USD, CHF) and provide a ``payto://``-URI of your real bank -account. In Europe, this will involve knowing your IBAN number. If you have an -IBAN, the corresponding ``payto://``-URI is simply ``payto://iban/$IBAN`` where -``$IBAN`` must be replaced with the actual IBAN number. - - -Setup ------- - -With the knowledge of the ``payto://``-URI, instances can be configured by POSTing -a request to ``/management/instances``. To create a first instance, -create a file ``instance.json`` with an `InstanceConfigurationMessage` +Instances can be created by POSTing a request to ``/management/instances`` +without using the Web interface. This could be useful if you want to create +many instances programmatically. To create an instance without the Web +interface create a file ``instance.json`` with an +`InstanceConfigurationMessage`: .. code-block:: json { - "payto_uris" : [ "$PAYTO_URI" ], + "accounts" : [{"payto_uri":"$PAYTO_URI"}], "id" : "default", "name": "example.com", "address": { "country" : "zz" }, "auth": { "method" : "external"} , "jurisdiction": { "country" : "zz" }, - "default_max_wire_fee": "KUDOS:1", - "default_wire_fee_amortization": 100, - "default_max_deposit_fee": "KUDOS:1", + "use_stefan": true, "default_wire_transfer_delay": { "d_ms" : 1209600000 }, "default_pay_delay": { "d_ms" : 1209600000 } } In the text above, you must replace ``$PAYTO_URI`` with your actual -``payto://``-URI. Also, be sure to replace ``KUDOS`` with the fiat currency if the -setup is for an actual bank. The ``name`` field will be shown as the name of -your shop. The ``address`` field is expected to contain your shop's physical -address. The various defaults specify defaults for transaction fees your shop -is willing to cover, how long offers made to the customer are valid, and how -long the exchange has before it must wire the funds to your bank -account. Those defaults can be modified for individual orders. -For details, see the :ref:`contract terms <contract-terms>` specification. +``payto://``-URI. You may also leave the account array empty. The instance +owner must then configure the accounts before the instance becomes usable. + +Be sure to replace ``KUDOS`` with the fiat currency if the setup is for an +actual bank. The ``name`` field will be shown as the name of your shop. The +``address`` field is expected to contain your shop's physical address. The +various defaults specify defaults for transaction fees your shop is willing to +cover, how long offers made to the customer are valid, and how long the +exchange has before it must wire the funds to your bank account. Those +defaults can be modified for individual orders. For details, see the +:ref:`contract terms <contract-terms>` specification. You can then create the instance using: @@ -852,11 +807,11 @@ Secure setup .. index:: security .. index:: TLS -The Taler backend does not include even the most basic forms of -access control or transport layer security. Thus, production -setups **must** deploy the Taler backend behind an HTTP(S) server -that acts as a *reverse proxy*, performs TLS termination and -authentication and then forwards requests to the backend. +The Taler backend does not include even the most basic forms of access control +or transport layer security. Thus, production setups **must** deploy the +Taler backend behind an HTTP(S) server that acts as a *reverse proxy*, +performs TLS termination and authentication and then forwards requests to the +backend. Using UNIX domain sockets ------------------------- @@ -866,8 +821,8 @@ you *should* bind the backend to a UNIX domain socket: .. code-block:: console - $ taler-config -s MERCHANT -o SERVE -V UNIX - $ taler-config -s MERCHANT -o UNIXPATH -V /some/path/here.sock + $ taler-config -s MERCHANT -o SERVE -V unix + $ taler-config -s MERCHANT -o UNIXPATH -V "/some/path/here.sock" Do not use a UNIX domain socket path in "/tmp": systemd (or other init systems) may give Web servers a private "/tmp" thereby hiding UNIX domain @@ -875,8 +830,9 @@ sockets created by other users/processes in "/tmp". If UNIX domain sockets are for some reason not possible, you *may* use a host-based firewall to block access to the TCP port of the merchant backend, -but this is *not recommended*. Relying on NAT or network firewalls for access -control is gross negligence. +but this is *not recommended*. If you do need a TCP socket, you should +instead strongly consider using the "BIND_TO" option to at least bind it only +to "localhost". .. _reverse-proxy-configuration: @@ -927,167 +883,33 @@ Note that the above again assumes your domain name is ``example.com`` and that you have TLS configured. Note that you must add the ``https`` header unless your site is not available via TLS. -The above configurations are both incomplete. You must still additionally -set up access control! - Access control -------------- All endpoints with ``/private/`` in the URL must be restricted to authorized users of the respective instance. Specifically, the HTTP server must be -configured to only allow access to ``$BASE_URL/private/`` and -``$BASE_URL/management/`` to the authorized users of the default instance, and -to ``$BASE_URL/instances/$ID/private/`` to the authorized users of the instance -``$ID``. +configured to only allow access to ``$BASE_URL/private/`` to the authorized +users of the default instance, and to ``$BASE_URL/instances/$ID/private/`` to +the authorized users of the instance ``$ID``. -How access control is done (TLS client authentication, HTTP basic or digest -authentication, etc.) is completely up to the merchant and does not matter to -the Taler merchant backend. +By default, the GNU Taler merchant backend simply requires the respective +HTTP requests to include an "Authorization" header with a "Bearer" token +set to the respective shared secret which must begin with "secret-token:" +(following RFC 8959). -Note that all of the other endpoints (without ``/private/`` or ``/management/``) +Note that all of the other endpoints (without ``/private/``) are expected to be fully exposed to the Internet, and wallets may have to interact with those endpoints directly without client authentication. -Nginx -^^^^^ - -For Nginx, you can implement token-based merchant backend authentication as -follows: - -.. code-block:: nginx - - location ~ /private/ { - if ($http_authorization !~ "(?i)ApiKey SECURITYTOKEN") { - return 401; - } - proxy_pass ...; # as above - } - location /management/ { - if ($http_authorization !~ "(?i)ApiKey SECURITYTOKEN") { - return 401; - } - proxy_pass ...; # as above - } - -Here, ``SECURITYTOKEN`` should be replaced with the actual shared secret. Note -that the ``~`` ensures that the above matches all endpoints that include the -string ``/private/``. If you only run a single instance, you could simply -specify ``/private/`` without the ``~`` to only configure the access policy for -the default instance. - -If you are running different instances on the same backend, you -likely will want to specify different access control tokens for -each instance: - -.. code-block:: nginx - - location ~ ^/instances/foo/private/ { - if ($http_authorization !~ "(?i)ApiKey FOOTOKEN") { - return 401; - } - proxy_pass ...; # as above - } - location ~ ^/instances/bar/private/ { - if ($http_authorization !~ "(?i)ApiKey BARTOKEN") { - return 401; - } - proxy_pass ...; # as above - } - location /private/ { - if ($http_authorization !~ "(?i)ApiKey MASTERTOKEN") { - return 401; - } - proxy_pass ...; # as above - } - location /management/ { - if ($http_authorization !~ "(?i)ApiKey MASTERTOKEN") { - return 401; - } - proxy_pass ...; # as above - } - location ~ /private/ { - return 401; # access to instances not explicitly configured is forbidden - } - -Apache -^^^^^^ - -For Apache, you should first enable ``mod_rewrite``: - -.. code-block:: console - - $ a2enmod rewrite - -Then, you can restrict to an access control token using: - -.. code-block:: apacheconf - - <Location "/"> - RewriteEngine On - RewriteCond "%{HTTP:AUTHORIZATION}" "!=SECURITYTOKEN" - RewriteRule "(.+)/private/" "-" [F] - RewriteRule "/management/" "-" [F] - - ProxyPass "unix:/some/path/here.sock|http://example.com/" - </Location> - -Here, ``SECURITYTOKEN`` should be replaced with the actual shared secret. Note -that the ``(.+)`` ensures that the above matches all endpoints that include the -string ``/private/``. If you only run a single instance, you could simply -specify ``/private/`` without the ``(.+)`` to only configure the access policy for -the default instance. - -If you are running different instances on the same backend, you -likely will want to specify different access control tokens for -each instance: - -.. code-block:: apacheconf - - <Location "/instances/foo/"> - RewriteEngine On - RewriteCond "%{HTTP:AUTHORIZATION}" "!=FOOTOKEN" - RewriteRule "/instances/foo/private/" "-" [F] - - ProxyPass ... # as above - </Location> - - <Location "/instances/bar/"> - RewriteEngine On - RewriteCond "%{HTTP:AUTHORIZATION}" "!=BARTOKEN" - RewriteRule "/instances/bar/private/" "-" [F] - - ProxyPass ... # as above - </Location> - - <Location "/"> - RewriteEngine On - RewriteCond "%{HTTP:AUTHORIZATION}" "!=MASTERTOKEN" - RewriteRule "/private/" "-" [F] - RewriteRule "/management/" "-" [F] - RewriteRule "(.+)/private/" "-" [F] # reject all others - - ProxyPass ... # as above - </Location> - -Please note that these are simply examples of how one could use Nginx or -Apache2 for access control. Both HTTP servers support many other forms of -authentication, including TLS client certificates, HTTP basic and digest -authentication and others, which can all be used (possibly in combination) to -restrict access to the internal API to authorized clients. - -System administrators are strongly advised to test their access control -setup before going into production! Status code remapping --------------------- -Normal API usage leaks instance existence information. -Distinguishing between 404 (Not found) and 403 (Forbidden) -is useful for diagnostics. +Normal API usage leaks instance existence information. Distinguishing between +404 (Not found) and 403 (Forbidden) is useful for diagnostics. -For higher security (by leaking less information), -you can add the following fragment, -which remaps all 404 response codes to 403. +For higher security (by leaking less information), you can add the following +fragment, which remaps all 404 response codes to 403. Nginx ^^^^^ @@ -1108,8 +930,14 @@ Apache Customization ============= -Templates ---------- +Legal conditions for using the service +-------------------------------------- + +.. include:: frags/legal.rst + + +Mustach HTML Templates +---------------------- The installation process will install various HTML templates to be served to trigger the wallet interaction. You may change those templates to your @@ -1146,7 +974,8 @@ Limitations All of the static files must fit into memory and it must be possible for the process to hold open file handles for all of these files. You may want to increase the ``ulimit`` of the ``taler-merchant-httpd`` process if you have -templates for many languages. +many static files. Note that Mustach templates do not increase the number of +open files. The backend determines the MIME type based on the file's extension. The list of supported extensions is hard-coded and includes common text and image @@ -1161,8 +990,8 @@ features. Upgrade procedure ================= -This is the general upgrade procedure. Please see the release notes -for your specific version to check if a particular release has special +This section describes the general upgrade procedure. Please see the release +notes for your specific version to check if a particular release has special upgrade requirements. Please note that upgrades are ONLY supported for released version of the @@ -1181,119 +1010,8 @@ DROP, and ALTER tables are GRANTed to ``$USER`` again. Then, run: $ taler-merchant-dbinit to upgrade the database to the latest schema. After that, you may again -REVOKE the database permissions. Finally, restart the HTTP service, either via -your systemd or init system, or directly using: - -.. code-block:: console - - $ taler-merchant-httpd - - -.. _Tipping-visitors: - -Tipping visitors -================ - -.. index:: tipping - -Taler can also be used to tip Web site visitors. For example, you may be -running an online survey, and you want to reward those people that have -dutifully completed the survey. If they have installed a Taler wallet, -you can provide them with a tip for their deeds. This section describes -how to setup the Taler merchant backend for tipping. - -There are three basic steps that must happen to tip a visitor. - -.. _Fund-the-reserve: - -Fund the reserve ----------------- - -.. index:: reserve - -First, the reserve must be setup in the merchant backend. A reserve -is always tied to a particular instance. To create a reserve with -10 KUDOS at instance ``default`` using the demo exchange, use: - -.. code-block:: console - - $ taler-merchant-setup-reserve \ - -a KUDOS:10 \ - -e https://exchange.demo.taler.net/ \ - -m http://localhost:8888/instances/default - -The above command assumes that the merchant runs on localhost on -port 8888. -For more information, including how to transmit authentication information -to the backend, see :doc:`manpages/taler-merchant-setup-reserve.1`. - -The command will output a ``payto://`` URI which specifies where to -wire the funds and which wire transfer subject to use. - -FIXME: add full example output. - -In our example, the output for the wire transfer subject is: - -.. code-block:: none - - QPE24X8PBX3BZ6E7GQ5VAVHV32FWTTCADR0TRQ183MSSJD2CHNEG - -You now need to make a wire transfer to the exchange’s bank account -using the given wire transfer subject. - -Make your wire transfer and (optionally) check at -“https://exchange/reserves/QPE24X...” whether your transfer has arrived at the -exchange. - -Once the funds have arrived, you can start to use the reserve for -tipping. - -Note that an exchange will typically close a reserve after four weeks, wiring -all remaining funds back to the sender’s account. Thus, you should plan to -wire funds corresponding to a campaign of about two weeks to the exchange -initially. If your campaign runs longer, you should setup another reserve -every other week to ensure one is always ready. - -.. _Authorize-a-tip: - -Authorize a tip ---------------- - -When your frontend has reached the point where a client is supposed to receive -a tip, it needs to first authorize the tip. For this, the frontend must use -a POST to ``/private/reserves/$RESERVE_PUB/authorize-tip``. To authorize a -tip, the frontend has to provide the following information in the body of the -POST request: - -- The amount of the tip - -- The justification (only used internally for the back-office) - -- The URL where the wallet should navigate next after the tip was - processed - -- The tip-pickup URL (see next section) - -In response to this request, the backend will return a tip token, an -expiration time and the exchange URL. The expiration time will indicate -how long the tip is valid (when the reserve expires). The tip token is -an opaque string that contains all the information needed by the wallet -to process the tip. The frontend must send this tip token to the browser -in a special “402 Payment Required” response inside the ``X-Taler-Tip`` -header. - -The frontend should handle errors returned by the backend, such as -misconfigured instances or a lack of remaining funds for tipping. - -.. _Picking-up-of-the-tip: - -Picking up of the tip ---------------------- - -The wallet will POST a JSON object to the shop’s -``/tips/$TIP_ID/pickup`` handler. -The frontend must then forward this request to the backend. The response -generated by the backend can then be forwarded directly to the wallet. +REVOKE the database permissions. Finally, restart the merchant services +processes, either via your systemd or init system, or directly. @@ -1315,159 +1033,46 @@ allowing administrators to purge records that are no longer required. The database scheme used by the merchant looks as follows: -.. image:: merchant-db.png - - - -Configuration format --------------------- - -.. index:: configuration - -In Taler realm, any component obeys to the same pattern to get -configuration values. According to this pattern, once the component has -been installed, the installation deploys default values in -``${prefix}/share/taler/config.d/``, in ``.conf`` files. In order to override -these defaults, the user can write a custom .conf file and either pass -it to the component at execution time, or name it ``taler.conf`` and place -it under ``$HOME/.config/``. - -A config file is a text file containing sections, and each section -contains its values. The right format follows: - -.. code-block:: ini - - [section1] - value1 = string - value2 = 23 +.. image:: images/merchant-db.png - [section2] - value21 = string - value22 = /path22 - -Throughout any configuration file, it is possible to use ``$``-prefixed -variables, like ``$VAR``, especially when they represent filesystem -paths. It is also possible to provide defaults values for those -variables that are unset, by using the following syntax: -``${VAR:-default}``. However, there are two ways a user can set -``$``-prefixable variables: - -by defining them under a ``[paths]`` section, see example below, - -.. code-block:: ini - - [paths] - TALER_DEPLOYMENT_SHARED = ${HOME}/shared-data - ... - [section-x] - path-x = ${TALER_DEPLOYMENT_SHARED}/x - -or by setting them in the environment: - -.. code-block:: console - - $ export VAR=/x - -The configuration loader will give precedence to variables set under -``[path]``, though. - -The utility ``taler-config``, which gets installed along with the -exchange, serves to get and set configuration values without directly -editing the ``.conf``. The option ``-f`` is particularly useful to resolve -pathnames, when they use several levels of ``$``-expanded variables. See -``taler-config --help``. - -Note that, in this stage of development, the file -``$HOME/.config/taler.conf`` can contain sections for *all* the -components. For example, both an exchange and a bank can read values from -it. - -The `deployment repository <https://git.taler.net/deployment>`_ contains examples of -configuration file used in our demos. See under ``deployment/config``. - - **Note** - - Expectably, some components will not work just by using default - values, as their work is often interdependent. For example, a - merchant needs to know an exchange URL, or a database name. - -.. _Using-taler_002dconfig: - -Using taler-config -^^^^^^^^^^^^^^^^^^ - -.. index:: taler-config - -The tool ``taler-config`` can be used to extract or manipulate -configuration values; however, the configuration use the well-known INI -file format and can also be edited by hand. - -Run: - -.. code-block:: console - - $ taler-config -s $SECTION - -to list all of the configuration values in section ``$SECTION``. - -Run: +.. _MerchantBenchmarking: -.. code-block:: console +Benchmarking +------------ - $ taler-config -s $section -o $option +The merchant codebase offers the ``taler-merchant-benchmark`` tool to populate +the database with fake payments. The main goal of the benchmarking tool is to +serve as a starting point (!) for merchants that are interested in developing +stress tests to see how far their infrastructure can scale. As is, it +currently is not actually good at stressing the payment system. -to extract the respective configuration value for option ``$option`` in -section ``$section``. +The ``taler-unified-setup.sh`` script can be used to launch all required +services and clients. However, the resulting deployment is simplistic +(everything on the local machine, one single-threaded process per service +type) and not optimized for performance at all. However, this can still be +useful to assess the performance impact of changes +to the code or configuration. -Finally, to change a setting, run: -.. code-block:: console +Various configuration files that can be used in the code snippets in this +section can be found in the ``src/merchant-tools/`` directory of the +merchant. These are generally intended as starting points. Note that the +configuration files ending in ``.edited`` are created by +``taler-unified-setup.sh`` and contain some options that are determined at +runtime by the setup logic provided by ``taler-unified-setup.sh``. - $ taler-config -s $section -o $option -V $value +See :ref:`Taler Exchange Manual <Benchmark-choose-bank>` for how to use ``taler-unified-setup.sh`` to setup the system and in particular on how to specify the bank to be used. -to set the respective configuration value to ``$value``. Note that you -have to manually restart the Taler backend after you change the -configuration to make the new configuration go into effect. +Running taler-merchant-benchmark +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Some default options will use ``$``-variables, such as ``$DATADIR`` within -their value. To expand the ``$DATADIR`` or other ``$``-variables in the -configuration, pass the ``-f`` option to ``taler-config``. For example, -compare: +You can run the tool as follows: .. code-block:: console - $ taler-config -s PATHS \ - -o TALER_DATA_HOME - $ taler-config -f -s PATHS \ - -o TALER_DATA_HOME - -While the configuration file is typically located at -``$HOME/.config/taler.conf``, an alternative location can be specified -to ``taler-merchant-httpd`` and ``taler-config`` using the ``-c`` -option. - - - -Advanced experimental features -============================== - -This section describes features that most merchants will not -need, or will not need initially. - -.. _MerchantBenchmarking: - -Benchmarking ------------- - -The merchant codebase offers the ``taler-merchant-benchmark`` tool to -populate the database with fake payments. This tool is in charge of -starting a merchant, exchange, and bank processes, and provides them all -the input to accomplish payments. Note that each component will use its -own configuration (as they would do in production). - -The main goal of the benchmarking tool is to serve as a starting point (!) for -merchants that are interested in developing stress tests to see how far their -infrastructure can scale. + $ CONF=benchmark-rsa.conf + $ taler-unified-setup.sh -emwt -c "$CONF" -f -u exchange-account-1 + $ time taler-merchant-benchmark ordinary -c "$CONF".edited -u exchange-account-1 -f -p 20 The current tool has already a few options, but we expect that to deliver *relevant* results it will need to be customized to better reflect the @@ -1476,47 +1081,16 @@ likely involve writing (C) code. We welcome contributions to make it easier to customize the benchmark and/or to cover more realistic workloads from the start. - -Benchmark setup ---------------- - -The ``taler-merchant-benchmark`` tool will automatically launch and configure the -exchange, (Python) bank and other tools required for the benchmark. However, -the configuration file must be provided and have consistent options set. The -options that require special care include the exchange's public key (which -must match the private key in the file specified by the configuration), the -currency (which must be consistent across the file), the denomination -structure (which must enable payments in the range of 100ths of the unit -currency (often called cents)). Furthermore, the benchmark will set the -Exchange bank account password to be "x", so the configuration must also -specify "x" for the passphrase. Finally, the bank must be configured to allow -for substantial debt least the transactions by the benchmark run out of -digital cash. - -A relatively minimal configuration could look like this: - -.. literalinclude:: merchant-benchmark.conf - - -Note that the public key must match the exchange's -private key and that the PostgreSQL database must -exist before launching the benchmark. You also -will need to ensure that the Exchange's -details are set up. -For details, see the :ref:`Exchange Operator Manual <Bank-account>`. - - -Running the benchmark command ------------------------------ - The tool takes all of the values it needs from the command line, with -one of them being mandatory: +some of them being common to all subcommands: -- ``--exchange-account=SECTION`` Specifies which configuration +- ``--exchange-account-section=SECTION`` Specifies which configuration section specifies the bank account for the exchange that should be used for the benchmark. For the example configuration above, the SECTION value provided must be ``exchange-account-exchange``. +- ``--fakebank`` Specifies that the benchmark should expect to interact + with a fakebank (instead of libeufin). The tool comes with two operation modes: *ordinary*, and *corner*. The first just executes normal payments, meaning that it uses the @@ -1547,17 +1121,11 @@ interesting, there are: perform *UN* (one coin) payments that will be left unaggregated. As for the ``ordinary`` subcommand, it is worth explaining the following -options: +option: - ``--payments-number=PN`` Instructs the tool to perform *PN* payments. -- ``--tracks-number=TN`` Instructs the tool to perform *TN* tracking - operations. Note that the **total** amount of operations will be two - times *TN*, since "one" tracking operation accounts for - ``/track/transaction`` and ``/track/transfer``. This command should - only be used to see if the operation ends without problems, as no - actual measurement of performance is provided (despite of the - ’benchmark’ word used in the tool’s name). + diff --git a/taler-merchant-pos-terminal.rst b/taler-merchant-pos-terminal.rst @@ -53,6 +53,7 @@ At the bottom of the main UI there is a row of buttons: * Prev: Goes to the previous order (if available). * Next: Goes to the next order or creates a new one if the current is not empty and there is no next. +* Data entry: Enter a product name and price manually. * Complete: Finalize an order and prompt the customer to pay. The top left corner features a hamburger icon. @@ -123,12 +124,9 @@ The elements of the JSON file are defined as follows: .. ts:def:: BackendConfiguration interface BackendConfiguration { - // The URL to the Taler Merchant Backend + // The URL to the Taler Merchant Backend (including instance if applicable) base_url: string; - // The name of backend instance to be used (see `Backend Options <Backend-options>`) - instance: string; - // The API key used for authentication api_key: string; } diff --git a/taler-nfc-guide.rst b/taler-nfc-guide.rst @@ -1,285 +0,0 @@ -GNU Taler NFC Guide -################### - -This guide explains how NFC (near-field communication) is -used in the GNU Taler payment system. - -Introduction -============ - -NFC is currently used for two different purposes: - -1. Operations in the wallet (payment, withdrawal, ...) can be triggered by a - merchant PoS (Point-of-Sale) terminal or Taler-capable ATM. -2. When either the wallet or the merchant do not have Internet connectivity, - the protocol messages to the exchange or merchant backend service can be - tunneled via NFC through the party that has Internet connectivity. - - -Background: Payment Processing with GNU Taler -============================================= - -The following steps show a simple payment process with GNU Taler. Examples are -written in `Bash <https://www.gnu.org/software/bash/>`_ syntax, -using `curl <https://curl.haxx.se/docs/manpage.html>`_ to make HTTP(S) requests. -They make use of the :http:post:`[/instances/$INSTANCE]/private/orders` -and :http:get:`[/instances/$INSTANCE]/private/orders` endpoints. - -1. The merchant creates an *order*, which contains the details of the payment - and the product/service that the customer will receive. - An order is identified by an alphanumeric *order ID*. - - The *fulfillment URL* is an URL that the wallet will redirect the customer - to once the payment is complete. For digital products, this is typically an - ``https(s)://`` URL that renders the purchased content. For physical - products and in-store purchases, a ``taler://fulfillment-success/<message>`` - URL should be specified instead. The wallet will display the URL-encoded - UTF-8 text ``<message>`` when the payment has succeeded. - - .. hint:: - - When an ``http(s)://`` URL is used as the fulfillment URL in an in-store / NFC payment, - the user might not be able to view the page, as request tunneling only works for requests - made by the wallet to the merchant backend / exchange. - - In these situations, wallets should display to the user that a page to view the purchase - can be opened, and give a warning if it is detected that the devices does not have Internet - connectivity. - - The following POST ``/private/orders`` request to the merchant backend creates a - simple order: - - .. code-block:: console - - $ backend_base_url=https://backend.demo.taler.net/ - $ auth_header='Authorization: ApiKey sandbox' - $ order_req=$(cat <<EOF - { - "order": { - "summary": "one ice cream", - "amount": "KUDOS:1.5", - "fulfillment_url": - "taler://fulfillment-success/Enjoy+your+ice+cream!" - } - } - EOF - ) - $ curl -XPOST -H"$auth_header" -d "$order_req" "$backend_base_url"/private/orders - { - "order_id": "2019.255-02YDHMXCBQP6J" - } - -2. The merchant checks the payment status of the order using - GET ``/private/orders/$ORDER_ID``: - - .. code-block:: console - - $ backend_base_url=https://backend.demo.taler.net/ - $ auth_header='Authorization: ApiKey sandbox' - $ curl -XGET -H"$auth_header" \ - "$backend_base_url/private/orders/2019.255-02YDHMXCBQP6J" - # Response: - { - "taler_pay_uri": "taler://pay/backend.demo.taler.net/-/-/2019.255-02YDHMXCBQP6J", - "paid": false, - # ... (some fields omitted) - } - - As expected, the order is not paid. To actually proceed with the payment, the value of ``taler_pay_uri`` - must be processed by the customer's wallet. There are multiple ways for the wallet to obtain the ``taler://pay/`` URI - - * in a QR code - * in the ``Taler:`` HTTP header of a Web site - * by manually entering it in the command-line wallet - * **via NFC** (explained in this guide) - - The details of ``taler://`` URIs are specified in :ref:`LSD 0006 <https://lsd.gnunet.org/lsd0006/>`_. - -3. The wallet processes the ``taler://pay/`` URI. In this example, we use the - command-line wallet: - - .. code-block:: console - - # Withdraw some toy money (KUDOS) from the demo bank - $ taler-wallet-cli test-withdraw \ - -e https://exchange.demo.taler.net/ \ - -b https://bank.demo.taler.net/ \ - -a KUDOS:10 - # Pay for the order from the merchant. - $ taler-wallet-cli pay-uri 'taler://pay/backend.demo.taler.net/-/-/2019.255-02YDHMXCBQP6J' - # [... User is asked to confirm the payment ...] - - .. hint:: - - The command-line wallet is typically used by developers and not by end-users. - See the :ref:`wallet manual <command-line-wallet>` for installation instructions. - - -4. The merchant checks the payment status again: - - .. code-block:: console - - $ backend_base_url=https://backend.demo.taler.net/ - $ auth_header='Authorization: ApiKey sandbox' - $ curl -XGET -H"$auth_header" \ - "$backend_base_url/private/orders/2019.255-02YDHMXCBQP6J" - # Response: - { - "paid": true, - # ... (some fields omitted) - } - - .. note:: - - When paying for digital products displayed on a Web site identified by the - fulfillment URL, the merchant only needs to check the payment status - before responding with the fulfillment page. - - For in-store payments, the merchant must periodically check the payment status. - Instead of polling in a busy loop, the ``timeout_ms`` parameter - of GET ``/private/orders/$ORDER_ID`` - should be used. - - -Taler NFC Basics -================ - -The NFC communication in GNU Taler follows the ISO-DEP (`ISO 14443-4 -<https://www.iso.org/standard/73599.html>`_) standard. The wallet always acts -as a tag (or more precisely, emulated card), while the merchant PoS terminal -and bank terminal act as a reader. - -The basic communication unit is the application protocol data unit (`APDU -<https://en.wikipedia.org/wiki/Smart_card_application_protocol_data_unit>`_), with the structure -and commands defined in `ISO 7816 <https://cardwerk.com/iso-7816-smart-card-standard>`_. - -The GNU Taler wallet uses the AID (application identifier) ``F00054414c4552``. -The ``F`` prefix indicates the proprietary/unregistered namespace of AIDs, and -the rest of the identifier is the hex-encoded ASCII-string ``TALER`` (with one -0-byte left padding). - -During the time that the wallet is paired with a reader, there is state -associated with the communication channel. Most importantly, the first message -sent by the reader to the wallet must be a ``SELECT FILE (=0xA4)`` that selects -the GNU Taler AID. Messages that are sent before the correct ``SELECT FILE`` -message results in implementation-defined behavior, such as the tag disconnecting, -ignoring the message or an app other than the wallet receiving the message. - -The reader sends commands to the wallet with the ``PUT DATA (=0xDA)`` -instruction, using the instruction parameters ``0x0100``, denoting a -proprietary instruction. - -The command data of the ``PUT DATA`` APDU is prefixed by a one-byte Taler -instruction ID (TID). Currently, the following TIDs are used: - -.. list-table:: - :widths: 5 50 - :header-rows: 1 - - * - TID (reader to wallet) - - Description - * - ``0x01`` - - Dereference the UTF-8 encoded ``taler://`` URI in the remainder of the command data. - * - ``0x02`` - - Accept the UTF-8 encoded JSON object in the remainder of the command data as a request tunneling response. - - -The ``GET DATA (=0xCA)`` instruction (again with the instruction parameters -``0x0100`` is used to request a command from the wallet. The APDU with this -instruction must be sent with a ``0x0000`` trailer to indicate that up to 65536 -bytes of data are expected in the response from the wallet. Note that the -wallet itself cannot initiate communication, and thus the reader must "poll" -the wallet for commands. - -The response to the ``GET DATA`` instruction has a Taler instruction ID in the -first byte. The rest of the -body is interpreted depending on the TID. - -.. list-table:: - :widths: 15 50 - :header-rows: 1 - - * - TID - (wallet to reader) - - Description - * - ``0x03`` - - Accept the UTF-8 encoded JSON object in the remainder of the command data as a request tunneling request. - - -Sending taler:// URIs to the Wallet via NFC -=========================================== - -To make the wallet process a ``taler://`` URI via NFC, the merchant PoS -terminal sends a ``SELECT FILE`` command with the GNU Taler AID, and a ``PUT -DATA`` command with TID ``0x01`` and the URI in the rest -of the command data. - -Here is an example protocol trace from an interaction which caused the wallet -to dereference the ``taler://pay`` URI from the example above: - -.. code-block:: none - - # SELECT FILE - m->w 00A4040007F00054414c4552 - # success response with no data - m<-w 9000 - - # PUT DATA (TID=0x01) - m->w 00DA01007c0174616c65723a2f2f7061792f6261636b656e642e64656d6f2e74 - 616c65722e6e65742f2d2f2d2f323031392e3235352d30325944484d58434251 - 50364a - # success response with no data - m<-w 9000 - -(Note that this process works analogously for communication between a bank/ATM -terminal or "tipping provider".) - - -Request tunneling -================= - -Request tunneling allows tunneling a (very) restricted subset of HTTP through -NFC. In particular, only JSON request and response bodies are allowed. - -It is currently assumed that the requests and responses fit into one APDU frame. -For devices with more limited maximum APDU sizes, additional TIDs for segmented -tunnel requests/responses may be defined in the future. - -A request for tunneling is initiated with TID ``0x03`` and responded to with -TID ``0x02`` (see tables above). A tunneling request is identified by a -numeric ID, which must be unique during one pairing between reader and tag. - -The request tunneling request/response JSON messages have the following schema: - -.. code-block:: tsref - - interface TalerRequestTunnelRequest { - // Identifier for the request - id: number; - - // Request URL - url: string; - - // HTTP method to use - method: "post" | "get"; - - // Request headers - headers?: { [name: string]: string }; - - // JSON body for the request, only applicable to POST requests - body?: object; - } - - interface TalerRequestTunnelResponse { - // Identifier for the request - id: number; - - // Response HTTP status code, - // "0" if there was no response. - status: number; - - // JSON body of the response, or undefined - // if the response wasn't JSON. - // May contain error details if 'status==0' - body?: object; - } diff --git a/taler-user-guide.rst b/taler-user-guide.rst @@ -0,0 +1,432 @@ +.. + This file is part of GNU TALER. + Copyright (C) 2014-2023 Taler Systems SA + + TALER 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 2.1, or (at your option) any later version. + + TALER 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 + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + + @author Christian Grothoff + + +GNU Taler User Guide +#################### + +Introduction +============ + +About GNU Taler +--------------- + +.. include:: frags/about-taler.rst + + +About this guide +---------------- + +This guide explains various ways how users can interact with a GNU Taler +installation. It assumes that a bank, exchange and merchant backend are +running and that the user has a GNU Taler wallet installed is able to create +an account at the bank. Some operations also require access to the merchant +backend. + + +Withdrawing +=========== + +Withdrawing is the step where money is moved from a bank account into +a GNU Taler wallet. There are two main ways to do this. + +Bank integrated withdrawal +-------------------------- + +If the bank supports it, you can withdraw money into your GNU Taler wallet +directly from your banking app or online banking website. If supported, there +should be an option in your online banking to withdraw money to a GNU Taler +wallet. The bank should ask for the amount and then generate a QR code that +you need to scan with your GNU Taler wallet. Alternatively, if the +WebExtension wallet is installed, the bank website may directly switch to the +GNU Taler wallet. In the GNU Taler wallet, you may have to first confirm the +terms of service of the selected GNU Taler exchange. Afterwards, applicable +fees will be shown and you will be given the option to accept the withdrawal. +Next, you need to authorize the withdraw operation in the bank. If possible, +the GNU Taler wallet may automatically switch to the bank's website, it is +also possible that you have to go back to the banking app explicitly. After +authorizing the withdraw operation, you will have to wait a bit for the money +to be wired to the exchange. Depending on the banking system, this can take +anywhere from a few seconds to many hours. Afterwards, the money will show up +in your wallet. + +Wallet initiated withdrawal +--------------------------- + +In this case, you will start the withdraw process from the GNU Taler wallet. +Under "Settings", you will find a list of exchanges. If the list is empty or +does not contain the desired exchange, you may have to first add the exchange +by providing the respective URL. + +Next to the exchange, there is a drop-down menu with an option to "withdraw". +(If you already have money in your wallet, you will also find the same button +when viewing the transaction history of the respective currency.) The wallet +will ask you to enter the amount to withdraw and accept the terms of service +and to pay the applicable fees (if any). Afterwards, the wallet will give you +wire instructions, telling you which amount to wire to which bank account. +Most importantly, the wallet will give you a wire transfer subject that must +be specified for the wire transfer. If you make a typo in the subject, the +wallet will not be topped up and the exchange will send the money back to your +bank account eventually (possibly minus a fee). Simply make the wire transfer +as instructed by the wallet. Once the money has arrived at the exchange, the +wallet will automatically withdraw the funds. + + +Depositing +========== + +If you have money in your wallet, you can use the "deposit" button to deposit +the funds into a bank account. The wallet will ask you to specify the amount +and the target bank account. + + +Sending cash +============ + +Once you have digital cash, you can send it to another GNU Taler +wallet. Simply specify the amount and a human-readable reason for the +transfer. The wallet will then show a QR code (and give the option to export +the payment as a taler://-URL). Send the image of the QR code to the +receiving wallet (or send the taler://-URL securely to the target wallet). + +The target wallet should scan the QR code (or enter the text of the +taler://-URL into the URL import dialog which is available by holding or +clicking the QR code scan button). Afterwards, review the reason text and +accept the funds to complete the transaction. + + +Invoicing +========= + +To receive funds from another user, you can send an invoice to another GNU +Taler wallet. Simply specify the amount and a human-readable reason for the +invoice. The wallet will then show a QR code (and give the option to export +the invoice as a taler://-URL). Send the image of the QR code to the payer +wallet (or send the taler://-URL to the target wallet). + +The target wallet should scan the QR code (or enter the text of the +taler://-URL into the URL import dialog which is available by holding or +clicking the QR code scan button). Afterwards, review the reason for +the invoice and decide whether or not to pay the invoice. Selecting +"pay" will complete the transaction. + +Depending on the configuration of the exchange, the receiving wallet may have +to undergo some KYC check before the funds are actually released to the +receiver. + + +.. index:: instance +.. _Instance-account-configuration: + +Configuring Accounts at a Merchant Instance +=========================================== + +Before you can setup a merchant instance, you need somebody to operate a +`Taler Merchant Backend <taler-merchant-backend-operator-manual>`_ and `grant +you access to an instance <Instance-setup>`_ at that backend. For this, you +should receive the base URL of the instance and an access token. + +The main configuration data that must be provided for each instance +is the bank account information. + +In order to receive payments, the merchant backend needs to +communicate bank account details to the exchange. + +The bank account information is provided in the form of a ``payto://``-URI. +See `RFC 8905 <https://tools.ietf.org/html/rfc8905>`_ +for the format of ``payto://``-URIs. Note that the "receiver-name" is +optional in RFC 8905 but mandatory in GNU Taler. + +For first tests, you may want to sign up for a KUDOS bank account at +`https://bank.demo.taler.net/ <https://bank.demo.taler.net/>`_. In this case, +the ``payto://``-URI will be of the form +``payto://iban/$IBAN?receiver-name=$NAME`` where ``$IBAN`` must be replaced +with the IBAN shown on the main page of the account shown at +`https://bank.demo.taler.net/ <https://bank.demo.taler.net/>`_ after logging +in. + +When deploying Taler with the real banking system, you primarily need to +change the currency of the configuration from KUDOS to the actual currency +(such as EUR, USD, CHF) and provide a ``payto://``-URI of your actual bank +account. In Europe, this will involve knowing your IBAN number. If you have an +IBAN, the corresponding ``payto://``-URI is simply +``payto://iban/$IBAN?receiver-name=$NAME`` where ``$IBAN`` must be replaced +with the actual IBAN number and ``$NAME`` with your actual name. Make sure to +URI-encode your name. The merchant SPA will do this automatically when you +use it to configure the bank account. + + + +Using the Point-of-Sale App +=========================== + +A simple way for merchants to accept GNU Taler payments is the use of the +point-of-sale app. The app can be installed on an Android phone or tablet +and is configured via a simple JSON file on a Web site: + + * In the app settings you need to specify the URL of the Web site where + the app can download the categories, products and prices from which + orders are to be compiled. You can optionally specify a username and + password to authenticate to the Web server. + + * The syntax of the JSON file is described in the point-of-sale app + manual. However, you may simply want to download the sample JSON + file from our documentation and use it as a starting point. + + * A key option is the merchant backend with the authorization key + which must be included in this JSON configuration. You may point + the point-of-sale app to any instance of a merchant backend. + +Once configured, the point-of-sale app allows the user to select a product +category and then to quickly add products from that category to an order. You +can easily edit the order, and finally use the "complete" button to generate a +QR code. The QR code must then be scanned by the GNU Taler wallet to initiate +the payment. Multiple orders can be entered concurrently, for example in a +restaurant where multiple tables are waited on at the same time. + + +Setting up an order in the merchant backoffice SPA +================================================== + +Arbitrary orders can also be created manually using the Web interface of +the GNU Taler merchant backend. For this, log into the single page app (SPA) +of the merchant backend using the authorization token of the respective +instance you want to use. + +You can then set up orders by providing all of the required fields of an +order, in particular an order summary and a price. You can also set various +optional fields or override instance default settings. + +When the order has been setup, you can follow a link to the payment page +which will show the QR code (and/or URL) that a GNU Taler wallet would need +to receive to initiate the payment process. The order status page also +shows you the progress of the order, including when a wallet has made the +payment. You can also use the backend to approve refunds. + + +Paying an order +=============== + +The payer simply scans the (dynamic) QR code to initiate the payment. If a +website is interacting with a WebExtension wallet, it may also directly +trigger the GNU Taler wallet without requiring the user to explicitly scan the +QR code. The payer should now review the contract terms and applicable fees. +Selecting "pay" will complete the transaction. Typically, the wallet will +then redirect the user to the fulfillment page where they can track the order +or directly view the digital product that they purchased. + + +Setting up a template +===================== + +A template provides all or part of the information needed to setup an order +and allows GNU Taler wallets to create an order. Usually, the creation of +orders is a privileged process that requires knowledge of the authorization +code for the respective instance. With templates, a customer's wallet can +directly create an order on-demand. The information of a template can be +partial, in which case the customer is expected to provide the remaining +details, typically the summary and/or amount of the order. + +When setting up a template you need to specify all of the fixed inputs that +the customer cannot change. You can then generate a template QR code where +you may additionally specify editable defaults for the order, such as a +default summary or a default amount which may still be changed by the wallet. +The resulting template QR code encodes the specific merchant backend, instance +and template ID as well as the (editable) default values. The resulting +static QR code can then be printed and put on display. + +Customers can scan the QR code with their GNU Taler wallet, complete the +missing details or edit the defaults (if any), and pay the resulting order. + +To secure template-based payments, you may specify a TOTP secret as part of +the template. In this case, the merchant backend will send a set of TOTP +payment confirmation codes to the GNU Taler wallet upon receiving a payment +for an order created based on the template. If the point-of-sale has a TOTP +generator with the same secret, they can compare their TOTP code with the +codes shown by the customer on their wallet. This provides additional +assurance that the customer actually made the payment instead of just showing +a fake confirmation screen. + + +Paying with static QR codes +=========================== + +The payer simply scans the (static) QR code to initiate the payment. If the +template does not specify a fixed amount, the payer will be prompted to enter +the amount to be paid (and possibly given the opportunity to specify or alter +the summary). Selecting "pay" will complete the transaction. If payment +confirmations are configured by the merchant backend, the wallet will then +display a confirmation code that can be shown to the merchant as a proof of +payment. + + + + +Setting up a webhook +==================== + +To receive notifications when a purchase has been made or a refund was given +to a wallet, you can set up webhooks in the GNU Taler merchant backend. +Webhooks allow you to trigger HTTP(S) requests based on certain events. A +webhook is thus simply an HTTP request that the GNU Taler merchant backend +will make when a certain event (such as a payment) happens. + +There are various providers that can send an SMS to a phone number based on an +HTTP request. Thus, by configuring such a provider in a webhook you can +receive an SMS notification whenever a customer makes a payment. + +Webhooks are configured per instance. In the Webhook configuration, +you can specify which URL, which HTTP headers, which HTTP method and what HTTP +body to send to the Webhook. Webhooks are automatically retried (with +increasing delays) when the target server returns a temporary error. + +Mustach templates are used when defining the contents of Webhooks. Depending +on the triggering event, the templates will be expanded with event-specific +data. + +Pay events +---------- + +For "pay" events, the backend will provide the following +information to the Mustach templating engine: + + * contract_terms: the contract terms of the paid order + * order_id: the ID of the order that received the refund + + +Refund events +------------- + +For "refund" events, the backend will provide the following information to the +Mustach templating engine: + + * timestamp: time of the refund (in nanoseconds since 1970) + * order_id: the ID of the order that received the refund + * contract_terms: the full JSON of the contract terms of the refunded order + * refund_amout: the amount that was being refunded + * reason: the reason entered by the merchant staff for granting the refund; + be careful, you probably want to inform your staff if a webhook may expose + this information to the consumer + + +.. _Rewarding-visitors: + +Rewarding visitors +================== + +.. index:: rewards + +Taler can also be used to reward digital cash to Web site visitors. For +example, you may be running an online survey, and you want to reward those +people that have dutifully completed the survey. If they have installed a +Taler wallet, you can provide them with a reward for their deeds. This section +describes how to setup the Taler merchant backend for rewarding. + +There are three basic steps that must happen to reward a visitor. + +.. _Fund-the-reserve: + +Fund the reserve +---------------- + +.. index:: reserve + +First, the reserve must be setup in the merchant backend. A reserve +is always tied to a particular instance. To create a reserve with +10 KUDOS at instance ``default`` using the demo exchange, use: + +.. code-block:: console + + $ taler-merchant-setup-reserve \ + -a KUDOS:10 \ + -e https://exchange.demo.taler.net/ \ + -m http://localhost:8888/instances/default + +The above command assumes that the merchant runs on localhost on +port 8888. +For more information, including how to transmit authentication information +to the backend, see :doc:`manpages/taler-merchant-setup-reserve.1`. + +The command will output a ``payto://`` URI which specifies where to +wire the funds and which wire transfer subject to use. + + .. note:: + + FIXME: add full example output. + +In our example, the output for the wire transfer subject is: + +.. code-block:: none + + QPE24X8PBX3BZ6E7GQ5VAVHV32FWTTCADR0TRQ183MSSJD2CHNEG + +You now need to make a wire transfer to the exchange’s bank account +using the given wire transfer subject. + +Make your wire transfer and (optionally) check at +“https://exchange/reserves/QPE24X...” whether your transfer has arrived at the +exchange. + +Once the funds have arrived, you can start to use the reserve for +rewarding. + +Note that an exchange will typically close a reserve after four weeks, wiring +all remaining funds back to the sender’s account. Thus, you should plan to +wire funds corresponding to a campaign of about two weeks to the exchange +initially. If your campaign runs longer, you should setup another reserve +every other week to ensure one is always ready. + +.. _Authorize-a-reward: + +Authorize a reward +------------------ + +When your frontend has reached the point where a client is supposed to receive +a reward, it needs to first authorize the reward. For this, the frontend must use +a POST to ``/private/reserves/$RESERVE_PUB/authorize-reward``. To authorize a +reward, the frontend has to provide the following information in the body of the +POST request: + +- The amount of the reward + +- The justification (only used internally for the back-office) + +- The URL where the wallet should navigate next after the reward was + processed + +- The reward-pickup URL (see next section) + +In response to this request, the backend will return a reward token, an +expiration time and the exchange URL. The expiration time will indicate +how long the reward is valid (when the reserve expires). The reward token is +an opaque string that contains all the information needed by the wallet +to process the reward. The frontend must send this reward token to the browser +in a special “402 Payment Required” response inside the ``Taler`` +header. + +The frontend should handle errors returned by the backend, such as +misconfigured instances or a lack of remaining funds for rewarding. + +.. _Picking-up-of-the-reward: + +Picking up of the reward +------------------------ + +The wallet will POST a JSON object to the shop’s +``/rewards/$REWARD_ID/pickup`` handler. +The frontend must then forward this request to the backend. The response +generated by the backend can then be forwarded directly to the wallet. diff --git a/taler-wallet-cli-manual.rst b/taler-wallet-cli-manual.rst @@ -1,138 +0,0 @@ -GNU Taler Wallet CLI Manual -########################### - -This manual describes how to use the GNU Taler wallet command line -interface (CLI). - -The the wallet CLI is targeted at developers and operators, but not meant to be -used by customers. It exposes all functionality that the more user-friendly -interfaces (Android app, browser extension) offer. However, it provides more -diagnostics and advanced features as well. - -Installation ------------- - -The easiest way to install the wallet is via NPM. Note that a recent version of -Node.JS (``>=12.20.1``) is required. - -We recommend to install the wallet package on a per-user basis. -To do so, configure node and adjust your ``$PATH``: - -.. code-block:: console - - $ npm set prefix $HOME/.npm-global - $ export PATH=$HOME/.npm-global:$PATH - -Now the wallet CLI can be installed without requiring elevated permissions: - -.. code-block:: console - - $ npm set prefix $HOME/.npm-global - $ npm install -g @gnu-taler/taler-wallet-cli - $ taler-wallet-cli --version - - -Getting Help ------------- - -The wallet CLI comes with built-in help. Invoke the wallet CLI (or any subcommand) with the ``--help`` flag to get help: - -.. code-block:: console - - $ taler-wallet-cli --help - Usage: taler-wallet-cli COMMAND - - Command line interface for the GNU Taler wallet. - - Options: - -h, --help Show this message and exit. - --wallet-db=VALUE location of the wallet database file - --timetravel=VALUE modify system time by given offset in microseconds - --inhibit=VALUE Inhibit running certain operations, useful for debugging and testing. - --no-throttle Don't do any request throttling. - -v, --version - -V, --verbose Enable verbose output. - - Commands: - advanced Subcommands for advanced operations (only use if you know what you're doing!). - api Call the wallet-core API directly. - backup Subcommands for backups - balance Show wallet balance. - deposit Subcommands for depositing money to payto:// accounts - exchanges Manage exchanges. - handle-uri Handle a taler:// URI. - pending Show pending operations. - run-pending Run pending operations. - run-until-done Run until no more work is left. - testing Subcommands for testing GNU Taler deployments. - transactions Show transactions. - -Completing operations ---------------------- - -Note that the CLI does not run as a background daemon. When starting -operations that don't immediately finish, the wallet needs to be run explicitly -to finish any pending tasks: - - -.. code-block:: console - - # Do one attempt to finish all pending operations - $ taler-wallet-cli run-pending - - # Run until all work is done - $ taler-wallet-cli run-until-done - -Resetting the wallet --------------------- - -The wallet can be reset by deleting its database file. By default, the database file -is ``$HOME/.talerwalletdb.json``. - - -Handling taler:// URIs ----------------------- - -Many interactions with the Taler wallet happen by scanning QR codes or special -headers on Websites. To emulate this with the command line interface, run the following -command: - -.. code-block:: console - - $ taler-wallet-cli handle-uri $URI - - -Testing an exchange deployment ------------------------------- - -The following series of commands can be used to check that an exchange deployment -is functional: - -.. code-block:: console - - # This will now output a payto URI that money needs to be sent to in order to allow withdrawal - # of taler coins - $ taler-wallet-cli advanced withdraw-manually --exchange $EXCHANGE_URL --amount EUR:10.50 - - # Show the status of the manual withdrawal operation - $ taler-wallet-cli transactions - - # Once the transfer has been made, try completing the withdrawal - $ taler-wallet-cli run-pending - - # Check status of transactions and show balance - $ taler-wallet-cli transactions - $ taler-wallet-cli balance - - # Now, directly deposit coins with the exchange into a target account - # (Usually, a payment is made via a merchant. The wallet provides - # this functionality for testing.) - $ taler-wallet-cli deposit create EUR:5 payto://iban/$IBAN - - # Check if transaction was successful. - # (If not, fix issue with exchange and run "run-pending" command again) - $ taler-wallet-cli transactions - - # The wallet can also track if the exchange wired the money to the merchant account. - # The "deposit group id" can be found in the output of the transactions list. - $ taler-wallet-cli deposit track $DEPOSIT_GROUP_ID diff --git a/taler-wallet.rst b/taler-wallet.rst @@ -1,18 +1,58 @@ -GNU Taler Wallet Developer Manual -################################# +GNU Taler Wallet Manual +####################### The GNU Taler wallet allows customers to withdraw and spend digital cash. + +WebExtension Wallet +=================== + +Building from source +-------------------- + +.. code-block:: console + + $ git clone https://git.taler.net/wallet-core.git + $ cd wallet-core + $ ./configure + $ make webex-stable + # Packaged extension now available as: + # dist/taler-wallet-$VERSION.zip + + +Android Wallet +============== + +Please see :ref:`Build-apps-from-source` in the :doc:`taler-developer-manual`. + + +iOS Wallet +========== + +Please see :ref:`Build-iOS-from-source` in the :doc:`taler-developer-manual`. + .. _command-line-wallet: Command-line Wallet =================== -The command-line wallet is used primarily for testing by developers. +This section describes how to use the GNU Taler wallet command line +interface (CLI). + +The the wallet CLI is targeted at developers and operators, but not meant to be +used by customers. It exposes all functionality that the more user-friendly +interfaces (Android app, browser extension) offer. However, it provides more +diagnostics and advanced features as well. Building from source -------------------- +The easiest way to install the wallet is via NPM. Note that a recent version of +Node.JS (``>=12.20.1``) is required. + +We recommend to install the wallet package on a per-user basis, +thus setting ``$INSTALL_PREFIX`` to a directory in ``$HOME``. + .. code-block:: console $ git clone https://git.taler.net/wallet-core.git @@ -52,8 +92,78 @@ To use the wallet as a library in your own project, run: $ npm install taler-wallet +Getting Help +------------ + +The wallet CLI comes with built-in help. Invoke the wallet CLI (or any subcommand) with the ``--help`` flag to get help: + +.. code-block:: console + + $ taler-wallet-cli --help + Usage: taler-wallet-cli COMMAND + + Command line interface for the GNU Taler wallet. + + Options: + -h, --help Show this message and exit. + --wallet-db=VALUE location of the wallet database file + --timetravel=VALUE modify system time by given offset in microseconds + --inhibit=VALUE Inhibit running certain operations, useful for debugging and testing. + --no-throttle Don't do any request throttling. + -v, --version + -V, --verbose Enable verbose output. + + Commands: + advanced Subcommands for advanced operations (only use if you know what you're doing!). + api Call the wallet-core API directly. + backup Subcommands for backups + balance Show wallet balance. + deposit Subcommands for depositing money to payto:// accounts + exchanges Manage exchanges. + handle-uri Handle a taler:// URI. + pending Show pending operations. + run-pending Run pending operations. + run-until-done Run until no more work is left. + testing Subcommands for testing GNU Taler deployments. + transactions Show transactions. + +Completing operations +--------------------- + +Note that the CLI does not run as a background daemon. When starting +operations that don't immediately finish, the wallet needs to be run explicitly +to finish any pending tasks: + + +.. code-block:: console + + # Do one attempt to finish all pending operations + $ taler-wallet-cli run-pending + + # Run until all work is done + $ taler-wallet-cli run-until-done + +Resetting the wallet +-------------------- + +The wallet can be reset by deleting its database file. By default, the database file +is ``$HOME/.talerwalletdb.json``. + + +Handling taler:// URIs +---------------------- + +Many interactions with the Taler wallet happen by scanning QR codes or special +headers on Websites. To emulate this with the command line interface, run the following +command: + +.. code-block:: console + + $ taler-wallet-cli handle-uri $URI + + Manual withdrawing -================== +------------------ .. code-block:: console @@ -61,26 +171,43 @@ Manual withdrawing --exchange https://exchange.eurint.taler.net/ \ --amount EUR:5 -WebExtension Wallet -=================== -Building from source --------------------- +Testing an exchange deployment +------------------------------ + +The following series of commands can be used to check that an exchange deployment +is functional: .. code-block:: console - $ git clone https://git.taler.net/wallet-core.git - $ cd wallet-core - $ ./configure - $ make webex-stable - # Packaged extension now available as: - # dist/taler-wallet-$VERSION.zip + # This will now output a payto URI that money needs to be sent to in order to allow withdrawal + # of taler coins + $ taler-wallet-cli advanced withdraw-manually --exchange $EXCHANGE_URL --amount EUR:10.50 + # Show the status of the manual withdrawal operation + $ taler-wallet-cli transactions + + # Once the transfer has been made, try completing the withdrawal + $ taler-wallet-cli run-pending + + # Check status of transactions and show balance + $ taler-wallet-cli transactions + $ taler-wallet-cli balance + + # Now, directly deposit coins with the exchange into a target account + # (Usually, a payment is made via a merchant. The wallet provides + # this functionality for testing.) + $ taler-wallet-cli deposit create EUR:5 payto://iban/$IBAN + + # Check if transaction was successful. + # (If not, fix issue with exchange and run "run-pending" command again) + $ taler-wallet-cli transactions + + # The wallet can also track if the exchange wired the money to the merchant account. + # The "deposit group id" can be found in the output of the transactions list. + $ taler-wallet-cli deposit track $DEPOSIT_GROUP_ID -Android Wallet -============== -Please see :ref:`Build-apps-from-source` in the :doc:`taler-developer-manual`. APIs and Data Formats @@ -262,7 +389,7 @@ Things we still need tests for: Or when the merchant is not reachable? Or the bank? This can be tested by temporarily killing those services. * How does the wallet deal with processing the same ``taler://(pay|withdraw)`` URI twice? -* Test tipping (accepting/refusing a tip) +* Test rewards (accepting/refusing a reward) * Test refunds * Test for :ref:`session-based payments <repurchase>` * Test case for auto-refunds diff --git a/wallet/wallet-core.md b/wallet/wallet-core.md @@ -7,13 +7,21 @@ This file is auto-generated from [wallet-core](https://git.taler.net/wallet-core ### Basic Wallet Information * [GetBalancesOp](#getbalancesop) * [GetBalancesDetailOp](#getbalancesdetailop) +* [GetPlanForOperationOp](#getplanforoperationop) +* [ConvertDepositAmountOp](#convertdepositamountop) +* [GetMaxDepositAmountOp](#getmaxdepositamountop) +* [ConvertPeerPushAmountOp](#convertpeerpushamountop) +* [GetMaxPeerPushAmountOp](#getmaxpeerpushamountop) +* [ConvertWithdrawalAmountOp](#convertwithdrawalamountop) ### Managing Transactions * [GetTransactionsOp](#gettransactionsop) +* [TestingGetSampleTransactionsOp](#testinggetsampletransactionsop) * [GetTransactionByIdOp](#gettransactionbyidop) * [RetryPendingNowOp](#retrypendingnowop) * [DeleteTransactionOp](#deletetransactionop) * [RetryTransactionOp](#retrytransactionop) * [AbortTransactionOp](#aborttransactionop) +* [FailTransactionOp](#failtransactionop) * [SuspendTransactionOp](#suspendtransactionop) * [ResumeTransactionOp](#resumetransactionop) ### Withdrawals @@ -23,13 +31,13 @@ This file is auto-generated from [wallet-core](https://git.taler.net/wallet-core * [AcceptManualWithdrawalOp](#acceptmanualwithdrawalop) ### Merchant Payments * [PreparePayForUriOp](#preparepayforuriop) +* [SharePaymentOp](#sharepaymentop) * [PreparePayForTemplateOp](#preparepayfortemplateop) * [GetContractTermsDetailsOp](#getcontracttermsdetailsop) * [ConfirmPayOp](#confirmpayop) -* [ApplyRefundOp](#applyrefundop) -* [ApplyRefundFromPurchaseIdOp](#applyrefundfrompurchaseidop) -* [PrepareRefundOp](#preparerefundop) -### Tipping +* [StartRefundQueryForUriOp](#startrefundqueryforuriop) +* [StartRefundQueryOp](#startrefundqueryop) +### Rewards * [PrepareTipOp](#preparetipop) * [AcceptTipOp](#accepttipop) ### Exchange Management @@ -42,10 +50,10 @@ This file is auto-generated from [wallet-core](https://git.taler.net/wallet-core * [GetExchangeTosOp](#getexchangetosop) * [GetExchangeDetailedInfoOp](#getexchangedetailedinfoop) * [ListCurrenciesOp](#listcurrenciesop) +* [GetScopedCurrencyInfoOp](#getscopedcurrencyinfoop) ### Deposits +* [GenerateDepositGroupTxIdOp](#generatedepositgrouptxidop) * [CreateDepositGroupOp](#createdepositgroupop) -* [TrackDepositGroupOp](#trackdepositgroupop) -* [GetFeeForDepositOp](#getfeefordepositop) * [PrepareDepositOp](#preparedepositop) ### Backups * [ExportBackupRecoveryOp](#exportbackuprecoveryop) @@ -56,7 +64,10 @@ This file is auto-generated from [wallet-core](https://git.taler.net/wallet-core * [RemoveBackupProviderOp](#removebackupproviderop) * [GetBackupInfoOp](#getbackupinfoop) * [SetWalletDeviceIdOp](#setwalletdeviceidop) -* [ExportBackupPlainOp](#exportbackupplainop) +* [ListStoredBackupsOp](#liststoredbackupsop) +* [CreateStoredBackupsOp](#createstoredbackupsop) +* [RecoverStoredBackupsOp](#recoverstoredbackupsop) +* [DeleteStoredBackupOp](#deletestoredbackupop) ### Peer Payments * [CheckPeerPushDebitOp](#checkpeerpushdebitop) * [InitiatePeerPushDebitOp](#initiatepeerpushdebitop) @@ -66,6 +77,8 @@ This file is auto-generated from [wallet-core](https://git.taler.net/wallet-core * [InitiatePeerPullCreditOp](#initiatepeerpullcreditop) * [PreparePeerPullDebitOp](#preparepeerpulldebitop) * [ConfirmPeerPullDebitOp](#confirmpeerpulldebitop) +### Data Validation +* [ValidateIbanOp](#validateibanop) ### Database Management * [ExportDbOp](#exportdbop) * [ImportDbOp](#importdbop) @@ -73,8 +86,8 @@ This file is auto-generated from [wallet-core](https://git.taler.net/wallet-core * [RecycleOp](#recycleop) ### Testing and Debugging * [ApplyDevExperimentOp](#applydevexperimentop) -* [SetDevModeOp](#setdevmodeop) * [RunIntegrationTestOp](#runintegrationtestop) +* [RunIntegrationTestV2Op](#runintegrationtestv2op) * [TestCryptoOp](#testcryptoop) * [WithdrawTestBalanceOp](#withdrawtestbalanceop) * [WithdrawTestkudosOp](#withdrawtestkudosop) @@ -82,6 +95,7 @@ This file is auto-generated from [wallet-core](https://git.taler.net/wallet-core * [WithdrawFakebankOp](#withdrawfakebankop) * [GetPendingTasksOp](#getpendingtasksop) * [DumpCoinsOp](#dumpcoinsop) +* [TestingSetTimetravelOp](#testingsettimetravelop) * [SetCoinSuspendedOp](#setcoinsuspendedop) * [ForceRefreshOp](#forcerefreshop) ## Operation Reference @@ -154,24 +168,6 @@ export interface Balance { } ``` -```typescript -export type ScopeInfo = - | { - type: ScopeType.Global; - currency: string; - } - | { - type: ScopeType.Exchange; - currency: string; - url: string; - } - | { - type: ScopeType.Auditor; - currency: string; - url: string; - }; - -``` ### GetBalancesDetailOp ```typescript @@ -236,6 +232,108 @@ export interface AmountJson { ``` +### GetPlanForOperationOp +```typescript +export type GetPlanForOperationOp = { + op: WalletApiOperation.GetPlanForOperation; + request: GetPlanForOperationRequest; + response: GetPlanForOperationResponse; +}; +// GetPlanForOperation = "getPlanForOperation" + +``` +```typescript +export type GetPlanForOperationRequest = + | GetPlanForWithdrawRequest + | GetPlanForDepositRequest; + +``` +```typescript +interface GetPlanForWithdrawRequest extends GetPlanForWalletInitiatedOperation { + type: TransactionType.Withdrawal; + exchangeUrl?: string; +} + +``` +```typescript +interface GetPlanForWalletInitiatedOperation { + instructedAmount: AmountString; + mode: TransactionAmountMode; +} + +``` +```typescript +interface GetPlanForDepositRequest extends GetPlanForWalletInitiatedOperation { + type: TransactionType.Deposit; + account: string; +} + +``` +```typescript +export interface GetPlanForOperationResponse { + effectiveAmount: AmountString; + rawAmount: AmountString; + counterPartyAmount?: AmountString; + details: any; +} + +``` + +### ConvertDepositAmountOp +```typescript +export type ConvertDepositAmountOp = { + op: WalletApiOperation.ConvertDepositAmount; + request: ConvertAmountRequest; + response: AmountResponse; +}; +// ConvertDepositAmount = "ConvertDepositAmount" + +``` + +### GetMaxDepositAmountOp +```typescript +export type GetMaxDepositAmountOp = { + op: WalletApiOperation.GetMaxDepositAmount; + request: GetAmountRequest; + response: AmountResponse; +}; +// GetMaxDepositAmount = "GetMaxDepositAmount" + +``` + +### ConvertPeerPushAmountOp +```typescript +export type ConvertPeerPushAmountOp = { + op: WalletApiOperation.ConvertPeerPushAmount; + request: ConvertAmountRequest; + response: AmountResponse; +}; +// ConvertPeerPushAmount = "ConvertPeerPushAmount" + +``` + +### GetMaxPeerPushAmountOp +```typescript +export type GetMaxPeerPushAmountOp = { + op: WalletApiOperation.GetMaxPeerPushAmount; + request: GetAmountRequest; + response: AmountResponse; +}; +// GetMaxPeerPushAmount = "GetMaxPeerPushAmount" + +``` + +### ConvertWithdrawalAmountOp +```typescript +export type ConvertWithdrawalAmountOp = { + op: WalletApiOperation.ConvertWithdrawalAmount; + request: ConvertAmountRequest; + response: AmountResponse; +}; +// ConvertWithdrawalAmount = "ConvertWithdrawalAmount" + +``` + ### GetTransactionsOp ```typescript /** @@ -263,13 +361,22 @@ export interface TransactionsRequest { * If true, include all refreshes in the transactions list. */ includeRefreshes?: boolean; + filterByState?: TransactionStateFilter; } ``` + +### TestingGetSampleTransactionsOp ```typescript -export interface TransactionsResponse { - transactions: Transaction[]; -} +/** + * Get sample transactions. + */ +export type TestingGetSampleTransactionsOp = { + op: WalletApiOperation.TestingGetSampleTransactions; + request: EmptyObject; + response: TransactionsResponse; +}; +// TestingGetSampleTransactions = "testingGetSampleTransactions" ``` @@ -316,7 +423,7 @@ export type DeleteTransactionOp = { ``` ```typescript export interface DeleteTransactionRequest { - transactionId: string; + transactionId: TransactionIdStr; } ``` @@ -336,7 +443,7 @@ export type RetryTransactionOp = { ``` ```typescript export interface RetryTransactionRequest { - transactionId: string; + transactionId: TransactionIdStr; } ``` @@ -357,6 +464,28 @@ export type AbortTransactionOp = { ``` +### FailTransactionOp +```typescript +/** + * Cancel aborting a transaction + * + * For payment transactions, it puts the payment into an "aborting" state. + */ +export type FailTransactionOp = { + op: WalletApiOperation.FailTransaction; + request: FailTransactionRequest; + response: EmptyObject; +}; +// FailTransaction = "failTransaction" + +``` +```typescript +export interface FailTransactionRequest { + transactionId: TransactionIdStr; +} + +``` + ### SuspendTransactionOp ```typescript /** @@ -422,6 +551,12 @@ export interface ManualWithdrawalDetails { */ amountEffective: AmountString; /** + * Number of coins that would be used for withdrawal. + * + * The UIs should warn if this number is too high (roughly at >100). + */ + numCoins: number; + /** * Ways to pay the exchange. */ paytoUris: string[]; @@ -489,7 +624,7 @@ export interface AcceptBankIntegratedWithdrawalRequest { export interface AcceptWithdrawalResponse { reservePub: string; confirmTransferUrl?: string; - transactionId: string; + transactionId: TransactionIdStr; } ``` @@ -525,7 +660,7 @@ export interface AcceptManualWithdrawalResult { * Public key of the newly created reserve. */ reservePub: string; - transactionId: string; + transactionId: TransactionIdStr; } ``` @@ -550,6 +685,30 @@ export interface PreparePayRequest { ``` +### SharePaymentOp +```typescript +export type SharePaymentOp = { + op: WalletApiOperation.SharePayment; + request: SharePaymentRequest; + response: SharePaymentResult; +}; +// SharePayment = "sharePayment" + +``` +```typescript +export interface SharePaymentRequest { + merchantBaseUrl: string; + orderId: string; +} + +``` +```typescript +export interface SharePaymentResult { + privatePayUri: string; +} + +``` + ### PreparePayForTemplateOp ```typescript /** @@ -620,7 +779,6 @@ export interface WalletContractData { wireFeeAmortization: number; payDeadline: TalerProtocolTimestamp; refundDeadline: TalerProtocolTimestamp; - allowedAuditors: AllowedAuditorInfo[]; allowedExchanges: AllowedExchangeInfo[]; timestamp: TalerProtocolTimestamp; wireMethod: string; @@ -633,13 +791,6 @@ export interface WalletContractData { ``` ```typescript -export interface AllowedAuditorInfo { - auditorBaseUrl: string; - auditorPub: string; -} - -``` -```typescript export interface AllowedExchangeInfo { exchangeBaseUrl: string; exchangePub: string; @@ -663,7 +814,11 @@ export type ConfirmPayOp = { ``` ```typescript export interface ConfirmPayRequest { - proposalId: string; + /** + * @deprecated use transactionId instead + */ + proposalId?: string; + transactionId?: string; sessionId?: string; forcedCoinSel?: ForcedCoinSel; } @@ -680,81 +835,58 @@ export type ConfirmPayResult = ConfirmPayResultDone | ConfirmPayResultPending; export interface ConfirmPayResultDone { type: ConfirmPayResultType.Done; contractTerms: MerchantContractTerms; - transactionId: string; + transactionId: TransactionIdStr; } ``` ```typescript export interface ConfirmPayResultPending { type: ConfirmPayResultType.Pending; - transactionId: string; + transactionId: TransactionIdStr; lastError: TalerErrorDetail | undefined; } ``` -### ApplyRefundOp +### StartRefundQueryForUriOp ```typescript /** * Check for a refund based on a taler://refund URI. */ -export type ApplyRefundOp = { - op: WalletApiOperation.ApplyRefund; - request: ApplyRefundRequest; - response: ApplyRefundResponse; +export type StartRefundQueryForUriOp = { + op: WalletApiOperation.StartRefundQueryForUri; + request: PrepareRefundRequest; + response: StartRefundQueryForUriResponse; }; -// ApplyRefund = "applyRefund" +// StartRefundQueryForUri = "startRefundQueryForUri" ``` ```typescript -export interface ApplyRefundRequest { +export interface PrepareRefundRequest { talerRefundUri: string; } ``` - -### ApplyRefundFromPurchaseIdOp ```typescript -export type ApplyRefundFromPurchaseIdOp = { - op: WalletApiOperation.ApplyRefundFromPurchaseId; - request: ApplyRefundFromPurchaseIdRequest; - response: ApplyRefundResponse; -}; -// ApplyRefundFromPurchaseId = "applyRefundFromPurchaseId" - -``` -```typescript -export interface ApplyRefundFromPurchaseIdRequest { - purchaseId: string; +export interface StartRefundQueryForUriResponse { + transactionId: TransactionIdStr; } ``` -### PrepareRefundOp +### StartRefundQueryOp ```typescript -export type PrepareRefundOp = { - op: WalletApiOperation.PrepareRefund; - request: PrepareRefundRequest; - response: PrepareRefundResult; +export type StartRefundQueryOp = { + op: WalletApiOperation.StartRefundQuery; + request: StartRefundQueryRequest; + response: EmptyObject; }; -// PrepareRefund = "prepareRefund" +// StartRefundQuery = "startRefundQuery" ``` ```typescript -export interface PrepareRefundRequest { - talerRefundUri: string; -} - -``` -```typescript -export interface PrepareRefundResult { - proposalId: string; - effectivePaid: AmountString; - gone: AmountString; - granted: AmountString; - pending: boolean; - awaiting: AmountString; - info: OrderShortInfo; +export interface StartRefundQueryRequest { + transactionId: TransactionIdStr; } ``` @@ -762,19 +894,19 @@ export interface PrepareRefundResult { ### PrepareTipOp ```typescript /** - * Query and store information about a tip. + * Query and store information about a reward. */ export type PrepareTipOp = { - op: WalletApiOperation.PrepareTip; - request: PrepareTipRequest; - response: PrepareTipResult; + op: WalletApiOperation.PrepareReward; + request: PrepareRewardRequest; + response: PrepareRewardResult; }; -// PrepareTip = "prepareTip" +// PrepareReward = "prepareReward" ``` ```typescript -export interface PrepareTipRequest { - talerTipUri: string; +export interface PrepareRewardRequest { + talerRewardUri: string; } ``` @@ -783,8 +915,14 @@ export interface PrepareTipResult { /** * Unique ID for the tip assigned by the wallet. * Typically different from the merchant-generated tip ID. + * + * @deprecated use transactionId instead + */ + walletRewardId: string; + /** + * Tip transaction ID. */ - walletTipId: string; + transactionId: string; /** * Has the tip already been accepted? */ @@ -792,12 +930,12 @@ export interface PrepareTipResult { /** * Amount that the merchant gave. */ - tipAmountRaw: AmountString; + rewardAmountRaw: AmountString; /** * Amount that arrived at the wallet. * Might be lower than the raw amount due to fees. */ - tipAmountEffective: AmountString; + rewardAmountEffective: AmountString; /** * Base URL of the merchant backend giving then tip. */ @@ -819,25 +957,25 @@ export interface PrepareTipResult { ### AcceptTipOp ```typescript /** - * Accept a tip. + * Accept a reward. */ export type AcceptTipOp = { - op: WalletApiOperation.AcceptTip; - request: AcceptTipRequest; + op: WalletApiOperation.AcceptReward; + request: AcceptRewardRequest; response: AcceptTipResponse; }; -// AcceptTip = "acceptTip" +// AcceptReward = "acceptReward" ``` ```typescript -export interface AcceptTipRequest { - walletTipId: string; +export interface AcceptRewardRequest { + walletRewardId: string; } ``` ```typescript export interface AcceptTipResponse { - transactionId: string; + transactionId: TransactionIdStr; next_url?: string; } @@ -924,7 +1062,7 @@ export interface PaytoUriUnknown extends PaytoUriGeneric { ``` ```typescript export interface PaytoUriGeneric { - targetType: string; + targetType: PaytoType | string; targetPath: string; params: { [name: string]: string; @@ -933,6 +1071,10 @@ export interface PaytoUriGeneric { ``` ```typescript +export type PaytoType = "iban" | "bitcoin" | "x-taler-bank"; + +``` +```typescript export interface PaytoUriIBAN extends PaytoUriGeneric { isKnown: true; targetType: "iban"; @@ -1158,113 +1300,93 @@ export interface WalletCurrencyInfo { ``` -### CreateDepositGroupOp +### GetScopedCurrencyInfoOp ```typescript -/** - * Create a new deposit group. - * - * Deposit groups are used to deposit multiple coins to a bank - * account, usually the wallet user's own bank account. - */ -export type CreateDepositGroupOp = { - op: WalletApiOperation.CreateDepositGroup; - request: CreateDepositGroupRequest; - response: CreateDepositGroupResponse; +export type GetScopedCurrencyInfoOp = { + op: WalletApiOperation.GetScopedCurrencyInfo; + request: GetCurrencyInfoRequest; + response: GetCurrencyInfoResponse; }; -// CreateDepositGroup = "createDepositGroup" +// GetScopedCurrencyInfo = "getScopedCurrencyInfo" ``` ```typescript -export interface CreateDepositGroupRequest { - depositPaytoUri: string; - amount: AmountString; +export interface GetCurrencyInfoRequest { + scope: ScopeInfo; } ``` ```typescript -export interface CreateDepositGroupResponse { - depositGroupId: string; - transactionId: string; +export interface GetCurrencyInfoResponse { + decimalSeparator: string; + numFractionalDigits: number; + numTinyDigits: number; + /** + * Is the currency name leading or trailing? + */ + isCurrencyNameLeading: boolean; } ``` -### TrackDepositGroupOp +### GenerateDepositGroupTxIdOp ```typescript /** - * Track the status of a deposit group by querying the exchange. + * Generate a fresh transaction ID for a deposit group. + * + * The resulting transaction ID can be specified when creating + * a deposit group, so that the client can already start waiting for notifications + * on that specific deposit group before the GreateDepositGroup request returns. */ -export type TrackDepositGroupOp = { - op: WalletApiOperation.TrackDepositGroup; - request: TrackDepositGroupRequest; - response: TrackDepositGroupResponse; +export type GenerateDepositGroupTxIdOp = { + op: WalletApiOperation.GenerateDepositGroupTxId; + request: EmptyObject; + response: TxIdResponse; }; -// TrackDepositGroup = "trackDepositGroup" +// GenerateDepositGroupTxId = "generateDepositGroupTxId" ``` ```typescript -export interface TrackDepositGroupRequest { - depositGroupId: string; -} - -``` -```typescript -export interface TrackDepositGroupResponse { - responses: TrackTransaction[]; -} - -``` -```typescript -export type TrackTransaction = - | ({ - type: "accepted"; - } & TrackTransactionAccepted) - | ({ - type: "wired"; - } & TrackTransactionWired); - -``` -```typescript -interface TrackTransactionAccepted { - requirement_row?: number; - kyc_ok: boolean; - execution_time: TalerProtocolTimestamp; -} - -``` -```typescript -export interface TrackTransactionWired { - wtid: Base32String; - execution_time: TalerProtocolTimestamp; - coin_contribution: AmountString; - exchange_sig: EddsaSignatureString; - exchange_pub: EddsaPublicKeyString; +export interface TxIdResponse { + transactionId: TransactionIdStr; } ``` -### GetFeeForDepositOp +### CreateDepositGroupOp ```typescript -export type GetFeeForDepositOp = { - op: WalletApiOperation.GetFeeForDeposit; - request: GetFeeForDepositRequest; - response: DepositGroupFees; +/** + * Create a new deposit group. + * + * Deposit groups are used to deposit multiple coins to a bank + * account, usually the wallet user's own bank account. + */ +export type CreateDepositGroupOp = { + op: WalletApiOperation.CreateDepositGroup; + request: CreateDepositGroupRequest; + response: CreateDepositGroupResponse; }; -// GetFeeForDeposit = "getFeeForDeposit" +// CreateDepositGroup = "createDepositGroup" ``` ```typescript -export interface GetFeeForDepositRequest { +export interface CreateDepositGroupRequest { + /** + * Pre-allocated transaction ID. + * Allows clients to easily handle notifications + * that occur while the operation has been created but + * before the creation request has returned. + */ + transactionId?: string; depositPaytoUri: string; amount: AmountString; } ``` ```typescript -export interface DepositGroupFees { - coin: AmountString; - wire: AmountString; - refresh: AmountString; +export interface CreateDepositGroupResponse { + depositGroupId: string; + transactionId: TransactionIdStr; } ``` @@ -1290,6 +1412,15 @@ export interface PrepareDepositRequest { export interface PrepareDepositResponse { totalDepositCost: AmountString; effectiveDepositAmount: AmountString; + fees: DepositGroupFees; +} + +``` +```typescript +export interface DepositGroupFees { + coin: AmountString; + wire: AmountString; + refresh: AmountString; } ``` @@ -1481,8 +1612,8 @@ export interface ProviderInfo { * Last communication issue with the provider. */ lastError?: TalerErrorDetail; - lastSuccessfulBackupTimestamp?: TalerProtocolTimestamp; - lastAttemptedBackupTimestamp?: TalerProtocolTimestamp; + lastSuccessfulBackupTimestamp?: TalerPreciseTimestamp; + lastAttemptedBackupTimestamp?: TalerPreciseTimestamp; paymentProposalIds: string[]; backupProblem?: BackupProblem; paymentStatus: ProviderPaymentStatus; @@ -1589,17 +1720,73 @@ export interface SetWalletDeviceIdRequest { ``` -### ExportBackupPlainOp +### ListStoredBackupsOp ```typescript -/** - * Export a backup JSON, mostly useful for testing. - */ -export type ExportBackupPlainOp = { - op: WalletApiOperation.ExportBackupPlain; +export type ListStoredBackupsOp = { + op: WalletApiOperation.ListStoredBackups; + request: EmptyObject; + response: StoredBackupList; +}; +// ListStoredBackups = "listStoredBackups" + +``` +```typescript +export interface StoredBackupList { + storedBackups: { + name: string; + }[]; +} + +``` + +### CreateStoredBackupsOp +```typescript +export type CreateStoredBackupsOp = { + op: WalletApiOperation.CreateStoredBackup; request: EmptyObject; - response: WalletBackupContentV1; + response: CreateStoredBackupResponse; }; -// ExportBackupPlain = "exportBackupPlain" +// CreateStoredBackup = "createStoredBackup" + +``` +```typescript +export interface CreateStoredBackupResponse { + name: string; +} + +``` + +### RecoverStoredBackupsOp +```typescript +export type RecoverStoredBackupsOp = { + op: WalletApiOperation.RecoverStoredBackup; + request: RecoverStoredBackupRequest; + response: EmptyObject; +}; +// RecoverStoredBackup = "recoverStoredBackup" + +``` +```typescript +export interface RecoverStoredBackupRequest { + name: string; +} + +``` + +### DeleteStoredBackupOp +```typescript +export type DeleteStoredBackupOp = { + op: WalletApiOperation.DeleteStoredBackup; + request: DeleteStoredBackupRequest; + response: EmptyObject; +}; +// DeleteStoredBackup = "deleteStoredBackup" + +``` +```typescript +export interface DeleteStoredBackupRequest { + name: string; +} ``` @@ -1647,27 +1834,27 @@ export interface CheckPeerPushDebitResponse { */ export type InitiatePeerPushDebitOp = { op: WalletApiOperation.InitiatePeerPushDebit; - request: InitiatePeerPushPaymentRequest; - response: InitiatePeerPushPaymentResponse; + request: InitiatePeerPushDebitRequest; + response: InitiatePeerPushDebitResponse; }; // InitiatePeerPushDebit = "initiatePeerPushDebit" ``` ```typescript -export interface InitiatePeerPushPaymentRequest { +export interface InitiatePeerPushDebitRequest { exchangeBaseUrl?: string; partialContractTerms: PeerContractTerms; } ``` ```typescript -export interface InitiatePeerPushPaymentResponse { +export interface InitiatePeerPushDebitResponse { exchangeBaseUrl: string; pursePub: string; mergePriv: string; contractPriv: string; talerUri: string; - transactionId: string; + transactionId: TransactionIdStr; } ``` @@ -1679,13 +1866,19 @@ export interface InitiatePeerPushPaymentResponse { */ export type PreparePeerPushCreditOp = { op: WalletApiOperation.PreparePeerPushCredit; - request: PreparePeerPushCredit; + request: PreparePeerPushCreditRequest; response: PreparePeerPushCreditResponse; }; // PreparePeerPushCredit = "preparePeerPushCredit" ``` ```typescript +export interface PreparePeerPushCreditRequest { + talerUri: string; +} + +``` +```typescript export interface PreparePeerPushCreditResponse { contractTerms: PeerContractTerms; /** @@ -1695,6 +1888,7 @@ export interface PreparePeerPushCreditResponse { amountRaw: AmountString; amountEffective: AmountString; peerPushPaymentIncomingId: string; + transactionId: string; } ``` @@ -1716,8 +1910,11 @@ export type ConfirmPeerPushCreditOp = { export interface ConfirmPeerPushCreditRequest { /** * Transparent identifier of the incoming peer push payment. + * + * @deprecated specify transactionId instead! */ - peerPushPaymentIncomingId: string; + peerPushPaymentIncomingId?: string; + transactionId?: string; } ``` @@ -1747,6 +1944,11 @@ export interface CheckPeerPullCreditResponse { exchangeBaseUrl: string; amountRaw: AmountString; amountEffective: AmountString; + /** + * Number of coins that will be used, + * can be used by the UI to warn if excessively large. + */ + numCoins: number; } ``` @@ -1776,9 +1978,11 @@ export interface InitiatePeerPullCreditResponse { /** * Taler URI for the other party to make the payment * that was requested. + * + * @deprecated since it's not necessarily valid yet until the tx is in the right state */ talerUri: string; - transactionId: string; + transactionId: TransactionIdStr; } ``` @@ -1812,6 +2016,7 @@ export interface PreparePeerPullDebitResponse { amountRaw: AmountString; amountEffective: AmountString; peerPullPaymentIncomingId: string; + transactionId: string; } ``` @@ -1833,8 +2038,34 @@ export type ConfirmPeerPullDebitOp = { export interface ConfirmPeerPullDebitRequest { /** * Transparent identifier of the incoming peer pull payment. + * + * @deprecated use transactionId instead */ - peerPullPaymentIncomingId: string; + peerPullPaymentIncomingId?: string; + transactionId?: string; +} + +``` + +### ValidateIbanOp +```typescript +export type ValidateIbanOp = { + op: WalletApiOperation.ValidateIban; + request: ValidateIbanRequest; + response: ValidateIbanResponse; +}; +// ValidateIban = "validateIban" + +``` +```typescript +export interface ValidateIbanRequest { + iban: string; +} + +``` +```typescript +export interface ValidateIbanResponse { + valid: boolean; } ``` @@ -1915,23 +2146,6 @@ export interface ApplyDevExperimentRequest { ``` -### SetDevModeOp -```typescript -export type SetDevModeOp = { - op: WalletApiOperation.SetDevMode; - request: SetDevModeRequest; - response: EmptyObject; -}; -// SetDevMode = "setDevMode" - -``` -```typescript -export interface SetDevModeRequest { - devModeEnabled: boolean; -} - -``` - ### RunIntegrationTestOp ```typescript /** @@ -1946,16 +2160,19 @@ export type RunIntegrationTestOp = { // RunIntegrationTest = "runIntegrationTest" ``` + +### RunIntegrationTestV2Op ```typescript -export interface IntegrationTestArgs { - exchangeBaseUrl: string; - bankBaseUrl: string; - bankAccessApiBaseUrl?: string; - merchantBaseUrl: string; - merchantAuthToken?: string; - amountToWithdraw: string; - amountToSpend: string; -} +/** + * Run a simple integration test on a test deployment + * of the exchange and merchant. + */ +export type RunIntegrationTestV2Op = { + op: WalletApiOperation.RunIntegrationTestV2; + request: IntegrationTestArgs; + response: EmptyObject; +}; +// RunIntegrationTestV2 = "runIntegrationTestV2" ``` @@ -1990,11 +2207,10 @@ export type WithdrawTestBalanceOp = { ```typescript export interface WithdrawTestBalanceRequest { amount: string; - bankBaseUrl: string; /** - * Bank access API base URL. Defaults to the bankBaseUrl. + * Bank access API base URL. */ - bankAccessApiBaseUrl?: string; + bankAccessApiBaseUrl: string; exchangeBaseUrl: string; forcedDenomSel?: ForcedDenomSel; } @@ -2158,7 +2374,7 @@ export interface PendingTaskInfoCommon { /** * Unique identifier for the pending task. */ - id: string; + id: TaskId; /** * Set to true if the operation indicates that something is really in progress, * as opposed to some regular scheduled operation that can be tried later. @@ -2191,19 +2407,24 @@ export enum PendingTaskType { Purchase = "purchase", Refresh = "refresh", Recoup = "recoup", - TipPickup = "tip-pickup", + RewardPickup = "reward-pickup", Withdraw = "withdraw", Deposit = "deposit", Backup = "backup", - // FIXME: Rename to peer-push-debit and peer-pull-debit - PeerPushInitiation = "peer-push-initiation", - PeerPullInitiation = "peer-pull-initiation", + PeerPushDebit = "peer-push-debit", + PeerPullCredit = "peer-pull-credit", PeerPushCredit = "peer-push-credit", PeerPullDebit = "peer-pull-debit", } ``` ```typescript +export type TaskId = string & { + [__taskId]: true; +}; + +``` +```typescript export interface RetryInfo { firstTry: AbsoluteTime; nextRetry: AbsoluteTime; @@ -2356,7 +2577,7 @@ export interface PendingRefreshTask { * The wallet is picking up a tip that the user has accepted. */ export interface PendingTipPickupTask { - type: PendingTaskType.TipPickup; + type: PendingTaskType.RewardPickup; tipId: string; merchantBaseUrl: string; merchantTipId: string; @@ -2409,7 +2630,7 @@ export interface PendingBackupTask { * The wallet wants to send a peer push payment. */ export interface PendingPeerPushInitiationTask { - type: PendingTaskType.PeerPushInitiation; + type: PendingTaskType.PeerPushDebit; pursePub: string; } @@ -2419,7 +2640,7 @@ export interface PendingPeerPushInitiationTask { * The wallet wants to send a peer pull payment. */ export interface PendingPeerPullInitiationTask { - type: PendingTaskType.PeerPullInitiation; + type: PendingTaskType.PeerPullCredit; pursePub: string; } @@ -2597,6 +2818,26 @@ export type Edx25519PrivateKeyEnc = FlavorP< ``` +### TestingSetTimetravelOp +```typescript +/** + * Add an offset to the wallet's internal time. + */ +export type TestingSetTimetravelOp = { + op: WalletApiOperation.TestingSetTimetravel; + request: TestingSetTimetravelRequest; + response: EmptyObject; +}; +// TestingSetTimetravel = "testingSetTimetravel" + +``` +```typescript +export interface TestingSetTimetravelRequest { + offsetMs: number; +} + +``` + ### SetCoinSuspendedOp ```typescript /** @@ -2643,28 +2884,76 @@ export interface ForceRefreshRequest { ## Common Declarations ```typescript export interface WalletCoreVersion { + /** + * @deprecated + */ hash: string | undefined; version: string; exchange: string; merchant: string; bank: string; + /** + * @deprecated will be removed + */ devMode: boolean; } ``` ```typescript +export type ScopeInfo = ScopeInfoGlobal | ScopeInfoExchange | ScopeInfoAuditor; +``` +```typescript +/** + * How the amount should be interpreted in a transaction + * Effective = how the balance is change + * Raw = effective amount without fee + * + * Depending on the transaction, raw can be higher than effective + */ +export declare enum TransactionAmountMode { + Effective = "effective", + Raw = "raw", +} +``` +```typescript +export interface ConvertAmountRequest { + amount: AmountString; + type: TransactionAmountMode; +} +``` +```typescript +export interface AmountResponse { + effectiveAmount: AmountString; + rawAmount: AmountString; +} +``` +```typescript +export interface GetAmountRequest { + currency: string; +} +``` +```typescript +export interface TransactionsResponse { + transactions: Transaction[]; +} +``` +```typescript export type Transaction = | TransactionWithdrawal | TransactionPayment | TransactionRefund - | TransactionTip + | TransactionReward | TransactionRefresh | TransactionDeposit | TransactionPeerPullCredit | TransactionPeerPullDebit | TransactionPeerPushCredit - | TransactionPeerPushDebit; + | TransactionPeerPushDebit + | TransactionInternalWithdrawal; ``` ```typescript +/** + * A withdrawal transaction (either bank-integrated or manual). + */ export interface TransactionWithdrawal extends TransactionCommon { type: TransactionType.Withdrawal; /** @@ -2686,23 +2975,15 @@ export interface TransactionWithdrawal extends TransactionCommon { export interface TransactionCommon { transactionId: TransactionIdStr; type: TransactionType; - timestamp: TalerProtocolTimestamp; - extendedStatus: ExtendedStatus; + timestamp: TalerPreciseTimestamp; /** - * true if the transaction is still pending, false otherwise - * If a transaction is not longer pending, its timestamp will be updated, - * but its transactionId will remain unchanged - * - * @deprecated show extendedStatus + * Transaction state, as per DD37. */ - pending: boolean; + txState: TransactionState; /** - * True if the transaction encountered a problem that might be - * permanent. A frozen transaction won't be automatically retried. - * - * @deprecated show extendedStatus + * Possible transitions based on the current state. */ - frozen: boolean; + txActions: TransactionAction[]; /** * Raw amount of the transaction (exclusive of fees or other extra costs). */ @@ -2712,15 +2993,26 @@ export interface TransactionCommon { */ amountEffective: AmountString; error?: TalerErrorDetail; + /** + * If the transaction minor state is in KycRequired this field is going to + * have the location where the user need to go to complete KYC information. + */ + kycUrl?: string; } ``` ```typescript +export type TransactionIdStr = `txn:${string}:${string}` & { + [__txId]: true; +}; +``` +```typescript export declare enum TransactionType { Withdrawal = "withdrawal", + InternalWithdrawal = "internal-withdrawal", Payment = "payment", Refund = "refund", Refresh = "refresh", - Tip = "tip", + Reward = "reward", Deposit = "deposit", PeerPushDebit = "peer-push-debit", PeerPushCredit = "peer-push-credit", @@ -2729,18 +3021,93 @@ export declare enum TransactionType { } ``` ```typescript +export interface TalerPreciseTimestamp { + /** + * Seconds (as integer) since epoch. + */ + readonly t_s: number | "never"; + /** + * Optional microsecond offset (non-negative integer). + */ + readonly off_us?: number; + readonly _flavor?: typeof flavor_TalerPreciseTimestamp; +} +``` +```typescript export interface TalerProtocolTimestamp { + /** + * Seconds (as integer) since epoch. + */ readonly t_s: number | "never"; + readonly _flavor?: typeof flavor_TalerProtocolTimestamp; +} +``` +```typescript +export interface TransactionState { + major: TransactionMajorState; + minor?: TransactionMinorState; } ``` ```typescript -export declare enum ExtendedStatus { +export declare enum TransactionMajorState { + None = "none", Pending = "pending", Done = "done", Aborting = "aborting", Aborted = "aborted", + Suspended = "suspended", + Dialog = "dialog", + SuspendedAborting = "suspended-aborting", Failed = "failed", - KycRequired = "kyc-required", + Expired = "expired", + Deleted = "deleted", +} +``` +```typescript +export declare enum TransactionMinorState { + Unknown = "unknown", + Deposit = "deposit", + KycRequired = "kyc", + AmlRequired = "aml", + MergeKycRequired = "merge-kyc", + Track = "track", + SubmitPayment = "submit-payment", + RebindSession = "rebind-session", + Refresh = "refresh", + Pickup = "pickup", + AutoRefund = "auto-refund", + User = "user", + Bank = "bank", + Exchange = "exchange", + ClaimProposal = "claim-proposal", + CheckRefund = "check-refund", + CreatePurse = "create-purse", + DeletePurse = "delete-purse", + Ready = "ready", + Merge = "merge", + Repurchase = "repurchase", + BankRegisterReserve = "bank-register-reserve", + BankConfirmTransfer = "bank-confirm-transfer", + WithdrawCoins = "withdraw-coins", + ExchangeWaitReserve = "exchange-wait-reserve", + AbortingBank = "aborting-bank", + Aborting = "aborting", + Refused = "refused", + Withdraw = "withdraw", + MerchantOrderProposed = "merchant-order-proposed", + Proposed = "proposed", + RefundAvailable = "refund-available", + AcceptRefund = "accept-refund", +} +``` +```typescript +export declare enum TransactionAction { + Delete = "delete", + Suspend = "suspend", + Resume = "resume", + Abort = "abort", + Fail = "fail", + Retry = "retry", } ``` ```typescript @@ -2757,6 +3124,8 @@ export interface AbsoluteTime { * Timestamp in milliseconds. */ readonly t_ms: number | "never"; + readonly _flavor?: typeof flavor_AbsoluteTime; + [opaque_AbsoluteTime]: true; } ``` ```typescript @@ -2826,12 +3195,6 @@ export interface TransactionPayment extends TransactionCommon { */ proposalId: string; /** - * How far did the wallet get with processing the payment? - * - * @deprecated use extendedStatus - */ - status: PaymentStatus; - /** * Amount that must be paid for the contract */ amountRaw: AmountString; @@ -2859,6 +3222,10 @@ export interface TransactionPayment extends TransactionCommon { * Is the wallet currently checking for a refund? */ refundQueryActive: boolean; + /** + * Does this purchase has an pos validation + */ + posConfirmation: string | undefined; } ``` ```typescript @@ -2962,27 +3329,6 @@ export interface Tax { } ``` ```typescript -export declare enum PaymentStatus { - /** - * Explicitly aborted after timeout / failure - */ - Aborted = "aborted", - /** - * Payment failed, wallet will auto-retry. - * User should be given the option to retry now / abort. - */ - Failed = "failed", - /** - * Paid successfully - */ - Paid = "paid", - /** - * User accepted, payment is processing. - */ - Accepted = "accepted", -} -``` -```typescript export interface RefundInfoShort { transactionId: string; timestamp: TalerProtocolTimestamp; @@ -2993,19 +3339,28 @@ export interface RefundInfoShort { ```typescript export interface TransactionRefund extends TransactionCommon { type: TransactionType.Refund; + amountRaw: AmountString; + amountEffective: AmountString; refundedTransactionId: string; - info: OrderShortInfo; + paymentInfo: RefundPaymentInfo | undefined; +} +``` +```typescript +/** + * Summary information about the payment that we got a refund for. + */ +export interface RefundPaymentInfo { + summary: string; + summary_i18n?: InternationalizedString; /** - * Amount pending to be picked up + * More information about the merchant */ - refundPending: AmountString | undefined; - amountRaw: AmountString; - amountEffective: AmountString; + merchant: MerchantInfo; } ``` ```typescript -export interface TransactionTip extends TransactionCommon { - type: TransactionType.Tip; +export interface TransactionReward extends TransactionCommon { + type: TransactionType.Reward; amountRaw: AmountString; /** * More information about the merchant @@ -3056,6 +3411,8 @@ export declare enum RefreshReason { PayPeerPull = "pay-peer-pull", Refund = "refund", AbortPay = "abort-pay", + AbortDeposit = "abort-deposit", + AbortPeerPushDebit = "abort-peer-push-debit", Recoup = "recoup", BackupRestored = "backup-restored", Scheduled = "scheduled", @@ -3087,6 +3444,12 @@ export interface TransactionDeposit extends TransactionCommon { * Did all the deposit requests succeed? */ deposited: boolean; + trackingState: Array<{ + wireTransferId: string; + timestampExecuted: TalerProtocolTimestamp; + amountRaw: AmountString; + wireFee: AmountString; + }>; } ``` ```typescript @@ -3182,16 +3545,39 @@ export interface TransactionPeerPushDebit extends TransactionCommon { } ``` ```typescript -export interface AbortTransactionRequest { - transactionId: string; +/** + * Internal withdrawal operation, only reported on request. + * + * Some transactions (peer-*-credit) internally do a withdrawal, + * but only the peer-*-credit transaction is reported. + * + * The internal withdrawal transaction allows to access the details of + * the underlying withdrawal for testing/debugging. + * + * It is usually not reported, so that amounts of transactions properly + * add up, since the amountEffecive of the withdrawal is already reported + * in the peer-*-credit transaction. + */ +export interface TransactionInternalWithdrawal extends TransactionCommon { + type: TransactionType.InternalWithdrawal; /** - * Move the payment immediately into an aborted state. - * The UI should warn the user that this might lead - * to money being lost. - * - * Defaults to false. + * Exchange of the withdrawal. */ - forceImmediateAbort?: boolean; + exchangeBaseUrl: string; + /** + * Amount that got subtracted from the reserve balance. + */ + amountRaw: AmountString; + /** + * Amount that actually was (or will be) added to the wallet's balance. + */ + amountEffective: AmountString; + withdrawalDetails: WithdrawalDetails; +} +``` +```typescript +export interface AbortTransactionRequest { + transactionId: TransactionIdStr; } ``` ```typescript @@ -3200,14 +3586,10 @@ export interface ExchangeListItem { currency: string | undefined; paytoUris: string[]; tosStatus: ExchangeTosStatus; - exchangeStatus: ExchangeEntryStatus; + exchangeEntryStatus: ExchangeEntryStatus; + exchangeUpdateStatus: ExchangeUpdateStatus; ageRestrictionOptions: number[]; /** - * Permanently added to the wallet, as opposed to just - * temporarily queried. - */ - permanent: boolean; - /** * Information about the last error that occurred when trying * to update the exchange info. */ @@ -3216,18 +3598,27 @@ export interface ExchangeListItem { ``` ```typescript export declare enum ExchangeTosStatus { - New = "new", + Pending = "pending", + Proposed = "proposed", Accepted = "accepted", - Changed = "changed", - NotFound = "not-found", - Unknown = "unknown", } ``` ```typescript export declare enum ExchangeEntryStatus { - Unknown = "unknown", - Outdated = "outdated", - Ok = "ok", + Preset = "preset", + Ephemeral = "ephemeral", + Used = "used", +} +``` +```typescript +export declare enum ExchangeUpdateStatus { + Initial = "initial", + InitialUpdate = "initial(update)", + Suspended = "suspended", + Failed = "failed", + OutdatedUpdate = "outdated(update)", + Ready = "ready", + ReadyUpdate = "ready(update)", } ``` ```typescript @@ -3255,10 +3646,13 @@ export type PreparePayResult = ```typescript export interface PreparePayResultInsufficientBalance { status: PreparePayResultType.InsufficientBalance; + transactionId: TransactionIdStr; + /** + * @deprecated use transactionId + */ proposalId: string; contractTerms: MerchantContractTerms; amountRaw: string; - noncePriv: string; talerUri: string; balanceDetails: PayMerchantInsufficientBalanceDetails; } @@ -3295,10 +3689,6 @@ export interface MerchantContractTerms { */ amount: string; /** - * Auditors accepted by the merchant. - */ - auditors: AuditorHandle[]; - /** * Deadline to pay for the contract. */ pay_deadline: TalerProtocolTimestamp; @@ -3385,22 +3775,6 @@ export interface MerchantContractTerms { } ``` ```typescript -export interface AuditorHandle { - /** - * Official name of the auditor. - */ - name: string; - /** - * Master public signing key of the auditor. - */ - auditor_pub: string; - /** - * Base URL of the auditor. - */ - url: string; -} -``` -```typescript /** * Information about an exchange as stored inside a * merchant's contract terms. @@ -3447,7 +3821,7 @@ export interface PayMerchantInsufficientBalanceDetails { balanceMerchantDepositable: AmountString; /** * If the payment would succeed without fees - * (i.e. balanceMechantWireable >= amountRequested), + * (i.e. balanceMerchantDepositable >= amountRequested), * this field contains an estimate of the amount that would additionally * be required to cover the fees. * @@ -3460,13 +3834,17 @@ export interface PayMerchantInsufficientBalanceDetails { ```typescript export interface PreparePayResultAlreadyConfirmed { status: PreparePayResultType.AlreadyConfirmed; + transactionId: TransactionIdStr; contractTerms: MerchantContractTerms; paid: boolean; amountRaw: string; - amountEffective: string; + amountEffective: string | undefined; contractTermsHash: string; + /** + * @deprecated use transactionId + */ proposalId: string; - talerUri?: string; + talerUri: string; } ``` ```typescript @@ -3475,12 +3853,15 @@ export interface PreparePayResultAlreadyConfirmed { */ export interface PreparePayResultPaymentPossible { status: PreparePayResultType.PaymentPossible; + transactionId: TransactionIdStr; + /** + * @deprecated use transactionId instead + */ proposalId: string; contractTerms: MerchantContractTerms; contractTermsHash: string; amountRaw: string; amountEffective: string; - noncePriv: string; talerUri: string; } ``` @@ -3496,20 +3877,9 @@ export interface ForcedCoinSel { } ``` ```typescript -export interface ApplyRefundResponse { - contractTermsHash: string; - transactionId: string; - proposalId: string; - amountEffectivePaid: AmountString; - amountRefundGranted: AmountString; - amountRefundGone: AmountString; - pendingAtExchange: boolean; - info: OrderShortInfo; -} -``` -```typescript export interface AddExchangeRequest { exchangeBaseUrl: string; + masterPub?: string; forceUpdate?: boolean; } ``` @@ -3532,3 +3902,13 @@ export interface PeerContractTerms { purse_expiration: TalerProtocolTimestamp; } ``` +```typescript +export interface IntegrationTestArgs { + exchangeBaseUrl: string; + bankAccessApiBaseUrl: string; + merchantBaseUrl: string; + merchantAuthToken?: string; + amountToWithdraw: string; + amountToSpend: string; +} +```