<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://everydaycompute.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://everydaycompute.github.io/" rel="alternate" type="text/html" /><updated>2026-05-23T10:29:02+02:00</updated><id>https://everydaycompute.github.io/feed.xml</id><title type="html">YeenDeer softness blog (programming and electronics)</title><subtitle>Ellie the Yeen is a soft YeenDeer that mweeoops and does programming</subtitle><author><name>ellietheyeen</name></author><entry><title type="html">How to copy an array</title><link href="https://everydaycompute.github.io/2024/11/15/copy-an-array.html" rel="alternate" type="text/html" title="How to copy an array" /><published>2024-11-15T16:40:00+01:00</published><updated>2024-11-15T16:40:00+01:00</updated><id>https://everydaycompute.github.io/2024/11/15/copy-an-array</id><content type="html" xml:base="https://everydaycompute.github.io/2024/11/15/copy-an-array.html"><![CDATA[<p>Copying arrays is something that seems like a very obvious thing in programming but different languages do it in completely different ways.</p>

<ul id="markdown-toc">
  <li><a href="#java" id="markdown-toc-java">Java</a></li>
  <li><a href="#javascript" id="markdown-toc-javascript">JavaScript</a></li>
  <li><a href="#python" id="markdown-toc-python">Python</a>    <ul>
      <li><a href="#array-and-copy-module" id="markdown-toc-array-and-copy-module">array and copy module</a></li>
    </ul>
  </li>
  <li><a href="#c" id="markdown-toc-c">C</a></li>
  <li><a href="#php" id="markdown-toc-php">PHP</a></li>
  <li><a href="#erlang" id="markdown-toc-erlang">Erlang</a></li>
</ul>

<h2 id="java">Java</h2>
<p>Java has the basic array type which is just any type suffixed with <code class="language-plaintext highlighter-rouge">[]</code> to make it an array. To copy an array like it you use the static method <code class="language-plaintext highlighter-rouge">arraycopy</code> from the <code class="language-plaintext highlighter-rouge">System</code> class.</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">Main</span> <span class="o">{</span>
    <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
        <span class="kt">byte</span><span class="o">[]</span> <span class="n">a</span> <span class="o">=</span> <span class="o">{</span><span class="mi">1</span><span class="o">,</span> <span class="mi">2</span><span class="o">,</span> <span class="mi">3</span><span class="o">,</span> <span class="mi">4</span><span class="o">,</span> <span class="mi">5</span><span class="o">,</span> <span class="mi">6</span><span class="o">,</span> <span class="mi">7</span><span class="o">,</span> <span class="mi">8</span><span class="o">,</span> <span class="mi">9</span><span class="o">,</span> <span class="mi">0</span><span class="o">};</span>
        <span class="kt">byte</span><span class="o">[]</span> <span class="n">b</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">byte</span><span class="o">[</span><span class="mi">10</span><span class="o">];</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">arraycopy</span><span class="o">(</span><span class="n">a</span><span class="o">,</span> <span class="mi">0</span><span class="o">,</span> <span class="n">b</span><span class="o">,</span> <span class="mi">0</span><span class="o">,</span> <span class="mi">10</span><span class="o">);</span>
        <span class="n">a</span><span class="o">[</span><span class="mi">9</span><span class="o">]</span> <span class="o">=</span> <span class="mi">10</span><span class="o">;</span> <span class="c1">// Change something to make sure we are printing the original values</span>
        <span class="k">for</span> <span class="o">(</span><span class="kt">byte</span> <span class="nl">c:</span> <span class="n">b</span><span class="o">)</span> <span class="o">{</span>
            <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">print</span><span class="o">(</span><span class="n">c</span><span class="o">);</span>
            <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">print</span><span class="o">(</span><span class="s">" "</span><span class="o">);</span>
        <span class="o">}</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">();</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>
<p>Output:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>1 2 3 4 5 6 7 8 9 0 
</code></pre></div></div>
<p>But keep in mind that such an array is not like a java primitive so it gets passed as is into functions without it being copied at any stage like a primitive type would.</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">Main</span> <span class="o">{</span>
    <span class="kd">public</span> <span class="kd">static</span> <span class="kt">byte</span><span class="o">[]</span> <span class="nf">dosomething</span><span class="o">(</span><span class="kt">byte</span><span class="o">[]</span> <span class="n">a</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">return</span> <span class="n">a</span><span class="o">;</span>
    <span class="o">}</span>
    <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
        <span class="kt">byte</span><span class="o">[]</span> <span class="n">a</span> <span class="o">=</span> <span class="o">{</span><span class="mi">1</span><span class="o">,</span> <span class="mi">2</span><span class="o">,</span> <span class="mi">3</span><span class="o">,</span> <span class="mi">4</span><span class="o">,</span> <span class="mi">5</span><span class="o">,</span> <span class="mi">6</span><span class="o">,</span> <span class="mi">7</span><span class="o">,</span> <span class="mi">8</span><span class="o">,</span> <span class="mi">9</span><span class="o">,</span> <span class="mi">0</span><span class="o">};</span>
        <span class="kt">byte</span><span class="o">[]</span> <span class="n">b</span> <span class="o">=</span> <span class="n">dosomething</span><span class="o">(</span><span class="n">a</span><span class="o">);</span>
        <span class="n">b</span><span class="o">[</span><span class="mi">9</span><span class="o">]</span> <span class="o">=</span> <span class="mi">10</span><span class="o">;</span>
        <span class="k">for</span> <span class="o">(</span><span class="kt">byte</span> <span class="nl">c:</span> <span class="n">b</span><span class="o">)</span> <span class="o">{</span>
         <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">print</span><span class="o">(</span><span class="n">c</span><span class="o">);</span>
         <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">print</span><span class="o">(</span><span class="s">" "</span><span class="o">);</span>
        <span class="o">}</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">();</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>
<p>Output</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>1 2 3 4 5 6 7 8 9 10
</code></pre></div></div>

<p>Java also has classes like <code class="language-plaintext highlighter-rouge">ArrayList</code> which is a dynamic array and to copy one you use the <code class="language-plaintext highlighter-rouge">clone</code> method.</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">Main</span> <span class="o">{</span>
    <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
        <span class="nc">ArrayList</span> <span class="n">l</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">ArrayList</span><span class="o">();</span>
        <span class="n">l</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="mi">1</span><span class="o">);</span>
        <span class="n">l</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="mi">2</span><span class="o">);</span>
        <span class="n">l</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="mi">3</span><span class="o">);</span>
        <span class="nc">ArrayList</span> <span class="n">l2</span> <span class="o">=</span> <span class="o">(</span><span class="nc">ArrayList</span><span class="o">)</span><span class="n">l</span><span class="o">.</span><span class="na">clone</span><span class="o">();</span>
        <span class="n">l</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="mi">4</span><span class="o">);</span>
        <span class="k">for</span> <span class="o">(</span><span class="nc">Object</span> <span class="nl">c:</span> <span class="n">l2</span><span class="o">.</span><span class="na">toArray</span><span class="o">())</span> <span class="o">{</span>
         <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">c</span><span class="o">);</span>
        <span class="o">}</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>
<p>Output</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>1
2
3
</code></pre></div></div>

<h2 id="javascript">JavaScript</h2>
<p>JavaScript has as of a few years back something called the <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax">spread operator</a> which you write as <code class="language-plaintext highlighter-rouge">...</code> and it can be used on iterable objects to get all members.</p>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">a</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span>
<span class="c1">// Array(3) [ 1, 2, 3 ]</span>
<span class="nx">b</span> <span class="o">=</span> <span class="p">[...</span><span class="nx">a</span><span class="p">]</span>
<span class="c1">// Array(3) [ 1, 2, 3 ]</span>
<span class="nx">a</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">=</span><span class="mi">0</span>
<span class="c1">// 0</span>
<span class="nx">a</span>
<span class="c1">// Array(3) [ 0, 2, 3 ]</span>
<span class="nx">b</span>
<span class="c1">// Array(3) [ 1, 2, 3 ]</span>
</code></pre></div></div>

<h2 id="python">Python</h2>
<p>Python has the basic <code class="language-plaintext highlighter-rouge">list</code> dynamic array type which uses the <code class="language-plaintext highlighter-rouge">[]</code> notation to construct it but you can call the constructor like <code class="language-plaintext highlighter-rouge">list()</code> too. To make a copy it you can use the <code class="language-plaintext highlighter-rouge">[:]</code> slice notation which does various forms of shallow copies of the list.</p>

<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">a</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">]</span>
<span class="n">b</span> <span class="o">=</span> <span class="n">a</span><span class="p">[:]</span>
<span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">print</span><span class="p">(</span><span class="n">b</span><span class="p">)</span>
<span class="c1"># [1, 2, 3]
</span><span class="n">a</span> <span class="o">=</span> <span class="n">b</span><span class="p">[::</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
<span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
<span class="c1"># [3, 2, 1] Yes it got reversed
</span><span class="n">a</span> <span class="o">=</span> <span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">:</span><span class="mi">2</span><span class="p">]</span>
<span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
<span class="c1"># [2]
</span><span class="n">a</span> <span class="o">=</span> <span class="n">b</span><span class="p">[::</span><span class="mi">2</span><span class="p">]</span>
<span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
<span class="c1"># [1, 3]
</span><span class="n">a</span> <span class="o">=</span> <span class="n">b</span><span class="p">[</span><span class="o">-</span><span class="mi">2</span><span class="p">::]</span>
<span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
<span class="c1"># [2, 3]
</span></code></pre></div></div>
<p>Up to 3 numbers are specified in the slice notiation of the form <code class="language-plaintext highlighter-rouge">[start:end:skip]</code> where start is the start position (inclusive) and end is the end position (exclusive) and skip is how many steps it will take between and negative is allowed in all the arguments where a negative skip will reverse. Negative starts will start reading at the specified index at the end of the list.</p>

<h3 id="array-and-copy-module">array and copy module</h3>
<p>Python also has an array type called <a href="https://docs.python.org/3/library/array.html">array</a> but in all the decades of me programming in Python I have used it about once but this is how you use it together with the <a href="https://docs.python.org/3/library/copy.html">copy</a> module with calls the <code class="language-plaintext highlighter-rouge">__copy__</code> special method.</p>
<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">array</span>
<span class="kn">import</span> <span class="nn">copy</span>

<span class="n">a</span> <span class="o">=</span> <span class="n">array</span><span class="p">.</span><span class="n">array</span><span class="p">(</span><span class="s">"i"</span><span class="p">,</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">])</span>
<span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
<span class="c1"># array('i', [1, 2, 3])
</span><span class="n">b</span> <span class="o">=</span> <span class="n">copy</span><span class="p">.</span><span class="n">copy</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
<span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">print</span><span class="p">(</span><span class="n">b</span><span class="p">)</span>
<span class="c1"># array('i', [1, 2, 3])
</span></code></pre></div></div>

<p>The copy module also supports deep copying which is very convenient for when you actually want to deep copy an object.</p>

<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">array</span>
<span class="kn">import</span> <span class="nn">copy</span>

<span class="n">a</span> <span class="o">=</span> <span class="p">[[</span><span class="s">'A'</span><span class="p">,</span> <span class="s">'B'</span><span class="p">,</span> <span class="s">'C'</span><span class="p">],</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">]</span>
<span class="n">b</span> <span class="o">=</span> <span class="n">copy</span><span class="p">.</span><span class="n">deepcopy</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
<span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">insert</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
<span class="c1"># [[0, 'A', 'B', 'C'], 1, 2, 3]
</span><span class="k">print</span><span class="p">(</span><span class="n">b</span><span class="p">)</span>
<span class="c1"># [['A', 'B', 'C'], 1, 2, 3]
</span></code></pre></div></div>

<h2 id="c">C</h2>
<p>C is a bit unusual compared to most modern languages as you operate pretty much in raw memory. This means that you can cast any type to any other type and this means also that you do not need to know the type of the thing you copy with <code class="language-plaintext highlighter-rouge">memcpy</code> but you do need to know the memory areas and the size of the array in memory.</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;string.h&gt;</span><span class="cp">
</span>
<span class="kt">void</span> <span class="nf">printArray</span><span class="p">(</span><span class="kt">int</span><span class="o">*</span> <span class="n">a</span><span class="p">,</span> <span class="kt">int</span> <span class="n">len</span><span class="p">)</span> <span class="p">{</span>
  <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">printf</span><span class="p">(</span><span class="s">"Position %d = %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
  <span class="p">}</span>
<span class="p">}</span>

<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
  <span class="kt">int</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">};</span>
  <span class="kt">int</span> <span class="n">b</span><span class="p">[</span><span class="mi">3</span><span class="p">];</span>
  <span class="n">memcpy</span><span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">));</span>
  <span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
  <span class="n">printArray</span><span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="mi">3</span><span class="p">);</span>
  <span class="n">printf</span><span class="p">(</span><span class="s">"%d is the size of the array in memory</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">));</span>

<span class="p">}</span>
</code></pre></div></div>
<p>Output</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Position 0 = 1
Position 1 = 2
Position 2 = 3
12 is the size of the array in memory
</code></pre></div></div>

<p>You might be confused why 12 is the memory size of the array when it has only 3 elements. The reason for that is that an integer in this version of C on this platform has a memory size of 4 bytes. The platform is ARM 64 bit here if you wonder. When it comes to stuff like casting and memory it has been common for some C programmers to create a struct type for example then cast it to a byte array to send over network and that is the reason why the struct module in Python is called that.</p>

<h2 id="php">PHP</h2>
<p>Want to copy an array in PHP? The bigger question is how to not copy an array in PHP. Assigning a variable to another variable will copy it almost completely.</p>

<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">&lt;?php</span>
<span class="nv">$a</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">];</span>
<span class="nv">$b</span> <span class="o">=</span> <span class="nv">$a</span><span class="p">;</span>
<span class="nv">$c</span> <span class="o">=</span> <span class="o">&amp;</span><span class="nv">$a</span><span class="p">;</span>
<span class="nv">$a</span><span class="p">[]</span> <span class="o">=</span> <span class="mi">4</span><span class="p">;</span>
<span class="k">echo</span> <span class="nb">json_encode</span><span class="p">(</span><span class="nv">$a</span><span class="p">),</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">;</span>
<span class="c1"># [1,2,3,4]</span>
<span class="k">echo</span> <span class="nb">json_encode</span><span class="p">(</span><span class="nv">$b</span><span class="p">),</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">;</span>
<span class="c1"># [1,2,3]</span>
<span class="k">echo</span> <span class="nb">json_encode</span><span class="p">(</span><span class="nv">$c</span><span class="p">),</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">;</span>
<span class="c1"># [1,2,3,4]</span>
</code></pre></div></div>

<p>If you thought it stopped at a shallow copy the answer is no. It is a deep copy (or perhaps copy on write) and will copy all the way down.</p>

<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">&lt;?php</span>
<span class="nv">$a</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"meow"</span><span class="p">,</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">]];</span>
<span class="nv">$b</span> <span class="o">=</span> <span class="nv">$a</span><span class="p">;</span>
<span class="nv">$a</span><span class="p">[</span><span class="mi">1</span><span class="p">][]</span> <span class="o">=</span> <span class="mi">4</span><span class="p">;</span>
<span class="k">echo</span> <span class="nb">json_encode</span><span class="p">(</span><span class="nv">$a</span><span class="p">),</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">;</span>
<span class="c1"># ["meow",[1,2,3,4]]</span>
<span class="k">echo</span> <span class="nb">json_encode</span><span class="p">(</span><span class="nv">$b</span><span class="p">),</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">;</span>
<span class="c1"># ["meow",[1,2,3]]</span>
</code></pre></div></div>

<p>There is however one specific exception to when something is copied and that is objects. Objects won’t be automatically copied like everything else.</p>

<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">&lt;?php</span>
<span class="kd">class</span> <span class="nc">A</span> <span class="p">{</span>
  <span class="k">public</span> <span class="kt">string</span> <span class="nv">$value</span><span class="p">;</span>
  <span class="k">public</span> <span class="k">function</span> <span class="n">__construct</span><span class="p">(</span><span class="nv">$in</span> <span class="o">=</span> <span class="s2">"meow"</span><span class="p">)</span> <span class="p">{</span>
    <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">value</span> <span class="o">=</span> <span class="nv">$in</span><span class="p">;</span>
  <span class="p">}</span>
<span class="p">}</span>
<span class="nv">$a</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">A</span><span class="p">;</span>
<span class="nv">$b</span> <span class="o">=</span> <span class="nv">$a</span><span class="p">;</span>
<span class="nv">$a</span><span class="o">-&gt;</span><span class="n">value</span> <span class="o">=</span> <span class="s2">"mew"</span><span class="p">;</span>
<span class="k">echo</span> <span class="nv">$a</span><span class="o">-&gt;</span><span class="n">value</span><span class="p">,</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">;</span>
<span class="c1"># mew</span>
<span class="k">echo</span> <span class="nv">$b</span><span class="o">-&gt;</span><span class="n">value</span><span class="p">,</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">;</span>
<span class="c1"># mew</span>
</code></pre></div></div>

<h2 id="erlang">Erlang</h2>

<p>Now for the strangest one. Want to know to to copy an array in Erlang? You simply don’t. Everything is immutable in Erlang so once a variable has been assigned a value it is set in stone and can never be changed. The variable can have different values in different invocations of the same function but that is it. Erlang also has no normally shaped stack and no iteration so you can do infinite recursion using something called trampolines. Also the language syntax is a bit unusual which you can see below.</p>

