gemini://technicalsuwako.moe
テクニカル諏訪子
2023-10-23T16:00:00Z
テクニカル諏訪子
blog/norikae-102.gmi
凛
【076】乗換 1.0.2登場
2023-10-23T16:00:00Z
<h2 id="heading">乗換って何?</h2>
<p>乗換はCLIでの路線情報を確認ツールです。<br />
Yahooでスパイウェアが多すぎるため、CLI用のフロントエンドを作りました。</p>
<h2 id="heading-1">変更</h2>
<ul>
<li>ヤフー社はHTMLをちょっと更新されたから、乗換を修正する事が必要となった</li>
</ul>
<h2 id="heading-2">ソースコード</h2>
<p><a href="https://gitler.moe/suwako/norikae">Gitler</a><br />
<a href="https://codeberg.org/TechnicalSuwako/norikae">Codeberg</a><br />
<a href="https://notabug.org/TechnicalSuwako/norikae">Notabug</a><br />
<a href="https://git.disroot.org/TechnicalSuwako/norikae">Disroot</a></p>
<h2 id="heading-3">ダウンロード</h2>
<p><a href="https://gitler.moe/suwako/norikae/releases">リリースページ</a><br />
<a href="https://076.moe/repo/src/norikae">ソースコード</a><br />
<a href="https://076.moe/repo/bin/norikae">バイナリー</a></p>
<p>以上</p>
blog/spliti-112.gmi
凛
【オワコンテック】spliti 1.1.2登場
2023-10-23T00:00:00Z
<h2 id="spliti">splitiって何?</h2>
<p>splitiはMixiのフェイクニュース部分向けプライバシーUIです。</p>
<h2 id="heading">変更</h2>
<ul>
<li>投稿内の画像もプロクシー化</li>
<li>投稿内の画像はレスポンシブに</li>
</ul>
<h2 id="heading-1">ソースコード</h2>
<p><a href="https://gitler.moe/suwako/spliti">Gitler</a></p>
<h2 id="heading-2">公式インスタンス</h2>
<p><a href="">https://mixi.owacon.moe/</a></p>
<p>以上</p>
blog/postmarketos-make-repository.gmi
凛
【PostmarketOS】自分のレポジトリを作り方
2023-10-15T00:00:00Z
<p><a href="/blog/crux-make-port-repository/">半年前に言った通り、あたしのパソコンでのLinuxを使用歴が非常に長いですが、スマホでの使用歴はそれ程長くないのです。</a><br />
2020年にはMan(ko)jaroを使用していましたが、毎回パッケージの更新後に度々問題が生じた為、Mobian(PinePhone用Debian)に切り替えました。<br />
Mobianは2022年まで使用していましたが、2年経ってもLinuxスマホの進歩があんまなかった為、再びPixel 3でGrapheneOS(Google非依存のAndroid)に戻りました。<br />
しかし、2023年10月現在、ついに大きな進展が見られる様になった為、PinePhoneを処理して、PostmarketOSを試してみたところ、Androidを使用する意欲がなくなりました。</p>
<p>ちなみに、PostmarketOSはスマホ専用Alpine Linuxベースのディストリビューションです。</p>
<h2 id="heading">レポジトリの作り方</h2>
<h3 id="heading-1">初回のみ</h3>
<p>以下のステップは初回だけ実行して下さい。<br />
まず、必要なツールをインストールします。</p>
<pre><code lang="">doas apk update
doas apk add alpine-sdk
doas addgroup <span style="color:#a2f;font-weight:bold">$(</span>whoami<span style="color:#a2f;font-weight:bold">)</span> abuild
doas reboot
</code></pre><p>再起動後、新しいディレクトリと鍵ペアを生成して下さい。</p>
<pre><code lang="">mkdir -p ~/.local/src/repo
abuild-keygen -a -i
</code></pre><h3 id="heading-2">新しいパッケージを作成する</h3>
<p>次のステップは、APKBUILDファイルを作成する事です。</p>
<pre><code lang=""><span style="color:#a2f">cd</span> ~/.local/src/repo
mkdir urloli
<span style="color:#a2f">cd</span> urloli
nvim APKBUILD
</code></pre><p>例:</p>
<pre><code lang=""># Maintainer: Suwako Moriya <suwako at 076 dot moe>
pkgname=urloli
pkgver=2.2.0
pkgrel=1
pkgdesc="$pkgname"
url="https://076.moe"
arch="all"
license="GPL"
source="https://076.moe/repo/src/$pkgname/$pkgname-$pkgver.tar.gz"
makedepends="go"
options="!check !strip"
package() {
mkdir -p $pkgdir/etc/urloli $pkgdir/usr/bin $pkgdir/etc/init.d $pkgdir/www/active/urlo.li
mv -i config.json $pkgdir/etc/urloli/config.json
make
mv urloli $pkgdir/usr/bin/urloli
curl https://076.moe/repo/init/openrc/init.d/urloli > $pkgdir/etc/init.d/urloli
mv view $pkgdir/www/active/urlo.li
mv static $pkgdir/www/active/urlo.li
chmod +x $pkgdir/etc/init.d/urloli
chmod +x $pkgdir/usr/bin/urloli
echo "Change the domain name in \"/etc/$pkgname/config.json\"."
}
</code></pre><p>URLロリはGo以外従属ソフトがありませんが、Goはコンパイル時だけで必要ですので、「makedepends」に追加しました。<br />
実行するには必要であれば、「depends」に追加して下さい。</p>
<p><strong>注意:PostmarketOSやAlpineで、「ninja」をインストールする場合、<code lang="">apk add ninja</code>ではなく<code lang="">apk add samurai</code>を使用して下さい。</strong></p>
<p>次は「sha512sum」を生成し、ビルドを行って下さい。</p>
<pre><code lang="">abuild checksum
abuild
</code></pre><p>Alpineではパッケージの署名が必要ですが、PostmarketOSでは自動で署名される為、これは不要です。</p>
<h2 id="heading-3">レポジトリサーバーの準備</h2>
<p>次のステップは、サーバーを準備です。<br />
サーバーはOpenBSDの場合:</p>
<pre><code lang="">doas nvim /etc/httpd.conf
</code></pre><pre><code lang="">...
server "076.moe" {
listen on * port 443 tls
tls certificate "/etc/ssl/076.moe.crt"
tls key "/etc/ssl/private/076.moe.key"
root "/htdocs/076.moe/www"
directory index "index.html"
location "/repo/*" {
directory auto index
}
location "/.well-known/acme-challenge/*" {
root "/acme"
request strip 2
}
}
server "www.076.moe" {
listen on * port 443 tls
tls certificate "/etc/ssl/076.moe.crt"
tls key "/etc/ssl/private/076.moe.key"
block return 301 "https://076.moe$REQUEST_URI"
}
server "www.076.moe" {
alternative { 076.moe }
listen on * port 80
block return 301 "https://076.moe$REQUEST_URI"
}
server "l3nbzyxgrkmd46nacmzf2sy6tpjrwh4iv3pgacbrbk72wcgxq5a.b32.i2p" {
listen on * port 8450
root "/htdocs/076.moe/www"
directory index "index.html"
location "/repo/*" {
directory auto index
}
}
server "7dt6irsmfvbrtgn4nuah56kky6mvr472fbwwaltuxpf26qdqkdhfvnqd.onion" {
listen on * port 8500
root "/htdocs/076.moe/www"
directory index "index.html"
location "/repo/*" {
directory auto index
}
}
...
</code></pre><pre><code lang="">doas mkdir -p /var/www/htdocs/076.moe/www/repo/alpine
doas chown -R <span style="color:#a2f;font-weight:bold">$(</span>whoami<span style="color:#a2f;font-weight:bold">)</span>:<span style="color:#a2f;font-weight:bold">$(</span>whoami<span style="color:#a2f;font-weight:bold">)</span> /var/www/htdocs/076.moe
doas rcctl restart httpd
</code></pre><h3 id="heading-4">パッケージを公開</h3>
<p>公開鍵をアップロードした後、パッケージを公開して下さい。</p>
<pre><code lang="">rsync -rtvzP ~/.abuild/*.rsa.pub <span style="color:#666">(</span>君のIPアドレス<span style="color:#666">)</span>:/var/www/htdocs/076.moe/www/repo/alpine
<span style="color:#a2f">cd</span> ~/packages
rsync -rtvzP repo <span style="color:#666">(</span>君のIPアドレス<span style="color:#666">)</span>:/var/www/htdocs/076.moe/www/repo/alpine
</code></pre><h2 id="heading-5">レポジトリの確認</h2>
<p>最後のステップは、自分のパッケージをインストールする事です。</p>
<pre><code lang=""><span style="color:#a2f">cd</span> /etc/apk/keys
doas wget https://<span style="color:#666">(</span>ドメイン名<span style="color:#666">)</span>/repo/alpine/<span style="color:#666">(</span>.rsa.pubのファイル名<span style="color:#666">)</span>
<span style="color:#a2f">cd</span> ..
doas nvim repositories
</code></pre><pre><code lang="">http://mirror.postmarketos.org/postmarketos/v23.06
http://dl-cdn.alpinelinux.org/alpine/v3.18/main
http://dl-cdn.alpinelinux.org/alpine/v3.18/community
http://(ドメイン名)/repo/alpine/repo # これを追加して下さい
</code></pre><pre><code lang="">doas apk update
doas apk add urloli
</code></pre><p>以上</p>
blog/spliti-111.gmi
凛
【オワコンテック】spliti 1.1.1登場
2023-09-09T00:00:00Z
<h2 id="spliti">splitiって何?</h2>
<p>splitiはMixiのフェイクニュース部分向けプライバシーUIです。</p>
<h2 id="heading">変更</h2>
<ul>
<li>YouTube動画があれば、オワコンYouTubeに変更させる様に</li>
<li>サムネイルがなければ、getimg()関数をす部に終了する様に</li>
<li>もっと小さいバグを修正</li>
</ul>
<h2 id="heading-1">ソースコード</h2>
<p><a href="https://gitler.moe/suwako/spliti">Gitler</a></p>
<h2 id="heading-2">公式インスタンス</h2>
<p><a href="">https://mixi.owacon.moe/</a></p>
<p>以上</p>
blog/fix-broken-contact-form.gmi
凛
【PHP】正しい連絡フォームの作り方(クライアント側をぜったいに信用するな!!)
2023-08-04T00:00:00Z
<h2 id="heading">問題</h2>
<p>現在の「モダン」ウェブ開発で、連絡フォームはJavascriptで制御されていますが、これは大きなリスクがあります。<br />
その理由について、直ぐに説明します。</p>
<p>以下のスクショをご覧いただいたら、何が問題は何だと思いますか?<br />
<a href="https://ass.technicalsuwako.moe/fuanform1.png"><img src="https://ass.technicalsuwako.moe/fuanform1.png" alt="" /></a></p>
<p>正解は:送信ボタンは<code lang=""><form></code>タグの外にある事です。<br />
これでは、Javascriptを無効にした場合、送信ボタンをクリックする事が出来ません。</p>
<p>このフォームを送信する為には、この送信ボタンをフォーム内に移動し、<code lang="">type="button"</code>を<code lang="">type="submit"</code>に変更する事で、Javascriptなしでもフォームを送信する事が可能になります。<br />
そんな感じ:<br />
<a href="https://ass.technicalsuwako.moe/fuanform2.png"><img src="https://ass.technicalsuwako.moe/fuanform2.png" alt="" /></a></p>
<p>そうして、入力画面で「required=""」というパラメータがあり、これによりJavascriptが無効であってもフィールドが入力されているかどうかを確認できます。<br />
例:<br />
<a href="https://ass.technicalsuwako.moe/fuanform3.png"><img src="https://ass.technicalsuwako.moe/fuanform3.png" alt="" /></a></p>
<p>しかし、このパラメータを削除すると、どのような事態が起こると思いますか?<br />
正解はこちら:<br />
<a href="https://ass.technicalsuwako.moe/fuanform4.png"><img src="https://ass.technicalsuwako.moe/fuanform4.png" alt="" /></a></p>
<p>また、確認画面ではフォームが<code lang=""><input type="hidden" /></code>タグを沢山含んでいます。<br />
その中の「value=""」部分を変更する事が可能です。<br />
これにより、MySQLインジェクションも可能となります。</p>
<h2 id="heading-1">解決策</h2>
<p>上述の問題を解決する為には、サーバー側でのチェックが必要です。<br />
勿論、クライアント側とサーバー側の両方でチェックを行う事も可能です。</p>
<p>例として、PHPの場合を紹介します(PHPを使用するフォームが多い為):</p>
<pre><code lang=""><span style="color:#666"><?</span>php
session_name(<span style="color:#b44">"formvals"</span>);
session_start([
<span style="color:#b44">"cookie_httponly"</span> <span style="color:#666">=></span> <span style="color:#a2f;font-weight:bold">true</span>,
]);
<span style="color:#a2f;font-weight:bold">if</span> (<span style="color:#a2f;font-weight:bold">empty</span>(<span style="color:#b8860b">$_SESSION</span>[<span style="color:#b44">"csrf_token"</span>])) <span style="color:#b8860b">$_SESSION</span>[<span style="color:#b44">"csrf_token"</span>] <span style="color:#666">=</span> bin2hex(random_bytes(<span style="color:#666">32</span>));
<span style="color:#a2f;font-weight:bold">if</span> (<span style="color:#666">!</span>isset(<span style="color:#b8860b">$_SESSION</span>[<span style="color:#b44">"step"</span>])) <span style="color:#b8860b">$_SESSION</span>[<span style="color:#b44">"step"</span>] <span style="color:#666">=</span> <span style="color:#666">1</span>;
<span style="color:#b8860b">$errmes</span> <span style="color:#666">=</span> [];
<span style="color:#b8860b">$reqvals</span> <span style="color:#666">=</span> [
<span style="color:#b44">"name"</span> <span style="color:#666">=></span> <span style="color:#b8860b">$_SESSION</span>[<span style="color:#b44">"name"</span>] <span style="color:#666">??</span> <span style="color:#b44">""</span>,
<span style="color:#b44">"kana"</span> <span style="color:#666">=></span> <span style="color:#b8860b">$_SESSION</span>[<span style="color:#b44">"kana"</span>] <span style="color:#666">??</span> <span style="color:#b44">""</span>,
];
<span style="color:#b8860b">$optvals</span> <span style="color:#666">=</span> [
<span style="color:#b44">"url"</span> <span style="color:#666">=></span> <span style="color:#b8860b">$_SESSION</span>[<span style="color:#b44">"url"</span>] <span style="color:#666">??</span> <span style="color:#b44">""</span>,
];
<span style="color:#a2f;font-weight:bold">if</span> (<span style="color:#b8860b">$_SERVER</span>[<span style="color:#b44">"REQUEST_METHOD"</span>] <span style="color:#666">==</span> <span style="color:#b44">"POST"</span>) {
<span style="color:#a2f;font-weight:bold">if</span> (<span style="color:#666">!</span>hash_equals(<span style="color:#b8860b">$_SESSION</span>[<span style="color:#b44">"csrf_token"</span>], <span style="color:#b8860b">$_POST</span>[<span style="color:#b44">"csrf_token"</span>])) {
<span style="color:#a2f;font-weight:bold">die</span>(<span style="color:#b44">"不正なCSRFトークン"</span>);
}
<span style="color:#a2f;font-weight:bold">if</span> (<span style="color:#b8860b">$_SESSION</span>[<span style="color:#b44">"step"</span>] <span style="color:#666">==</span> <span style="color:#666">1</span>) {
<span style="color:#a2f;font-weight:bold">foreach</span> (<span style="color:#b8860b">$reqvals</span> <span style="color:#a2f;font-weight:bold">as</span> <span style="color:#b8860b">$k</span> <span style="color:#666">=></span> <span style="color:#b8860b">$v</span>) {
<span style="color:#b8860b">$_SESSION</span>[<span style="color:#b8860b">$k</span>] <span style="color:#666">=</span> filter_input(INPUT_POST, <span style="color:#b8860b">$k</span>, FILTER_SANITIZE_STRING);
<span style="color:#a2f;font-weight:bold">if</span> (<span style="color:#b8860b">$_SESSION</span>[<span style="color:#b8860b">$k</span>]) <span style="color:#b8860b">$reqvals</span>[<span style="color:#b8860b">$k</span>] <span style="color:#666">=</span> <span style="color:#b8860b">$_SESSION</span>[<span style="color:#b8860b">$k</span>];
<span style="color:#a2f;font-weight:bold">else</span> <span style="color:#b8860b">$errmes</span>[] <span style="color:#666">=</span> <span style="color:#b8860b">$k</span><span style="color:#666">.</span><span style="color:#b44">"をご入力下さい。"</span>;
}
<span style="color:#a2f;font-weight:bold">foreach</span> (<span style="color:#b8860b">$optvals</span> <span style="color:#a2f;font-weight:bold">as</span> <span style="color:#b8860b">$k</span> <span style="color:#666">=></span> <span style="color:#b8860b">$v</span>) {
<span style="color:#b8860b">$_SESSION</span>[<span style="color:#b8860b">$k</span>] <span style="color:#666">=</span> filter_input(INPUT_POST, <span style="color:#b8860b">$k</span>, FILTER_SANITIZE_STRING);
<span style="color:#b8860b">$optvals</span>[<span style="color:#b8860b">$k</span>] <span style="color:#666">=</span> <span style="color:#b8860b">$_SESSION</span>[<span style="color:#b8860b">$k</span>];
}
<span style="color:#a2f;font-weight:bold">if</span> (<span style="color:#a2f;font-weight:bold">empty</span>(<span style="color:#b8860b">$errmes</span>)) <span style="color:#b8860b">$_SESSION</span>[<span style="color:#b44">"step"</span>] <span style="color:#666">=</span> <span style="color:#666">2</span>;
}
<span style="color:#a2f;font-weight:bold">else</span> <span style="color:#a2f;font-weight:bold">if</span> (<span style="color:#b8860b">$_SESSION</span>[<span style="color:#b44">"step"</span>] <span style="color:#666">==</span> <span style="color:#666">2</span>) {
<span style="color:#b8860b">$_SESSION</span>[<span style="color:#b44">"step"</span>] <span style="color:#666">=</span> <span style="color:#666">1</span>;
session_destroy();
header(<span style="color:#b44">"Location: /success.html"</span>);
<span style="color:#a2f;font-weight:bold">die</span>();
}
}
<span style="color:#a2f;font-weight:bold">else</span> {
<span style="color:#b8860b">$_SESSION</span>[<span style="color:#b44">"csrf_token"</span>] <span style="color:#666">=</span> bin2hex(random_bytes(<span style="color:#666">32</span>));
<span style="color:#b8860b">$_SESSION</span>[<span style="color:#b44">"step"</span>] <span style="color:#666">=</span> <span style="color:#666">1</span>;
}
<span style="color:#080">?></span><span style="">
</span><span style="">
</span><span style=""><!DOCTYPE html>
</span><span style=""><html>
</span><span style=""> <head>
</span><span style=""> <meta charset="utf-8" />
</span><span style=""> <title>連絡フォーム</title>
</span><span style=""> </head>
</span><span style=""> <body>
</span><span style=""><?php
</span><span style=""> if ($_SESSION["step"] == 1) {
</span><span style=""> if (count($errmes) != 0) {
</span><span style="">?>
</span><span style=""> <ul style="font-width: bolder; color: #f00; list-style: none;">
</span><span style=""><?php
</span><span style=""> foreach ($errmes as $e) {
</span><span style=""> echo "<li>".$e."</li>";
</span><span style=""> }
</span><span style="">?>
</span><span style=""> </ul>
</span><span style=""><?php
</span><span style=""> }
</span><span style="">?>
</span><span style=""> <form method="POST" action="/contact.php">
</span><span style=""> <input type="hidden" name="csrf_token" value="<?= $_SESSION['csrf_token'] ?>">
</span><span style=""> <table>
</span><span style=""> <tbody>
</span><span style=""> <tr>
</span><span style=""> <td>お名前 (必須):</td>
</span><span style=""> <td><input placeholder="山田 太郎" required="" name="name" type="text" value="<?= $reqvals["name"] ?>" /></td>
</span><span style=""> </tr>
</span><span style=""> <tr>
</span><span style=""> <td>お名前 (かな) (必須):</td>
</span><span style=""> <td><input placeholder="やまだ たろう" required="" name="kana" type="text" value="<?= $reqvals["kana"] ?>" /></td>
</span><span style=""> </tr>
</span><span style=""> <tr>
</span><span style=""> <td>御社又は関連サイトのURL:</td>
</span><span style=""> <td><input placeholder="https://076.moe/" name="url" type="text" value="<?= $optvals["url"] ?>" /></td>
</span><span style=""> </tr>
</span><span style=""> </tbody>
</span><span style=""> </table>
</span><span style=""> <button>確認画面へ</button>
</span><span style=""> </form>
</span><span style=""><?php
</span><span style=""> } else if ($_SESSION["step"] == 2) {
</span><span style="">?>
</span><span style=""> <form method="POST" action="/contact.php">
</span><span style=""> <input type="hidden" name="csrf_token" value="<?= $_SESSION['csrf_token'] ?>">
</span><span style=""> お名前 (必須): <?= $reqvals["name"] ?><br />
</span><span style=""> お名前 (かな) (必須): <?= $reqvals["kana"] ?><br />
</span><span style=""> 御社又は関連サイトのURL: <?= $optvals["url"] ?><br /><br />
</span><span style=""> <button>送信する</button>
</span><span style=""> </form>
</span><span style=""><?php
</span><span style=""> } else {
</span><span style="">?>
</span><span style=""> <p>不明なエラー。</p>
</span><span style=""><?php
</span><span style=""> }
</span><span style="">?>
</span><span style=""> </body>
</span><span style=""></html>
</span></code></pre><p>結果:<br />
<a href="https://ass.technicalsuwako.moe/anzenform1.png"><img src="https://ass.technicalsuwako.moe/anzenform1.png" alt="" /></a></p>
<p><a href="https://ass.technicalsuwako.moe/anzenform2.png"><img src="https://ass.technicalsuwako.moe/anzenform2.png" alt="" /></a></p>
<p><a href="https://ass.technicalsuwako.moe/anzenform3.png"><img src="https://ass.technicalsuwako.moe/anzenform3.png" alt="" /></a></p>
<p><a href="https://ass.technicalsuwako.moe/anzenform4.png"><img src="https://ass.technicalsuwako.moe/anzenform4.png" alt="" /></a></p>
<p><a href="https://ass.technicalsuwako.moe/anzenform5.png"><img src="https://ass.technicalsuwako.moe/anzenform5.png" alt="" /></a></p>
<p><a href="https://ass.technicalsuwako.moe/anzenform6.png"><img src="https://ass.technicalsuwako.moe/anzenform6.png" alt="" /></a></p>
<p>ねぇねぇー!<br />
簡単でしょー!</p>
<p>以上</p>