evennia/docs/5.x/_modules/django/utils/http.html
2025-07-01 10:01:48 +02:00

477 lines
No EOL
54 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>django.utils.http &#8212; Evennia latest documentation</title>
<link rel="stylesheet" href="../../../_static/nature.css" type="text/css" />
<link rel="stylesheet" href="../../../_static/pygments.css" type="text/css" />
<link rel="stylesheet" type="text/css" href="../../../_static/pygments.css?v=d75fae25" />
<link rel="stylesheet" type="text/css" href="../../../_static/nature.css?v=245aff17" />
<script id="documentation_options" data-url_root="../../../" src="../../../_static/documentation_options.js"></script>
<script src="../../../_static/documentation_options.js?v=c6e86fd7"></script>
<script src="../../../_static/doctools.js?v=9bcbadda"></script>
<script src="../../../_static/sphinx_highlight.js?v=dc90522c"></script>
<link rel="index" title="Index" href="../../../genindex.html" />
<link rel="search" title="Search" href="../../../search.html" />
</head><body>
<div class="related" role="navigation" aria-label="related navigation">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../../../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../../../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="nav-item nav-item-0"><a href="../../../index.html">Evennia latest</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="../../index.html" accesskey="U">Module code</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">django.utils.http</a></li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
<div class="sphinxsidebarwrapper">
<search id="searchbox" style="display: none" role="search">
<h3 id="searchlabel">Quick search</h3>
<div class="searchformwrapper">
<form class="search" action="../../../search.html" method="get">
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
<input type="submit" value="Go" />
</form>
</div>
</search>
<script>document.getElementById('searchbox').style.display = "block"</script><h3>Links</h3>
<ul>
<li><a href="https://www.evennia.com/docs/latest/index.html">Documentation Top</a> </li>
<li><a href="https://www.evennia.com">Evennia Home</a> </li>
<li><a href="https://github.com/evennia/evennia">Github</a> </li>
<li><a href="http://games.evennia.com">Game Index</a> </li>
<li>
<a href="https://discord.gg/AJJpcRUhtF">Discord</a> -
<a href="https://github.com/evennia/evennia/discussions">Discussions</a> -
<a href="https://evennia.blogspot.com/">Blog</a>
</li>
</ul>
</div>
</div>
<div class="bodywrapper">
<div class="body" role="main">
<h1>Source code for django.utils.http</h1><div class="highlight"><pre>
<span></span><span class="kn">import</span><span class="w"> </span><span class="nn">base64</span>
<span class="kn">import</span><span class="w"> </span><span class="nn">re</span>
<span class="kn">import</span><span class="w"> </span><span class="nn">unicodedata</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">binascii</span><span class="w"> </span><span class="kn">import</span> <span class="n">Error</span> <span class="k">as</span> <span class="n">BinasciiError</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">datetime</span><span class="w"> </span><span class="kn">import</span> <span class="n">datetime</span><span class="p">,</span> <span class="n">timezone</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">email.utils</span><span class="w"> </span><span class="kn">import</span> <span class="n">formatdate</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">urllib.parse</span><span class="w"> </span><span class="kn">import</span> <span class="n">quote</span><span class="p">,</span> <span class="n">unquote</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">urllib.parse</span><span class="w"> </span><span class="kn">import</span> <span class="n">urlencode</span> <span class="k">as</span> <span class="n">original_urlencode</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">urllib.parse</span><span class="w"> </span><span class="kn">import</span> <span class="n">urlparse</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">django.utils.datastructures</span><span class="w"> </span><span class="kn">import</span> <span class="n">MultiValueDict</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">django.utils.regex_helper</span><span class="w"> </span><span class="kn">import</span> <span class="n">_lazy_re_compile</span>
<span class="c1"># Based on RFC 9110 Appendix A.</span>
<span class="n">ETAG_MATCH</span> <span class="o">=</span> <span class="n">_lazy_re_compile</span><span class="p">(</span>
<span class="w"> </span><span class="sa">r</span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> \A( # start of string and capture group</span>
<span class="sd"> (?:W/)? # optional weak indicator</span>
<span class="sd"> &quot; # opening quote</span>
<span class="sd"> [^&quot;]* # any sequence of non-quote characters</span>
<span class="sd"> &quot; # end quote</span>
<span class="sd"> )\Z # end of string and capture group</span>
<span class="sd">&quot;&quot;&quot;</span><span class="p">,</span>
<span class="n">re</span><span class="o">.</span><span class="n">X</span><span class="p">,</span>
<span class="p">)</span>
<span class="n">MONTHS</span> <span class="o">=</span> <span class="s2">&quot;jan feb mar apr may jun jul aug sep oct nov dec&quot;</span><span class="o">.</span><span class="n">split</span><span class="p">()</span>
<span class="n">__D</span> <span class="o">=</span> <span class="sa">r</span><span class="s2">&quot;(?P&lt;day&gt;[0-9]</span><span class="si">{2}</span><span class="s2">)&quot;</span>
<span class="n">__D2</span> <span class="o">=</span> <span class="sa">r</span><span class="s2">&quot;(?P&lt;day&gt;[ 0-9][0-9])&quot;</span>
<span class="n">__M</span> <span class="o">=</span> <span class="sa">r</span><span class="s2">&quot;(?P&lt;mon&gt;\w</span><span class="si">{3}</span><span class="s2">)&quot;</span>
<span class="n">__Y</span> <span class="o">=</span> <span class="sa">r</span><span class="s2">&quot;(?P&lt;year&gt;[0-9]</span><span class="si">{4}</span><span class="s2">)&quot;</span>
<span class="n">__Y2</span> <span class="o">=</span> <span class="sa">r</span><span class="s2">&quot;(?P&lt;year&gt;[0-9]</span><span class="si">{2}</span><span class="s2">)&quot;</span>
<span class="n">__T</span> <span class="o">=</span> <span class="sa">r</span><span class="s2">&quot;(?P&lt;hour&gt;[0-9]</span><span class="si">{2}</span><span class="s2">):(?P&lt;min&gt;[0-9]</span><span class="si">{2}</span><span class="s2">):(?P&lt;sec&gt;[0-9]</span><span class="si">{2}</span><span class="s2">)&quot;</span>
<span class="n">RFC1123_DATE</span> <span class="o">=</span> <span class="n">_lazy_re_compile</span><span class="p">(</span><span class="sa">r</span><span class="s2">&quot;^\w</span><span class="si">{3}</span><span class="s2">, </span><span class="si">%s</span><span class="s2"> </span><span class="si">%s</span><span class="s2"> </span><span class="si">%s</span><span class="s2"> </span><span class="si">%s</span><span class="s2"> GMT$&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">__D</span><span class="p">,</span> <span class="n">__M</span><span class="p">,</span> <span class="n">__Y</span><span class="p">,</span> <span class="n">__T</span><span class="p">))</span>
<span class="n">RFC850_DATE</span> <span class="o">=</span> <span class="n">_lazy_re_compile</span><span class="p">(</span><span class="sa">r</span><span class="s2">&quot;^\w{6,9}, </span><span class="si">%s</span><span class="s2">-</span><span class="si">%s</span><span class="s2">-</span><span class="si">%s</span><span class="s2"> </span><span class="si">%s</span><span class="s2"> GMT$&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">__D</span><span class="p">,</span> <span class="n">__M</span><span class="p">,</span> <span class="n">__Y2</span><span class="p">,</span> <span class="n">__T</span><span class="p">))</span>
<span class="n">ASCTIME_DATE</span> <span class="o">=</span> <span class="n">_lazy_re_compile</span><span class="p">(</span><span class="sa">r</span><span class="s2">&quot;^\w</span><span class="si">{3}</span><span class="s2"> </span><span class="si">%s</span><span class="s2"> </span><span class="si">%s</span><span class="s2"> </span><span class="si">%s</span><span class="s2"> </span><span class="si">%s</span><span class="s2">$&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">__M</span><span class="p">,</span> <span class="n">__D2</span><span class="p">,</span> <span class="n">__T</span><span class="p">,</span> <span class="n">__Y</span><span class="p">))</span>
<span class="n">RFC3986_GENDELIMS</span> <span class="o">=</span> <span class="s2">&quot;:/?#[]@&quot;</span>
<span class="n">RFC3986_SUBDELIMS</span> <span class="o">=</span> <span class="s2">&quot;!$&amp;&#39;()*+,;=&quot;</span>
<span class="k">def</span><span class="w"> </span><span class="nf">urlencode</span><span class="p">(</span><span class="n">query</span><span class="p">,</span> <span class="n">doseq</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> A version of Python&#39;s urllib.parse.urlencode() function that can operate on</span>
<span class="sd"> MultiValueDict and non-string values.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">query</span><span class="p">,</span> <span class="n">MultiValueDict</span><span class="p">):</span>
<span class="n">query</span> <span class="o">=</span> <span class="n">query</span><span class="o">.</span><span class="n">lists</span><span class="p">()</span>
<span class="k">elif</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">query</span><span class="p">,</span> <span class="s2">&quot;items&quot;</span><span class="p">):</span>
<span class="n">query</span> <span class="o">=</span> <span class="n">query</span><span class="o">.</span><span class="n">items</span><span class="p">()</span>
<span class="n">query_params</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">query</span><span class="p">:</span>
<span class="k">if</span> <span class="n">value</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span>
<span class="s2">&quot;Cannot encode None for key &#39;</span><span class="si">%s</span><span class="s2">&#39; in a query string. Did you &quot;</span>
<span class="s2">&quot;mean to pass an empty string or omit the value?&quot;</span> <span class="o">%</span> <span class="n">key</span>
<span class="p">)</span>
<span class="k">elif</span> <span class="ow">not</span> <span class="n">doseq</span> <span class="ow">or</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="p">(</span><span class="nb">str</span><span class="p">,</span> <span class="nb">bytes</span><span class="p">)):</span>
<span class="n">query_val</span> <span class="o">=</span> <span class="n">value</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">itr</span> <span class="o">=</span> <span class="nb">iter</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
<span class="k">except</span> <span class="ne">TypeError</span><span class="p">:</span>
<span class="n">query_val</span> <span class="o">=</span> <span class="n">value</span>
<span class="k">else</span><span class="p">:</span>
<span class="c1"># Consume generators and iterators, when doseq=True, to</span>
<span class="c1"># work around https://bugs.python.org/issue31706.</span>
<span class="n">query_val</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">itr</span><span class="p">:</span>
<span class="k">if</span> <span class="n">item</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span>
<span class="s2">&quot;Cannot encode None for key &#39;</span><span class="si">%s</span><span class="s2">&#39; in a query &quot;</span>
<span class="s2">&quot;string. Did you mean to pass an empty string or &quot;</span>
<span class="s2">&quot;omit the value?&quot;</span> <span class="o">%</span> <span class="n">key</span>
<span class="p">)</span>
<span class="k">elif</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">item</span><span class="p">,</span> <span class="nb">bytes</span><span class="p">):</span>
<span class="n">item</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
<span class="n">query_val</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
<span class="n">query_params</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">key</span><span class="p">,</span> <span class="n">query_val</span><span class="p">))</span>
<span class="k">return</span> <span class="n">original_urlencode</span><span class="p">(</span><span class="n">query_params</span><span class="p">,</span> <span class="n">doseq</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">http_date</span><span class="p">(</span><span class="n">epoch_seconds</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Format the time to match the RFC 5322 date format as specified by RFC 9110</span>
<span class="sd"> Section 5.6.7.</span>
<span class="sd"> `epoch_seconds` is a floating point number expressed in seconds since the</span>
<span class="sd"> epoch, in UTC - such as that outputted by time.time(). If set to None, it</span>
<span class="sd"> defaults to the current time.</span>
<span class="sd"> Output a string in the format &#39;Wdy, DD Mon YYYY HH:MM:SS GMT&#39;.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">return</span> <span class="n">formatdate</span><span class="p">(</span><span class="n">epoch_seconds</span><span class="p">,</span> <span class="n">usegmt</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">parse_http_date</span><span class="p">(</span><span class="n">date</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Parse a date format as specified by HTTP RFC 9110 Section 5.6.7.</span>
<span class="sd"> The three formats allowed by the RFC are accepted, even if only the first</span>
<span class="sd"> one is still in widespread use.</span>
<span class="sd"> Return an integer expressed in seconds since the epoch, in UTC.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="c1"># email.utils.parsedate() does the job for RFC 1123 dates; unfortunately</span>
<span class="c1"># RFC 9110 makes it mandatory to support RFC 850 dates too. So we roll</span>
<span class="c1"># our own RFC-compliant parsing.</span>
<span class="k">for</span> <span class="n">regex</span> <span class="ow">in</span> <span class="n">RFC1123_DATE</span><span class="p">,</span> <span class="n">RFC850_DATE</span><span class="p">,</span> <span class="n">ASCTIME_DATE</span><span class="p">:</span>
<span class="n">m</span> <span class="o">=</span> <span class="n">regex</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">date</span><span class="p">)</span>
<span class="k">if</span> <span class="n">m</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
<span class="k">break</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&quot;</span><span class="si">%r</span><span class="s2"> is not in a valid HTTP date format&quot;</span> <span class="o">%</span> <span class="n">date</span><span class="p">)</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">year</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">m</span><span class="p">[</span><span class="s2">&quot;year&quot;</span><span class="p">])</span>
<span class="k">if</span> <span class="n">year</span> <span class="o">&lt;</span> <span class="mi">100</span><span class="p">:</span>
<span class="n">current_year</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">now</span><span class="p">(</span><span class="n">tz</span><span class="o">=</span><span class="n">timezone</span><span class="o">.</span><span class="n">utc</span><span class="p">)</span><span class="o">.</span><span class="n">year</span>
<span class="n">current_century</span> <span class="o">=</span> <span class="n">current_year</span> <span class="o">-</span> <span class="p">(</span><span class="n">current_year</span> <span class="o">%</span> <span class="mi">100</span><span class="p">)</span>
<span class="k">if</span> <span class="n">year</span> <span class="o">-</span> <span class="p">(</span><span class="n">current_year</span> <span class="o">%</span> <span class="mi">100</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">50</span><span class="p">:</span>
<span class="c1"># year that appears to be more than 50 years in the future are</span>
<span class="c1"># interpreted as representing the past.</span>
<span class="n">year</span> <span class="o">+=</span> <span class="n">current_century</span> <span class="o">-</span> <span class="mi">100</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">year</span> <span class="o">+=</span> <span class="n">current_century</span>
<span class="n">month</span> <span class="o">=</span> <span class="n">MONTHS</span><span class="o">.</span><span class="n">index</span><span class="p">(</span><span class="n">m</span><span class="p">[</span><span class="s2">&quot;mon&quot;</span><span class="p">]</span><span class="o">.</span><span class="n">lower</span><span class="p">())</span> <span class="o">+</span> <span class="mi">1</span>
<span class="n">day</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">m</span><span class="p">[</span><span class="s2">&quot;day&quot;</span><span class="p">])</span>
<span class="n">hour</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">m</span><span class="p">[</span><span class="s2">&quot;hour&quot;</span><span class="p">])</span>
<span class="nb">min</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">m</span><span class="p">[</span><span class="s2">&quot;min&quot;</span><span class="p">])</span>
<span class="n">sec</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">m</span><span class="p">[</span><span class="s2">&quot;sec&quot;</span><span class="p">])</span>
<span class="n">result</span> <span class="o">=</span> <span class="n">datetime</span><span class="p">(</span><span class="n">year</span><span class="p">,</span> <span class="n">month</span><span class="p">,</span> <span class="n">day</span><span class="p">,</span> <span class="n">hour</span><span class="p">,</span> <span class="nb">min</span><span class="p">,</span> <span class="n">sec</span><span class="p">,</span> <span class="n">tzinfo</span><span class="o">=</span><span class="n">timezone</span><span class="o">.</span><span class="n">utc</span><span class="p">)</span>
<span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="n">result</span><span class="o">.</span><span class="n">timestamp</span><span class="p">())</span>
<span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&quot;</span><span class="si">%r</span><span class="s2"> is not a valid date&quot;</span> <span class="o">%</span> <span class="n">date</span><span class="p">)</span> <span class="kn">from</span><span class="w"> </span><span class="nn">exc</span>
<span class="k">def</span><span class="w"> </span><span class="nf">parse_http_date_safe</span><span class="p">(</span><span class="n">date</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Same as parse_http_date, but return None if the input is invalid.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">try</span><span class="p">:</span>
<span class="k">return</span> <span class="n">parse_http_date</span><span class="p">(</span><span class="n">date</span><span class="p">)</span>
<span class="k">except</span> <span class="ne">Exception</span><span class="p">:</span>
<span class="k">pass</span>
<span class="c1"># Base 36 functions: useful for generating compact URLs</span>
<span class="k">def</span><span class="w"> </span><span class="nf">base36_to_int</span><span class="p">(</span><span class="n">s</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Convert a base 36 string to an int. Raise ValueError if the input won&#39;t fit</span>
<span class="sd"> into an int.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="c1"># To prevent overconsumption of server resources, reject any</span>
<span class="c1"># base36 string that is longer than 13 base36 digits (13 digits</span>
<span class="c1"># is sufficient to base36-encode any 64-bit integer)</span>
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">13</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&quot;Base36 input too large&quot;</span><span class="p">)</span>
<span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="mi">36</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">int_to_base36</span><span class="p">(</span><span class="n">i</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Convert an integer to a base36 string.&quot;&quot;&quot;</span>
<span class="n">char_set</span> <span class="o">=</span> <span class="s2">&quot;0123456789abcdefghijklmnopqrstuvwxyz&quot;</span>
<span class="k">if</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&quot;Negative base36 conversion input.&quot;</span><span class="p">)</span>
<span class="k">if</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">36</span><span class="p">:</span>
<span class="k">return</span> <span class="n">char_set</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
<span class="n">b36</span> <span class="o">=</span> <span class="s2">&quot;&quot;</span>
<span class="k">while</span> <span class="n">i</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">:</span>
<span class="n">i</span><span class="p">,</span> <span class="n">n</span> <span class="o">=</span> <span class="nb">divmod</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="mi">36</span><span class="p">)</span>
<span class="n">b36</span> <span class="o">=</span> <span class="n">char_set</span><span class="p">[</span><span class="n">n</span><span class="p">]</span> <span class="o">+</span> <span class="n">b36</span>
<span class="k">return</span> <span class="n">b36</span>
<span class="k">def</span><span class="w"> </span><span class="nf">urlsafe_base64_encode</span><span class="p">(</span><span class="n">s</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Encode a bytestring to a base64 string for use in URLs. Strip any trailing</span>
<span class="sd"> equal signs.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">return</span> <span class="n">base64</span><span class="o">.</span><span class="n">urlsafe_b64encode</span><span class="p">(</span><span class="n">s</span><span class="p">)</span><span class="o">.</span><span class="n">rstrip</span><span class="p">(</span><span class="sa">b</span><span class="s2">&quot;</span><span class="se">\n</span><span class="s2">=&quot;</span><span class="p">)</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">&quot;ascii&quot;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">urlsafe_base64_decode</span><span class="p">(</span><span class="n">s</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Decode a base64 encoded string. Add back any trailing equal signs that</span>
<span class="sd"> might have been stripped.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">s</span> <span class="o">=</span> <span class="n">s</span><span class="o">.</span><span class="n">encode</span><span class="p">()</span>
<span class="k">try</span><span class="p">:</span>
<span class="k">return</span> <span class="n">base64</span><span class="o">.</span><span class="n">urlsafe_b64decode</span><span class="p">(</span><span class="n">s</span><span class="o">.</span><span class="n">ljust</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="o">+</span> <span class="nb">len</span><span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="o">%</span> <span class="mi">4</span><span class="p">,</span> <span class="sa">b</span><span class="s2">&quot;=&quot;</span><span class="p">))</span>
<span class="k">except</span> <span class="p">(</span><span class="ne">LookupError</span><span class="p">,</span> <span class="n">BinasciiError</span><span class="p">)</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="n">e</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">parse_etags</span><span class="p">(</span><span class="n">etag_str</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Parse a string of ETags given in an If-None-Match or If-Match header as</span>
<span class="sd"> defined by RFC 9110. Return a list of quoted ETags, or [&#39;*&#39;] if all ETags</span>
<span class="sd"> should be matched.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">if</span> <span class="n">etag_str</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span> <span class="o">==</span> <span class="s2">&quot;*&quot;</span><span class="p">:</span>
<span class="k">return</span> <span class="p">[</span><span class="s2">&quot;*&quot;</span><span class="p">]</span>
<span class="k">else</span><span class="p">:</span>
<span class="c1"># Parse each ETag individually, and return any that are valid.</span>
<span class="n">etag_matches</span> <span class="o">=</span> <span class="p">(</span><span class="n">ETAG_MATCH</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">etag</span><span class="o">.</span><span class="n">strip</span><span class="p">())</span> <span class="k">for</span> <span class="n">etag</span> <span class="ow">in</span> <span class="n">etag_str</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">&quot;,&quot;</span><span class="p">))</span>
<span class="k">return</span> <span class="p">[</span><span class="n">match</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="k">for</span> <span class="n">match</span> <span class="ow">in</span> <span class="n">etag_matches</span> <span class="k">if</span> <span class="n">match</span><span class="p">]</span>
<span class="k">def</span><span class="w"> </span><span class="nf">quote_etag</span><span class="p">(</span><span class="n">etag_str</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> If the provided string is already a quoted ETag, return it. Otherwise, wrap</span>
<span class="sd"> the string in quotes, making it a strong ETag.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">if</span> <span class="n">ETAG_MATCH</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">etag_str</span><span class="p">):</span>
<span class="k">return</span> <span class="n">etag_str</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">return</span> <span class="s1">&#39;&quot;</span><span class="si">%s</span><span class="s1">&quot;&#39;</span> <span class="o">%</span> <span class="n">etag_str</span>
<span class="k">def</span><span class="w"> </span><span class="nf">is_same_domain</span><span class="p">(</span><span class="n">host</span><span class="p">,</span> <span class="n">pattern</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Return ``True`` if the host is either an exact match or a match</span>
<span class="sd"> to the wildcard pattern.</span>
<span class="sd"> Any pattern beginning with a period matches a domain and all of its</span>
<span class="sd"> subdomains. (e.g. ``.example.com`` matches ``example.com`` and</span>
<span class="sd"> ``foo.example.com``). Anything else is an exact string match.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">pattern</span><span class="p">:</span>
<span class="k">return</span> <span class="kc">False</span>
<span class="n">pattern</span> <span class="o">=</span> <span class="n">pattern</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span>
<span class="k">return</span> <span class="p">(</span>
<span class="n">pattern</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s2">&quot;.&quot;</span>
<span class="ow">and</span> <span class="p">(</span><span class="n">host</span><span class="o">.</span><span class="n">endswith</span><span class="p">(</span><span class="n">pattern</span><span class="p">)</span> <span class="ow">or</span> <span class="n">host</span> <span class="o">==</span> <span class="n">pattern</span><span class="p">[</span><span class="mi">1</span><span class="p">:])</span>
<span class="ow">or</span> <span class="n">pattern</span> <span class="o">==</span> <span class="n">host</span>
<span class="p">)</span>
<div class="viewcode-block" id="url_has_allowed_host_and_scheme">
<a class="viewcode-back" href="../../../api/evennia.web.website.views.characters.html#evennia.web.website.views.characters.url_has_allowed_host_and_scheme">[docs]</a>
<span class="k">def</span><span class="w"> </span><span class="nf">url_has_allowed_host_and_scheme</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">allowed_hosts</span><span class="p">,</span> <span class="n">require_https</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Return ``True`` if the url uses an allowed host and a safe scheme.</span>
<span class="sd"> Always return ``False`` on an empty url.</span>
<span class="sd"> If ``require_https`` is ``True``, only &#39;https&#39; will be considered a valid</span>
<span class="sd"> scheme, as opposed to &#39;http&#39; and &#39;https&#39; with the default, ``False``.</span>
<span class="sd"> Note: &quot;True&quot; doesn&#39;t entail that a URL is &quot;safe&quot;. It may still be e.g.</span>
<span class="sd"> quoted incorrectly. Ensure to also use django.utils.encoding.iri_to_uri()</span>
<span class="sd"> on the path component of untrusted URLs.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">if</span> <span class="n">url</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">url</span> <span class="o">=</span> <span class="n">url</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">url</span><span class="p">:</span>
<span class="k">return</span> <span class="kc">False</span>
<span class="k">if</span> <span class="n">allowed_hosts</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">allowed_hosts</span> <span class="o">=</span> <span class="nb">set</span><span class="p">()</span>
<span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">allowed_hosts</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
<span class="n">allowed_hosts</span> <span class="o">=</span> <span class="p">{</span><span class="n">allowed_hosts</span><span class="p">}</span>
<span class="c1"># Chrome treats \ completely as / in paths but it could be part of some</span>
<span class="c1"># basic auth credentials so we need to check both URLs.</span>
<span class="k">return</span> <span class="n">_url_has_allowed_host_and_scheme</span><span class="p">(</span>
<span class="n">url</span><span class="p">,</span> <span class="n">allowed_hosts</span><span class="p">,</span> <span class="n">require_https</span><span class="o">=</span><span class="n">require_https</span>
<span class="p">)</span> <span class="ow">and</span> <span class="n">_url_has_allowed_host_and_scheme</span><span class="p">(</span>
<span class="n">url</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s2">&quot;</span><span class="se">\\</span><span class="s2">&quot;</span><span class="p">,</span> <span class="s2">&quot;/&quot;</span><span class="p">),</span> <span class="n">allowed_hosts</span><span class="p">,</span> <span class="n">require_https</span><span class="o">=</span><span class="n">require_https</span>
<span class="p">)</span></div>
<span class="k">def</span><span class="w"> </span><span class="nf">_url_has_allowed_host_and_scheme</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">allowed_hosts</span><span class="p">,</span> <span class="n">require_https</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
<span class="c1"># Chrome considers any URL with more than two slashes to be absolute, but</span>
<span class="c1"># urlparse is not so flexible. Treat any url with three slashes as unsafe.</span>
<span class="k">if</span> <span class="n">url</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s2">&quot;///&quot;</span><span class="p">):</span>
<span class="k">return</span> <span class="kc">False</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">url_info</span> <span class="o">=</span> <span class="n">urlparse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
<span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span> <span class="c1"># e.g. invalid IPv6 addresses</span>
<span class="k">return</span> <span class="kc">False</span>
<span class="c1"># Forbid URLs like http:///example.com - with a scheme, but without a hostname.</span>
<span class="c1"># In that URL, example.com is not the hostname but, a path component. However,</span>
<span class="c1"># Chrome will still consider example.com to be the hostname, so we must not</span>
<span class="c1"># allow this syntax.</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">url_info</span><span class="o">.</span><span class="n">netloc</span> <span class="ow">and</span> <span class="n">url_info</span><span class="o">.</span><span class="n">scheme</span><span class="p">:</span>
<span class="k">return</span> <span class="kc">False</span>
<span class="c1"># Forbid URLs that start with control characters. Some browsers (like</span>
<span class="c1"># Chrome) ignore quite a few control characters at the start of a</span>
<span class="c1"># URL and might consider the URL as scheme relative.</span>
<span class="k">if</span> <span class="n">unicodedata</span><span class="o">.</span><span class="n">category</span><span class="p">(</span><span class="n">url</span><span class="p">[</span><span class="mi">0</span><span class="p">])[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s2">&quot;C&quot;</span><span class="p">:</span>
<span class="k">return</span> <span class="kc">False</span>
<span class="n">scheme</span> <span class="o">=</span> <span class="n">url_info</span><span class="o">.</span><span class="n">scheme</span>
<span class="c1"># Consider URLs without a scheme (e.g. //example.com/p) to be http.</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">url_info</span><span class="o">.</span><span class="n">scheme</span> <span class="ow">and</span> <span class="n">url_info</span><span class="o">.</span><span class="n">netloc</span><span class="p">:</span>
<span class="n">scheme</span> <span class="o">=</span> <span class="s2">&quot;http&quot;</span>
<span class="n">valid_schemes</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&quot;https&quot;</span><span class="p">]</span> <span class="k">if</span> <span class="n">require_https</span> <span class="k">else</span> <span class="p">[</span><span class="s2">&quot;http&quot;</span><span class="p">,</span> <span class="s2">&quot;https&quot;</span><span class="p">]</span>
<span class="k">return</span> <span class="p">(</span><span class="ow">not</span> <span class="n">url_info</span><span class="o">.</span><span class="n">netloc</span> <span class="ow">or</span> <span class="n">url_info</span><span class="o">.</span><span class="n">netloc</span> <span class="ow">in</span> <span class="n">allowed_hosts</span><span class="p">)</span> <span class="ow">and</span> <span class="p">(</span>
<span class="ow">not</span> <span class="n">scheme</span> <span class="ow">or</span> <span class="n">scheme</span> <span class="ow">in</span> <span class="n">valid_schemes</span>
<span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">escape_leading_slashes</span><span class="p">(</span><span class="n">url</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> If redirecting to an absolute path (two leading slashes), a slash must be</span>
<span class="sd"> escaped to prevent browsers from handling the path as schemaless and</span>
<span class="sd"> redirecting to another host.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">if</span> <span class="n">url</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s2">&quot;//&quot;</span><span class="p">):</span>
<span class="n">url</span> <span class="o">=</span> <span class="s2">&quot;/</span><span class="si">%2F{}</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">url</span><span class="o">.</span><span class="n">removeprefix</span><span class="p">(</span><span class="s2">&quot;//&quot;</span><span class="p">))</span>
<span class="k">return</span> <span class="n">url</span>
<span class="k">def</span><span class="w"> </span><span class="nf">_parseparam</span><span class="p">(</span><span class="n">s</span><span class="p">):</span>
<span class="k">while</span> <span class="n">s</span><span class="p">[:</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="s2">&quot;;&quot;</span><span class="p">:</span>
<span class="n">s</span> <span class="o">=</span> <span class="n">s</span><span class="p">[</span><span class="mi">1</span><span class="p">:]</span>
<span class="n">end</span> <span class="o">=</span> <span class="n">s</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="s2">&quot;;&quot;</span><span class="p">)</span>
<span class="k">while</span> <span class="n">end</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="ow">and</span> <span class="p">(</span><span class="n">s</span><span class="o">.</span><span class="n">count</span><span class="p">(</span><span class="s1">&#39;&quot;&#39;</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">end</span><span class="p">)</span> <span class="o">-</span> <span class="n">s</span><span class="o">.</span><span class="n">count</span><span class="p">(</span><span class="s1">&#39;</span><span class="se">\\</span><span class="s1">&quot;&#39;</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">end</span><span class="p">))</span> <span class="o">%</span> <span class="mi">2</span><span class="p">:</span>
<span class="n">end</span> <span class="o">=</span> <span class="n">s</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="s2">&quot;;&quot;</span><span class="p">,</span> <span class="n">end</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span>
<span class="k">if</span> <span class="n">end</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">:</span>
<span class="n">end</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">s</span><span class="p">)</span>
<span class="n">f</span> <span class="o">=</span> <span class="n">s</span><span class="p">[:</span><span class="n">end</span><span class="p">]</span>
<span class="k">yield</span> <span class="n">f</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
<span class="n">s</span> <span class="o">=</span> <span class="n">s</span><span class="p">[</span><span class="n">end</span><span class="p">:]</span>
<span class="k">def</span><span class="w"> </span><span class="nf">parse_header_parameters</span><span class="p">(</span><span class="n">line</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Parse a Content-type like header.</span>
<span class="sd"> Return the main content-type and a dictionary of options.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">parts</span> <span class="o">=</span> <span class="n">_parseparam</span><span class="p">(</span><span class="s2">&quot;;&quot;</span> <span class="o">+</span> <span class="n">line</span><span class="p">)</span>
<span class="n">key</span> <span class="o">=</span> <span class="n">parts</span><span class="o">.</span><span class="fm">__next__</span><span class="p">()</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span>
<span class="n">pdict</span> <span class="o">=</span> <span class="p">{}</span>
<span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">parts</span><span class="p">:</span>
<span class="n">i</span> <span class="o">=</span> <span class="n">p</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="s2">&quot;=&quot;</span><span class="p">)</span>
<span class="k">if</span> <span class="n">i</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">:</span>
<span class="n">has_encoding</span> <span class="o">=</span> <span class="kc">False</span>
<span class="n">name</span> <span class="o">=</span> <span class="n">p</span><span class="p">[:</span><span class="n">i</span><span class="p">]</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span>
<span class="k">if</span> <span class="n">name</span><span class="o">.</span><span class="n">endswith</span><span class="p">(</span><span class="s2">&quot;*&quot;</span><span class="p">):</span>
<span class="c1"># Lang/encoding embedded in the value (like &quot;filename*=UTF-8&#39;&#39;file.ext&quot;)</span>
<span class="c1"># https://tools.ietf.org/html/rfc2231#section-4</span>
<span class="n">name</span> <span class="o">=</span> <span class="n">name</span><span class="p">[:</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
<span class="k">if</span> <span class="n">p</span><span class="o">.</span><span class="n">count</span><span class="p">(</span><span class="s2">&quot;&#39;&quot;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">2</span><span class="p">:</span>
<span class="n">has_encoding</span> <span class="o">=</span> <span class="kc">True</span>
<span class="n">value</span> <span class="o">=</span> <span class="n">p</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span> <span class="p">:]</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">value</span><span class="p">)</span> <span class="o">&gt;=</span> <span class="mi">2</span> <span class="ow">and</span> <span class="n">value</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="n">value</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="s1">&#39;&quot;&#39;</span><span class="p">:</span>
<span class="n">value</span> <span class="o">=</span> <span class="n">value</span><span class="p">[</span><span class="mi">1</span><span class="p">:</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
<span class="n">value</span> <span class="o">=</span> <span class="n">value</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s2">&quot;</span><span class="se">\\\\</span><span class="s2">&quot;</span><span class="p">,</span> <span class="s2">&quot;</span><span class="se">\\</span><span class="s2">&quot;</span><span class="p">)</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s1">&#39;</span><span class="se">\\</span><span class="s1">&quot;&#39;</span><span class="p">,</span> <span class="s1">&#39;&quot;&#39;</span><span class="p">)</span>
<span class="k">if</span> <span class="n">has_encoding</span><span class="p">:</span>
<span class="n">encoding</span><span class="p">,</span> <span class="n">lang</span><span class="p">,</span> <span class="n">value</span> <span class="o">=</span> <span class="n">value</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">&quot;&#39;&quot;</span><span class="p">)</span>
<span class="n">value</span> <span class="o">=</span> <span class="n">unquote</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="n">encoding</span><span class="o">=</span><span class="n">encoding</span><span class="p">)</span>
<span class="n">pdict</span><span class="p">[</span><span class="n">name</span><span class="p">]</span> <span class="o">=</span> <span class="n">value</span>
<span class="k">return</span> <span class="n">key</span><span class="p">,</span> <span class="n">pdict</span>
<span class="k">def</span><span class="w"> </span><span class="nf">content_disposition_header</span><span class="p">(</span><span class="n">as_attachment</span><span class="p">,</span> <span class="n">filename</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Construct a Content-Disposition HTTP header value from the given filename</span>
<span class="sd"> as specified by RFC 6266.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">if</span> <span class="n">filename</span><span class="p">:</span>
<span class="n">disposition</span> <span class="o">=</span> <span class="s2">&quot;attachment&quot;</span> <span class="k">if</span> <span class="n">as_attachment</span> <span class="k">else</span> <span class="s2">&quot;inline&quot;</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">filename</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">&quot;ascii&quot;</span><span class="p">)</span>
<span class="n">file_expr</span> <span class="o">=</span> <span class="s1">&#39;filename=&quot;</span><span class="si">{}</span><span class="s1">&quot;&#39;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span>
<span class="n">filename</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s2">&quot;</span><span class="se">\\</span><span class="s2">&quot;</span><span class="p">,</span> <span class="s2">&quot;</span><span class="se">\\\\</span><span class="s2">&quot;</span><span class="p">)</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s1">&#39;&quot;&#39;</span><span class="p">,</span> <span class="sa">r</span><span class="s2">&quot;</span><span class="se">\&quot;</span><span class="s2">&quot;</span><span class="p">)</span>
<span class="p">)</span>
<span class="k">except</span> <span class="ne">UnicodeEncodeError</span><span class="p">:</span>
<span class="n">file_expr</span> <span class="o">=</span> <span class="s2">&quot;filename*=utf-8&#39;&#39;</span><span class="si">{}</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">quote</span><span class="p">(</span><span class="n">filename</span><span class="p">))</span>
<span class="k">return</span> <span class="sa">f</span><span class="s2">&quot;</span><span class="si">{</span><span class="n">disposition</span><span class="si">}</span><span class="s2">; </span><span class="si">{</span><span class="n">file_expr</span><span class="si">}</span><span class="s2">&quot;</span>
<span class="k">elif</span> <span class="n">as_attachment</span><span class="p">:</span>
<span class="k">return</span> <span class="s2">&quot;attachment&quot;</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">return</span> <span class="kc">None</span>
</pre></div>
</div>
</div>
</div>
</div>
<div class="related" role="navigation" aria-label="related navigation">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../../../genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="../../../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="nav-item nav-item-0"><a href="../../../index.html">Evennia latest</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="../../index.html" >Module code</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">django.utils.http</a></li>
</ul>
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2024, The Evennia developer community.
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.2.3.
</div>
</body>
</html>