<div class="language-erlang highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">moan</span><span class="p">(</span><span class="nv">A</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nn">io</span><span class="p">:</span><span class="nf">fwrite</span><span class="p">(</span><span class="s">"the value is </span><span class="si">~w~n</span><span class="s">"</span><span class="p">,</span> <span class="p">[</span><span class="nv">A</span><span class="p">]).</span>
<span class="nf">meow</span><span class="p">(</span><span class="nv">B</span><span class="p">)</span> <span class="o">-&gt;</span>
  <span class="nf">moan</span><span class="p">(</span><span class="nv">B</span><span class="p">),</span>
  <span class="c">% the value is 1
</span>  <span class="nv">A</span><span class="o">=</span><span class="nv">B</span><span class="p">,</span>
  <span class="nf">moan</span><span class="p">(</span><span class="nv">A</span><span class="p">).</span>
  <span class="c">% the value is 1
</span><span class="nf">main</span><span class="p">(_)</span> <span class="o">-&gt;</span> 
  <span class="nv">A</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span>
  <span class="nf">meow</span><span class="p">(</span><span class="nv">A</span><span class="p">).</span>
</code></pre></div></div>]]></content><author><name>ellietheyeen</name></author><category term="javascript" /><category term="python" /><category term="erlang" /><category term="java" /><category term="php" /><category term="c" /><summary type="html"><![CDATA[Copying arrays is something that seems like a very obvious thing in programming but different languages do it in completely different ways.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://github.com/EllieTheYeen.png" /><media:content medium="image" url="https://github.com/EllieTheYeen.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">How to configure Apache to do nothing</title><link href="https://everydaycompute.github.io/2024/11/05/how-to-configure-apache-to-do-nothing.html" rel="alternate" type="text/html" title="How to configure Apache to do nothing" /><published>2024-11-05T21:37:00+01:00</published><updated>2024-11-05T21:37:00+01:00</updated><id>https://everydaycompute.github.io/2024/11/05/how-to-configure-apache-to-do-nothing</id><content type="html" xml:base="https://everydaycompute.github.io/2024/11/05/how-to-configure-apache-to-do-nothing.html"><![CDATA[<p>Sometimes you want to configure Apache to really do nothing. No server scripts and just use it as a purely static file server. An example of this would be when you have a Downloads folder and you want to share without there being issues due to how Apache functions.</p>

<p>The first thing we are going to do is make sure <code class="language-plaintext highlighter-rouge">mod_header</code> is enabled which can be done with the command</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>a2enmod headers
</code></pre></div></div>
<p>and after that is done and the config is changed you should restart Apache with</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>systemctl restart apache2
</code></pre></div></div>
<p>and we are ready for what config to be set.</p>

<p>Now we have the config which you should put in some file that Apache includes for example I have mine in <code class="language-plaintext highlighter-rouge">/etc/apache2/sites-enabled/000-default.conf</code> but you can put yours anywhere really. There are quite a few quirks in general we must defeat in order for Apache to just serve files as is without executing any of them by accident. This is the actual config I use to share some downloads between computers that as you can see very commented and explained.</p>

<div class="language-apache highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">&lt;</span><span class="nl">Directory</span><span class="sr"> /var/www/html/aria/finished</span><span class="p">&gt;
</span>	<span class="c"># Various fixes</span>
	<span class="c"># Make sure everything is granted by default</span>
	<span class="c">#  as certain file types might be limited by other config</span>
	<span class="p">&lt;</span><span class="nl">FilesMatch</span><span class="sr"> ".*"</span><span class="p">&gt;
</span>		<span class="nc">Require</span> <span class="ss">all</span> granted
	<span class="p">&lt;/</span><span class="nl">FilesMatch</span><span class="p">&gt;
</span>	<span class="c"># .htaccess should not be read</span>
	<span class="nc">AllowOverride</span> <span class="ss">None</span>
	<span class="c"># No symlinks here as they might lead to odd things unless you want them here ofc</span>
	<span class="nc">Options</span> -FollowSymLinks
	<span class="nc">Options</span> -SymLinksIfOwnerMatch
	<span class="c"># Turn off the feature of trying to correct faulty filenames to similar ones</span>
	<span class="nc">Options</span> -MultiViews

	<span class="c"># Executable code</span>
	<span class="c"># No cgi scripts should be executed here</span>
	<span class="nc">Options</span> -ExecCGI
	<span class="c"># Disable server side includes .shtml</span>
	<span class="nc">Options</span> -Includes
	<span class="nc">Options</span> -IncludesNOEXEC
	<span class="c"># Turn off php in this directory in a way that no .htaccess can turn them on again</span>
	<span class="p">&lt;</span><span class="nl">IfModule</span><span class="sr"> mod_php.c</span><span class="p">&gt;
</span>		php_admin_flag engine <span class="ss">off</span>
	<span class="p">&lt;/</span><span class="nl">IfModule</span><span class="p">&gt;
</span>
	<span class="c"># Directory listings</span>
	<span class="nc">Options</span> +Indexes
	<span class="c"># Good options for directory listing</span>
	<span class="nc">IndexOptions</span> +FancyIndexing +IgnoreCase +ShowForbidden
	<span class="c"># Descending Date is good as the newest files </span>
	<span class="c">#  will be in the top so you do not have to scroll</span>
	<span class="nc">IndexOrderDefault</span> <span class="ss">Descending</span> <span class="ss">Date</span>
	<span class="c"># the README.html should not be automatically be read and shown as part of the listing</span>
	<span class="nc">ReadmeName</span> /
	<span class="c"># The same but the HEADER.html that appears on top</span>
	<span class="nc">HeaderName</span> /
	<span class="c"># Prevent index.html or similar from displaying and hiding the directory listing</span>
	<span class="nc">DirectoryIndex</span> <span class="ss">disabled</span>

	<span class="c"># Content-Type</span>
	<span class="c"># Prevent text/html as that can run code we do not want to</span>
	<span class="c"># Many browsers will assume text/html if no Content-Type is found so we need to be explicit</span>
	<span class="c"># If there is no Content-Type header set to text/plain for viewing rather than download</span>
	<span class="nc">Header</span> <span class="ss">set</span> Content-Type "text/plain" "expr=-z %{CONTENT_TYPE}"
	<span class="c"># If it is not a directory since those always end with slash</span>
	<span class="p">&lt;</span><span class="nl">FilesMatch</span><span class="sr"> "[^/]$"</span><span class="p">&gt;</span> 
		<span class="c"># Set Content-Type to text/plain if it is set to text/html</span>
		<span class="c"># This means that only directory listings can output html</span>
		<span class="nc">Header</span> <span class="ss">set</span> Content-Type "text/plain" "expr=%{CONTENT_TYPE} =~ m|text/html|"
	<span class="p">&lt;/</span><span class="nl">FilesMatch</span><span class="p">&gt;
&lt;/</span><span class="nl">Directory</span><span class="p">&gt;
</span><span class="c"># So there is a certain problem where IndexIgnoreReset does not work in a Directory</span>
<span class="c">#  section therefore defining a Location section instead is needed.</span>
<span class="c"># If you wonder why there just cannot be a single Location section it is</span>
<span class="c"># that FilesMatch and LocationMatch sections are forbidden inside Directory sections.</span>
<span class="p">&lt;</span><span class="nl">Location</span><span class="sr"> "/aria/finished"</span><span class="p">&gt;
</span>	<span class="c"># Reset the index ignore so everything gets listed</span>
	<span class="nc">IndexIgnoreReset</span> <span class="ss">ON</span>
	<span class="c"># Set the ignore to an impossible file to not ignore anything</span>
	<span class="nc">IndexIgnore</span> /
<span class="p">&lt;/</span><span class="nl">Location</span><span class="p">&gt;
</span></code></pre></div></div>

<p>Now we have finally defeated the web server and it will no longer do anything unexpected or strange hopefully.</p>]]></content><author><name>ellietheyeen</name></author><category term="apache" /><summary type="html"><![CDATA[Sometimes you want to configure Apache to really do nothing. No server scripts and just use it as a purely static file server. An example of this would be when you have a Downloads folder and you want to share without there being issues due to how Apache functions.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://github.com/EllieTheYeen.png" /><media:content medium="image" url="https://github.com/EllieTheYeen.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Shell symbol magic</title><link href="https://everydaycompute.github.io/2024/11/01/shell-symbol-magic.html" rel="alternate" type="text/html" title="Shell symbol magic" /><published>2024-11-01T20:48:00+01:00</published><updated>2024-11-01T20:48:00+01:00</updated><id>https://everydaycompute.github.io/2024/11/01/shell-symbol-magic</id><content type="html" xml:base="https://everydaycompute.github.io/2024/11/01/shell-symbol-magic.html"><![CDATA[<p>Shell languages like bash have some interesting syntax that looks like magic as it is just symbols in the syntax and not a single word actually written. This makes writing these things extremely hard to remember or write but once you know them you can do quite some useful things using shells.</p>

<ul id="markdown-toc">
  <li><a href="#setting-up-for-testing" id="markdown-toc-setting-up-for-testing">Setting up for testing</a></li>
  <li><a href="#symbolry" id="markdown-toc-symbolry">Symbolry</a>    <ul>
      <li><a href="#-each-command-line-argument-as-separate-argumemnt" id="markdown-toc--each-command-line-argument-as-separate-argumemnt">”$@” each command line argument as separate argumemnt</a></li>
      <li><a href="#-or--all-shell-args" id="markdown-toc--or--all-shell-args">$* or $@ all shell args</a></li>
      <li><a href="#-all-shell-args-into-one" id="markdown-toc--all-shell-args-into-one">”$*” all shell args into one</a></li>
      <li><a href="#--each-shell-arg-into-separate-argument" id="markdown-toc---each-shell-arg-into-separate-argument">$@ “$@” each shell arg into separate argument</a></li>
      <li><a href="#var-length-of-string" id="markdown-toc-var-length-of-string">${#var} length of string</a></li>
      <li><a href="#arr-length-of-an-array" id="markdown-toc-arr-length-of-an-array">${#arr[@]} length of an array</a></li>
      <li><a href="#arr-all-members-of-array-with-each-element-as-an-argument" id="markdown-toc-arr-all-members-of-array-with-each-element-as-an-argument">”${arr[@]}” all members of array with each element as an argument</a></li>
      <li><a href="#arr-all-members-of-array-with-each-element-as-an-argument-but-losing-spaces" id="markdown-toc-arr-all-members-of-array-with-each-element-as-an-argument-but-losing-spaces">”${arr[@]}” all members of array with each element as an argument but losing spaces</a></li>
      <li><a href="#arr-all-members-of-array-joined-by-space-into-a-single-argument" id="markdown-toc-arr-all-members-of-array-joined-by-space-into-a-single-argument">”${arr[*]}” all members of array joined by space into a single argument</a></li>
      <li><a href="#arr--arr-or-arr-all-members-of-array-but-cut-members-up" id="markdown-toc-arr--arr-or-arr-all-members-of-array-but-cut-members-up">${arr[*]} , “${arr[@]}” or ${arr[@]} all members of array but cut members up</a></li>
      <li><a href="#arrstart-or-arrstartlength-slice-an-array" id="markdown-toc-arrstart-or-arrstartlength-slice-an-array">${arr[@]:start} or ${arr[@]:start:length} slice an array</a></li>
      <li><a href="#varstring-cut-off-beginning" id="markdown-toc-varstring-cut-off-beginning">${var#string} cut off beginning</a></li>
      <li><a href="#varstring-cut-off-end" id="markdown-toc-varstring-cut-off-end">${var%string} cut off end</a></li>
      <li><a href="#var-default-get-value-of-variable-or-return-default-if-empty" id="markdown-toc-var-default-get-value-of-variable-or-return-default-if-empty">${var-default} get value of variable or return default if empty</a></li>
      <li><a href="#vardefault-get-value-of-variable-or-set-default-if-empty" id="markdown-toc-vardefault-get-value-of-variable-or-set-default-if-empty">${var:=default} get value of variable or set default if empty</a></li>
      <li><a href="#varstart-or-varstartlength-substring" id="markdown-toc-varstart-or-varstartlength-substring">${var:start} or ${var:start:length} substring</a></li>
      <li><a href="#var-uppercase-string" id="markdown-toc-var-uppercase-string">${var^^} uppercase string</a></li>
      <li><a href="#var-lowercase-string" id="markdown-toc-var-lowercase-string">${var,,} lowercase string</a></li>
      <li><a href="#--do-math" id="markdown-toc---do-math">$(( )) do math</a></li>
      <li><a href="#vara" id="markdown-toc-vara">${var[@]@A}</a></li>
      <li><a href="#varq" id="markdown-toc-varq">${var[@]@Q}</a></li>
      <li><a href="#----pwd-oldpwd-home" id="markdown-toc-----pwd-oldpwd-home">~- ~+ ~ $PWD $OLDPWD $HOME</a></li>
    </ul>
  </li>
  <li><a href="#end" id="markdown-toc-end">End</a></li>
</ul>

<h2 id="setting-up-for-testing">Setting up for testing</h2>

<p>We are going to focus on Bash for this as there is <code class="language-plaintext highlighter-rouge">dash</code>, <code class="language-plaintext highlighter-rouge">zsh</code> and a bunch of others but what is inside bash is very similar to zsh and works almost identical except a few quirks. Most of these symbol related syntaxes are called expansions or substitutions.</p>

<p>To begin let’s define some variables to use to test these where one is a string, second one a simple array and third is resetting the shell input often called ARGV and is the arguments passed to the current script or function.</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">var</span><span class="o">=</span><span class="s1">'this is a variable with lowercase and UPPERCASE'</span>
<span class="nv">arr</span><span class="o">=(</span><span class="s1">'after '</span> <span class="s1">' before'</span> <span class="s1">' surrounded '</span> <span class="s1">'alone'</span><span class="o">)</span>
<span class="nb">set</span> <span class="s1">'one '</span> <span class="s1">' two '</span> <span class="s1">'three'</span>
</code></pre></div></div>
<p>Also we need to define how to actually display the output which we will do with this where lines starting with <code class="language-plaintext highlighter-rouge">$ </code> are commands being run.</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">printf</span> %q<span class="se">\\</span>n several <span class="s2">"arguments here"</span> to <span class="nb">test</span> <span class="s1">' this '</span>
several
arguments<span class="se">\ </span>here
to
<span class="nb">test</span>
<span class="se">\ </span>this<span class="se">\</span>
</code></pre></div></div>
<p>As it prints one thing per line escaped we can see what is actually shaped by these symbols. Now on to what ones there are.</p>

<h2 id="symbolry">Symbolry</h2>
<p>Let’s get started with the magic symbols.</p>

<h3 id="-each-command-line-argument-as-separate-argumemnt">”$@” each command line argument as separate argumemnt</h3>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">printf</span> %q<span class="se">\\</span>n <span class="s2">"</span><span class="nv">$@</span><span class="s2">"</span>
one<span class="se">\</span>
<span class="se">\ </span>two<span class="se">\</span>
three
</code></pre></div></div>
<p>Good for getting all shell arguments to pass elsewhere.</p>

<h3 id="-or--all-shell-args">$* or $@ all shell args</h3>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">printf</span> %q<span class="se">\\</span>n <span class="nv">$*</span>
one
two
three
<span class="nv">$ </span><span class="nb">set</span> <span class="s1">' a '</span> <span class="s1">'b '</span> <span class="s1">' c d '</span>
a
b
c
d
</code></pre></div></div>
<p>This does same as above but takes away spaces.</p>

<h3 id="-all-shell-args-into-one">”$*” all shell args into one</h3>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">printf</span> %q<span class="se">\\</span>n <span class="s2">"</span><span class="nv">$*</span><span class="s2">"</span>
one<span class="se">\ \ \ </span>two<span class="se">\ \ </span>three
</code></pre></div></div>
<p>Yes this packs everything into a single argument.</p>

<h3 id="--each-shell-arg-into-separate-argument">$@ “$@” each shell arg into separate argument</h3>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">printf</span> %q<span class="se">\\</span>n <span class="s2">"</span><span class="nv">$@</span><span class="s2">"</span>
one<span class="se">\</span>
<span class="se">\ </span>two<span class="se">\</span>
three
</code></pre></div></div>

<h3 id="var-length-of-string">${#var} length of string</h3>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">printf</span> %q<span class="se">\\</span>n <span class="s2">"</span><span class="k">${#</span><span class="nv">var</span><span class="k">}</span><span class="s2">"</span>
47
</code></pre></div></div>
<p>Yes the length.</p>

<h3 id="arr-length-of-an-array">${#arr[@]} length of an array</h3>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">printf</span> %q<span class="se">\\</span>n <span class="s2">"</span><span class="k">${#</span><span class="nv">arr</span><span class="p">[@]</span><span class="k">}</span><span class="s2">"</span>
4
</code></pre></div></div>
<p>Yep the length.</p>

<h3 id="arr-all-members-of-array-with-each-element-as-an-argument">”${arr[@]}” all members of array with each element as an argument</h3>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">printf</span> %q<span class="se">\\</span>n <span class="s2">"</span><span class="k">${</span><span class="nv">arr</span><span class="p">[@]</span><span class="k">}</span><span class="s2">"</span>
after<span class="se">\</span>
<span class="se">\ </span>before
<span class="se">\ </span>surrounded<span class="se">\</span>
alone
</code></pre></div></div>

<h3 id="arr-all-members-of-array-with-each-element-as-an-argument-but-losing-spaces">”${arr[@]}” all members of array with each element as an argument but losing spaces</h3>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">printf</span> %q<span class="se">\\</span>n <span class="k">${</span><span class="nv">arr</span><span class="p">[@]</span><span class="k">}</span>
after
before
surrounded
alone
</code></pre></div></div>

<h3 id="arr-all-members-of-array-joined-by-space-into-a-single-argument">”${arr[*]}” all members of array joined by space into a single argument</h3>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">printf</span> %q<span class="se">\\</span>n <span class="s2">"</span><span class="k">${</span><span class="nv">arr</span><span class="p">[*]</span><span class="k">}</span><span class="s2">"</span>
after<span class="se">\ \ \ </span>before<span class="se">\ \ </span>surrounded<span class="se">\ \ </span>alone
</code></pre></div></div>
<p>Good for joining arrays.</p>

<h3 id="arr--arr-or-arr-all-members-of-array-but-cut-members-up">${arr[*]} , “${arr[@]}” or ${arr[@]} all members of array but cut members up</h3>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">printf</span> %q<span class="se">\\</span>n <span class="k">${</span><span class="nv">arr</span><span class="p">[*]</span><span class="k">}</span>
after<span class="se">\</span>
<span class="se">\ </span>before
<span class="se">\ </span>surrounded<span class="se">\</span>
alone
<span class="nv">$ </span><span class="nb">printf</span> %q<span class="se">\\</span>n <span class="k">${</span><span class="nv">arr</span><span class="p">[@]</span><span class="k">}</span>
after<span class="se">\</span>
<span class="se">\ </span>before
<span class="se">\ </span>surrounded<span class="se">\</span>
alone
<span class="nv">$ </span><span class="nb">printf</span> %q<span class="se">\\</span>n <span class="s2">"</span><span class="k">${</span><span class="nv">arr</span><span class="p">[@]</span><span class="k">}</span><span class="s2">"</span>
after<span class="se">\</span>
<span class="se">\ </span>before
<span class="se">\ </span>surrounded<span class="se">\</span>
alone
</code></pre></div></div>

<h3 id="arrstart-or-arrstartlength-slice-an-array">${arr[@]:start} or ${arr[@]:start:length} slice an array</h3>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">printf</span> %q<span class="se">\\</span>n <span class="s2">"</span><span class="k">${</span><span class="nv">arr</span><span class="p">[@]</span>:2<span class="k">}</span><span class="s2">"</span>
<span class="se">\ </span>surrounded<span class="se">\</span>
alone
<span class="nv">$ </span><span class="nb">printf</span> %q<span class="se">\\</span>n <span class="s2">"</span><span class="k">${</span><span class="nv">arr</span><span class="p">[@]</span>:2:1<span class="k">}</span><span class="s2">"</span>
<span class="se">\ </span>surrounded<span class="se">\</span>
<span class="nv">$ </span><span class="nb">printf</span> %q<span class="se">\\</span>n <span class="k">${</span><span class="nv">arr</span><span class="p">[@]</span>:1:1<span class="k">}</span>
<span class="se">\ </span>before
<span class="nv">$ </span><span class="nb">printf</span> %q<span class="se">\\</span>n <span class="k">${</span><span class="nv">arr</span><span class="p">[@]</span>:3<span class="k">}</span>
alone
</code></pre></div></div>

<h3 id="varstring-cut-off-beginning">${var#string} cut off beginning</h3>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">printf</span> %q<span class="se">\\</span>n <span class="k">${</span><span class="nv">var</span><span class="p">#</span><span class="k">}</span>
this<span class="se">\ </span>is<span class="se">\ </span>a<span class="se">\ </span>variable<span class="se">\ </span>with<span class="se">\ </span>lowercase<span class="se">\ </span>and<span class="se">\ </span>UPPERCASE
<span class="nv">$ </span><span class="nb">printf</span> %q<span class="se">\\</span>n <span class="k">${</span><span class="nv">var</span><span class="p">#var</span><span class="k">}</span>
this<span class="se">\ </span>is<span class="se">\ </span>a<span class="se">\ </span>variable<span class="se">\ </span>with<span class="se">\ </span>lowercase<span class="se">\ </span>and<span class="se">\ </span>UPPERCASE
<span class="nv">$ </span><span class="nb">printf</span> %q<span class="se">\\</span>n <span class="k">${</span><span class="nv">var</span><span class="p">#*var</span><span class="k">}</span>
iable<span class="se">\ </span>with<span class="se">\ </span>lowercase<span class="se">\ </span>and<span class="se">\ </span>UPPERCASE
<span class="nv">$ </span><span class="nb">printf</span> %q<span class="se">\\</span>n <span class="k">${</span><span class="nv">var</span><span class="p">#this</span><span class="k">}</span>
<span class="se">\ </span>is<span class="se">\ </span>a<span class="se">\ </span>variable<span class="se">\ </span>with<span class="se">\ </span>lowercase<span class="se">\ </span>and<span class="se">\ </span>UPPERCASE
<span class="nv">$ </span><span class="nb">printf</span> %q<span class="se">\\</span>n <span class="k">${</span><span class="nv">var</span><span class="p">#</span><span class="k">}</span>
this<span class="se">\ </span>is<span class="se">\ </span>a<span class="se">\ </span>variable<span class="se">\ </span>with<span class="se">\ </span>lowercase<span class="se">\ </span>and<span class="se">\ </span>UPPERCASE
<span class="nv">$ </span><span class="nb">printf</span> %q<span class="se">\\</span>n <span class="k">${</span><span class="nv">var</span><span class="p">#*var</span><span class="k">}</span>
iable<span class="se">\ </span>with<span class="se">\ </span>lowercase<span class="se">\ </span>and<span class="se">\ </span>UPPERCASE
</code></pre></div></div>
<p>Quite convenient substring like feature.</p>

<h3 id="varstring-cut-off-end">${var%string} cut off end</h3>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">printf</span> %q<span class="se">\\</span>n <span class="k">${</span><span class="nv">var</span><span class="p">%and*</span><span class="k">}</span>
this<span class="se">\ </span>is<span class="se">\ </span>a<span class="se">\ </span>variable<span class="se">\ </span>with<span class="se">\ </span>lowercase<span class="se">\</span>
<span class="nv">$ </span><span class="nb">printf</span> %q<span class="se">\\</span>n <span class="k">${</span><span class="nv">var</span><span class="p">%with*</span><span class="k">}</span>
this<span class="se">\ </span>is<span class="se">\ </span>a<span class="se">\ </span>variable<span class="se">\</span>
<span class="nv">$ </span><span class="nb">printf</span> %q<span class="se">\\</span>n <span class="k">${</span><span class="nv">var</span><span class="p">%CASE</span><span class="k">}</span>
this<span class="se">\ </span>is<span class="se">\ </span>a<span class="se">\ </span>variable<span class="se">\ </span>with<span class="se">\ </span>lowercase<span class="se">\ </span>and<span class="se">\ </span>UPPER
<span class="nv">$ </span><span class="nb">printf</span> %q<span class="se">\\</span>n <span class="k">${</span><span class="nv">var</span><span class="p">%low*</span><span class="k">}</span>
this<span class="se">\ </span>is<span class="se">\ </span>a<span class="se">\ </span>variable<span class="se">\ </span>with<span class="se">\</span>
<span class="nv">$ </span><span class="nb">printf</span> %q<span class="se">\\</span>n <span class="k">${</span><span class="nv">var</span><span class="p">% *</span><span class="k">}</span>
this<span class="se">\ </span>is<span class="se">\ </span>a<span class="se">\ </span>variable<span class="se">\ </span>with<span class="se">\ </span>lowercase<span class="se">\ </span>and
</code></pre></div></div>
<p>Quite useful but might be hard to figure out</p>

<h3 id="var-default-get-value-of-variable-or-return-default-if-empty">${var-default} get value of variable or return default if empty</h3>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">printf</span> %q<span class="se">\\</span>n <span class="k">${</span><span class="nv">var</span><span class="p">-default</span><span class="k">}</span>
this<span class="se">\ </span>is<span class="se">\ </span>a<span class="se">\ </span>variable<span class="se">\ </span>with<span class="se">\ </span>lowercase<span class="se">\ </span>and<span class="se">\ </span>UPPERCASE
<span class="nv">$ </span><span class="nb">printf</span> %q<span class="se">\\</span>n <span class="k">${</span><span class="nv">nonexistent</span><span class="p">-default</span><span class="k">}</span>
default
</code></pre></div></div>
<p>Good when a variable might not be set.</p>

<h3 id="vardefault-get-value-of-variable-or-set-default-if-empty">${var:=default} get value of variable or set default if empty</h3>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">printf</span> %q<span class="se">\\</span>n <span class="k">${</span><span class="nv">var</span>:<span class="p">=default value</span><span class="k">}</span>
this<span class="se">\ </span>is<span class="se">\ </span>a<span class="se">\ </span>variable<span class="se">\ </span>with<span class="se">\ </span>lowercase<span class="se">\ </span>and<span class="se">\ </span>UPPERCASE
<span class="nv">$ </span><span class="nb">printf</span> %q<span class="se">\\</span>n <span class="k">${</span><span class="nv">varr</span>:<span class="p">=default value</span><span class="k">}</span>
default<span class="se">\ </span>value
<span class="nv">$ </span><span class="nb">printf</span> %q<span class="se">\\</span>n <span class="k">${</span><span class="nv">varr</span><span class="k">}</span>
default<span class="se">\ </span>value
</code></pre></div></div>
<p>Similar to Python’s <code class="language-plaintext highlighter-rouge">dict.setdefault</code>.</p>

<h3 id="varstart-or-varstartlength-substring">${var:start} or ${var:start:length} substring</h3>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">printf</span> %q<span class="se">\\</span>n <span class="k">${</span><span class="nv">var</span>:10<span class="k">}</span>
variable<span class="se">\ </span>with<span class="se">\ </span>lowercase<span class="se">\ </span>and<span class="se">\ </span>UPPERCASE
<span class="nv">$ </span><span class="nb">printf</span> %q<span class="se">\\</span>n <span class="k">${</span><span class="nv">var</span>:10:6<span class="k">}</span>
variab
<span class="nv">$ </span><span class="nb">printf</span> %q<span class="se">\\</span>n <span class="k">${</span><span class="nv">var</span>:1:10<span class="k">}</span>
his<span class="se">\ </span>is<span class="se">\ </span>a<span class="se">\ </span>v
</code></pre></div></div>
<p>Fully functional substring with a length argument that is better than those that want you to specify the end.</p>

<h3 id="var-uppercase-string">${var^^} uppercase string</h3>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">printf</span> %q<span class="se">\\</span>n <span class="k">${</span><span class="nv">var</span><span class="p">^^</span><span class="k">}</span>
THIS<span class="se">\ </span>IS<span class="se">\ </span>A<span class="se">\ </span>VARIABLE<span class="se">\ </span>WITH<span class="se">\ </span>LOWERCASE<span class="se">\ </span>AND<span class="se">\ </span>UPPERCASE
</code></pre></div></div>
<p>VERY!</p>

<h3 id="var-lowercase-string">${var,,} lowercase string</h3>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">printf</span> %q<span class="se">\\</span>n <span class="k">${</span><span class="nv">var</span><span class="p">,,</span><span class="k">}</span>
this<span class="se">\ </span>is<span class="se">\ </span>a<span class="se">\ </span>variable<span class="se">\ </span>with<span class="se">\ </span>lowercase<span class="se">\ </span>and<span class="se">\ </span>uppercase
</code></pre></div></div>
<p>no uppercase anymore.</p>

<h3 id="--do-math">$(( )) do math</h3>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">printf</span> %q<span class="se">\\</span>n <span class="k">$((</span> <span class="m">42</span> <span class="o">-</span> <span class="m">69</span> <span class="o">+</span> <span class="m">2</span> <span class="o">+</span> <span class="m">1337</span> <span class="k">))</span>
1312
</code></pre></div></div>
<p>Precisely what it says.</p>

<h3 id="vara">${var[@]@A}</h3>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">echo</span> <span class="k">${</span><span class="nv">var</span><span class="p">@A</span><span class="k">}</span>
<span class="nv">var</span><span class="o">=</span><span class="s1">'this is a variable with lowercase and UPPERCASE'</span>
<span class="nv">$ </span><span class="nb">echo</span> <span class="k">${</span><span class="nv">arr</span><span class="p">[@]@A</span><span class="k">}</span>
<span class="nb">declare</span> <span class="nt">-a</span> <span class="nv">arr</span><span class="o">=([</span>0]<span class="o">=</span><span class="s2">"after "</span> <span class="o">[</span>1]<span class="o">=</span><span class="s2">" before"</span> <span class="o">[</span>2]<span class="o">=</span><span class="s2">" surrounded "</span> <span class="o">[</span>3]<span class="o">=</span><span class="s2">"alone"</span><span class="o">)</span>
</code></pre></div></div>
<p>Notice the echo here but also yes this gives the array definition or string definition needed to properly export the variable</p>

<h3 id="varq">${var[@]@Q}</h3>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">echo</span> <span class="k">${</span><span class="nv">var</span><span class="p">@Q</span><span class="k">}</span>
<span class="s1">'this is a variable with lowercase and UPPERCASE'</span>
<span class="nv">$ </span><span class="nb">echo</span> <span class="k">${</span><span class="nv">arr</span><span class="p">[*]@Q</span><span class="k">}</span>
<span class="s1">'after '</span> <span class="s1">' before'</span> <span class="s1">' surrounded '</span> <span class="s1">'alone'</span>
<span class="nv">$ </span><span class="nb">echo</span> <span class="k">${</span><span class="nv">arr</span><span class="p">[@]@Q</span><span class="k">}</span>
<span class="s1">'after '</span> <span class="s1">' before'</span> <span class="s1">' surrounded '</span> <span class="s1">'alone'</span>
</code></pre></div></div>
<p>This quotes stuff.</p>

<h3 id="----pwd-oldpwd-home">~- ~+ ~ $PWD $OLDPWD $HOME</h3>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">printf</span> %q<span class="se">\\</span>n ~- ~+ ~ <span class="nv">$PWD</span> <span class="nv">$OLDPWD</span> <span class="nv">$HOME</span>
/home
/home/pi
/home/pi
/home/pi
/home
/home/pi
</code></pre></div></div>

<h2 id="end">End</h2>
<p>This shows that shells do indeed have quite some features that can be used for quite a few tasks and while many of these tricks do not work in zsh it has its own magic.</p>]]></content><author><name>ellietheyeen</name></author><category term="shell" /><category term="bash" /><category term="zsh" /><summary type="html"><![CDATA[Shell languages like bash have some interesting syntax that looks like magic as it is just symbols in the syntax and not a single word actually written. This makes writing these things extremely hard to remember or write but once you know them you can do quite some useful things using shells.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://github.com/EllieTheYeen.png" /><media:content medium="image" url="https://github.com/EllieTheYeen.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Downloader browser extension for aria2</title><link href="https://everydaycompute.github.io/2024/10/29/downloader-browser-extension.html" rel="alternate" type="text/html" title="Downloader browser extension for aria2" /><published>2024-10-29T00:00:00+01:00</published><updated>2024-10-29T00:00:00+01:00</updated><id>https://everydaycompute.github.io/2024/10/29/downloader-browser-extension</id><content type="html" xml:base="https://everydaycompute.github.io/2024/10/29/downloader-browser-extension.html"><![CDATA[<p>So previously we looked at how to <a href="/2024/10/28/hardlink-finished-files.html">hardlink downloaded files in aria2</a> but this time we are going to look how to make a simple browser extension to quickly add anything you want to the download queue.</p>

<p>For this I recommend you use <a href="https://www.mozilla.org/en-US/firefox/developer/">Mozilla Firefox Developer Edition</a> and go into <code class="language-plaintext highlighter-rouge">about:config</code> in the address bar and set <code class="language-plaintext highlighter-rouge">xpinstall.signatures.required</code> to <code class="language-plaintext highlighter-rouge">false</code> or you can use Google Chrome. The reason for this is that if you use the standard Firefox it will not properly accept unsigned plugins or it might uninstall them whenever you restart Firefox.</p>

<ul id="markdown-toc">
  <li><a href="#cors-and-config-issues" id="markdown-toc-cors-and-config-issues">CORS and config issues</a></li>
  <li><a href="#apache-as-cors-proxy" id="markdown-toc-apache-as-cors-proxy">Apache as CORS proxy</a></li>
  <li><a href="#the-extension" id="markdown-toc-the-extension">The extension</a></li>
</ul>

<h2 id="cors-and-config-issues">CORS and config issues</h2>

<p>Next there is a thing we must get to function and that is CORS which stands for Cross Origin Resource Sharing and that is a special set of headers to send client side HTTP requests inside a browser to a different domain than the page is on.</p>

<p>There is a in <code class="language-plaintext highlighter-rouge">aria2.conf</code> that will supposedly fix that</p>
<div class="language-ini highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="py">rpc-allow-origin-all</span><span class="p">=</span><span class="s">true</span>
</code></pre></div></div>
<p>that is if it actually helped in this situation. I never got this to properly to work and it seems that one of the issues is that it really does try to use HTTPS at all times which breaks things. There are some things that should be possible in setting the setting <code class="language-plaintext highlighter-rouge">rpc-secure</code> to fix things but that requires many options to be set properly so we are doing it another way.</p>

<h2 id="apache-as-cors-proxy">Apache as CORS proxy</h2>

<p>What we are going to do instead as a workaround is make an apache CORS proxy. Start by making sure you have apache installed which you can install by using</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>apt <span class="nb">install </span>apache2
</code></pre></div></div>
<p>Next we must make sure certain mods are enabled with the following command</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>a2enmod headers proxy_http ssl
</code></pre></div></div>
<p>Now outside any VirtualHost section we should set this and it can sort of be inside any .conf file in <code class="language-plaintext highlighter-rouge">/etc/apache2/apache2.conf</code> in the end</p>
<div class="language-apache highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">&lt;</span><span class="nl">Location</span><span class="sr"> /ariarpc</span><span class="p">&gt;
</span>  <span class="nc">ProxyPass</span> http://127.0.0.1:6800/jsonrpc
  <span class="nc">Header</span> <span class="ss">setifempty</span> Access-Control-Allow-Origin "*"
  <span class="nc">Header</span> <span class="ss">setifempty</span> Access-Control-Allow-Headers "*"
<span class="p">&lt;/</span><span class="nl">Location</span><span class="p">&gt;
</span></code></pre></div></div>
<p>Now we must create a <code class="language-plaintext highlighter-rouge">VirtualHost</code> section for the SSL that the extension we are creating insists on using. It tends to exist at <code class="language-plaintext highlighter-rouge">/etc/apache2/sites-enabled/000-default.conf</code> so creating another virtual host there or in a file beside it might be good but ensure both virtual hosts exists where one has the content below.</p>
<div class="language-apache highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">&lt;</span><span class="nl">VirtualHost</span><span class="sr"> *:443</span><span class="p">&gt;
</span>        <span class="nc">SSLEngine</span> <span class="ss">on</span>
        <span class="nc">SSLCertificateFile</span>    /etc/ssl/certs/ssl-cert-snakeoil.pem
        <span class="nc">SSLCertificateKeyFile</span> /etc/ssl/private/ssl-cert-snakeoil.key
        <span class="nc">SSLCertificateChainFile</span> /etc/ssl/certs/ssl-cert-snakeoil.pem

        <span class="nc">ServerName</span> smol

        <span class="nc">ServerAdmin</span> webmaster@localhost
        <span class="nc">DocumentRoot</span> /var/www/html

        <span class="p">&lt;</span><span class="nl">Directory</span><span class="sr"> /var/www/html</span><span class="p">&gt;
</span>            <span class="nc">AllowOverride</span> <span class="ss">All</span>
        <span class="p">&lt;/</span><span class="nl">Directory</span><span class="p">&gt;
</span>
        <span class="nc">ErrorLog</span> ${APACHE_LOG_DIR}/error.log
        <span class="nc">CustomLog</span> ${APACHE_LOG_DIR}/access.log combined
<span class="p">&lt;/</span><span class="nl">VirtualHost</span><span class="p">&gt;
</span></code></pre></div></div>
<p>There is a risk that the selt signed cert is not there but you can <a href="https://www.baeldung.com/openssl-self-signed-cert">generate it with the openssl command</a> if needed.</p>

<p>Now we only need to restart apache and go to <code class="language-plaintext highlighter-rouge">https://192.168.0.44/ariarpc</code> or whatever the address is to your host and press to accept the fault certificate which we will need to have accepted for the extension to b e able to use it.</p>

<h2 id="the-extension">The extension</h2>
<p>Now for the actual extension we need to create a zip file that has no subdirectories but does contain a few files called <code class="language-plaintext highlighter-rouge">manifest.json</code>, <code class="language-plaintext highlighter-rouge">icon.png</code> and <code class="language-plaintext highlighter-rouge">background.js</code>. For the icon just make anything really an image that is maybe 100x100 or so. In the manifest we can place the following to make sure the permissions are right and everything.</p>

<p><code class="language-plaintext highlighter-rouge">manifest.json</code></p>
<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
    </span><span class="nl">"background"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
        </span><span class="nl">"scripts"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
            </span><span class="s2">"background.js"</span><span class="w">
        </span><span class="p">]</span><span class="w">
    </span><span class="p">},</span><span class="w">
    </span><span class="nl">"action"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
        </span><span class="nl">"default_icon"</span><span class="p">:</span><span class="w"> </span><span class="s2">"icon.png"</span><span class="p">,</span><span class="w">
        </span><span class="nl">"default_title"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Share"</span><span class="w">
    </span><span class="p">},</span><span class="w">
    </span><span class="nl">"browser_specific_settings"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
        </span><span class="nl">"gecko"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
            </span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="s2">"downloadaddon@example.com"</span><span class="w">
        </span><span class="p">}</span><span class="w">
    </span><span class="p">},</span><span class="w">
    </span><span class="nl">"description"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Download Addon just for testing"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"icons"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
        </span><span class="nl">"128"</span><span class="p">:</span><span class="w"> </span><span class="s2">"icon.png"</span><span class="w">
    </span><span class="p">},</span><span class="w">
    </span><span class="nl">"manifest_version"</span><span class="p">:</span><span class="w"> </span><span class="mi">3</span><span class="p">,</span><span class="w">
    </span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Download Addon"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"permissions"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
        </span><span class="s2">"contextMenus"</span><span class="p">,</span><span class="w">
        </span><span class="s2">"notifications"</span><span class="w">
    </span><span class="p">],</span><span class="w">
    </span><span class="nl">"host_permissions"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
        </span><span class="s2">"&lt;all_urls&gt;"</span><span class="w">
    </span><span class="p">],</span><span class="w">
    </span><span class="nl">"version"</span><span class="p">:</span><span class="w"> </span><span class="s2">"1.0"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>The actual script here will do the thing of creating a context menu with you can open with the second mouse button over links or images or pages and then it should send the request to your NAS or whatever has apache and aria2 on it but make sure to set the password and the address in the line with <code class="language-plaintext highlighter-rouge">xhr.open</code> in it.</p>

<p><code class="language-plaintext highlighter-rouge">background.js</code></p>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">context</span><span class="p">(</span><span class="nx">event</span><span class="p">,</span> <span class="nx">tab</span><span class="p">)</span> <span class="p">{</span>
    <span class="kd">var</span> <span class="nx">url</span> <span class="o">=</span> <span class="nx">event</span><span class="p">.</span><span class="nx">pageUrl</span><span class="p">;</span>
	<span class="k">if</span> <span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">menuItemId</span> <span class="o">===</span> <span class="dl">"</span><span class="s2">link</span><span class="dl">"</span><span class="p">)</span> <span class="p">{</span>
		<span class="nx">url</span> <span class="o">=</span> <span class="nx">event</span><span class="p">.</span><span class="nx">linkUrl</span><span class="p">;</span>
	<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">menuItemId</span> <span class="o">===</span> <span class="dl">"</span><span class="s2">image</span><span class="dl">"</span><span class="p">)</span> <span class="p">{</span>
		<span class="nx">url</span> <span class="o">=</span> <span class="nx">event</span><span class="p">.</span><span class="nx">srcUrl</span>
	<span class="p">}</span>

	<span class="kd">var</span> <span class="nx">data</span> <span class="o">=</span> <span class="p">{</span>
		<span class="dl">"</span><span class="s2">jsonrpc</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">2.0</span><span class="dl">"</span><span class="p">,</span>
		<span class="dl">"</span><span class="s2">id</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">whatever</span><span class="dl">"</span><span class="p">,</span>
		<span class="dl">"</span><span class="s2">method</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">aria2.addUri</span><span class="dl">"</span><span class="p">,</span>
		<span class="dl">"</span><span class="s2">params</span><span class="dl">"</span><span class="p">:</span> <span class="p">[</span><span class="s2">`token:</span><span class="p">${</span><span class="nx">token</span><span class="p">}</span><span class="s2">`</span><span class="p">,</span> <span class="p">[</span><span class="nx">url</span><span class="p">]],</span>
	<span class="p">};</span>

	<span class="kd">var</span> <span class="nx">xhr</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">XMLHttpRequest</span><span class="p">();</span>
	<span class="nx">xhr</span><span class="p">.</span><span class="nx">onreadystatechange</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
		<span class="k">if</span> <span class="p">(</span><span class="nx">xhr</span><span class="p">.</span><span class="nx">readyState</span> <span class="o">!==</span> <span class="mi">4</span><span class="p">)</span> <span class="k">return</span><span class="p">;</span>
		<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">xhr</span><span class="p">.</span><span class="nx">responseText</span><span class="p">);</span>
		<span class="nx">chrome</span><span class="p">.</span><span class="nx">notifications</span><span class="p">.</span><span class="nx">create</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="p">{</span>
			<span class="dl">"</span><span class="s2">message</span><span class="dl">"</span><span class="p">:</span> <span class="nx">xhr</span><span class="p">.</span><span class="nx">responseText</span><span class="p">,</span>
			<span class="dl">"</span><span class="s2">title</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Download</span><span class="dl">"</span><span class="p">,</span>
			<span class="dl">"</span><span class="s2">iconUrl</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">icon.png</span><span class="dl">"</span><span class="p">,</span>
			<span class="dl">"</span><span class="s2">type</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">basic</span><span class="dl">"</span><span class="p">,</span>
		<span class="p">})</span>
	<span class="p">};</span>
	<span class="nx">xhr</span><span class="p">.</span><span class="nx">open</span><span class="p">(</span><span class="dl">"</span><span class="s2">POST</span><span class="dl">"</span><span class="p">,</span> <span class="dl">"</span><span class="s2">http://192.168.0.44/ariarpc</span><span class="dl">"</span><span class="p">);</span>
	<span class="nx">xhr</span><span class="p">.</span><span class="nx">setRequestHeader</span><span class="p">(</span><span class="dl">"</span><span class="s2">Content-Type</span><span class="dl">"</span><span class="p">,</span> <span class="dl">"</span><span class="s2">application/json</span><span class="dl">"</span><span class="p">);</span>
	<span class="nx">xhr</span><span class="p">.</span><span class="nx">send</span><span class="p">(</span><span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="nx">data</span><span class="p">));</span>
<span class="p">}</span>

