<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Monal</title><link>https://monal-im.org/</link><description>Recent content on Monal</description><generator>Hugo -- 0.157.0</generator><language>en</language><atom:link href="https://monal-im.org/index.xml" rel="self" type="application/rss+xml"/><item><title>Monal Internals - Serializable Promise framework</title><link>https://monal-im.org/post/00015-monal-internals-promise-framework/</link><pubDate>Sun, 14 Dec 2025 00:00:00 +0000</pubDate><guid>https://monal-im.org/post/00015-monal-internals-promise-framework/</guid><description>&lt;p&gt;In this new series, I want to shine some light onto specific parts of Monal&amp;rsquo;s internals. It&amp;rsquo;s dedicated to programmers or people curious about how Monal works internally.
If you want to give some feedback, feel free to send an email to &lt;a href="mailto:thilo@monal-im.org"&gt;thilo@monal-im.org&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Other articles in this series:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://monal-im.org/post/00007-monal-internals-handlers/"&gt;Monal Internals - Handlers framework&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://monal-im.org/post/00014-monal-internals-xml-query-language/"&gt;Monal Internals - XML Query Language&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="serializable-promise-framework"&gt;Serializable Promise Framework&lt;/h1&gt;
&lt;p&gt;XMPP as a protocol is, as most protocols are, inherently asynchronous.
In Monal we therefore use the popular &lt;a href="https://github.com/mxcl/PromiseKit"&gt;PromiseKit&lt;/a&gt; library
to let the UI know when a XMPP action finished or failed.&lt;/p&gt;</description><content:encoded><![CDATA[<p>In this new series, I want to shine some light onto specific parts of Monal&rsquo;s internals. It&rsquo;s dedicated to programmers or people curious about how Monal works internally.
If you want to give some feedback, feel free to send an email to <a href="mailto:thilo@monal-im.org">thilo@monal-im.org</a></p>
<p><strong>Other articles in this series:</strong></p>
<ul>
<li><a href="/post/00007-monal-internals-handlers/">Monal Internals - Handlers framework</a></li>
<li><a href="/post/00014-monal-internals-xml-query-language/">Monal Internals - XML Query Language</a></li>
</ul>
<h1 id="serializable-promise-framework">Serializable Promise Framework</h1>
<p>XMPP as a protocol is, as most protocols are, inherently asynchronous.
In Monal we therefore use the popular <a href="https://github.com/mxcl/PromiseKit">PromiseKit</a> library
to let the UI know when a XMPP action finished or failed.</p>
<p>But this has a huge drawback: PromiseKit-based promises aren&rsquo;t serializable, so we can&rsquo;t respond to events
that got handled by the Notification Service App Extension while the app was suspended.
The serializable promise framework is a new framework in Monal, which exactly fills that gap.</p>
<h2 id="overall-process">Overall Process</h2>
<p>For instance, imagine you want to remove the avatar of a group chat in Monal, while on a slow, unreliable network.</p>
<ol>
<li>You submit the request, and the loading screen appears over the view (0:03)</li>
<li>Because the network is slow, the loading screen persists for a long time</li>
<li>You get frustrated and switch apps, sending Monal to the background (0:06)</li>
<li>After 30s in the background, Monal gets suspended (0:36)</li>
<li>The server fails to remove the avatar and sends an error to Monal</li>
<li>The response is handled by Monal’s app extension in the background (0:51)</li>
<li>You switch apps back to Monal (0:57)</li>
</ol>
<p>Without the promise framework, the app would have continued to show the loading screen indefinitely, requiring you to fully close and open the app.</p>
<p>However, with the promise framework, when you switch back to the app, the loading screen disappears and correctly shows the error returned by the server:</p>
<video preload="metadata" style=" max-height:32em ; " controls>
    <source
      src="/post/00015-monal-internals-promise-framework/remove_avatar.mp4"
      type="video/mp4"
    >
    Your browser does not support the video element.
  </video>
<p>The promise framework allows any such interaction, where the UI has to update in response from the server, to be handled in a general way.</p>
<h2 id="background">Background</h2>
<p>We will briefly describe the important parts below. But these links provide more detailed context and are recommended reading:</p>
<ul>
<li>The <a href="https://xmpp-meetup.in-berlin.de/talks/monal-and-push.pdf#Navigation6">app decomposition slides</a> explain the split between the main app and app extension.</li>
<li>The <a href="https://monal-im.github.io/monal-im.org/site/post/00007-monal-internals-handlers/#handlers">handler framework blog post</a> explores some of the consequences of this split.</li>
</ul>
<h3 id="main-app-and-app-extension">Main app and app extension</h3>
<p>In Monal there are two separate processes: the “main app” (<code>MonalAppDelegate</code>) and “app extension” (<code>NotificationService</code>), which is sometimes abbreviated to “appex”.</p>
<p>Since they do not share memory, they hand over to each other via the <a href="https://monal-im.github.io/monal-im.org/site/post/00007-monal-internals-handlers/#handlers">handler framework</a>.</p>
<p>An xmpp stanza can be processed by either, depending on whether the app is running or not:</p>
<p><img alt="Diagram showing that, if the app is active or in the background, stanzas get processed by the main app, otherwise they get processed by the appex, triggered by Apple&rsquo;s push servers if it is not already running" loading="lazy" src="/post/00015-monal-internals-promise-framework/stanza_processing.png"></p>
<h3 id="app-states">App states</h3>
<p>Below is a slightly simplified diagram of the app’s lifecycle. A more detailed lifecycle from Apple’s perspective is <a href="https://developer.apple.com/documentation/uikit/managing-your-app-s-life-cycle">available here</a>.</p>
<p><img alt="Diagram showing the different states the app can be in. It is a visual depiction of the description below" loading="lazy" src="/post/00015-monal-internals-promise-framework/app_states.png"></p>
<table>
  <thead>
      <tr>
          <th>State</th>
          <th>Description</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>App not running</td>
          <td>App is not running, and when it is opened, it will start afresh</td>
      </tr>
      <tr>
          <td>App active</td>
          <td>App is open and in the foreground</td>
      </tr>
      <tr>
          <td>App in background</td>
          <td>App is running, but in the background</td>
      </tr>
      <tr>
          <td>App suspended</td>
          <td>App is not running, but its state is saved for when the app is reopened</td>
      </tr>
  </tbody>
</table>
<ul>
<li>The app moves from &ldquo;active&rdquo; to &ldquo;in background&rdquo; when it is swiped away without being closed
<ul>
<li>It continues to run and process stanzas for ~30s in the background</li>
</ul>
</li>
<li>Once the 30s are complete, it moves to &ldquo;suspended&rdquo;
<ul>
<li>Apple saves the UI&rsquo;s state</li>
<li>When the app is reopened, it returns to the same screen as before</li>
<li>Any stanzas that were processed in the meantime were processed by the appex</li>
</ul>
</li>
</ul>
<h4 id="appex-states">Appex states</h4>
<p>Meanwhile, the appex has a more simple lifecycle - it is either running, or not running:</p>
<p><img alt="Diagram showing that the appex can be in two states: &ldquo;running&rdquo; or &ldquo;not running&rdquo;. It moves to &ldquo;running&rdquo; state on receipt of a notification, then returns to &ldquo;not running&rdquo; state after 30s have passed" loading="lazy" src="/post/00015-monal-internals-promise-framework/appex_states.png"></p>
<ul>
<li>Once the appex starts, it will connect to the server and run for 30s</li>
<li>If the app is opened while the appex is running, the appex will return to &ldquo;not running&rdquo; state in deference to the app.</li>
</ul>
<h2 id="serializable-promise-framework-1">Serializable promise framework</h2>
<p>Ok, now the background is out of the way, time to explain the promise framework!</p>
<p>While promises are very useful in SwiftUI, there is one problem: they only exist in that particular process, and cannot easily be passed between the app and appex.</p>
<p>This means that, if the promise was resolved in the appex, once the app is reopened (moves from suspended to active), it will not be consumed. This is because the appex has no way of tying the result back to the promise that updates the UI.</p>
<p>Since the handler framework is what allows the seamless handoff between the app and appex, we need a way to trigger consumption of a promise as a result of processing in the handler. This is precisely what the promise framework does!</p>
<h3 id="high-level-overview">High-level overview</h3>
<p>We create a &ldquo;serializable promise&rdquo; class called <code>MLPromise</code>. This class stores a &ldquo;UI promise&rdquo; which is an <code>AnyPromise</code> from PromiseKit. Consumption of this <code>AnyPromise</code> is what ultimately causes the UI to update.</p>
<p>Whenever we want to bind a UI action to the result of a handler, we create an <code>MLPromise</code> and pass it as an argument to the handler. We then return the <code>MLPromise</code>&rsquo;s <code>AnyPromise</code> to the UI.</p>
<p>Unlike the <code>AnyPromise</code> it contains, the <code>MLPromise</code> is (mostly) serializable. When the <code>MLPromise</code> is created, and whenever it is resolved, it <a href="https://github.com/monal-im/Monal/blob/c20c9f9968109f0652bf640804b852f143bd5000/Monal/Classes/DataLayer.m#L2542-L2553">persists itself</a> to a <a href="https://github.com/monal-im/Monal/blob/c20c9f9968109f0652bf640804b852f143bd5000/Monal/Classes/DataLayerMigrations.m#L1153-L1156">new <code>promises</code> table</a> in the database.</p>
<p>Meanwhile, whenever the app or appex is unfrozen, and <a href="https://github.com/monal-im/Monal/blob/c20c9f9968109f0652bf640804b852f143bd5000/Monal/Classes/MLPromise.m#L49-L56">the promise table is read into memory</a>, the resolved arguments of any already existing promises are overwritten.</p>
<p>Note that <a href="https://github.com/monal-im/Monal/blob/c20c9f9968109f0652bf640804b852f143bd5000/Monal/Classes/MLPromise.m#L168-L173">this persisted version of the <code>MLPromise</code> is not complete</a> - while the resolved argument can be persisted, the UI promise is not persisted at any stage.</p>
<p>This means that, while the resolved argument can be passed betwen the app and appex, the UI promise itself cannot. The consequence of this is that a promise cannot be consumed in the appex - it can only be resolved there, leaving consumption for when the app becomes active again:</p>
<table>
  <thead>
      <tr>
          <th>Process</th>
          <th>Can resolve?</th>
          <th>Can consume?</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>App</td>
          <td>Yes</td>
          <td>Yes</td>
      </tr>
      <tr>
          <td>Appex</td>
          <td>Yes</td>
          <td>No</td>
      </tr>
  </tbody>
</table>
<p>This makes some sense, as the whole purpose of the <code>AnyPromise</code> is to update the UI as a result of some backend action. It only makes sense to update the UI from the process which manages the UI - the app itself.</p>
<p>As a result, whenever the app becomes active again, all outstanding <code>MLPromise</code>s check the version retrieved from the DB if they have been resolved in the meantime, <a href="https://github.com/monal-im/Monal/blob/c20c9f9968109f0652bf640804b852f143bd5000/Monal/Classes/MLPromise.m#L77">and if so, consume themselves</a>. This is how the loading overlay gets removed in the above example.</p>
<h3 id="step-by-step-overview">Step-by-step overview</h3>
<p>Let&rsquo;s return to the initial scenario of removing the avatar of a group chat. The user chooses the new avatar and presses submit. Then, the following happens:</p>
<p><img alt="Diagram showing the flow of promises throughout the app, as explained in detail below" loading="lazy" src="/post/00015-monal-internals-promise-framework/promises_flow.png"></p>
<h4 id="1-ui-code-calls-backend"><a href="https://github.com/monal-im/Monal/blob/c20c9f9968109f0652bf640804b852f143bd5000/Monal/Classes/ContactDetails.swift#L146-L148">(1) UI code calls backend</a></h4>
<p>The UI code responding to requests to remove the avatar calls the backend method to do this.</p>
<p>Once the backend function completes, it will return an <code>AnyPromise</code>, allowing the UI code to continue immediately:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-swift" data-lang="swift"><span style="display:flex;"><span>showPromisingLoadingOverlay(overlay, headlineView:Text(<span style="color:#e6db74">&#34;Removing avatar...&#34;</span>), descriptionView:Text(<span style="color:#e6db74">&#34;&#34;</span>)) {
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// this returns an AnyPromise used by the loading overly to hide itself once it gets resolved</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">self</span>.account.mucProcessor.publishAvatar(<span style="color:#66d9ef">nil</span>, forMuc: contact.contactJid)
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h4 id="2-core-code-creates-promise"><a href="https://github.com/monal-im/Monal/blob/c20c9f9968109f0652bf640804b852f143bd5000/Monal/Classes/MLMucProcessor.m#L1292">(2) Core code creates promise</a></h4>
<p>The core code creates an <code>MLPromise</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-objc" data-lang="objc"><span style="display:flex;"><span>-(AnyPromise<span style="color:#f92672">*</span>) <span style="color:#a6e22e">publishAvatar:</span>(UIImage<span style="color:#f92672">*</span> _Nullable) image <span style="color:#a6e22e">forMuc:</span>(NSString<span style="color:#f92672">*</span>) room
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    MLPromise<span style="color:#f92672">*</span> promise <span style="color:#f92672">=</span> [MLPromise new];
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// ...
</span></span></span></code></pre></div><h4 id="3-core-code-creates-handler-and-4-sends-iq"><a href="https://github.com/monal-im/Monal/blob/c20c9f9968109f0652bf640804b852f143bd5000/Monal/Classes/MLMucProcessor.m#L1299">(3) Core code creates handler and (4) sends IQ</a></h4>
<p>The core code creates a new handler, and passes the <code>MLPromise</code> to it as an argument. Recall that <a href="https://github.com/monal-im/Monal/wiki/Handler-Framework">handlers serialize their arguments</a> - this means that, even if the app is suspended and the handler is called in the appex, the <code>MLPromise</code> will be available.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-objc" data-lang="objc"><span style="display:flex;"><span>[_account sendIq:vcard withHandler:<span style="color:#960050;background-color:#1e0010">$</span>newHandlerWithInvalidation(self, handleAvatarPublishResult, handleAvatarPublishResultInvalidation, <span style="color:#960050;background-color:#1e0010">$</span>ID(room), <span style="color:#960050;background-color:#1e0010">$</span>ID(promise))];
</span></span></code></pre></div><h4 id="5-promise-returned-to-ui"><a href="https://github.com/monal-im/Monal/blob/c20c9f9968109f0652bf640804b852f143bd5000/Monal/Classes/MLMucProcessor.m#L1300">(5) Promise returned to UI</a></h4>
<p>Internally, the <code>MLPromise</code> has created an <code>AnyPromise</code>. This is a type provided by PromiseKit that can be returned directly to the UI, and that the SwiftUI code understands. It gets returned to the UI code.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-objc" data-lang="objc"><span style="display:flex;"><span><span style="color:#66d9ef">return</span> [promise toAnyPromise];
</span></span></code></pre></div><h4 id="6-xmpp-server-provides-response">(6) XMPP server provides response</h4>
<p>This happens on the server side and is not relevant to Monal.</p>
<p>However, while waiting for the response, the user puts the app into the background, and the app gets suspended.</p>
<h4 id="7-handler-resolves-promise"><a href="https://github.com/monal-im/Monal/blob/c20c9f9968109f0652bf640804b852f143bd5000/Monal/Classes/MLMucProcessor.m#L1330">(7) Handler resolves promise</a></h4>
<p>Now, the response from the server activates the appex, since the app was suspended.</p>
<p>The handler is called with the response from the server. It resolves the promise (via either <code>reject</code> or <code>fulfill</code>) - passing that response to the promise.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-objc" data-lang="objc"><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">$$</span>instance_handler(handleAvatarPublishResult, account.mucProcessor, <span style="color:#960050;background-color:#1e0010">$$</span>ID(xmpp<span style="color:#f92672">*</span>, account), <span style="color:#960050;background-color:#1e0010">$$</span>ID(XMPPIQ<span style="color:#f92672">*</span>, iqNode), <span style="color:#960050;background-color:#1e0010">$$</span>ID(MLPromise<span style="color:#f92672">*</span>, promise))
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span>([iqNode check:<span style="color:#e6db74">@&#34;/&lt;type=error&gt;&#34;</span>])
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// ...
</span></span></span><span style="display:flex;"><span>        [promise reject:error];
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// ...
</span></span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// ...
</span></span></span><span style="display:flex;"><span>    [promise fulfill:nil];
</span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">$$</span>
</span></span></code></pre></div><h4 id="8-promise-waits-until-app-is-open"><a href="https://github.com/monal-im/Monal/blob/c20c9f9968109f0652bf640804b852f143bd5000/Monal/Classes/MLPromise.m#L42">(8) Promise waits until app is open</a></h4>
<p>If the promise had been resolved from the app, it could have been consumed immediately. However, since it was resolved from the appex, the <code>AnyPromise</code> was not available to call at that time.</p>
<p>Therefore, the promise does not consume itself yet - it instead waits for the app to return to active state.</p>
<p>This waiting is performed by the following observer - whenever either the app or appex is unfrozen, the <code>deserialize</code> method is called:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-objc" data-lang="objc"><span style="display:flex;"><span>-(<span style="color:#66d9ef">instancetype</span>) <span style="color:#a6e22e">init</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// ...
</span></span></span><span style="display:flex;"><span>    [[NSNotificationCenter defaultCenter] addObserver:self selector:<span style="color:#66d9ef">@selector</span>(deserialize) name:kMonalUnfrozen object:nil];
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// ...
</span></span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p><code>deserialize</code> calls <code>attemptConsume</code> on each run. <code>attemptConsume</code> checks if we are inside the appex (in which case we do not consume the promise), and only if we are inside the app does it consume the promise:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-objc" data-lang="objc"><span style="display:flex;"><span>-(<span style="color:#66d9ef">void</span>) <span style="color:#a6e22e">attemptConsume</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    DDLogDebug(<span style="color:#e6db74">@&#34;Intend to consume promise %@ with uuid %@ and argument %@&#34;</span>, self, self.uuid, self.resolvedArgument);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span>([HelperTools isAppExtension])
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        DDLogDebug(<span style="color:#e6db74">@&#34;Not consuming promise %@ with uuid %@ as we are in the app extension&#34;</span>, self, self.uuid);
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span>;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// ...
</span></span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Note that both <code>reject</code> and <code>fulfill</code> also call <code>attemptConsume</code> after resolving the promise. This would let the promise be consumed immediately if we are inside the app instead of the appex.</p>
<h4 id="9-promise-consumes-ui-promise"><a href="https://github.com/monal-im/Monal/blob/c20c9f9968109f0652bf640804b852f143bd5000/Monal/Classes/MLPromise.m#L154">(9) Promise consumes UI promise</a></h4>
<p>Once we progress past the checks in <code>attemptConsume</code>, we finally consume the promise by calling the <code>resolve</code> callback tied to the PromiseKit <code>AnyPromise</code> returned earlier. This in turn prompts the UI to hide the loading overlay.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-objc" data-lang="objc"><span style="display:flex;"><span>-(<span style="color:#66d9ef">void</span>) <span style="color:#a6e22e">attemptConsume</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// ...
</span></span></span><span style="display:flex;"><span>    PMKResolver resolve <span style="color:#f92672">=</span> _resolvers[self.uuid];
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// ...
</span></span></span><span style="display:flex;"><span>    resolve(self.resolvedArgument);
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// ...
</span></span></span><span style="display:flex;"><span>}
</span></span></code></pre></div>]]></content:encoded></item><item><title>Monal Internals - XML Query Language</title><link>https://monal-im.org/post/00014-monal-internals-xml-query-language/</link><pubDate>Mon, 09 Sep 2024 00:00:00 +0000</pubDate><guid>https://monal-im.org/post/00014-monal-internals-xml-query-language/</guid><description>&lt;p&gt;In this new series, I want to shine some light onto specific parts of Monal&amp;rsquo;s internals. It&amp;rsquo;s dedicated to programmers or people curious about how Monal works internally. If you want to give some feedback, feel free to send an email to &lt;a href="mailto:thilo@monal-im.org"&gt;thilo@monal-im.org&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Other articles in this series:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://monal-im.org/post/00007-monal-internals-handlers/"&gt;Monal Internals - Handlers framework&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://monal-im.org/post/00015-monal-internals-promise-framework/"&gt;Monal Internals - Serializable Promise framework&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="the-mlxmlnode-methods"&gt;The &lt;code&gt;MLXMLNode&lt;/code&gt; methods&lt;/h1&gt;
&lt;p&gt;All incoming and outgoing XMPP stanzas are parsed to/from an instance of nested &lt;code&gt;MLXMLNode&lt;/code&gt; elements.
This class therefore provides some methods for creating such elements as well as querying them.
In this chapter I want to briefly introduce some parts of the &lt;code&gt;MLXMLNode&lt;/code&gt; interface before diving into our XML Query Language in the next chapter.&lt;/p&gt;</description><content:encoded><![CDATA[<p>In this new series, I want to shine some light onto specific parts of Monal&rsquo;s internals. It&rsquo;s dedicated to programmers or people curious about how Monal works internally. If you want to give some feedback, feel free to send an email to <a href="mailto:thilo@monal-im.org">thilo@monal-im.org</a></p>
<p><strong>Other articles in this series:</strong></p>
<ul>
<li><a href="/post/00007-monal-internals-handlers/">Monal Internals - Handlers framework</a></li>
<li><a href="/post/00015-monal-internals-promise-framework/">Monal Internals - Serializable Promise framework</a></li>
</ul>
<h1 id="the-mlxmlnode-methods">The <code>MLXMLNode</code> methods</h1>
<p>All incoming and outgoing XMPP stanzas are parsed to/from an instance of nested <code>MLXMLNode</code> elements.
This class therefore provides some methods for creating such elements as well as querying them.
In this chapter I want to briefly introduce some parts of the <code>MLXMLNode</code> interface before diving into our XML Query Language in the next chapter.</p>
<h2 id="creating-an-mlxmlnode">Creating an <code>MLXMLNode</code></h2>
<p>There are several initializers for <code>MLXMLNode</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-objc" data-lang="objc"><span style="display:flex;"><span>-(<span style="color:#66d9ef">id</span>) <span style="color:#a6e22e">initWithElement:</span>(NSString<span style="color:#f92672">*</span>) element;
</span></span><span style="display:flex;"><span>-(<span style="color:#66d9ef">id</span>) <span style="color:#a6e22e">initWithElement:</span>(NSString<span style="color:#f92672">*</span>) element <span style="color:#a6e22e">andNamespace:</span>(NSString<span style="color:#f92672">*</span>) xmlns;
</span></span><span style="display:flex;"><span>-(<span style="color:#66d9ef">id</span>) <span style="color:#a6e22e">initWithElement:</span>(NSString<span style="color:#f92672">*</span>) element <span style="color:#a6e22e">andNamespace:</span>(NSString<span style="color:#f92672">*</span>) xmlns <span style="color:#a6e22e">withAttributes:</span>(NSDictionary<span style="color:#f92672">*</span>) attributes <span style="color:#a6e22e">andChildren:</span>(NSArray<span style="color:#f92672">*</span>) children <span style="color:#a6e22e">andData:</span>(NSString<span style="color:#f92672">*</span> _Nullable) data;
</span></span><span style="display:flex;"><span>-(<span style="color:#66d9ef">id</span>) <span style="color:#a6e22e">initWithElement:</span>(NSString<span style="color:#f92672">*</span>) element <span style="color:#a6e22e">withAttributes:</span>(NSDictionary<span style="color:#f92672">*</span>) attributes <span style="color:#a6e22e">andChildren:</span>(NSArray<span style="color:#f92672">*</span>) children <span style="color:#a6e22e">andData:</span>(NSString<span style="color:#f92672">*</span> _Nullable) data;
</span></span><span style="display:flex;"><span>-(<span style="color:#66d9ef">id</span>) <span style="color:#a6e22e">initWithElement:</span>(NSString<span style="color:#f92672">*</span>) element <span style="color:#a6e22e">andData:</span>(NSString<span style="color:#f92672">*</span> _Nullable) data;
</span></span><span style="display:flex;"><span>-(<span style="color:#66d9ef">id</span>) <span style="color:#a6e22e">initWithElement:</span>(NSString<span style="color:#f92672">*</span>) element <span style="color:#a6e22e">andNamespace:</span>(NSString<span style="color:#f92672">*</span>) xmlns <span style="color:#a6e22e">andData:</span>(NSString<span style="color:#f92672">*</span> _Nullable) data;
</span></span></code></pre></div><p>The initializers not taking a namespace argument will create XML nodes that automatically inherit the namespace of their containing node, once added to a tree of XML nodes.</p>
<p>When nesting <code>MLXMLNode</code>s , it looks like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-objc" data-lang="objc"><span style="display:flex;"><span>MLXMLNode<span style="color:#f92672">*</span> exampleNode <span style="color:#f92672">=</span> [[MLXMLNode alloc] initWithElement:<span style="color:#e6db74">@&#34;credentials&#34;</span> andNamespace:<span style="color:#e6db74">@&#34;urn:xmpp:extdisco:2&#34;</span> withAttributes:<span style="color:#ae81ff">@{}</span> andChildren:<span style="color:#ae81ff">@[</span>
</span></span><span style="display:flex;"><span>    [[MLXMLNode alloc] initWithElement:<span style="color:#e6db74">@&#34;service&#34;</span>  withAttributes:<span style="color:#ae81ff">@{</span>
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">@&#34;type&#34;</span><span style="color:#f92672">:</span> service[<span style="color:#e6db74">@&#34;type&#34;</span>],
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">@&#34;host&#34;</span><span style="color:#f92672">:</span> service[<span style="color:#e6db74">@&#34;host&#34;</span>],
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">@&#34;port&#34;</span><span style="color:#f92672">:</span> service[<span style="color:#e6db74">@&#34;port&#34;</span>],
</span></span><span style="display:flex;"><span>    <span style="color:#ae81ff">}</span> andChildren:<span style="color:#ae81ff">@[]</span> andData:nil]
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">]</span> andData:nil]
</span></span></code></pre></div><h2 id="querying-a-possibly-nested-mlxmlnode">Querying a (possibly nested) <code>MLXMLNode</code></h2>
<p>All XML queries are implemented as an interface of <code>MLXMLNode</code> as well. For XML queries this class has three different methods:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-objc" data-lang="objc"><span style="display:flex;"><span>-(NSArray<span style="color:#f92672">*</span>) <span style="color:#a6e22e">find:</span>(NSString<span style="color:#f92672">*</span> _Nonnull) queryString, ... NS_FORMAT_FUNCTION(<span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">2</span>);
</span></span><span style="display:flex;"><span>-(<span style="color:#66d9ef">id</span>) <span style="color:#a6e22e">findFirst:</span>(NSString<span style="color:#f92672">*</span> _Nonnull) queryString, ... NS_FORMAT_FUNCTION(<span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">2</span>);
</span></span><span style="display:flex;"><span>-(<span style="color:#66d9ef">BOOL</span>) <span style="color:#a6e22e">check:</span>(NSString<span style="color:#f92672">*</span> _Nonnull) queryString, ... NS_FORMAT_FUNCTION(<span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">2</span>);
</span></span></code></pre></div><p><code>find:</code> will return an <code>NSArray</code> listing all results matching your query, <code>findFirst:</code> will only return the first result of your query (or nil if the resulting <code>NSArray</code> was empty). This should be used, if you are certain that there should only be one element matching (or none at all). <code>check:</code> can be used to determine if <code>find:</code> would return an empty <code>NSArray</code>.</p>
<p>All three methods take a string argument possibly containing <code>printf</code>-style format specifiers including the <code>%@</code> specifier as supported by <code>NSString stringWithFormat:</code> and a variable argument list for providing the values for these format specifiers.</p>
<h1 id="the-query-language">The Query Language</h1>
<p>To query single values out of a complex XML stanza, we use a XML query language inspired by XPath, but <strong>not</strong> compatible with it.
Instead, our language, as implemented in Monal, is a strict superset of Prosody&rsquo;s query language as documented in <a href="https://prosody.im/doc/developers/util/stanza#stanzafind_path">Prosody&rsquo;s documentation of util.stanza</a>. This makes it possible to copy over queries from Prosody and directly use them in Monal without any modification.</p>
<p>The query language consists of a <code>path</code> followed by an optional <code>extraction command</code> and <code>conversion command</code> and is parsed by complex regular expressions in <code>MLXMLNode.m</code>. These regular expressions and the usage of the xml language throughout Monal were <a href="https://monal-im.org/post/00011-security-audit-1/">security audited in 2024</a>.</p>
<p><strong><em>Note:</em></strong> If the following description talks about the <code>find:</code> method, the <code>findFirst:</code> and <code>check:</code> methods are automatically included.</p>
<h2 id="path-segments">Path Segments</h2>
<p>The path is built of <code>/</code>-separated segments each representing an XML node, selected by either an XML namespace or an element name or both. The XML namespace is wrapped in <code>{ }</code> and prefixes the element name.
Each path segment is used to select all XML nodes matching the criteria listed in this path segment.
The special wildcard value <code>*</code> for element name or namespace mean &ldquo;any namespace&rdquo; or &ldquo;any element&rdquo;.</p>
<p>If the namespace is omitted, the namespace of the parent node in the XML tree the query is acted upon is used (or <code>* </code>, if there is no parent node), see <em>example 0</em>. The namespace of the parent node is used even if the <code>find:</code> method is executed on a child XML node, see <em>example 1</em>. The element name can not be omitted and should be set to <code>*</code> if unknown.</p>
<p>A path beginning with a <code>/</code> is called a <code>rooted query</code>. That means the following first path segment is to be used to select the node the <code>find:</code> method is called on, if the leading <code>/</code> is omitted, the first path segment is used to select the <strong>child nodes</strong> of the node the <code>find:</code> method is called on.</p>
<p><strong><em>Note:</em></strong> If using such a <code>rooted query</code> to access attributes, element names etc. of the XML node the whole query is acting upon, both the element name and namespace can be fully omitted and are automatically replaced by <code>{*}*</code>. This allows us to write queries like <code>/@h|int&quot;</code> or <code>/@autojoin|bool</code>.</p>
<p>The special path segment with element name <code>..</code> not naming any namespace or other selection criteria (e.g. <code>/../</code>) will ascend one node in the XML node tree to the parent of the XML node that the query reached and apply the remaining query to this XML node. Thus using <code>/{jabber:client}iq/{http://jabber.org/protocol/pubsub}pubsub/items/../../../@type</code> will return the value of the type attribute on the root element (the <code>{jabber:iq}iq</code>).</p>
<p><strong><em>Note:</em></strong> Not using an extraction command (see the next chapter below) will return the matching <code>MLXMLNode</code>s <em>as reference</em>. Changing the attributes etc. of that reference will change the original <code>MLXMLNode</code> in the XML tree it is part of.
If you don&rsquo;t want that, you&rsquo;ll have to call <code>copy</code> on the returned <code>MLXMLNode</code>s to decouple them from their original.</p>
<p><strong>Example 0:</strong></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#f92672">&lt;message</span> <span style="color:#a6e22e">from=</span><span style="color:#e6db74">&#39;test@example.org&#39;</span> <span style="color:#a6e22e">id=</span><span style="color:#e6db74">&#39;some_id&#39;</span> <span style="color:#a6e22e">xmlns=</span><span style="color:#e6db74">&#39;jabber:client&#39;</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;body&gt;</span>Message text<span style="color:#f92672">&lt;/body&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;body</span> <span style="color:#a6e22e">xmlns=</span><span style="color:#e6db74">&#39;urn:some:different:namespace&#39;</span><span style="color:#f92672">&gt;</span>This will NOT be used<span style="color:#f92672">&lt;/body&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;/message&gt;</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-objc" data-lang="objc"><span style="display:flex;"><span>MLXMLNode<span style="color:#f92672">*</span> message <span style="color:#f92672">=</span> <span style="color:#f92672">&lt;</span>the stanza above as MLXMLNode tree<span style="color:#f92672">&gt;</span>;
</span></span><span style="display:flex;"><span>NSArray<span style="color:#f92672">&lt;</span>NSString<span style="color:#f92672">*&gt;*</span> bodyStrings <span style="color:#f92672">=</span> [message find:<span style="color:#e6db74">@&#34;body#&#34;</span>];
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>MLAssert(bodyStrings.count <span style="color:#f92672">==</span> <span style="color:#ae81ff">1</span>, <span style="color:#e6db74">@&#34;Only one body text should be returned!&#34;</span>);
</span></span><span style="display:flex;"><span>MLAssert([bodyStrings[<span style="color:#ae81ff">0</span>] isEqualToString:<span style="color:#e6db74">@&#34;Message text&#34;</span>, <span style="color:#e6db74">@&#34;The body with inherited namespace &#39;jabber:client&#39; should be used!&#34;</span>);
</span></span></code></pre></div><p><strong>Example 1:</strong></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#f92672">&lt;message</span> <span style="color:#a6e22e">from=</span><span style="color:#e6db74">&#39;test@example.org&#39;</span> <span style="color:#a6e22e">id=</span><span style="color:#e6db74">&#39;some_id&#39;</span> <span style="color:#a6e22e">xmlns=</span><span style="color:#e6db74">&#39;jabber:client&#39;</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;body&gt;</span>Message text<span style="color:#f92672">&lt;/body&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;/message&gt;</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-objc" data-lang="objc"><span style="display:flex;"><span>MLXMLNode<span style="color:#f92672">*</span> message <span style="color:#f92672">=</span> <span style="color:#f92672">&lt;</span>the stanza above as MLXMLNode tree<span style="color:#f92672">&gt;</span>;
</span></span><span style="display:flex;"><span>NSString<span style="color:#f92672">*</span> messageId <span style="color:#f92672">=</span> [message findFirst:<span style="color:#e6db74">@&#34;/@id&#34;</span>];
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>MLAssert([messageId isEqualToString:<span style="color:#e6db74">@&#34;some_id&#34;</span>, <span style="color:#e6db74">@&#34;The extracted message id should be &#39;some_id&#39;!&#34;</span>);
</span></span></code></pre></div><h3 id="more-selection-criteria">More selection criteria</h3>
<ul>
<li><strong>Not element name:</strong><br>
If you want to select all XML nodes <strong>not</strong> having a specified name, you&rsquo;ll have to prefix the element name with <code>!</code>. This will negate the selection, e.g. <code>!text</code> will select all XML nodes <strong>not</strong> named <code>text</code>, see <em>example 2</em>.</li>
<li><strong>Element attribute equals value</strong>:<br>
If you want to select XML nodes on the basis of their XML attributes, you can list those attributes as <code>attributeName=value</code> pairs each inside <code>&lt; &gt;</code>, see <em>example 3</em>. You can use format string specifiers in the value part of those pairs to replace those with the variadic arguments of <code>find:</code>. The order of variadic arguments has to resemble <em>all</em> format specifiers of the complete query string given to <code>find:</code> Note: the value part of those pairs can not be omitted, use regular expression matching to select for mere XML attribute presence (e.g. <code>&lt;attributeName~^.*$&gt;</code>).</li>
<li><strong>Element attribute matches regular expression</strong>:<br>
To select XML nodes on the basis of their XML attributes, but using a regular expression, you&rsquo;ll have to use <code>attributeName~regex</code> pairs inside <code>&lt; &gt;</code>. No format string specifiers will be replaced inside your regular expression following the <code>~</code>. You&rsquo;ll have to use <code>^</code> and <code>$</code> to match begin and end of the attribute value yourself, e.g. <code>&lt;attributeName~.&gt;</code> will match all attribute values having <strong>at least</strong> one character, while <code>&lt;attributeName~^.$&gt;</code> will match all attribute values having <strong>exactly</strong> one character.</li>
</ul>
<p><strong>Example 2:</strong></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#f92672">&lt;stream:error&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;not-well-formed</span> <span style="color:#a6e22e">xmlns=</span><span style="color:#e6db74">&#39;urn:ietf:params:xml:ns:xmpp-streams&#39;</span><span style="color:#f92672">/&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;text</span> <span style="color:#a6e22e">xmlns=</span><span style="color:#e6db74">&#39;urn:ietf:params:xml:ns:xmpp-streams&#39;</span><span style="color:#f92672">&gt;</span>Some descriptive Text...<span style="color:#f92672">&lt;/text&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;/stream:error&gt;</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-objc" data-lang="objc"><span style="display:flex;"><span>MLXMLNode<span style="color:#f92672">*</span> streamError <span style="color:#f92672">=</span> <span style="color:#f92672">&lt;</span>the stanza above as MLXMLNode tree<span style="color:#f92672">&gt;</span>;
</span></span><span style="display:flex;"><span>NSString<span style="color:#f92672">*</span> errorReason <span style="color:#f92672">=</span> [streamError findFirst:<span style="color:#e6db74">@&#34;{urn:ietf:params:xml:ns:xmpp-streams}!text$&#34;</span>];
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>MLAssert([errorReason isEqualToString:<span style="color:#e6db74">@&#34;not-well-formed&#34;</span>], <span style="color:#e6db74">@&#34;The extracted error should be &#39;not-well-formed&#39;!&#34;</span>);
</span></span></code></pre></div><p><strong>Example 3 (also using an extraction command, see below):</strong></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#f92672">&lt;iq</span> <span style="color:#a6e22e">id=</span><span style="color:#e6db74">&#39;605818D4-4D16-4ACC-B003-BFA3E11849E1&#39;</span> <span style="color:#a6e22e">to=</span><span style="color:#e6db74">&#39;user@example.com/Monal-iOS.15e153a8&#39;</span> <span style="color:#a6e22e">xmlns=</span><span style="color:#e6db74">&#39;jabber:client&#39;</span> <span style="color:#a6e22e">type=</span><span style="color:#e6db74">&#39;result&#39;</span> <span style="color:#a6e22e">from=</span><span style="color:#e6db74">&#39;asdkjfhskdf@messaging.one&#39;</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;pubsub</span> <span style="color:#a6e22e">xmlns=</span><span style="color:#e6db74">&#39;http://jabber.org/protocol/pubsub&#39;</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&lt;subscription</span> <span style="color:#a6e22e">node=</span><span style="color:#e6db74">&#39;eu.siacs.conversations.axolotl.devicelist&#39;</span> <span style="color:#a6e22e">subid=</span><span style="color:#e6db74">&#39;6795F13596465&#39;</span> <span style="color:#a6e22e">subscription=</span><span style="color:#e6db74">&#39;subscribed&#39;</span> <span style="color:#a6e22e">jid=</span><span style="color:#e6db74">&#39;user@example.com&#39;</span><span style="color:#f92672">/&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;/pubsub&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;/iq&gt;</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-objc" data-lang="objc"><span style="display:flex;"><span>MLXMLNode<span style="color:#f92672">*</span> iq <span style="color:#f92672">=</span> <span style="color:#f92672">&lt;</span>the stanza above as MLXMLNode tree<span style="color:#f92672">&gt;</span>;
</span></span><span style="display:flex;"><span>NSString<span style="color:#f92672">*</span> subscriptionStatus <span style="color:#f92672">=</span> [iq findFirst:<span style="color:#e6db74">@&#34;/&lt;type=result&gt;/{http://jabber.org/protocol/pubsub}pubsub/subscription&lt;node=%@&gt;&lt;jid=%@&gt;@subscription&#34;</span>, <span style="color:#e6db74">@&#34;eu.siacs.conversations.axolotl.devicelist&#34;</span>, <span style="color:#e6db74">@&#34;user@example.com&#34;</span>];
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>MLAssert([subscriptionStatus isEqualToString:<span style="color:#e6db74">@&#34;subscribed&#34;</span>], <span style="color:#e6db74">@&#34;The extracted value of the subscription attribute should be &#39;subscribed&#39;!&#34;</span>);
</span></span></code></pre></div><h2 id="extraction-commands">Extraction Commands</h2>
<p>An extraction command can be appended to the last path segment. Without those extraction commands, <code>find:</code> will return the full <code>MLXMLNode</code> matching the selection criteria of the XML query. If you rather want to read a special attribute, element value etc. of the full XML node, you&rsquo;ll have to use one of the extractions commands below</p>
<ul>
<li><code>@attributeName</code>:<br>
This will return the value of the attribute named after the <code>@</code> as <code>NSString</code>, use a conversion command to convert the value to other data types.</li>
<li><code>@@</code>:
This will return all attributes of the selected XML node as key-value-pairs in an <code>NSDictionary</code>. No conversion commands can be used together with this extraction command.</li>
<li><code>#</code>:
This will return the text contents of the selected XML node as <code>NSString</code>, use a conversion command to convert the value to other data types.</li>
<li><code>$</code>:
This will return the element name of the selected XML node as <code>NSString</code>. This is only really useful if the last path segment contained a wildcard element name or its element name was negated. A Conversion command can be used to convert the returned element name to other data types as well.</li>
</ul>
<p>For data-form (<a href="https://xmpp.org/extensions/xep-0004.html">XEP-0004</a>) subqueries, see the corresponding section below.</p>
<h2 id="conversion-commands">Conversion Commands</h2>
<p>Conversion commands can be used to convert the returned <code>NSString</code> of an extraction command to some other data type. Conversion commands can not be used without an extraction command and must be separated from the preceeding extraction command by a pipe symbol (<code>|</code>).
The following conversions are currently defined:</p>
<ul>
<li><code>bool</code>:<br>
This will convert the extracted <code>NSString</code> to an <code>NSNumber</code> representing a <code>BOOL</code>. <code>true</code>/<code>1</code> becomes <code>@YES</code> and <code>false</code>/<code>0</code> becomes <code>@NO</code>. This is in accordance to the representation of truth values in XMPP.</li>
<li><code>int</code>:<br>
This will convert the extracted <code>NSString</code> to an <code>NSNumber</code> representing a <code>NSInteger</code> (<code>integerValue</code> property).</li>
<li><code>uint</code>:<br>
This will convert the extracted <code>NSString</code> to an <code>NSNumber</code> representing a <code>NSUInteger</code> (<code>unsignedIntegerValue</code> property).</li>
<li><code>double</code>:<br>
This will convert the extracted <code>NSString</code> to an <code>NSNumber</code> representing a <code>double</code> (<code>doubleValue</code> property).</li>
<li><code>datetime</code>:<br>
This will use the <code>HelperTools</code> method <code>parseDateTimeString:</code> to parse the given <code>NSString</code> into an <code>NSDate</code> object.</li>
<li><code>base64</code>:<br>
This will use the <code>HelperTools</code> method <code>dataWithBase64EncodedString:</code> to parse the given <code>NSString</code> into an <code>NSData</code> object.</li>
<li><code>uuid</code>:<br>
This will try to parse the given <code>NSString</code> into an <code>NSUUID</code> object using the <code>initWithUUIDString</code> initializer of <code>NSUUID</code>. This will return <code>nil</code> for an invalid string, which will omit this result from the <code>NSArray</code> returned by <code>find:</code> (<code>findFirst:</code> will return nil, and <code>check:</code> will return NO).</li>
<li><code>uuidcast</code>:<br>
This will do the same as the <code>uuid</code> conversion command for valid uuid strings, but use the <code>HelperTools</code>method <code>stringToUUID</code> to cast any other given string to a UUIDv4 by hashing it using SHA256 and arranging the result to resemble a valid UUIDv4.</li>
</ul>
<p><strong>Example 4 (attribute extraction command together with a <code>bool</code> conversion command):</strong></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#f92672">&lt;iq</span> <span style="color:#a6e22e">type=</span><span style="color:#e6db74">&#39;result&#39;</span> <span style="color:#a6e22e">id=</span><span style="color:#e6db74">&#39;juliet1&#39;</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;fin</span> <span style="color:#a6e22e">xmlns=</span><span style="color:#e6db74">&#39;urn:xmpp:mam:2&#39;</span> <span style="color:#a6e22e">complete=</span><span style="color:#e6db74">&#39;true&#39;</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;set</span> <span style="color:#a6e22e">xmlns=</span><span style="color:#e6db74">&#39;http://jabber.org/protocol/rsm&#39;</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&lt;first</span> <span style="color:#a6e22e">index=</span><span style="color:#e6db74">&#39;0&#39;</span><span style="color:#f92672">&gt;</span>28482-98726-73623<span style="color:#f92672">&lt;/first&gt;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&lt;last&gt;</span>09af3-cc343-b409f<span style="color:#f92672">&lt;/last&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;/set&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;/fin&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;/iq&gt;</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-objc" data-lang="objc"><span style="display:flex;"><span>MLXMLNode<span style="color:#f92672">*</span> iqNode <span style="color:#f92672">=</span> <span style="color:#f92672">&lt;</span>the stanza above as MLXMLNode tree<span style="color:#f92672">&gt;</span>;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span>([[iqNode findFirst:<span style="color:#e6db74">@&#34;{urn:xmpp:mam:2}fin@complete|bool&#34;</span>] boolValue])
</span></span><span style="display:flex;"><span>    DDLogInfo(<span style="color:#e6db74">@&#34;Mam query finished&#34;</span>)
</span></span></code></pre></div><p><strong>Example 5 (attribute extraction command together with a <code>datetime</code> conversion command):</strong></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#f92672">&lt;message</span> <span style="color:#a6e22e">from=</span><span style="color:#e6db74">&#39;romeo@montague.net/orchard&#39;</span> <span style="color:#a6e22e">to=</span><span style="color:#e6db74">&#39;juliet@capulet.com&#39;</span> <span style="color:#a6e22e">type=</span><span style="color:#e6db74">&#39;chat&#39;</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;body&gt;</span>O blessed, blessed night! I am afeard.<span style="color:#f92672">&lt;/body&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;delay</span> <span style="color:#a6e22e">xmlns=</span><span style="color:#e6db74">&#39;urn:xmpp:delay&#39;</span> <span style="color:#a6e22e">from=</span><span style="color:#e6db74">&#39;capulet.com&#39;</span> <span style="color:#a6e22e">stamp=</span><span style="color:#e6db74">&#39;2002-09-10T23:08:25Z&#39;</span><span style="color:#f92672">/&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;/message&gt;</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-objc" data-lang="objc"><span style="display:flex;"><span>MLXMLNode<span style="color:#f92672">*</span> messageNode <span style="color:#f92672">=</span> <span style="color:#f92672">&lt;</span>the stanza above as MLXMLNode tree<span style="color:#f92672">&gt;</span>;
</span></span><span style="display:flex;"><span>NSDate<span style="color:#f92672">*</span> delayStamp <span style="color:#f92672">=</span> [messageNode findFirst:<span style="color:#e6db74">@&#34;{urn:xmpp:delay}delay@stamp|datetime&#34;</span>];
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>MLAssert(delayStamp.timeIntervalSince1970 <span style="color:#f92672">==</span> <span style="color:#ae81ff">1031699305</span>, @The delay stamp should be <span style="color:#ae81ff">1031699305</span> seconds after the epoch<span style="color:#f92672">!</span><span style="color:#e6db74">&#34;);</span>
</span></span></code></pre></div><p><strong>Some more queries as found in our codebase:</strong></p>
<ul>
<li><code>{urn:xmpp:jingle:1}jingle&lt;action~^session-(initiate|accept)$&gt;</code></li>
<li><code>error/{urn:ietf:params:xml:ns:xmpp-stanzas}item-not-found</code></li>
<li><code>{urn:xmpp:avatar:metadata}metadata/info</code></li>
<li><code>{urn:xmpp:avatar:data}data#|base64</code></li>
</ul>
<h1 id="the-data-forms-xep-0004-query-language-extension">The data-forms (XEP-0004) query language extension</h1>
<p>To query fields etc. of a <a href="https://xmpp.org/extensions/xep-0004.html">XEP-0004</a> data-form, the last path segment of an XML query can contain a data-forms subquery.
Thes parser for these subqueries is an <code>MLXMLNode</code> extension implemented in <code>XMPPDataForm.m</code> and glued into <code>MLXMLNode.m</code> as the extraction command <code>\</code> (backslash). This extraction command is also special as it has to be terminated by a <code>\</code> (optionally followed by a conversion command, see below).</p>
<p><strong><em>Note:</em></strong> since our query is a string, double backslashes (<code>\\</code>) have to be used because of string escaping rules.</p>
<p>Like other extraction commands, these subqueries must be in the last path segment. Naming the element name and namespace of the node this extraction command is applied to, is optional and automatically defaults to name <code>x</code> and namespace <code>jabber:x:data</code> as defined by <a href="https://xmpp.org/extensions/xep-0004.html">XEP-0004</a>.</p>
<p>This query language extension is its own small query language tailored to data-forms implemented in <code>-(id _Nullable) processDataFormQuery:(NSString*) query;</code>.
To ease its use, this language reuses some constructs of the main query language, but gives them a new meaning:</p>
<ul>
<li><strong>&ldquo;Namespace&rdquo; and &ldquo;element name&rdquo;:</strong><br>
The subquery can begin with something looking like a namespace and element name (both optional) like so: <code>{http://jabber.org/protocol/muc#roominfo}result</code>. The &ldquo;element name&rdquo; is used to select data forms with this form-type (<code>result</code> in this case). The &ldquo;namespace&rdquo; is used to select data-forms with a form field (usually of type hidden) with name <code>FORM_TYPE</code> having this value, see <em>example 6</em>. The special form-type <code>*</code> and <code>FORM_TYPE</code> value <code>*</code> can be used to denote &ldquo;any form-type&rdquo; and &ldquo;any FORM_TYPE field value&rdquo;.</li>
<li><strong>Item index:</strong><br>
This is something not present in the main query language. Between the form-type (the &ldquo;element name&rdquo;, see above) and the &ldquo;extraction command&rdquo; (see below) an index in square brackets is allowed (<code>[0]</code>). An example query using an index as seen in our codebase would be <code>\\result[0]@expire\\</code> or <code>\\[0]@expire\\</code>. An index is only allowed for data-forms having multiple item elements encapsulating the form fields, see <a href="https://xmpp.org/extensions/xep-0004.html#example-8">example 8 of XEP-0004</a>. If the index is out of bounds (e.g. greater than or equal to the count of <code>&lt;item/&gt;</code> XML nodes in the form), the data-form query will return nil, which will be omitted from the resulting <code>NSArray</code> by the <code>MLXMLNode</code> implementation of <code>find:</code> (<code>findFirst:</code> will return nil, and <code>check:</code> will return NO).</li>
<li><strong>Extraction command:</strong><br>
Data-Form subqueries have only two extraction commands: <code>@fieldName</code> and <code>&amp;fieldName</code>. <code>@fieldName</code> is used to extract the value of that field, while <code>&amp;fieldName</code> returns an <code>NSDictionary</code> describing that field, like returned with the <code>-(NSDictionary* _Nullable) getField:(NSString* _Nonnull) name;</code> method of <code>XMPPDataForm</code>.</li>
</ul>
<p><strong><em>Note:</em></strong> The implementation in <code>XMPPDataForm.m</code> has many useful methods for creating and working with <a href="https://xmpp.org/extensions/xep-0004.html">XEP-0004</a> data-forms. Make sure to check out <code>XMPPDataForm.h</code> or the implementation in <code>XMPPDataForm.m</code>.</p>
<p><strong><em>Note:</em></strong> An <code>@fieldName</code> extraction command can be used together with a conversion command, see <em>example 6</em>. Conversion commands are not allowed for <code>&amp;fieldName</code> extraction commands or data-form queries not using an extraction command at all (e.g. returning the whole data-form).</p>
<p><strong>Example 6:</strong></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#f92672">&lt;iq</span> <span style="color:#a6e22e">from=</span><span style="color:#e6db74">&#39;upload.montague.tld&#39;</span> <span style="color:#a6e22e">id=</span><span style="color:#e6db74">&#39;step_02&#39;</span> <span style="color:#a6e22e">to=</span><span style="color:#e6db74">&#39;romeo@montague.tld/garden&#39;</span> <span style="color:#a6e22e">type=</span><span style="color:#e6db74">&#39;result&#39;</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;query</span> <span style="color:#a6e22e">xmlns=</span><span style="color:#e6db74">&#39;http://jabber.org/protocol/disco#info&#39;</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;identity</span> <span style="color:#a6e22e">category=</span><span style="color:#e6db74">&#39;store&#39;</span> <span style="color:#a6e22e">type=</span><span style="color:#e6db74">&#39;file&#39;</span> <span style="color:#a6e22e">name=</span><span style="color:#e6db74">&#39;HTTP File Upload&#39;</span> <span style="color:#f92672">/&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;feature</span> <span style="color:#a6e22e">var=</span><span style="color:#e6db74">&#39;urn:xmpp:http:upload:0&#39;</span> <span style="color:#f92672">/&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;x</span> <span style="color:#a6e22e">type=</span><span style="color:#e6db74">&#39;result&#39;</span> <span style="color:#a6e22e">xmlns=</span><span style="color:#e6db74">&#39;jabber:x:data&#39;</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&lt;field</span> <span style="color:#a6e22e">var=</span><span style="color:#e6db74">&#39;FORM_TYPE&#39;</span> <span style="color:#a6e22e">type=</span><span style="color:#e6db74">&#39;hidden&#39;</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&lt;value&gt;</span>urn:xmpp:http:upload:0<span style="color:#f92672">&lt;/value&gt;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&lt;/field&gt;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&lt;field</span> <span style="color:#a6e22e">var=</span><span style="color:#e6db74">&#39;max-file-size&#39;</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&lt;value&gt;</span>5242880<span style="color:#f92672">&lt;/value&gt;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&lt;/field&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;/x&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;/query&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;/iq&gt;</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-objc" data-lang="objc"><span style="display:flex;"><span>MLXMLNode<span style="color:#f92672">*</span> iqNode <span style="color:#f92672">=</span> <span style="color:#f92672">&lt;</span>the stanza above as MLXMLNode tree<span style="color:#f92672">&gt;</span>;
</span></span><span style="display:flex;"><span>NSInteger uploadSize <span style="color:#f92672">=</span> [[iqNode findFirst:<span style="color:#e6db74">@&#34;{http://jabber.org/protocol/disco#info}query/</span><span style="color:#ae81ff">\\</span><span style="color:#e6db74">{urn:xmpp:http:upload:0}result@max-file-size</span><span style="color:#ae81ff">\\</span><span style="color:#e6db74">|int&#34;</span>] integerValue];
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>MLAssert(uploadSize <span style="color:#f92672">==</span> <span style="color:#ae81ff">5242880</span>, <span style="color:#e6db74">@&#34;Extracted upload size should be 5242880 bytes!&#34;</span>);
</span></span></code></pre></div><p><strong>Some more data-form queries as found in our codebase:</strong></p>
<ul>
<li><code>{http://jabber.org/protocol/disco#info}query/\\{http://jabber.org/protocol/muc#roominfo}result@muc#roomconfig_roomname\\</code></li>
<li><code>{http://jabber.org/protocol/commands}command&lt;node=urn:xmpp:invite#invite&gt;/\\[0]@expire\\|datetime</code> (the form-type and FORM_TYPE field value was omitted, the query matches every data-form)</li>
<li><code>{http://jabber.org/protocol/commands}command&lt;node=urn:xmpp:invite#invite&gt;/\\@expire\\|datetime</code> (the form-type and FORM_TYPE field value was omitted, the query matches every data-form)</li>
</ul>
]]></content:encoded></item><item><title>New NLNet Funding</title><link>https://monal-im.org/post/00013-nlnet-funding2/</link><pubDate>Mon, 22 Jul 2024 00:00:00 +0000</pubDate><guid>https://monal-im.org/post/00013-nlnet-funding2/</guid><description>&lt;p&gt;We are pleased to announce that we &lt;a href="https://nlnet.nl/project/Monal-IM-UI/"&gt;got selected in another funding round&lt;/a&gt; by the &lt;a href="https://ngi.eu/"&gt;EU’s NGI&lt;/a&gt; via the &lt;a href="https://nlnet.nl/entrust"&gt;NLnet Foundation NGI0 Entrust Fund&lt;/a&gt; to work on some important features in Monal.&lt;/p&gt;
&lt;p&gt;In short this consists of the following tasks (in no special order).&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Implement Dialpad:&lt;/strong&gt;
Add Dialpad to our Call-UI and backend code to be able to send DTMF tones in A/V calls. This will
make Monal fully compatible with jmp.chat, like Snikket is already.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rewrite Chat UI:&lt;/strong&gt;
Our current chat UI is still UIKit-based and it&amp;rsquo;s hard to improve it or fix some UI glitches. We want
to rewrite and modernize the whole chat UI using SwiftUI. This will not only simplify maintenance a
lot and allow us to fix these UI glitches, but also enable us to implement modern XMPP features
like message reactions, message styling, message replies or mentions.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;UI work: Implement Message Reactions, Rich Replies and Stickers:&lt;/strong&gt;
Implement UI and backend for message reactions (XEP-0444), rich replies (XEP-0461) and
Stickers, once the chat UI is ported to SwiftUI&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;XSF work:&lt;/strong&gt;
After having successfully worked on the SASL2 XEP-suite, I want to modernize XEP-0389: Extensible In-Band Registration to also send only password hashes
instead of cleartext passwords (similar to password upgrades specced in XEP-0480: SASL Upgrade Tasks)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Write documentation of Monal internals:&lt;/strong&gt;
After having started to publish a blog series and wiki articles about Monal&amp;rsquo;s internals (beginning
with the Handlers Framework), I want to publish blog and wiki articles on our XML query-language
(intentionally based on the XPath-like syntax of Prosody&amp;rsquo;s query language), the PubSub/PEP
framework, Model-Classes used as data sources for our UI (MLContact, MLMessage etc.) and
possibly more.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Thanks again to NLNet for fund this!&lt;/strong&gt;&lt;/p&gt;</description><content:encoded><![CDATA[<p>We are pleased to announce that we <a href="https://nlnet.nl/project/Monal-IM-UI/">got selected in another funding round</a> by the <a href="https://ngi.eu/">EU’s NGI</a> via the <a href="https://nlnet.nl/entrust">NLnet Foundation NGI0 Entrust Fund</a> to work on some important features in Monal.</p>
<p>In short this consists of the following tasks (in no special order).</p>
<ul>
<li><strong>Implement Dialpad:</strong>
Add Dialpad to our Call-UI and backend code to be able to send DTMF tones in A/V calls. This will
make Monal fully compatible with jmp.chat, like Snikket is already.</li>
<li><strong>Rewrite Chat UI:</strong>
Our current chat UI is still UIKit-based and it&rsquo;s hard to improve it or fix some UI glitches. We want
to rewrite and modernize the whole chat UI using SwiftUI. This will not only simplify maintenance a
lot and allow us to fix these UI glitches, but also enable us to implement modern XMPP features
like message reactions, message styling, message replies or mentions.</li>
<li><strong>UI work: Implement Message Reactions, Rich Replies and Stickers:</strong>
Implement UI and backend for message reactions (XEP-0444), rich replies (XEP-0461) and
Stickers, once the chat UI is ported to SwiftUI</li>
<li><strong>XSF work:</strong>
After having successfully worked on the SASL2 XEP-suite, I want to modernize XEP-0389: Extensible In-Band Registration to also send only password hashes
instead of cleartext passwords (similar to password upgrades specced in XEP-0480: SASL Upgrade Tasks)</li>
<li><strong>Write documentation of Monal internals:</strong>
After having started to publish a blog series and wiki articles about Monal&rsquo;s internals (beginning
with the Handlers Framework), I want to publish blog and wiki articles on our XML query-language
(intentionally based on the XPath-like syntax of Prosody&rsquo;s query language), the PubSub/PEP
framework, Model-Classes used as data sources for our UI (MLContact, MLMessage etc.) and
possibly more.</li>
</ul>
<p><strong>Thanks again to NLNet for fund this!</strong></p>
]]></content:encoded></item><item><title>New fundraising campaign</title><link>https://monal-im.org/post/00012-funding-iphone13/</link><pubDate>Tue, 18 Jun 2024 00:00:00 +0000</pubDate><guid>https://monal-im.org/post/00012-funding-iphone13/</guid><description>&lt;p&gt;Our current development iPhone 8, which we bought in 2020, is getting on in years, is not able to run iOS 17 and the battery is broken.&lt;/p&gt;
&lt;p&gt;So it&amp;rsquo;s that time again: we are launching a new fundraising campaign for &lt;strong&gt;350 EUR&lt;/strong&gt; to finance a new development iPhone capable of running iOS 17 and several upcoming iOS versions.
Currently we are aiming for an &lt;strong&gt;iPhone 13&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;You can view our donation options over here: &lt;a href="https://monal-im.org/support/#donate"&gt;Donate&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</description><content:encoded><![CDATA[<p>Our current development iPhone 8, which we bought in 2020, is getting on in years, is not able to run iOS 17 and the battery is broken.</p>
<p>So it&rsquo;s that time again: we are launching a new fundraising campaign for <strong>350 EUR</strong> to finance a new development iPhone capable of running iOS 17 and several upcoming iOS versions.
Currently we are aiming for an <strong>iPhone 13</strong>.</p>
<p><strong>You can view our donation options over here: <a href="https://monal-im.org/support/#donate">Donate</a></strong></p>
]]></content:encoded></item><item><title>ROS Security Audit</title><link>https://monal-im.org/post/00011-security-audit-1/</link><pubDate>Mon, 15 Apr 2024 00:00:00 +0000</pubDate><guid>https://monal-im.org/post/00011-security-audit-1/</guid><description>&lt;p&gt;&lt;a href="https://www.radicallyopensecurity.com/"&gt;Radically Open Security (ROS)&lt;/a&gt; kindly performed a security audit of some parts of Monal.&lt;br&gt;
Specifically they audited the usage of our XML query language and the implementations of &lt;a href="https://xmpp.org/extensions/xep-0388.html"&gt;SASL2&lt;/a&gt;, &lt;a href="https://datatracker.ietf.org/doc/html/rfc5802"&gt;SCRAM&lt;/a&gt; and &lt;a href="https://xmpp.org/extensions/xep-0474.html"&gt;SSDP&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The results in a nutshell: &lt;em&gt;no security issues found&lt;/em&gt;, read the full report here:
&lt;a href="https://monal-im.org/post/00011-security-audit-1/pentest_1.pdf"&gt;Monal IM penetration test report 2024 1.0&lt;/a&gt;
.&lt;/p&gt;</description><content:encoded><![CDATA[<p><a href="https://www.radicallyopensecurity.com/">Radically Open Security (ROS)</a> kindly performed a security audit of some parts of Monal.<br>
Specifically they audited the usage of our XML query language and the implementations of <a href="https://xmpp.org/extensions/xep-0388.html">SASL2</a>, <a href="https://datatracker.ietf.org/doc/html/rfc5802">SCRAM</a> and <a href="https://xmpp.org/extensions/xep-0474.html">SSDP</a>.</p>
<p>The results in a nutshell: <em>no security issues found</em>, read the full report here: 
  
  
  <a href="/post/00011-security-audit-1/pentest_1.pdf">Monal IM penetration test report 2024 1.0</a>

.</p>
]]></content:encoded></item><item><title>iOS app banned from chinese appstore</title><link>https://monal-im.org/post/00010-ios-banned/</link><pubDate>Sun, 31 Mar 2024 00:00:00 +0000</pubDate><guid>https://monal-im.org/post/00010-ios-banned/</guid><description>&lt;p&gt;Some may have predicted it, but now it happened: the chinese government banned Monal from the chinese appstore.
Below is the complete email we got from Apple regarding this ban. We got that mail twice, once on &lt;em&gt;Wed, 27 Mar 2024 15:46:18 +0100&lt;/em&gt;
and a second time on &lt;em&gt;Thu, 28 Mar 2024 17:01:19 +0100&lt;/em&gt;.&lt;br&gt;
&lt;strong&gt;The macOS version of Monal is still available in the appstore and with homebrew, though.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Here is the full mail, a translation of the CAC articles can be found
&lt;a href="https://digichina.stanford.edu/work/new-rules-target-public-opinion-and-mobilization-online-in-china-translation/"&gt;over here&lt;/a&gt;
for reference.&lt;/p&gt;</description><content:encoded><![CDATA[<p>Some may have predicted it, but now it happened: the chinese government banned Monal from the chinese appstore.
Below is the complete email we got from Apple regarding this ban. We got that mail twice, once on  <em>Wed, 27 Mar 2024 15:46:18 +0100</em>
and a second time on <em>Thu, 28 Mar 2024 17:01:19 +0100</em>.<br>
<strong>The macOS version of Monal is still available in the appstore and with homebrew, though.</strong></p>
<p>Here is the full mail, a translation of the CAC articles can be found
<a href="https://digichina.stanford.edu/work/new-rules-target-public-opinion-and-mobilization-online-in-china-translation/">over here</a>
for reference.</p>
<hr>
<p>Hello,</p>
<p>We are writing to notify you that your application, per demand from the CAC (Cyberspace Administration of China), will be removed from the China App Store because it includes content that is illegal in China, which is not in compliance with the <a href="https://developer.apple.com/appstore/resources/approval/guidelines.html">App Review Guidelines</a>:</p>
<ol start="5">
<li>Legal
Apps must comply with all legal requirements in any location where you make them available (if you’re not sure, check with a lawyer). We know this stuff is complicated, but it is your responsibility to understand and make sure your app conforms with all local laws, not just the guidelines below. And of course, apps that solicit, promote, or encourage criminal or clearly reckless behavior will be rejected.</li>
</ol>
<p>According to the CAC, your app violates Articles 3 of the Provisions on the Security Assessment of Internet-based Information Services with Attribute of Public Opinions or Capable of Social Mobilization (具有舆论属性或社会动员能力的互联网信息服务安全评估规定).</p>
<p>If you need additional information regarding this removal or the laws and requirements in China, we encourage you to reach out directly to the <a href="https://www.cac.gov.cn">CAC (Cyberspace Administration of China)</a>.</p>
<p>While your app has been removed from the China App Store, it is still available in the App Stores for the other territories you selected in App Store Connect. The TestFlight version of this app will also be unavailable for external and internal testing in China and all public TestFlight links will no longer be functional.</p>
<p>Best regards,</p>
<p>App Review</p>
]]></content:encoded></item><item><title>Publications moved</title><link>https://monal-im.org/post/00009-publications/</link><pubDate>Wed, 03 Jan 2024 00:00:00 +0000</pubDate><guid>https://monal-im.org/post/00009-publications/</guid><description>&lt;p&gt;It came to light that our publications previously linked in a section under &lt;a href="https://monal-im.org/about/"&gt;About&lt;/a&gt; were not that discoverable.
Now we moved the whole publications list to its own top level menu entry unter &lt;a href="https://monal-im.org/publications/"&gt;Publications&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Enjoy watching the talk recordings and reading the slides and XEPs.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;And last but not least: Happy new year!&lt;/strong&gt;&lt;/p&gt;</description><content:encoded><![CDATA[<p>It came to light that our publications previously linked in a section under <a href="/about/">About</a> were not that discoverable.
Now we moved the whole publications list to its own top level menu entry unter <a href="/publications/">Publications</a>.</p>
<p>Enjoy watching the talk recordings and reading the slides and XEPs.</p>
<p><strong>And last but not least: Happy new year!</strong></p>
]]></content:encoded></item><item><title>Monal 6.0 released</title><link>https://monal-im.org/post/00008-monal-6.0-released/</link><pubDate>Wed, 18 Oct 2023 00:00:00 +0000</pubDate><guid>https://monal-im.org/post/00008-monal-6.0-released/</guid><description>&lt;p&gt;After several month of hard work we just released Monal 6.0.
This version comes with new artwork by Ann-Sophie Zwahlen, support for Audio-Calls funded by the EU’s &lt;a href="https://nlnet.nl/assure/"&gt;NGI Assure via the NLnet Foundation&lt;/a&gt; and many other improvements and bugfixes.
The full list of changes can be seen below:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;NEW:&lt;/strong&gt; Audio-call support (This feature will not be available to users in China and macOS users!)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Other changes:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;New Logo and new placeholder images by Ann-Sophie Zwahlen&lt;/li&gt;
&lt;li&gt;New &amp;ldquo;Add Contact&amp;rdquo; and &amp;ldquo;Contact Requests&amp;rdquo; UI&lt;/li&gt;
&lt;li&gt;Complete rewrite of OMEMO code&lt;/li&gt;
&lt;li&gt;Speed up app start&lt;/li&gt;
&lt;li&gt;Add support for SASL2 (XEP-0388)&lt;/li&gt;
&lt;li&gt;Implement XEP-0424: Message Retraction&lt;/li&gt;
&lt;li&gt;Add support for creating invitations (button only displayed if your server supports it, see &lt;a href="https://docs.modernxmpp.org/client/invites/"&gt;https://docs.modernxmpp.org/client/invites/&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Add timestamp when quoting older messages&lt;/li&gt;
&lt;li&gt;Always show a &amp;ldquo;Notes to self“ chat&lt;/li&gt;
&lt;li&gt;Overhaul implementation of last interaction display&lt;/li&gt;
&lt;li&gt;Show scroll-down button in groupchats&lt;/li&gt;
&lt;li&gt;OMEMO keys are copyable now (double tap)&lt;/li&gt;
&lt;li&gt;Add OSS based crash reporting (KSCrash), reports can be voluntarily sent via mail&lt;/li&gt;
&lt;li&gt;Fix logfile handling&lt;/li&gt;
&lt;li&gt;Add XEP-0215 (external services) to server details ui&lt;/li&gt;
&lt;li&gt;Only show contacts in contacts panel if they are in our roster&lt;/li&gt;
&lt;li&gt;Implement invitations using qr codes in addition of xmpp: uris&lt;/li&gt;
&lt;li&gt;Implement new image viewer compatible with iOS 17&lt;/li&gt;
&lt;li&gt;Implement gif support in image viewer&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Bugfixes:&lt;/strong&gt;&lt;/p&gt;</description><content:encoded><![CDATA[<p>After several month of hard work we just released Monal 6.0.
This version comes with new artwork by Ann-Sophie Zwahlen, support for Audio-Calls funded by the EU’s <a href="https://nlnet.nl/assure/">NGI Assure via the NLnet Foundation</a> and many other improvements and bugfixes.
The full list of changes can be seen below:</p>
<p><strong>NEW:</strong> Audio-call support (This feature will not be available to users in China and macOS users!)</p>
<p><strong>Other changes:</strong></p>
<ul>
<li>New Logo and new placeholder images by Ann-Sophie Zwahlen</li>
<li>New &ldquo;Add Contact&rdquo; and &ldquo;Contact Requests&rdquo; UI</li>
<li>Complete rewrite of OMEMO code</li>
<li>Speed up app start</li>
<li>Add support for SASL2 (XEP-0388)</li>
<li>Implement XEP-0424: Message Retraction</li>
<li>Add support for creating invitations (button only displayed if your server supports it, see <a href="https://docs.modernxmpp.org/client/invites/">https://docs.modernxmpp.org/client/invites/</a>)</li>
<li>Add timestamp when quoting older messages</li>
<li>Always show a &ldquo;Notes to self“ chat</li>
<li>Overhaul implementation of last interaction display</li>
<li>Show scroll-down button in groupchats</li>
<li>OMEMO keys are copyable now (double tap)</li>
<li>Add OSS based crash reporting (KSCrash), reports can be voluntarily sent via mail</li>
<li>Fix logfile handling</li>
<li>Add XEP-0215 (external services) to server details ui</li>
<li>Only show contacts in contacts panel if they are in our roster</li>
<li>Implement invitations using qr codes in addition of xmpp: uris</li>
<li>Implement new image viewer compatible with iOS 17</li>
<li>Implement gif support in image viewer</li>
</ul>
<p><strong>Bugfixes:</strong></p>
<ul>
<li>Many bugfixes</li>
<li>Fix bookmarks2 handling</li>
<li>Fix XEP-0333 in private groups</li>
<li>Fix url preview for sites not having oc: tags</li>
<li>Set notifications to &ldquo;mention only&rdquo; when joining public channels</li>
<li>Show per-resource last interaction timestamp in resource list</li>
<li>Fix file uploading and sharing</li>
<li>Fix timer when recording audio messages</li>
<li>Fix muc avatar fetching</li>
</ul>
]]></content:encoded></item><item><title>Monal Internals - Handlers framework</title><link>https://monal-im.org/post/00007-monal-internals-handlers/</link><pubDate>Wed, 12 Jul 2023 00:00:00 +0000</pubDate><guid>https://monal-im.org/post/00007-monal-internals-handlers/</guid><description>&lt;p&gt;In this new series, I want to shine some light onto specific parts of Monal&amp;rsquo;s internals. It&amp;rsquo;s dedicated to programmers or people curious about how Monal works internally.
If you want to give some feedback, feel free to send an email to &lt;a href="mailto:thilo@monal-im.org"&gt;thilo@monal-im.org&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Other articles in this series:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://monal-im.org/post/00014-monal-internals-xml-query-language/"&gt;Monal Internals - XML Query Language&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://monal-im.org/post/00015-monal-internals-promise-framework/"&gt;Monal Internals - Serializable Promise framework&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="handlers"&gt;Handlers&lt;/h1&gt;
&lt;p&gt;Handlers in Monal are something like serializable callbacks.
In iOS the app can get frozen or even killed any time and the push implementation requires the complete app state to frequently
transition between the Main App and the Notification Service App Extension (NSE). Using normal callbacks (called blocks in ObjC)
is not possible because blocks are not serializable which means they could not survive an app kill or transition to / from the NSE.&lt;/p&gt;</description><content:encoded><![CDATA[<p>In this new series, I want to shine some light onto specific parts of Monal&rsquo;s internals. It&rsquo;s dedicated to programmers or people curious about how Monal works internally.
If you want to give some feedback, feel free to send an email to <a href="mailto:thilo@monal-im.org">thilo@monal-im.org</a></p>
<p><strong>Other articles in this series:</strong></p>
<ul>
<li><a href="/post/00014-monal-internals-xml-query-language/">Monal Internals - XML Query Language</a></li>
<li><a href="/post/00015-monal-internals-promise-framework/">Monal Internals - Serializable Promise framework</a></li>
</ul>
<h1 id="handlers">Handlers</h1>
<p>Handlers in Monal are something like serializable callbacks.
In iOS the app can get frozen or even killed any time and the push implementation requires the complete app state to frequently
transition between the Main App and the Notification Service App Extension (NSE). Using normal callbacks (called blocks in ObjC)
is not possible because blocks are not serializable which means they could not survive an app kill or transition to / from the NSE.</p>
<p>Short overview:</p>
<ul>
<li>Simple generalized concept usable throughout the app</li>
<li>Leverages dynamic language features of ObjC</li>
<li>&ldquo;Serializable callbacks&rdquo; to class / instance methods of ObjC classes</li>
<li>Bind values (<em>not vars</em>) when creating a handler (e.g. to bind state to handler that can be serialized together with the handler)</li>
<li>Bind vars when calling handler (overwriting creation-time bound values having the same name)</li>
<li>Used in various places throughout the app like the IQ or PubSub framework (see <a href="/post/00007-monal-internals-handlers/#code-examples-found-in-the-wild">Code examples found in the wild</a>)</li>
<li><a href="/post/00007-monal-internals-handlers/#available-data-types">Jump directly to list of supported data types</a></li>
</ul>
<h2 id="usage-description-with-examples">Usage description with examples</h2>
<h3 id="define-handler-method">Define handler method</h3>
<p>This will be a static class method and doesn&rsquo;t have to be declared in any
interface to be usable. The argument number or order does not matter,
feel free to reorder or even remove arguments you don&rsquo;t need.
Arguments declared with $$-prefix are mandatory and can not be removed, though.
Arguments with $_-prefix are optional and can be removed.
Primitive datatypes like BOOL, int, NSINTEGER (aka $$INTEGER) etc. can not be
imported as optional and are always mandatory.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-objc" data-lang="objc"><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">$$</span>class_handler(myHandlerName, <span style="color:#960050;background-color:#1e0010">$</span>_ID(xmpp<span style="color:#f92672">*</span>, account), <span style="color:#960050;background-color:#1e0010">$$</span><span style="color:#66d9ef">BOOL</span>(success))
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// your code comes here
</span></span></span><span style="display:flex;"><span>    <span style="color:#75715e">// variables defined/imported: account (optional), success (mandatory)
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">$$</span>
</span></span></code></pre></div><p>Instance handlers are instance methods instead of static methods.
You need to specify on which instance these handlers should operate.
The instance extraxtion statement (the second argument to $$instance_handler() can be everything that
returns an objc object. For example: <code>account.omemo</code> or <code>[account getInstanceToUse]</code> or just <code>account</code>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-objc" data-lang="objc"><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">$$</span>instance_handler(myHandlerName, instanceToUse, <span style="color:#960050;background-color:#1e0010">$$</span>ID(xmpp<span style="color:#f92672">*</span>, account), <span style="color:#960050;background-color:#1e0010">$$</span><span style="color:#66d9ef">BOOL</span>(success))
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// your code comes here
</span></span></span><span style="display:flex;"><span>    <span style="color:#75715e">// &#39;self&#39; is now the instance of the class extracted by the instanceToUse statement.
</span></span></span><span style="display:flex;"><span>    <span style="color:#75715e">// instead of the class instance as it would be if $$class_handler() was used instead of $$instance_handler()
</span></span></span><span style="display:flex;"><span>    <span style="color:#75715e">// variables defined/imported: account, success (both mandatory)
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">$$</span>
</span></span></code></pre></div><h3 id="call-defined-handlers">Call defined handlers</h3>
<p>Calling a defined handler is simple, just create a handler object using <code>$newHandler()</code> and <code>$call()</code> it.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-objc" data-lang="objc"><span style="display:flex;"><span>MLHandler<span style="color:#f92672">*</span> h <span style="color:#f92672">=</span> <span style="color:#960050;background-color:#1e0010">$</span>newHandler(ClassName, myHandlerName);
</span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">$</span>call(h);
</span></span></code></pre></div><h3 id="bind-variables-when-creating-a-handler">Bind variables when creating a handler</h3>
<p>You can bind variables to MLHandler objects when creating them and when
invoking them. Variables supplied on invocation overwrite variables
supplied when creating the handler if the names are equal.
Variables bound to the handler when creating it have to conform to the
NSCoding protocol to make the handler serializable.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-objc" data-lang="objc"><span style="display:flex;"><span>NSString<span style="color:#f92672">*</span> var1 <span style="color:#f92672">=</span> <span style="color:#e6db74">@&#34;value&#34;</span>;
</span></span><span style="display:flex;"><span>MLHandler<span style="color:#f92672">*</span> h <span style="color:#f92672">=</span> <span style="color:#960050;background-color:#1e0010">$</span>newHandler(ClassName, myHandlerName,
</span></span><span style="display:flex;"><span>        <span style="color:#960050;background-color:#1e0010">$</span>ID(var1),
</span></span><span style="display:flex;"><span>        <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#66d9ef">BOOL</span>(success, YES)
</span></span><span style="display:flex;"><span>}));
</span></span><span style="display:flex;"><span>xmpp<span style="color:#f92672">*</span> account <span style="color:#f92672">=</span> nil;
</span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">$</span>call(h, <span style="color:#960050;background-color:#1e0010">$</span>ID(account), <span style="color:#960050;background-color:#1e0010">$</span>ID(otherAccountVarWithSameValue, account))
</span></span></code></pre></div><h3 id="usable-shortcuts-to-create-mlhandler-objects">Usable shortcuts to create MLHandler objects:</h3>
<ul>
<li><code>$newHandler(ClassName, handlerName, boundArgs...)</code></li>
<li><code>$newHandlerWithInvalidation(ClassName, handlerName, invalidationHandlerName, boundArgs...)</code></li>
</ul>
<h3 id="using-invalidation-handlers">Using invalidation handlers</h3>
<p>You can add an invalidation method to a handler when creating the
MLHandler object (after invalidating a handler you can not call or
invalidate it again!). Invalidation handlers can be instance handlers or static handlers,
just like with &ldquo;normal&rdquo; handlers:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-objc" data-lang="objc"><span style="display:flex;"><span><span style="color:#75715e">// definition of normal handler method as instance_handler
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">$$</span>instance_handler(myHandlerName, [account getInstanceToUse], <span style="color:#960050;background-color:#1e0010">$</span>_ID(xmpp<span style="color:#f92672">*</span>, account), <span style="color:#960050;background-color:#1e0010">$$</span><span style="color:#66d9ef">BOOL</span>(success))
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// your code comes here
</span></span></span><span style="display:flex;"><span>        <span style="color:#75715e">// &#39;self&#39; is now the instance of the class extracted by [account getInstanceToUse]
</span></span></span><span style="display:flex;"><span>        <span style="color:#75715e">// instead of the class instance as it would be if $$class_handler() was used instead of $$instance_handler()
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">$$</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// definition of invalidation method
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">$$</span>class_handler(myInvalidationHandlerName, <span style="color:#960050;background-color:#1e0010">$$</span><span style="color:#66d9ef">BOOL</span>(done), <span style="color:#960050;background-color:#1e0010">$</span>_ID(NSString<span style="color:#f92672">*</span>, var1))
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// your code comes here
</span></span></span><span style="display:flex;"><span>        <span style="color:#75715e">// variables imported: var1, done
</span></span></span><span style="display:flex;"><span>        <span style="color:#75715e">// variables that could have been imported according to $newHandler and $call below: var1, success, done
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">$$</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>MLHandler<span style="color:#f92672">*</span> h <span style="color:#f92672">=</span> <span style="color:#960050;background-color:#1e0010">$</span>newHandlerWithInvalidation(ClassName, myHandlerName, myInvalidationHandlerName,
</span></span><span style="display:flex;"><span>        <span style="color:#960050;background-color:#1e0010">$</span>ID(var1, <span style="color:#e6db74">@&#34;value&#34;</span>),
</span></span><span style="display:flex;"><span>        <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#66d9ef">BOOL</span>(success, YES)
</span></span><span style="display:flex;"><span>}));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// call invalidation method with &#34;done&#34; argument set to YES
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">$</span>invalidate(h, <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#66d9ef">BOOL</span>(done, YES))
</span></span></code></pre></div><h3 id="available-data-types">Available data types</h3>
<p>The following datatypes can be bound to a handler defining them using the corresponding definitions having either the <code>$$</code> or <code>$_</code> prefix.
If the single argument binding is used, the value is bound using the same name like the var the value is coming from (in this example: name).</p>
<ul>
<li>define: <code>$$ID(NSObject*, name)</code>, <code>$_ID(NSObject*, name)</code>, bind: <code>$ID(name)</code>, <code>$ID(name, value)</code></li>
<li>define: <code>$$HANDLER(name)</code>, <code>$_HANDLER(name)</code>, bind: <code>$HANDLER(name)</code>, <code>$HANDLER(name, value)</code></li>
<li>define: <code>$$BOOL(name)</code>, bind: <code>$BOOL(name)</code>, <code>$BOOL(name, value)</code></li>
<li>define: <code>$$INT(name)</code>, bind: <code>$INT(name)</code>, <code>$INT(name, value)</code></li>
<li>define: <code>$$DOUBLE(name)</code>, bind: <code>$DOUBLE(name)</code>, <code>$DOUBLE(name, value)</code></li>
<li>define: <code>$$INTEGER(name)</code>, bind: <code>$INTEGER(name)</code>, <code>$INTEGER(name, value)</code>, <em>this corresponds to the NSInteger type alias</em></li>
<li>define: <code>$$UINTEGER(name)</code>, bind: <code>$UINTEGER(name)</code>, <code>$UINTEGER(name, value)</code>, <em>this corresponds to the NSUInteger type alias</em></li>
</ul>
<h2 id="code-examples-found-in-the-wild">Code examples found in the wild</h2>
<h3 id="enabling-carbons">Enabling carbons</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-objc" data-lang="objc"><span style="display:flex;"><span><span style="color:#66d9ef">if</span>([features containsObject:<span style="color:#e6db74">@&#34;urn:xmpp:carbons:2&#34;</span>])
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    DDLogInfo(<span style="color:#e6db74">@&#34;got disco result with carbons ns&#34;</span>);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span>(<span style="color:#f92672">!</span>account.connectionProperties.usingCarbons2)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        DDLogInfo(<span style="color:#e6db74">@&#34;enabling carbons&#34;</span>);
</span></span><span style="display:flex;"><span>        XMPPIQ<span style="color:#f92672">*</span> carbons <span style="color:#f92672">=</span> [[XMPPIQ alloc] initWithType:kiqSetType];
</span></span><span style="display:flex;"><span>        [carbons addChildNode:[[MLXMLNode alloc] initWithElement:<span style="color:#e6db74">@&#34;enable&#34;</span> andNamespace:<span style="color:#e6db74">@&#34;urn:xmpp:carbons:2&#34;</span>]];
</span></span><span style="display:flex;"><span>        [account sendIq:carbons withHandler:<span style="color:#960050;background-color:#1e0010">$</span>newHandler(self, handleCarbonsEnabled)];
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-objc" data-lang="objc"><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">$$</span>class_handler(handleCarbonsEnabled, <span style="color:#960050;background-color:#1e0010">$$</span>ID(xmpp<span style="color:#f92672">*</span>, account), <span style="color:#960050;background-color:#1e0010">$$</span>ID(XMPPIQ<span style="color:#f92672">*</span>, iqNode))
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span>([iqNode check:<span style="color:#e6db74">@&#34;/&lt;type=error&gt;&#34;</span>])
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        DDLogWarn(<span style="color:#e6db74">@&#34;carbon enable iq returned error: %@&#34;</span>, [iqNode findFirst:<span style="color:#e6db74">@&#34;error&#34;</span>]);
</span></span><span style="display:flex;"><span>        [HelperTools postError:[NSString stringWithFormat:NSLocalizedString(<span style="color:#e6db74">@&#34;Failed to enable carbons for account %@&#34;</span>, <span style="color:#e6db74">@&#34;&#34;</span>), account.connectionProperties.identity.jid] withNode:iqNode andAccount:account andIsSevere:YES];
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span>;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    account.connectionProperties.usingCarbons2 <span style="color:#f92672">=</span> YES;
</span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">$$</span>
</span></span></code></pre></div><h3 id="fetching-omemo-bundles">Fetching OMEMO bundles</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-objc" data-lang="objc"><span style="display:flex;"><span>NSString<span style="color:#f92672">*</span> bundleNode <span style="color:#f92672">=</span> [NSString stringWithFormat:<span style="color:#e6db74">@&#34;eu.siacs.conversations.axolotl.bundles:%@&#34;</span>, deviceid];
</span></span><span style="display:flex;"><span>[self.account.pubsub fetchNode:bundleNode from:jid withItemsList:nil andHandler:<span style="color:#960050;background-color:#1e0010">$</span>newHandler(self, handleBundleFetchResult, <span style="color:#960050;background-color:#1e0010">$</span>ID(rid, deviceid))];
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-objc" data-lang="objc"><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">$$</span>instance_handler(handleBundleFetchResult, account.omemo, <span style="color:#960050;background-color:#1e0010">$$</span>ID(xmpp<span style="color:#f92672">*</span>, account), <span style="color:#960050;background-color:#1e0010">$$</span>ID(NSString<span style="color:#f92672">*</span>, jid), <span style="color:#960050;background-color:#1e0010">$$</span><span style="color:#66d9ef">BOOL</span>(success), <span style="color:#960050;background-color:#1e0010">$</span>_ID(XMPPIQ<span style="color:#f92672">*</span>, errorIq), <span style="color:#960050;background-color:#1e0010">$</span>_ID(NSString<span style="color:#f92672">*</span>, errorReason), <span style="color:#960050;background-color:#1e0010">$</span>_ID((NSDictionary<span style="color:#f92672">&lt;</span>NSString<span style="color:#f92672">*</span>, MLXMLNode<span style="color:#f92672">*&gt;*</span>), data), <span style="color:#960050;background-color:#1e0010">$$</span>ID(NSString<span style="color:#f92672">*</span>, rid))
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span>(<span style="color:#f92672">!</span>success)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span>(errorIq)
</span></span><span style="display:flex;"><span>            DDLogError(<span style="color:#e6db74">@&#34;Could not fetch bundle from %@: rid: %@ - %@&#34;</span>, jid, rid, errorIq);
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">else</span>
</span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">DDLogError</span>(<span style="color:#e6db74">@&#34;Could not fetch bundle from %@: rid: %@ - %@&#34;</span>, jid, rid, errorReason);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">else</span>
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// check that a corresponding buddy exists -&gt; prevent foreign key errors
</span></span></span><span style="display:flex;"><span>        MLXMLNode<span style="color:#f92672">*</span> receivedKeys <span style="color:#f92672">=</span> [data objectForKey:<span style="color:#e6db74">@&#34;current&#34;</span>];
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span>(<span style="color:#f92672">!</span>receivedKeys <span style="color:#f92672">&amp;&amp;</span> data.count <span style="color:#f92672">==</span> <span style="color:#ae81ff">1</span>)
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            <span style="color:#75715e">// some clients do not use &lt;item id=&#34;current&#34;&gt;
</span></span></span><span style="display:flex;"><span>            receivedKeys <span style="color:#f92672">=</span> [[data allValues] firstObject];
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">else</span> <span style="color:#66d9ef">if</span>(<span style="color:#f92672">!</span>receivedKeys <span style="color:#f92672">&amp;&amp;</span> data.count <span style="color:#f92672">&gt;</span> <span style="color:#ae81ff">1</span>)
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            DDLogWarn(<span style="color:#e6db74">@&#34;More than one bundle item found from %@ rid: %@&#34;</span>, jid, rid);
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span>(receivedKeys)
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            [self processOMEMOKeys:receivedKeys forJid:jid andRid:rid];
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">$$</span>
</span></span></code></pre></div>]]></content:encoded></item><item><title>XMPP Tutorials</title><link>https://monal-im.org/post/00006-eversten-xmpp-videos/</link><pubDate>Wed, 19 Apr 2023 00:00:00 +0000</pubDate><guid>https://monal-im.org/post/00006-eversten-xmpp-videos/</guid><description>&lt;p&gt;Axel Reimer recently created some good video tutorials about Monal and XMPP in general.&lt;/p&gt;
&lt;p&gt;These video tutorials can be found over here: &lt;a href="https://www.eversten.net/videotutorials/"&gt;https://www.eversten.net/videotutorials/&lt;/a&gt;.&lt;br&gt;
Currently the audio of these videos is German only.&lt;/p&gt;</description><content:encoded><![CDATA[<p>Axel Reimer recently created some good video tutorials about Monal and XMPP in general.</p>
<p>These video tutorials can be found over here: <a href="https://www.eversten.net/videotutorials/">https://www.eversten.net/videotutorials/</a>.<br>
Currently the audio of these videos is German only.</p>
]]></content:encoded></item><item><title>Privacy Monal App ≥ 6.0.0</title><link>https://monal-im.org/privacyarchive/monal_app_rev_003/</link><pubDate>Fri, 10 Feb 2023 13:00:00 +0100</pubDate><guid>https://monal-im.org/privacyarchive/monal_app_rev_003/</guid><description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Monal Website&lt;/strong&gt;&lt;br&gt;
You can find our latest privacy policy for our website here: &lt;a href="https://monal-im.org/privacyarchive/monal_website/" title="Website Privacy Policy"&gt;Website Privacy Policy&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Monal App&lt;/strong&gt;&lt;br&gt;
Our privacy policy may differ between app versions.
Before reading our privacy policy for our App you first need to find out the Monal version that you are using. &lt;br&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How to find out your Monal version&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;Open Monal&lt;/li&gt;
&lt;li&gt;Open up the settings menu in the upper left corner (gearwheel)&lt;/li&gt;
&lt;li&gt;Scroll down to the last entry &amp;ldquo;version&amp;rdquo;&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Monal App Privacy Policies&lt;/strong&gt;&lt;/p&gt;</description><content:encoded><![CDATA[<blockquote>

<p><strong>Monal Website</strong><br>
You can find our latest privacy policy for our website here: <a href="/privacyarchive/monal_website/" title="Website Privacy Policy">Website Privacy Policy</a></p>
<p><strong>Monal App</strong><br>
Our privacy policy may differ between app versions.
Before reading our privacy policy for our App you first need to find out the Monal version that you are using. <br></p>
<p><strong>How to find out your Monal version</strong></p>
<blockquote>
<ol>
<li>Open Monal</li>
<li>Open up the settings menu in the upper left corner (gearwheel)</li>
<li>Scroll down to the last entry &ldquo;version&rdquo;</li>
</ol>
</blockquote>
<p><strong>Monal App Privacy Policies</strong></p>
<table>
  <thead>
      <tr>
          <th>Releases</th>
          <th>Privacy Policy</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>6.0 and newer</td>
          <td><a href="/privacyarchive/monal_app_rev_003/" title="Privacy Policy Rev 003">Privacy Policy Rev 003</a></td>
      </tr>
      <tr>
          <td>5.2.0 up to 5.4.x</td>
          <td><a href="/privacyarchive/monal_app_rev_002/" title="Privacy Policy Rev 002">Privacy Policy Rev 002</a></td>
      </tr>
      <tr>
          <td>before 5.2.0</td>
          <td><a href="/privacyarchive/monal_app_rev_001/" title="Privacy Policy Rev 001">Privacy Policy Rev 001</a></td>
      </tr>
  </tbody>
</table>

</blockquote>
<h1 id="privacy-monal-app--600">Privacy Monal App ≥ 6.0.0</h1>
<h2 id="tldr">TLDR</h2>
<ul>
<li>We <strong>never</strong> see your messages.</li>
<li>We <strong>do not</strong> know who you are chatting with.</li>
<li>We <strong>can not</strong> identify a user.</li>
<li>We can see your XMPP domain and a Monal specific unique device id every time you receive a push message</li>
<li>We see your IP addresses if you are on a call and your XMPP server does not provide a STUN or TURN server.</li>
<li>We may see your contact&rsquo;s IP address if you are using our TURN server.</li>
</ul>
<h2 id="structure">Structure</h2>
<p>The App Monal may interact with Monal servers to support Push messages or if you are establishing a call with a contact but your XMPP Server does neither provide a STUN nor a TURN server.</p>
<p>Our privacy details are structured as follows.
First, we would like to give you a short introduction how Monal is handling push messages to ensure a pleasant user experience.
We will then briefly explain VoIP calls and its privacy implications.
Afterwards we like to inform you how we are using crash and usage reports, logs and GDPR Subject Access Requests (SAR).</p>
<h2 id="push">Push</h2>
<p>App Resources are very limited on iOS and macOS.
Monal for example can only run a limited time in the background after a user either locked the screen or switched the app.
Hence, apps on iOS and macOS can not simply keep a connection to your XMPP server open 24/7 to inform you about new messages.
To overcome these limitations your XMPP server can request our push server to send push messages to your device through Apple.
With these push messages we can request Apple to wake up Monal on your device.
Once it is woken up it has about 30 seconds to connect to your XMPP server, fetch all new messages and show a push notification for these new messages, if needed.</p>
<h3 id="how-push-works">How push works</h3>
<p>Every time that Monal loggs in at your XMPP servers, it asks your server to inform our push server once you receive an XMPP message while Monal is closed/disconnected.
To do this, we request a Monal specific push token from Apple and provide this token to your XMPP server.
Using this Monal specific push token your XMPP server can instruct our push server to send push messages via Apples push system to wake up the app on your device.</p>
<p>Once push messages are enabled for your Monal instance on all your XMPP servers, your XMPP servers will open a encrypted server to server (s2s) connection to one of our push servers.
Using this s2s connection your XMPP servers will then be able to talk to our push servers.
To wake up your Monal instance your XMPP servers send us:</p>
<ul>
<li>Your unique Monal specific push token that was generated by Apple</li>
<li>The domain of the XMPP server that you are using</li>
</ul>
<h3 id="push-1">Push</h3>
<ul>
<li>We <strong>never</strong> see your messages.</li>
<li>We <strong>do not</strong> know who you are chatting with.</li>
<li>We could <strong>only</strong> ever track what XMPP domains a push token is/was using.</li>
<li>We <strong>can not</strong> identify a user.</li>
</ul>
<h4 id="push-servers">Push-Servers</h4>
<p>We currently provide the following independent push server regions:</p>
<ul>
<li>Europe</li>
<li>Alpha (based in Europe, only used for debugging with higher log levels, not for production use)</li>
</ul>
<p><strong>Note:</strong> Our previously used US push region was unfortunately shutdown <a href="https://fosshost.org/">due to fosshost ceasing operation</a>.</p>
<h4 id="how-to-change-the-push-region">How to change the push region</h4>
<blockquote>
<ol>
<li>Open Monal</li>
<li>Open up the settings menu in the upper left corner (gearwheel)</li>
<li>Open the Notifications menu</li>
<li>Scroll down</li>
<li>Select a region</li>
</ol>
</blockquote>
<h4 id="push-server-regions">Push server regions</h4>
<p>If you are an XMPP server administrator, and you restricted s2s connections, please allow s2s to all our regions.</p>
<table>
  <thead>
      <tr>
          <th>Region</th>
          <th>Hostname</th>
          <th>Notice</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Europe</td>
          <td>eu.prod.push.monal-im.org</td>
          <td></td>
      </tr>
  </tbody>
</table>
<h3 id="push-server-locations">Push server locations</h3>
<table>
  <thead>
      <tr>
          <th>Name</th>
          <th>Region</th>
          <th>Hoster</th>
          <th>Location</th>
          <th>Notice</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>s1.eu.prod.push.monal-im.org</td>
          <td>Europe</td>
          <td>Hetzner</td>
          <td>Finland</td>
          <td></td>
      </tr>
      <tr>
          <td>s2.eu.prod.push.monal-im.org</td>
          <td>Europe</td>
          <td>PHP-Friends</td>
          <td>Germany</td>
          <td></td>
      </tr>
  </tbody>
</table>
<h2 id="voip-stun--turn">VoIP (STUN / TURN)</h2>
<p>With Monal 6.0 we introduced VoIP support.
To establish the connection between you and the remote party (the remote contact) Monal utilizes STUN and TURN.
In general STUN (Session Traversal Utilities for NAT) is used to allow a VoIP call even when you are behind firewalls.</p>
<p>Calls established using only STUN will directly exchange packets (P2P) between you and your contact.
Hence, your contact may see your IP address.
If you do not want your contact to see your IP Address while being on a call, disable P2P connection in Monal&rsquo;s privacy settings.
Once disabled Monal tries to establish the call using a TURN (Traversal Using Relays around NAT) server.</p>
<p><strong>Note:</strong> Not all XMPP servers currently provide STUN and TURN servers.
If your XMPP server does <em>not</em> provide STUN and TURN servers, Monal may use our fallback servers.
These fallback servers provide both STUN and TURN.
You can disable Monal to use these fallback turn servers.
Please note, that we may disable our fallback STUN and TURN servers at any time, if too many users are using them.</p>
<p>If you use our fallback servers we will see:</p>
<ul>
<li>Your IP Addresses</li>
<li>The IPs of your contact or the IPs of their TURN-Server</li>
<li>The duration of the call</li>
</ul>
<p>We will <strong>not</strong> see the contents of that call, because these are E2E encrypted.</p>
<h2 id="crash-reports-and-app-usage">Crash reports and app usage</h2>
<p>Monal does track crashes and usage data anonymously using the tools provided by Apple.
This is opt-in only and controlled by iOS and macOS global settings.
If a user decides not to send any data to developers, no crash logs are sent to Monal developers.</p>
<h2 id="logs">Logs</h2>
<p>Your local device will contain a log file with all sent and received raw XMPP messages as well as debug logs.
It does contain sensitive personal data!
This file will never be transferred to us, except if you explicitly (manually) send it to us (e.g., via mail).</p>
<h2 id="gdpr-subject-access-requests-sar">GDPR Subject Access Requests (SAR)</h2>
<p>European GDPR allows users to request a copy of all data retained about them. Starting with Monal 5.2.0 we no longer see your JIDs (<a href="mailto:username@domain.tld">username@domain.tld</a>) in our push servers.
We therefore are not able to send you retained data related to your JID.
We furthermore are unable to provide your retained data related to your unique push token because we have no way to verify that Apple issued you a provided token.
If you have questions regarding GDPR, please send us a mail to <a href="mailto:info@monal-im.org">info@monal-im.org</a>.</p>
]]></content:encoded></item><item><title>Push on iOS</title><link>https://monal-im.org/post/00005-push-on-ios/</link><pubDate>Sat, 04 Feb 2023 00:00:00 +0000</pubDate><guid>https://monal-im.org/post/00005-push-on-ios/</guid><description>&lt;p&gt;I recently wrote a summary about push on iOS in the xmpp.org wiki.&lt;br&gt;
See &lt;a href="https://wiki.xmpp.org/web/Push_notifications"&gt;over here&lt;/a&gt; for all the technical details and links to the documentation.
I also talked about that topic in my talk &amp;ldquo;&lt;em&gt;Modern XMPP - A story based on Monal&lt;/em&gt;&amp;rdquo; linked &lt;a href="https://monal-im.org/about/"&gt;on the About page over here&lt;/a&gt;.&lt;br&gt;
For convenience I&amp;rsquo;d like to summarize some parts of that wiki entry in this blog-post, too.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;UPDATE:&lt;/strong&gt; This post describes the way Monal implements push as well as the pitfalls of implementing it in another way. I tried to make this clearer in the text now.&lt;/p&gt;</description><content:encoded><![CDATA[<p>I recently wrote a summary about push on iOS in the xmpp.org wiki.<br>
See <a href="https://wiki.xmpp.org/web/Push_notifications">over here</a> for all the technical details and links to the documentation.
I also talked about that topic in my talk &ldquo;<em>Modern XMPP - A story based on Monal</em>&rdquo; linked <a href="/about/">on the About page over here</a>.<br>
For convenience I&rsquo;d like to summarize some parts of that wiki entry in this blog-post, too.</p>
<p><strong>UPDATE:</strong> This post describes the way Monal implements push as well as the pitfalls of implementing it in another way. I tried to make this clearer in the text now.</p>
<h1 id="background-knowledge-push-on-ios">Background knowledge: Push on iOS</h1>
<p>On iOS there are several push modes having different properties. All modes, except VoiIP pushes, have in common, that they only provide 30 seconds of background time.</p>
<ul>
<li><strong>VoIP pushes:</strong> MUST always make the device ring via Apple&rsquo;s CallKit framework. You can&rsquo;t use these pushes to silently retrieve messages or other XMPP stanzas in the background.</li>
<li><strong>Low priority pushes:</strong> These pushes don&rsquo;t show any user-visible notification, but they can be dropped or arbitrarily delayed by Apple. They grant 30 seconds of background time.</li>
<li><strong>High priority pushes:</strong> These MUST show a user-visible notification. They grant 30 seconds of background time.
<ul>
<li><strong>But:</strong> Since iOS 13.3, apps having the <code>com.apple.developer.usernotifications.filtering</code> entitlement are allowed to suppress the user-visible notification. To cite Apple:
<blockquote>
<p>This entitlement is intended for certain types of apps — such as messaging apps or location sharing apps — that use notification service extensions to receive push notifications without delivering notifications to the user.</p>
</blockquote>
</li>
</ul>
</li>
</ul>
<p>High priority pushes in combination with the <code>com.apple.developer.usernotifications.filtering</code> entitlement are not only used by Monal, but some other popular messaging apps, too (links to the source):</p>
<ul>
<li><a href="https://www.reddit.com/r/TweakBounty/comments/z9oyf7/comment/iyirqor/?utm_source=reddit&amp;utm_medium=web2x&amp;context=3">WhatsApp</a></li>
<li><a href="https://github.com/signalapp/Signal-iOS/blob/main/SignalNSE/SignalNSE-AppStore.entitlements#L7">Signal</a></li>
<li><a href="https://github.com/threema-ch/threema-ios/blob/main/ThreemaNotificationExtension/SupportingFiles/ThreemaForWorkRedNotificationExtension.entitlements#L7">Threema</a></li>
<li><a href="https://github.com/TelegramMessenger/Telegram-iOS/blob/master/build-system/fake-codesigning/profiles/NotificationService.mobileprovision">Telegram</a> (binary)</li>
</ul>
<h1 id="monal">Monal</h1>
<p>Monal is using this entitlement to wake up background processing without sending any message data through Apple&rsquo;s servers (not even ecrypted data).
When iOS grants the app it&rsquo;s 30 seconds background time because of the incoming push, Monal then connects to the XMPP server over the network to retrieve the actual message
and display a notification to the user, if needed.</p>
<p>Signal does exactly the same:  It uses push only to wake up the app and then fetches the messages using a dedicated network connection: <a href="https://github.com/signalapp/Signal-iOS/blob/main/SignalNSE/NotificationService.swift#L236">Example in Signal&rsquo;s code</a></p>
<p><strong>This way Monal avoids all of the pitfalls depicted below!</strong></p>
<h1 id="diving-deeper-some-more-details-about-ios-push-and-xmpp">Diving deeper: Some more details about iOS push and XMPP</h1>
<p>The following explanations and thoughts are a bit more technical and require some understanding of the XMPP protocol and it&rsquo;s inner workings.</p>
<h2 id="push-server-implementations-and-ios-time-limits">Push server implementations and iOS time limits</h2>
<p>Pushes of all types (see above) can only wake up the iOS app for 30 seconds. But in most cases that&rsquo;s more than enough to connect to the xmpp server and retrieve pending stanzas (if using the entitlement mentioned above and XEP-0198, it is even possible to get pushes for iq stanzas etc., thus behaving like being permanently connected while still sleeping most of the time because of CSI).
Even if the 30 seconds don&rsquo;t suffice, the client can disconnect and both, Prosody and eJabberd, will send another push if there are still unacked stanzas in the XEP-0198 queue. This will give the app another 30 seconds. Even longer catchups lasting for &gt; 5 minutes can be done completely in the background this way (observed in the wild with Monal stable).</p>
<p>This means that even with the 30 second time limit in place, it usually is possible to do a longer lasting catchup completely in the background, effectively extending the time limit to several minutes.
This obviously only holds, if you use the <code>com.apple.developer.usernotifications.filtering</code> entitlement and connect directly to the xmpp server and is hardly possible if you try to transport stanzas through the push sent through Apple (see below).</p>
<h2 id="pitfalls-transporting-encrypted-xmpp-message-stanzas-through-push-out-of-band">Pitfalls: Transporting (encrypted) xmpp message stanzas through push (out of band)</h2>
<p>When using the iOS push infrastructure provided by apple for transporting (encrypted) stanzas out of band, multiple things have to be considered. First of all, pushes can get lost. That frequently happens if the device was in flight mode while the push was sent.
Second, xmpp is a streaming protocol, strongly relying on the ordering of stanza (even inter-type ordering like the ordering of message and iq stanzas for mam). The order of message stanza matters for other XEPs, too (for example message retraction or last message correction). Using the iOS push service which is loosing pushes or even only sending pushes for a particular type of stanza (message stanzas having a body for example) breaks this ordering of events that every XEP implicitly relies upon.
The payload sizes allowed for each push are also somewhat low (~4kb including some of the push metadata).
OMEMO&rsquo;s self-healing through key-transport-elements requires the client to send those key-transport message stanzas once a broken session gets detected. But using the push service for data transport is a one way channel only.</p>
<p>Last but not least the UX can be really degraded if a user does not open the app for some hours (while still receiving push notifications). Once they open the app, a long mam catchup has to be waited for until the ui does reflect what the user already saw in notifications. If the device has no connectivity when the user opens it, they might even be really confused why those messages they alread saw a notification for are not displayed in the app at all). Writing incoming messages to the database to solve this will only make the ordering problem depicted above harder. The client not being able to execute the OMEMO self-healing stuff mentioned above will degrade UX further.</p>
<p>NOT using the entitlement mentioned above will prevent the client from receiving push notifications for XEP-0333 read markers and remove already displayed notifications instead of posting a new one (because apps not having that entitlement are forced to show a notification for each incoming high priority push, even if the push was only for a XEP-0333 read marker).
<strong>To be clear: without that entitlement neither message retraction nor XEP-0333 read markers can be implemented reliably!</strong><br>
<em>And if an app has the entitlement:</em> why bother delivering some stanzas out of band and running into the ordering problem if the app could as well connect to the xmpp server in the background and retrieve all pending stanzas in the right order?</p>
]]></content:encoded></item><item><title>On the state of SASL in XMPP</title><link>https://monal-im.org/post/00004-sasl/</link><pubDate>Thu, 06 Oct 2022 00:00:00 +0000</pubDate><guid>https://monal-im.org/post/00004-sasl/</guid><description>&lt;p&gt;SASL (Simple Authentication and Security Layer) &lt;a href="https://xmpp.org/rfcs/rfc6120.html#sasl"&gt;as used in XMPP&lt;/a&gt; is broken. In this blog post I&amp;rsquo;ll try to explain why and propose some fixes.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update (2023-04-21):&lt;/strong&gt; Since I originally wrote this blog post, I&amp;rsquo;ve had the ability to discuss several of my ideas with Dave (the original author of XEP-0388 dubbed SASL2), MattJ (one of the authors of the prosody xmpp server) and others.
Most, if not all, of my issues are now addressed in a bunch of updates to existing XEPs as well as new XEPs:&lt;/p&gt;</description><content:encoded><![CDATA[<p>SASL (Simple Authentication and Security Layer) <a href="https://xmpp.org/rfcs/rfc6120.html#sasl">as used in XMPP</a> is broken. In this blog post I&rsquo;ll try to explain why and propose some fixes.</p>
<p><strong>Update (2023-04-21):</strong> Since I originally wrote this blog post, I&rsquo;ve had the ability to discuss several of my ideas with Dave (the original author of XEP-0388 dubbed SASL2), MattJ (one of the authors of the prosody xmpp server) and others.
Most, if not all, of my issues are now addressed in a bunch of updates to existing XEPs as well as new XEPs:</p>
<ul>
<li>Update of XEP-0388 (SASL2): <a href="https://xmpp.org/extensions/xep-0388.html">https://xmpp.org/extensions/xep-0388.html</a></li>
<li>New SASL2- and SCRAM-upgrade XEP: <a href="https://xmpp.org/extensions/xep-0480.html">https://xmpp.org/extensions/xep-0480.html</a></li>
<li>New XEP for downgrade protection when using SCRAM: <a href="https://xmpp.org/extensions/xep-0474.html">https://xmpp.org/extensions/xep-0474.html</a></li>
<li>Already existing XEP that only now gets adopted by server developers: <a href="https://xmpp.org/extensions/xep-0440.html">XEP-0440</a></li>
</ul>
<p>The rest of this blog post remains as is and can be used for a deeper introduction into the material and as explanation of some of the rationale behind the SASL2 updates and my ProtoXEP.</p>
<h1 id="a-modern-authentication-protocol">A Modern Authentication Protocol</h1>
<p>In my opinion a modern authentication protocol should have at least the following properties. Of course that can be subject to debate, but I think most of us will agree on the following list.</p>
<ol>
<li>allow for protocol agility (e.g. adding new authentication mechanisms, like adding new cipher suites in TLS)</li>
<li>prevent downgrade attacks on authentication mechanisms (we don&rsquo;t want an active attacker to be able to force us to use a weak mechanism)</li>
<li>prevent storage of plaintext passwords on the server (that&rsquo;s obvious: we don&rsquo;t want a hacker to be able to steal our plaintext passwords once he hacked the database)</li>
<li>prevent replay attacks (we don&rsquo;t want a MITM (man in the middle) be able to steal a (possibly hashed) password and use it to authenticate herself)</li>
<li>(possibly) prevent/detect MITM altogether</li>
</ol>
<h2 id="how-sasl-tries-to-fulfill-these-properties">How SASL tries to fulfill these properties</h2>
<p>First of all: <a href="https://xmpp.org/rfcs/rfc6120.html">XMPP Core</a> mandates the use of TLS for everything, including authentication. Keep that in mind, when reading the rest of this blog post.</p>
<h3 id="property-1">Property 1</h3>
<p>SASL <a href="https://xmpp.org/rfcs/rfc6120.html#sasl">as defined for XMPP</a> allows the server to present a list of authentication methods. The client then picks the one having the highest perceived strength (<a href="https://xmpp.org/rfcs/rfc6120.html#sasl-rules-preferences">see XMPP-Core 6.3.3</a>) among the ones it implements. <a href="https://xmpp.org/extensions/xep-0438.html#required">XEP-0438: Best practices for password hashing and storage</a> lists some common authentication methods and how they should be ordered. Currently, the methods PLAIN (plaintext password), EXTERNAL (using client certificates to authenticate the user) and <a href="https://www.rfc-editor.org/rfc/rfc5802">SCRAM</a> (Salted Challenge Response Authentication Mechanism) are common.</p>
<blockquote>
<p>(I will not talk about SASL EXTERNAL in this blog post, because it does not use passwords and seems to be super uncommon in the XMPP world.)</p>
</blockquote>
<p>This generally allows adding new mechanisms in the future, protocol agility seems to be fulfilled, right?</p>
<h3 id="property-3">Property 3</h3>
<p>Current <a href="https://xmpp.org/rfcs/rfc6120.html#security-mti">mandatory SASL methods</a> include SCRAM-SHA-1 and SCRAM-SHA-1-PLUS (if possible). <a href="https://www.rfc-editor.org/rfc/rfc5802">SCRAM</a> generally allows the server to store a salted hash instead of plaintext passwords.</p>
<p>Even if the client uses the PLAIN method, the server could store the password as salted hash.<br>
And EXTERNAL usually does not use any form of password.</p>
<p>So that&rsquo;s another property of our list that is fulfilled, right?</p>
<h3 id="property-4">Property 4</h3>
<p>Using <a href="https://www.rfc-editor.org/rfc/rfc5802">SCRAM</a> it is even possible to prevent replay attacks because of the used challenge-response scheme. That&rsquo;s even possible if no TLS channel is used.</p>
<p>Cool, another property that&rsquo;s fulfilled by SCRAM as well, right?</p>
<h3 id="property-5">Property 5</h3>
<p><a href="https://www.rfc-editor.org/rfc/rfc5802">SCRAM</a> is even cooler because it allows for <a href="https://www.rfc-editor.org/rfc/rfc5929">TLS channel-binding</a>.<br>
This allows both entities (client and server) taking part in the SCRAM authentication to bind the authentication to the TLS channel using a HMAC (Hash-Based Message Authentication Code) to sign a unique data blob tied to the TLS session in use.</p>
<p>If the TLS channel is intercepted by a MITM, the attacker would have to use two separate TLS channels, one to the server and one to the client.<br>
Binding the authentication to the TLS channel allows the server and client to detect such an attacker and fail the authentication.</p>
<p>To indicate, that a server supports channel-binding, it appends the string <code>-PLUS</code> to the advertised SCRAM methods.<br>
If the client supports channel-binding, it picks <code>SCRAM-SHA-1-PLUS</code> instead of <code>SCRAM-SHA-1</code>.<br>
In case the client supports channel-binding, but only received methods without channel-binding,  the client uses the SCRAM method without -PLUS, but also indicates that it would have used the PLUS varriant if offered by the server (<a href="https://www.rfc-editor.org/rfc/rfc5802#section-6">SCRAM Channel Binding</a>).<br>
This allows for the server to detect downgrade attacks and fail the authentication.<br>
Because there are multiple different kinds of channel-binding to TLS possible, the client also specifies which binding it uses during the SCRAM flow (protocol agility).</p>
<p>Channel binding prevents MITM altogether, right? Another property that&rsquo;s fulfilled!</p>
<h1 id="whats-broken-with-sasl-in-xmpp">What&rsquo;s broken with SASL in XMPP</h1>
<p>Cautious readers will have noticed, that I left out property 2 (downgrade attack prevention) in my above explanation. That&rsquo;s because SASL does not prevent downgrade attacks regarding the method negotiation at all. And that&rsquo;s one of the main reasons why the whole SASL in XMPP stuff is so horribly broken.</p>
<h2 id="downgrade-of-sasl-methods">Downgrade of SASL methods</h2>
<p>The XMPP Core RFC even <a href="https://xmpp.org/rfcs/rfc6120.html#security-reuse-sasl">mentions downgrade attacks and suggests using TLS to mitigate them</a>. But that&rsquo;s not enough. If we assume the TLS channel to always be secure and MITM-free, we don&rsquo;t even need <a href="https://www.rfc-editor.org/rfc/rfc5802">SCRAM</a> but could solely use PLAIN. The TLS channel already ensures no replay attacks can happen and storing the passwords securely using salted hashes on the server is still possible. We don&rsquo;t need any channel-binding either, because that&rsquo;s only needed if we assume someone has tampered with the TLS channel in the first place. In this scenario MITM-Prevention (property 5) is simply out of scope for SASL, because we assume TLS to always be MITM-free. That means our properties mentioned above are all fulfilled (property 5 by definition, the other ones by use of TLS) even if we abandon SCRAM and solely use PLAIN.</p>
<p>If we, on the other hand, don&rsquo;t assume to always have a MITM-free TLS channel, then the above listed properties 2, 4 and 5 are all not fulfilled (that means: no downgrade prevention, no replay attack prevention and no MITM detection/prevention). The attacker could simply remove every advertised SASL method except PLAIN and thus get the plaintext password which is replayable and neither the server nor the client will detect this MITM. Supporting SCRAM in clients and servers does not help at all with this, because it simply will not be negotiated.</p>
<p>Well, okay, but <a href="https://xmpp.org/extensions/xep-0438.html#pinning">XEP-0438: Best practices for password hashing and storage</a> (and some RFC I don&rsquo;t remember) says, we should pin the last used SASL mechanism in the client to prevent downgrade attacks in further SASL sessions. That way the client won&rsquo;t use SASL mechanisms having a perceived lower strength than the pinned one. Using a stronger one is still possible. That&rsquo;s right, but it makes matters worse in regard to protocol agility while still not preventing the downgrade attack for the first connection of a client to the XMPP server.</p>
<h2 id="broken-protocol-agility">Broken protocol agility</h2>
<p>Protocol agility means we can specify new authentication methods later on and our client will always use the best one advertised by the server. That&rsquo;s important because it allows us to gradually upgrade the security strength of our authentication while still maintaining backwards compatibility with older clients, eventually removing an old authentication method once most/all clients use a newer one (like replacing DIGEST-MD5 or CRAM-MD5 with SCRAM-SHA-XXX).</p>
<h3 id="scram-without-plus-variants">SCRAM <em>without</em> PLUS variants</h3>
<p>Because of SCRAM fulfilling property 3 (preventing storage of plaintext passwords on the server), we can not upgrade the stored password hashes in the server&rsquo;s database to a new SCRAM-based SASL mechanism. The obvious partial solution is to store new user&rsquo;s passwords using the newer SCRAM algorithm and leave the old user&rsquo;s passwords like they are. That way at least <em>some</em> of your users get to use the new SCRAM algorithm, slowly phasing out the old one eventually. An example would be a server that previously only supported SCRAM-SHA-1 now advertising support for SCRAM-SHA-256.</p>
<p>Oh, no! That doesn&rsquo;t work either! The current <a href="https://xmpp.org/rfcs/rfc6120.html#sasl">specification of SASL in XMPP</a> does send the list of supported SASL methods to the client before knowing which username the client wants to authenticate for. That means the server will always advertise SCRAM-SHA-256, even if the hash in the database is still SHA-1. If the client supports SCRAM-SHA-256 as well, it will happily pick that one and the server, only having the SHA-1 hash at hand, won&rsquo;t be able to authenticate the user. The client on the other hand will have no way to detect why the authentication failed and switch to a percieved lower strength SASL algorithm (and even if that would be possible, it could possibly be used as a downgrade vector if done wrong).</p>
<p>Well, method pinning to the rescue! We already talked about SASL method pinning. The client obviously knows which SASL method it used the last time it authenticated successfully and can always use just this method, no other, even if it implements some having a higher strength. That extends the pinning described in <a href="https://xmpp.org/extensions/xep-0438.html#pinning">XEP-0438: Best practices for password hashing and storage</a> to algorithms having a higher strength as well, something that, to my knowledge, isn&rsquo;t specified anywhere. Additionally, that means we completely loose protocol agility after our first authentication. And newly offering SCRAM-SHA-256 on a server not storing plaintext passwords after it previously only advertised SCRAM-SHA-1 will likely still break authentication for all clients not doing this exact &ldquo;always use the mechanism used on first auth&rdquo; pinning.</p>
<p>The only way to advertise support for a new SCRAM hash algorithm and make clients use it is to upgrade your complete password database on the server by forcing a password reset upon all of your existing users. This must presumably be done out of band for XMPP. Clients implementing the strict pinning outlined above will have to reset the pinning once a new password gets entered by the user. If they don&rsquo;t do so, this strict pinning to the old algorithm will still be in place and this client won&rsquo;t be able to authenticate the user after the password reset.</p>
<p>And I&rsquo;ve not even started to talk about a user having two clients, one that only supports an old SCRAM algorithm (say SCRAM-SHA-1) and one that supports a new one (say SCRAM-SHA-256). The server obviously must store both hashes in its database to allow logins for both clients.</p>
<p>Sounds all pretty bad, right? How come, that hasn&rsquo;t been discovered yet? Well, someone already identified these problems back in 2019. See <a href="https://mail.jabber.org/pipermail/standards/2019-January/035720.html">this thread</a> on the <a href="mailto:standards@xmpp.org">standards@xmpp.org</a> mailinglist. But no attempt was made to fix them. Even the new <a href="https://xmpp.org/extensions/xep-0388.html">XEP-0388: Extensible SASL Profile</a> still uses the same protocol flow with no fix, albeit allowing for additional handshakes during the authorization phase like pipelining a bind request or <a href="https://xmpp.org/extensions/xep-0198.html">resumption via XEP-0198: Stream Management</a> onto the authorization.</p>
<p>Sidenote: One could solve this mess by sacrificing property 3 (not storing plaintext passwords on the server). If the plaintext password is stored on the server, every SCRAM algorithm can be used by the client. But do we really want that? At least that would allow the server to advertise new SCRAM algorithms without having to force a password reset.</p>
<h3 id="scram-with-plus-variants">SCRAM <em>with</em> PLUS variants</h3>
<p>When looking at the channel-binding situation we already saw that the client specifies the type of channel-binding it wants to use. That allows for protocol agility, right?</p>
<p>No! The client does not have any way to detect which channel-binding type the server supports (appending <code>-PLUS</code> to the advertised SCRAM algorithm does not in any way specify which channel-binding to use). And if the client uses the wrong channel-binding the server does not support, the server will simply fail the authentication. The client will have no way to detect if the authentication failed because of the wrong channel-binding type used or if the actual password was wrong, like with using the &ldquo;wrong&rdquo; SASL algorithm above.</p>
<p>This renders the whole channel-binding protocol agility completely useless. <a href="https://www.rfc-editor.org/rfc/rfc9266#section-1">And protocol agility is needed even for channel-binding!</a></p>
<h1 id="some-solutions">Some Solutions</h1>
<p>Well, that&rsquo;s pretty bad news, right? But I don&rsquo;t want to simply rant and leave the shard for someone else to collect, but propose fixes instead. And to my knowledge some of these problems are really fixable.</p>
<p>In this section I want to propose fixes to at least some of these problems. These fixes are open to debate and if we come up with even better solutions during this debate, that&rsquo;d be great.</p>
<h2 id="restoring-protocol-agility-for-channel-binding">Restoring protocol agility for channel-binding</h2>
<p>The server must not use <code>-PLUS</code> to indicate SCRAM algorithms with channel-binding, but use the name of the concrete channel-binding type as SCRAM algorithm suffix. That way the client will be able to determine if it supports that type of channel-binding and only select those SCRAM algorithms having a channel-binding it supports. The server is only allowed to advertise channel binding methods supported by the currently used channel (e.g. don&rsquo;t advertise <code>tls-unique</code> on a TLS 1.3 channel, but only <code>tls-exporter</code> (if implemented)). Clients and servers may choose to still support the <code>-PLUS</code> SCRAM method names in addition to these new ones containing the concrete channel-binding type, but I don&rsquo;t think that gets us anywhere.</p>
<p>Some examples: <code>SCRAM-SHA-1_TLS-UNIQUE</code> or <code>SCRAM-SHA-512_TLS-EXPORTER</code>. That, of course, does not help at all, if channel-binding support can be rendered useless by a downgrade attack.</p>
<h2 id="preventing-downgrade-of-sasl-methods">Preventing downgrade of SASL methods</h2>
<p>Downgrades can be prevented by only allowing SASL EXTERNAL and SCRAM methods (or something similar to SCRAM that then mutual authenticates the whole protocol flow). The <a href="https://www.rfc-editor.org/rfc/rfc5802">SCRAM</a> client-final message must contain a client proof built using a HMAC not only covering the <code>client-first-message-bare</code>, <code>server-first-message</code> and <code>client-final-message-without-proof</code>, but also the (sorted) SASL method list. That allows the server to verify if the client used the correct list and this could not be manipulated, because it is ultimately signed with the client password, a MITM attacker can not know.</p>
<p>We can achieve this by adding an optional SCRAM attribute to <code>client-first-message-bare</code> which will be ignored by non-supporting servers, but secure the handshake against downgrades on supporting servers. This attribute (let&rsquo;s name it <code>d</code>) will contain a base64-encoded hash of the sorted SASL method list as received by the client (using the same hash method as used in the whole SCRAM stuff). The server then checks if that hash matches the one it calculated itself by hashing the sorted SCRAM method list it advertised and fail the authentication, if these hashes don&rsquo;t match.</p>
<p>The sorting can be done alphabetical in ascending order and the individual SASL methods be separated by <code>&lt;</code> like done in <a href="https://xmpp.org/extensions/xep-0115.html">XEP-0115: Entity Capabilities</a> before the whole string is hashed.</p>
<p>We now have a working downgrade attack prevention that&rsquo;s even backwards compatible with existing SCRAM methods and servers not supporting this new SCRAM attribute.</p>
<h2 id="restoring-protocol-agility-for-sasl-methods-part-1">Restoring protocol agility for SASL methods part #1</h2>
<p>First of all, the server will have to store SCRAM hashes (or something similar for non-scram methods) for all methods it does support. If the server operator later decides to not offer a specific SASL method anymore, they can delete the (hash) data stored for that method from their server.</p>
<p>Second, the server can only advertise those methods it has hashes for in its database. That means it needs to know the username before advertising which methods it supports. This requires a change in the protocol flow for mechanism negotiation, which is not codified in the SASL RFC and can be changed via XEP. A good candidate would be <a href="https://xmpp.org/extensions/xep-0388.html">XEP-0388: Extensible SASL Profile</a> (also dubbed SASL2) which is not yet in <code>Final</code> state and thus can be adjusted to our needs.</p>
<p>Let&rsquo;s assume a SASL2 protocol flow by advertising support for this protocol, but not simultaneously advertising which SASL methods the server supports. The client would then first send the desired username it wants to authenticate for, and the server would respond with a list of supported SASL mechanisms for exactly this user. The username is of course not safe from a MITM attacker, but it will be included in the SCRAM authentication flow and the server will fail the authentication if that user differs from the one given earlier.</p>
<p>An example protocol flow using a modified SASL2 might look as follows (resembling more or less a normal SCRAM flow):</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#75715e">&lt;!--
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  Server sends stream features indicating support for SASL2.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">--&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;stream:features&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;authentication</span> <span style="color:#a6e22e">xmlns=</span><span style="color:#e6db74">&#39;urn:xmpp:sasl:1&#39;</span><span style="color:#f92672">/&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;/stream:features&gt;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">&lt;!--
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  Client intiates authentication by sending the base64 encoded username it wishes to authenticate for.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">--&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;request</span> <span style="color:#a6e22e">xmlns=</span><span style="color:#e6db74">&#39;urn:xmpp:sasl:1&#39;</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;user&gt;</span>dXNlcg==<span style="color:#f92672">&lt;/user&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;/request&gt;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">&lt;!--
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  Server sends the list of supported mechanisms for this user.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  The sorted list will be &#39;SCRAM-SHA-1&lt;SCRAM-SHA-1_TLS-EXPORTER&lt;SCRAM-SHA-256&lt;SCRAM-SHA-256_TLS-EXPORTER&#39;,
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  the corresponding base64 encoded SHA-1 hash (SHA-1 will be used because negotiated below) is: &#39;U3vZANxXbl1pMOMBAFPnTb5YXWk=&#39;
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">--&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;mechanisms</span> <span style="color:#a6e22e">xmlns=</span><span style="color:#e6db74">&#39;urn:xmpp:sasl:1&#39;</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;mechanism&gt;</span>SCRAM-SHA-1<span style="color:#f92672">&lt;/mechanism&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;mechanism&gt;</span>SCRAM-SHA-1_TLS-EXPORTER<span style="color:#f92672">&lt;/mechanism&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;mechanism&gt;</span>SCRAM-SHA-256<span style="color:#f92672">&lt;/mechanism&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;mechanism&gt;</span>SCRAM-SHA-256_TLS-EXPORTER<span style="color:#f92672">&lt;/mechanism&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;/mechanisms&gt;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">&lt;!--
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  Client sends the selected mechanism alogside the initial-response data.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">--&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;authenticate</span> <span style="color:#a6e22e">xmlns=</span><span style="color:#e6db74">&#39;urn:xmpp:sasl:1&#39;</span> <span style="color:#a6e22e">mechanism=</span><span style="color:#e6db74">&#39;SCRAM-SHA-1_TLS-EXPORTER&#39;</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">&lt;!-- Base64 of: &#39;p=tls-exporter,,n=user,r=12C4CD5C-E38E-4A98-8F6D-15C38F51CCC6,d=U3vZANxXbl1pMOMBAFPnTb5YXWk=&#39; --&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;initial-response&gt;</span>cD10bHMtZXhwb3J0ZXIsLG49dXNlcixyPTEyQzRDRDVDLUUzOEUtNEE5OC04RjZELTE1QzM4RjUxQ0NDNixkPVUzdlpBTnhYYmwxcE1PTUJBRlBuVGI1WVhXaz0=<span style="color:#f92672">&lt;/initial-response&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;/authenticate&gt;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">&lt;!--
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  SCRAM-SHA-1 challenge issued by the server.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  Base64 of: &#39;r=12C4CD5C-E38E-4A98-8F6D-15C38F51CCC6a09117a6-ac50-4f2f-93f1-93799c2bddf6,s=QSXCR+Q6sek8bf92,i=4096&#39;
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">--&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;challenge</span> <span style="color:#a6e22e">xmlns=</span><span style="color:#e6db74">&#39;urn:xmpp:sasl:1&#39;</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>  cj0xMkM0Q0Q1Qy1FMzhFLTRBOTgtOEY2RC0xNUMzOEY1MUNDQzZhMDkxMTdhNi1hYzUwLTRmMmYtOTNmMS05Mzc5OWMyYmRkZjYscz1RU1hDUitRNnNlazhiZjkyLGk9NDA5Ng==
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;/challenge&gt;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">&lt;!--
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  The client responds with the base64 encoded client-final-message (password: &#39;pencil&#39;).
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  Base64 of: &#39;c=cD10bHMtZXhwb3J0ZXIsLMcoQvOdBDePd4OswlmAWV3dg1a1Wh1tYPTBwVid10VU,r=12C4CD5C-E38E-4A98-8F6D-15C38F51CCC6a09117a6-ac50-4f2f-93f1-93799c2bddf6,p=icrRuoQBB0htw5+K/6RNEDJ0Q4Y=&#39;
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  The c-attribute contains the GS2-header and channel-binding data blob (32 bytes).
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">--&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;response</span> <span style="color:#a6e22e">xmlns=</span><span style="color:#e6db74">&#39;urn:xmpp:sasl:1&#39;</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>  Yz1jRDEwYkhNdFpYaHdiM0owWlhJc0xNY29Rdk9kQkRlUGQ0T3N3bG1BV1YzZGcxYTFXaDF0WVBUQndWaWQxMFZVLHI9MTJDNENENUMtRTM4RS00QTk4LThGNkQtMTVDMzhGNTFDQ0M2YTA5MTE3YTYtYWM1MC00ZjJmLTkzZjEtOTM3OTljMmJkZGY2LHA9aWNyUnVvUUJCMGh0dzUrSy82Uk5FREowUTRZPQ==
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;/response&gt;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">&lt;!--
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  This completes, so the Server sends a success containing the base64 encoded server signature.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  A SASL2 success always includes the authorization identifier.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">--&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;success</span> <span style="color:#a6e22e">xmlns=</span><span style="color:#e6db74">&#39;urn:xmpp:sasl:1&#39;</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;authorization-identifier&gt;</span>user@example.org<span style="color:#f92672">&lt;/authorization-identifier&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">&lt;!-- Base64 of: &#39;v=Ax+ZEP5hf90z8+KnakwspK9mEhk=&#39; --&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;additional-data&gt;</span>
</span></span><span style="display:flex;"><span>    dj1BeCtaRVA1aGY5MHo4K0tuYWt3c3BLOW1FaGs9
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;/additional-data&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;/success&gt;</span>
</span></span></code></pre></div><h2 id="restoring-protocol-agility-for-sasl-methods-part-2">Restoring protocol agility for SASL methods part #2</h2>
<p>Activating a new SASL (SCRAM) method and saving new hashes for these methods for already known users on the server is a bit trickier. To solve this, the server offers new SASL mechanisms indicating that he allows for hash upgrades, if he doesn&rsquo;t have all required hashes in its database yet. The ordering of these new upgrade mechanisms should use a stable sorting algorithm. First sorting by perceived strength of the algorithm updated to, then by the percieved strength of the algorithm used for authentication (e.g. use the highest strength for authentication and upgrade to the highest strength possible with this authentication).</p>
<p>For reference, the SCRAM flow as stated in <a href="https://www.rfc-editor.org/rfc/rfc5802#section-3">RFC 5802 section 3</a> is as follows, with HMAC() and HASH() corresponding to the hash method used to authenticate (e.g. SHA-256 for SCRAM-SHA-256):</p>
<pre tabindex="0"><code>SaltedPassword  := Hi(Normalize(password), salt, i)
ClientKey       := HMAC(SaltedPassword, &#34;Client Key&#34;)
StoredKey       := H(ClientKey)
AuthMessage     := client-first-message-bare + &#34;,&#34; +
                   server-first-message + &#34;,&#34; +
                   client-final-message-without-proof
ClientSignature := HMAC(StoredKey, AuthMessage)
ClientProof     := ClientKey XOR ClientSignature
ServerKey       := HMAC(SaltedPassword, &#34;Server Key&#34;)
ServerSignature := HMAC(ServerKey, AuthMessage)
</code></pre><p>The <code>SaltedPassword</code> is the hash saved in the database on the server alongside the <code>salt</code>. Using additional SASL2 tasks we can now require the client to perform an additional task which consists of sending the <code>SaltedPassword</code> for the hash algorithm to upgrade to. The server just provides the required salt (that must be a new random value not equal to the one used for the old hash) and iteration count. By providing the salted hash <em>after</em> the successful completion of our SCRAM authentication, server and client can be sure to talk to the right one and when channel-binding is used, both can be sure no MITM is involved that could intercept the new <code>SaltedPassword</code>. I strongly suggest to only support password upgrades if channel-binding is used.</p>
<p>An example protocol flow using a modified SASL2 might look as follows (resembling more or less the SCRAM flow used in part #1 above and adding a second task for the desired hash upgrade):</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#75715e">&lt;!--
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  Server sends stream features indicating support for SASL2.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">--&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;stream:features&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;authentication</span> <span style="color:#a6e22e">xmlns=</span><span style="color:#e6db74">&#39;urn:xmpp:sasl:1&#39;</span><span style="color:#f92672">/&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;/stream:features&gt;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">&lt;!--
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  Client intiates authentication by sending the base64 encoded username it wishes to authenticate for.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">--&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;request</span> <span style="color:#a6e22e">xmlns=</span><span style="color:#e6db74">&#39;urn:xmpp:sasl:1&#39;</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;user&gt;</span>dXNlcg==<span style="color:#f92672">&lt;/user&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;/request&gt;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">&lt;!--
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  Server sends the list of supported mechanisms for this user.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  The sorted list will be &#39;SCRAM-SHA-1_TLS-EXPORTER&lt;SCRAM-SHA-256_TLS-EXPORTER&lt;UPGRADE-SCRAM-SHA-256_SCRAM-SHA-1&lt;UPGRADE-SCRAM-SHA-256_SCRAM-SHA-1_TLS-EXPORTER&#39;,
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  the corresponding base64 encoded SHA-1 hash (SHA-1 will be used because negotiated below) is: &#39;nKFUXQ7h9IL3eo17pKygmacnEsk=&#39;
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">--&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;mechanisms</span> <span style="color:#a6e22e">xmlns=</span><span style="color:#e6db74">&#39;urn:xmpp:sasl:1&#39;</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;mechanism&gt;</span>SCRAM-SHA-1<span style="color:#f92672">&lt;/mechanism&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;mechanism&gt;</span>SCRAM-SHA-1_TLS-EXPORTER<span style="color:#f92672">&lt;/mechanism&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;mechanism&gt;</span>UPGRADE-SCRAM-SHA-256_SCRAM-SHA-1<span style="color:#f92672">&lt;/mechanism&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;mechanism&gt;</span>UPGRADE-SCRAM-SHA-256_SCRAM-SHA-1_TLS-EXPORTER<span style="color:#f92672">&lt;/mechanism&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;/mechanisms&gt;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">&lt;!--
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  Client sends the selected mechanism alogside the initial-response data.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">--&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;authenticate</span> <span style="color:#a6e22e">xmlns=</span><span style="color:#e6db74">&#39;urn:xmpp:sasl:1&#39;</span> <span style="color:#a6e22e">mechanism=</span><span style="color:#e6db74">&#39;SCRAM-SHA-1_TLS-EXPORTER&#39;</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">&lt;!-- Base64 of: &#39;p=tls-exporter,,n=user,r=12C4CD5C-E38E-4A98-8F6D-15C38F51CCC6,d=nKFUXQ7h9IL3eo17pKygmacnEsk=&#39; --&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;initial-response&gt;</span>cD10bHMtZXhwb3J0ZXIsLG49dXNlcixyPTEyQzRDRDVDLUUzOEUtNEE5OC04RjZELTE1QzM4RjUxQ0NDNixkPVUzdlpBTnhYYmwxcE1PTUJBRlBuVGI1WVhXaz0=<span style="color:#f92672">&lt;/initial-response&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;/authenticate&gt;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">&lt;!--
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  SCRAM-SHA-1 challenge issued by the server.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  Base64 of: &#39;r=12C4CD5C-E38E-4A98-8F6D-15C38F51CCC6a09117a6-ac50-4f2f-93f1-93799c2bddf6,s=QSXCR+Q6sek8bf92,i=4096&#39;
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">--&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;challenge</span> <span style="color:#a6e22e">xmlns=</span><span style="color:#e6db74">&#39;urn:xmpp:sasl:1&#39;</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>  cj0xMkM0Q0Q1Qy1FMzhFLTRBOTgtOEY2RC0xNUMzOEY1MUNDQzZhMDkxMTdhNi1hYzUwLTRmMmYtOTNmMS05Mzc5OWMyYmRkZjYscz1RU1hDUitRNnNlazhiZjkyLGk9NDA5Ng==
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;/challenge&gt;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">&lt;!--
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  The client responds with the base64 encoded client-final-message (password: &#39;pencil&#39;).
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  Base64 of: &#39;c=cD10bHMtZXhwb3J0ZXIsLMcoQvOdBDePd4OswlmAWV3dg1a1Wh1tYPTBwVid10VU,r=12C4CD5C-E38E-4A98-8F6D-15C38F51CCC6a09117a6-ac50-4f2f-93f1-93799c2bddf6,p=UApo7xo6Pa9J+Vaejfz/dG7BomU=&#39;
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  The c-attribute contains the GS2-header and channel-binding data blob (32 bytes).
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">--&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;response</span> <span style="color:#a6e22e">xmlns=</span><span style="color:#e6db74">&#39;urn:xmpp:sasl:1&#39;</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>  Yz1jRDEwYkhNdFpYaHdiM0owWlhJc0xNY29Rdk9kQkRlUGQ0T3N3bG1BV1YzZGcxYTFXaDF0WVBUQndWaWQxMFZVLHI9MTJDNENENUMtRTM4RS00QTk4LThGNkQtMTVDMzhGNTFDQ0M2YTA5MTE3YTYtYWM1MC00ZjJmLTkzZjEtOTM3OTljMmJkZGY2LHA9VUFwbzd4bzZQYTlKK1ZhZWpmei9kRzdCb21VPQ==
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;/response&gt;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">&lt;!--
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  This completes, so the Server sends a continue containing the base64 encoded server signature and the upgrade task to perform.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">--&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;continue</span> <span style="color:#a6e22e">xmlns=</span><span style="color:#e6db74">&#39;urn:xmpp:sasl:1&#39;</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;authorization-identifier&gt;</span>user@example.org<span style="color:#f92672">&lt;/authorization-identifier&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">&lt;!-- Base64 of: &#39;msVHs/BzIOHDqXeVH7EmmDu9id8=&#39; --&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;additional-data&gt;</span>
</span></span><span style="display:flex;"><span>    dj1tc1ZIcy9CeklPSERxWGVWSDdFbW1EdTlpZDg9
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;/additional-data&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;tasks&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;task&gt;</span>UPGRADE-SCRAM-SHA-256<span style="color:#f92672">&lt;/task&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;/tasks&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;/continue&gt;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">&lt;!--
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  The client provides the SaltedPassword hash for SCRAM-SHA-256
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">--&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;next</span> <span style="color:#a6e22e">xmlns=</span><span style="color:#e6db74">&#39;urn:xmpp:sasl:1&#39;</span> <span style="color:#a6e22e">task=</span><span style="color:#e6db74">&#39;UPGRADE-SCRAM-SHA-256&#39;</span><span style="color:#f92672">/&gt;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">&lt;!--
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  The server sends the required salt and iteration count encoded as base64 encoded SASL attributes.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  Base64 of: &#39;s=A_SXCRXQ6sek8bf_Z,i=4096&#39;
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">--&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;challenge</span> <span style="color:#a6e22e">xmlns=</span><span style="color:#e6db74">&#39;urn:xmpp:sasl:1&#39;</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>  cz1BX1NYQ1JYUTZzZWs4YmZfWixpPTQwOTY=
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;/challenge&gt;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">&lt;!--
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  The client responds with the base64 encoded SaltedPassword.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">--&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;response</span> <span style="color:#a6e22e">xmlns=</span><span style="color:#e6db74">&#39;urn:xmpp:sasl:1&#39;</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>  BzOnw3Pc5H4bOLlPZ/8JAy6wnTpH05aH21KW2+Xfpaw=
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;/response&gt;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">&lt;!--
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  Finally, the server sends a success after adding the salted SHA-256 hash to it&#39;s database.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  A SASL2 success always includes the authorization identifier.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">--&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;success</span> <span style="color:#a6e22e">xmlns=</span><span style="color:#e6db74">&#39;urn:xmpp:sasl:1&#39;</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;authorization-identifier&gt;</span>user@example.org<span style="color:#f92672">&lt;/authorization-identifier&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;/success&gt;</span>
</span></span></code></pre></div><p>If the server needs to upgrade to multiple new SCRAM algorithms, he can do so one at a time on every new authentication. This is no &ldquo;do everything once&rdquo; anyways, because not every client might support every upgrade possible.</p>
<h1 id="conclusion">Conclusion</h1>
<p>To conclude this, we now identified several improvements to regain the properties listed in the beginning. These improvements can mainly be achieved by updating the SASL2 XEP (<a href="https://xmpp.org/extensions/xep-0388.html">XEP-0388: Extensible SASL Profile</a>). The downgrade prevention (the additional SCRAM attribute <code>d</code>) should possibly be published as RFC, but a XEP could suffice, too.</p>
<p>Feel free to comment on anything in here. I&rsquo;m always open to feedback and improvements. Just contact me at <a href="mailto:thilo@monal-im.org">thilo@monal-im.org</a>.</p>
]]></content:encoded></item><item><title>NLNet Funding</title><link>https://monal-im.org/post/00003-nlnet-funding/</link><pubDate>Sun, 11 Sep 2022 00:00:00 +0000</pubDate><guid>https://monal-im.org/post/00003-nlnet-funding/</guid><description>&lt;p&gt;We are pleased to announce that we got funding by the EU’s &lt;a href="https://nlnet.nl/assure/"&gt;NGI Assure via the NLnet Foundation&lt;/a&gt; to work on some important features in Monal.&lt;/p&gt;
&lt;p&gt;In short this consists of the following tasks (in no special order).&lt;/p&gt;
&lt;h3 id="1-implement-more-privacy-friendly-push-server"&gt;1. Implement more privacy-friendly push server&lt;/h3&gt;
&lt;p&gt;The current push appserver (&lt;a href="https://github.com/tmolitor-stud-tu/mod_push_appserver"&gt;https://github.com/tmolitor-stud-tu/mod_push_appserver&lt;/a&gt;) saves more data than strictly needed to perform its task, let’s change that. On top of that, a possible HA-setup and load balancing should be strived for.&lt;/p&gt;</description><content:encoded><![CDATA[<p>We are pleased to announce that we got funding by the EU’s <a href="https://nlnet.nl/assure/">NGI Assure via the NLnet Foundation</a> to work on some important features in Monal.</p>
<p>In short this consists of the following tasks (in no special order).</p>
<h3 id="1-implement-more-privacy-friendly-push-server">1. Implement more privacy-friendly push server</h3>
<p>The current push appserver (<a href="https://github.com/tmolitor-stud-tu/mod_push_appserver">https://github.com/tmolitor-stud-tu/mod_push_appserver</a>) saves more data than strictly needed to perform its task, let’s change that. On top of that, a possible HA-setup and load balancing should be strived for.</p>
<h3 id="2-implement-basic-audio-calls-using-webrtc">2. Implement basic Audio calls using WebRTC</h3>
<p>Include WebRTC library into our codebase and wire it up to allow for simple audio calls not involving XMPP (maybe send SDP data through a Monal specific non-standardized XMPP stanza to make this work without hardcoded ip and port).</p>
<p>This is to test Audio Calls in the field first before wiring them up using correct XMPP XEPs.</p>
<h3 id="3-implement-all-xeps-needed-for-audio-calls">3. Implement all XEPs needed for Audio Calls</h3>
<p>To make Audio Calls for XMPP work, we need proper XMPP integration. This wires up the stuff implemented in (2) into the XMPP layer by implementing the proper XEPs listed below. This will add support for 1:1 audio calls to Conversations, Dino and many more XMPP clients.</p>
<h3 id="4-implement-video-calls-using-webrtc">4. Implement Video calls using WebRTC</h3>
<p>On top of the work done in (2) and (3) we want to implement Video Call support as well. This will add support for 1:1 video calls to Conversations, Dino, and more.</p>
<h3 id="5-security-quickscan">5. Security quickscan</h3>
<p>We want a security quickscan performed by Radically Open Security and implement mitigations for problems found by them.</p>
<h3 id="6-implement-muc-ui-management-addremovepromote-users-etc">6. Implement MUC UI management (add/remove/promote users etc.)</h3>
<p>While Monal supports MUCs (multi user chats) in its flavours “channel” and “group”, the app is still lacking proper support for creating and managing group-type MUCs. We will implement that missing piece in this task.</p>
<h3 id="7-port-addcontact-ui-to-swiftui">7. Port addContact UI to SwiftUI</h3>
<p>The existing UI to add a contact or show pending contact requests is not user-friendly. We will therefore port it to SwiftUI. Once contacts can be added using the new UI, a UI for creating MUCs will be added. Monal will then support the creation of new private MUCs. Additionally, the existing functionality to scan contact QR-Codes and open contact links from other apps / iOS camera will be refactored. After the refactoring the user can preview the action and select an appropriate account before adding the contact.</p>
<h3 id="8-add-sasl-mechanism-upgrade-capability-to-xep-0388">8. Add SASL mechanism upgrade capability to XEP-0388</h3>
<p>XEP-0388 (“Extensible SASL Profile”) modernizes the old XMPP SASL profile defined in RFC 6120 and reduces round-trips. But neither the old SASL profile nor the new one (dubbed SASL2) solve the problem of SASL mechanism upgrades. A server that saves the hashed password for SCRAM-SHA-1 authentication has no way of upgrading to SCRAM-SHA-256. It does not know the cleartext password to calculate the hash to store itself and no way to ask the client for it. We want to take the opportunity and update the SASL2 XEP before it gets widely deployed to provide a way for a smooth upgrade path that allows the servers to store multiple hashes and get new hashes provided by clients that support the new algorithm without the need of ever knowing the cleartext password.</p>
<h3 id="9-implement-sasl2-in-monal-including-scram-sha1-sha256-and-sha512">9. Implement SASL2 in Monal (including SCRAM SHA1, SHA256 and SHA512)</h3>
<p>Implement the updated SASL2 XEP and the accompanying XEP-0440 (“SASL Channel-Binding Type Capability”) in Monal which serves as foundation for the implementation of XEP-0397 (“Instant Stream Resumption”).</p>
<h3 id="10-write-new-xep-for-downgrade-protection-of-channel-binding-types-and-sasl-mechanisms-and-implement-it">10. Write new XEP for downgrade protection of channel-binding types and SASL mechanisms and implement it</h3>
<p>A Man-In-The-Middle capable of impersonating the XMPP server on the TLS level can use SASL Mechanism
Stripping and/or strip channel-binding types to downgrade the security. Adding an optional SCRAM attribute
containing the hash of all server-advertised SASL mechanisms and channel-binding types as seen by the client
will enable the server to check if any downgrade took place and to abort the authentication, if so. Because the
SCRAM attribute will be part of the mutual authentication between client and server, a MITM will not be able to
forge it.</p>
]]></content:encoded></item><item><title>Monal IM - project moved</title><link>https://monal-im.org/post/00002-project-moved/</link><pubDate>Sat, 10 Sep 2022 00:00:00 +0000</pubDate><guid>https://monal-im.org/post/00002-project-moved/</guid><description>&lt;p&gt;We recently started to migrate the App from Anu Pokharel‘s Apple account to Thilo Molitor‘s Apple account.&lt;/p&gt;
&lt;p&gt;As part of this transition we also deployed some new push servers to not let an old retired developer pay for the infrastructure needed for Monal.&lt;/p&gt;
&lt;p&gt;Coming along with this transition from the old developer team to the new one is our new clean website at &lt;a href="https://monal-im.org/"&gt;https://monal-im.org/&lt;/a&gt;. From now on, the old blog at &lt;a href="https://monal.im/"&gt;https://monal.im/&lt;/a&gt; will not be used for Monal anymore.&lt;/p&gt;</description><content:encoded><![CDATA[<p>We recently started to migrate the App from Anu Pokharel‘s Apple account to Thilo Molitor‘s Apple account.</p>
<p>As part of this transition we also deployed some new push servers to not let an old retired developer pay for the infrastructure needed for Monal.</p>
<p>Coming along with this transition from the old developer team to the new one is our new clean website at <a href="https://monal-im.org/">https://monal-im.org/</a>. From now on, the old blog at <a href="https://monal.im/">https://monal.im/</a> will not be used for Monal anymore.</p>
<p>Many thanks to all users, contributors and followers so far.</p>
<p>Special thanks goes to Anu. Without him and his passion, Monal would not have been possible. He developed and maintained Monal for more than 10 years, always ensuring compatibility with the latest iOS releases.</p>
<p>When I (Thilo) gradually took over development, I was able to build upon an app with a decent codebase rather than writing my own app from scratch. That made it possible to improve Monal further while already being used by thousands of people. I can not stress enough how thankful I was and still am for all the work Anu put into the development of Monal.
Thank you, Anu, for your wonderful work towards a modern XMPP client for iOS and macOS!</p>
<p>Thilo, Friedrich, Anu</p>
]]></content:encoded></item><item><title>Supported XEPs</title><link>https://monal-im.org/supportedxeps/</link><pubDate>Sat, 12 Mar 2022 10:19:25 +0100</pubDate><guid>https://monal-im.org/supportedxeps/</guid><description>&lt;h2 id="implemented-xeps"&gt;Implemented XEPs&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;XEP&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;th&gt;Since&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0004.html"&gt;
XEP-0004: Data Forms
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;4.9&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0030.html"&gt;
XEP-0030: Service Discovery
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;4.6&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0045.html"&gt;
XEP-0045: Multi-User Chat
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;partial&lt;/td&gt;
&lt;td&gt;5.0&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0048.html"&gt;
XEP-0048: Bookmarks
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;5.0&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0054.html"&gt;
XEP-0054: vcard-temp
&lt;/a&gt;
&lt;br&gt;Implemented only for MUC profiles
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;5.0&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0059.html"&gt;
XEP-0059: Result Set Management
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;4.8&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0060.html"&gt;
XEP-0060: Publish-Subscribe
&lt;/a&gt;
&lt;br&gt;Used mainly for Pep
&lt;/td&gt;
&lt;td&gt;partial&lt;/td&gt;
&lt;td&gt;4.9&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0066.html"&gt;
XEP-0066: Out of Band Data
&lt;/a&gt;
&lt;br&gt;Used to mark XEP-0363 filetransfers only
&lt;/td&gt;
&lt;td&gt;partial&lt;/td&gt;
&lt;td&gt;4.9&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0077.html"&gt;
XEP-0077: In-Band Registration
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;partial&lt;/td&gt;
&lt;td&gt;4.7&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0084.html"&gt;
XEP-0084: User Avatar
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;4.9&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0085.html"&gt;
XEP-0085: Chat State Notifications
&lt;/a&gt;
&lt;br&gt;Only typing notifications, use XEP-0319 to publish interactions
&lt;/td&gt;
&lt;td&gt;partial&lt;/td&gt;
&lt;td&gt;4.7&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0092.html"&gt;
XEP-0092: Software Version
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;5.0&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0115.html"&gt;
XEP-0115: Entity Capabilities
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;4.7&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0153.html"&gt;
XEP-0153: vCard-Based Avatars
&lt;/a&gt;
&lt;br&gt;XEP-0153: vCard-Based Avatars (implemented only for MUC profiles)
&lt;/td&gt;
&lt;td&gt;partial&lt;/td&gt;
&lt;td&gt;5.0&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0162.html"&gt;
XEP-0162: Best Practices for Roster and Subscription Management
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;partial&lt;/td&gt;
&lt;td&gt;5.4&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0163.html"&gt;
XEP-0163: Personal Eventing Protocol
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;4.9&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0167.html"&gt;
XEP-0167: Jingle RTP Sessions
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;6.0&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0176.html"&gt;
XEP-0176: Jingle ICE-UDP Transport Method
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;6.0&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0172.html"&gt;
XEP-0172: User Nickname
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;4.9&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0184.html"&gt;
XEP-0184: Message Delivery Receipts
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;4.7&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0191.html"&gt;
XEP-0191: Blocking Command
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;5.0&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0198.html"&gt;
XEP-0198: Stream Management
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;4.6&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0199.html"&gt;
XEP-0199: XMPP Ping
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;4.7&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0215.html"&gt;
XEP-0215: External Service Discovery
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;6.0&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0223.html"&gt;
XEP-0223: Persistent Storage of Private Data via PubSub
&lt;/a&gt;
&lt;br&gt;XEP-0223: Persistent Storage of Private Data via PubSub
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;4.9&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0237.html"&gt;
XEP-0237: Roster Versioning
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;4.6&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0245.html"&gt;
XEP-0245: The /me Command
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;4.9&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0249.html"&gt;
XEP-0249: Direct MUC Invitations
&lt;/a&gt;
&lt;br&gt;XEP-0249: Direct MUC Invitations
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;5.0&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0280.html"&gt;
XEP-0280: Message Carbons
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;4.5&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0286.html"&gt;
XEP-0286: Mobile Considerations on LTE Networks
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;4.7&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0293.html"&gt;
XEP-0293: Jingle RTP Feedback Negotiation
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;6.0&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0294.html"&gt;
XEP-0294: Jingle RTP Header Extensions Negotiation
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;6.0&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0305.html"&gt;
XEP-0305: XMPP Quickstart
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;5.1.1&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0308.html"&gt;
XEP-0308: Last Message Correction
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;4.8&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0313.html"&gt;
XEP-0313: Message Archive Management
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;4.8&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0319.html"&gt;
XEP-0319: Last User Interaction in Presence
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;4.7&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0320.html"&gt;
XEP-0320: Use of DTLS-SRTP in Jingle Sessions
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;6.0&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0333.html"&gt;
XEP-0333: Displayed Markers
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;4.8&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0338.html"&gt;
XEP-0338: Jingle Grouping Framework
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;6.0&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0339.html"&gt;
XEP-0339: Source-Specific Media Attributes in Jingle
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;6.0&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0352.html"&gt;
XEP-0352: Client State Indication
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;4.7&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0353.html"&gt;
XEP-0353: Jingle Message Initiation
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;6.0&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0357.html"&gt;
XEP-0357: Push Notifications
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;4.8&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0359.html"&gt;
XEP-0359: Unique and Stable Stanza IDs
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;4.8&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0363.html"&gt;
XEP-0363: HTTP File Upload
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;4.9&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0368.html"&gt;
XEP-0368: SRV records for XMPP over TLS
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;4.6&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0379.html"&gt;
XEP-0379: Pre-Authenticated Roster Subscription
&lt;/a&gt;
&lt;br&gt;No automatic approval if server does not support subscription pre-approval; No checking of tokens, if server does not do so (XEP-0401)
&lt;/td&gt;
&lt;td&gt;partial&lt;/td&gt;
&lt;td&gt;4.9&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0380.html"&gt;
XEP-0380: Explicit Message Encryption
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;5.1&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0384.html"&gt;
XEP-0384: OMEMO Encryption
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;4.8&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0388.html"&gt;
XEP-0388: Extensible SASL Profile
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;6.0&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0392.html"&gt;
XEP-0392: Consistent Color Generation
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;5.1&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0398.html"&gt;
XEP-0398: User Avatar to vCard-Based Avatars Conversion
&lt;/a&gt;
&lt;br&gt;Used for MUC avatars
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;6.0&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0401.html"&gt;
XEP-0401: Ad-hoc Account Invitation Generation
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;6.0&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0402.html"&gt;
XEP-0402: PEP Native Bookmarks
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;5.4&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0410.html"&gt;
XEP-0410: MUC Self-Ping (Schrödinger&amp;#39;s Chat)
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;5.0&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0421.html"&gt;
XEP-0421: Occupant identifiers for semi-anonymous MUCs
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;6.4.1&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0423.html"&gt;
XEP-0423: XMPP Compliance Suites 2020
&lt;/a&gt;
&lt;br&gt;Check this XEP to see what&amp;#39;s missing
&lt;/td&gt;
&lt;td&gt;partial&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0424.html"&gt;
XEP-0424: Message Retraction
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;6.3&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0425.html"&gt;
XEP-0425: Moderated Message Retraction
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;6.3&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0440.html"&gt;
XEP-0440: SASL Channel-Binding Type Capability
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;6.0&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0441.html"&gt;
XEP-0441: Message Archive Management Preferences
&lt;/a&gt;
&lt;br&gt;Only to automatically turn on archiving if possible (setting: always)
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;4.8&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0445.html"&gt;
XEP-0445: Pre-Authenticated In-Band Registration
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;5.2&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0454.html"&gt;
XEP-0454: OMEMO Media sharing
&lt;/a&gt;
&lt;br&gt;No support for embedded thumbnails
&lt;/td&gt;
&lt;td&gt;partial&lt;/td&gt;
&lt;td&gt;5.0&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0474.html"&gt;
XEP-0474: SASL SCRAM Downgrade Protection
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;6.0&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0480.html"&gt;
XEP-0480: SASL Upgrade Tasks
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;6.0&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0490.html"&gt;
XEP-0490: Message Displayed Synchronization
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;complete&lt;/td&gt;
&lt;td&gt;6.3&lt;/td&gt;
&lt;tr&gt;
&lt;/table&gt;
&lt;h2 id="planned-xeps"&gt;Planned XEPs&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;XEP&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0158.html"&gt;
XEP-0158: CAPTCHA Forms
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;planned&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0374.html"&gt;
XEP-0374: OpenPGP for XMPP Instant Messaging
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;planned&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0386.html"&gt;
XEP-0386: Bind 2
&lt;/a&gt;
&lt;br&gt;XEP-0386: Bind 2.0
&lt;/td&gt;
&lt;td&gt;planned&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0420.html"&gt;
XEP-0420: Stanza Content Encryption
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;planned&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0158.html"&gt;
XEP-0158: CAPTCHA Forms
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;planned&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://xmpp.org/extensions/xep-0486.html"&gt;
XEP-0486: MUC Avatars
&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;planned&lt;/td&gt;
&lt;tr&gt;
&lt;/table&gt;</description><content:encoded><![CDATA[<h2 id="implemented-xeps">Implemented XEPs</h2>


<table>
    <thead>
        <tr>
            <th>XEP</th>
            <th>Status</th>
            <th>Since</th>
        </tr>
    </thead>
    
        
    
        
    
        
    
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0004.html">
                        
                        
                            XEP-0004: Data Forms
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>4.9</td>
            <tr>
        
    
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0030.html">
                        
                        
                            XEP-0030: Service Discovery
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>4.6</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0045.html">
                        
                        
                            XEP-0045: Multi-User Chat
                        
                    </a>
                    
                </td>
                <td>partial</td>
                <td>5.0</td>
            <tr>
        
    
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0048.html">
                        
                        
                            XEP-0048: Bookmarks
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>5.0</td>
            <tr>
        
    
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0054.html">
                        
                        
                            XEP-0054: vcard-temp
                        
                    </a>
                    
                        <br>Implemented only for MUC profiles
                    
                </td>
                <td>complete</td>
                <td>5.0</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0059.html">
                        
                        
                            XEP-0059: Result Set Management
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>4.8</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0060.html">
                        
                        
                            XEP-0060: Publish-Subscribe
                        
                    </a>
                    
                        <br>Used mainly for Pep
                    
                </td>
                <td>partial</td>
                <td>4.9</td>
            <tr>
        
    
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0066.html">
                        
                        
                            XEP-0066: Out of Band Data
                        
                    </a>
                    
                        <br>Used to mark XEP-0363 filetransfers only
                    
                </td>
                <td>partial</td>
                <td>4.9</td>
            <tr>
        
    
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0077.html">
                        
                        
                            XEP-0077: In-Band Registration
                        
                    </a>
                    
                </td>
                <td>partial</td>
                <td>4.7</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0084.html">
                        
                        
                            XEP-0084: User Avatar
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>4.9</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0085.html">
                        
                        
                            XEP-0085: Chat State Notifications
                        
                    </a>
                    
                        <br>Only typing notifications, use XEP-0319 to publish interactions
                    
                </td>
                <td>partial</td>
                <td>4.7</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0092.html">
                        
                        
                            XEP-0092: Software Version
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>5.0</td>
            <tr>
        
    
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0115.html">
                        
                        
                            XEP-0115: Entity Capabilities
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>4.7</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0153.html">
                        
                        
                            XEP-0153: vCard-Based Avatars
                        
                    </a>
                    
                        <br>XEP-0153: vCard-Based Avatars (implemented only for MUC profiles)
                    
                </td>
                <td>partial</td>
                <td>5.0</td>
            <tr>
        
    
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0162.html">
                        
                        
                            XEP-0162: Best Practices for Roster and Subscription Management
                        
                    </a>
                    
                </td>
                <td>partial</td>
                <td>5.4</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0163.html">
                        
                        
                            XEP-0163: Personal Eventing Protocol
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>4.9</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0167.html">
                        
                        
                            XEP-0167: Jingle RTP Sessions
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>6.0</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0176.html">
                        
                        
                            XEP-0176: Jingle ICE-UDP Transport Method
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>6.0</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0172.html">
                        
                        
                            XEP-0172: User Nickname
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>4.9</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0184.html">
                        
                        
                            XEP-0184: Message Delivery Receipts
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>4.7</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0191.html">
                        
                        
                            XEP-0191: Blocking Command
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>5.0</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0198.html">
                        
                        
                            XEP-0198: Stream Management
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>4.6</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0199.html">
                        
                        
                            XEP-0199: XMPP Ping
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>4.7</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0215.html">
                        
                        
                            XEP-0215: External Service Discovery
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>6.0</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0223.html">
                        
                        
                            XEP-0223: Persistent Storage of Private Data via PubSub
                        
                    </a>
                    
                        <br>XEP-0223: Persistent Storage of Private Data via PubSub
                    
                </td>
                <td>complete</td>
                <td>4.9</td>
            <tr>
        
    
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0237.html">
                        
                        
                            XEP-0237: Roster Versioning
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>4.6</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0245.html">
                        
                        
                            XEP-0245: The /me Command
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>4.9</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0249.html">
                        
                        
                            XEP-0249: Direct MUC Invitations
                        
                    </a>
                    
                        <br>XEP-0249: Direct MUC Invitations
                    
                </td>
                <td>complete</td>
                <td>5.0</td>
            <tr>
        
    
        
    
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0280.html">
                        
                        
                            XEP-0280: Message Carbons
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>4.5</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0286.html">
                        
                        
                            XEP-0286: Mobile Considerations on LTE Networks
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>4.7</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0293.html">
                        
                        
                            XEP-0293: Jingle RTP Feedback Negotiation
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>6.0</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0294.html">
                        
                        
                            XEP-0294: Jingle RTP Header Extensions Negotiation
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>6.0</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0305.html">
                        
                        
                            XEP-0305: XMPP Quickstart
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>5.1.1</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0308.html">
                        
                        
                            XEP-0308: Last Message Correction
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>4.8</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0313.html">
                        
                        
                            XEP-0313: Message Archive Management
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>4.8</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0319.html">
                        
                        
                            XEP-0319: Last User Interaction in Presence
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>4.7</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0320.html">
                        
                        
                            XEP-0320: Use of DTLS-SRTP in Jingle Sessions
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>6.0</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0333.html">
                        
                        
                            XEP-0333: Displayed Markers
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>4.8</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0338.html">
                        
                        
                            XEP-0338: Jingle Grouping Framework
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>6.0</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0339.html">
                        
                        
                            XEP-0339: Source-Specific Media Attributes in Jingle
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>6.0</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0352.html">
                        
                        
                            XEP-0352: Client State Indication
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>4.7</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0353.html">
                        
                        
                            XEP-0353: Jingle Message Initiation
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>6.0</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0357.html">
                        
                        
                            XEP-0357: Push Notifications
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>4.8</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0359.html">
                        
                        
                            XEP-0359: Unique and Stable Stanza IDs
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>4.8</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0363.html">
                        
                        
                            XEP-0363: HTTP File Upload
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>4.9</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0368.html">
                        
                        
                            XEP-0368: SRV records for XMPP over TLS
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>4.6</td>
            <tr>
        
    
        
    
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0379.html">
                        
                        
                            XEP-0379: Pre-Authenticated Roster Subscription
                        
                    </a>
                    
                        <br>No automatic approval if server does not support subscription pre-approval; No checking of tokens, if server does not do so (XEP-0401)
                    
                </td>
                <td>partial</td>
                <td>4.9</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0380.html">
                        
                        
                            XEP-0380: Explicit Message Encryption
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>5.1</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0384.html">
                        
                        
                            XEP-0384: OMEMO Encryption
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>4.8</td>
            <tr>
        
    
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0388.html">
                        
                        
                            XEP-0388: Extensible SASL Profile
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>6.0</td>
            <tr>
        
    
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0392.html">
                        
                        
                            XEP-0392: Consistent Color Generation
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>5.1</td>
            <tr>
        
    
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0398.html">
                        
                        
                            XEP-0398: User Avatar to vCard-Based Avatars Conversion
                        
                    </a>
                    
                        <br>Used for MUC avatars
                    
                </td>
                <td>complete</td>
                <td>6.0</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0401.html">
                        
                        
                            XEP-0401: Ad-hoc Account Invitation Generation
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>6.0</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0402.html">
                        
                        
                            XEP-0402: PEP Native Bookmarks
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>5.4</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0410.html">
                        
                        
                            XEP-0410: MUC Self-Ping (Schrödinger&#39;s Chat)
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>5.0</td>
            <tr>
        
    
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0421.html">
                        
                        
                            XEP-0421: Occupant identifiers for semi-anonymous MUCs
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>6.4.1</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0423.html">
                        
                        
                            XEP-0423: XMPP Compliance Suites 2020
                        
                    </a>
                    
                        <br>Check this XEP to see what&#39;s missing
                    
                </td>
                <td>partial</td>
                <td></td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0424.html">
                        
                        
                            XEP-0424: Message Retraction
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>6.3</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0425.html">
                        
                        
                            XEP-0425: Moderated Message Retraction
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>6.3</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0440.html">
                        
                        
                            XEP-0440: SASL Channel-Binding Type Capability
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>6.0</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0441.html">
                        
                        
                            XEP-0441: Message Archive Management Preferences
                        
                    </a>
                    
                        <br>Only to automatically turn on archiving if possible (setting: always)
                    
                </td>
                <td>complete</td>
                <td>4.8</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0445.html">
                        
                        
                            XEP-0445: Pre-Authenticated In-Band Registration
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>5.2</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0454.html">
                        
                        
                            XEP-0454: OMEMO Media sharing
                        
                    </a>
                    
                        <br>No support for embedded thumbnails
                    
                </td>
                <td>partial</td>
                <td>5.0</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0474.html">
                        
                        
                            XEP-0474: SASL SCRAM Downgrade Protection
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>6.0</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0480.html">
                        
                        
                            XEP-0480: SASL Upgrade Tasks
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>6.0</td>
            <tr>
        
    
        
    
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0490.html">
                        
                        
                            XEP-0490: Message Displayed Synchronization
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>6.3</td>
            <tr>
        
    
</table>


<h2 id="planned-xeps">Planned XEPs</h2>


<table>
    <thead>
        <tr>
            <th>XEP</th>
            <th>Status</th>
        </tr>
    </thead>
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0158.html">
                        
                        
                            XEP-0158: CAPTCHA Forms
                        
                    </a>
                    
                </td>
                <td>planned</td>
            <tr>
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0374.html">
                        
                        
                            XEP-0374: OpenPGP for XMPP Instant Messaging
                        
                    </a>
                    
                </td>
                <td>planned</td>
            <tr>
        
    
        
    
        
    
        
    
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0386.html">
                        
                        
                            XEP-0386: Bind 2
                        
                    </a>
                    
                        <br>XEP-0386: Bind 2.0
                    
                </td>
                <td>planned</td>
            <tr>
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0420.html">
                        
                        
                            XEP-0420: Stanza Content Encryption
                        
                    </a>
                    
                </td>
                <td>planned</td>
            <tr>
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0158.html">
                        
                        
                            XEP-0158: CAPTCHA Forms
                        
                    </a>
                    
                </td>
                <td>planned</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0486.html">
                        
                        
                            XEP-0486: MUC Avatars
                        
                    </a>
                    
                </td>
                <td>planned</td>
            <tr>
        
    
        
    
</table>


]]></content:encoded></item><item><title>Support</title><link>https://monal-im.org/support/</link><pubDate>Sat, 12 Mar 2022 10:01:54 +0100</pubDate><guid>https://monal-im.org/support/</guid><description>&lt;ul&gt;
&lt;li&gt;Monal Support Channel (XMPP MUC): &lt;a href="#ZgotmplZ"&gt;monal@chat.yax.im&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Github Tickets: &lt;a href="https://github.com/monal-im/Monal/issues"&gt;https://github.com/monal-im/Monal/issues&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Email: info[at]monal[minus]im[dot]org.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="donate"&gt;Donate&lt;/h2&gt;
&lt;p&gt;Monal is developed by volunteers and community collaboration. The work which has been done is usually not paid,
and the developers ask for donations to keep up service costs and development in the future!
Please consider giving a little back for the hard work which has been conducted.
Currently, there are three ways for financial support of the Monal development:&lt;/p&gt;</description><content:encoded><![CDATA[<ul>
<li>Monal Support Channel (XMPP MUC): <a href="#ZgotmplZ">monal@chat.yax.im</a></li>
<li>Github Tickets: <a href="https://github.com/monal-im/Monal/issues">https://github.com/monal-im/Monal/issues</a></li>
<li>Email: info[at]monal[minus]im[dot]org.</li>
</ul>
<h2 id="donate">Donate</h2>
<p>Monal is developed by volunteers and community collaboration. The work which has been done is usually not paid,
and the developers ask for donations to keep up service costs and development in the future!
Please consider giving a little back for the hard work which has been conducted.
Currently, there are three ways for financial support of the Monal development:</p>
<ul>
<li>Donate via <a href="https://github.com/sponsors/tmolitor-stud-tu">GitHub Sponsors</a></li>
<li>Donate via <a href="https://liberapay.com/tmolitor">Libera Pay</a></li>
<li>EU citizens can donate via SEPA, too. IBAN: DE66 5007 0371 0856 0419 01</li>
</ul>
<p>Here you can read about further <a href="https://github.com/monal-im/Monal/issues/363">support of the development</a>!</p>
<p>Find general information in the <a href="https://github.com/monal-im/Monal/wiki">Monal Wiki</a>.</p>
<h2 id="translations">Translations</h2>
<p>Translations of the app itself as well as the appstore description and even the changelog displayed
inside the appstore are hosted and managed via <a href="https://hosted.weblate.org/engage/monal/">Weblate</a>.<br>
Feel free to translate Monal to your language!</p>
<p><a href="https://hosted.weblate.org/engage/monal/?utm_source=widget">                                                


                                         
       
  <img src="https://monal-im.org/multi-auto_4983799081706151337.svg" title="Detailed translation status">   
</a></p>
<h2 id="reporting-a-vulnerability">Reporting a Vulnerability</h2>
<p>It is highly appreciated reporting a vulnerability to the Monal developers.
We ask you to not disclose it to the public until the vulnerability has been fixed.
This prevents abuse and exploitation in the current published releases.
Please report issues directly to info[at]monal[minus]im[dot]org.</p>
<p>Please try to report</p>
<ul>
<li>in detail what you are concerned about</li>
<li>if applicable, how to reproduce</li>
<li>your contact details, if the sending email is not enough.
That way we can ask questions back to you.</li>
</ul>
<p>You are also invited to make a recommendation on how to fix a potential security vulnerability.</p>
<p>Once a vulnerability has been announced and indicated we try our very best to provide a fix as soon as possible,
at its best within days. However, dependent on the potential issue it can take longer
if many code sections need to be changed.</p>
<p>Please be reminded that this is a non-commercial software project.</p>
<p>Thank you for considering reporting a security vulnerability.
This improves the quality of the app significantly.</p>
]]></content:encoded></item><item><title>Install</title><link>https://monal-im.org/install/</link><pubDate>Sat, 12 Mar 2022 08:09:44 +0100</pubDate><guid>https://monal-im.org/install/</guid><description>&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;iOS&lt;/th&gt;
&lt;th&gt;macOS&lt;/th&gt;
&lt;th&gt;macOS (homebrew)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Stable&lt;/td&gt;
&lt;td&gt;&lt;a href="https://apps.apple.com/app/id317711500"&gt;App Store&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://apps.apple.com/app/id1637078500"&gt;App Store&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;brew install --cask monal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Beta&lt;/td&gt;
&lt;td&gt;&lt;a href="https://testflight.apple.com/join/lLLlgHpB"&gt;Testflight Invitation&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://testflight.apple.com/join/tGH2m5vf"&gt;Testflight Invitation&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;brew install --cask monal@beta&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Alpha&lt;/td&gt;
&lt;td&gt;upon request to &lt;a href="mailto:info@monal-im.org"&gt;info@monal-im.org&lt;/a&gt;&lt;br&gt;Then download from our &lt;a href="https://downloads.monal-im.org/monal-im/alpha/"&gt;alpha download site&lt;/a&gt;&lt;br&gt;&lt;br&gt;You can get updates about alpha releases by joining this channel: &lt;a href="#ZgotmplZ"&gt;monal-alpha@chat.yax.im&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;brew tap monal-im/homebrew-monal-alpha&lt;br&gt;brew install --cask monal-alpha&lt;br&gt;&lt;br&gt;You can get updates about alpha releases by joining this channel: &lt;a href="#ZgotmplZ"&gt;monal-alpha@chat.yax.im&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h1 id="features"&gt;Features&lt;/h1&gt;
&lt;p&gt;Monal currently covers the following chat features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Decentralised and federated chat standard &lt;a href="https://xmpp.org/"&gt;XMPP&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Private and group messaging&lt;/li&gt;
&lt;li&gt;Privacy-respecting push notifications&lt;/li&gt;
&lt;li&gt;Encrypted private and group chats (state-of-the-art encryption (&lt;a href="https://conversations.im/omemo/"&gt;OMEMO&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Message history&lt;/li&gt;
&lt;li&gt;Free selection of your XMPP account provider&lt;/li&gt;
&lt;li&gt;Voice messaging&lt;/li&gt;
&lt;li&gt;Message archiving&lt;/li&gt;
&lt;li&gt;Upload of files, videos and images (HTTP Upload)&lt;/li&gt;
&lt;li&gt;Audio and Video calls&lt;/li&gt;
&lt;li&gt;Many settings and a design to offer privacy settings in the app to the need of the user&lt;/li&gt;
&lt;li&gt;A detailed and technical listing of your supported features (so called XMPP Extensions) can be found in our &lt;a href="https://github.com/monal-im/Monal/blob/develop/monal.doap"&gt;DOAP file&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="planned-features"&gt;Planned features&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;User-interface overhaul&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="implemented-xeps"&gt;Implemented XEPs&lt;/h2&gt;
&lt;p&gt;You can check the complete list of supported XEPs at &lt;a href="https://xmpp.org/software/monal-im/"&gt;&lt;a href="https://xmpp.org/software/monal-im/"&gt;https://xmpp.org/software/monal-im/&lt;/a&gt;&lt;/a&gt;&lt;/p&gt;</description><content:encoded><![CDATA[<table>
  <thead>
      <tr>
          <th></th>
          <th>iOS</th>
          <th>macOS</th>
          <th>macOS (homebrew)</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Stable</td>
          <td><a href="https://apps.apple.com/app/id317711500">App Store</a></td>
          <td><a href="https://apps.apple.com/app/id1637078500">App Store</a></td>
          <td>brew install --cask monal</td>
      </tr>
      <tr>
          <td>Beta</td>
          <td><a href="https://testflight.apple.com/join/lLLlgHpB">Testflight Invitation</a></td>
          <td><a href="https://testflight.apple.com/join/tGH2m5vf">Testflight Invitation</a></td>
          <td>brew install --cask monal@beta</td>
      </tr>
      <tr>
          <td>Alpha</td>
          <td>upon request to <a href="mailto:info@monal-im.org">info@monal-im.org</a><br>Then download from our <a href="https://downloads.monal-im.org/monal-im/alpha/">alpha download site</a><br><br>You can get updates about alpha releases by joining this channel: <a href="#ZgotmplZ">monal-alpha@chat.yax.im</a></td>
          <td></td>
          <td>brew tap monal-im/homebrew-monal-alpha<br>brew install --cask monal-alpha<br><br>You can get updates about alpha releases by joining this channel: <a href="#ZgotmplZ">monal-alpha@chat.yax.im</a></td>
      </tr>
  </tbody>
</table>
<h1 id="features">Features</h1>
<p>Monal currently covers the following chat features:</p>
<ul>
<li>Decentralised and federated chat standard <a href="https://xmpp.org/">XMPP</a></li>
<li>Private and group messaging</li>
<li>Privacy-respecting push notifications</li>
<li>Encrypted private and group chats (state-of-the-art encryption (<a href="https://conversations.im/omemo/">OMEMO</a>)</li>
<li>Message history</li>
<li>Free selection of your XMPP account provider</li>
<li>Voice messaging</li>
<li>Message archiving</li>
<li>Upload of files, videos and images (HTTP Upload)</li>
<li>Audio and Video calls</li>
<li>Many settings and a design to offer privacy settings in the app to the need of the user</li>
<li>A detailed and technical listing of your supported features (so called XMPP Extensions) can be found in our <a href="https://github.com/monal-im/Monal/blob/develop/monal.doap">DOAP file</a>.</li>
</ul>
<h2 id="planned-features">Planned features</h2>
<ul>
<li>User-interface overhaul</li>
</ul>
<h2 id="implemented-xeps">Implemented XEPs</h2>
<p>You can check the complete list of supported XEPs at <a href="https://xmpp.org/software/monal-im/"><a href="https://xmpp.org/software/monal-im/">https://xmpp.org/software/monal-im/</a></a></p>


<table>
    <thead>
        <tr>
            <th>XEP</th>
            <th>Status</th>
            <th>Since</th>
        </tr>
    </thead>
    
        
    
        
    
        
    
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0004.html">
                        
                        
                            XEP-0004: Data Forms
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>4.9</td>
            <tr>
        
    
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0030.html">
                        
                        
                            XEP-0030: Service Discovery
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>4.6</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0045.html">
                        
                        
                            XEP-0045: Multi-User Chat
                        
                    </a>
                    
                </td>
                <td>partial</td>
                <td>5.0</td>
            <tr>
        
    
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0048.html">
                        
                        
                            XEP-0048: Bookmarks
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>5.0</td>
            <tr>
        
    
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0054.html">
                        
                        
                            XEP-0054: vcard-temp
                        
                    </a>
                    
                        <br>Implemented only for MUC profiles
                    
                </td>
                <td>complete</td>
                <td>5.0</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0059.html">
                        
                        
                            XEP-0059: Result Set Management
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>4.8</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0060.html">
                        
                        
                            XEP-0060: Publish-Subscribe
                        
                    </a>
                    
                        <br>Used mainly for Pep
                    
                </td>
                <td>partial</td>
                <td>4.9</td>
            <tr>
        
    
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0066.html">
                        
                        
                            XEP-0066: Out of Band Data
                        
                    </a>
                    
                        <br>Used to mark XEP-0363 filetransfers only
                    
                </td>
                <td>partial</td>
                <td>4.9</td>
            <tr>
        
    
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0077.html">
                        
                        
                            XEP-0077: In-Band Registration
                        
                    </a>
                    
                </td>
                <td>partial</td>
                <td>4.7</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0084.html">
                        
                        
                            XEP-0084: User Avatar
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>4.9</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0085.html">
                        
                        
                            XEP-0085: Chat State Notifications
                        
                    </a>
                    
                        <br>Only typing notifications, use XEP-0319 to publish interactions
                    
                </td>
                <td>partial</td>
                <td>4.7</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0092.html">
                        
                        
                            XEP-0092: Software Version
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>5.0</td>
            <tr>
        
    
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0115.html">
                        
                        
                            XEP-0115: Entity Capabilities
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>4.7</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0153.html">
                        
                        
                            XEP-0153: vCard-Based Avatars
                        
                    </a>
                    
                        <br>XEP-0153: vCard-Based Avatars (implemented only for MUC profiles)
                    
                </td>
                <td>partial</td>
                <td>5.0</td>
            <tr>
        
    
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0162.html">
                        
                        
                            XEP-0162: Best Practices for Roster and Subscription Management
                        
                    </a>
                    
                </td>
                <td>partial</td>
                <td>5.4</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0163.html">
                        
                        
                            XEP-0163: Personal Eventing Protocol
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>4.9</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0167.html">
                        
                        
                            XEP-0167: Jingle RTP Sessions
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>6.0</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0176.html">
                        
                        
                            XEP-0176: Jingle ICE-UDP Transport Method
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>6.0</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0172.html">
                        
                        
                            XEP-0172: User Nickname
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>4.9</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0184.html">
                        
                        
                            XEP-0184: Message Delivery Receipts
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>4.7</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0191.html">
                        
                        
                            XEP-0191: Blocking Command
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>5.0</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0198.html">
                        
                        
                            XEP-0198: Stream Management
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>4.6</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0199.html">
                        
                        
                            XEP-0199: XMPP Ping
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>4.7</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0215.html">
                        
                        
                            XEP-0215: External Service Discovery
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>6.0</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0223.html">
                        
                        
                            XEP-0223: Persistent Storage of Private Data via PubSub
                        
                    </a>
                    
                        <br>XEP-0223: Persistent Storage of Private Data via PubSub
                    
                </td>
                <td>complete</td>
                <td>4.9</td>
            <tr>
        
    
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0237.html">
                        
                        
                            XEP-0237: Roster Versioning
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>4.6</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0245.html">
                        
                        
                            XEP-0245: The /me Command
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>4.9</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0249.html">
                        
                        
                            XEP-0249: Direct MUC Invitations
                        
                    </a>
                    
                        <br>XEP-0249: Direct MUC Invitations
                    
                </td>
                <td>complete</td>
                <td>5.0</td>
            <tr>
        
    
        
    
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0280.html">
                        
                        
                            XEP-0280: Message Carbons
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>4.5</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0286.html">
                        
                        
                            XEP-0286: Mobile Considerations on LTE Networks
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>4.7</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0293.html">
                        
                        
                            XEP-0293: Jingle RTP Feedback Negotiation
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>6.0</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0294.html">
                        
                        
                            XEP-0294: Jingle RTP Header Extensions Negotiation
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>6.0</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0305.html">
                        
                        
                            XEP-0305: XMPP Quickstart
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>5.1.1</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0308.html">
                        
                        
                            XEP-0308: Last Message Correction
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>4.8</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0313.html">
                        
                        
                            XEP-0313: Message Archive Management
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>4.8</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0319.html">
                        
                        
                            XEP-0319: Last User Interaction in Presence
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>4.7</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0320.html">
                        
                        
                            XEP-0320: Use of DTLS-SRTP in Jingle Sessions
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>6.0</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0333.html">
                        
                        
                            XEP-0333: Displayed Markers
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>4.8</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0338.html">
                        
                        
                            XEP-0338: Jingle Grouping Framework
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>6.0</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0339.html">
                        
                        
                            XEP-0339: Source-Specific Media Attributes in Jingle
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>6.0</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0352.html">
                        
                        
                            XEP-0352: Client State Indication
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>4.7</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0353.html">
                        
                        
                            XEP-0353: Jingle Message Initiation
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>6.0</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0357.html">
                        
                        
                            XEP-0357: Push Notifications
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>4.8</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0359.html">
                        
                        
                            XEP-0359: Unique and Stable Stanza IDs
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>4.8</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0363.html">
                        
                        
                            XEP-0363: HTTP File Upload
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>4.9</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0368.html">
                        
                        
                            XEP-0368: SRV records for XMPP over TLS
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>4.6</td>
            <tr>
        
    
        
    
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0379.html">
                        
                        
                            XEP-0379: Pre-Authenticated Roster Subscription
                        
                    </a>
                    
                        <br>No automatic approval if server does not support subscription pre-approval; No checking of tokens, if server does not do so (XEP-0401)
                    
                </td>
                <td>partial</td>
                <td>4.9</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0380.html">
                        
                        
                            XEP-0380: Explicit Message Encryption
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>5.1</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0384.html">
                        
                        
                            XEP-0384: OMEMO Encryption
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>4.8</td>
            <tr>
        
    
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0388.html">
                        
                        
                            XEP-0388: Extensible SASL Profile
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>6.0</td>
            <tr>
        
    
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0392.html">
                        
                        
                            XEP-0392: Consistent Color Generation
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>5.1</td>
            <tr>
        
    
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0398.html">
                        
                        
                            XEP-0398: User Avatar to vCard-Based Avatars Conversion
                        
                    </a>
                    
                        <br>Used for MUC avatars
                    
                </td>
                <td>complete</td>
                <td>6.0</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0401.html">
                        
                        
                            XEP-0401: Ad-hoc Account Invitation Generation
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>6.0</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0402.html">
                        
                        
                            XEP-0402: PEP Native Bookmarks
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>5.4</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0410.html">
                        
                        
                            XEP-0410: MUC Self-Ping (Schrödinger&#39;s Chat)
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>5.0</td>
            <tr>
        
    
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0421.html">
                        
                        
                            XEP-0421: Occupant identifiers for semi-anonymous MUCs
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>6.4.1</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0423.html">
                        
                        
                            XEP-0423: XMPP Compliance Suites 2020
                        
                    </a>
                    
                        <br>Check this XEP to see what&#39;s missing
                    
                </td>
                <td>partial</td>
                <td></td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0424.html">
                        
                        
                            XEP-0424: Message Retraction
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>6.3</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0425.html">
                        
                        
                            XEP-0425: Moderated Message Retraction
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>6.3</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0440.html">
                        
                        
                            XEP-0440: SASL Channel-Binding Type Capability
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>6.0</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0441.html">
                        
                        
                            XEP-0441: Message Archive Management Preferences
                        
                    </a>
                    
                        <br>Only to automatically turn on archiving if possible (setting: always)
                    
                </td>
                <td>complete</td>
                <td>4.8</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0445.html">
                        
                        
                            XEP-0445: Pre-Authenticated In-Band Registration
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>5.2</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0454.html">
                        
                        
                            XEP-0454: OMEMO Media sharing
                        
                    </a>
                    
                        <br>No support for embedded thumbnails
                    
                </td>
                <td>partial</td>
                <td>5.0</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0474.html">
                        
                        
                            XEP-0474: SASL SCRAM Downgrade Protection
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>6.0</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0480.html">
                        
                        
                            XEP-0480: SASL Upgrade Tasks
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>6.0</td>
            <tr>
        
    
        
    
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0490.html">
                        
                        
                            XEP-0490: Message Displayed Synchronization
                        
                    </a>
                    
                </td>
                <td>complete</td>
                <td>6.3</td>
            <tr>
        
    
</table>


<h2 id="planned-xeps">Planned XEPs</h2>


<table>
    <thead>
        <tr>
            <th>XEP</th>
            <th>Status</th>
        </tr>
    </thead>
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0158.html">
                        
                        
                            XEP-0158: CAPTCHA Forms
                        
                    </a>
                    
                </td>
                <td>planned</td>
            <tr>
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0374.html">
                        
                        
                            XEP-0374: OpenPGP for XMPP Instant Messaging
                        
                    </a>
                    
                </td>
                <td>planned</td>
            <tr>
        
    
        
    
        
    
        
    
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0386.html">
                        
                        
                            XEP-0386: Bind 2
                        
                    </a>
                    
                        <br>XEP-0386: Bind 2.0
                    
                </td>
                <td>planned</td>
            <tr>
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0420.html">
                        
                        
                            XEP-0420: Stanza Content Encryption
                        
                    </a>
                    
                </td>
                <td>planned</td>
            <tr>
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0158.html">
                        
                        
                            XEP-0158: CAPTCHA Forms
                        
                    </a>
                    
                </td>
                <td>planned</td>
            <tr>
        
    
        
            <tr>
                <td>
                    <a href="https://xmpp.org/extensions/xep-0486.html">
                        
                        
                            XEP-0486: MUC Avatars
                        
                    </a>
                    
                </td>
                <td>planned</td>
            <tr>
        
    
        
    
</table>


]]></content:encoded></item><item><title>Privacy</title><link>https://monal-im.org/privacy/</link><pubDate>Sat, 12 Mar 2022 08:08:57 +0100</pubDate><guid>https://monal-im.org/privacy/</guid><description>&lt;p&gt;&lt;strong&gt;Monal Website&lt;/strong&gt;&lt;br&gt;
You can find our latest privacy policy for our website here: &lt;a href="https://monal-im.org/privacyarchive/monal_website/" title="Website Privacy Policy"&gt;Website Privacy Policy&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Monal App&lt;/strong&gt;&lt;br&gt;
Our privacy policy may differ between app versions.
Before reading our privacy policy for our App you first need to find out the Monal version that you are using. &lt;br&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How to find out your Monal version&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;Open Monal&lt;/li&gt;
&lt;li&gt;Open up the settings menu in the upper left corner (gearwheel)&lt;/li&gt;
&lt;li&gt;Scroll down to the last entry &amp;ldquo;version&amp;rdquo;&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Monal App Privacy Policies&lt;/strong&gt;&lt;/p&gt;</description><content:encoded><![CDATA[
<p><strong>Monal Website</strong><br>
You can find our latest privacy policy for our website here: <a href="/privacyarchive/monal_website/" title="Website Privacy Policy">Website Privacy Policy</a></p>
<p><strong>Monal App</strong><br>
Our privacy policy may differ between app versions.
Before reading our privacy policy for our App you first need to find out the Monal version that you are using. <br></p>
<p><strong>How to find out your Monal version</strong></p>
<blockquote>
<ol>
<li>Open Monal</li>
<li>Open up the settings menu in the upper left corner (gearwheel)</li>
<li>Scroll down to the last entry &ldquo;version&rdquo;</li>
</ol>
</blockquote>
<p><strong>Monal App Privacy Policies</strong></p>
<table>
  <thead>
      <tr>
          <th>Releases</th>
          <th>Privacy Policy</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>6.0 and newer</td>
          <td><a href="/privacyarchive/monal_app_rev_003/" title="Privacy Policy Rev 003">Privacy Policy Rev 003</a></td>
      </tr>
      <tr>
          <td>5.2.0 up to 5.4.x</td>
          <td><a href="/privacyarchive/monal_app_rev_002/" title="Privacy Policy Rev 002">Privacy Policy Rev 002</a></td>
      </tr>
      <tr>
          <td>before 5.2.0</td>
          <td><a href="/privacyarchive/monal_app_rev_001/" title="Privacy Policy Rev 001">Privacy Policy Rev 001</a></td>
      </tr>
  </tbody>
</table>

]]></content:encoded></item><item><title>Privacy Monal App &lt; 5.2.0</title><link>https://monal-im.org/privacyarchive/monal_app_rev_001/</link><pubDate>Sat, 12 Mar 2022 08:08:57 +0100</pubDate><guid>https://monal-im.org/privacyarchive/monal_app_rev_001/</guid><description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Monal Website&lt;/strong&gt;&lt;br&gt;
You can find our latest privacy policy for our website here: &lt;a href="https://monal-im.org/privacyarchive/monal_website/" title="Website Privacy Policy"&gt;Website Privacy Policy&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Monal App&lt;/strong&gt;&lt;br&gt;
Our privacy policy may differ between app versions.
Before reading our privacy policy for our App you first need to find out the Monal version that you are using. &lt;br&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How to find out your Monal version&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;Open Monal&lt;/li&gt;
&lt;li&gt;Open up the settings menu in the upper left corner (gearwheel)&lt;/li&gt;
&lt;li&gt;Scroll down to the last entry &amp;ldquo;version&amp;rdquo;&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Monal App Privacy Policies&lt;/strong&gt;&lt;/p&gt;</description><content:encoded><![CDATA[<blockquote>

<p><strong>Monal Website</strong><br>
You can find our latest privacy policy for our website here: <a href="/privacyarchive/monal_website/" title="Website Privacy Policy">Website Privacy Policy</a></p>
<p><strong>Monal App</strong><br>
Our privacy policy may differ between app versions.
Before reading our privacy policy for our App you first need to find out the Monal version that you are using. <br></p>
<p><strong>How to find out your Monal version</strong></p>
<blockquote>
<ol>
<li>Open Monal</li>
<li>Open up the settings menu in the upper left corner (gearwheel)</li>
<li>Scroll down to the last entry &ldquo;version&rdquo;</li>
</ol>
</blockquote>
<p><strong>Monal App Privacy Policies</strong></p>
<table>
  <thead>
      <tr>
          <th>Releases</th>
          <th>Privacy Policy</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>6.0 and newer</td>
          <td><a href="/privacyarchive/monal_app_rev_003/" title="Privacy Policy Rev 003">Privacy Policy Rev 003</a></td>
      </tr>
      <tr>
          <td>5.2.0 up to 5.4.x</td>
          <td><a href="/privacyarchive/monal_app_rev_002/" title="Privacy Policy Rev 002">Privacy Policy Rev 002</a></td>
      </tr>
      <tr>
          <td>before 5.2.0</td>
          <td><a href="/privacyarchive/monal_app_rev_001/" title="Privacy Policy Rev 001">Privacy Policy Rev 001</a></td>
      </tr>
  </tbody>
</table>

</blockquote>
<h1 id="privacy-monal-app--520">Privacy Monal App &lt; 5.2.0</h1>
<p>Monal for iOS and macOS will register for APNS push notifications via a server to server (s2s) connection from your XMPP server to our push server.
Your XMPP JID alongside with a push identifier and secret token from Apple, that is only valid for this app, will be saved and logged in the push-server logs.
We do not intend to track you.
All server logs are purged every two weeks.
Our logs allow us to see the following details:</p>
<ul>
<li>Your JID (including your server’s hostname)</li>
<li>Time when you register for push notifications</li>
<li>Your apple push node and push token that was generated for Monal by Apple</li>
<li>Time when your XMPP server triggered a push notification to your Monal device</li>
</ul>
<p>To fulfill its duty, our push server has to hold some information associated with an Apple push token, until Apple marks the token a deleted, which usually means you have uninstalled the app (Info: Apple confirms if a token is still valid on every push).
In detail these information consists of:</p>
<ul>
<li>The Apple push token</li>
<li>The timestamp of the last push error</li>
<li>The timestamp of the last successful push</li>
<li>The timestamp of the registration of your device with Monal’s push-server</li>
<li>The timestamp when the registration was renewed</li>
<li>A random UUID identifying your device</li>
<li>A random secret used by your XMPP server to authenticate a push</li>
</ul>
<h4 id="push-server-locations">Push server locations</h4>
<table>
  <thead>
      <tr>
          <th>Name</th>
          <th>Hoster</th>
          <th>Location</th>
          <th>Notice</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>ios13push.monal.im</td>
          <td>AWS</td>
          <td>US</td>
          <td>Provided by Anurodh Pokharel<br>IPv4 only</td>
      </tr>
      <tr>
          <td>push.monal.im</td>
          <td>AWS</td>
          <td>US</td>
          <td>Provided by Anurodh Pokharel<br>IPv4 only<br>iOS 12 only</td>
      </tr>
  </tbody>
</table>
<h3 id="crash-reports-and-app-usage">Crash reports and app usage</h3>
<p>Monal does track crashes and usage data anonymously using the tools provided by Apple.
This is opt-in only and controlled by iOS and macOS global settings.
If a user decides not to send any data to developers, no crash logs are sent to Monal developers.</p>
<h3 id="logs">Logs</h3>
<p>Your local device will contain a log file with all sent and received raw XMPP messages as well as debug logs.
It does contain sensitive personal data! This file will never be transferred to us, except if you explicitly (manually) send it to us (e.g. via mail).</p>
<h3 id="gdpr-subject-access-requests-sar">GDPR Subject Access Requests (SAR)</h3>
<p>European GDPR allows users to request a copy of all data retained about them.
Please send GDPR requests to <a href="mailto:info@monal-im.org">info@monal-im.org</a>.
As by GDPR we need to validate your JID before answering to your inquiry.
Therefore, we will provide you a JID you must send a confirmation to, before we can answer your request and send you all retained data related to your JID.</p>
]]></content:encoded></item><item><title>Privacy Monal App 5.2.0 - 5.4.x</title><link>https://monal-im.org/privacyarchive/monal_app_rev_002/</link><pubDate>Sat, 12 Mar 2022 08:08:57 +0100</pubDate><guid>https://monal-im.org/privacyarchive/monal_app_rev_002/</guid><description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Monal Website&lt;/strong&gt;&lt;br&gt;
You can find our latest privacy policy for our website here: &lt;a href="https://monal-im.org/privacyarchive/monal_website/" title="Website Privacy Policy"&gt;Website Privacy Policy&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Monal App&lt;/strong&gt;&lt;br&gt;
Our privacy policy may differ between app versions.
Before reading our privacy policy for our App you first need to find out the Monal version that you are using. &lt;br&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How to find out your Monal version&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;Open Monal&lt;/li&gt;
&lt;li&gt;Open up the settings menu in the upper left corner (gearwheel)&lt;/li&gt;
&lt;li&gt;Scroll down to the last entry &amp;ldquo;version&amp;rdquo;&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Monal App Privacy Policies&lt;/strong&gt;&lt;/p&gt;</description><content:encoded><![CDATA[<blockquote>

<p><strong>Monal Website</strong><br>
You can find our latest privacy policy for our website here: <a href="/privacyarchive/monal_website/" title="Website Privacy Policy">Website Privacy Policy</a></p>
<p><strong>Monal App</strong><br>
Our privacy policy may differ between app versions.
Before reading our privacy policy for our App you first need to find out the Monal version that you are using. <br></p>
<p><strong>How to find out your Monal version</strong></p>
<blockquote>
<ol>
<li>Open Monal</li>
<li>Open up the settings menu in the upper left corner (gearwheel)</li>
<li>Scroll down to the last entry &ldquo;version&rdquo;</li>
</ol>
</blockquote>
<p><strong>Monal App Privacy Policies</strong></p>
<table>
  <thead>
      <tr>
          <th>Releases</th>
          <th>Privacy Policy</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>6.0 and newer</td>
          <td><a href="/privacyarchive/monal_app_rev_003/" title="Privacy Policy Rev 003">Privacy Policy Rev 003</a></td>
      </tr>
      <tr>
          <td>5.2.0 up to 5.4.x</td>
          <td><a href="/privacyarchive/monal_app_rev_002/" title="Privacy Policy Rev 002">Privacy Policy Rev 002</a></td>
      </tr>
      <tr>
          <td>before 5.2.0</td>
          <td><a href="/privacyarchive/monal_app_rev_001/" title="Privacy Policy Rev 001">Privacy Policy Rev 001</a></td>
      </tr>
  </tbody>
</table>

</blockquote>
<h1 id="privacy-monal-app-520---54x">Privacy Monal App 5.2.0 - 5.4.x</h1>
<p>App Resources are very limited on iOS and macOS.
Monal for example can only run a limited time in the background after a user either locked the screen or switched the app.
Hence, apps can not simply keep a connection to your xmpp server open 24/7 to inform you about new messages.
To overcome these limitations your XMPP-Server can can request our push server to send push messages to Apple.
With these push messages we can request Apple to wake up the app on your phone.
Once it is woken up it has about 30 seconds to connect to your XMPP server, fetch all new messages and show a push notification for these new messages.</p>
<h2 id="how-push-works">How push works</h2>
<p>Every time that Monal logins at your XMPP servers, it requests your server to inform us once your received an XMPP message while Monal was closed.
We therefore requests a Monal specific push token from Apple.
Using this Monal specific push token our push server can send push messages via Apples push system to wake up the app on your device.</p>
<p>Once push messages are enabled for your Monal instance on your XMPP servers, your XMPP servers will open a encrypted server to server (s2s) connection to one of our push servers.
Using this s2s connection your XMPP servers will then request our push servers to wake up Monal every time that new messages should be processed.
To wake up your instance your XMPP servers send us:</p>
<ul>
<li>your unique Monal specific push token that was generated by Apple</li>
<li>the domain of the XMPP server that you are using.</li>
</ul>
<h2 id="push">Push</h2>
<ul>
<li>We <strong>never</strong> see your messages.</li>
<li>We <strong>do not</strong> know who you are chatting with.</li>
<li>We could <strong>only</strong> ever track what XMPP domains a push token is/was using.</li>
<li>We <strong>can not</strong> identify a user.</li>
</ul>
<h3 id="push-servers">Push-Servers</h3>
<p>We provide two independent push server regions at the moment: Europe and US.
By default, each device will choose our Europe based push region unless the device local is set to the US.</p>
<h3 id="how-to-change-the-push-region">How to change the push region</h3>
<blockquote>
<ol>
<li>Open Monal</li>
<li>Open up the settings menu in the upper left corner (gearwheel)</li>
<li>Open the Notifications menu</li>
<li>Scroll down</li>
<li>Select a region</li>
</ol>
</blockquote>
<h3 id="push-server-regions">Push server regions</h3>
<p>If you are an XMPP server administrator, and you restricted s2s connections, please allow s2s to all our regions.</p>
<table>
  <thead>
      <tr>
          <th>Region</th>
          <th>Hostname</th>
          <th>Notice</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Europe</td>
          <td>eu.prod.push.monal-im.org</td>
          <td></td>
      </tr>
      <tr>
          <td>US</td>
          <td>us.prod.push.monal-im.org</td>
          <td></td>
      </tr>
  </tbody>
</table>
<h3 id="push-server-locations">Push server locations</h3>
<table>
  <thead>
      <tr>
          <th>Name</th>
          <th>Region</th>
          <th>Hoster</th>
          <th>Location</th>
          <th>Notice</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>s1.eu.prod.push.monal-im.org</td>
          <td>Europe</td>
          <td>Hetzner</td>
          <td>Finland</td>
          <td></td>
      </tr>
      <tr>
          <td>s2.eu.prod.push.monal-im.org</td>
          <td>Europe</td>
          <td>PHP-Friends</td>
          <td>Germany</td>
          <td></td>
      </tr>
      <tr>
          <td>s1.us.prod.push.monal-im.org</td>
          <td>US</td>
          <td>Fosshost</td>
          <td>US</td>
          <td>IPv4 only</td>
      </tr>
      <tr>
          <td>s2.us.prod.push.monal-im.org</td>
          <td>US</td>
          <td>Fosshost</td>
          <td>US</td>
          <td></td>
      </tr>
  </tbody>
</table>
<h2 id="crash-reports-and-app-usage">Crash reports and app usage</h2>
<p>Monal does track crashes and usage data anonymously using the tools provided by Apple.
This is opt-in only and controlled by iOS and macOS global settings.
If a user decides not to send any data to developers, no crash logs are sent to Monal developers.</p>
<h2 id="logs">Logs</h2>
<p>Your local device will contain a log file with all sent and received raw XMPP messages as well as debug logs.
It does contain sensitive personal data!
This file will never be transferred to us, except if you explicitly (manually) send it to us (e.g. via mail).</p>
<h2 id="gdpr-subject-access-requests-sar">GDPR Subject Access Requests (SAR)</h2>
<p>European GDPR allows users to request a copy of all data retained about them. Starting with Monal 5.2.0 we no longer see your JIDs (<a href="mailto:username@domain.tld">username@domain.tld</a>) in our push servers.
We therefore are not able to send you retained data related to your JID.
We furthermore are unable to provide your retained data related to your unique push token because we have no way to verify that Apple issued you a provided token.
If you have questions regarding GDPR, please send us a mail to <a href="mailto:info@monal-im.org">info@monal-im.org</a>.</p>
]]></content:encoded></item><item><title>Privacy Website</title><link>https://monal-im.org/privacyarchive/monal_website/</link><pubDate>Sat, 12 Mar 2022 08:08:57 +0100</pubDate><guid>https://monal-im.org/privacyarchive/monal_website/</guid><description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Monal Website&lt;/strong&gt;&lt;br&gt;
You can find our latest privacy policy for our website here: &lt;a href="https://monal-im.org/privacyarchive/monal_website/" title="Website Privacy Policy"&gt;Website Privacy Policy&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Monal App&lt;/strong&gt;&lt;br&gt;
Our privacy policy may differ between app versions.
Before reading our privacy policy for our App you first need to find out the Monal version that you are using. &lt;br&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How to find out your Monal version&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;Open Monal&lt;/li&gt;
&lt;li&gt;Open up the settings menu in the upper left corner (gearwheel)&lt;/li&gt;
&lt;li&gt;Scroll down to the last entry &amp;ldquo;version&amp;rdquo;&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Monal App Privacy Policies&lt;/strong&gt;&lt;/p&gt;</description><content:encoded><![CDATA[<blockquote>

<p><strong>Monal Website</strong><br>
You can find our latest privacy policy for our website here: <a href="/privacyarchive/monal_website/" title="Website Privacy Policy">Website Privacy Policy</a></p>
<p><strong>Monal App</strong><br>
Our privacy policy may differ between app versions.
Before reading our privacy policy for our App you first need to find out the Monal version that you are using. <br></p>
<p><strong>How to find out your Monal version</strong></p>
<blockquote>
<ol>
<li>Open Monal</li>
<li>Open up the settings menu in the upper left corner (gearwheel)</li>
<li>Scroll down to the last entry &ldquo;version&rdquo;</li>
</ol>
</blockquote>
<p><strong>Monal App Privacy Policies</strong></p>
<table>
  <thead>
      <tr>
          <th>Releases</th>
          <th>Privacy Policy</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>6.0 and newer</td>
          <td><a href="/privacyarchive/monal_app_rev_003/" title="Privacy Policy Rev 003">Privacy Policy Rev 003</a></td>
      </tr>
      <tr>
          <td>5.2.0 up to 5.4.x</td>
          <td><a href="/privacyarchive/monal_app_rev_002/" title="Privacy Policy Rev 002">Privacy Policy Rev 002</a></td>
      </tr>
      <tr>
          <td>before 5.2.0</td>
          <td><a href="/privacyarchive/monal_app_rev_001/" title="Privacy Policy Rev 001">Privacy Policy Rev 001</a></td>
      </tr>
  </tbody>
</table>

</blockquote>
<h1 id="website-privacy">Website Privacy</h1>
<p>A user’s IP address will be logged in the HTTP server logs.
All server logs are purged every two weeks and there isn’t any way for us to associate this information with any particular individual.
Our websites do not use or need any cookies. And of course it doesn&rsquo;t use any third party/external (JS-CSS-Font) dependencies.</p>
]]></content:encoded></item><item><title>Insights Into Monal Development</title><link>https://monal-im.org/post/00001-monal-development/</link><pubDate>Mon, 07 Mar 2022 00:00:00 +0000</pubDate><guid>https://monal-im.org/post/00001-monal-development/</guid><description>&lt;blockquote&gt;
&lt;p&gt;TLDR:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Info: Monal will stop support for iOS 12, iOS 13 and macOS Catalina!&lt;br&gt;
We are searching for a SwiftUI developer.&lt;br&gt;
We need a new simplified website.&lt;br&gt;
With better continuous funding, our push servers will move from the US to Europe.&lt;br&gt;
We have a new support mail: info@monal-im.org&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Two years ago we decided to rewrite the Monal app almost entirely and improve it gradually in the process, instead of creating another XMPP Client for iOS and macOS. We successfully managed to transform Monal from an app that had flaws and issues with many functions to a level that promotes a user-friendly experience with working features such as push notification, group chat, and partially end-to-end encryption support (OMEMO). If you are selecting an XMPP client for Apple systems we think that Monal is a great choice nowadays. We have been investing more than a thousand hours and worked hard to overcome all the flaws, the legacy app had. We invite you to give the recent beta a try!&lt;/p&gt;</description><content:encoded><![CDATA[<blockquote>
<p>TLDR:</p>
<p><em>Info: Monal will stop support for iOS 12, iOS 13 and macOS Catalina!<br>
We are searching for a SwiftUI developer.<br>
We need a new simplified website.<br>
With better continuous funding, our push servers will move from the US to Europe.<br>
We have a new support mail: info@monal-im.org</em></p>
</blockquote>
<p>Two years ago we decided to rewrite the Monal app almost entirely and improve it gradually in the process, instead of creating another XMPP Client for iOS and macOS. We successfully managed to transform Monal from an app that had flaws and issues with many functions to a level that promotes a user-friendly experience with working features such as push notification, group chat, and partially end-to-end encryption support (OMEMO). If you are selecting an XMPP client for Apple systems we think that Monal is a great choice nowadays. We have been investing more than a thousand hours and worked hard to overcome all the flaws, the legacy app had. We invite you to give the recent beta a try!</p>
<p>The development of Monal has not yet finished though, and many more features are hopefully to come. But due to our time constraints, it sometimes takes a bit longer than we and the community would like. We are at most two developers at the moment using our spare time to maintain Monal and develop new features. As we are developing Monal in our spare time without decent funding, it is sometimes hard to prioritize specific features. Please give this circumstance some credits.</p>
<h3 id="what-should-monal-look-like-in-the-future">What should Monal look like in the future?</h3>
<p>To give you a bit of insight knowledge of our plans we tried to summarize the most important tasks.</p>
<h4 id="interface-swiftui">Interface (SwiftUI)</h4>
<p>In the future Monal should be easy to use. Therefore, the interface requires a proper rework and while we are at it, it should be ported to SwiftUI. While we are still improving in designing with SwiftUI, we would be glad if there is a SwiftUI &amp; Open Source enthusiast who would like to help us with this.<br>
With this transition we would like to improve the accessibility of the app as well. If you like to support an open source project, and you would like to be part of our SwiftUI journey please contact us.</p>
<p>Task:</p>
<ul>
<li>Add new MUC creation and management UI</li>
<li>Port the chat view</li>
<li>Finish contact Details
<ul>
<li>List group chat (MUC) participants</li>
<li>Display OMEMO encryption fingerprints for verification</li>
</ul>
</li>
<li>Port our settings</li>
<li>Port all other remaining views</li>
</ul>
<p>Qualifications:</p>
<ul>
<li>General knowledge around SwiftUI (iOS and Catalyst)</li>
<li>Interest in improving a (XMPP) chat client</li>
<li>Optional, but preferred: Some experience with XMPP (e.g. some weeks, or maybe months of usage of Monal or any other “modern” XMPP client)</li>
<li>Optional: Experience in designing inclusive / accessible UI</li>
</ul>
<h4 id="website">Website</h4>
<p>We need a modern (simplified) Hugo based website that is easier to understand, similar to Conversations, Dino or Gajim.</p>
<p>If you have some spare time, and you are a skilled in creating websites with Hugo please contact us.</p>
<p>Requirements:</p>
<ul>
<li>Simple design nothing too fancy</li>
<li>Privacy by design → No analytics, no external CSS, jss, … usage</li>
</ul>
<h4 id="omemo-encryption-in-group-chat-muc">OMEMO Encryption in Group Chat (MUC)</h4>
<p>We started to integrate OMEMO for group chats (MUC) into our alpha build. The receiving and sending sides are already implemented, but there are a few more steps until we can release it into the beta.</p>
<h4 id="switching-to-our-new-domain-monal-imorg">Switching to our new Domain monal-im.org</h4>
<p>In late 2021 we decided that we would like to have a domain with <a href="https://en.wikipedia.org/wiki/Domain_Name_System_Security_Extensions">DNSSEC</a> as our current top level domain does not support it. This domain will mainly be used for our push servers and mail servers in the future. From now on you will be able to reach us via <a href="mailto:info@monal-im.org">info@monal-im.org</a>.</p>
<h4 id="build-server">Build server</h4>
<p>Thanks to ~20 generous donors, we were able to buy a new build server that will be used to build our alpha, beta and stable releases. Furthermore, Thilo is now finally able to debug code with a proper debugger connected to his phone.</p>
<h4 id="redundant-push-servers">Redundant Push Servers</h4>
<p>We are currently using an AWS US instance for our push server that is not redundant and failed in 2021 more frequently than we liked it to. For that reason we started an internal project to auto-deploy our push server with Ansible and looked into ways for running a redundant push server setup. The first tests look promising so far, but a few more things need to be sorted out before we can switch over to our new setup.</p>
<p>Before we can switch to the new push server setup, we need a stable funding each month. We estimate that renting a VM in Germany and one at a different hoster in Finland would cost us between 16€ to 32€ each month. Without a stable funding we might not be able to afford this new setup and our push servers would stay in the US.</p>
<p>Thanks to our generous build server donors, we have a few bucks left that will be used as a ~5 month buffer in case of fluctuant push server funding</p>
<h4 id="privacy-improved-push-servers">Privacy improved push servers</h4>
<p>With our current push implementation our so-called “app servers” see your JID (username + server), a unique but otherwise opaque device id and an opaque token generated by apple, as well as your interaction times (when you register for push notifications, timestamps when your XMPP server triggers a push notification device).<br>
If you use multiple accounts on one device, the unique device id is shared across all accounts. We don’t think that this is ideal, as we know all jid’s a user is using.<br>
In the future we want to try to reduce our knowledge by hiding your username from our app servers. If our idea works, we would only see that a device is registered on one or more domains and the timestamps that a push message was triggered from each domain that is used.</p>
<h4 id="audio-and-video-calls">Audio and Video Calls</h4>
<p>Many clients such as Conversations and Dino support audio and video calls, so Monal should be next 🙂</p>
<h4 id="end-of-life-ios-12-ios-13-and-macos-catalina-will-not-be-supported-anymore">End-of-life: iOS 12, iOS 13 and macOS Catalina will not be supported anymore</h4>
<p>Our user group on iOS 12, iOS 13 as well as macOS Catalina has decreased in last years while the resources needed to maintain these old platforms increased. We therefore decided to focus on newer iOS versions and drop the old ones. The next stable release will only be supported on iOS 14 and higher and macOS Big Sur and higher. We are still unsure how long we will support iOS 14, as most of the devices also support iOS15.</p>
<h2 id="donations-and-support">Donations and Support</h2>
<p>Monal is developed by volunteers and community collaboration. The work which has been done is usually not paid, and the developers need to keep up service costs and development in the future! Please consider giving a bit back for the hard work which has been conducted. Currently, there are three ways to financially support the Monal development:</p>
<ul>
<li>Donate via <a href="https://github.com/sponsors/tmolitor-stud-tu">GitHub Sponsors</a></li>
<li>Donate via <a href="https://liberapay.com/tmolitor">Libera Pay</a></li>
<li>EU citizens can donate via SEPA, too. Just contact Thilo Molitor via mail to <a href="mailto:info@monal-im.org">info@monal-im.org</a> to get his IBAN.</li>
</ul>
<p>Here you can read about further <a href="https://github.com/monal-im/Monal/issues/363">support of the development</a>! Find general information in the <a href="https://github.com/monal-im/Monal/wiki">Monal Wiki</a>.</p>
<h4 id="translations">Translations</h4>
<p>We host and manage translations via <a href="https://hosted.weblate.org/engage/monal/">Weblate</a>.</p>
<h4 id="many-thanks">Many thanks!</h4>
<p>Of course, thank you very much to everyone who supported us in the past two years! 🙂</p>
<p>You can follow us via <a href="https://fosstodon.org/@Monal">Mastodon</a>.</p>
]]></content:encoded></item><item><title>Monal-IM. Privacy like it's 1999</title><link>https://monal-im.org/home/</link><pubDate>Mon, 07 Mar 2022 00:00:00 +0000</pubDate><guid>https://monal-im.org/home/</guid><description>&lt;p&gt;Monal is an XMPP instant messaging client for macOS and iOS which strives to be the go-to client for these platforms just like the app Conversations IM is for Android.
XMPP in general is an open and standardized protocol for real time communication.
Anyone can host their own server and communicate freely with each other, just like with email and just like email the used addresses are of the form &amp;ldquo;&lt;a href="mailto:user@domain.tld"&gt;user@domain.tld&lt;/a&gt;&amp;rdquo;.
The user can use different apps and services, such as Monal, from a single but also multiple accounts.
This serves a decentral and sovereign infrastructure and digital communication on the internet but also offers many potential for innovation.
The chat client for iOS and macOS involves implementing various XEP standards (XMPP extension protocols, adding modern functionality to the XMPP-core and XMPP-im RFCs, see &lt;a href="https://xmpp.org/extensions/"&gt;XMPP Extensions&lt;/a&gt;).&lt;/p&gt;</description><content:encoded><![CDATA[<p>Monal is an XMPP instant messaging client for macOS and iOS which strives to be the go-to client for these platforms just like the app Conversations IM is for Android.
XMPP in general is an open and standardized protocol for real time communication.
Anyone can host their own server and communicate freely with each other, just like with email and just like email the used addresses are of the form &ldquo;<a href="mailto:user@domain.tld">user@domain.tld</a>&rdquo;.
The user can use different apps and services, such as Monal, from a single but also multiple accounts.
This serves a decentral and sovereign infrastructure and digital communication on the internet but also offers many potential for innovation.
The chat client for iOS and macOS involves implementing various XEP standards (XMPP extension protocols, adding modern functionality to the XMPP-core and XMPP-im RFCs, see <a href="https://xmpp.org/extensions/">XMPP Extensions</a>).</p>
<table>
  <thead>
      <tr>
          <th></th>
          <th></th>
          <th></th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>
  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  

  

  








<figure>
  <div class="img-box">
    <img srcset="https://monal-im.org/images/screenshots/iphone/06_signin_hu_e079135aac17121e.webp 240w,https://monal-im.org/images/screenshots/iphone/06_signin_hu_dee6286f4cb51411.webp 300w,https://monal-im.org/images/screenshots/iphone/06_signin_hu_dca1367ff79dcf51.webp 360w,https://monal-im.org/images/screenshots/iphone/06_signin_hu_6ea06041f717eb6.webp 420w,https://monal-im.org/images/screenshots/iphone/06_signin_hu_7df07310d0bd8ea2.webp 480w,https://monal-im.org/images/screenshots/iphone/06_signin_hu_8262b0636dc93e88.webp 600w,https://monal-im.org/images/screenshots/iphone/06_signin_hu_81561864a5eb3da.webp 768w,https://monal-im.org/images/screenshots/iphone/06_signin_hu_ee398a0f4ea7603a.webp 800w,https://monal-im.org/images/screenshots/iphone/06_signin_hu_a9d6894f0c61a252.webp 960w,https://monal-im.org/images/screenshots/iphone/06_signin_hu_eb65b6c7942c2a83.webp 1024w,https://monal-im.org/images/screenshots/iphone/06_signin_hu_562310dc9b3987a3.webp 1080w,https://monal-im.org/images/screenshots/iphone/06_signin_hu_1731105f47da4e17.webp 1200w,https://monal-im.org/images/screenshots/iphone/06_signin_hu_70ebec2f0bf115c9.webp 1284w" style="max-width:1284px;width:100%" src="https://monal-im.org/images/screenshots/iphone/06_signin.png" fetchpriority="low" alt="" title=""/>
  </div>
  <figcaption></figcaption>
</figure>
</td>
          <td>
  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  

  

  








<figure>
  <div class="img-box">
    <img srcset="https://monal-im.org/images/screenshots/iphone/07_register_hu_476eaa7b57517d4f.webp 240w,https://monal-im.org/images/screenshots/iphone/07_register_hu_501f702ef773fa2e.webp 300w,https://monal-im.org/images/screenshots/iphone/07_register_hu_6abb5cd10d388dfc.webp 360w,https://monal-im.org/images/screenshots/iphone/07_register_hu_d5de8554fa419286.webp 420w,https://monal-im.org/images/screenshots/iphone/07_register_hu_e6a789cf43659f33.webp 480w,https://monal-im.org/images/screenshots/iphone/07_register_hu_f76c93cd2d3e2708.webp 600w,https://monal-im.org/images/screenshots/iphone/07_register_hu_999ae6b3b7f61a9b.webp 768w,https://monal-im.org/images/screenshots/iphone/07_register_hu_58ec11df758139f1.webp 800w,https://monal-im.org/images/screenshots/iphone/07_register_hu_c1fdbe4ff3a7dcf2.webp 960w,https://monal-im.org/images/screenshots/iphone/07_register_hu_b1e20f37ba4c5eeb.webp 1024w,https://monal-im.org/images/screenshots/iphone/07_register_hu_f6d35ff221b1e4b7.webp 1080w,https://monal-im.org/images/screenshots/iphone/07_register_hu_e5e107a6a5c50f26.webp 1200w,https://monal-im.org/images/screenshots/iphone/07_register_hu_b8e95e1807f78e24.webp 1284w" style="max-width:1284px;width:100%" src="https://monal-im.org/images/screenshots/iphone/07_register.png" fetchpriority="low" alt="" title=""/>
  </div>
  <figcaption></figcaption>
</figure>
</td>
          <td>
  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  

  

  








<figure>
  <div class="img-box">
    <img srcset="https://monal-im.org/images/screenshots/iphone/02_chats_hu_c6b5bf07c420ea06.webp 240w,https://monal-im.org/images/screenshots/iphone/02_chats_hu_76552e936b43c86d.webp 300w,https://monal-im.org/images/screenshots/iphone/02_chats_hu_2be90e899735534e.webp 360w,https://monal-im.org/images/screenshots/iphone/02_chats_hu_f978299d95546448.webp 420w,https://monal-im.org/images/screenshots/iphone/02_chats_hu_21f9e1e901ecb9f.webp 480w,https://monal-im.org/images/screenshots/iphone/02_chats_hu_7ad68229144d4e04.webp 600w,https://monal-im.org/images/screenshots/iphone/02_chats_hu_9b14d135cf87c2cd.webp 768w,https://monal-im.org/images/screenshots/iphone/02_chats_hu_f8e6968750d9ea20.webp 800w,https://monal-im.org/images/screenshots/iphone/02_chats_hu_761fd290935bbba1.webp 960w,https://monal-im.org/images/screenshots/iphone/02_chats_hu_cf70216b62d60c82.webp 1024w,https://monal-im.org/images/screenshots/iphone/02_chats_hu_cb1390a2d531fdfa.webp 1080w,https://monal-im.org/images/screenshots/iphone/02_chats_hu_37167a7d75cf9f0c.webp 1200w,https://monal-im.org/images/screenshots/iphone/02_chats_hu_9f655aceac8f518.webp 1284w" style="max-width:1284px;width:100%" src="https://monal-im.org/images/screenshots/iphone/02_chats.png" fetchpriority="low" alt="" title=""/>
  </div>
  <figcaption></figcaption>
</figure>
</td>
      </tr>
  </tbody>
</table>
<h2 id="designed-for-ios-and-mac">Designed for iOS and Mac</h2>
<p>Things look and work the way you expect. iOS, iPadOS or macOS, there is a version of Monal for you.</p>
<table>
  <thead>
      <tr>
          <th></th>
          <th></th>
          <th></th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>
  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  

  

  








<figure>
  <div class="img-box">
    <img srcset="https://monal-im.org/images/screenshots/iphone/01_groupchats_hu_c06c558b5867608.webp 240w,https://monal-im.org/images/screenshots/iphone/01_groupchats_hu_701c74daae2942f1.webp 300w,https://monal-im.org/images/screenshots/iphone/01_groupchats_hu_d48f39ffc1633d23.webp 360w,https://monal-im.org/images/screenshots/iphone/01_groupchats_hu_5ac1cc31702674c8.webp 420w,https://monal-im.org/images/screenshots/iphone/01_groupchats_hu_8e8b9739ef5afd03.webp 480w,https://monal-im.org/images/screenshots/iphone/01_groupchats_hu_f4aa2a5a2dc47a31.webp 600w,https://monal-im.org/images/screenshots/iphone/01_groupchats_hu_7b5e0ed3f16fd5cd.webp 768w,https://monal-im.org/images/screenshots/iphone/01_groupchats_hu_451a20386098abea.webp 800w,https://monal-im.org/images/screenshots/iphone/01_groupchats_hu_c7394a27dc942f4e.webp 960w,https://monal-im.org/images/screenshots/iphone/01_groupchats_hu_bf3a986df8b9bbf1.webp 1024w,https://monal-im.org/images/screenshots/iphone/01_groupchats_hu_7488892522a72a6c.webp 1080w,https://monal-im.org/images/screenshots/iphone/01_groupchats_hu_ee23c43049087c97.webp 1200w,https://monal-im.org/images/screenshots/iphone/01_groupchats_hu_c1690c23a9e439b0.webp 1284w" style="max-width:1284px;width:100%" src="https://monal-im.org/images/screenshots/iphone/01_groupchats.png" fetchpriority="low" alt="" title=""/>
  </div>
  <figcaption></figcaption>
</figure>
</td>
          <td>
  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  

  
    
    
    
  








<figure>
  <div class="img-box">
    <img srcset="https://monal-im.org/images/screenshots/ipad/01_groupchats_hu_2cac2f9728af78c4.webp 240w,https://monal-im.org/images/screenshots/ipad/01_groupchats_hu_fc9d8dde4a8eb2a9.webp 300w,https://monal-im.org/images/screenshots/ipad/01_groupchats_hu_e118fe9e824ed72.webp 360w,https://monal-im.org/images/screenshots/ipad/01_groupchats_hu_7e794ea408bda94.webp 420w,https://monal-im.org/images/screenshots/ipad/01_groupchats_hu_2aad19036f5424e5.webp 480w,https://monal-im.org/images/screenshots/ipad/01_groupchats_hu_32623b64324b345b.webp 600w,https://monal-im.org/images/screenshots/ipad/01_groupchats_hu_2e77cadd961acfc1.webp 768w,https://monal-im.org/images/screenshots/ipad/01_groupchats_hu_28830df62e35936b.webp 800w,https://monal-im.org/images/screenshots/ipad/01_groupchats_hu_61076fd658d4bd4.webp 960w,https://monal-im.org/images/screenshots/ipad/01_groupchats_hu_1da8d1898163fb69.webp 1024w,https://monal-im.org/images/screenshots/ipad/01_groupchats_hu_99b25c389e759044.webp 1080w,https://monal-im.org/images/screenshots/ipad/01_groupchats_hu_327c088d1e5d73e1.webp 1200w,https://monal-im.org/images/screenshots/ipad/01_groupchats_hu_e1a1e4669a9216c.webp 1366w,https://monal-im.org/images/screenshots/ipad/01_groupchats_hu_550c77441ac8b699.webp 1440w,https://monal-im.org/images/screenshots/ipad/01_groupchats_hu_ba0d3c78ec84d511.webp 1920w,https://monal-im.org/images/screenshots/ipad/01_groupchats_hu_4a0adc1cf53db72a.webp 2048w" style="max-width:2048px;width:100%" src="https://monal-im.org/images/screenshots/ipad/01_groupchats.png" fetchpriority="low" alt="" title=""/>
  </div>
  <figcaption></figcaption>
</figure>
</td>
          <td></td>
      </tr>
  </tbody>
</table>
<p>Monal is developed under an open-source BSD license that serves the user, while not selling or tracking information for external parties (nor for anyone else).
This app exists because it is key to ensure usability on all platforms and within the XMPP network with all its positives aspects when it comes to decentral communication and infrastructure.</p>
<p><a href="https://github.com/monal-im/Monal">Find the development on GitHub!</a></p>
]]></content:encoded></item><item><title/><link>https://monal-im.org/privacyarchive/privacyheader/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://monal-im.org/privacyarchive/privacyheader/</guid><description>&lt;p&gt;&lt;strong&gt;Monal Website&lt;/strong&gt;&lt;br&gt;
You can find our latest privacy policy for our website here: &lt;a href="https://monal-im.org/privacyarchive/monal_website/" title="Website Privacy Policy"&gt;Website Privacy Policy&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Monal App&lt;/strong&gt;&lt;br&gt;
Our privacy policy may differ between app versions.
Before reading our privacy policy for our App you first need to find out the Monal version that you are using. &lt;br&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How to find out your Monal version&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;Open Monal&lt;/li&gt;
&lt;li&gt;Open up the settings menu in the upper left corner (gearwheel)&lt;/li&gt;
&lt;li&gt;Scroll down to the last entry &amp;ldquo;version&amp;rdquo;&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Monal App Privacy Policies&lt;/strong&gt;&lt;/p&gt;</description><content:encoded><![CDATA[<p><strong>Monal Website</strong><br>
You can find our latest privacy policy for our website here: <a href="/privacyarchive/monal_website/" title="Website Privacy Policy">Website Privacy Policy</a></p>
<p><strong>Monal App</strong><br>
Our privacy policy may differ between app versions.
Before reading our privacy policy for our App you first need to find out the Monal version that you are using. <br></p>
<p><strong>How to find out your Monal version</strong></p>
<blockquote>
<ol>
<li>Open Monal</li>
<li>Open up the settings menu in the upper left corner (gearwheel)</li>
<li>Scroll down to the last entry &ldquo;version&rdquo;</li>
</ol>
</blockquote>
<p><strong>Monal App Privacy Policies</strong></p>
<table>
  <thead>
      <tr>
          <th>Releases</th>
          <th>Privacy Policy</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>6.0 and newer</td>
          <td><a href="/privacyarchive/monal_app_rev_003/" title="Privacy Policy Rev 003">Privacy Policy Rev 003</a></td>
      </tr>
      <tr>
          <td>5.2.0 up to 5.4.x</td>
          <td><a href="/privacyarchive/monal_app_rev_002/" title="Privacy Policy Rev 002">Privacy Policy Rev 002</a></td>
      </tr>
      <tr>
          <td>before 5.2.0</td>
          <td><a href="/privacyarchive/monal_app_rev_001/" title="Privacy Policy Rev 001">Privacy Policy Rev 001</a></td>
      </tr>
  </tbody>
</table>
]]></content:encoded></item><item><title>About</title><link>https://monal-im.org/about/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://monal-im.org/about/</guid><description>&lt;h1 id="imprint"&gt;Imprint&lt;/h1&gt;
&lt;p&gt;Thilo Molitor&lt;/br&gt;
Vogelsbergstr. 18&lt;/br&gt;
68642 Bürstadt&lt;/br&gt;
Germany&lt;/p&gt;
&lt;p&gt;eMail: info[at]monal[minus]im[dot]org&lt;/p&gt;
&lt;h1 id="about"&gt;About&lt;/h1&gt;
&lt;p&gt;Monal originates in 2002 as fork of the SworIM app.
Until 2019 it has been developed by Anu Pokharel.
Since then Thilo Molitor took over the development and joined in 2020 with Friedrich Altheide (until 2024).
From initial rewrite of code in the backend the entire app has been upgraded with a modern XMPP engine, new features and future-proof setup.
Monal challenges to be the go-to XMPP chat-app for the iOS and macOS platform.&lt;/p&gt;</description><content:encoded><![CDATA[<h1 id="imprint">Imprint</h1>
<p>Thilo Molitor</br>
Vogelsbergstr. 18</br>
68642 Bürstadt</br>
Germany</p>
<p>eMail: info[at]monal[minus]im[dot]org</p>
<h1 id="about">About</h1>
<p>Monal originates in 2002 as fork of the SworIM app.
Until 2019 it has been developed by Anu Pokharel.
Since then Thilo Molitor took over the development and joined in 2020 with Friedrich Altheide (until 2024).
From initial rewrite of code in the backend the entire app has been upgraded with a modern XMPP engine, new features and future-proof setup.
Monal challenges to be the go-to XMPP chat-app for the iOS and macOS platform.</p>
<h2 id="monal-team">Monal Team</h2>
<p><strong>Thilo Molitor</strong> - <a href="https://wiki.xmpp.org/web/User:TMolitor">About me on wiki.xmpp.org</a></p>
]]></content:encoded></item><item><title>Publications</title><link>https://monal-im.org/publications/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://monal-im.org/publications/</guid><description>&lt;h2 id="talks-and-other-documents"&gt;Talks and other documents&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Molitor, Thilo; Altheide, Friedrich. &lt;strong&gt;Modern XMPP - A story based on Monal&lt;/strong&gt; &lt;em&gt;Berlin XMPP Meetup&lt;/em&gt;, 13th April 2022, &lt;a href="https://xmpp-meetup.in-berlin.de/talks/monal-2022.mp4"&gt;Recording&lt;/a&gt;, &lt;a href="https://xmpp-meetup.in-berlin.de/talks/monal-and-push.pdf"&gt;Slides&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Molitor, Thilo; Altheide, Friedrich. &lt;strong&gt;Privacy friendly push&lt;/strong&gt; &lt;em&gt;Berlin XMPP Meetup&lt;/em&gt;, 13th April 2022, &lt;a href="https://xmpp-meetup.in-berlin.de/talks/privacy-friendly-push.mp4"&gt;Recording&lt;/a&gt;, &lt;a href="https://xmpp-meetup.in-berlin.de/talks/monal-and-push.pdf#Navigation31"&gt;Slides&lt;/a&gt; (starting after page 29)&lt;/li&gt;
&lt;li&gt;Molitor, Thilo. &lt;a href="https://wiki.xmpp.org/web/Push_notifications#Push_notifications_on_iOS"&gt;XMPP Push notifications on iOS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Molitor, Thilo. &lt;strong&gt;Monal development recap 2019 - 2021 and open discussion&lt;/strong&gt; &lt;em&gt;Berlin XMPP Meetup&lt;/em&gt;, 13th October 2021, &lt;a href="https://xmpp-meetup.in-berlin.de/talks/monal-2021.mp4"&gt;Recording&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="xep-publications"&gt;XEP publications&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://xmpp.org/extensions/xep-0198.html"&gt;XEP-0198: Stream Management&lt;/a&gt;&lt;br/&gt;
Authors: Justin Karneges, Peter Saint-Andre, Joe Hildebrand, Fabio Forno, Dave Cridland, Matthew Wild, Thilo Molitor
&lt;blockquote&gt;
&lt;p&gt;This specification defines an XMPP protocol extension for active management of an XML stream between two XMPP entities, including features for stanza acknowledgements and stream resumption.&lt;/p&gt;</description><content:encoded><![CDATA[<h2 id="talks-and-other-documents">Talks and other documents</h2>
<ul>
<li>Molitor, Thilo; Altheide, Friedrich. <strong>Modern XMPP - A story based on Monal</strong> <em>Berlin XMPP Meetup</em>, 13th April 2022, <a href="https://xmpp-meetup.in-berlin.de/talks/monal-2022.mp4">Recording</a>, <a href="https://xmpp-meetup.in-berlin.de/talks/monal-and-push.pdf">Slides</a></li>
<li>Molitor, Thilo; Altheide, Friedrich. <strong>Privacy friendly push</strong> <em>Berlin XMPP Meetup</em>, 13th April 2022, <a href="https://xmpp-meetup.in-berlin.de/talks/privacy-friendly-push.mp4">Recording</a>, <a href="https://xmpp-meetup.in-berlin.de/talks/monal-and-push.pdf#Navigation31">Slides</a> (starting after page 29)</li>
<li>Molitor, Thilo. <a href="https://wiki.xmpp.org/web/Push_notifications#Push_notifications_on_iOS">XMPP Push notifications on iOS</a></li>
<li>Molitor, Thilo. <strong>Monal development recap 2019 - 2021 and open discussion</strong> <em>Berlin XMPP Meetup</em>, 13th October 2021, <a href="https://xmpp-meetup.in-berlin.de/talks/monal-2021.mp4">Recording</a></li>
</ul>
<h2 id="xep-publications">XEP publications</h2>
<ul>
<li><a href="https://xmpp.org/extensions/xep-0198.html">XEP-0198: Stream Management</a><br/>
Authors: Justin Karneges, Peter Saint-Andre, Joe Hildebrand, Fabio Forno, Dave Cridland, Matthew Wild, Thilo Molitor
<blockquote>
<p>This specification defines an XMPP protocol extension for active management of an XML stream between two XMPP entities, including features for stanza acknowledgements and stream resumption.</p>
</blockquote>
</li>
<li><a href="https://xmpp.org/extensions/xep-0353.html">XEP-0353: Jingle Message Initiation</a><br/>
Authors: Philipp Hancke, Peter Saint-Andre, Thilo Molitor
<blockquote>
<p>This specification provides a way for the initiator of a Jingle session to propose sending an invitation in an XMPP message stanza, thus taking advantage of message delivery semantics instead of sending IQ stanzas to all of the responder&rsquo;s online resources or choosing a particular online resource.</p>
</blockquote>
</li>
<li><a href="https://xmpp.org/extensions/xep-0474.html">XEP-0474: SASL SCRAM Downgrade Protection</a><br/>
Authors: Thilo Molitor
<blockquote>
<p>This specification provides a way to secure the SASL and SASL2 handshakes against method and channel-binding downgrades.</p>
</blockquote>
</li>
<li><a href="https://xmpp.org/extensions/xep-0388.html">XEP-0388: Extensible SASL Profile</a><br/>
Authors: Dave Cridland, Thilo Molitor, Matthew Wild
<blockquote>
<p>This document describes a replacement for the SASL profile documented in RFC 6120 which allows for greater extensibility.</p>
</blockquote>
</li>
<li><a href="https://xmpp.org/extensions/xep-0480.html">XEP-0480: SASL Upgrade Tasks</a><br/>
Authors: Thilo Molitor
<blockquote>
<p>This specification provides a way to upgrade to newer SASL mechanisms using SASL2 tasks.</p>
</blockquote>
</li>
<li><a href="https://xmpp.org/extensions/xep-0440.html">XEP-0440: SASL Channel-Binding Type Capability</a><br/>
Authors: Florian Schmaus, Thilo Molitor
<blockquote>
<p>This specification allows servers to annouce their supported SASL channel-binding types to clients.</p>
</blockquote>
</li>
<li><a href="https://xmpp.org/extensions/xep-0492.html">XEP-0492: Chat notification settings</a><br/>
Authors: Nicolas Cedilnik, Thilo Molitor
<blockquote>
<p>This document defines an XMPP protocol extension to synchronise per-chat notification settings across different clients.</p>
</blockquote>
</li>
</ul>
]]></content:encoded></item></channel></rss>