<span class="nx">browser</span><span class="p">.</span><span class="nx">contextMenus</span><span class="p">.</span><span class="nx">create</span><span class="p">({</span>
	<span class="dl">"</span><span class="s2">title</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Download page</span><span class="dl">"</span><span class="p">,</span>
	<span class="dl">"</span><span class="s2">id</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">page</span><span class="dl">"</span><span class="p">,</span>
	<span class="dl">"</span><span class="s2">contexts</span><span class="dl">"</span><span class="p">:</span> <span class="p">[</span><span class="dl">"</span><span class="s2">page</span><span class="dl">"</span><span class="p">]</span>
<span class="p">},</span>
	<span class="p">()</span> <span class="o">=&gt;</span> <span class="k">void</span> <span class="nx">browser</span><span class="p">.</span><span class="nx">runtime</span><span class="p">.</span><span class="nx">lastError</span><span class="p">,</span>
<span class="p">);</span>

<span class="nx">browser</span><span class="p">.</span><span class="nx">contextMenus</span><span class="p">.</span><span class="nx">create</span><span class="p">({</span>
	<span class="dl">"</span><span class="s2">title</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Download link</span><span class="dl">"</span><span class="p">,</span>
	<span class="dl">"</span><span class="s2">id</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">link</span><span class="dl">"</span><span class="p">,</span>
	<span class="dl">"</span><span class="s2">contexts</span><span class="dl">"</span><span class="p">:</span> <span class="p">[</span><span class="dl">"</span><span class="s2">link</span><span class="dl">"</span><span class="p">]</span>
<span class="p">},</span>
	<span class="p">()</span> <span class="o">=&gt;</span> <span class="k">void</span> <span class="nx">browser</span><span class="p">.</span><span class="nx">runtime</span><span class="p">.</span><span class="nx">lastError</span><span class="p">,</span>
<span class="p">);</span>

<span class="nx">browser</span><span class="p">.</span><span class="nx">contextMenus</span><span class="p">.</span><span class="nx">create</span><span class="p">({</span>
	<span class="dl">"</span><span class="s2">title</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Download image</span><span class="dl">"</span><span class="p">,</span>
	<span class="dl">"</span><span class="s2">id</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">image</span><span class="dl">"</span><span class="p">,</span>
	<span class="dl">"</span><span class="s2">contexts</span><span class="dl">"</span><span class="p">:</span> <span class="p">[</span><span class="dl">"</span><span class="s2">image</span><span class="dl">"</span><span class="p">]</span>
<span class="p">},</span>
	<span class="p">()</span> <span class="o">=&gt;</span> <span class="k">void</span> <span class="nx">browser</span><span class="p">.</span><span class="nx">runtime</span><span class="p">.</span><span class="nx">lastError</span><span class="p">,</span>
<span class="p">);</span>

<span class="nx">browser</span><span class="p">.</span><span class="nx">contextMenus</span><span class="p">.</span><span class="nx">onClicked</span><span class="p">.</span><span class="nx">addListener</span><span class="p">(</span><span class="nx">context</span><span class="p">)</span>

<span class="kd">var</span> <span class="nx">token</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">YourPasswordHerePleaseChange</span><span class="dl">"</span><span class="p">;</span>
</code></pre></div></div>

<p>Now all of the 3 files should be inside the zip and now you are going to rename the zip file to anything with the <code class="language-plaintext highlighter-rouge">.xpi</code> ending and next you can run it inside Firefox Developer Edition by dragging it into tab or setting xpi files to run using it. Now go to any page and second clicking on anything at all like a link, an image or the page it self will give you a context menu to download it. Tell how your experience was in the comments if you decide to try this.</p>]]></content><author><name>ellietheyeen</name></author><category term="browserextensions" /><category term="javascript" /><category term="apache" /><category term="proxy" /><category term="aria2" /><summary type="html"><![CDATA[So previously we looked at how to hardlink downloaded files in aria2 but this time we are going to look how to make a simple browser extension to quickly add anything you want to the download queue.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://github.com/EllieTheYeen.png" /><media:content medium="image" url="https://github.com/EllieTheYeen.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Hardlink finished files in aria2</title><link href="https://everydaycompute.github.io/2024/10/28/hardlink-finished-files.html" rel="alternate" type="text/html" title="Hardlink finished files in aria2" /><published>2024-10-28T14:21:00+01:00</published><updated>2024-10-28T14:21:00+01:00</updated><id>https://everydaycompute.github.io/2024/10/28/hardlink-finished-files</id><content type="html" xml:base="https://everydaycompute.github.io/2024/10/28/hardlink-finished-files.html"><![CDATA[<p>So I recently started to use the <a href="https://aria2.github.io/">aria2</a> download manager since my NAS is starting to really break down at this point but there is one single feature it lacks. That feature is to be able to move finished files into a different directory. With torrents this tends to be somewhat hard to do since they have a seeding phase after the download phase and only the application itself is allowed to move the files during that phase as otherwise it cannot upload them to other users.</p>

<ul id="markdown-toc">
  <li><a href="#about-links" id="markdown-toc-about-links">About links</a></li>
  <li><a href="#aria2" id="markdown-toc-aria2">aria2</a></li>
  <li><a href="#more" id="markdown-toc-more">More</a></li>
</ul>

<h2 id="about-links">About links</h2>

<p>To solve this there was several things to consider. One thing was that if I moved the files that would be an issue since seeding. If I copied the files there was another issue of them taking up double the amount of space. However there is a third and even a fourth option. The third option is to make a symbolic link that acts just like that file in almost every single case except one where the files are moved or copied by a tool that is aware of those being links and then fail to copy the actual files. Therefore we are using a fourth option which is called a hard link.</p>

<p>A hard link is a very nifty feature where a file can exist in many places at once similarly to a value inside a programming language that is garbage collected. Similarly if all hard links to a file is removed the file is essentially gone from the file system and might be overwritten. Due to how this works if you create another link to the same file it will not take up all that files space and instead it just takes up a few bytes extra.</p>

<p>To create any form of link on a Linux system we will use the <code class="language-plaintext highlighter-rouge">ln</code> command which stands for link. The ln command has a bunch of flags like <code class="language-plaintext highlighter-rouge">-f</code> to forefully place a file destroying the previous file at target if necessary and <code class="language-plaintext highlighter-rouge">-s</code> which makes links symbolic. To use the command the first argument should be the path to the target source file which the newly created link should lead to and the second argument is where that link should be placed. The links can be relative paths or absolute but make sure you are specifying the correct path as of when the link is used as compared to when the link is created or just use absolute paths.</p>

<h2 id="aria2">aria2</h2>

<p>Back to what we need to do with aria for this. Let’s go to the home directory and make sure the directory <code class="language-plaintext highlighter-rouge">.aria2</code> exists and inside it there should be a file called <code class="language-plaintext highlighter-rouge">aria2.conf</code> which you shoulc create if not existing.</p>

<p><code class="language-plaintext highlighter-rouge">/home/yeen/.aria2/aria2.conf</code></p>
<div class="language-ini highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="py">on-bt-download-complete</span><span class="p">=</span><span class="s">/home/yeen/.aria2/done.sh</span>
<span class="py">on-download-complete</span><span class="p">=</span><span class="s">/home/yeen/.aria2/done.sh</span>
<span class="py">dir</span><span class="p">=</span><span class="s">/home/yeen/Downloads/aria/unfinished</span>
</code></pre></div></div>
<p>As you see my username is yeen but change it to what yours is. Also notice <code class="language-plaintext highlighter-rouge">done.sh</code> which we are also going to create which you can do with any text editor really but make sure you do <code class="language-plaintext highlighter-rouge">chmod +x done.sh</code> to make sure it is executable and here is the contents of it.</p>

<p><code class="language-plaintext highlighter-rouge">/home/yeen/.aria2/done.sh</code></p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/bin/bash</span>
<span class="nb">cd</span> <span class="s2">"</span><span class="si">$(</span><span class="nb">dirname</span> <span class="s2">"</span><span class="nv">$0</span><span class="s2">"</span><span class="si">)</span><span class="s2">"</span>

<span class="nv">uid</span><span class="o">=</span><span class="s2">"</span><span class="nv">$1</span><span class="s2">"</span>
<span class="nv">code</span><span class="o">=</span><span class="s2">"</span><span class="nv">$2</span><span class="s2">"</span>
<span class="nv">file</span><span class="o">=</span><span class="s2">"</span><span class="nv">$3</span><span class="s2">"</span>

<span class="nv">srcdir</span><span class="o">=</span><span class="s1">'/home/yeen/Downloads/aria/unfinished/'</span>
<span class="nv">dstdir</span><span class="o">=</span><span class="s1">'/home/yeen/Downloads/aria/finished/'</span>

<span class="c"># If file does not start with srcdir which</span>
<span class="c">#  would mean it is not inside the correct folder then exit</span>
<span class="k">if</span> <span class="o">[[</span> <span class="s2">"</span><span class="nv">$file</span><span class="s2">"</span> <span class="o">!=</span> <span class="s2">"</span><span class="nv">$srcdir</span><span class="s2">"</span><span class="k">*</span> <span class="o">]]</span><span class="p">;</span> <span class="k">then
    </span><span class="nb">exit </span>1
<span class="k">fi</span>
<span class="c"># If $file is not a file then exit</span>
<span class="k">if</span> <span class="o">[[</span> <span class="o">!</span> <span class="nt">-f</span> <span class="s2">"</span><span class="nv">$file</span><span class="s2">"</span> <span class="o">]]</span><span class="p">;</span> <span class="k">then
    </span><span class="nb">exit </span>1
<span class="k">fi</span>
<span class="c"># Get the relative path by subtracting the absolute directory path</span>
<span class="nv">rel</span><span class="o">=</span><span class="s2">"</span><span class="k">${</span><span class="nv">file</span><span class="p">#</span><span class="nv">$srcdir</span><span class="k">}</span><span class="s2">"</span>
<span class="nb">echo</span> <span class="nv">$rel</span>
<span class="c"># Get if the file is inside any kind of subdirectory then create it</span>
<span class="nv">dname</span><span class="o">=</span><span class="s2">"</span><span class="si">$(</span><span class="nb">dirname</span> <span class="s2">"</span><span class="nv">$rel</span><span class="s2">"</span><span class="si">)</span><span class="s2">"</span>
<span class="k">if</span> <span class="o">[[</span> <span class="s2">"</span><span class="nv">$dname</span><span class="s2">"</span> <span class="o">!=</span> <span class="s1">'.'</span> <span class="o">]]</span><span class="p">;</span> <span class="k">then
    </span><span class="nb">mkdir</span> <span class="nt">-p</span> <span class="s2">"</span><span class="nv">$dstdir$dname</span><span class="s2">"</span>
<span class="k">fi</span>
<span class="c"># Hardlink since there is no s flag the file to the dest dir in the subdir if there</span>
<span class="nb">ln</span> <span class="s2">"</span><span class="nv">$file</span><span class="s2">"</span> <span class="s2">"</span><span class="nv">$dstdir$rel</span><span class="s2">"</span>
</code></pre></div></div>

<p>There is quite a bunch of things inside here but all of it is to do the following steps.</p>
<ol>
  <li>Change directory to the directory of the script just in case</li>
  <li>Get the variables from input arguments</li>
  <li>Define the source dir and destination paths as absolute paths ending with slash</li>
  <li>Check to make sure the input file is inside the source directory or exit</li>
  <li>Check that the file actually exists and is an actual file or exit</li>
  <li>Calculate the relative path of the file from the absolute path for later usage using a bash expression.</li>
  <li>Check if the resulting relative path is inside any form of subdirectory</li>
  <li>If inside any form of subdirectory create that inside the destination path</li>
  <li>Make a hardlink to the file</li>
</ol>

<p>So yeah that is not that complex and ln gets the arguments as absolute paths. Now there is just one step left that is to create a systemd unit to run the whole thing and let’s do a user unit for that. An easy way to create the unit is to run the command</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>systemctl <span class="nt">--user</span> edit <span class="nt">--full</span> <span class="nt">--force</span> aria
</code></pre></div></div>
<p>which will open nano or whatever editor you have chosen but if you have not selected an editor run <code class="language-plaintext highlighter-rouge">select-editor</code> first. Now for the contents to paste in</p>

<p><code class="language-plaintext highlighter-rouge">/home/yeen/.config/systemd/user/aria.service</code></p>
<div class="language-ini highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nn">[Unit]</span>
<span class="py">Description</span><span class="p">=</span><span class="s">Aria2 download manager</span>

<span class="nn">[Service]</span>
<span class="py">ExecStart</span><span class="p">=</span><span class="s">/bin/aria2c --enable-rpc --rpc-listen-all --rpc-secret YourPasswordHerePleaseChange</span>
<span class="py">WorkingDirectory</span><span class="p">=</span><span class="s">/home/yeen/Downloads/aria/unfinished</span>

<span class="nn">[Install]</span>
<span class="py">WantedBy</span><span class="p">=</span><span class="s">default.target</span>
</code></pre></div></div>
<p>and save and exit.</p>

<p>Before you run it make sure all the paths are existing that you want to use for the downloads or else things might not work but you can run the following command to create all those directories</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">mkdir</span> <span class="nt">-p</span> ~/.aria2/ ~/Downloads/aria2/<span class="o">{</span>finished,unfinished<span class="o">}</span>
</code></pre></div></div>

<p>Now you can start aria2 in RPC mode using this and it will run on every start and be ready for any downloads you add. Just run</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>systemctl <span class="nt">--user</span> <span class="nb">enable</span> <span class="nt">--now</span> aria
</code></pre></div></div>
<p>and it will start up now and be enabled on the next upstart.</p>

<h2 id="more">More</h2>
<p>There are a few more things that I recommend and one of them is to install <a href="https://github.com/ziahamza/webui-aria2">webui-aria2</a> to be able to control aria since otherwise you will just have a JSON-RPC API to access it through.</p>

<p>Personally I use that and I also use my own browser extension which gives me a menu on every page to start a download which I might write about next.</p>

<p>Now if you get everything working you can just look at your finished files directory now and then and see whenever a file is downloaded and finished and start using it even tho the whole torrent that is downloading is not fully finished yet or see every other file too as soon as it is downloaded without it taking extra hard drive space as soon as it finished.</p>

<p><a href="/2024/10/29/downloader-browser-extension.html">Part 2</a></p>]]></content><author><name>ellietheyeen</name></author><category term="aria2" /><category term="shell" /><category term="linux" /><summary type="html"><![CDATA[So I recently started to use the aria2 download manager since my NAS is starting to really break down at this point but there is one single feature it lacks. That feature is to be able to move finished files into a different directory. With torrents this tends to be somewhat hard to do since they have a seeding phase after the download phase and only the application itself is allowed to move the files during that phase as otherwise it cannot upload them to other users.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://github.com/EllieTheYeen.png" /><media:content medium="image" url="https://github.com/EllieTheYeen.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Escapes</title><link href="https://everydaycompute.github.io/2024/10/25/escapes.html" rel="alternate" type="text/html" title="Escapes" /><published>2024-10-25T12:40:00+02:00</published><updated>2024-10-25T12:40:00+02:00</updated><id>https://everydaycompute.github.io/2024/10/25/escapes</id><content type="html" xml:base="https://everydaycompute.github.io/2024/10/25/escapes.html"><![CDATA[<p>Escaping is when you want to place some code in some other code and you modify it first in order to. Here are some examples of the concept and how it might look in different situations.</p>

<ul id="markdown-toc">
  <li><a href="#html-and-xml" id="markdown-toc-html-and-xml">HTML and XML</a>    <ul>
      <li><a href="#attribute" id="markdown-toc-attribute">Attribute</a></li>
      <li><a href="#optional" id="markdown-toc-optional">Optional</a></li>
    </ul>
  </li>
  <li><a href="#url" id="markdown-toc-url">URL</a></li>
  <li><a href="#json" id="markdown-toc-json">JSON</a></li>
</ul>

<p>Escaping code that is generated somehow is a extremely important practice. SQL injections are a huge issue when it comes to code that is not properly escaped therefore you should use prepared statements whenever you can in SQL. In this article however we are going to look at places where the code is escaped.</p>

<p>There are various examples of this but the definition of it would be that you have any form of data structure that is usually a string and want to fit it inside another data structure. Things such as numbers tend to not be needed to be escaped as most languages use the same format for numbers but it is a good practice to do it anyway. You could call this a form of code generation as the goal is to produce a textual representation of the data inside the target language as a literal.</p>

<p>Now the goal is to produce something that does not break the syntax of the target language. While prepending and appending double quote <code class="language-plaintext highlighter-rouge">"</code> might work many times to escape something it does not work on something actually containing double quote and while prepending <code class="language-plaintext highlighter-rouge">\</code> to each double quote might work in those cases it might not be the best representation of the string.</p>

<p>Due to the nature of this there might be multiple representation of the same string such as some strings contain characters that might or might not be escaped such as newlines that might either be an actual newline written in the code or the escaped version <code class="language-plaintext highlighter-rouge">\n</code>.</p>

<h2 id="html-and-xml">HTML and XML</h2>
<p>HTML is escaped by first replacing <code class="language-plaintext highlighter-rouge">&amp;</code> with with <code class="language-plaintext highlighter-rouge">&amp;amp;</code> or <code class="language-plaintext highlighter-rouge">&amp;#38;</code> then <code class="language-plaintext highlighter-rouge">&lt;</code> with <code class="language-plaintext highlighter-rouge">&amp;lt;</code> or <code class="language-plaintext highlighter-rouge">&amp;#60;</code> and <code class="language-plaintext highlighter-rouge">&gt;</code> with <code class="language-plaintext highlighter-rouge">&amp;gt;</code> or <code class="language-plaintext highlighter-rouge">&amp;#62;</code>. The characters <code class="language-plaintext highlighter-rouge">&amp;</code>, <code class="language-plaintext highlighter-rouge">&lt;</code> and <code class="language-plaintext highlighter-rouge">&gt;</code> have special meaning in HTML for example a HTML tag looks like <code class="language-plaintext highlighter-rouge">&lt;tag&gt;&lt;/tag&gt;</code>. XML can have some additional restrictions of what is allowed and there might be other additional restrictions on both XML and HTML when it comes to unprintable characters.</p>

<h3 id="attribute">Attribute</h3>
<p>Attributes in HTML have additional restrictions of what characters need to be escaped. It also has some characters that technically no longer needs to be escaped like <code class="language-plaintext highlighter-rouge">&lt;</code> and <code class="language-plaintext highlighter-rouge">&gt;</code> but <code class="language-plaintext highlighter-rouge">"</code> needs to be escaped into <code class="language-plaintext highlighter-rouge">&amp;quot;</code> or <code class="language-plaintext highlighter-rouge">&amp;#34;</code> and <code class="language-plaintext highlighter-rouge">'</code> into <code class="language-plaintext highlighter-rouge">&amp;apos;</code> or <code class="language-plaintext highlighter-rouge">&amp;#39;</code>. There are esceptions and special cases to this but it is better to escape than not escape to prevent accidents.</p>

<h3 id="optional">Optional</h3>
<p>It is possible to escape characters that you do not need to escape for readability reasons such as replacing <code class="language-plaintext highlighter-rouge">\n</code> an actual newline with <code class="language-plaintext highlighter-rouge">&amp;#10;</code>. An example of this is that you can write</p>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;meta</span> <span class="na">name=</span><span class="s">"og:description"</span> <span class="na">content=</span><span class="s">"something
with
lines"</span> <span class="nt">/&gt;</span>
</code></pre></div></div>

<p>and it will parse just fine but you should really write</p>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;meta</span> <span class="na">name=</span><span class="s">"og:description"</span> <span class="na">content=</span><span class="s">"something&amp;#10;with&amp;#10;lines"</span> <span class="nt">/&gt;</span>
</code></pre></div></div>

<p>if you want some better looking indentation. As you see <code class="language-plaintext highlighter-rouge">&amp;#10;</code> is a newline since it is of the value 10 in base 10 which is a newline in encodings such as ASCII and UTF-8.</p>

<p>See <a href="https://docs.python.org/3/library/html.html#html.escape">html.escape</a> to escape HTML in Python.</p>

<h2 id="url">URL</h2>
<p>URLs use something called URL encoding to escape characters that have a special meaning inside URLs or in <code class="language-plaintext highlighter-rouge">application/x-www-form-urlencoded</code> HTTP requests. URL encoding works that all characters that have special meaning or is not printable are replaced with a percent sign <code class="language-plaintext highlighter-rouge">%</code> and two hex characters which means that it uses an alphabet not only <code class="language-plaintext highlighter-rouge">0-9</code> but also <code class="language-plaintext highlighter-rouge">A-Z</code>. This means that newline encoded is <code class="language-plaintext highlighter-rouge">%0A</code> rather than <code class="language-plaintext highlighter-rouge">&amp;#10;</code> as it is in HTML as the number base is 16 and not 10.</p>

<p>The characters that should be escaped in an URL is both the non printable characters which are under 32 in ASCII and UTF-8 and above 126 in ASCII and the following printable chars.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>@&amp;*][,"|!(' #;&lt;^=`+%$)\}:{&gt;?/
# Which escapes into
%40%26%2A%5D%5B%2C%22%7C%21%28%27%20%23%3B%3C%5E%3D%60%2B%25%24%29%5C%7D%3A%7B%3E%3F%2F
# Which is 3 times bigger
</code></pre></div></div>

<p>There are more things to consider for example a special rule that says that a space URL in a browser might either be written as <code class="language-plaintext highlighter-rouge">+</code> as plus <code class="language-plaintext highlighter-rouge">%20</code> or an actual space ` ` which will be converted into <code class="language-plaintext highlighter-rouge">%20</code> unlike the <code class="language-plaintext highlighter-rouge">+</code>. Certain APIs might have strange rules of when to use plus and when to use <code class="language-plaintext highlighter-rouge">+</code> or <code class="language-plaintext highlighter-rouge">%20</code> such as the Telldus API in the past.</p>

<p>There are some other oddities such as <code class="language-plaintext highlighter-rouge">/</code> is not escaped by Python’s <code class="language-plaintext highlighter-rouge">quote</code> but it is using <code class="language-plaintext highlighter-rouge">quote_plus</code> and I have no idea why but found out when checking <a href="https://github.com/python/cpython/blob/main/Lib/urllib/parse.py">the Python source code</a> for this article.</p>

<p>As always it is possible to escape characters that do not need to be escaped like you can escape the entirety of the alphabet in uppercase which looks like this</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>%41%42%43%44%45%46%47%48%49%4a%4b%4c%4d%4e%4f%50%51%52%53%54%55%56%57%58%59%5a
</code></pre></div></div>

<p>which could maybe be good if you want to hide some code so you accidentally do not remember it or something like that or maybe you are trying to sneak past some code past some anti cheat or antivirus program.</p>

<p>You can use the following function to completely URL encode any string in Python.</p>
<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">escall</span><span class="p">(</span><span class="n">i</span><span class="p">):</span> <span class="k">return</span> <span class="s">''</span><span class="p">.</span><span class="n">join</span><span class="p">(</span><span class="s">'%%%02x'</span> <span class="o">%</span> <span class="nb">ord</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="k">for</span> <span class="n">a</span> <span class="ow">in</span> <span class="n">i</span><span class="p">)</span>
</code></pre></div></div>

<p>See <a href="https://docs.python.org/3/library/urllib.parse.html#urllib.parse.quote">urllib.quote</a> to escape URLs in Python.</p>

<h2 id="json">JSON</h2>
<p>JSON which is the object notation for JavaScript used for data transport is quite simple that it is based on C and has similar escape codes and it is <a href="https://www.json.org/json-en.html">very well documented</a>. It is valid code in JavaScript and sort of valid Python. There is a funny trick you can do in Python where you enter the line</p>

<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">null</span><span class="p">,</span><span class="n">false</span><span class="p">,</span><span class="n">true</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span><span class="bp">False</span><span class="p">,</span><span class="bp">True</span>
</code></pre></div></div>

<p>and after it is in scope you can usually just eval to get the JSON out which is something you should really not do with untrusted data.</p>

<p>JSON uses unicode escape codes for escaping so if we make an example function to escape it would look like this</p>

<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">escall2</span><span class="p">(</span><span class="n">i</span><span class="p">):</span> <span class="k">return</span> <span class="s">''</span><span class="p">.</span><span class="n">join</span><span class="p">(</span><span class="s">'</span><span class="se">\\</span><span class="s">u%04x'</span> <span class="o">%</span> <span class="nb">ord</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="k">for</span> <span class="n">a</span> <span class="ow">in</span> <span class="n">i</span><span class="p">)</span>
</code></pre></div></div>

<p>and would escape every single character to a string in JSON.</p>

<p>Anyway this some basic examples how escaping in programming languages work and I hope you had fun reading.</p>]]></content><author><name>ellietheyeen</name></author><category term="javascript" /><category term="python" /><category term="json" /><summary type="html"><![CDATA[Escaping is when you want to place some code in some other code and you modify it first in order to. Here are some examples of the concept and how it might look in different situations.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://github.com/EllieTheYeen.png" /><media:content medium="image" url="https://github.com/EllieTheYeen.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">What is false?</title><link href="https://everydaycompute.github.io/2024/10/18/what-is-false.html" rel="alternate" type="text/html" title="What is false?" /><published>2024-10-18T21:55:00+02:00</published><updated>2024-10-18T21:55:00+02:00</updated><id>https://everydaycompute.github.io/2024/10/18/what-is-false</id><content type="html" xml:base="https://everydaycompute.github.io/2024/10/18/what-is-false.html"><![CDATA[<p>An interesting thing in programming languages is what is actually considered false when comparing it as a boolean such as inside an if clause. Each language has their own way of comparing what is false where some have bizarre rules and some have very simple ones. Certain languages eve have rules where some types are considered false sometimes.</p>

<ul id="markdown-toc">
  <li><a href="#java" id="markdown-toc-java">Java</a></li>
  <li><a href="#python" id="markdown-toc-python">Python</a></li>
  <li><a href="#perl" id="markdown-toc-perl">Perl</a></li>
  <li><a href="#php" id="markdown-toc-php">PHP</a></li>
  <li><a href="#javascript" id="markdown-toc-javascript">JavaScript</a></li>
</ul>

<h2 id="java">Java</h2>
<p>Known falsehoods: <code class="language-plaintext highlighter-rouge">false</code>, <code class="language-plaintext highlighter-rouge">Boolean(false)</code></p>

<p>Java has the most simple rule that only a boolean may ever be considered considered for truth or falsehood and that is either the simple <code class="language-plaintext highlighter-rouge">boolean</code> primitive true or the object <code class="language-plaintext highlighter-rouge">Boolean()</code> that is. Be careful that you do not dereference a null pointer as a variable that is set as the type Boolean can contain one unlike the primitive.</p>

<h2 id="python">Python</h2>
<p>Known falsehoods: <code class="language-plaintext highlighter-rouge">False</code>, <code class="language-plaintext highlighter-rouge">None</code>, <code class="language-plaintext highlighter-rouge">""</code>, <code class="language-plaintext highlighter-rouge">b""</code>, <code class="language-plaintext highlighter-rouge">0</code>, <code class="language-plaintext highlighter-rouge">0.0</code>, <code class="language-plaintext highlighter-rouge">()</code>, <code class="language-plaintext highlighter-rouge">{}</code>, <code class="language-plaintext highlighter-rouge">[]</code>, <code class="language-plaintext highlighter-rouge">set()</code></p>

<p>Python has way more complex rules when it comes to what is <code class="language-plaintext highlighter-rouge">True</code> and <code class="language-plaintext highlighter-rouge">False</code> and yes they must be capitalized in order to work. Empty strings are considered false and also empty bytestrings <code class="language-plaintext highlighter-rouge">bytes</code> are also considered false. Numbers like the <code class="language-plaintext highlighter-rouge">int</code> <code class="language-plaintext highlighter-rouge">0</code> is considered false and the <code class="language-plaintext highlighter-rouge">float</code> <code class="language-plaintext highlighter-rouge">0</code> is also considered false and similarly with the complex <code class="language-plaintext highlighter-rouge">0j</code> and so on.</p>

<p>What is unusual with Python here is that any type can chose if it is True or False at any time using the <code class="language-plaintext highlighter-rouge">__bool__</code> method that is called whenever there is a comparison so <code class="language-plaintext highlighter-rouge">()</code> <code class="language-plaintext highlighter-rouge">tuple</code>s <code class="language-plaintext highlighter-rouge">set()</code> <code class="language-plaintext highlighter-rouge">set</code>s <code class="language-plaintext highlighter-rouge">[]</code> <code class="language-plaintext highlighter-rouge">list</code>s and <code class="language-plaintext highlighter-rouge">{} dict</code>s are considered false if empty.</p>

<p>If you define your own type you can do like this</p>
<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">A</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">__bool__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="bp">False</span>

<span class="k">print</span><span class="p">(</span><span class="nb">bool</span><span class="p">(</span><span class="n">A</span><span class="p">()))</span>
</code></pre></div></div>
<p>And it will print <code class="language-plaintext highlighter-rouge">False</code> in this example as that is what the type compares to.</p>

<h2 id="perl">Perl</h2>
<p>Known falsehoods: <code class="language-plaintext highlighter-rouge">0</code>, <code class="language-plaintext highlighter-rouge">"0"</code>, <code class="language-plaintext highlighter-rouge">""</code>, <code class="language-plaintext highlighter-rouge">undef</code></p>

<p>Perl has some sort of consistent rules except one single bizarre quirk when it comes to that a string containing exactly a single <code class="language-plaintext highlighter-rouge">0</code> zero character will evaluate to false. However in Perl there is not a real boolean type in all versions. I am very new to this language so there might be a lot more quirks like these are the types are not acting like I am used to</p>

<h2 id="php">PHP</h2>
<p>Known falsehoods: <code class="language-plaintext highlighter-rouge">false</code>, <code class="language-plaintext highlighter-rouge">null</code>, <code class="language-plaintext highlighter-rouge">0</code>, <code class="language-plaintext highlighter-rouge">0.0</code>, <code class="language-plaintext highlighter-rouge">""</code>, <code class="language-plaintext highlighter-rouge">"0"</code>, <code class="language-plaintext highlighter-rouge">[]</code></p>

<p>Just like Perl the string containing exactly one zero is false so you should probably compare against what you really want to compare against which you should do in code anyway.</p>

<p>Keep in mind that there is also the special function <code class="language-plaintext highlighter-rouge">isset</code> that does a different kind of truth check compared to <code class="language-plaintext highlighter-rouge">boolval</code> in that everything that is not <code class="language-plaintext highlighter-rouge">null</code> or <code class="language-plaintext highlighter-rouge">false</code> is considered true.</p>

<p><code class="language-plaintext highlighter-rouge">isset</code> also has the functionality that you can use <code class="language-plaintext highlighter-rouge">isset($array["nonexistentkey"])</code> without getting any warnings or errors so you do not have to use <code class="language-plaintext highlighter-rouge">in_array("nonexistentkey", $array, true)</code> for example.</p>

<p>There is “supposed” to be boolean overloading for classes in PHP but that is <a href="https://stackoverflow.com/questions/6113387/how-to-create-a-php-class-which-can-be-casted-to-boolean-be-truthy-or-falsy">a whole other absurdity</a>.</p>

<h2 id="javascript">JavaScript</h2>
<p>Known falsehoods: <code class="language-plaintext highlighter-rouge">false</code>, <code class="language-plaintext highlighter-rouge">undefined</code>, <code class="language-plaintext highlighter-rouge">0</code>, <code class="language-plaintext highlighter-rouge">""</code></p>

<p>JavaScript has simpler rules than you would expect from such a wonky language but just like PHP it has extremely wonky rules for comparison that I might write about another time.</p>

<p>To cast to boolean in PHP you can use <code class="language-plaintext highlighter-rouge">!!something</code> or <code class="language-plaintext highlighter-rouge">Boolean(something)</code> but you are not supposed to use <code class="language-plaintext highlighter-rouge">new Boolean(something)</code> <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean">for some reason</a>.</p>

<p>Anyway it is good to know how to really check if something is really false in programming before you assume that something is considered in when compared.</p>]]></content><author><name>ellietheyeen</name></author><category term="javascript" /><category term="python" /><category term="java" /><category term="perl" /><category term="php" /><summary type="html"><![CDATA[An interesting thing in programming languages is what is actually considered false when comparing it as a boolean such as inside an if clause. Each language has their own way of comparing what is false where some have bizarre rules and some have very simple ones. Certain languages eve have rules where some types are considered false sometimes.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://github.com/EllieTheYeen.png" /><media:content medium="image" url="https://github.com/EllieTheYeen.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Systemd sockets</title><link href="https://everydaycompute.github.io/2024/10/11/systemd-sockets.html" rel="alternate" type="text/html" title="Systemd sockets" /><published>2024-10-11T22:07:00+02:00</published><updated>2024-10-11T22:07:00+02:00</updated><id>https://everydaycompute.github.io/2024/10/11/systemd-sockets</id><content type="html" xml:base="https://everydaycompute.github.io/2024/10/11/systemd-sockets.html"><![CDATA[<p>You might have heard about <a href="https://en.wikipedia.org/wiki/Inetd">inetd</a> which is often called a <a href="https://en.wikipedia.org/wiki/Super-server">super-server</a> according to Wikipedia. But did you know the systemd can do the same thing using something called <a href="https://www.freedesktop.org/software/systemd/man/latest/systemd.socket.html">systemd sockets</a>. I will show you how to use them.</p>

<ul id="markdown-toc">
  <li><a href="#added-later" id="markdown-toc-added-later">Added later</a>    <ul>
      <li><a href="#2024-10-11-2330" id="markdown-toc-2024-10-11-2330">2024-10-11 23:30</a></li>
    </ul>
  </li>
</ul>

<p>At first we are going to start with how to actually set them up and how they work.</p>

<p>The first thing to do is to create the socket unit which looks like this</p>

<p><code class="language-plaintext highlighter-rouge">testsocket.socket</code></p>
<div class="language-ini highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nn">[Unit]</span>
<span class="py">Description</span><span class="p">=</span><span class="s">Test socket</span>

<span class="nn">[Socket]</span>
<span class="py">ListenStream</span><span class="p">=</span><span class="s">1024</span>
<span class="py">Accept</span><span class="p">=</span><span class="s">yes</span>

<span class="nn">[Install]</span>
<span class="py">WantedBy</span><span class="p">=</span><span class="s">default.target</span>
</code></pre></div></div>

<p>To create a unit you can use the command</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>systemctl <span class="nt">--user</span> edit <span class="nt">--full</span> <span class="nt">--force</span> testsocket.socket <span class="c"># For user unit</span>
<span class="nb">sudo </span>systemctl edit <span class="nt">--full</span> <span class="nt">--force</span> testsocket.socket <span class="c"># For system unit</span>
</code></pre></div></div>
<p>Which will open up an editor like <code class="language-plaintext highlighter-rouge">nano</code> but if you have not selected an editor I recommend using nano which you can set using</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">select</span><span class="nt">-editor</span>
</code></pre></div></div>

<p>Except this unit you also need to define a second unit that is a service</p>

<p><code class="language-plaintext highlighter-rouge">testsocket@.service</code></p>
<div class="language-ini highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nn">[Unit]</span>
<span class="py">Description</span><span class="p">=</span><span class="s">Test socket service</span>

<span class="nn">[Service]</span>
<span class="py">ExecStart</span><span class="p">=</span><span class="s">/home/yeen/blep.sh</span>
</code></pre></div></div>

<p>And do note that there is an @ in the name just like in the <a href="https://ellietheyeen.github.io/2023/11/19/discord-systemd-error-handler.html">Failure handler</a> guide from a while ago.</p>

<p>Not to take a look what the started script actually does using <code class="language-plaintext highlighter-rouge">lsof -p $$</code> inside the script. As you can probably see a socket is open in file descriptor 3 and I have no idea what the pipe in 4 is but that does not matter much.</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>COMMAND  PID USER   FD   TYPE             DEVICE SIZE/OFF     NODE NAME
blep.sh 9877 yeen  cwd    DIR                8,2     4096 50298626 /home/yeen
blep.sh 9877 yeen  rtd    DIR                8,2     4096        2 /
blep.sh 9877 yeen  txt    REG                8,2   125688   262951 /usr/bin/dash
blep.sh 9877 yeen  mem    REG                8,2  2220400   263025 /usr/lib/x86_64-linux-gnu/libc.so.6
blep.sh 9877 yeen  mem    REG                8,2   240936   263020 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
blep.sh 9877 yeen    0r   CHR                1,3      0t0        5 /dev/null
blep.sh 9877 yeen    1u  unix 0x0000000000000000      0t0   120353 <span class="nb">type</span><span class="o">=</span>STREAM
blep.sh 9877 yeen    2u  unix 0x0000000000000000      0t0   120353 <span class="nb">type</span><span class="o">=</span>STREAM
blep.sh 9877 yeen    3u  IPv6             121878      0t0      TCP localhost:1024-&gt;localhost:42958 <span class="o">(</span>ESTABLISHED<span class="o">)</span>
blep.sh 9877 yeen    4r  FIFO               0,13      0t0   117586 pipe
blep.sh 9877 yeen   10r   REG                8,2       81 50333753 /home/yeen/blep.sh
</code></pre></div></div>

<p>The script itself used to test it is here</p>

<p>``blep.sh`</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/bin/sh</span>
<span class="nv">a</span><span class="o">=</span><span class="s2">"</span><span class="si">$(</span>lsof <span class="nt">-p</span> <span class="nv">$$</span><span class="si">)</span><span class="s2">"</span>
<span class="nb">echo</span> <span class="s2">"</span><span class="nv">$a</span><span class="s2">"</span> <span class="o">&gt;</span> ~/sdfdfg.txt
<span class="nb">echo</span> <span class="s2">"</span><span class="nv">$a</span><span class="s2">"</span> <span class="o">&gt;</span>&amp;3
<span class="nb">env</span> <span class="o">&gt;</span> env.txt
</code></pre></div></div>

<p>What the <code class="language-plaintext highlighter-rouge">&gt;&amp;3</code> does is tell it to write to file descriptor 3 so the lsof output from above is emitted from netcat connecting to the systemd socket.</p>

<p>The reason for <code class="language-plaintext highlighter-rouge">env</code> to be there is that some variables set there might be very useful and we can take a look at them here filtered from what usually exists in the env vars of systemd units being run.</p>

<div class="language-diff highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">12,13c12,13
</span><span class="gd">&lt; INVOCATION_ID=2106c6f489634605b77ec4c53b18e6ad
&lt; JOURNAL_STREAM=8:139232
</span><span class="p">---
</span><span class="gi">&gt; INVOCATION_ID=10f97a5493074bf8b914b8bbbcd421c2
&gt; JOURNAL_STREAM=8:120353
</span><span class="p">23a24,26
</span><span class="gi">&gt; LISTEN_FDNAMES=connection
&gt; LISTEN_FDS=1
&gt; LISTEN_PID=9877
</span><span class="p">29a33,34
</span><span class="gi">&gt; REMOTE_ADDR=127.0.0.1
&gt; REMOTE_PORT=42958
</span><span class="p">32c37
</span><span class="gd">&lt; SHLVL=1
</span><span class="p">---
</span><span class="gi">&gt; SHLVL=0
</span><span class="p">34c39
</span><span class="gd">&lt; SYSTEMD_EXEC_PID=11197
</span><span class="p">---
</span><span class="gi">&gt; SYSTEMD_EXEC_PID=9877
</span><span class="p">36c41
</span><span class="gd">&lt; _=/usr/bin/env
</span><span class="p">---
</span><span class="gi">&gt; _=/usr/bin/dbus-update-activation-environment
</span></code></pre></div></div>

<p>As you see there are some things to take note of like <code class="language-plaintext highlighter-rouge">REMOTE_ADDR=127.0.0.1</code> and <code class="language-plaintext highlighter-rouge">REMOTE_PORT=42958</code> which were from a run where I just ran <code class="language-plaintext highlighter-rouge">nc localhost 1024</code> which is netcat.</p>

<p>If you wonder how to get this diff do something like</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>systemd-run --user bash -c 'env &gt; enva.txt'
diff &lt;(sort enva.txt) &lt;(sort env.txt)
</code></pre></div></div>
<p>And you will get a good diff.</p>

<p>Now we can test with python too by making a script in it that receives the invocation.</p>

<p><code class="language-plaintext highlighter-rouge">blep.py</code></p>
<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#!/usr/bin/python3
</span><span class="kn">import</span> <span class="nn">socket</span>
<span class="n">s</span> <span class="o">=</span> <span class="n">socket</span><span class="p">.</span><span class="n">fromfd</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="n">socket</span><span class="p">.</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">socket</span><span class="p">.</span><span class="n">SOCK_STREAM</span><span class="p">,</span> <span class="n">proto</span><span class="o">=</span><span class="mi">0</span><span class="p">)</span>
<span class="n">s</span><span class="p">.</span><span class="n">send</span><span class="p">(</span><span class="sa">b</span><span class="s">"Blep I am cat meow</span><span class="se">\n</span><span class="s">"</span><span class="p">)</span>
<span class="n">s</span><span class="p">.</span><span class="n">close</span><span class="p">()</span>
</code></pre></div></div>
<p>And as you can guess it will send <code class="language-plaintext highlighter-rouge">Blep I am cat meow</code> to anyone who connects to the socket.</p>

<p>One last note is that you might have to use a command like</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>systemctl <span class="nt">--user</span> status testsocket@<span class="se">\*</span>
</code></pre></div></div>
<p>and scroll a bit up and down to find the status as it creates a temporary service for every invocation that you can find in the logs.</p>

<p>Anyway now you know the basics of systemd sockets so you can have fun with them.</p>

<h2 id="added-later">Added later</h2>

<h3 id="2024-10-11-2330">2024-10-11 23:30</h3>
<p>So apparently you can set stdin and stdout to be used to write to the socket. Here is an example. Start by changing your
<code class="language-plaintext highlighter-rouge">testsocket@.service</code></p>
<div class="language-ini highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nn">[Unit]</span>
<span class="py">Description</span><span class="p">=</span><span class="s">Test socket</span>

<span class="nn">[Service]</span>
<span class="py">ExecStart</span><span class="p">=</span><span class="s">/home/yeen/blep.sh</span>
<span class="py">StandardInput</span><span class="p">=</span><span class="s">socket</span>
<span class="py">StandardOutput</span><span class="p">=</span><span class="s">socket</span>
<span class="py">StandardError</span><span class="p">=</span><span class="s">journal</span>
</code></pre></div></div>
<p>It is possible to set all 3 to socket but you should generally set the error one specifically to journal since otherwise it will write stderr to the socket too instead of into the journal.</p>

<p>Now we can update the
<code class="language-plaintext highlighter-rouge">blep.sh</code></p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/bin/sh</span>
lsof <span class="nt">-p</span> <span class="nv">$$</span>
<span class="nb">echo </span>log something here <span class="o">&gt;</span>&amp;2
</code></pre></div></div>
<p>And now you can log things while also using stdout to write to the socket.</p>

<p>It is also very useful to start another terminal and use the following command to follow everything that happens in the log.</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>journalctl <span class="nt">--user</span> <span class="nt">-f</span>
</code></pre></div></div>]]></content><author><name>ellietheyeen</name></author><category term="systemd" /><category term="sockets" /><category term="python" /><category term="shell" /><summary type="html"><![CDATA[You might have heard about inetd which is often called a super-server according to Wikipedia. But did you know the systemd can do the same thing using something called systemd sockets. I will show you how to use them.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://github.com/EllieTheYeen.png" /><media:content medium="image" url="https://github.com/EllieTheYeen.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Useful Keyboard Shortcuts</title><link href="https://everydaycompute.github.io/2024/10/10/useful-keyboard-shortcuts.html" rel="alternate" type="text/html" title="Useful Keyboard Shortcuts" /><published>2024-10-10T22:09:00+02:00</published><updated>2024-10-10T22:09:00+02:00</updated><id>https://everydaycompute.github.io/2024/10/10/useful-keyboard-shortcuts</id><content type="html" xml:base="https://everydaycompute.github.io/2024/10/10/useful-keyboard-shortcuts.html"><![CDATA[<p>There are a lot of useful keyboard shortcuts in a large amount of applications and operating systems that make using those a lot easier and faster. You should always look up the keyboard shortcuts for the applications you use to be able them better. Here are some various examples from apps I commonly use.</p>

<ul id="markdown-toc">
  <li><a href="#windows" id="markdown-toc-windows">Windows</a>    <ul>
      <li><a href="#ctrl--shift--esc" id="markdown-toc-ctrl--shift--esc">Ctrl + Shift + ESC</a></li>
      <li><a href="#ctrl--esc" id="markdown-toc-ctrl--esc">Ctrl + ESC</a></li>
      <li><a href="#win--shift--s" id="markdown-toc-win--shift--s">Win + Shift + S</a></li>
      <li><a href="#win--alt--printscreen" id="markdown-toc-win--alt--printscreen">Win + Alt + PrintScreen</a></li>
      <li><a href="#win--g" id="markdown-toc-win--g">Win + G</a></li>
      <li><a href="#alt--printscreen" id="markdown-toc-alt--printscreen">Alt + PrintScreen</a></li>
      <li><a href="#alt--space" id="markdown-toc-alt--space">Alt + Space</a></li>
    </ul>
  </li>
  <li><a href="#text-editors" id="markdown-toc-text-editors">Text editors</a>    <ul>
      <li><a href="#ctrl--up-or-down-key" id="markdown-toc-ctrl--up-or-down-key">Ctrl + Up or Down key</a></li>
      <li><a href="#ctrl--left-or-right-key" id="markdown-toc-ctrl--left-or-right-key">Ctrl + Left or Right key</a></li>
      <li><a href="#tab-when-text-is-selected" id="markdown-toc-tab-when-text-is-selected">Tab when text is selected</a></li>
    </ul>
  </li>
  <li><a href="#firefox" id="markdown-toc-firefox">Firefox</a>    <ul>
      <li><a href="#shift--esc" id="markdown-toc-shift--esc">Shift + ESC</a></li>
      <li><a href="#space-bar" id="markdown-toc-space-bar">Space bar</a></li>
      <li><a href="#ctrl--tab" id="markdown-toc-ctrl--tab">Ctrl + Tab</a></li>
      <li><a href="#ctrl--1-9" id="markdown-toc-ctrl--1-9">Ctrl + 1-9</a></li>
      <li><a href="#ctrl--shift--s" id="markdown-toc-ctrl--shift--s">Ctrl + Shift + s</a></li>
    </ul>
  </li>
  <li><a href="#more" id="markdown-toc-more">More</a></li>
</ul>

<h2 id="windows">Windows</h2>

<h3 id="ctrl--shift--esc">Ctrl + Shift + ESC</h3>
<p>This will bring up the task manager directly which is incredibly useful.</p>

<h3 id="ctrl--esc">Ctrl + ESC</h3>
<p>This will bring up the start menu which is good when you have a non working windows key such as when you have removed it for gaming purposes.</p>

<h3 id="win--shift--s">Win + Shift + S</h3>
<p>This will bring up a menu where you take a screenshot just by clicking on a window and you can also select other modes using the menu that pops up.</p>

<h3 id="win--alt--printscreen">Win + Alt + PrintScreen</h3>
<p>This will use Windows Game Bar to take a screenshot which is good for games that are not on Steam therefore does not have any <code class="language-plaintext highlighter-rouge">F12</code> screenshot key.</p>

<h3 id="win--g">Win + G</h3>
<p>This will bring up Windows gamebar where you can do things like record video of games, adjust volume controls or take screenshots.</p>

<h3 id="alt--printscreen">Alt + PrintScreen</h3>
<p>This will take the current window and take a screenshot of it and place in clipboard. I useed to use this a lot before I knew of other methods and had a special <a href="https://randomness.nu/ClipImage.jar">tool</a> that I ran afterwards to save the image. Then I made <a href="https://kserver.nu/tools/clipthing.php">an even better tool</a> for it. Keep in mind if Dropbox is installed it tends to use this shortcut to save a screenshot to Dropbox.</p>

<h3 id="alt--space">Alt + Space</h3>
<p>This will bring up a menu for the current window where you can for example maximize or minimize or even move it. This is very good when windows get stuck in weird positions.</p>

<h2 id="text-editors">Text editors</h2>

<h3 id="ctrl--up-or-down-key">Ctrl + Up or Down key</h3>
<p>This will scroll up and down without moving the cursor</p>

<h3 id="ctrl--left-or-right-key">Ctrl + Left or Right key</h3>
<p>Skip a whole word forwards or backwards in a text document. You can also hold down <code class="language-plaintext highlighter-rouge">shift</code> to select at the same time</p>

<h3 id="tab-when-text-is-selected">Tab when text is selected</h3>
<p>This will indent the lines where the text is selected one step and you can use <code class="language-plaintext highlighter-rouge">shift</code> also at the same time to unindent instead.</p>

<h2 id="firefox">Firefox</h2>

<h3 id="shift--esc">Shift + ESC</h3>
<p>This will bring up the task manager for firefox which can be very</p>

<h3 id="space-bar">Space bar</h3>
<p>Just pressing space bar without anything selected will scroll down. If you use <code class="language-plaintext highlighter-rouge">shift</code> at the same time you will scroll up instead.</p>

<h3 id="ctrl--tab">Ctrl + Tab</h3>
<p>This will switch to the next tab and holding <code class="language-plaintext highlighter-rouge">shift</code> at the same time will go to the previous.</p>

<h3 id="ctrl--1-9">Ctrl + 1-9</h3>
<p>Will switch to the tab with that position.</p>

<h3 id="ctrl--shift--s">Ctrl + Shift + s</h3>
<p>Open a special take screenshot menu with built in cropping.</p>

<p>Firefox <a href="https://firefox-source-docs.mozilla.org/devtools-user/keyboard_shortcuts/index.html">has a large amount of shortcuts</a> in general which are good to know</p>

<h2 id="more">More</h2>
<p>Which of these shortcuts did you already know and do you know of any other useful shortcuts. Tell in the comments.</p>]]></content><author><name>ellietheyeen</name></author><category term="basic" /><summary type="html"><![CDATA[There are a lot of useful keyboard shortcuts in a large amount of applications and operating systems that make using those a lot easier and faster. You should always look up the keyboard shortcuts for the applications you use to be able them better. Here are some various examples from apps I commonly use.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://github.com/EllieTheYeen.png" /><media:content medium="image" url="https://github.com/EllieTheYeen.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Ensure a line is in a file in bash, zsh and sh</title><link href="https://everydaycompute.github.io/2024/10/05/ensurelineinfile.html" rel="alternate" type="text/html" title="Ensure a line is in a file in bash, zsh and sh" /><published>2024-10-05T23:05:00+02:00</published><updated>2024-10-05T23:05:00+02:00</updated><id>https://everydaycompute.github.io/2024/10/05/ensurelineinfile</id><content type="html" xml:base="https://everydaycompute.github.io/2024/10/05/ensurelineinfile.html"><![CDATA[<p>Sometimes you want to ensure a certain line is in a config file for example that there is something in <code class="language-plaintext highlighter-rouge">authorized_keys</code> or anything like that really. It is quite common to do this manually by opening the file and putting in the line if it is missing and so on. You can however automate the entire process using shell.</p>

<ul id="markdown-toc">
  <li><a href="#first-quirk-newlines-in-variables" id="markdown-toc-first-quirk-newlines-in-variables">First quirk. Newlines in variables</a></li>
  <li><a href="#second-quirk-zsh-not-expanding-stuff" id="markdown-toc-second-quirk-zsh-not-expanding-stuff">Second quirk. Zsh not expanding stuff</a></li>
  <li><a href="#goal" id="markdown-toc-goal">Goal</a></li>
</ul>

<p>I went through a lot of iterations in order to set this up as the compatibilities between shells are not the best. Here you can see the actual result of what I came up wit in order to solve the problem and make a script to ensure that the keys are in the correct location and installed.</p>

<div class="language-zsh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ensurefileline<span class="o">()</span> <span class="o">{</span>
  <span class="nv">file</span><span class="o">=</span><span class="s2">"</span><span class="nv">$1</span><span class="s2">"</span>
  <span class="nv">line</span><span class="o">=</span><span class="s2">"</span><span class="nv">$2</span><span class="s2">"</span>
  <span class="k">if</span> <span class="o">[</span> <span class="o">!</span> <span class="nt">-f</span> <span class="s2">"</span><span class="nv">$file</span><span class="s2">"</span> <span class="o">]</span><span class="p">;</span> <span class="k">then
    </span><span class="nb">touch</span> <span class="s2">"</span><span class="nv">$file</span><span class="s2">"</span>
    <span class="nb">echo </span>creating file <span class="o">&gt;</span>&amp;2
    <span class="nb">echo</span> <span class="s2">"</span><span class="nv">$line</span><span class="s2">"</span> <span class="o">&gt;&gt;</span> <span class="s2">"</span><span class="nv">$file</span><span class="s2">"</span>
  <span class="k">else
    </span><span class="nb">echo </span>file exists
    <span class="k">if </span><span class="nb">grep</span> <span class="nt">-F</span> <span class="s2">"</span><span class="nv">$line</span><span class="s2">"</span> <span class="s2">"</span><span class="nv">$file</span><span class="s2">"</span> <span class="o">&gt;</span>/dev/null 2&gt;&amp;1 <span class="p">;</span> <span class="k">then
     </span><span class="nb">echo </span>line <span class="k">in </span>file <span class="o">&gt;</span>&amp;2
    <span class="k">else
     </span><span class="nb">echo </span>no line <span class="k">in </span>file <span class="o">&gt;</span>&amp;2
     <span class="nb">echo</span> <span class="s2">"</span><span class="nv">$line</span><span class="s2">"</span> <span class="o">&gt;&gt;</span> <span class="s2">"</span><span class="nv">$file</span><span class="s2">"</span>
    <span class="k">fi
  fi</span>
<span class="o">}</span>

<span class="nv">keys</span><span class="o">=</span><span class="si">$(</span>
<span class="nb">cat</span> <span class="o">&lt;&lt;</span> <span class="sh">'</span><span class="no">EOT</span><span class="sh">'
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCLFZusq0Gmyk17xRI0b8vXalKM9cKyjcA6SCSaHoGYHlz39S32zZ7DacDHYx1txiglTEIUVgjzIah2gWcpB7FFvIKoWvfF5VVXhleUjd3y8erRPJ+TuPV5f6po5eUL1iqtTEVrbRmIExzKVPQRSFRuYuCinY6P+wEDm902Kql/aNl9YqPRlc6pnYIvnyXVw2HeyR23noro8GV7CKjBw4PfbWDmH52CYDmvCs0W8xwl27Vg1N97wwMNe93rCqax928nZBdSNipo1bVmL9MhToJgkIMdF73+aNWV4/ug60E79PcB4l6PwnxT2NPASgkcTlugsrkonEfI9xy4OIZt0oD75RQWkbTLU6/di9l8Te/rcQv2UZQEEhU+DesL6nZWRo8YuPbo0WcMcDczXOHq/nsI4vm4rghdR/NotalZxbClpXwAx4tG+mf913fSNHCbnORAUrPMBN9l1XavuVyITvTNRlFCZGNsGXOvH44jpiedU9vSX+kGGofBp+QrDYmjaGs= root@clear
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDLBCvhDnR2oEuFGaLxW+63HYotCt2wIWEB36nXeeuPznoT1TEcBuYT0XsGxA7jzr48X4yHzU38TaHXHAghknMiSNmZpcNxNc49jshj7DyFoeOa84O1cq9An1oVODfOkiQ9Q8k1p4nG+dPnxlBBGXYoINl4qbdZM0NEJM0pXGtXdz5BtGBcL20ZsfJZNHp2jDFtGLxn6TY04wh6KMZ4tHORgVQdMboHKvrUUxtH+s/Y47MAPiwJqbXfCOkZb2dLhrYfV6RhbDZ3Bo3CR3oKtqhBsuBn6HK7FXHHvwzIkuYxt0MowV4/6UO6AIaGC9sFNqkzCyj1diN/rt8UBRC/gNz+2eRsl7pVIt1WBty7XY7Nq9Q5Vo2IjZ/M0k2HY8lLQUxiKzTw1eTYEfqbg9pZzs7ljG9f1ohKcQ1+4WZWh9w52jovdMjB8qvfQLltRyoPEl9xOk3v3+UGCJM0aJTPviGBi+Io0qlNfdzkqCqYzS5ETFCF/PH4cSecokOWALiN0A0= root@clear
</span><span class="no">EOT
</span><span class="si">)</span>

<span class="nv">OLDIFS</span><span class="o">=</span><span class="s2">"</span><span class="nv">$IFS</span><span class="s2">"</span> <span class="c"># Save IFS in case</span>
<span class="nb">export </span><span class="nv">IFS</span><span class="o">=</span><span class="s2">"
"</span> <span class="c"># This looks cursed but does give compatibility with /bin/sh</span>
<span class="k">for </span>key <span class="k">in</span> <span class="si">$(</span> <span class="nb">echo</span> <span class="s2">"</span><span class="nv">$keys</span><span class="s2">"</span> <span class="si">)</span><span class="p">;</span> <span class="k">do</span> <span class="c"># This iterates and splits by IFS</span>
ensurefileline ~/.ssh/authorized_keys <span class="s2">"</span><span class="nv">$key</span><span class="s2">"</span>
<span class="k">done
</span><span class="nv">IFS</span><span class="o">=</span><span class="s2">"</span><span class="nv">$OLDIFS</span><span class="s2">"</span> <span class="c"># Restore IFS</span>
</code></pre></div></div>

<p>Debugging this entire thing was quite a process as the entire thing inside the function was no problem as it ran no problem inside all shells but some of the other stuff had huge issues. To get exactly the right heredoc syntax was a bit of a pain until I found the <code class="language-plaintext highlighter-rouge">'EOT'</code> thing that works well and to enclose it all in a command substitution with <code class="language-plaintext highlighter-rouge">$()</code> in order to get it into a variable.</p>

<h2 id="first-quirk-newlines-in-variables">First quirk. Newlines in variables</h2>

<p>Here we are going to look at some strange quirks in the whole thing.</p>

<p>This is looking very odd but it works in both zsh, sh and bash</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">IFS</span><span class="o">=</span><span class="s2">"
"</span>
</code></pre></div></div>
<p>I have no idea if there is a better solution for this.</p>

<p>However there are other syntaxes that work on many shells such as the following</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">variable</span><span class="o">=</span><span class="s1">$'</span><span class="se">\n</span><span class="s1">'</span>
</code></pre></div></div>

<p>But the result of that code running in all shells is the following</p>

<p><code class="language-plaintext highlighter-rouge">test.sh</code></p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># sh</span>
<span class="o">[</span><span class="s1">'$\\n'</span><span class="o">]</span>
<span class="c"># zsh</span>
<span class="o">[</span><span class="s1">'\n'</span><span class="o">]</span>
<span class="c"># bash</span>
<span class="o">[</span><span class="s1">'\n'</span><span class="o">]</span>
</code></pre></div></div>

<p>Here as you can see the content of the variable becomes <code class="language-plaintext highlighter-rouge">$\\n</code> which is a literal dollar sign, a backslash and the character n where there is supposed to be a newline.</p>

<p>Here is what is used to test that and get that output. To test this set this up to exist in <code class="language-plaintext highlighter-rouge">PATH</code> as <code class="language-plaintext highlighter-rouge">args</code></p>

<p><code class="language-plaintext highlighter-rouge">args</code></p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">sys</span>

<span class="k">print</span><span class="p">(</span><span class="n">sys</span><span class="p">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">:])</span>
</code></pre></div></div>

<p>Ensure <code class="language-plaintext highlighter-rouge">test.sh</code> exist with the contents to test and run this in command line</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">echo</span> <span class="s1">'#'</span> sh
sh test.sh
<span class="nb">echo</span> <span class="s1">'#'</span> zsh
zsh test.sh
<span class="nb">echo</span> <span class="s1">'#'</span> bash
bash test.sh  
</code></pre></div></div>

<h2 id="second-quirk-zsh-not-expanding-stuff">Second quirk. Zsh not expanding stuff</h2>

<p>First to give an idea of this we are going to put that args command before the ensurefileline function call to see what is being outputted and run first like normal to see what it should look like.</p>

<div class="language-zsh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># sh</span>
<span class="o">[</span><span class="s1">'ensurefileline'</span>, <span class="s1">'/home/pi/.ssh/authorized_keys'</span>, <span class="s1">'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCLFZusq0Gmyk17xRI0b8vXalKM9cKyjcA6SCSaHoGYHlz39S32zZ7DacDHYx1txiglTEIUVgjzIah2gWcpB7FFvIKoWvfF5VVXhleUjd3y8erRPJ+TuPV5f6po5eUL1iqtTEVrbRmIExzKVPQRSFRuYuCinY6P+wEDm902Kql/aNl9YqPRlc6pnYIvnyXVw2HeyR23noro8GV7CKjBw4PfbWDmH52CYDmvCs0W8xwl27Vg1N97wwMNe93rCqax928nZBdSNipo1bVmL9MhToJgkIMdF73+aNWV4/ug60E79PcB4l6PwnxT2NPASgkcTlugsrkonEfI9xy4OIZt0oD75RQWkbTLU6/di9l8Te/rcQv2UZQEEhU+DesL6nZWRo8YuPbo0WcMcDczXOHq/nsI4vm4rghdR/NotalZxbClpXwAx4tG+mf913fSNHCbnORAUrPMBN9l1XavuVyITvTNRlFCZGNsGXOvH44jpiedU9vSX+kGGofBp+QrDYmjaGs= root@clear'</span><span class="o">]</span>

<span class="o">[</span><span class="s1">'ensurefileline'</span>, <span class="s1">'/home/pi/.ssh/authorized_keys'</span>, <span class="s1">'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDLBCvhDnR2oEuFGaLxW+63HYotCt2wIWEB36nXeeuPznoT1TEcBuYT0XsGxA7jzr48X4yHzU38TaHXHAghknMiSNmZpcNxNc49jshj7DyFoeOa84O1cq9An1oVODfOkiQ9Q8k1p4nG+dPnxlBBGXYoINl4qbdZM0NEJM0pXGtXdz5BtGBcL20ZsfJZNHp2jDFtGLxn6TY04wh6KMZ4tHORgVQdMboHKvrUUxtH+s/Y47MAPiwJqbXfCOkZb2dLhrYfV6RhbDZ3Bo3CR3oKtqhBsuBn6HK7FXHHvwzIkuYxt0MowV4/6UO6AIaGC9sFNqkzCyj1diN/rt8UBRC/gNz+2eRsl7pVIt1WBty7XY7Nq9Q5Vo2IjZ/M0k2HY8lLQUxiKzTw1eTYEfqbg9pZzs7ljG9f1ohKcQ1+4WZWh9w52jovdMjB8qvfQLltRyoPEl9xOk3v3+UGCJM0aJTPviGBi+Io0qlNfdzkqCqYzS5ETFCF/PH4cSecokOWALiN0A0= root@clear'</span><span class="o">]</span>

<span class="c"># zsh</span>
<span class="o">[</span><span class="s1">'ensurefileline'</span>, <span class="s1">'/home/pi/.ssh/authorized_keys'</span>, <span class="s1">'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCLFZusq0Gmyk17xRI0b8vXalKM9cKyjcA6SCSaHoGYHlz39S32zZ7DacDHYx1txiglTEIUVgjzIah2gWcpB7FFvIKoWvfF5VVXhleUjd3y8erRPJ+TuPV5f6po5eUL1iqtTEVrbRmIExzKVPQRSFRuYuCinY6P+wEDm902Kql/aNl9YqPRlc6pnYIvnyXVw2HeyR23noro8GV7CKjBw4PfbWDmH52CYDmvCs0W8xwl27Vg1N97wwMNe93rCqax928nZBdSNipo1bVmL9MhToJgkIMdF73+aNWV4/ug60E79PcB4l6PwnxT2NPASgkcTlugsrkonEfI9xy4OIZt0oD75RQWkbTLU6/di9l8Te/rcQv2UZQEEhU+DesL6nZWRo8YuPbo0WcMcDczXOHq/nsI4vm4rghdR/NotalZxbClpXwAx4tG+mf913fSNHCbnORAUrPMBN9l1XavuVyITvTNRlFCZGNsGXOvH44jpiedU9vSX+kGGofBp+QrDYmjaGs= root@clear'</span><span class="o">]</span>

<span class="o">[</span><span class="s1">'ensurefileline'</span>, <span class="s1">'/home/pi/.ssh/authorized_keys'</span>, <span class="s1">'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDLBCvhDnR2oEuFGaLxW+63HYotCt2wIWEB36nXeeuPznoT1TEcBuYT0XsGxA7jzr48X4yHzU38TaHXHAghknMiSNmZpcNxNc49jshj7DyFoeOa84O1cq9An1oVODfOkiQ9Q8k1p4nG+dPnxlBBGXYoINl4qbdZM0NEJM0pXGtXdz5BtGBcL20ZsfJZNHp2jDFtGLxn6TY04wh6KMZ4tHORgVQdMboHKvrUUxtH+s/Y47MAPiwJqbXfCOkZb2dLhrYfV6RhbDZ3Bo3CR3oKtqhBsuBn6HK7FXHHvwzIkuYxt0MowV4/6UO6AIaGC9sFNqkzCyj1diN/rt8UBRC/gNz+2eRsl7pVIt1WBty7XY7Nq9Q5Vo2IjZ/M0k2HY8lLQUxiKzTw1eTYEfqbg9pZzs7ljG9f1ohKcQ1+4WZWh9w52jovdMjB8qvfQLltRyoPEl9xOk3v3+UGCJM0aJTPviGBi+Io0qlNfdzkqCqYzS5ETFCF/PH4cSecokOWALiN0A0= root@clear'</span><span class="o">]</span>

<span class="c"># bash</span>
<span class="o">[</span><span class="s1">'ensurefileline'</span>, <span class="s1">'/home/pi/.ssh/authorized_keys'</span>, <span class="s1">'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCLFZusq0Gmyk17xRI0b8vXalKM9cKyjcA6SCSaHoGYHlz39S32zZ7DacDHYx1txiglTEIUVgjzIah2gWcpB7FFvIKoWvfF5VVXhleUjd3y8erRPJ+TuPV5f6po5eUL1iqtTEVrbRmIExzKVPQRSFRuYuCinY6P+wEDm902Kql/aNl9YqPRlc6pnYIvnyXVw2HeyR23noro8GV7CKjBw4PfbWDmH52CYDmvCs0W8xwl27Vg1N97wwMNe93rCqax928nZBdSNipo1bVmL9MhToJgkIMdF73+aNWV4/ug60E79PcB4l6PwnxT2NPASgkcTlugsrkonEfI9xy4OIZt0oD75RQWkbTLU6/di9l8Te/rcQv2UZQEEhU+DesL6nZWRo8YuPbo0WcMcDczXOHq/nsI4vm4rghdR/NotalZxbClpXwAx4tG+mf913fSNHCbnORAUrPMBN9l1XavuVyITvTNRlFCZGNsGXOvH44jpiedU9vSX+kGGofBp+QrDYmjaGs= root@clear'</span><span class="o">]</span>

<span class="o">[</span><span class="s1">'ensurefileline'</span>, <span class="s1">'/home/pi/.ssh/authorized_keys'</span>, <span class="s1">'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDLBCvhDnR2oEuFGaLxW+63HYotCt2wIWEB36nXeeuPznoT1TEcBuYT0XsGxA7jzr48X4yHzU38TaHXHAghknMiSNmZpcNxNc49jshj7DyFoeOa84O1cq9An1oVODfOkiQ9Q8k1p4nG+dPnxlBBGXYoINl4qbdZM0NEJM0pXGtXdz5BtGBcL20ZsfJZNHp2jDFtGLxn6TY04wh6KMZ4tHORgVQdMboHKvrUUxtH+s/Y47MAPiwJqbXfCOkZb2dLhrYfV6RhbDZ3Bo3CR3oKtqhBsuBn6HK7FXHHvwzIkuYxt0MowV4/6UO6AIaGC9sFNqkzCyj1diN/rt8UBRC/gNz+2eRsl7pVIt1WBty7XY7Nq9Q5Vo2IjZ/M0k2HY8lLQUxiKzTw1eTYEfqbg9pZzs7ljG9f1ohKcQ1+4WZWh9w52jovdMjB8qvfQLltRyoPEl9xOk3v3+UGCJM0aJTPviGBi+Io0qlNfdzkqCqYzS5ETFCF/PH4cSecokOWALiN0A0= root@clear'</span><span class="o">]</span>
</code></pre></div></div>

<p>This looks correct and you know what the function is supposed to be called with but now look at this.</p>

<div class="language-zsh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># sh</span>
<span class="o">[</span><span class="s1">'ensurefileline'</span>, <span class="s1">'/home/pi/.ssh/authorized_keys'</span>, <span class="s1">'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCLFZusq0Gmyk17xRI0b8vXalKM9cKyjcA6SCSaHoGYHlz39S32zZ7DacDHYx1txiglTEIUVgjzIah2gWcpB7FFvIKoWvfF5VVXhleUjd3y8erRPJ+TuPV5f6po5eUL1iqtTEVrbRmIExzKVPQRSFRuYuCinY6P+wEDm902Kql/aNl9YqPRlc6pnYIvnyXVw2HeyR23noro8GV7CKjBw4PfbWDmH52CYDmvCs0W8xwl27Vg1N97wwMNe93rCqax928nZBdSNipo1bVmL9MhToJgkIMdF73+aNWV4/ug60E79PcB4l6PwnxT2NPASgkcTlugsrkonEfI9xy4OIZt0oD75RQWkbTLU6/di9l8Te/rcQv2UZQEEhU+DesL6nZWRo8YuPbo0WcMcDczXOHq/nsI4vm4rghdR/NotalZxbClpXwAx4tG+mf913fSNHCbnORAUrPMBN9l1XavuVyITvTNRlFCZGNsGXOvH44jpiedU9vSX+kGGofBp+QrDYmjaGs= root@clear'</span><span class="o">]</span>

<span class="o">[</span><span class="s1">'ensurefileline'</span>, <span class="s1">'/home/pi/.ssh/authorized_keys'</span>, <span class="s1">'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDLBCvhDnR2oEuFGaLxW+63HYotCt2wIWEB36nXeeuPznoT1TEcBuYT0XsGxA7jzr48X4yHzU38TaHXHAghknMiSNmZpcNxNc49jshj7DyFoeOa84O1cq9An1oVODfOkiQ9Q8k1p4nG+dPnxlBBGXYoINl4qbdZM0NEJM0pXGtXdz5BtGBcL20ZsfJZNHp2jDFtGLxn6TY04wh6KMZ4tHORgVQdMboHKvrUUxtH+s/Y47MAPiwJqbXfCOkZb2dLhrYfV6RhbDZ3Bo3CR3oKtqhBsuBn6HK7FXHHvwzIkuYxt0MowV4/6UO6AIaGC9sFNqkzCyj1diN/rt8UBRC/gNz+2eRsl7pVIt1WBty7XY7Nq9Q5Vo2IjZ/M0k2HY8lLQUxiKzTw1eTYEfqbg9pZzs7ljG9f1ohKcQ1+4WZWh9w52jovdMjB8qvfQLltRyoPEl9xOk3v3+UGCJM0aJTPviGBi+Io0qlNfdzkqCqYzS5ETFCF/PH4cSecokOWALiN0A0= root@clear'</span><span class="o">]</span>

<span class="c"># zsh</span>
<span class="o">[</span><span class="s1">'ensurefileline'</span>, <span class="s1">'/home/pi/.ssh/authorized_keys'</span>, <span class="s1">'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCLFZusq0Gmyk17xRI0b8vXalKM9cKyjcA6SCSaHoGYHlz39S32zZ7DacDHYx1txiglTEIUVgjzIah2gWcpB7FFvIKoWvfF5VVXhleUjd3y8erRPJ+TuPV5f6po5eUL1iqtTEVrbRmIExzKVPQRSFRuYuCinY6P+wEDm902Kql/aNl9YqPRlc6pnYIvnyXVw2HeyR23noro8GV7CKjBw4PfbWDmH52CYDmvCs0W8xwl27Vg1N97wwMNe93rCqax928nZBdSNipo1bVmL9MhToJgkIMdF73+aNWV4/ug60E79PcB4l6PwnxT2NPASgkcTlugsrkonEfI9xy4OIZt0oD75RQWkbTLU6/di9l8Te/rcQv2UZQEEhU+DesL6nZWRo8YuPbo0WcMcDczXOHq/nsI4vm4rghdR/NotalZxbClpXwAx4tG+mf913fSNHCbnORAUrPMBN9l1XavuVyITvTNRlFCZGNsGXOvH44jpiedU9vSX+kGGofBp+QrDYmjaGs= root@clear\nssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDLBCvhDnR2oEuFGaLxW+63HYotCt2wIWEB36nXeeuPznoT1TEcBuYT0XsGxA7jzr48X4yHzU38TaHXHAghknMiSNmZpcNxNc49jshj7DyFoeOa84O1cq9An1oVODfOkiQ9Q8k1p4nG+dPnxlBBGXYoINl4qbdZM0NEJM0pXGtXdz5BtGBcL20ZsfJZNHp2jDFtGLxn6TY04wh6KMZ4tHORgVQdMboHKvrUUxtH+s/Y47MAPiwJqbXfCOkZb2dLhrYfV6RhbDZ3Bo3CR3oKtqhBsuBn6HK7FXHHvwzIkuYxt0MowV4/6UO6AIaGC9sFNqkzCyj1diN/rt8UBRC/gNz+2eRsl7pVIt1WBty7XY7Nq9Q5Vo2IjZ/M0k2HY8lLQUxiKzTw1eTYEfqbg9pZzs7ljG9f1ohKcQ1+4WZWh9w52jovdMjB8qvfQLltRyoPEl9xOk3v3+UGCJM0aJTPviGBi+Io0qlNfdzkqCqYzS5ETFCF/PH4cSecokOWALiN0A0= root@clear'</span><span class="o">]</span>

<span class="c"># bash</span>
<span class="o">[</span><span class="s1">'ensurefileline'</span>, <span class="s1">'/home/pi/.ssh/authorized_keys'</span>, <span class="s1">'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCLFZusq0Gmyk17xRI0b8vXalKM9cKyjcA6SCSaHoGYHlz39S32zZ7DacDHYx1txiglTEIUVgjzIah2gWcpB7FFvIKoWvfF5VVXhleUjd3y8erRPJ+TuPV5f6po5eUL1iqtTEVrbRmIExzKVPQRSFRuYuCinY6P+wEDm902Kql/aNl9YqPRlc6pnYIvnyXVw2HeyR23noro8GV7CKjBw4PfbWDmH52CYDmvCs0W8xwl27Vg1N97wwMNe93rCqax928nZBdSNipo1bVmL9MhToJgkIMdF73+aNWV4/ug60E79PcB4l6PwnxT2NPASgkcTlugsrkonEfI9xy4OIZt0oD75RQWkbTLU6/di9l8Te/rcQv2UZQEEhU+DesL6nZWRo8YuPbo0WcMcDczXOHq/nsI4vm4rghdR/NotalZxbClpXwAx4tG+mf913fSNHCbnORAUrPMBN9l1XavuVyITvTNRlFCZGNsGXOvH44jpiedU9vSX+kGGofBp+QrDYmjaGs= root@clear'</span><span class="o">]</span>

<span class="o">[</span><span class="s1">'ensurefileline'</span>, <span class="s1">'/home/pi/.ssh/authorized_keys'</span>, <span class="s1">'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDLBCvhDnR2oEuFGaLxW+63HYotCt2wIWEB36nXeeuPznoT1TEcBuYT0XsGxA7jzr48X4yHzU38TaHXHAghknMiSNmZpcNxNc49jshj7DyFoeOa84O1cq9An1oVODfOkiQ9Q8k1p4nG+dPnxlBBGXYoINl4qbdZM0NEJM0pXGtXdz5BtGBcL20ZsfJZNHp2jDFtGLxn6TY04wh6KMZ4tHORgVQdMboHKvrUUxtH+s/Y47MAPiwJqbXfCOkZb2dLhrYfV6RhbDZ3Bo3CR3oKtqhBsuBn6HK7FXHHvwzIkuYxt0MowV4/6UO6AIaGC9sFNqkzCyj1diN/rt8UBRC/gNz+2eRsl7pVIt1WBty7XY7Nq9Q5Vo2IjZ/M0k2HY8lLQUxiKzTw1eTYEfqbg9pZzs7ljG9f1ohKcQ1+4WZWh9w52jovdMjB8qvfQLltRyoPEl9xOk3v3+UGCJM0aJTPviGBi+Io0qlNfdzkqCqYzS5ETFCF/PH4cSecokOWALiN0A0= root@clear'</span><span class="o">]</span>
</code></pre></div></div>

<p>Can you see the difference? If you do not see it did not split the content inside the heredoc by newline. The line</p>

<div class="language-zsh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">for </span>key <span class="k">in</span> <span class="si">$(</span> <span class="nb">echo</span> <span class="s2">"</span><span class="nv">$keys</span><span class="s2">"</span> <span class="si">)</span><span class="p">;</span> <span class="k">do</span>
</code></pre></div></div>

<p>Was replaced with</p>

<div class="language-zsh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">for </span>key <span class="k">in</span> <span class="nv">$keys</span><span class="p">;</span> <span class="k">do</span>
</code></pre></div></div>

<p>Which looks like it makes sense but this does not function inside zsh for some reason. That reason is zsh splitting does not work like normal and according to <a href="https://unix.stackexchange.com/questions/295033/loop-over-a-string-in-zsh-and-bash">Stack Exchange</a> in Zsh command expansions are split but not variable expansion.</p>

<h2 id="goal">Goal</h2>

<p>So this goal of the entire this as discussed in the beginning is to be able to change some configs to ensure consistency and such. Lets give another example of usage where we have a file that is <code class="language-plaintext highlighter-rouge">~/.aliases</code> and we want it sourced and we want to make sure it is sourced but only once on multiple executions of some install script. We create the following code for that.</p>

<div class="language-zsh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ensurefileline .zshrc <span class="s2">"if [ -f ~/.aliases ]; then source ~/.aliases fi"</span>
ensurefileline .bashrc <span class="s2">"if [ -f ~/.aliases ]; then . ~/.aliases fi"</span>
</code></pre></div></div>

<p>This can then be run any number of times and only if the line is missing it will be added to the file. Another thing to note is that the <code class="language-plaintext highlighter-rouge">grep</code> command must be called with the <code class="language-plaintext highlighter-rouge">-F</code> flag that uses a fixed string as otherwise we would have to escape it somehow. Try this out if you want and have fun</p>]]></content><author><name>ellietheyeen</name></author><category term="shell" /><category term="bash" /><category term="zsh" /><category term="sh" /><summary type="html"><![CDATA[Sometimes you want to ensure a certain line is in a config file for example that there is something in authorized_keys or anything like that really. It is quite common to do this manually by opening the file and putting in the line if it is missing and so on. You can however automate the entire process using shell.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://github.com/EllieTheYeen.png" /><media:content medium="image" url="https://github.com/EllieTheYeen.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>